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 uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK);
asciilifeform_dns... 33 CAddress addrLocalHost("0.0.0.0", 0, nLocalServices);
genesis 34 static CNode* pnodeLocalHost = NULL;
genesis 35 uint64 nLocalHostNonce = 0;
genesis 36 array<int, 10> vnThreadsRunning;
genesis 37 static SOCKET hListenSocket = INVALID_SOCKET;
genesis 38
genesis 39 vector<CNode*> vNodes;
genesis 40 CCriticalSection cs_vNodes;
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
genesis 247 void ThreadGetMyExternalIP(void* parg)
genesis 248 {
genesis 249
genesis 250 if (!GetBoolArg("-noirc"))
genesis 251 {
genesis 252 for (int i = 0; i < 2 * 60; i++)
genesis 253 {
genesis 254 Sleep(1000);
genesis 255 if (fGotExternalIP || fShutdown)
genesis 256 return;
genesis 257 }
genesis 258 }
genesis 259
genesis 260
asciilifeform_zap... 261
genesis 262 }
genesis 263
genesis 264
genesis 265 bool AddAddress(CAddress addr, int64 nTimePenalty, CAddrDB *pAddrDB)
genesis 266 {
genesis 267 if (!addr.IsRoutable())
genesis 268 return false;
genesis 269 if (addr.ip == addrLocalHost.ip)
genesis 270 return false;
genesis 271 addr.nTime = max((int64)0, (int64)addr.nTime - nTimePenalty);
genesis 272 bool fUpdated = false;
genesis 273 bool fNew = false;
genesis 274 CAddress addrFound = addr;
genesis 275
genesis 276 CRITICAL_BLOCK(cs_mapAddresses)
genesis 277 {
genesis 278 map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
genesis 279 if (it == mapAddresses.end())
genesis 280 {
genesis 281
genesis 282 printf("AddAddress(%s)\n", addr.ToString().c_str());
genesis 283 mapAddresses.insert(make_pair(addr.GetKey(), addr));
genesis 284 fUpdated = true;
genesis 285 fNew = true;
genesis 286 }
genesis 287 else
genesis 288 {
genesis 289 addrFound = (*it).second;
genesis 290 if ((addrFound.nServices | addr.nServices) != addrFound.nServices)
genesis 291 {
genesis 292
genesis 293 addrFound.nServices |= addr.nServices;
genesis 294 fUpdated = true;
genesis 295 }
genesis 296 bool fCurrentlyOnline = (GetAdjustedTime() - addr.nTime < 24 * 60 * 60);
genesis 297 int64 nUpdateInterval = (fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60);
genesis 298 if (addrFound.nTime < addr.nTime - nUpdateInterval)
genesis 299 {
genesis 300
genesis 301 addrFound.nTime = addr.nTime;
genesis 302 fUpdated = true;
genesis 303 }
genesis 304 }
genesis 305 }
genesis 306
genesis 307
genesis 308
genesis 309
genesis 310
genesis 311
genesis 312 if (fUpdated)
genesis 313 {
genesis 314 if (pAddrDB)
genesis 315 pAddrDB->WriteAddress(addrFound);
genesis 316 else
genesis 317 CAddrDB().WriteAddress(addrFound);
genesis 318 }
genesis 319 return fNew;
genesis 320 }
genesis 321
genesis 322 void AddressCurrentlyConnected(const CAddress& addr)
genesis 323 {
genesis 324 CAddress *paddrFound = NULL;
genesis 325
genesis 326 CRITICAL_BLOCK(cs_mapAddresses)
genesis 327 {
genesis 328
genesis 329 map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
genesis 330 if (it != mapAddresses.end())
genesis 331 paddrFound = &(*it).second;
genesis 332 }
genesis 333
genesis 334 if (paddrFound)
genesis 335 {
genesis 336 int64 nUpdateInterval = 20 * 60;
genesis 337 if (paddrFound->nTime < GetAdjustedTime() - nUpdateInterval)
genesis 338 {
genesis 339
genesis 340 paddrFound->nTime = GetAdjustedTime();
genesis 341 CAddrDB addrdb;
genesis 342 addrdb.WriteAddress(*paddrFound);
genesis 343 }
genesis 344 }
genesis 345 }
genesis 346
genesis 347
genesis 348
genesis 349
genesis 350
genesis 351 void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1)
genesis 352 {
genesis 353
genesis 354
genesis 355 CRITICAL_BLOCK(cs_vNodes)
genesis 356 {
genesis 357 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 358 {
genesis 359 CRITICAL_BLOCK(pnode->cs_mapRequests)
genesis 360 {
genesis 361 for (map<uint256, CRequestTracker>::iterator mi = pnode->mapRequests.begin(); mi != pnode->mapRequests.end();)
genesis 362 {
genesis 363 CRequestTracker& tracker = (*mi).second;
genesis 364 if (tracker.fn == fn && tracker.param1 == param1)
genesis 365 pnode->mapRequests.erase(mi++);
genesis 366 else
genesis 367 mi++;
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
genesis 386
genesis 387
genesis 388
genesis 389 bool AnySubscribed(unsigned int nChannel)
genesis 390 {
genesis 391 if (pnodeLocalHost->IsSubscribed(nChannel))
genesis 392 return true;
genesis 393 CRITICAL_BLOCK(cs_vNodes)
genesis 394 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 395 if (pnode->IsSubscribed(nChannel))
genesis 396 return true;
genesis 397 return false;
genesis 398 }
genesis 399
genesis 400 bool CNode::IsSubscribed(unsigned int nChannel)
genesis 401 {
genesis 402 if (nChannel >= vfSubscribe.size())
genesis 403 return false;
genesis 404 return vfSubscribe[nChannel];
genesis 405 }
genesis 406
genesis 407 void CNode::Subscribe(unsigned int nChannel, unsigned int nHops)
genesis 408 {
genesis 409 if (nChannel >= vfSubscribe.size())
genesis 410 return;
genesis 411
genesis 412 if (!AnySubscribed(nChannel))
genesis 413 {
genesis 414
genesis 415 CRITICAL_BLOCK(cs_vNodes)
genesis 416 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 417 if (pnode != this)
genesis 418 pnode->PushMessage("subscribe", nChannel, nHops);
genesis 419 }
genesis 420
genesis 421 vfSubscribe[nChannel] = true;
genesis 422 }
genesis 423
genesis 424 void CNode::CancelSubscribe(unsigned int nChannel)
genesis 425 {
genesis 426 if (nChannel >= vfSubscribe.size())
genesis 427 return;
genesis 428
genesis 429
genesis 430 if (!vfSubscribe[nChannel])
genesis 431 return;
genesis 432 vfSubscribe[nChannel] = false;
genesis 433
genesis 434 if (!AnySubscribed(nChannel))
genesis 435 {
genesis 436
genesis 437 CRITICAL_BLOCK(cs_vNodes)
genesis 438 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 439 if (pnode != this)
genesis 440 pnode->PushMessage("sub-cancel", nChannel);
genesis 441 }
genesis 442 }
genesis 443
genesis 444
genesis 445
genesis 446
genesis 447
genesis 448
genesis 449
genesis 450
genesis 451
genesis 452 CNode* FindNode(unsigned int ip)
genesis 453 {
genesis 454 CRITICAL_BLOCK(cs_vNodes)
genesis 455 {
genesis 456 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 457 if (pnode->addr.ip == ip)
genesis 458 return (pnode);
genesis 459 }
genesis 460 return NULL;
genesis 461 }
genesis 462
genesis 463 CNode* FindNode(CAddress addr)
genesis 464 {
genesis 465 CRITICAL_BLOCK(cs_vNodes)
genesis 466 {
genesis 467 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 468 if (pnode->addr == addr)
genesis 469 return (pnode);
genesis 470 }
genesis 471 return NULL;
genesis 472 }
genesis 473
genesis 474 CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
genesis 475 {
genesis 476 if (addrConnect.ip == addrLocalHost.ip)
genesis 477 return NULL;
genesis 478
genesis 479
genesis 480 CNode* pnode = FindNode(addrConnect.ip);
genesis 481 if (pnode)
genesis 482 {
genesis 483 if (nTimeout != 0)
genesis 484 pnode->AddRef(nTimeout);
genesis 485 else
genesis 486 pnode->AddRef();
genesis 487 return pnode;
genesis 488 }
genesis 489
genesis 490
genesis 491 printf("trying connection %s lastseen=%.1fhrs lasttry=%.1fhrs\n",
genesis 492 addrConnect.ToString().c_str(),
genesis 493 (double)(addrConnect.nTime - GetAdjustedTime())/3600.0,
genesis 494 (double)(addrConnect.nLastTry - GetAdjustedTime())/3600.0);
genesis 495
genesis 496 CRITICAL_BLOCK(cs_mapAddresses)
genesis 497 mapAddresses[addrConnect.GetKey()].nLastTry = GetAdjustedTime();
genesis 498
genesis 499
genesis 500 SOCKET hSocket;
genesis 501 if (ConnectSocket(addrConnect, hSocket))
genesis 502 {
genesis 503
genesis 504 printf("connected %s\n", addrConnect.ToString().c_str());
genesis 505
genesis 506
genesis 507 if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
genesis 508 printf("ConnectSocket() : fcntl nonblocking setting failed, error %d\n", errno);
genesis 509
genesis 510
genesis 511 CNode* pnode = new CNode(hSocket, addrConnect, false);
genesis 512 if (nTimeout != 0)
genesis 513 pnode->AddRef(nTimeout);
genesis 514 else
genesis 515 pnode->AddRef();
genesis 516 CRITICAL_BLOCK(cs_vNodes)
genesis 517 vNodes.push_back(pnode);
genesis 518
genesis 519 pnode->nTimeConnected = GetTime();
genesis 520 return pnode;
genesis 521 }
genesis 522 else
genesis 523 {
genesis 524 return NULL;
genesis 525 }
genesis 526 }
genesis 527
genesis 528 void CNode::CloseSocketDisconnect()
genesis 529 {
genesis 530 fDisconnect = true;
genesis 531 if (hSocket != INVALID_SOCKET)
genesis 532 {
genesis 533 if (fDebug)
genesis 534 printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
genesis 535 printf("disconnecting node %s\n", addr.ToString().c_str());
genesis 536 closesocket(hSocket);
genesis 537 hSocket = INVALID_SOCKET;
genesis 538 }
genesis 539 }
genesis 540
genesis 541 void CNode::Cleanup()
genesis 542 {
genesis 543
genesis 544
genesis 545
genesis 546
genesis 547 for (unsigned int nChannel = 0; nChannel < vfSubscribe.size(); nChannel++)
genesis 548 if (vfSubscribe[nChannel])
genesis 549 CancelSubscribe(nChannel);
genesis 550 }
genesis 551
genesis 552
genesis 553 std::map<unsigned int, int64> CNode::setBanned;
genesis 554 CCriticalSection CNode::cs_setBanned;
genesis 555
genesis 556 void CNode::ClearBanned()
genesis 557 {
genesis 558 setBanned.clear();
genesis 559 }
genesis 560
genesis 561 bool CNode::IsBanned(unsigned int ip)
genesis 562 {
genesis 563 bool fResult = false;
genesis 564 CRITICAL_BLOCK(cs_setBanned)
genesis 565 {
genesis 566 std::map<unsigned int, int64>::iterator i = setBanned.find(ip);
genesis 567 if (i != setBanned.end())
genesis 568 {
genesis 569 int64 t = (*i).second;
genesis 570 if (GetTime() < t)
genesis 571 fResult = true;
genesis 572 }
genesis 573 }
genesis 574 return fResult;
genesis 575 }
genesis 576
genesis 577 bool CNode::Misbehaving(int howmuch)
genesis 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 {
genesis 646 if (pnode->fDisconnect ||
genesis 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
genesis 1065 if (nGotIRCAddresses > 0 && vNodes.size() >= 2 && nSinceLastSeen > 24 * 60 * 60)
genesis 1066 continue;
genesis 1067
genesis 1068
genesis 1069 if (vNodes.size() >= 8 && nSinceLastSeen > 24 * 60 * 60)
genesis 1070 continue;
genesis 1071
genesis 1072
genesis 1073
genesis 1074 int64 nScore = min(nSinceLastTry, (int64)24 * 60 * 60) - nSinceLastSeen - nRandomizer;
genesis 1075 if (nScore > nBest)
genesis 1076 {
genesis 1077 nBest = nScore;
genesis 1078 addrConnect = addr;
genesis 1079 }
genesis 1080 }
genesis 1081 }
genesis 1082
genesis 1083 if (addrConnect.IsValid())
genesis 1084 OpenNetworkConnection(addrConnect);
genesis 1085 }
genesis 1086 }
genesis 1087
genesis 1088 bool OpenNetworkConnection(const CAddress& addrConnect)
genesis 1089 {
genesis 1090
genesis 1091
genesis 1092
genesis 1093 if (fShutdown)
genesis 1094 return false;
genesis 1095 if (addrConnect.ip == addrLocalHost.ip || !addrConnect.IsIPv4() ||
genesis 1096 FindNode(addrConnect.ip) || CNode::IsBanned(addrConnect.ip))
genesis 1097 return false;
genesis 1098
genesis 1099 vnThreadsRunning[1]--;
genesis 1100 CNode* pnode = ConnectNode(addrConnect);
genesis 1101 vnThreadsRunning[1]++;
genesis 1102 if (fShutdown)
genesis 1103 return false;
genesis 1104 if (!pnode)
genesis 1105 return false;
genesis 1106 pnode->fNetworkNode = true;
genesis 1107
genesis 1108 return true;
genesis 1109 }
genesis 1110
genesis 1111
genesis 1112
genesis 1113
genesis 1114
genesis 1115
genesis 1116
genesis 1117
genesis 1118 void ThreadMessageHandler(void* parg)
genesis 1119 {
genesis 1120 IMPLEMENT_RANDOMIZE_STACK(ThreadMessageHandler(parg));
genesis 1121 try
genesis 1122 {
genesis 1123 vnThreadsRunning[2]++;
genesis 1124 ThreadMessageHandler2(parg);
genesis 1125 vnThreadsRunning[2]--;
genesis 1126 }
genesis 1127 catch (std::exception& e) {
genesis 1128 vnThreadsRunning[2]--;
genesis 1129 PrintException(&e, "ThreadMessageHandler()");
genesis 1130 } catch (...) {
genesis 1131 vnThreadsRunning[2]--;
genesis 1132 PrintException(NULL, "ThreadMessageHandler()");
genesis 1133 }
genesis 1134 printf("ThreadMessageHandler exiting\n");
genesis 1135 }
genesis 1136
genesis 1137 void ThreadMessageHandler2(void* parg)
genesis 1138 {
genesis 1139 printf("ThreadMessageHandler started\n");
genesis 1140 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
genesis 1141 while (!fShutdown)
genesis 1142 {
genesis 1143 vector<CNode*> vNodesCopy;
genesis 1144 CRITICAL_BLOCK(cs_vNodes)
genesis 1145 {
genesis 1146 vNodesCopy = vNodes;
genesis 1147 BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis 1148 pnode->AddRef();
genesis 1149 }
genesis 1150
genesis 1151
genesis 1152 CNode* pnodeTrickle = NULL;
genesis 1153 if (!vNodesCopy.empty())
genesis 1154 pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
genesis 1155 BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis 1156 {
genesis 1157
genesis 1158 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
genesis 1159 ProcessMessages(pnode);
genesis 1160 if (fShutdown)
genesis 1161 return;
genesis 1162
genesis 1163
genesis 1164 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
genesis 1165 SendMessages(pnode, pnode == pnodeTrickle);
genesis 1166 if (fShutdown)
genesis 1167 return;
genesis 1168 }
genesis 1169
genesis 1170 CRITICAL_BLOCK(cs_vNodes)
genesis 1171 {
genesis 1172 BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis 1173 pnode->Release();
genesis 1174 }
genesis 1175
genesis 1176
genesis 1177
genesis 1178
genesis 1179 vnThreadsRunning[2]--;
genesis 1180 Sleep(100);
genesis 1181 if (fRequestShutdown)
genesis 1182 Shutdown(NULL);
genesis 1183 vnThreadsRunning[2]++;
genesis 1184 if (fShutdown)
genesis 1185 return;
genesis 1186 }
genesis 1187 }
genesis 1188
genesis 1189
genesis 1190
genesis 1191
genesis 1192
genesis 1193
genesis 1194 bool BindListenPort(string& strError)
genesis 1195 {
genesis 1196 strError = "";
genesis 1197 int nOne = 1;
genesis 1198 addrLocalHost.port = htons(GetListenPort());
genesis 1199
genesis 1200
genesis 1201 hListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
genesis 1202 if (hListenSocket == INVALID_SOCKET)
genesis 1203 {
genesis 1204 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
genesis 1205 printf("%s\n", strError.c_str());
genesis 1206 return false;
genesis 1207 }
genesis 1208
genesis 1209 #ifdef SO_NOSIGPIPE
genesis 1210
genesis 1211 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
genesis 1212 #endif
genesis 1213
genesis 1214
genesis 1215
genesis 1216 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
genesis 1217
genesis 1218 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
genesis 1219 {
genesis 1220 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
genesis 1221 printf("%s\n", strError.c_str());
genesis 1222 return false;
genesis 1223 }
genesis 1224
genesis 1225
genesis 1226
genesis 1227 struct sockaddr_in sockaddr;
genesis 1228 memset(&sockaddr, 0, sizeof(sockaddr));
genesis 1229 sockaddr.sin_family = AF_INET;
genesis 1230 sockaddr.sin_addr.s_addr = INADDR_ANY;
genesis 1231 sockaddr.sin_port = htons(GetListenPort());
genesis 1232 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
genesis 1233 {
genesis 1234 int nErr = WSAGetLastError();
genesis 1235 if (nErr == WSAEADDRINUSE)
genesis 1236 strError = strprintf(_("Unable to bind to port %d on this computer. Bitcoin is probably already running."), ntohs(sockaddr.sin_port));
genesis 1237 else
genesis 1238 strError = strprintf("Error: Unable to bind to port %d on this computer (bind returned error %d)", ntohs(sockaddr.sin_port), nErr);
genesis 1239 printf("%s\n", strError.c_str());
genesis 1240 return false;
genesis 1241 }
genesis 1242 printf("Bound to port %d\n", ntohs(sockaddr.sin_port));
genesis 1243
genesis 1244
genesis 1245 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
genesis 1246 {
genesis 1247 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
genesis 1248 printf("%s\n", strError.c_str());
genesis 1249 return false;
genesis 1250 }
genesis 1251
genesis 1252 return true;
genesis 1253 }
genesis 1254
genesis 1255 void StartNode(void* parg)
genesis 1256 {
genesis 1257 if (pnodeLocalHost == NULL)
asciilifeform_dns... 1258 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress("127.0.0.1", 0, nLocalServices));
genesis 1259
genesis 1260
genesis 1261 struct ifaddrs* myaddrs;
genesis 1262 if (getifaddrs(&myaddrs) == 0)
genesis 1263 {
genesis 1264 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
genesis 1265 {
genesis 1266 if (ifa->ifa_addr == NULL) continue;
genesis 1267 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
genesis 1268 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
genesis 1269 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
genesis 1270 char pszIP[100];
genesis 1271 if (ifa->ifa_addr->sa_family == AF_INET)
genesis 1272 {
genesis 1273 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
genesis 1274 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s4->sin_addr), pszIP, sizeof(pszIP)) != NULL)
genesis 1275 printf("ipv4 %s: %s\n", ifa->ifa_name, pszIP);
genesis 1276
genesis 1277
genesis 1278 CAddress addr(*(unsigned int*)&s4->sin_addr, GetListenPort(), nLocalServices);
genesis 1279 if (addr.IsValid() && addr.GetByte(3) != 127)
genesis 1280 {
genesis 1281 addrLocalHost = addr;
genesis 1282 break;
genesis 1283 }
genesis 1284 }
genesis 1285 else if (ifa->ifa_addr->sa_family == AF_INET6)
genesis 1286 {
genesis 1287 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
genesis 1288 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s6->sin6_addr), pszIP, sizeof(pszIP)) != NULL)
genesis 1289 printf("ipv6 %s: %s\n", ifa->ifa_name, pszIP);
genesis 1290 }
genesis 1291 }
genesis 1292 freeifaddrs(myaddrs);
genesis 1293 }
bitcoin-asciilife... 1294
genesis 1295 printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
genesis 1296
genesis 1297 if (fUseProxy || mapArgs.count("-connect") || fNoListen)
genesis 1298 {
genesis 1299
genesis 1300 addrLocalHost.ip = CAddress("0.0.0.0").ip;
genesis 1301 printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
genesis 1302 }
genesis 1303 else
genesis 1304 {
genesis 1305 CreateThread(ThreadGetMyExternalIP, NULL);
genesis 1306 }
genesis 1307
genesis 1308
genesis 1309
genesis 1310
genesis 1311
genesis 1312
genesis 1313 if (!CreateThread(ThreadIRCSeed, NULL))
genesis 1314 printf("Error: CreateThread(ThreadIRCSeed) failed\n");
genesis 1315
genesis 1316
genesis 1317 if (!CreateThread(ThreadSocketHandler, NULL))
genesis 1318 printf("Error: CreateThread(ThreadSocketHandler) failed\n");
genesis 1319
genesis 1320
genesis 1321 if (!CreateThread(ThreadOpenConnections, NULL))
genesis 1322 printf("Error: CreateThread(ThreadOpenConnections) failed\n");
genesis 1323
genesis 1324
genesis 1325 if (!CreateThread(ThreadMessageHandler, NULL))
genesis 1326 printf("Error: CreateThread(ThreadMessageHandler) failed\n");
genesis 1327
genesis 1328
genesis 1329 GenerateBitcoins(fGenerateBitcoins, pwalletMain);
genesis 1330 }
genesis 1331
genesis 1332 bool StopNode()
genesis 1333 {
genesis 1334 printf("StopNode()\n");
genesis 1335 fShutdown = true;
genesis 1336 nTransactionsUpdated++;
genesis 1337 int64 nStart = GetTime();
genesis 1338 while (vnThreadsRunning[0] > 0 || vnThreadsRunning[1] > 0 || vnThreadsRunning[2] > 0 || vnThreadsRunning[3] > 0 || vnThreadsRunning[4] > 0
genesis 1339 )
genesis 1340 {
genesis 1341 if (GetTime() - nStart > 20)
genesis 1342 break;
genesis 1343 Sleep(20);
genesis 1344 }
genesis 1345 if (vnThreadsRunning[0] > 0) printf("ThreadSocketHandler still running\n");
genesis 1346 if (vnThreadsRunning[1] > 0) printf("ThreadOpenConnections still running\n");
genesis 1347 if (vnThreadsRunning[2] > 0) printf("ThreadMessageHandler still running\n");
genesis 1348 if (vnThreadsRunning[3] > 0) printf("ThreadBitcoinMiner still running\n");
genesis 1349 if (vnThreadsRunning[4] > 0) printf("ThreadRPCServer still running\n");
genesis 1350 while (vnThreadsRunning[2] > 0 || vnThreadsRunning[4] > 0)
genesis 1351 Sleep(20);
genesis 1352 Sleep(50);
genesis 1353
genesis 1354 return true;
genesis 1355 }
genesis 1356
genesis 1357 class CNetCleanup
genesis 1358 {
genesis 1359 public:
genesis 1360 CNetCleanup()
genesis 1361 {
genesis 1362 }
genesis 1363 ~CNetCleanup()
genesis 1364 {
genesis 1365
genesis 1366 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 1367 if (pnode->hSocket != INVALID_SOCKET)
genesis 1368 closesocket(pnode->hSocket);
genesis 1369 if (hListenSocket != INVALID_SOCKET)
genesis 1370 if (closesocket(hListenSocket) == SOCKET_ERROR)
genesis 1371 printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
genesis 1372
genesis 1373 }
genesis 1374 }
genesis 1375 instance_of_cnetcleanup;