keep network from going down when external ip addresses haven't changed

This commit is contained in:
Christien Rioux 2023-10-11 23:12:54 -04:00
parent 084d4ae98b
commit 54c403ebfb
3 changed files with 80 additions and 7 deletions
veilid-core/src/network_manager/native

View File

@ -39,8 +39,11 @@ struct DiscoveryContextInner {
struct DiscoveryContextUnlockedInner {
routing_table: RoutingTable,
net: Network,
clear_network_callback: ClearNetworkCallback,
// per-protocol
intf_addrs: Vec<SocketAddress>,
existing_external_address: Option<SocketAddress>,
protocol_type: ProtocolType,
address_type: AddressType,
}
@ -51,21 +54,45 @@ pub struct DiscoveryContext {
inner: Arc<Mutex<DiscoveryContextInner>>,
}
pub type ClearNetworkCallback = Arc<dyn Fn() -> SendPinBoxFuture<()> + Send + Sync>;
impl DiscoveryContext {
pub fn new(
routing_table: RoutingTable,
net: Network,
protocol_type: ProtocolType,
address_type: AddressType,
clear_network_callback: ClearNetworkCallback,
) -> Self {
let intf_addrs =
Self::get_local_addresses(routing_table.clone(), protocol_type, address_type);
// Get the existing external address to check to see if it has changed
let existing_dial_info = routing_table.all_filtered_dial_info_details(
RoutingDomain::PublicInternet.into(),
&DialInfoFilter::default()
.with_address_type(address_type)
.with_protocol_type(protocol_type),
);
let existing_external_address = if existing_dial_info.len() == 1 {
Some(
existing_dial_info
.first()
.unwrap()
.dial_info
.socket_address(),
)
} else {
None
};
Self {
unlocked_inner: Arc::new(DiscoveryContextUnlockedInner {
routing_table,
net,
clear_network_callback,
intf_addrs,
existing_external_address,
protocol_type,
address_type,
}),
@ -631,6 +658,22 @@ impl DiscoveryContext {
return;
}
// Did external addresses change from the last time we made dialinfo?
let some_clear_network_callback = {
let inner = self.inner.lock();
let ext_1 = inner.external_1.as_ref().unwrap().address;
let ext_2 = inner.external_2.as_ref().unwrap().address;
if (ext_1 != ext_2) || Some(ext_1) != self.unlocked_inner.existing_external_address {
// External address was not found, or has changed, go ahead and clear the network so we can do better
Some(self.unlocked_inner.clear_network_callback.clone())
} else {
None
}
};
if let Some(clear_network_callback) = some_clear_network_callback {
clear_network_callback().await;
}
// UPNP Automatic Mapping
///////////
if enable_upnp {

View File

@ -99,6 +99,8 @@ struct NetworkInner {
enable_ipv6_local: bool,
/// set if we need to calculate our public dial info again
needs_public_dial_info_check: bool,
/// set if we have yet to clear the network during public dial info checking
network_already_cleared: bool,
/// the punishment closure to enax
public_dial_info_check_punishment: Option<Box<dyn FnOnce() + Send + 'static>>,
/// udp socket record for bound-first sockets, which are used to guarantee a port is available before
@ -148,6 +150,7 @@ impl Network {
network_started: false,
network_needs_restart: false,
needs_public_dial_info_check: false,
network_already_cleared: false,
public_dial_info_check_punishment: None,
protocol_config: Default::default(),
static_public_dialinfo: ProtocolTypeSet::empty(),

View File

@ -22,7 +22,6 @@ impl Network {
editor.clear_dial_info_details(None, None);
editor.set_network_class(Some(NetworkClass::OutboundOnly));
editor.clear_relay_node();
editor.commit(true).await;
}
}
@ -103,7 +102,7 @@ impl Network {
) -> EyreResult<()> {
// Figure out if we can optimize TCP/WS checking since they are often on the same port
let (protocol_config, tcp_same_port) = {
let inner = self.inner.lock();
let mut inner = self.inner.lock();
let protocol_config = inner.protocol_config.clone();
let tcp_same_port = if protocol_config.inbound.contains(ProtocolType::TCP)
&& protocol_config.inbound.contains(ProtocolType::WS)
@ -112,6 +111,10 @@ impl Network {
} else {
false
};
// Allow network to be cleared if external addresses change
inner.network_already_cleared = false;
//
(protocol_config, tcp_same_port)
};
@ -125,8 +128,7 @@ impl Network {
.into_iter()
.collect();
// Clear public dialinfo and network class in prep for discovery
// Set most permissive network config
let mut editor = self
.routing_table()
.edit_routing_domain(RoutingDomain::PublicInternet);
@ -136,11 +138,30 @@ impl Network {
protocol_config.family_global,
protocol_config.public_internet_capabilities.clone(),
);
editor.clear_dial_info_details(None, None);
editor.set_network_class(None);
editor.clear_relay_node();
editor.commit(true).await;
// Create a callback to clear the network if we need to 'start over'
let this = self.clone();
let clear_network_callback: ClearNetworkCallback = Arc::new(move || {
let this = this.clone();
Box::pin(async move {
// Ensure we only do this once per network class discovery
{
let mut inner = this.inner.lock();
if inner.network_already_cleared {
return;
}
inner.network_already_cleared = true;
}
let mut editor = this
.routing_table()
.edit_routing_domain(RoutingDomain::PublicInternet);
editor.clear_dial_info_details(None, None);
editor.set_network_class(None);
editor.commit(true).await;
})
});
// Process all protocol and address combinations
let mut unord = FuturesUnordered::new();
// Do UDPv4+v6 at the same time as everything else
@ -152,6 +173,7 @@ impl Network {
self.clone(),
ProtocolType::UDP,
AddressType::IPV4,
clear_network_callback.clone(),
);
udpv4_context
.discover(&mut unord)
@ -166,6 +188,7 @@ impl Network {
self.clone(),
ProtocolType::UDP,
AddressType::IPV6,
clear_network_callback.clone(),
);
udpv6_context
.discover(&mut unord)
@ -182,6 +205,7 @@ impl Network {
self.clone(),
ProtocolType::TCP,
AddressType::IPV4,
clear_network_callback.clone(),
);
tcpv4_context
.discover(&mut unord)
@ -195,6 +219,7 @@ impl Network {
self.clone(),
ProtocolType::WS,
AddressType::IPV4,
clear_network_callback.clone(),
);
wsv4_context
.discover(&mut unord)
@ -211,6 +236,7 @@ impl Network {
self.clone(),
ProtocolType::TCP,
AddressType::IPV6,
clear_network_callback.clone(),
);
tcpv6_context
.discover(&mut unord)
@ -225,6 +251,7 @@ impl Network {
self.clone(),
ProtocolType::WS,
AddressType::IPV6,
clear_network_callback.clone(),
);
wsv6_context
.discover(&mut unord)