Skip to content

Commit 539e4ee

Browse files
author
MarcoFalke
committed
Merge #21236: net processing: Extract addr send functionality into MaybeSendAddr()
935d488 [net processing] Refactor MaybeSendAddr() (John Newbery) 01a79ff [net processing] Fix overindentation in MaybeSendAddr() (John Newbery) 38c0be5 [net processing] Refactor MaybeSendAddr() - early exits (John Newbery) c87423c [net processing] Change MaybeSendAddr() to take a reference (John Newbery) ad71929 [net processing] Extract `addr` send functionality into MaybeSendAddr() (John Newbery) 4ad4abc [net] Change addr send times fields to be guarded by new mutex (John Newbery) c02fa47 [net processing] Only call GetTime() once in SendMessages() (John Newbery) Pull request description: This continues the work of moving application layer data into net_processing. It refactors `addr` send functionality into its own function `MaybeSendAddr()` and flattens/simplifies the code. Isolating and simplifying the addr handling code makes subsequent changes (which will move addr data and logic into net processing) easier to review. This is a pure refactor. There are no functional changes. For motivation of the project, see #19398. ACKs for top commit: sipa: utACK 935d488 hebasto: ACK 935d488, I have reviewed the code and it looks OK, I agree it can be merged. MarcoFalke: review ACK 935d488 🐑 Tree-SHA512: 4e9dc84603147e74f479a211b42bcf315bdf5d14c21c08cf0b17d6c252775b90b012f0e0d834f1a607ed63c7ed5c63d5cf49b134344e7b64a1695bfcff111c92
2 parents 602b038 + 935d488 commit 539e4ee

File tree

2 files changed

+87
-75
lines changed

2 files changed

+87
-75
lines changed

src/net.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -549,8 +549,9 @@ class CNode
549549
std::vector<CAddress> vAddrToSend;
550550
std::unique_ptr<CRollingBloomFilter> m_addr_known{nullptr};
551551
bool fGetAddr{false};
552-
std::chrono::microseconds m_next_addr_send GUARDED_BY(cs_sendProcessing){0};
553-
std::chrono::microseconds m_next_local_addr_send GUARDED_BY(cs_sendProcessing){0};
552+
Mutex m_addr_send_times_mutex;
553+
std::chrono::microseconds m_next_addr_send GUARDED_BY(m_addr_send_times_mutex){0};
554+
std::chrono::microseconds m_next_local_addr_send GUARDED_BY(m_addr_send_times_mutex){0};
554555

555556
struct TxRelay {
556557
mutable RecursiveMutex cs_filter;

src/net_processing.cpp

Lines changed: 84 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include <util/system.h>
3434
#include <validation.h>
3535

36+
#include <algorithm>
3637
#include <memory>
3738
#include <optional>
3839
#include <typeinfo>
@@ -317,8 +318,13 @@ class PeerManagerImpl final : public PeerManager
317318
void PushNodeVersion(CNode& pnode, int64_t nTime);
318319

319320
/** 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);
322328

323329
const CChainParams& m_chainparams;
324330
CConnman& m_connman;
@@ -4100,12 +4106,8 @@ void PeerManagerImpl::CheckForStaleTipAndEvictPeers()
41004106
}
41014107
}
41024108

4103-
void PeerManagerImpl::MaybeSendPing(CNode& node_to, Peer& peer)
4109+
void PeerManagerImpl::MaybeSendPing(CNode& node_to, Peer& peer, std::chrono::microseconds now)
41044110
{
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-
41094111
if (m_connman.RunInactivityChecks(node_to) && peer.m_ping_nonce_sent &&
41104112
now > peer.m_ping_start.load() + std::chrono::seconds{TIMEOUT_INTERVAL}) {
41114113
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)
41444146
}
41454147
}
41464148

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+
41474218
namespace {
41484219
class CompareInvMempoolOrder
41494220
{
@@ -4182,79 +4253,20 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
41824253
// If we get here, the outgoing message serialization version is set and can't change.
41834254
const CNetMsgMaker msgMaker(pto->GetCommonVersion());
41844255

4185-
MaybeSendPing(*pto, *peer);
4256+
const auto current_time = GetTime<std::chrono::microseconds>();
4257+
4258+
MaybeSendPing(*pto, *peer, current_time);
41864259

41874260
// MaybeSendPing may have marked peer for disconnection
41884261
if (pto->fDisconnect) return true;
41894262

4263+
MaybeSendAddr(*pto, current_time);
4264+
41904265
{
41914266
LOCK(cs_main);
41924267

41934268
CNodeState &state = *State(pto->GetId());
41944269

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-
42584270
// Start block sync
42594271
if (pindexBestHeader == nullptr)
42604272
pindexBestHeader = m_chainman.ActiveChain().Tip();
@@ -4489,7 +4501,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
44894501
vInv.clear();
44904502
}
44914503
}
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);
44934505
}
44944506

44954507
// Determine transactions to relay
@@ -4577,7 +4589,6 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
45774589
m_connman.PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv));
45784590

45794591
// Detect whether we're stalling
4580-
current_time = GetTime<std::chrono::microseconds>();
45814592
if (state.m_stalling_since.count() && state.m_stalling_since < current_time - BLOCK_STALLING_TIMEOUT) {
45824593
// Stalling only triggers when the block download window cannot move. During normal steady state,
45834594
// the download window should be much larger than the to-be-downloaded set of blocks, so disconnection

0 commit comments

Comments
 (0)