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