genesis 1
genesis 2
genesis 3
genesis 4
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
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
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
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
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
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
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
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
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
asciilifeform_wir... 248
asciilifeform_wir... 249
asciilifeform_wir... 250
asciilifeform_wir... 251
asciilifeform_wir... 252
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));
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
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
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
genesis 297 addrFound.nTime = addr.nTime;
genesis 298 fUpdated = true;
genesis 299 }
genesis 300 }
genesis 301 }
genesis 302
genesis 303
genesis 304
genesis 305
genesis 306
genesis 307
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
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
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
genesis 350
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
genesis 378
genesis 379
genesis 380
genesis 381
genesis 382
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
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
genesis 426 if (!vfSubscribe[nChannel])
genesis 427 return;
genesis 428 vfSubscribe[nChannel] = false;
genesis 429
genesis 430 if (!AnySubscribed(nChannel))
genesis 431 {
genesis 432
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
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
genesis 494 SOCKET hSocket;
genesis 495 if (ConnectSocket(addrConnect, hSocket))
genesis 496 {
genesis 497
genesis 498 printf("connected %s\n", addrConnect.ToString().c_str());
genesis 499
genesis 500
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
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
genesis 546
genesis 547
genesis 548
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);
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;
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
genesis 647
genesis 648 CRITICAL_BLOCK(cs_vNodes)
genesis 649 {
genesis 650
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
genesis 658 vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
genesis 659
genesis 660
genesis 661 pnode->CloseSocketDisconnect();
genesis 662 pnode->Cleanup();
genesis 663
genesis 664
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
genesis 673 list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
genesis 674 BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy)
genesis 675 {
genesis 676
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
genesis 702
genesis 703 struct timeval timeout;
genesis 704 timeout.tv_sec = 0;
genesis 705 timeout.tv_usec = 50000;
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
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
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
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
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
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
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
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
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
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 {
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
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
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
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
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
genesis 1023
genesis 1024 CAddress addrConnect;
genesis 1025 int64 nBest = INT64_MIN;
genesis 1026
genesis 1027
genesis 1028
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
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
genesis 1052
genesis 1053
genesis 1054
genesis 1055
genesis 1056
genesis 1057
genesis 1058
genesis 1059
genesis 1060
genesis 1061 int64 nDelay = (int64)(3600.0 * sqrt(fabs((double)nSinceLastSeen) / 3600.0) + nRandomizer);
genesis 1062
genesis 1063
genesis 1064 if (nSinceLastSeen < 60 * 60)
genesis 1065 nDelay = 10 * 60;
genesis 1066
genesis 1067
genesis 1068 if (nSinceLastTry < nDelay)
genesis 1069 continue;
genesis 1070
genesis 1071
genesis 1072 if (vNodes.size() >= 8 && nSinceLastSeen > 24 * 60 * 60)
genesis 1073 continue;
genesis 1074
genesis 1075
genesis 1076
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
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
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
genesis 1197 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
genesis 1198 ProcessMessages(pnode);
genesis 1199 if (fShutdown)
genesis 1200 return;
genesis 1201
genesis 1202
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
genesis 1216
genesis 1217
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
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
genesis 1250 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
genesis 1251 #endif
genesis 1252
genesis 1253
genesis 1254
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
genesis 1265
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;
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
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
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
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
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
genesis 1354
genesis 1355
genesis 1356
genesis 1357 if (!CreateThread(ThreadSocketHandler, NULL))
genesis 1358 printf("Error: CreateThread(ThreadSocketHandler) failed\n");
genesis 1359
genesis 1360
genesis 1361 if (!CreateThread(ThreadOpenConnections, NULL))
genesis 1362 printf("Error: CreateThread(ThreadOpenConnections) failed\n");
genesis 1363
asciilifeform_wir... 1364
asciilifeform_wir... 1365 if (fWires && !CreateThread(ThreadOpenWires, NULL))
asciilifeform_wir... 1366 printf("Error: CreateThread(ThreadOpenWires) failed\n");
asciilifeform_wir... 1367
genesis 1368
genesis 1369 if (!CreateThread(ThreadMessageHandler, NULL))
genesis 1370 printf("Error: CreateThread(ThreadMessageHandler) failed\n");
genesis 1371
genesis 1372
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
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;