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