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