From a443d4e2d0bcc072872143e76b431edf2749d52a Mon Sep 17 00:00:00 2001 From: Oleg Girko Date: Thu, 29 Jun 2017 02:51:10 +0100 Subject: [PATCH] Backport Bitcoin PRs #6589, #7180 and remaining part of #7181: enable per-command byte counters in `CNode` (#1496) * log bytes recv/sent per command * net: Account for `sendheaders` `verack` messages Looks like these were forgotten in #6589. * Backport remaining part of Bitcoin PR bitcoin/bitcoin#7181. Most of this PR is already merged, but a small part remaining that makes per-command byte counts in CNode working. Signed-off-by: Oleg Girko --- src/net.cpp | 21 ++++++++++++++++++++- src/net.h | 34 ++++++++++++++++++++-------------- src/rpcnet.cpp | 22 ++++++++++++++++++++++ 3 files changed, 62 insertions(+), 15 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index d676a1d44..94672e76f 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -77,6 +77,8 @@ namespace { }; } +const static std::string NET_MESSAGE_COMMAND_OTHER = "*other*"; + // // Global state variables // @@ -646,7 +648,9 @@ void CNode::copyStats(CNodeStats &stats) X(fInbound); X(nStartingHeight); X(nSendBytes); + X(mapSendBytesPerMsgCmd); X(nRecvBytes); + X(mapRecvBytesPerMsgCmd); X(fWhitelisted); // It is common for nodes with good ping times to suddenly become lagged, @@ -701,6 +705,15 @@ bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes) nBytes -= handled; if (msg.complete()) { + + //store received bytes per message command + //to prevent a memory DOS, only allow valid commands + mapMsgCmdSize::iterator i = mapRecvBytesPerMsgCmd.find(msg.hdr.pchCommand); + if (i == mapRecvBytesPerMsgCmd.end()) + i = mapRecvBytesPerMsgCmd.find(NET_MESSAGE_COMMAND_OTHER); + assert(i != mapRecvBytesPerMsgCmd.end()); + i->second += msg.hdr.nMessageSize + CMessageHeader::HEADER_SIZE; + msg.nTime = GetTimeMicros(); messageHandlerCondition.notify_one(); } @@ -2437,6 +2450,9 @@ CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNa fMasternode = false; nMinPingUsecTime = std::numeric_limits::max(); vchKeyedNetGroup = CalculateKeyedNetGroup(addr); + BOOST_FOREACH(const std::string &msg, getAllNetMessageTypes()) + mapRecvBytesPerMsgCmd[msg] = 0; + mapRecvBytesPerMsgCmd[NET_MESSAGE_COMMAND_OTHER] = 0; { LOCK(cs_nLastNodeId); @@ -2531,7 +2547,7 @@ void CNode::AbortMessage() UNLOCK_FUNCTION(cs_vSend) LogPrint("net", "(aborted)\n"); } -void CNode::EndMessage() UNLOCK_FUNCTION(cs_vSend) +void CNode::EndMessage(const char* pszCommand) UNLOCK_FUNCTION(cs_vSend) { // The -*messagestest options are intentionally not documented in the help message, // since they are only used during development to debug the networking code and are @@ -2554,6 +2570,9 @@ void CNode::EndMessage() UNLOCK_FUNCTION(cs_vSend) unsigned int nSize = ssSend.size() - CMessageHeader::HEADER_SIZE; WriteLE32((uint8_t*)&ssSend[CMessageHeader::MESSAGE_SIZE_OFFSET], nSize); + //log total amount of bytes per command + mapSendBytesPerMsgCmd[std::string(pszCommand)] += nSize + CMessageHeader::HEADER_SIZE; + // Set the checksum uint256 hash = Hash(ssSend.begin() + CMessageHeader::HEADER_SIZE, ssSend.end()); unsigned int nChecksum = 0; diff --git a/src/net.h b/src/net.h index 627386aeb..eec17f55d 100644 --- a/src/net.h +++ b/src/net.h @@ -186,6 +186,7 @@ struct LocalServiceInfo { extern CCriticalSection cs_mapLocalHost; extern std::map mapLocalHost; +typedef std::map mapMsgCmdSize; //command, total bytes class CNodeStats { @@ -203,7 +204,9 @@ public: bool fInbound; int nStartingHeight; uint64_t nSendBytes; + mapMsgCmdSize mapSendBytesPerMsgCmd; uint64_t nRecvBytes; + mapMsgCmdSize mapRecvBytesPerMsgCmd; bool fWhitelisted; double dPingTime; double dPingWait; @@ -382,6 +385,9 @@ protected: static std::vector vWhitelistedRange; static CCriticalSection cs_vWhitelistedRange; + mapMsgCmdSize mapSendBytesPerMsgCmd; + mapMsgCmdSize mapRecvBytesPerMsgCmd; + // Basic fuzz-testing void Fuzz(int nChance); // modifies ssSend @@ -551,7 +557,7 @@ public: void AbortMessage() UNLOCK_FUNCTION(cs_vSend); // TODO: Document the precondition of this function. Is cs_vSend locked? - void EndMessage() UNLOCK_FUNCTION(cs_vSend); + void EndMessage(const char* pszCommand) UNLOCK_FUNCTION(cs_vSend); void PushVersion(); @@ -561,7 +567,7 @@ public: try { BeginMessage(pszCommand); - EndMessage(); + EndMessage(pszCommand); } catch (...) { @@ -577,7 +583,7 @@ public: { BeginMessage(pszCommand); ssSend << a1; - EndMessage(); + EndMessage(pszCommand); } catch (...) { @@ -593,7 +599,7 @@ public: { BeginMessage(pszCommand); ssSend << a1 << a2; - EndMessage(); + EndMessage(pszCommand); } catch (...) { @@ -609,7 +615,7 @@ public: { BeginMessage(pszCommand); ssSend << a1 << a2 << a3; - EndMessage(); + EndMessage(pszCommand); } catch (...) { @@ -625,7 +631,7 @@ public: { BeginMessage(pszCommand); ssSend << a1 << a2 << a3 << a4; - EndMessage(); + EndMessage(pszCommand); } catch (...) { @@ -641,7 +647,7 @@ public: { BeginMessage(pszCommand); ssSend << a1 << a2 << a3 << a4 << a5; - EndMessage(); + EndMessage(pszCommand); } catch (...) { @@ -657,7 +663,7 @@ public: { BeginMessage(pszCommand); ssSend << a1 << a2 << a3 << a4 << a5 << a6; - EndMessage(); + EndMessage(pszCommand); } catch (...) { @@ -673,7 +679,7 @@ public: { BeginMessage(pszCommand); ssSend << a1 << a2 << a3 << a4 << a5 << a6 << a7; - EndMessage(); + EndMessage(pszCommand); } catch (...) { @@ -689,7 +695,7 @@ public: { BeginMessage(pszCommand); ssSend << a1 << a2 << a3 << a4 << a5 << a6 << a7 << a8; - EndMessage(); + EndMessage(pszCommand); } catch (...) { @@ -705,7 +711,7 @@ public: { BeginMessage(pszCommand); ssSend << a1 << a2 << a3 << a4 << a5 << a6 << a7 << a8 << a9; - EndMessage(); + EndMessage(pszCommand); } catch (...) { @@ -721,7 +727,7 @@ public: { BeginMessage(pszCommand); ssSend << a1 << a2 << a3 << a4 << a5 << a6 << a7 << a8 << a9 << a10; - EndMessage(); + EndMessage(pszCommand); } catch (...) { @@ -737,7 +743,7 @@ public: { BeginMessage(pszCommand); ssSend << a1 << a2 << a3 << a4 << a5 << a6 << a7 << a8 << a9 << a10 << a11; - EndMessage(); + EndMessage(pszCommand); } catch (...) { @@ -753,7 +759,7 @@ public: { BeginMessage(pszCommand); ssSend << a1 << a2 << a3 << a4 << a5 << a6 << a7 << a8 << a9 << a10 << a11 << a12; - EndMessage(); + EndMessage(pszCommand); } catch (...) { diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index c6b0ffdc9..186347c17 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -112,6 +112,14 @@ UniValue getpeerinfo(const UniValue& params, bool fHelp) " n, (numeric) The heights of blocks we're currently asking from this peer\n" " ...\n" " ]\n" + " \"bytessent_per_msg\": {\n" + " \"addr\": n, (numeric) The total bytes sent aggregated by message type\n" + " ...\n" + " }\n" + " \"bytesrecv_per_msg\": {\n" + " \"addr\": n, (numeric) The total bytes received aggregated by message type\n" + " ...\n" + " }\n" " }\n" " ,...\n" "]\n" @@ -166,6 +174,20 @@ UniValue getpeerinfo(const UniValue& params, bool fHelp) } obj.push_back(Pair("whitelisted", stats.fWhitelisted)); + UniValue sendPerMsgCmd(UniValue::VOBJ); + BOOST_FOREACH(const mapMsgCmdSize::value_type &i, stats.mapSendBytesPerMsgCmd) { + if (i.second > 0) + sendPerMsgCmd.push_back(Pair(i.first, i.second)); + } + obj.push_back(Pair("bytessent_per_msg", sendPerMsgCmd)); + + UniValue recvPerMsgCmd(UniValue::VOBJ); + BOOST_FOREACH(const mapMsgCmdSize::value_type &i, stats.mapRecvBytesPerMsgCmd) { + if (i.second > 0) + recvPerMsgCmd.push_back(Pair(i.first, i.second)); + } + obj.push_back(Pair("bytesrecv_per_msg", recvPerMsgCmd)); + ret.push_back(obj); }