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_wires 21 void ThreadOpenWires2(void* parg);
asciilifeform_wires 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_wires 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_wires 247
asciilifeform_wires 248
asciilifeform_wires 249
asciilifeform_wires 250
asciilifeform_wires 251
asciilifeform_wires 252
asciilifeform_wires 253 bool AddWire(CAddress addr)
asciilifeform_wires 254 {
asciilifeform_wires 255 printf("AddWire(%s)\n", addr.ToString().c_str());
asciilifeform_wires 256 mapWires.insert(make_pair(addr.GetKey(), addr));
asciilifeform_wires 257 return true;
asciilifeform_wires 258 }
asciilifeform_wires 259
asciilifeform_wires 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_wires 470 CNode* ConnectNode(CAddress addrConnect, int64 nTimeout, bool fWireNode)
genesis 471 {
asciilifeform_wires 472 if (!fWireNode && (addrConnect.ip == addrLocalHost.ip))
genesis 473 return NULL;
asciilifeform_wires 474
asciilifeform_wires 475 if (fWireNode)
asciilifeform_wires 476 nTimeout = 0;
asciilifeform_wires 477
genesis 478
genesis 479 printf("trying connection %s lastseen=%.1fhrs lasttry=%.1fhrs\n",
genesis 480 addrConnect.ToString().c_str(),
genesis 481 (double)(addrConnect.nTime - GetAdjustedTime())/3600.0,
genesis 482 (double)(addrConnect.nLastTry - GetAdjustedTime())/3600.0);
genesis 483
asciilifeform_wires 484 if (!fWireNode)
asciilifeform_wires 485 {
asciilifeform_wires 486 CRITICAL_BLOCK(cs_mapAddresses)
asciilifeform_wires 487 mapAddresses[addrConnect.GetKey()].nLastTry = GetAdjustedTime();
asciilifeform_wires 488 }
asciilifeform_wires 489
genesis 490
genesis 491 SOCKET hSocket;
genesis 492 if (ConnectSocket(addrConnect, hSocket))
genesis 493 {
genesis 494
genesis 495 printf("connected %s\n", addrConnect.ToString().c_str());
genesis 496
genesis 497
genesis 498 if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
genesis 499 printf("ConnectSocket() : fcntl nonblocking setting failed, error %d\n", errno);
genesis 500
genesis 501
genesis 502 CNode* pnode = new CNode(hSocket, addrConnect, false);
asciilifeform_wires 503 pnode->fWireNode = fWireNode;
asciilifeform_wires 504
genesis 505 if (nTimeout != 0)
genesis 506 pnode->AddRef(nTimeout);
genesis 507 else
genesis 508 pnode->AddRef();
genesis 509 CRITICAL_BLOCK(cs_vNodes)
genesis 510 vNodes.push_back(pnode);
genesis 511
genesis 512 pnode->nTimeConnected = GetTime();
genesis 513 return pnode;
genesis 514 }
genesis 515 else
genesis 516 {
genesis 517 return NULL;
genesis 518 }
genesis 519 }
genesis 520
genesis 521 void CNode::CloseSocketDisconnect()
genesis 522 {
asciilifeform_wires 523 if (fWireNode) return;
genesis 524 fDisconnect = true;
genesis 525 if (hSocket != INVALID_SOCKET)
genesis 526 {
genesis 527 if (fDebug)
genesis 528 printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
genesis 529 printf("disconnecting node %s\n", addr.ToString().c_str());
genesis 530 closesocket(hSocket);
genesis 531 hSocket = INVALID_SOCKET;
genesis 532 }
genesis 533 }
genesis 534
genesis 535 void CNode::Cleanup()
genesis 536 {
genesis 537
genesis 538
genesis 539
genesis 540
genesis 541 for (unsigned int nChannel = 0; nChannel < vfSubscribe.size(); nChannel++)
genesis 542 if (vfSubscribe[nChannel])
genesis 543 CancelSubscribe(nChannel);
genesis 544 }
genesis 545
genesis 546
genesis 547 std::map<unsigned int, int64> CNode::setBanned;
genesis 548 CCriticalSection CNode::cs_setBanned;
genesis 549
genesis 550 void CNode::ClearBanned()
genesis 551 {
genesis 552 setBanned.clear();
genesis 553 }
genesis 554
genesis 555 bool CNode::IsBanned(unsigned int ip)
genesis 556 {
genesis 557 bool fResult = false;
genesis 558 CRITICAL_BLOCK(cs_setBanned)
genesis 559 {
genesis 560 std::map<unsigned int, int64>::iterator i = setBanned.find(ip);
genesis 561 if (i != setBanned.end())
genesis 562 {
genesis 563 int64 t = (*i).second;
genesis 564 if (GetTime() < t)
genesis 565 fResult = true;
genesis 566 }
genesis 567 }
genesis 568 return fResult;
genesis 569 }
genesis 570
genesis 571 bool CNode::Misbehaving(int howmuch)
genesis 572 {
asciilifeform_wires 573 if (fWireNode)
asciilifeform_wires 574 {
asciilifeform_wires 575 printf("Warning: wire node %s misbehaving\n", addr.ToString().c_str());
asciilifeform_wires 576 return false;
asciilifeform_wires 577 }
asciilifeform_wires 578
genesis 579 if (addr.IsLocal())
genesis 580 {
genesis 581 printf("Warning: local node %s misbehaving\n", addr.ToString().c_str());
genesis 582 return false;
genesis 583 }
genesis 584
genesis 585 nMisbehavior += howmuch;
genesis 586 if (nMisbehavior >= GetArg("-banscore", 100))
genesis 587 {
genesis 588 int64 banTime = GetTime()+GetArg("-bantime", 60*60*24);
genesis 589 CRITICAL_BLOCK(cs_setBanned)
genesis 590 if (setBanned[addr.ip] < banTime)
genesis 591 setBanned[addr.ip] = banTime;
genesis 592 CloseSocketDisconnect();
genesis 593 printf("Disconnected %s for misbehavior (score=%d)\n", addr.ToString().c_str(), nMisbehavior);
genesis 594 return true;
genesis 595 }
genesis 596 return false;
genesis 597 }
genesis 598
genesis 599
genesis 600
genesis 601
genesis 602
genesis 603
genesis 604
genesis 605
genesis 606
genesis 607
genesis 608
genesis 609
genesis 610 void ThreadSocketHandler(void* parg)
genesis 611 {
genesis 612 IMPLEMENT_RANDOMIZE_STACK(ThreadSocketHandler(parg));
genesis 613 try
genesis 614 {
genesis 615 vnThreadsRunning[0]++;
genesis 616 ThreadSocketHandler2(parg);
genesis 617 vnThreadsRunning[0]--;
genesis 618 }
genesis 619 catch (std::exception& e) {
genesis 620 vnThreadsRunning[0]--;
genesis 621 PrintException(&e, "ThreadSocketHandler()");
genesis 622 } catch (...) {
genesis 623 vnThreadsRunning[0]--;
genesis 624 throw;
genesis 625 }
genesis 626 printf("ThreadSocketHandler exiting\n");
genesis 627 }
genesis 628
genesis 629 void ThreadSocketHandler2(void* parg)
genesis 630 {
genesis 631 printf("ThreadSocketHandler started\n");
genesis 632 list<CNode*> vNodesDisconnected;
genesis 633 int nPrevNodeCount = 0;
genesis 634
genesis 635 loop
genesis 636 {
genesis 637
genesis 638
genesis 639
genesis 640 CRITICAL_BLOCK(cs_vNodes)
genesis 641 {
genesis 642
genesis 643 vector<CNode*> vNodesCopy = vNodes;
genesis 644 BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis 645 {
asciilifeform_wires 646 if (!pnode->fWireNode && (pnode->fDisconnect ||
asciilifeform_wires 647 (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty())))
genesis 648 {
genesis 649
genesis 650 vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
genesis 651
genesis 652
genesis 653 pnode->CloseSocketDisconnect();
genesis 654 pnode->Cleanup();
genesis 655
genesis 656
genesis 657 pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
genesis 658 if (pnode->fNetworkNode || pnode->fInbound)
genesis 659 pnode->Release();
genesis 660 vNodesDisconnected.push_back(pnode);
genesis 661 }
genesis 662 }
genesis 663
genesis 664
genesis 665 list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
genesis 666 BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy)
genesis 667 {
genesis 668
genesis 669 if (pnode->GetRefCount() <= 0)
genesis 670 {
genesis 671 bool fDelete = false;
genesis 672 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
genesis 673 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
genesis 674 TRY_CRITICAL_BLOCK(pnode->cs_mapRequests)
genesis 675 TRY_CRITICAL_BLOCK(pnode->cs_inventory)
genesis 676 fDelete = true;
genesis 677 if (fDelete)
genesis 678 {
genesis 679 vNodesDisconnected.remove(pnode);
genesis 680 delete pnode;
genesis 681 }
genesis 682 }
genesis 683 }
genesis 684 }
genesis 685 if (vNodes.size() != nPrevNodeCount)
genesis 686 {
genesis 687 nPrevNodeCount = vNodes.size();
genesis 688 MainFrameRepaint();
genesis 689 }
genesis 690
genesis 691
genesis 692
genesis 693
genesis 694
genesis 695 struct timeval timeout;
genesis 696 timeout.tv_sec = 0;
genesis 697 timeout.tv_usec = 50000;
genesis 698
genesis 699 fd_set fdsetRecv;
genesis 700 fd_set fdsetSend;
genesis 701 fd_set fdsetError;
genesis 702 FD_ZERO(&fdsetRecv);
genesis 703 FD_ZERO(&fdsetSend);
genesis 704 FD_ZERO(&fdsetError);
genesis 705 SOCKET hSocketMax = 0;
genesis 706
genesis 707 if(hListenSocket != INVALID_SOCKET)
genesis 708 FD_SET(hListenSocket, &fdsetRecv);
genesis 709 hSocketMax = max(hSocketMax, hListenSocket);
genesis 710 CRITICAL_BLOCK(cs_vNodes)
genesis 711 {
genesis 712 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 713 {
genesis 714 if (pnode->hSocket == INVALID_SOCKET)
genesis 715 continue;
genesis 716 FD_SET(pnode->hSocket, &fdsetRecv);
genesis 717 FD_SET(pnode->hSocket, &fdsetError);
genesis 718 hSocketMax = max(hSocketMax, pnode->hSocket);
genesis 719 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
genesis 720 if (!pnode->vSend.empty())
genesis 721 FD_SET(pnode->hSocket, &fdsetSend);
genesis 722 }
genesis 723 }
genesis 724
genesis 725 vnThreadsRunning[0]--;
genesis 726 int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
genesis 727 vnThreadsRunning[0]++;
genesis 728 if (fShutdown)
genesis 729 return;
genesis 730 if (nSelect == SOCKET_ERROR)
genesis 731 {
genesis 732 int nErr = WSAGetLastError();
genesis 733 if (hSocketMax > -1)
genesis 734 {
genesis 735 printf("socket select error %d\n", nErr);
genesis 736 for (int i = 0; i <= hSocketMax; i++)
genesis 737 FD_SET(i, &fdsetRecv);
genesis 738 }
genesis 739 FD_ZERO(&fdsetSend);
genesis 740 FD_ZERO(&fdsetError);
genesis 741 Sleep(timeout.tv_usec/1000);
genesis 742 }
genesis 743
genesis 744
genesis 745
genesis 746
genesis 747
genesis 748 if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
genesis 749 {
genesis 750 struct sockaddr_in sockaddr;
genesis 751 socklen_t len = sizeof(sockaddr);
genesis 752 SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
genesis 753 CAddress addr;
genesis 754 int nInbound = 0;
genesis 755
genesis 756 if (hSocket != INVALID_SOCKET)
genesis 757 addr = CAddress(sockaddr);
genesis 758
genesis 759 CRITICAL_BLOCK(cs_vNodes)
genesis 760 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 761 if (pnode->fInbound)
genesis 762 nInbound++;
genesis 763
genesis 764 if (hSocket == INVALID_SOCKET)
genesis 765 {
genesis 766 if (WSAGetLastError() != WSAEWOULDBLOCK)
genesis 767 printf("socket error accept failed: %d\n", WSAGetLastError());
genesis 768 }
genesis 769 else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
genesis 770 {
genesis 771 closesocket(hSocket);
genesis 772 }
genesis 773 else if (CNode::IsBanned(addr.ip))
genesis 774 {
genesis 775 printf("connection from %s dropped (banned)\n", addr.ToString().c_str());
genesis 776 closesocket(hSocket);
genesis 777 }
genesis 778 else
genesis 779 {
genesis 780 printf("accepted connection %s\n", addr.ToString().c_str());
genesis 781 CNode* pnode = new CNode(hSocket, addr, true);
genesis 782 pnode->AddRef();
genesis 783 CRITICAL_BLOCK(cs_vNodes)
genesis 784 vNodes.push_back(pnode);
genesis 785 }
genesis 786 }
genesis 787
genesis 788
genesis 789
genesis 790
genesis 791
genesis 792 vector<CNode*> vNodesCopy;
genesis 793 CRITICAL_BLOCK(cs_vNodes)
genesis 794 {
genesis 795 vNodesCopy = vNodes;
genesis 796 BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis 797 pnode->AddRef();
genesis 798 }
genesis 799 BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis 800 {
genesis 801 if (fShutdown)
genesis 802 return;
genesis 803
genesis 804
genesis 805
genesis 806
genesis 807 if (pnode->hSocket == INVALID_SOCKET)
genesis 808 continue;
genesis 809 if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
genesis 810 {
genesis 811 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
genesis 812 {
genesis 813 CDataStream& vRecv = pnode->vRecv;
genesis 814 unsigned int nPos = vRecv.size();
genesis 815
genesis 816 if (nPos > ReceiveBufferSize()) {
genesis 817 if (!pnode->fDisconnect)
genesis 818 printf("socket recv flood control disconnect (%d bytes)\n", vRecv.size());
genesis 819 pnode->CloseSocketDisconnect();
genesis 820 }
genesis 821 else {
genesis 822
genesis 823 char pchBuf[0x10000];
genesis 824 int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
genesis 825 if (nBytes > 0)
genesis 826 {
genesis 827 vRecv.resize(nPos + nBytes);
genesis 828 memcpy(&vRecv[nPos], pchBuf, nBytes);
genesis 829 pnode->nLastRecv = GetTime();
genesis 830 }
genesis 831 else if (nBytes == 0)
genesis 832 {
genesis 833
genesis 834 if (!pnode->fDisconnect)
genesis 835 printf("socket closed\n");
genesis 836 pnode->CloseSocketDisconnect();
genesis 837 }
genesis 838 else if (nBytes < 0)
genesis 839 {
genesis 840
genesis 841 int nErr = WSAGetLastError();
genesis 842 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
genesis 843 {
genesis 844 if (!pnode->fDisconnect)
genesis 845 printf("socket recv error %d\n", nErr);
genesis 846 pnode->CloseSocketDisconnect();
genesis 847 }
genesis 848 }
genesis 849 }
genesis 850 }
genesis 851 }
genesis 852
genesis 853
genesis 854
genesis 855
genesis 856 if (pnode->hSocket == INVALID_SOCKET)
genesis 857 continue;
genesis 858 if (FD_ISSET(pnode->hSocket, &fdsetSend))
genesis 859 {
genesis 860 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
genesis 861 {
genesis 862 CDataStream& vSend = pnode->vSend;
genesis 863 if (!vSend.empty())
genesis 864 {
genesis 865 int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
genesis 866 if (nBytes > 0)
genesis 867 {
genesis 868 vSend.erase(vSend.begin(), vSend.begin() + nBytes);
genesis 869 pnode->nLastSend = GetTime();
genesis 870 }
genesis 871 else if (nBytes < 0)
genesis 872 {
genesis 873
genesis 874 int nErr = WSAGetLastError();
genesis 875 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
genesis 876 {
genesis 877 printf("socket send error %d\n", nErr);
genesis 878 pnode->CloseSocketDisconnect();
genesis 879 }
genesis 880 }
genesis 881 if (vSend.size() > SendBufferSize()) {
genesis 882 if (!pnode->fDisconnect)
genesis 883 printf("socket send flood control disconnect (%d bytes)\n", vSend.size());
genesis 884 pnode->CloseSocketDisconnect();
genesis 885 }
genesis 886 }
genesis 887 }
genesis 888 }
genesis 889
genesis 890
genesis 891
genesis 892
genesis 893 if (pnode->vSend.empty())
genesis 894 pnode->nLastSendEmpty = GetTime();
genesis 895 if (GetTime() - pnode->nTimeConnected > 60)
genesis 896 {
genesis 897 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
genesis 898 {
genesis 899 printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
genesis 900 pnode->fDisconnect = true;
genesis 901 }
genesis 902 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
genesis 903 {
genesis 904 printf("socket not sending\n");
genesis 905 pnode->fDisconnect = true;
genesis 906 }
genesis 907 else if (GetTime() - pnode->nLastRecv > 90*60)
genesis 908 {
genesis 909 printf("socket inactivity timeout\n");
genesis 910 pnode->fDisconnect = true;
genesis 911 }
genesis 912 }
genesis 913 }
genesis 914 CRITICAL_BLOCK(cs_vNodes)
genesis 915 {
genesis 916 BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis 917 pnode->Release();
genesis 918 }
genesis 919
genesis 920 Sleep(10);
genesis 921 }
genesis 922 }
genesis 923
genesis 924
genesis 925 void ThreadOpenConnections(void* parg)
genesis 926 {
genesis 927 IMPLEMENT_RANDOMIZE_STACK(ThreadOpenConnections(parg));
genesis 928 try
genesis 929 {
genesis 930 vnThreadsRunning[1]++;
genesis 931 ThreadOpenConnections2(parg);
genesis 932 vnThreadsRunning[1]--;
genesis 933 }
genesis 934 catch (std::exception& e) {
genesis 935 vnThreadsRunning[1]--;
genesis 936 PrintException(&e, "ThreadOpenConnections()");
genesis 937 } catch (...) {
genesis 938 vnThreadsRunning[1]--;
genesis 939 PrintException(NULL, "ThreadOpenConnections()");
genesis 940 }
genesis 941 printf("ThreadOpenConnections exiting\n");
genesis 942 }
genesis 943
genesis 944 void ThreadOpenConnections2(void* parg)
genesis 945 {
genesis 946 printf("ThreadOpenConnections started\n");
genesis 947
genesis 948
genesis 949 if (mapArgs.count("-connect"))
genesis 950 {
genesis 951 for (int64 nLoop = 0;; nLoop++)
genesis 952 {
genesis 953 BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
genesis 954 {
asciilifeform_dns... 955 CAddress addr(strAddr);
genesis 956 if (addr.IsValid())
genesis 957 OpenNetworkConnection(addr);
genesis 958 for (int i = 0; i < 10 && i < nLoop; i++)
genesis 959 {
genesis 960 Sleep(500);
genesis 961 if (fShutdown)
genesis 962 return;
genesis 963 }
genesis 964 }
genesis 965 }
genesis 966 }
genesis 967
genesis 968
genesis 969 if (mapArgs.count("-addnode"))
genesis 970 {
genesis 971 BOOST_FOREACH(string strAddr, mapMultiArgs["-addnode"])
genesis 972 {
asciilifeform_dns... 973 CAddress addr(strAddr);
genesis 974 if (addr.IsValid())
genesis 975 {
genesis 976 OpenNetworkConnection(addr);
genesis 977 Sleep(500);
genesis 978 if (fShutdown)
genesis 979 return;
genesis 980 }
genesis 981 }
genesis 982 }
genesis 983
genesis 984
genesis 985 int64 nStart = GetTime();
genesis 986 loop
genesis 987 {
genesis 988 vnThreadsRunning[1]--;
genesis 989 Sleep(500);
genesis 990 vnThreadsRunning[1]++;
genesis 991 if (fShutdown)
genesis 992 return;
genesis 993
genesis 994
genesis 995 loop
genesis 996 {
genesis 997 int nOutbound = 0;
genesis 998 CRITICAL_BLOCK(cs_vNodes)
genesis 999 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 1000 if (!pnode->fInbound)
genesis 1001 nOutbound++;
genesis 1002 int nMaxOutboundConnections = MAX_OUTBOUND_CONNECTIONS;
genesis 1003 nMaxOutboundConnections = min(nMaxOutboundConnections, (int)GetArg("-maxconnections", 125));
genesis 1004 if (nOutbound < nMaxOutboundConnections)
genesis 1005 break;
genesis 1006 vnThreadsRunning[1]--;
genesis 1007 Sleep(2000);
genesis 1008 vnThreadsRunning[1]++;
genesis 1009 if (fShutdown)
genesis 1010 return;
genesis 1011 }
genesis 1012
genesis 1013
genesis 1014
genesis 1015
genesis 1016 CAddress addrConnect;
genesis 1017 int64 nBest = INT64_MIN;
genesis 1018
genesis 1019
genesis 1020
genesis 1021 set<unsigned int> setConnected;
genesis 1022 CRITICAL_BLOCK(cs_vNodes)
genesis 1023 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 1024 setConnected.insert(pnode->addr.ip & 0x0000ffff);
genesis 1025
genesis 1026 int64 nANow = GetAdjustedTime();
genesis 1027
genesis 1028 CRITICAL_BLOCK(cs_mapAddresses)
genesis 1029 {
genesis 1030 BOOST_FOREACH(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
genesis 1031 {
genesis 1032 const CAddress& addr = item.second;
genesis 1033 if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.ip & 0x0000ffff))
genesis 1034 continue;
genesis 1035 int64 nSinceLastSeen = nANow - addr.nTime;
genesis 1036 int64 nSinceLastTry = nANow - addr.nLastTry;
genesis 1037
genesis 1038
genesis 1039 int64 nRandomizer = (uint64)(nStart * 4951 + addr.nLastTry * 9567851 + addr.ip * 7789) % (2 * 60 * 60);
genesis 1040 if (addr.port != htons(GetDefaultPort()))
genesis 1041 nRandomizer += 2 * 60 * 60;
genesis 1042
genesis 1043
genesis 1044
genesis 1045
genesis 1046
genesis 1047
genesis 1048
genesis 1049
genesis 1050
genesis 1051
genesis 1052
genesis 1053 int64 nDelay = (int64)(3600.0 * sqrt(fabs((double)nSinceLastSeen) / 3600.0) + nRandomizer);
genesis 1054
genesis 1055
genesis 1056 if (nSinceLastSeen < 60 * 60)
genesis 1057 nDelay = 10 * 60;
genesis 1058
genesis 1059
genesis 1060 if (nSinceLastTry < nDelay)
genesis 1061 continue;
genesis 1062
genesis 1063
genesis 1064 if (vNodes.size() >= 8 && nSinceLastSeen > 24 * 60 * 60)
genesis 1065 continue;
genesis 1066
genesis 1067
genesis 1068
genesis 1069 int64 nScore = min(nSinceLastTry, (int64)24 * 60 * 60) - nSinceLastSeen - nRandomizer;
genesis 1070 if (nScore > nBest)
genesis 1071 {
genesis 1072 nBest = nScore;
genesis 1073 addrConnect = addr;
genesis 1074 }
genesis 1075 }
genesis 1076 }
genesis 1077
genesis 1078 if (addrConnect.IsValid())
genesis 1079 OpenNetworkConnection(addrConnect);
genesis 1080 }
genesis 1081 }
genesis 1082
asciilifeform_wires 1083 bool OpenNetworkConnection(const CAddress& addrConnect, bool fWireConnection)
genesis 1084 {
genesis 1085
genesis 1086
genesis 1087
genesis 1088 if (fShutdown)
genesis 1089 return false;
asciilifeform_wires 1090
asciilifeform_wires 1091 if (!fWireConnection &&
asciilifeform_wires 1092 (addrConnect.ip == addrLocalHost.ip || CNode::IsBanned(addrConnect.ip)))
asciilifeform_wires 1093 return false;
asciilifeform_wires 1094
asciilifeform_wires 1095 if (!addrConnect.IsIPv4() || FindNode(addrConnect.ip))
genesis 1096 return false;
genesis 1097
genesis 1098 vnThreadsRunning[1]--;
asciilifeform_wires 1099 CNode* pnode = ConnectNode(addrConnect, 0, fWireConnection);
genesis 1100 vnThreadsRunning[1]++;
genesis 1101 if (fShutdown)
genesis 1102 return false;
genesis 1103 if (!pnode)
genesis 1104 return false;
genesis 1105 pnode->fNetworkNode = true;
genesis 1106
genesis 1107 return true;
genesis 1108 }
genesis 1109
genesis 1110
asciilifeform_wires 1111 void ThreadOpenWires(void* parg)
asciilifeform_wires 1112 {
asciilifeform_wires 1113 IMPLEMENT_RANDOMIZE_STACK(ThreadOpenWires(parg));
asciilifeform_wires 1114 try
asciilifeform_wires 1115 {
asciilifeform_wires 1116 vnThreadsRunning[5]++;
asciilifeform_wires 1117 ThreadOpenWires2(parg);
asciilifeform_wires 1118 vnThreadsRunning[5]--;
asciilifeform_wires 1119 }
asciilifeform_wires 1120 catch (std::exception& e) {
asciilifeform_wires 1121 vnThreadsRunning[5]--;
asciilifeform_wires 1122 PrintException(&e, "ThreadOpenWires()");
asciilifeform_wires 1123 } catch (...) {
asciilifeform_wires 1124 vnThreadsRunning[5]--;
asciilifeform_wires 1125 PrintException(NULL, "ThreadOpenWires()");
asciilifeform_wires 1126 }
asciilifeform_wires 1127 printf("ThreadOpenWires exiting\n");
asciilifeform_wires 1128 }
genesis 1129
genesis 1130
asciilifeform_wires 1131 void ThreadOpenWires2(void* parg)
asciilifeform_wires 1132 {
asciilifeform_wires 1133 printf("ThreadOpenWires started\n");
genesis 1134
asciilifeform_wires 1135 while (1)
asciilifeform_wires 1136 {
asciilifeform_wires 1137 BOOST_FOREACH(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapWires)
asciilifeform_wires 1138 {
asciilifeform_wires 1139 const CAddress& addr = item.second;
asciilifeform_wires 1140 OpenNetworkConnection(addr, true);
asciilifeform_wires 1141 if (fShutdown)
asciilifeform_wires 1142 return;
asciilifeform_wires 1143 }
asciilifeform_wires 1144 Sleep(500);
asciilifeform_wires 1145 }
asciilifeform_wires 1146 }
genesis 1147
genesis 1148
genesis 1149 void ThreadMessageHandler(void* parg)
genesis 1150 {
genesis 1151 IMPLEMENT_RANDOMIZE_STACK(ThreadMessageHandler(parg));
genesis 1152 try
genesis 1153 {
genesis 1154 vnThreadsRunning[2]++;
genesis 1155 ThreadMessageHandler2(parg);
genesis 1156 vnThreadsRunning[2]--;
genesis 1157 }
genesis 1158 catch (std::exception& e) {
genesis 1159 vnThreadsRunning[2]--;
genesis 1160 PrintException(&e, "ThreadMessageHandler()");
genesis 1161 } catch (...) {
genesis 1162 vnThreadsRunning[2]--;
genesis 1163 PrintException(NULL, "ThreadMessageHandler()");
genesis 1164 }
genesis 1165 printf("ThreadMessageHandler exiting\n");
genesis 1166 }
genesis 1167
genesis 1168 void ThreadMessageHandler2(void* parg)
genesis 1169 {
genesis 1170 printf("ThreadMessageHandler started\n");
genesis 1171 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
genesis 1172 while (!fShutdown)
genesis 1173 {
genesis 1174 vector<CNode*> vNodesCopy;
genesis 1175 CRITICAL_BLOCK(cs_vNodes)
genesis 1176 {
genesis 1177 vNodesCopy = vNodes;
genesis 1178 BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis 1179 pnode->AddRef();
genesis 1180 }
genesis 1181
genesis 1182
genesis 1183 CNode* pnodeTrickle = NULL;
genesis 1184 if (!vNodesCopy.empty())
genesis 1185 pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
genesis 1186 BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis 1187 {
genesis 1188
genesis 1189 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
genesis 1190 ProcessMessages(pnode);
genesis 1191 if (fShutdown)
genesis 1192 return;
genesis 1193
genesis 1194
genesis 1195 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
genesis 1196 SendMessages(pnode, pnode == pnodeTrickle);
genesis 1197 if (fShutdown)
genesis 1198 return;
genesis 1199 }
genesis 1200
genesis 1201 CRITICAL_BLOCK(cs_vNodes)
genesis 1202 {
genesis 1203 BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis 1204 pnode->Release();
genesis 1205 }
genesis 1206
genesis 1207
genesis 1208
genesis 1209
genesis 1210 vnThreadsRunning[2]--;
genesis 1211 Sleep(100);
genesis 1212 if (fRequestShutdown)
genesis 1213 Shutdown(NULL);
genesis 1214 vnThreadsRunning[2]++;
genesis 1215 if (fShutdown)
genesis 1216 return;
genesis 1217 }
genesis 1218 }
genesis 1219
genesis 1220
genesis 1221
genesis 1222
genesis 1223
genesis 1224
genesis 1225 bool BindListenPort(string& strError)
genesis 1226 {
genesis 1227 strError = "";
genesis 1228 int nOne = 1;
genesis 1229 addrLocalHost.port = htons(GetListenPort());
genesis 1230
genesis 1231
genesis 1232 hListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
genesis 1233 if (hListenSocket == INVALID_SOCKET)
genesis 1234 {
genesis 1235 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
genesis 1236 printf("%s\n", strError.c_str());
genesis 1237 return false;
genesis 1238 }
genesis 1239
genesis 1240 #ifdef SO_NOSIGPIPE
genesis 1241
genesis 1242 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
genesis 1243 #endif
genesis 1244
genesis 1245
genesis 1246
genesis 1247 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
genesis 1248
genesis 1249 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
genesis 1250 {
genesis 1251 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
genesis 1252 printf("%s\n", strError.c_str());
genesis 1253 return false;
genesis 1254 }
genesis 1255
genesis 1256
genesis 1257
genesis 1258 struct sockaddr_in sockaddr;
genesis 1259 memset(&sockaddr, 0, sizeof(sockaddr));
genesis 1260 sockaddr.sin_family = AF_INET;
genesis 1261 sockaddr.sin_addr.s_addr = INADDR_ANY;
genesis 1262 sockaddr.sin_port = htons(GetListenPort());
genesis 1263 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
genesis 1264 {
genesis 1265 int nErr = WSAGetLastError();
genesis 1266 if (nErr == WSAEADDRINUSE)
genesis 1267 strError = strprintf(_("Unable to bind to port %d on this computer. Bitcoin is probably already running."), ntohs(sockaddr.sin_port));
genesis 1268 else
genesis 1269 strError = strprintf("Error: Unable to bind to port %d on this computer (bind returned error %d)", ntohs(sockaddr.sin_port), nErr);
genesis 1270 printf("%s\n", strError.c_str());
genesis 1271 return false;
genesis 1272 }
genesis 1273 printf("Bound to port %d\n", ntohs(sockaddr.sin_port));
genesis 1274
genesis 1275
genesis 1276 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
genesis 1277 {
genesis 1278 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
genesis 1279 printf("%s\n", strError.c_str());
genesis 1280 return false;
genesis 1281 }
genesis 1282
genesis 1283 return true;
genesis 1284 }
genesis 1285
genesis 1286 void StartNode(void* parg)
genesis 1287 {
genesis 1288 if (pnodeLocalHost == NULL)
asciilifeform_dns... 1289 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress("127.0.0.1", 0, nLocalServices));
genesis 1290
genesis 1291
genesis 1292 struct ifaddrs* myaddrs;
genesis 1293 if (getifaddrs(&myaddrs) == 0)
genesis 1294 {
genesis 1295 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
genesis 1296 {
genesis 1297 if (ifa->ifa_addr == NULL) continue;
genesis 1298 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
genesis 1299 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
genesis 1300 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
genesis 1301 char pszIP[100];
genesis 1302 if (ifa->ifa_addr->sa_family == AF_INET)
genesis 1303 {
genesis 1304 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
genesis 1305 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s4->sin_addr), pszIP, sizeof(pszIP)) != NULL)
genesis 1306 printf("ipv4 %s: %s\n", ifa->ifa_name, pszIP);
genesis 1307
genesis 1308
genesis 1309 CAddress addr(*(unsigned int*)&s4->sin_addr, GetListenPort(), nLocalServices);
genesis 1310 if (addr.IsValid() && addr.GetByte(3) != 127)
genesis 1311 {
genesis 1312 addrLocalHost = addr;
genesis 1313 break;
genesis 1314 }
genesis 1315 }
genesis 1316 else if (ifa->ifa_addr->sa_family == AF_INET6)
genesis 1317 {
genesis 1318 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
genesis 1319 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s6->sin6_addr), pszIP, sizeof(pszIP)) != NULL)
genesis 1320 printf("ipv6 %s: %s\n", ifa->ifa_name, pszIP);
genesis 1321 }
genesis 1322 }
genesis 1323 freeifaddrs(myaddrs);
genesis 1324 }
bitcoin-asciilife... 1325
genesis 1326 printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
genesis 1327
genesis 1328 if (fUseProxy || mapArgs.count("-connect") || fNoListen)
genesis 1329 {
genesis 1330
genesis 1331 addrLocalHost.ip = CAddress("0.0.0.0").ip;
genesis 1332 }
genesis 1333 else
genesis 1334 {
asciilifeform_ver... 1335 addrLocalHost.ip = CAddress(mapArgs["-myip"]).ip;
asciilifeform_ver... 1336 if (!addrLocalHost.IsValid())
asciilifeform_ver... 1337 throw runtime_error(strprintf(_("You must set myip=<ipaddress> on the command line or in the configuration file:\n%s\n"
asciilifeform_ver... 1338 "If the file does not exist, create it with owner-readable-only file permissions."),
asciilifeform_ver... 1339 GetConfigFile().c_str()));
genesis 1340 }
genesis 1341
asciilifeform_ver... 1342 printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
asciilifeform_ver... 1343
genesis 1344
genesis 1345
genesis 1346
genesis 1347
genesis 1348
genesis 1349 if (!CreateThread(ThreadSocketHandler, NULL))
genesis 1350 printf("Error: CreateThread(ThreadSocketHandler) failed\n");
genesis 1351
genesis 1352
genesis 1353 if (!CreateThread(ThreadOpenConnections, NULL))
genesis 1354 printf("Error: CreateThread(ThreadOpenConnections) failed\n");
genesis 1355
asciilifeform_wires 1356
asciilifeform_wires 1357 if (!CreateThread(ThreadOpenWires, NULL))
asciilifeform_wires 1358 printf("Error: CreateThread(ThreadOpenWires) failed\n");
asciilifeform_wires 1359
genesis 1360
genesis 1361 if (!CreateThread(ThreadMessageHandler, NULL))
genesis 1362 printf("Error: CreateThread(ThreadMessageHandler) failed\n");
genesis 1363
genesis 1364
genesis 1365 GenerateBitcoins(fGenerateBitcoins, pwalletMain);
genesis 1366 }
genesis 1367
genesis 1368 bool StopNode()
genesis 1369 {
genesis 1370 printf("StopNode()\n");
genesis 1371 fShutdown = true;
genesis 1372 nTransactionsUpdated++;
genesis 1373 int64 nStart = GetTime();
asciilifeform_wires 1374 while (vnThreadsRunning[0] > 0 || vnThreadsRunning[1] > 0 || vnThreadsRunning[2] > 0 || vnThreadsRunning[3] > 0 || vnThreadsRunning[4] > 0 || vnThreadsRunning[5] > 0
genesis 1375 )
genesis 1376 {
genesis 1377 if (GetTime() - nStart > 20)
genesis 1378 break;
genesis 1379 Sleep(20);
genesis 1380 }
genesis 1381 if (vnThreadsRunning[0] > 0) printf("ThreadSocketHandler still running\n");
genesis 1382 if (vnThreadsRunning[1] > 0) printf("ThreadOpenConnections still running\n");
genesis 1383 if (vnThreadsRunning[2] > 0) printf("ThreadMessageHandler still running\n");
genesis 1384 if (vnThreadsRunning[3] > 0) printf("ThreadBitcoinMiner still running\n");
genesis 1385 if (vnThreadsRunning[4] > 0) printf("ThreadRPCServer still running\n");
asciilifeform_wires 1386 if (vnThreadsRunning[5] > 0) printf("ThreadOpenWires still running\n");
genesis 1387 while (vnThreadsRunning[2] > 0 || vnThreadsRunning[4] > 0)
genesis 1388 Sleep(20);
genesis 1389 Sleep(50);
genesis 1390
genesis 1391 return true;
genesis 1392 }
genesis 1393
genesis 1394 class CNetCleanup
genesis 1395 {
genesis 1396 public:
genesis 1397 CNetCleanup()
genesis 1398 {
genesis 1399 }
genesis 1400 ~CNetCleanup()
genesis 1401 {
genesis 1402
genesis 1403 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 1404 if (pnode->hSocket != INVALID_SOCKET)
genesis 1405 closesocket(pnode->hSocket);
genesis 1406 if (hListenSocket != INVALID_SOCKET)
genesis 1407 if (closesocket(hListenSocket) == SOCKET_ERROR)
genesis 1408 printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
genesis 1409
genesis 1410 }
genesis 1411 }
genesis 1412 instance_of_cnetcleanup;