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