diff options
author | John Newbery <john@johnnewbery.com> | 2020-06-21 18:56:19 -0400 |
---|---|---|
committer | John Newbery <john@johnnewbery.com> | 2021-02-15 16:15:51 +0000 |
commit | 45dcf2266125c65d7f546bdb211a278bd090a284 (patch) | |
tree | 384028a852c66190b8f8b1cd5773b90e15880049 /src/net_processing.cpp | |
parent | dd2646d12c172cb8899669af717c590483a17404 (diff) | |
download | bitcoin-45dcf2266125c65d7f546bdb211a278bd090a284.tar.xz |
[net processing] Move ping data fields to net processing
Diffstat (limited to 'src/net_processing.cpp')
-rw-r--r-- | src/net_processing.cpp | 65 |
1 files changed, 45 insertions, 20 deletions
diff --git a/src/net_processing.cpp b/src/net_processing.cpp index ac3e6d0343..5ac9cbdcb5 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -219,6 +219,13 @@ struct Peer { /** This peer's reported block height when we connected */ std::atomic<int> m_starting_height{-1}; + /** The pong reply we're expecting, or 0 if no pong expected. */ + std::atomic<uint64_t> nPingNonceSent{0}; + /** When the last ping was sent, or 0 if no ping was ever sent */ + std::atomic<std::chrono::microseconds> m_ping_start{0us}; + /** Whether a ping has been requested by the user */ + std::atomic<bool> fPingQueued{false}; + /** Set of txids to reconsider once their parent transactions have been accepted **/ std::set<uint256> m_orphan_work_set GUARDED_BY(g_cs_orphans); @@ -256,6 +263,7 @@ public: void CheckForStaleTipAndEvictPeers() override; bool GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats) override; bool IgnoresIncomingTxs() override { return m_ignore_incoming_txs; } + void SendPings() override; void SetBestHeight(int height) override { m_best_height = height; }; void Misbehaving(const NodeId pnode, const int howmuch, const std::string& message) override; void ProcessMessage(CNode& pfrom, const std::string& msg_type, CDataStream& vRecv, @@ -326,7 +334,7 @@ private: /** Send a ping message every PING_INTERVAL or if requested via RPC. May * mark the peer to be disconnected if a ping has timed out. */ - void MaybeSendPing(CNode& node_to); + void MaybeSendPing(CNode& node_to, Peer& peer); const CChainParams& m_chainparams; CConnman& m_connman; @@ -1093,6 +1101,18 @@ bool PeerManagerImpl::GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) PeerRef peer = GetPeerRef(nodeid); if (peer == nullptr) return false; stats.m_starting_height = peer->m_starting_height; + // It is common for nodes with good ping times to suddenly become lagged, + // due to a new block arriving or other large transfer. + // Merely reporting pingtime might fool the caller into thinking the node was still responsive, + // since pingtime does not update until the ping is complete, which might take a while. + // So, if a ping is taking an unusually long time in flight, + // the caller can immediately detect that this is happening. + std::chrono::microseconds ping_wait{0}; + if ((0 != peer->nPingNonceSent) && (0 != peer->m_ping_start.load().count())) { + ping_wait = GetTime<std::chrono::microseconds>() - peer->m_ping_start.load(); + } + + stats.m_ping_wait_usec = count_microseconds(ping_wait); return true; } @@ -1632,6 +1652,12 @@ bool static AlreadyHaveBlock(const uint256& block_hash) EXCLUSIVE_LOCKS_REQUIRED return g_chainman.m_blockman.LookupBlockIndex(block_hash) != nullptr; } +void PeerManagerImpl::SendPings() +{ + LOCK(m_peer_mutex); + for(auto& it : m_peer_map) it.second->fPingQueued = true; +} + void RelayTransaction(const uint256& txid, const uint256& wtxid, const CConnman& connman) { connman.ForEachNode([&txid, &wtxid](CNode* pnode) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { @@ -3842,15 +3868,14 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type, vRecv >> nonce; // Only process pong message if there is an outstanding ping (old ping without nonce should never pong) - if (pfrom.nPingNonceSent != 0) { - if (nonce == pfrom.nPingNonceSent) { + if (peer->nPingNonceSent != 0) { + if (nonce == peer->nPingNonceSent) { // Matching pong received, this ping is no longer outstanding bPingFinished = true; - const auto ping_time = ping_end - pfrom.m_ping_start.load(); + const auto ping_time = ping_end - peer->m_ping_start.load(); if (ping_time.count() >= 0) { - // Successful ping time measurement, replace previous - pfrom.nPingUsecTime = count_microseconds(ping_time); - pfrom.nMinPingUsecTime = std::min(pfrom.nMinPingUsecTime.load(), count_microseconds(ping_time)); + // Let connman know about this successful ping-pong + pfrom.PongReceived(ping_time); } else { // This should never happen sProblem = "Timing mishap"; @@ -3877,12 +3902,12 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type, LogPrint(BCLog::NET, "pong peer=%d: %s, %x expected, %x received, %u bytes\n", pfrom.GetId(), sProblem, - pfrom.nPingNonceSent, + peer->nPingNonceSent, nonce, nAvail); } if (bPingFinished) { - pfrom.nPingNonceSent = 0; + peer->nPingNonceSent = 0; } return; } @@ -4296,15 +4321,15 @@ void PeerManagerImpl::CheckForStaleTipAndEvictPeers() } } -void PeerManagerImpl::MaybeSendPing(CNode& node_to) +void PeerManagerImpl::MaybeSendPing(CNode& node_to, Peer& peer) { // Use mockable time for ping timeouts. // This means that setmocktime may cause pings to time out. auto now = GetTime<std::chrono::microseconds>(); - if (m_connman.RunInactivityChecks(node_to) && node_to.nPingNonceSent && - now > node_to.m_ping_start.load() + std::chrono::seconds{TIMEOUT_INTERVAL}) { - LogPrint(BCLog::NET, "ping timeout: %fs peer=%d\n", 0.000001 * count_microseconds(now - node_to.m_ping_start.load()), node_to.GetId()); + if (m_connman.RunInactivityChecks(node_to) && peer.nPingNonceSent && + now > peer.m_ping_start.load() + std::chrono::seconds{TIMEOUT_INTERVAL}) { + LogPrint(BCLog::NET, "ping timeout: %fs peer=%d\n", 0.000001 * count_microseconds(now - peer.m_ping_start.load()), peer.m_id); node_to.fDisconnect = true; return; } @@ -4312,12 +4337,12 @@ void PeerManagerImpl::MaybeSendPing(CNode& node_to) const CNetMsgMaker msgMaker(node_to.GetCommonVersion()); bool pingSend = false; - if (node_to.fPingQueued) { + if (peer.fPingQueued) { // RPC ping request by user pingSend = true; } - if (node_to.nPingNonceSent == 0 && now > node_to.m_ping_start.load() + PING_INTERVAL) { + if (peer.nPingNonceSent == 0 && now > peer.m_ping_start.load() + PING_INTERVAL) { // Ping automatically sent as a latency probe & keepalive. pingSend = true; } @@ -4327,14 +4352,14 @@ void PeerManagerImpl::MaybeSendPing(CNode& node_to) while (nonce == 0) { GetRandBytes((unsigned char*)&nonce, sizeof(nonce)); } - node_to.fPingQueued = false; - node_to.m_ping_start = now; + peer.fPingQueued = false; + peer.m_ping_start = now; if (node_to.GetCommonVersion() > BIP0031_VERSION) { - node_to.nPingNonceSent = nonce; + peer.nPingNonceSent = nonce; m_connman.PushMessage(&node_to, msgMaker.Make(NetMsgType::PING, nonce)); } else { // Peer is too old to support ping command with nonce, pong will never arrive. - node_to.nPingNonceSent = 0; + peer.nPingNonceSent = 0; m_connman.PushMessage(&node_to, msgMaker.Make(NetMsgType::PING)); } } @@ -4378,7 +4403,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto) // If we get here, the outgoing message serialization version is set and can't change. const CNetMsgMaker msgMaker(pto->GetCommonVersion()); - MaybeSendPing(*pto); + MaybeSendPing(*pto, *peer); // MaybeSendPing may have marked peer for disconnection if (pto->fDisconnect) return true; |