add StartupDisposition to handle waiting for binding without reporting errors

This commit is contained in:
Christien Rioux 2024-07-08 18:26:26 -04:00
parent 8c297acdee
commit 1048fc6bb9
8 changed files with 441 additions and 350 deletions

View File

@ -219,46 +219,61 @@ impl AttachmentManager {
let netman = self.network_manager(); let netman = self.network_manager();
let mut restart; let mut restart;
loop { let mut restart_delay;
while self.inner.lock().maintain_peers {
restart = false; restart = false;
if let Err(err) = netman.startup().await { restart_delay = 1;
error!("network startup failed: {}", err);
netman.shutdown().await; match netman.startup().await {
restart = true; Err(err) => {
} else { error!("network startup failed: {}", err);
log_net!(debug "started maintaining peers"); restart = true;
while self.inner.lock().maintain_peers { }
// tick network manager Ok(StartupDisposition::BindRetry) => {
if let Err(err) = netman.tick().await { info!("waiting for network to bind...");
error!("Error in network manager: {}", err); restart = true;
self.inner.lock().maintain_peers = false; restart_delay = 10;
restart = true; }
break; Ok(StartupDisposition::Success) => {
log_net!(debug "started maintaining peers");
while self.inner.lock().maintain_peers {
// tick network manager
let next_tick_ts = get_timestamp() + 1_000_000u64;
if let Err(err) = netman.tick().await {
error!("Error in network manager: {}", err);
self.inner.lock().maintain_peers = false;
restart = true;
break;
}
// see if we need to restart the network
if netman.network_needs_restart() {
info!("Restarting network");
restart = true;
break;
}
// Update attachment and network readiness state
// and possibly send a VeilidUpdate::Attachment
self.update_attachment();
// sleep should be at the end in case maintain_peers changes state
let wait_duration = next_tick_ts
.saturating_sub(get_timestamp())
.clamp(0, 1_000_000u64);
sleep((wait_duration / 1_000) as u32).await;
}
log_net!(debug "stopped maintaining peers");
if !restart {
self.update_attaching_detaching_state(AttachmentState::Detaching);
log_net!(debug "attachment stopping");
} }
// see if we need to restart the network log_net!(debug "stopping network");
if netman.network_needs_restart() { netman.shutdown().await;
info!("Restarting network");
restart = true;
break;
}
// Update attachment and network readiness state
// and possibly send a VeilidUpdate::Attachment
self.update_attachment();
// sleep should be at the end in case maintain_peers changes state
sleep(1000).await;
} }
log_net!(debug "stopped maintaining peers");
if !restart {
self.update_attaching_detaching_state(AttachmentState::Detaching);
log_net!(debug "attachment stopping");
}
log_net!(debug "stopping network");
netman.shutdown().await;
} }
if !restart { if !restart {
@ -266,8 +281,14 @@ impl AttachmentManager {
} }
log_net!(debug "completely restarting attachment"); log_net!(debug "completely restarting attachment");
// chill out for a second first, give network stack time to settle out // chill out for a second first, give network stack time to settle out
sleep(1000).await; for _ in 0..restart_delay {
if !self.inner.lock().maintain_peers {
break;
}
sleep(1000).await;
}
} }
self.update_attaching_detaching_state(AttachmentState::Detached); self.update_attaching_detaching_state(AttachmentState::Detached);

View File

@ -136,6 +136,12 @@ enum SendDataToExistingFlowResult {
NotSent(Vec<u8>), NotSent(Vec<u8>),
} }
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum StartupDisposition {
Success,
BindRetry,
}
// The mutable state of the network manager // The mutable state of the network manager
struct NetworkManagerInner { struct NetworkManagerInner {
stats: NetworkManagerStats, stats: NetworkManagerStats,
@ -388,10 +394,10 @@ impl NetworkManager {
} }
#[instrument(level = "debug", skip_all, err)] #[instrument(level = "debug", skip_all, err)]
pub async fn internal_startup(&self) -> EyreResult<()> { pub async fn internal_startup(&self) -> EyreResult<StartupDisposition> {
if self.unlocked_inner.components.read().is_some() { if self.unlocked_inner.components.read().is_some() {
log_net!(debug "NetworkManager::internal_startup already started"); log_net!(debug "NetworkManager::internal_startup already started");
return Ok(()); return Ok(StartupDisposition::Success);
} }
// Clean address filter for things that should not be persistent // Clean address filter for things that should not be persistent
@ -423,26 +429,37 @@ impl NetworkManager {
// Start network components // Start network components
connection_manager.startup().await; connection_manager.startup().await;
net.startup().await?; match net.startup().await? {
StartupDisposition::Success => {}
StartupDisposition::BindRetry => {
return Ok(StartupDisposition::BindRetry);
}
}
rpc_processor.startup().await?; rpc_processor.startup().await?;
receipt_manager.startup().await?; receipt_manager.startup().await?;
log_net!("NetworkManager::internal_startup end"); log_net!("NetworkManager::internal_startup end");
Ok(()) Ok(StartupDisposition::Success)
} }
#[instrument(level = "debug", skip_all, err)] #[instrument(level = "debug", skip_all, err)]
pub async fn startup(&self) -> EyreResult<()> { pub async fn startup(&self) -> EyreResult<StartupDisposition> {
if let Err(e) = self.internal_startup().await { match self.internal_startup().await {
self.shutdown().await; Ok(StartupDisposition::Success) => {
return Err(e); // Inform api clients that things have changed
self.send_network_update();
Ok(StartupDisposition::Success)
}
Ok(StartupDisposition::BindRetry) => {
self.shutdown().await;
Ok(StartupDisposition::BindRetry)
}
Err(e) => {
self.shutdown().await;
Err(e)
}
} }
// Inform api clients that things have changed
self.send_network_update();
Ok(())
} }
#[instrument(level = "debug", skip_all)] #[instrument(level = "debug", skip_all)]

View File

@ -709,216 +709,238 @@ impl Network {
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
#[instrument(level = "debug", err, skip_all)] pub async fn startup_internal(&self) -> EyreResult<StartupDisposition> {
pub async fn startup(&self) -> EyreResult<()> { // initialize interfaces
self.inner.lock().network_started = None; self.unlocked_inner.interfaces.refresh().await?;
let startup_func = async {
// initialize interfaces
self.unlocked_inner.interfaces.refresh().await?;
// build the set of networks we should consider for the 'LocalNetwork' routing domain // build the set of networks we should consider for the 'LocalNetwork' routing domain
let mut local_networks: HashSet<(IpAddr, IpAddr)> = HashSet::new(); let mut local_networks: HashSet<(IpAddr, IpAddr)> = HashSet::new();
self.unlocked_inner self.unlocked_inner
.interfaces .interfaces
.with_interfaces(|interfaces| { .with_interfaces(|interfaces| {
log_net!(debug "interfaces: {:#?}", interfaces); log_net!(debug "interfaces: {:#?}", interfaces);
for intf in interfaces.values() { for intf in interfaces.values() {
// Skip networks that we should never encounter // Skip networks that we should never encounter
if intf.is_loopback() || !intf.is_running() { if intf.is_loopback() || !intf.is_running() {
continue; continue;
}
// Add network to local networks table
for addr in &intf.addrs {
let netmask = addr.if_addr().netmask();
let network_ip = ipaddr_apply_netmask(addr.if_addr().ip(), netmask);
local_networks.insert((network_ip, netmask));
}
} }
}); // Add network to local networks table
let local_networks: Vec<(IpAddr, IpAddr)> = local_networks.into_iter().collect(); for addr in &intf.addrs {
self.unlocked_inner let netmask = addr.if_addr().netmask();
.routing_table let network_ip = ipaddr_apply_netmask(addr.if_addr().ip(), netmask);
.configure_local_network_routing_domain(local_networks); local_networks.insert((network_ip, netmask));
// determine if we have ipv4/ipv6 addresses
{
let mut inner = self.inner.lock();
let stable_interface_addresses = self.get_stable_interface_addresses();
inner.enable_ipv4 = false;
for addr in stable_interface_addresses.iter().copied() {
if addr.is_ipv4() {
log_net!(debug "enable address {:?} as ipv4", addr);
inner.enable_ipv4 = true;
} else if addr.is_ipv6() {
let address = Address::from_ip_addr(addr);
if address.is_global() {
log_net!(debug "enable address {:?} as ipv6 global", address);
inner.enable_ipv6_global = true;
} else if address.is_local() {
log_net!(debug "enable address {:?} as ipv6 local", address);
inner.enable_ipv6_local = true;
}
} }
} }
inner.stable_interface_addresses_at_startup = stable_interface_addresses; });
} let local_networks: Vec<(IpAddr, IpAddr)> = local_networks.into_iter().collect();
self.unlocked_inner
.routing_table
.configure_local_network_routing_domain(local_networks);
// Build our protocol config to share it with other nodes // determine if we have ipv4/ipv6 addresses
let protocol_config = { {
let mut inner = self.inner.lock(); let mut inner = self.inner.lock();
// Create stop source let stable_interface_addresses = self.get_stable_interface_addresses();
inner.stop_source = Some(StopSource::new());
// get protocol config inner.enable_ipv4 = false;
let protocol_config = { for addr in stable_interface_addresses.iter().copied() {
let c = self.config.get(); if addr.is_ipv4() {
let mut inbound = ProtocolTypeSet::new(); log_net!(debug "enable address {:?} as ipv4", addr);
inner.enable_ipv4 = true;
if c.network.protocol.udp.enabled { } else if addr.is_ipv6() {
inbound.insert(ProtocolType::UDP); let address = Address::from_ip_addr(addr);
if address.is_global() {
log_net!(debug "enable address {:?} as ipv6 global", address);
inner.enable_ipv6_global = true;
} else if address.is_local() {
log_net!(debug "enable address {:?} as ipv6 local", address);
inner.enable_ipv6_local = true;
} }
if c.network.protocol.tcp.listen {
inbound.insert(ProtocolType::TCP);
}
if c.network.protocol.ws.listen {
inbound.insert(ProtocolType::WS);
}
if c.network.protocol.wss.listen {
inbound.insert(ProtocolType::WSS);
}
let mut outbound = ProtocolTypeSet::new();
if c.network.protocol.udp.enabled {
outbound.insert(ProtocolType::UDP);
}
if c.network.protocol.tcp.connect {
outbound.insert(ProtocolType::TCP);
}
if c.network.protocol.ws.connect {
outbound.insert(ProtocolType::WS);
}
if c.network.protocol.wss.connect {
outbound.insert(ProtocolType::WSS);
}
let mut family_global = AddressTypeSet::new();
let mut family_local = AddressTypeSet::new();
if inner.enable_ipv4 {
family_global.insert(AddressType::IPV4);
family_local.insert(AddressType::IPV4);
}
if inner.enable_ipv6_global {
family_global.insert(AddressType::IPV6);
}
if inner.enable_ipv6_local {
family_local.insert(AddressType::IPV6);
}
// set up the routing table's network config
// if we have static public dialinfo, upgrade our network class
let public_internet_capabilities = {
PUBLIC_INTERNET_CAPABILITIES
.iter()
.copied()
.filter(|cap| !c.capabilities.disable.contains(cap))
.collect::<Vec<Capability>>()
};
let local_network_capabilities = {
LOCAL_NETWORK_CAPABILITIES
.iter()
.copied()
.filter(|cap| !c.capabilities.disable.contains(cap))
.collect::<Vec<Capability>>()
};
ProtocolConfig {
outbound,
inbound,
family_global,
family_local,
public_internet_capabilities,
local_network_capabilities,
}
};
inner.protocol_config = protocol_config.clone();
protocol_config
};
// Start editing routing table
let mut editor_public_internet = self
.unlocked_inner
.routing_table
.edit_routing_domain(RoutingDomain::PublicInternet);
let mut editor_local_network = self
.unlocked_inner
.routing_table
.edit_routing_domain(RoutingDomain::LocalNetwork);
// start listeners
if protocol_config.inbound.contains(ProtocolType::UDP) {
self.bind_udp_protocol_handlers(
&mut editor_public_internet,
&mut editor_local_network,
)
.await?;
}
if protocol_config.inbound.contains(ProtocolType::WS) {
self.start_ws_listeners(&mut editor_public_internet, &mut editor_local_network)
.await?;
}
if protocol_config.inbound.contains(ProtocolType::WSS) {
self.start_wss_listeners(&mut editor_public_internet, &mut editor_local_network)
.await?;
}
if protocol_config.inbound.contains(ProtocolType::TCP) {
self.start_tcp_listeners(&mut editor_public_internet, &mut editor_local_network)
.await?;
}
editor_public_internet.setup_network(
protocol_config.outbound,
protocol_config.inbound,
protocol_config.family_global,
protocol_config.public_internet_capabilities,
);
editor_local_network.setup_network(
protocol_config.outbound,
protocol_config.inbound,
protocol_config.family_local,
protocol_config.local_network_capabilities,
);
let detect_address_changes = {
let c = self.config.get();
c.network.detect_address_changes
};
if !detect_address_changes {
let inner = self.inner.lock();
if !inner.static_public_dialinfo.is_empty() {
editor_public_internet.set_network_class(Some(NetworkClass::InboundCapable));
} }
} }
inner.stable_interface_addresses_at_startup = stable_interface_addresses;
// commit routing table edits
editor_public_internet.commit(true).await;
editor_local_network.commit(true).await;
Ok(())
};
let res = startup_func.await;
if res.is_err() {
info!("network failed to start");
self.inner.lock().network_started = Some(false);
return res;
} }
info!("network started"); // Build our protocol config to share it with other nodes
self.inner.lock().network_started = Some(true); let protocol_config = {
Ok(()) let mut inner = self.inner.lock();
// Create stop source
inner.stop_source = Some(StopSource::new());
// get protocol config
let protocol_config = {
let c = self.config.get();
let mut inbound = ProtocolTypeSet::new();
if c.network.protocol.udp.enabled {
inbound.insert(ProtocolType::UDP);
}
if c.network.protocol.tcp.listen {
inbound.insert(ProtocolType::TCP);
}
if c.network.protocol.ws.listen {
inbound.insert(ProtocolType::WS);
}
if c.network.protocol.wss.listen {
inbound.insert(ProtocolType::WSS);
}
let mut outbound = ProtocolTypeSet::new();
if c.network.protocol.udp.enabled {
outbound.insert(ProtocolType::UDP);
}
if c.network.protocol.tcp.connect {
outbound.insert(ProtocolType::TCP);
}
if c.network.protocol.ws.connect {
outbound.insert(ProtocolType::WS);
}
if c.network.protocol.wss.connect {
outbound.insert(ProtocolType::WSS);
}
let mut family_global = AddressTypeSet::new();
let mut family_local = AddressTypeSet::new();
if inner.enable_ipv4 {
family_global.insert(AddressType::IPV4);
family_local.insert(AddressType::IPV4);
}
if inner.enable_ipv6_global {
family_global.insert(AddressType::IPV6);
}
if inner.enable_ipv6_local {
family_local.insert(AddressType::IPV6);
}
// set up the routing table's network config
// if we have static public dialinfo, upgrade our network class
let public_internet_capabilities = {
PUBLIC_INTERNET_CAPABILITIES
.iter()
.copied()
.filter(|cap| !c.capabilities.disable.contains(cap))
.collect::<Vec<Capability>>()
};
let local_network_capabilities = {
LOCAL_NETWORK_CAPABILITIES
.iter()
.copied()
.filter(|cap| !c.capabilities.disable.contains(cap))
.collect::<Vec<Capability>>()
};
ProtocolConfig {
outbound,
inbound,
family_global,
family_local,
public_internet_capabilities,
local_network_capabilities,
}
};
inner.protocol_config = protocol_config.clone();
protocol_config
};
// Start editing routing table
let mut editor_public_internet = self
.unlocked_inner
.routing_table
.edit_routing_domain(RoutingDomain::PublicInternet);
let mut editor_local_network = self
.unlocked_inner
.routing_table
.edit_routing_domain(RoutingDomain::LocalNetwork);
// start listeners
if protocol_config.inbound.contains(ProtocolType::UDP) {
let res = self
.bind_udp_protocol_handlers(&mut editor_public_internet, &mut editor_local_network)
.await;
if !matches!(res, Ok(StartupDisposition::Success)) {
return res;
}
}
if protocol_config.inbound.contains(ProtocolType::WS) {
let res = self
.start_ws_listeners(&mut editor_public_internet, &mut editor_local_network)
.await;
if !matches!(res, Ok(StartupDisposition::Success)) {
return res;
}
}
if protocol_config.inbound.contains(ProtocolType::WSS) {
let res = self
.start_wss_listeners(&mut editor_public_internet, &mut editor_local_network)
.await;
if !matches!(res, Ok(StartupDisposition::Success)) {
return res;
}
}
if protocol_config.inbound.contains(ProtocolType::TCP) {
let res = self
.start_tcp_listeners(&mut editor_public_internet, &mut editor_local_network)
.await;
if !matches!(res, Ok(StartupDisposition::Success)) {
return res;
}
}
editor_public_internet.setup_network(
protocol_config.outbound,
protocol_config.inbound,
protocol_config.family_global,
protocol_config.public_internet_capabilities,
);
editor_local_network.setup_network(
protocol_config.outbound,
protocol_config.inbound,
protocol_config.family_local,
protocol_config.local_network_capabilities,
);
let detect_address_changes = {
let c = self.config.get();
c.network.detect_address_changes
};
if !detect_address_changes {
let inner = self.inner.lock();
if !inner.static_public_dialinfo.is_empty() {
editor_public_internet.set_network_class(Some(NetworkClass::InboundCapable));
}
}
// commit routing table edits
editor_public_internet.commit(true).await;
editor_local_network.commit(true).await;
Ok(StartupDisposition::Success)
}
#[instrument(level = "debug", err, skip_all)]
pub async fn startup(&self) -> EyreResult<StartupDisposition> {
self.inner.lock().network_started = None;
match self.startup_internal().await {
Ok(StartupDisposition::Success) => {
info!("network started");
self.inner.lock().network_started = Some(true);
Ok(StartupDisposition::Success)
}
Ok(StartupDisposition::BindRetry) => {
debug!("network bind retry");
self.inner.lock().network_started = Some(false);
Ok(StartupDisposition::BindRetry)
}
Err(e) => {
debug!("network failed to start");
self.inner.lock().network_started = Some(false);
Err(e)
}
}
} }
pub fn needs_restart(&self) -> bool { pub fn needs_restart(&self) -> bool {

View File

@ -349,7 +349,7 @@ impl Network {
bind_set: NetworkBindSet, bind_set: NetworkBindSet,
is_tls: bool, is_tls: bool,
new_protocol_accept_handler: Box<NewProtocolAcceptHandler>, new_protocol_accept_handler: Box<NewProtocolAcceptHandler>,
) -> EyreResult<Vec<SocketAddress>> { ) -> EyreResult<Option<Vec<SocketAddress>>> {
let mut out = Vec::<SocketAddress>::new(); let mut out = Vec::<SocketAddress>::new();
for ip_addr in bind_set.addrs { for ip_addr in bind_set.addrs {
@ -404,7 +404,8 @@ impl Network {
} }
if !bind_set.search { if !bind_set.search {
bail!("unable to bind to tcp {}", addr); log_net!(debug "unable to bind to tcp {}", addr);
return Ok(None);
} }
if port == 65535u16 { if port == 65535u16 {
@ -419,6 +420,6 @@ impl Network {
} }
} }
Ok(out) Ok(Some(out))
} }
} }

View File

@ -151,7 +151,7 @@ impl Network {
pub(super) async fn create_udp_protocol_handlers( pub(super) async fn create_udp_protocol_handlers(
&self, &self,
bind_set: NetworkBindSet, bind_set: NetworkBindSet,
) -> EyreResult<Vec<DialInfo>> { ) -> EyreResult<Option<Vec<DialInfo>>> {
let mut out = Vec::<DialInfo>::new(); let mut out = Vec::<DialInfo>::new();
for ip_addr in bind_set.addrs { for ip_addr in bind_set.addrs {
@ -175,7 +175,8 @@ impl Network {
} }
if !bind_set.search { if !bind_set.search {
bail!("unable to bind to udp {}", addr); log_net!(debug "unable to bind to udp {}", addr);
return Ok(None);
} }
if port == 65535u16 { if port == 65535u16 {
@ -189,7 +190,7 @@ impl Network {
} }
} }
} }
Ok(out) Ok(Some(out))
} }
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////

