]> Git Repo - VerusCoin.git/blame - src/net.cpp
Merge pull request #844 from sipa/shutdownfix
[VerusCoin.git] / src / net.cpp
CommitLineData
0a61b0df 1// Copyright (c) 2009-2010 Satoshi Nakamoto
88216419 2// Copyright (c) 2009-2012 The Bitcoin developers
0a61b0df 3// Distributed under the MIT/X11 software license, see the accompanying
4// file license.txt or http://www.opensource.org/licenses/mit-license.php.
5
6#include "headers.h"
f23f9a03 7#include "irc.h"
1512d5ce 8#include "db.h"
40c2614e 9#include "net.h"
edd309e5 10#include "init.h"
fdd7d047 11#include "strlcpy.h"
0a61b0df 12
6853e627 13#ifdef WIN32
013df1cc
MC
14#include <string.h>
15#endif
16
8bb5edc1
MC
17#ifdef USE_UPNP
18#include <miniupnpc/miniwget.h>
19#include <miniupnpc/miniupnpc.h>
20#include <miniupnpc/upnpcommands.h>
21#include <miniupnpc/upnperrors.h>
22#endif
23
223b6f1b
WL
24using namespace std;
25using namespace boost;
26
0a61b0df 27static const int MAX_OUTBOUND_CONNECTIONS = 8;
28
29void ThreadMessageHandler2(void* parg);
30void ThreadSocketHandler2(void* parg);
31void ThreadOpenConnections2(void* parg);
b24e6e4d 32void ThreadOpenAddedConnections2(void* parg);
8bb5edc1
MC
33#ifdef USE_UPNP
34void ThreadMapPort2(void* parg);
35#endif
2bc6cece 36void ThreadDNSAddressSeed2(void* parg);
0a61b0df 37bool OpenNetworkConnection(const CAddress& addrConnect);
38
39
40
41
42
43//
44// Global state variables
45//
46bool fClient = false;
a6a5bb7c 47bool fAllowDNS = false;
bde280b9 48uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK);
67a42f92 49CAddress addrLocalHost(CService("0.0.0.0", 0), nLocalServices);
99860de3 50static CNode* pnodeLocalHost = NULL;
bde280b9 51uint64 nLocalHostNonce = 0;
0a61b0df 52array<int, 10> vnThreadsRunning;
99860de3 53static SOCKET hListenSocket = INVALID_SOCKET;
0a61b0df 54
55vector<CNode*> vNodes;
56CCriticalSection cs_vNodes;
57map<vector<unsigned char>, CAddress> mapAddresses;
58CCriticalSection cs_mapAddresses;
59map<CInv, CDataStream> mapRelay;
bde280b9 60deque<pair<int64, CInv> > vRelayExpiration;
0a61b0df 61CCriticalSection cs_mapRelay;
bde280b9 62map<CInv, int64> mapAlreadyAskedFor;
0a61b0df 63
0a61b0df 64
b24e6e4d
MC
65set<CNetAddr> setservAddNodeAddresses;
66CCriticalSection cs_setservAddNodeAddresses;
67
0a61b0df 68
69
70
00bcfe0b
GA
71unsigned short GetListenPort()
72{
73 return (unsigned short)(GetArg("-port", GetDefaultPort()));
74}
0a61b0df 75
76void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd)
77{
78 // Filter out duplicate requests
79 if (pindexBegin == pindexLastGetBlocksBegin && hashEnd == hashLastGetBlocksEnd)
80 return;
81 pindexLastGetBlocksBegin = pindexBegin;
82 hashLastGetBlocksEnd = hashEnd;
83
84 PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd);
85}
86
87
88
89
90
67a42f92 91bool GetMyExternalIP2(const CService& addrConnect, const char* pszGet, const char* pszKeyword, CNetAddr& ipRet)
0a61b0df 92{
93 SOCKET hSocket;
94 if (!ConnectSocket(addrConnect, hSocket))
95 return error("GetMyExternalIP() : connection to %s failed", addrConnect.ToString().c_str());
96
97 send(hSocket, pszGet, strlen(pszGet), MSG_NOSIGNAL);
98
99 string strLine;
100 while (RecvLine(hSocket, strLine))
101 {
222e3de4 102 if (strLine.empty()) // HTTP response is separated from headers by blank line
0a61b0df 103 {
104 loop
105 {
106 if (!RecvLine(hSocket, strLine))
107 {
108 closesocket(hSocket);
109 return false;
110 }
222e3de4 111 if (pszKeyword == NULL)
112 break;
0a61b0df 113 if (strLine.find(pszKeyword) != -1)
114 {
115 strLine = strLine.substr(strLine.find(pszKeyword) + strlen(pszKeyword));
116 break;
117 }
118 }
119 closesocket(hSocket);
c891967b 120 if (strLine.find("<") != -1)
0a61b0df 121 strLine = strLine.substr(0, strLine.find("<"));
122 strLine = strLine.substr(strspn(strLine.c_str(), " \t\n\r"));
123 while (strLine.size() > 0 && isspace(strLine[strLine.size()-1]))
124 strLine.resize(strLine.size()-1);
67a42f92 125 CService addr(strLine,0,true);
0a61b0df 126 printf("GetMyExternalIP() received [%s] %s\n", strLine.c_str(), addr.ToString().c_str());
67a42f92 127 if (!addr.IsValid() || !addr.IsRoutable())
0a61b0df 128 return false;
67a42f92 129 ipRet.SetIP(addr);
0a61b0df 130 return true;
131 }
132 }
133 closesocket(hSocket);
134 return error("GetMyExternalIP() : connection closed");
135}
136
629e37dd 137// We now get our external IP from the IRC server first and only use this as a backup
67a42f92 138bool GetMyExternalIP(CNetAddr& ipRet)
0a61b0df 139{
c981d768 140 CService addrConnect;
0a61b0df 141 const char* pszGet;
142 const char* pszKeyword;
143
5d1b8f17 144 if (fNoListen||fUseProxy)
0a61b0df 145 return false;
146
147 for (int nLookup = 0; nLookup <= 1; nLookup++)
148 for (int nHost = 1; nHost <= 2; nHost++)
149 {
629e37dd 150 // We should be phasing out our use of sites like these. If we need
151 // replacements, we should ask for volunteers to put this simple
152 // php file on their webserver that prints the client IP:
153 // <?php echo $_SERVER["REMOTE_ADDR"]; ?>
0a61b0df 154 if (nHost == 1)
155 {
c981d768 156 addrConnect = CService("91.198.22.70",80); // checkip.dyndns.org
0a61b0df 157
158 if (nLookup == 1)
159 {
67a42f92 160 CService addrIP("checkip.dyndns.org", 80, true);
a6a5bb7c
PW
161 if (addrIP.IsValid())
162 addrConnect = addrIP;
0a61b0df 163 }
164
683bcb91 165 pszGet = "GET / HTTP/1.1\r\n"
166 "Host: checkip.dyndns.org\r\n"
167 "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
0a61b0df 168 "Connection: close\r\n"
169 "\r\n";
170
683bcb91 171 pszKeyword = "Address:";
0a61b0df 172 }
173 else if (nHost == 2)
174 {
c981d768 175 addrConnect = CService("74.208.43.192", 80); // www.showmyip.com
0a61b0df 176
177 if (nLookup == 1)
178 {
67a42f92 179 CService addrIP("www.showmyip.com", 80, true);
a6a5bb7c
PW
180 if (addrIP.IsValid())
181 addrConnect = addrIP;
0a61b0df 182 }
183
683bcb91 184 pszGet = "GET /simple/ HTTP/1.1\r\n"
185 "Host: www.showmyip.com\r\n"
0a61b0df 186 "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
187 "Connection: close\r\n"
188 "\r\n";
189
683bcb91 190 pszKeyword = NULL; // Returns just IP address
0a61b0df 191 }
192
193 if (GetMyExternalIP2(addrConnect, pszGet, pszKeyword, ipRet))
194 return true;
195 }
196
197 return false;
198}
199
629e37dd 200void ThreadGetMyExternalIP(void* parg)
201{
202 // Wait for IRC to get it first
9d952d17 203 if (GetBoolArg("-irc", false))
629e37dd 204 {
205 for (int i = 0; i < 2 * 60; i++)
206 {
207 Sleep(1000);
208 if (fGotExternalIP || fShutdown)
209 return;
210 }
211 }
212
213 // Fallback in case IRC fails to get it
67a42f92 214 if (GetMyExternalIP(addrLocalHost))
629e37dd 215 {
216 printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
217 if (addrLocalHost.IsRoutable())
218 {
219 // If we already connected to a few before we had our IP, go back and addr them.
220 // setAddrKnown automatically filters any duplicate sends.
221 CAddress addr(addrLocalHost);
222 addr.nTime = GetAdjustedTime();
223 CRITICAL_BLOCK(cs_vNodes)
223b6f1b 224 BOOST_FOREACH(CNode* pnode, vNodes)
629e37dd 225 pnode->PushAddress(addr);
226 }
227 }
228}
229
0a61b0df 230
231
232
233
bde280b9 234bool AddAddress(CAddress addr, int64 nTimePenalty, CAddrDB *pAddrDB)
0a61b0df 235{
236 if (!addr.IsRoutable())
237 return false;
67a42f92 238 if ((CService)addr == (CService)addrLocalHost)
0a61b0df 239 return false;
bde280b9 240 addr.nTime = max((int64)0, (int64)addr.nTime - nTimePenalty);
94066965
GA
241 bool fUpdated = false;
242 bool fNew = false;
243 CAddress addrFound = addr;
244
0a61b0df 245 CRITICAL_BLOCK(cs_mapAddresses)
246 {
247 map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
248 if (it == mapAddresses.end())
249 {
250 // New address
a6a5bb7c 251 printf("AddAddress(%s)\n", addr.ToString().c_str());
0a61b0df 252 mapAddresses.insert(make_pair(addr.GetKey(), addr));
94066965
GA
253 fUpdated = true;
254 fNew = true;
0a61b0df 255 }
256 else
257 {
94066965 258 addrFound = (*it).second;
0a61b0df 259 if ((addrFound.nServices | addr.nServices) != addrFound.nServices)
260 {
261 // Services have been added
262 addrFound.nServices |= addr.nServices;
263 fUpdated = true;
264 }
265 bool fCurrentlyOnline = (GetAdjustedTime() - addr.nTime < 24 * 60 * 60);
bde280b9 266 int64 nUpdateInterval = (fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60);
0a61b0df 267 if (addrFound.nTime < addr.nTime - nUpdateInterval)
268 {
269 // Periodically update most recently seen time
270 addrFound.nTime = addr.nTime;
271 fUpdated = true;
272 }
0a61b0df 273 }
274 }
94066965
GA
275 // There is a nasty deadlock bug if this is done inside the cs_mapAddresses
276 // CRITICAL_BLOCK:
277 // Thread 1: begin db transaction (locks inside-db-mutex)
278 // then AddAddress (locks cs_mapAddresses)
279 // Thread 2: AddAddress (locks cs_mapAddresses)
280 // ... then db operation hangs waiting for inside-db-mutex
281 if (fUpdated)
282 {
283 if (pAddrDB)
284 pAddrDB->WriteAddress(addrFound);
285 else
286 CAddrDB().WriteAddress(addrFound);
287 }
288 return fNew;
0a61b0df 289}
290
67a42f92 291void AddressCurrentlyConnected(const CService& addr)
0a61b0df 292{
a75d7066
PW
293 CAddress *paddrFound = NULL;
294
0a61b0df 295 CRITICAL_BLOCK(cs_mapAddresses)
296 {
297 // Only if it's been published already
298 map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
299 if (it != mapAddresses.end())
a75d7066
PW
300 paddrFound = &(*it).second;
301 }
302
303 if (paddrFound)
304 {
305 int64 nUpdateInterval = 20 * 60;
306 if (paddrFound->nTime < GetAdjustedTime() - nUpdateInterval)
0a61b0df 307 {
a75d7066
PW
308 // Periodically update most recently seen time
309 paddrFound->nTime = GetAdjustedTime();
310 CAddrDB addrdb;
311 addrdb.WriteAddress(*paddrFound);
0a61b0df 312 }
313 }
314}
315
316
317
318
319
320void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1)
321{
322 // If the dialog might get closed before the reply comes back,
323 // call this in the destructor so it doesn't get called after it's deleted.
324 CRITICAL_BLOCK(cs_vNodes)
325 {
223b6f1b 326 BOOST_FOREACH(CNode* pnode, vNodes)
0a61b0df 327 {
328 CRITICAL_BLOCK(pnode->cs_mapRequests)
329 {
330 for (map<uint256, CRequestTracker>::iterator mi = pnode->mapRequests.begin(); mi != pnode->mapRequests.end();)
331 {
332 CRequestTracker& tracker = (*mi).second;
333 if (tracker.fn == fn && tracker.param1 == param1)
334 pnode->mapRequests.erase(mi++);
335 else
336 mi++;
337 }
338 }
339 }
340 }
341}
342
343
344
345
346
347
348
349//
350// Subscription methods for the broadcast and subscription system.
351// Channel numbers are message numbers, i.e. MSG_TABLE and MSG_PRODUCT.
352//
353// The subscription system uses a meet-in-the-middle strategy.
354// With 100,000 nodes, if senders broadcast to 1000 random nodes and receivers
355// subscribe to 1000 random nodes, 99.995% (1 - 0.99^1000) of messages will get through.
356//
357
358bool AnySubscribed(unsigned int nChannel)
359{
360 if (pnodeLocalHost->IsSubscribed(nChannel))
361 return true;
362 CRITICAL_BLOCK(cs_vNodes)
223b6f1b 363 BOOST_FOREACH(CNode* pnode, vNodes)
0a61b0df 364 if (pnode->IsSubscribed(nChannel))
365 return true;
366 return false;
367}
368
369bool CNode::IsSubscribed(unsigned int nChannel)
370{
371 if (nChannel >= vfSubscribe.size())
372 return false;
373 return vfSubscribe[nChannel];
374}
375
376void CNode::Subscribe(unsigned int nChannel, unsigned int nHops)
377{
378 if (nChannel >= vfSubscribe.size())
379 return;
380
381 if (!AnySubscribed(nChannel))
382 {
383 // Relay subscribe
384 CRITICAL_BLOCK(cs_vNodes)
223b6f1b 385 BOOST_FOREACH(CNode* pnode, vNodes)
0a61b0df 386 if (pnode != this)
387 pnode->PushMessage("subscribe", nChannel, nHops);
388 }
389
390 vfSubscribe[nChannel] = true;
391}
392
393void CNode::CancelSubscribe(unsigned int nChannel)
394{
395 if (nChannel >= vfSubscribe.size())
396 return;
397
398 // Prevent from relaying cancel if wasn't subscribed
399 if (!vfSubscribe[nChannel])
400 return;
401 vfSubscribe[nChannel] = false;
402
403 if (!AnySubscribed(nChannel))
404 {
405 // Relay subscription cancel
406 CRITICAL_BLOCK(cs_vNodes)
223b6f1b 407 BOOST_FOREACH(CNode* pnode, vNodes)
0a61b0df 408 if (pnode != this)
409 pnode->PushMessage("sub-cancel", nChannel);
410 }
411}
412
413
414
415
416
417
418
419
420
67a42f92 421CNode* FindNode(const CNetAddr& ip)
0a61b0df 422{
423 CRITICAL_BLOCK(cs_vNodes)
424 {
223b6f1b 425 BOOST_FOREACH(CNode* pnode, vNodes)
67a42f92 426 if ((CNetAddr)pnode->addr == ip)
0a61b0df 427 return (pnode);
428 }
429 return NULL;
430}
431
67a42f92 432CNode* FindNode(const CService& addr)
0a61b0df 433{
434 CRITICAL_BLOCK(cs_vNodes)
435 {
223b6f1b 436 BOOST_FOREACH(CNode* pnode, vNodes)
67a42f92 437 if ((CService)pnode->addr == addr)
0a61b0df 438 return (pnode);
439 }
440 return NULL;
441}
442
bde280b9 443CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
0a61b0df 444{
67a42f92 445 if ((CNetAddr)addrConnect == (CNetAddr)addrLocalHost)
0a61b0df 446 return NULL;
447
448 // Look for an existing connection
67a42f92 449 CNode* pnode = FindNode((CService)addrConnect);
0a61b0df 450 if (pnode)
451 {
452 if (nTimeout != 0)
453 pnode->AddRef(nTimeout);
454 else
455 pnode->AddRef();
456 return pnode;
457 }
458
459 /// debug print
460 printf("trying connection %s lastseen=%.1fhrs lasttry=%.1fhrs\n",
a6a5bb7c 461 addrConnect.ToString().c_str(),
0a61b0df 462 (double)(addrConnect.nTime - GetAdjustedTime())/3600.0,
463 (double)(addrConnect.nLastTry - GetAdjustedTime())/3600.0);
464
465 CRITICAL_BLOCK(cs_mapAddresses)
466 mapAddresses[addrConnect.GetKey()].nLastTry = GetAdjustedTime();
467
468 // Connect
469 SOCKET hSocket;
470 if (ConnectSocket(addrConnect, hSocket))
471 {
472 /// debug print
a6a5bb7c 473 printf("connected %s\n", addrConnect.ToString().c_str());
0a61b0df 474
475 // Set to nonblocking
6853e627 476#ifdef WIN32
0a61b0df 477 u_long nOne = 1;
478 if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
479 printf("ConnectSocket() : ioctlsocket nonblocking setting failed, error %d\n", WSAGetLastError());
480#else
481 if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
482 printf("ConnectSocket() : fcntl nonblocking setting failed, error %d\n", errno);
483#endif
484
485 // Add node
486 CNode* pnode = new CNode(hSocket, addrConnect, false);
487 if (nTimeout != 0)
488 pnode->AddRef(nTimeout);
489 else
490 pnode->AddRef();
491 CRITICAL_BLOCK(cs_vNodes)
492 vNodes.push_back(pnode);
493
494 pnode->nTimeConnected = GetTime();
495 return pnode;
496 }
497 else
498 {
499 return NULL;
500 }
501}
502
503void CNode::CloseSocketDisconnect()
504{
505 fDisconnect = true;
506 if (hSocket != INVALID_SOCKET)
507 {
508 if (fDebug)
509 printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
a6a5bb7c 510 printf("disconnecting node %s\n", addr.ToString().c_str());
0a61b0df 511 closesocket(hSocket);
512 hSocket = INVALID_SOCKET;
513 }
514}
515
516void CNode::Cleanup()
517{
518 // All of a nodes broadcasts and subscriptions are automatically torn down
519 // when it goes down, so a node has to stay up to keep its broadcast going.
520
521 // Cancel subscriptions
522 for (unsigned int nChannel = 0; nChannel < vfSubscribe.size(); nChannel++)
523 if (vfSubscribe[nChannel])
524 CancelSubscribe(nChannel);
525}
526
527
f8ded588
GA
528void CNode::PushVersion()
529{
530 /// when NTP implemented, change to just nTime = GetAdjustedTime()
bde280b9 531 int64 nTime = (fInbound ? GetAdjustedTime() : GetTime());
c981d768 532 CAddress addrYou = (fUseProxy ? CAddress(CService("0.0.0.0",0)) : addr);
baba6e7d 533 CAddress addrMe = (fUseProxy || !addrLocalHost.IsRoutable() ? CAddress(CService("0.0.0.0",0)) : addrLocalHost);
f8ded588
GA
534 RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
535 PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
536 nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()), nBestHeight);
537}
538
539
540
541
542
67a42f92 543std::map<CNetAddr, int64> CNode::setBanned;
15f3ad4d
GA
544CCriticalSection CNode::cs_setBanned;
545
546void CNode::ClearBanned()
547{
548 setBanned.clear();
549}
550
67a42f92 551bool CNode::IsBanned(CNetAddr ip)
15f3ad4d
GA
552{
553 bool fResult = false;
554 CRITICAL_BLOCK(cs_setBanned)
555 {
67a42f92 556 std::map<CNetAddr, int64>::iterator i = setBanned.find(ip);
15f3ad4d
GA
557 if (i != setBanned.end())
558 {
bde280b9 559 int64 t = (*i).second;
15f3ad4d
GA
560 if (GetTime() < t)
561 fResult = true;
562 }
563 }
564 return fResult;
565}
566
567bool CNode::Misbehaving(int howmuch)
568{
569 if (addr.IsLocal())
570 {
571 printf("Warning: local node %s misbehaving\n", addr.ToString().c_str());
572 return false;
573 }
574
575 nMisbehavior += howmuch;
576 if (nMisbehavior >= GetArg("-banscore", 100))
577 {
bde280b9 578 int64 banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban
15f3ad4d 579 CRITICAL_BLOCK(cs_setBanned)
67a42f92
PW
580 if (setBanned[addr] < banTime)
581 setBanned[addr] = banTime;
15f3ad4d
GA
582 CloseSocketDisconnect();
583 printf("Disconnected %s for misbehavior (score=%d)\n", addr.ToString().c_str(), nMisbehavior);
584 return true;
585 }
586 return false;
587}
588
0a61b0df 589
590
591
592
593
594
595
596
597
598
599
600void ThreadSocketHandler(void* parg)
601{
602 IMPLEMENT_RANDOMIZE_STACK(ThreadSocketHandler(parg));
603 try
604 {
605 vnThreadsRunning[0]++;
606 ThreadSocketHandler2(parg);
607 vnThreadsRunning[0]--;
608 }
609 catch (std::exception& e) {
610 vnThreadsRunning[0]--;
611 PrintException(&e, "ThreadSocketHandler()");
612 } catch (...) {
613 vnThreadsRunning[0]--;
614 throw; // support pthread_cancel()
615 }
616 printf("ThreadSocketHandler exiting\n");
617}
618
619void ThreadSocketHandler2(void* parg)
620{
621 printf("ThreadSocketHandler started\n");
622 list<CNode*> vNodesDisconnected;
623 int nPrevNodeCount = 0;
624
625 loop
626 {
627 //
628 // Disconnect nodes
629 //
630 CRITICAL_BLOCK(cs_vNodes)
631 {
632 // Disconnect unused nodes
633 vector<CNode*> vNodesCopy = vNodes;
223b6f1b 634 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 635 {
636 if (pnode->fDisconnect ||
637 (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
638 {
639 // remove from vNodes
640 vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
641
642 // close socket and cleanup
643 pnode->CloseSocketDisconnect();
644 pnode->Cleanup();
645
646 // hold in disconnected pool until all refs are released
647 pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
648 if (pnode->fNetworkNode || pnode->fInbound)
649 pnode->Release();
650 vNodesDisconnected.push_back(pnode);
651 }
652 }
653
654 // Delete disconnected nodes
655 list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
223b6f1b 656 BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy)
0a61b0df 657 {
658 // wait until threads are done using it
659 if (pnode->GetRefCount() <= 0)
660 {
661 bool fDelete = false;
662 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
663 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
664 TRY_CRITICAL_BLOCK(pnode->cs_mapRequests)
665 TRY_CRITICAL_BLOCK(pnode->cs_inventory)
666 fDelete = true;
667 if (fDelete)
668 {
669 vNodesDisconnected.remove(pnode);
670 delete pnode;
671 }
672 }
673 }
674 }
675 if (vNodes.size() != nPrevNodeCount)
676 {
677 nPrevNodeCount = vNodes.size();
678 MainFrameRepaint();
679 }
680
681
682 //
683 // Find which sockets have data to receive
684 //
685 struct timeval timeout;
686 timeout.tv_sec = 0;
687 timeout.tv_usec = 50000; // frequency to poll pnode->vSend
688
689 fd_set fdsetRecv;
690 fd_set fdsetSend;
691 fd_set fdsetError;
692 FD_ZERO(&fdsetRecv);
693 FD_ZERO(&fdsetSend);
694 FD_ZERO(&fdsetError);
695 SOCKET hSocketMax = 0;
5f88e888
W
696
697 if(hListenSocket != INVALID_SOCKET)
698 FD_SET(hListenSocket, &fdsetRecv);
0a61b0df 699 hSocketMax = max(hSocketMax, hListenSocket);
700 CRITICAL_BLOCK(cs_vNodes)
701 {
223b6f1b 702 BOOST_FOREACH(CNode* pnode, vNodes)
0a61b0df 703 {
d7f1d200 704 if (pnode->hSocket == INVALID_SOCKET)
0a61b0df 705 continue;
706 FD_SET(pnode->hSocket, &fdsetRecv);
707 FD_SET(pnode->hSocket, &fdsetError);
708 hSocketMax = max(hSocketMax, pnode->hSocket);
709 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
710 if (!pnode->vSend.empty())
711 FD_SET(pnode->hSocket, &fdsetSend);
712 }
713 }
714
715 vnThreadsRunning[0]--;
716 int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
717 vnThreadsRunning[0]++;
718 if (fShutdown)
719 return;
720 if (nSelect == SOCKET_ERROR)
721 {
722 int nErr = WSAGetLastError();
c6710c7a
MC
723 if (hSocketMax > -1)
724 {
725 printf("socket select error %d\n", nErr);
726 for (int i = 0; i <= hSocketMax; i++)
727 FD_SET(i, &fdsetRecv);
728 }
0a61b0df 729 FD_ZERO(&fdsetSend);
730 FD_ZERO(&fdsetError);
731 Sleep(timeout.tv_usec/1000);
732 }
733
734
735 //
736 // Accept new connections
737 //
5f88e888 738 if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
0a61b0df 739 {
740 struct sockaddr_in sockaddr;
741 socklen_t len = sizeof(sockaddr);
742 SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
25ab1758 743 CAddress addr;
4698dd9a
CM
744 int nInbound = 0;
745
25ab1758
PW
746 if (hSocket != INVALID_SOCKET)
747 addr = CAddress(sockaddr);
748
5a3e82f9 749 CRITICAL_BLOCK(cs_vNodes)
223b6f1b 750 BOOST_FOREACH(CNode* pnode, vNodes)
5a3e82f9
GA
751 if (pnode->fInbound)
752 nInbound++;
25ab1758 753
0a61b0df 754 if (hSocket == INVALID_SOCKET)
755 {
756 if (WSAGetLastError() != WSAEWOULDBLOCK)
757 printf("socket error accept failed: %d\n", WSAGetLastError());
758 }
5a3e82f9 759 else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
0a61b0df 760 {
b24e6e4d
MC
761 CRITICAL_BLOCK(cs_setservAddNodeAddresses)
762 if (!setservAddNodeAddresses.count(addr))
763 closesocket(hSocket);
0a61b0df 764 }
67a42f92 765 else if (CNode::IsBanned(addr))
15f3ad4d
GA
766 {
767 printf("connetion from %s dropped (banned)\n", addr.ToString().c_str());
768 closesocket(hSocket);
769 }
0a61b0df 770 else
771 {
a6a5bb7c 772 printf("accepted connection %s\n", addr.ToString().c_str());
0a61b0df 773 CNode* pnode = new CNode(hSocket, addr, true);
774 pnode->AddRef();
775 CRITICAL_BLOCK(cs_vNodes)
776 vNodes.push_back(pnode);
777 }
778 }
779
780
781 //
782 // Service each socket
783 //
784 vector<CNode*> vNodesCopy;
785 CRITICAL_BLOCK(cs_vNodes)
786 {
787 vNodesCopy = vNodes;
223b6f1b 788 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 789 pnode->AddRef();
790 }
223b6f1b 791 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 792 {
793 if (fShutdown)
794 return;
795
796 //
797 // Receive
798 //
799 if (pnode->hSocket == INVALID_SOCKET)
800 continue;
801 if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
802 {
803 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
804 {
805 CDataStream& vRecv = pnode->vRecv;
806 unsigned int nPos = vRecv.size();
807
49731745 808 if (nPos > ReceiveBufferSize()) {
0a61b0df 809 if (!pnode->fDisconnect)
9cbae55a 810 printf("socket recv flood control disconnect (%d bytes)\n", vRecv.size());
0a61b0df 811 pnode->CloseSocketDisconnect();
812 }
9cbae55a
GA
813 else {
814 // typical socket buffer is 8K-64K
815 char pchBuf[0x10000];
816 int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
817 if (nBytes > 0)
0a61b0df 818 {
9cbae55a
GA
819 vRecv.resize(nPos + nBytes);
820 memcpy(&vRecv[nPos], pchBuf, nBytes);
821 pnode->nLastRecv = GetTime();
822 }
823 else if (nBytes == 0)
824 {
825 // socket closed gracefully
0a61b0df 826 if (!pnode->fDisconnect)
9cbae55a 827 printf("socket closed\n");
0a61b0df 828 pnode->CloseSocketDisconnect();
829 }
9cbae55a
GA
830 else if (nBytes < 0)
831 {
832 // error
833 int nErr = WSAGetLastError();
834 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
835 {
836 if (!pnode->fDisconnect)
837 printf("socket recv error %d\n", nErr);
838 pnode->CloseSocketDisconnect();
839 }
840 }
0a61b0df 841 }
842 }
843 }
844
845 //
846 // Send
847 //
848 if (pnode->hSocket == INVALID_SOCKET)
849 continue;
850 if (FD_ISSET(pnode->hSocket, &fdsetSend))
851 {
852 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
853 {
854 CDataStream& vSend = pnode->vSend;
855 if (!vSend.empty())
856 {
857 int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
858 if (nBytes > 0)
859 {
860 vSend.erase(vSend.begin(), vSend.begin() + nBytes);
861 pnode->nLastSend = GetTime();
862 }
863 else if (nBytes < 0)
864 {
865 // error
866 int nErr = WSAGetLastError();
867 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
868 {
869 printf("socket send error %d\n", nErr);
870 pnode->CloseSocketDisconnect();
871 }
872 }
49731745 873 if (vSend.size() > SendBufferSize()) {
9cbae55a
GA
874 if (!pnode->fDisconnect)
875 printf("socket send flood control disconnect (%d bytes)\n", vSend.size());
876 pnode->CloseSocketDisconnect();
877 }
0a61b0df 878 }
879 }
880 }
881
882 //
883 // Inactivity checking
884 //
885 if (pnode->vSend.empty())
886 pnode->nLastSendEmpty = GetTime();
887 if (GetTime() - pnode->nTimeConnected > 60)
888 {
889 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
890 {
891 printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
892 pnode->fDisconnect = true;
893 }
894 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
895 {
896 printf("socket not sending\n");
897 pnode->fDisconnect = true;
898 }
899 else if (GetTime() - pnode->nLastRecv > 90*60)
900 {
901 printf("socket inactivity timeout\n");
902 pnode->fDisconnect = true;
903 }
904 }
905 }
906 CRITICAL_BLOCK(cs_vNodes)
907 {
223b6f1b 908 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 909 pnode->Release();
910 }
911
0a61b0df 912 Sleep(10);
913 }
914}
915
916
917
918
919
920
921
922
923
8bb5edc1
MC
924#ifdef USE_UPNP
925void ThreadMapPort(void* parg)
926{
927 IMPLEMENT_RANDOMIZE_STACK(ThreadMapPort(parg));
928 try
929 {
930 vnThreadsRunning[5]++;
931 ThreadMapPort2(parg);
932 vnThreadsRunning[5]--;
933 }
934 catch (std::exception& e) {
935 vnThreadsRunning[5]--;
936 PrintException(&e, "ThreadMapPort()");
937 } catch (...) {
938 vnThreadsRunning[5]--;
939 PrintException(NULL, "ThreadMapPort()");
940 }
941 printf("ThreadMapPort exiting\n");
942}
943
944void ThreadMapPort2(void* parg)
945{
946 printf("ThreadMapPort started\n");
947
948 char port[6];
00bcfe0b 949 sprintf(port, "%d", GetListenPort());
8bb5edc1 950
8bb5edc1
MC
951 const char * multicastif = 0;
952 const char * minissdpdpath = 0;
953 struct UPNPDev * devlist = 0;
954 char lanaddr[64];
955
94b97046
LD
956#ifndef UPNPDISCOVER_SUCCESS
957 /* miniupnpc 1.5 */
958 devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0);
959#else
960 /* miniupnpc 1.6 */
961 int error = 0;
b4ada906 962 devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error);
94b97046 963#endif
8bb5edc1
MC
964
965 struct UPNPUrls urls;
966 struct IGDdatas data;
967 int r;
968
f285d4f4
DH
969 r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
970 if (r == 1)
8bb5edc1 971 {
baba6e7d
MC
972 if (!addrLocalHost.IsRoutable())
973 {
974 char externalIPAddress[40];
975 r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
976 if(r != UPNPCOMMAND_SUCCESS)
977 printf("UPnP: GetExternalIPAddress() returned %d\n", r);
978 else
979 {
980 if(externalIPAddress[0])
981 {
982 printf("UPnP: ExternalIPAddress = %s\n", externalIPAddress);
983 CAddress addrExternalFromUPnP(CService(externalIPAddress, 0), nLocalServices);
984 if (addrExternalFromUPnP.IsRoutable())
985 addrLocalHost = addrExternalFromUPnP;
986 }
987 else
988 printf("UPnP: GetExternalIPAddress failed.\n");
989 }
990 }
991
15656981 992 string strDesc = "Bitcoin " + FormatFullVersion();
94b97046 993#ifndef UPNPDISCOVER_SUCCESS
177dbcaa 994 /* miniupnpc 1.5 */
94b97046 995 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
b985efaa 996 port, port, lanaddr, strDesc.c_str(), "TCP", 0);
94b97046 997#else
177dbcaa 998 /* miniupnpc 1.6 */
8bb5edc1 999 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
b985efaa 1000 port, port, lanaddr, strDesc.c_str(), "TCP", 0, "0");
94b97046 1001#endif
b4ada906 1002
8bb5edc1
MC
1003 if(r!=UPNPCOMMAND_SUCCESS)
1004 printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
1005 port, port, lanaddr, r, strupnperror(r));
1006 else
1007 printf("UPnP Port Mapping successful.\n");
177dbcaa 1008 int i = 1;
8bb5edc1
MC
1009 loop {
1010 if (fShutdown || !fUseUPnP)
1011 {
1012 r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port, "TCP", 0);
1013 printf("UPNP_DeletePortMapping() returned : %d\n", r);
1014 freeUPNPDevlist(devlist); devlist = 0;
1015 FreeUPNPUrls(&urls);
1016 return;
1017 }
177dbcaa
MC
1018 if (i % 600 == 0) // Refresh every 20 minutes
1019 {
1020#ifndef UPNPDISCOVER_SUCCESS
1021 /* miniupnpc 1.5 */
1022 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1023 port, port, lanaddr, strDesc.c_str(), "TCP", 0);
1024#else
1025 /* miniupnpc 1.6 */
1026 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1027 port, port, lanaddr, strDesc.c_str(), "TCP", 0, "0");
1028#endif
1029
1030 if(r!=UPNPCOMMAND_SUCCESS)
1031 printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
1032 port, port, lanaddr, r, strupnperror(r));
1033 else
1034 printf("UPnP Port Mapping successful.\n");;
1035 }
8bb5edc1 1036 Sleep(2000);
177dbcaa 1037 i++;
8bb5edc1
MC
1038 }
1039 } else {
1040 printf("No valid UPnP IGDs found\n");
1041 freeUPNPDevlist(devlist); devlist = 0;
f285d4f4
DH
1042 if (r != 0)
1043 FreeUPNPUrls(&urls);
8bb5edc1 1044 loop {
973800b5 1045 if (fShutdown || !fUseUPnP)
8bb5edc1
MC
1046 return;
1047 Sleep(2000);
1048 }
1049 }
1050}
1051
1052void MapPort(bool fMapPort)
1053{
1054 if (fUseUPnP != fMapPort)
1055 {
1056 fUseUPnP = fMapPort;
64c7ee7e 1057 WriteSetting("fUseUPnP", fUseUPnP);
8bb5edc1
MC
1058 }
1059 if (fUseUPnP && vnThreadsRunning[5] < 1)
1060 {
1061 if (!CreateThread(ThreadMapPort, NULL))
1062 printf("Error: ThreadMapPort(ThreadMapPort) failed\n");
1063 }
1064}
9f0ac169
GA
1065#else
1066void MapPort(bool /* unused fMapPort */)
1067{
1068 // Intentionally left blank.
1069}
8bb5edc1
MC
1070#endif
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
f684aec4
JG
1081static const char *strDNSSeed[] = {
1082 "bitseed.xf2.org",
f03c31db 1083 "dnsseed.bluematt.me",
61a8c056 1084 "seed.bitcoin.sipa.be",
64773488 1085 "dnsseed.bitcoin.dashjr.org",
f684aec4 1086};
0a61b0df 1087
2bc6cece 1088void ThreadDNSAddressSeed(void* parg)
f684aec4 1089{
2bc6cece
MC
1090 IMPLEMENT_RANDOMIZE_STACK(ThreadDNSAddressSeed(parg));
1091 try
1092 {
1093 vnThreadsRunning[6]++;
1094 ThreadDNSAddressSeed2(parg);
1095 vnThreadsRunning[6]--;
1096 }
1097 catch (std::exception& e) {
1098 vnThreadsRunning[6]--;
1099 PrintException(&e, "ThreadDNSAddressSeed()");
1100 } catch (...) {
1101 vnThreadsRunning[6]--;
1102 throw; // support pthread_cancel()
1103 }
1104 printf("ThreadDNSAddressSeed exiting\n");
1105}
1106
1107void ThreadDNSAddressSeed2(void* parg)
1108{
1109 printf("ThreadDNSAddressSeed started\n");
f684aec4
JG
1110 int found = 0;
1111
ce8f78a7
MC
1112 if (!fTestNet)
1113 {
1114 printf("Loading addresses from DNS seeds (could take a while)\n");
f684aec4 1115
ce8f78a7 1116 for (int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
67a42f92
PW
1117 vector<CNetAddr> vaddr;
1118 if (LookupHost(strDNSSeed[seed_idx], vaddr))
a6a5bb7c 1119 {
a75d7066
PW
1120 CAddrDB addrDB;
1121 addrDB.TxnBegin();
67a42f92 1122 BOOST_FOREACH (CNetAddr& ip, vaddr)
a6a5bb7c 1123 {
67a42f92 1124 if (ip.IsRoutable())
ce8f78a7 1125 {
67a42f92 1126 CAddress addr(CService(ip, GetDefaultPort()), NODE_NETWORK);
ce8f78a7 1127 addr.nTime = 0;
d655a26c 1128 AddAddress(addr, 0, &addrDB);
ce8f78a7
MC
1129 found++;
1130 }
a6a5bb7c 1131 }
a75d7066 1132 addrDB.TxnCommit(); // Save addresses (it's ok if this fails)
f684aec4
JG
1133 }
1134 }
1135 }
1136
448b4516 1137 printf("%d addresses found from DNS seeds\n", found);
f684aec4 1138}
0a61b0df 1139
1140
1141
2bc6cece
MC
1142
1143
1144
1145
1146
1147
1148
1149
1150
0a61b0df 1151unsigned int pnSeed[] =
1152{
b2f76e9d
DF
1153 0x959bd347, 0xf8de42b2, 0x73bc0518, 0xea6edc50, 0x21b00a4d, 0xc725b43d, 0xd665464d, 0x1a2a770e,
1154 0x27c93946, 0x65b2fa46, 0xb80ae255, 0x66b3b446, 0xb1877a3e, 0x6ee89e3e, 0xc3175b40, 0x2a01a83c,
1155 0x95b1363a, 0xa079ad3d, 0xe6ca801f, 0x027f4f4a, 0x34f7f03a, 0xf790f04a, 0x16ca801f, 0x2f4d5e40,
1156 0x3a4d5e40, 0xc43a322e, 0xc8159753, 0x14d4724c, 0x7919a118, 0xe0bdb34e, 0x68a16b2e, 0xff64b44d,
1157 0x6099115b, 0x9b57b05b, 0x7bd1b4ad, 0xdf95944f, 0x29d2b73d, 0xafa8db79, 0xe247ba41, 0x24078348,
1158 0xf722f03c, 0x33567ebc, 0xace64ed4, 0x984d3932, 0xb5f34e55, 0x27b7024d, 0x94579247, 0x8894042e,
1159 0x9357d34c, 0x1063c24b, 0xcaa228b1, 0xa3c5a8b2, 0x5dc64857, 0xa2c23643, 0xa8369a54, 0x31203077,
1160 0x00707c5c, 0x09fc0b3a, 0x272e9e2e, 0xf80f043e, 0x9449ca3e, 0x5512c33e, 0xd106b555, 0xe8024157,
1161 0xe288ec29, 0xc79c5461, 0xafb63932, 0xdb02ab4b, 0x0e512777, 0x8a145a4c, 0xb201ff4f, 0x5e09314b,
1162 0xcd9bfbcd, 0x1c023765, 0x4394e75c, 0xa728bd4d, 0x65331552, 0xa98420b1, 0x89ecf559, 0x6e80801f,
1163 0xf404f118, 0xefd62b51, 0x05918346, 0x9b186d5f, 0xacabab46, 0xf912e255, 0xc188ea62, 0xcc55734e,
1164 0xc668064d, 0xd77a4558, 0x46201c55, 0xf17dfc80, 0xf7142f2e, 0x87bfb718, 0x8aa54fb2, 0xc451d518,
1165 0xc4ae8831, 0x8dd44d55, 0x5bbd206c, 0x64536b5d, 0x5c667e60, 0x3b064242, 0xfe963a42, 0xa28e6dc8,
1166 0xe8a9604a, 0xc989464e, 0xd124a659, 0x50065140, 0xa44dfe5e, 0x1079e655, 0x3fb986d5, 0x47895b18,
1167 0x7d3ce4ad, 0x4561ba50, 0x296eec62, 0x255b41ad, 0xaed35ec9, 0x55556f12, 0xc7d3154d, 0x3297b65d,
1168 0x8930121f, 0xabf42e4e, 0x4a29e044, 0x1212685d, 0x676c1e40, 0xce009744, 0x383a8948, 0xa2dbd0ad,
1169 0xecc2564d, 0x07dbc252, 0x887ee24b, 0x5171644c, 0x6bb798c1, 0x847f495d, 0x4cbb7145, 0x3bb81c32,
1170 0x45eb262e, 0xc8015a4e, 0x250a361b, 0xf694f946, 0xd64a183e, 0xd4f1dd59, 0x8f20ffd4, 0x51d9e55c,
1171 0x09521763, 0x5e02002e, 0x32c8074d, 0xe685762e, 0x8290b0bc, 0x762a922e, 0xfc5ee754, 0x83a24829,
1172 0x775b224d, 0x6295bb4d, 0x38ec0555, 0xbffbba50, 0xe5560260, 0x86b16a7c, 0xd372234e, 0x49a3c24b,
1173 0x2f6a171f, 0x4d75ed60, 0xae94115b, 0xcb543744, 0x63080c59, 0x3f9c724c, 0xc977ce18, 0x532efb18,
1174 0x69dc3b2e, 0x5f94d929, 0x1732bb4d, 0x9c814b4d, 0xe6b3762e, 0xc024f662, 0x8face35b, 0x6b5b044d,
1175 0x798c7b57, 0x79a6b44c, 0x067d3057, 0xf9e94e5f, 0x91cbe15b, 0x71405eb2, 0x2662234e, 0xcbcc4a6d,
1176 0xbf69d54b, 0xa79b4e55, 0xec6d3e51, 0x7c0b3c02, 0x60f83653, 0x24c1e15c, 0x1110b62e, 0x10350f59,
1177 0xa56f1d55, 0x3509e7a9, 0xeb128354, 0x14268e2e, 0x934e28bc, 0x8e32692e, 0x8331a21f, 0x3e633932,
1178 0xc812b12e, 0xc684bf2e, 0x80112d2e, 0xe0ddc96c, 0xc630ca4a, 0x5c09b3b2, 0x0b580518, 0xc8e9d54b,
1179 0xd169aa43, 0x17d0d655, 0x1d029963, 0x7ff87559, 0xcb701f1f, 0x6fa3e85d, 0xe45e9a54, 0xf05d1802,
1180 0x44d03b2e, 0x837b692e, 0xccd4354e, 0x3d6da13c, 0x3423084d, 0xf707c34a, 0x55f6db3a, 0xad26e442,
1181 0x6233a21f, 0x09e80e59, 0x8caeb54d, 0xbe870941, 0xb407d20e, 0x20b51018, 0x56fb152e, 0x460d2a4e,
1182 0xbb9a2946, 0x560eb12e, 0xed83dd29, 0xd6724f53, 0xa50aafb8, 0x451346d9, 0x88348e2e, 0x7312fead,
1183 0x8ecaf96f, 0x1bda4e5f, 0xf1671e40, 0x3c8c3e3b, 0x4716324d, 0xdde24ede, 0xf98cd17d, 0xa91d4644,
1184 0x28124eb2, 0x147d5129, 0xd022042e, 0x61733d3b, 0xad0d5e02, 0x8ce2932e, 0xe5c18502, 0x549c1e32,
1185 0x9685801f, 0x86e217ad, 0xd948214b, 0x4110f462, 0x3a2e894e, 0xbd35492e, 0x87e0d558, 0x64b8ef7d,
1186 0x7c3eb962, 0x72a84b3e, 0x7cd667c9, 0x28370a2e, 0x4bc60e7b, 0x6fc1ec60, 0x14a6983f, 0x86739a4b,
1187 0x46954e5f, 0x32e2e15c, 0x2e9326cf, 0xe5801c5e, 0x379607b2, 0x32151145, 0xf0e39744, 0xacb54c55,
1188 0xa37dfb60, 0x83b55cc9, 0x388f7ca5, 0x15034f5f, 0x3e94965b, 0x68e0ffad, 0x35280f59, 0x8fe190cf,
1189 0x7c6ba5b2, 0xa5e9db43, 0x4ee1fc60, 0xd9d94e5f, 0x04040677, 0x0ea9b35e, 0x5961f14f, 0x67fda063,
1190 0xa48a5a31, 0xc6524e55, 0x283d325e, 0x3f37515f, 0x96b94b3e, 0xacce620e, 0x6481cc5b, 0xa4a06d4b,
1191 0x9e95d2d9, 0xe40c03d5, 0xc2f4514b, 0xb79aad44, 0xf64be843, 0xb2064070, 0xfca00455, 0x429dfa4e,
1192 0x2323f173, 0xeda4185e, 0xabd5227d, 0x9efd4d58, 0xb1104758, 0x4811e955, 0xbd9ab355, 0xe921f44b,
1193 0x9f166dce, 0x09e279b2, 0xe0c9ac7b, 0x7901a5ad, 0xa145d4b0, 0x79104671, 0xec31e35a, 0x4fe0b555,
1194 0xc7d9cbad, 0xad057f55, 0xe94cc759, 0x7fe0b043, 0xe4529f2e, 0x0d4dd4b2, 0x9f11a54d, 0x031e2e4e,
1195 0xe6014f5f, 0x11d1ca6c, 0x26bd7f61, 0xeb86854f, 0x4d347b57, 0x116bbe2e, 0xdba7234e, 0x7bcbfd2e,
1196 0x174dd4b2, 0x6686762e, 0xb089ba50, 0xc6258246, 0x087e767b, 0xc4a8cb4a, 0x595dba50, 0x7f0ae502,
1197 0x7b1dbd5a, 0xa0603492, 0x57d1af4b, 0x9e21ffd4, 0x6393064d, 0x7407376e, 0xe484762e, 0x122a4e53,
1198 0x4a37aa43, 0x3888a6be, 0xee77864e, 0x039c8dd5, 0x688d89af, 0x0e988f62, 0x08218246, 0xfc2f8246,
1199 0xd1d97040, 0xd64cd4b2, 0x5ae4a6b8, 0x7d0de9bc, 0x8d304d61, 0x06c5c672, 0xa4c8bd4d, 0xe0fd373b,
1200 0x575ebe4d, 0x72d26277, 0x55570f55, 0x77b154d9, 0xe214293a, 0xfc740f4b, 0xfe3f6a57, 0xa9c55f02,
1201 0xae4054db, 0x2394d918, 0xb511b24a, 0xb8741ab2, 0x0758e65e, 0xc7b5795b, 0xb0a30a4c, 0xaf7f170c,
1202 0xf3b4762e, 0x8179576d, 0x738a1581, 0x4b95b64c, 0x9829b618, 0x1bea932e, 0x7bdeaa4b, 0xcb5e0281,
1203 0x65618f54, 0x0658474b, 0x27066acf, 0x40556d65, 0x7d204d53, 0xf28bc244, 0xdce23455, 0xadc0ff54,
1204 0x3863c948, 0xcee34e5f, 0xdeb85e02, 0x2ed17a61, 0x6a7b094d, 0x7f0cfc40, 0x59603f54, 0x3220afbc,
1205 0xb5dfd962, 0x125d21c0, 0x13f8d243, 0xacfefb4e, 0x86c2c147, 0x3d8bbd59, 0xbd02a21f, 0x2593042e,
1206 0xc6a17a7c, 0x28925861, 0xb487ed44, 0xb5f4fd6d, 0x90c28a45, 0x5a14f74d, 0x43d71b4c, 0x728ebb5d,
1207 0x885bf950, 0x08134dd0, 0x38ec046e, 0xc575684b, 0x50082d2e, 0xa2f47757, 0x270f86ae, 0xf3ff6462,
1208 0x10ed3f4e, 0x4b58d462, 0xe01ce23e, 0x8c5b092e, 0x63e52f4e, 0x22c1e85d, 0xa908f54e, 0x8591624f,
1209 0x2c0fb94e, 0xa280ba3c, 0xb6f41b4c, 0x24f9aa47, 0x27201647, 0x3a3ea6dc, 0xa14fc3be, 0x3c34bdd5,
1210 0x5b8d4f5b, 0xaadeaf4b, 0xc71cab50, 0x15697a4c, 0x9a1a734c, 0x2a037d81, 0x2590bd59, 0x48ec2741,
1211 0x53489c5b, 0x7f00314b, 0x2170d362, 0xf2e92542, 0x42c10b44, 0x98f0f118, 0x883a3456, 0x099a932e,
1212 0xea38f7bc, 0x644e9247, 0xbb61b62e, 0x30e0863d, 0x5f51be54, 0x207215c7, 0x5f306c45, 0xaa7f3932,
1213 0x98da7d45, 0x4e339b59, 0x2e411581, 0xa808f618, 0xad2c0c59, 0x54476741, 0x09e99fd1, 0x5db8f752,
1214 0xc16df8bd, 0x1dd4b44f, 0x106edf2e, 0x9e15c180, 0x2ad6b56f, 0x633a5332, 0xff33787c, 0x077cb545,
1215 0x6610be6d, 0x75aad2c4, 0x72fb4d5b, 0xe81e0f59, 0x576f6332, 0x47333373, 0x351ed783, 0x2d90fb50,
1216 0x8d5e0f6c, 0x5b27a552, 0xdb293ebb, 0xe55ef950, 0x4b133ad8, 0x75df975a, 0x7b6a8740, 0xa899464b,
1217 0xfab15161, 0x10f8b64d, 0xd055ea4d, 0xee8e146b, 0x4b14afb8, 0x4bc1c44a, 0x9b961dcc, 0xd111ff43,
1218 0xfca0b745, 0xc800e412, 0x0afad9d1, 0xf751c350, 0xf9f0cccf, 0xa290a545, 0x8ef13763, 0x7ec70d59,
1219 0x2b066acf, 0x65496c45, 0xade02c1b, 0xae6eb077, 0x92c1e65b, 0xc064e6a9, 0xc649e56d, 0x5287a243,
1220 0x36de4f5b, 0x5b1df6ad, 0x65c39a59, 0xdba805b2, 0x20067aa8, 0x6457e56d, 0x3cee26cf, 0xfd3ff26d,
1221 0x04f86d4a, 0x06b8e048, 0xa93bcd5c, 0x91135852, 0xbe90a643, 0x8fa0094d, 0x06d8215f, 0x2677094d,
1222 0xd735685c, 0x164a00c9, 0x5209ac5f, 0xa9564c5c, 0x3b504f5f, 0xcc826bd0, 0x4615042e, 0x5fe13b4a,
1223 0x8c81b86d, 0x879ab68c, 0x1de564b8, 0x434487d8, 0x2dcb1b63, 0x82ab524a, 0xb0676abb, 0xa13d9c62,
1224 0xdbb5b86d, 0x5b7f4b59, 0xaddfb44d, 0xad773532, 0x3997054c, 0x72cebd89, 0xb194544c, 0xc5b8046e,
1225 0x6e1adeb2, 0xaa5abb51, 0xefb54b44, 0x15efc54f, 0xe9f1bc4d, 0x5f401b6c, 0x97f018ad, 0xc82f9252,
1226 0x2cdc762e, 0x8e52e56d, 0x1827175e, 0x9b7d7d80, 0xb2ad6845, 0x51065140, 0x71180a18, 0x5b27006c,
1227 0x0621e255, 0x721cbe58, 0x670c0cb8, 0xf8bd715d, 0xe0bdc5d9, 0xed843501, 0x4b84554d, 0x7f1a18bc,
1228 0x53bcaf47, 0x5729d35f, 0xf0dda246, 0x22382bd0, 0x4d641fb0, 0x316afcde, 0x50a22f1f, 0x73608046,
1229 0xc461d84a, 0xb2dbe247,
0a61b0df 1230};
1231
1232
1233
1234void ThreadOpenConnections(void* parg)
1235{
1236 IMPLEMENT_RANDOMIZE_STACK(ThreadOpenConnections(parg));
1237 try
1238 {
1239 vnThreadsRunning[1]++;
1240 ThreadOpenConnections2(parg);
1241 vnThreadsRunning[1]--;
1242 }
1243 catch (std::exception& e) {
1244 vnThreadsRunning[1]--;
1245 PrintException(&e, "ThreadOpenConnections()");
1246 } catch (...) {
1247 vnThreadsRunning[1]--;
1248 PrintException(NULL, "ThreadOpenConnections()");
1249 }
1250 printf("ThreadOpenConnections exiting\n");
1251}
1252
1253void ThreadOpenConnections2(void* parg)
1254{
1255 printf("ThreadOpenConnections started\n");
1256
1257 // Connect to specific addresses
1258 if (mapArgs.count("-connect"))
1259 {
bde280b9 1260 for (int64 nLoop = 0;; nLoop++)
0a61b0df 1261 {
223b6f1b 1262 BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
0a61b0df 1263 {
c981d768 1264 CAddress addr(CService(strAddr, GetDefaultPort(), fAllowDNS));
0a61b0df 1265 if (addr.IsValid())
1266 OpenNetworkConnection(addr);
1267 for (int i = 0; i < 10 && i < nLoop; i++)
1268 {
1269 Sleep(500);
1270 if (fShutdown)
1271 return;
1272 }
1273 }
1274 }
1275 }
1276
0a61b0df 1277 // Initiate network connections
bde280b9 1278 int64 nStart = GetTime();
0a61b0df 1279 loop
1280 {
0a61b0df 1281 vnThreadsRunning[1]--;
1282 Sleep(500);
cc201e01
PW
1283 vnThreadsRunning[1]++;
1284 if (fShutdown)
1285 return;
1286
1287 // Limit outbound connections
0a61b0df 1288 loop
1289 {
1290 int nOutbound = 0;
1291 CRITICAL_BLOCK(cs_vNodes)
223b6f1b 1292 BOOST_FOREACH(CNode* pnode, vNodes)
0a61b0df 1293 if (!pnode->fInbound)
1294 nOutbound++;
1295 int nMaxOutboundConnections = MAX_OUTBOUND_CONNECTIONS;
5a3e82f9 1296 nMaxOutboundConnections = min(nMaxOutboundConnections, (int)GetArg("-maxconnections", 125));
0a61b0df 1297 if (nOutbound < nMaxOutboundConnections)
1298 break;
cc201e01 1299 vnThreadsRunning[1]--;
0a61b0df 1300 Sleep(2000);
cc201e01 1301 vnThreadsRunning[1]++;
0a61b0df 1302 if (fShutdown)
1303 return;
1304 }
0a61b0df 1305
a75d7066
PW
1306 bool fAddSeeds = false;
1307
0a61b0df 1308 CRITICAL_BLOCK(cs_mapAddresses)
1309 {
1310 // Add seed nodes if IRC isn't working
67a42f92
PW
1311 bool fTOR = (fUseProxy && addrProxy.GetPort() == 9050);
1312 if (mapAddresses.empty() && (GetTime() - nStart > 60 || fTOR) && !fTestNet)
a75d7066
PW
1313 fAddSeeds = true;
1314 }
1315
1316 if (fAddSeeds)
1317 {
1318 for (int i = 0; i < ARRAYLEN(pnSeed); i++)
0a61b0df 1319 {
a75d7066
PW
1320 // It'll only connect to one or two seed nodes because once it connects,
1321 // it'll get a pile of addresses with newer timestamps.
1322 // Seed nodes are given a random 'last seen time' of between one and two
1323 // weeks ago.
1324 const int64 nOneWeek = 7*24*60*60;
67a42f92
PW
1325 struct in_addr ip;
1326 memcpy(&ip, &pnSeed[i], sizeof(ip));
1327 CAddress addr(CService(ip, GetDefaultPort()));
a75d7066
PW
1328 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1329 AddAddress(addr);
0a61b0df 1330 }
1331 }
1332
0a61b0df 1333 //
1334 // Choose an address to connect to based on most recently seen
1335 //
1336 CAddress addrConnect;
bde280b9 1337 int64 nBest = std::numeric_limits<int64>::min();
0a61b0df 1338
1339 // Only connect to one address per a.b.?.? range.
1340 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
67a42f92 1341 set<vector<unsigned char> > setConnected;
0a61b0df 1342 CRITICAL_BLOCK(cs_vNodes)
223b6f1b 1343 BOOST_FOREACH(CNode* pnode, vNodes)
67a42f92 1344 setConnected.insert(pnode->addr.GetGroup());
0a61b0df 1345
bde280b9 1346 int64 nANow = GetAdjustedTime();
a4e6ae10 1347
0a61b0df 1348 CRITICAL_BLOCK(cs_mapAddresses)
1349 {
223b6f1b 1350 BOOST_FOREACH(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
0a61b0df 1351 {
1352 const CAddress& addr = item.second;
67a42f92 1353 if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.GetGroup()))
0a61b0df 1354 continue;
bde280b9
WL
1355 int64 nSinceLastSeen = nANow - addr.nTime;
1356 int64 nSinceLastTry = nANow - addr.nLastTry;
0a61b0df 1357
1358 // Randomize the order in a deterministic way, putting the standard port first
67a42f92
PW
1359 int64 nRandomizer = (uint64)(nStart * 4951 + addr.nLastTry * 9567851 + addr.GetHash()) % (2 * 60 * 60);
1360 if (addr.GetPort() != GetDefaultPort())
0a61b0df 1361 nRandomizer += 2 * 60 * 60;
1362
1363 // Last seen Base retry frequency
1364 // <1 hour 10 min
1365 // 1 hour 1 hour
1366 // 4 hours 2 hours
1367 // 24 hours 5 hours
1368 // 48 hours 7 hours
1369 // 7 days 13 hours
1370 // 30 days 27 hours
1371 // 90 days 46 hours
1372 // 365 days 93 hours
bde280b9 1373 int64 nDelay = (int64)(3600.0 * sqrt(fabs((double)nSinceLastSeen) / 3600.0) + nRandomizer);
0a61b0df 1374
1375 // Fast reconnect for one hour after last seen
1376 if (nSinceLastSeen < 60 * 60)
1377 nDelay = 10 * 60;
1378
1379 // Limit retry frequency
1380 if (nSinceLastTry < nDelay)
1381 continue;
1382
1383 // If we have IRC, we'll be notified when they first come online,
1384 // and again every 24 hours by the refresh broadcast.
1385 if (nGotIRCAddresses > 0 && vNodes.size() >= 2 && nSinceLastSeen > 24 * 60 * 60)
1386 continue;
1387
1388 // Only try the old stuff if we don't have enough connections
1389 if (vNodes.size() >= 8 && nSinceLastSeen > 24 * 60 * 60)
1390 continue;
1391
1392 // If multiple addresses are ready, prioritize by time since
1393 // last seen and time since last tried.
bde280b9 1394 int64 nScore = min(nSinceLastTry, (int64)24 * 60 * 60) - nSinceLastSeen - nRandomizer;
0a61b0df 1395 if (nScore > nBest)
1396 {
1397 nBest = nScore;
1398 addrConnect = addr;
1399 }
1400 }
1401 }
1402
1403 if (addrConnect.IsValid())
1404 OpenNetworkConnection(addrConnect);
1405 }
1406}
1407
b24e6e4d
MC
1408void ThreadOpenAddedConnections(void* parg)
1409{
1410 IMPLEMENT_RANDOMIZE_STACK(ThreadOpenAddedConnections(parg));
1411 try
1412 {
1413 vnThreadsRunning[7]++;
1414 ThreadOpenAddedConnections2(parg);
1415 vnThreadsRunning[7]--;
1416 }
1417 catch (std::exception& e) {
1418 vnThreadsRunning[7]--;
1419 PrintException(&e, "ThreadOpenAddedConnections()");
1420 } catch (...) {
1421 vnThreadsRunning[7]--;
1422 PrintException(NULL, "ThreadOpenAddedConnections()");
1423 }
1424 printf("ThreadOpenAddedConnections exiting\n");
1425}
1426
1427void ThreadOpenAddedConnections2(void* parg)
1428{
1429 printf("ThreadOpenAddedConnections started\n");
1430
1431 if (mapArgs.count("-addnode") == 0)
1432 return;
1433
1434 vector<vector<CService> > vservAddressesToAdd(0);
1435 BOOST_FOREACH(string& strAddNode, mapMultiArgs["-addnode"])
1436 {
1437 vector<CService> vservNode(0);
1438 if(Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fAllowDNS, 0))
1439 {
1440 vservAddressesToAdd.push_back(vservNode);
1441 CRITICAL_BLOCK(cs_setservAddNodeAddresses)
1442 BOOST_FOREACH(CService& serv, vservNode)
1443 setservAddNodeAddresses.insert(serv);
1444 }
1445 }
1446 loop
1447 {
1448 vector<vector<CService> > vservConnectAddresses = vservAddressesToAdd;
1449 // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
1450 // (keeping in mind that addnode entries can have many IPs if fAllowDNS)
1451 CRITICAL_BLOCK(cs_vNodes)
1452 BOOST_FOREACH(CNode* pnode, vNodes)
1453 for (vector<vector<CService> >::iterator it = vservConnectAddresses.begin(); it != vservConnectAddresses.end(); it++)
1454 BOOST_FOREACH(CService& addrNode, *(it))
1455 if (pnode->addr == addrNode)
1456 {
1457 it = vservConnectAddresses.erase(it);
1458 it--;
1459 break;
1460 }
1461 BOOST_FOREACH(vector<CService>& vserv, vservConnectAddresses)
1462 {
1463 OpenNetworkConnection(CAddress(*(vserv.begin())));
1464 Sleep(500);
1465 if (fShutdown)
1466 return;
1467 }
1468 if (fShutdown)
1469 return;
1470 vnThreadsRunning[7]--;
1471 Sleep(120000); // Retry every 2 minutes
1472 vnThreadsRunning[7]++;
1473 if (fShutdown)
1474 return;
1475 }
1476}
1477
0a61b0df 1478bool OpenNetworkConnection(const CAddress& addrConnect)
1479{
1480 //
1481 // Initiate outbound network connection
1482 //
1483 if (fShutdown)
1484 return false;
67a42f92
PW
1485 if ((CNetAddr)addrConnect == (CNetAddr)addrLocalHost || !addrConnect.IsIPv4() ||
1486 FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect))
0a61b0df 1487 return false;
1488
1489 vnThreadsRunning[1]--;
1490 CNode* pnode = ConnectNode(addrConnect);
1491 vnThreadsRunning[1]++;
1492 if (fShutdown)
1493 return false;
1494 if (!pnode)
1495 return false;
1496 pnode->fNetworkNode = true;
1497
0a61b0df 1498 return true;
1499}
1500
1501
1502
1503
1504
1505
1506
1507
1508void ThreadMessageHandler(void* parg)
1509{
1510 IMPLEMENT_RANDOMIZE_STACK(ThreadMessageHandler(parg));
1511 try
1512 {
1513 vnThreadsRunning[2]++;
1514 ThreadMessageHandler2(parg);
1515 vnThreadsRunning[2]--;
1516 }
1517 catch (std::exception& e) {
1518 vnThreadsRunning[2]--;
1519 PrintException(&e, "ThreadMessageHandler()");
1520 } catch (...) {
1521 vnThreadsRunning[2]--;
1522 PrintException(NULL, "ThreadMessageHandler()");
1523 }
1524 printf("ThreadMessageHandler exiting\n");
1525}
1526
1527void ThreadMessageHandler2(void* parg)
1528{
1529 printf("ThreadMessageHandler started\n");
1530 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1531 while (!fShutdown)
1532 {
1533 vector<CNode*> vNodesCopy;
1534 CRITICAL_BLOCK(cs_vNodes)
1535 {
1536 vNodesCopy = vNodes;
223b6f1b 1537 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 1538 pnode->AddRef();
1539 }
1540
1541 // Poll the connected nodes for messages
1542 CNode* pnodeTrickle = NULL;
1543 if (!vNodesCopy.empty())
1544 pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
223b6f1b 1545 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 1546 {
1547 // Receive messages
1548 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
1549 ProcessMessages(pnode);
1550 if (fShutdown)
1551 return;
1552
1553 // Send messages
1554 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
1555 SendMessages(pnode, pnode == pnodeTrickle);
1556 if (fShutdown)
1557 return;
1558 }
1559
1560 CRITICAL_BLOCK(cs_vNodes)
1561 {
223b6f1b 1562 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 1563 pnode->Release();
1564 }
1565
7629d36a 1566 // Wait and allow messages to bunch up.
1567 // Reduce vnThreadsRunning so StopNode has permission to exit while
1568 // we're sleeping, but we must always check fShutdown after doing this.
0a61b0df 1569 vnThreadsRunning[2]--;
1570 Sleep(100);
3f647537 1571 if (fRequestShutdown)
1572 Shutdown(NULL);
0a61b0df 1573 vnThreadsRunning[2]++;
1574 if (fShutdown)
1575 return;
1576 }
1577}
1578
1579
1580
1581
1582
1583
0a61b0df 1584bool BindListenPort(string& strError)
1585{
1586 strError = "";
1587 int nOne = 1;
67a42f92 1588 addrLocalHost.SetPort(GetListenPort());
0a61b0df 1589
6853e627 1590#ifdef WIN32
0a61b0df 1591 // Initialize Windows Sockets
1592 WSADATA wsadata;
1593 int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
1594 if (ret != NO_ERROR)
1595 {
1596 strError = strprintf("Error: TCP/IP socket library failed to start (WSAStartup returned error %d)", ret);
1597 printf("%s\n", strError.c_str());
1598 return false;
1599 }
1600#endif
1601
1602 // Create socket for listening for incoming connections
1603 hListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
1604 if (hListenSocket == INVALID_SOCKET)
1605 {
1606 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1607 printf("%s\n", strError.c_str());
1608 return false;
1609 }
1610
ec93a0e2 1611#ifdef SO_NOSIGPIPE
0a61b0df 1612 // Different way of disabling SIGPIPE on BSD
1613 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1614#endif
1615
6853e627 1616#ifndef WIN32
0a61b0df 1617 // Allow binding if the port is still in TIME_WAIT state after
1618 // the program was closed and restarted. Not an issue on windows.
1619 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1620#endif
1621
6853e627 1622#ifdef WIN32
0a61b0df 1623 // Set to nonblocking, incoming connections will also inherit this
1624 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1625#else
1626 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1627#endif
1628 {
1629 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1630 printf("%s\n", strError.c_str());
1631 return false;
1632 }
1633
1634 // The sockaddr_in structure specifies the address family,
1635 // IP address, and port for the socket that is being bound
1636 struct sockaddr_in sockaddr;
1637 memset(&sockaddr, 0, sizeof(sockaddr));
1638 sockaddr.sin_family = AF_INET;
1639 sockaddr.sin_addr.s_addr = INADDR_ANY; // bind to all IPs on this computer
00bcfe0b 1640 sockaddr.sin_port = htons(GetListenPort());
0a61b0df 1641 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
1642 {
1643 int nErr = WSAGetLastError();
1644 if (nErr == WSAEADDRINUSE)
d9c6b09a 1645 strError = strprintf(_("Unable to bind to port %d on this computer. Bitcoin is probably already running."), ntohs(sockaddr.sin_port));
0a61b0df 1646 else
1647 strError = strprintf("Error: Unable to bind to port %d on this computer (bind returned error %d)", ntohs(sockaddr.sin_port), nErr);
1648 printf("%s\n", strError.c_str());
1649 return false;
1650 }
1651 printf("Bound to port %d\n", ntohs(sockaddr.sin_port));
1652
1653 // Listen for incoming connections
1654 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1655 {
1656 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1657 printf("%s\n", strError.c_str());
1658 return false;
1659 }
1660
1661 return true;
1662}
1663
1664void StartNode(void* parg)
1665{
1666 if (pnodeLocalHost == NULL)
67a42f92 1667 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", 0), nLocalServices));
0a61b0df 1668
6853e627 1669#ifdef WIN32
0a61b0df 1670 // Get local host ip
1671 char pszHostName[1000] = "";
1672 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1673 {
67a42f92
PW
1674 vector<CNetAddr> vaddr;
1675 if (LookupHost(pszHostName, vaddr))
1676 BOOST_FOREACH (const CNetAddr &addr, vaddr)
1677 if (!addr.IsLocal())
0a61b0df 1678 {
67a42f92 1679 addrLocalHost.SetIP(addr);
0a61b0df 1680 break;
1681 }
0a61b0df 1682 }
1683#else
1684 // Get local host ip
1685 struct ifaddrs* myaddrs;
1686 if (getifaddrs(&myaddrs) == 0)
1687 {
1688 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1689 {
1690 if (ifa->ifa_addr == NULL) continue;
1691 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1692 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1693 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1694 char pszIP[100];
1695 if (ifa->ifa_addr->sa_family == AF_INET)
1696 {
1697 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1698 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s4->sin_addr), pszIP, sizeof(pszIP)) != NULL)
1699 printf("ipv4 %s: %s\n", ifa->ifa_name, pszIP);
1700
1701 // Take the first IP that isn't loopback 127.x.x.x
67a42f92
PW
1702 CAddress addr(CService(s4->sin_addr, GetListenPort()), nLocalServices);
1703 if (addr.IsValid() && !addr.IsLocal())
0a61b0df 1704 {
1705 addrLocalHost = addr;
1706 break;
1707 }
1708 }
1709 else if (ifa->ifa_addr->sa_family == AF_INET6)
1710 {
1711 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1712 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s6->sin6_addr), pszIP, sizeof(pszIP)) != NULL)
1713 printf("ipv6 %s: %s\n", ifa->ifa_name, pszIP);
1714 }
1715 }
1716 freeifaddrs(myaddrs);
1717 }
1718#endif
1719 printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
1720
5f88e888 1721 if (fUseProxy || mapArgs.count("-connect") || fNoListen)
0a61b0df 1722 {
1723 // Proxies can't take incoming connections
67a42f92 1724 addrLocalHost.SetIP(CNetAddr("0.0.0.0"));
0a61b0df 1725 printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
1726 }
1727 else
1728 {
629e37dd 1729 CreateThread(ThreadGetMyExternalIP, NULL);
0a61b0df 1730 }
1731
1732 //
1733 // Start threads
1734 //
1735
9d952d17 1736 if (!GetBoolArg("-dnsseed", true))
2bc6cece
MC
1737 printf("DNS seeding disabled\n");
1738 else
1739 if (!CreateThread(ThreadDNSAddressSeed, NULL))
1740 printf("Error: CreateThread(ThreadDNSAddressSeed) failed\n");
1741
8bb5edc1
MC
1742 // Map ports with UPnP
1743 if (fHaveUPnP)
1744 MapPort(fUseUPnP);
1745
0a61b0df 1746 // Get addresses from IRC and advertise ours
1747 if (!CreateThread(ThreadIRCSeed, NULL))
1748 printf("Error: CreateThread(ThreadIRCSeed) failed\n");
1749
1750 // Send and receive from sockets, accept connections
65ba3e2f
LD
1751 if (!CreateThread(ThreadSocketHandler, NULL))
1752 printf("Error: CreateThread(ThreadSocketHandler) failed\n");
0a61b0df 1753
b24e6e4d
MC
1754 // Initiate outbound connections from -addnode
1755 if (!CreateThread(ThreadOpenAddedConnections, NULL))
1756 printf("Error: CreateThread(ThreadOpenAddedConnections) failed\n");
1757
0a61b0df 1758 // Initiate outbound connections
1759 if (!CreateThread(ThreadOpenConnections, NULL))
1760 printf("Error: CreateThread(ThreadOpenConnections) failed\n");
1761
1762 // Process messages
1763 if (!CreateThread(ThreadMessageHandler, NULL))
1764 printf("Error: CreateThread(ThreadMessageHandler) failed\n");
1765
1766 // Generate coins in the background
64c7ee7e 1767 GenerateBitcoins(fGenerateBitcoins, pwalletMain);
0a61b0df 1768}
1769
1770bool StopNode()
1771{
1772 printf("StopNode()\n");
1773 fShutdown = true;
1774 nTransactionsUpdated++;
bde280b9 1775 int64 nStart = GetTime();
cc201e01 1776 while (vnThreadsRunning[0] > 0 || vnThreadsRunning[1] > 0 || vnThreadsRunning[2] > 0 || vnThreadsRunning[3] > 0 || vnThreadsRunning[4] > 0
10ba0a3e 1777 || (fHaveUPnP && vnThreadsRunning[5] > 0) || vnThreadsRunning[6] > 0 || vnThreadsRunning[7] > 0
8bb5edc1 1778 )
0a61b0df 1779 {
1780 if (GetTime() - nStart > 20)
1781 break;
1782 Sleep(20);
1783 }
1784 if (vnThreadsRunning[0] > 0) printf("ThreadSocketHandler still running\n");
1785 if (vnThreadsRunning[1] > 0) printf("ThreadOpenConnections still running\n");
1786 if (vnThreadsRunning[2] > 0) printf("ThreadMessageHandler still running\n");
1787 if (vnThreadsRunning[3] > 0) printf("ThreadBitcoinMiner still running\n");
1788 if (vnThreadsRunning[4] > 0) printf("ThreadRPCServer still running\n");
8bb5edc1 1789 if (fHaveUPnP && vnThreadsRunning[5] > 0) printf("ThreadMapPort still running\n");
2bc6cece 1790 if (vnThreadsRunning[6] > 0) printf("ThreadDNSAddressSeed still running\n");
b24e6e4d 1791 if (vnThreadsRunning[7] > 0) printf("ThreadOpenAddedConnections still running\n");
0a61b0df 1792 while (vnThreadsRunning[2] > 0 || vnThreadsRunning[4] > 0)
1793 Sleep(20);
1794 Sleep(50);
1795
1796 return true;
1797}
1798
1799class CNetCleanup
1800{
1801public:
1802 CNetCleanup()
1803 {
1804 }
1805 ~CNetCleanup()
1806 {
1807 // Close sockets
223b6f1b 1808 BOOST_FOREACH(CNode* pnode, vNodes)
0a61b0df 1809 if (pnode->hSocket != INVALID_SOCKET)
1810 closesocket(pnode->hSocket);
1811 if (hListenSocket != INVALID_SOCKET)
1812 if (closesocket(hListenSocket) == SOCKET_ERROR)
1813 printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
1814
6853e627 1815#ifdef WIN32
0a61b0df 1816 // Shutdown Windows Sockets
1817 WSACleanup();
1818#endif
1819 }
1820}
1821instance_of_cnetcleanup;
This page took 0.351016 seconds and 4 git commands to generate.