raw
genesis                 1 // Copyright (c) 2009-2010 Satoshi Nakamoto
genesis 2 // Copyright (c) 2009-2012 The Bitcoin developers
genesis 3 // Distributed under the MIT/X11 software license, see the accompanying
genesis 4 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
genesis 5
genesis 6 #include "headers.h"
genesis 7 #include "irc.h"
genesis 8 #include "db.h"
genesis 9 #include "net.h"
genesis 10 #include "init.h"
genesis 11 #include "strlcpy.h"
genesis 12
genesis 13 #ifdef WIN32
genesis 14 #include <string.h>
genesis 15 #endif
genesis 16
genesis 17 #ifdef USE_UPNP
genesis 18 #include <miniupnpc/miniwget.h>
genesis 19 #include <miniupnpc/miniupnpc.h>
genesis 20 #include <miniupnpc/upnpcommands.h>
genesis 21 #include <miniupnpc/upnperrors.h>
genesis 22 #endif
genesis 23
genesis 24 using namespace std;
genesis 25 using namespace boost;
genesis 26
genesis 27 static const int MAX_OUTBOUND_CONNECTIONS = 8;
genesis 28
genesis 29 void ThreadMessageHandler2(void* parg);
genesis 30 void ThreadSocketHandler2(void* parg);
genesis 31 void ThreadOpenConnections2(void* parg);
genesis 32 #ifdef USE_UPNP
genesis 33 void ThreadMapPort2(void* parg);
genesis 34 #endif
genesis 35 void ThreadDNSAddressSeed2(void* parg);
genesis 36 bool OpenNetworkConnection(const CAddress& addrConnect);
genesis 37
genesis 38
genesis 39
genesis 40
genesis 41
genesis 42 //
genesis 43 // Global state variables
genesis 44 //
genesis 45 bool fClient = false;
genesis 46 bool fAllowDNS = false;
genesis 47 uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK);
genesis 48 CAddress addrLocalHost("0.0.0.0", 0, false, nLocalServices);
genesis 49 static CNode* pnodeLocalHost = NULL;
genesis 50 uint64 nLocalHostNonce = 0;
genesis 51 array<int, 10> vnThreadsRunning;
genesis 52 static SOCKET hListenSocket = INVALID_SOCKET;
genesis 53
genesis 54 vector<CNode*> vNodes;
genesis 55 CCriticalSection cs_vNodes;
genesis 56 map<vector<unsigned char>, CAddress> mapAddresses;
genesis 57 CCriticalSection cs_mapAddresses;
genesis 58 map<CInv, CDataStream> mapRelay;
genesis 59 deque<pair<int64, CInv> > vRelayExpiration;
genesis 60 CCriticalSection cs_mapRelay;
genesis 61 map<CInv, int64> mapAlreadyAskedFor;
genesis 62
genesis 63 // Settings
genesis 64 int fUseProxy = false;
genesis 65 int nConnectTimeout = 5000;
genesis 66 CAddress addrProxy("127.0.0.1",9050);
genesis 67
genesis 68
genesis 69
genesis 70
genesis 71 unsigned short GetListenPort()
genesis 72 {
genesis 73 return (unsigned short)(GetArg("-port", GetDefaultPort()));
genesis 74 }
genesis 75
genesis 76 void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd)
genesis 77 {
genesis 78 // Filter out duplicate requests
genesis 79 if (pindexBegin == pindexLastGetBlocksBegin && hashEnd == hashLastGetBlocksEnd)
genesis 80 return;
genesis 81 pindexLastGetBlocksBegin = pindexBegin;
genesis 82 hashLastGetBlocksEnd = hashEnd;
genesis 83
genesis 84 PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd);
genesis 85 }
genesis 86
genesis 87
genesis 88
genesis 89
genesis 90
genesis 91 bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet, int nTimeout)
genesis 92 {
genesis 93 hSocketRet = INVALID_SOCKET;
genesis 94
genesis 95 SOCKET hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
genesis 96 if (hSocket == INVALID_SOCKET)
genesis 97 return false;
genesis 98 #ifdef SO_NOSIGPIPE
genesis 99 int set = 1;
genesis 100 setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
genesis 101 #endif
genesis 102
genesis 103 bool fProxy = (fUseProxy && addrConnect.IsRoutable());
genesis 104 struct sockaddr_in sockaddr = (fProxy ? addrProxy.GetSockAddr() : addrConnect.GetSockAddr());
genesis 105
genesis 106 #ifdef WIN32
genesis 107 u_long fNonblock = 1;
genesis 108 if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
genesis 109 #else
genesis 110 int fFlags = fcntl(hSocket, F_GETFL, 0);
genesis 111 if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == -1)
genesis 112 #endif
genesis 113 {
genesis 114 closesocket(hSocket);
genesis 115 return false;
genesis 116 }
genesis 117
genesis 118
genesis 119 if (connect(hSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
genesis 120 {
genesis 121 // WSAEINVAL is here because some legacy version of winsock uses it
genesis 122 if (WSAGetLastError() == WSAEINPROGRESS || WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINVAL)
genesis 123 {
genesis 124 struct timeval timeout;
genesis 125 timeout.tv_sec = nTimeout / 1000;
genesis 126 timeout.tv_usec = (nTimeout % 1000) * 1000;
genesis 127
genesis 128 fd_set fdset;
genesis 129 FD_ZERO(&fdset);
genesis 130 FD_SET(hSocket, &fdset);
genesis 131 int nRet = select(hSocket + 1, NULL, &fdset, NULL, &timeout);
genesis 132 if (nRet == 0)
genesis 133 {
genesis 134 printf("connection timeout\n");
genesis 135 closesocket(hSocket);
genesis 136 return false;
genesis 137 }
genesis 138 if (nRet == SOCKET_ERROR)
genesis 139 {
genesis 140 printf("select() for connection failed: %i\n",WSAGetLastError());
genesis 141 closesocket(hSocket);
genesis 142 return false;
genesis 143 }
genesis 144 socklen_t nRetSize = sizeof(nRet);
genesis 145 #ifdef WIN32
genesis 146 if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, (char*)(&nRet), &nRetSize) == SOCKET_ERROR)
genesis 147 #else
genesis 148 if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, &nRet, &nRetSize) == SOCKET_ERROR)
genesis 149 #endif
genesis 150 {
genesis 151 printf("getsockopt() for connection failed: %i\n",WSAGetLastError());
genesis 152 closesocket(hSocket);
genesis 153 return false;
genesis 154 }
genesis 155 if (nRet != 0)
genesis 156 {
genesis 157 printf("connect() failed after select(): %s\n",strerror(nRet));
genesis 158 closesocket(hSocket);
genesis 159 return false;
genesis 160 }
genesis 161 }
genesis 162 #ifdef WIN32
genesis 163 else if (WSAGetLastError() != WSAEISCONN)
genesis 164 #else
genesis 165 else
genesis 166 #endif
genesis 167 {
genesis 168 printf("connect() failed: %i\n",WSAGetLastError());
genesis 169 closesocket(hSocket);
genesis 170 return false;
genesis 171 }
genesis 172 }
genesis 173
genesis 174 /*
genesis 175 this isn't even strictly necessary
genesis 176 CNode::ConnectNode immediately turns the socket back to non-blocking
genesis 177 but we'll turn it back to blocking just in case
genesis 178 */
genesis 179 #ifdef WIN32
genesis 180 fNonblock = 0;
genesis 181 if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
genesis 182 #else
genesis 183 fFlags = fcntl(hSocket, F_GETFL, 0);
genesis 184 if (fcntl(hSocket, F_SETFL, fFlags & !O_NONBLOCK) == SOCKET_ERROR)
genesis 185 #endif
genesis 186 {
genesis 187 closesocket(hSocket);
genesis 188 return false;
genesis 189 }
genesis 190
genesis 191 if (fProxy)
genesis 192 {
genesis 193 printf("proxy connecting %s\n", addrConnect.ToString().c_str());
genesis 194 char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user";
genesis 195 memcpy(pszSocks4IP + 2, &addrConnect.port, 2);
genesis 196 memcpy(pszSocks4IP + 4, &addrConnect.ip, 4);
genesis 197 char* pszSocks4 = pszSocks4IP;
genesis 198 int nSize = sizeof(pszSocks4IP);
genesis 199
genesis 200 int ret = send(hSocket, pszSocks4, nSize, MSG_NOSIGNAL);
genesis 201 if (ret != nSize)
genesis 202 {
genesis 203 closesocket(hSocket);
genesis 204 return error("Error sending to proxy");
genesis 205 }
genesis 206 char pchRet[8];
genesis 207 if (recv(hSocket, pchRet, 8, 0) != 8)
genesis 208 {
genesis 209 closesocket(hSocket);
genesis 210 return error("Error reading proxy response");
genesis 211 }
genesis 212 if (pchRet[1] != 0x5a)
genesis 213 {
genesis 214 closesocket(hSocket);
genesis 215 if (pchRet[1] != 0x5b)
genesis 216 printf("ERROR: Proxy returned error %d\n", pchRet[1]);
genesis 217 return false;
genesis 218 }
genesis 219 printf("proxy connected %s\n", addrConnect.ToString().c_str());
genesis 220 }
genesis 221
genesis 222 hSocketRet = hSocket;
genesis 223 return true;
genesis 224 }
genesis 225
genesis 226 // portDefault is in host order
genesis 227 bool Lookup(const char *pszName, vector<CAddress>& vaddr, int nServices, int nMaxSolutions, bool fAllowLookup, int portDefault, bool fAllowPort)
genesis 228 {
genesis 229 vaddr.clear();
genesis 230 if (pszName[0] == 0)
genesis 231 return false;
genesis 232 int port = portDefault;
genesis 233 char psz[256];
genesis 234 char *pszHost = psz;
genesis 235 strlcpy(psz, pszName, sizeof(psz));
genesis 236 if (fAllowPort)
genesis 237 {
genesis 238 char* pszColon = strrchr(psz+1,':');
genesis 239 char *pszPortEnd = NULL;
genesis 240 int portParsed = pszColon ? strtoul(pszColon+1, &pszPortEnd, 10) : 0;
genesis 241 if (pszColon && pszPortEnd && pszPortEnd[0] == 0)
genesis 242 {
genesis 243 if (psz[0] == '[' && pszColon[-1] == ']')
genesis 244 {
genesis 245 // Future: enable IPv6 colon-notation inside []
genesis 246 pszHost = psz+1;
genesis 247 pszColon[-1] = 0;
genesis 248 }
genesis 249 else
genesis 250 pszColon[0] = 0;
genesis 251 port = portParsed;
genesis 252 if (port < 0 || port > USHRT_MAX)
genesis 253 port = USHRT_MAX;
genesis 254 }
genesis 255 }
genesis 256
genesis 257 unsigned int addrIP = inet_addr(pszHost);
genesis 258 if (addrIP != INADDR_NONE)
genesis 259 {
genesis 260 // valid IP address passed
genesis 261 vaddr.push_back(CAddress(addrIP, port, nServices));
genesis 262 return true;
genesis 263 }
genesis 264
genesis 265 if (!fAllowLookup)
genesis 266 return false;
genesis 267
genesis 268 struct hostent* phostent = gethostbyname(pszHost);
genesis 269 if (!phostent)
genesis 270 return false;
genesis 271
genesis 272 if (phostent->h_addrtype != AF_INET)
genesis 273 return false;
genesis 274
genesis 275 char** ppAddr = phostent->h_addr_list;
genesis 276 while (*ppAddr != NULL && vaddr.size() != nMaxSolutions)
genesis 277 {
genesis 278 CAddress addr(((struct in_addr*)ppAddr[0])->s_addr, port, nServices);
genesis 279 if (addr.IsValid())
genesis 280 vaddr.push_back(addr);
genesis 281 ppAddr++;
genesis 282 }
genesis 283
genesis 284 return (vaddr.size() > 0);
genesis 285 }
genesis 286
genesis 287 // portDefault is in host order
genesis 288 bool Lookup(const char *pszName, CAddress& addr, int nServices, bool fAllowLookup, int portDefault, bool fAllowPort)
genesis 289 {
genesis 290 vector<CAddress> vaddr;
genesis 291 bool fRet = Lookup(pszName, vaddr, nServices, 1, fAllowLookup, portDefault, fAllowPort);
genesis 292 if (fRet)
genesis 293 addr = vaddr[0];
genesis 294 return fRet;
genesis 295 }
genesis 296
genesis 297 bool GetMyExternalIP2(const CAddress& addrConnect, const char* pszGet, const char* pszKeyword, unsigned int& ipRet)
genesis 298 {
genesis 299 SOCKET hSocket;
genesis 300 if (!ConnectSocket(addrConnect, hSocket))
genesis 301 return error("GetMyExternalIP() : connection to %s failed", addrConnect.ToString().c_str());
genesis 302
genesis 303 send(hSocket, pszGet, strlen(pszGet), MSG_NOSIGNAL);
genesis 304
genesis 305 string strLine;
genesis 306 while (RecvLine(hSocket, strLine))
genesis 307 {
genesis 308 if (strLine.empty()) // HTTP response is separated from headers by blank line
genesis 309 {
genesis 310 loop
genesis 311 {
genesis 312 if (!RecvLine(hSocket, strLine))
genesis 313 {
genesis 314 closesocket(hSocket);
genesis 315 return false;
genesis 316 }
genesis 317 if (pszKeyword == NULL)
genesis 318 break;
genesis 319 if (strLine.find(pszKeyword) != -1)
genesis 320 {
genesis 321 strLine = strLine.substr(strLine.find(pszKeyword) + strlen(pszKeyword));
genesis 322 break;
genesis 323 }
genesis 324 }
genesis 325 closesocket(hSocket);
genesis 326 if (strLine.find("<") != -1)
genesis 327 strLine = strLine.substr(0, strLine.find("<"));
genesis 328 strLine = strLine.substr(strspn(strLine.c_str(), " \t\n\r"));
genesis 329 while (strLine.size() > 0 && isspace(strLine[strLine.size()-1]))
genesis 330 strLine.resize(strLine.size()-1);
genesis 331 CAddress addr(strLine,0,true);
genesis 332 printf("GetMyExternalIP() received [%s] %s\n", strLine.c_str(), addr.ToString().c_str());
genesis 333 if (addr.ip == 0 || addr.ip == INADDR_NONE || !addr.IsRoutable())
genesis 334 return false;
genesis 335 ipRet = addr.ip;
genesis 336 return true;
genesis 337 }
genesis 338 }
genesis 339 closesocket(hSocket);
genesis 340 return error("GetMyExternalIP() : connection closed");
genesis 341 }
genesis 342
genesis 343 // We now get our external IP from the IRC server first and only use this as a backup
genesis 344 bool GetMyExternalIP(unsigned int& ipRet)
genesis 345 {
genesis 346 CAddress addrConnect;
genesis 347 const char* pszGet;
genesis 348 const char* pszKeyword;
genesis 349
genesis 350 if (fUseProxy)
genesis 351 return false;
genesis 352
genesis 353 for (int nLookup = 0; nLookup <= 1; nLookup++)
genesis 354 for (int nHost = 1; nHost <= 2; nHost++)
genesis 355 {
genesis 356 // We should be phasing out our use of sites like these. If we need
genesis 357 // replacements, we should ask for volunteers to put this simple
genesis 358 // php file on their webserver that prints the client IP:
genesis 359 // <?php echo $_SERVER["REMOTE_ADDR"]; ?>
genesis 360 if (nHost == 1)
genesis 361 {
genesis 362 addrConnect = CAddress("91.198.22.70",80); // checkip.dyndns.org
genesis 363
genesis 364 if (nLookup == 1)
genesis 365 {
genesis 366 CAddress addrIP("checkip.dyndns.org", 80, true);
genesis 367 if (addrIP.IsValid())
genesis 368 addrConnect = addrIP;
genesis 369 }
genesis 370
genesis 371 pszGet = "GET / HTTP/1.1\r\n"
genesis 372 "Host: checkip.dyndns.org\r\n"
genesis 373 "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
genesis 374 "Connection: close\r\n"
genesis 375 "\r\n";
genesis 376
genesis 377 pszKeyword = "Address:";
genesis 378 }
genesis 379 else if (nHost == 2)
genesis 380 {
genesis 381 addrConnect = CAddress("74.208.43.192", 80); // www.showmyip.com
genesis 382
genesis 383 if (nLookup == 1)
genesis 384 {
genesis 385 CAddress addrIP("www.showmyip.com", 80, true);
genesis 386 if (addrIP.IsValid())
genesis 387 addrConnect = addrIP;
genesis 388 }
genesis 389
genesis 390 pszGet = "GET /simple/ HTTP/1.1\r\n"
genesis 391 "Host: www.showmyip.com\r\n"
genesis 392 "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
genesis 393 "Connection: close\r\n"
genesis 394 "\r\n";
genesis 395
genesis 396 pszKeyword = NULL; // Returns just IP address
genesis 397 }
genesis 398
genesis 399 if (GetMyExternalIP2(addrConnect, pszGet, pszKeyword, ipRet))
genesis 400 return true;
genesis 401 }
genesis 402
genesis 403 return false;
genesis 404 }
genesis 405
genesis 406 void ThreadGetMyExternalIP(void* parg)
genesis 407 {
genesis 408 // Wait for IRC to get it first
genesis 409 if (!GetBoolArg("-noirc"))
genesis 410 {
genesis 411 for (int i = 0; i < 2 * 60; i++)
genesis 412 {
genesis 413 Sleep(1000);
genesis 414 if (fGotExternalIP || fShutdown)
genesis 415 return;
genesis 416 }
genesis 417 }
genesis 418
genesis 419 // Fallback in case IRC fails to get it
genesis 420 if (GetMyExternalIP(addrLocalHost.ip))
genesis 421 {
genesis 422 printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
genesis 423 if (addrLocalHost.IsRoutable())
genesis 424 {
genesis 425 // If we already connected to a few before we had our IP, go back and addr them.
genesis 426 // setAddrKnown automatically filters any duplicate sends.
genesis 427 CAddress addr(addrLocalHost);
genesis 428 addr.nTime = GetAdjustedTime();
genesis 429 CRITICAL_BLOCK(cs_vNodes)
genesis 430 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 431 pnode->PushAddress(addr);
genesis 432 }
genesis 433 }
genesis 434 }
genesis 435
genesis 436
genesis 437
genesis 438
genesis 439
genesis 440 bool AddAddress(CAddress addr, int64 nTimePenalty, CAddrDB *pAddrDB)
genesis 441 {
genesis 442 if (!addr.IsRoutable())
genesis 443 return false;
genesis 444 if (addr.ip == addrLocalHost.ip)
genesis 445 return false;
genesis 446 addr.nTime = max((int64)0, (int64)addr.nTime - nTimePenalty);
genesis 447 bool fUpdated = false;
genesis 448 bool fNew = false;
genesis 449 CAddress addrFound = addr;
genesis 450
genesis 451 CRITICAL_BLOCK(cs_mapAddresses)
genesis 452 {
genesis 453 map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
genesis 454 if (it == mapAddresses.end())
genesis 455 {
genesis 456 // New address
genesis 457 printf("AddAddress(%s)\n", addr.ToString().c_str());
genesis 458 mapAddresses.insert(make_pair(addr.GetKey(), addr));
genesis 459 fUpdated = true;
genesis 460 fNew = true;
genesis 461 }
genesis 462 else
genesis 463 {
genesis 464 addrFound = (*it).second;
genesis 465 if ((addrFound.nServices | addr.nServices) != addrFound.nServices)
genesis 466 {
genesis 467 // Services have been added
genesis 468 addrFound.nServices |= addr.nServices;
genesis 469 fUpdated = true;
genesis 470 }
genesis 471 bool fCurrentlyOnline = (GetAdjustedTime() - addr.nTime < 24 * 60 * 60);
genesis 472 int64 nUpdateInterval = (fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60);
genesis 473 if (addrFound.nTime < addr.nTime - nUpdateInterval)
genesis 474 {
genesis 475 // Periodically update most recently seen time
genesis 476 addrFound.nTime = addr.nTime;
genesis 477 fUpdated = true;
genesis 478 }
genesis 479 }
genesis 480 }
genesis 481 // There is a nasty deadlock bug if this is done inside the cs_mapAddresses
genesis 482 // CRITICAL_BLOCK:
genesis 483 // Thread 1: begin db transaction (locks inside-db-mutex)
genesis 484 // then AddAddress (locks cs_mapAddresses)
genesis 485 // Thread 2: AddAddress (locks cs_mapAddresses)
genesis 486 // ... then db operation hangs waiting for inside-db-mutex
genesis 487 if (fUpdated)
genesis 488 {
genesis 489 if (pAddrDB)
genesis 490 pAddrDB->WriteAddress(addrFound);
genesis 491 else
genesis 492 CAddrDB().WriteAddress(addrFound);
genesis 493 }
genesis 494 return fNew;
genesis 495 }
genesis 496
genesis 497 void AddressCurrentlyConnected(const CAddress& addr)
genesis 498 {
genesis 499 CAddress *paddrFound = NULL;
genesis 500
genesis 501 CRITICAL_BLOCK(cs_mapAddresses)
genesis 502 {
genesis 503 // Only if it's been published already
genesis 504 map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
genesis 505 if (it != mapAddresses.end())
genesis 506 paddrFound = &(*it).second;
genesis 507 }
genesis 508
genesis 509 if (paddrFound)
genesis 510 {
genesis 511 int64 nUpdateInterval = 20 * 60;
genesis 512 if (paddrFound->nTime < GetAdjustedTime() - nUpdateInterval)
genesis 513 {
genesis 514 // Periodically update most recently seen time
genesis 515 paddrFound->nTime = GetAdjustedTime();
genesis 516 CAddrDB addrdb;
genesis 517 addrdb.WriteAddress(*paddrFound);
genesis 518 }
genesis 519 }
genesis 520 }
genesis 521
genesis 522
genesis 523
genesis 524
genesis 525
genesis 526 void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1)
genesis 527 {
genesis 528 // If the dialog might get closed before the reply comes back,
genesis 529 // call this in the destructor so it doesn't get called after it's deleted.
genesis 530 CRITICAL_BLOCK(cs_vNodes)
genesis 531 {
genesis 532 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 533 {
genesis 534 CRITICAL_BLOCK(pnode->cs_mapRequests)
genesis 535 {
genesis 536 for (map<uint256, CRequestTracker>::iterator mi = pnode->mapRequests.begin(); mi != pnode->mapRequests.end();)
genesis 537 {
genesis 538 CRequestTracker& tracker = (*mi).second;
genesis 539 if (tracker.fn == fn && tracker.param1 == param1)
genesis 540 pnode->mapRequests.erase(mi++);
genesis 541 else
genesis 542 mi++;
genesis 543 }
genesis 544 }
genesis 545 }
genesis 546 }
genesis 547 }
genesis 548
genesis 549
genesis 550
genesis 551
genesis 552
genesis 553
genesis 554
genesis 555 //
genesis 556 // Subscription methods for the broadcast and subscription system.
genesis 557 // Channel numbers are message numbers, i.e. MSG_TABLE and MSG_PRODUCT.
genesis 558 //
genesis 559 // The subscription system uses a meet-in-the-middle strategy.
genesis 560 // With 100,000 nodes, if senders broadcast to 1000 random nodes and receivers
genesis 561 // subscribe to 1000 random nodes, 99.995% (1 - 0.99^1000) of messages will get through.
genesis 562 //
genesis 563
genesis 564 bool AnySubscribed(unsigned int nChannel)
genesis 565 {
genesis 566 if (pnodeLocalHost->IsSubscribed(nChannel))
genesis 567 return true;
genesis 568 CRITICAL_BLOCK(cs_vNodes)
genesis 569 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 570 if (pnode->IsSubscribed(nChannel))
genesis 571 return true;
genesis 572 return false;
genesis 573 }
genesis 574
genesis 575 bool CNode::IsSubscribed(unsigned int nChannel)
genesis 576 {
genesis 577 if (nChannel >= vfSubscribe.size())
genesis 578 return false;
genesis 579 return vfSubscribe[nChannel];
genesis 580 }
genesis 581
genesis 582 void CNode::Subscribe(unsigned int nChannel, unsigned int nHops)
genesis 583 {
genesis 584 if (nChannel >= vfSubscribe.size())
genesis 585 return;
genesis 586
genesis 587 if (!AnySubscribed(nChannel))
genesis 588 {
genesis 589 // Relay subscribe
genesis 590 CRITICAL_BLOCK(cs_vNodes)
genesis 591 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 592 if (pnode != this)
genesis 593 pnode->PushMessage("subscribe", nChannel, nHops);
genesis 594 }
genesis 595
genesis 596 vfSubscribe[nChannel] = true;
genesis 597 }
genesis 598
genesis 599 void CNode::CancelSubscribe(unsigned int nChannel)
genesis 600 {
genesis 601 if (nChannel >= vfSubscribe.size())
genesis 602 return;
genesis 603
genesis 604 // Prevent from relaying cancel if wasn't subscribed
genesis 605 if (!vfSubscribe[nChannel])
genesis 606 return;
genesis 607 vfSubscribe[nChannel] = false;
genesis 608
genesis 609 if (!AnySubscribed(nChannel))
genesis 610 {
genesis 611 // Relay subscription cancel
genesis 612 CRITICAL_BLOCK(cs_vNodes)
genesis 613 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 614 if (pnode != this)
genesis 615 pnode->PushMessage("sub-cancel", nChannel);
genesis 616 }
genesis 617 }
genesis 618
genesis 619
genesis 620
genesis 621
genesis 622
genesis 623
genesis 624
genesis 625
genesis 626
genesis 627 CNode* FindNode(unsigned int ip)
genesis 628 {
genesis 629 CRITICAL_BLOCK(cs_vNodes)
genesis 630 {
genesis 631 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 632 if (pnode->addr.ip == ip)
genesis 633 return (pnode);
genesis 634 }
genesis 635 return NULL;
genesis 636 }
genesis 637
genesis 638 CNode* FindNode(CAddress addr)
genesis 639 {
genesis 640 CRITICAL_BLOCK(cs_vNodes)
genesis 641 {
genesis 642 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 643 if (pnode->addr == addr)
genesis 644 return (pnode);
genesis 645 }
genesis 646 return NULL;
genesis 647 }
genesis 648
genesis 649 CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
genesis 650 {
genesis 651 if (addrConnect.ip == addrLocalHost.ip)
genesis 652 return NULL;
genesis 653
genesis 654 // Look for an existing connection
genesis 655 CNode* pnode = FindNode(addrConnect.ip);
genesis 656 if (pnode)
genesis 657 {
genesis 658 if (nTimeout != 0)
genesis 659 pnode->AddRef(nTimeout);
genesis 660 else
genesis 661 pnode->AddRef();
genesis 662 return pnode;
genesis 663 }
genesis 664
genesis 665 /// debug print
genesis 666 printf("trying connection %s lastseen=%.1fhrs lasttry=%.1fhrs\n",
genesis 667 addrConnect.ToString().c_str(),
genesis 668 (double)(addrConnect.nTime - GetAdjustedTime())/3600.0,
genesis 669 (double)(addrConnect.nLastTry - GetAdjustedTime())/3600.0);
genesis 670
genesis 671 CRITICAL_BLOCK(cs_mapAddresses)
genesis 672 mapAddresses[addrConnect.GetKey()].nLastTry = GetAdjustedTime();
genesis 673
genesis 674 // Connect
genesis 675 SOCKET hSocket;
genesis 676 if (ConnectSocket(addrConnect, hSocket))
genesis 677 {
genesis 678 /// debug print
genesis 679 printf("connected %s\n", addrConnect.ToString().c_str());
genesis 680
genesis 681 // Set to nonblocking
genesis 682 #ifdef WIN32
genesis 683 u_long nOne = 1;
genesis 684 if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
genesis 685 printf("ConnectSocket() : ioctlsocket nonblocking setting failed, error %d\n", WSAGetLastError());
genesis 686 #else
genesis 687 if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
genesis 688 printf("ConnectSocket() : fcntl nonblocking setting failed, error %d\n", errno);
genesis 689 #endif
genesis 690
genesis 691 // Add node
genesis 692 CNode* pnode = new CNode(hSocket, addrConnect, false);
genesis 693 if (nTimeout != 0)
genesis 694 pnode->AddRef(nTimeout);
genesis 695 else
genesis 696 pnode->AddRef();
genesis 697 CRITICAL_BLOCK(cs_vNodes)
genesis 698 vNodes.push_back(pnode);
genesis 699
genesis 700 pnode->nTimeConnected = GetTime();
genesis 701 return pnode;
genesis 702 }
genesis 703 else
genesis 704 {
genesis 705 return NULL;
genesis 706 }
genesis 707 }
genesis 708
genesis 709 void CNode::CloseSocketDisconnect()
genesis 710 {
genesis 711 fDisconnect = true;
genesis 712 if (hSocket != INVALID_SOCKET)
genesis 713 {
genesis 714 if (fDebug)
genesis 715 printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
genesis 716 printf("disconnecting node %s\n", addr.ToString().c_str());
genesis 717 closesocket(hSocket);
genesis 718 hSocket = INVALID_SOCKET;
genesis 719 }
genesis 720 }
genesis 721
genesis 722 void CNode::Cleanup()
genesis 723 {
genesis 724 // All of a nodes broadcasts and subscriptions are automatically torn down
genesis 725 // when it goes down, so a node has to stay up to keep its broadcast going.
genesis 726
genesis 727 // Cancel subscriptions
genesis 728 for (unsigned int nChannel = 0; nChannel < vfSubscribe.size(); nChannel++)
genesis 729 if (vfSubscribe[nChannel])
genesis 730 CancelSubscribe(nChannel);
genesis 731 }
genesis 732
genesis 733
genesis 734 std::map<unsigned int, int64> CNode::setBanned;
genesis 735 CCriticalSection CNode::cs_setBanned;
genesis 736
genesis 737 void CNode::ClearBanned()
genesis 738 {
genesis 739 setBanned.clear();
genesis 740 }
genesis 741
genesis 742 bool CNode::IsBanned(unsigned int ip)
genesis 743 {
genesis 744 bool fResult = false;
genesis 745 CRITICAL_BLOCK(cs_setBanned)
genesis 746 {
genesis 747 std::map<unsigned int, int64>::iterator i = setBanned.find(ip);
genesis 748 if (i != setBanned.end())
genesis 749 {
genesis 750 int64 t = (*i).second;
genesis 751 if (GetTime() < t)
genesis 752 fResult = true;
genesis 753 }
genesis 754 }
genesis 755 return fResult;
genesis 756 }
genesis 757
genesis 758 bool CNode::Misbehaving(int howmuch)
genesis 759 {
genesis 760 if (addr.IsLocal())
genesis 761 {
genesis 762 printf("Warning: local node %s misbehaving\n", addr.ToString().c_str());
genesis 763 return false;
genesis 764 }
genesis 765
genesis 766 nMisbehavior += howmuch;
genesis 767 if (nMisbehavior >= GetArg("-banscore", 100))
genesis 768 {
genesis 769 int64 banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban
genesis 770 CRITICAL_BLOCK(cs_setBanned)
genesis 771 if (setBanned[addr.ip] < banTime)
genesis 772 setBanned[addr.ip] = banTime;
genesis 773 CloseSocketDisconnect();
genesis 774 printf("Disconnected %s for misbehavior (score=%d)\n", addr.ToString().c_str(), nMisbehavior);
genesis 775 return true;
genesis 776 }
genesis 777 return false;
genesis 778 }
genesis 779
genesis 780
genesis 781
genesis 782
genesis 783
genesis 784
genesis 785
genesis 786
genesis 787
genesis 788
genesis 789
genesis 790
genesis 791 void ThreadSocketHandler(void* parg)
genesis 792 {
genesis 793 IMPLEMENT_RANDOMIZE_STACK(ThreadSocketHandler(parg));
genesis 794 try
genesis 795 {
genesis 796 vnThreadsRunning[0]++;
genesis 797 ThreadSocketHandler2(parg);
genesis 798 vnThreadsRunning[0]--;
genesis 799 }
genesis 800 catch (std::exception& e) {
genesis 801 vnThreadsRunning[0]--;
genesis 802 PrintException(&e, "ThreadSocketHandler()");
genesis 803 } catch (...) {
genesis 804 vnThreadsRunning[0]--;
genesis 805 throw; // support pthread_cancel()
genesis 806 }
genesis 807 printf("ThreadSocketHandler exiting\n");
genesis 808 }
genesis 809
genesis 810 void ThreadSocketHandler2(void* parg)
genesis 811 {
genesis 812 printf("ThreadSocketHandler started\n");
genesis 813 list<CNode*> vNodesDisconnected;
genesis 814 int nPrevNodeCount = 0;
genesis 815
genesis 816 loop
genesis 817 {
genesis 818 //
genesis 819 // Disconnect nodes
genesis 820 //
genesis 821 CRITICAL_BLOCK(cs_vNodes)
genesis 822 {
genesis 823 // Disconnect unused nodes
genesis 824 vector<CNode*> vNodesCopy = vNodes;
genesis 825 BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis 826 {
genesis 827 if (pnode->fDisconnect ||
genesis 828 (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
genesis 829 {
genesis 830 // remove from vNodes
genesis 831 vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
genesis 832
genesis 833 // close socket and cleanup
genesis 834 pnode->CloseSocketDisconnect();
genesis 835 pnode->Cleanup();
genesis 836
genesis 837 // hold in disconnected pool until all refs are released
genesis 838 pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
genesis 839 if (pnode->fNetworkNode || pnode->fInbound)
genesis 840 pnode->Release();
genesis 841 vNodesDisconnected.push_back(pnode);
genesis 842 }
genesis 843 }
genesis 844
genesis 845 // Delete disconnected nodes
genesis 846 list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
genesis 847 BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy)
genesis 848 {
genesis 849 // wait until threads are done using it
genesis 850 if (pnode->GetRefCount() <= 0)
genesis 851 {
genesis 852 bool fDelete = false;
genesis 853 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
genesis 854 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
genesis 855 TRY_CRITICAL_BLOCK(pnode->cs_mapRequests)
genesis 856 TRY_CRITICAL_BLOCK(pnode->cs_inventory)
genesis 857 fDelete = true;
genesis 858 if (fDelete)
genesis 859 {
genesis 860 vNodesDisconnected.remove(pnode);
genesis 861 delete pnode;
genesis 862 }
genesis 863 }
genesis 864 }
genesis 865 }
genesis 866 if (vNodes.size() != nPrevNodeCount)
genesis 867 {
genesis 868 nPrevNodeCount = vNodes.size();
genesis 869 MainFrameRepaint();
genesis 870 }
genesis 871
genesis 872
genesis 873 //
genesis 874 // Find which sockets have data to receive
genesis 875 //
genesis 876 struct timeval timeout;
genesis 877 timeout.tv_sec = 0;
genesis 878 timeout.tv_usec = 50000; // frequency to poll pnode->vSend
genesis 879
genesis 880 fd_set fdsetRecv;
genesis 881 fd_set fdsetSend;
genesis 882 fd_set fdsetError;
genesis 883 FD_ZERO(&fdsetRecv);
genesis 884 FD_ZERO(&fdsetSend);
genesis 885 FD_ZERO(&fdsetError);
genesis 886 SOCKET hSocketMax = 0;
genesis 887
genesis 888 if(hListenSocket != INVALID_SOCKET)
genesis 889 FD_SET(hListenSocket, &fdsetRecv);
genesis 890 hSocketMax = max(hSocketMax, hListenSocket);
genesis 891 CRITICAL_BLOCK(cs_vNodes)
genesis 892 {
genesis 893 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 894 {
genesis 895 if (pnode->hSocket == INVALID_SOCKET)
genesis 896 continue;
genesis 897 FD_SET(pnode->hSocket, &fdsetRecv);
genesis 898 FD_SET(pnode->hSocket, &fdsetError);
genesis 899 hSocketMax = max(hSocketMax, pnode->hSocket);
genesis 900 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
genesis 901 if (!pnode->vSend.empty())
genesis 902 FD_SET(pnode->hSocket, &fdsetSend);
genesis 903 }
genesis 904 }
genesis 905
genesis 906 vnThreadsRunning[0]--;
genesis 907 int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
genesis 908 vnThreadsRunning[0]++;
genesis 909 if (fShutdown)
genesis 910 return;
genesis 911 if (nSelect == SOCKET_ERROR)
genesis 912 {
genesis 913 int nErr = WSAGetLastError();
genesis 914 if (hSocketMax > -1)
genesis 915 {
genesis 916 printf("socket select error %d\n", nErr);
genesis 917 for (int i = 0; i <= hSocketMax; i++)
genesis 918 FD_SET(i, &fdsetRecv);
genesis 919 }
genesis 920 FD_ZERO(&fdsetSend);
genesis 921 FD_ZERO(&fdsetError);
genesis 922 Sleep(timeout.tv_usec/1000);
genesis 923 }
genesis 924
genesis 925
genesis 926 //
genesis 927 // Accept new connections
genesis 928 //
genesis 929 if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
genesis 930 {
genesis 931 struct sockaddr_in sockaddr;
genesis 932 socklen_t len = sizeof(sockaddr);
genesis 933 SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
genesis 934 CAddress addr;
genesis 935 int nInbound = 0;
genesis 936
genesis 937 if (hSocket != INVALID_SOCKET)
genesis 938 addr = CAddress(sockaddr);
genesis 939
genesis 940 CRITICAL_BLOCK(cs_vNodes)
genesis 941 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 942 if (pnode->fInbound)
genesis 943 nInbound++;
genesis 944
genesis 945 if (hSocket == INVALID_SOCKET)
genesis 946 {
genesis 947 if (WSAGetLastError() != WSAEWOULDBLOCK)
genesis 948 printf("socket error accept failed: %d\n", WSAGetLastError());
genesis 949 }
genesis 950 else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
genesis 951 {
genesis 952 closesocket(hSocket);
genesis 953 }
genesis 954 else if (CNode::IsBanned(addr.ip))
genesis 955 {
genesis 956 printf("connection from %s dropped (banned)\n", addr.ToString().c_str());
genesis 957 closesocket(hSocket);
genesis 958 }
genesis 959 else
genesis 960 {
genesis 961 printf("accepted connection %s\n", addr.ToString().c_str());
genesis 962 CNode* pnode = new CNode(hSocket, addr, true);
genesis 963 pnode->AddRef();
genesis 964 CRITICAL_BLOCK(cs_vNodes)
genesis 965 vNodes.push_back(pnode);
genesis 966 }
genesis 967 }
genesis 968
genesis 969
genesis 970 //
genesis 971 // Service each socket
genesis 972 //
genesis 973 vector<CNode*> vNodesCopy;
genesis 974 CRITICAL_BLOCK(cs_vNodes)
genesis 975 {
genesis 976 vNodesCopy = vNodes;
genesis 977 BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis 978 pnode->AddRef();
genesis 979 }
genesis 980 BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis 981 {
genesis 982 if (fShutdown)
genesis 983 return;
genesis 984
genesis 985 //
genesis 986 // Receive
genesis 987 //
genesis 988 if (pnode->hSocket == INVALID_SOCKET)
genesis 989 continue;
genesis 990 if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
genesis 991 {
genesis 992 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
genesis 993 {
genesis 994 CDataStream& vRecv = pnode->vRecv;
genesis 995 unsigned int nPos = vRecv.size();
genesis 996
genesis 997 if (nPos > ReceiveBufferSize()) {
genesis 998 if (!pnode->fDisconnect)
genesis 999 printf("socket recv flood control disconnect (%d bytes)\n", vRecv.size());
genesis 1000 pnode->CloseSocketDisconnect();
genesis 1001 }
genesis 1002 else {
genesis 1003 // typical socket buffer is 8K-64K
genesis 1004 char pchBuf[0x10000];
genesis 1005 int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
genesis 1006 if (nBytes > 0)
genesis 1007 {
genesis 1008 vRecv.resize(nPos + nBytes);
genesis 1009 memcpy(&vRecv[nPos], pchBuf, nBytes);
genesis 1010 pnode->nLastRecv = GetTime();
genesis 1011 }
genesis 1012 else if (nBytes == 0)
genesis 1013 {
genesis 1014 // socket closed gracefully
genesis 1015 if (!pnode->fDisconnect)
genesis 1016 printf("socket closed\n");
genesis 1017 pnode->CloseSocketDisconnect();
genesis 1018 }
genesis 1019 else if (nBytes < 0)
genesis 1020 {
genesis 1021 // error
genesis 1022 int nErr = WSAGetLastError();
genesis 1023 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
genesis 1024 {
genesis 1025 if (!pnode->fDisconnect)
genesis 1026 printf("socket recv error %d\n", nErr);
genesis 1027 pnode->CloseSocketDisconnect();
genesis 1028 }
genesis 1029 }
genesis 1030 }
genesis 1031 }
genesis 1032 }
genesis 1033
genesis 1034 //
genesis 1035 // Send
genesis 1036 //
genesis 1037 if (pnode->hSocket == INVALID_SOCKET)
genesis 1038 continue;
genesis 1039 if (FD_ISSET(pnode->hSocket, &fdsetSend))
genesis 1040 {
genesis 1041 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
genesis 1042 {
genesis 1043 CDataStream& vSend = pnode->vSend;
genesis 1044 if (!vSend.empty())
genesis 1045 {
genesis 1046 int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
genesis 1047 if (nBytes > 0)
genesis 1048 {
genesis 1049 vSend.erase(vSend.begin(), vSend.begin() + nBytes);
genesis 1050 pnode->nLastSend = GetTime();
genesis 1051 }
genesis 1052 else if (nBytes < 0)
genesis 1053 {
genesis 1054 // error
genesis 1055 int nErr = WSAGetLastError();
genesis 1056 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
genesis 1057 {
genesis 1058 printf("socket send error %d\n", nErr);
genesis 1059 pnode->CloseSocketDisconnect();
genesis 1060 }
genesis 1061 }
genesis 1062 if (vSend.size() > SendBufferSize()) {
genesis 1063 if (!pnode->fDisconnect)
genesis 1064 printf("socket send flood control disconnect (%d bytes)\n", vSend.size());
genesis 1065 pnode->CloseSocketDisconnect();
genesis 1066 }
genesis 1067 }
genesis 1068 }
genesis 1069 }
genesis 1070
genesis 1071 //
genesis 1072 // Inactivity checking
genesis 1073 //
genesis 1074 if (pnode->vSend.empty())
genesis 1075 pnode->nLastSendEmpty = GetTime();
genesis 1076 if (GetTime() - pnode->nTimeConnected > 60)
genesis 1077 {
genesis 1078 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
genesis 1079 {
genesis 1080 printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
genesis 1081 pnode->fDisconnect = true;
genesis 1082 }
genesis 1083 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
genesis 1084 {
genesis 1085 printf("socket not sending\n");
genesis 1086 pnode->fDisconnect = true;
genesis 1087 }
genesis 1088 else if (GetTime() - pnode->nLastRecv > 90*60)
genesis 1089 {
genesis 1090 printf("socket inactivity timeout\n");
genesis 1091 pnode->fDisconnect = true;
genesis 1092 }
genesis 1093 }
genesis 1094 }
genesis 1095 CRITICAL_BLOCK(cs_vNodes)
genesis 1096 {
genesis 1097 BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis 1098 pnode->Release();
genesis 1099 }
genesis 1100
genesis 1101 Sleep(10);
genesis 1102 }
genesis 1103 }
genesis 1104
genesis 1105
genesis 1106
genesis 1107
genesis 1108
genesis 1109
genesis 1110
genesis 1111
genesis 1112
genesis 1113 #ifdef USE_UPNP
genesis 1114 void ThreadMapPort(void* parg)
genesis 1115 {
genesis 1116 IMPLEMENT_RANDOMIZE_STACK(ThreadMapPort(parg));
genesis 1117 try
genesis 1118 {
genesis 1119 vnThreadsRunning[5]++;
genesis 1120 ThreadMapPort2(parg);
genesis 1121 vnThreadsRunning[5]--;
genesis 1122 }
genesis 1123 catch (std::exception& e) {
genesis 1124 vnThreadsRunning[5]--;
genesis 1125 PrintException(&e, "ThreadMapPort()");
genesis 1126 } catch (...) {
genesis 1127 vnThreadsRunning[5]--;
genesis 1128 PrintException(NULL, "ThreadMapPort()");
genesis 1129 }
genesis 1130 printf("ThreadMapPort exiting\n");
genesis 1131 }
genesis 1132
genesis 1133 void ThreadMapPort2(void* parg)
genesis 1134 {
genesis 1135 printf("ThreadMapPort started\n");
genesis 1136
genesis 1137 char port[6];
genesis 1138 sprintf(port, "%d", GetListenPort());
genesis 1139
genesis 1140 const char * multicastif = 0;
genesis 1141 const char * minissdpdpath = 0;
genesis 1142 struct UPNPDev * devlist = 0;
genesis 1143 char lanaddr[64];
genesis 1144
genesis 1145 #ifndef UPNPDISCOVER_SUCCESS
genesis 1146 /* miniupnpc 1.5 */
genesis 1147 devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0);
genesis 1148 #else
genesis 1149 /* miniupnpc 1.6 */
genesis 1150 int error = 0;
genesis 1151 devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error);
genesis 1152 #endif
genesis 1153
genesis 1154 struct UPNPUrls urls;
genesis 1155 struct IGDdatas data;
genesis 1156 int r;
genesis 1157
genesis 1158 r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
genesis 1159 if (r == 1)
genesis 1160 {
genesis 1161 if (!addrLocalHost.IsRoutable())
genesis 1162 {
genesis 1163 char externalIPAddress[40];
genesis 1164 r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
genesis 1165 if(r != UPNPCOMMAND_SUCCESS)
genesis 1166 printf("UPnP: GetExternalIPAddress() returned %d\n", r);
genesis 1167 else
genesis 1168 {
genesis 1169 if(externalIPAddress[0])
genesis 1170 {
genesis 1171 printf("UPnP: ExternalIPAddress = %s\n", externalIPAddress);
genesis 1172 CAddress addrExternalFromUPnP(externalIPAddress, 0, false, nLocalServices);
genesis 1173 if (addrExternalFromUPnP.IsRoutable())
genesis 1174 addrLocalHost = addrExternalFromUPnP;
genesis 1175 }
genesis 1176 else
genesis 1177 printf("UPnP: GetExternalIPAddress failed.\n");
genesis 1178 }
genesis 1179 }
genesis 1180
genesis 1181 string strDesc = "Bitcoin " + FormatFullVersion();
genesis 1182 #ifndef UPNPDISCOVER_SUCCESS
genesis 1183 /* miniupnpc 1.5 */
genesis 1184 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
genesis 1185 port, port, lanaddr, strDesc.c_str(), "TCP", 0);
genesis 1186 #else
genesis 1187 /* miniupnpc 1.6 */
genesis 1188 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
genesis 1189 port, port, lanaddr, strDesc.c_str(), "TCP", 0, "0");
genesis 1190 #endif
genesis 1191
genesis 1192 if(r!=UPNPCOMMAND_SUCCESS)
genesis 1193 printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
genesis 1194 port, port, lanaddr, r, strupnperror(r));
genesis 1195 else
genesis 1196 printf("UPnP Port Mapping successful.\n");
genesis 1197 int i = 1;
genesis 1198 loop {
genesis 1199 if (fShutdown || !fUseUPnP)
genesis 1200 {
genesis 1201 r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port, "TCP", 0);
genesis 1202 printf("UPNP_DeletePortMapping() returned : %d\n", r);
genesis 1203 freeUPNPDevlist(devlist); devlist = 0;
genesis 1204 FreeUPNPUrls(&urls);
genesis 1205 return;
genesis 1206 }
genesis 1207 if (i % 600 == 0) // Refresh every 20 minutes
genesis 1208 {
genesis 1209 #ifndef UPNPDISCOVER_SUCCESS
genesis 1210 /* miniupnpc 1.5 */
genesis 1211 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
genesis 1212 port, port, lanaddr, strDesc.c_str(), "TCP", 0);
genesis 1213 #else
genesis 1214 /* miniupnpc 1.6 */
genesis 1215 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
genesis 1216 port, port, lanaddr, strDesc.c_str(), "TCP", 0, "0");
genesis 1217 #endif
genesis 1218
genesis 1219 if(r!=UPNPCOMMAND_SUCCESS)
genesis 1220 printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
genesis 1221 port, port, lanaddr, r, strupnperror(r));
genesis 1222 else
genesis 1223 printf("UPnP Port Mapping successful.\n");;
genesis 1224 }
genesis 1225 Sleep(2000);
genesis 1226 i++;
genesis 1227 }
genesis 1228 } else {
genesis 1229 printf("No valid UPnP IGDs found\n");
genesis 1230 freeUPNPDevlist(devlist); devlist = 0;
genesis 1231 if (r != 0)
genesis 1232 FreeUPNPUrls(&urls);
genesis 1233 loop {
genesis 1234 if (fShutdown || !fUseUPnP)
genesis 1235 return;
genesis 1236 Sleep(2000);
genesis 1237 }
genesis 1238 }
genesis 1239 }
genesis 1240
genesis 1241 void MapPort(bool fMapPort)
genesis 1242 {
genesis 1243 if (fUseUPnP != fMapPort)
genesis 1244 {
genesis 1245 fUseUPnP = fMapPort;
genesis 1246 WriteSetting("fUseUPnP", fUseUPnP);
genesis 1247 }
genesis 1248 if (fUseUPnP && vnThreadsRunning[5] < 1)
genesis 1249 {
genesis 1250 if (!CreateThread(ThreadMapPort, NULL))
genesis 1251 printf("Error: ThreadMapPort(ThreadMapPort) failed\n");
genesis 1252 }
genesis 1253 }
genesis 1254 #else
genesis 1255 void MapPort(bool /* unused fMapPort */)
genesis 1256 {
genesis 1257 // Intentionally left blank.
genesis 1258 }
genesis 1259 #endif
genesis 1260
genesis 1261
genesis 1262
genesis 1263
genesis 1264
genesis 1265
genesis 1266
genesis 1267
genesis 1268
genesis 1269
genesis 1270 static const char *strDNSSeed[] = {
genesis 1271 "bitseed.xf2.org",
genesis 1272 "dnsseed.bluematt.me",
genesis 1273 "seed.bitcoin.sipa.be",
genesis 1274 "dnsseed.bitcoin.dashjr.org",
genesis 1275 };
genesis 1276
genesis 1277 void ThreadDNSAddressSeed(void* parg)
genesis 1278 {
genesis 1279 IMPLEMENT_RANDOMIZE_STACK(ThreadDNSAddressSeed(parg));
genesis 1280 try
genesis 1281 {
genesis 1282 vnThreadsRunning[6]++;
genesis 1283 ThreadDNSAddressSeed2(parg);
genesis 1284 vnThreadsRunning[6]--;
genesis 1285 }
genesis 1286 catch (std::exception& e) {
genesis 1287 vnThreadsRunning[6]--;
genesis 1288 PrintException(&e, "ThreadDNSAddressSeed()");
genesis 1289 } catch (...) {
genesis 1290 vnThreadsRunning[6]--;
genesis 1291 throw; // support pthread_cancel()
genesis 1292 }
genesis 1293 printf("ThreadDNSAddressSeed exiting\n");
genesis 1294 }
genesis 1295
genesis 1296 void ThreadDNSAddressSeed2(void* parg)
genesis 1297 {
genesis 1298 printf("ThreadDNSAddressSeed started\n");
genesis 1299 int found = 0;
genesis 1300
genesis 1301 if (!fTestNet)
genesis 1302 {
genesis 1303 printf("Loading addresses from DNS seeds (could take a while)\n");
genesis 1304
genesis 1305 for (int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
genesis 1306 vector<CAddress> vaddr;
genesis 1307 if (Lookup(strDNSSeed[seed_idx], vaddr, NODE_NETWORK, -1, true))
genesis 1308 {
genesis 1309 CAddrDB addrDB;
genesis 1310 addrDB.TxnBegin();
genesis 1311 BOOST_FOREACH (CAddress& addr, vaddr)
genesis 1312 {
genesis 1313 if (addr.GetByte(3) != 127)
genesis 1314 {
genesis 1315 addr.nTime = 0;
genesis 1316 AddAddress(addr, 0, &addrDB);
genesis 1317 found++;
genesis 1318 }
genesis 1319 }
genesis 1320 addrDB.TxnCommit(); // Save addresses (it's ok if this fails)
genesis 1321 }
genesis 1322 }
genesis 1323 }
genesis 1324
genesis 1325 printf("%d addresses found from DNS seeds\n", found);
genesis 1326 }
genesis 1327
genesis 1328
genesis 1329
genesis 1330
genesis 1331
genesis 1332
genesis 1333
genesis 1334
genesis 1335
genesis 1336
genesis 1337
genesis 1338
genesis 1339 unsigned int pnSeed[] =
genesis 1340 {
genesis 1341 0x959bd347, 0xf8de42b2, 0x73bc0518, 0xea6edc50, 0x21b00a4d, 0xc725b43d, 0xd665464d, 0x1a2a770e,
genesis 1342 0x27c93946, 0x65b2fa46, 0xb80ae255, 0x66b3b446, 0xb1877a3e, 0x6ee89e3e, 0xc3175b40, 0x2a01a83c,
genesis 1343 0x95b1363a, 0xa079ad3d, 0xe6ca801f, 0x027f4f4a, 0x34f7f03a, 0xf790f04a, 0x16ca801f, 0x2f4d5e40,
genesis 1344 0x3a4d5e40, 0xc43a322e, 0xc8159753, 0x14d4724c, 0x7919a118, 0xe0bdb34e, 0x68a16b2e, 0xff64b44d,
genesis 1345 0x6099115b, 0x9b57b05b, 0x7bd1b4ad, 0xdf95944f, 0x29d2b73d, 0xafa8db79, 0xe247ba41, 0x24078348,
genesis 1346 0xf722f03c, 0x33567ebc, 0xace64ed4, 0x984d3932, 0xb5f34e55, 0x27b7024d, 0x94579247, 0x8894042e,
genesis 1347 0x9357d34c, 0x1063c24b, 0xcaa228b1, 0xa3c5a8b2, 0x5dc64857, 0xa2c23643, 0xa8369a54, 0x31203077,
genesis 1348 0x00707c5c, 0x09fc0b3a, 0x272e9e2e, 0xf80f043e, 0x9449ca3e, 0x5512c33e, 0xd106b555, 0xe8024157,
genesis 1349 0xe288ec29, 0xc79c5461, 0xafb63932, 0xdb02ab4b, 0x0e512777, 0x8a145a4c, 0xb201ff4f, 0x5e09314b,
genesis 1350 0xcd9bfbcd, 0x1c023765, 0x4394e75c, 0xa728bd4d, 0x65331552, 0xa98420b1, 0x89ecf559, 0x6e80801f,
genesis 1351 0xf404f118, 0xefd62b51, 0x05918346, 0x9b186d5f, 0xacabab46, 0xf912e255, 0xc188ea62, 0xcc55734e,
genesis 1352 0xc668064d, 0xd77a4558, 0x46201c55, 0xf17dfc80, 0xf7142f2e, 0x87bfb718, 0x8aa54fb2, 0xc451d518,
genesis 1353 0xc4ae8831, 0x8dd44d55, 0x5bbd206c, 0x64536b5d, 0x5c667e60, 0x3b064242, 0xfe963a42, 0xa28e6dc8,
genesis 1354 0xe8a9604a, 0xc989464e, 0xd124a659, 0x50065140, 0xa44dfe5e, 0x1079e655, 0x3fb986d5, 0x47895b18,
genesis 1355 0x7d3ce4ad, 0x4561ba50, 0x296eec62, 0x255b41ad, 0xaed35ec9, 0x55556f12, 0xc7d3154d, 0x3297b65d,
genesis 1356 0x8930121f, 0xabf42e4e, 0x4a29e044, 0x1212685d, 0x676c1e40, 0xce009744, 0x383a8948, 0xa2dbd0ad,
genesis 1357 0xecc2564d, 0x07dbc252, 0x887ee24b, 0x5171644c, 0x6bb798c1, 0x847f495d, 0x4cbb7145, 0x3bb81c32,
genesis 1358 0x45eb262e, 0xc8015a4e, 0x250a361b, 0xf694f946, 0xd64a183e, 0xd4f1dd59, 0x8f20ffd4, 0x51d9e55c,
genesis 1359 0x09521763, 0x5e02002e, 0x32c8074d, 0xe685762e, 0x8290b0bc, 0x762a922e, 0xfc5ee754, 0x83a24829,
genesis 1360 0x775b224d, 0x6295bb4d, 0x38ec0555, 0xbffbba50, 0xe5560260, 0x86b16a7c, 0xd372234e, 0x49a3c24b,
genesis 1361 0x2f6a171f, 0x4d75ed60, 0xae94115b, 0xcb543744, 0x63080c59, 0x3f9c724c, 0xc977ce18, 0x532efb18,
genesis 1362 0x69dc3b2e, 0x5f94d929, 0x1732bb4d, 0x9c814b4d, 0xe6b3762e, 0xc024f662, 0x8face35b, 0x6b5b044d,
genesis 1363 0x798c7b57, 0x79a6b44c, 0x067d3057, 0xf9e94e5f, 0x91cbe15b, 0x71405eb2, 0x2662234e, 0xcbcc4a6d,
genesis 1364 0xbf69d54b, 0xa79b4e55, 0xec6d3e51, 0x7c0b3c02, 0x60f83653, 0x24c1e15c, 0x1110b62e, 0x10350f59,
genesis 1365 0xa56f1d55, 0x3509e7a9, 0xeb128354, 0x14268e2e, 0x934e28bc, 0x8e32692e, 0x8331a21f, 0x3e633932,
genesis 1366 0xc812b12e, 0xc684bf2e, 0x80112d2e, 0xe0ddc96c, 0xc630ca4a, 0x5c09b3b2, 0x0b580518, 0xc8e9d54b,
genesis 1367 0xd169aa43, 0x17d0d655, 0x1d029963, 0x7ff87559, 0xcb701f1f, 0x6fa3e85d, 0xe45e9a54, 0xf05d1802,
genesis 1368 0x44d03b2e, 0x837b692e, 0xccd4354e, 0x3d6da13c, 0x3423084d, 0xf707c34a, 0x55f6db3a, 0xad26e442,
genesis 1369 0x6233a21f, 0x09e80e59, 0x8caeb54d, 0xbe870941, 0xb407d20e, 0x20b51018, 0x56fb152e, 0x460d2a4e,
genesis 1370 0xbb9a2946, 0x560eb12e, 0xed83dd29, 0xd6724f53, 0xa50aafb8, 0x451346d9, 0x88348e2e, 0x7312fead,
genesis 1371 0x8ecaf96f, 0x1bda4e5f, 0xf1671e40, 0x3c8c3e3b, 0x4716324d, 0xdde24ede, 0xf98cd17d, 0xa91d4644,
genesis 1372 0x28124eb2, 0x147d5129, 0xd022042e, 0x61733d3b, 0xad0d5e02, 0x8ce2932e, 0xe5c18502, 0x549c1e32,
genesis 1373 0x9685801f, 0x86e217ad, 0xd948214b, 0x4110f462, 0x3a2e894e, 0xbd35492e, 0x87e0d558, 0x64b8ef7d,
genesis 1374 0x7c3eb962, 0x72a84b3e, 0x7cd667c9, 0x28370a2e, 0x4bc60e7b, 0x6fc1ec60, 0x14a6983f, 0x86739a4b,
genesis 1375 0x46954e5f, 0x32e2e15c, 0x2e9326cf, 0xe5801c5e, 0x379607b2, 0x32151145, 0xf0e39744, 0xacb54c55,
genesis 1376 0xa37dfb60, 0x83b55cc9, 0x388f7ca5, 0x15034f5f, 0x3e94965b, 0x68e0ffad, 0x35280f59, 0x8fe190cf,
genesis 1377 0x7c6ba5b2, 0xa5e9db43, 0x4ee1fc60, 0xd9d94e5f, 0x04040677, 0x0ea9b35e, 0x5961f14f, 0x67fda063,
genesis 1378 0xa48a5a31, 0xc6524e55, 0x283d325e, 0x3f37515f, 0x96b94b3e, 0xacce620e, 0x6481cc5b, 0xa4a06d4b,
genesis 1379 0x9e95d2d9, 0xe40c03d5, 0xc2f4514b, 0xb79aad44, 0xf64be843, 0xb2064070, 0xfca00455, 0x429dfa4e,
genesis 1380 0x2323f173, 0xeda4185e, 0xabd5227d, 0x9efd4d58, 0xb1104758, 0x4811e955, 0xbd9ab355, 0xe921f44b,
genesis 1381 0x9f166dce, 0x09e279b2, 0xe0c9ac7b, 0x7901a5ad, 0xa145d4b0, 0x79104671, 0xec31e35a, 0x4fe0b555,
genesis 1382 0xc7d9cbad, 0xad057f55, 0xe94cc759, 0x7fe0b043, 0xe4529f2e, 0x0d4dd4b2, 0x9f11a54d, 0x031e2e4e,
genesis 1383 0xe6014f5f, 0x11d1ca6c, 0x26bd7f61, 0xeb86854f, 0x4d347b57, 0x116bbe2e, 0xdba7234e, 0x7bcbfd2e,
genesis 1384 0x174dd4b2, 0x6686762e, 0xb089ba50, 0xc6258246, 0x087e767b, 0xc4a8cb4a, 0x595dba50, 0x7f0ae502,
genesis 1385 0x7b1dbd5a, 0xa0603492, 0x57d1af4b, 0x9e21ffd4, 0x6393064d, 0x7407376e, 0xe484762e, 0x122a4e53,
genesis 1386 0x4a37aa43, 0x3888a6be, 0xee77864e, 0x039c8dd5, 0x688d89af, 0x0e988f62, 0x08218246, 0xfc2f8246,
genesis 1387 0xd1d97040, 0xd64cd4b2, 0x5ae4a6b8, 0x7d0de9bc, 0x8d304d61, 0x06c5c672, 0xa4c8bd4d, 0xe0fd373b,
genesis 1388 0x575ebe4d, 0x72d26277, 0x55570f55, 0x77b154d9, 0xe214293a, 0xfc740f4b, 0xfe3f6a57, 0xa9c55f02,
genesis 1389 0xae4054db, 0x2394d918, 0xb511b24a, 0xb8741ab2, 0x0758e65e, 0xc7b5795b, 0xb0a30a4c, 0xaf7f170c,
genesis 1390 0xf3b4762e, 0x8179576d, 0x738a1581, 0x4b95b64c, 0x9829b618, 0x1bea932e, 0x7bdeaa4b, 0xcb5e0281,
genesis 1391 0x65618f54, 0x0658474b, 0x27066acf, 0x40556d65, 0x7d204d53, 0xf28bc244, 0xdce23455, 0xadc0ff54,
genesis 1392 0x3863c948, 0xcee34e5f, 0xdeb85e02, 0x2ed17a61, 0x6a7b094d, 0x7f0cfc40, 0x59603f54, 0x3220afbc,
genesis 1393 0xb5dfd962, 0x125d21c0, 0x13f8d243, 0xacfefb4e, 0x86c2c147, 0x3d8bbd59, 0xbd02a21f, 0x2593042e,
genesis 1394 0xc6a17a7c, 0x28925861, 0xb487ed44, 0xb5f4fd6d, 0x90c28a45, 0x5a14f74d, 0x43d71b4c, 0x728ebb5d,
genesis 1395 0x885bf950, 0x08134dd0, 0x38ec046e, 0xc575684b, 0x50082d2e, 0xa2f47757, 0x270f86ae, 0xf3ff6462,
genesis 1396 0x10ed3f4e, 0x4b58d462, 0xe01ce23e, 0x8c5b092e, 0x63e52f4e, 0x22c1e85d, 0xa908f54e, 0x8591624f,
genesis 1397 0x2c0fb94e, 0xa280ba3c, 0xb6f41b4c, 0x24f9aa47, 0x27201647, 0x3a3ea6dc, 0xa14fc3be, 0x3c34bdd5,
genesis 1398 0x5b8d4f5b, 0xaadeaf4b, 0xc71cab50, 0x15697a4c, 0x9a1a734c, 0x2a037d81, 0x2590bd59, 0x48ec2741,
genesis 1399 0x53489c5b, 0x7f00314b, 0x2170d362, 0xf2e92542, 0x42c10b44, 0x98f0f118, 0x883a3456, 0x099a932e,
genesis 1400 0xea38f7bc, 0x644e9247, 0xbb61b62e, 0x30e0863d, 0x5f51be54, 0x207215c7, 0x5f306c45, 0xaa7f3932,
genesis 1401 0x98da7d45, 0x4e339b59, 0x2e411581, 0xa808f618, 0xad2c0c59, 0x54476741, 0x09e99fd1, 0x5db8f752,
genesis 1402 0xc16df8bd, 0x1dd4b44f, 0x106edf2e, 0x9e15c180, 0x2ad6b56f, 0x633a5332, 0xff33787c, 0x077cb545,
genesis 1403 0x6610be6d, 0x75aad2c4, 0x72fb4d5b, 0xe81e0f59, 0x576f6332, 0x47333373, 0x351ed783, 0x2d90fb50,
genesis 1404 0x8d5e0f6c, 0x5b27a552, 0xdb293ebb, 0xe55ef950, 0x4b133ad8, 0x75df975a, 0x7b6a8740, 0xa899464b,
genesis 1405 0xfab15161, 0x10f8b64d, 0xd055ea4d, 0xee8e146b, 0x4b14afb8, 0x4bc1c44a, 0x9b961dcc, 0xd111ff43,
genesis 1406 0xfca0b745, 0xc800e412, 0x0afad9d1, 0xf751c350, 0xf9f0cccf, 0xa290a545, 0x8ef13763, 0x7ec70d59,
genesis 1407 0x2b066acf, 0x65496c45, 0xade02c1b, 0xae6eb077, 0x92c1e65b, 0xc064e6a9, 0xc649e56d, 0x5287a243,
genesis 1408 0x36de4f5b, 0x5b1df6ad, 0x65c39a59, 0xdba805b2, 0x20067aa8, 0x6457e56d, 0x3cee26cf, 0xfd3ff26d,
genesis 1409 0x04f86d4a, 0x06b8e048, 0xa93bcd5c, 0x91135852, 0xbe90a643, 0x8fa0094d, 0x06d8215f, 0x2677094d,
genesis 1410 0xd735685c, 0x164a00c9, 0x5209ac5f, 0xa9564c5c, 0x3b504f5f, 0xcc826bd0, 0x4615042e, 0x5fe13b4a,
genesis 1411 0x8c81b86d, 0x879ab68c, 0x1de564b8, 0x434487d8, 0x2dcb1b63, 0x82ab524a, 0xb0676abb, 0xa13d9c62,
genesis 1412 0xdbb5b86d, 0x5b7f4b59, 0xaddfb44d, 0xad773532, 0x3997054c, 0x72cebd89, 0xb194544c, 0xc5b8046e,
genesis 1413 0x6e1adeb2, 0xaa5abb51, 0xefb54b44, 0x15efc54f, 0xe9f1bc4d, 0x5f401b6c, 0x97f018ad, 0xc82f9252,
genesis 1414 0x2cdc762e, 0x8e52e56d, 0x1827175e, 0x9b7d7d80, 0xb2ad6845, 0x51065140, 0x71180a18, 0x5b27006c,
genesis 1415 0x0621e255, 0x721cbe58, 0x670c0cb8, 0xf8bd715d, 0xe0bdc5d9, 0xed843501, 0x4b84554d, 0x7f1a18bc,
genesis 1416 0x53bcaf47, 0x5729d35f, 0xf0dda246, 0x22382bd0, 0x4d641fb0, 0x316afcde, 0x50a22f1f, 0x73608046,
genesis 1417 0xc461d84a, 0xb2dbe247,
genesis 1418 };
genesis 1419
genesis 1420
genesis 1421
genesis 1422 void ThreadOpenConnections(void* parg)
genesis 1423 {
genesis 1424 IMPLEMENT_RANDOMIZE_STACK(ThreadOpenConnections(parg));
genesis 1425 try
genesis 1426 {
genesis 1427 vnThreadsRunning[1]++;
genesis 1428 ThreadOpenConnections2(parg);
genesis 1429 vnThreadsRunning[1]--;
genesis 1430 }
genesis 1431 catch (std::exception& e) {
genesis 1432 vnThreadsRunning[1]--;
genesis 1433 PrintException(&e, "ThreadOpenConnections()");
genesis 1434 } catch (...) {
genesis 1435 vnThreadsRunning[1]--;
genesis 1436 PrintException(NULL, "ThreadOpenConnections()");
genesis 1437 }
genesis 1438 printf("ThreadOpenConnections exiting\n");
genesis 1439 }
genesis 1440
genesis 1441 void ThreadOpenConnections2(void* parg)
genesis 1442 {
genesis 1443 printf("ThreadOpenConnections started\n");
genesis 1444
genesis 1445 // Connect to specific addresses
genesis 1446 if (mapArgs.count("-connect"))
genesis 1447 {
genesis 1448 for (int64 nLoop = 0;; nLoop++)
genesis 1449 {
genesis 1450 BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
genesis 1451 {
genesis 1452 CAddress addr(strAddr, fAllowDNS);
genesis 1453 if (addr.IsValid())
genesis 1454 OpenNetworkConnection(addr);
genesis 1455 for (int i = 0; i < 10 && i < nLoop; i++)
genesis 1456 {
genesis 1457 Sleep(500);
genesis 1458 if (fShutdown)
genesis 1459 return;
genesis 1460 }
genesis 1461 }
genesis 1462 }
genesis 1463 }
genesis 1464
genesis 1465 // Connect to manually added nodes first
genesis 1466 if (mapArgs.count("-addnode"))
genesis 1467 {
genesis 1468 BOOST_FOREACH(string strAddr, mapMultiArgs["-addnode"])
genesis 1469 {
genesis 1470 CAddress addr(strAddr, fAllowDNS);
genesis 1471 if (addr.IsValid())
genesis 1472 {
genesis 1473 OpenNetworkConnection(addr);
genesis 1474 Sleep(500);
genesis 1475 if (fShutdown)
genesis 1476 return;
genesis 1477 }
genesis 1478 }
genesis 1479 }
genesis 1480
genesis 1481 // Initiate network connections
genesis 1482 int64 nStart = GetTime();
genesis 1483 loop
genesis 1484 {
genesis 1485 vnThreadsRunning[1]--;
genesis 1486 Sleep(500);
genesis 1487 vnThreadsRunning[1]++;
genesis 1488 if (fShutdown)
genesis 1489 return;
genesis 1490
genesis 1491 // Limit outbound connections
genesis 1492 loop
genesis 1493 {
genesis 1494 int nOutbound = 0;
genesis 1495 CRITICAL_BLOCK(cs_vNodes)
genesis 1496 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 1497 if (!pnode->fInbound)
genesis 1498 nOutbound++;
genesis 1499 int nMaxOutboundConnections = MAX_OUTBOUND_CONNECTIONS;
genesis 1500 nMaxOutboundConnections = min(nMaxOutboundConnections, (int)GetArg("-maxconnections", 125));
genesis 1501 if (nOutbound < nMaxOutboundConnections)
genesis 1502 break;
genesis 1503 vnThreadsRunning[1]--;
genesis 1504 Sleep(2000);
genesis 1505 vnThreadsRunning[1]++;
genesis 1506 if (fShutdown)
genesis 1507 return;
genesis 1508 }
genesis 1509
genesis 1510 bool fAddSeeds = false;
genesis 1511
genesis 1512 CRITICAL_BLOCK(cs_mapAddresses)
genesis 1513 {
genesis 1514 // Add seed nodes if IRC isn't working
genesis 1515 bool fTOR = (fUseProxy && addrProxy.port == htons(9050));
genesis 1516 if (mapAddresses.empty() && (GetTime() - nStart > 60 || fUseProxy) && !fTestNet)
genesis 1517 fAddSeeds = true;
genesis 1518 }
genesis 1519
genesis 1520 if (fAddSeeds)
genesis 1521 {
genesis 1522 for (int i = 0; i < ARRAYLEN(pnSeed); i++)
genesis 1523 {
genesis 1524 // It'll only connect to one or two seed nodes because once it connects,
genesis 1525 // it'll get a pile of addresses with newer timestamps.
genesis 1526 // Seed nodes are given a random 'last seen time' of between one and two
genesis 1527 // weeks ago.
genesis 1528 const int64 nOneWeek = 7*24*60*60;
genesis 1529 CAddress addr;
genesis 1530 addr.ip = pnSeed[i];
genesis 1531 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
genesis 1532 AddAddress(addr);
genesis 1533 }
genesis 1534 }
genesis 1535
genesis 1536 //
genesis 1537 // Choose an address to connect to based on most recently seen
genesis 1538 //
genesis 1539 CAddress addrConnect;
genesis 1540 int64 nBest = INT64_MIN;
genesis 1541
genesis 1542 // Only connect to one address per a.b.?.? range.
genesis 1543 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
genesis 1544 set<unsigned int> setConnected;
genesis 1545 CRITICAL_BLOCK(cs_vNodes)
genesis 1546 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 1547 setConnected.insert(pnode->addr.ip & 0x0000ffff);
genesis 1548
genesis 1549 int64 nANow = GetAdjustedTime();
genesis 1550
genesis 1551 CRITICAL_BLOCK(cs_mapAddresses)
genesis 1552 {
genesis 1553 BOOST_FOREACH(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
genesis 1554 {
genesis 1555 const CAddress& addr = item.second;
genesis 1556 if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.ip & 0x0000ffff))
genesis 1557 continue;
genesis 1558 int64 nSinceLastSeen = nANow - addr.nTime;
genesis 1559 int64 nSinceLastTry = nANow - addr.nLastTry;
genesis 1560
genesis 1561 // Randomize the order in a deterministic way, putting the standard port first
genesis 1562 int64 nRandomizer = (uint64)(nStart * 4951 + addr.nLastTry * 9567851 + addr.ip * 7789) % (2 * 60 * 60);
genesis 1563 if (addr.port != htons(GetDefaultPort()))
genesis 1564 nRandomizer += 2 * 60 * 60;
genesis 1565
genesis 1566 // Last seen Base retry frequency
genesis 1567 // <1 hour 10 min
genesis 1568 // 1 hour 1 hour
genesis 1569 // 4 hours 2 hours
genesis 1570 // 24 hours 5 hours
genesis 1571 // 48 hours 7 hours
genesis 1572 // 7 days 13 hours
genesis 1573 // 30 days 27 hours
genesis 1574 // 90 days 46 hours
genesis 1575 // 365 days 93 hours
genesis 1576 int64 nDelay = (int64)(3600.0 * sqrt(fabs((double)nSinceLastSeen) / 3600.0) + nRandomizer);
genesis 1577
genesis 1578 // Fast reconnect for one hour after last seen
genesis 1579 if (nSinceLastSeen < 60 * 60)
genesis 1580 nDelay = 10 * 60;
genesis 1581
genesis 1582 // Limit retry frequency
genesis 1583 if (nSinceLastTry < nDelay)
genesis 1584 continue;
genesis 1585
genesis 1586 // If we have IRC, we'll be notified when they first come online,
genesis 1587 // and again every 24 hours by the refresh broadcast.
genesis 1588 if (nGotIRCAddresses > 0 && vNodes.size() >= 2 && nSinceLastSeen > 24 * 60 * 60)
genesis 1589 continue;
genesis 1590
genesis 1591 // Only try the old stuff if we don't have enough connections
genesis 1592 if (vNodes.size() >= 8 && nSinceLastSeen > 24 * 60 * 60)
genesis 1593 continue;
genesis 1594
genesis 1595 // If multiple addresses are ready, prioritize by time since
genesis 1596 // last seen and time since last tried.
genesis 1597 int64 nScore = min(nSinceLastTry, (int64)24 * 60 * 60) - nSinceLastSeen - nRandomizer;
genesis 1598 if (nScore > nBest)
genesis 1599 {
genesis 1600 nBest = nScore;
genesis 1601 addrConnect = addr;
genesis 1602 }
genesis 1603 }
genesis 1604 }
genesis 1605
genesis 1606 if (addrConnect.IsValid())
genesis 1607 OpenNetworkConnection(addrConnect);
genesis 1608 }
genesis 1609 }
genesis 1610
genesis 1611 bool OpenNetworkConnection(const CAddress& addrConnect)
genesis 1612 {
genesis 1613 //
genesis 1614 // Initiate outbound network connection
genesis 1615 //
genesis 1616 if (fShutdown)
genesis 1617 return false;
genesis 1618 if (addrConnect.ip == addrLocalHost.ip || !addrConnect.IsIPv4() ||
genesis 1619 FindNode(addrConnect.ip) || CNode::IsBanned(addrConnect.ip))
genesis 1620 return false;
genesis 1621
genesis 1622 vnThreadsRunning[1]--;
genesis 1623 CNode* pnode = ConnectNode(addrConnect);
genesis 1624 vnThreadsRunning[1]++;
genesis 1625 if (fShutdown)
genesis 1626 return false;
genesis 1627 if (!pnode)
genesis 1628 return false;
genesis 1629 pnode->fNetworkNode = true;
genesis 1630
genesis 1631 return true;
genesis 1632 }
genesis 1633
genesis 1634
genesis 1635
genesis 1636
genesis 1637
genesis 1638
genesis 1639
genesis 1640
genesis 1641 void ThreadMessageHandler(void* parg)
genesis 1642 {
genesis 1643 IMPLEMENT_RANDOMIZE_STACK(ThreadMessageHandler(parg));
genesis 1644 try
genesis 1645 {
genesis 1646 vnThreadsRunning[2]++;
genesis 1647 ThreadMessageHandler2(parg);
genesis 1648 vnThreadsRunning[2]--;
genesis 1649 }
genesis 1650 catch (std::exception& e) {
genesis 1651 vnThreadsRunning[2]--;
genesis 1652 PrintException(&e, "ThreadMessageHandler()");
genesis 1653 } catch (...) {
genesis 1654 vnThreadsRunning[2]--;
genesis 1655 PrintException(NULL, "ThreadMessageHandler()");
genesis 1656 }
genesis 1657 printf("ThreadMessageHandler exiting\n");
genesis 1658 }
genesis 1659
genesis 1660 void ThreadMessageHandler2(void* parg)
genesis 1661 {
genesis 1662 printf("ThreadMessageHandler started\n");
genesis 1663 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
genesis 1664 while (!fShutdown)
genesis 1665 {
genesis 1666 vector<CNode*> vNodesCopy;
genesis 1667 CRITICAL_BLOCK(cs_vNodes)
genesis 1668 {
genesis 1669 vNodesCopy = vNodes;
genesis 1670 BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis 1671 pnode->AddRef();
genesis 1672 }
genesis 1673
genesis 1674 // Poll the connected nodes for messages
genesis 1675 CNode* pnodeTrickle = NULL;
genesis 1676 if (!vNodesCopy.empty())
genesis 1677 pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
genesis 1678 BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis 1679 {
genesis 1680 // Receive messages
genesis 1681 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
genesis 1682 ProcessMessages(pnode);
genesis 1683 if (fShutdown)
genesis 1684 return;
genesis 1685
genesis 1686 // Send messages
genesis 1687 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
genesis 1688 SendMessages(pnode, pnode == pnodeTrickle);
genesis 1689 if (fShutdown)
genesis 1690 return;
genesis 1691 }
genesis 1692
genesis 1693 CRITICAL_BLOCK(cs_vNodes)
genesis 1694 {
genesis 1695 BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis 1696 pnode->Release();
genesis 1697 }
genesis 1698
genesis 1699 // Wait and allow messages to bunch up.
genesis 1700 // Reduce vnThreadsRunning so StopNode has permission to exit while
genesis 1701 // we're sleeping, but we must always check fShutdown after doing this.
genesis 1702 vnThreadsRunning[2]--;
genesis 1703 Sleep(100);
genesis 1704 if (fRequestShutdown)
genesis 1705 Shutdown(NULL);
genesis 1706 vnThreadsRunning[2]++;
genesis 1707 if (fShutdown)
genesis 1708 return;
genesis 1709 }
genesis 1710 }
genesis 1711
genesis 1712
genesis 1713
genesis 1714
genesis 1715
genesis 1716
genesis 1717 bool BindListenPort(string& strError)
genesis 1718 {
genesis 1719 strError = "";
genesis 1720 int nOne = 1;
genesis 1721 addrLocalHost.port = htons(GetListenPort());
genesis 1722
genesis 1723 #ifdef WIN32
genesis 1724 // Initialize Windows Sockets
genesis 1725 WSADATA wsadata;
genesis 1726 int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
genesis 1727 if (ret != NO_ERROR)
genesis 1728 {
genesis 1729 strError = strprintf("Error: TCP/IP socket library failed to start (WSAStartup returned error %d)", ret);
genesis 1730 printf("%s\n", strError.c_str());
genesis 1731 return false;
genesis 1732 }
genesis 1733 #endif
genesis 1734
genesis 1735 // Create socket for listening for incoming connections
genesis 1736 hListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
genesis 1737 if (hListenSocket == INVALID_SOCKET)
genesis 1738 {
genesis 1739 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
genesis 1740 printf("%s\n", strError.c_str());
genesis 1741 return false;
genesis 1742 }
genesis 1743
genesis 1744 #ifdef SO_NOSIGPIPE
genesis 1745 // Different way of disabling SIGPIPE on BSD
genesis 1746 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
genesis 1747 #endif
genesis 1748
genesis 1749 #ifndef WIN32
genesis 1750 // Allow binding if the port is still in TIME_WAIT state after
genesis 1751 // the program was closed and restarted. Not an issue on windows.
genesis 1752 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
genesis 1753 #endif
genesis 1754
genesis 1755 #ifdef WIN32
genesis 1756 // Set to nonblocking, incoming connections will also inherit this
genesis 1757 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
genesis 1758 #else
genesis 1759 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
genesis 1760 #endif
genesis 1761 {
genesis 1762 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
genesis 1763 printf("%s\n", strError.c_str());
genesis 1764 return false;
genesis 1765 }
genesis 1766
genesis 1767 // The sockaddr_in structure specifies the address family,
genesis 1768 // IP address, and port for the socket that is being bound
genesis 1769 struct sockaddr_in sockaddr;
genesis 1770 memset(&sockaddr, 0, sizeof(sockaddr));
genesis 1771 sockaddr.sin_family = AF_INET;
genesis 1772 sockaddr.sin_addr.s_addr = INADDR_ANY; // bind to all IPs on this computer
genesis 1773 sockaddr.sin_port = htons(GetListenPort());
genesis 1774 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
genesis 1775 {
genesis 1776 int nErr = WSAGetLastError();
genesis 1777 if (nErr == WSAEADDRINUSE)
genesis 1778 strError = strprintf(_("Unable to bind to port %d on this computer. Bitcoin is probably already running."), ntohs(sockaddr.sin_port));
genesis 1779 else
genesis 1780 strError = strprintf("Error: Unable to bind to port %d on this computer (bind returned error %d)", ntohs(sockaddr.sin_port), nErr);
genesis 1781 printf("%s\n", strError.c_str());
genesis 1782 return false;
genesis 1783 }
genesis 1784 printf("Bound to port %d\n", ntohs(sockaddr.sin_port));
genesis 1785
genesis 1786 // Listen for incoming connections
genesis 1787 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
genesis 1788 {
genesis 1789 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
genesis 1790 printf("%s\n", strError.c_str());
genesis 1791 return false;
genesis 1792 }
genesis 1793
genesis 1794 return true;
genesis 1795 }
genesis 1796
genesis 1797 void StartNode(void* parg)
genesis 1798 {
genesis 1799 if (pnodeLocalHost == NULL)
genesis 1800 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress("127.0.0.1", 0, false, nLocalServices));
genesis 1801
genesis 1802 #ifdef WIN32
genesis 1803 // Get local host ip
genesis 1804 char pszHostName[1000] = "";
genesis 1805 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
genesis 1806 {
genesis 1807 vector<CAddress> vaddr;
genesis 1808 if (Lookup(pszHostName, vaddr, nLocalServices, -1, true))
genesis 1809 BOOST_FOREACH (const CAddress &addr, vaddr)
genesis 1810 if (addr.GetByte(3) != 127)
genesis 1811 {
genesis 1812 addrLocalHost = addr;
genesis 1813 break;
genesis 1814 }
genesis 1815 }
genesis 1816 #else
genesis 1817 // Get local host ip
genesis 1818 struct ifaddrs* myaddrs;
genesis 1819 if (getifaddrs(&myaddrs) == 0)
genesis 1820 {
genesis 1821 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
genesis 1822 {
genesis 1823 if (ifa->ifa_addr == NULL) continue;
genesis 1824 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
genesis 1825 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
genesis 1826 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
genesis 1827 char pszIP[100];
genesis 1828 if (ifa->ifa_addr->sa_family == AF_INET)
genesis 1829 {
genesis 1830 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
genesis 1831 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s4->sin_addr), pszIP, sizeof(pszIP)) != NULL)
genesis 1832 printf("ipv4 %s: %s\n", ifa->ifa_name, pszIP);
genesis 1833
genesis 1834 // Take the first IP that isn't loopback 127.x.x.x
genesis 1835 CAddress addr(*(unsigned int*)&s4->sin_addr, GetListenPort(), nLocalServices);
genesis 1836 if (addr.IsValid() && addr.GetByte(3) != 127)
genesis 1837 {
genesis 1838 addrLocalHost = addr;
genesis 1839 break;
genesis 1840 }
genesis 1841 }
genesis 1842 else if (ifa->ifa_addr->sa_family == AF_INET6)
genesis 1843 {
genesis 1844 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
genesis 1845 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s6->sin6_addr), pszIP, sizeof(pszIP)) != NULL)
genesis 1846 printf("ipv6 %s: %s\n", ifa->ifa_name, pszIP);
genesis 1847 }
genesis 1848 }
genesis 1849 freeifaddrs(myaddrs);
genesis 1850 }
genesis 1851 #endif
genesis 1852 printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
genesis 1853
genesis 1854 if (fUseProxy || mapArgs.count("-connect") || fNoListen)
genesis 1855 {
genesis 1856 // Proxies can't take incoming connections
genesis 1857 addrLocalHost.ip = CAddress("0.0.0.0").ip;
genesis 1858 printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
genesis 1859 }
genesis 1860 else
genesis 1861 {
genesis 1862 CreateThread(ThreadGetMyExternalIP, NULL);
genesis 1863 }
genesis 1864
genesis 1865 //
genesis 1866 // Start threads
genesis 1867 //
genesis 1868
genesis 1869 if (GetBoolArg("-nodnsseed"))
genesis 1870 printf("DNS seeding disabled\n");
genesis 1871 else
genesis 1872 if (!CreateThread(ThreadDNSAddressSeed, NULL))
genesis 1873 printf("Error: CreateThread(ThreadDNSAddressSeed) failed\n");
genesis 1874
genesis 1875 // Map ports with UPnP
genesis 1876 if (fHaveUPnP)
genesis 1877 MapPort(fUseUPnP);
genesis 1878
genesis 1879 // Get addresses from IRC and advertise ours
genesis 1880 if (!CreateThread(ThreadIRCSeed, NULL))
genesis 1881 printf("Error: CreateThread(ThreadIRCSeed) failed\n");
genesis 1882
genesis 1883 // Send and receive from sockets, accept connections
genesis 1884 if (!CreateThread(ThreadSocketHandler, NULL))
genesis 1885 printf("Error: CreateThread(ThreadSocketHandler) failed\n");
genesis 1886
genesis 1887 // Initiate outbound connections
genesis 1888 if (!CreateThread(ThreadOpenConnections, NULL))
genesis 1889 printf("Error: CreateThread(ThreadOpenConnections) failed\n");
genesis 1890
genesis 1891 // Process messages
genesis 1892 if (!CreateThread(ThreadMessageHandler, NULL))
genesis 1893 printf("Error: CreateThread(ThreadMessageHandler) failed\n");
genesis 1894
genesis 1895 // Generate coins in the background
genesis 1896 GenerateBitcoins(fGenerateBitcoins, pwalletMain);
genesis 1897 }
genesis 1898
genesis 1899 bool StopNode()
genesis 1900 {
genesis 1901 printf("StopNode()\n");
genesis 1902 fShutdown = true;
genesis 1903 nTransactionsUpdated++;
genesis 1904 int64 nStart = GetTime();
genesis 1905 while (vnThreadsRunning[0] > 0 || vnThreadsRunning[1] > 0 || vnThreadsRunning[2] > 0 || vnThreadsRunning[3] > 0 || vnThreadsRunning[4] > 0
genesis 1906 #ifdef USE_UPNP
genesis 1907 || vnThreadsRunning[5] > 0
genesis 1908 #endif
genesis 1909 )
genesis 1910 {
genesis 1911 if (GetTime() - nStart > 20)
genesis 1912 break;
genesis 1913 Sleep(20);
genesis 1914 }
genesis 1915 if (vnThreadsRunning[0] > 0) printf("ThreadSocketHandler still running\n");
genesis 1916 if (vnThreadsRunning[1] > 0) printf("ThreadOpenConnections still running\n");
genesis 1917 if (vnThreadsRunning[2] > 0) printf("ThreadMessageHandler still running\n");
genesis 1918 if (vnThreadsRunning[3] > 0) printf("ThreadBitcoinMiner still running\n");
genesis 1919 if (vnThreadsRunning[4] > 0) printf("ThreadRPCServer still running\n");
genesis 1920 if (fHaveUPnP && vnThreadsRunning[5] > 0) printf("ThreadMapPort still running\n");
genesis 1921 if (vnThreadsRunning[6] > 0) printf("ThreadDNSAddressSeed still running\n");
genesis 1922 while (vnThreadsRunning[2] > 0 || vnThreadsRunning[4] > 0)
genesis 1923 Sleep(20);
genesis 1924 Sleep(50);
genesis 1925
genesis 1926 return true;
genesis 1927 }
genesis 1928
genesis 1929 class CNetCleanup
genesis 1930 {
genesis 1931 public:
genesis 1932 CNetCleanup()
genesis 1933 {
genesis 1934 }
genesis 1935 ~CNetCleanup()
genesis 1936 {
genesis 1937 // Close sockets
genesis 1938 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 1939 if (pnode->hSocket != INVALID_SOCKET)
genesis 1940 closesocket(pnode->hSocket);
genesis 1941 if (hListenSocket != INVALID_SOCKET)
genesis 1942 if (closesocket(hListenSocket) == SOCKET_ERROR)
genesis 1943 printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
genesis 1944
genesis 1945 #ifdef WIN32
genesis 1946 // Shutdown Windows Sockets
genesis 1947 WSACleanup();
genesis 1948 #endif
genesis 1949 }
genesis 1950 }
genesis 1951 instance_of_cnetcleanup;