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