diff --git a/veilid-core/src/network_manager/mod.rs b/veilid-core/src/network_manager/mod.rs index 8cfa4f7d..4f370784 100644 --- a/veilid-core/src/network_manager/mod.rs +++ b/veilid-core/src/network_manager/mod.rs @@ -964,12 +964,17 @@ impl NetworkManager { Some(RoutingDomain::PublicInternet), &reverse_dif, ) { - // Can we receive a direct reverse connection? - if !reverse_did.class.requires_signal() { - return ContactMethod::SignalReverse( - inbound_relay_nr, - target_node_ref, - ); + // Ensure we aren't on the same public IP address (no hairpin nat) + if reverse_did.dial_info.to_ip_addr() + != target_public_did.dial_info.to_ip_addr() + { + // Can we receive a direct reverse connection? + if !reverse_did.class.requires_signal() { + return ContactMethod::SignalReverse( + inbound_relay_nr, + target_node_ref, + ); + } } } @@ -979,27 +984,33 @@ impl NetworkManager { let udp_target_nr = target_node_ref.filtered_clone( DialInfoFilter::global().with_protocol_type(ProtocolType::UDP), ); - let target_has_udp_dialinfo = udp_target_nr + if let Some(target_udp_dialinfo_detail) = udp_target_nr .first_filtered_dial_info_detail(Some(RoutingDomain::PublicInternet)) - .is_some(); - - // Does the self node have a direct udp dialinfo the target can reach? - let inbound_udp_dif = self - .get_inbound_dial_info_filter(RoutingDomain::PublicInternet) - .filtered(target_node_ref.node_info_outbound_filter()) - .filtered( - DialInfoFilter::global().with_protocol_type(ProtocolType::UDP), - ); - let self_has_udp_dialinfo = routing_table - .first_filtered_dial_info_detail( - Some(RoutingDomain::PublicInternet), - &inbound_udp_dif, - ) - .is_some(); - - // Does the target and ourselves have a udp dialinfo that they can reach? - if target_has_udp_dialinfo && self_has_udp_dialinfo { - return ContactMethod::SignalHolePunch(inbound_relay_nr, udp_target_nr); + { + // Does the self node have a direct udp dialinfo the target can reach? + let inbound_udp_dif = self + .get_inbound_dial_info_filter(RoutingDomain::PublicInternet) + .filtered(target_node_ref.node_info_outbound_filter()) + .filtered( + DialInfoFilter::global().with_protocol_type(ProtocolType::UDP), + ); + if let Some(self_udp_dialinfo_detail) = routing_table + .first_filtered_dial_info_detail( + Some(RoutingDomain::PublicInternet), + &inbound_udp_dif, + ) + { + // Ensure we aren't on the same public IP address (no hairpin nat) + if target_udp_dialinfo_detail.dial_info.to_ip_addr() + != self_udp_dialinfo_detail.dial_info.to_ip_addr() + { + // The target and ourselves have a udp dialinfo that they can reach + return ContactMethod::SignalHolePunch( + inbound_relay_nr, + udp_target_nr, + ); + } + } } // Otherwise we have to inbound relay } diff --git a/veilid-core/src/routing_table/bucket_entry.rs b/veilid-core/src/routing_table/bucket_entry.rs index 0b469e46..dd9742da 100644 --- a/veilid-core/src/routing_table/bucket_entry.rs +++ b/veilid-core/src/routing_table/bucket_entry.rs @@ -108,14 +108,15 @@ impl BucketEntryInner { move |e1, e2| Self::cmp_fastest_reliable(cur_ts, e1, e2) } - pub fn update_node_info(&mut self, signed_node_info: SignedNodeInfo) { + // Retuns true if the node info changed + pub fn update_node_info(&mut self, signed_node_info: SignedNodeInfo) -> bool { // Don't update with older node info, or something less valid if let Some(current_sni) = &self.opt_signed_node_info { if current_sni.signature.valid && !signed_node_info.signature.valid { - return; + return false; } if signed_node_info.timestamp < current_sni.timestamp { - return; + return false; } } self.min_max_version = Some(( @@ -123,6 +124,8 @@ impl BucketEntryInner { signed_node_info.node_info.max_version, )); self.opt_signed_node_info = Some(signed_node_info); + + true } pub fn update_local_node_info(&mut self, local_node_info: LocalNodeInfo) { self.opt_local_node_info = Some(local_node_info) diff --git a/veilid-core/src/routing_table/mod.rs b/veilid-core/src/routing_table/mod.rs index d451e4f1..1426c930 100644 --- a/veilid-core/src/routing_table/mod.rs +++ b/veilid-core/src/routing_table/mod.rs @@ -581,7 +581,10 @@ impl RoutingTable { } self.create_node_ref(node_id, |e| { - e.update_node_info(signed_node_info); + if e.update_node_info(signed_node_info) { + // at least someone thought this node was live and its node info changed so lets try to contact it + e.touch_last_seen(intf::get_timestamp()); + } }) } @@ -596,6 +599,9 @@ impl RoutingTable { self.create_node_ref(node_id, |e| { // set the most recent node address for connection finding and udp replies e.set_last_connection(descriptor, timestamp); + + // this node is live because it literally just connected to us + e.touch_last_seen(timestamp); }) } diff --git a/veilid-server/src/settings.rs b/veilid-server/src/settings.rs index 2183815a..fad0abfd 100644 --- a/veilid-server/src/settings.rs +++ b/veilid-server/src/settings.rs @@ -93,7 +93,7 @@ core: set_value_timeout: set_value_count: 20 set_value_fanout: 5 - min_peer_count: 20 + min_peer_count: 2 # 20 min_peer_refresh_time_ms: 2000 validate_dial_info_receipt_time_ms: 2000 upnp: false