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