diff options
author | John Newbery <john@johnnewbery.com> | 2020-07-09 11:32:15 +0100 |
---|---|---|
committer | John Newbery <john@johnnewbery.com> | 2021-03-31 18:06:51 +0100 |
commit | 935d4889228e7e361c8b0020761fa0e08a55fb48 (patch) | |
tree | d6cf9be6e0b44be088a2ba3cda3cdbc07d423fd1 | |
parent | 01a79ff924b11f91796d4aa63c571897b047ac7d (diff) |
[net processing] Refactor MaybeSendAddr()
Changes to make MaybeSendAddr simpler and easier to maintain/update:
- assert invariant that node.vAddrToSend.size() can never exceed
MAX_ADDR_TO_SEND
- erase known addresses from vAddrToSend in one pass
- no check for (vAddr.size() >= MAX_ADDR_TO_SEND) during iteration,
since vAddr can never exceed MAX_ADDR_TO_SEND.
-rw-r--r-- | src/net_processing.cpp | 46 |
1 files changed, 24 insertions, 22 deletions
diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 1e58225158..4fd37d3f76 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -33,6 +33,7 @@ #include <util/system.h> #include <validation.h> +#include <algorithm> #include <memory> #include <optional> #include <typeinfo> @@ -4148,8 +4149,6 @@ void PeerManagerImpl::MaybeSendAddr(CNode& node, std::chrono::microseconds curre assert(node.m_addr_known); - const CNetMsgMaker msgMaker(node.GetCommonVersion()); - LOCK(node.m_addr_send_times_mutex); // Periodically advertise our local address to the peer. if (fListen && !m_chainman.ActiveChainstate().IsInitialBlockDownload() && @@ -4174,8 +4173,25 @@ void PeerManagerImpl::MaybeSendAddr(CNode& node, std::chrono::microseconds curre if (current_time <= node.m_next_addr_send) return; node.m_next_addr_send = PoissonNextSend(current_time, AVG_ADDRESS_BROADCAST_INTERVAL); - std::vector<CAddress> vAddr; - vAddr.reserve(node.vAddrToSend.size()); + + if (!Assume(node.vAddrToSend.size() <= MAX_ADDR_TO_SEND)) { + // Should be impossible since we always check size before adding to + // vAddrToSend. Recover by trimming the vector. + node.vAddrToSend.resize(MAX_ADDR_TO_SEND); + } + + // Remove addr records that the peer already knows about, and add new + // addrs to the m_addr_known filter on the same pass. + auto addr_already_known = [&node](const CAddress& addr) { + bool ret = node.m_addr_known->contains(addr.GetKey()); + if (!ret) node.m_addr_known->insert(addr.GetKey()); + return ret; + }; + node.vAddrToSend.erase(std::remove_if(node.vAddrToSend.begin(), node.vAddrToSend.end(), addr_already_known), + node.vAddrToSend.end()); + + // No addr messages to send + if (node.vAddrToSend.empty()) return; const char* msg_type; int make_flags; @@ -4186,27 +4202,13 @@ void PeerManagerImpl::MaybeSendAddr(CNode& node, std::chrono::microseconds curre msg_type = NetMsgType::ADDR; make_flags = 0; } - - for (const CAddress& addr : node.vAddrToSend) - { - if (!node.m_addr_known->contains(addr.GetKey())) - { - node.m_addr_known->insert(addr.GetKey()); - vAddr.push_back(addr); - // receiver rejects addr messages larger than MAX_ADDR_TO_SEND - if (vAddr.size() >= MAX_ADDR_TO_SEND) - { - m_connman.PushMessage(&node, msgMaker.Make(make_flags, msg_type, vAddr)); - vAddr.clear(); - } - } - } + m_connman.PushMessage(&node, CNetMsgMaker(node.GetCommonVersion()).Make(make_flags, msg_type, node.vAddrToSend)); node.vAddrToSend.clear(); - if (!vAddr.empty()) - m_connman.PushMessage(&node, msgMaker.Make(make_flags, msg_type, vAddr)); + // we only send the big addr message once - if (node.vAddrToSend.capacity() > 40) + if (node.vAddrToSend.capacity() > 40) { node.vAddrToSend.shrink_to_fit(); + } } namespace { |