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