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