aboutsummaryrefslogtreecommitdiff
path: root/src/net.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/net.cpp')
-rw-r--r--src/net.cpp88
1 files changed, 59 insertions, 29 deletions
diff --git a/src/net.cpp b/src/net.cpp
index 7f575b66c6..95ba6da819 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -10,7 +10,6 @@
#include <net.h>
#include <banman.h>
-#include <chainparams.h>
#include <clientversion.h>
#include <consensus/consensus.h>
#include <crypto/sha256.h>
@@ -612,6 +611,16 @@ void CNode::copyStats(CNodeStats &stats, const std::vector<bool> &m_asmap)
}
#undef X
+/**
+ * Receive bytes from the buffer and deserialize them into messages.
+ *
+ * @param[in] pch A pointer to the raw data
+ * @param[in] nBytes Size of the data
+ * @param[out] complete Set True if at least one message has been
+ * deserialized and is ready to be processed
+ * @return True if the peer should stay connected,
+ * False if the peer should be disconnected from.
+ */
bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes, bool& complete)
{
complete = false;
@@ -622,25 +631,35 @@ bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes, bool& complete
while (nBytes > 0) {
// absorb network data
int handled = m_deserializer->Read(pch, nBytes);
- if (handled < 0) return false;
+ if (handled < 0) {
+ // Serious header problem, disconnect from the peer.
+ return false;
+ }
pch += handled;
nBytes -= handled;
if (m_deserializer->Complete()) {
// decompose a transport agnostic CNetMessage from the deserializer
- CNetMessage msg = m_deserializer->GetMessage(Params().MessageStart(), time);
+ uint32_t out_err_raw_size{0};
+ Optional<CNetMessage> result{m_deserializer->GetMessage(time, out_err_raw_size)};
+ if (!result) {
+ // Message deserialization failed. Drop the message but don't disconnect the peer.
+ // store the size of the corrupt message
+ mapRecvBytesPerMsgCmd.find(NET_MESSAGE_COMMAND_OTHER)->second += out_err_raw_size;
+ continue;
+ }
//store received bytes per message command
//to prevent a memory DOS, only allow valid commands
- mapMsgCmdSize::iterator i = mapRecvBytesPerMsgCmd.find(msg.m_command);
+ mapMsgCmdSize::iterator i = mapRecvBytesPerMsgCmd.find(result->m_command);
if (i == mapRecvBytesPerMsgCmd.end())
i = mapRecvBytesPerMsgCmd.find(NET_MESSAGE_COMMAND_OTHER);
assert(i != mapRecvBytesPerMsgCmd.end());
- i->second += msg.m_raw_message_size;
+ i->second += result->m_raw_message_size;
// push the message to the process queue,
- vRecvMsg.push_back(std::move(msg));
+ vRecvMsg.push_back(std::move(*result));
complete = true;
}
@@ -667,11 +686,19 @@ int V1TransportDeserializer::readHeader(const char *pch, unsigned int nBytes)
hdrbuf >> hdr;
}
catch (const std::exception&) {
+ LogPrint(BCLog::NET, "HEADER ERROR - UNABLE TO DESERIALIZE, peer=%d\n", m_node_id);
+ return -1;
+ }
+
+ // Check start string, network magic
+ if (memcmp(hdr.pchMessageStart, m_chain_params.MessageStart(), CMessageHeader::MESSAGE_START_SIZE) != 0) {
+ LogPrint(BCLog::NET, "HEADER ERROR - MESSAGESTART (%s, %u bytes), received %s, peer=%d\n", hdr.GetCommand(), hdr.nMessageSize, HexStr(hdr.pchMessageStart), m_node_id);
return -1;
}
// reject messages larger than MAX_SIZE or MAX_PROTOCOL_MESSAGE_LENGTH
if (hdr.nMessageSize > MAX_SIZE || hdr.nMessageSize > MAX_PROTOCOL_MESSAGE_LENGTH) {
+ LogPrint(BCLog::NET, "HEADER ERROR - SIZE (%s, %u bytes), peer=%d\n", hdr.GetCommand(), hdr.nMessageSize, m_node_id);
return -1;
}
@@ -706,36 +733,39 @@ const uint256& V1TransportDeserializer::GetMessageHash() const
return data_hash;
}
-CNetMessage V1TransportDeserializer::GetMessage(const CMessageHeader::MessageStartChars& message_start, const std::chrono::microseconds time)
+Optional<CNetMessage> V1TransportDeserializer::GetMessage(const std::chrono::microseconds time, uint32_t& out_err_raw_size)
{
// decompose a single CNetMessage from the TransportDeserializer
- CNetMessage msg(std::move(vRecv));
+ Optional<CNetMessage> msg(std::move(vRecv));
- // store state about valid header, netmagic and checksum
- msg.m_valid_header = hdr.IsValid(message_start);
- msg.m_valid_netmagic = (memcmp(hdr.pchMessageStart, message_start, CMessageHeader::MESSAGE_START_SIZE) == 0);
- uint256 hash = GetMessageHash();
+ // store command string, time, and sizes
+ msg->m_command = hdr.GetCommand();
+ msg->m_time = time;
+ msg->m_message_size = hdr.nMessageSize;
+ msg->m_raw_message_size = hdr.nMessageSize + CMessageHeader::HEADER_SIZE;
- // store command string, payload size
- msg.m_command = hdr.GetCommand();
- msg.m_message_size = hdr.nMessageSize;
- msg.m_raw_message_size = hdr.nMessageSize + CMessageHeader::HEADER_SIZE;
+ uint256 hash = GetMessageHash();
// We just received a message off the wire, harvest entropy from the time (and the message checksum)
RandAddEvent(ReadLE32(hash.begin()));
- msg.m_valid_checksum = (memcmp(hash.begin(), hdr.pchChecksum, CMessageHeader::CHECKSUM_SIZE) == 0);
- if (!msg.m_valid_checksum) {
- LogPrint(BCLog::NET, "CHECKSUM ERROR (%s, %u bytes), expected %s was %s\n",
- SanitizeString(msg.m_command), msg.m_message_size,
+ // Check checksum and header command string
+ if (memcmp(hash.begin(), hdr.pchChecksum, CMessageHeader::CHECKSUM_SIZE) != 0) {
+ LogPrint(BCLog::NET, "CHECKSUM ERROR (%s, %u bytes), expected %s was %s, peer=%d\n",
+ SanitizeString(msg->m_command), msg->m_message_size,
HexStr(Span<uint8_t>(hash.begin(), hash.begin() + CMessageHeader::CHECKSUM_SIZE)),
- HexStr(hdr.pchChecksum));
- }
-
- // store receive time
- msg.m_time = time;
-
- // reset the network deserializer (prepare for the next message)
+ HexStr(hdr.pchChecksum),
+ m_node_id);
+ out_err_raw_size = msg->m_raw_message_size;
+ msg = nullopt;
+ } else if (!hdr.IsCommandValid()) {
+ LogPrint(BCLog::NET, "HEADER ERROR - COMMAND (%s, %u bytes), peer=%d\n",
+ hdr.GetCommand(), msg->m_message_size, m_node_id);
+ out_err_raw_size = msg->m_raw_message_size;
+ msg = nullopt;
+ }
+
+ // Always reset the network deserializer (prepare for the next message)
Reset();
return msg;
}
@@ -1786,7 +1816,7 @@ void CConnman::SetTryNewOutboundPeer(bool flag)
// Return the number of peers we have over our outbound connection limit
// Exclude peers that are marked for disconnect, or are going to be
-// disconnected soon (eg one-shots and feelers)
+// disconnected soon (eg ADDR_FETCH and FEELER)
// Also exclude peers that haven't finished initial connection handshake yet
// (so that we don't decide we're over our desired connection limit, and then
// evict some peer that has finished the handshake)
@@ -2864,7 +2894,7 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn
LogPrint(BCLog::NET, "Added connection peer=%d\n", id);
}
- m_deserializer = MakeUnique<V1TransportDeserializer>(V1TransportDeserializer(Params().MessageStart(), SER_NETWORK, INIT_PROTO_VERSION));
+ m_deserializer = MakeUnique<V1TransportDeserializer>(V1TransportDeserializer(Params(), GetId(), SER_NETWORK, INIT_PROTO_VERSION));
m_serializer = MakeUnique<V1TransportSerializer>(V1TransportSerializer());
}