diff --git a/src/net.h b/src/net.h --- a/src/net.h +++ b/src/net.h @@ -493,7 +493,8 @@ void AcceptConnection(const ListenSocket &hListenSocket); void DisconnectNodes(); void NotifyNumConnectionsChanged(); - void InactivityCheck(CNode *pnode); + /** Return true if the peer is inactive and should be disconnected. */ + bool InactivityCheck(const CNode &node) const; bool GenerateSelectSet(std::set &recv_set, std::set &send_set, std::set &error_set); diff --git a/src/net.cpp b/src/net.cpp --- a/src/net.cpp +++ b/src/net.cpp @@ -1422,41 +1422,55 @@ } } -void CConnman::InactivityCheck(CNode *pnode) { - int64_t nTime = GetSystemTimeInSeconds(); - if (nTime - pnode->nTimeConnected > m_peer_connect_timeout) { - if (pnode->nLastRecv == 0 || pnode->nLastSend == 0) { - LogPrint(BCLog::NET, - "socket no message in first %i seconds, %d %d from %d\n", - m_peer_connect_timeout, pnode->nLastRecv != 0, - pnode->nLastSend != 0, pnode->GetId()); - pnode->fDisconnect = true; - } else if (nTime - pnode->nLastSend > TIMEOUT_INTERVAL) { - LogPrintf("socket sending timeout: %is\n", - nTime - pnode->nLastSend); - pnode->fDisconnect = true; - } else if (nTime - pnode->nLastRecv > - (pnode->GetCommonVersion() > BIP0031_VERSION - ? TIMEOUT_INTERVAL - : 90 * 60)) { - LogPrintf("socket receive timeout: %is\n", - nTime - pnode->nLastRecv); - pnode->fDisconnect = true; - } else if (pnode->nPingNonceSent && - pnode->m_ping_start.load() + - std::chrono::seconds{TIMEOUT_INTERVAL} < - GetTime()) { - LogPrintf("ping timeout: %fs\n", - 0.000001 * count_microseconds( - GetTime() - - pnode->m_ping_start.load())); - pnode->fDisconnect = true; - } else if (!pnode->fSuccessfullyConnected) { - LogPrint(BCLog::NET, "version handshake timeout from %d\n", - pnode->GetId()); - pnode->fDisconnect = true; - } +bool CConnman::InactivityCheck(const CNode &node) const { + // Use non-mockable system time (otherwise these timers will pop when we use + // setmocktime in the tests). + int64_t now = GetSystemTimeInSeconds(); + + if (now <= node.nTimeConnected + m_peer_connect_timeout) { + // Only run inactivity checks if the peer has been connected longer than + // m_peer_connect_timeout. + return false; + } + + if (node.nLastRecv == 0 || node.nLastSend == 0) { + LogPrint(BCLog::NET, + "socket no message in first %i seconds, %d %d from %d\n", + m_peer_connect_timeout, node.nLastRecv != 0, + node.nLastSend != 0, node.GetId()); + return true; + } + + if (now > node.nLastSend + TIMEOUT_INTERVAL) { + LogPrintf("socket sending timeout: %is\n", now - node.nLastSend); + return true; } + + if (now > node.nLastRecv + TIMEOUT_INTERVAL) { + LogPrintf("socket receive timeout: %is\n", now - node.nLastRecv); + return true; + } + + if (node.nPingNonceSent && + node.m_ping_start.load() + std::chrono::seconds{TIMEOUT_INTERVAL} < + GetTime()) { + // We use mockable time for ping timeouts. This means that setmocktime + // may cause pings to time out for peers that have been connected for + // longer than m_peer_connect_timeout. + LogPrintf("ping timeout: %fs\n", + 0.000001 * + count_microseconds(GetTime() - + node.m_ping_start.load())); + return true; + } + + if (!node.fSuccessfullyConnected) { + LogPrint(BCLog::NET, "version handshake timeout from %d\n", + node.GetId()); + return true; + } + + return false; } bool CConnman::GenerateSelectSet(std::set &recv_set, @@ -1768,7 +1782,9 @@ } } - InactivityCheck(pnode); + if (InactivityCheck(*pnode)) { + pnode->fDisconnect = true; + } } { LOCK(cs_vNodes);