// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2011 The Bitcoin developers
+// Copyright (c) 2009-2012 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.
-
-
//
// Global state variables
//
CAddress addrLocalHost(CService("0.0.0.0", 0), nLocalServices);
static CNode* pnodeLocalHost = NULL;
uint64 nLocalHostNonce = 0;
-array<int, 10> vnThreadsRunning;
+array<int, THREAD_MAX> vnThreadsRunning;
static SOCKET hListenSocket = INVALID_SOCKET;
vector<CNode*> vNodes;
-
unsigned short GetListenPort()
{
return (unsigned short)(GetArg("-port", GetDefaultPort()));
+bool RecvLine(SOCKET hSocket, string& strLine)
+{
+ strLine = "";
+ loop
+ {
+ char c;
+ int nBytes = recv(hSocket, &c, 1, 0);
+ if (nBytes > 0)
+ {
+ if (c == '\n')
+ continue;
+ if (c == '\r')
+ return true;
+ strLine += c;
+ if (strLine.size() >= 9000)
+ return true;
+ }
+ else if (nBytes <= 0)
+ {
+ if (fShutdown)
+ return false;
+ if (nBytes < 0)
+ {
+ int nErr = WSAGetLastError();
+ if (nErr == WSAEMSGSIZE)
+ continue;
+ if (nErr == WSAEWOULDBLOCK || nErr == WSAEINTR || nErr == WSAEINPROGRESS)
+ {
+ Sleep(10);
+ continue;
+ }
+ }
+ if (!strLine.empty())
+ return true;
+ if (nBytes == 0)
+ {
+ // socket closed
+ printf("socket closed\n");
+ return false;
+ }
+ else
+ {
+ // socket error
+ int nErr = WSAGetLastError();
+ printf("recv failed: %d\n", nErr);
+ return false;
+ }
+ }
+ }
+}
+
bool GetMyExternalIP2(const CService& addrConnect, const char* pszGet, const char* pszKeyword, CNetAddr& ipRet)
/// when NTP implemented, change to just nTime = GetAdjustedTime()
int64 nTime = (fInbound ? GetAdjustedTime() : GetTime());
CAddress addrYou = (fUseProxy ? CAddress(CService("0.0.0.0",0)) : addr);
- CAddress addrMe = (fUseProxy ? CAddress(CService("0.0.0.0",0)) : addrLocalHost);
+ CAddress addrMe = (fUseProxy || !addrLocalHost.IsRoutable() ? CAddress(CService("0.0.0.0",0)) : addrLocalHost);
RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()), nBestHeight);
IMPLEMENT_RANDOMIZE_STACK(ThreadSocketHandler(parg));
try
{
- vnThreadsRunning[0]++;
+ vnThreadsRunning[THREAD_SOCKETHANDLER]++;
ThreadSocketHandler2(parg);
- vnThreadsRunning[0]--;
+ vnThreadsRunning[THREAD_SOCKETHANDLER]--;
}
catch (std::exception& e) {
- vnThreadsRunning[0]--;
+ vnThreadsRunning[THREAD_SOCKETHANDLER]--;
PrintException(&e, "ThreadSocketHandler()");
} catch (...) {
- vnThreadsRunning[0]--;
+ vnThreadsRunning[THREAD_SOCKETHANDLER]--;
throw; // support pthread_cancel()
}
printf("ThreadSocketHandler exiting\n");
}
}
- vnThreadsRunning[0]--;
+ vnThreadsRunning[THREAD_SOCKETHANDLER]--;
int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
- vnThreadsRunning[0]++;
+ vnThreadsRunning[THREAD_SOCKETHANDLER]++;
if (fShutdown)
return;
if (nSelect == SOCKET_ERROR)
struct sockaddr_in sockaddr;
socklen_t len = sizeof(sockaddr);
SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
- CAddress addr(sockaddr);
+ CAddress addr;
int nInbound = 0;
+ if (hSocket != INVALID_SOCKET)
+ addr = CAddress(sockaddr);
+
CRITICAL_BLOCK(cs_vNodes)
BOOST_FOREACH(CNode* pnode, vNodes)
if (pnode->fInbound)
nInbound++;
+
if (hSocket == INVALID_SOCKET)
{
if (WSAGetLastError() != WSAEWOULDBLOCK)
IMPLEMENT_RANDOMIZE_STACK(ThreadMapPort(parg));
try
{
- vnThreadsRunning[5]++;
+ vnThreadsRunning[THREAD_UPNP]++;
ThreadMapPort2(parg);
- vnThreadsRunning[5]--;
+ vnThreadsRunning[THREAD_UPNP]--;
}
catch (std::exception& e) {
- vnThreadsRunning[5]--;
+ vnThreadsRunning[THREAD_UPNP]--;
PrintException(&e, "ThreadMapPort()");
} catch (...) {
- vnThreadsRunning[5]--;
+ vnThreadsRunning[THREAD_UPNP]--;
PrintException(NULL, "ThreadMapPort()");
}
printf("ThreadMapPort exiting\n");
r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
if (r == 1)
{
+ if (!addrLocalHost.IsRoutable())
+ {
+ char externalIPAddress[40];
+ r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
+ if(r != UPNPCOMMAND_SUCCESS)
+ printf("UPnP: GetExternalIPAddress() returned %d\n", r);
+ else
+ {
+ if(externalIPAddress[0])
+ {
+ printf("UPnP: ExternalIPAddress = %s\n", externalIPAddress);
+ CAddress addrExternalFromUPnP(CService(externalIPAddress, 0), nLocalServices);
+ if (addrExternalFromUPnP.IsRoutable())
+ addrLocalHost = addrExternalFromUPnP;
+ }
+ else
+ printf("UPnP: GetExternalIPAddress failed.\n");
+ }
+ }
+
string strDesc = "Bitcoin " + FormatFullVersion();
#ifndef UPNPDISCOVER_SUCCESS
/* miniupnpc 1.5 */
fUseUPnP = fMapPort;
WriteSetting("fUseUPnP", fUseUPnP);
}
- if (fUseUPnP && vnThreadsRunning[5] < 1)
+ if (fUseUPnP && vnThreadsRunning[THREAD_UPNP] < 1)
{
if (!CreateThread(ThreadMapPort, NULL))
printf("Error: ThreadMapPort(ThreadMapPort) failed\n");
IMPLEMENT_RANDOMIZE_STACK(ThreadDNSAddressSeed(parg));
try
{
- vnThreadsRunning[6]++;
+ vnThreadsRunning[THREAD_DNSSEED]++;
ThreadDNSAddressSeed2(parg);
- vnThreadsRunning[6]--;
+ vnThreadsRunning[THREAD_DNSSEED]--;
}
catch (std::exception& e) {
- vnThreadsRunning[6]--;
+ vnThreadsRunning[THREAD_DNSSEED]--;
PrintException(&e, "ThreadDNSAddressSeed()");
} catch (...) {
- vnThreadsRunning[6]--;
+ vnThreadsRunning[THREAD_DNSSEED]--;
throw; // support pthread_cancel()
}
printf("ThreadDNSAddressSeed exiting\n");
IMPLEMENT_RANDOMIZE_STACK(ThreadOpenConnections(parg));
try
{
- vnThreadsRunning[1]++;
+ vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
ThreadOpenConnections2(parg);
- vnThreadsRunning[1]--;
+ vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
}
catch (std::exception& e) {
- vnThreadsRunning[1]--;
+ vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
PrintException(&e, "ThreadOpenConnections()");
} catch (...) {
- vnThreadsRunning[1]--;
+ vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
PrintException(NULL, "ThreadOpenConnections()");
}
printf("ThreadOpenConnections exiting\n");
int64 nStart = GetTime();
loop
{
- // Limit outbound connections
- vnThreadsRunning[1]--;
+ vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
Sleep(500);
+ vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
+ if (fShutdown)
+ return;
+
+ // Limit outbound connections
loop
{
int nOutbound = 0;
nMaxOutboundConnections = min(nMaxOutboundConnections, (int)GetArg("-maxconnections", 125));
if (nOutbound < nMaxOutboundConnections)
break;
+ vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
Sleep(2000);
+ vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
if (fShutdown)
return;
}
- vnThreadsRunning[1]++;
- if (fShutdown)
- return;
bool fAddSeeds = false;
IMPLEMENT_RANDOMIZE_STACK(ThreadOpenAddedConnections(parg));
try
{
- vnThreadsRunning[7]++;
+ vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
ThreadOpenAddedConnections2(parg);
- vnThreadsRunning[7]--;
+ vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
}
catch (std::exception& e) {
- vnThreadsRunning[7]--;
+ vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
PrintException(&e, "ThreadOpenAddedConnections()");
} catch (...) {
- vnThreadsRunning[7]--;
+ vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
PrintException(NULL, "ThreadOpenAddedConnections()");
}
printf("ThreadOpenAddedConnections exiting\n");
}
if (fShutdown)
return;
- vnThreadsRunning[7]--;
+ vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
Sleep(120000); // Retry every 2 minutes
- vnThreadsRunning[7]++;
+ vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
if (fShutdown)
return;
}
FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect))
return false;
- vnThreadsRunning[1]--;
+ vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
CNode* pnode = ConnectNode(addrConnect);
- vnThreadsRunning[1]++;
+ vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
if (fShutdown)
return false;
if (!pnode)
IMPLEMENT_RANDOMIZE_STACK(ThreadMessageHandler(parg));
try
{
- vnThreadsRunning[2]++;
+ vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
ThreadMessageHandler2(parg);
- vnThreadsRunning[2]--;
+ vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
}
catch (std::exception& e) {
- vnThreadsRunning[2]--;
+ vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
PrintException(&e, "ThreadMessageHandler()");
} catch (...) {
- vnThreadsRunning[2]--;
+ vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
PrintException(NULL, "ThreadMessageHandler()");
}
printf("ThreadMessageHandler exiting\n");
// Wait and allow messages to bunch up.
// Reduce vnThreadsRunning so StopNode has permission to exit while
// we're sleeping, but we must always check fShutdown after doing this.
- vnThreadsRunning[2]--;
+ vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
Sleep(100);
if (fRequestShutdown)
Shutdown(NULL);
- vnThreadsRunning[2]++;
+ vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
if (fShutdown)
return;
}
fShutdown = true;
nTransactionsUpdated++;
int64 nStart = GetTime();
- while (vnThreadsRunning[0] > 0 || vnThreadsRunning[2] > 0 || vnThreadsRunning[3] > 0 || vnThreadsRunning[4] > 0
- || (fHaveUPnP && vnThreadsRunning[5] > 0) || vnThreadsRunning[6] > 0 || vnThreadsRunning[7] > 0
- )
+ do
{
+ int nThreadsRunning = 0;
+ for (int n = 0; n < THREAD_MAX; n++)
+ nThreadsRunning += vnThreadsRunning[n];
+ if (nThreadsRunning == 0)
+ break;
if (GetTime() - nStart > 20)
break;
Sleep(20);
- }
- if (vnThreadsRunning[0] > 0) printf("ThreadSocketHandler still running\n");
- if (vnThreadsRunning[1] > 0) printf("ThreadOpenConnections still running\n");
- if (vnThreadsRunning[2] > 0) printf("ThreadMessageHandler still running\n");
- if (vnThreadsRunning[3] > 0) printf("ThreadBitcoinMiner still running\n");
- if (vnThreadsRunning[4] > 0) printf("ThreadRPCServer still running\n");
- if (fHaveUPnP && vnThreadsRunning[5] > 0) printf("ThreadMapPort still running\n");
- if (vnThreadsRunning[6] > 0) printf("ThreadDNSAddressSeed still running\n");
- if (vnThreadsRunning[7] > 0) printf("ThreadOpenAddedConnections still running\n");
- while (vnThreadsRunning[2] > 0 || vnThreadsRunning[4] > 0)
+ } while(true);
+ if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
+ if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
+ if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
+ if (vnThreadsRunning[THREAD_MINER] > 0) printf("ThreadBitcoinMiner still running\n");
+ if (vnThreadsRunning[THREAD_RPCSERVER] > 0) printf("ThreadRPCServer still running\n");
+ if (fHaveUPnP && vnThreadsRunning[THREAD_UPNP] > 0) printf("ThreadMapPort still running\n");
+ if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
+ if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
+ while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCSERVER] > 0)
Sleep(20);
Sleep(50);