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