|
33 | 33 | #include <util/system.h>
|
34 | 34 | #include <validation.h>
|
35 | 35 |
|
| 36 | +#include <algorithm> |
36 | 37 | #include <memory>
|
37 | 38 | #include <optional>
|
38 | 39 | #include <typeinfo>
|
@@ -317,8 +318,13 @@ class PeerManagerImpl final : public PeerManager
|
317 | 318 | void PushNodeVersion(CNode& pnode, int64_t nTime);
|
318 | 319 |
|
319 | 320 | /** Send a ping message every PING_INTERVAL or if requested via RPC. May
|
320 |
| - * mark the peer to be disconnected if a ping has timed out. */ |
321 |
| - void MaybeSendPing(CNode& node_to, Peer& peer); |
| 321 | + * mark the peer to be disconnected if a ping has timed out. |
| 322 | + * We use mockable time for ping timeouts, so setmocktime may cause pings |
| 323 | + * to time out. */ |
| 324 | + void MaybeSendPing(CNode& node_to, Peer& peer, std::chrono::microseconds now); |
| 325 | + |
| 326 | + /** Send `addr` messages on a regular schedule. */ |
| 327 | + void MaybeSendAddr(CNode& node, std::chrono::microseconds current_time); |
322 | 328 |
|
323 | 329 | const CChainParams& m_chainparams;
|
324 | 330 | CConnman& m_connman;
|
@@ -4100,12 +4106,8 @@ void PeerManagerImpl::CheckForStaleTipAndEvictPeers()
|
4100 | 4106 | }
|
4101 | 4107 | }
|
4102 | 4108 |
|
4103 |
| -void PeerManagerImpl::MaybeSendPing(CNode& node_to, Peer& peer) |
| 4109 | +void PeerManagerImpl::MaybeSendPing(CNode& node_to, Peer& peer, std::chrono::microseconds now) |
4104 | 4110 | {
|
4105 |
| - // Use mockable time for ping timeouts. |
4106 |
| - // This means that setmocktime may cause pings to time out. |
4107 |
| - auto now = GetTime<std::chrono::microseconds>(); |
4108 |
| - |
4109 | 4111 | if (m_connman.RunInactivityChecks(node_to) && peer.m_ping_nonce_sent &&
|
4110 | 4112 | now > peer.m_ping_start.load() + std::chrono::seconds{TIMEOUT_INTERVAL}) {
|
4111 | 4113 | LogPrint(BCLog::NET, "ping timeout: %fs peer=%d\n", 0.000001 * count_microseconds(now - peer.m_ping_start.load()), peer.m_id);
|
@@ -4144,6 +4146,75 @@ void PeerManagerImpl::MaybeSendPing(CNode& node_to, Peer& peer)
|
4144 | 4146 | }
|
4145 | 4147 | }
|
4146 | 4148 |
|
| 4149 | +void PeerManagerImpl::MaybeSendAddr(CNode& node, std::chrono::microseconds current_time) |
| 4150 | +{ |
| 4151 | + // Nothing to do for non-address-relay peers |
| 4152 | + if (!node.RelayAddrsWithConn()) return; |
| 4153 | + |
| 4154 | + assert(node.m_addr_known); |
| 4155 | + |
| 4156 | + LOCK(node.m_addr_send_times_mutex); |
| 4157 | + // Periodically advertise our local address to the peer. |
| 4158 | + if (fListen && !m_chainman.ActiveChainstate().IsInitialBlockDownload() && |
| 4159 | + node.m_next_local_addr_send < current_time) { |
| 4160 | + // If we've sent before, clear the bloom filter for the peer, so that our |
| 4161 | + // self-announcement will actually go out. |
| 4162 | + // This might be unnecessary if the bloom filter has already rolled |
| 4163 | + // over since our last self-announcement, but there is only a small |
| 4164 | + // bandwidth cost that we can incur by doing this (which happens |
| 4165 | + // once a day on average). |
| 4166 | + if (node.m_next_local_addr_send != 0us) { |
| 4167 | + node.m_addr_known->reset(); |
| 4168 | + } |
| 4169 | + if (std::optional<CAddress> local_addr = GetLocalAddrForPeer(&node)) { |
| 4170 | + FastRandomContext insecure_rand; |
| 4171 | + node.PushAddress(*local_addr, insecure_rand); |
| 4172 | + } |
| 4173 | + node.m_next_local_addr_send = PoissonNextSend(current_time, AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL); |
| 4174 | + } |
| 4175 | + |
| 4176 | + // We sent an `addr` message to this peer recently. Nothing more to do. |
| 4177 | + if (current_time <= node.m_next_addr_send) return; |
| 4178 | + |
| 4179 | + node.m_next_addr_send = PoissonNextSend(current_time, AVG_ADDRESS_BROADCAST_INTERVAL); |
| 4180 | + |
| 4181 | + if (!Assume(node.vAddrToSend.size() <= MAX_ADDR_TO_SEND)) { |
| 4182 | + // Should be impossible since we always check size before adding to |
| 4183 | + // vAddrToSend. Recover by trimming the vector. |
| 4184 | + node.vAddrToSend.resize(MAX_ADDR_TO_SEND); |
| 4185 | + } |
| 4186 | + |
| 4187 | + // Remove addr records that the peer already knows about, and add new |
| 4188 | + // addrs to the m_addr_known filter on the same pass. |
| 4189 | + auto addr_already_known = [&node](const CAddress& addr) { |
| 4190 | + bool ret = node.m_addr_known->contains(addr.GetKey()); |
| 4191 | + if (!ret) node.m_addr_known->insert(addr.GetKey()); |
| 4192 | + return ret; |
| 4193 | + }; |
| 4194 | + node.vAddrToSend.erase(std::remove_if(node.vAddrToSend.begin(), node.vAddrToSend.end(), addr_already_known), |
| 4195 | + node.vAddrToSend.end()); |
| 4196 | + |
| 4197 | + // No addr messages to send |
| 4198 | + if (node.vAddrToSend.empty()) return; |
| 4199 | + |
| 4200 | + const char* msg_type; |
| 4201 | + int make_flags; |
| 4202 | + if (node.m_wants_addrv2) { |
| 4203 | + msg_type = NetMsgType::ADDRV2; |
| 4204 | + make_flags = ADDRV2_FORMAT; |
| 4205 | + } else { |
| 4206 | + msg_type = NetMsgType::ADDR; |
| 4207 | + make_flags = 0; |
| 4208 | + } |
| 4209 | + m_connman.PushMessage(&node, CNetMsgMaker(node.GetCommonVersion()).Make(make_flags, msg_type, node.vAddrToSend)); |
| 4210 | + node.vAddrToSend.clear(); |
| 4211 | + |
| 4212 | + // we only send the big addr message once |
| 4213 | + if (node.vAddrToSend.capacity() > 40) { |
| 4214 | + node.vAddrToSend.shrink_to_fit(); |
| 4215 | + } |
| 4216 | +} |
| 4217 | + |
4147 | 4218 | namespace {
|
4148 | 4219 | class CompareInvMempoolOrder
|
4149 | 4220 | {
|
@@ -4182,79 +4253,20 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
|
4182 | 4253 | // If we get here, the outgoing message serialization version is set and can't change.
|
4183 | 4254 | const CNetMsgMaker msgMaker(pto->GetCommonVersion());
|
4184 | 4255 |
|
4185 |
| - MaybeSendPing(*pto, *peer); |
| 4256 | + const auto current_time = GetTime<std::chrono::microseconds>(); |
| 4257 | + |
| 4258 | + MaybeSendPing(*pto, *peer, current_time); |
4186 | 4259 |
|
4187 | 4260 | // MaybeSendPing may have marked peer for disconnection
|
4188 | 4261 | if (pto->fDisconnect) return true;
|
4189 | 4262 |
|
| 4263 | + MaybeSendAddr(*pto, current_time); |
| 4264 | + |
4190 | 4265 | {
|
4191 | 4266 | LOCK(cs_main);
|
4192 | 4267 |
|
4193 | 4268 | CNodeState &state = *State(pto->GetId());
|
4194 | 4269 |
|
4195 |
| - // Address refresh broadcast |
4196 |
| - auto current_time = GetTime<std::chrono::microseconds>(); |
4197 |
| - |
4198 |
| - if (fListen && pto->RelayAddrsWithConn() && |
4199 |
| - !m_chainman.ActiveChainstate().IsInitialBlockDownload() && |
4200 |
| - pto->m_next_local_addr_send < current_time) { |
4201 |
| - // If we've sent before, clear the bloom filter for the peer, so that our |
4202 |
| - // self-announcement will actually go out. |
4203 |
| - // This might be unnecessary if the bloom filter has already rolled |
4204 |
| - // over since our last self-announcement, but there is only a small |
4205 |
| - // bandwidth cost that we can incur by doing this (which happens |
4206 |
| - // once a day on average). |
4207 |
| - if (pto->m_next_local_addr_send != 0us) { |
4208 |
| - pto->m_addr_known->reset(); |
4209 |
| - } |
4210 |
| - if (std::optional<CAddress> local_addr = GetLocalAddrForPeer(pto)) { |
4211 |
| - FastRandomContext insecure_rand; |
4212 |
| - pto->PushAddress(*local_addr, insecure_rand); |
4213 |
| - } |
4214 |
| - pto->m_next_local_addr_send = PoissonNextSend(current_time, AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL); |
4215 |
| - } |
4216 |
| - |
4217 |
| - // |
4218 |
| - // Message: addr |
4219 |
| - // |
4220 |
| - if (pto->RelayAddrsWithConn() && pto->m_next_addr_send < current_time) { |
4221 |
| - pto->m_next_addr_send = PoissonNextSend(current_time, AVG_ADDRESS_BROADCAST_INTERVAL); |
4222 |
| - std::vector<CAddress> vAddr; |
4223 |
| - vAddr.reserve(pto->vAddrToSend.size()); |
4224 |
| - assert(pto->m_addr_known); |
4225 |
| - |
4226 |
| - const char* msg_type; |
4227 |
| - int make_flags; |
4228 |
| - if (pto->m_wants_addrv2) { |
4229 |
| - msg_type = NetMsgType::ADDRV2; |
4230 |
| - make_flags = ADDRV2_FORMAT; |
4231 |
| - } else { |
4232 |
| - msg_type = NetMsgType::ADDR; |
4233 |
| - make_flags = 0; |
4234 |
| - } |
4235 |
| - |
4236 |
| - for (const CAddress& addr : pto->vAddrToSend) |
4237 |
| - { |
4238 |
| - if (!pto->m_addr_known->contains(addr.GetKey())) |
4239 |
| - { |
4240 |
| - pto->m_addr_known->insert(addr.GetKey()); |
4241 |
| - vAddr.push_back(addr); |
4242 |
| - // receiver rejects addr messages larger than MAX_ADDR_TO_SEND |
4243 |
| - if (vAddr.size() >= MAX_ADDR_TO_SEND) |
4244 |
| - { |
4245 |
| - m_connman.PushMessage(pto, msgMaker.Make(make_flags, msg_type, vAddr)); |
4246 |
| - vAddr.clear(); |
4247 |
| - } |
4248 |
| - } |
4249 |
| - } |
4250 |
| - pto->vAddrToSend.clear(); |
4251 |
| - if (!vAddr.empty()) |
4252 |
| - m_connman.PushMessage(pto, msgMaker.Make(make_flags, msg_type, vAddr)); |
4253 |
| - // we only send the big addr message once |
4254 |
| - if (pto->vAddrToSend.capacity() > 40) |
4255 |
| - pto->vAddrToSend.shrink_to_fit(); |
4256 |
| - } |
4257 |
| - |
4258 | 4270 | // Start block sync
|
4259 | 4271 | if (pindexBestHeader == nullptr)
|
4260 | 4272 | pindexBestHeader = m_chainman.ActiveChain().Tip();
|
@@ -4489,7 +4501,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
|
4489 | 4501 | vInv.clear();
|
4490 | 4502 | }
|
4491 | 4503 | }
|
4492 |
| - pto->m_tx_relay->m_last_mempool_req = GetTime<std::chrono::seconds>(); |
| 4504 | + pto->m_tx_relay->m_last_mempool_req = std::chrono::duration_cast<std::chrono::seconds>(current_time); |
4493 | 4505 | }
|
4494 | 4506 |
|
4495 | 4507 | // Determine transactions to relay
|
@@ -4577,7 +4589,6 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
|
4577 | 4589 | m_connman.PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv));
|
4578 | 4590 |
|
4579 | 4591 | // Detect whether we're stalling
|
4580 |
| - current_time = GetTime<std::chrono::microseconds>(); |
4581 | 4592 | if (state.m_stalling_since.count() && state.m_stalling_since < current_time - BLOCK_STALLING_TIMEOUT) {
|
4582 | 4593 | // Stalling only triggers when the block download window cannot move. During normal steady state,
|
4583 | 4594 | // the download window should be much larger than the to-be-downloaded set of blocks, so disconnection
|
|
0 commit comments