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