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