Changeset View
Changeset View
Standalone View
Standalone View
src/net.cpp
Show First 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | |||||
#ifdef USE_POLL | #ifdef USE_POLL | ||||
#include <poll.h> | #include <poll.h> | ||||
#endif | #endif | ||||
#include <algorithm> | #include <algorithm> | ||||
#include <array> | #include <array> | ||||
#include <cmath> | #include <cmath> | ||||
#include <cstdint> | #include <cstdint> | ||||
#include <exception> | |||||
#include <functional> | #include <functional> | ||||
#include <limits> | #include <limits> | ||||
#include <optional> | #include <optional> | ||||
#include <unordered_map> | #include <unordered_map> | ||||
class NetException : public std::exception {}; | |||||
class InvalidNetMagic : public NetException {}; | |||||
class ChecksumError : public NetException {}; | |||||
/** Maximum number of block-relay-only anchor connections */ | /** Maximum number of block-relay-only anchor connections */ | ||||
static constexpr size_t MAX_BLOCK_RELAY_ONLY_ANCHORS = 2; | static constexpr size_t MAX_BLOCK_RELAY_ONLY_ANCHORS = 2; | ||||
static_assert(MAX_BLOCK_RELAY_ONLY_ANCHORS <= | static_assert(MAX_BLOCK_RELAY_ONLY_ANCHORS <= | ||||
static_cast<size_t>(MAX_BLOCK_RELAY_ONLY_CONNECTIONS), | static_cast<size_t>(MAX_BLOCK_RELAY_ONLY_CONNECTIONS), | ||||
"MAX_BLOCK_RELAY_ONLY_ANCHORS must not exceed " | "MAX_BLOCK_RELAY_ONLY_ANCHORS must not exceed " | ||||
"MAX_BLOCK_RELAY_ONLY_CONNECTIONS."); | "MAX_BLOCK_RELAY_ONLY_CONNECTIONS."); | ||||
/** Anchor IP address database file name */ | /** Anchor IP address database file name */ | ||||
const char *const ANCHORS_DATABASE_FILENAME = "anchors.dat"; | const char *const ANCHORS_DATABASE_FILENAME = "anchors.dat"; | ||||
▲ Show 20 Lines • Show All 591 Lines • ▼ Show 20 Lines | while (msg_bytes.size() > 0) { | ||||
if (handled < 0) { | if (handled < 0) { | ||||
// Serious header problem, disconnect from the peer. | // Serious header problem, disconnect from the peer. | ||||
return false; | return false; | ||||
} | } | ||||
if (m_deserializer->Complete()) { | if (m_deserializer->Complete()) { | ||||
// decompose a transport agnostic CNetMessage from the deserializer | // decompose a transport agnostic CNetMessage from the deserializer | ||||
uint32_t out_err_raw_size{0}; | uint32_t out_err_raw_size{0}; | ||||
std::optional<CNetMessage> result{ | std::optional<CNetMessage> result{std::nullopt}; | ||||
m_deserializer->GetMessage(time, out_err_raw_size)}; | try { | ||||
result = m_deserializer->GetMessage(time, out_err_raw_size); | |||||
} catch (const ChecksumError &) { | |||||
mapRecvBytesPerMsgCmd.find(NET_MESSAGE_COMMAND_OTHER)->second += | |||||
out_err_raw_size; | |||||
throw; | |||||
} | |||||
if (!result) { | if (!result) { | ||||
// Message deserialization failed. Drop the message but don't | // Message deserialization failed. Drop the message but don't | ||||
// disconnect the peer. store the size of the corrupt message | // disconnect the peer. store the size of the corrupt message | ||||
mapRecvBytesPerMsgCmd.find(NET_MESSAGE_COMMAND_OTHER)->second += | mapRecvBytesPerMsgCmd.find(NET_MESSAGE_COMMAND_OTHER)->second += | ||||
out_err_raw_size; | out_err_raw_size; | ||||
continue; | continue; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | int V1TransportDeserializer::readHeader(const Config &config, | ||||
// Check start string, network magic | // Check start string, network magic | ||||
if (memcmp(hdr.pchMessageStart.begin(), m_chain_params.NetMagic().begin(), | if (memcmp(hdr.pchMessageStart.begin(), m_chain_params.NetMagic().begin(), | ||||
CMessageHeader::MESSAGE_START_SIZE) != 0) { | CMessageHeader::MESSAGE_START_SIZE) != 0) { | ||||
LogPrint(BCLog::NET, | LogPrint(BCLog::NET, | ||||
"HEADER ERROR - MESSAGESTART (%s, %u bytes), received %s, " | "HEADER ERROR - MESSAGESTART (%s, %u bytes), received %s, " | ||||
"peer=%d\n", | "peer=%d\n", | ||||
hdr.GetCommand(), hdr.nMessageSize, | hdr.GetCommand(), hdr.nMessageSize, | ||||
HexStr(hdr.pchMessageStart), m_node_id); | HexStr(hdr.pchMessageStart), m_node_id); | ||||
throw InvalidNetMagic{}; | |||||
return -1; | return -1; | ||||
} | } | ||||
// Reject oversized messages | // Reject oversized messages | ||||
if (hdr.IsOversized(config)) { | if (hdr.IsOversized(config)) { | ||||
LogPrint(BCLog::NET, "HEADER ERROR - SIZE (%s, %u bytes), peer=%d\n", | LogPrint(BCLog::NET, "HEADER ERROR - SIZE (%s, %u bytes), peer=%d\n", | ||||
hdr.GetCommand(), hdr.nMessageSize, m_node_id); | hdr.GetCommand(), hdr.nMessageSize, m_node_id); | ||||
return -1; | return -1; | ||||
▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | if (memcmp(hash.begin(), hdr.pchChecksum, CMessageHeader::CHECKSUM_SIZE) != | ||||
LogPrint( | LogPrint( | ||||
BCLog::NET, | BCLog::NET, | ||||
"CHECKSUM ERROR (%s, %u bytes), expected %s was %s, peer=%d\n", | "CHECKSUM ERROR (%s, %u bytes), expected %s was %s, peer=%d\n", | ||||
SanitizeString(msg->m_command), msg->m_message_size, | SanitizeString(msg->m_command), msg->m_message_size, | ||||
HexStr(Span<uint8_t>(hash.begin(), | HexStr(Span<uint8_t>(hash.begin(), | ||||
hash.begin() + CMessageHeader::CHECKSUM_SIZE)), | hash.begin() + CMessageHeader::CHECKSUM_SIZE)), | ||||
HexStr(hdr.pchChecksum), m_node_id); | HexStr(hdr.pchChecksum), m_node_id); | ||||
out_err_raw_size = msg->m_raw_message_size; | out_err_raw_size = msg->m_raw_message_size; | ||||
msg = std::nullopt; | Reset(); | ||||
throw ChecksumError{}; | |||||
} else if (!hdr.IsCommandValid()) { | } else if (!hdr.IsCommandValid()) { | ||||
LogPrint(BCLog::NET, "HEADER ERROR - COMMAND (%s, %u bytes), peer=%d\n", | LogPrint(BCLog::NET, "HEADER ERROR - COMMAND (%s, %u bytes), peer=%d\n", | ||||
hdr.GetCommand(), msg->m_message_size, m_node_id); | hdr.GetCommand(), msg->m_message_size, m_node_id); | ||||
out_err_raw_size = msg->m_raw_message_size; | out_err_raw_size = msg->m_raw_message_size; | ||||
msg = std::nullopt; | msg = std::nullopt; | ||||
} | } | ||||
// Always reset the network deserializer (prepare for the next message) | // Always reset the network deserializer (prepare for the next message) | ||||
▲ Show 20 Lines • Show All 1,031 Lines • ▼ Show 20 Lines | for (CNode *pnode : vNodesCopy) { | ||||
if (pnode->hSocket == INVALID_SOCKET) { | if (pnode->hSocket == INVALID_SOCKET) { | ||||
continue; | continue; | ||||
} | } | ||||
nBytes = recv(pnode->hSocket, (char *)pchBuf, sizeof(pchBuf), | nBytes = recv(pnode->hSocket, (char *)pchBuf, sizeof(pchBuf), | ||||
MSG_DONTWAIT); | MSG_DONTWAIT); | ||||
} | } | ||||
if (nBytes > 0) { | if (nBytes > 0) { | ||||
bool notify = false; | bool notify = false; | ||||
try { | |||||
if (!pnode->ReceiveMsgBytes( | if (!pnode->ReceiveMsgBytes( | ||||
*config, Span<const uint8_t>(pchBuf, nBytes), notify)) { | *config, Span<const uint8_t>(pchBuf, nBytes), | ||||
notify)) { | |||||
pnode->CloseSocketDisconnect(); | |||||
} | |||||
} catch (const NetException &) { | |||||
if (m_banman) { | |||||
m_banman->Discourage(pnode->addr); | |||||
} | |||||
DisconnectNode(pnode->addr); | |||||
pnode->CloseSocketDisconnect(); | pnode->CloseSocketDisconnect(); | ||||
} | } | ||||
RecordBytesRecv(nBytes); | RecordBytesRecv(nBytes); | ||||
if (notify) { | if (notify) { | ||||
size_t nSizeAdded = 0; | size_t nSizeAdded = 0; | ||||
auto it(pnode->vRecvMsg.begin()); | auto it(pnode->vRecvMsg.begin()); | ||||
for (; it != pnode->vRecvMsg.end(); ++it) { | for (; it != pnode->vRecvMsg.end(); ++it) { | ||||
// vRecvMsg contains only completed CNetMessage | // vRecvMsg contains only completed CNetMessage | ||||
▲ Show 20 Lines • Show All 1,827 Lines • Show Last 20 Lines |