// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2011 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
#include "headers.h"
#include "irc.h"
+#include "db.h"
+#include "net.h"
+#include "init.h"
+#include "strlcpy.h"
+
+#ifdef __WXMSW__
+#include <string.h>
+// This file can be downloaded as a part of the Windows Platform SDK
+// and is required for Bitcoin binaries to work properly on versions
+// of Windows before XP. If you are doing builds of Bitcoin for
+// public release, you should uncomment this line.
+//#include <WSPiApi.h>
+#endif
#ifdef USE_UPNP
#include <miniupnpc/miniwget.h>
bool fAllowDNS = false;
uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK);
CAddress addrLocalHost("0.0.0.0", 0, false, nLocalServices);
-CNode* pnodeLocalHost = NULL;
+static CNode* pnodeLocalHost = NULL;
uint64 nLocalHostNonce = 0;
array<int, 10> vnThreadsRunning;
-SOCKET hListenSocket = INVALID_SOCKET;
+static SOCKET hListenSocket = INVALID_SOCKET;
vector<CNode*> vNodes;
CCriticalSection cs_vNodes;
// Settings
int fUseProxy = false;
+int nConnectTimeout = 5000;
CAddress addrProxy("127.0.0.1",9050);
+unsigned short GetListenPort()
+{
+ return (unsigned short)(GetArg("-port", GetDefaultPort()));
+}
void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd)
{
-bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet)
+bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet, int nTimeout)
{
hSocketRet = INVALID_SOCKET;
SOCKET hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (hSocket == INVALID_SOCKET)
return false;
-#ifdef BSD
+#ifdef SO_NOSIGPIPE
int set = 1;
setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
#endif
- bool fRoutable = !(addrConnect.GetByte(3) == 10 || (addrConnect.GetByte(3) == 192 && addrConnect.GetByte(2) == 168));
- bool fProxy = (fUseProxy && fRoutable);
+ bool fProxy = (fUseProxy && addrConnect.IsRoutable());
struct sockaddr_in sockaddr = (fProxy ? addrProxy.GetSockAddr() : addrConnect.GetSockAddr());
+#ifdef __WXMSW__
+ u_long fNonblock = 1;
+ if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
+#else
+ int fFlags = fcntl(hSocket, F_GETFL, 0);
+ if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == -1)
+#endif
+ {
+ closesocket(hSocket);
+ return false;
+ }
+
+
if (connect(hSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
{
+ // WSAEINVAL is here because some legacy version of winsock uses it
+ if (WSAGetLastError() == WSAEINPROGRESS || WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINVAL)
+ {
+ struct timeval timeout;
+ timeout.tv_sec = nTimeout / 1000;
+ timeout.tv_usec = (nTimeout % 1000) * 1000;
+
+ fd_set fdset;
+ FD_ZERO(&fdset);
+ FD_SET(hSocket, &fdset);
+ int nRet = select(hSocket + 1, NULL, &fdset, NULL, &timeout);
+ if (nRet == 0)
+ {
+ printf("connection timeout\n");
+ closesocket(hSocket);
+ return false;
+ }
+ if (nRet == SOCKET_ERROR)
+ {
+ printf("select() for connection failed: %i\n",WSAGetLastError());
+ closesocket(hSocket);
+ return false;
+ }
+ socklen_t nRetSize = sizeof(nRet);
+#ifdef __WXMSW__
+ if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, (char*)(&nRet), &nRetSize) == SOCKET_ERROR)
+#else
+ if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, &nRet, &nRetSize) == SOCKET_ERROR)
+#endif
+ {
+ printf("getsockopt() for connection failed: %i\n",WSAGetLastError());
+ closesocket(hSocket);
+ return false;
+ }
+ if (nRet != 0)
+ {
+ printf("connect() failed after select(): %s\n",strerror(nRet));
+ closesocket(hSocket);
+ return false;
+ }
+ }
+#ifdef __WXMSW__
+ else if (WSAGetLastError() != WSAEISCONN)
+#else
+ else
+#endif
+ {
+ printf("connect() failed: %i\n",WSAGetLastError());
+ closesocket(hSocket);
+ return false;
+ }
+ }
+
+ /*
+ this isn't even strictly necessary
+ CNode::ConnectNode immediately turns the socket back to non-blocking
+ but we'll turn it back to blocking just in case
+ */
+#ifdef __WXMSW__
+ fNonblock = 0;
+ if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
+#else
+ fFlags = fcntl(hSocket, F_GETFL, 0);
+ if (fcntl(hSocket, F_SETFL, fFlags & !O_NONBLOCK) == SOCKET_ERROR)
+#endif
+ {
closesocket(hSocket);
return false;
}
-bool AddAddress(CAddress addr, int64 nTimePenalty)
+bool AddAddress(CAddress addr, int64 nTimePenalty, CAddrDB *pAddrDB)
{
if (!addr.IsRoutable())
return false;
// New address
printf("AddAddress(%s)\n", addr.ToString().c_str());
mapAddresses.insert(make_pair(addr.GetKey(), addr));
- CAddrDB().WriteAddress(addr);
+ if (pAddrDB)
+ pAddrDB->WriteAddress(addr);
+ else
+ CAddrDB().WriteAddress(addr);
return true;
}
else
fUpdated = true;
}
if (fUpdated)
- CAddrDB().WriteAddress(addrFound);
+ {
+ if (pAddrDB)
+ pAddrDB->WriteAddress(addrFound);
+ else
+ CAddrDB().WriteAddress(addrFound);
+ }
}
}
return false;
{
BOOST_FOREACH(CNode* pnode, vNodes)
{
- if (pnode->hSocket == INVALID_SOCKET || pnode->hSocket < 0)
+ if (pnode->hSocket == INVALID_SOCKET)
continue;
FD_SET(pnode->hSocket, &fdsetRecv);
FD_SET(pnode->hSocket, &fdsetError);
if (nSelect == SOCKET_ERROR)
{
int nErr = WSAGetLastError();
- printf("socket select error %d\n", nErr);
- for (int i = 0; i <= hSocketMax; i++)
- FD_SET(i, &fdsetRecv);
+ if (hSocketMax > -1)
+ {
+ printf("socket select error %d\n", nErr);
+ for (int i = 0; i <= hSocketMax; i++)
+ FD_SET(i, &fdsetRecv);
+ }
FD_ZERO(&fdsetSend);
FD_ZERO(&fdsetError);
Sleep(timeout.tv_usec/1000);
CDataStream& vRecv = pnode->vRecv;
unsigned int nPos = vRecv.size();
- if (nPos > 1000*GetArg("-maxreceivebuffer", 10*1000)) {
+ if (nPos > ReceiveBufferSize()) {
if (!pnode->fDisconnect)
printf("socket recv flood control disconnect (%d bytes)\n", vRecv.size());
pnode->CloseSocketDisconnect();
pnode->CloseSocketDisconnect();
}
}
- if (vSend.size() > 1000*GetArg("-maxsendbuffer", 10*1000)) {
+ if (vSend.size() > SendBufferSize()) {
if (!pnode->fDisconnect)
printf("socket send flood control disconnect (%d bytes)\n", vSend.size());
pnode->CloseSocketDisconnect();
printf("ThreadMapPort started\n");
char port[6];
- sprintf(port, "%d", GetDefaultPort());
+ sprintf(port, "%d", GetListenPort());
const char * rootdescurl = 0;
const char * multicastif = 0;
{
char intClient[16];
char intPort[6];
+ string strDesc = "Bitcoin " + FormatFullVersion();
#ifndef __WXMSW__
r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
- port, port, lanaddr, 0, "TCP", 0);
+ port, port, lanaddr, strDesc.c_str(), "TCP", 0);
#else
r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
- port, port, lanaddr, 0, "TCP", 0, "0");
+ port, port, lanaddr, strDesc.c_str(), "TCP", 0, "0");
#endif
if(r!=UPNPCOMMAND_SUCCESS)
printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
if (fUseUPnP != fMapPort)
{
fUseUPnP = fMapPort;
- CWalletDB().WriteSetting("fUseUPnP", fUseUPnP);
+ WriteSetting("fUseUPnP", fUseUPnP);
}
if (fUseUPnP && vnThreadsRunning[5] < 1)
{
printf("Error: ThreadMapPort(ThreadMapPort) failed\n");
}
}
+#else
+void MapPort(bool /* unused fMapPort */)
+{
+ // Intentionally left blank.
+}
#endif
static const char *strDNSSeed[] = {
"bitseed.xf2.org",
"bitseed.bitcoin.org.uk",
+ "dnsseed.bluematt.me",
};
void DNSAddressSeed()
{
int found = 0;
- printf("Loading addresses from DNS seeds (could take a while)\n");
+ if (!fTestNet)
+ {
+ printf("Loading addresses from DNS seeds (could take a while)\n");
+ CAddrDB addrDB;
+ addrDB.TxnBegin();
- for (int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
- vector<CAddress> vaddr;
- if (Lookup(strDNSSeed[seed_idx], vaddr, NODE_NETWORK, true))
- {
- BOOST_FOREACH (CAddress& addr, vaddr)
+ for (int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
+ vector<CAddress> vaddr;
+ if (Lookup(strDNSSeed[seed_idx], vaddr, NODE_NETWORK, -1, true))
{
- if (addr.GetByte(3) != 127)
+ BOOST_FOREACH (CAddress& addr, vaddr)
{
- addr.nTime = 0;
- AddAddress(addr);
- found++;
+ if (addr.GetByte(3) != 127)
+ {
+ addr.nTime = 0;
+ AddAddress(addr, 0, &addrDB);
+ found++;
+ }
}
}
}
+
+ addrDB.TxnCommit(); // Save addresses (it's ok if this fails)
}
printf("%d addresses found from DNS seeds\n", found);
-
-
-
bool BindListenPort(string& strError)
{
strError = "";
int nOne = 1;
- addrLocalHost.port = htons(GetDefaultPort());
+ addrLocalHost.port = htons(GetListenPort());
#ifdef __WXMSW__
// Initialize Windows Sockets
return false;
}
-#ifdef BSD
+#ifdef SO_NOSIGPIPE
// Different way of disabling SIGPIPE on BSD
setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
#endif
memset(&sockaddr, 0, sizeof(sockaddr));
sockaddr.sin_family = AF_INET;
sockaddr.sin_addr.s_addr = INADDR_ANY; // bind to all IPs on this computer
- sockaddr.sin_port = htons(GetDefaultPort());
+ sockaddr.sin_port = htons(GetListenPort());
if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
{
int nErr = WSAGetLastError();
printf("ipv4 %s: %s\n", ifa->ifa_name, pszIP);
// Take the first IP that isn't loopback 127.x.x.x
- CAddress addr(*(unsigned int*)&s4->sin_addr, 0, nLocalServices);
+ CAddress addr(*(unsigned int*)&s4->sin_addr, GetListenPort(), nLocalServices);
if (addr.IsValid() && addr.GetByte(3) != 127)
{
addrLocalHost = addr;
printf("Error: CreateThread(ThreadIRCSeed) failed\n");
// Send and receive from sockets, accept connections
- pthread_t hThreadSocketHandler = CreateThread(ThreadSocketHandler, NULL, true);
+ CreateThread(ThreadSocketHandler, NULL, true);
// Initiate outbound connections
if (!CreateThread(ThreadOpenConnections, NULL))
printf("Error: CreateThread(ThreadMessageHandler) failed\n");
// Generate coins in the background
- GenerateBitcoins(fGenerateBitcoins);
+ GenerateBitcoins(fGenerateBitcoins, pwalletMain);
}
bool StopNode()