View File

@ -140,7 +140,7 @@ impl Network {
&self, &self,
editor_public_internet: &mut RoutingDomainEditor, editor_public_internet: &mut RoutingDomainEditor,
editor_local_network: &mut RoutingDomainEditor, editor_local_network: &mut RoutingDomainEditor,
) -> EyreResult<()> { ) -> EyreResult<StartupDisposition> {
log_net!("UDP: binding protocol handlers"); log_net!("UDP: binding protocol handlers");
let routing_table = self.routing_table(); let routing_table = self.routing_table();
let (listen_address, public_address, detect_address_changes) = { let (listen_address, public_address, detect_address_changes) = {
@ -170,7 +170,10 @@ impl Network {
); );
} }
let mut local_dial_info_list = self.create_udp_protocol_handlers(bind_set).await?; let Some(mut local_dial_info_list) = self.create_udp_protocol_handlers(bind_set).await?
else {
return Ok(StartupDisposition::BindRetry);
};
local_dial_info_list.sort(); local_dial_info_list.sort();
let mut static_public = false; let mut static_public = false;
@ -241,14 +244,16 @@ impl Network {
} }
// Now create tasks for udp listeners // Now create tasks for udp listeners
self.create_udp_listener_tasks().await self.create_udp_listener_tasks().await?;
Ok(StartupDisposition::Success)
} }
pub(super) async fn start_ws_listeners( pub(super) async fn start_ws_listeners(
&self, &self,
editor_public_internet: &mut RoutingDomainEditor, editor_public_internet: &mut RoutingDomainEditor,
editor_local_network: &mut RoutingDomainEditor, editor_local_network: &mut RoutingDomainEditor,
) -> EyreResult<()> { ) -> EyreResult<StartupDisposition> {
log_net!("WS: binding protocol handlers"); log_net!("WS: binding protocol handlers");
let routing_table = self.routing_table(); let routing_table = self.routing_table();
let (listen_address, url, path, detect_address_changes) = { let (listen_address, url, path, detect_address_changes) = {
@ -277,13 +282,16 @@ impl Network {
bind_set.port, bind_set.addrs bind_set.port, bind_set.addrs
); );
} }
let socket_addresses = self let Some(socket_addresses) = self
.start_tcp_listener( .start_tcp_listener(
bind_set, bind_set,
false, false,
Box::new(|c, t| Box::new(WebsocketProtocolHandler::new(c, t))), Box::new(|c, t| Box::new(WebsocketProtocolHandler::new(c, t))),
) )
.await?; .await?
else {
return Ok(StartupDisposition::BindRetry);
};
log_net!("WS: protocol handlers started on {:#?}", socket_addresses); log_net!("WS: protocol handlers started on {:#?}", socket_addresses);
let mut static_public = false; let mut static_public = false;
@ -353,14 +361,14 @@ impl Network {
Self::add_preferred_local_address(&mut inner, PeerAddress::new(sa, ProtocolType::WS)); Self::add_preferred_local_address(&mut inner, PeerAddress::new(sa, ProtocolType::WS));
} }
Ok(()) Ok(StartupDisposition::Success)
} }
pub(super) async fn start_wss_listeners( pub(super) async fn start_wss_listeners(
&self, &self,
editor_public_internet: &mut RoutingDomainEditor, editor_public_internet: &mut RoutingDomainEditor,
editor_local_network: &mut RoutingDomainEditor, editor_local_network: &mut RoutingDomainEditor,
) -> EyreResult<()> { ) -> EyreResult<StartupDisposition> {
log_net!("WSS: binding protocol handlers"); log_net!("WSS: binding protocol handlers");
let (listen_address, url, _detect_address_changes) = { let (listen_address, url, _detect_address_changes) = {
@ -389,13 +397,17 @@ impl Network {
); );
} }
let socket_addresses = self let Some(socket_addresses) = self
.start_tcp_listener( .start_tcp_listener(
bind_set, bind_set,
true, true,
Box::new(|c, t| Box::new(WebsocketProtocolHandler::new(c, t))), Box::new(|c, t| Box::new(WebsocketProtocolHandler::new(c, t))),
) )
.await?; .await?
else {
return Ok(StartupDisposition::BindRetry);
};
log_net!("WSS: protocol handlers started on {:#?}", socket_addresses); log_net!("WSS: protocol handlers started on {:#?}", socket_addresses);
// NOTE: No interface dial info for WSS, as there is no way to connect to a local dialinfo via TLS // NOTE: No interface dial info for WSS, as there is no way to connect to a local dialinfo via TLS
@ -448,14 +460,14 @@ impl Network {
Self::add_preferred_local_address(&mut inner, PeerAddress::new(sa, ProtocolType::WSS)); Self::add_preferred_local_address(&mut inner, PeerAddress::new(sa, ProtocolType::WSS));
} }
Ok(()) Ok(StartupDisposition::Success)
} }
pub(super) async fn start_tcp_listeners( pub(super) async fn start_tcp_listeners(
&self, &self,
editor_public_internet: &mut RoutingDomainEditor, editor_public_internet: &mut RoutingDomainEditor,
editor_local_network: &mut RoutingDomainEditor, editor_local_network: &mut RoutingDomainEditor,
) -> EyreResult<()> { ) -> EyreResult<StartupDisposition> {
log_net!("TCP: binding protocol handlers"); log_net!("TCP: binding protocol handlers");
let routing_table = self.routing_table(); let routing_table = self.routing_table();
@ -484,13 +496,17 @@ impl Network {
bind_set.port, bind_set.addrs bind_set.port, bind_set.addrs
); );
} }
let socket_addresses = self let Some(socket_addresses) = self
.start_tcp_listener( .start_tcp_listener(
bind_set, bind_set,
false, false,
Box::new(|c, _| Box::new(RawTcpProtocolHandler::new(c))), Box::new(|c, _| Box::new(RawTcpProtocolHandler::new(c))),
) )
.await?; .await?
else {
return Ok(StartupDisposition::BindRetry);
};
log_net!("TCP: protocol handlers started on {:#?}", socket_addresses); log_net!("TCP: protocol handlers started on {:#?}", socket_addresses);
let mut static_public = false; let mut static_public = false;
@ -546,6 +562,6 @@ impl Network {
Self::add_preferred_local_address(&mut inner, PeerAddress::new(sa, ProtocolType::TCP)); Self::add_preferred_local_address(&mut inner, PeerAddress::new(sa, ProtocolType::TCP));
} }
Ok(()) Ok(StartupDisposition::Success)
} }
} }

