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