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