upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/net.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/net.h')
-rw-r--r--src/net.h1100
1 files changed, 1100 insertions, 0 deletions
diff --git a/src/net.h b/src/net.h
new file mode 100644
index 0000000..bcd0b2a
--- /dev/null
+++ b/src/net.h
@@ -0,0 +1,1100 @@
1// Copyright (c) 2009 Satoshi Nakamoto
2// Distributed under the MIT/X11 software license, see the accompanying
3// file license.txt or http://www.opensource.org/licenses/mit-license.php.
4
5class CMessageHeader;
6class CAddress;
7class CInv;
8class CRequestTracker;
9class CNode;
10// Defined in main.h, which is included after this file. Only ever used here as
11// a pointer, so the forward declaration is enough.
12class CBlockIndex;
13
14
15
16static const unsigned short DEFAULT_PORT = htons(8433);
17static const unsigned int PUBLISH_HOPS = 5;
18enum
19{
20 NODE_NETWORK = (1 << 0),
21};
22
23
24
25
26
27
28bool GetMyExternalIP(unsigned int& ipRet);
29CNode* ConnectNodeBtf(const string& strBtfAddr);
30CNode* ConnectNodeBtfResolved(const string& strBtfAddr, const string& strMeeting,
31 const unsigned char enc_pub[32]);
32void ThreadBtfAccept(void* parg);
33void ThreadBtfConnect(void* parg);
34extern string strBtfConnect;
35// Bootstrap seeds added at runtime with /btfseed=ADDRESS:ENCHEX (repeatable).
36// The compiled-in list lives in net.cpp; these are appended to it.
37extern std::vector<std::pair<std::string, std::string> > vBtfExtraSeeds;
38
39// --- .btf peer exchange ---------------------------------------------------
40// Peers gossip signed descriptors so discovery survives a relay outage. Both
41// caps apply to a single "btfpeers" message; the generic header limit is 256 MB,
42// which is no protection at all for something a stranger can send unprompted.
43static const unsigned int MAX_PEX_DESCRIPTORS = 20;
44static const unsigned int MAX_PEX_DESCRIPTOR_BYTES = 1024;
45// Ignore a peer's exchange more often than this. One announcement per side per
46// connection is the intended traffic; anything faster is someone else's idea.
47static const int64 PEX_MIN_INTERVAL = 60;
48
49// How long to sit registered at a rendezvous relay before giving up on this
50// attempt and registering again. Bounded because a registration socket that
51// goes quiet is indistinguishable, from inside recv(), from one whose path has
52// died -- and the second kind never wakes up. Five minutes is short enough
53// that a node is unreachable only briefly and long enough that the reconnect
54// traffic is nothing: one per relay per five minutes.
55static const int BTF_RENDEZVOUS_WAIT_SECS = 300;
56
57// Registrations this node parks at a rendezvous at once.
58//
59// Back to one, and it stays at one until every relay in vBtfMeetingRelays runs
60// the queue from #113. More than one is what keeps a node reachable while one
61// registration is being paired -- but only against a relay that accepts more
62// than one. An older relay closes the previous registration whenever the same
63// node registers again, so several accept threads pointed at one of those
64// evict each other in a loop: thread 2 registers and kills thread 1, thread 3
65// kills thread 2, thread 1 sees its socket die and kills thread 3.
66//
67// #113 called that harmless. It is not. Measured on a node running three
68// threads against the un-upgraded New Jersey relay: 189 registrations in about
69// fifteen minutes -- roughly twelve a minute -- and not one pairing. The node
70// was not merely failing to benefit, it was unreachable through that relay and
71// hammering it. A node with one thread does none of this.
72//
73// The bench that approved #113 could not see it: its harness re-registers by
74// design, which is exactly what hides an eviction loop.
75//
76// Raise this to 3 only when the other two relays are upgraded.
77static const int BTF_ACCEPT_THREADS = 1;
78
79// Liveness of an established peer connection. BTF_RENDEZVOUS_WAIT_SECS bounds
80// the wait for a dial to arrive; these bound the connection that comes out of
81// it, which has the same failure mode once it goes quiet.
82//
83// A healthy peer relays a block inventory roughly every nTargetSpacing (two
84// minutes), so silence measured in block intervals is the honest signal.
85// Bitcoin used ninety minutes against ten-minute blocks -- nine intervals --
86// and the same nine intervals here is eighteen minutes; thirty leaves margin
87// for a slow stretch without letting a dead path last an hour.
88static const int BTF_RECV_TIMEOUT_SECS = 30 * 60;
89static const int BTF_SEND_STALL_SECS = 10 * 60;
90static const int BTF_HANDSHAKE_GRACE_SECS = 60;
91
92// A serialized object cannot be larger than MAX_SIZE, so no valid network
93// message needs the old 256 MB header allowance. Keep the wire cap aligned with
94// what the deserializer can accept and bound how long one peer may sit on a
95// partial payload after a complete header has arrived.
96static const unsigned int MAX_PROTOCOL_MESSAGE_SIZE = MAX_SIZE;
97static const int BTF_INCOMPLETE_MESSAGE_TIMEOUT_SECS = 2 * 60;
98
99// Ceiling on simultaneous connections.
100//
101// ThreadSocketHandler watches every peer through one select(), and select()
102// cannot watch more descriptors than FD_SETSIZE. On Windows FD_SET simply
103// stops adding once the set is full -- no error, no log -- so every socket
104// past the limit stays open and is never read again. Nothing capped vNodes,
105// so a node accepted connections it had no way to service, and because new
106// entries go on the end of vNodes it was always the newest connection that
107// starved, including the ones dialed to fix connectivity.
108//
109// Measured on two nodes before this ceiling existed: 277 and 90 CNode objects
110// against 93 and 90 live sockets, and a status bar reporting hundreds of
111// peers for a node that was really talking to thirty.
112//
113// 125 is Bitcoin's number and sits far below FD_SETSIZE on both platforms.
114static const unsigned int MAX_CONNECTIONS = 125;
115
116// A node marked for disconnect is normally held until its buffers drain, so
117// a last message still goes out. But vSend cannot drain through a socket
118// whose far end is gone, and that made such a node immortal: it stayed in
119// vNodes, kept its socket open, and kept being counted. Force it out after
120// this long regardless of what is still buffered.
121static const int64 DISCONNECT_DRAIN_SECS = 60;
122
123// Send a ping after this long with nothing to say, so a peer running the
124// inactivity check above does not mistake a quiet node for a dead one. Must
125// stay well under BTF_RECV_TIMEOUT_SECS.
126static const int BTF_PING_INTERVAL_SECS = 10 * 60;
127
128// How long a node must stay behind the network before it says so, and how
129// often it repeats itself. Five minutes is two and a half block intervals --
130// long enough that ordinary relay lag never trips it.
131static const int BTF_BEHIND_GRACE_SECS = 5 * 60;
132static const int BTF_BEHIND_WARN_INTERVAL_SECS = 5 * 60;
133
134// --- Self-diagnosis -------------------------------------------------------
135//
136// A node that has stopped working looks exactly like a node with nothing to
137// do. That has cost this project real time more than once: a node deaf to
138// most of its peers, a miner allocating one RandomX dataset per thread, a
139// third of arriving blocks missing their parent -- each was found from
140// outside, by reading the process's sockets or its memory from another
141// machine, because the node itself had no way to say so.
142//
143// These counters exist so it can. Cheap to keep, and they name the failures
144// that actually happened rather than the ones that sound impressive.
145extern int nPeersWatched; // peers in the last select() set
146extern int64 nBlocksReceived; // blocks handed to ProcessBlock
147extern int64 nBlocksWithoutParent; // ...of those, how many arrived orphaned
148
149// One report, rendered the same way for the GUI panel and the log, so what a
150// user pastes into an issue is what a developer already knows how to read.
151string GetDiagnosticsText();
152
153#include "sockcount.h"
154
155// Defined in main.cpp. Declared here because CNode announces it in the version
156// message, and net.h is included before main.h.
157extern int nBestHeight;
158
159// Median height announced by the peers we are connected to, or -1 while nobody
160// has told us anything. Median rather than maximum so one peer claiming an
161// absurd height cannot move it.
162int GetPeerMedianHeight();
163
164// Lightweight .btf churn accounting. These counters are diagnostics only: they
165// let an operator tell stale descriptors, relay pairing failures, and paired
166// tunnels that never speak apart before changing behaviour.
167void BtfChurnNoteResolveAttempt();
168void BtfChurnNoteResolveResult(bool fOk);
169void BtfChurnNoteDialAttempt(const string& strBtfAddr, const string& strMeeting);
170void BtfChurnNoteDialResult(const string& strBtfAddr, const string& strMeeting, bool fOk);
171void BtfChurnNoteRegisterResult(const string& strMeeting, bool fOk);
172void BtfChurnNotePairResult(const string& strMeeting, bool fOk);
173void BtfChurnNoteHandshakeTimeout(const string& strBtfAddr, const string& strMeeting,
174 bool fRecv, bool fSend);
175
176// Descriptors to hand a peer: ours first, then peers that answered us.
177void BtfPexCollect(std::vector<std::string>& vDescOut);
178// Verify descriptors a peer sent and remember the good ones. Returns how many.
179int BtfPexAccept(const std::vector<std::string>& vDesc);
180void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1);
181bool AnySubscribed(unsigned int nChannel);
182void ThreadBitcoinMiner(void* parg);
183// Starts MinerThreadCount() miners; returns how many came up.
184int StartMinerThreads();
185bool StartNode(string& strError=REF(string()));
186bool StopNode();
187void CheckForShutdown(int n);
188
189
190
191
192
193
194
195
196
197//
198// Message header
199// (4) message start
200// (12) command
201// (4) size
202
203// The message start string is designed to be unlikely to occur in normal data.
204// The characters are rarely used upper ascii, not valid as UTF-8, and produce
205// a large 4-byte int at any alignment.
206// Magic bytes unique to the Bitflash network (0xbf = "BF"). Second byte bumped
207// to 0x20 for the 2026 stable relaunch so the old test chain can't interfere.
208static const char pchMessageStart[4] = { 0xbf, 0x20, 0x5c, 0xfd };
209
210class CMessageHeader
211{
212public:
213 enum { COMMAND_SIZE=12 };
214 char pchMessageStart[sizeof(::pchMessageStart)];
215 char pchCommand[COMMAND_SIZE];
216 unsigned int nMessageSize;
217
218 CMessageHeader()
219 {
220 memcpy(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart));
221 memset(pchCommand, 0, sizeof(pchCommand));
222 pchCommand[1] = 1;
223 nMessageSize = -1;
224 }
225
226 CMessageHeader(const char* pszCommand, unsigned int nMessageSizeIn)
227 {
228 memcpy(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart));
229 strncpy(pchCommand, pszCommand, COMMAND_SIZE);
230 nMessageSize = nMessageSizeIn;
231 }
232
233 IMPLEMENT_SERIALIZE
234 (
235 READWRITE(FLATDATA(pchMessageStart));
236 READWRITE(FLATDATA(pchCommand));
237 READWRITE(nMessageSize);
238 )
239
240 string GetCommand()
241 {
242 if (pchCommand[COMMAND_SIZE-1] == 0)
243 return string(pchCommand, pchCommand + strlen(pchCommand));
244 else
245 return string(pchCommand, pchCommand + COMMAND_SIZE);
246 }
247
248 bool IsValid()
249 {
250 // Check start string
251 if (memcmp(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart)) != 0)
252 return false;
253
254 // Check the command string for errors
255 for (char* p1 = pchCommand; p1 < pchCommand + COMMAND_SIZE; p1++)
256 {
257 if (*p1 == 0)
258 {
259 // Must be all zeros after the first zero
260 for (; p1 < pchCommand + COMMAND_SIZE; p1++)
261 if (*p1 != 0)
262 return false;
263 }
264 else if (*p1 < ' ' || *p1 > 0x7E)
265 return false;
266 }
267
268 // Message size
269 if (nMessageSize > MAX_PROTOCOL_MESSAGE_SIZE)
270 {
271 if (LogAcceptsCategory("net")) printf("CMessageHeader::IsValid() : nMessageSize too large %u\n", nMessageSize);
272 return false;
273 }
274
275 return true;
276 }
277};
278
279
280
281
282
283
284static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
285
286class CAddress
287{
288public:
289 uint64 nServices;
290 unsigned char pchReserved[12];
291 unsigned int ip;
292 unsigned short port;
293
294 // disk only
295 unsigned int nTime;
296
297 // memory only
298 unsigned int nLastFailed;
299
300 CAddress()
301 {
302 nServices = 0;
303 memcpy(pchReserved, pchIPv4, sizeof(pchReserved));
304 ip = 0;
305 port = DEFAULT_PORT;
306 nTime = GetAdjustedTime();
307 nLastFailed = 0;
308 }
309
310 CAddress(unsigned int ipIn, unsigned short portIn, uint64 nServicesIn=0)
311 {
312 nServices = nServicesIn;
313 memcpy(pchReserved, pchIPv4, sizeof(pchReserved));
314 ip = ipIn;
315 port = portIn;
316 nTime = GetAdjustedTime();
317 nLastFailed = 0;
318 }
319
320 explicit CAddress(const struct sockaddr_in& sockaddr, uint64 nServicesIn=0)
321 {
322 nServices = nServicesIn;
323 memcpy(pchReserved, pchIPv4, sizeof(pchReserved));
324 ip = sockaddr.sin_addr.s_addr;
325 port = sockaddr.sin_port;
326 nTime = GetAdjustedTime();
327 nLastFailed = 0;
328 }
329
330 explicit CAddress(const char* pszIn, uint64 nServicesIn=0)
331 {
332 nServices = nServicesIn;
333 memcpy(pchReserved, pchIPv4, sizeof(pchReserved));
334 ip = 0;
335 port = DEFAULT_PORT;
336 nTime = GetAdjustedTime();
337 nLastFailed = 0;
338
339 char psz[100];
340 if (strlen(pszIn) > ARRAYLEN(psz)-1)
341 return;
342 strcpy(psz, pszIn);
343 unsigned int a, b, c, d, e;
344 if (sscanf(psz, "%u.%u.%u.%u:%u", &a, &b, &c, &d, &e) < 4)
345 return;
346 char* pszPort = strchr(psz, ':');
347 if (pszPort)
348 {
349 *pszPort++ = '\0';
350 port = htons(atoi(pszPort));
351 }
352 ip = inet_addr(psz);
353 }
354
355 IMPLEMENT_SERIALIZE
356 (
357 if (nType & SER_DISK)
358 {
359 READWRITE(nVersion);
360 READWRITE(nTime);
361 }
362 READWRITE(nServices);
363 READWRITE(FLATDATA(pchReserved));
364 READWRITE(ip);
365 READWRITE(port);
366 )
367
368 friend inline bool operator==(const CAddress& a, const CAddress& b)
369 {
370 return (memcmp(a.pchReserved, b.pchReserved, sizeof(a.pchReserved)) == 0 &&
371 a.ip == b.ip &&
372 a.port == b.port);
373 }
374
375 friend inline bool operator<(const CAddress& a, const CAddress& b)
376 {
377 int ret = memcmp(a.pchReserved, b.pchReserved, sizeof(a.pchReserved));
378 if (ret < 0)
379 return true;
380 else if (ret == 0)
381 {
382 if (ntohl(a.ip) < ntohl(b.ip))
383 return true;
384 else if (a.ip == b.ip)
385 return ntohs(a.port) < ntohs(b.port);
386 }
387 return false;
388 }
389
390 vector<unsigned char> GetKey() const
391 {
392 CDataStream ss;
393 ss.reserve(18);
394 ss << FLATDATA(pchReserved) << ip << port;
395
396 #if defined(_MSC_VER) && _MSC_VER < 1300
397 return vector<unsigned char>((unsigned char*)&ss.begin()[0], (unsigned char*)&ss.end()[0]);
398 #else
399 return vector<unsigned char>(ss.begin(), ss.end());
400 #endif
401 }
402
403 struct sockaddr_in GetSockAddr() const
404 {
405 struct sockaddr_in sockaddr;
406 sockaddr.sin_family = AF_INET;
407 sockaddr.sin_addr.s_addr = ip;
408 sockaddr.sin_port = port;
409 return sockaddr;
410 }
411
412 bool IsIPv4() const
413 {
414 return (memcmp(pchReserved, pchIPv4, sizeof(pchIPv4)) == 0);
415 }
416
417 bool IsRoutable() const
418 {
419 return !(GetByte(3) == 10 || (GetByte(3) == 192 && GetByte(2) == 168));
420 }
421
422 unsigned char GetByte(int n) const
423 {
424 return ((unsigned char*)&ip)[3-n];
425 }
426
427 string ToStringIPPort() const
428 {
429 return strprintf("%u.%u.%u.%u:%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0), ntohs(port));
430 }
431
432 string ToStringIP() const
433 {
434 return strprintf("%u.%u.%u.%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0));
435 }
436
437 string ToString() const
438 {
439 return strprintf("%u.%u.%u.%u:%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0), ntohs(port));
440 //return strprintf("%u.%u.%u.%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0));
441 }
442
443 void print() const
444 {
445 if (LogAcceptsCategory("net")) printf("CAddress(%s)\n", ToString().c_str());
446 }
447};
448
449
450
451
452
453
454
455enum
456{
457 MSG_TX = 1,
458 MSG_BLOCK,
459 MSG_REVIEW,
460 MSG_PRODUCT,
461 MSG_TABLE,
462};
463
464static const char* ppszTypeName[] =
465{
466 "ERROR",
467 "tx",
468 "block",
469 "review",
470 "product",
471 "table",
472};
473
474class CInv
475{
476public:
477 int type;
478 uint256 hash;
479
480 CInv()
481 {
482 type = 0;
483 hash = 0;
484 }
485
486 CInv(int typeIn, const uint256& hashIn)
487 {
488 type = typeIn;
489 hash = hashIn;
490 }
491
492 CInv(const string& strType, const uint256& hashIn)
493 {
494 int i;
495 for (i = 1; i < ARRAYLEN(ppszTypeName); i++)
496 {
497 if (strType == ppszTypeName[i])
498 {
499 type = i;
500 break;
501 }
502 }
503 if (i == ARRAYLEN(ppszTypeName))
504 throw std::out_of_range(strprintf("CInv::CInv(string, uint256) : unknown type '%s'", strType.c_str()));
505 hash = hashIn;
506 }
507
508 IMPLEMENT_SERIALIZE
509 (
510 READWRITE(type);
511 READWRITE(hash);
512 )
513
514 friend inline bool operator<(const CInv& a, const CInv& b)
515 {
516 return (a.type < b.type || (a.type == b.type && a.hash < b.hash));
517 }
518
519 bool IsKnownType() const
520 {
521 return (type >= 1 && type < ARRAYLEN(ppszTypeName));
522 }
523
524 const char* GetCommand() const
525 {
526 if (!IsKnownType())
527 // Was "type=% unknown type": the % swallowed the space as a flag and
528 // the u as the conversion, so this read "type= 3nknown type".
529 throw std::out_of_range(strprintf("CInv::GetCommand() : type=%d unknown type", type));
530 return ppszTypeName[type];
531 }
532
533 string ToString() const
534 {
535 return strprintf("%s %s", GetCommand(), hash.ToString().substr(0,14).c_str());
536 }
537
538 void print() const
539 {
540 if (LogAcceptsCategory("net")) printf("CInv(%s)\n", ToString().c_str());
541 }
542};
543
544
545
546
547
548class CRequestTracker
549{
550public:
551 void (*fn)(void*, CDataStream&);
552 void* param1;
553
554 explicit CRequestTracker(void (*fnIn)(void*, CDataStream&)=NULL, void* param1In=NULL)
555 {
556 fn = fnIn;
557 param1 = param1In;
558 }
559
560 bool IsNull()
561 {
562 return fn == NULL;
563 }
564};
565
566
567
568
569
570extern bool fClient;
571extern uint64 nLocalServices;
572extern CAddress addrLocalHost;
573extern unsigned short nListenPort;
574extern CNode* pnodeLocalHost;
575extern bool fShutdown;
576extern array<bool, 10> vfThreadRunning;
577extern vector<CNode*> vNodes;
578extern CCriticalSection cs_vNodes;
579extern map<CInv, CDataStream> mapRelay;
580extern deque<pair<int64, CInv> > vRelayExpiration;
581extern CCriticalSection cs_mapRelay;
582extern map<CInv, int64> mapAlreadyAskedFor;
583
584
585
586
587
588class CNode
589{
590public:
591 // socket
592 uint64 nServices;
593 SOCKET hSocket;
594 CDataStream vSend;
595 CDataStream vRecv;
596 CCriticalSection cs_vSend;
597 CCriticalSection cs_vRecv;
598 unsigned int nPushPos;
599 CAddress addr;
600 int nVersion;
601 bool fClient;
602 bool fInbound;
603 bool fNetworkNode;
604 bool fDisconnect;
605protected:
606 int nRefCount;
607public:
608 int64 nReleaseTime;
609 int64 nDisconnectSince;
610 map<uint256, CRequestTracker> mapRequests;
611 CCriticalSection cs_mapRequests;
612
613 // inventory based relay
614 set<CInv> setInventoryKnown;
615 set<CInv> setInventoryKnown2;
616 vector<CInv> vInventoryToSend;
617 CCriticalSection cs_inventory;
618 multimap<int64, CInv> mapAskFor;
619
620 // publish and subscription
621 vector<char> vfSubscribe;
622
623 // Last "btfpeers" we accepted from this node, to rate-limit the exchange.
624 int64 nLastPexRecv;
625
626 // Last getblocks we sent this peer, so we do not ask the same question
627 // over and over. See CNode::PushGetBlocks.
628 CBlockIndex* pindexLastGetBlocksBegin;
629 uint256 hashLastGetBlocksEnd;
630
631 // Liveness. A peer whose network path dies silently -- NAT drops an idle
632 // mapping, a relay restarts, a route changes -- never sends FIN, so the
633 // socket stays readable-never and the node simply stops hearing from it
634 // with no error anywhere. These stamps are the only way to tell that
635 // apart from a peer that merely has nothing to say.
636 int64 nTimeConnected;
637 int64 nLastSend;
638 int64 nLastRecv;
639 int64 nLastSendEmpty;
640 int64 nIncompleteMessageStart;
641 unsigned int nIncompleteMessageSize;
642 string strIncompleteMessageCommand;
643 string strBtfAddr;
644 string strBtfMeeting;
645
646 // Height this peer announced in its version message, or -1 if it sent a
647 // version message that predates the field. Knowing how far along everyone
648 // else is, is the only way a node can tell "in sync" from "not hearing".
649 int nStartingHeight;
650
651
652 CNode(SOCKET hSocketIn, CAddress addrIn, bool fInboundIn=false)
653 {
654 nServices = 0;
655 hSocket = hSocketIn;
656 vSend.SetType(SER_NETWORK);
657 vRecv.SetType(SER_NETWORK);
658 nPushPos = -1;
659 addr = addrIn;
660 nVersion = 0;
661 fClient = false; // set by version message
662 fInbound = fInboundIn;
663 fNetworkNode = false;
664 fDisconnect = false;
665 nRefCount = 0;
666 nReleaseTime = 0;
667 nDisconnectSince = 0;
668 nLastPexRecv = 0;
669 pindexLastGetBlocksBegin = NULL;
670 hashLastGetBlocksEnd = 0;
671 nTimeConnected = GetTime();
672 nLastSend = 0;
673 nLastRecv = 0;
674 nLastSendEmpty = GetTime();
675 nIncompleteMessageStart = 0;
676 nIncompleteMessageSize = 0;
677 strIncompleteMessageCommand.clear();
678 strBtfAddr.clear();
679 strBtfMeeting.clear();
680 nStartingHeight = -1;
681 vfSubscribe.assign(256, false);
682
683 // Push a version message
684 /// when NTP implemented, change to just nTime = GetAdjustedTime()
685 int64 nTime = (fInbound ? GetAdjustedTime() : GetTime());
686 // nBestHeight goes last so a node that predates it stops reading after
687 // addr and treats the rest as trailing bytes, which cost it a log line
688 // and nothing else.
689 PushMessage("version", VERSION, nLocalServices, nTime, addr, nBestHeight);
690 }
691
692 // Disconnect() closes the socket and sets this to INVALID_SOCKET, so by the
693 // time a node is deleted there is normally nothing left to do here. It used
694 // not to: Disconnect() closed the handle and left the number in place, and
695 // this destructor closed that same number a second time -- with a raw
696 // closesocket() that the socket accounting never saw, so neither the double
697 // close nor the stale claim showed up in any report.
698 //
699 // A double close is not a harmless no-op. Between the two, the operating
700 // system is free to hand that number to a new socket -- this node opens
701 // hundreds a minute -- and the second close then takes down a connection
702 // that belongs to somebody else, which the log can only report as a peer
703 // vanishing for no reason. `dropping node: its socket is no longer valid`
704 // is what that looks like from the outside.
705 ~CNode()
706 {
707 if (hSocket != INVALID_SOCKET)
708 {
709 BtfCloseSocket(hSocket);
710 hSocket = INVALID_SOCKET;
711 }
712 }
713
714private:
715 CNode(const CNode&);
716 void operator=(const CNode&);
717public:
718
719
720 bool ReadyToDisconnect()
721 {
722 return fDisconnect || GetRefCount() <= 0;
723 }
724
725 int GetRefCount()
726 {
727 return max(nRefCount, 0) + (GetTime() < nReleaseTime ? 1 : 0);
728 }
729
730 void AddRef(int64 nTimeout=0)
731 {
732 if (nTimeout != 0)
733 nReleaseTime = max(nReleaseTime, GetTime() + nTimeout);
734 else
735 nRefCount++;
736 }
737
738 void Release()
739 {
740 nRefCount--;
741 }
742
743
744
745 void AddInventoryKnown(const CInv& inv)
746 {
747 CRITICAL_BLOCK(cs_inventory)
748 setInventoryKnown.insert(inv);
749 }
750
751 void PushInventory(const CInv& inv)
752 {
753 CRITICAL_BLOCK(cs_inventory)
754 if (!setInventoryKnown.count(inv))
755 vInventoryToSend.push_back(inv);
756 }
757
758 void AskFor(const CInv& inv)
759 {
760 // We're using mapAskFor as a priority queue,
761 // the key is the earliest time the request can be sent
762 int64& nRequestTime = mapAlreadyAskedFor[inv];
763 if (LogAcceptsCategory("net")) printf("askfor %s %lld\n", inv.ToString().c_str(), nRequestTime);
764
765 // Make sure not to reuse time indexes to keep things in the same order
766 int64 nNow = (GetTime() - 1) * 1000000;
767 static int64 nLastTime;
768 nLastTime = nNow = max(nNow, ++nLastTime);
769
770 // Each retry is 2 minutes after the last
771 nRequestTime = max(nRequestTime + 2 * 60 * 1000000, nNow);
772 mapAskFor.insert(make_pair(nRequestTime, inv));
773 }
774
775
776
777 void BeginMessage(const char* pszCommand)
778 {
779 EnterCriticalSection(&cs_vSend);
780 if (nPushPos != -1)
781 AbortMessage();
782 nPushPos = vSend.size();
783 vSend << CMessageHeader(pszCommand, 0);
784 if (LogAcceptsCategory("net")) printf("sending: %-12s ", pszCommand);
785 }
786
787 void AbortMessage()
788 {
789 if (nPushPos == -1)
790 return;
791 vSend.resize(nPushPos);
792 nPushPos = -1;
793 LeaveCriticalSection(&cs_vSend);
794 if (LogAcceptsCategory("net")) printf("(aborted)\n");
795 }
796
797 void EndMessage()
798 {
799 extern int nDropMessagesTest;
800 if (nDropMessagesTest > 0 && GetRand(nDropMessagesTest) == 0)
801 {
802 if (LogAcceptsCategory("net")) printf("dropmessages DROPPING SEND MESSAGE\n");
803 AbortMessage();
804 return;
805 }
806
807 if (nPushPos == -1)
808 return;
809
810 // Patch in the size
811 unsigned int nSize = vSend.size() - nPushPos - sizeof(CMessageHeader);
812 memcpy((char*)&vSend[nPushPos] + offsetof(CMessageHeader, nMessageSize), &nSize, sizeof(nSize));
813
814 if (LogAcceptsCategory("net")) printf("(%d bytes) ", nSize);
815 //for (int i = nPushPos+sizeof(CMessageHeader); i < min(vSend.size(), nPushPos+sizeof(CMessageHeader)+20U); i++)
816 // printf("%02x ", vSend[i] & 0xff);
817 if (LogAcceptsCategory("net")) printf("\n");
818
819 nPushPos = -1;
820 LeaveCriticalSection(&cs_vSend);
821 }
822
823 void EndMessageAbortIfEmpty()
824 {
825 if (nPushPos == -1)
826 return;
827 int nSize = vSend.size() - nPushPos - sizeof(CMessageHeader);
828 if (nSize > 0)
829 EndMessage();
830 else
831 AbortMessage();
832 }
833
834 const char* GetMessageCommand() const
835 {
836 if (nPushPos == -1)
837 return "";
838 return &vSend[nPushPos] + offsetof(CMessageHeader, pchCommand);
839 }
840
841
842
843
844 // Ask this peer to fill in blocks we are missing, but only once per
845 // question.
846 //
847 // Every orphan block fires one of these, and an inv for a block we already
848 // hold as an orphan fires another. A node that is missing part of the
849 // chain therefore asks the same peer the same thing repeatedly: measured
850 // on a production node, 1287 orphan blocks out of 4117 processed, and 97
851 // "already have block" from the answers coming back more than once. The
852 // duplicate answers create more orphans, which fire more requests.
853 //
854 // Remembering the last question asked breaks that loop. Same fix Bitcoin
855 // made in e2c2648c1.
856 // Body lives in net.cpp: it builds a CBlockLocator, which main.h defines,
857 // and main.h is included after this file.
858 void PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd);
859
860 void PushMessage(const char* pszCommand)
861 {
862 try
863 {
864 BeginMessage(pszCommand);
865 EndMessage();
866 }
867 catch (...)
868 {
869 AbortMessage();
870 throw;
871 }
872 }
873
874 template<typename T1>
875 void PushMessage(const char* pszCommand, const T1& a1)
876 {
877 try
878 {
879 BeginMessage(pszCommand);
880 vSend << a1;
881 EndMessage();
882 }
883 catch (...)
884 {
885 AbortMessage();
886 throw;
887 }
888 }
889
890 template<typename T1, typename T2>
891 void PushMessage(const char* pszCommand, const T1& a1, const T2& a2)
892 {
893 try
894 {
895 BeginMessage(pszCommand);
896 vSend << a1 << a2;
897 EndMessage();
898 }
899 catch (...)
900 {
901 AbortMessage();
902 throw;
903 }
904 }
905
906 template<typename T1, typename T2, typename T3>
907 void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3)
908 {
909 try
910 {
911 BeginMessage(pszCommand);
912 vSend << a1 << a2 << a3;
913 EndMessage();
914 }
915 catch (...)
916 {
917 AbortMessage();
918 throw;
919 }
920 }
921
922 template<typename T1, typename T2, typename T3, typename T4>
923 void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4)
924 {
925 try
926 {
927 BeginMessage(pszCommand);
928 vSend << a1 << a2 << a3 << a4;
929 EndMessage();
930 }
931 catch (...)
932 {
933 AbortMessage();
934 throw;
935 }
936 }
937
938 template<typename T1, typename T2, typename T3, typename T4, typename T5>
939 void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5)
940 {
941 try
942 {
943 BeginMessage(pszCommand);
944 vSend << a1 << a2 << a3 << a4 << a5;
945 EndMessage();
946 }
947 catch (...)
948 {
949 AbortMessage();
950 throw;
951 }
952 }
953
954
955 void PushRequest(const char* pszCommand,
956 void (*fn)(void*, CDataStream&), void* param1)
957 {
958 uint256 hashReply;
959 RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
960
961 CRITICAL_BLOCK(cs_mapRequests)
962 mapRequests[hashReply] = CRequestTracker(fn, param1);
963
964 PushMessage(pszCommand, hashReply);
965 }
966
967 template<typename T1>
968 void PushRequest(const char* pszCommand, const T1& a1,
969 void (*fn)(void*, CDataStream&), void* param1)
970 {
971 uint256 hashReply;
972 RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
973
974 CRITICAL_BLOCK(cs_mapRequests)
975 mapRequests[hashReply] = CRequestTracker(fn, param1);
976
977 PushMessage(pszCommand, hashReply, a1);
978 }
979
980 template<typename T1, typename T2>
981 void PushRequest(const char* pszCommand, const T1& a1, const T2& a2,
982 void (*fn)(void*, CDataStream&), void* param1)
983 {
984 uint256 hashReply;
985 RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
986
987 CRITICAL_BLOCK(cs_mapRequests)
988 mapRequests[hashReply] = CRequestTracker(fn, param1);
989
990 PushMessage(pszCommand, hashReply, a1, a2);
991 }
992
993
994
995 bool IsSubscribed(unsigned int nChannel);
996 void Subscribe(unsigned int nChannel, unsigned int nHops=0);
997 void CancelSubscribe(unsigned int nChannel);
998 void Disconnect();
999};
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010inline void RelayInventory(const CInv& inv)
1011{
1012 // Put on lists to offer to the other nodes
1013 CRITICAL_BLOCK(cs_vNodes)
1014 foreach(CNode* pnode, vNodes)
1015 pnode->PushInventory(inv);
1016}
1017
1018template<typename T>
1019void RelayMessage(const CInv& inv, const T& a)
1020{
1021 CDataStream ss(SER_NETWORK);
1022 ss.reserve(10000);
1023 ss << a;
1024 RelayMessage(inv, ss);
1025}
1026
1027template<>
1028inline void RelayMessage<>(const CInv& inv, const CDataStream& ss)
1029{
1030 CRITICAL_BLOCK(cs_mapRelay)
1031 {
1032 // Expire old relay messages
1033 while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
1034 {
1035 mapRelay.erase(vRelayExpiration.front().second);
1036 vRelayExpiration.pop_front();
1037 }
1038
1039 // Save original serialized message so newer versions are preserved
1040 mapRelay[inv] = ss;
1041 vRelayExpiration.push_back(make_pair(GetTime() + 15 * 60, inv));
1042 }
1043
1044 RelayInventory(inv);
1045}
1046
1047
1048
1049
1050
1051
1052
1053
1054//
1055// Templates for the publish and subscription system.
1056// The object being published as T& obj needs to have:
1057// a set<unsigned int> setSources member
1058// specializations of AdvertInsert and AdvertErase
1059// Currently implemented for CTable and CProduct.
1060//
1061
1062template<typename T>
1063void AdvertStartPublish(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj)
1064{
1065 // Add to sources
1066 obj.setSources.insert(pfrom->addr.ip);
1067
1068 if (!AdvertInsert(obj))
1069 return;
1070
1071 // Relay
1072 CRITICAL_BLOCK(cs_vNodes)
1073 foreach(CNode* pnode, vNodes)
1074 if (pnode != pfrom && (nHops < PUBLISH_HOPS || pnode->IsSubscribed(nChannel)))
1075 pnode->PushMessage("publish", nChannel, nHops, obj);
1076}
1077
1078template<typename T>
1079void AdvertStopPublish(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj)
1080{
1081 uint256 hash = obj.GetHash();
1082
1083 CRITICAL_BLOCK(cs_vNodes)
1084 foreach(CNode* pnode, vNodes)
1085 if (pnode != pfrom && (nHops < PUBLISH_HOPS || pnode->IsSubscribed(nChannel)))
1086 pnode->PushMessage("pub-cancel", nChannel, nHops, hash);
1087
1088 AdvertErase(obj);
1089}
1090
1091template<typename T>
1092void AdvertRemoveSource(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj)
1093{
1094 // Remove a source
1095 obj.setSources.erase(pfrom->addr.ip);
1096
1097 // If no longer supported by any sources, cancel it
1098 if (obj.setSources.empty())
1099 AdvertStopPublish(pfrom, nChannel, nHops, obj);
1100}