]> Git Repo - VerusCoin.git/blame - src/net.cpp
Limit message sizes before transfer
[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"
51ed9ec9 17
6853e627 18#ifdef WIN32
013df1cc 19#include <string.h>
51ed9ec9 20#else
98148a71 21#include <fcntl.h>
22#endif
23
8bb5edc1 24#ifdef USE_UPNP
8bb5edc1 25#include <miniupnpc/miniupnpc.h>
51ed9ec9 26#include <miniupnpc/miniwget.h>
8bb5edc1
MC
27#include <miniupnpc/upnpcommands.h>
28#include <miniupnpc/upnperrors.h>
29#endif
30
a486abd4 31#include <boost/filesystem.hpp>
ad49c256 32#include <boost/thread.hpp>
a486abd4 33
c43da3f1
PW
34// Dump addresses to peers.dat every 15 minutes (900s)
35#define DUMP_ADDRESSES_INTERVAL 900
51ed9ec9
BD
36
37#if !defined(HAVE_MSG_NOSIGNAL) && !defined(MSG_NOSIGNAL)
35b8af92
CF
38#define MSG_NOSIGNAL 0
39#endif
c43da3f1 40
9e9ca2b6
PK
41// Fix for ancient MinGW versions, that don't have defined these in ws2tcpip.h.
42// Todo: Can be removed when our pull-tester is upgraded to a modern MinGW version.
43#ifdef WIN32
44#ifndef PROTECTION_LEVEL_UNRESTRICTED
45#define PROTECTION_LEVEL_UNRESTRICTED 10
46#endif
47#ifndef IPV6_PROTECTION_LEVEL
48#define IPV6_PROTECTION_LEVEL 23
49#endif
50#endif
51
611116d4 52using namespace std;
223b6f1b 53
dc942e6f
PW
54namespace {
55 const int MAX_OUTBOUND_CONNECTIONS = 8;
56
57 struct ListenSocket {
58 SOCKET socket;
59 bool whitelisted;
60
61 ListenSocket(SOCKET socket, bool whitelisted) : socket(socket), whitelisted(whitelisted) {}
62 };
63}
0a61b0df 64
0a61b0df 65//
66// Global state variables
67//
587f929c 68bool fDiscover = true;
53a08815 69bool fListen = true;
70352e11 70uint64_t nLocalServices = NODE_NETWORK;
d387b8ec
WL
71CCriticalSection cs_mapLocalHost;
72map<CNetAddr, LocalServiceInfo> mapLocalHost;
090e5b40 73static bool vfReachable[NET_MAX] = {};
457754d2 74static bool vfLimited[NET_MAX] = {};
99860de3 75static CNode* pnodeLocalHost = NULL;
51ed9ec9 76uint64_t nLocalHostNonce = 0;
dc942e6f 77static std::vector<ListenSocket> vhListenSocket;
5fee401f 78CAddrMan addrman;
ba29a559 79int nMaxConnections = 125;
94064710 80bool fAddressesInitialized = false;
0a61b0df 81
82vector<CNode*> vNodes;
83CCriticalSection cs_vNodes;
0a61b0df 84map<CInv, CDataStream> mapRelay;
51ed9ec9 85deque<pair<int64_t, CInv> > vRelayExpiration;
0a61b0df 86CCriticalSection cs_mapRelay;
51ed9ec9 87limitedmap<CInv, int64_t> mapAlreadyAskedFor(MAX_INV_SZ);
0a61b0df 88
478b01d9
PW
89static deque<string> vOneShots;
90CCriticalSection cs_vOneShots;
0a61b0df 91
b24e6e4d
MC
92set<CNetAddr> setservAddNodeAddresses;
93CCriticalSection cs_setservAddNodeAddresses;
94
74088e86
MC
95vector<std::string> vAddedNodes;
96CCriticalSection cs_vAddedNodes;
97
b2864d2f
PW
98NodeId nLastNodeId = 0;
99CCriticalSection cs_nLastNodeId;
100
c59abe25 101static CSemaphore *semOutbound = NULL;
0a61b0df 102
501da250
EL
103// Signals for message handling
104static CNodeSignals g_signals;
105CNodeSignals& GetNodeSignals() { return g_signals; }
663224c2 106
478b01d9
PW
107void AddOneShot(string strDest)
108{
109 LOCK(cs_vOneShots);
110 vOneShots.push_back(strDest);
111}
112
00bcfe0b
GA
113unsigned short GetListenPort()
114{
0e4b3175 115 return (unsigned short)(GetArg("-port", Params().GetDefaultPort()));
00bcfe0b 116}
0a61b0df 117
39857190 118// find 'best' local address for a particular peer
7fa4443f 119bool GetLocal(CService& addr, const CNetAddr *paddrPeer)
39857190 120{
53a08815 121 if (!fListen)
39857190 122 return false;
0a61b0df 123
139d2f7c 124 int nBestScore = -1;
39857190
PW
125 int nBestReachability = -1;
126 {
127 LOCK(cs_mapLocalHost);
139d2f7c 128 for (map<CNetAddr, LocalServiceInfo>::iterator it = mapLocalHost.begin(); it != mapLocalHost.end(); it++)
39857190 129 {
139d2f7c 130 int nScore = (*it).second.nScore;
39857190 131 int nReachability = (*it).first.GetReachabilityFrom(paddrPeer);
139d2f7c 132 if (nReachability > nBestReachability || (nReachability == nBestReachability && nScore > nBestScore))
39857190 133 {
139d2f7c 134 addr = CService((*it).first, (*it).second.nPort);
39857190 135 nBestReachability = nReachability;
139d2f7c 136 nBestScore = nScore;
39857190
PW
137 }
138 }
139 }
139d2f7c 140 return nBestScore >= 0;
39857190 141}
0a61b0df 142
39857190 143// get best local address for a particular peer as a CAddress
845c86d1
GM
144// Otherwise, return the unroutable 0.0.0.0 but filled in with
145// the normal parameters, since the IP may be changed to a useful
146// one by discovery.
39857190
PW
147CAddress GetLocalAddress(const CNetAddr *paddrPeer)
148{
845c86d1 149 CAddress ret(CService("0.0.0.0",GetListenPort()),0);
7fa4443f 150 CService addr;
39857190
PW
151 if (GetLocal(addr, paddrPeer))
152 {
7fa4443f 153 ret = CAddress(addr);
39857190 154 }
845c86d1
GM
155 ret.nServices = nLocalServices;
156 ret.nTime = GetAdjustedTime();
39857190
PW
157 return ret;
158}
0a61b0df 159
845c86d1 160int GetnScore(const CService& addr)
39857190 161{
845c86d1
GM
162 LOCK(cs_mapLocalHost);
163 if (mapLocalHost.count(addr) == LOCAL_NONE)
164 return 0;
165 return mapLocalHost[addr].nScore;
166}
167
168// Is our peer's addrLocal potentially useful as an external IP source?
169bool IsPeerAddrLocalGood(CNode *pnode)
170{
171 return fDiscover && pnode->addr.IsRoutable() && pnode->addrLocal.IsRoutable() &&
172 !IsLimited(pnode->addrLocal.GetNetwork());
173}
174
175// pushes our own address to a peer
176void AdvertizeLocal(CNode *pnode)
177{
178 if (fListen && pnode->fSuccessfullyConnected)
39857190 179 {
845c86d1
GM
180 CAddress addrLocal = GetLocalAddress(&pnode->addr);
181 // If discovery is enabled, sometimes give our peer the address it
182 // tells us that it sees us as in case it has a better idea of our
183 // address than we do.
184 if (IsPeerAddrLocalGood(pnode) && (!addrLocal.IsRoutable() ||
185 GetRand((GetnScore(addrLocal) > LOCAL_MANUAL) ? 8:2) == 0))
39857190 186 {
845c86d1
GM
187 addrLocal.SetIP(pnode->addrLocal);
188 }
189 if (addrLocal.IsRoutable())
190 {
191 pnode->PushAddress(addrLocal);
39857190
PW
192 }
193 }
194}
195
54ce3bad
PW
196void SetReachable(enum Network net, bool fFlag)
197{
198 LOCK(cs_mapLocalHost);
199 vfReachable[net] = fFlag;
200 if (net == NET_IPV6 && fFlag)
201 vfReachable[NET_IPV4] = true;
202}
203
39857190 204// learn a new local address
7fa4443f 205bool AddLocal(const CService& addr, int nScore)
39857190
PW
206{
207 if (!addr.IsRoutable())
208 return false;
209
587f929c 210 if (!fDiscover && nScore < LOCAL_MANUAL)
af4006b3
PW
211 return false;
212
09b4e26a 213 if (IsLimited(addr))
1653f97c
PW
214 return false;
215
7d9d134b 216 LogPrintf("AddLocal(%s,%i)\n", addr.ToString(), nScore);
39857190
PW
217
218 {
219 LOCK(cs_mapLocalHost);
139d2f7c
PW
220 bool fAlready = mapLocalHost.count(addr) > 0;
221 LocalServiceInfo &info = mapLocalHost[addr];
222 if (!fAlready || nScore >= info.nScore) {
af4da4be
PW
223 info.nScore = nScore + (fAlready ? 1 : 0);
224 info.nPort = addr.GetPort();
139d2f7c 225 }
54ce3bad 226 SetReachable(addr.GetNetwork());
39857190
PW
227 }
228
39857190
PW
229 return true;
230}
231
5a3cb32e 232bool AddLocal(const CNetAddr &addr, int nScore)
7fa4443f 233{
5a3cb32e 234 return AddLocal(CService(addr, GetListenPort()), nScore);
7fa4443f
PW
235}
236
457754d2
PW
237/** Make a particular network entirely off-limits (no automatic connects to it) */
238void SetLimited(enum Network net, bool fLimited)
239{
0f1707de
PW
240 if (net == NET_UNROUTABLE)
241 return;
457754d2
PW
242 LOCK(cs_mapLocalHost);
243 vfLimited[net] = fLimited;
244}
245
0f1707de 246bool IsLimited(enum Network net)
457754d2
PW
247{
248 LOCK(cs_mapLocalHost);
0f1707de
PW
249 return vfLimited[net];
250}
251
252bool IsLimited(const CNetAddr &addr)
253{
254 return IsLimited(addr.GetNetwork());
457754d2
PW
255}
256
257/** vote for a local address */
7fa4443f 258bool SeenLocal(const CService& addr)
39857190
PW
259{
260 {
261 LOCK(cs_mapLocalHost);
262 if (mapLocalHost.count(addr) == 0)
263 return false;
139d2f7c 264 mapLocalHost[addr].nScore++;
39857190 265 }
39857190
PW
266 return true;
267}
268
845c86d1 269
457754d2 270/** check whether a given address is potentially local */
7fa4443f 271bool IsLocal(const CService& addr)
39857190
PW
272{
273 LOCK(cs_mapLocalHost);
274 return mapLocalHost.count(addr) > 0;
275}
0a61b0df 276
c91a9471
WL
277/** check whether a given network is one we can probably connect to */
278bool IsReachable(enum Network net)
279{
280 LOCK(cs_mapLocalHost);
281 return vfReachable[net] && !vfLimited[net];
282}
283
457754d2 284/** check whether a given address is in a network we can probably connect to */
090e5b40
PW
285bool IsReachable(const CNetAddr& addr)
286{
457754d2 287 enum Network net = addr.GetNetwork();
c91a9471 288 return IsReachable(net);
090e5b40 289}
0a61b0df 290
67a42f92 291void AddressCurrentlyConnected(const CService& addr)
0a61b0df 292{
5fee401f 293 addrman.Connected(addr);
0a61b0df 294}
295
296
51ed9ec9
BD
297uint64_t CNode::nTotalBytesRecv = 0;
298uint64_t CNode::nTotalBytesSent = 0;
ce14345a
SE
299CCriticalSection CNode::cs_totalBytesRecv;
300CCriticalSection CNode::cs_totalBytesSent;
0a61b0df 301
67a42f92 302CNode* FindNode(const CNetAddr& ip)
0a61b0df 303{
b001c871
PK
304 LOCK(cs_vNodes);
305 BOOST_FOREACH(CNode* pnode, vNodes)
306 if ((CNetAddr)pnode->addr == ip)
307 return (pnode);
0a61b0df 308 return NULL;
309}
310
0430c30a 311CNode* FindNode(const std::string& addrName)
9bab521d
PW
312{
313 LOCK(cs_vNodes);
314 BOOST_FOREACH(CNode* pnode, vNodes)
315 if (pnode->addrName == addrName)
316 return (pnode);
317 return NULL;
318}
319
67a42f92 320CNode* FindNode(const CService& addr)
0a61b0df 321{
b001c871
PK
322 LOCK(cs_vNodes);
323 BOOST_FOREACH(CNode* pnode, vNodes)
324 if ((CService)pnode->addr == addr)
325 return (pnode);
0a61b0df 326 return NULL;
327}
328
cedaa714 329CNode* ConnectNode(CAddress addrConnect, const char *pszDest)
0a61b0df 330{
478b01d9 331 if (pszDest == NULL) {
39857190 332 if (IsLocal(addrConnect))
9bab521d 333 return NULL;
0a61b0df 334
9bab521d
PW
335 // Look for an existing connection
336 CNode* pnode = FindNode((CService)addrConnect);
337 if (pnode)
338 {
cedaa714 339 pnode->AddRef();
9bab521d
PW
340 return pnode;
341 }
0a61b0df 342 }
343
344 /// debug print
881a85a2 345 LogPrint("net", "trying connection %s lastseen=%.1fhrs\n",
7d9d134b 346 pszDest ? pszDest : addrConnect.ToString(),
5bd6c31b 347 pszDest ? 0.0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0);
0a61b0df 348
349 // Connect
350 SOCKET hSocket;
35e408f8
WL
351 bool proxyConnectionFailed = false;
352 if (pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, Params().GetDefaultPort(), nConnectTimeout, &proxyConnectionFailed) :
353 ConnectSocket(addrConnect, hSocket, nConnectTimeout, &proxyConnectionFailed))
0a61b0df 354 {
9bab521d
PW
355 addrman.Attempt(addrConnect);
356
0a61b0df 357 // Add node
9bab521d 358 CNode* pnode = new CNode(hSocket, addrConnect, pszDest ? pszDest : "", false);
cedaa714 359 pnode->AddRef();
9bab521d 360
f8dcd5ca
PW
361 {
362 LOCK(cs_vNodes);
0a61b0df 363 vNodes.push_back(pnode);
f8dcd5ca 364 }
0a61b0df 365
366 pnode->nTimeConnected = GetTime();
2e36866f 367
0a61b0df 368 return pnode;
35e408f8
WL
369 } else if (!proxyConnectionFailed) {
370 // If connecting to the node failed, and failure is not caused by a problem connecting to
371 // the proxy, mark this as an attempt.
372 addrman.Attempt(addrConnect);
0a61b0df 373 }
5bd6c31b
PK
374
375 return NULL;
0a61b0df 376}
377
378void CNode::CloseSocketDisconnect()
379{
380 fDisconnect = true;
381 if (hSocket != INVALID_SOCKET)
382 {
2e36866f 383 LogPrint("net", "disconnecting peer=%d\n", id);
43f510d3 384 CloseSocket(hSocket);
0a61b0df 385 }
6ed71b5e
PW
386
387 // in case this fails, we'll empty the recv buffer when the CNode is deleted
388 TRY_LOCK(cs_vRecvMsg, lockRecv);
389 if (lockRecv)
390 vRecvMsg.clear();
0a61b0df 391}
392
f8ded588
GA
393void CNode::PushVersion()
394{
4c6d41b8
PW
395 int nBestHeight = g_signals.GetHeight().get_value_or(0);
396
51ed9ec9 397 int64_t nTime = (fInbound ? GetAdjustedTime() : GetTime());
587f929c 398 CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0",0)));
39857190 399 CAddress addrMe = GetLocalAddress(&addr);
001a53d7 400 GetRandBytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
2e36866f
B
401 if (fLogIPs)
402 LogPrint("net", "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%d\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString(), addrYou.ToString(), id);
403 else
404 LogPrint("net", "send version message: version %d, blocks=%d, us=%s, peer=%d\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString(), id);
f8ded588 405 PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
c87f462b 406 nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()), nBestHeight, true);
f8ded588
GA
407}
408
409
410
411
412
51ed9ec9 413std::map<CNetAddr, int64_t> CNode::setBanned;
15f3ad4d
GA
414CCriticalSection CNode::cs_setBanned;
415
416void CNode::ClearBanned()
417{
418 setBanned.clear();
419}
420
67a42f92 421bool CNode::IsBanned(CNetAddr ip)
15f3ad4d
GA
422{
423 bool fResult = false;
15f3ad4d 424 {
f8dcd5ca 425 LOCK(cs_setBanned);
51ed9ec9 426 std::map<CNetAddr, int64_t>::iterator i = setBanned.find(ip);
15f3ad4d
GA
427 if (i != setBanned.end())
428 {
51ed9ec9 429 int64_t t = (*i).second;
15f3ad4d
GA
430 if (GetTime() < t)
431 fResult = true;
432 }
433 }
434 return fResult;
435}
436
b2864d2f
PW
437bool CNode::Ban(const CNetAddr &addr) {
438 int64_t banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban
15f3ad4d 439 {
b2864d2f
PW
440 LOCK(cs_setBanned);
441 if (setBanned[addr] < banTime)
442 setBanned[addr] = banTime;
15f3ad4d 443 }
b2864d2f 444 return true;
15f3ad4d
GA
445}
446
dc942e6f
PW
447
448std::vector<CSubNet> CNode::vWhitelistedRange;
449CCriticalSection CNode::cs_vWhitelistedRange;
450
451bool CNode::IsWhitelistedRange(const CNetAddr &addr) {
452 LOCK(cs_vWhitelistedRange);
453 BOOST_FOREACH(const CSubNet& subnet, vWhitelistedRange) {
454 if (subnet.Match(addr))
455 return true;
456 }
457 return false;
458}
459
460void CNode::AddWhitelistedRange(const CSubNet &subnet) {
461 LOCK(cs_vWhitelistedRange);
462 vWhitelistedRange.push_back(subnet);
463}
464
1006f070
JG
465#undef X
466#define X(name) stats.name = name
467void CNode::copyStats(CNodeStats &stats)
468{
b2864d2f 469 stats.nodeid = this->GetId();
1006f070
JG
470 X(nServices);
471 X(nLastSend);
472 X(nLastRecv);
473 X(nTimeConnected);
26a6bae7 474 X(nTimeOffset);
1006f070
JG
475 X(addrName);
476 X(nVersion);
a946aa8d 477 X(cleanSubVer);
1006f070 478 X(fInbound);
1006f070 479 X(nStartingHeight);
86648a8d
PW
480 X(nSendBytes);
481 X(nRecvBytes);
dc942e6f 482 X(fWhitelisted);
fabba0e6 483
971bb3e9
JL
484 // It is common for nodes with good ping times to suddenly become lagged,
485 // due to a new block arriving or other large transfer.
486 // Merely reporting pingtime might fool the caller into thinking the node was still responsive,
487 // since pingtime does not update until the ping is complete, which might take a while.
488 // So, if a ping is taking an unusually long time in flight,
489 // the caller can immediately detect that this is happening.
51ed9ec9 490 int64_t nPingUsecWait = 0;
971bb3e9
JL
491 if ((0 != nPingNonceSent) && (0 != nPingUsecStart)) {
492 nPingUsecWait = GetTimeMicros() - nPingUsecStart;
493 }
fabba0e6 494
971bb3e9
JL
495 // 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 :)
496 stats.dPingTime = (((double)nPingUsecTime) / 1e6);
497 stats.dPingWait = (((double)nPingUsecWait) / 1e6);
fabba0e6 498
547c61f8
JL
499 // Leave string empty if addrLocal invalid (not filled in yet)
500 stats.addrLocal = addrLocal.IsValid() ? addrLocal.ToString() : "";
1006f070
JG
501}
502#undef X
0a61b0df 503
607dbfde
JG
504// requires LOCK(cs_vRecvMsg)
505bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes)
506{
507 while (nBytes > 0) {
508
509 // get current incomplete message, or create a new one
967f2459 510 if (vRecvMsg.empty() ||
607dbfde
JG
511 vRecvMsg.back().complete())
512 vRecvMsg.push_back(CNetMessage(SER_NETWORK, nRecvVersion));
513
514 CNetMessage& msg = vRecvMsg.back();
515
516 // absorb network data
517 int handled;
518 if (!msg.in_data)
519 handled = msg.readHeader(pch, nBytes);
520 else
521 handled = msg.readData(pch, nBytes);
522
523 if (handled < 0)
524 return false;
525
ba04c4a7
PW
526 if (msg.in_data && msg.hdr.nMessageSize > MAX_PROTOCOL_MESSAGE_LENGTH) {
527 LogPrint("net", "Oversized message from peer=%i, disconnecting", GetId());
528 return false;
529 }
530
607dbfde
JG
531 pch += handled;
532 nBytes -= handled;
9f4da19b
PW
533
534 if (msg.complete())
535 msg.nTime = GetTimeMicros();
607dbfde
JG
536 }
537
538 return true;
539}
540
541int CNetMessage::readHeader(const char *pch, unsigned int nBytes)
542{
543 // copy data to temporary parsing buffer
544 unsigned int nRemaining = 24 - nHdrPos;
545 unsigned int nCopy = std::min(nRemaining, nBytes);
546
547 memcpy(&hdrbuf[nHdrPos], pch, nCopy);
548 nHdrPos += nCopy;
549
550 // if header incomplete, exit
551 if (nHdrPos < 24)
552 return nCopy;
553
554 // deserialize to CMessageHeader
555 try {
556 hdrbuf >> hdr;
557 }
27df4123 558 catch (const std::exception&) {
607dbfde
JG
559 return -1;
560 }
561
562 // reject messages larger than MAX_SIZE
563 if (hdr.nMessageSize > MAX_SIZE)
564 return -1;
565
566 // switch state to reading message data
567 in_data = true;
607dbfde
JG
568
569 return nCopy;
570}
571
572int CNetMessage::readData(const char *pch, unsigned int nBytes)
573{
574 unsigned int nRemaining = hdr.nMessageSize - nDataPos;
575 unsigned int nCopy = std::min(nRemaining, nBytes);
576
806fd19e
PW
577 if (vRecv.size() < nDataPos + nCopy) {
578 // Allocate up to 256 KiB ahead, but never more than the total message size.
579 vRecv.resize(std::min(hdr.nMessageSize, nDataPos + nCopy + 256 * 1024));
580 }
581
607dbfde
JG
582 memcpy(&vRecv[nDataPos], pch, nCopy);
583 nDataPos += nCopy;
584
585 return nCopy;
586}
587
0a61b0df 588
589
590
591
592
593
594
595
bc2f5aa7
JG
596// requires LOCK(cs_vSend)
597void SocketSendData(CNode *pnode)
598{
41b052ad
PW
599 std::deque<CSerializeData>::iterator it = pnode->vSendMsg.begin();
600
601 while (it != pnode->vSendMsg.end()) {
602 const CSerializeData &data = *it;
603 assert(data.size() > pnode->nSendOffset);
604 int nBytes = send(pnode->hSocket, &data[pnode->nSendOffset], data.size() - pnode->nSendOffset, MSG_NOSIGNAL | MSG_DONTWAIT);
605 if (nBytes > 0) {
606 pnode->nLastSend = GetTime();
86648a8d 607 pnode->nSendBytes += nBytes;
41b052ad 608 pnode->nSendOffset += nBytes;
ce14345a 609 pnode->RecordBytesSent(nBytes);
41b052ad
PW
610 if (pnode->nSendOffset == data.size()) {
611 pnode->nSendOffset = 0;
612 pnode->nSendSize -= data.size();
613 it++;
614 } else {
615 // could not send full message; stop sending more
616 break;
617 }
618 } else {
619 if (nBytes < 0) {
620 // error
621 int nErr = WSAGetLastError();
622 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
623 {
a60838d0 624 LogPrintf("socket send error %s\n", NetworkErrorString(nErr));
41b052ad
PW
625 pnode->CloseSocketDisconnect();
626 }
627 }
628 // couldn't send anything at all
629 break;
bc2f5aa7
JG
630 }
631 }
41b052ad
PW
632
633 if (it == pnode->vSendMsg.end()) {
634 assert(pnode->nSendOffset == 0);
635 assert(pnode->nSendSize == 0);
636 }
637 pnode->vSendMsg.erase(pnode->vSendMsg.begin(), it);
bc2f5aa7 638}
0a61b0df 639
3427517d
PW
640static list<CNode*> vNodesDisconnected;
641
21eb5ada 642void ThreadSocketHandler()
0a61b0df 643{
735a6069 644 unsigned int nPrevNodeCount = 0;
050d2e95 645 while (true)
0a61b0df 646 {
647 //
648 // Disconnect nodes
649 //
0a61b0df 650 {
f8dcd5ca 651 LOCK(cs_vNodes);
0a61b0df 652 // Disconnect unused nodes
653 vector<CNode*> vNodesCopy = vNodes;
223b6f1b 654 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 655 {
656 if (pnode->fDisconnect ||
41b052ad 657 (pnode->GetRefCount() <= 0 && pnode->vRecvMsg.empty() && pnode->nSendSize == 0 && pnode->ssSend.empty()))
0a61b0df 658 {
659 // remove from vNodes
660 vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
661
c59abe25
PW
662 // release outbound grant (if any)
663 pnode->grantOutbound.Release();
092631f0 664
0a61b0df 665 // close socket and cleanup
666 pnode->CloseSocketDisconnect();
0a61b0df 667
668 // hold in disconnected pool until all refs are released
0a61b0df 669 if (pnode->fNetworkNode || pnode->fInbound)
670 pnode->Release();
671 vNodesDisconnected.push_back(pnode);
672 }
673 }
49d754d9
PW
674 }
675 {
0a61b0df 676 // Delete disconnected nodes
677 list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
223b6f1b 678 BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy)
0a61b0df 679 {
680 // wait until threads are done using it
681 if (pnode->GetRefCount() <= 0)
682 {
683 bool fDelete = false;
f8dcd5ca
PW
684 {
685 TRY_LOCK(pnode->cs_vSend, lockSend);
686 if (lockSend)
687 {
607dbfde 688 TRY_LOCK(pnode->cs_vRecvMsg, lockRecv);
f8dcd5ca
PW
689 if (lockRecv)
690 {
529a4d48
WL
691 TRY_LOCK(pnode->cs_inventory, lockInv);
692 if (lockInv)
693 fDelete = true;
f8dcd5ca
PW
694 }
695 }
696 }
0a61b0df 697 if (fDelete)
698 {
699 vNodesDisconnected.remove(pnode);
700 delete pnode;
701 }
702 }
703 }
704 }
ce14345a 705 if(vNodes.size() != nPrevNodeCount) {
0a61b0df 706 nPrevNodeCount = vNodes.size();
ce14345a 707 uiInterface.NotifyNumConnectionsChanged(nPrevNodeCount);
0a61b0df 708 }
709
0a61b0df 710 //
711 // Find which sockets have data to receive
712 //
713 struct timeval timeout;
714 timeout.tv_sec = 0;
715 timeout.tv_usec = 50000; // frequency to poll pnode->vSend
716
717 fd_set fdsetRecv;
718 fd_set fdsetSend;
719 fd_set fdsetError;
720 FD_ZERO(&fdsetRecv);
721 FD_ZERO(&fdsetSend);
722 FD_ZERO(&fdsetError);
723 SOCKET hSocketMax = 0;
23879447 724 bool have_fds = false;
5f88e888 725
dc942e6f
PW
726 BOOST_FOREACH(const ListenSocket& hListenSocket, vhListenSocket) {
727 FD_SET(hListenSocket.socket, &fdsetRecv);
728 hSocketMax = max(hSocketMax, hListenSocket.socket);
23879447 729 have_fds = true;
8f10a288 730 }
5d599212 731
0a61b0df 732 {
f8dcd5ca 733 LOCK(cs_vNodes);
223b6f1b 734 BOOST_FOREACH(CNode* pnode, vNodes)
0a61b0df 735 {
d7f1d200 736 if (pnode->hSocket == INVALID_SOCKET)
0a61b0df 737 continue;
a9d9f0f5
PW
738 FD_SET(pnode->hSocket, &fdsetError);
739 hSocketMax = max(hSocketMax, pnode->hSocket);
740 have_fds = true;
741
742 // Implement the following logic:
743 // * If there is data to send, select() for sending data. As this only
744 // happens when optimistic write failed, we choose to first drain the
745 // write buffer in this case before receiving more. This avoids
746 // needlessly queueing received data, if the remote peer is not themselves
747 // receiving data. This means properly utilizing TCP flow control signalling.
748 // * Otherwise, if there is no (complete) message in the receive buffer,
749 // or there is space left in the buffer, select() for receiving data.
750 // * (if neither of the above applies, there is certainly one message
751 // in the receiver buffer ready to be processed).
752 // Together, that means that at least one of the following is always possible,
753 // so we don't deadlock:
754 // * We send some data.
755 // * We wait for data to be received (and disconnect after timeout).
756 // * We process a message in the buffer (message handler thread).
f8dcd5ca
PW
757 {
758 TRY_LOCK(pnode->cs_vSend, lockSend);
a9d9f0f5
PW
759 if (lockSend && !pnode->vSendMsg.empty()) {
760 FD_SET(pnode->hSocket, &fdsetSend);
761 continue;
b9ff2970 762 }
f8dcd5ca 763 }
a9d9f0f5
PW
764 {
765 TRY_LOCK(pnode->cs_vRecvMsg, lockRecv);
766 if (lockRecv && (
767 pnode->vRecvMsg.empty() || !pnode->vRecvMsg.front().complete() ||
768 pnode->GetTotalRecvSize() <= ReceiveFloodSize()))
769 FD_SET(pnode->hSocket, &fdsetRecv);
770 }
0a61b0df 771 }
772 }
773
23879447
JG
774 int nSelect = select(have_fds ? hSocketMax + 1 : 0,
775 &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
21eb5ada
GA
776 boost::this_thread::interruption_point();
777
0a61b0df 778 if (nSelect == SOCKET_ERROR)
779 {
23879447 780 if (have_fds)
c6710c7a 781 {
23879447 782 int nErr = WSAGetLastError();
a60838d0 783 LogPrintf("socket select error %s\n", NetworkErrorString(nErr));
c376ac35 784 for (unsigned int i = 0; i <= hSocketMax; i++)
c6710c7a
MC
785 FD_SET(i, &fdsetRecv);
786 }
0a61b0df 787 FD_ZERO(&fdsetSend);
788 FD_ZERO(&fdsetError);
1b43bf0d 789 MilliSleep(timeout.tv_usec/1000);
0a61b0df 790 }
791
0a61b0df 792 //
793 // Accept new connections
794 //
dc942e6f 795 BOOST_FOREACH(const ListenSocket& hListenSocket, vhListenSocket)
0a61b0df 796 {
dc942e6f 797 if (hListenSocket.socket != INVALID_SOCKET && FD_ISSET(hListenSocket.socket, &fdsetRecv))
f8dcd5ca 798 {
5d599212
PK
799 struct sockaddr_storage sockaddr;
800 socklen_t len = sizeof(sockaddr);
dc942e6f 801 SOCKET hSocket = accept(hListenSocket.socket, (struct sockaddr*)&sockaddr, &len);
5d599212
PK
802 CAddress addr;
803 int nInbound = 0;
804
805 if (hSocket != INVALID_SOCKET)
806 if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
807 LogPrintf("Warning: Unknown socket family\n");
25ab1758 808
dc942e6f 809 bool whitelisted = hListenSocket.whitelisted || CNode::IsWhitelistedRange(addr);
f8dcd5ca
PW
810 {
811 LOCK(cs_vNodes);
5d599212
PK
812 BOOST_FOREACH(CNode* pnode, vNodes)
813 if (pnode->fInbound)
814 nInbound++;
815 }
816
817 if (hSocket == INVALID_SOCKET)
818 {
819 int nErr = WSAGetLastError();
820 if (nErr != WSAEWOULDBLOCK)
821 LogPrintf("socket error accept failed: %s\n", NetworkErrorString(nErr));
822 }
823 else if (nInbound >= nMaxConnections - MAX_OUTBOUND_CONNECTIONS)
824 {
43f510d3 825 CloseSocket(hSocket);
5d599212 826 }
dc942e6f 827 else if (CNode::IsBanned(addr) && !whitelisted)
5d599212
PK
828 {
829 LogPrintf("connection from %s dropped (banned)\n", addr.ToString());
43f510d3 830 CloseSocket(hSocket);
5d599212
PK
831 }
832 else
833 {
5d599212
PK
834 CNode* pnode = new CNode(hSocket, addr, "", true);
835 pnode->AddRef();
dc942e6f 836 pnode->fWhitelisted = whitelisted;
5d599212
PK
837
838 {
839 LOCK(cs_vNodes);
840 vNodes.push_back(pnode);
841 }
f8dcd5ca 842 }
0a61b0df 843 }
844 }
845
0a61b0df 846 //
847 // Service each socket
848 //
849 vector<CNode*> vNodesCopy;
0a61b0df 850 {
f8dcd5ca 851 LOCK(cs_vNodes);
0a61b0df 852 vNodesCopy = vNodes;
223b6f1b 853 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 854 pnode->AddRef();
855 }
223b6f1b 856 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 857 {
21eb5ada 858 boost::this_thread::interruption_point();
0a61b0df 859
860 //
861 // Receive
862 //
863 if (pnode->hSocket == INVALID_SOCKET)
864 continue;
865 if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
866 {
607dbfde 867 TRY_LOCK(pnode->cs_vRecvMsg, lockRecv);
f8dcd5ca 868 if (lockRecv)
0a61b0df 869 {
a9d9f0f5 870 {
9cbae55a
GA
871 // typical socket buffer is 8K-64K
872 char pchBuf[0x10000];
873 int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
874 if (nBytes > 0)
0a61b0df 875 {
607dbfde
JG
876 if (!pnode->ReceiveMsgBytes(pchBuf, nBytes))
877 pnode->CloseSocketDisconnect();
9cbae55a 878 pnode->nLastRecv = GetTime();
86648a8d 879 pnode->nRecvBytes += nBytes;
ce14345a 880 pnode->RecordBytesRecv(nBytes);
9cbae55a
GA
881 }
882 else if (nBytes == 0)
883 {
884 // socket closed gracefully
0a61b0df 885 if (!pnode->fDisconnect)
881a85a2 886 LogPrint("net", "socket closed\n");
0a61b0df 887 pnode->CloseSocketDisconnect();
888 }
9cbae55a
GA
889 else if (nBytes < 0)
890 {
891 // error
892 int nErr = WSAGetLastError();
893 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
894 {
895 if (!pnode->fDisconnect)
a60838d0 896 LogPrintf("socket recv error %s\n", NetworkErrorString(nErr));
9cbae55a
GA
897 pnode->CloseSocketDisconnect();
898 }
899 }
0a61b0df 900 }
901 }
902 }
903
904 //
905 // Send
906 //
907 if (pnode->hSocket == INVALID_SOCKET)
908 continue;
909 if (FD_ISSET(pnode->hSocket, &fdsetSend))
910 {
f8dcd5ca
PW
911 TRY_LOCK(pnode->cs_vSend, lockSend);
912 if (lockSend)
bc2f5aa7 913 SocketSendData(pnode);
0a61b0df 914 }
915
916 //
917 // Inactivity checking
918 //
f1920e86
PW
919 int64_t nTime = GetTime();
920 if (nTime - pnode->nTimeConnected > 60)
0a61b0df 921 {
922 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
923 {
2e36866f 924 LogPrint("net", "socket no message in first 60 seconds, %d %d from %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0, pnode->id);
0a61b0df 925 pnode->fDisconnect = true;
926 }
f1920e86 927 else if (nTime - pnode->nLastSend > TIMEOUT_INTERVAL)
0a61b0df 928 {
f1920e86 929 LogPrintf("socket sending timeout: %is\n", nTime - pnode->nLastSend);
0a61b0df 930 pnode->fDisconnect = true;
931 }
f1920e86 932 else if (nTime - pnode->nLastRecv > (pnode->nVersion > BIP0031_VERSION ? TIMEOUT_INTERVAL : 90*60))
0a61b0df 933 {
f1920e86
PW
934 LogPrintf("socket receive timeout: %is\n", nTime - pnode->nLastRecv);
935 pnode->fDisconnect = true;
936 }
937 else if (pnode->nPingNonceSent && pnode->nPingUsecStart + TIMEOUT_INTERVAL * 1000000 < GetTimeMicros())
938 {
939 LogPrintf("ping timeout: %fs\n", 0.000001 * (GetTimeMicros() - pnode->nPingUsecStart));
0a61b0df 940 pnode->fDisconnect = true;
941 }
942 }
943 }
0a61b0df 944 {
f8dcd5ca 945 LOCK(cs_vNodes);
223b6f1b 946 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 947 pnode->Release();
948 }
0a61b0df 949 }
950}
951
952
953
954
955
956
957
958
959
8bb5edc1 960#ifdef USE_UPNP
21eb5ada 961void ThreadMapPort()
8bb5edc1 962{
463a1cab 963 std::string port = strprintf("%u", GetListenPort());
8bb5edc1
MC
964 const char * multicastif = 0;
965 const char * minissdpdpath = 0;
966 struct UPNPDev * devlist = 0;
967 char lanaddr[64];
968
94b97046
LD
969#ifndef UPNPDISCOVER_SUCCESS
970 /* miniupnpc 1.5 */
971 devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0);
972#else
973 /* miniupnpc 1.6 */
974 int error = 0;
b4ada906 975 devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error);
94b97046 976#endif
8bb5edc1
MC
977
978 struct UPNPUrls urls;
979 struct IGDdatas data;
980 int r;
981
f285d4f4
DH
982 r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
983 if (r == 1)
8bb5edc1 984 {
587f929c 985 if (fDiscover) {
baba6e7d
MC
986 char externalIPAddress[40];
987 r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
988 if(r != UPNPCOMMAND_SUCCESS)
881a85a2 989 LogPrintf("UPnP: GetExternalIPAddress() returned %d\n", r);
baba6e7d
MC
990 else
991 {
992 if(externalIPAddress[0])
993 {
881a85a2 994 LogPrintf("UPnP: ExternalIPAddress = %s\n", externalIPAddress);
19b6958c 995 AddLocal(CNetAddr(externalIPAddress), LOCAL_UPNP);
baba6e7d
MC
996 }
997 else
881a85a2 998 LogPrintf("UPnP: GetExternalIPAddress failed.\n");
baba6e7d
MC
999 }
1000 }
1001
15656981 1002 string strDesc = "Bitcoin " + FormatFullVersion();
b4ada906 1003
21eb5ada 1004 try {
050d2e95 1005 while (true) {
177dbcaa
MC
1006#ifndef UPNPDISCOVER_SUCCESS
1007 /* miniupnpc 1.5 */
1008 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
9c809094 1009 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0);
177dbcaa
MC
1010#else
1011 /* miniupnpc 1.6 */
1012 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
9c809094 1013 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0");
177dbcaa
MC
1014#endif
1015
1016 if(r!=UPNPCOMMAND_SUCCESS)
881a85a2 1017 LogPrintf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
7d9d134b 1018 port, port, lanaddr, r, strupnperror(r));
177dbcaa 1019 else
881a85a2 1020 LogPrintf("UPnP Port Mapping successful.\n");;
21eb5ada
GA
1021
1022 MilliSleep(20*60*1000); // Refresh every 20 minutes
177dbcaa 1023 }
21eb5ada 1024 }
27df4123 1025 catch (const boost::thread_interrupted&)
21eb5ada
GA
1026 {
1027 r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0);
5262fde0 1028 LogPrintf("UPNP_DeletePortMapping() returned: %d\n", r);
21eb5ada
GA
1029 freeUPNPDevlist(devlist); devlist = 0;
1030 FreeUPNPUrls(&urls);
1031 throw;
8bb5edc1
MC
1032 }
1033 } else {
881a85a2 1034 LogPrintf("No valid UPnP IGDs found\n");
8bb5edc1 1035 freeUPNPDevlist(devlist); devlist = 0;
f285d4f4
DH
1036 if (r != 0)
1037 FreeUPNPUrls(&urls);
8bb5edc1
MC
1038 }
1039}
1040
21eb5ada 1041void MapPort(bool fUseUPnP)
8bb5edc1 1042{
21eb5ada
GA
1043 static boost::thread* upnp_thread = NULL;
1044
1045 if (fUseUPnP)
8bb5edc1 1046 {
21eb5ada
GA
1047 if (upnp_thread) {
1048 upnp_thread->interrupt();
1049 upnp_thread->join();
1050 delete upnp_thread;
1051 }
53e71135 1052 upnp_thread = new boost::thread(boost::bind(&TraceThread<void (*)()>, "upnp", &ThreadMapPort));
21eb5ada
GA
1053 }
1054 else if (upnp_thread) {
1055 upnp_thread->interrupt();
1056 upnp_thread->join();
1057 delete upnp_thread;
1058 upnp_thread = NULL;
8bb5edc1
MC
1059 }
1060}
21eb5ada 1061
9f0ac169 1062#else
21eb5ada 1063void MapPort(bool)
9f0ac169
GA
1064{
1065 // Intentionally left blank.
1066}
8bb5edc1
MC
1067#endif
1068
1069
1070
1071
1072
1073
21eb5ada 1074void ThreadDNSAddressSeed()
2bc6cece 1075{
2e7009d6
JG
1076 // goal: only query DNS seeds if address need is acute
1077 if ((addrman.size() > 0) &&
1078 (!GetBoolArg("-forcednsseed", false))) {
1079 MilliSleep(11 * 1000);
1080
1081 LOCK(cs_vNodes);
1082 if (vNodes.size() >= 2) {
1083 LogPrintf("P2P peers available. Skipped DNS seeding.\n");
1084 return;
1085 }
1086 }
1087
0e4b3175 1088 const vector<CDNSSeedData> &vSeeds = Params().DNSSeeds();
f684aec4
JG
1089 int found = 0;
1090
881a85a2 1091 LogPrintf("Loading addresses from DNS seeds (could take a while)\n");
af899882 1092
0e4b3175 1093 BOOST_FOREACH(const CDNSSeedData &seed, vSeeds) {
af899882 1094 if (HaveNameProxy()) {
0e4b3175 1095 AddOneShot(seed.host);
af899882 1096 } else {
0e4b3175 1097 vector<CNetAddr> vIPs;
af899882 1098 vector<CAddress> vAdd;
0e4b3175 1099 if (LookupHost(seed.host.c_str(), vIPs))
af899882 1100 {
0e4b3175 1101 BOOST_FOREACH(CNetAddr& ip, vIPs)
a6a5bb7c 1102 {
af899882 1103 int nOneDay = 24*3600;
0e4b3175 1104 CAddress addr = CAddress(CService(ip, Params().GetDefaultPort()));
af899882
PT
1105 addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
1106 vAdd.push_back(addr);
1107 found++;
a6a5bb7c 1108 }
f684aec4 1109 }
0e4b3175 1110 addrman.Add(vAdd, CNetAddr(seed.name, true));
f684aec4
JG
1111 }
1112 }
1113
881a85a2 1114 LogPrintf("%d addresses found from DNS seeds\n", found);
f684aec4 1115}
0a61b0df 1116
1117
1118
2bc6cece
MC
1119
1120
1121
1122
1123
1124
1125
1126
1127
5fee401f
PW
1128void DumpAddresses()
1129{
51ed9ec9 1130 int64_t nStart = GetTimeMillis();
928d3a01 1131
5fee401f 1132 CAddrDB adb;
928d3a01
JG
1133 adb.Write(addrman);
1134
f48742c2 1135 LogPrint("net", "Flushed %d addresses to peers.dat %dms\n",
928d3a01 1136 addrman.size(), GetTimeMillis() - nStart);
5fee401f 1137}
0a61b0df 1138
478b01d9
PW
1139void static ProcessOneShot()
1140{
1141 string strDest;
1142 {
1143 LOCK(cs_vOneShots);
1144 if (vOneShots.empty())
1145 return;
1146 strDest = vOneShots.front();
1147 vOneShots.pop_front();
1148 }
1149 CAddress addr;
c59abe25
PW
1150 CSemaphoreGrant grant(*semOutbound, true);
1151 if (grant) {
1152 if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true))
1153 AddOneShot(strDest);
1154 }
478b01d9
PW
1155}
1156
21eb5ada 1157void ThreadOpenConnections()
0a61b0df 1158{
0a61b0df 1159 // Connect to specific addresses
f161a2c2 1160 if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
0a61b0df 1161 {
51ed9ec9 1162 for (int64_t nLoop = 0;; nLoop++)
0a61b0df 1163 {
478b01d9 1164 ProcessOneShot();
223b6f1b 1165 BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
0a61b0df 1166 {
478b01d9 1167 CAddress addr;
c59abe25 1168 OpenNetworkConnection(addr, NULL, strAddr.c_str());
0a61b0df 1169 for (int i = 0; i < 10 && i < nLoop; i++)
1170 {
1b43bf0d 1171 MilliSleep(500);
0a61b0df 1172 }
1173 }
1b43bf0d 1174 MilliSleep(500);
0a61b0df 1175 }
1176 }
1177
0a61b0df 1178 // Initiate network connections
51ed9ec9 1179 int64_t nStart = GetTime();
050d2e95 1180 while (true)
0a61b0df 1181 {
478b01d9
PW
1182 ProcessOneShot();
1183
1b43bf0d 1184 MilliSleep(500);
cc201e01 1185
c59abe25 1186 CSemaphoreGrant grant(*semOutbound);
21eb5ada 1187 boost::this_thread::interruption_point();
0a61b0df 1188
0e4b3175
MH
1189 // Add seed nodes if DNS seeds are all down (an infrastructure attack?).
1190 if (addrman.size() == 0 && (GetTime() - nStart > 60)) {
1191 static bool done = false;
1192 if (!done) {
881a85a2 1193 LogPrintf("Adding fixed seed nodes as DNS doesn't seem to be available.\n");
0e4b3175
MH
1194 addrman.Add(Params().FixedSeeds(), CNetAddr("127.0.0.1"));
1195 done = true;
0a61b0df 1196 }
1197 }
1198
0a61b0df 1199 //
1200 // Choose an address to connect to based on most recently seen
1201 //
1202 CAddress addrConnect;
0a61b0df 1203
19521acf 1204 // Only connect out to one peer per network group (/16 for IPv4).
0a61b0df 1205 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
c59abe25 1206 int nOutbound = 0;
67a42f92 1207 set<vector<unsigned char> > setConnected;
f8dcd5ca
PW
1208 {
1209 LOCK(cs_vNodes);
c59abe25 1210 BOOST_FOREACH(CNode* pnode, vNodes) {
19521acf
GM
1211 if (!pnode->fInbound) {
1212 setConnected.insert(pnode->addr.GetGroup());
c59abe25 1213 nOutbound++;
19521acf 1214 }
c59abe25 1215 }
f8dcd5ca 1216 }
0a61b0df 1217
51ed9ec9 1218 int64_t nANow = GetAdjustedTime();
a4e6ae10 1219
5fee401f 1220 int nTries = 0;
050d2e95 1221 while (true)
0a61b0df 1222 {
5fee401f
PW
1223 // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
1224 CAddress addr = addrman.Select(10 + min(nOutbound,8)*10);
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
EL
1407 if (lockSend)
1408 g_signals.SendMessages(pnode, pnode == pnodeTrickle);
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);
1978 ssSend << CMessageHeader(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;
2010 memcpy((char*)&ssSend[CMessageHeader::MESSAGE_SIZE_OFFSET], &nSize, sizeof(nSize));
2011
2012 // Set the checksum
2013 uint256 hash = Hash(ssSend.begin() + CMessageHeader::HEADER_SIZE, ssSend.end());
2014 unsigned int nChecksum = 0;
2015 memcpy(&nChecksum, &hash, sizeof(nChecksum));
2016 assert(ssSend.size () >= CMessageHeader::CHECKSUM_OFFSET + sizeof(nChecksum));
2017 memcpy((char*)&ssSend[CMessageHeader::CHECKSUM_OFFSET], &nChecksum, sizeof(nChecksum));
2018
2019 LogPrint("net", "(%d bytes) peer=%d\n", nSize, id);
2020
2021 std::deque<CSerializeData>::iterator it = vSendMsg.insert(vSendMsg.end(), CSerializeData());
2022 ssSend.GetAndClear(*it);
2023 nSendSize += (*it).size();
2024
2025 // If write queue empty, attempt "optimistic write"
2026 if (it == vSendMsg.begin())
2027 SocketSendData(this);
2028
2029 LEAVE_CRITICAL_SECTION(cs_vSend);
2030}
This page took 0.561398 seconds and 4 git commands to generate.