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
polarbeard_add_ge... 580 void CNode::CopyStats(CNodeStats &stats)
polarbeard_add_ge... 581 {
polarbeard_add_ge... 582 stats.nServices = nServices;
polarbeard_add_ge... 583 stats.nLastSend = nLastSend;
polarbeard_add_ge... 584 stats.nLastRecv = nLastRecv;
polarbeard_add_ge... 585 stats.nTimeConnected = nTimeConnected;
polarbeard_add_ge... 586 stats.addr = addr;
polarbeard_add_ge... 587 stats.nVersion = nVersion;
polarbeard_add_ge... 588 stats.strSubVer = strSubVer;
polarbeard_add_ge... 589 stats.fInbound = fInbound;
polarbeard_add_ge... 590 stats.nReleaseTime = nReleaseTime;
polarbeard_add_ge... 591 stats.nStartingHeight = nStartingHeight;
polarbeard_add_ge... 592 stats.nMisbehavior = nMisbehavior;
polarbeard_add_ge... 593 }
genesis 594
genesis 595 void ThreadSocketHandler(void* parg)
genesis 596 {
genesis 597 IMPLEMENT_RANDOMIZE_STACK(ThreadSocketHandler(parg));
genesis 598 try
genesis 599 {
genesis 600 vnThreadsRunning[0]++;
genesis 601 ThreadSocketHandler2(parg);
genesis 602 vnThreadsRunning[0]--;
genesis 603 }
genesis 604 catch (std::exception& e) {
genesis 605 vnThreadsRunning[0]--;
genesis 606 PrintException(&e, "ThreadSocketHandler()");
genesis 607 } catch (...) {
genesis 608 vnThreadsRunning[0]--;
genesis 609 throw;
genesis 610 }
polarbeard_better... 611 printf(SWAR SNET "socket handling thread exiting\n");
genesis 612 }
genesis 613
genesis 614 void ThreadSocketHandler2(void* parg)
genesis 615 {
polarbeard_better... 616 printf(SINF SNET "socket handling thread started\n");
genesis 617 list<CNode*> vNodesDisconnected;
genesis 618 int nPrevNodeCount = 0;
genesis 619
genesis 620 loop
genesis 621 {
genesis 622
genesis 623
genesis 624
genesis 625 CRITICAL_BLOCK(cs_vNodes)
genesis 626 {
genesis 627
genesis 628 vector<CNode*> vNodesCopy = vNodes;
genesis 629 BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis 630 {
genesis 631 if (pnode->fDisconnect ||
genesis 632 (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
genesis 633 {
genesis 634
genesis 635 vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
genesis 636
genesis 637
genesis 638 pnode->CloseSocketDisconnect();
genesis 639 pnode->Cleanup();
genesis 640
genesis 641
genesis 642 pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
genesis 643 if (pnode->fNetworkNode || pnode->fInbound)
genesis 644 pnode->Release();
genesis 645 vNodesDisconnected.push_back(pnode);
genesis 646 }
genesis 647 }
genesis 648
genesis 649
genesis 650 list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
genesis 651 BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy)
genesis 652 {
genesis 653
genesis 654 if (pnode->GetRefCount() <= 0)
genesis 655 {
genesis 656 bool fDelete = false;
genesis 657 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
genesis 658 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
genesis 659 TRY_CRITICAL_BLOCK(pnode->cs_mapRequests)
genesis 660 TRY_CRITICAL_BLOCK(pnode->cs_inventory)
genesis 661 fDelete = true;
genesis 662 if (fDelete)
genesis 663 {
genesis 664 vNodesDisconnected.remove(pnode);
genesis 665 delete pnode;
genesis 666 }
genesis 667 }
genesis 668 }
genesis 669 }
genesis 670 if (vNodes.size() != nPrevNodeCount)
genesis 671 {
genesis 672 nPrevNodeCount = vNodes.size();
genesis 673 MainFrameRepaint();
genesis 674 }
genesis 675
genesis 676
genesis 677
genesis 678
genesis 679
genesis 680 struct timeval timeout;
genesis 681 timeout.tv_sec = 0;
genesis 682 timeout.tv_usec = 50000;
genesis 683
genesis 684 fd_set fdsetRecv;
genesis 685 fd_set fdsetSend;
genesis 686 fd_set fdsetError;
genesis 687 FD_ZERO(&fdsetRecv);
genesis 688 FD_ZERO(&fdsetSend);
genesis 689 FD_ZERO(&fdsetError);
genesis 690 SOCKET hSocketMax = 0;
genesis 691
genesis 692 if(hListenSocket != INVALID_SOCKET)
genesis 693 FD_SET(hListenSocket, &fdsetRecv);
genesis 694 hSocketMax = max(hSocketMax, hListenSocket);
genesis 695 CRITICAL_BLOCK(cs_vNodes)
genesis 696 {
genesis 697 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 698 {
genesis 699 if (pnode->hSocket == INVALID_SOCKET)
genesis 700 continue;
genesis 701 FD_SET(pnode->hSocket, &fdsetRecv);
genesis 702 FD_SET(pnode->hSocket, &fdsetError);
genesis 703 hSocketMax = max(hSocketMax, pnode->hSocket);
genesis 704 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
genesis 705 if (!pnode->vSend.empty())
genesis 706 FD_SET(pnode->hSocket, &fdsetSend);
genesis 707 }
genesis 708 }
genesis 709
genesis 710 vnThreadsRunning[0]--;
genesis 711 int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
genesis 712 vnThreadsRunning[0]++;
genesis 713 if (fShutdown)
genesis 714 return;
genesis 715 if (nSelect == SOCKET_ERROR)
genesis 716 {
genesis 717 int nErr = WSAGetLastError();
genesis 718 if (hSocketMax > -1)
genesis 719 {
polarbeard_better... 720 printf(SERR SNET "socket select error %d\n", nErr);
genesis 721 for (int i = 0; i <= hSocketMax; i++)
genesis 722 FD_SET(i, &fdsetRecv);
genesis 723 }
genesis 724 FD_ZERO(&fdsetSend);
genesis 725 FD_ZERO(&fdsetError);
genesis 726 Sleep(timeout.tv_usec/1000);
genesis 727 }
genesis 728
genesis 729
genesis 730
genesis 731
genesis 732
genesis 733 if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
genesis 734 {
genesis 735 struct sockaddr_in sockaddr;
genesis 736 socklen_t len = sizeof(sockaddr);
genesis 737 SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
genesis 738 CAddress addr;
genesis 739 int nInbound = 0;
genesis 740
genesis 741 if (hSocket != INVALID_SOCKET)
genesis 742 addr = CAddress(sockaddr);
genesis 743
genesis 744 CRITICAL_BLOCK(cs_vNodes)
genesis 745 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 746 if (pnode->fInbound)
genesis 747 nInbound++;
genesis 748
genesis 749 if (hSocket == INVALID_SOCKET)
genesis 750 {
genesis 751 if (WSAGetLastError() != WSAEWOULDBLOCK)
polarbeard_better... 752 printf(SERR SNET "socket error accept failed: %d\n", WSAGetLastError());
genesis 753 }
genesis 754 else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
genesis 755 {
genesis 756 closesocket(hSocket);
genesis 757 }
genesis 758 else if (CNode::IsBanned(addr.ip))
genesis 759 {
polarbeard_better... 760 printf(SWAR SNET "connection from %s dropped. (banned)\n", addr.ToString().c_str());
genesis 761 closesocket(hSocket);
genesis 762 }
genesis 763 else
genesis 764 {
polarbeard_better... 765 printf(SINF SNET "accepted connection to %s\n", addr.ToString().c_str());
genesis 766 CNode* pnode = new CNode(hSocket, addr, true);
genesis 767 pnode->AddRef();
genesis 768 CRITICAL_BLOCK(cs_vNodes)
genesis 769 vNodes.push_back(pnode);
genesis 770 }
genesis 771 }
genesis 772
genesis 773
genesis 774
genesis 775
genesis 776
genesis 777 vector<CNode*> vNodesCopy;
genesis 778 CRITICAL_BLOCK(cs_vNodes)
genesis 779 {
genesis 780 vNodesCopy = vNodes;
genesis 781 BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis 782 pnode->AddRef();
genesis 783 }
genesis 784 BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis 785 {
genesis 786 if (fShutdown)
genesis 787 return;
genesis 788
genesis 789
genesis 790
genesis 791
genesis 792 if (pnode->hSocket == INVALID_SOCKET)
genesis 793 continue;
genesis 794 if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
genesis 795 {
genesis 796 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
genesis 797 {
genesis 798 CDataStream& vRecv = pnode->vRecv;
genesis 799 unsigned int nPos = vRecv.size();
genesis 800
genesis 801 if (nPos > ReceiveBufferSize()) {
genesis 802 if (!pnode->fDisconnect)
polarbeard_better... 803 printf(SWAR SNET "socket received flood, disconnecting. (%d bytes)\n", vRecv.size());
genesis 804 pnode->CloseSocketDisconnect();
genesis 805 }
genesis 806 else {
genesis 807
genesis 808 char pchBuf[0x10000];
genesis 809 int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
genesis 810 if (nBytes > 0)
genesis 811 {
genesis 812 vRecv.resize(nPos + nBytes);
genesis 813 memcpy(&vRecv[nPos], pchBuf, nBytes);
genesis 814 pnode->nLastRecv = GetTime();
genesis 815 }
genesis 816 else if (nBytes == 0)
genesis 817 {
genesis 818
genesis 819 if (!pnode->fDisconnect)
polarbeard_better... 820 printf(SWAR SNET "socket closed\n");
genesis 821 pnode->CloseSocketDisconnect();
genesis 822 }
genesis 823 else if (nBytes < 0)
genesis 824 {
genesis 825
genesis 826 int nErr = WSAGetLastError();
genesis 827 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
genesis 828 {
genesis 829 if (!pnode->fDisconnect)
polarbeard_better... 830 printf(SERR SNET "socket received error %d\n", nErr);
genesis 831 pnode->CloseSocketDisconnect();
genesis 832 }
genesis 833 }
genesis 834 }
genesis 835 }
genesis 836 }
genesis 837
genesis 838
genesis 839
genesis 840
genesis 841 if (pnode->hSocket == INVALID_SOCKET)
genesis 842 continue;
genesis 843 if (FD_ISSET(pnode->hSocket, &fdsetSend))
genesis 844 {
genesis 845 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
genesis 846 {
genesis 847 CDataStream& vSend = pnode->vSend;
genesis 848 if (!vSend.empty())
genesis 849 {
genesis 850 int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
genesis 851 if (nBytes > 0)
genesis 852 {
genesis 853 vSend.erase(vSend.begin(), vSend.begin() + nBytes);
genesis 854 pnode->nLastSend = GetTime();
genesis 855 }
genesis 856 else if (nBytes < 0)
genesis 857 {
genesis 858
genesis 859 int nErr = WSAGetLastError();
genesis 860 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
genesis 861 {
polarbeard_better... 862 printf(SERR SNET "socket send error %d\n", nErr);
genesis 863 pnode->CloseSocketDisconnect();
genesis 864 }
genesis 865 }
genesis 866 if (vSend.size() > SendBufferSize()) {
genesis 867 if (!pnode->fDisconnect)
polarbeard_better... 868 printf(SWAR SNET "socket send flood, disconnecting. (%d bytes)\n", vSend.size());
genesis 869 pnode->CloseSocketDisconnect();
genesis 870 }
genesis 871 }
genesis 872 }
genesis 873 }
genesis 874
genesis 875
genesis 876
genesis 877
genesis 878 if (pnode->vSend.empty())
genesis 879 pnode->nLastSendEmpty = GetTime();
genesis 880 if (GetTime() - pnode->nTimeConnected > 60)
genesis 881 {
genesis 882 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
genesis 883 {
polarbeard_better... 884 printf(SWAR SNET "socket received no message in first 60 seconds, disconnecting\n");
genesis 885 pnode->fDisconnect = true;
genesis 886 }
genesis 887 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
genesis 888 {
polarbeard_better... 889 printf(SWAR SNET "socket not sending, disconnecting\n");
genesis 890 pnode->fDisconnect = true;
genesis 891 }
genesis 892 else if (GetTime() - pnode->nLastRecv > 90*60)
genesis 893 {
polarbeard_better... 894 printf(SWAR SNET "socket inactivity timeout, disconnecting\n");
genesis 895 pnode->fDisconnect = true;
genesis 896 }
genesis 897 }
genesis 898 }
genesis 899 CRITICAL_BLOCK(cs_vNodes)
genesis 900 {
genesis 901 BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis 902 pnode->Release();
genesis 903 }
genesis 904
genesis 905 Sleep(10);
genesis 906 }
genesis 907 }
genesis 908
genesis 909
genesis 910 void ThreadOpenConnections(void* parg)
genesis 911 {
genesis 912 IMPLEMENT_RANDOMIZE_STACK(ThreadOpenConnections(parg));
genesis 913 try
genesis 914 {
genesis 915 vnThreadsRunning[1]++;
genesis 916 ThreadOpenConnections2(parg);
genesis 917 vnThreadsRunning[1]--;
genesis 918 }
genesis 919 catch (std::exception& e) {
genesis 920 vnThreadsRunning[1]--;
genesis 921 PrintException(&e, "ThreadOpenConnections()");
genesis 922 } catch (...) {
genesis 923 vnThreadsRunning[1]--;
genesis 924 PrintException(NULL, "ThreadOpenConnections()");
genesis 925 }
polarbeard_better... 926 printf(SWAR SNET "connection opening thread exiting\n");
genesis 927 }
genesis 928
genesis 929 void ThreadOpenConnections2(void* parg)
genesis 930 {
polarbeard_better... 931 printf(SINF SNET "connection opening thread started\n");
genesis 932
genesis 933
genesis 934 if (mapArgs.count("-connect"))
genesis 935 {
genesis 936 for (int64 nLoop = 0;; nLoop++)
genesis 937 {
genesis 938 BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
genesis 939 {
asciilifeform_dns... 940 CAddress addr(strAddr);
genesis 941 if (addr.IsValid())
genesis 942 OpenNetworkConnection(addr);
genesis 943 for (int i = 0; i < 10 && i < nLoop; i++)
genesis 944 {
genesis 945 Sleep(500);
genesis 946 if (fShutdown)
genesis 947 return;
genesis 948 }
genesis 949 }
genesis 950 }
genesis 951 }
genesis 952
genesis 953
genesis 954 if (mapArgs.count("-addnode"))
genesis 955 {
genesis 956 BOOST_FOREACH(string strAddr, mapMultiArgs["-addnode"])
genesis 957 {
asciilifeform_dns... 958 CAddress addr(strAddr);
genesis 959 if (addr.IsValid())
genesis 960 {
genesis 961 OpenNetworkConnection(addr);
genesis 962 Sleep(500);
genesis 963 if (fShutdown)
genesis 964 return;
genesis 965 }
genesis 966 }
genesis 967 }
genesis 968
genesis 969
genesis 970 int64 nStart = GetTime();
genesis 971 loop
genesis 972 {
genesis 973 vnThreadsRunning[1]--;
genesis 974 Sleep(500);
genesis 975 vnThreadsRunning[1]++;
genesis 976 if (fShutdown)
genesis 977 return;
genesis 978
genesis 979
genesis 980 loop
genesis 981 {
genesis 982 int nOutbound = 0;
genesis 983 CRITICAL_BLOCK(cs_vNodes)
genesis 984 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 985 if (!pnode->fInbound)
genesis 986 nOutbound++;
genesis 987 int nMaxOutboundConnections = MAX_OUTBOUND_CONNECTIONS;
genesis 988 nMaxOutboundConnections = min(nMaxOutboundConnections, (int)GetArg("-maxconnections", 125));
genesis 989 if (nOutbound < nMaxOutboundConnections)
genesis 990 break;
genesis 991 vnThreadsRunning[1]--;
genesis 992 Sleep(2000);
genesis 993 vnThreadsRunning[1]++;
genesis 994 if (fShutdown)
genesis 995 return;
genesis 996 }
genesis 997
genesis 998
genesis 999
genesis 1000
genesis 1001 CAddress addrConnect;
genesis 1002 int64 nBest = INT64_MIN;
genesis 1003
genesis 1004
genesis 1005
genesis 1006 set<unsigned int> setConnected;
genesis 1007 CRITICAL_BLOCK(cs_vNodes)
genesis 1008 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 1009 setConnected.insert(pnode->addr.ip & 0x0000ffff);
genesis 1010
genesis 1011 int64 nANow = GetAdjustedTime();
genesis 1012
genesis 1013 CRITICAL_BLOCK(cs_mapAddresses)
genesis 1014 {
genesis 1015 BOOST_FOREACH(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
genesis 1016 {
genesis 1017 const CAddress& addr = item.second;
genesis 1018 if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.ip & 0x0000ffff))
genesis 1019 continue;
genesis 1020 int64 nSinceLastSeen = nANow - addr.nTime;
genesis 1021 int64 nSinceLastTry = nANow - addr.nLastTry;
genesis 1022
genesis 1023
genesis 1024 int64 nRandomizer = (uint64)(nStart * 4951 + addr.nLastTry * 9567851 + addr.ip * 7789) % (2 * 60 * 60);
genesis 1025 if (addr.port != htons(GetDefaultPort()))
genesis 1026 nRandomizer += 2 * 60 * 60;
genesis 1027
genesis 1028
genesis 1029
genesis 1030
genesis 1031
genesis 1032
genesis 1033
genesis 1034
genesis 1035
genesis 1036
genesis 1037
genesis 1038 int64 nDelay = (int64)(3600.0 * sqrt(fabs((double)nSinceLastSeen) / 3600.0) + nRandomizer);
genesis 1039
genesis 1040
genesis 1041 if (nSinceLastSeen < 60 * 60)
genesis 1042 nDelay = 10 * 60;
genesis 1043
genesis 1044
genesis 1045 if (nSinceLastTry < nDelay)
genesis 1046 continue;
genesis 1047
genesis 1048
genesis 1049 if (vNodes.size() >= 8 && nSinceLastSeen > 24 * 60 * 60)
genesis 1050 continue;
genesis 1051
genesis 1052
genesis 1053
genesis 1054 int64 nScore = min(nSinceLastTry, (int64)24 * 60 * 60) - nSinceLastSeen - nRandomizer;
genesis 1055 if (nScore > nBest)
genesis 1056 {
genesis 1057 nBest = nScore;
genesis 1058 addrConnect = addr;
genesis 1059 }
genesis 1060 }
genesis 1061 }
genesis 1062
genesis 1063 if (addrConnect.IsValid())
genesis 1064 OpenNetworkConnection(addrConnect);
genesis 1065 }
genesis 1066 }
genesis 1067
genesis 1068 bool OpenNetworkConnection(const CAddress& addrConnect)
genesis 1069 {
genesis 1070
genesis 1071
genesis 1072
genesis 1073 if (fShutdown)
genesis 1074 return false;
genesis 1075 if (addrConnect.ip == addrLocalHost.ip || !addrConnect.IsIPv4() ||
genesis 1076 FindNode(addrConnect.ip) || CNode::IsBanned(addrConnect.ip))
genesis 1077 return false;
genesis 1078
genesis 1079 vnThreadsRunning[1]--;
genesis 1080 CNode* pnode = ConnectNode(addrConnect);
genesis 1081 vnThreadsRunning[1]++;
genesis 1082 if (fShutdown)
genesis 1083 return false;
genesis 1084 if (!pnode)
genesis 1085 return false;
genesis 1086 pnode->fNetworkNode = true;
genesis 1087
genesis 1088 return true;
genesis 1089 }
genesis 1090
genesis 1091
genesis 1092
genesis 1093
genesis 1094
genesis 1095
genesis 1096
genesis 1097
genesis 1098 void ThreadMessageHandler(void* parg)
genesis 1099 {
genesis 1100 IMPLEMENT_RANDOMIZE_STACK(ThreadMessageHandler(parg));
genesis 1101 try
genesis 1102 {
genesis 1103 vnThreadsRunning[2]++;
genesis 1104 ThreadMessageHandler2(parg);
genesis 1105 vnThreadsRunning[2]--;
genesis 1106 }
genesis 1107 catch (std::exception& e) {
genesis 1108 vnThreadsRunning[2]--;
genesis 1109 PrintException(&e, "ThreadMessageHandler()");
genesis 1110 } catch (...) {
genesis 1111 vnThreadsRunning[2]--;
genesis 1112 PrintException(NULL, "ThreadMessageHandler()");
genesis 1113 }
polarbeard_better... 1114 printf(SWAR SNET "message handling thread exiting\n");
genesis 1115 }
genesis 1116
genesis 1117 void ThreadMessageHandler2(void* parg)
genesis 1118 {
polarbeard_better... 1119 printf(SINF SNET "message handling thread starting\n");
genesis 1120 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
genesis 1121 while (!fShutdown)
genesis 1122 {
genesis 1123 vector<CNode*> vNodesCopy;
genesis 1124 CRITICAL_BLOCK(cs_vNodes)
genesis 1125 {
genesis 1126 vNodesCopy = vNodes;
genesis 1127 BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis 1128 pnode->AddRef();
genesis 1129 }
genesis 1130
genesis 1131
genesis 1132 CNode* pnodeTrickle = NULL;
genesis 1133 if (!vNodesCopy.empty())
genesis 1134 pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
genesis 1135 BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis 1136 {
genesis 1137
genesis 1138 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
genesis 1139 ProcessMessages(pnode);
genesis 1140 if (fShutdown)
genesis 1141 return;
genesis 1142
genesis 1143
genesis 1144 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
genesis 1145 SendMessages(pnode, pnode == pnodeTrickle);
genesis 1146 if (fShutdown)
genesis 1147 return;
genesis 1148 }
genesis 1149
genesis 1150 CRITICAL_BLOCK(cs_vNodes)
genesis 1151 {
genesis 1152 BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis 1153 pnode->Release();
genesis 1154 }
genesis 1155
genesis 1156
genesis 1157
genesis 1158
genesis 1159 vnThreadsRunning[2]--;
genesis 1160 Sleep(100);
genesis 1161 if (fRequestShutdown)
genesis 1162 Shutdown(NULL);
genesis 1163 vnThreadsRunning[2]++;
genesis 1164 if (fShutdown)
genesis 1165 return;
genesis 1166 }
genesis 1167 }
genesis 1168
genesis 1169
genesis 1170
genesis 1171
genesis 1172
genesis 1173
genesis 1174 bool BindListenPort(string& strError)
genesis 1175 {
genesis 1176 strError = "";
genesis 1177 int nOne = 1;
genesis 1178 addrLocalHost.port = htons(GetListenPort());
genesis 1179
genesis 1180
genesis 1181 hListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
genesis 1182 if (hListenSocket == INVALID_SOCKET)
genesis 1183 {
polarbeard_better... 1184 printf(SERR SNET "couldn't open socket for incoming connections, error %d\n", WSAGetLastError());
genesis 1185 return false;
genesis 1186 }
genesis 1187
genesis 1188 #ifdef SO_NOSIGPIPE
genesis 1189
genesis 1190 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
genesis 1191 #endif
genesis 1192
genesis 1193
genesis 1194
genesis 1195 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
genesis 1196
genesis 1197 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
genesis 1198 {
polarbeard_better... 1199 printf(SERR SNET "couldn't set properties on socket for incoming connections, error %d\n", WSAGetLastError());
genesis 1200 return false;
genesis 1201 }
genesis 1202
genesis 1203
genesis 1204
genesis 1205 struct sockaddr_in sockaddr;
genesis 1206 memset(&sockaddr, 0, sizeof(sockaddr));
genesis 1207 sockaddr.sin_family = AF_INET;
genesis 1208 sockaddr.sin_addr.s_addr = INADDR_ANY;
genesis 1209 sockaddr.sin_port = htons(GetListenPort());
genesis 1210 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
genesis 1211 {
genesis 1212 int nErr = WSAGetLastError();
genesis 1213 if (nErr == WSAEADDRINUSE)
polarbeard_better... 1214 printf(SERR SNET "unable to bind to port %d, bitcoind is probably already running\n", ntohs(sockaddr.sin_port));
genesis 1215 else
polarbeard_better... 1216 printf(SERR SNET "unable to bind to port %d, error %d\n", ntohs(sockaddr.sin_port), nErr);
genesis 1217 return false;
genesis 1218 }
polarbeard_better... 1219 printf(SINF SNET "bound to port %d\n", ntohs(sockaddr.sin_port));
genesis 1220
genesis 1221
genesis 1222 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
genesis 1223 {
polarbeard_better... 1224 printf(SERR SNET "listening for incoming connections failed, error %d", WSAGetLastError());
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)
polarbeard_better... 1251 printf(SINF SNET "ipv4 address %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)
polarbeard_better... 1265 printf(SINF SNET "ipv6 address %s: %s\n", ifa->ifa_name, pszIP);
genesis 1266 }
genesis 1267 }
genesis 1268 freeifaddrs(myaddrs);
genesis 1269 }
bitcoin-asciilife... 1270
polarbeard_better... 1271 printf(SINF SNET "local host address is %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
polarbeard_better... 1287 printf(SINF SNET "local host address is %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))
polarbeard_better... 1295 printf(SERR SNET "can't create socket handling thread\n");
genesis 1296
genesis 1297
genesis 1298 if (!CreateThread(ThreadOpenConnections, NULL))
polarbeard_better... 1299 printf(SERR SNET "can't create connection opening thread\n");
genesis 1300
genesis 1301
genesis 1302 if (!CreateThread(ThreadMessageHandler, NULL))
polarbeard_better... 1303 printf(SERR SNET "can't create message handling thread\n");
genesis 1304
genesis 1305
genesis 1306 GenerateBitcoins(fGenerateBitcoins, pwalletMain);
genesis 1307 }
genesis 1308
genesis 1309 bool StopNode()
genesis 1310 {
polarbeard_better... 1311 printf(SWAR SNET "stopping node\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 }
polarbeard_better... 1322 if (vnThreadsRunning[0] > 0) printf(SWAR SNET "socket handling thread still running\n");
polarbeard_better... 1323 if (vnThreadsRunning[1] > 0) printf(SWAR SNET "connection opening thread still running\n");
polarbeard_better... 1324 if (vnThreadsRunning[2] > 0) printf(SWAR SNET "message handling thread still running\n");
polarbeard_better... 1325 if (vnThreadsRunning[3] > 0) printf(SWAR SMIN "miner thread still running\n");
polarbeard_better... 1326 if (vnThreadsRunning[4] > 0) printf(SWAR SNET "rpc server thread 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)
polarbeard_better... 1348 printf(SERR SNET "closing socket failed with error %d\n", WSAGetLastError());
genesis 1349
genesis 1350 }
genesis 1351 }
genesis 1352 instance_of_cnetcleanup;