aboutsummaryrefslogtreecommitdiff
path: root/src/main.cpp
diff options
context:
space:
mode:
authorPieter Wuille <pieter.wuille@gmail.com>2013-10-13 17:37:02 +0200
committerPieter Wuille <pieter.wuille@gmail.com>2013-10-13 17:41:28 +0200
commit9269d0e96e621a6e02da8074785ac310ce64db73 (patch)
tree9707084615745ee0e8a929b220e3588cdaf47e9b /src/main.cpp
parentc74b6c3d8fcc1750fa0861ae851b353a7f3495d2 (diff)
parent971bb3e901aad5d4f04a651e3e2a75161d3a4e2a (diff)
downloadbitcoin-9269d0e96e621a6e02da8074785ac310ce64db73.tar.xz
Merge pull request #2937
971bb3e Added ping time measurement. New RPC "ping" command to request ping. Implemented "pong" message handler. New "pingtime" field in getpeerinfo, to provide results to user. New "pingwait" field, to show pings still in flight, to better see newly lagging peers. (Josh Lehan)
Diffstat (limited to 'src/main.cpp')
-rw-r--r--src/main.cpp85
1 files changed, 81 insertions, 4 deletions
diff --git a/src/main.cpp b/src/main.cpp
index ed40a3550a..5ce330a9dc 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -3863,6 +3863,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;
@@ -4084,14 +4141,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