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