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