]> Git Repo - VerusCoin.git/blame - src/net.cpp
Merge pull request #5095
[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 51using namespace boost;
611116d4 52using namespace std;
223b6f1b 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;
51ed9ec9 76uint64_t nLocalHostNonce = 0;
dc942e6f 77static std::vector<ListenSocket> vhListenSocket;
5fee401f 78CAddrMan addrman;
ba29a559 79int nMaxConnections = 125;
94064710 80bool fAddressesInitialized = false;
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
0a61b0df 491 // Add node
9bab521d 492 CNode* pnode = new CNode(hSocket, addrConnect, pszDest ? pszDest : "", false);
cedaa714 493 pnode->AddRef();
9bab521d 494
f8dcd5ca
PW
495 {
496 LOCK(cs_vNodes);
0a61b0df 497 vNodes.push_back(pnode);
f8dcd5ca 498 }
0a61b0df 499
500 pnode->nTimeConnected = GetTime();
2e36866f 501
0a61b0df 502 return pnode;
503 }
5bd6c31b
PK
504
505 return NULL;
0a61b0df 506}
507
508void CNode::CloseSocketDisconnect()
509{
510 fDisconnect = true;
511 if (hSocket != INVALID_SOCKET)
512 {
2e36866f 513 LogPrint("net", "disconnecting peer=%d\n", id);
43f510d3 514 CloseSocket(hSocket);
0a61b0df 515 }
6ed71b5e
PW
516
517 // in case this fails, we'll empty the recv buffer when the CNode is deleted
518 TRY_LOCK(cs_vRecvMsg, lockRecv);
519 if (lockRecv)
520 vRecvMsg.clear();
0a61b0df 521}
522
f8ded588
GA
523void CNode::PushVersion()
524{
4c6d41b8
PW
525 int nBestHeight = g_signals.GetHeight().get_value_or(0);
526
f8ded588 527 /// when NTP implemented, change to just nTime = GetAdjustedTime()
51ed9ec9 528 int64_t nTime = (fInbound ? GetAdjustedTime() : GetTime());
587f929c 529 CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0",0)));
39857190 530 CAddress addrMe = GetLocalAddress(&addr);
001a53d7 531 GetRandBytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
2e36866f
B
532 if (fLogIPs)
533 LogPrint("net", "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%d\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString(), addrYou.ToString(), id);
534 else
535 LogPrint("net", "send version message: version %d, blocks=%d, us=%s, peer=%d\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString(), id);
f8ded588 536 PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
c87f462b 537 nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()), nBestHeight, true);
f8ded588
GA
538}
539
540
541
542
543
51ed9ec9 544std::map<CNetAddr, int64_t> CNode::setBanned;
15f3ad4d
GA
545CCriticalSection CNode::cs_setBanned;
546
547void CNode::ClearBanned()
548{
549 setBanned.clear();
550}
551
67a42f92 552bool CNode::IsBanned(CNetAddr ip)
15f3ad4d
GA
553{
554 bool fResult = false;
15f3ad4d 555 {
f8dcd5ca 556 LOCK(cs_setBanned);
51ed9ec9 557 std::map<CNetAddr, int64_t>::iterator i = setBanned.find(ip);
15f3ad4d
GA
558 if (i != setBanned.end())
559 {
51ed9ec9 560 int64_t t = (*i).second;
15f3ad4d
GA
561 if (GetTime() < t)
562 fResult = true;
563 }
564 }
565 return fResult;
566}
567
b2864d2f
PW
568bool CNode::Ban(const CNetAddr &addr) {
569 int64_t banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban
15f3ad4d 570 {
b2864d2f
PW
571 LOCK(cs_setBanned);
572 if (setBanned[addr] < banTime)
573 setBanned[addr] = banTime;
15f3ad4d 574 }
b2864d2f 575 return true;
15f3ad4d
GA
576}
577
dc942e6f
PW
578
579std::vector<CSubNet> CNode::vWhitelistedRange;
580CCriticalSection CNode::cs_vWhitelistedRange;
581
582bool CNode::IsWhitelistedRange(const CNetAddr &addr) {
583 LOCK(cs_vWhitelistedRange);
584 BOOST_FOREACH(const CSubNet& subnet, vWhitelistedRange) {
585 if (subnet.Match(addr))
586 return true;
587 }
588 return false;
589}
590
591void CNode::AddWhitelistedRange(const CSubNet &subnet) {
592 LOCK(cs_vWhitelistedRange);
593 vWhitelistedRange.push_back(subnet);
594}
595
1006f070
JG
596#undef X
597#define X(name) stats.name = name
598void CNode::copyStats(CNodeStats &stats)
599{
b2864d2f 600 stats.nodeid = this->GetId();
1006f070
JG
601 X(nServices);
602 X(nLastSend);
603 X(nLastRecv);
604 X(nTimeConnected);
605 X(addrName);
606 X(nVersion);
a946aa8d 607 X(cleanSubVer);
1006f070 608 X(fInbound);
1006f070 609 X(nStartingHeight);
86648a8d
PW
610 X(nSendBytes);
611 X(nRecvBytes);
dc942e6f 612 X(fWhitelisted);
fabba0e6 613
971bb3e9
JL
614 // It is common for nodes with good ping times to suddenly become lagged,
615 // due to a new block arriving or other large transfer.
616 // Merely reporting pingtime might fool the caller into thinking the node was still responsive,
617 // since pingtime does not update until the ping is complete, which might take a while.
618 // So, if a ping is taking an unusually long time in flight,
619 // the caller can immediately detect that this is happening.
51ed9ec9 620 int64_t nPingUsecWait = 0;
971bb3e9
JL
621 if ((0 != nPingNonceSent) && (0 != nPingUsecStart)) {
622 nPingUsecWait = GetTimeMicros() - nPingUsecStart;
623 }
fabba0e6 624
971bb3e9
JL
625 // 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 :)
626 stats.dPingTime = (((double)nPingUsecTime) / 1e6);
627 stats.dPingWait = (((double)nPingUsecWait) / 1e6);
fabba0e6 628
547c61f8
JL
629 // Leave string empty if addrLocal invalid (not filled in yet)
630 stats.addrLocal = addrLocal.IsValid() ? addrLocal.ToString() : "";
1006f070
JG
631}
632#undef X
0a61b0df 633
607dbfde
JG
634// requires LOCK(cs_vRecvMsg)
635bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes)
636{
637 while (nBytes > 0) {
638
639 // get current incomplete message, or create a new one
967f2459 640 if (vRecvMsg.empty() ||
607dbfde
JG
641 vRecvMsg.back().complete())
642 vRecvMsg.push_back(CNetMessage(SER_NETWORK, nRecvVersion));
643
644 CNetMessage& msg = vRecvMsg.back();
645
646 // absorb network data
647 int handled;
648 if (!msg.in_data)
649 handled = msg.readHeader(pch, nBytes);
650 else
651 handled = msg.readData(pch, nBytes);
652
653 if (handled < 0)
654 return false;
655
656 pch += handled;
657 nBytes -= handled;
9f4da19b
PW
658
659 if (msg.complete())
660 msg.nTime = GetTimeMicros();
607dbfde
JG
661 }
662
663 return true;
664}
665
666int CNetMessage::readHeader(const char *pch, unsigned int nBytes)
667{
668 // copy data to temporary parsing buffer
669 unsigned int nRemaining = 24 - nHdrPos;
670 unsigned int nCopy = std::min(nRemaining, nBytes);
671
672 memcpy(&hdrbuf[nHdrPos], pch, nCopy);
673 nHdrPos += nCopy;
674
675 // if header incomplete, exit
676 if (nHdrPos < 24)
677 return nCopy;
678
679 // deserialize to CMessageHeader
680 try {
681 hdrbuf >> hdr;
682 }
ec91092d 683 catch (const std::exception &) {
607dbfde
JG
684 return -1;
685 }
686
687 // reject messages larger than MAX_SIZE
688 if (hdr.nMessageSize > MAX_SIZE)
689 return -1;
690
691 // switch state to reading message data
692 in_data = true;
607dbfde
JG
693
694 return nCopy;
695}
696
697int CNetMessage::readData(const char *pch, unsigned int nBytes)
698{
699 unsigned int nRemaining = hdr.nMessageSize - nDataPos;
700 unsigned int nCopy = std::min(nRemaining, nBytes);
701
806fd19e
PW
702 if (vRecv.size() < nDataPos + nCopy) {
703 // Allocate up to 256 KiB ahead, but never more than the total message size.
704 vRecv.resize(std::min(hdr.nMessageSize, nDataPos + nCopy + 256 * 1024));
705 }
706
607dbfde
JG
707 memcpy(&vRecv[nDataPos], pch, nCopy);
708 nDataPos += nCopy;
709
710 return nCopy;
711}
712
0a61b0df 713
714
715
716
717
718
719
720
bc2f5aa7
JG
721// requires LOCK(cs_vSend)
722void SocketSendData(CNode *pnode)
723{
41b052ad
PW
724 std::deque<CSerializeData>::iterator it = pnode->vSendMsg.begin();
725
726 while (it != pnode->vSendMsg.end()) {
727 const CSerializeData &data = *it;
728 assert(data.size() > pnode->nSendOffset);
729 int nBytes = send(pnode->hSocket, &data[pnode->nSendOffset], data.size() - pnode->nSendOffset, MSG_NOSIGNAL | MSG_DONTWAIT);
730 if (nBytes > 0) {
731 pnode->nLastSend = GetTime();
86648a8d 732 pnode->nSendBytes += nBytes;
41b052ad 733 pnode->nSendOffset += nBytes;
ce14345a 734 pnode->RecordBytesSent(nBytes);
41b052ad
PW
735 if (pnode->nSendOffset == data.size()) {
736 pnode->nSendOffset = 0;
737 pnode->nSendSize -= data.size();
738 it++;
739 } else {
740 // could not send full message; stop sending more
741 break;
742 }
743 } else {
744 if (nBytes < 0) {
745 // error
746 int nErr = WSAGetLastError();
747 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
748 {
a60838d0 749 LogPrintf("socket send error %s\n", NetworkErrorString(nErr));
41b052ad
PW
750 pnode->CloseSocketDisconnect();
751 }
752 }
753 // couldn't send anything at all
754 break;
bc2f5aa7
JG
755 }
756 }
41b052ad
PW
757
758 if (it == pnode->vSendMsg.end()) {
759 assert(pnode->nSendOffset == 0);
760 assert(pnode->nSendSize == 0);
761 }
762 pnode->vSendMsg.erase(pnode->vSendMsg.begin(), it);
bc2f5aa7 763}
0a61b0df 764
3427517d
PW
765static list<CNode*> vNodesDisconnected;
766
21eb5ada 767void ThreadSocketHandler()
0a61b0df 768{
735a6069 769 unsigned int nPrevNodeCount = 0;
050d2e95 770 while (true)
0a61b0df 771 {
772 //
773 // Disconnect nodes
774 //
0a61b0df 775 {
f8dcd5ca 776 LOCK(cs_vNodes);
0a61b0df 777 // Disconnect unused nodes
778 vector<CNode*> vNodesCopy = vNodes;
223b6f1b 779 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 780 {
781 if (pnode->fDisconnect ||
41b052ad 782 (pnode->GetRefCount() <= 0 && pnode->vRecvMsg.empty() && pnode->nSendSize == 0 && pnode->ssSend.empty()))
0a61b0df 783 {
784 // remove from vNodes
785 vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
786
c59abe25
PW
787 // release outbound grant (if any)
788 pnode->grantOutbound.Release();
092631f0 789
0a61b0df 790 // close socket and cleanup
791 pnode->CloseSocketDisconnect();
0a61b0df 792
793 // hold in disconnected pool until all refs are released
0a61b0df 794 if (pnode->fNetworkNode || pnode->fInbound)
795 pnode->Release();
796 vNodesDisconnected.push_back(pnode);
797 }
798 }
49d754d9
PW
799 }
800 {
0a61b0df 801 // Delete disconnected nodes
802 list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
223b6f1b 803 BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy)
0a61b0df 804 {
805 // wait until threads are done using it
806 if (pnode->GetRefCount() <= 0)
807 {
808 bool fDelete = false;
f8dcd5ca
PW
809 {
810 TRY_LOCK(pnode->cs_vSend, lockSend);
811 if (lockSend)
812 {
607dbfde 813 TRY_LOCK(pnode->cs_vRecvMsg, lockRecv);
f8dcd5ca
PW
814 if (lockRecv)
815 {
529a4d48
WL
816 TRY_LOCK(pnode->cs_inventory, lockInv);
817 if (lockInv)
818 fDelete = true;
f8dcd5ca
PW
819 }
820 }
821 }
0a61b0df 822 if (fDelete)
823 {
824 vNodesDisconnected.remove(pnode);
825 delete pnode;
826 }
827 }
828 }
829 }
ce14345a 830 if(vNodes.size() != nPrevNodeCount) {
0a61b0df 831 nPrevNodeCount = vNodes.size();
ce14345a 832 uiInterface.NotifyNumConnectionsChanged(nPrevNodeCount);
0a61b0df 833 }
834
0a61b0df 835 //
836 // Find which sockets have data to receive
837 //
838 struct timeval timeout;
839 timeout.tv_sec = 0;
840 timeout.tv_usec = 50000; // frequency to poll pnode->vSend
841
842 fd_set fdsetRecv;
843 fd_set fdsetSend;
844 fd_set fdsetError;
845 FD_ZERO(&fdsetRecv);
846 FD_ZERO(&fdsetSend);
847 FD_ZERO(&fdsetError);
848 SOCKET hSocketMax = 0;
23879447 849 bool have_fds = false;
5f88e888 850
dc942e6f
PW
851 BOOST_FOREACH(const ListenSocket& hListenSocket, vhListenSocket) {
852 FD_SET(hListenSocket.socket, &fdsetRecv);
853 hSocketMax = max(hSocketMax, hListenSocket.socket);
23879447 854 have_fds = true;
8f10a288 855 }
5d599212 856
0a61b0df 857 {
f8dcd5ca 858 LOCK(cs_vNodes);
223b6f1b 859 BOOST_FOREACH(CNode* pnode, vNodes)
0a61b0df 860 {
d7f1d200 861 if (pnode->hSocket == INVALID_SOCKET)
0a61b0df 862 continue;
a9d9f0f5
PW
863 FD_SET(pnode->hSocket, &fdsetError);
864 hSocketMax = max(hSocketMax, pnode->hSocket);
865 have_fds = true;
866
867 // Implement the following logic:
868 // * If there is data to send, select() for sending data. As this only
869 // happens when optimistic write failed, we choose to first drain the
870 // write buffer in this case before receiving more. This avoids
871 // needlessly queueing received data, if the remote peer is not themselves
872 // receiving data. This means properly utilizing TCP flow control signalling.
873 // * Otherwise, if there is no (complete) message in the receive buffer,
874 // or there is space left in the buffer, select() for receiving data.
875 // * (if neither of the above applies, there is certainly one message
876 // in the receiver buffer ready to be processed).
877 // Together, that means that at least one of the following is always possible,
878 // so we don't deadlock:
879 // * We send some data.
880 // * We wait for data to be received (and disconnect after timeout).
881 // * We process a message in the buffer (message handler thread).
f8dcd5ca
PW
882 {
883 TRY_LOCK(pnode->cs_vSend, lockSend);
a9d9f0f5
PW
884 if (lockSend && !pnode->vSendMsg.empty()) {
885 FD_SET(pnode->hSocket, &fdsetSend);
886 continue;
b9ff2970 887 }
f8dcd5ca 888 }
a9d9f0f5
PW
889 {
890 TRY_LOCK(pnode->cs_vRecvMsg, lockRecv);
891 if (lockRecv && (
892 pnode->vRecvMsg.empty() || !pnode->vRecvMsg.front().complete() ||
893 pnode->GetTotalRecvSize() <= ReceiveFloodSize()))
894 FD_SET(pnode->hSocket, &fdsetRecv);
895 }
0a61b0df 896 }
897 }
898
23879447
JG
899 int nSelect = select(have_fds ? hSocketMax + 1 : 0,
900 &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
21eb5ada
GA
901 boost::this_thread::interruption_point();
902
0a61b0df 903 if (nSelect == SOCKET_ERROR)
904 {
23879447 905 if (have_fds)
c6710c7a 906 {
23879447 907 int nErr = WSAGetLastError();
a60838d0 908 LogPrintf("socket select error %s\n", NetworkErrorString(nErr));
c376ac35 909 for (unsigned int i = 0; i <= hSocketMax; i++)
c6710c7a
MC
910 FD_SET(i, &fdsetRecv);
911 }
0a61b0df 912 FD_ZERO(&fdsetSend);
913 FD_ZERO(&fdsetError);
1b43bf0d 914 MilliSleep(timeout.tv_usec/1000);
0a61b0df 915 }
916
0a61b0df 917 //
918 // Accept new connections
919 //
dc942e6f 920 BOOST_FOREACH(const ListenSocket& hListenSocket, vhListenSocket)
0a61b0df 921 {
dc942e6f 922 if (hListenSocket.socket != INVALID_SOCKET && FD_ISSET(hListenSocket.socket, &fdsetRecv))
f8dcd5ca 923 {
5d599212
PK
924 struct sockaddr_storage sockaddr;
925 socklen_t len = sizeof(sockaddr);
dc942e6f 926 SOCKET hSocket = accept(hListenSocket.socket, (struct sockaddr*)&sockaddr, &len);
5d599212
PK
927 CAddress addr;
928 int nInbound = 0;
929
930 if (hSocket != INVALID_SOCKET)
931 if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
932 LogPrintf("Warning: Unknown socket family\n");
25ab1758 933
dc942e6f 934 bool whitelisted = hListenSocket.whitelisted || CNode::IsWhitelistedRange(addr);
f8dcd5ca
PW
935 {
936 LOCK(cs_vNodes);
5d599212
PK
937 BOOST_FOREACH(CNode* pnode, vNodes)
938 if (pnode->fInbound)
939 nInbound++;
940 }
941
942 if (hSocket == INVALID_SOCKET)
943 {
944 int nErr = WSAGetLastError();
945 if (nErr != WSAEWOULDBLOCK)
946 LogPrintf("socket error accept failed: %s\n", NetworkErrorString(nErr));
947 }
948 else if (nInbound >= nMaxConnections - MAX_OUTBOUND_CONNECTIONS)
949 {
43f510d3 950 CloseSocket(hSocket);
5d599212 951 }
dc942e6f 952 else if (CNode::IsBanned(addr) && !whitelisted)
5d599212
PK
953 {
954 LogPrintf("connection from %s dropped (banned)\n", addr.ToString());
43f510d3 955 CloseSocket(hSocket);
5d599212
PK
956 }
957 else
958 {
5d599212
PK
959 CNode* pnode = new CNode(hSocket, addr, "", true);
960 pnode->AddRef();
dc942e6f 961 pnode->fWhitelisted = whitelisted;
5d599212
PK
962
963 {
964 LOCK(cs_vNodes);
965 vNodes.push_back(pnode);
966 }
f8dcd5ca 967 }
0a61b0df 968 }
969 }
970
0a61b0df 971 //
972 // Service each socket
973 //
974 vector<CNode*> vNodesCopy;
0a61b0df 975 {
f8dcd5ca 976 LOCK(cs_vNodes);
0a61b0df 977 vNodesCopy = vNodes;
223b6f1b 978 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 979 pnode->AddRef();
980 }
223b6f1b 981 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 982 {
21eb5ada 983 boost::this_thread::interruption_point();
0a61b0df 984
985 //
986 // Receive
987 //
988 if (pnode->hSocket == INVALID_SOCKET)
989 continue;
990 if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
991 {
607dbfde 992 TRY_LOCK(pnode->cs_vRecvMsg, lockRecv);
f8dcd5ca 993 if (lockRecv)
0a61b0df 994 {
a9d9f0f5 995 {
9cbae55a
GA
996 // typical socket buffer is 8K-64K
997 char pchBuf[0x10000];
998 int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
999 if (nBytes > 0)
0a61b0df 1000 {
607dbfde
JG
1001 if (!pnode->ReceiveMsgBytes(pchBuf, nBytes))
1002 pnode->CloseSocketDisconnect();
9cbae55a 1003 pnode->nLastRecv = GetTime();
86648a8d 1004 pnode->nRecvBytes += nBytes;
ce14345a 1005 pnode->RecordBytesRecv(nBytes);
9cbae55a
GA
1006 }
1007 else if (nBytes == 0)
1008 {
1009 // socket closed gracefully
0a61b0df 1010 if (!pnode->fDisconnect)
881a85a2 1011 LogPrint("net", "socket closed\n");
0a61b0df 1012 pnode->CloseSocketDisconnect();
1013 }
9cbae55a
GA
1014 else if (nBytes < 0)
1015 {
1016 // error
1017 int nErr = WSAGetLastError();
1018 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
1019 {
1020 if (!pnode->fDisconnect)
a60838d0 1021 LogPrintf("socket recv error %s\n", NetworkErrorString(nErr));
9cbae55a
GA
1022 pnode->CloseSocketDisconnect();
1023 }
1024 }
0a61b0df 1025 }
1026 }
1027 }
1028
1029 //
1030 // Send
1031 //
1032 if (pnode->hSocket == INVALID_SOCKET)
1033 continue;
1034 if (FD_ISSET(pnode->hSocket, &fdsetSend))
1035 {
f8dcd5ca
PW
1036 TRY_LOCK(pnode->cs_vSend, lockSend);
1037 if (lockSend)
bc2f5aa7 1038 SocketSendData(pnode);
0a61b0df 1039 }
1040
1041 //
1042 // Inactivity checking
1043 //
f1920e86
PW
1044 int64_t nTime = GetTime();
1045 if (nTime - pnode->nTimeConnected > 60)
0a61b0df 1046 {
1047 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
1048 {
2e36866f 1049 LogPrint("net", "socket no message in first 60 seconds, %d %d from %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0, pnode->id);
0a61b0df 1050 pnode->fDisconnect = true;
1051 }
f1920e86 1052 else if (nTime - pnode->nLastSend > TIMEOUT_INTERVAL)
0a61b0df 1053 {
f1920e86 1054 LogPrintf("socket sending timeout: %is\n", nTime - pnode->nLastSend);
0a61b0df 1055 pnode->fDisconnect = true;
1056 }
f1920e86 1057 else if (nTime - pnode->nLastRecv > (pnode->nVersion > BIP0031_VERSION ? TIMEOUT_INTERVAL : 90*60))
0a61b0df 1058 {
f1920e86
PW
1059 LogPrintf("socket receive timeout: %is\n", nTime - pnode->nLastRecv);
1060 pnode->fDisconnect = true;
1061 }
1062 else if (pnode->nPingNonceSent && pnode->nPingUsecStart + TIMEOUT_INTERVAL * 1000000 < GetTimeMicros())
1063 {
1064 LogPrintf("ping timeout: %fs\n", 0.000001 * (GetTimeMicros() - pnode->nPingUsecStart));
0a61b0df 1065 pnode->fDisconnect = true;
1066 }
1067 }
1068 }
0a61b0df 1069 {
f8dcd5ca 1070 LOCK(cs_vNodes);
223b6f1b 1071 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 1072 pnode->Release();
1073 }
0a61b0df 1074 }
1075}
1076
1077
1078
1079
1080
1081
1082
1083
1084
8bb5edc1 1085#ifdef USE_UPNP
21eb5ada 1086void ThreadMapPort()
8bb5edc1 1087{
463a1cab 1088 std::string port = strprintf("%u", GetListenPort());
8bb5edc1
MC
1089 const char * multicastif = 0;
1090 const char * minissdpdpath = 0;
1091 struct UPNPDev * devlist = 0;
1092 char lanaddr[64];
1093
94b97046
LD
1094#ifndef UPNPDISCOVER_SUCCESS
1095 /* miniupnpc 1.5 */
1096 devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0);
1097#else
1098 /* miniupnpc 1.6 */
1099 int error = 0;
b4ada906 1100 devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error);
94b97046 1101#endif
8bb5edc1
MC
1102
1103 struct UPNPUrls urls;
1104 struct IGDdatas data;
1105 int r;
1106
f285d4f4
DH
1107 r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
1108 if (r == 1)
8bb5edc1 1109 {
587f929c 1110 if (fDiscover) {
baba6e7d
MC
1111 char externalIPAddress[40];
1112 r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
1113 if(r != UPNPCOMMAND_SUCCESS)
881a85a2 1114 LogPrintf("UPnP: GetExternalIPAddress() returned %d\n", r);
baba6e7d
MC
1115 else
1116 {
1117 if(externalIPAddress[0])
1118 {
881a85a2 1119 LogPrintf("UPnP: ExternalIPAddress = %s\n", externalIPAddress);
19b6958c 1120 AddLocal(CNetAddr(externalIPAddress), LOCAL_UPNP);
baba6e7d
MC
1121 }
1122 else
881a85a2 1123 LogPrintf("UPnP: GetExternalIPAddress failed.\n");
baba6e7d
MC
1124 }
1125 }
1126
15656981 1127 string strDesc = "Bitcoin " + FormatFullVersion();
b4ada906 1128
21eb5ada 1129 try {
050d2e95 1130 while (true) {
177dbcaa
MC
1131#ifndef UPNPDISCOVER_SUCCESS
1132 /* miniupnpc 1.5 */
1133 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
9c809094 1134 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0);
177dbcaa
MC
1135#else
1136 /* miniupnpc 1.6 */
1137 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
9c809094 1138 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0");
177dbcaa
MC
1139#endif
1140
1141 if(r!=UPNPCOMMAND_SUCCESS)
881a85a2 1142 LogPrintf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
7d9d134b 1143 port, port, lanaddr, r, strupnperror(r));
177dbcaa 1144 else
881a85a2 1145 LogPrintf("UPnP Port Mapping successful.\n");;
21eb5ada
GA
1146
1147 MilliSleep(20*60*1000); // Refresh every 20 minutes
177dbcaa 1148 }
21eb5ada
GA
1149 }
1150 catch (boost::thread_interrupted)
1151 {
1152 r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0);
881a85a2 1153 LogPrintf("UPNP_DeletePortMapping() returned : %d\n", r);
21eb5ada
GA
1154 freeUPNPDevlist(devlist); devlist = 0;
1155 FreeUPNPUrls(&urls);
1156 throw;
8bb5edc1
MC
1157 }
1158 } else {
881a85a2 1159 LogPrintf("No valid UPnP IGDs found\n");
8bb5edc1 1160 freeUPNPDevlist(devlist); devlist = 0;
f285d4f4
DH
1161 if (r != 0)
1162 FreeUPNPUrls(&urls);
8bb5edc1
MC
1163 }
1164}
1165
21eb5ada 1166void MapPort(bool fUseUPnP)
8bb5edc1 1167{
21eb5ada
GA
1168 static boost::thread* upnp_thread = NULL;
1169
1170 if (fUseUPnP)
8bb5edc1 1171 {
21eb5ada
GA
1172 if (upnp_thread) {
1173 upnp_thread->interrupt();
1174 upnp_thread->join();
1175 delete upnp_thread;
1176 }
53e71135 1177 upnp_thread = new boost::thread(boost::bind(&TraceThread<void (*)()>, "upnp", &ThreadMapPort));
21eb5ada
GA
1178 }
1179 else if (upnp_thread) {
1180 upnp_thread->interrupt();
1181 upnp_thread->join();
1182 delete upnp_thread;
1183 upnp_thread = NULL;
8bb5edc1
MC
1184 }
1185}
21eb5ada 1186
9f0ac169 1187#else
21eb5ada 1188void MapPort(bool)
9f0ac169
GA
1189{
1190 // Intentionally left blank.
1191}
8bb5edc1
MC
1192#endif
1193
1194
1195
1196
1197
1198
21eb5ada 1199void ThreadDNSAddressSeed()
2bc6cece 1200{
2e7009d6
JG
1201 // goal: only query DNS seeds if address need is acute
1202 if ((addrman.size() > 0) &&
1203 (!GetBoolArg("-forcednsseed", false))) {
1204 MilliSleep(11 * 1000);
1205
1206 LOCK(cs_vNodes);
1207 if (vNodes.size() >= 2) {
1208 LogPrintf("P2P peers available. Skipped DNS seeding.\n");
1209 return;
1210 }
1211 }
1212
0e4b3175 1213 const vector<CDNSSeedData> &vSeeds = Params().DNSSeeds();
f684aec4
JG
1214 int found = 0;
1215
881a85a2 1216 LogPrintf("Loading addresses from DNS seeds (could take a while)\n");
af899882 1217
0e4b3175 1218 BOOST_FOREACH(const CDNSSeedData &seed, vSeeds) {
af899882 1219 if (HaveNameProxy()) {
0e4b3175 1220 AddOneShot(seed.host);
af899882 1221 } else {
0e4b3175 1222 vector<CNetAddr> vIPs;
af899882 1223 vector<CAddress> vAdd;
0e4b3175 1224 if (LookupHost(seed.host.c_str(), vIPs))
af899882 1225 {
0e4b3175 1226 BOOST_FOREACH(CNetAddr& ip, vIPs)
a6a5bb7c 1227 {
af899882 1228 int nOneDay = 24*3600;
0e4b3175 1229 CAddress addr = CAddress(CService(ip, Params().GetDefaultPort()));
af899882
PT
1230 addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
1231 vAdd.push_back(addr);
1232 found++;
a6a5bb7c 1233 }
f684aec4 1234 }
0e4b3175 1235 addrman.Add(vAdd, CNetAddr(seed.name, true));
f684aec4
JG
1236 }
1237 }
1238
881a85a2 1239 LogPrintf("%d addresses found from DNS seeds\n", found);
f684aec4 1240}
0a61b0df 1241
1242
1243
2bc6cece
MC
1244
1245
1246
1247
1248
1249
1250
1251
1252
5fee401f
PW
1253void DumpAddresses()
1254{
51ed9ec9 1255 int64_t nStart = GetTimeMillis();
928d3a01 1256
5fee401f 1257 CAddrDB adb;
928d3a01
JG
1258 adb.Write(addrman);
1259
f48742c2 1260 LogPrint("net", "Flushed %d addresses to peers.dat %dms\n",
928d3a01 1261 addrman.size(), GetTimeMillis() - nStart);
5fee401f 1262}
0a61b0df 1263
478b01d9
PW
1264void static ProcessOneShot()
1265{
1266 string strDest;
1267 {
1268 LOCK(cs_vOneShots);
1269 if (vOneShots.empty())
1270 return;
1271 strDest = vOneShots.front();
1272 vOneShots.pop_front();
1273 }
1274 CAddress addr;
c59abe25
PW
1275 CSemaphoreGrant grant(*semOutbound, true);
1276 if (grant) {
1277 if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true))
1278 AddOneShot(strDest);
1279 }
478b01d9
PW
1280}
1281
21eb5ada 1282void ThreadOpenConnections()
0a61b0df 1283{
0a61b0df 1284 // Connect to specific addresses
f161a2c2 1285 if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
0a61b0df 1286 {
51ed9ec9 1287 for (int64_t nLoop = 0;; nLoop++)
0a61b0df 1288 {
478b01d9 1289 ProcessOneShot();
223b6f1b 1290 BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
0a61b0df 1291 {
478b01d9 1292 CAddress addr;
c59abe25 1293 OpenNetworkConnection(addr, NULL, strAddr.c_str());
0a61b0df 1294 for (int i = 0; i < 10 && i < nLoop; i++)
1295 {
1b43bf0d 1296 MilliSleep(500);
0a61b0df 1297 }
1298 }
1b43bf0d 1299 MilliSleep(500);
0a61b0df 1300 }
1301 }
1302
0a61b0df 1303 // Initiate network connections
51ed9ec9 1304 int64_t nStart = GetTime();
050d2e95 1305 while (true)
0a61b0df 1306 {
478b01d9
PW
1307 ProcessOneShot();
1308
1b43bf0d 1309 MilliSleep(500);
cc201e01 1310
c59abe25 1311 CSemaphoreGrant grant(*semOutbound);
21eb5ada 1312 boost::this_thread::interruption_point();
0a61b0df 1313
0e4b3175
MH
1314 // Add seed nodes if DNS seeds are all down (an infrastructure attack?).
1315 if (addrman.size() == 0 && (GetTime() - nStart > 60)) {
1316 static bool done = false;
1317 if (!done) {
881a85a2 1318 LogPrintf("Adding fixed seed nodes as DNS doesn't seem to be available.\n");
0e4b3175
MH
1319 addrman.Add(Params().FixedSeeds(), CNetAddr("127.0.0.1"));
1320 done = true;
0a61b0df 1321 }
1322 }
1323
0a61b0df 1324 //
1325 // Choose an address to connect to based on most recently seen
1326 //
1327 CAddress addrConnect;
0a61b0df 1328
19521acf 1329 // Only connect out to one peer per network group (/16 for IPv4).
0a61b0df 1330 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
c59abe25 1331 int nOutbound = 0;
67a42f92 1332 set<vector<unsigned char> > setConnected;
f8dcd5ca
PW
1333 {
1334 LOCK(cs_vNodes);
c59abe25 1335 BOOST_FOREACH(CNode* pnode, vNodes) {
19521acf
GM
1336 if (!pnode->fInbound) {
1337 setConnected.insert(pnode->addr.GetGroup());
c59abe25 1338 nOutbound++;
19521acf 1339 }
c59abe25 1340 }
f8dcd5ca 1341 }
0a61b0df 1342
51ed9ec9 1343 int64_t nANow = GetAdjustedTime();
a4e6ae10 1344
5fee401f 1345 int nTries = 0;
050d2e95 1346 while (true)
0a61b0df 1347 {
5fee401f
PW
1348 // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
1349 CAddress addr = addrman.Select(10 + min(nOutbound,8)*10);
0a61b0df 1350
5fee401f 1351 // if we selected an invalid address, restart
23aa78c4 1352 if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
5fee401f 1353 break;
0a61b0df 1354
f161a2c2
PW
1355 // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
1356 // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
1357 // already-connected network ranges, ...) before trying new addrman addresses.
5fee401f 1358 nTries++;
f161a2c2
PW
1359 if (nTries > 100)
1360 break;
0a61b0df 1361
457754d2
PW
1362 if (IsLimited(addr))
1363 continue;
1364
5fee401f
PW
1365 // only consider very recently tried nodes after 30 failed attempts
1366 if (nANow - addr.nLastTry < 600 && nTries < 30)
1367 continue;
1368
1369 // do not allow non-default ports, unless after 50 invalid addresses selected already
0e4b3175 1370 if (addr.GetPort() != Params().GetDefaultPort() && nTries < 50)
5fee401f
PW
1371 continue;
1372
1373 addrConnect = addr;
1374 break;
0a61b0df 1375 }
1376
1377 if (addrConnect.IsValid())
c59abe25 1378 OpenNetworkConnection(addrConnect, &grant);
0a61b0df 1379 }
1380}
1381
21eb5ada 1382void ThreadOpenAddedConnections()
b24e6e4d 1383{
74088e86
MC
1384 {
1385 LOCK(cs_vAddedNodes);
1386 vAddedNodes = mapMultiArgs["-addnode"];
1387 }
b24e6e4d 1388
81bbef26 1389 if (HaveNameProxy()) {
21eb5ada 1390 while(true) {
74088e86
MC
1391 list<string> lAddresses(0);
1392 {
1393 LOCK(cs_vAddedNodes);
1394 BOOST_FOREACH(string& strAddNode, vAddedNodes)
1395 lAddresses.push_back(strAddNode);
1396 }
1397 BOOST_FOREACH(string& strAddNode, lAddresses) {
9bab521d 1398 CAddress addr;
c59abe25
PW
1399 CSemaphoreGrant grant(*semOutbound);
1400 OpenNetworkConnection(addr, &grant, strAddNode.c_str());
1b43bf0d 1401 MilliSleep(500);
9bab521d 1402 }
1b43bf0d 1403 MilliSleep(120000); // Retry every 2 minutes
9bab521d 1404 }
9bab521d
PW
1405 }
1406
f2bd6c28 1407 for (unsigned int i = 0; true; i++)
b24e6e4d 1408 {
74088e86
MC
1409 list<string> lAddresses(0);
1410 {
1411 LOCK(cs_vAddedNodes);
1412 BOOST_FOREACH(string& strAddNode, vAddedNodes)
1413 lAddresses.push_back(strAddNode);
1414 }
1415
1416 list<vector<CService> > lservAddressesToAdd(0);
1417 BOOST_FOREACH(string& strAddNode, lAddresses)
b24e6e4d 1418 {
74088e86 1419 vector<CService> vservNode(0);
0e4b3175 1420 if(Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0))
f8dcd5ca 1421 {
74088e86
MC
1422 lservAddressesToAdd.push_back(vservNode);
1423 {
1424 LOCK(cs_setservAddNodeAddresses);
1425 BOOST_FOREACH(CService& serv, vservNode)
1426 setservAddNodeAddresses.insert(serv);
1427 }
f8dcd5ca 1428 }
b24e6e4d 1429 }
b24e6e4d 1430 // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
9bab521d 1431 // (keeping in mind that addnode entries can have many IPs if fNameLookup)
f8dcd5ca
PW
1432 {
1433 LOCK(cs_vNodes);
b24e6e4d 1434 BOOST_FOREACH(CNode* pnode, vNodes)
74088e86 1435 for (list<vector<CService> >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
b24e6e4d
MC
1436 BOOST_FOREACH(CService& addrNode, *(it))
1437 if (pnode->addr == addrNode)
1438 {
74088e86 1439 it = lservAddressesToAdd.erase(it);
b24e6e4d
MC
1440 it--;
1441 break;
1442 }
f8dcd5ca 1443 }
74088e86 1444 BOOST_FOREACH(vector<CService>& vserv, lservAddressesToAdd)
b24e6e4d 1445 {
c59abe25 1446 CSemaphoreGrant grant(*semOutbound);
f2bd6c28 1447 OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant);
1b43bf0d 1448 MilliSleep(500);
b24e6e4d 1449 }
1b43bf0d 1450 MilliSleep(120000); // Retry every 2 minutes
b24e6e4d
MC
1451 }
1452}
1453
814efd6f 1454// if successful, this moves the passed grant to the constructed node
5bd6c31b 1455bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *pszDest, bool fOneShot)
0a61b0df 1456{
1457 //
1458 // Initiate outbound network connection
1459 //
21eb5ada 1460 boost::this_thread::interruption_point();
5bd6c31b 1461 if (!pszDest) {
39857190
PW
1462 if (IsLocal(addrConnect) ||
1463 FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
f469f79f 1464 FindNode(addrConnect.ToStringIPPort()))
9bab521d 1465 return false;
634bd61b 1466 } else if (FindNode(pszDest))
0a61b0df 1467 return false;
1468
5bd6c31b 1469 CNode* pnode = ConnectNode(addrConnect, pszDest);
21eb5ada
GA
1470 boost::this_thread::interruption_point();
1471
0a61b0df 1472 if (!pnode)
1473 return false;
c59abe25
PW
1474 if (grantOutbound)
1475 grantOutbound->MoveTo(pnode->grantOutbound);
0a61b0df 1476 pnode->fNetworkNode = true;
478b01d9
PW
1477 if (fOneShot)
1478 pnode->fOneShot = true;
0a61b0df 1479
0a61b0df 1480 return true;
1481}
1482
1483
21eb5ada 1484void ThreadMessageHandler()
0a61b0df 1485{
0a61b0df 1486 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
21eb5ada 1487 while (true)
0a61b0df 1488 {
1489 vector<CNode*> vNodesCopy;
0a61b0df 1490 {
f8dcd5ca 1491 LOCK(cs_vNodes);
0a61b0df 1492 vNodesCopy = vNodes;
6ed71b5e 1493 BOOST_FOREACH(CNode* pnode, vNodesCopy) {
0a61b0df 1494 pnode->AddRef();
6ed71b5e 1495 }
0a61b0df 1496 }
1497
1498 // Poll the connected nodes for messages
1499 CNode* pnodeTrickle = NULL;
1500 if (!vNodesCopy.empty())
1501 pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
fabba0e6 1502
75ef87dd 1503 bool fSleep = true;
fabba0e6 1504
223b6f1b 1505 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 1506 {
967f2459
PW
1507 if (pnode->fDisconnect)
1508 continue;
1509
0a61b0df 1510 // Receive messages
f8dcd5ca 1511 {
607dbfde 1512 TRY_LOCK(pnode->cs_vRecvMsg, lockRecv);
f8dcd5ca 1513 if (lockRecv)
75ef87dd 1514 {
501da250 1515 if (!g_signals.ProcessMessages(pnode))
607dbfde 1516 pnode->CloseSocketDisconnect();
fabba0e6 1517
75ef87dd
PS
1518 if (pnode->nSendSize < SendBufferSize())
1519 {
1520 if (!pnode->vRecvGetData.empty() || (!pnode->vRecvMsg.empty() && pnode->vRecvMsg[0].complete()))
1521 {
1522 fSleep = false;
1523 }
1524 }
1525 }
f8dcd5ca 1526 }
21eb5ada 1527 boost::this_thread::interruption_point();
0a61b0df 1528
1529 // Send messages
f8dcd5ca
PW
1530 {
1531 TRY_LOCK(pnode->cs_vSend, lockSend);
501da250
EL
1532 if (lockSend)
1533 g_signals.SendMessages(pnode, pnode == pnodeTrickle);
f8dcd5ca 1534 }
21eb5ada 1535 boost::this_thread::interruption_point();
0a61b0df 1536 }
1537
0a61b0df 1538 {
f8dcd5ca 1539 LOCK(cs_vNodes);
223b6f1b 1540 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 1541 pnode->Release();
1542 }
fabba0e6 1543
75ef87dd
PS
1544 if (fSleep)
1545 MilliSleep(100);
0a61b0df 1546 }
1547}
1548
1549
1550
1551
1552
1553
dc942e6f 1554bool BindListenPort(const CService &addrBind, string& strError, bool fWhitelisted)
0a61b0df 1555{
1556 strError = "";
1557 int nOne = 1;
1558
0a61b0df 1559 // Create socket for listening for incoming connections
8f10a288 1560 struct sockaddr_storage sockaddr;
8f10a288
PW
1561 socklen_t len = sizeof(sockaddr);
1562 if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
1563 {
5bd6c31b 1564 strError = strprintf("Error: Bind address family for %s not supported", addrBind.ToString());
7d9d134b 1565 LogPrintf("%s\n", strError);
8f10a288
PW
1566 return false;
1567 }
1568
1569 SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
0a61b0df 1570 if (hListenSocket == INVALID_SOCKET)
1571 {
a60838d0 1572 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %s)", NetworkErrorString(WSAGetLastError()));
7d9d134b 1573 LogPrintf("%s\n", strError);
0a61b0df 1574 return false;
1575 }
1576
9e9ca2b6 1577#ifndef WIN32
ec93a0e2 1578#ifdef SO_NOSIGPIPE
0a61b0df 1579 // Different way of disabling SIGPIPE on BSD
1580 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1581#endif
0a61b0df 1582 // Allow binding if the port is still in TIME_WAIT state after
9e9ca2b6 1583 // the program was closed and restarted. Not an issue on windows!
0a61b0df 1584 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1585#endif
1586
814efd6f 1587 // Set to non-blocking, incoming connections will also inherit this
eaedb59e
PK
1588 if (!SetSocketNonBlocking(hListenSocket, true)) {
1589 strError = strprintf("BindListenPort: Setting listening socket to non-blocking failed, error %s\n", NetworkErrorString(WSAGetLastError()));
7d9d134b 1590 LogPrintf("%s\n", strError);
0a61b0df 1591 return false;
1592 }
1593
8f10a288
PW
1594 // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
1595 // and enable it by default or not. Try to enable it, if possible.
1596 if (addrBind.IsIPv6()) {
1597#ifdef IPV6_V6ONLY
b3e0aaf3
PK
1598#ifdef WIN32
1599 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int));
1600#else
8f10a288 1601 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int));
23aa78c4 1602#endif
b3e0aaf3 1603#endif
8f10a288 1604#ifdef WIN32
9e9ca2b6
PK
1605 int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
1606 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int));
8f10a288
PW
1607#endif
1608 }
8f10a288
PW
1609
1610 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
0a61b0df 1611 {
1612 int nErr = WSAGetLastError();
1613 if (nErr == WSAEADDRINUSE)
d30d379b 1614 strError = strprintf(_("Unable to bind to %s on this computer. Bitcoin Core is probably already running."), addrBind.ToString());
0a61b0df 1615 else
a60838d0 1616 strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %s)"), addrBind.ToString(), NetworkErrorString(nErr));
7d9d134b 1617 LogPrintf("%s\n", strError);
c994d2e7 1618 CloseSocket(hListenSocket);
0a61b0df 1619 return false;
1620 }
7d9d134b 1621 LogPrintf("Bound to %s\n", addrBind.ToString());
0a61b0df 1622
1623 // Listen for incoming connections
1624 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1625 {
a60838d0 1626 strError = strprintf(_("Error: Listening for incoming connections failed (listen returned error %s)"), NetworkErrorString(WSAGetLastError()));
7d9d134b 1627 LogPrintf("%s\n", strError);
c994d2e7 1628 CloseSocket(hListenSocket);
0a61b0df 1629 return false;
1630 }
1631
dc942e6f 1632 vhListenSocket.push_back(ListenSocket(hListenSocket, fWhitelisted));
8f10a288 1633
dc942e6f 1634 if (addrBind.IsRoutable() && fDiscover && !fWhitelisted)
8f10a288
PW
1635 AddLocal(addrBind, LOCAL_BIND);
1636
0a61b0df 1637 return true;
1638}
1639
80ecf670 1640void static Discover(boost::thread_group& threadGroup)
0a61b0df 1641{
587f929c 1642 if (!fDiscover)
19b6958c 1643 return;
0a61b0df 1644
6853e627 1645#ifdef WIN32
814efd6f 1646 // Get local host IP
0a61b0df 1647 char pszHostName[1000] = "";
1648 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1649 {
67a42f92
PW
1650 vector<CNetAddr> vaddr;
1651 if (LookupHost(pszHostName, vaddr))
f8e4d43b 1652 {
67a42f92 1653 BOOST_FOREACH (const CNetAddr &addr, vaddr)
f8e4d43b 1654 {
39857190 1655 AddLocal(addr, LOCAL_IF);
f8e4d43b
PK
1656 }
1657 }
0a61b0df 1658 }
1659#else
1660 // Get local host ip
1661 struct ifaddrs* myaddrs;
1662 if (getifaddrs(&myaddrs) == 0)
1663 {
1664 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1665 {
1666 if (ifa->ifa_addr == NULL) continue;
1667 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1668 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1669 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
0a61b0df 1670 if (ifa->ifa_addr->sa_family == AF_INET)
1671 {
1672 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
39857190 1673 CNetAddr addr(s4->sin_addr);
23aa78c4 1674 if (AddLocal(addr, LOCAL_IF))
7d9d134b 1675 LogPrintf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString());
0a61b0df 1676 }
1677 else if (ifa->ifa_addr->sa_family == AF_INET6)
1678 {
1679 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
39857190 1680 CNetAddr addr(s6->sin6_addr);
23aa78c4 1681 if (AddLocal(addr, LOCAL_IF))
7d9d134b 1682 LogPrintf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString());
0a61b0df 1683 }
1684 }
1685 freeifaddrs(myaddrs);
1686 }
1687#endif
0a61b0df 1688
a76552ce
PK
1689 // Don't use external IPv4 discovery, when -onlynet="IPv6"
1690 if (!IsLimited(NET_IPV4))
80ecf670 1691 threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "ext-ip", &ThreadGetMyExternalIP));
19b6958c
PW
1692}
1693
b31499ec 1694void StartNode(boost::thread_group& threadGroup)
19b6958c 1695{
94064710
WL
1696 uiInterface.InitMessage(_("Loading addresses..."));
1697 // Load addresses for peers.dat
1698 int64_t nStart = GetTimeMillis();
1699 {
1700 CAddrDB adb;
1701 if (!adb.Read(addrman))
1702 LogPrintf("Invalid or missing peers.dat; recreating\n");
1703 }
1704 LogPrintf("Loaded %i addresses from peers.dat %dms\n",
1705 addrman.size(), GetTimeMillis() - nStart);
1706 fAddressesInitialized = true;
1707
c59abe25
PW
1708 if (semOutbound == NULL) {
1709 // initialize semaphore
ba29a559 1710 int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, nMaxConnections);
c59abe25
PW
1711 semOutbound = new CSemaphore(nMaxOutbound);
1712 }
1713
19b6958c
PW
1714 if (pnodeLocalHost == NULL)
1715 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", 0), nLocalServices));
1716
80ecf670 1717 Discover(threadGroup);
0a61b0df 1718
1719 //
1720 // Start threads
1721 //
1722
9d952d17 1723 if (!GetBoolArg("-dnsseed", true))
881a85a2 1724 LogPrintf("DNS seeding disabled\n");
2bc6cece 1725 else
53e71135 1726 threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "dnsseed", &ThreadDNSAddressSeed));
2bc6cece 1727
8bb5edc1 1728 // Map ports with UPnP
d4e1c612 1729 MapPort(GetBoolArg("-upnp", DEFAULT_UPNP));
8bb5edc1 1730
0a61b0df 1731 // Send and receive from sockets, accept connections
b31499ec 1732 threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "net", &ThreadSocketHandler));
0a61b0df 1733
b24e6e4d 1734 // Initiate outbound connections from -addnode
b31499ec 1735 threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "addcon", &ThreadOpenAddedConnections));
b24e6e4d 1736
0a61b0df 1737 // Initiate outbound connections
b31499ec 1738 threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "opencon", &ThreadOpenConnections));
0a61b0df 1739
1740 // Process messages
b31499ec 1741 threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "msghand", &ThreadMessageHandler));
0a61b0df 1742
5fee401f 1743 // Dump network addresses
c43da3f1 1744 threadGroup.create_thread(boost::bind(&LoopForever<void (*)()>, "dumpaddr", &DumpAddresses, DUMP_ADDRESSES_INTERVAL * 1000));
0a61b0df 1745}
1746
1747bool StopNode()
1748{
881a85a2 1749 LogPrintf("StopNode()\n");
21eb5ada 1750 MapPort(false);
89b5616d
PW
1751 if (semOutbound)
1752 for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
1753 semOutbound->post();
94064710
WL
1754
1755 if (fAddressesInitialized)
1756 {
1757 DumpAddresses();
1758 fAddressesInitialized = false;
1759 }
3427517d 1760
0a61b0df 1761 return true;
1762}
1763
1764class CNetCleanup
1765{
1766public:
5bd6c31b
PK
1767 CNetCleanup() {}
1768
0a61b0df 1769 ~CNetCleanup()
1770 {
1771 // Close sockets
223b6f1b 1772 BOOST_FOREACH(CNode* pnode, vNodes)
0a61b0df 1773 if (pnode->hSocket != INVALID_SOCKET)
43f510d3 1774 CloseSocket(pnode->hSocket);
dc942e6f
PW
1775 BOOST_FOREACH(ListenSocket& hListenSocket, vhListenSocket)
1776 if (hListenSocket.socket != INVALID_SOCKET)
43f510d3
WL
1777 if (!CloseSocket(hListenSocket.socket))
1778 LogPrintf("CloseSocket(hListenSocket) failed with error %s\n", NetworkErrorString(WSAGetLastError()));
0a61b0df 1779
3427517d
PW
1780 // clean up some globals (to help leak detection)
1781 BOOST_FOREACH(CNode *pnode, vNodes)
1782 delete pnode;
1783 BOOST_FOREACH(CNode *pnode, vNodesDisconnected)
1784 delete pnode;
1785 vNodes.clear();
1786 vNodesDisconnected.clear();
3dc1464f 1787 vhListenSocket.clear();
3427517d
PW
1788 delete semOutbound;
1789 semOutbound = NULL;
1790 delete pnodeLocalHost;
1791 pnodeLocalHost = NULL;
1792
6853e627 1793#ifdef WIN32
0a61b0df 1794 // Shutdown Windows Sockets
1795 WSACleanup();
1796#endif
1797 }
1798}
1799instance_of_cnetcleanup;
269d9c64
MC
1800
1801
1802
1803
1804
1805
1806
d38da59b 1807void RelayTransaction(const CTransaction& tx)
269d9c64
MC
1808{
1809 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
1810 ss.reserve(10000);
1811 ss << tx;
d38da59b 1812 RelayTransaction(tx, ss);
269d9c64
MC
1813}
1814
d38da59b 1815void RelayTransaction(const CTransaction& tx, const CDataStream& ss)
269d9c64 1816{
d38da59b 1817 CInv inv(MSG_TX, tx.GetHash());
269d9c64
MC
1818 {
1819 LOCK(cs_mapRelay);
1820 // Expire old relay messages
1821 while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
1822 {
1823 mapRelay.erase(vRelayExpiration.front().second);
1824 vRelayExpiration.pop_front();
1825 }
1826
1827 // Save original serialized message so newer versions are preserved
1828 mapRelay.insert(std::make_pair(inv, ss));
1829 vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
1830 }
1831 LOCK(cs_vNodes);
1832 BOOST_FOREACH(CNode* pnode, vNodes)
1833 {
4c8fc1a5
MC
1834 if(!pnode->fRelayTxes)
1835 continue;
269d9c64
MC
1836 LOCK(pnode->cs_filter);
1837 if (pnode->pfilter)
1838 {
d38da59b 1839 if (pnode->pfilter->IsRelevantAndUpdate(tx))
269d9c64
MC
1840 pnode->PushInventory(inv);
1841 } else
1842 pnode->PushInventory(inv);
1843 }
1844}
ce14345a 1845
51ed9ec9 1846void CNode::RecordBytesRecv(uint64_t bytes)
ce14345a
SE
1847{
1848 LOCK(cs_totalBytesRecv);
1849 nTotalBytesRecv += bytes;
1850}
1851
51ed9ec9 1852void CNode::RecordBytesSent(uint64_t bytes)
ce14345a
SE
1853{
1854 LOCK(cs_totalBytesSent);
1855 nTotalBytesSent += bytes;
1856}
1857
51ed9ec9 1858uint64_t CNode::GetTotalBytesRecv()
ce14345a
SE
1859{
1860 LOCK(cs_totalBytesRecv);
1861 return nTotalBytesRecv;
1862}
1863
51ed9ec9 1864uint64_t CNode::GetTotalBytesSent()
ce14345a
SE
1865{
1866 LOCK(cs_totalBytesSent);
1867 return nTotalBytesSent;
1868}
9038b18f
GA
1869
1870void CNode::Fuzz(int nChance)
1871{
1872 if (!fSuccessfullyConnected) return; // Don't fuzz initial handshake
1873 if (GetRand(nChance) != 0) return; // Fuzz 1 of every nChance messages
1874
1875 switch (GetRand(3))
1876 {
1877 case 0:
1878 // xor a random byte with a random value:
1879 if (!ssSend.empty()) {
1880 CDataStream::size_type pos = GetRand(ssSend.size());
1881 ssSend[pos] ^= (unsigned char)(GetRand(256));
1882 }
1883 break;
1884 case 1:
1885 // delete a random byte:
1886 if (!ssSend.empty()) {
1887 CDataStream::size_type pos = GetRand(ssSend.size());
1888 ssSend.erase(ssSend.begin()+pos);
1889 }
1890 break;
1891 case 2:
1892 // insert a random byte at a random position
1893 {
1894 CDataStream::size_type pos = GetRand(ssSend.size());
1895 char ch = (char)GetRand(256);
1896 ssSend.insert(ssSend.begin()+pos, ch);
1897 }
1898 break;
1899 }
1900 // Chance of more than one change half the time:
1901 // (more changes exponentially less likely):
1902 Fuzz(2);
1903}
d004d727
WL
1904
1905//
1906// CAddrDB
1907//
1908
1909CAddrDB::CAddrDB()
1910{
1911 pathAddr = GetDataDir() / "peers.dat";
1912}
1913
1914bool CAddrDB::Write(const CAddrMan& addr)
1915{
1916 // Generate random temporary filename
1917 unsigned short randv = 0;
001a53d7 1918 GetRandBytes((unsigned char*)&randv, sizeof(randv));
d004d727
WL
1919 std::string tmpfn = strprintf("peers.dat.%04x", randv);
1920
1921 // serialize addresses, checksum data up to that point, then append csum
1922 CDataStream ssPeers(SER_DISK, CLIENT_VERSION);
1923 ssPeers << FLATDATA(Params().MessageStart());
1924 ssPeers << addr;
1925 uint256 hash = Hash(ssPeers.begin(), ssPeers.end());
1926 ssPeers << hash;
1927
1928 // open temp output file, and associate with CAutoFile
1929 boost::filesystem::path pathTmp = GetDataDir() / tmpfn;
1930 FILE *file = fopen(pathTmp.string().c_str(), "wb");
eee030f6 1931 CAutoFile fileout(file, SER_DISK, CLIENT_VERSION);
d004d727 1932 if (!fileout)
2fdd4c79 1933 return error("%s : Failed to open file %s", __func__, pathTmp.string());
d004d727
WL
1934
1935 // Write and commit header, data
1936 try {
1937 fileout << ssPeers;
1938 }
1939 catch (std::exception &e) {
2fdd4c79 1940 return error("%s : Serialize or I/O error - %s", __func__, e.what());
d004d727
WL
1941 }
1942 FileCommit(fileout);
1943 fileout.fclose();
1944
1945 // replace existing peers.dat, if any, with new peers.dat.XXXX
1946 if (!RenameOver(pathTmp, pathAddr))
2fdd4c79 1947 return error("%s : Rename-into-place failed", __func__);
d004d727
WL
1948
1949 return true;
1950}
1951
1952bool CAddrDB::Read(CAddrMan& addr)
1953{
1954 // open input file, and associate with CAutoFile
1955 FILE *file = fopen(pathAddr.string().c_str(), "rb");
eee030f6 1956 CAutoFile filein(file, SER_DISK, CLIENT_VERSION);
d004d727 1957 if (!filein)
2fdd4c79 1958 return error("%s : Failed to open file %s", __func__, pathAddr.string());
d004d727
WL
1959
1960 // use file size to size memory buffer
a486abd4 1961 int fileSize = boost::filesystem::file_size(pathAddr);
d004d727 1962 int dataSize = fileSize - sizeof(uint256);
a486abd4 1963 // Don't try to resize to a negative number if file is small
2fdd4c79
PK
1964 if (dataSize < 0)
1965 dataSize = 0;
d004d727
WL
1966 vector<unsigned char> vchData;
1967 vchData.resize(dataSize);
1968 uint256 hashIn;
1969
1970 // read data and checksum from file
1971 try {
1972 filein.read((char *)&vchData[0], dataSize);
1973 filein >> hashIn;
1974 }
1975 catch (std::exception &e) {
2fdd4c79 1976 return error("%s : Deserialize or I/O error - %s", __func__, e.what());
d004d727
WL
1977 }
1978 filein.fclose();
1979
1980 CDataStream ssPeers(vchData, SER_DISK, CLIENT_VERSION);
1981
1982 // verify stored checksum matches input data
1983 uint256 hashTmp = Hash(ssPeers.begin(), ssPeers.end());
1984 if (hashIn != hashTmp)
2fdd4c79 1985 return error("%s : Checksum mismatch, data corrupted", __func__);
d004d727
WL
1986
1987 unsigned char pchMsgTmp[4];
1988 try {
1989 // de-serialize file header (network specific magic number) and ..
1990 ssPeers >> FLATDATA(pchMsgTmp);
1991
1992 // ... verify the network matches ours
1993 if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp)))
2fdd4c79 1994 return error("%s : Invalid network magic number", __func__);
d004d727
WL
1995
1996 // de-serialize address data into one CAddrMan object
1997 ssPeers >> addr;
1998 }
1999 catch (std::exception &e) {
2fdd4c79 2000 return error("%s : Deserialize or I/O error - %s", __func__, e.what());
d004d727
WL
2001 }
2002
2003 return true;
2004}
651480c8
WL
2005
2006unsigned int ReceiveFloodSize() { return 1000*GetArg("-maxreceivebuffer", 5*1000); }
2007unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 1*1000); }
2008
2009CNode::CNode(SOCKET hSocketIn, CAddress addrIn, std::string addrNameIn, bool fInboundIn) : ssSend(SER_NETWORK, INIT_PROTO_VERSION), setAddrKnown(5000)
2010{
2011 nServices = 0;
2012 hSocket = hSocketIn;
2013 nRecvVersion = INIT_PROTO_VERSION;
2014 nLastSend = 0;
2015 nLastRecv = 0;
2016 nSendBytes = 0;
2017 nRecvBytes = 0;
2018 nTimeConnected = GetTime();
2019 addr = addrIn;
2020 addrName = addrNameIn == "" ? addr.ToStringIPPort() : addrNameIn;
2021 nVersion = 0;
2022 strSubVer = "";
2023 fWhitelisted = false;
2024 fOneShot = false;
2025 fClient = false; // set by version message
2026 fInbound = fInboundIn;
2027 fNetworkNode = false;
2028 fSuccessfullyConnected = false;
2029 fDisconnect = false;
2030 nRefCount = 0;
2031 nSendSize = 0;
2032 nSendOffset = 0;
2033 hashContinue = 0;
651480c8 2034 nStartingHeight = -1;
651480c8
WL
2035 fGetAddr = false;
2036 fRelayTxes = false;
2037 setInventoryKnown.max_size(SendBufferSize() / 1000);
2038 pfilter = new CBloomFilter();
2039 nPingNonceSent = 0;
2040 nPingUsecStart = 0;
2041 nPingUsecTime = 0;
2042 fPingQueued = false;
2043
2044 {
2045 LOCK(cs_nLastNodeId);
2046 id = nLastNodeId++;
2047 }
2048
2049 if (fLogIPs)
2050 LogPrint("net", "Added connection to %s peer=%d\n", addrName, id);
2051 else
2052 LogPrint("net", "Added connection peer=%d\n", id);
2053
2054 // Be shy and don't send version until we hear
2055 if (hSocket != INVALID_SOCKET && !fInbound)
2056 PushVersion();
2057
2058 GetNodeSignals().InitializeNode(GetId(), this);
2059}
2060
2061CNode::~CNode()
2062{
2063 CloseSocket(hSocket);
2064
2065 if (pfilter)
2066 delete pfilter;
2067
2068 GetNodeSignals().FinalizeNode(GetId());
2069}
2070
2071void CNode::AskFor(const CInv& inv)
2072{
d4168c82
WL
2073 if (mapAskFor.size() > MAPASKFOR_MAX_SZ)
2074 return;
651480c8
WL
2075 // We're using mapAskFor as a priority queue,
2076 // the key is the earliest time the request can be sent
2077 int64_t nRequestTime;
2078 limitedmap<CInv, int64_t>::const_iterator it = mapAlreadyAskedFor.find(inv);
2079 if (it != mapAlreadyAskedFor.end())
2080 nRequestTime = it->second;
2081 else
2082 nRequestTime = 0;
2c2cc5da 2083 LogPrint("net", "askfor %s %d (%s) peer=%d\n", inv.ToString(), nRequestTime, DateTimeStrFormat("%H:%M:%S", nRequestTime/1000000), id);
651480c8
WL
2084
2085 // Make sure not to reuse time indexes to keep things in the same order
2086 int64_t nNow = GetTimeMicros() - 1000000;
2087 static int64_t nLastTime;
2088 ++nLastTime;
2089 nNow = std::max(nNow, nLastTime);
2090 nLastTime = nNow;
2091
2092 // Each retry is 2 minutes after the last
2093 nRequestTime = std::max(nRequestTime + 2 * 60 * 1000000, nNow);
2094 if (it != mapAlreadyAskedFor.end())
2095 mapAlreadyAskedFor.update(it, nRequestTime);
2096 else
2097 mapAlreadyAskedFor.insert(std::make_pair(inv, nRequestTime));
2098 mapAskFor.insert(std::make_pair(nRequestTime, inv));
2099}
2100
2101void CNode::BeginMessage(const char* pszCommand) EXCLUSIVE_LOCK_FUNCTION(cs_vSend)
2102{
2103 ENTER_CRITICAL_SECTION(cs_vSend);
2104 assert(ssSend.size() == 0);
2105 ssSend << CMessageHeader(pszCommand, 0);
2106 LogPrint("net", "sending: %s ", pszCommand);
2107}
2108
2109void CNode::AbortMessage() UNLOCK_FUNCTION(cs_vSend)
2110{
2111 ssSend.clear();
2112
2113 LEAVE_CRITICAL_SECTION(cs_vSend);
2114
2115 LogPrint("net", "(aborted)\n");
2116}
2117
2118void CNode::EndMessage() UNLOCK_FUNCTION(cs_vSend)
2119{
2120 // The -*messagestest options are intentionally not documented in the help message,
2121 // since they are only used during development to debug the networking code and are
2122 // not intended for end-users.
2123 if (mapArgs.count("-dropmessagestest") && GetRand(GetArg("-dropmessagestest", 2)) == 0)
2124 {
2125 LogPrint("net", "dropmessages DROPPING SEND MESSAGE\n");
2126 AbortMessage();
2127 return;
2128 }
2129 if (mapArgs.count("-fuzzmessagestest"))
2130 Fuzz(GetArg("-fuzzmessagestest", 10));
2131
2132 if (ssSend.size() == 0)
2133 return;
2134
2135 // Set the size
2136 unsigned int nSize = ssSend.size() - CMessageHeader::HEADER_SIZE;
2137 memcpy((char*)&ssSend[CMessageHeader::MESSAGE_SIZE_OFFSET], &nSize, sizeof(nSize));
2138
2139 // Set the checksum
2140 uint256 hash = Hash(ssSend.begin() + CMessageHeader::HEADER_SIZE, ssSend.end());
2141 unsigned int nChecksum = 0;
2142 memcpy(&nChecksum, &hash, sizeof(nChecksum));
2143 assert(ssSend.size () >= CMessageHeader::CHECKSUM_OFFSET + sizeof(nChecksum));
2144 memcpy((char*)&ssSend[CMessageHeader::CHECKSUM_OFFSET], &nChecksum, sizeof(nChecksum));
2145
2146 LogPrint("net", "(%d bytes) peer=%d\n", nSize, id);
2147
2148 std::deque<CSerializeData>::iterator it = vSendMsg.insert(vSendMsg.end(), CSerializeData());
2149 ssSend.GetAndClear(*it);
2150 nSendSize += (*it).size();
2151
2152 // If write queue empty, attempt "optimistic write"
2153 if (it == vSendMsg.begin())
2154 SocketSendData(this);
2155
2156 LEAVE_CRITICAL_SECTION(cs_vSend);
2157}
This page took 0.578869 seconds and 4 git commands to generate.