aboutsummaryrefslogtreecommitdiff
path: root/src/net.cpp
diff options
context:
space:
mode:
authorPieter Wuille <pieter@wuille.net>2023-07-26 13:19:31 -0400
committerPieter Wuille <pieter@wuille.net>2023-08-23 19:56:24 -0400
commit27f9ba23efe82531a465c5e63bf7dc62b6a3a8db (patch)
treedabff76c69490b9d17486e7a255a14121c40438a /src/net.cpp
parent93594e42c3f92d82427d2b284ff0f94cdbebe99c (diff)
net: add V1Transport lock protecting receive state
Rather than relying on the caller to prevent concurrent calls to the various receive-side functions of Transport, introduce a private m_cs_recv inside the implementation to protect the lock state. Of course, this does not remove the need for callers to synchronize calls entirely, as it is a stateful object, and e.g. the order in which Receive(), Complete(), and GetMessage() are called matters. It seems impossible to use a Transport object in a meaningful way in a multi-threaded way without some form of external synchronization, but it still feels safer to make the transport object itself responsible for protecting its internal state.
Diffstat (limited to 'src/net.cpp')
-rw-r--r--src/net.cpp7
1 files changed, 6 insertions, 1 deletions
diff --git a/src/net.cpp b/src/net.cpp
index fa20136bb1..b350c58c61 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -719,6 +719,7 @@ bool CNode::ReceiveMsgBytes(Span<const uint8_t> msg_bytes, bool& complete)
int V1Transport::readHeader(Span<const uint8_t> msg_bytes)
{
+ AssertLockHeld(m_recv_mutex);
// copy data to temporary parsing buffer
unsigned int nRemaining = CMessageHeader::HEADER_SIZE - nHdrPos;
unsigned int nCopy = std::min<unsigned int>(nRemaining, msg_bytes.size());
@@ -759,6 +760,7 @@ int V1Transport::readHeader(Span<const uint8_t> msg_bytes)
int V1Transport::readData(Span<const uint8_t> msg_bytes)
{
+ AssertLockHeld(m_recv_mutex);
unsigned int nRemaining = hdr.nMessageSize - nDataPos;
unsigned int nCopy = std::min<unsigned int>(nRemaining, msg_bytes.size());
@@ -776,7 +778,8 @@ int V1Transport::readData(Span<const uint8_t> msg_bytes)
const uint256& V1Transport::GetMessageHash() const
{
- assert(Complete());
+ AssertLockHeld(m_recv_mutex);
+ assert(CompleteInternal());
if (data_hash.IsNull())
hasher.Finalize(data_hash);
return data_hash;
@@ -784,9 +787,11 @@ const uint256& V1Transport::GetMessageHash() const
CNetMessage V1Transport::GetMessage(const std::chrono::microseconds time, bool& reject_message)
{
+ AssertLockNotHeld(m_recv_mutex);
// Initialize out parameter
reject_message = false;
// decompose a single CNetMessage from the TransportDeserializer
+ LOCK(m_recv_mutex);
CNetMessage msg(std::move(vRecv));
// store message type string, time, and sizes