genesis 1
genesis 2
genesis 3
genesis 4
genesis 5
genesis 6 #include "headers.h"
genesis 7 #include "irc.h"
genesis 8 #include "db.h"
genesis 9 #include "net.h"
genesis 10 #include "init.h"
genesis 11 #include "strlcpy.h"
genesis 12
genesis 13
genesis 14 using namespace std;
genesis 15 using namespace boost;
genesis 16
genesis 17 static const int MAX_OUTBOUND_CONNECTIONS = 8;
genesis 18
genesis 19 void ThreadMessageHandler2(void* parg);
genesis 20 void ThreadSocketHandler2(void* parg);
genesis 21 void ThreadOpenConnections2(void* parg);
genesis 22 bool OpenNetworkConnection(const CAddress& addrConnect);
genesis 23
genesis 24
genesis 25
genesis 26
genesis 27
genesis 28
genesis 29
genesis 30
genesis 31 bool fClient = false;
genesis 32 bool fAllowDNS = false;
genesis 33 uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK);
genesis 34 CAddress addrLocalHost("0.0.0.0", 0, false, nLocalServices);
genesis 35 static CNode* pnodeLocalHost = NULL;
genesis 36 uint64 nLocalHostNonce = 0;
genesis 37 array<int, 10> vnThreadsRunning;
genesis 38 static SOCKET hListenSocket = INVALID_SOCKET;
genesis 39
genesis 40 vector<CNode*> vNodes;
genesis 41 CCriticalSection cs_vNodes;
genesis 42 map<vector<unsigned char>, CAddress> mapAddresses;
genesis 43 CCriticalSection cs_mapAddresses;
genesis 44 map<CInv, CDataStream> mapRelay;
genesis 45 deque<pair<int64, CInv> > vRelayExpiration;
genesis 46 CCriticalSection cs_mapRelay;
genesis 47 map<CInv, int64> mapAlreadyAskedFor;
genesis 48
genesis 49
genesis 50 int fUseProxy = false;
genesis 51 int nConnectTimeout = 5000;
genesis 52 CAddress addrProxy("127.0.0.1",9050);
genesis 53
genesis 54
genesis 55
genesis 56
genesis 57 unsigned short GetListenPort()
genesis 58 {
genesis 59 return (unsigned short)(GetArg("-port", GetDefaultPort()));
genesis 60 }
genesis 61
genesis 62 void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd)
genesis 63 {
genesis 64
genesis 65 if (pindexBegin == pindexLastGetBlocksBegin && hashEnd == hashLastGetBlocksEnd)
genesis 66 return;
genesis 67 pindexLastGetBlocksBegin = pindexBegin;
genesis 68 hashLastGetBlocksEnd = hashEnd;
genesis 69
genesis 70 PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd);
genesis 71 }
genesis 72
genesis 73
genesis 74
genesis 75
genesis 76
genesis 77 bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet, int nTimeout)
genesis 78 {
genesis 79 hSocketRet = INVALID_SOCKET;
genesis 80
genesis 81 SOCKET hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
genesis 82 if (hSocket == INVALID_SOCKET)
genesis 83 return false;
genesis 84 #ifdef SO_NOSIGPIPE
genesis 85 int set = 1;
genesis 86 setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
genesis 87 #endif
genesis 88
genesis 89 bool fProxy = (fUseProxy && addrConnect.IsRoutable());
genesis 90 struct sockaddr_in sockaddr = (fProxy ? addrProxy.GetSockAddr() : addrConnect.GetSockAddr());
genesis 91
genesis 92 int fFlags = fcntl(hSocket, F_GETFL, 0);
genesis 93 if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == -1)
bitcoin-asciilife... 94
genesis 95 {
genesis 96 closesocket(hSocket);
genesis 97 return false;
genesis 98 }
genesis 99
genesis 100
genesis 101 if (connect(hSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
genesis 102 {
genesis 103
genesis 104 if (WSAGetLastError() == WSAEINPROGRESS || WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINVAL)
genesis 105 {
genesis 106 struct timeval timeout;
genesis 107 timeout.tv_sec = nTimeout / 1000;
genesis 108 timeout.tv_usec = (nTimeout % 1000) * 1000;
genesis 109
genesis 110 fd_set fdset;
genesis 111 FD_ZERO(&fdset);
genesis 112 FD_SET(hSocket, &fdset);
genesis 113 int nRet = select(hSocket + 1, NULL, &fdset, NULL, &timeout);
genesis 114 if (nRet == 0)
genesis 115 {
genesis 116 printf("connection timeout\n");
genesis 117 closesocket(hSocket);
genesis 118 return false;
genesis 119 }
genesis 120 if (nRet == SOCKET_ERROR)
genesis 121 {
genesis 122 printf("select() for connection failed: %i\n",WSAGetLastError());
genesis 123 closesocket(hSocket);
genesis 124 return false;
genesis 125 }
genesis 126 socklen_t nRetSize = sizeof(nRet);
genesis 127 if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, &nRet, &nRetSize) == SOCKET_ERROR)
genesis 128 {
genesis 129 printf("getsockopt() for connection failed: %i\n",WSAGetLastError());
genesis 130 closesocket(hSocket);
genesis 131 return false;
genesis 132 }
genesis 133 if (nRet != 0)
genesis 134 {
genesis 135 printf("connect() failed after select(): %s\n",strerror(nRet));
genesis 136 closesocket(hSocket);
genesis 137 return false;
genesis 138 }
genesis 139 }
genesis 140 else
genesis 141 {
genesis 142 printf("connect() failed: %i\n",WSAGetLastError());
genesis 143 closesocket(hSocket);
genesis 144 return false;
genesis 145 }
genesis 146 }
genesis 147
genesis 148
genesis 149 this isn't even strictly necessary
genesis 150 CNode::ConnectNode immediately turns the socket back to non-blocking
genesis 151 but we'll turn it back to blocking just in case
genesis 152 */
genesis 153 fFlags = fcntl(hSocket, F_GETFL, 0);
genesis 154 if (fcntl(hSocket, F_SETFL, fFlags & !O_NONBLOCK) == SOCKET_ERROR)
genesis 155 {
genesis 156 closesocket(hSocket);
genesis 157 return false;
genesis 158 }
genesis 159
genesis 160 if (fProxy)
genesis 161 {
genesis 162 printf("proxy connecting %s\n", addrConnect.ToString().c_str());
genesis 163 char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user";
genesis 164 memcpy(pszSocks4IP + 2, &addrConnect.port, 2);
genesis 165 memcpy(pszSocks4IP + 4, &addrConnect.ip, 4);
genesis 166 char* pszSocks4 = pszSocks4IP;
genesis 167 int nSize = sizeof(pszSocks4IP);
genesis 168
genesis 169 int ret = send(hSocket, pszSocks4, nSize, MSG_NOSIGNAL);
genesis 170 if (ret != nSize)
genesis 171 {
genesis 172 closesocket(hSocket);
genesis 173 return error("Error sending to proxy");
genesis 174 }
genesis 175 char pchRet[8];
genesis 176 if (recv(hSocket, pchRet, 8, 0) != 8)
genesis 177 {
genesis 178 closesocket(hSocket);
genesis 179 return error("Error reading proxy response");
genesis 180 }
genesis 181 if (pchRet[1] != 0x5a)
genesis 182 {
genesis 183 closesocket(hSocket);
genesis 184 if (pchRet[1] != 0x5b)
genesis 185 printf("ERROR: Proxy returned error %d\n", pchRet[1]);
genesis 186 return false;
genesis 187 }
genesis 188 printf("proxy connected %s\n", addrConnect.ToString().c_str());
genesis 189 }
genesis 190
genesis 191 hSocketRet = hSocket;
genesis 192 return true;
genesis 193 }
genesis 194
genesis 195
genesis 196 bool Lookup(const char *pszName, vector<CAddress>& vaddr, int nServices, int nMaxSolutions, bool fAllowLookup, int portDefault, bool fAllowPort)
genesis 197 {
genesis 198 vaddr.clear();
genesis 199 if (pszName[0] == 0)
genesis 200 return false;
genesis 201 int port = portDefault;
genesis 202 char psz[256];
genesis 203 char *pszHost = psz;
genesis 204 strlcpy(psz, pszName, sizeof(psz));
genesis 205 if (fAllowPort)
genesis 206 {
genesis 207 char* pszColon = strrchr(psz+1,':');
genesis 208 char *pszPortEnd = NULL;
genesis 209 int portParsed = pszColon ? strtoul(pszColon+1, &pszPortEnd, 10) : 0;
genesis 210 if (pszColon && pszPortEnd && pszPortEnd[0] == 0)
genesis 211 {
genesis 212 if (psz[0] == '[' && pszColon[-1] == ']')
genesis 213 {
genesis 214
genesis 215 pszHost = psz+1;
genesis 216 pszColon[-1] = 0;
genesis 217 }
genesis 218 else
genesis 219 pszColon[0] = 0;
genesis 220 port = portParsed;
genesis 221 if (port < 0 || port > USHRT_MAX)
genesis 222 port = USHRT_MAX;
genesis 223 }
genesis 224 }
genesis 225
genesis 226 unsigned int addrIP = inet_addr(pszHost);
genesis 227 if (addrIP != INADDR_NONE)
genesis 228 {
genesis 229
genesis 230 vaddr.push_back(CAddress(addrIP, port, nServices));
genesis 231 return true;
genesis 232 }
genesis 233
genesis 234 if (!fAllowLookup)
genesis 235 return false;
genesis 236
genesis 237 struct hostent* phostent = gethostbyname(pszHost);
genesis 238 if (!phostent)
genesis 239 return false;
genesis 240
genesis 241 if (phostent->h_addrtype != AF_INET)
genesis 242 return false;
genesis 243
genesis 244 char** ppAddr = phostent->h_addr_list;
genesis 245 while (*ppAddr != NULL && vaddr.size() != nMaxSolutions)
genesis 246 {
genesis 247 CAddress addr(((struct in_addr*)ppAddr[0])->s_addr, port, nServices);
genesis 248 if (addr.IsValid())
genesis 249 vaddr.push_back(addr);
genesis 250 ppAddr++;
genesis 251 }
genesis 252
genesis 253 return (vaddr.size() > 0);
genesis 254 }
genesis 255
genesis 256
genesis 257 bool Lookup(const char *pszName, CAddress& addr, int nServices, bool fAllowLookup, int portDefault, bool fAllowPort)
genesis 258 {
genesis 259 vector<CAddress> vaddr;
genesis 260 bool fRet = Lookup(pszName, vaddr, nServices, 1, fAllowLookup, portDefault, fAllowPort);
genesis 261 if (fRet)
genesis 262 addr = vaddr[0];
genesis 263 return fRet;
genesis 264 }
genesis 265
genesis 266 bool GetMyExternalIP2(const CAddress& addrConnect, const char* pszGet, const char* pszKeyword, unsigned int& ipRet)
genesis 267 {
genesis 268 SOCKET hSocket;
genesis 269 if (!ConnectSocket(addrConnect, hSocket))
genesis 270 return error("GetMyExternalIP() : connection to %s failed", addrConnect.ToString().c_str());
genesis 271
genesis 272 send(hSocket, pszGet, strlen(pszGet), MSG_NOSIGNAL);
genesis 273
genesis 274 string strLine;
genesis 275 while (RecvLine(hSocket, strLine))
genesis 276 {
genesis 277 if (strLine.empty())
genesis 278 {
genesis 279 loop
genesis 280 {
genesis 281 if (!RecvLine(hSocket, strLine))
genesis 282 {
genesis 283 closesocket(hSocket);
genesis 284 return false;
genesis 285 }
genesis 286 if (pszKeyword == NULL)
genesis 287 break;
genesis 288 if (strLine.find(pszKeyword) != -1)
genesis 289 {
genesis 290 strLine = strLine.substr(strLine.find(pszKeyword) + strlen(pszKeyword));
genesis 291 break;
genesis 292 }
genesis 293 }
genesis 294 closesocket(hSocket);
genesis 295 if (strLine.find("<") != -1)
genesis 296 strLine = strLine.substr(0, strLine.find("<"));
genesis 297 strLine = strLine.substr(strspn(strLine.c_str(), " \t\n\r"));
genesis 298 while (strLine.size() > 0 && isspace(strLine[strLine.size()-1]))
genesis 299 strLine.resize(strLine.size()-1);
genesis 300 CAddress addr(strLine,0,true);
genesis 301 printf("GetMyExternalIP() received [%s] %s\n", strLine.c_str(), addr.ToString().c_str());
genesis 302 if (addr.ip == 0 || addr.ip == INADDR_NONE || !addr.IsRoutable())
genesis 303 return false;
genesis 304 ipRet = addr.ip;
genesis 305 return true;
genesis 306 }
genesis 307 }
genesis 308 closesocket(hSocket);
genesis 309 return error("GetMyExternalIP() : connection closed");
genesis 310 }
genesis 311
genesis 312
genesis 313 bool GetMyExternalIP(unsigned int& ipRet)
genesis 314 {
genesis 315 CAddress addrConnect;
genesis 316 const char* pszGet;
genesis 317 const char* pszKeyword;
genesis 318
genesis 319 if (fUseProxy)
genesis 320 return false;
genesis 321
genesis 322 for (int nLookup = 0; nLookup <= 1; nLookup++)
genesis 323 for (int nHost = 1; nHost <= 2; nHost++)
genesis 324 {
genesis 325
genesis 326
genesis 327
genesis 328
genesis 329 if (nHost == 1)
genesis 330 {
genesis 331 addrConnect = CAddress("91.198.22.70",80);
genesis 332
genesis 333 if (nLookup == 1)
genesis 334 {
genesis 335 CAddress addrIP("checkip.dyndns.org", 80, true);
genesis 336 if (addrIP.IsValid())
genesis 337 addrConnect = addrIP;
genesis 338 }
genesis 339
genesis 340 pszGet = "GET / HTTP/1.1\r\n"
genesis 341 "Host: checkip.dyndns.org\r\n"
genesis 342 "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
genesis 343 "Connection: close\r\n"
genesis 344 "\r\n";
genesis 345
genesis 346 pszKeyword = "Address:";
genesis 347 }
genesis 348 else if (nHost == 2)
genesis 349 {
genesis 350 addrConnect = CAddress("74.208.43.192", 80);
genesis 351
genesis 352 if (nLookup == 1)
genesis 353 {
genesis 354 CAddress addrIP("www.showmyip.com", 80, true);
genesis 355 if (addrIP.IsValid())
genesis 356 addrConnect = addrIP;
genesis 357 }
genesis 358
genesis 359 pszGet = "GET /simple/ HTTP/1.1\r\n"
genesis 360 "Host: www.showmyip.com\r\n"
genesis 361 "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
genesis 362 "Connection: close\r\n"
genesis 363 "\r\n";
genesis 364
genesis 365 pszKeyword = NULL;
genesis 366 }
genesis 367
genesis 368 if (GetMyExternalIP2(addrConnect, pszGet, pszKeyword, ipRet))
genesis 369 return true;
genesis 370 }
genesis 371
genesis 372 return false;
genesis 373 }
genesis 374
genesis 375 void ThreadGetMyExternalIP(void* parg)
genesis 376 {
genesis 377
genesis 378 if (!GetBoolArg("-noirc"))
genesis 379 {
genesis 380 for (int i = 0; i < 2 * 60; i++)
genesis 381 {
genesis 382 Sleep(1000);
genesis 383 if (fGotExternalIP || fShutdown)
genesis 384 return;
genesis 385 }
genesis 386 }
genesis 387
genesis 388
genesis 389 if (GetMyExternalIP(addrLocalHost.ip))
genesis 390 {
genesis 391 printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
genesis 392 if (addrLocalHost.IsRoutable())
genesis 393 {
genesis 394
genesis 395
genesis 396 CAddress addr(addrLocalHost);
genesis 397 addr.nTime = GetAdjustedTime();
genesis 398 CRITICAL_BLOCK(cs_vNodes)
genesis 399 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 400 pnode->PushAddress(addr);
genesis 401 }
genesis 402 }
genesis 403 }
genesis 404
genesis 405
genesis 406
genesis 407
genesis 408
genesis 409 bool AddAddress(CAddress addr, int64 nTimePenalty, CAddrDB *pAddrDB)
genesis 410 {
genesis 411 if (!addr.IsRoutable())
genesis 412 return false;
genesis 413 if (addr.ip == addrLocalHost.ip)
genesis 414 return false;
genesis 415 addr.nTime = max((int64)0, (int64)addr.nTime - nTimePenalty);
genesis 416 bool fUpdated = false;
genesis 417 bool fNew = false;
genesis 418 CAddress addrFound = addr;
genesis 419
genesis 420 CRITICAL_BLOCK(cs_mapAddresses)
genesis 421 {
genesis 422 map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
genesis 423 if (it == mapAddresses.end())
genesis 424 {
genesis 425
genesis 426 printf("AddAddress(%s)\n", addr.ToString().c_str());
genesis 427 mapAddresses.insert(make_pair(addr.GetKey(), addr));
genesis 428 fUpdated = true;
genesis 429 fNew = true;
genesis 430 }
genesis 431 else
genesis 432 {
genesis 433 addrFound = (*it).second;
genesis 434 if ((addrFound.nServices | addr.nServices) != addrFound.nServices)
genesis 435 {
genesis 436
genesis 437 addrFound.nServices |= addr.nServices;
genesis 438 fUpdated = true;
genesis 439 }
genesis 440 bool fCurrentlyOnline = (GetAdjustedTime() - addr.nTime < 24 * 60 * 60);
genesis 441 int64 nUpdateInterval = (fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60);
genesis 442 if (addrFound.nTime < addr.nTime - nUpdateInterval)
genesis 443 {
genesis 444
genesis 445 addrFound.nTime = addr.nTime;
genesis 446 fUpdated = true;
genesis 447 }
genesis 448 }
genesis 449 }
genesis 450
genesis 451
genesis 452
genesis 453
genesis 454
genesis 455
genesis 456 if (fUpdated)
genesis 457 {
genesis 458 if (pAddrDB)
genesis 459 pAddrDB->WriteAddress(addrFound);
genesis 460 else
genesis 461 CAddrDB().WriteAddress(addrFound);
genesis 462 }
genesis 463 return fNew;
genesis 464 }
genesis 465
genesis 466 void AddressCurrentlyConnected(const CAddress& addr)
genesis 467 {
genesis 468 CAddress *paddrFound = NULL;
genesis 469
genesis 470 CRITICAL_BLOCK(cs_mapAddresses)
genesis 471 {
genesis 472
genesis 473 map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
genesis 474 if (it != mapAddresses.end())
genesis 475 paddrFound = &(*it).second;
genesis 476 }
genesis 477
genesis 478 if (paddrFound)
genesis 479 {
genesis 480 int64 nUpdateInterval = 20 * 60;
genesis 481 if (paddrFound->nTime < GetAdjustedTime() - nUpdateInterval)
genesis 482 {
genesis 483
genesis 484 paddrFound->nTime = GetAdjustedTime();
genesis 485 CAddrDB addrdb;
genesis 486 addrdb.WriteAddress(*paddrFound);
genesis 487 }
genesis 488 }
genesis 489 }
genesis 490
genesis 491
genesis 492
genesis 493
genesis 494
genesis 495 void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1)
genesis 496 {
genesis 497
genesis 498
genesis 499 CRITICAL_BLOCK(cs_vNodes)
genesis 500 {
genesis 501 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 502 {
genesis 503 CRITICAL_BLOCK(pnode->cs_mapRequests)
genesis 504 {
genesis 505 for (map<uint256, CRequestTracker>::iterator mi = pnode->mapRequests.begin(); mi != pnode->mapRequests.end();)
genesis 506 {
genesis 507 CRequestTracker& tracker = (*mi).second;
genesis 508 if (tracker.fn == fn && tracker.param1 == param1)
genesis 509 pnode->mapRequests.erase(mi++);
genesis 510 else
genesis 511 mi++;
genesis 512 }
genesis 513 }
genesis 514 }
genesis 515 }
genesis 516 }
genesis 517
genesis 518
genesis 519
genesis 520
genesis 521
genesis 522
genesis 523
genesis 524
genesis 525
genesis 526
genesis 527
genesis 528
genesis 529
genesis 530
genesis 531
genesis 532
genesis 533 bool AnySubscribed(unsigned int nChannel)
genesis 534 {
genesis 535 if (pnodeLocalHost->IsSubscribed(nChannel))
genesis 536 return true;
genesis 537 CRITICAL_BLOCK(cs_vNodes)
genesis 538 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 539 if (pnode->IsSubscribed(nChannel))
genesis 540 return true;
genesis 541 return false;
genesis 542 }
genesis 543
genesis 544 bool CNode::IsSubscribed(unsigned int nChannel)
genesis 545 {
genesis 546 if (nChannel >= vfSubscribe.size())
genesis 547 return false;
genesis 548 return vfSubscribe[nChannel];
genesis 549 }
genesis 550
genesis 551 void CNode::Subscribe(unsigned int nChannel, unsigned int nHops)
genesis 552 {
genesis 553 if (nChannel >= vfSubscribe.size())
genesis 554 return;
genesis 555
genesis 556 if (!AnySubscribed(nChannel))
genesis 557 {
genesis 558
genesis 559 CRITICAL_BLOCK(cs_vNodes)
genesis 560 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 561 if (pnode != this)
genesis 562 pnode->PushMessage("subscribe", nChannel, nHops);
genesis 563 }
genesis 564
genesis 565 vfSubscribe[nChannel] = true;
genesis 566 }
genesis 567
genesis 568 void CNode::CancelSubscribe(unsigned int nChannel)
genesis 569 {
genesis 570 if (nChannel >= vfSubscribe.size())
genesis 571 return;
genesis 572
genesis 573
genesis 574 if (!vfSubscribe[nChannel])
genesis 575 return;
genesis 576 vfSubscribe[nChannel] = false;
genesis 577
genesis 578 if (!AnySubscribed(nChannel))
genesis 579 {
genesis 580
genesis 581 CRITICAL_BLOCK(cs_vNodes)
genesis 582 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 583 if (pnode != this)
genesis 584 pnode->PushMessage("sub-cancel", nChannel);
genesis 585 }
genesis 586 }
genesis 587
genesis 588
genesis 589
genesis 590
genesis 591
genesis 592
genesis 593
genesis 594
genesis 595
genesis 596 CNode* FindNode(unsigned int ip)
genesis 597 {
genesis 598 CRITICAL_BLOCK(cs_vNodes)
genesis 599 {
genesis 600 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 601 if (pnode->addr.ip == ip)
genesis 602 return (pnode);
genesis 603 }
genesis 604 return NULL;
genesis 605 }
genesis 606
genesis 607 CNode* FindNode(CAddress addr)
genesis 608 {
genesis 609 CRITICAL_BLOCK(cs_vNodes)
genesis 610 {
genesis 611 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 612 if (pnode->addr == addr)
genesis 613 return (pnode);
genesis 614 }
genesis 615 return NULL;
genesis 616 }
genesis 617
genesis 618 CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
genesis 619 {
genesis 620 if (addrConnect.ip == addrLocalHost.ip)
genesis 621 return NULL;
genesis 622
genesis 623
genesis 624 CNode* pnode = FindNode(addrConnect.ip);
genesis 625 if (pnode)
genesis 626 {
genesis 627 if (nTimeout != 0)
genesis 628 pnode->AddRef(nTimeout);
genesis 629 else
genesis 630 pnode->AddRef();
genesis 631 return pnode;
genesis 632 }
genesis 633
genesis 634
genesis 635 printf("trying connection %s lastseen=%.1fhrs lasttry=%.1fhrs\n",
genesis 636 addrConnect.ToString().c_str(),
genesis 637 (double)(addrConnect.nTime - GetAdjustedTime())/3600.0,
genesis 638 (double)(addrConnect.nLastTry - GetAdjustedTime())/3600.0);
genesis 639
genesis 640 CRITICAL_BLOCK(cs_mapAddresses)
genesis 641 mapAddresses[addrConnect.GetKey()].nLastTry = GetAdjustedTime();
genesis 642
genesis 643
genesis 644 SOCKET hSocket;
genesis 645 if (ConnectSocket(addrConnect, hSocket))
genesis 646 {
genesis 647
genesis 648 printf("connected %s\n", addrConnect.ToString().c_str());
genesis 649
genesis 650
genesis 651 if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
genesis 652 printf("ConnectSocket() : fcntl nonblocking setting failed, error %d\n", errno);
genesis 653
genesis 654
genesis 655 CNode* pnode = new CNode(hSocket, addrConnect, false);
genesis 656 if (nTimeout != 0)
genesis 657 pnode->AddRef(nTimeout);
genesis 658 else
genesis 659 pnode->AddRef();
genesis 660 CRITICAL_BLOCK(cs_vNodes)
genesis 661 vNodes.push_back(pnode);
genesis 662
genesis 663 pnode->nTimeConnected = GetTime();
genesis 664 return pnode;
genesis 665 }
genesis 666 else
genesis 667 {
genesis 668 return NULL;
genesis 669 }
genesis 670 }
genesis 671
genesis 672 void CNode::CloseSocketDisconnect()
genesis 673 {
genesis 674 fDisconnect = true;
genesis 675 if (hSocket != INVALID_SOCKET)
genesis 676 {
genesis 677 if (fDebug)
genesis 678 printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
genesis 679 printf("disconnecting node %s\n", addr.ToString().c_str());
genesis 680 closesocket(hSocket);
genesis 681 hSocket = INVALID_SOCKET;
genesis 682 }
genesis 683 }
genesis 684
genesis 685 void CNode::Cleanup()
genesis 686 {
genesis 687
genesis 688
genesis 689
genesis 690
genesis 691 for (unsigned int nChannel = 0; nChannel < vfSubscribe.size(); nChannel++)
genesis 692 if (vfSubscribe[nChannel])
genesis 693 CancelSubscribe(nChannel);
genesis 694 }
genesis 695
genesis 696
genesis 697 std::map<unsigned int, int64> CNode::setBanned;
genesis 698 CCriticalSection CNode::cs_setBanned;
genesis 699
genesis 700 void CNode::ClearBanned()
genesis 701 {
genesis 702 setBanned.clear();
genesis 703 }
genesis 704
genesis 705 bool CNode::IsBanned(unsigned int ip)
genesis 706 {
genesis 707 bool fResult = false;
genesis 708 CRITICAL_BLOCK(cs_setBanned)
genesis 709 {
genesis 710 std::map<unsigned int, int64>::iterator i = setBanned.find(ip);
genesis 711 if (i != setBanned.end())
genesis 712 {
genesis 713 int64 t = (*i).second;
genesis 714 if (GetTime() < t)
genesis 715 fResult = true;
genesis 716 }
genesis 717 }
genesis 718 return fResult;
genesis 719 }
genesis 720
genesis 721 bool CNode::Misbehaving(int howmuch)
genesis 722 {
genesis 723 if (addr.IsLocal())
genesis 724 {
genesis 725 printf("Warning: local node %s misbehaving\n", addr.ToString().c_str());
genesis 726 return false;
genesis 727 }
genesis 728
genesis 729 nMisbehavior += howmuch;
genesis 730 if (nMisbehavior >= GetArg("-banscore", 100))
genesis 731 {
genesis 732 int64 banTime = GetTime()+GetArg("-bantime", 60*60*24);
genesis 733 CRITICAL_BLOCK(cs_setBanned)
genesis 734 if (setBanned[addr.ip] < banTime)
genesis 735 setBanned[addr.ip] = banTime;
genesis 736 CloseSocketDisconnect();
genesis 737 printf("Disconnected %s for misbehavior (score=%d)\n", addr.ToString().c_str(), nMisbehavior);
genesis 738 return true;
genesis 739 }
genesis 740 return false;
genesis 741 }
genesis 742
genesis 743
genesis 744
genesis 745
genesis 746
genesis 747
genesis 748
genesis 749
genesis 750
genesis 751
genesis 752
genesis 753
genesis 754 void ThreadSocketHandler(void* parg)
genesis 755 {
genesis 756 IMPLEMENT_RANDOMIZE_STACK(ThreadSocketHandler(parg));
genesis 757 try
genesis 758 {
genesis 759 vnThreadsRunning[0]++;
genesis 760 ThreadSocketHandler2(parg);
genesis 761 vnThreadsRunning[0]--;
genesis 762 }
genesis 763 catch (std::exception& e) {
genesis 764 vnThreadsRunning[0]--;
genesis 765 PrintException(&e, "ThreadSocketHandler()");
genesis 766 } catch (...) {
genesis 767 vnThreadsRunning[0]--;
genesis 768 throw;
genesis 769 }
genesis 770 printf("ThreadSocketHandler exiting\n");
genesis 771 }
genesis 772
genesis 773 void ThreadSocketHandler2(void* parg)
genesis 774 {
genesis 775 printf("ThreadSocketHandler started\n");
genesis 776 list<CNode*> vNodesDisconnected;
genesis 777 int nPrevNodeCount = 0;
genesis 778
genesis 779 loop
genesis 780 {
genesis 781
genesis 782
genesis 783
genesis 784 CRITICAL_BLOCK(cs_vNodes)
genesis 785 {
genesis 786
genesis 787 vector<CNode*> vNodesCopy = vNodes;
genesis 788 BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis 789 {
genesis 790 if (pnode->fDisconnect ||
genesis 791 (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
genesis 792 {
genesis 793
genesis 794 vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
genesis 795
genesis 796
genesis 797 pnode->CloseSocketDisconnect();
genesis 798 pnode->Cleanup();
genesis 799
genesis 800
genesis 801 pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
genesis 802 if (pnode->fNetworkNode || pnode->fInbound)
genesis 803 pnode->Release();
genesis 804 vNodesDisconnected.push_back(pnode);
genesis 805 }
genesis 806 }
genesis 807
genesis 808
genesis 809 list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
genesis 810 BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy)
genesis 811 {
genesis 812
genesis 813 if (pnode->GetRefCount() <= 0)
genesis 814 {
genesis 815 bool fDelete = false;
genesis 816 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
genesis 817 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
genesis 818 TRY_CRITICAL_BLOCK(pnode->cs_mapRequests)
genesis 819 TRY_CRITICAL_BLOCK(pnode->cs_inventory)
genesis 820 fDelete = true;
genesis 821 if (fDelete)
genesis 822 {
genesis 823 vNodesDisconnected.remove(pnode);
genesis 824 delete pnode;
genesis 825 }
genesis 826 }
genesis 827 }
genesis 828 }
genesis 829 if (vNodes.size() != nPrevNodeCount)
genesis 830 {
genesis 831 nPrevNodeCount = vNodes.size();
genesis 832 MainFrameRepaint();
genesis 833 }
genesis 834
genesis 835
genesis 836
genesis 837
genesis 838
genesis 839 struct timeval timeout;
genesis 840 timeout.tv_sec = 0;
genesis 841 timeout.tv_usec = 50000;
genesis 842
genesis 843 fd_set fdsetRecv;
genesis 844 fd_set fdsetSend;
genesis 845 fd_set fdsetError;
genesis 846 FD_ZERO(&fdsetRecv);
genesis 847 FD_ZERO(&fdsetSend);
genesis 848 FD_ZERO(&fdsetError);
genesis 849 SOCKET hSocketMax = 0;
genesis 850
genesis 851 if(hListenSocket != INVALID_SOCKET)
genesis 852 FD_SET(hListenSocket, &fdsetRecv);
genesis 853 hSocketMax = max(hSocketMax, hListenSocket);
genesis 854 CRITICAL_BLOCK(cs_vNodes)
genesis 855 {
genesis 856 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 857 {
genesis 858 if (pnode->hSocket == INVALID_SOCKET)
genesis 859 continue;
genesis 860 FD_SET(pnode->hSocket, &fdsetRecv);
genesis 861 FD_SET(pnode->hSocket, &fdsetError);
genesis 862 hSocketMax = max(hSocketMax, pnode->hSocket);
genesis 863 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
genesis 864 if (!pnode->vSend.empty())
genesis 865 FD_SET(pnode->hSocket, &fdsetSend);
genesis 866 }
genesis 867 }
genesis 868
genesis 869 vnThreadsRunning[0]--;
genesis 870 int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
genesis 871 vnThreadsRunning[0]++;
genesis 872 if (fShutdown)
genesis 873 return;
genesis 874 if (nSelect == SOCKET_ERROR)
genesis 875 {
genesis 876 int nErr = WSAGetLastError();
genesis 877 if (hSocketMax > -1)
genesis 878 {
genesis 879 printf("socket select error %d\n", nErr);
genesis 880 for (int i = 0; i <= hSocketMax; i++)
genesis 881 FD_SET(i, &fdsetRecv);
genesis 882 }
genesis 883 FD_ZERO(&fdsetSend);
genesis 884 FD_ZERO(&fdsetError);
genesis 885 Sleep(timeout.tv_usec/1000);
genesis 886 }
genesis 887
genesis 888
genesis 889
genesis 890
genesis 891
genesis 892 if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
genesis 893 {
genesis 894 struct sockaddr_in sockaddr;
genesis 895 socklen_t len = sizeof(sockaddr);
genesis 896 SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
genesis 897 CAddress addr;
genesis 898 int nInbound = 0;
genesis 899
genesis 900 if (hSocket != INVALID_SOCKET)
genesis 901 addr = CAddress(sockaddr);
genesis 902
genesis 903 CRITICAL_BLOCK(cs_vNodes)
genesis 904 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 905 if (pnode->fInbound)
genesis 906 nInbound++;
genesis 907
genesis 908 if (hSocket == INVALID_SOCKET)
genesis 909 {
genesis 910 if (WSAGetLastError() != WSAEWOULDBLOCK)
genesis 911 printf("socket error accept failed: %d\n", WSAGetLastError());
genesis 912 }
genesis 913 else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
genesis 914 {
genesis 915 closesocket(hSocket);
genesis 916 }
genesis 917 else if (CNode::IsBanned(addr.ip))
genesis 918 {
genesis 919 printf("connection from %s dropped (banned)\n", addr.ToString().c_str());
genesis 920 closesocket(hSocket);
genesis 921 }
genesis 922 else
genesis 923 {
genesis 924 printf("accepted connection %s\n", addr.ToString().c_str());
genesis 925 CNode* pnode = new CNode(hSocket, addr, true);
genesis 926 pnode->AddRef();
genesis 927 CRITICAL_BLOCK(cs_vNodes)
genesis 928 vNodes.push_back(pnode);
genesis 929 }
genesis 930 }
genesis 931
genesis 932
genesis 933
genesis 934
genesis 935
genesis 936 vector<CNode*> vNodesCopy;
genesis 937 CRITICAL_BLOCK(cs_vNodes)
genesis 938 {
genesis 939 vNodesCopy = vNodes;
genesis 940 BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis 941 pnode->AddRef();
genesis 942 }
genesis 943 BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis 944 {
genesis 945 if (fShutdown)
genesis 946 return;
genesis 947
genesis 948
genesis 949
genesis 950
genesis 951 if (pnode->hSocket == INVALID_SOCKET)
genesis 952 continue;
genesis 953 if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
genesis 954 {
genesis 955 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
genesis 956 {
genesis 957 CDataStream& vRecv = pnode->vRecv;
genesis 958 unsigned int nPos = vRecv.size();
genesis 959
genesis 960 if (nPos > ReceiveBufferSize()) {
genesis 961 if (!pnode->fDisconnect)
genesis 962 printf("socket recv flood control disconnect (%d bytes)\n", vRecv.size());
genesis 963 pnode->CloseSocketDisconnect();
genesis 964 }
genesis 965 else {
genesis 966
genesis 967 char pchBuf[0x10000];
genesis 968 int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
genesis 969 if (nBytes > 0)
genesis 970 {
genesis 971 vRecv.resize(nPos + nBytes);
genesis 972 memcpy(&vRecv[nPos], pchBuf, nBytes);
genesis 973 pnode->nLastRecv = GetTime();
genesis 974 }
genesis 975 else if (nBytes == 0)
genesis 976 {
genesis 977
genesis 978 if (!pnode->fDisconnect)
genesis 979 printf("socket closed\n");
genesis 980 pnode->CloseSocketDisconnect();
genesis 981 }
genesis 982 else if (nBytes < 0)
genesis 983 {
genesis 984
genesis 985 int nErr = WSAGetLastError();
genesis 986 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
genesis 987 {
genesis 988 if (!pnode->fDisconnect)
genesis 989 printf("socket recv error %d\n", nErr);
genesis 990 pnode->CloseSocketDisconnect();
genesis 991 }
genesis 992 }
genesis 993 }
genesis 994 }
genesis 995 }
genesis 996
genesis 997
genesis 998
genesis 999
genesis 1000 if (pnode->hSocket == INVALID_SOCKET)
genesis 1001 continue;
genesis 1002 if (FD_ISSET(pnode->hSocket, &fdsetSend))
genesis 1003 {
genesis 1004 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
genesis 1005 {
genesis 1006 CDataStream& vSend = pnode->vSend;
genesis 1007 if (!vSend.empty())
genesis 1008 {
genesis 1009 int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
genesis 1010 if (nBytes > 0)
genesis 1011 {
genesis 1012 vSend.erase(vSend.begin(), vSend.begin() + nBytes);
genesis 1013 pnode->nLastSend = GetTime();
genesis 1014 }
genesis 1015 else if (nBytes < 0)
genesis 1016 {
genesis 1017
genesis 1018 int nErr = WSAGetLastError();
genesis 1019 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
genesis 1020 {
genesis 1021 printf("socket send error %d\n", nErr);
genesis 1022 pnode->CloseSocketDisconnect();
genesis 1023 }
genesis 1024 }
genesis 1025 if (vSend.size() > SendBufferSize()) {
genesis 1026 if (!pnode->fDisconnect)
genesis 1027 printf("socket send flood control disconnect (%d bytes)\n", vSend.size());
genesis 1028 pnode->CloseSocketDisconnect();
genesis 1029 }
genesis 1030 }
genesis 1031 }
genesis 1032 }
genesis 1033
genesis 1034
genesis 1035
genesis 1036
genesis 1037 if (pnode->vSend.empty())
genesis 1038 pnode->nLastSendEmpty = GetTime();
genesis 1039 if (GetTime() - pnode->nTimeConnected > 60)
genesis 1040 {
genesis 1041 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
genesis 1042 {
genesis 1043 printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
genesis 1044 pnode->fDisconnect = true;
genesis 1045 }
genesis 1046 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
genesis 1047 {
genesis 1048 printf("socket not sending\n");
genesis 1049 pnode->fDisconnect = true;
genesis 1050 }
genesis 1051 else if (GetTime() - pnode->nLastRecv > 90*60)
genesis 1052 {
genesis 1053 printf("socket inactivity timeout\n");
genesis 1054 pnode->fDisconnect = true;
genesis 1055 }
genesis 1056 }
genesis 1057 }
genesis 1058 CRITICAL_BLOCK(cs_vNodes)
genesis 1059 {
genesis 1060 BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis 1061 pnode->Release();
genesis 1062 }
genesis 1063
genesis 1064 Sleep(10);
genesis 1065 }
genesis 1066 }
genesis 1067
genesis 1068
genesis 1069 void ThreadOpenConnections(void* parg)
genesis 1070 {
genesis 1071 IMPLEMENT_RANDOMIZE_STACK(ThreadOpenConnections(parg));
genesis 1072 try
genesis 1073 {
genesis 1074 vnThreadsRunning[1]++;
genesis 1075 ThreadOpenConnections2(parg);
genesis 1076 vnThreadsRunning[1]--;
genesis 1077 }
genesis 1078 catch (std::exception& e) {
genesis 1079 vnThreadsRunning[1]--;
genesis 1080 PrintException(&e, "ThreadOpenConnections()");
genesis 1081 } catch (...) {
genesis 1082 vnThreadsRunning[1]--;
genesis 1083 PrintException(NULL, "ThreadOpenConnections()");
genesis 1084 }
genesis 1085 printf("ThreadOpenConnections exiting\n");
genesis 1086 }
genesis 1087
genesis 1088 void ThreadOpenConnections2(void* parg)
genesis 1089 {
genesis 1090 printf("ThreadOpenConnections started\n");
genesis 1091
genesis 1092
genesis 1093 if (mapArgs.count("-connect"))
genesis 1094 {
genesis 1095 for (int64 nLoop = 0;; nLoop++)
genesis 1096 {
genesis 1097 BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
genesis 1098 {
genesis 1099 CAddress addr(strAddr, fAllowDNS);
genesis 1100 if (addr.IsValid())
genesis 1101 OpenNetworkConnection(addr);
genesis 1102 for (int i = 0; i < 10 && i < nLoop; i++)
genesis 1103 {
genesis 1104 Sleep(500);
genesis 1105 if (fShutdown)
genesis 1106 return;
genesis 1107 }
genesis 1108 }
genesis 1109 }
genesis 1110 }
genesis 1111
genesis 1112
genesis 1113 if (mapArgs.count("-addnode"))
genesis 1114 {
genesis 1115 BOOST_FOREACH(string strAddr, mapMultiArgs["-addnode"])
genesis 1116 {
genesis 1117 CAddress addr(strAddr, fAllowDNS);
genesis 1118 if (addr.IsValid())
genesis 1119 {
genesis 1120 OpenNetworkConnection(addr);
genesis 1121 Sleep(500);
genesis 1122 if (fShutdown)
genesis 1123 return;
genesis 1124 }
genesis 1125 }
genesis 1126 }
genesis 1127
genesis 1128
genesis 1129 int64 nStart = GetTime();
genesis 1130 loop
genesis 1131 {
genesis 1132 vnThreadsRunning[1]--;
genesis 1133 Sleep(500);
genesis 1134 vnThreadsRunning[1]++;
genesis 1135 if (fShutdown)
genesis 1136 return;
genesis 1137
genesis 1138
genesis 1139 loop
genesis 1140 {
genesis 1141 int nOutbound = 0;
genesis 1142 CRITICAL_BLOCK(cs_vNodes)
genesis 1143 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 1144 if (!pnode->fInbound)
genesis 1145 nOutbound++;
genesis 1146 int nMaxOutboundConnections = MAX_OUTBOUND_CONNECTIONS;
genesis 1147 nMaxOutboundConnections = min(nMaxOutboundConnections, (int)GetArg("-maxconnections", 125));
genesis 1148 if (nOutbound < nMaxOutboundConnections)
genesis 1149 break;
genesis 1150 vnThreadsRunning[1]--;
genesis 1151 Sleep(2000);
genesis 1152 vnThreadsRunning[1]++;
genesis 1153 if (fShutdown)
genesis 1154 return;
genesis 1155 }
genesis 1156
genesis 1157
genesis 1158
genesis 1159
genesis 1160 CAddress addrConnect;
genesis 1161 int64 nBest = INT64_MIN;
genesis 1162
genesis 1163
genesis 1164
genesis 1165 set<unsigned int> setConnected;
genesis 1166 CRITICAL_BLOCK(cs_vNodes)
genesis 1167 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 1168 setConnected.insert(pnode->addr.ip & 0x0000ffff);
genesis 1169
genesis 1170 int64 nANow = GetAdjustedTime();
genesis 1171
genesis 1172 CRITICAL_BLOCK(cs_mapAddresses)
genesis 1173 {
genesis 1174 BOOST_FOREACH(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
genesis 1175 {
genesis 1176 const CAddress& addr = item.second;
genesis 1177 if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.ip & 0x0000ffff))
genesis 1178 continue;
genesis 1179 int64 nSinceLastSeen = nANow - addr.nTime;
genesis 1180 int64 nSinceLastTry = nANow - addr.nLastTry;
genesis 1181
genesis 1182
genesis 1183 int64 nRandomizer = (uint64)(nStart * 4951 + addr.nLastTry * 9567851 + addr.ip * 7789) % (2 * 60 * 60);
genesis 1184 if (addr.port != htons(GetDefaultPort()))
genesis 1185 nRandomizer += 2 * 60 * 60;
genesis 1186
genesis 1187
genesis 1188
genesis 1189
genesis 1190
genesis 1191
genesis 1192
genesis 1193
genesis 1194
genesis 1195
genesis 1196
genesis 1197 int64 nDelay = (int64)(3600.0 * sqrt(fabs((double)nSinceLastSeen) / 3600.0) + nRandomizer);
genesis 1198
genesis 1199
genesis 1200 if (nSinceLastSeen < 60 * 60)
genesis 1201 nDelay = 10 * 60;
genesis 1202
genesis 1203
genesis 1204 if (nSinceLastTry < nDelay)
genesis 1205 continue;
genesis 1206
genesis 1207
genesis 1208
genesis 1209 if (nGotIRCAddresses > 0 && vNodes.size() >= 2 && nSinceLastSeen > 24 * 60 * 60)
genesis 1210 continue;
genesis 1211
genesis 1212
genesis 1213 if (vNodes.size() >= 8 && nSinceLastSeen > 24 * 60 * 60)
genesis 1214 continue;
genesis 1215
genesis 1216
genesis 1217
genesis 1218 int64 nScore = min(nSinceLastTry, (int64)24 * 60 * 60) - nSinceLastSeen - nRandomizer;
genesis 1219 if (nScore > nBest)
genesis 1220 {
genesis 1221 nBest = nScore;
genesis 1222 addrConnect = addr;
genesis 1223 }
genesis 1224 }
genesis 1225 }
genesis 1226
genesis 1227 if (addrConnect.IsValid())
genesis 1228 OpenNetworkConnection(addrConnect);
genesis 1229 }
genesis 1230 }
genesis 1231
genesis 1232 bool OpenNetworkConnection(const CAddress& addrConnect)
genesis 1233 {
genesis 1234
genesis 1235
genesis 1236
genesis 1237 if (fShutdown)
genesis 1238 return false;
genesis 1239 if (addrConnect.ip == addrLocalHost.ip || !addrConnect.IsIPv4() ||
genesis 1240 FindNode(addrConnect.ip) || CNode::IsBanned(addrConnect.ip))
genesis 1241 return false;
genesis 1242
genesis 1243 vnThreadsRunning[1]--;
genesis 1244 CNode* pnode = ConnectNode(addrConnect);
genesis 1245 vnThreadsRunning[1]++;
genesis 1246 if (fShutdown)
genesis 1247 return false;
genesis 1248 if (!pnode)
genesis 1249 return false;
genesis 1250 pnode->fNetworkNode = true;
genesis 1251
genesis 1252 return true;
genesis 1253 }
genesis 1254
genesis 1255
genesis 1256
genesis 1257
genesis 1258
genesis 1259
genesis 1260
genesis 1261
genesis 1262 void ThreadMessageHandler(void* parg)
genesis 1263 {
genesis 1264 IMPLEMENT_RANDOMIZE_STACK(ThreadMessageHandler(parg));
genesis 1265 try
genesis 1266 {
genesis 1267 vnThreadsRunning[2]++;
genesis 1268 ThreadMessageHandler2(parg);
genesis 1269 vnThreadsRunning[2]--;
genesis 1270 }
genesis 1271 catch (std::exception& e) {
genesis 1272 vnThreadsRunning[2]--;
genesis 1273 PrintException(&e, "ThreadMessageHandler()");
genesis 1274 } catch (...) {
genesis 1275 vnThreadsRunning[2]--;
genesis 1276 PrintException(NULL, "ThreadMessageHandler()");
genesis 1277 }
genesis 1278 printf("ThreadMessageHandler exiting\n");
genesis 1279 }
genesis 1280
genesis 1281 void ThreadMessageHandler2(void* parg)
genesis 1282 {
genesis 1283 printf("ThreadMessageHandler started\n");
genesis 1284 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
genesis 1285 while (!fShutdown)
genesis 1286 {
genesis 1287 vector<CNode*> vNodesCopy;
genesis 1288 CRITICAL_BLOCK(cs_vNodes)
genesis 1289 {
genesis 1290 vNodesCopy = vNodes;
genesis 1291 BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis 1292 pnode->AddRef();
genesis 1293 }
genesis 1294
genesis 1295
genesis 1296 CNode* pnodeTrickle = NULL;
genesis 1297 if (!vNodesCopy.empty())
genesis 1298 pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
genesis 1299 BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis 1300 {
genesis 1301
genesis 1302 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
genesis 1303 ProcessMessages(pnode);
genesis 1304 if (fShutdown)
genesis 1305 return;
genesis 1306
genesis 1307
genesis 1308 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
genesis 1309 SendMessages(pnode, pnode == pnodeTrickle);
genesis 1310 if (fShutdown)
genesis 1311 return;
genesis 1312 }
genesis 1313
genesis 1314 CRITICAL_BLOCK(cs_vNodes)
genesis 1315 {
genesis 1316 BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis 1317 pnode->Release();
genesis 1318 }
genesis 1319
genesis 1320
genesis 1321
genesis 1322
genesis 1323 vnThreadsRunning[2]--;
genesis 1324 Sleep(100);
genesis 1325 if (fRequestShutdown)
genesis 1326 Shutdown(NULL);
genesis 1327 vnThreadsRunning[2]++;
genesis 1328 if (fShutdown)
genesis 1329 return;
genesis 1330 }
genesis 1331 }
genesis 1332
genesis 1333
genesis 1334
genesis 1335
genesis 1336
genesis 1337
genesis 1338 bool BindListenPort(string& strError)
genesis 1339 {
genesis 1340 strError = "";
genesis 1341 int nOne = 1;
genesis 1342 addrLocalHost.port = htons(GetListenPort());
genesis 1343
genesis 1344
genesis 1345 hListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
genesis 1346 if (hListenSocket == INVALID_SOCKET)
genesis 1347 {
genesis 1348 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
genesis 1349 printf("%s\n", strError.c_str());
genesis 1350 return false;
genesis 1351 }
genesis 1352
genesis 1353 #ifdef SO_NOSIGPIPE
genesis 1354
genesis 1355 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
genesis 1356 #endif
genesis 1357
genesis 1358
genesis 1359
genesis 1360 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
genesis 1361
genesis 1362 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
genesis 1363 {
genesis 1364 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
genesis 1365 printf("%s\n", strError.c_str());
genesis 1366 return false;
genesis 1367 }
genesis 1368
genesis 1369
genesis 1370
genesis 1371 struct sockaddr_in sockaddr;
genesis 1372 memset(&sockaddr, 0, sizeof(sockaddr));
genesis 1373 sockaddr.sin_family = AF_INET;
genesis 1374 sockaddr.sin_addr.s_addr = INADDR_ANY;
genesis 1375 sockaddr.sin_port = htons(GetListenPort());
genesis 1376 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
genesis 1377 {
genesis 1378 int nErr = WSAGetLastError();
genesis 1379 if (nErr == WSAEADDRINUSE)
genesis 1380 strError = strprintf(_("Unable to bind to port %d on this computer. Bitcoin is probably already running."), ntohs(sockaddr.sin_port));
genesis 1381 else
genesis 1382 strError = strprintf("Error: Unable to bind to port %d on this computer (bind returned error %d)", ntohs(sockaddr.sin_port), nErr);
genesis 1383 printf("%s\n", strError.c_str());
genesis 1384 return false;
genesis 1385 }
genesis 1386 printf("Bound to port %d\n", ntohs(sockaddr.sin_port));
genesis 1387
genesis 1388
genesis 1389 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
genesis 1390 {
genesis 1391 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
genesis 1392 printf("%s\n", strError.c_str());
genesis 1393 return false;
genesis 1394 }
genesis 1395
genesis 1396 return true;
genesis 1397 }
genesis 1398
genesis 1399 void StartNode(void* parg)
genesis 1400 {
genesis 1401 if (pnodeLocalHost == NULL)
genesis 1402 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress("127.0.0.1", 0, false, nLocalServices));
genesis 1403
genesis 1404
genesis 1405 struct ifaddrs* myaddrs;
genesis 1406 if (getifaddrs(&myaddrs) == 0)
genesis 1407 {
genesis 1408 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
genesis 1409 {
genesis 1410 if (ifa->ifa_addr == NULL) continue;
genesis 1411 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
genesis 1412 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
genesis 1413 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
genesis 1414 char pszIP[100];
genesis 1415 if (ifa->ifa_addr->sa_family == AF_INET)
genesis 1416 {
genesis 1417 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
genesis 1418 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s4->sin_addr), pszIP, sizeof(pszIP)) != NULL)
genesis 1419 printf("ipv4 %s: %s\n", ifa->ifa_name, pszIP);
genesis 1420
genesis 1421
genesis 1422 CAddress addr(*(unsigned int*)&s4->sin_addr, GetListenPort(), nLocalServices);
genesis 1423 if (addr.IsValid() && addr.GetByte(3) != 127)
genesis 1424 {
genesis 1425 addrLocalHost = addr;
genesis 1426 break;
genesis 1427 }
genesis 1428 }
genesis 1429 else if (ifa->ifa_addr->sa_family == AF_INET6)
genesis 1430 {
genesis 1431 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
genesis 1432 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s6->sin6_addr), pszIP, sizeof(pszIP)) != NULL)
genesis 1433 printf("ipv6 %s: %s\n", ifa->ifa_name, pszIP);
genesis 1434 }
genesis 1435 }
genesis 1436 freeifaddrs(myaddrs);
genesis 1437 }
bitcoin-asciilife... 1438
genesis 1439 printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
genesis 1440
genesis 1441 if (fUseProxy || mapArgs.count("-connect") || fNoListen)
genesis 1442 {
genesis 1443
genesis 1444 addrLocalHost.ip = CAddress("0.0.0.0").ip;
genesis 1445 printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
genesis 1446 }
genesis 1447 else
genesis 1448 {
genesis 1449 CreateThread(ThreadGetMyExternalIP, NULL);
genesis 1450 }
genesis 1451
genesis 1452
genesis 1453
genesis 1454
genesis 1455
genesis 1456
genesis 1457 if (!CreateThread(ThreadIRCSeed, NULL))
genesis 1458 printf("Error: CreateThread(ThreadIRCSeed) failed\n");
genesis 1459
genesis 1460
genesis 1461 if (!CreateThread(ThreadSocketHandler, NULL))
genesis 1462 printf("Error: CreateThread(ThreadSocketHandler) failed\n");
genesis 1463
genesis 1464
genesis 1465 if (!CreateThread(ThreadOpenConnections, NULL))
genesis 1466 printf("Error: CreateThread(ThreadOpenConnections) failed\n");
genesis 1467
genesis 1468
genesis 1469 if (!CreateThread(ThreadMessageHandler, NULL))
genesis 1470 printf("Error: CreateThread(ThreadMessageHandler) failed\n");
genesis 1471
genesis 1472
genesis 1473 GenerateBitcoins(fGenerateBitcoins, pwalletMain);
genesis 1474 }
genesis 1475
genesis 1476 bool StopNode()
genesis 1477 {
genesis 1478 printf("StopNode()\n");
genesis 1479 fShutdown = true;
genesis 1480 nTransactionsUpdated++;
genesis 1481 int64 nStart = GetTime();
genesis 1482 while (vnThreadsRunning[0] > 0 || vnThreadsRunning[1] > 0 || vnThreadsRunning[2] > 0 || vnThreadsRunning[3] > 0 || vnThreadsRunning[4] > 0
genesis 1483 )
genesis 1484 {
genesis 1485 if (GetTime() - nStart > 20)
genesis 1486 break;
genesis 1487 Sleep(20);
genesis 1488 }
genesis 1489 if (vnThreadsRunning[0] > 0) printf("ThreadSocketHandler still running\n");
genesis 1490 if (vnThreadsRunning[1] > 0) printf("ThreadOpenConnections still running\n");
genesis 1491 if (vnThreadsRunning[2] > 0) printf("ThreadMessageHandler still running\n");
genesis 1492 if (vnThreadsRunning[3] > 0) printf("ThreadBitcoinMiner still running\n");
genesis 1493 if (vnThreadsRunning[4] > 0) printf("ThreadRPCServer still running\n");
genesis 1494 while (vnThreadsRunning[2] > 0 || vnThreadsRunning[4] > 0)
genesis 1495 Sleep(20);
genesis 1496 Sleep(50);
genesis 1497
genesis 1498 return true;
genesis 1499 }
genesis 1500
genesis 1501 class CNetCleanup
genesis 1502 {
genesis 1503 public:
genesis 1504 CNetCleanup()
genesis 1505 {
genesis 1506 }
genesis 1507 ~CNetCleanup()
genesis 1508 {
genesis 1509
genesis 1510 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 1511 if (pnode->hSocket != INVALID_SOCKET)
genesis 1512 closesocket(pnode->hSocket);
genesis 1513 if (hListenSocket != INVALID_SOCKET)
genesis 1514 if (closesocket(hListenSocket) == SOCKET_ERROR)
genesis 1515 printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
genesis 1516
genesis 1517 }
genesis 1518 }
genesis 1519 instance_of_cnetcleanup;