]> Git Repo - VerusCoin.git/blame - src/net.cpp
Merge pull request #3104 from Diapolo/rpcssl-defaultciphers
[VerusCoin.git] / src / net.cpp
CommitLineData
0a61b0df 1// Copyright (c) 2009-2010 Satoshi Nakamoto
db0e8ccd 2// Copyright (c) 2009-2013 The Bitcoin developers
0a61b0df 3// Distributed under the MIT/X11 software license, see the accompanying
3a25a2b9 4// file COPYING or http://www.opensource.org/licenses/mit-license.php.
0a61b0df 5
35b8af92
CF
6#if defined(HAVE_CONFIG_H)
7#include "bitcoin-config.h"
8#endif
9
0e4b3175 10#include "chainparams.h"
1512d5ce 11#include "db.h"
40c2614e 12#include "net.h"
6e68524e 13#include "core.h"
5fee401f 14#include "addrman.h"
ed6d0b5f 15#include "ui_interface.h"
269d9c64 16#include "script.h"
0a61b0df 17
6853e627 18#ifdef WIN32
013df1cc
MC
19#include <string.h>
20#endif
21
98148a71 22#ifndef WIN32
23#include <fcntl.h>
24#endif
25
8bb5edc1
MC
26#ifdef USE_UPNP
27#include <miniupnpc/miniwget.h>
28#include <miniupnpc/miniupnpc.h>
29#include <miniupnpc/upnpcommands.h>
30#include <miniupnpc/upnperrors.h>
31#endif
32
c43da3f1
PW
33// Dump addresses to peers.dat every 15 minutes (900s)
34#define DUMP_ADDRESSES_INTERVAL 900
35b8af92
CF
35#if !defined(HAVE_MSG_NOSIGNAL)
36#define MSG_NOSIGNAL 0
37#endif
c43da3f1 38
223b6f1b
WL
39using namespace std;
40using namespace boost;
41
0a61b0df 42static const int MAX_OUTBOUND_CONNECTIONS = 8;
43
c59abe25 44bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false);
0a61b0df 45
46
139d2f7c
PW
47struct LocalServiceInfo {
48 int nScore;
49 int nPort;
50};
0a61b0df 51
0a61b0df 52//
53// Global state variables
54//
587f929c 55bool fDiscover = true;
c2b72ba2 56uint64 nLocalServices = NODE_NETWORK;
090e5b40 57static CCriticalSection cs_mapLocalHost;
139d2f7c 58static map<CNetAddr, LocalServiceInfo> mapLocalHost;
090e5b40 59static bool vfReachable[NET_MAX] = {};
457754d2 60static bool vfLimited[NET_MAX] = {};
99860de3 61static CNode* pnodeLocalHost = NULL;
6ed71b5e 62static CNode* pnodeSync = NULL;
bde280b9 63uint64 nLocalHostNonce = 0;
8f10a288 64static std::vector<SOCKET> vhListenSocket;
5fee401f 65CAddrMan addrman;
ba29a559 66int nMaxConnections = 125;
0a61b0df 67
68vector<CNode*> vNodes;
69CCriticalSection cs_vNodes;
0a61b0df 70map<CInv, CDataStream> mapRelay;
bde280b9 71deque<pair<int64, CInv> > vRelayExpiration;
0a61b0df 72CCriticalSection cs_mapRelay;
b5afda67 73limitedmap<CInv, int64> mapAlreadyAskedFor(MAX_INV_SZ);
0a61b0df 74
478b01d9
PW
75static deque<string> vOneShots;
76CCriticalSection cs_vOneShots;
0a61b0df 77
b24e6e4d
MC
78set<CNetAddr> setservAddNodeAddresses;
79CCriticalSection cs_setservAddNodeAddresses;
80
74088e86
MC
81vector<std::string> vAddedNodes;
82CCriticalSection cs_vAddedNodes;
83
c59abe25 84static CSemaphore *semOutbound = NULL;
0a61b0df 85
501da250
EL
86// Signals for message handling
87static CNodeSignals g_signals;
88CNodeSignals& GetNodeSignals() { return g_signals; }
663224c2 89
478b01d9
PW
90void AddOneShot(string strDest)
91{
92 LOCK(cs_vOneShots);
93 vOneShots.push_back(strDest);
94}
95
00bcfe0b
GA
96unsigned short GetListenPort()
97{
0e4b3175 98 return (unsigned short)(GetArg("-port", Params().GetDefaultPort()));
00bcfe0b 99}
0a61b0df 100
39857190 101// find 'best' local address for a particular peer
7fa4443f 102bool GetLocal(CService& addr, const CNetAddr *paddrPeer)
39857190 103{
587f929c 104 if (fNoListen)
39857190 105 return false;
0a61b0df 106
139d2f7c 107 int nBestScore = -1;
39857190
PW
108 int nBestReachability = -1;
109 {
110 LOCK(cs_mapLocalHost);
139d2f7c 111 for (map<CNetAddr, LocalServiceInfo>::iterator it = mapLocalHost.begin(); it != mapLocalHost.end(); it++)
39857190 112 {
139d2f7c 113 int nScore = (*it).second.nScore;
39857190 114 int nReachability = (*it).first.GetReachabilityFrom(paddrPeer);
139d2f7c 115 if (nReachability > nBestReachability || (nReachability == nBestReachability && nScore > nBestScore))
39857190 116 {
139d2f7c 117 addr = CService((*it).first, (*it).second.nPort);
39857190 118 nBestReachability = nReachability;
139d2f7c 119 nBestScore = nScore;
39857190
PW
120 }
121 }
122 }
139d2f7c 123 return nBestScore >= 0;
39857190 124}
0a61b0df 125
39857190
PW
126// get best local address for a particular peer as a CAddress
127CAddress GetLocalAddress(const CNetAddr *paddrPeer)
128{
129 CAddress ret(CService("0.0.0.0",0),0);
7fa4443f 130 CService addr;
39857190
PW
131 if (GetLocal(addr, paddrPeer))
132 {
7fa4443f 133 ret = CAddress(addr);
39857190
PW
134 ret.nServices = nLocalServices;
135 ret.nTime = GetAdjustedTime();
136 }
137 return ret;
138}
0a61b0df 139
a3342d09
PW
140bool RecvLine(SOCKET hSocket, string& strLine)
141{
142 strLine = "";
050d2e95 143 while (true)
a3342d09
PW
144 {
145 char c;
146 int nBytes = recv(hSocket, &c, 1, 0);
147 if (nBytes > 0)
148 {
149 if (c == '\n')
150 continue;
151 if (c == '\r')
152 return true;
153 strLine += c;
154 if (strLine.size() >= 9000)
155 return true;
156 }
157 else if (nBytes <= 0)
158 {
b31499ec 159 boost::this_thread::interruption_point();
a3342d09
PW
160 if (nBytes < 0)
161 {
162 int nErr = WSAGetLastError();
163 if (nErr == WSAEMSGSIZE)
164 continue;
165 if (nErr == WSAEWOULDBLOCK || nErr == WSAEINTR || nErr == WSAEINPROGRESS)
166 {
1b43bf0d 167 MilliSleep(10);
a3342d09
PW
168 continue;
169 }
170 }
171 if (!strLine.empty())
172 return true;
173 if (nBytes == 0)
174 {
175 // socket closed
881a85a2 176 LogPrint("net", "socket closed\n");
a3342d09
PW
177 return false;
178 }
179 else
180 {
181 // socket error
182 int nErr = WSAGetLastError();
881a85a2 183 LogPrint("net", "recv failed: %d\n", nErr);
a3342d09
PW
184 return false;
185 }
186 }
187 }
188}
189
39857190
PW
190// used when scores of local addresses may have changed
191// pushes better local address to peers
192void static AdvertizeLocal()
193{
194 LOCK(cs_vNodes);
195 BOOST_FOREACH(CNode* pnode, vNodes)
196 {
197 if (pnode->fSuccessfullyConnected)
198 {
199 CAddress addrLocal = GetLocalAddress(&pnode->addr);
7fa4443f 200 if (addrLocal.IsRoutable() && (CService)addrLocal != (CService)pnode->addrLocal)
39857190
PW
201 {
202 pnode->PushAddress(addrLocal);
203 pnode->addrLocal = addrLocal;
204 }
205 }
206 }
207}
208
54ce3bad
PW
209void SetReachable(enum Network net, bool fFlag)
210{
211 LOCK(cs_mapLocalHost);
212 vfReachable[net] = fFlag;
213 if (net == NET_IPV6 && fFlag)
214 vfReachable[NET_IPV4] = true;
215}
216
39857190 217// learn a new local address
7fa4443f 218bool AddLocal(const CService& addr, int nScore)
39857190
PW
219{
220 if (!addr.IsRoutable())
221 return false;
222
587f929c 223 if (!fDiscover && nScore < LOCAL_MANUAL)
af4006b3
PW
224 return false;
225
09b4e26a 226 if (IsLimited(addr))
1653f97c
PW
227 return false;
228
881a85a2 229 LogPrintf("AddLocal(%s,%i)\n", addr.ToString().c_str(), nScore);
39857190
PW
230
231 {
232 LOCK(cs_mapLocalHost);
139d2f7c
PW
233 bool fAlready = mapLocalHost.count(addr) > 0;
234 LocalServiceInfo &info = mapLocalHost[addr];
235 if (!fAlready || nScore >= info.nScore) {
af4da4be
PW
236 info.nScore = nScore + (fAlready ? 1 : 0);
237 info.nPort = addr.GetPort();
139d2f7c 238 }
54ce3bad 239 SetReachable(addr.GetNetwork());
39857190
PW
240 }
241
242 AdvertizeLocal();
243
244 return true;
245}
246
5a3cb32e 247bool AddLocal(const CNetAddr &addr, int nScore)
7fa4443f 248{
5a3cb32e 249 return AddLocal(CService(addr, GetListenPort()), nScore);
7fa4443f
PW
250}
251
457754d2
PW
252/** Make a particular network entirely off-limits (no automatic connects to it) */
253void SetLimited(enum Network net, bool fLimited)
254{
0f1707de
PW
255 if (net == NET_UNROUTABLE)
256 return;
457754d2
PW
257 LOCK(cs_mapLocalHost);
258 vfLimited[net] = fLimited;
259}
260
0f1707de 261bool IsLimited(enum Network net)
457754d2
PW
262{
263 LOCK(cs_mapLocalHost);
0f1707de
PW
264 return vfLimited[net];
265}
266
267bool IsLimited(const CNetAddr &addr)
268{
269 return IsLimited(addr.GetNetwork());
457754d2
PW
270}
271
272/** vote for a local address */
7fa4443f 273bool SeenLocal(const CService& addr)
39857190
PW
274{
275 {
276 LOCK(cs_mapLocalHost);
277 if (mapLocalHost.count(addr) == 0)
278 return false;
139d2f7c 279 mapLocalHost[addr].nScore++;
39857190
PW
280 }
281
282 AdvertizeLocal();
283
284 return true;
285}
286
457754d2 287/** check whether a given address is potentially local */
7fa4443f 288bool IsLocal(const CService& addr)
39857190
PW
289{
290 LOCK(cs_mapLocalHost);
291 return mapLocalHost.count(addr) > 0;
292}
0a61b0df 293
457754d2 294/** check whether a given address is in a network we can probably connect to */
090e5b40
PW
295bool IsReachable(const CNetAddr& addr)
296{
297 LOCK(cs_mapLocalHost);
457754d2
PW
298 enum Network net = addr.GetNetwork();
299 return vfReachable[net] && !vfLimited[net];
090e5b40 300}
0a61b0df 301
67a42f92 302bool GetMyExternalIP2(const CService& addrConnect, const char* pszGet, const char* pszKeyword, CNetAddr& ipRet)
0a61b0df 303{
304 SOCKET hSocket;
305 if (!ConnectSocket(addrConnect, hSocket))
306 return error("GetMyExternalIP() : connection to %s failed", addrConnect.ToString().c_str());
307
308 send(hSocket, pszGet, strlen(pszGet), MSG_NOSIGNAL);
309
310 string strLine;
311 while (RecvLine(hSocket, strLine))
312 {
222e3de4 313 if (strLine.empty()) // HTTP response is separated from headers by blank line
0a61b0df 314 {
050d2e95 315 while (true)
0a61b0df 316 {
317 if (!RecvLine(hSocket, strLine))
318 {
319 closesocket(hSocket);
320 return false;
321 }
222e3de4 322 if (pszKeyword == NULL)
323 break;
ab9dc75a 324 if (strLine.find(pszKeyword) != string::npos)
0a61b0df 325 {
326 strLine = strLine.substr(strLine.find(pszKeyword) + strlen(pszKeyword));
327 break;
328 }
329 }
330 closesocket(hSocket);
ab9dc75a 331 if (strLine.find("<") != string::npos)
0a61b0df 332 strLine = strLine.substr(0, strLine.find("<"));
333 strLine = strLine.substr(strspn(strLine.c_str(), " \t\n\r"));
334 while (strLine.size() > 0 && isspace(strLine[strLine.size()-1]))
335 strLine.resize(strLine.size()-1);
67a42f92 336 CService addr(strLine,0,true);
881a85a2 337 LogPrintf("GetMyExternalIP() received [%s] %s\n", strLine.c_str(), addr.ToString().c_str());
67a42f92 338 if (!addr.IsValid() || !addr.IsRoutable())
0a61b0df 339 return false;
67a42f92 340 ipRet.SetIP(addr);
0a61b0df 341 return true;
342 }
343 }
344 closesocket(hSocket);
345 return error("GetMyExternalIP() : connection closed");
346}
347
67a42f92 348bool GetMyExternalIP(CNetAddr& ipRet)
0a61b0df 349{
c981d768 350 CService addrConnect;
0a61b0df 351 const char* pszGet;
352 const char* pszKeyword;
353
0a61b0df 354 for (int nLookup = 0; nLookup <= 1; nLookup++)
355 for (int nHost = 1; nHost <= 2; nHost++)
356 {
b001c871 357 // We should be phasing out our use of sites like these. If we need
629e37dd 358 // replacements, we should ask for volunteers to put this simple
814efd6f 359 // php file on their web server that prints the client IP:
629e37dd 360 // <?php echo $_SERVER["REMOTE_ADDR"]; ?>
0a61b0df 361 if (nHost == 1)
362 {
b001c871 363 addrConnect = CService("91.198.22.70", 80); // checkip.dyndns.org
0a61b0df 364
365 if (nLookup == 1)
366 {
67a42f92 367 CService addrIP("checkip.dyndns.org", 80, true);
a6a5bb7c
PW
368 if (addrIP.IsValid())
369 addrConnect = addrIP;
0a61b0df 370 }
371
683bcb91 372 pszGet = "GET / HTTP/1.1\r\n"
373 "Host: checkip.dyndns.org\r\n"
374 "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
0a61b0df 375 "Connection: close\r\n"
376 "\r\n";
377
683bcb91 378 pszKeyword = "Address:";
0a61b0df 379 }
380 else if (nHost == 2)
381 {
c981d768 382 addrConnect = CService("74.208.43.192", 80); // www.showmyip.com
0a61b0df 383
384 if (nLookup == 1)
385 {
67a42f92 386 CService addrIP("www.showmyip.com", 80, true);
a6a5bb7c
PW
387 if (addrIP.IsValid())
388 addrConnect = addrIP;
0a61b0df 389 }
390
683bcb91 391 pszGet = "GET /simple/ HTTP/1.1\r\n"
392 "Host: www.showmyip.com\r\n"
0a61b0df 393 "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
394 "Connection: close\r\n"
395 "\r\n";
396
683bcb91 397 pszKeyword = NULL; // Returns just IP address
0a61b0df 398 }
399
400 if (GetMyExternalIP2(addrConnect, pszGet, pszKeyword, ipRet))
401 return true;
402 }
403
404 return false;
405}
406
53e71135 407void ThreadGetMyExternalIP()
629e37dd 408{
39857190 409 CNetAddr addrLocalHost;
67a42f92 410 if (GetMyExternalIP(addrLocalHost))
629e37dd 411 {
881a85a2 412 LogPrintf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
39857190 413 AddLocal(addrLocalHost, LOCAL_HTTP);
629e37dd 414 }
415}
416
0a61b0df 417
418
419
420
67a42f92 421void AddressCurrentlyConnected(const CService& addr)
0a61b0df 422{
5fee401f 423 addrman.Connected(addr);
0a61b0df 424}
425
426
427
428
ce14345a
SE
429uint64 CNode::nTotalBytesRecv = 0;
430uint64 CNode::nTotalBytesSent = 0;
431CCriticalSection CNode::cs_totalBytesRecv;
432CCriticalSection CNode::cs_totalBytesSent;
0a61b0df 433
67a42f92 434CNode* FindNode(const CNetAddr& ip)
0a61b0df 435{
b001c871
PK
436 LOCK(cs_vNodes);
437 BOOST_FOREACH(CNode* pnode, vNodes)
438 if ((CNetAddr)pnode->addr == ip)
439 return (pnode);
0a61b0df 440 return NULL;
441}
442
9bab521d
PW
443CNode* FindNode(std::string addrName)
444{
445 LOCK(cs_vNodes);
446 BOOST_FOREACH(CNode* pnode, vNodes)
447 if (pnode->addrName == addrName)
448 return (pnode);
449 return NULL;
450}
451
67a42f92 452CNode* FindNode(const CService& addr)
0a61b0df 453{
b001c871
PK
454 LOCK(cs_vNodes);
455 BOOST_FOREACH(CNode* pnode, vNodes)
456 if ((CService)pnode->addr == addr)
457 return (pnode);
0a61b0df 458 return NULL;
459}
460
cedaa714 461CNode* ConnectNode(CAddress addrConnect, const char *pszDest)
0a61b0df 462{
478b01d9 463 if (pszDest == NULL) {
39857190 464 if (IsLocal(addrConnect))
9bab521d 465 return NULL;
0a61b0df 466
9bab521d
PW
467 // Look for an existing connection
468 CNode* pnode = FindNode((CService)addrConnect);
469 if (pnode)
470 {
cedaa714 471 pnode->AddRef();
9bab521d
PW
472 return pnode;
473 }
0a61b0df 474 }
475
9bab521d 476
0a61b0df 477 /// debug print
881a85a2 478 LogPrint("net", "trying connection %s lastseen=%.1fhrs\n",
9bab521d 479 pszDest ? pszDest : addrConnect.ToString().c_str(),
83e047ea 480 pszDest ? 0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0);
0a61b0df 481
482 // Connect
483 SOCKET hSocket;
0e4b3175 484 if (pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, Params().GetDefaultPort()) : ConnectSocket(addrConnect, hSocket))
0a61b0df 485 {
9bab521d
PW
486 addrman.Attempt(addrConnect);
487
881a85a2 488 LogPrint("net", "connected %s\n", pszDest ? pszDest : addrConnect.ToString().c_str());
0a61b0df 489
814efd6f 490 // Set to non-blocking
6853e627 491#ifdef WIN32
0a61b0df 492 u_long nOne = 1;
493 if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
881a85a2 494 LogPrintf("ConnectSocket() : ioctlsocket non-blocking setting failed, error %d\n", WSAGetLastError());
0a61b0df 495#else
496 if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
881a85a2 497 LogPrintf("ConnectSocket() : fcntl non-blocking setting failed, error %d\n", errno);
0a61b0df 498#endif
499
500 // Add node
9bab521d 501 CNode* pnode = new CNode(hSocket, addrConnect, pszDest ? pszDest : "", false);
cedaa714 502 pnode->AddRef();
9bab521d 503
f8dcd5ca
PW
504 {
505 LOCK(cs_vNodes);
0a61b0df 506 vNodes.push_back(pnode);
f8dcd5ca 507 }
0a61b0df 508
509 pnode->nTimeConnected = GetTime();
510 return pnode;
511 }
512 else
513 {
514 return NULL;
515 }
516}
517
518void CNode::CloseSocketDisconnect()
519{
520 fDisconnect = true;
521 if (hSocket != INVALID_SOCKET)
522 {
881a85a2 523 LogPrint("net", "disconnecting node %s\n", addrName.c_str());
0a61b0df 524 closesocket(hSocket);
525 hSocket = INVALID_SOCKET;
526 }
6ed71b5e
PW
527
528 // in case this fails, we'll empty the recv buffer when the CNode is deleted
529 TRY_LOCK(cs_vRecvMsg, lockRecv);
530 if (lockRecv)
531 vRecvMsg.clear();
532
533 // if this was the sync node, we'll need a new one
534 if (this == pnodeSync)
535 pnodeSync = NULL;
0a61b0df 536}
537
538void CNode::Cleanup()
539{
0a61b0df 540}
541
542
f8ded588
GA
543void CNode::PushVersion()
544{
4c6d41b8
PW
545 int nBestHeight = g_signals.GetHeight().get_value_or(0);
546
f8ded588 547 /// when NTP implemented, change to just nTime = GetAdjustedTime()
bde280b9 548 int64 nTime = (fInbound ? GetAdjustedTime() : GetTime());
587f929c 549 CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0",0)));
39857190 550 CAddress addrMe = GetLocalAddress(&addr);
f8ded588 551 RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
881a85a2 552 LogPrint("net", "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%s\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString().c_str(), addrYou.ToString().c_str(), addr.ToString().c_str());
f8ded588 553 PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
c87f462b 554 nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()), nBestHeight, true);
f8ded588
GA
555}
556
557
558
559
560
67a42f92 561std::map<CNetAddr, int64> CNode::setBanned;
15f3ad4d
GA
562CCriticalSection CNode::cs_setBanned;
563
564void CNode::ClearBanned()
565{
566 setBanned.clear();
567}
568
67a42f92 569bool CNode::IsBanned(CNetAddr ip)
15f3ad4d
GA
570{
571 bool fResult = false;
15f3ad4d 572 {
f8dcd5ca 573 LOCK(cs_setBanned);
67a42f92 574 std::map<CNetAddr, int64>::iterator i = setBanned.find(ip);
15f3ad4d
GA
575 if (i != setBanned.end())
576 {
bde280b9 577 int64 t = (*i).second;
15f3ad4d
GA
578 if (GetTime() < t)
579 fResult = true;
580 }
581 }
582 return fResult;
583}
584
585bool CNode::Misbehaving(int howmuch)
586{
587 if (addr.IsLocal())
588 {
881a85a2 589 LogPrintf("Warning: Local node %s misbehaving (delta: %d)!\n", addrName.c_str(), howmuch);
15f3ad4d
GA
590 return false;
591 }
592
593 nMisbehavior += howmuch;
594 if (nMisbehavior >= GetArg("-banscore", 100))
595 {
bde280b9 596 int64 banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban
881a85a2 597 LogPrintf("Misbehaving: %s (%d -> %d) DISCONNECTING\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
f8dcd5ca
PW
598 {
599 LOCK(cs_setBanned);
67a42f92
PW
600 if (setBanned[addr] < banTime)
601 setBanned[addr] = banTime;
f8dcd5ca 602 }
15f3ad4d 603 CloseSocketDisconnect();
15f3ad4d 604 return true;
90c838da 605 } else
881a85a2 606 LogPrintf("Misbehaving: %s (%d -> %d)\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
15f3ad4d
GA
607 return false;
608}
609
1006f070
JG
610#undef X
611#define X(name) stats.name = name
612void CNode::copyStats(CNodeStats &stats)
613{
614 X(nServices);
615 X(nLastSend);
616 X(nLastRecv);
617 X(nTimeConnected);
618 X(addrName);
619 X(nVersion);
620 X(strSubVer);
621 X(fInbound);
1006f070
JG
622 X(nStartingHeight);
623 X(nMisbehavior);
86648a8d
PW
624 X(nSendBytes);
625 X(nRecvBytes);
626 stats.fSyncNode = (this == pnodeSync);
971bb3e9
JL
627
628 // It is common for nodes with good ping times to suddenly become lagged,
629 // due to a new block arriving or other large transfer.
630 // Merely reporting pingtime might fool the caller into thinking the node was still responsive,
631 // since pingtime does not update until the ping is complete, which might take a while.
632 // So, if a ping is taking an unusually long time in flight,
633 // the caller can immediately detect that this is happening.
634 int64 nPingUsecWait = 0;
635 if ((0 != nPingNonceSent) && (0 != nPingUsecStart)) {
636 nPingUsecWait = GetTimeMicros() - nPingUsecStart;
637 }
638
639 // Raw ping time is in microseconds, but show it to user as whole seconds (Bitcoin users should be well used to small numbers with many decimal places by now :)
640 stats.dPingTime = (((double)nPingUsecTime) / 1e6);
641 stats.dPingWait = (((double)nPingUsecWait) / 1e6);
1006f070
JG
642}
643#undef X
0a61b0df 644
607dbfde
JG
645// requires LOCK(cs_vRecvMsg)
646bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes)
647{
648 while (nBytes > 0) {
649
650 // get current incomplete message, or create a new one
967f2459 651 if (vRecvMsg.empty() ||
607dbfde
JG
652 vRecvMsg.back().complete())
653 vRecvMsg.push_back(CNetMessage(SER_NETWORK, nRecvVersion));
654
655 CNetMessage& msg = vRecvMsg.back();
656
657 // absorb network data
658 int handled;
659 if (!msg.in_data)
660 handled = msg.readHeader(pch, nBytes);
661 else
662 handled = msg.readData(pch, nBytes);
663
664 if (handled < 0)
665 return false;
666
667 pch += handled;
668 nBytes -= handled;
669 }
670
671 return true;
672}
673
674int CNetMessage::readHeader(const char *pch, unsigned int nBytes)
675{
676 // copy data to temporary parsing buffer
677 unsigned int nRemaining = 24 - nHdrPos;
678 unsigned int nCopy = std::min(nRemaining, nBytes);
679
680 memcpy(&hdrbuf[nHdrPos], pch, nCopy);
681 nHdrPos += nCopy;
682
683 // if header incomplete, exit
684 if (nHdrPos < 24)
685 return nCopy;
686
687 // deserialize to CMessageHeader
688 try {
689 hdrbuf >> hdr;
690 }
691 catch (std::exception &e) {
692 return -1;
693 }
694
695 // reject messages larger than MAX_SIZE
696 if (hdr.nMessageSize > MAX_SIZE)
697 return -1;
698
699 // switch state to reading message data
700 in_data = true;
701 vRecv.resize(hdr.nMessageSize);
702
703 return nCopy;
704}
705
706int CNetMessage::readData(const char *pch, unsigned int nBytes)
707{
708 unsigned int nRemaining = hdr.nMessageSize - nDataPos;
709 unsigned int nCopy = std::min(nRemaining, nBytes);
710
711 memcpy(&vRecv[nDataPos], pch, nCopy);
712 nDataPos += nCopy;
713
714 return nCopy;
715}
716
0a61b0df 717
718
719
720
721
722
723
724
bc2f5aa7
JG
725// requires LOCK(cs_vSend)
726void SocketSendData(CNode *pnode)
727{
41b052ad
PW
728 std::deque<CSerializeData>::iterator it = pnode->vSendMsg.begin();
729
730 while (it != pnode->vSendMsg.end()) {
731 const CSerializeData &data = *it;
732 assert(data.size() > pnode->nSendOffset);
733 int nBytes = send(pnode->hSocket, &data[pnode->nSendOffset], data.size() - pnode->nSendOffset, MSG_NOSIGNAL | MSG_DONTWAIT);
734 if (nBytes > 0) {
735 pnode->nLastSend = GetTime();
86648a8d 736 pnode->nSendBytes += nBytes;
41b052ad 737 pnode->nSendOffset += nBytes;
ce14345a 738 pnode->RecordBytesSent(nBytes);
41b052ad
PW
739 if (pnode->nSendOffset == data.size()) {
740 pnode->nSendOffset = 0;
741 pnode->nSendSize -= data.size();
742 it++;
743 } else {
744 // could not send full message; stop sending more
745 break;
746 }
747 } else {
748 if (nBytes < 0) {
749 // error
750 int nErr = WSAGetLastError();
751 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
752 {
881a85a2 753 LogPrintf("socket send error %d\n", nErr);
41b052ad
PW
754 pnode->CloseSocketDisconnect();
755 }
756 }
757 // couldn't send anything at all
758 break;
bc2f5aa7
JG
759 }
760 }
41b052ad
PW
761
762 if (it == pnode->vSendMsg.end()) {
763 assert(pnode->nSendOffset == 0);
764 assert(pnode->nSendSize == 0);
765 }
766 pnode->vSendMsg.erase(pnode->vSendMsg.begin(), it);
bc2f5aa7 767}
0a61b0df 768
3427517d
PW
769static list<CNode*> vNodesDisconnected;
770
21eb5ada 771void ThreadSocketHandler()
0a61b0df 772{
735a6069 773 unsigned int nPrevNodeCount = 0;
050d2e95 774 while (true)
0a61b0df 775 {
776 //
777 // Disconnect nodes
778 //
0a61b0df 779 {
f8dcd5ca 780 LOCK(cs_vNodes);
0a61b0df 781 // Disconnect unused nodes
782 vector<CNode*> vNodesCopy = vNodes;
223b6f1b 783 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 784 {
785 if (pnode->fDisconnect ||
41b052ad 786 (pnode->GetRefCount() <= 0 && pnode->vRecvMsg.empty() && pnode->nSendSize == 0 && pnode->ssSend.empty()))
0a61b0df 787 {
788 // remove from vNodes
789 vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
790
c59abe25
PW
791 // release outbound grant (if any)
792 pnode->grantOutbound.Release();
092631f0 793
0a61b0df 794 // close socket and cleanup
795 pnode->CloseSocketDisconnect();
796 pnode->Cleanup();
797
798 // hold in disconnected pool until all refs are released
0a61b0df 799 if (pnode->fNetworkNode || pnode->fInbound)
800 pnode->Release();
801 vNodesDisconnected.push_back(pnode);
802 }
803 }
49d754d9
PW
804 }
805 {
0a61b0df 806 // Delete disconnected nodes
807 list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
223b6f1b 808 BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy)
0a61b0df 809 {
810 // wait until threads are done using it
811 if (pnode->GetRefCount() <= 0)
812 {
813 bool fDelete = false;
f8dcd5ca
PW
814 {
815 TRY_LOCK(pnode->cs_vSend, lockSend);
816 if (lockSend)
817 {
607dbfde 818 TRY_LOCK(pnode->cs_vRecvMsg, lockRecv);
f8dcd5ca
PW
819 if (lockRecv)
820 {
529a4d48
WL
821 TRY_LOCK(pnode->cs_inventory, lockInv);
822 if (lockInv)
823 fDelete = true;
f8dcd5ca
PW
824 }
825 }
826 }
0a61b0df 827 if (fDelete)
828 {
829 vNodesDisconnected.remove(pnode);
830 delete pnode;
831 }
832 }
833 }
834 }
ce14345a 835 if(vNodes.size() != nPrevNodeCount) {
0a61b0df 836 nPrevNodeCount = vNodes.size();
ce14345a 837 uiInterface.NotifyNumConnectionsChanged(nPrevNodeCount);
0a61b0df 838 }
839
840
841 //
842 // Find which sockets have data to receive
843 //
844 struct timeval timeout;
845 timeout.tv_sec = 0;
846 timeout.tv_usec = 50000; // frequency to poll pnode->vSend
847
848 fd_set fdsetRecv;
849 fd_set fdsetSend;
850 fd_set fdsetError;
851 FD_ZERO(&fdsetRecv);
852 FD_ZERO(&fdsetSend);
853 FD_ZERO(&fdsetError);
854 SOCKET hSocketMax = 0;
23879447 855 bool have_fds = false;
5f88e888 856
8f10a288 857 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket) {
5f88e888 858 FD_SET(hListenSocket, &fdsetRecv);
8f10a288 859 hSocketMax = max(hSocketMax, hListenSocket);
23879447 860 have_fds = true;
8f10a288 861 }
0a61b0df 862 {
f8dcd5ca 863 LOCK(cs_vNodes);
223b6f1b 864 BOOST_FOREACH(CNode* pnode, vNodes)
0a61b0df 865 {
d7f1d200 866 if (pnode->hSocket == INVALID_SOCKET)
0a61b0df 867 continue;
a9d9f0f5
PW
868 FD_SET(pnode->hSocket, &fdsetError);
869 hSocketMax = max(hSocketMax, pnode->hSocket);
870 have_fds = true;
871
872 // Implement the following logic:
873 // * If there is data to send, select() for sending data. As this only
874 // happens when optimistic write failed, we choose to first drain the
875 // write buffer in this case before receiving more. This avoids
876 // needlessly queueing received data, if the remote peer is not themselves
877 // receiving data. This means properly utilizing TCP flow control signalling.
878 // * Otherwise, if there is no (complete) message in the receive buffer,
879 // or there is space left in the buffer, select() for receiving data.
880 // * (if neither of the above applies, there is certainly one message
881 // in the receiver buffer ready to be processed).
882 // Together, that means that at least one of the following is always possible,
883 // so we don't deadlock:
884 // * We send some data.
885 // * We wait for data to be received (and disconnect after timeout).
886 // * We process a message in the buffer (message handler thread).
f8dcd5ca
PW
887 {
888 TRY_LOCK(pnode->cs_vSend, lockSend);
a9d9f0f5
PW
889 if (lockSend && !pnode->vSendMsg.empty()) {
890 FD_SET(pnode->hSocket, &fdsetSend);
891 continue;
b9ff2970 892 }
f8dcd5ca 893 }
a9d9f0f5
PW
894 {
895 TRY_LOCK(pnode->cs_vRecvMsg, lockRecv);
896 if (lockRecv && (
897 pnode->vRecvMsg.empty() || !pnode->vRecvMsg.front().complete() ||
898 pnode->GetTotalRecvSize() <= ReceiveFloodSize()))
899 FD_SET(pnode->hSocket, &fdsetRecv);
900 }
0a61b0df 901 }
902 }
903
23879447
JG
904 int nSelect = select(have_fds ? hSocketMax + 1 : 0,
905 &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
21eb5ada
GA
906 boost::this_thread::interruption_point();
907
0a61b0df 908 if (nSelect == SOCKET_ERROR)
909 {
23879447 910 if (have_fds)
c6710c7a 911 {
23879447 912 int nErr = WSAGetLastError();
881a85a2 913 LogPrintf("socket select error %d\n", nErr);
c376ac35 914 for (unsigned int i = 0; i <= hSocketMax; i++)
c6710c7a
MC
915 FD_SET(i, &fdsetRecv);
916 }
0a61b0df 917 FD_ZERO(&fdsetSend);
918 FD_ZERO(&fdsetError);
1b43bf0d 919 MilliSleep(timeout.tv_usec/1000);
0a61b0df 920 }
921
922
923 //
924 // Accept new connections
925 //
8f10a288 926 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
5f88e888 927 if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
0a61b0df 928 {
23aa78c4 929#ifdef USE_IPV6
8f10a288 930 struct sockaddr_storage sockaddr;
23aa78c4 931#else
8f10a288 932 struct sockaddr sockaddr;
23aa78c4 933#endif
0a61b0df 934 socklen_t len = sizeof(sockaddr);
935 SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
25ab1758 936 CAddress addr;
4698dd9a
CM
937 int nInbound = 0;
938
25ab1758 939 if (hSocket != INVALID_SOCKET)
8f10a288 940 if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
881a85a2 941 LogPrintf("Warning: Unknown socket family\n");
25ab1758 942
f8dcd5ca
PW
943 {
944 LOCK(cs_vNodes);
223b6f1b 945 BOOST_FOREACH(CNode* pnode, vNodes)
f8dcd5ca
PW
946 if (pnode->fInbound)
947 nInbound++;
948 }
25ab1758 949
0a61b0df 950 if (hSocket == INVALID_SOCKET)
951 {
4bd34b49
PK
952 int nErr = WSAGetLastError();
953 if (nErr != WSAEWOULDBLOCK)
881a85a2 954 LogPrintf("socket error accept failed: %d\n", nErr);
0a61b0df 955 }
ba29a559 956 else if (nInbound >= nMaxConnections - MAX_OUTBOUND_CONNECTIONS)
0a61b0df 957 {
f8dcd5ca
PW
958 {
959 LOCK(cs_setservAddNodeAddresses);
b24e6e4d
MC
960 if (!setservAddNodeAddresses.count(addr))
961 closesocket(hSocket);
f8dcd5ca 962 }
0a61b0df 963 }
67a42f92 964 else if (CNode::IsBanned(addr))
15f3ad4d 965 {
881a85a2 966 LogPrintf("connection from %s dropped (banned)\n", addr.ToString().c_str());
15f3ad4d
GA
967 closesocket(hSocket);
968 }
0a61b0df 969 else
970 {
881a85a2 971 LogPrint("net", "accepted connection %s\n", addr.ToString().c_str());
9bab521d 972 CNode* pnode = new CNode(hSocket, addr, "", true);
0a61b0df 973 pnode->AddRef();
f8dcd5ca
PW
974 {
975 LOCK(cs_vNodes);
0a61b0df 976 vNodes.push_back(pnode);
f8dcd5ca 977 }
0a61b0df 978 }
979 }
980
981
982 //
983 // Service each socket
984 //
985 vector<CNode*> vNodesCopy;
0a61b0df 986 {
f8dcd5ca 987 LOCK(cs_vNodes);
0a61b0df 988 vNodesCopy = vNodes;
223b6f1b 989 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 990 pnode->AddRef();
991 }
223b6f1b 992 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 993 {
21eb5ada 994 boost::this_thread::interruption_point();
0a61b0df 995
996 //
997 // Receive
998 //
999 if (pnode->hSocket == INVALID_SOCKET)
1000 continue;
1001 if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
1002 {
607dbfde 1003 TRY_LOCK(pnode->cs_vRecvMsg, lockRecv);
f8dcd5ca 1004 if (lockRecv)
0a61b0df 1005 {
a9d9f0f5 1006 {
9cbae55a
GA
1007 // typical socket buffer is 8K-64K
1008 char pchBuf[0x10000];
1009 int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
1010 if (nBytes > 0)
0a61b0df 1011 {
607dbfde
JG
1012 if (!pnode->ReceiveMsgBytes(pchBuf, nBytes))
1013 pnode->CloseSocketDisconnect();
9cbae55a 1014 pnode->nLastRecv = GetTime();
86648a8d 1015 pnode->nRecvBytes += nBytes;
ce14345a 1016 pnode->RecordBytesRecv(nBytes);
9cbae55a
GA
1017 }
1018 else if (nBytes == 0)
1019 {
1020 // socket closed gracefully
0a61b0df 1021 if (!pnode->fDisconnect)
881a85a2 1022 LogPrint("net", "socket closed\n");
0a61b0df 1023 pnode->CloseSocketDisconnect();
1024 }
9cbae55a
GA
1025 else if (nBytes < 0)
1026 {
1027 // error
1028 int nErr = WSAGetLastError();
1029 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
1030 {
1031 if (!pnode->fDisconnect)
881a85a2 1032 LogPrintf("socket recv error %d\n", nErr);
9cbae55a
GA
1033 pnode->CloseSocketDisconnect();
1034 }
1035 }
0a61b0df 1036 }
1037 }
1038 }
1039
1040 //
1041 // Send
1042 //
1043 if (pnode->hSocket == INVALID_SOCKET)
1044 continue;
1045 if (FD_ISSET(pnode->hSocket, &fdsetSend))
1046 {
f8dcd5ca
PW
1047 TRY_LOCK(pnode->cs_vSend, lockSend);
1048 if (lockSend)
bc2f5aa7 1049 SocketSendData(pnode);
0a61b0df 1050 }
1051
1052 //
1053 // Inactivity checking
1054 //
41b052ad 1055 if (pnode->vSendMsg.empty())
0a61b0df 1056 pnode->nLastSendEmpty = GetTime();
1057 if (GetTime() - pnode->nTimeConnected > 60)
1058 {
1059 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
1060 {
881a85a2 1061 LogPrint("net", "socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
0a61b0df 1062 pnode->fDisconnect = true;
1063 }
1064 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
1065 {
881a85a2 1066 LogPrintf("socket not sending\n");
0a61b0df 1067 pnode->fDisconnect = true;
1068 }
1069 else if (GetTime() - pnode->nLastRecv > 90*60)
1070 {
881a85a2 1071 LogPrintf("socket inactivity timeout\n");
0a61b0df 1072 pnode->fDisconnect = true;
1073 }
1074 }
1075 }
0a61b0df 1076 {
f8dcd5ca 1077 LOCK(cs_vNodes);
223b6f1b 1078 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 1079 pnode->Release();
1080 }
1081
1b43bf0d 1082 MilliSleep(10);
0a61b0df 1083 }
1084}
1085
1086
1087
1088
1089
1090
1091
1092
1093
8bb5edc1 1094#ifdef USE_UPNP
21eb5ada 1095void ThreadMapPort()
8bb5edc1 1096{
463a1cab 1097 std::string port = strprintf("%u", GetListenPort());
8bb5edc1
MC
1098 const char * multicastif = 0;
1099 const char * minissdpdpath = 0;
1100 struct UPNPDev * devlist = 0;
1101 char lanaddr[64];
1102
94b97046
LD
1103#ifndef UPNPDISCOVER_SUCCESS
1104 /* miniupnpc 1.5 */
1105 devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0);
1106#else
1107 /* miniupnpc 1.6 */
1108 int error = 0;
b4ada906 1109 devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error);
94b97046 1110#endif
8bb5edc1
MC
1111
1112 struct UPNPUrls urls;
1113 struct IGDdatas data;
1114 int r;
1115
f285d4f4
DH
1116 r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
1117 if (r == 1)
8bb5edc1 1118 {
587f929c 1119 if (fDiscover) {
baba6e7d
MC
1120 char externalIPAddress[40];
1121 r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
1122 if(r != UPNPCOMMAND_SUCCESS)
881a85a2 1123 LogPrintf("UPnP: GetExternalIPAddress() returned %d\n", r);
baba6e7d
MC
1124 else
1125 {
1126 if(externalIPAddress[0])
1127 {
881a85a2 1128 LogPrintf("UPnP: ExternalIPAddress = %s\n", externalIPAddress);
19b6958c 1129 AddLocal(CNetAddr(externalIPAddress), LOCAL_UPNP);
baba6e7d
MC
1130 }
1131 else
881a85a2 1132 LogPrintf("UPnP: GetExternalIPAddress failed.\n");
baba6e7d
MC
1133 }
1134 }
1135
15656981 1136 string strDesc = "Bitcoin " + FormatFullVersion();
b4ada906 1137
21eb5ada 1138 try {
050d2e95 1139 while (true) {
177dbcaa
MC
1140#ifndef UPNPDISCOVER_SUCCESS
1141 /* miniupnpc 1.5 */
1142 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
9c809094 1143 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0);
177dbcaa
MC
1144#else
1145 /* miniupnpc 1.6 */
1146 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
9c809094 1147 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0");
177dbcaa
MC
1148#endif
1149
1150 if(r!=UPNPCOMMAND_SUCCESS)
881a85a2 1151 LogPrintf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
9c809094 1152 port.c_str(), port.c_str(), lanaddr, r, strupnperror(r));
177dbcaa 1153 else
881a85a2 1154 LogPrintf("UPnP Port Mapping successful.\n");;
21eb5ada
GA
1155
1156 MilliSleep(20*60*1000); // Refresh every 20 minutes
177dbcaa 1157 }
21eb5ada
GA
1158 }
1159 catch (boost::thread_interrupted)
1160 {
1161 r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0);
881a85a2 1162 LogPrintf("UPNP_DeletePortMapping() returned : %d\n", r);
21eb5ada
GA
1163 freeUPNPDevlist(devlist); devlist = 0;
1164 FreeUPNPUrls(&urls);
1165 throw;
8bb5edc1
MC
1166 }
1167 } else {
881a85a2 1168 LogPrintf("No valid UPnP IGDs found\n");
8bb5edc1 1169 freeUPNPDevlist(devlist); devlist = 0;
f285d4f4
DH
1170 if (r != 0)
1171 FreeUPNPUrls(&urls);
8bb5edc1
MC
1172 }
1173}
1174
21eb5ada 1175void MapPort(bool fUseUPnP)
8bb5edc1 1176{
21eb5ada
GA
1177 static boost::thread* upnp_thread = NULL;
1178
1179 if (fUseUPnP)
8bb5edc1 1180 {
21eb5ada
GA
1181 if (upnp_thread) {
1182 upnp_thread->interrupt();
1183 upnp_thread->join();
1184 delete upnp_thread;
1185 }
53e71135 1186 upnp_thread = new boost::thread(boost::bind(&TraceThread<void (*)()>, "upnp", &ThreadMapPort));
21eb5ada
GA
1187 }
1188 else if (upnp_thread) {
1189 upnp_thread->interrupt();
1190 upnp_thread->join();
1191 delete upnp_thread;
1192 upnp_thread = NULL;
8bb5edc1
MC
1193 }
1194}
21eb5ada 1195
9f0ac169 1196#else
21eb5ada 1197void MapPort(bool)
9f0ac169
GA
1198{
1199 // Intentionally left blank.
1200}
8bb5edc1
MC
1201#endif
1202
1203
1204
1205
1206
1207
21eb5ada 1208void ThreadDNSAddressSeed()
2bc6cece 1209{
0e4b3175 1210 const vector<CDNSSeedData> &vSeeds = Params().DNSSeeds();
f684aec4
JG
1211 int found = 0;
1212
881a85a2 1213 LogPrintf("Loading addresses from DNS seeds (could take a while)\n");
af899882 1214
0e4b3175 1215 BOOST_FOREACH(const CDNSSeedData &seed, vSeeds) {
af899882 1216 if (HaveNameProxy()) {
0e4b3175 1217 AddOneShot(seed.host);
af899882 1218 } else {
0e4b3175 1219 vector<CNetAddr> vIPs;
af899882 1220 vector<CAddress> vAdd;
0e4b3175 1221 if (LookupHost(seed.host.c_str(), vIPs))
af899882 1222 {
0e4b3175 1223 BOOST_FOREACH(CNetAddr& ip, vIPs)
a6a5bb7c 1224 {
af899882 1225 int nOneDay = 24*3600;
0e4b3175 1226 CAddress addr = CAddress(CService(ip, Params().GetDefaultPort()));
af899882
PT
1227 addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
1228 vAdd.push_back(addr);
1229 found++;
a6a5bb7c 1230 }
f684aec4 1231 }
0e4b3175 1232 addrman.Add(vAdd, CNetAddr(seed.name, true));
f684aec4
JG
1233 }
1234 }
1235
881a85a2 1236 LogPrintf("%d addresses found from DNS seeds\n", found);
f684aec4 1237}
0a61b0df 1238
1239
1240
2bc6cece
MC
1241
1242
1243
1244
1245
1246
1247
1248
1249
5fee401f
PW
1250void DumpAddresses()
1251{
928d3a01
JG
1252 int64 nStart = GetTimeMillis();
1253
5fee401f 1254 CAddrDB adb;
928d3a01
JG
1255 adb.Write(addrman);
1256
881a85a2 1257 LogPrint("net", "Flushed %d addresses to peers.dat %"PRI64d"ms\n",
928d3a01 1258 addrman.size(), GetTimeMillis() - nStart);
5fee401f 1259}
0a61b0df 1260
478b01d9
PW
1261void static ProcessOneShot()
1262{
1263 string strDest;
1264 {
1265 LOCK(cs_vOneShots);
1266 if (vOneShots.empty())
1267 return;
1268 strDest = vOneShots.front();
1269 vOneShots.pop_front();
1270 }
1271 CAddress addr;
c59abe25
PW
1272 CSemaphoreGrant grant(*semOutbound, true);
1273 if (grant) {
1274 if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true))
1275 AddOneShot(strDest);
1276 }
478b01d9
PW
1277}
1278
21eb5ada 1279void ThreadOpenConnections()
0a61b0df 1280{
0a61b0df 1281 // Connect to specific addresses
f161a2c2 1282 if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
0a61b0df 1283 {
bde280b9 1284 for (int64 nLoop = 0;; nLoop++)
0a61b0df 1285 {
478b01d9 1286 ProcessOneShot();
223b6f1b 1287 BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
0a61b0df 1288 {
478b01d9 1289 CAddress addr;
c59abe25 1290 OpenNetworkConnection(addr, NULL, strAddr.c_str());
0a61b0df 1291 for (int i = 0; i < 10 && i < nLoop; i++)
1292 {
1b43bf0d 1293 MilliSleep(500);
0a61b0df 1294 }
1295 }
1b43bf0d 1296 MilliSleep(500);
0a61b0df 1297 }
1298 }
1299
0a61b0df 1300 // Initiate network connections
bde280b9 1301 int64 nStart = GetTime();
050d2e95 1302 while (true)
0a61b0df 1303 {
478b01d9
PW
1304 ProcessOneShot();
1305
1b43bf0d 1306 MilliSleep(500);
cc201e01 1307
c59abe25 1308 CSemaphoreGrant grant(*semOutbound);
21eb5ada 1309 boost::this_thread::interruption_point();
0a61b0df 1310
0e4b3175
MH
1311 // Add seed nodes if DNS seeds are all down (an infrastructure attack?).
1312 if (addrman.size() == 0 && (GetTime() - nStart > 60)) {
1313 static bool done = false;
1314 if (!done) {
881a85a2 1315 LogPrintf("Adding fixed seed nodes as DNS doesn't seem to be available.\n");
0e4b3175
MH
1316 addrman.Add(Params().FixedSeeds(), CNetAddr("127.0.0.1"));
1317 done = true;
0a61b0df 1318 }
1319 }
1320
0a61b0df 1321 //
1322 // Choose an address to connect to based on most recently seen
1323 //
1324 CAddress addrConnect;
0a61b0df 1325
19521acf 1326 // Only connect out to one peer per network group (/16 for IPv4).
0a61b0df 1327 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
c59abe25 1328 int nOutbound = 0;
67a42f92 1329 set<vector<unsigned char> > setConnected;
f8dcd5ca
PW
1330 {
1331 LOCK(cs_vNodes);
c59abe25 1332 BOOST_FOREACH(CNode* pnode, vNodes) {
19521acf
GM
1333 if (!pnode->fInbound) {
1334 setConnected.insert(pnode->addr.GetGroup());
c59abe25 1335 nOutbound++;
19521acf 1336 }
c59abe25 1337 }
f8dcd5ca 1338 }
0a61b0df 1339
bde280b9 1340 int64 nANow = GetAdjustedTime();
a4e6ae10 1341
5fee401f 1342 int nTries = 0;
050d2e95 1343 while (true)
0a61b0df 1344 {
5fee401f
PW
1345 // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
1346 CAddress addr = addrman.Select(10 + min(nOutbound,8)*10);
0a61b0df 1347
5fee401f 1348 // if we selected an invalid address, restart
23aa78c4 1349 if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
5fee401f 1350 break;
0a61b0df 1351
f161a2c2
PW
1352 // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
1353 // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
1354 // already-connected network ranges, ...) before trying new addrman addresses.
5fee401f 1355 nTries++;
f161a2c2
PW
1356 if (nTries > 100)
1357 break;
0a61b0df 1358
457754d2
PW
1359 if (IsLimited(addr))
1360 continue;
1361
5fee401f
PW
1362 // only consider very recently tried nodes after 30 failed attempts
1363 if (nANow - addr.nLastTry < 600 && nTries < 30)
1364 continue;
1365
1366 // do not allow non-default ports, unless after 50 invalid addresses selected already
0e4b3175 1367 if (addr.GetPort() != Params().GetDefaultPort() && nTries < 50)
5fee401f
PW
1368 continue;
1369
1370 addrConnect = addr;
1371 break;
0a61b0df 1372 }
1373
1374 if (addrConnect.IsValid())
c59abe25 1375 OpenNetworkConnection(addrConnect, &grant);
0a61b0df 1376 }
1377}
1378
21eb5ada 1379void ThreadOpenAddedConnections()
b24e6e4d 1380{
74088e86
MC
1381 {
1382 LOCK(cs_vAddedNodes);
1383 vAddedNodes = mapMultiArgs["-addnode"];
1384 }
b24e6e4d 1385
81bbef26 1386 if (HaveNameProxy()) {
21eb5ada 1387 while(true) {
74088e86
MC
1388 list<string> lAddresses(0);
1389 {
1390 LOCK(cs_vAddedNodes);
1391 BOOST_FOREACH(string& strAddNode, vAddedNodes)
1392 lAddresses.push_back(strAddNode);
1393 }
1394 BOOST_FOREACH(string& strAddNode, lAddresses) {
9bab521d 1395 CAddress addr;
c59abe25
PW
1396 CSemaphoreGrant grant(*semOutbound);
1397 OpenNetworkConnection(addr, &grant, strAddNode.c_str());
1b43bf0d 1398 MilliSleep(500);
9bab521d 1399 }
1b43bf0d 1400 MilliSleep(120000); // Retry every 2 minutes
9bab521d 1401 }
9bab521d
PW
1402 }
1403
f2bd6c28 1404 for (unsigned int i = 0; true; i++)
b24e6e4d 1405 {
74088e86
MC
1406 list<string> lAddresses(0);
1407 {
1408 LOCK(cs_vAddedNodes);
1409 BOOST_FOREACH(string& strAddNode, vAddedNodes)
1410 lAddresses.push_back(strAddNode);
1411 }
1412
1413 list<vector<CService> > lservAddressesToAdd(0);
1414 BOOST_FOREACH(string& strAddNode, lAddresses)
b24e6e4d 1415 {
74088e86 1416 vector<CService> vservNode(0);
0e4b3175 1417 if(Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0))
f8dcd5ca 1418 {
74088e86
MC
1419 lservAddressesToAdd.push_back(vservNode);
1420 {
1421 LOCK(cs_setservAddNodeAddresses);
1422 BOOST_FOREACH(CService& serv, vservNode)
1423 setservAddNodeAddresses.insert(serv);
1424 }
f8dcd5ca 1425 }
b24e6e4d 1426 }
b24e6e4d 1427 // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
9bab521d 1428 // (keeping in mind that addnode entries can have many IPs if fNameLookup)
f8dcd5ca
PW
1429 {
1430 LOCK(cs_vNodes);
b24e6e4d 1431 BOOST_FOREACH(CNode* pnode, vNodes)
74088e86 1432 for (list<vector<CService> >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
b24e6e4d
MC
1433 BOOST_FOREACH(CService& addrNode, *(it))
1434 if (pnode->addr == addrNode)
1435 {
74088e86 1436 it = lservAddressesToAdd.erase(it);
b24e6e4d
MC
1437 it--;
1438 break;
1439 }
f8dcd5ca 1440 }
74088e86 1441 BOOST_FOREACH(vector<CService>& vserv, lservAddressesToAdd)
b24e6e4d 1442 {
c59abe25 1443 CSemaphoreGrant grant(*semOutbound);
f2bd6c28 1444 OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant);
1b43bf0d 1445 MilliSleep(500);
b24e6e4d 1446 }
1b43bf0d 1447 MilliSleep(120000); // Retry every 2 minutes
b24e6e4d
MC
1448 }
1449}
1450
814efd6f 1451// if successful, this moves the passed grant to the constructed node
c59abe25 1452bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot)
0a61b0df 1453{
1454 //
1455 // Initiate outbound network connection
1456 //
21eb5ada 1457 boost::this_thread::interruption_point();
9bab521d 1458 if (!strDest)
39857190
PW
1459 if (IsLocal(addrConnect) ||
1460 FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
9bab521d
PW
1461 FindNode(addrConnect.ToStringIPPort().c_str()))
1462 return false;
1463 if (strDest && FindNode(strDest))
0a61b0df 1464 return false;
1465
9bab521d 1466 CNode* pnode = ConnectNode(addrConnect, strDest);
21eb5ada
GA
1467 boost::this_thread::interruption_point();
1468
0a61b0df 1469 if (!pnode)
1470 return false;
c59abe25
PW
1471 if (grantOutbound)
1472 grantOutbound->MoveTo(pnode->grantOutbound);
0a61b0df 1473 pnode->fNetworkNode = true;
478b01d9
PW
1474 if (fOneShot)
1475 pnode->fOneShot = true;
0a61b0df 1476
0a61b0df 1477 return true;
1478}
1479
1480
6ed71b5e
PW
1481// for now, use a very simple selection metric: the node from which we received
1482// most recently
1483double static NodeSyncScore(const CNode *pnode) {
1484 return -pnode->nLastRecv;
1485}
0a61b0df 1486
6ed71b5e
PW
1487void static StartSync(const vector<CNode*> &vNodes) {
1488 CNode *pnodeNewSync = NULL;
1489 double dBestScore = 0;
0a61b0df 1490
4c6d41b8
PW
1491 int nBestHeight = g_signals.GetHeight().get_value_or(0);
1492
6ed71b5e
PW
1493 // Iterate over all nodes
1494 BOOST_FOREACH(CNode* pnode, vNodes) {
1495 // check preconditions for allowing a sync
1496 if (!pnode->fClient && !pnode->fOneShot &&
1497 !pnode->fDisconnect && pnode->fSuccessfullyConnected &&
1498 (pnode->nStartingHeight > (nBestHeight - 144)) &&
1499 (pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) {
1500 // if ok, compare node's score with the best so far
1501 double dScore = NodeSyncScore(pnode);
1502 if (pnodeNewSync == NULL || dScore > dBestScore) {
1503 pnodeNewSync = pnode;
1504 dBestScore = dScore;
1505 }
1506 }
1507 }
1508 // if a new sync candidate was found, start sync!
1509 if (pnodeNewSync) {
1510 pnodeNewSync->fStartSync = true;
1511 pnodeSync = pnodeNewSync;
1512 }
1513}
0a61b0df 1514
21eb5ada 1515void ThreadMessageHandler()
0a61b0df 1516{
0a61b0df 1517 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
21eb5ada 1518 while (true)
0a61b0df 1519 {
6ed71b5e
PW
1520 bool fHaveSyncNode = false;
1521
0a61b0df 1522 vector<CNode*> vNodesCopy;
0a61b0df 1523 {
f8dcd5ca 1524 LOCK(cs_vNodes);
0a61b0df 1525 vNodesCopy = vNodes;
6ed71b5e 1526 BOOST_FOREACH(CNode* pnode, vNodesCopy) {
0a61b0df 1527 pnode->AddRef();
6ed71b5e
PW
1528 if (pnode == pnodeSync)
1529 fHaveSyncNode = true;
1530 }
0a61b0df 1531 }
1532
6ed71b5e
PW
1533 if (!fHaveSyncNode)
1534 StartSync(vNodesCopy);
1535
0a61b0df 1536 // Poll the connected nodes for messages
1537 CNode* pnodeTrickle = NULL;
1538 if (!vNodesCopy.empty())
1539 pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
223b6f1b 1540 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 1541 {
967f2459
PW
1542 if (pnode->fDisconnect)
1543 continue;
1544
0a61b0df 1545 // Receive messages
f8dcd5ca 1546 {
607dbfde 1547 TRY_LOCK(pnode->cs_vRecvMsg, lockRecv);
f8dcd5ca 1548 if (lockRecv)
501da250 1549 if (!g_signals.ProcessMessages(pnode))
607dbfde 1550 pnode->CloseSocketDisconnect();
f8dcd5ca 1551 }
21eb5ada 1552 boost::this_thread::interruption_point();
0a61b0df 1553
1554 // Send messages
f8dcd5ca
PW
1555 {
1556 TRY_LOCK(pnode->cs_vSend, lockSend);
501da250
EL
1557 if (lockSend)
1558 g_signals.SendMessages(pnode, pnode == pnodeTrickle);
f8dcd5ca 1559 }
21eb5ada 1560 boost::this_thread::interruption_point();
0a61b0df 1561 }
1562
0a61b0df 1563 {
f8dcd5ca 1564 LOCK(cs_vNodes);
223b6f1b 1565 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 1566 pnode->Release();
1567 }
1568
1b43bf0d 1569 MilliSleep(100);
0a61b0df 1570 }
1571}
1572
1573
1574
1575
1576
1577
8f10a288 1578bool BindListenPort(const CService &addrBind, string& strError)
0a61b0df 1579{
1580 strError = "";
1581 int nOne = 1;
1582
0a61b0df 1583 // Create socket for listening for incoming connections
23aa78c4 1584#ifdef USE_IPV6
8f10a288 1585 struct sockaddr_storage sockaddr;
23aa78c4 1586#else
8f10a288 1587 struct sockaddr sockaddr;
23aa78c4 1588#endif
8f10a288
PW
1589 socklen_t len = sizeof(sockaddr);
1590 if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
1591 {
1592 strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString().c_str());
881a85a2 1593 LogPrintf("%s\n", strError.c_str());
8f10a288
PW
1594 return false;
1595 }
1596
1597 SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
0a61b0df 1598 if (hListenSocket == INVALID_SOCKET)
1599 {
1600 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
881a85a2 1601 LogPrintf("%s\n", strError.c_str());
0a61b0df 1602 return false;
1603 }
1604
ec93a0e2 1605#ifdef SO_NOSIGPIPE
0a61b0df 1606 // Different way of disabling SIGPIPE on BSD
1607 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1608#endif
1609
6853e627 1610#ifndef WIN32
0a61b0df 1611 // Allow binding if the port is still in TIME_WAIT state after
1612 // the program was closed and restarted. Not an issue on windows.
1613 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1614#endif
1615
8f10a288 1616
6853e627 1617#ifdef WIN32
814efd6f 1618 // Set to non-blocking, incoming connections will also inherit this
0a61b0df 1619 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1620#else
1621 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1622#endif
1623 {
1624 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
881a85a2 1625 LogPrintf("%s\n", strError.c_str());
0a61b0df 1626 return false;
1627 }
1628
23aa78c4 1629#ifdef USE_IPV6
8f10a288
PW
1630 // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
1631 // and enable it by default or not. Try to enable it, if possible.
1632 if (addrBind.IsIPv6()) {
1633#ifdef IPV6_V6ONLY
b3e0aaf3
PK
1634#ifdef WIN32
1635 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int));
1636#else
8f10a288 1637 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int));
23aa78c4 1638#endif
b3e0aaf3 1639#endif
8f10a288
PW
1640#ifdef WIN32
1641 int nProtLevel = 10 /* PROTECTION_LEVEL_UNRESTRICTED */;
1642 int nParameterId = 23 /* IPV6_PROTECTION_LEVEl */;
1643 // this call is allowed to fail
1644 setsockopt(hListenSocket, IPPROTO_IPV6, nParameterId, (const char*)&nProtLevel, sizeof(int));
1645#endif
1646 }
1647#endif
1648
1649 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
0a61b0df 1650 {
1651 int nErr = WSAGetLastError();
1652 if (nErr == WSAEADDRINUSE)
8b4d6536 1653 strError = strprintf(_("Unable to bind to %s on this computer. Bitcoin is probably already running."), addrBind.ToString().c_str());
0a61b0df 1654 else
8f10a288 1655 strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString().c_str(), nErr, strerror(nErr));
881a85a2 1656 LogPrintf("%s\n", strError.c_str());
0a61b0df 1657 return false;
1658 }
881a85a2 1659 LogPrintf("Bound to %s\n", addrBind.ToString().c_str());
0a61b0df 1660
1661 // Listen for incoming connections
1662 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1663 {
1664 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
881a85a2 1665 LogPrintf("%s\n", strError.c_str());
0a61b0df 1666 return false;
1667 }
1668
8f10a288
PW
1669 vhListenSocket.push_back(hListenSocket);
1670
587f929c 1671 if (addrBind.IsRoutable() && fDiscover)
8f10a288
PW
1672 AddLocal(addrBind, LOCAL_BIND);
1673
0a61b0df 1674 return true;
1675}
1676
19b6958c 1677void static Discover()
0a61b0df 1678{
587f929c 1679 if (!fDiscover)
19b6958c 1680 return;
0a61b0df 1681
6853e627 1682#ifdef WIN32
814efd6f 1683 // Get local host IP
0a61b0df 1684 char pszHostName[1000] = "";
1685 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1686 {
67a42f92
PW
1687 vector<CNetAddr> vaddr;
1688 if (LookupHost(pszHostName, vaddr))
f8e4d43b 1689 {
67a42f92 1690 BOOST_FOREACH (const CNetAddr &addr, vaddr)
f8e4d43b 1691 {
39857190 1692 AddLocal(addr, LOCAL_IF);
f8e4d43b
PK
1693 }
1694 }
0a61b0df 1695 }
1696#else
1697 // Get local host ip
1698 struct ifaddrs* myaddrs;
1699 if (getifaddrs(&myaddrs) == 0)
1700 {
1701 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1702 {
1703 if (ifa->ifa_addr == NULL) continue;
1704 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1705 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1706 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
0a61b0df 1707 if (ifa->ifa_addr->sa_family == AF_INET)
1708 {
1709 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
39857190 1710 CNetAddr addr(s4->sin_addr);
23aa78c4 1711 if (AddLocal(addr, LOCAL_IF))
881a85a2 1712 LogPrintf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
0a61b0df 1713 }
23aa78c4 1714#ifdef USE_IPV6
0a61b0df 1715 else if (ifa->ifa_addr->sa_family == AF_INET6)
1716 {
1717 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
39857190 1718 CNetAddr addr(s6->sin6_addr);
23aa78c4 1719 if (AddLocal(addr, LOCAL_IF))
881a85a2 1720 LogPrintf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
0a61b0df 1721 }
23aa78c4 1722#endif
0a61b0df 1723 }
1724 freeifaddrs(myaddrs);
1725 }
1726#endif
0a61b0df 1727
a76552ce
PK
1728 // Don't use external IPv4 discovery, when -onlynet="IPv6"
1729 if (!IsLimited(NET_IPV4))
53e71135 1730 boost::thread(boost::bind(&TraceThread<void (*)()>, "ext-ip", &ThreadGetMyExternalIP));
19b6958c
PW
1731}
1732
b31499ec 1733void StartNode(boost::thread_group& threadGroup)
19b6958c 1734{
c59abe25
PW
1735 if (semOutbound == NULL) {
1736 // initialize semaphore
ba29a559 1737 int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, nMaxConnections);
c59abe25
PW
1738 semOutbound = new CSemaphore(nMaxOutbound);
1739 }
1740
19b6958c
PW
1741 if (pnodeLocalHost == NULL)
1742 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", 0), nLocalServices));
1743
1744 Discover();
0a61b0df 1745
1746 //
1747 // Start threads
1748 //
1749
9d952d17 1750 if (!GetBoolArg("-dnsseed", true))
881a85a2 1751 LogPrintf("DNS seeding disabled\n");
2bc6cece 1752 else
53e71135 1753 threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "dnsseed", &ThreadDNSAddressSeed));
2bc6cece 1754
b31499ec 1755#ifdef USE_UPNP
8bb5edc1 1756 // Map ports with UPnP
21eb5ada 1757 MapPort(GetBoolArg("-upnp", USE_UPNP));
b31499ec 1758#endif
8bb5edc1 1759
0a61b0df 1760 // Send and receive from sockets, accept connections
b31499ec 1761 threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "net", &ThreadSocketHandler));
0a61b0df 1762
b24e6e4d 1763 // Initiate outbound connections from -addnode
b31499ec 1764 threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "addcon", &ThreadOpenAddedConnections));
b24e6e4d 1765
0a61b0df 1766 // Initiate outbound connections
b31499ec 1767 threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "opencon", &ThreadOpenConnections));
0a61b0df 1768
1769 // Process messages
b31499ec 1770 threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "msghand", &ThreadMessageHandler));
0a61b0df 1771
5fee401f 1772 // Dump network addresses
c43da3f1 1773 threadGroup.create_thread(boost::bind(&LoopForever<void (*)()>, "dumpaddr", &DumpAddresses, DUMP_ADDRESSES_INTERVAL * 1000));
0a61b0df 1774}
1775
1776bool StopNode()
1777{
881a85a2 1778 LogPrintf("StopNode()\n");
21eb5ada 1779 MapPort(false);
89b5616d
PW
1780 if (semOutbound)
1781 for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
1782 semOutbound->post();
1b43bf0d 1783 MilliSleep(50);
5fee401f 1784 DumpAddresses();
3427517d 1785
0a61b0df 1786 return true;
1787}
1788
1789class CNetCleanup
1790{
1791public:
1792 CNetCleanup()
1793 {
1794 }
1795 ~CNetCleanup()
1796 {
1797 // Close sockets
223b6f1b 1798 BOOST_FOREACH(CNode* pnode, vNodes)
0a61b0df 1799 if (pnode->hSocket != INVALID_SOCKET)
1800 closesocket(pnode->hSocket);
8f10a288
PW
1801 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
1802 if (hListenSocket != INVALID_SOCKET)
1803 if (closesocket(hListenSocket) == SOCKET_ERROR)
881a85a2 1804 LogPrintf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
0a61b0df 1805
3427517d
PW
1806 // clean up some globals (to help leak detection)
1807 BOOST_FOREACH(CNode *pnode, vNodes)
1808 delete pnode;
1809 BOOST_FOREACH(CNode *pnode, vNodesDisconnected)
1810 delete pnode;
1811 vNodes.clear();
1812 vNodesDisconnected.clear();
1813 delete semOutbound;
1814 semOutbound = NULL;
1815 delete pnodeLocalHost;
1816 pnodeLocalHost = NULL;
1817
6853e627 1818#ifdef WIN32
0a61b0df 1819 // Shutdown Windows Sockets
1820 WSACleanup();
1821#endif
1822 }
1823}
1824instance_of_cnetcleanup;
269d9c64
MC
1825
1826
1827
1828
1829
1830
1831
1832void RelayTransaction(const CTransaction& tx, const uint256& hash)
1833{
1834 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
1835 ss.reserve(10000);
1836 ss << tx;
1837 RelayTransaction(tx, hash, ss);
1838}
1839
1840void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
1841{
1842 CInv inv(MSG_TX, hash);
1843 {
1844 LOCK(cs_mapRelay);
1845 // Expire old relay messages
1846 while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
1847 {
1848 mapRelay.erase(vRelayExpiration.front().second);
1849 vRelayExpiration.pop_front();
1850 }
1851
1852 // Save original serialized message so newer versions are preserved
1853 mapRelay.insert(std::make_pair(inv, ss));
1854 vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
1855 }
1856 LOCK(cs_vNodes);
1857 BOOST_FOREACH(CNode* pnode, vNodes)
1858 {
4c8fc1a5
MC
1859 if(!pnode->fRelayTxes)
1860 continue;
269d9c64
MC
1861 LOCK(pnode->cs_filter);
1862 if (pnode->pfilter)
1863 {
d3b26f70 1864 if (pnode->pfilter->IsRelevantAndUpdate(tx, hash))
269d9c64
MC
1865 pnode->PushInventory(inv);
1866 } else
1867 pnode->PushInventory(inv);
1868 }
1869}
ce14345a
SE
1870
1871void CNode::RecordBytesRecv(uint64 bytes)
1872{
1873 LOCK(cs_totalBytesRecv);
1874 nTotalBytesRecv += bytes;
1875}
1876
1877void CNode::RecordBytesSent(uint64 bytes)
1878{
1879 LOCK(cs_totalBytesSent);
1880 nTotalBytesSent += bytes;
1881}
1882
1883uint64 CNode::GetTotalBytesRecv()
1884{
1885 LOCK(cs_totalBytesRecv);
1886 return nTotalBytesRecv;
1887}
1888
1889uint64 CNode::GetTotalBytesSent()
1890{
1891 LOCK(cs_totalBytesSent);
1892 return nTotalBytesSent;
1893}
This page took 0.469494 seconds and 4 git commands to generate.