diff options
Diffstat (limited to 'src/main.cpp')
-rw-r--r-- | src/main.cpp | 85 |
1 files changed, 81 insertions, 4 deletions
diff --git a/src/main.cpp b/src/main.cpp index d0cf3f8eb2..732a828524 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3862,6 +3862,63 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) } + else if (strCommand == "pong") + { + int64 pingUsecEnd = GetTimeMicros(); + uint64 nonce = 0; + size_t nAvail = vRecv.in_avail(); + bool bPingFinished = false; + std::string sProblem; + + if (nAvail >= sizeof(nonce)) { + vRecv >> nonce; + + // Only process pong message if there is an outstanding ping (old ping without nonce should never pong) + if (pfrom->nPingNonceSent != 0) { + if (nonce == pfrom->nPingNonceSent) { + // Matching pong received, this ping is no longer outstanding + bPingFinished = true; + int64 pingUsecTime = pingUsecEnd - pfrom->nPingUsecStart; + if (pingUsecTime > 0) { + // Successful ping time measurement, replace previous + pfrom->nPingUsecTime = pingUsecTime; + } else { + // This should never happen + sProblem = "Timing mishap"; + } + } else { + // Nonce mismatches are normal when pings are overlapping + sProblem = "Nonce mismatch"; + if (nonce == 0) { + // This is most likely a bug in another implementation somewhere, cancel this ping + bPingFinished = true; + sProblem = "Nonce zero"; + } + } + } else { + sProblem = "Unsolicited pong without ping"; + } + } else { + // This is most likely a bug in another implementation somewhere, cancel this ping + bPingFinished = true; + sProblem = "Short payload"; + } + + if (!(sProblem.empty())) { + LogPrint("net", "pong %s %s: %s, %"PRI64x" expected, %"PRI64x" received, %zu bytes\n" + , pfrom->addr.ToString().c_str() + , pfrom->strSubVer.c_str() + , sProblem.c_str() + , pfrom->nPingNonceSent + , nonce + , nAvail); + } + if (bPingFinished) { + pfrom->nPingNonceSent = 0; + } + } + + else if (strCommand == "alert") { CAlert alert; @@ -4083,14 +4140,34 @@ bool SendMessages(CNode* pto, bool fSendTrickle) if (pto->nVersion == 0) return true; - // Keep-alive ping. We send a nonce of zero because we don't use it anywhere - // right now. + // + // Message: ping + // + bool pingSend = false; + if (pto->fPingQueued) { + // RPC ping request by user + pingSend = true; + } if (pto->nLastSend && GetTime() - pto->nLastSend > 30 * 60 && pto->vSendMsg.empty()) { + // Ping automatically sent as a keepalive + pingSend = true; + } + if (pingSend) { uint64 nonce = 0; - if (pto->nVersion > BIP0031_VERSION) + while (nonce == 0) { + RAND_bytes((unsigned char*)&nonce, sizeof(nonce)); + } + pto->nPingNonceSent = nonce; + pto->fPingQueued = false; + if (pto->nVersion > BIP0031_VERSION) { + // Take timestamp as close as possible before transmitting ping + pto->nPingUsecStart = GetTimeMicros(); pto->PushMessage("ping", nonce); - else + } else { + // Peer is too old to support ping command with nonce, pong will never arrive, disable timing + pto->nPingUsecStart = 0; pto->PushMessage("ping"); + } } // Start block sync |