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