mirror of
https://github.com/jmcorgan/fips.git
synced 2026-08-09 08:14:42 +00:00
Fix transit node coord_cache expiry breaking multi-hop routing
Transit nodes cache destination coordinates when they forward SessionSetup messages (via try_warm_coord_cache). These coord_cache entries have a 5-minute TTL, after which they expire. Once expired, the transit node can no longer forward data packets for that destination — find_next_hop returns None and the node sends CoordsRequired errors back to the source. This creates a permanent routing failure for any multi-hop path after 5 minutes of the initial session establishment, even if traffic is actively flowing. The root cause was that find_next_hop used coord_cache.get(), a read-only lookup that checks expiry but never extends it. Active forwarding did not keep the cache warm. Meanwhile, get_and_touch() existed but only updated last_used without extending expires_at. Fix: - find_next_hop now calls coord_cache.get_and_touch() instead of get() - get_and_touch now calls entry.refresh() instead of entry.touch(), which extends expires_at by the default TTL on each access - find_next_hop signature changed from &self to &mut self to allow the mutable cache access This ensures that as long as traffic flows through a transit node, the coord_cache entries stay warm and routing continues to work. Entries still expire after 5 minutes of inactivity as designed.
This commit is contained in:
+5
-5
@@ -896,7 +896,7 @@ impl Node {
|
||||
/// fallback). Without coordinates, the node cannot make loop-free
|
||||
/// forwarding decisions. The caller should signal `CoordsRequired` back
|
||||
/// to the source when `None` is returned for a non-local destination.
|
||||
pub fn find_next_hop(&self, dest_node_addr: &NodeAddr) -> Option<&ActivePeer> {
|
||||
pub fn find_next_hop(&mut self, dest_node_addr: &NodeAddr) -> Option<&ActivePeer> {
|
||||
// 1. Local delivery
|
||||
if dest_node_addr == self.node_addr() {
|
||||
return None;
|
||||
@@ -915,17 +915,17 @@ impl Node {
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.map(|d| d.as_millis() as u64)
|
||||
.unwrap_or(0);
|
||||
let dest_coords = self.coord_cache.get(dest_node_addr, now_ms)
|
||||
.or_else(|| self.route_cache.get(dest_node_addr).map(|c| c.coords()))?;
|
||||
let dest_coords = self.coord_cache.get_and_touch(dest_node_addr, now_ms)
|
||||
.or_else(|| self.route_cache.get(dest_node_addr).map(|c| c.coords()))?.clone();
|
||||
|
||||
// 3. Bloom filter candidates — requires dest_coords for loop-free selection
|
||||
let candidates: Vec<&ActivePeer> = self.destination_in_filters(dest_node_addr);
|
||||
if !candidates.is_empty() {
|
||||
return self.select_best_candidate(&candidates, dest_coords);
|
||||
return self.select_best_candidate(&candidates, &dest_coords);
|
||||
}
|
||||
|
||||
// 4. Greedy tree routing fallback
|
||||
let next_hop_id = self.tree_state.find_next_hop(dest_coords)?;
|
||||
let next_hop_id = self.tree_state.find_next_hop(&dest_coords)?;
|
||||
|
||||
self.peers.get(&next_hop_id).filter(|p| p.can_send())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user