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>
@@ -4148,8 +4149,6 @@ void PeerManagerImpl::MaybeSendAddr(CNode& node, std::chrono::microseconds curre
4148
4149
4149
4150
assert (node.m_addr_known );
4150
4151
4151
- const CNetMsgMaker msgMaker (node.GetCommonVersion ());
4152
-
4153
4152
LOCK (node.m_addr_send_times_mutex );
4154
4153
// Periodically advertise our local address to the peer.
4155
4154
if (fListen && !m_chainman.ActiveChainstate ().IsInitialBlockDownload () &&
@@ -4174,8 +4173,25 @@ void PeerManagerImpl::MaybeSendAddr(CNode& node, std::chrono::microseconds curre
4174
4173
if (current_time <= node.m_next_addr_send ) return ;
4175
4174
4176
4175
node.m_next_addr_send = PoissonNextSend (current_time, AVG_ADDRESS_BROADCAST_INTERVAL);
4177
- std::vector<CAddress> vAddr;
4178
- vAddr.reserve (node.vAddrToSend .size ());
4176
+
4177
+ if (!Assume (node.vAddrToSend .size () <= MAX_ADDR_TO_SEND)) {
4178
+ // Should be impossible since we always check size before adding to
4179
+ // vAddrToSend. Recover by trimming the vector.
4180
+ node.vAddrToSend .resize (MAX_ADDR_TO_SEND);
4181
+ }
4182
+
4183
+ // Remove addr records that the peer already knows about, and add new
4184
+ // addrs to the m_addr_known filter on the same pass.
4185
+ auto addr_already_known = [&node](const CAddress& addr) {
4186
+ bool ret = node.m_addr_known ->contains (addr.GetKey ());
4187
+ if (!ret) node.m_addr_known ->insert (addr.GetKey ());
4188
+ return ret;
4189
+ };
4190
+ node.vAddrToSend .erase (std::remove_if (node.vAddrToSend .begin (), node.vAddrToSend .end (), addr_already_known),
4191
+ node.vAddrToSend .end ());
4192
+
4193
+ // No addr messages to send
4194
+ if (node.vAddrToSend .empty ()) return ;
4179
4195
4180
4196
const char * msg_type;
4181
4197
int make_flags;
@@ -4186,27 +4202,13 @@ void PeerManagerImpl::MaybeSendAddr(CNode& node, std::chrono::microseconds curre
4186
4202
msg_type = NetMsgType::ADDR;
4187
4203
make_flags = 0 ;
4188
4204
}
4189
-
4190
- for (const CAddress& addr : node.vAddrToSend )
4191
- {
4192
- if (!node.m_addr_known ->contains (addr.GetKey ()))
4193
- {
4194
- node.m_addr_known ->insert (addr.GetKey ());
4195
- vAddr.push_back (addr);
4196
- // receiver rejects addr messages larger than MAX_ADDR_TO_SEND
4197
- if (vAddr.size () >= MAX_ADDR_TO_SEND)
4198
- {
4199
- m_connman.PushMessage (&node, msgMaker.Make (make_flags, msg_type, vAddr));
4200
- vAddr.clear ();
4201
- }
4202
- }
4203
- }
4205
+ m_connman.PushMessage (&node, CNetMsgMaker (node.GetCommonVersion ()).Make (make_flags, msg_type, node.vAddrToSend ));
4204
4206
node.vAddrToSend .clear ();
4205
- if (!vAddr.empty ())
4206
- m_connman.PushMessage (&node, msgMaker.Make (make_flags, msg_type, vAddr));
4207
+
4207
4208
// we only send the big addr message once
4208
- if (node.vAddrToSend .capacity () > 40 )
4209
+ if (node.vAddrToSend .capacity () > 40 ) {
4209
4210
node.vAddrToSend .shrink_to_fit ();
4211
+ }
4210
4212
}
4211
4213
4212
4214
namespace {
0 commit comments