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