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