diff options
Diffstat (limited to 'src/net.cpp')
| -rw-r--r-- | src/net.cpp | 194 |
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; | |||
| 51 | int64 nBlocksWithoutParent = 0; | 51 | int64 nBlocksWithoutParent = 0; |
| 52 | static int64 nNodeStartTime = 0; | 52 | static int64 nNodeStartTime = 0; |
| 53 | 53 | ||
| 54 | static CCriticalSection cs_btfChurn; | ||
| 55 | static int64 nBtfResolveAttempts = 0; | ||
| 56 | static int64 nBtfResolveOk = 0; | ||
| 57 | static int64 nBtfResolveMiss = 0; | ||
| 58 | static int64 nBtfDialAttempts = 0; | ||
| 59 | static int64 nBtfDialOk = 0; | ||
| 60 | static int64 nBtfDialFailed = 0; | ||
| 61 | static int64 nBtfRegisterOk = 0; | ||
| 62 | static int64 nBtfRegisterFailed = 0; | ||
| 63 | static int64 nBtfPairOk = 0; | ||
| 64 | static int64 nBtfPairFailed = 0; | ||
| 65 | static int64 nBtfHandshakeNoRecv = 0; | ||
| 66 | static int64 nBtfHandshakeNoSend = 0; | ||
| 67 | static int64 nBtfHandshakeSilent = 0; | ||
| 68 | static string strBtfLastDialFail; | ||
| 69 | static string strBtfLastHandshakeTimeout; | ||
| 70 | |||
| 71 | void BtfChurnNoteResolveAttempt() | ||
| 72 | { | ||
| 73 | CRITICAL_BLOCK(cs_btfChurn) | ||
| 74 | nBtfResolveAttempts++; | ||
| 75 | } | ||
| 76 | |||
| 77 | void BtfChurnNoteResolveResult(bool fOk) | ||
| 78 | { | ||
| 79 | CRITICAL_BLOCK(cs_btfChurn) | ||
| 80 | { | ||
| 81 | if (fOk) nBtfResolveOk++; | ||
| 82 | else nBtfResolveMiss++; | ||
| 83 | } | ||
| 84 | } | ||
| 85 | |||
| 86 | void 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 | |||
| 94 | void 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 | |||
| 110 | void 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 | |||
| 121 | void 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 | |||
| 132 | void 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) -------------- |
| 55 | static const char* pszSockSite[SOCK_SITES] = { | 152 | static 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()) |