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