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