View File

@ -333,83 +333,92 @@ impl Network {
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
pub async fn startup(&self) -> EyreResult<()> { pub async fn startup_internal(&self) -> EyreResult<StartupDisposition> {
self.inner.lock().network_started = None; log_net!(debug "starting network");
let startup_func = async { // get protocol config
log_net!(debug "starting network"); let protocol_config = {
// get protocol config let c = self.config.get();
let protocol_config = { let inbound = ProtocolTypeSet::new();
let c = self.config.get(); let mut outbound = ProtocolTypeSet::new();
let inbound = ProtocolTypeSet::new();
let mut outbound = ProtocolTypeSet::new();
if c.network.protocol.ws.connect { if c.network.protocol.ws.connect {
outbound.insert(ProtocolType::WS); outbound.insert(ProtocolType::WS);
} }
if c.network.protocol.wss.connect { if c.network.protocol.wss.connect {
outbound.insert(ProtocolType::WSS); outbound.insert(ProtocolType::WSS);
} }
let supported_address_types: AddressTypeSet = if is_ipv6_supported() { let supported_address_types: AddressTypeSet = if is_ipv6_supported() {
AddressType::IPV4 | AddressType::IPV6 AddressType::IPV4 | AddressType::IPV6
} else { } else {
AddressType::IPV4.into() AddressType::IPV4.into()
};
let family_global = supported_address_types;
let family_local = supported_address_types;
let public_internet_capabilities = {
PUBLIC_INTERNET_CAPABILITIES
.iter()
.copied()
.filter(|cap| !c.capabilities.disable.contains(cap))
.collect::<Vec<Capability>>()
};
ProtocolConfig {
outbound,
inbound,
family_global,
family_local,
local_network_capabilities: vec![],
public_internet_capabilities,
}
}; };
self.inner.lock().protocol_config = protocol_config.clone();
// Start editing routing table let family_global = supported_address_types;
let mut editor_public_internet = self let family_local = supported_address_types;
.unlocked_inner
.routing_table
.edit_routing_domain(RoutingDomain::PublicInternet);
// set up the routing table's network config let public_internet_capabilities = {
// if we have static public dialinfo, upgrade our network class PUBLIC_INTERNET_CAPABILITIES
.iter()
.copied()
.filter(|cap| !c.capabilities.disable.contains(cap))
.collect::<Vec<Capability>>()
};
editor_public_internet.setup_network( ProtocolConfig {
protocol_config.outbound, outbound,
protocol_config.inbound, inbound,
protocol_config.family_global, family_global,
protocol_config.public_internet_capabilities.clone(), family_local,
); local_network_capabilities: vec![],
editor_public_internet.set_network_class(Some(NetworkClass::WebApp)); public_internet_capabilities,
}
// commit routing table edits
editor_public_internet.commit(true).await;
Ok(())
}; };
self.inner.lock().protocol_config = protocol_config.clone();
let res = startup_func.await; // Start editing routing table
if res.is_err() { let mut editor_public_internet = self
info!("network failed to start"); .unlocked_inner
self.inner.lock().network_started = Some(false); .routing_table
return res; .edit_routing_domain(RoutingDomain::PublicInternet);
// set up the routing table's network config
// if we have static public dialinfo, upgrade our network class
editor_public_internet.setup_network(
protocol_config.outbound,
protocol_config.inbound,
protocol_config.family_global,
protocol_config.public_internet_capabilities.clone(),
);
editor_public_internet.set_network_class(Some(NetworkClass::WebApp));
// commit routing table edits
editor_public_internet.commit(true).await;
Ok(StartupDisposition::Success)
}
pub async fn startup(&self) -> EyreResult<StartupDisposition> {
self.inner.lock().network_started = None;
match self.startup_internal().await {
Ok(StartupDisposition::Success) => {
info!("network started");
self.inner.lock().network_started = Some(true);
Ok(StartupDisposition::Success)
}
Ok(StartupDisposition::BindRetry) => {
debug!("network bind retry");
self.inner.lock().network_started = Some(false);
Ok(StartupDisposition::BindRetry)
}
Err(e) => {
debug!("network failed to start");
self.inner.lock().network_started = Some(false);
Err(e)
}
} }
info!("network started");
self.inner.lock().network_started = Some(true);
Ok(())
} }
pub fn needs_restart(&self) -> bool { pub fn needs_restart(&self) -> bool {

View File

@ -149,19 +149,21 @@ impl RoutingDomainEditor {
address_type, address_type,
protocol_type, protocol_type,
} => { } => {
if address_type.is_some() || protocol_type.is_some() { if !detail.common_mut().dial_info_details().is_empty() {
info!( if address_type.is_some() || protocol_type.is_some() {
"[{:?}] cleared dial info: {}:{}", info!(
self.routing_domain, "[{:?}] cleared dial info: {}:{}",
address_type self.routing_domain,
.map(|at| format!("{:?}", at)) address_type
.unwrap_or("---".to_string()), .map(|at| format!("{:?}", at))
protocol_type .unwrap_or("---".to_string()),
.map(|at| format!("{:?}", at)) protocol_type
.unwrap_or("---".to_string()), .map(|at| format!("{:?}", at))
); .unwrap_or("---".to_string()),
} else { );
info!("[{:?}] cleared all dial info", self.routing_domain); } else {
info!("[{:?}] cleared all dial info", self.routing_domain);
}
} }
detail detail
.common_mut() .common_mut()
@ -169,7 +171,9 @@ impl RoutingDomainEditor {
peer_info_changed = true; peer_info_changed = true;
} }
RoutingDomainChange::ClearRelayNode => { RoutingDomainChange::ClearRelayNode => {
info!("[{:?}] cleared relay node", self.routing_domain); if detail.common_mut().relay_node().is_some() {
info!("[{:?}] cleared relay node", self.routing_domain);
}
detail.common_mut().set_relay_node(None); detail.common_mut().set_relay_node(None);
peer_info_changed = true; peer_info_changed = true;
} }