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