diff options
Diffstat (limited to 'src/net.h')
| -rw-r--r-- | src/net.h | 204 |
1 files changed, 74 insertions, 130 deletions
| @@ -5,7 +5,6 @@ | |||
| 5 | class CMessageHeader; | 5 | class CMessageHeader; |
| 6 | class CAddress; | 6 | class CAddress; |
| 7 | class CInv; | 7 | class CInv; |
| 8 | class CRequestTracker; | ||
| 9 | class CNode; | 8 | class 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 | ||
| 16 | static const unsigned short DEFAULT_PORT = htons(8433); | 15 | static const unsigned short DEFAULT_PORT = htons(8433); |
| 17 | static const unsigned int PUBLISH_HOPS = 5; | ||
| 18 | enum | 16 | enum |
| 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. |
| 96 | static const unsigned int MAX_PROTOCOL_MESSAGE_SIZE = MAX_SIZE; | 94 | static const unsigned int MAX_PROTOCOL_MESSAGE_SIZE = MAX_SIZE; |
| 97 | static 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. |
| 118 | static const int64 DISCONNECT_DRAIN_SECS = 60; | 115 | static 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. | ||
| 122 | static 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. | ||
| 141 | static 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. |
| 159 | int GetPeerMedianHeight(); | 192 | int GetPeerMedianHeight(); |
| 193 | int64 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 | |||
| 174 | void BtfPexCollect(std::vector<std::string>& vDescOut); | 208 | void 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. |
| 176 | int BtfPexAccept(const std::vector<std::string>& vDesc); | 210 | int BtfPexAccept(const std::vector<std::string>& vDesc); |
| 177 | void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1); | ||
| 178 | bool AnySubscribed(unsigned int nChannel); | ||
| 179 | void ThreadBitcoinMiner(void* parg); | 211 | void ThreadBitcoinMiner(void* parg); |
| 180 | // Starts MinerThreadCount() miners; returns how many came up. | 212 | // Starts MinerThreadCount() miners; returns how many came up. |
| 181 | int StartMinerThreads(); | 213 | int 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. | ||
| 452 | enum | 490 | enum |
| 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 | ||
| 461 | static const char* ppszTypeName[] = | 499 | static const char* ppszTypeName[] = |
| @@ -542,23 +580,9 @@ public: | |||
| 542 | 580 | ||
| 543 | 581 | ||
| 544 | 582 | ||
| 545 | class 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 |
| 547 | public: | 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: | |||
| 604 | public: | 628 | public: |
| 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 | |||
| 1059 | template<typename T> | ||
| 1060 | void 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 | |||
| 1075 | template<typename T> | ||
| 1076 | void 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 | |||
| 1088 | template<typename T> | ||
| 1089 | void 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 | } | ||