/* * Send a ping packet to one of the endpoints. */ static void sendPing(struct InterfaceController_Peer* ep) { struct InterfaceController_pvt* ic = ifcontrollerForPeer(ep); ep->pingCount++; struct SwitchPinger_Ping* ping = SwitchPinger_newPing(ep->switchLabel, String_CONST(""), ic->timeoutMilliseconds, onPingResponse, ic->allocator, ic->switchPinger); #ifdef Log_DEBUG uint8_t key[56]; Base32_encode(key, 56, CryptoAuth_getHerPublicKey(ep->cryptoAuthIf), 32); #endif if (!ping) { Log_debug(ic->logger, "Failed to ping [%s.k], out of ping slots", key); return; } else { Log_debug(ic->logger, "SwitchPing [%s.k]", key); } ping->onResponseContext = ep; }
/* * Send a ping packet to one of the endpoints. */ static void sendPing(struct Peer* ep) { struct InterfaceController_pvt* ic = Identity_check(ep->ici->ic); ep->pingCount++; struct SwitchPinger_Ping* ping = SwitchPinger_newPing(ep->addr.path, String_CONST(""), ic->timeoutMilliseconds, onPingResponse, ep->alloc, ic->switchPinger); if (Defined(Log_DEBUG)) { uint8_t key[56]; Base32_encode(key, 56, ep->caSession->herPublicKey, 32); if (!ping) { Log_debug(ic->logger, "Failed to ping [%s.k], out of ping slots", key); } else { Log_debug(ic->logger, "SwitchPing [%s.k]", key); } } if (ping) { ping->onResponseContext = ep; } }
static void adminPing(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc) { struct Context* context = vcontext; String* pathStr = Dict_getString(args, String_CONST("path")); int64_t* timeoutPtr = Dict_getInt(args, String_CONST("timeout")); String* data = Dict_getString(args, String_CONST("data")); int64_t* keyPing = Dict_getInt(args, String_CONST("keyPing")); uint32_t timeout = (timeoutPtr) ? *timeoutPtr : DEFAULT_TIMEOUT; uint64_t path; String* err = NULL; if (pathStr->len != 19 || AddrTools_parsePath(&path, (uint8_t*) pathStr->bytes)) { err = String_CONST("path was not parsable."); } else { struct SwitchPinger_Ping* ping = SwitchPinger_newPing(path, data, timeout, adminPingOnResponse, context->alloc, context->switchPinger); if (keyPing && *keyPing) { ping->keyPing = true; } if (!ping) { err = String_CONST("no open slots to store ping, try later."); } else { ping->onResponseContext = Allocator_clone(ping->pingAlloc, (&(struct Ping) { .context = context, .txid = String_clone(txid, ping->pingAlloc), .path = String_clone(pathStr, ping->pingAlloc) })); } }
// Called from the pingInteral timeout. static void pingCallback(void* vic) { struct Context* ic = Identity_cast((struct Context*) vic); uint64_t now = Time_currentTimeMilliseconds(ic->eventBase); ic->pingCount++; // scan for endpoints have not sent anything recently. for (uint32_t i = 0; i < ic->peerMap.count; i++) { struct IFCPeer* ep = ic->peerMap.values[i]; if (now > ep->timeOfLastMessage + ic->pingAfterMilliseconds) { #ifdef Log_DEBUG uint8_t key[56]; Base32_encode(key, 56, CryptoAuth_getHerPublicKey(ep->cryptoAuthIf), 32); #endif if (ep->transient && now > ep->timeOfLastMessage + ic->forgetAfterMilliseconds) { Log_debug(ic->logger, "Unresponsive peer [%s.k] has not responded in [%u] " "seconds, dropping connection", key, ic->forgetAfterMilliseconds / 1024); Allocator_free(ep->external->allocator); } else if (now > ep->timeOfLastMessage + ic->unresponsiveAfterMilliseconds) { // Lets skip 87% of pings when they're really down. if (ic->pingCount % 8) { continue; } ep->state = InterfaceController_PeerState_UNRESPONSIVE; uint32_t lag = ((now - ep->timeOfLastMessage) / 1024); Log_debug(ic->logger, "Pinging unresponsive peer [%s.k] lag [%u]", key, lag); } else { uint32_t lag = ((now - ep->timeOfLastMessage) / 1024); Log_debug(ic->logger, "Pinging lazy peer [%s] lag [%u]", key, lag); } struct SwitchPinger_Ping* ping = SwitchPinger_newPing(ep->switchLabel, String_CONST(""), ic->timeoutMilliseconds, onPingResponse, ic->switchPinger); ping->onResponseContext = ep; SwitchPinger_sendPing(ping); } } }
// Called from the pingInteral timeout. static void pingCallback(void* vic) { struct Context* ic = Identity_cast((struct Context*) vic); uint64_t now = Time_currentTimeMilliseconds(ic->eventBase); ic->pingCount++; // scan for endpoints have not sent anything recently. for (uint32_t i = 0; i < ic->peerMap.count; i++) { struct IFCPeer* ep = ic->peerMap.values[i]; // This is here because of a pathological state where the connection is in ESTABLISHED // state but the *direct peer* has somehow been dropped from the routing table. // TODO: understand the cause of this issue rather than checking for it once per second. struct Node* peerNode = RouterModule_getNode(ep->switchLabel, ic->routerModule); if (now > ep->timeOfLastMessage + ic->pingAfterMilliseconds || !peerNode) { #ifdef Log_DEBUG uint8_t key[56]; Base32_encode(key, 56, CryptoAuth_getHerPublicKey(ep->cryptoAuthIf), 32); #endif if (ep->isIncomingConnection && now > ep->timeOfLastMessage + ic->forgetAfterMilliseconds) { Log_debug(ic->logger, "Unresponsive peer [%s.k] has not responded in [%u] " "seconds, dropping connection", key, ic->forgetAfterMilliseconds / 1024); Allocator_free(ep->external->allocator); return; } bool unresponsive = (now > ep->timeOfLastMessage + ic->unresponsiveAfterMilliseconds); uint32_t lag = ~0u; if (unresponsive) { // flush the peer from the table... RouterModule_brokenPath(ep->switchLabel, ic->routerModule); // Lets skip 87% of pings when they're really down. if (ic->pingCount % 8) { continue; } ep->state = InterfaceController_PeerState_UNRESPONSIVE; lag = ((now - ep->timeOfLastMessage) / 1024); } else { lag = ((now - ep->timeOfLastMessage) / 1024); } struct SwitchPinger_Ping* ping = SwitchPinger_newPing(ep->switchLabel, String_CONST(""), ic->timeoutMilliseconds, onPingResponse, ic->allocator, ic->switchPinger); if (!ping) { Log_debug(ic->logger, "Failed to ping %s peer [%s.k] lag [%u], out of ping slots.", (unresponsive ? "unresponsive" : "lazy"), key, lag); return; } ping->onResponseContext = ep; SwitchPinger_sendPing(ping); Log_debug(ic->logger, "Pinging %s peer [%s.k] lag [%u]", (unresponsive ? "unresponsive" : "lazy"), key, lag); } } }