mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-03-05 14:06:27 -05:00
net: make V2Transport preallocate receive buffer space
This commit is contained in:
parent
3ffa5fb49e
commit
297c888997
1 changed files with 37 additions and 0 deletions
37
src/net.cpp
37
src/net.cpp
|
@ -1317,6 +1317,9 @@ size_t V2Transport::GetMaxBytesToProcess() noexcept
|
||||||
bool V2Transport::ReceivedBytes(Span<const uint8_t>& msg_bytes) noexcept
|
bool V2Transport::ReceivedBytes(Span<const uint8_t>& msg_bytes) noexcept
|
||||||
{
|
{
|
||||||
AssertLockNotHeld(m_recv_mutex);
|
AssertLockNotHeld(m_recv_mutex);
|
||||||
|
/** How many bytes to allocate in the receive buffer at most above what is received so far. */
|
||||||
|
static constexpr size_t MAX_RESERVE_AHEAD = 256 * 1024;
|
||||||
|
|
||||||
LOCK(m_recv_mutex);
|
LOCK(m_recv_mutex);
|
||||||
if (m_recv_state == RecvState::V1) return m_v1_fallback.ReceivedBytes(msg_bytes);
|
if (m_recv_state == RecvState::V1) return m_v1_fallback.ReceivedBytes(msg_bytes);
|
||||||
|
|
||||||
|
@ -1327,6 +1330,40 @@ bool V2Transport::ReceivedBytes(Span<const uint8_t>& msg_bytes) noexcept
|
||||||
while (!msg_bytes.empty()) {
|
while (!msg_bytes.empty()) {
|
||||||
// Decide how many bytes to copy from msg_bytes to m_recv_buffer.
|
// Decide how many bytes to copy from msg_bytes to m_recv_buffer.
|
||||||
size_t max_read = GetMaxBytesToProcess();
|
size_t max_read = GetMaxBytesToProcess();
|
||||||
|
|
||||||
|
// Reserve space in the buffer if there is not enough.
|
||||||
|
if (m_recv_buffer.size() + std::min(msg_bytes.size(), max_read) > m_recv_buffer.capacity()) {
|
||||||
|
switch (m_recv_state) {
|
||||||
|
case RecvState::KEY_MAYBE_V1:
|
||||||
|
case RecvState::KEY:
|
||||||
|
case RecvState::GARB_GARBTERM:
|
||||||
|
// During the initial states (key/garbage), allocate once to fit the maximum (4111
|
||||||
|
// bytes).
|
||||||
|
m_recv_buffer.reserve(MAX_GARBAGE_LEN + BIP324Cipher::GARBAGE_TERMINATOR_LEN);
|
||||||
|
break;
|
||||||
|
case RecvState::GARBAUTH:
|
||||||
|
case RecvState::VERSION:
|
||||||
|
case RecvState::APP: {
|
||||||
|
// During states where a packet is being received, as much as is expected but never
|
||||||
|
// more than MAX_RESERVE_AHEAD bytes in addition to what is received so far.
|
||||||
|
// This means attackers that want to cause us to waste allocated memory are limited
|
||||||
|
// to MAX_RESERVE_AHEAD above the largest allowed message contents size, and to
|
||||||
|
// MAX_RESERVE_AHEAD more than they've actually sent us.
|
||||||
|
size_t alloc_add = std::min(max_read, msg_bytes.size() + MAX_RESERVE_AHEAD);
|
||||||
|
m_recv_buffer.reserve(m_recv_buffer.size() + alloc_add);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case RecvState::APP_READY:
|
||||||
|
// The buffer is empty in this state.
|
||||||
|
Assume(m_recv_buffer.empty());
|
||||||
|
break;
|
||||||
|
case RecvState::V1:
|
||||||
|
// Should have bailed out above.
|
||||||
|
Assume(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Can't read more than provided input.
|
// Can't read more than provided input.
|
||||||
max_read = std::min(msg_bytes.size(), max_read);
|
max_read = std::min(msg_bytes.size(), max_read);
|
||||||
// Copy data to buffer.
|
// Copy data to buffer.
|
||||||
|
|
Loading…
Add table
Reference in a new issue