upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src/net.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/net.cpp')
-rw-r--r--src/net.cpp194
1 files changed, 188 insertions, 6 deletions
diff --git a/src/net.cpp b/src/net.cpp
index 7091981..449d91c 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -51,6 +51,103 @@ int64 nBlocksReceived = 0;
51int64 nBlocksWithoutParent = 0; 51int64 nBlocksWithoutParent = 0;
52static int64 nNodeStartTime = 0; 52static int64 nNodeStartTime = 0;
53 53
54static CCriticalSection cs_btfChurn;
55static int64 nBtfResolveAttempts = 0;
56static int64 nBtfResolveOk = 0;
57static int64 nBtfResolveMiss = 0;
58static int64 nBtfDialAttempts = 0;
59static int64 nBtfDialOk = 0;
60static int64 nBtfDialFailed = 0;
61static int64 nBtfRegisterOk = 0;
62static int64 nBtfRegisterFailed = 0;
63static int64 nBtfPairOk = 0;
64static int64 nBtfPairFailed = 0;
65static int64 nBtfHandshakeNoRecv = 0;
66static int64 nBtfHandshakeNoSend = 0;
67static int64 nBtfHandshakeSilent = 0;
68static string strBtfLastDialFail;
69static string strBtfLastHandshakeTimeout;
70
71void BtfChurnNoteResolveAttempt()
72{
73 CRITICAL_BLOCK(cs_btfChurn)
74 nBtfResolveAttempts++;
75}
76
77void BtfChurnNoteResolveResult(bool fOk)
78{
79 CRITICAL_BLOCK(cs_btfChurn)
80 {
81 if (fOk) nBtfResolveOk++;
82 else nBtfResolveMiss++;
83 }
84}
85
86void BtfChurnNoteDialAttempt(const string& strBtfAddr, const string& strMeeting)
87{
88 CRITICAL_BLOCK(cs_btfChurn)
89 nBtfDialAttempts++;
90 LogPrint("net", "btfchurn: dial attempt addr=%s meeting=%s\n",
91 strBtfAddr.c_str(), strMeeting.c_str());
92}
93
94void BtfChurnNoteDialResult(const string& strBtfAddr, const string& strMeeting, bool fOk)
95{
96 CRITICAL_BLOCK(cs_btfChurn)
97 {
98 if (fOk)
99 nBtfDialOk++;
100 else
101 {
102 nBtfDialFailed++;
103 strBtfLastDialFail = strBtfAddr + " via " + strMeeting;
104 }
105 }
106 LogPrint("net", "btfchurn: dial %s addr=%s meeting=%s\n",
107 fOk ? "ok" : "failed", strBtfAddr.c_str(), strMeeting.c_str());
108}
109
110void BtfChurnNoteRegisterResult(const string& strMeeting, bool fOk)
111{
112 CRITICAL_BLOCK(cs_btfChurn)
113 {
114 if (fOk) nBtfRegisterOk++;
115 else nBtfRegisterFailed++;
116 }
117 LogPrint("net", "btfchurn: register %s meeting=%s\n",
118 fOk ? "ok" : "failed", strMeeting.c_str());
119}
120
121void BtfChurnNotePairResult(const string& strMeeting, bool fOk)
122{
123 CRITICAL_BLOCK(cs_btfChurn)
124 {
125 if (fOk) nBtfPairOk++;
126 else nBtfPairFailed++;
127 }
128 LogPrint("net", "btfchurn: pair %s meeting=%s\n",
129 fOk ? "ok" : "timeout-or-drop", strMeeting.c_str());
130}
131
132void BtfChurnNoteHandshakeTimeout(const string& strBtfAddr, const string& strMeeting,
133 bool fRecv, bool fSend)
134{
135 CRITICAL_BLOCK(cs_btfChurn)
136 {
137 if (!fRecv && !fSend)
138 nBtfHandshakeSilent++;
139 else
140 {
141 if (!fRecv) nBtfHandshakeNoRecv++;
142 if (!fSend) nBtfHandshakeNoSend++;
143 }
144 strBtfLastHandshakeTimeout = strprintf("%s via %s recv=%d send=%d",
145 strBtfAddr.empty() ? "unknown" : strBtfAddr.c_str(),
146 strMeeting.empty() ? "unknown" : strMeeting.c_str(),
147 fRecv, fSend);
148 }
149}
150
54// --- Socket accounting (implementation lives in sockcount.h) -------------- 151// --- Socket accounting (implementation lives in sockcount.h) --------------
55static const char* pszSockSite[SOCK_SITES] = { 152static const char* pszSockSite[SOCK_SITES] = {
56 "external-ip probe", "listen socket", "inbound accept", 153 "external-ip probe", "listen socket", "inbound accept",
@@ -199,19 +296,64 @@ string GetDiagnosticsText()
199 296
200 str += SockAccountingText(); 297 str += SockAccountingText();
201 298
202 str += "\n peer dir height last recv last send unsent\n"; 299 int64 nResolveAttempts, nResolveOk, nResolveMiss;
300 int64 nDialAttempts, nDialOk, nDialFailed;
301 int64 nRegisterOk, nRegisterFailed, nPairOk, nPairFailed;
302 int64 nHandshakeNoRecv, nHandshakeNoSend, nHandshakeSilent;
303 string strLastDialFail, strLastHandshakeTimeout;
304 CRITICAL_BLOCK(cs_btfChurn)
305 {
306 nResolveAttempts = nBtfResolveAttempts;
307 nResolveOk = nBtfResolveOk;
308 nResolveMiss = nBtfResolveMiss;
309 nDialAttempts = nBtfDialAttempts;
310 nDialOk = nBtfDialOk;
311 nDialFailed = nBtfDialFailed;
312 nRegisterOk = nBtfRegisterOk;
313 nRegisterFailed = nBtfRegisterFailed;
314 nPairOk = nBtfPairOk;
315 nPairFailed = nBtfPairFailed;
316 nHandshakeNoRecv = nBtfHandshakeNoRecv;
317 nHandshakeNoSend = nBtfHandshakeNoSend;
318 nHandshakeSilent = nBtfHandshakeSilent;
319 strLastDialFail = strBtfLastDialFail;
320 strLastHandshakeTimeout = strBtfLastHandshakeTimeout;
321 }
322 str += "\n .btf churn\n";
323 str += strprintf(" resolves %lld attempts, %lld ok, %lld no descriptor\n",
324 (long long)nResolveAttempts, (long long)nResolveOk,
325 (long long)nResolveMiss);
326 str += strprintf(" outbound dials %lld attempts, %lld ok, %lld failed\n",
327 (long long)nDialAttempts, (long long)nDialOk,
328 (long long)nDialFailed);
329 str += strprintf(" rendezvous local register ok/fail %lld/%lld, pair ok/drop %lld/%lld\n",
330 (long long)nRegisterOk, (long long)nRegisterFailed,
331 (long long)nPairOk, (long long)nPairFailed);
332 str += strprintf(" handshake grace silent %lld, no recv %lld, no send %lld\n",
333 (long long)nHandshakeSilent, (long long)nHandshakeNoRecv,
334 (long long)nHandshakeNoSend);
335 if (!strLastDialFail.empty())
336 str += strprintf(" last dial failure %s\n", strLastDialFail.c_str());
337 if (!strLastHandshakeTimeout.empty())
338 str += strprintf(" last handshake %s\n", strLastHandshakeTimeout.c_str());
339
340 str += "\n peer dir height last recv last send unsent via\n";
203 foreach(CNode* pnode, vCopy) 341 foreach(CNode* pnode, vCopy)
204 { 342 {
205 int nSendSize = 0; 343 int nSendSize = 0;
206 TRY_CRITICAL_BLOCK(pnode->cs_vSend) 344 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
207 nSendSize = (int)pnode->vSend.size(); 345 nSendSize = (int)pnode->vSend.size();
208 str += strprintf(" %-28s %-4s %6d %10s %10s %7d\n", 346 string strVia;
347 if (!pnode->strBtfMeeting.empty())
348 strVia = pnode->strBtfMeeting;
349 str += strprintf(" %-28s %-4s %6d %10s %10s %7d %s\n",
209 pnode->addr.ToString().substr(0, 28).c_str(), 350 pnode->addr.ToString().substr(0, 28).c_str(),
210 pnode->fInbound ? "in" : "out", 351 pnode->fInbound ? "in" : "out",
211 pnode->nStartingHeight, 352 pnode->nStartingHeight,
212 FormatAge(pnode->nLastRecv ? nNow - pnode->nLastRecv : -1).c_str(), 353 FormatAge(pnode->nLastRecv ? nNow - pnode->nLastRecv : -1).c_str(),
213 FormatAge(pnode->nLastSend ? nNow - pnode->nLastSend : -1).c_str(), 354 FormatAge(pnode->nLastSend ? nNow - pnode->nLastSend : -1).c_str(),
214 nSendSize); 355 nSendSize,
356 strVia.substr(0, 28).c_str());
215 } 357 }
216 return str; 358 return str;
217} 359}
@@ -814,30 +956,41 @@ static CNode* ConnectNodeBtfTail(const string& strBtfAddr, const unsigned char p
814 return pnode; 956 return pnode;
815 } 957 }
816 958
959 BtfChurnNoteDialAttempt(strBtfAddr, strMeeting);
817 size_t colon = strMeeting.rfind(':'); 960 size_t colon = strMeeting.rfind(':');
818 if (colon == string::npos) 961 if (colon == string::npos)
962 {
963 BtfChurnNoteDialResult(strBtfAddr, strMeeting, false);
819 return NULL; 964 return NULL;
965 }
820 string strHost = strMeeting.substr(0, colon); 966 string strHost = strMeeting.substr(0, colon);
821 int nPort = atoi(strMeeting.substr(colon + 1).c_str()); 967 int nPort = atoi(strMeeting.substr(colon + 1).c_str());
822 if (nPort <= 0 || nPort > 65535) 968 if (nPort <= 0 || nPort > 65535)
969 {
970 BtfChurnNoteDialResult(strBtfAddr, strMeeting, false);
823 return NULL; 971 return NULL;
972 }
824 973
825 btf_socket_t hSocket = btf::BtfClientTunnel(strHost.c_str(), (unsigned short)nPort, pk, enc_pub); 974 btf_socket_t hSocket = btf::BtfClientTunnel(strHost.c_str(), (unsigned short)nPort, pk, enc_pub);
826 if (hSocket == INVALID_SOCKET) 975 if (hSocket == INVALID_SOCKET)
827 { 976 {
828 if (fDebug) 977 if (fDebug)
829 LogPrint("net", "ConnectNodeBtf: tunnel to %s via %s failed\n", strBtfAddr.c_str(), strMeeting.c_str()); 978 LogPrint("net", "ConnectNodeBtf: tunnel to %s via %s failed\n", strBtfAddr.c_str(), strMeeting.c_str());
979 BtfChurnNoteDialResult(strBtfAddr, strMeeting, false);
830 return NULL; 980 return NULL;
831 } 981 }
832 982
833 if (fDebug) 983 if (fDebug)
834 LogPrint("net", "connected %s via rendezvous %s\n", strBtfAddr.c_str(), strMeeting.c_str()); 984 LogPrint("net", "connected %s via rendezvous %s\n", strBtfAddr.c_str(), strMeeting.c_str());
985 BtfChurnNoteDialResult(strBtfAddr, strMeeting, true);
835 986
836 // This one answered -- worth trying first next time we start. 987 // This one answered -- worth trying first next time we start.
837 RememberBtfPeer(strBtfAddr, strMeeting, enc_pub); 988 RememberBtfPeer(strBtfAddr, strMeeting, enc_pub);
838 989
839 // Add node 990 // Add node
840 pnode = new CNode(hSocket, addr, false); 991 pnode = new CNode(hSocket, addr, false);
992 pnode->strBtfAddr = strBtfAddr;
993 pnode->strBtfMeeting = strMeeting;
841 pnode->AddRef(); 994 pnode->AddRef();
842 CRITICAL_BLOCK(cs_vNodes) 995 CRITICAL_BLOCK(cs_vNodes)
843 vNodes.push_back(pnode); 996 vNodes.push_back(pnode);
@@ -863,12 +1016,15 @@ CNode* ConnectNodeBtf(const string& strBtfAddr)
863 1016
864 string strMeeting; 1017 string strMeeting;
865 unsigned char enc_pub[32]; 1018 unsigned char enc_pub[32];
1019 BtfChurnNoteResolveAttempt();
866 if (!BtfResolve(strBtfAddr, strMeeting, enc_pub)) 1020 if (!BtfResolve(strBtfAddr, strMeeting, enc_pub))
867 { 1021 {
1022 BtfChurnNoteResolveResult(false);
868 if (fDebug) 1023 if (fDebug)
869 LogPrint("net", "ConnectNodeBtf: could not resolve a descriptor for %s\n", strBtfAddr.c_str()); 1024 LogPrint("net", "ConnectNodeBtf: could not resolve a descriptor for %s\n", strBtfAddr.c_str());
870 return NULL; 1025 return NULL;
871 } 1026 }
1027 BtfChurnNoteResolveResult(true);
872 return ConnectNodeBtfTail(strBtfAddr, pk, strMeeting, enc_pub); 1028 return ConnectNodeBtfTail(strBtfAddr, pk, strMeeting, enc_pub);
873} 1029}
874 1030
@@ -951,12 +1107,14 @@ void ThreadBtfAccept(void* parg)
951 } 1107 }
952 if (rv == btf::RV_INVALID) 1108 if (rv == btf::RV_INVALID)
953 { 1109 {
1110 BtfChurnNoteRegisterResult(strMeeting, false);
954 LogPrint("net", "rendezvous: could not register at %s, trying another\n", 1111 LogPrint("net", "rendezvous: could not register at %s, trying another\n",
955 strMeeting.c_str()); 1112 strMeeting.c_str());
956 iRelay++; // this relay is down/attacked -> try the next one 1113 iRelay++; // this relay is down/attacked -> try the next one
957 Sleep(3000); 1114 Sleep(3000);
958 continue; 1115 continue;
959 } 1116 }
1117 BtfChurnNoteRegisterResult(strMeeting, true);
960 1118
961 // Registered. Advertise THIS relay now, while we are listed and before 1119 // Registered. Advertise THIS relay now, while we are listed and before
962 // anybody dials -- a descriptor naming it is what makes a dial possible 1120 // anybody dials -- a descriptor naming it is what makes a dial possible
@@ -971,7 +1129,9 @@ void ThreadBtfAccept(void* parg)
971 // here, the node stopped being reachable, and nothing in the log said 1129 // here, the node stopped being reachable, and nothing in the log said
972 // so. Re-registering every few minutes when nobody has dialled costs 1130 // so. Re-registering every few minutes when nobody has dialled costs
973 // one reconnect and removes the whole failure mode. 1131 // one reconnect and removes the whole failure mode.
974 if (!btf::RvServiceWaitPaired(rv, BTF_RENDEZVOUS_WAIT_SECS)) 1132 bool fPaired = btf::RvServiceWaitPaired(rv, BTF_RENDEZVOUS_WAIT_SECS);
1133 BtfChurnNotePairResult(strMeeting, fPaired);
1134 if (!fPaired)
975 { 1135 {
976 btf::RvClose(rv); 1136 btf::RvClose(rv);
977 LogPrint("net", "rendezvous: no dial at %s within %ds (or it dropped us), " 1137 LogPrint("net", "rendezvous: no dial at %s within %ds (or it dropped us), "
@@ -981,7 +1141,11 @@ void ThreadBtfAccept(void* parg)
981 1141
982 btf_socket_t hSocket = btf::BtfServiceWrap(rv, sk); 1142 btf_socket_t hSocket = btf::BtfServiceWrap(rv, sk);
983 if (hSocket == INVALID_SOCKET) 1143 if (hSocket == INVALID_SOCKET)
1144 {
1145 LogPrint("net", "rendezvous: paired at %s but channel setup failed\n",
1146 strMeeting.c_str());
984 continue; 1147 continue;
1148 }
985 1149
986 // The dialer is anonymous (its pubkey never reaches us), so tag the 1150 // The dialer is anonymous (its pubkey never reaches us), so tag the
987 // connection with a random marker address. 1151 // connection with a random marker address.
@@ -991,6 +1155,8 @@ void ThreadBtfAccept(void* parg)
991 1155
992 LogPrint("net", "accepted .btf connection via rendezvous %s\n", strMeeting.c_str()); 1156 LogPrint("net", "accepted .btf connection via rendezvous %s\n", strMeeting.c_str());
993 CNode* pnode = new CNode(hSocket, addr, true); 1157 CNode* pnode = new CNode(hSocket, addr, true);
1158 pnode->strBtfAddr = "inbound";
1159 pnode->strBtfMeeting = strMeeting;
994 pnode->AddRef(); 1160 pnode->AddRef();
995 CRITICAL_BLOCK(cs_vNodes) 1161 CRITICAL_BLOCK(cs_vNodes)
996 vNodes.push_back(pnode); 1162 vNodes.push_back(pnode);
@@ -1457,6 +1623,9 @@ void ThreadSocketHandler2(void* parg)
1457 { 1623 {
1458 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0) 1624 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
1459 { 1625 {
1626 if (!pnode->strBtfMeeting.empty())
1627 BtfChurnNoteHandshakeTimeout(pnode->strBtfAddr, pnode->strBtfMeeting,
1628 pnode->nLastRecv != 0, pnode->nLastSend != 0);
1460 LogPrint("net", "socket no message in first %d seconds, recv=%d send=%d\n", 1629 LogPrint("net", "socket no message in first %d seconds, recv=%d send=%d\n",
1461 BTF_HANDSHAKE_GRACE_SECS, pnode->nLastRecv != 0, pnode->nLastSend != 0); 1630 BTF_HANDSHAKE_GRACE_SECS, pnode->nLastRecv != 0, pnode->nLastSend != 0);
1462 pnode->fDisconnect = true; 1631 pnode->fDisconnect = true;
@@ -1803,9 +1972,22 @@ bool StartNode(string& strError)
1803 1972
1804 // Anonymous inbound: this node's .btf hidden service, reachable through the 1973 // Anonymous inbound: this node's .btf hidden service, reachable through the
1805 // meeting relay without exposing our IP or needing a public port. 1974 // meeting relay without exposing our IP or needing a public port.
1975 //
1976 // Several of these, not one. Each holds its own registration at a
1977 // rendezvous, and a registration is consumed the moment a caller is paired
1978 // with it -- so with a single thread the node is unreachable for the whole
1979 // gap between being paired and registering again. Measured from a node's
1980 // own counters: half of all outbound dials failed for exactly that reason,
1981 // 15 of 30 in eleven minutes, while descriptors resolved 53 times out of
1982 // 54. Spares parked at the relay close that gap.
1983 //
1984 // Needs a relay that keeps more than one registration per node; against an
1985 // older relay the extra threads are harmless, because it drops the previous
1986 // registration on each new one and the node ends up where it started.
1806 if (!vBtfMeetingRelays.empty()) 1987 if (!vBtfMeetingRelays.empty())
1807 if (_beginthread(ThreadBtfAccept, 0, NULL) == -1) 1988 for (int i = 0; i < BTF_ACCEPT_THREADS; i++)
1808 printf("Error: _beginthread(ThreadBtfAccept) failed\n"); 1989 if (_beginthread(ThreadBtfAccept, 0, NULL) == -1)
1990 printf("Error: _beginthread(ThreadBtfAccept) failed\n");
1809 1991
1810 // Anonymous outbound: keep a connection to a specific .btf peer, if asked. 1992 // Anonymous outbound: keep a connection to a specific .btf peer, if asked.
1811 if (!strBtfConnect.empty()) 1993 if (!strBtfConnect.empty())