net: Use mockable time for ping/pong, add tests

This commit is contained in:
MarcoFalke
2020-04-14 13:24:18 -04:00
parent faab4aaf2f
commit fa3365430c
9 changed files with 166 additions and 34 deletions

View File

@@ -563,15 +563,15 @@ void CNode::copyStats(CNodeStats &stats, const std::vector<bool> &m_asmap)
// since pingtime does not update until the ping is complete, which might take a while.
// So, if a ping is taking an unusually long time in flight,
// the caller can immediately detect that this is happening.
int64_t nPingUsecWait = 0;
if ((0 != nPingNonceSent) && (0 != nPingUsecStart)) {
nPingUsecWait = GetTimeMicros() - nPingUsecStart;
std::chrono::microseconds ping_wait{0};
if ((0 != nPingNonceSent) && (0 != m_ping_start.load().count())) {
ping_wait = GetTime<std::chrono::microseconds>() - m_ping_start.load();
}
// Raw ping time is in microseconds, but show it to user as whole seconds (Bitcoin users should be well used to small numbers with many decimal places by now :)
stats.m_ping_usec = nPingUsecTime;
stats.m_min_ping_usec = nMinPingUsecTime;
stats.m_ping_wait_usec = nPingUsecWait;
stats.m_ping_wait_usec = count_microseconds(ping_wait);
// Leave string empty if addrLocal invalid (not filled in yet)
CService addrLocalUnlocked = GetAddrLocal();
@@ -582,9 +582,9 @@ void CNode::copyStats(CNodeStats &stats, const std::vector<bool> &m_asmap)
bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes, bool& complete)
{
complete = false;
int64_t nTimeMicros = GetTimeMicros();
const auto time = GetTime<std::chrono::microseconds>();
LOCK(cs_vRecv);
nLastRecv = nTimeMicros / 1000000;
nLastRecv = std::chrono::duration_cast<std::chrono::seconds>(time).count();
nRecvBytes += nBytes;
while (nBytes > 0) {
// absorb network data
@@ -596,7 +596,7 @@ bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes, bool& complete
if (m_deserializer->Complete()) {
// decompose a transport agnostic CNetMessage from the deserializer
CNetMessage msg = m_deserializer->GetMessage(Params().MessageStart(), nTimeMicros);
CNetMessage msg = m_deserializer->GetMessage(Params().MessageStart(), time);
//store received bytes per message command
//to prevent a memory DOS, only allow valid commands
@@ -699,7 +699,8 @@ const uint256& V1TransportDeserializer::GetMessageHash() const
return data_hash;
}
CNetMessage V1TransportDeserializer::GetMessage(const CMessageHeader::MessageStartChars& message_start, int64_t time) {
CNetMessage V1TransportDeserializer::GetMessage(const CMessageHeader::MessageStartChars& message_start, const std::chrono::microseconds time)
{
// decompose a single CNetMessage from the TransportDeserializer
CNetMessage msg(std::move(vRecv));
@@ -1154,9 +1155,9 @@ void CConnman::InactivityCheck(CNode *pnode)
LogPrintf("socket receive timeout: %is\n", nTime - pnode->nLastRecv);
pnode->fDisconnect = true;
}
else if (pnode->nPingNonceSent && pnode->nPingUsecStart + TIMEOUT_INTERVAL * 1000000 < GetTimeMicros())
else if (pnode->nPingNonceSent && pnode->m_ping_start.load() + std::chrono::seconds{TIMEOUT_INTERVAL} < GetTime<std::chrono::microseconds>())
{
LogPrintf("ping timeout: %fs\n", 0.000001 * (GetTimeMicros() - pnode->nPingUsecStart));
LogPrintf("ping timeout: %fs\n", 0.000001 * count_microseconds(GetTime<std::chrono::microseconds>() - pnode->m_ping_start.load()));
pnode->fDisconnect = true;
}
else if (!pnode->fSuccessfullyConnected)