// 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); } } }