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.h204
1 files changed, 74 insertions, 130 deletions
diff --git a/src/net.h b/src/net.h
index feecf96..653a015 100644
--- a/src/net.h
+++ b/src/net.h
@@ -5,7 +5,6 @@
5class CMessageHeader; 5class CMessageHeader;
6class CAddress; 6class CAddress;
7class CInv; 7class CInv;
8class CRequestTracker;
9class CNode; 8class CNode;
10// Defined in main.h, which is included after this file. Only ever used here as 9// Defined in main.h, which is included after this file. Only ever used here as
11// a pointer, so the forward declaration is enough. 10// a pointer, so the forward declaration is enough.
@@ -14,7 +13,6 @@ class CBlockIndex;
14 13
15 14
16static const unsigned short DEFAULT_PORT = htons(8433); 15static const unsigned short DEFAULT_PORT = htons(8433);
17static const unsigned int PUBLISH_HOPS = 5;
18enum 16enum
19{ 17{
20 NODE_NETWORK = (1 << 0), 18 NODE_NETWORK = (1 << 0),
@@ -91,10 +89,9 @@ static const int BTF_HANDSHAKE_GRACE_SECS = 60;
91 89
92// A serialized object cannot be larger than MAX_SIZE, so no valid network 90// 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 91// 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 92// what the deserializer can accept. How long a peer may sit on a partial
95// partial payload after a complete header has arrived. 93// payload after a complete header has arrived is BTF_MSG_WAIT_MAX_SECS, below.
96static const unsigned int MAX_PROTOCOL_MESSAGE_SIZE = MAX_SIZE; 94static const unsigned int MAX_PROTOCOL_MESSAGE_SIZE = MAX_SIZE;
97static const int BTF_INCOMPLETE_MESSAGE_TIMEOUT_SECS = 2 * 60;
98 95
99// Ceiling on simultaneous connections. 96// Ceiling on simultaneous connections.
100// 97//
@@ -117,6 +114,42 @@ static const unsigned int MAX_CONNECTIONS = 125;
117// this long regardless of what is still buffered. 114// this long regardless of what is still buffered.
118static const int64 DISCONNECT_DRAIN_SECS = 60; 115static const int64 DISCONNECT_DRAIN_SECS = 60;
119 116
117// How long a pool may go without hearing a height from ANY peer before it
118// stops issuing jobs. Long enough that ordinary peer churn and a quiet
119// handshake window do not trip it; short enough that a deaf pool cannot build
120// more than a few blocks of private fork before it is stopped. Heights
121// 3966-4085 -- 120 blocks, 5890.50 BTF -- were mined in exactly this state.
122static const int64 BTF_NO_PEER_HEIGHT_MAX_SECS = 20 * 60;
123
124// How long a peer may leave this node waiting for the rest of a message it
125// announced in a header.
126//
127// ProcessMessages rewinds the header and breaks when the body has not all
128// arrived, which is correct for a message still in flight and unbounded for
129// one that never completes: the same header is re-read, the loop breaks
130// again, and that peer is never parsed again for the life of the process.
131// Satoshi left the note -- "need a mechanism to give up waiting for overlong
132// message size error" -- and this is it.
133//
134// It never self-corrects, because any byte that arrives refreshes nLastRecv,
135// so the inactivity timeout that would otherwise drop the peer never fires.
136// The socket stays healthy, select() keeps reporting it, and the node goes
137// silently deaf one peer at a time.
138//
139// A header may legitimately outrun its body by a round trip or two; two
140// minutes is far beyond that, and well inside BTF_RECV_TIMEOUT_SECS.
141static const int64 BTF_MSG_WAIT_MAX_SECS = 2 * 60;
142
143// Largest payload a peer may announce in a message header: MAX_PROTOCOL_MESSAGE_SIZE
144// is defined further up this file. This tree reached the same cap by the same
145// reasoning as upstream #109 -- a 256 MB allowance is eight times what the
146// deserializer will accept (serialize.h throws above MAX_SIZE), so the header
147// check admitted an allocation the parser would only reject later, after
148// BTF_MSG_WAIT_MAX_SECS of a stalled peer slot -- so only the note survives.
149//
150// Both definitions were textually clean and 59 lines apart, so the replay onto
151// upstream merged them without a conflict and only the compiler objected.
152
120// Send a ping after this long with nothing to say, so a peer running the 153// Send a ping after this long with nothing to say, so a peer running the
121// inactivity check above does not mistake a quiet node for a dead one. Must 154// inactivity check above does not mistake a quiet node for a dead one. Must
122// stay well under BTF_RECV_TIMEOUT_SECS. 155// stay well under BTF_RECV_TIMEOUT_SECS.
@@ -157,6 +190,7 @@ extern int nBestHeight;
157// has told us anything. Median rather than maximum so one peer claiming an 190// has told us anything. Median rather than maximum so one peer claiming an
158// absurd height cannot move it. 191// absurd height cannot move it.
159int GetPeerMedianHeight(); 192int GetPeerMedianHeight();
193int64 GetPeerHeightAgeSecs();
160 194
161// Lightweight .btf churn accounting. These counters are diagnostics only: they 195// Lightweight .btf churn accounting. These counters are diagnostics only: they
162// let an operator tell stale descriptors, relay pairing failures, and paired 196// let an operator tell stale descriptors, relay pairing failures, and paired
@@ -174,8 +208,6 @@ void BtfChurnNoteHandshakeTimeout(const string& strBtfAddr, const string& strMee
174void BtfPexCollect(std::vector<std::string>& vDescOut); 208void BtfPexCollect(std::vector<std::string>& vDescOut);
175// Verify descriptors a peer sent and remember the good ones. Returns how many. 209// Verify descriptors a peer sent and remember the good ones. Returns how many.
176int BtfPexAccept(const std::vector<std::string>& vDesc); 210int BtfPexAccept(const std::vector<std::string>& vDesc);
177void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1);
178bool AnySubscribed(unsigned int nChannel);
179void ThreadBitcoinMiner(void* parg); 211void ThreadBitcoinMiner(void* parg);
180// Starts MinerThreadCount() miners; returns how many came up. 212// Starts MinerThreadCount() miners; returns how many came up.
181int StartMinerThreads(); 213int StartMinerThreads();
@@ -449,13 +481,19 @@ public:
449 481
450 482
451 483
484// MSG_REVIEW, MSG_PRODUCT and MSG_TABLE no longer have a handler, a producer
485// or a store -- the marketplace they belonged to is gone. They stay in the
486// enum, and their names stay in ppszTypeName below, because CInv serialises
487// `type` as a plain integer: dropping them would renumber nothing today but
488// would make it tempting to renumber later, and MSG_TX and MSG_BLOCK are wire
489// values shared with every other node. Reserved, never emitted, never served.
452enum 490enum
453{ 491{
454 MSG_TX = 1, 492 MSG_TX = 1,
455 MSG_BLOCK, 493 MSG_BLOCK,
456 MSG_REVIEW, 494 MSG_REVIEW, // reserved, dead
457 MSG_PRODUCT, 495 MSG_PRODUCT, // reserved, dead
458 MSG_TABLE, 496 MSG_TABLE, // reserved, dead
459}; 497};
460 498
461static const char* ppszTypeName[] = 499static const char* ppszTypeName[] =
@@ -542,23 +580,9 @@ public:
542 580
543 581
544 582
545class CRequestTracker 583// CRequestTracker and the PushRequest/"reply" round trip lived here. Nothing
546{ 584// in this tree ever called PushRequest, so the table was always empty and the
547public: 585// "reply" handler was pure inbound parser. Both removed.
548 void (*fn)(void*, CDataStream&);
549 void* param1;
550
551 explicit CRequestTracker(void (*fnIn)(void*, CDataStream&)=NULL, void* param1In=NULL)
552 {
553 fn = fnIn;
554 param1 = param1In;
555 }
556
557 bool IsNull()
558 {
559 return fn == NULL;
560 }
561};
562 586
563 587
564 588
@@ -604,9 +628,6 @@ protected:
604public: 628public:
605 int64 nReleaseTime; 629 int64 nReleaseTime;
606 int64 nDisconnectSince; 630 int64 nDisconnectSince;
607 map<uint256, CRequestTracker> mapRequests;
608 CCriticalSection cs_mapRequests;
609
610 // inventory based relay 631 // inventory based relay
611 set<CInv> setInventoryKnown; 632 set<CInv> setInventoryKnown;
612 set<CInv> setInventoryKnown2; 633 set<CInv> setInventoryKnown2;
@@ -614,9 +635,6 @@ public:
614 CCriticalSection cs_inventory; 635 CCriticalSection cs_inventory;
615 multimap<int64, CInv> mapAskFor; 636 multimap<int64, CInv> mapAskFor;
616 637
617 // publish and subscription
618 vector<char> vfSubscribe;
619
620 // Last "btfpeers" we accepted from this node, to rate-limit the exchange. 638 // Last "btfpeers" we accepted from this node, to rate-limit the exchange.
621 int64 nLastPexRecv; 639 int64 nLastPexRecv;
622 640
@@ -634,12 +652,17 @@ public:
634 int64 nLastSend; 652 int64 nLastSend;
635 int64 nLastRecv; 653 int64 nLastRecv;
636 int64 nLastSendEmpty; 654 int64 nLastSendEmpty;
637 int64 nIncompleteMessageStart;
638 unsigned int nIncompleteMessageSize;
639 string strIncompleteMessageCommand;
640 string strBtfAddr; 655 string strBtfAddr;
641 string strBtfMeeting; 656 string strBtfMeeting;
642 657
658 // When this peer's message loop last rewound a header without having made
659 // progress, or 0 when it is not waiting, plus how much was buffered then.
660 // The pair times a STALL rather than a duration, so a large message
661 // arriving slowly is never mistaken for one that is never arriving.
662 // See ProcessMessages.
663 int64 nMsgWaitSince;
664 unsigned int nMsgWaitSize;
665
643 // Height this peer announced in its version message, or -1 if it sent a 666 // Height this peer announced in its version message, or -1 if it sent a
644 // version message that predates the field. Knowing how far along everyone 667 // version message that predates the field. Knowing how far along everyone
645 // else is, is the only way a node can tell "in sync" from "not hearing". 668 // else is, is the only way a node can tell "in sync" from "not hearing".
@@ -669,13 +692,14 @@ public:
669 nLastSend = 0; 692 nLastSend = 0;
670 nLastRecv = 0; 693 nLastRecv = 0;
671 nLastSendEmpty = GetTime(); 694 nLastSendEmpty = GetTime();
672 nIncompleteMessageStart = 0;
673 nIncompleteMessageSize = 0;
674 strIncompleteMessageCommand.clear();
675 strBtfAddr.clear(); 695 strBtfAddr.clear();
676 strBtfMeeting.clear(); 696 strBtfMeeting.clear();
697 // Not waiting on anything yet. Left indeterminate, the first partial
698 // message this peer sends is measured against whatever was in this
699 // memory, and ProcessMessages drops it as unreadable on first contact.
700 nMsgWaitSince = 0;
701 nMsgWaitSize = 0;
677 nStartingHeight = -1; 702 nStartingHeight = -1;
678 vfSubscribe.assign(256, false);
679 703
680 // Push a version message 704 // Push a version message
681 /// when NTP implemented, change to just nTime = GetAdjustedTime() 705 /// when NTP implemented, change to just nTime = GetAdjustedTime()
@@ -703,6 +727,11 @@ public:
703 { 727 {
704 if (hSocket != INVALID_SOCKET) 728 if (hSocket != INVALID_SOCKET)
705 { 729 {
730 // Route through BtfCloseSocket so the accounting sees this close.
731 // A raw closesocket() here was invisible to sockcount, which is
732 // why the leak numbers never added up, and leaving the descriptor
733 // set afterwards is how a number that now belongs to somebody else
734 // gets closed a second time. (#103)
706 BtfCloseSocket(hSocket); 735 BtfCloseSocket(hSocket);
707 hSocket = INVALID_SOCKET; 736 hSocket = INVALID_SOCKET;
708 } 737 }
@@ -949,49 +978,6 @@ public:
949 } 978 }
950 979
951 980
952 void PushRequest(const char* pszCommand,
953 void (*fn)(void*, CDataStream&), void* param1)
954 {
955 uint256 hashReply;
956 RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
957
958 CRITICAL_BLOCK(cs_mapRequests)
959 mapRequests[hashReply] = CRequestTracker(fn, param1);
960
961 PushMessage(pszCommand, hashReply);
962 }
963
964 template<typename T1>
965 void PushRequest(const char* pszCommand, const T1& a1,
966 void (*fn)(void*, CDataStream&), void* param1)
967 {
968 uint256 hashReply;
969 RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
970
971 CRITICAL_BLOCK(cs_mapRequests)
972 mapRequests[hashReply] = CRequestTracker(fn, param1);
973
974 PushMessage(pszCommand, hashReply, a1);
975 }
976
977 template<typename T1, typename T2>
978 void PushRequest(const char* pszCommand, const T1& a1, const T2& a2,
979 void (*fn)(void*, CDataStream&), void* param1)
980 {
981 uint256 hashReply;
982 RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
983
984 CRITICAL_BLOCK(cs_mapRequests)
985 mapRequests[hashReply] = CRequestTracker(fn, param1);
986
987 PushMessage(pszCommand, hashReply, a1, a2);
988 }
989
990
991
992 bool IsSubscribed(unsigned int nChannel);
993 void Subscribe(unsigned int nChannel, unsigned int nHops=0);
994 void CancelSubscribe(unsigned int nChannel);
995 void Disconnect(); 981 void Disconnect();
996}; 982};
997 983
@@ -1048,50 +1034,8 @@ inline void RelayMessage<>(const CInv& inv, const CDataStream& ss)
1048 1034
1049 1035
1050 1036
1051// 1037// The publish/subscribe advert templates that used to close this file
1052// Templates for the publish and subscription system. 1038// (AdvertStartPublish / AdvertStopPublish / AdvertRemoveSource) are gone along
1053// The object being published as T& obj needs to have: 1039// with the marketplace objects they carried. Nothing ever handled an inbound
1054// a set<unsigned int> setSources member 1040// "publish" or "pub-cancel", so the machinery only ever pushed; what it pushed
1055// specializations of AdvertInsert and AdvertErase 1041// was CProduct, which no longer exists.
1056// Currently implemented for CTable and CProduct.
1057//
1058
1059template<typename T>
1060void AdvertStartPublish(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj)
1061{
1062 // Add to sources
1063 obj.setSources.insert(pfrom->addr.ip);
1064
1065 if (!AdvertInsert(obj))
1066 return;
1067
1068 // Relay
1069 CRITICAL_BLOCK(cs_vNodes)
1070 foreach(CNode* pnode, vNodes)
1071 if (pnode != pfrom && (nHops < PUBLISH_HOPS || pnode->IsSubscribed(nChannel)))
1072 pnode->PushMessage("publish", nChannel, nHops, obj);
1073}
1074
1075template<typename T>
1076void AdvertStopPublish(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj)
1077{
1078 uint256 hash = obj.GetHash();
1079
1080 CRITICAL_BLOCK(cs_vNodes)
1081 foreach(CNode* pnode, vNodes)
1082 if (pnode != pfrom && (nHops < PUBLISH_HOPS || pnode->IsSubscribed(nChannel)))
1083 pnode->PushMessage("pub-cancel", nChannel, nHops, hash);
1084
1085 AdvertErase(obj);
1086}
1087
1088template<typename T>
1089void AdvertRemoveSource(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj)
1090{
1091 // Remove a source
1092 obj.setSources.erase(pfrom->addr.ip);
1093
1094 // If no longer supported by any sources, cancel it
1095 if (obj.setSources.empty())
1096 AdvertStopPublish(pfrom, nChannel, nHops, obj);
1097}