upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.cpp23
-rw-r--r--src/net.cpp43
-rw-r--r--src/net.h32
3 files changed, 97 insertions, 1 deletions
diff --git a/src/main.cpp b/src/main.cpp
index d4fc6d0..f4e6ce2 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -2190,6 +2190,18 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
2190 } 2190 }
2191 2191
2192 2192
2193 else if (strCommand == "ping")
2194 {
2195 // Nothing to do and nothing to answer. Arriving at all is the entire
2196 // content of the message: the receive path has already stamped
2197 // nLastRecv, which is what the sender wanted us to notice.
2198 //
2199 // Deliberately no reply. A node old enough not to know "ping" ignores
2200 // it as an unknown command and would never answer one, so a scheme
2201 // that required an answer would read every such peer as dead.
2202 }
2203
2204
2193 else 2205 else
2194 { 2206 {
2195 // Ignore unknown commands for extensibility 2207 // Ignore unknown commands for extensibility
@@ -2222,6 +2234,17 @@ bool SendMessages(CNode* pto)
2222 2234
2223 2235
2224 // 2236 //
2237 // Message: keep-alive ping
2238 //
2239 // Only when we have nothing else queued -- any real message serves the
2240 // same purpose. A peer with nothing to relay is otherwise silent, and
2241 // silence is exactly what the inactivity check disconnects on.
2242 //
2243 if (pto->nLastSend && GetTime() - pto->nLastSend > BTF_PING_INTERVAL_SECS && pto->vSend.empty())
2244 pto->PushMessage("ping");
2245
2246
2247 //
2225 // Message: inventory 2248 // Message: inventory
2226 // 2249 //
2227 vector<CInv> vInventoryToSend; 2250 vector<CInv> vInventoryToSend;
diff --git a/src/net.cpp b/src/net.cpp
index 9ee056f..81932d7 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -1092,7 +1092,11 @@ void ThreadSocketHandler2(void* parg)
1092 vRecv.resize(nPos + nBufSize); 1092 vRecv.resize(nPos + nBufSize);
1093 int nBytes = recv(hSocket, &vRecv[nPos], nBufSize, 0); 1093 int nBytes = recv(hSocket, &vRecv[nPos], nBufSize, 0);
1094 vRecv.resize(nPos + max(nBytes, 0)); 1094 vRecv.resize(nPos + max(nBytes, 0));
1095 if (nBytes == 0) 1095 if (nBytes > 0)
1096 {
1097 pnode->nLastRecv = GetTime();
1098 }
1099 else if (nBytes == 0)
1096 { 1100 {
1097 // socket closed gracefully 1101 // socket closed gracefully
1098 if (!pnode->fDisconnect) 1102 if (!pnode->fDisconnect)
@@ -1127,6 +1131,7 @@ void ThreadSocketHandler2(void* parg)
1127 if (nBytes > 0) 1131 if (nBytes > 0)
1128 { 1132 {
1129 vSend.erase(vSend.begin(), vSend.begin() + nBytes); 1133 vSend.erase(vSend.begin(), vSend.begin() + nBytes);
1134 pnode->nLastSend = GetTime();
1130 } 1135 }
1131 else if (nBytes == 0) 1136 else if (nBytes == 0)
1132 { 1137 {
@@ -1140,6 +1145,42 @@ void ThreadSocketHandler2(void* parg)
1140 pnode->vSend.clear(); 1145 pnode->vSend.clear();
1141 } 1146 }
1142 } 1147 }
1148 if (vSend.empty())
1149 pnode->nLastSendEmpty = GetTime();
1150 }
1151 }
1152
1153 //
1154 // Inactivity
1155 //
1156 // Dropping the connection is the whole cure: everything above this
1157 // layer already knows how to reconnect, and a peer we cannot hear
1158 // is worth exactly as much as no peer at all. Give a new
1159 // connection a grace period first, or we would cut off peers that
1160 // are still completing the rendezvous handshake.
1161 //
1162 if (GetTime() - pnode->nTimeConnected > BTF_HANDSHAKE_GRACE_SECS)
1163 {
1164 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
1165 {
1166 LogPrint("net", "socket no message in first %d seconds, recv=%d send=%d\n",
1167 BTF_HANDSHAKE_GRACE_SECS, pnode->nLastRecv != 0, pnode->nLastSend != 0);
1168 pnode->fDisconnect = true;
1169 }
1170 else if (GetTime() - pnode->nLastSend > BTF_SEND_STALL_SECS &&
1171 GetTime() - pnode->nLastSendEmpty > BTF_SEND_STALL_SECS)
1172 {
1173 // We have had something queued to send for this long and
1174 // none of it has gone out: the socket accepts no more.
1175 LogPrint("net", "socket not sending\n");
1176 pnode->fDisconnect = true;
1177 }
1178 else if (GetTime() - pnode->nLastRecv > BTF_RECV_TIMEOUT_SECS)
1179 {
1180 // The deaf case. Nothing has arrived for many block
1181 // intervals while the socket still looks perfectly fine.
1182 LogPrint("net", "socket inactivity timeout\n");
1183 pnode->fDisconnect = true;
1143 } 1184 }
1144 } 1185 }
1145 } 1186 }
diff --git a/src/net.h b/src/net.h
index 11c023e..449cff5 100644
--- a/src/net.h
+++ b/src/net.h
@@ -51,6 +51,24 @@ static const int64 PEX_MIN_INTERVAL = 60;
51// traffic is nothing: one per relay per five minutes. 51// traffic is nothing: one per relay per five minutes.
52static const int BTF_RENDEZVOUS_WAIT_SECS = 300; 52static const int BTF_RENDEZVOUS_WAIT_SECS = 300;
53 53
54// Liveness of an established peer connection. BTF_RENDEZVOUS_WAIT_SECS bounds
55// the wait for a dial to arrive; these bound the connection that comes out of
56// it, which has the same failure mode once it goes quiet.
57//
58// A healthy peer relays a block inventory roughly every nTargetSpacing (two
59// minutes), so silence measured in block intervals is the honest signal.
60// Bitcoin used ninety minutes against ten-minute blocks -- nine intervals --
61// and the same nine intervals here is eighteen minutes; thirty leaves margin
62// for a slow stretch without letting a dead path last an hour.
63static const int BTF_RECV_TIMEOUT_SECS = 30 * 60;
64static const int BTF_SEND_STALL_SECS = 10 * 60;
65static const int BTF_HANDSHAKE_GRACE_SECS = 60;
66
67// Send a ping after this long with nothing to say, so a peer running the
68// inactivity check above does not mistake a quiet node for a dead one. Must
69// stay well under BTF_RECV_TIMEOUT_SECS.
70static const int BTF_PING_INTERVAL_SECS = 10 * 60;
71
54// Descriptors to hand a peer: ours first, then peers that answered us. 72// Descriptors to hand a peer: ours first, then peers that answered us.
55void BtfPexCollect(std::vector<std::string>& vDescOut); 73void BtfPexCollect(std::vector<std::string>& vDescOut);
56// Verify descriptors a peer sent and remember the good ones. Returns how many. 74// Verify descriptors a peer sent and remember the good ones. Returns how many.
@@ -500,6 +518,16 @@ public:
500 // Last "btfpeers" we accepted from this node, to rate-limit the exchange. 518 // Last "btfpeers" we accepted from this node, to rate-limit the exchange.
501 int64 nLastPexRecv; 519 int64 nLastPexRecv;
502 520
521 // Liveness. A peer whose network path dies silently -- NAT drops an idle
522 // mapping, a relay restarts, a route changes -- never sends FIN, so the
523 // socket stays readable-never and the node simply stops hearing from it
524 // with no error anywhere. These stamps are the only way to tell that
525 // apart from a peer that merely has nothing to say.
526 int64 nTimeConnected;
527 int64 nLastSend;
528 int64 nLastRecv;
529 int64 nLastSendEmpty;
530
503 531
504 CNode(SOCKET hSocketIn, CAddress addrIn, bool fInboundIn=false) 532 CNode(SOCKET hSocketIn, CAddress addrIn, bool fInboundIn=false)
505 { 533 {
@@ -517,6 +545,10 @@ public:
517 nRefCount = 0; 545 nRefCount = 0;
518 nReleaseTime = 0; 546 nReleaseTime = 0;
519 nLastPexRecv = 0; 547 nLastPexRecv = 0;
548 nTimeConnected = GetTime();
549 nLastSend = 0;
550 nLastRecv = 0;
551 nLastSendEmpty = GetTime();
520 vfSubscribe.assign(256, false); 552 vfSubscribe.assign(256, false);
521 553
522 // Push a version message 554 // Push a version message