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 {
polarbeard_better... 114 printf(SERR SNET "connection timeout\n");
genesis 115 closesocket(hSocket);
genesis 116 return false;
genesis 117 }
genesis 118 if (nRet == SOCKET_ERROR)
genesis 119 {
polarbeard_better... 120 printf(SERR SNET "select 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 {
polarbeard_better... 127 printf(SERR SNET "getsockopt for connection failed: %i\n", WSAGetLastError());
genesis 128 closesocket(hSocket);
genesis 129 return false;
genesis 130 }
genesis 131 if (nRet != 0)
genesis 132 {
polarbeard_better... 133 printf(SERR SNET "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 {
polarbeard_better... 140 printf(SERR SNET "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 {
polarbeard_better... 160 printf(SWAR SNET "connecting through proxy to %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);
polarbeard_better... 171 return error(SNET "couldn't send message over proxy address %s",
polarbeard_better... 172 addrConnect.ToString().c_str());
genesis 173 }
genesis 174 char pchRet[8];
genesis 175 if (recv(hSocket, pchRet, 8, 0) != 8)
genesis 176 {
genesis 177 closesocket(hSocket);
polarbeard_better... 178 return error(SNET "couldn't read response over proxy address %s",
polarbeard_better... 179 addrConnect.ToString().c_str());
genesis 180 }
genesis 181 if (pchRet[1] != 0x5a)
genesis 182 {
genesis 183 closesocket(hSocket);
genesis 184 if (pchRet[1] != 0x5b)
polarbeard_better... 185 printf(SERR SNET "proxy returned error %d\n", pchRet[1]);
genesis 186 return false;
genesis 187 }
polarbeard_better... 188 printf(SWAR SNET "connected through proxy to %s\n", addrConnect.ToString().c_str());
genesis 189 }
genesis 190
genesis 191 hSocketRet = hSocket;
genesis 192 return true;
genesis 193 }
genesis 194
genesis 195
asciilifeform_dns... 196 bool Lookup(const char *pszName, vector<CAddress>& vaddr, int nServices, int nMaxSolutions, int portDefault, bool fAllowPort)
genesis 197 {
genesis 198 vaddr.clear();
genesis 199 if (pszName[0] == 0)
genesis 200 return false;
genesis 201 int port = portDefault;
genesis 202 char psz[256];
genesis 203 char *pszHost = psz;
genesis 204 strlcpy(psz, pszName, sizeof(psz));
genesis 205 if (fAllowPort)
genesis 206 {
genesis 207 char* pszColon = strrchr(psz+1,':');
genesis 208 char *pszPortEnd = NULL;
genesis 209 int portParsed = pszColon ? strtoul(pszColon+1, &pszPortEnd, 10) : 0;
genesis 210 if (pszColon && pszPortEnd && pszPortEnd[0] == 0)
genesis 211 {
genesis 212 if (psz[0] == '[' && pszColon[-1] == ']')
genesis 213 {
genesis 214
genesis 215 pszHost = psz+1;
genesis 216 pszColon[-1] = 0;
genesis 217 }
genesis 218 else
genesis 219 pszColon[0] = 0;
genesis 220 port = portParsed;
genesis 221 if (port < 0 || port > USHRT_MAX)
genesis 222 port = USHRT_MAX;
genesis 223 }
genesis 224 }
genesis 225
genesis 226 unsigned int addrIP = inet_addr(pszHost);
genesis 227 if (addrIP != INADDR_NONE)
genesis 228 {
genesis 229
genesis 230 vaddr.push_back(CAddress(addrIP, port, nServices));
genesis 231 return true;
genesis 232 }
genesis 233
asciilifeform_dns... 234 return false;
genesis 235 }
genesis 236
genesis 237
asciilifeform_dns... 238 bool Lookup(const char *pszName, CAddress& addr, int nServices, int portDefault, bool fAllowPort)
genesis 239 {
genesis 240 vector<CAddress> vaddr;
asciilifeform_dns... 241 bool fRet = Lookup(pszName, vaddr, nServices, 1, portDefault, fAllowPort);
genesis 242 if (fRet)
genesis 243 addr = vaddr[0];
genesis 244 return fRet;
genesis 245 }
genesis 246
genesis 247
genesis 248 bool AddAddress(CAddress addr, int64 nTimePenalty, CAddrDB *pAddrDB)
genesis 249 {
genesis 250 if (!addr.IsRoutable())
genesis 251 return false;
genesis 252 if (addr.ip == addrLocalHost.ip)
genesis 253 return false;
genesis 254 addr.nTime = max((int64)0, (int64)addr.nTime - nTimePenalty);
genesis 255 bool fUpdated = false;
genesis 256 bool fNew = false;
genesis 257 CAddress addrFound = addr;
genesis 258
genesis 259 CRITICAL_BLOCK(cs_mapAddresses)
genesis 260 {
genesis 261 map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
genesis 262 if (it == mapAddresses.end())
genesis 263 {
genesis 264
polarbeard_better... 265 printf(SINF SADR "adding %s\n", addr.ToString().c_str());
genesis 266 mapAddresses.insert(make_pair(addr.GetKey(), addr));
genesis 267 fUpdated = true;
genesis 268 fNew = true;
genesis 269 }
genesis 270 else
genesis 271 {
genesis 272 addrFound = (*it).second;
genesis 273 if ((addrFound.nServices | addr.nServices) != addrFound.nServices)
genesis 274 {
genesis 275
genesis 276 addrFound.nServices |= addr.nServices;
genesis 277 fUpdated = true;
genesis 278 }
genesis 279 bool fCurrentlyOnline = (GetAdjustedTime() - addr.nTime < 24 * 60 * 60);
genesis 280 int64 nUpdateInterval = (fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60);
genesis 281 if (addrFound.nTime < addr.nTime - nUpdateInterval)
genesis 282 {
genesis 283
genesis 284 addrFound.nTime = addr.nTime;
genesis 285 fUpdated = true;
genesis 286 }
genesis 287 }
genesis 288 }
genesis 289
genesis 290
genesis 291
genesis 292
genesis 293
genesis 294
genesis 295 if (fUpdated)
genesis 296 {
genesis 297 if (pAddrDB)
genesis 298 pAddrDB->WriteAddress(addrFound);
genesis 299 else
genesis 300 CAddrDB().WriteAddress(addrFound);
genesis 301 }
genesis 302 return fNew;
genesis 303 }
genesis 304
genesis 305 void AddressCurrentlyConnected(const CAddress& addr)
genesis 306 {
genesis 307 CAddress *paddrFound = NULL;
genesis 308
genesis 309 CRITICAL_BLOCK(cs_mapAddresses)
genesis 310 {
genesis 311
genesis 312 map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
genesis 313 if (it != mapAddresses.end())
genesis 314 paddrFound = &(*it).second;
genesis 315 }
genesis 316
genesis 317 if (paddrFound)
genesis 318 {
genesis 319 int64 nUpdateInterval = 20 * 60;
genesis 320 if (paddrFound->nTime < GetAdjustedTime() - nUpdateInterval)
genesis 321 {
genesis 322
genesis 323 paddrFound->nTime = GetAdjustedTime();
genesis 324 CAddrDB addrdb;
genesis 325 addrdb.WriteAddress(*paddrFound);
genesis 326 }
genesis 327 }
genesis 328 }
genesis 329
genesis 330
genesis 331
genesis 332
genesis 333
genesis 334 void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1)
genesis 335 {
genesis 336
genesis 337
genesis 338 CRITICAL_BLOCK(cs_vNodes)
genesis 339 {
genesis 340 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 341 {
genesis 342 CRITICAL_BLOCK(pnode->cs_mapRequests)
genesis 343 {
genesis 344 for (map<uint256, CRequestTracker>::iterator mi = pnode->mapRequests.begin(); mi != pnode->mapRequests.end();)
genesis 345 {
genesis 346 CRequestTracker& tracker = (*mi).second;
genesis 347 if (tracker.fn == fn && tracker.param1 == param1)
genesis 348 pnode->mapRequests.erase(mi++);
genesis 349 else
genesis 350 mi++;
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
genesis 371
genesis 372 bool AnySubscribed(unsigned int nChannel)
genesis 373 {
genesis 374 if (pnodeLocalHost->IsSubscribed(nChannel))
genesis 375 return true;
genesis 376 CRITICAL_BLOCK(cs_vNodes)
genesis 377 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 378 if (pnode->IsSubscribed(nChannel))
genesis 379 return true;
genesis 380 return false;
genesis 381 }
genesis 382
genesis 383 bool CNode::IsSubscribed(unsigned int nChannel)
genesis 384 {
genesis 385 if (nChannel >= vfSubscribe.size())
genesis 386 return false;
genesis 387 return vfSubscribe[nChannel];
genesis 388 }
genesis 389
genesis 390 void CNode::Subscribe(unsigned int nChannel, unsigned int nHops)
genesis 391 {
genesis 392 if (nChannel >= vfSubscribe.size())
genesis 393 return;
genesis 394
genesis 395 if (!AnySubscribed(nChannel))
genesis 396 {
genesis 397
genesis 398 CRITICAL_BLOCK(cs_vNodes)
genesis 399 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 400 if (pnode != this)
genesis 401 pnode->PushMessage("subscribe", nChannel, nHops);
genesis 402 }
genesis 403
genesis 404 vfSubscribe[nChannel] = true;
genesis 405 }
genesis 406
genesis 407 void CNode::CancelSubscribe(unsigned int nChannel)
genesis 408 {
genesis 409 if (nChannel >= vfSubscribe.size())
genesis 410 return;
genesis 411
genesis 412
genesis 413 if (!vfSubscribe[nChannel])
genesis 414 return;
genesis 415 vfSubscribe[nChannel] = false;
genesis 416
genesis 417 if (!AnySubscribed(nChannel))
genesis 418 {
genesis 419
genesis 420 CRITICAL_BLOCK(cs_vNodes)
genesis 421 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 422 if (pnode != this)
genesis 423 pnode->PushMessage("sub-cancel", nChannel);
genesis 424 }
genesis 425 }
genesis 426
genesis 427
genesis 428
genesis 429
genesis 430
genesis 431
genesis 432
genesis 433
genesis 434
genesis 435 CNode* FindNode(unsigned int ip)
genesis 436 {
genesis 437 CRITICAL_BLOCK(cs_vNodes)
genesis 438 {
genesis 439 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 440 if (pnode->addr.ip == ip)
genesis 441 return (pnode);
genesis 442 }
genesis 443 return NULL;
genesis 444 }
genesis 445
genesis 446 CNode* FindNode(CAddress addr)
genesis 447 {
genesis 448 CRITICAL_BLOCK(cs_vNodes)
genesis 449 {
genesis 450 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 451 if (pnode->addr == addr)
genesis 452 return (pnode);
genesis 453 }
genesis 454 return NULL;
genesis 455 }
genesis 456
genesis 457 CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
genesis 458 {
genesis 459 if (addrConnect.ip == addrLocalHost.ip)
genesis 460 return NULL;
genesis 461
genesis 462
genesis 463 CNode* pnode = FindNode(addrConnect.ip);
genesis 464 if (pnode)
genesis 465 {
genesis 466 if (nTimeout != 0)
genesis 467 pnode->AddRef(nTimeout);
genesis 468 else
genesis 469 pnode->AddRef();
genesis 470 return pnode;
genesis 471 }
genesis 472
genesis 473
polarbeard_better... 474 printf(SINF SNET "trying to connect to %s\n",
genesis 475 addrConnect.ToString().c_str(),
genesis 476 (double)(addrConnect.nTime - GetAdjustedTime())/3600.0,
genesis 477 (double)(addrConnect.nLastTry - GetAdjustedTime())/3600.0);
genesis 478
genesis 479 CRITICAL_BLOCK(cs_mapAddresses)
genesis 480 mapAddresses[addrConnect.GetKey()].nLastTry = GetAdjustedTime();
genesis 481
genesis 482
genesis 483 SOCKET hSocket;
genesis 484 if (ConnectSocket(addrConnect, hSocket))
genesis 485 {
genesis 486
polarbeard_better... 487 printf(SINF SNET "connected to %s\n", addrConnect.ToString().c_str());
genesis 488
genesis 489
genesis 490 if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
polarbeard_better... 491 printf(SERR SNET "socket fcntl nonblocking setting failed, error %d\n", errno);
genesis 492
genesis 493
genesis 494 CNode* pnode = new CNode(hSocket, addrConnect, false);
genesis 495 if (nTimeout != 0)
genesis 496 pnode->AddRef(nTimeout);
genesis 497 else
genesis 498 pnode->AddRef();
genesis 499 CRITICAL_BLOCK(cs_vNodes)
genesis 500 vNodes.push_back(pnode);
genesis 501
genesis 502 pnode->nTimeConnected = GetTime();
genesis 503 return pnode;
genesis 504 }
genesis 505 else
genesis 506 {
genesis 507 return NULL;
genesis 508 }
genesis 509 }
genesis 510
genesis 511 void CNode::CloseSocketDisconnect()
genesis 512 {
genesis 513 fDisconnect = true;
genesis 514 if (hSocket != INVALID_SOCKET)
genesis 515 {
polarbeard_better... 516 printf(SWAR SNET "disconnecting from 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 {
polarbeard_better... 562 printf(SWAR SNET "local node %s is 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 }
polarbeard_better... 607 printf(SWAR SNET "socket handling thread exiting\n");
genesis 608 }
genesis 609
genesis 610 void ThreadSocketHandler2(void* parg)
genesis 611 {
polarbeard_better... 612 printf(SINF SNET "socket handling thread 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 {
polarbeard_better... 716 printf(SERR SNET "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)
polarbeard_better... 748 printf(SERR SNET "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 {
polarbeard_better... 756 printf(SWAR SNET "connection from %s dropped. (banned)\n", addr.ToString().c_str());
genesis 757 closesocket(hSocket);
genesis 758 }
genesis 759 else
genesis 760 {
polarbeard_better... 761 printf(SINF SNET "accepted connection to %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)
polarbeard_better... 799 printf(SWAR SNET "socket received flood, disconnecting. (%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)
polarbeard_better... 816 printf(SWAR SNET "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)
polarbeard_better... 826 printf(SERR SNET "socket received 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 {
polarbeard_better... 858 printf(SERR SNET "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)
polarbeard_better... 864 printf(SWAR SNET "socket send flood, disconnecting. (%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 {
polarbeard_better... 880 printf(SWAR SNET "socket received no message in first 60 seconds, disconnecting\n");
genesis 881 pnode->fDisconnect = true;
genesis 882 }
genesis 883 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
genesis 884 {
polarbeard_better... 885 printf(SWAR SNET "socket not sending, disconnecting\n");
genesis 886 pnode->fDisconnect = true;
genesis 887 }
genesis 888 else if (GetTime() - pnode->nLastRecv > 90*60)
genesis 889 {
polarbeard_better... 890 printf(SWAR SNET "socket inactivity timeout, disconnecting\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 }
polarbeard_better... 922 printf(SWAR SNET "connection opening thread exiting\n");
genesis 923 }
genesis 924
genesis 925 void ThreadOpenConnections2(void* parg)
genesis 926 {
polarbeard_better... 927 printf(SINF SNET "connection opening thread 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 }
polarbeard_better... 1110 printf(SWAR SNET "message handling thread exiting\n");
genesis 1111 }
genesis 1112
genesis 1113 void ThreadMessageHandler2(void* parg)
genesis 1114 {
polarbeard_better... 1115 printf(SINF SNET "message handling thread starting\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 {
polarbeard_better... 1180 printf(SERR SNET "couldn't open socket for incoming connections, error %d\n", WSAGetLastError());
genesis 1181 return false;
genesis 1182 }
genesis 1183
genesis 1184 #ifdef SO_NOSIGPIPE
genesis 1185
genesis 1186 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
genesis 1187 #endif
genesis 1188
genesis 1189
genesis 1190
genesis 1191 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
genesis 1192
genesis 1193 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
genesis 1194 {
polarbeard_better... 1195 printf(SERR SNET "couldn't set properties on socket for incoming connections, error %d\n", WSAGetLastError());
genesis 1196 return false;
genesis 1197 }
genesis 1198
genesis 1199
genesis 1200
genesis 1201 struct sockaddr_in sockaddr;
genesis 1202 memset(&sockaddr, 0, sizeof(sockaddr));
genesis 1203 sockaddr.sin_family = AF_INET;
genesis 1204 sockaddr.sin_addr.s_addr = INADDR_ANY;
genesis 1205 sockaddr.sin_port = htons(GetListenPort());
genesis 1206 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
genesis 1207 {
genesis 1208 int nErr = WSAGetLastError();
genesis 1209 if (nErr == WSAEADDRINUSE)
polarbeard_better... 1210 printf(SERR SNET "unable to bind to port %d, bitcoind is probably already running\n", ntohs(sockaddr.sin_port));
genesis 1211 else
polarbeard_better... 1212 printf(SERR SNET "unable to bind to port %d, error %d\n", ntohs(sockaddr.sin_port), nErr);
genesis 1213 return false;
genesis 1214 }
polarbeard_better... 1215 printf(SINF SNET "bound to port %d\n", ntohs(sockaddr.sin_port));
genesis 1216
genesis 1217
genesis 1218 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
genesis 1219 {
polarbeard_better... 1220 printf(SERR SNET "listening for incoming connections failed, error %d", WSAGetLastError());
genesis 1221 return false;
genesis 1222 }
genesis 1223
genesis 1224 return true;
genesis 1225 }
genesis 1226
genesis 1227 void StartNode(void* parg)
genesis 1228 {
genesis 1229 if (pnodeLocalHost == NULL)
asciilifeform_dns... 1230 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress("127.0.0.1", 0, nLocalServices));
genesis 1231
genesis 1232
genesis 1233 struct ifaddrs* myaddrs;
genesis 1234 if (getifaddrs(&myaddrs) == 0)
genesis 1235 {
genesis 1236 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
genesis 1237 {
genesis 1238 if (ifa->ifa_addr == NULL) continue;
genesis 1239 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
genesis 1240 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
genesis 1241 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
genesis 1242 char pszIP[100];
genesis 1243 if (ifa->ifa_addr->sa_family == AF_INET)
genesis 1244 {
genesis 1245 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
genesis 1246 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s4->sin_addr), pszIP, sizeof(pszIP)) != NULL)
polarbeard_better... 1247 printf(SINF SNET "ipv4 address %s: %s\n", ifa->ifa_name, pszIP);
genesis 1248
genesis 1249
genesis 1250 CAddress addr(*(unsigned int*)&s4->sin_addr, GetListenPort(), nLocalServices);
genesis 1251 if (addr.IsValid() && addr.GetByte(3) != 127)
genesis 1252 {
genesis 1253 addrLocalHost = addr;
genesis 1254 break;
genesis 1255 }
genesis 1256 }
genesis 1257 else if (ifa->ifa_addr->sa_family == AF_INET6)
genesis 1258 {
genesis 1259 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
genesis 1260 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s6->sin6_addr), pszIP, sizeof(pszIP)) != NULL)
polarbeard_better... 1261 printf(SINF SNET "ipv6 address %s: %s\n", ifa->ifa_name, pszIP);
genesis 1262 }
genesis 1263 }
genesis 1264 freeifaddrs(myaddrs);
genesis 1265 }
bitcoin-asciilife... 1266
polarbeard_better... 1267 printf(SINF SNET "local host address is %s\n", addrLocalHost.ToString().c_str());
genesis 1268
genesis 1269 if (fUseProxy || mapArgs.count("-connect") || fNoListen)
genesis 1270 {
genesis 1271
genesis 1272 addrLocalHost.ip = CAddress("0.0.0.0").ip;
genesis 1273 }
genesis 1274 else
genesis 1275 {
asciilifeform_ver... 1276 addrLocalHost.ip = CAddress(mapArgs["-myip"]).ip;
asciilifeform_ver... 1277 if (!addrLocalHost.IsValid())
asciilifeform_ver... 1278 throw runtime_error(strprintf(_("You must set myip=<ipaddress> on the command line or in the configuration file:\n%s\n"
asciilifeform_ver... 1279 "If the file does not exist, create it with owner-readable-only file permissions."),
asciilifeform_ver... 1280 GetConfigFile().c_str()));
genesis 1281 }
genesis 1282
polarbeard_better... 1283 printf(SINF SNET "local host address is %s\n", addrLocalHost.ToString().c_str());
asciilifeform_ver... 1284
genesis 1285
genesis 1286
genesis 1287
genesis 1288
genesis 1289
genesis 1290 if (!CreateThread(ThreadSocketHandler, NULL))
polarbeard_better... 1291 printf(SERR SNET "can't create socket handling thread\n");
genesis 1292
genesis 1293
genesis 1294 if (!CreateThread(ThreadOpenConnections, NULL))
polarbeard_better... 1295 printf(SERR SNET "can't create connection opening thread\n");
genesis 1296
genesis 1297
genesis 1298 if (!CreateThread(ThreadMessageHandler, NULL))
polarbeard_better... 1299 printf(SERR SNET "can't create message handling thread\n");
genesis 1300
genesis 1301
genesis 1302 GenerateBitcoins(fGenerateBitcoins, pwalletMain);
genesis 1303 }
genesis 1304
genesis 1305 bool StopNode()
genesis 1306 {
polarbeard_better... 1307 printf(SWAR SNET "stopping node\n");
genesis 1308 fShutdown = true;
genesis 1309 nTransactionsUpdated++;
genesis 1310 int64 nStart = GetTime();
genesis 1311 while (vnThreadsRunning[0] > 0 || vnThreadsRunning[1] > 0 || vnThreadsRunning[2] > 0 || vnThreadsRunning[3] > 0 || vnThreadsRunning[4] > 0
genesis 1312 )
genesis 1313 {
genesis 1314 if (GetTime() - nStart > 20)
genesis 1315 break;
genesis 1316 Sleep(20);
genesis 1317 }
polarbeard_better... 1318 if (vnThreadsRunning[0] > 0) printf(SWAR SNET "socket handling thread still running\n");
polarbeard_better... 1319 if (vnThreadsRunning[1] > 0) printf(SWAR SNET "connection opening thread still running\n");
polarbeard_better... 1320 if (vnThreadsRunning[2] > 0) printf(SWAR SNET "message handling thread still running\n");
polarbeard_better... 1321 if (vnThreadsRunning[3] > 0) printf(SWAR SMIN "miner thread still running\n");
polarbeard_better... 1322 if (vnThreadsRunning[4] > 0) printf(SWAR SNET "rpc server thread still running\n");
genesis 1323 while (vnThreadsRunning[2] > 0 || vnThreadsRunning[4] > 0)
genesis 1324 Sleep(20);
genesis 1325 Sleep(50);
genesis 1326
genesis 1327 return true;
genesis 1328 }
genesis 1329
genesis 1330 class CNetCleanup
genesis 1331 {
genesis 1332 public:
genesis 1333 CNetCleanup()
genesis 1334 {
genesis 1335 }
genesis 1336 ~CNetCleanup()
genesis 1337 {
genesis 1338
genesis 1339 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 1340 if (pnode->hSocket != INVALID_SOCKET)
genesis 1341 closesocket(pnode->hSocket);
genesis 1342 if (hListenSocket != INVALID_SOCKET)
genesis 1343 if (closesocket(hListenSocket) == SOCKET_ERROR)
polarbeard_better... 1344 printf(SERR SNET "closing socket failed with error %d\n", WSAGetLastError());
genesis 1345
genesis 1346 }
genesis 1347 }
genesis 1348 instance_of_cnetcleanup;