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