diff --git a/veilid-core/src/intf/native/network/mod.rs b/veilid-core/src/intf/native/network/mod.rs index ca145e81..bccc9ce1 100644 --- a/veilid-core/src/intf/native/network/mod.rs +++ b/veilid-core/src/intf/native/network/mod.rs @@ -39,13 +39,11 @@ pub const PEEK_DETECT_LEN: usize = 64; struct NetworkInner { routing_table: RoutingTable, network_manager: NetworkManager, + network_started: bool, network_needs_restart: bool, - udp_listen: bool, + protocol_config: Option, udp_static_public_dialinfo: bool, - tcp_listen: bool, tcp_static_public_dialinfo: bool, - ws_listen: bool, - wss_listen: bool, network_class: Option, join_handles: Vec>, listener_states: BTreeMap>>, @@ -81,13 +79,11 @@ impl Network { NetworkInner { routing_table: network_manager.routing_table(), network_manager, + network_started: false, network_needs_restart: false, - udp_listen: false, + protocol_config: None, udp_static_public_dialinfo: false, - tcp_listen: false, tcp_static_public_dialinfo: false, - ws_listen: false, - wss_listen: false, network_class: None, join_handles: Vec::new(), listener_states: BTreeMap::new(), @@ -681,14 +677,11 @@ impl Network { match descriptor.protocol_type() { ProtocolType::UDP => { // send over the best udp socket we have bound since UDP is not connection oriented - let peer_socket_addr = descriptor - .remote - .to_socket_addr() - .map_err(map_to_string) - .map_err(logthru_net!(error))?; - if let Some(ph) = - self.find_best_udp_protocol_handler(&peer_socket_addr, &descriptor.local) - { + let peer_socket_addr = descriptor.remote.to_socket_addr(); + if let Some(ph) = self.find_best_udp_protocol_handler( + &peer_socket_addr, + &descriptor.local.map(|sa| sa.to_socket_addr()), + ) { ph.clone() .send_message(data, peer_socket_addr) .await @@ -724,14 +717,13 @@ impl Network { ) -> Result<(), String> { match &dial_info { DialInfo::UDP(_) => { - let peer_socket_addr = dial_info.to_socket_addr().map_err(logthru_net!())?; - + let peer_socket_addr = dial_info.to_socket_addr(); RawUdpProtocolHandler::send_unbound_message(data, peer_socket_addr) .await .map_err(logthru_net!()) } DialInfo::TCP(_) => { - let peer_socket_addr = dial_info.to_socket_addr().map_err(logthru_net!())?; + let peer_socket_addr = dial_info.to_socket_addr(); RawTcpProtocolHandler::send_unbound_message(data, peer_socket_addr) .await .map_err(logthru_net!()) @@ -752,7 +744,7 @@ impl Network { let conn = match &dial_info { DialInfo::UDP(_) => { - let peer_socket_addr = dial_info.to_socket_addr().map_err(logthru_net!())?; + let peer_socket_addr = dial_info.to_socket_addr(); if let Some(ph) = self.find_best_udp_protocol_handler(&peer_socket_addr, &None) { return ph .send_message(data, peer_socket_addr) @@ -764,7 +756,7 @@ impl Network { } } DialInfo::TCP(_) => { - let peer_socket_addr = dial_info.to_socket_addr().map_err(logthru_net!())?; + let peer_socket_addr = dial_info.to_socket_addr(); let local_addr = self.get_preferred_local_address(self.inner.lock().tcp_port, &peer_socket_addr); RawTcpProtocolHandler::connect(network_manager, local_addr, peer_socket_addr) @@ -772,22 +764,20 @@ impl Network { .map_err(logthru_net!())? } DialInfo::WS(_) => { - let remote_ip_addr = dial_info.resolve()?; - + let peer_socket_addr = dial_info.to_socket_addr(); let local_addr = self.get_preferred_local_address(self.inner.lock().ws_port, &peer_socket_addr); - WebsocketProtocolHandler::connect(network_manager, local_addr, dial_info) .await .map_err(logthru_net!(error))? } DialInfo::WSS(_) => { + let peer_socket_addr = dial_info.to_socket_addr(); let local_addr = - self.get_preferred_local_address(self.inner.lock().ws_port, &peer_socket_addr); - - WebsocketProtocolHandler::connect(network_manager, dial_info) - .await - .map_err(logthru_net!(error))?, + self.get_preferred_local_address(self.inner.lock().wss_port, &peer_socket_addr); + WebsocketProtocolHandler::connect(network_manager, local_addr, dial_info) + .await + .map_err(logthru_net!(error))? } }; @@ -865,7 +855,7 @@ impl Network { } else { // Register local dial info as public if it is publicly routable for x in &dial_infos { - if x.is_public().unwrap_or(false) { + if x.is_global() { routing_table.register_global_dial_info( x.clone(), Some(NetworkClass::Server), @@ -875,7 +865,6 @@ impl Network { } } } - self.inner.lock().udp_listen = true; self.inner.lock().udp_static_public_dialinfo = static_public; Ok(()) } @@ -904,8 +893,8 @@ impl Network { for (a, p) in addresses { // Pick out WS port for outbound connections (they will all be the same) self.inner.lock().ws_port = p; - - let di = DialInfo::ws(a.address_string(), p, path.clone()); +xxx continue here + let di = DialInfo::try_ws(a.address_string(), p, path.clone()); dial_infos.push(di.clone()); routing_table.register_local_dial_info(di, DialInfoOrigin::Static); } @@ -930,7 +919,6 @@ impl Network { ); } - self.inner.lock().ws_listen = true; Ok(()) } @@ -990,7 +978,6 @@ impl Network { return Err("WSS URL must be specified due to TLS requirements".to_owned()); } - self.inner.lock().wss_listen = true; Ok(()) } @@ -1044,7 +1031,7 @@ impl Network { } else { // Register local dial info as public if it is publicly routable for x in &dial_infos { - if x.is_public().unwrap_or(false) { + if x.is_global() { routing_table.register_global_dial_info( x.clone(), Some(NetworkClass::Server), @@ -1055,12 +1042,15 @@ impl Network { } } - self.inner.lock().tcp_listen = true; self.inner.lock().tcp_static_public_dialinfo = static_public; Ok(()) } + pub fn get_protocol_config(&self) -> Option { + self.inner.lock().protocol_config.clone() + } + pub async fn startup(&self) -> Result<(), String> { info!("starting network"); let network_manager = self.inner.lock().network_manager.clone(); @@ -1068,36 +1058,38 @@ impl Network { // initialize interfaces self.inner.lock().interfaces.refresh()?; - // get network config - let (enabled_udp, connect_tcp, listen_tcp, connect_ws, listen_ws, connect_wss, listen_wss) = { + // get protocol config + let protocol_config = { let c = self.config.get(); - ( - c.network.protocol.udp.enabled && c.capabilities.protocol_udp, - c.network.protocol.tcp.connect && c.capabilities.protocol_connect_tcp, - c.network.protocol.tcp.listen && c.capabilities.protocol_accept_tcp, - c.network.protocol.ws.connect && c.capabilities.protocol_connect_ws, - c.network.protocol.ws.listen && c.capabilities.protocol_accept_ws, - c.network.protocol.wss.connect && c.capabilities.protocol_connect_wss, - c.network.protocol.wss.listen && c.capabilities.protocol_accept_wss, - ) + ProtocolConfig { + udp_enabled: c.network.protocol.udp.enabled && c.capabilities.protocol_udp, + tcp_connect: c.network.protocol.tcp.connect && c.capabilities.protocol_connect_tcp, + tcp_listen: c.network.protocol.tcp.listen && c.capabilities.protocol_accept_tcp, + ws_connect: c.network.protocol.ws.connect && c.capabilities.protocol_connect_ws, + ws_listen: c.network.protocol.ws.listen && c.capabilities.protocol_accept_ws, + wss_connect: c.network.protocol.wss.connect && c.capabilities.protocol_connect_wss, + wss_listen: c.network.protocol.wss.listen && c.capabilities.protocol_accept_wss, + } }; + self.inner.lock().protocol_config = Some(protocol_config); // start listeners - if enabled_udp { + if protocol_config.udp_enabled { self.start_udp_listeners().await?; self.create_udp_outbound_sockets().await?; } - if listen_ws { + if protocol_config.ws_listen { self.start_ws_listeners().await?; } - if listen_wss { + if protocol_config.wss_listen { self.start_wss_listeners().await?; } - if listen_tcp { + if protocol_config.tcp_listen { self.start_tcp_listeners().await?; } info!("network started"); + self.inner.lock().network_started = true; Ok(()) } @@ -1123,13 +1115,17 @@ impl Network { } ////////////////////////////////////////// - pub fn get_network_class(&self) -> NetworkClass { + pub fn get_network_class(&self) -> Option { let inner = self.inner.lock(); let routing_table = inner.routing_table.clone(); + if !inner.network_started { + return None; + } + // If we've fixed the network class, return it rather than calculating it - if let Some(network_class) = inner.network_class { - return network_class; + if inner.network_class.is_some() { + return inner.network_class; } // Go through our public dialinfo and see what our best network class is @@ -1141,7 +1137,7 @@ impl Network { } } } - network_class + Some(network_class) } ////////////////////////////////////////// @@ -1149,18 +1145,19 @@ impl Network { pub async fn tick(&self) -> Result<(), String> { let ( routing_table, - udp_listen, + protocol_config, udp_static_public_dialinfo, - tcp_listen, tcp_static_public_dialinfo, network_class, ) = { let inner = self.inner.lock(); ( inner.network_manager.routing_table(), - inner.udp_listen, + inner + .protocol_config + .clone() + .unwrap_or_else(|| ProtocolConfig::default()), inner.udp_static_public_dialinfo, - inner.tcp_listen, inner.tcp_static_public_dialinfo, inner.network_class.unwrap_or(NetworkClass::Invalid), ) @@ -1171,7 +1168,7 @@ impl Network { // If we can have public dialinfo, or we haven't figured out our network class yet, // and we're active for UDP, we should attempt to get our public dialinfo sorted out // and assess our network class if we haven't already - if udp_listen + if protocol_config.udp_enabled && !udp_static_public_dialinfo && (network_class.inbound_capable() || network_class == NetworkClass::Invalid) { @@ -1189,7 +1186,7 @@ impl Network { } // Same but for TCPv4 - if tcp_listen + if protocol_config.tcp_enabled && !tcp_static_public_dialinfo && (network_class.inbound_capable() || network_class == NetworkClass::Invalid) { diff --git a/veilid-core/src/intf/native/network/protocol/tcp.rs b/veilid-core/src/intf/native/network/protocol/tcp.rs index 8cf7c4ee..01074d86 100644 --- a/veilid-core/src/intf/native/network/protocol/tcp.rs +++ b/veilid-core/src/intf/native/network/protocol/tcp.rs @@ -153,8 +153,7 @@ impl RawTcpProtocolHandler { let conn = NetworkConnection::RawTcp(RawTcpNetworkConnection::new(stream)); let peer_addr = PeerAddress::new( - Address::from_socket_addr(socket_addr).to_canonical(), - socket_addr.port(), + SocketAddress::from_socket_addr(socket_addr), ProtocolType::TCP, ); let (network_manager, local_address) = { @@ -162,7 +161,13 @@ impl RawTcpProtocolHandler { (inner.network_manager.clone(), inner.local_address) }; network_manager - .on_new_connection(ConnectionDescriptor::new(peer_addr, local_address), conn) + .on_new_connection( + ConnectionDescriptor::new( + peer_addr, + SocketAddress::from_socket_addr(local_address), + ), + conn, + ) .await?; Ok(true) } @@ -191,8 +196,7 @@ impl RawTcpProtocolHandler { .map_err(logthru_net!())?; let ps = AsyncPeekStream::new(ts); let peer_addr = PeerAddress::new( - Address::from_socket_addr(remote_socket_addr).to_canonical(), - remote_socket_addr.port(), + SocketAddress::from_socket_addr(remote_socket_addr), ProtocolType::TCP, ); @@ -200,7 +204,10 @@ impl RawTcpProtocolHandler { let conn = NetworkConnection::RawTcp(RawTcpNetworkConnection::new(ps)); network_manager .on_new_connection( - ConnectionDescriptor::new(peer_addr, local_address), + ConnectionDescriptor::new( + peer_addr, + SocketAddress::from_socket_addr(local_address), + ), conn.clone(), ) .await?; diff --git a/veilid-core/src/intf/native/network/protocol/udp.rs b/veilid-core/src/intf/native/network/protocol/udp.rs index 9929bc3a..59cef7e6 100644 --- a/veilid-core/src/intf/native/network/protocol/udp.rs +++ b/veilid-core/src/intf/native/network/protocol/udp.rs @@ -48,15 +48,17 @@ impl RawUdpProtocolHandler { }; let peer_addr = PeerAddress::new( - Address::from_socket_addr(remote_addr), - remote_addr.port(), + SocketAddress::from_socket_addr(remote_addr), ProtocolType::UDP, ); let local_socket_addr = socket.local_addr().map_err(|e| format!("{}", e))?; network_manager .on_recv_envelope( data, - &ConnectionDescriptor::new(peer_addr, local_socket_addr), + &ConnectionDescriptor::new( + peer_addr, + SocketAddress::from_socket_addr(local_socket_addr), + ), ) .await } diff --git a/veilid-core/src/intf/native/network/protocol/ws.rs b/veilid-core/src/intf/native/network/protocol/ws.rs index be263574..7959043e 100644 --- a/veilid-core/src/intf/native/network/protocol/ws.rs +++ b/veilid-core/src/intf/native/network/protocol/ws.rs @@ -221,11 +221,8 @@ impl WebsocketProtocolHandler { ProtocolType::WS }; - let peer_addr = PeerAddress::new( - Address::from_socket_addr(socket_addr), - socket_addr.port(), - protocol_type, - ); + let peer_addr = + PeerAddress::new(SocketAddress::from_socket_addr(socket_addr), protocol_type); let conn = NetworkConnection::WsAccepted(WebsocketNetworkConnection::new( self.inner.tls, @@ -235,7 +232,10 @@ impl WebsocketProtocolHandler { .network_manager .clone() .on_new_connection( - ConnectionDescriptor::new(peer_addr, self.inner.local_address), + ConnectionDescriptor::new( + peer_addr, + SocketAddress::from_socket_addr(self.inner.local_address), + ), conn, ) .await?; @@ -248,27 +248,20 @@ impl WebsocketProtocolHandler { dial_info: &DialInfo, ) -> Result { // Split dial info up - let (tls, request, domain, port, protocol_type) = match &dial_info { - DialInfo::WS(di) => ( - false, - format!("ws://{}:{}/{}", di.host, di.port, di.path), - di.host.clone(), - di.port, - ProtocolType::WS, - ), - DialInfo::WSS(di) => ( - true, - format!("wss://{}:{}/{}", di.host, di.port, di.path), - di.host.clone(), - di.port, - ProtocolType::WSS, - ), + let (tls, protocol_type, scheme) = match &dial_info { + DialInfo::WS(_) => (false, ProtocolType::WS, "ws"), + DialInfo::WSS(_) => (true, ProtocolType::WSS, "wss"), _ => panic!("invalid dialinfo for WS/WSS protocol"), }; + let request = dial_info.request().unwrap(); + let split_url = SplitUrl::from_str(&request)?; + if split_url.scheme != scheme { + return Err("invalid websocket url scheme".to_string()); + } + let domain = split_url.host.clone(); // Resolve remote address - let remote_ip_addr = dial_info.resolve()?; - let remote_socket_addr = SocketAddr::new(remote_ip_addr, port); + let remote_socket_addr = dial_info.to_socket_addr(); // Make a shared socket let socket = new_shared_tcp_socket(local_address)?; @@ -304,15 +297,17 @@ impl WebsocketProtocolHandler { // Make the connection descriptor peer address let peer_addr = PeerAddress::new( - Address::from_socket_addr(remote_socket_addr), - port, + SocketAddress::from_socket_addr(remote_socket_addr), ProtocolType::WSS, ); // Register the WSS connection network_manager .on_new_connection( - ConnectionDescriptor::new(peer_addr, actual_local_addr), + ConnectionDescriptor::new( + peer_addr, + SocketAddress::from_socket_addr(actual_local_addr), + ), conn.clone(), ) .await?; @@ -326,15 +321,17 @@ impl WebsocketProtocolHandler { // Make the connection descriptor peer address let peer_addr = PeerAddress::new( - Address::from_socket_addr(remote_socket_addr), - port, + SocketAddress::from_socket_addr(remote_socket_addr), ProtocolType::WS, ); // Register the WS connection network_manager .on_new_connection( - ConnectionDescriptor::new(peer_addr, actual_local_addr), + ConnectionDescriptor::new( + peer_addr, + SocketAddress::from_socket_addr(actual_local_addr), + ), conn.clone(), ) .await?; diff --git a/veilid-core/src/intf/wasm/network/mod.rs b/veilid-core/src/intf/wasm/network/mod.rs index 6fb958de..8ccae1c2 100644 --- a/veilid-core/src/intf/wasm/network/mod.rs +++ b/veilid-core/src/intf/wasm/network/mod.rs @@ -12,12 +12,15 @@ pub use protocol::*; struct NetworkInner { network_manager: NetworkManager, stop_network: Eventual, + network_started: bool, network_needs_restart: bool, + protocol_config: Option, //join_handle: TryJoin? } #[derive(Clone)] pub struct Network { + config: VeilidConfig, inner: Arc>, } @@ -26,13 +29,15 @@ impl Network { NetworkInner { network_manager, stop_network: Eventual::new(), + network_started: false, network_needs_restart: false, - //join_handle: None, + protocol_config: None, //join_handle: None, } } pub fn new(network_manager: NetworkManager) -> Self { Self { + config: network_manager.config(), inner: Arc::new(Mutex::new(Self::new_inner(network_manager))), } } @@ -150,10 +155,21 @@ impl Network { ///////////////////////////////////////////////////////////////// pub async fn startup(&self) -> Result<(), String> { - //let network_manager = self.inner.lock().network_manager.clone(); - //let config_shared = network_manager.core().config(); - //let config = config_shared.get(); + // get protocol config + self.inner.lock().protocol_config = Some({ + let c = self.config.get(); + ProtocolConfig { + udp_enabled: false, //c.network.protocol.udp.enabled && c.capabilities.protocol_udp, + tcp_connect: false, //c.network.protocol.tcp.connect && c.capabilities.protocol_connect_tcp, + tcp_listen: false, //c.network.protocol.tcp.listen && c.capabilities.protocol_accept_tcp, + ws_connect: c.network.protocol.ws.connect && c.capabilities.protocol_connect_ws, + ws_listen: c.network.protocol.ws.listen && c.capabilities.protocol_accept_ws, + wss_connect: c.network.protocol.wss.connect && c.capabilities.protocol_connect_wss, + wss_listen: c.network.protocol.wss.listen && c.capabilities.protocol_accept_wss, + } + }); + self.inner.lock().network_started = true; Ok(()) } @@ -179,9 +195,16 @@ impl Network { } ////////////////////////////////////////// - pub fn get_network_class(&self) -> NetworkClass { + pub fn get_network_class(&self) -> Option { // xxx eventually detect tor browser? - return NetworkClass::WebApp; + return if self.inner.lock().network_started { + Some(NetworkClass::WebApp) + } else { + None + }; + } + pub fn get_protocol_config(&self) -> Option { + self.inner.lock().protocol_config.clone() } ////////////////////////////////////////// diff --git a/veilid-core/src/lease_manager.rs b/veilid-core/src/lease_manager.rs index b959f9e2..cb53b429 100644 --- a/veilid-core/src/lease_manager.rs +++ b/veilid-core/src/lease_manager.rs @@ -110,17 +110,20 @@ impl LeaseManager { if inner.max_server_signal_leases == 0 { return false; } - let network_class = inner.network_manager.get_network_class(); - match network_class { - NetworkClass::Server => true, - NetworkClass::Mapped => true, - NetworkClass::FullNAT => true, - NetworkClass::AddressRestrictedNAT => false, - NetworkClass::PortRestrictedNAT => false, - NetworkClass::OutboundOnly => false, - NetworkClass::WebApp => false, - NetworkClass::TorWebApp => false, - NetworkClass::Invalid => false, + if let Some(network_class) = inner.network_manager.get_network_class() { + match network_class { + NetworkClass::Server => true, + NetworkClass::Mapped => true, + NetworkClass::FullNAT => true, + NetworkClass::AddressRestrictedNAT => false, + NetworkClass::PortRestrictedNAT => false, + NetworkClass::OutboundOnly => false, + NetworkClass::WebApp => false, + NetworkClass::TorWebApp => false, + NetworkClass::Invalid => false, + } + } else { + false } } pub fn server_will_provide_signal_lease(&self) -> bool { @@ -152,17 +155,20 @@ impl LeaseManager { if inner.max_server_signal_leases == 0 { return false; } - let network_class = inner.network_manager.get_network_class(); - match network_class { - NetworkClass::Server => true, - NetworkClass::Mapped => true, - NetworkClass::FullNAT => true, - NetworkClass::AddressRestrictedNAT => false, - NetworkClass::PortRestrictedNAT => false, - NetworkClass::OutboundOnly => false, - NetworkClass::WebApp => false, - NetworkClass::TorWebApp => false, - NetworkClass::Invalid => false, + if let Some(network_class) = inner.network_manager.get_network_class() { + match network_class { + NetworkClass::Server => true, + NetworkClass::Mapped => true, + NetworkClass::FullNAT => true, + NetworkClass::AddressRestrictedNAT => false, + NetworkClass::PortRestrictedNAT => false, + NetworkClass::OutboundOnly => false, + NetworkClass::WebApp => false, + NetworkClass::TorWebApp => false, + NetworkClass::Invalid => false, + } + } else { + false } // xxx: also depends on network strength / bandwidth availability? } diff --git a/veilid-core/src/network_manager.rs b/veilid-core/src/network_manager.rs index ca6931e2..a488fcf7 100644 --- a/veilid-core/src/network_manager.rs +++ b/veilid-core/src/network_manager.rs @@ -42,6 +42,17 @@ impl NetworkClass { } } +#[derive(Copy, Clone, Debug, Default)] +pub struct ProtocolConfig { + pub udp_enabled: bool, + pub tcp_connect: bool, + pub tcp_listen: bool, + pub ws_connect: bool, + pub ws_listen: bool, + pub wss_connect: bool, + pub wss_listen: bool, +} + // Things we get when we start up and go away when we shut down // Routing table is not in here because we want it to survive a network shutdown/startup restart #[derive(Clone)] @@ -381,11 +392,20 @@ impl NetworkManager { } // Return what network class we are in - pub fn get_network_class(&self) -> NetworkClass { + pub fn get_network_class(&self) -> Option { if let Some(components) = &self.inner.lock().components { components.net.get_network_class() } else { - NetworkClass::Invalid + None + } + } + + // Return what protocols we have enabled + pub fn get_protocol_config(&self) -> Option { + if let Some(components) = &self.inner.lock().components { + components.net.get_protocol_config() + } else { + None } } diff --git a/veilid-core/src/routing_table/bucket_entry.rs b/veilid-core/src/routing_table/bucket_entry.rs index 665c73a4..af0c38f5 100644 --- a/veilid-core/src/routing_table/bucket_entry.rs +++ b/veilid-core/src/routing_table/bucket_entry.rs @@ -31,7 +31,7 @@ pub struct BucketEntry { pub(super) ref_count: u32, min_max_version: Option<(u8, u8)>, last_connection: Option<(ConnectionDescriptor, u64)>, - dial_info_entries: VecDeque, + dial_infos: Vec, stats_accounting: StatsAccounting, peer_stats: PeerStats, } @@ -43,7 +43,7 @@ impl BucketEntry { ref_count: 0, min_max_version: None, last_connection: None, - dial_info_entries: VecDeque::new(), + dial_infos: Vec::new(), stats_accounting: StatsAccounting::new(), peer_stats: PeerStats { time_added: now, @@ -56,145 +56,48 @@ impl BucketEntry { } } - pub fn add_dial_info(&mut self, dial_info: DialInfo) -> Result<(), String> { - let mut idx: Option = None; - for i in 0..self.dial_info_entries.len() { - if self.dial_info_entries[i].dial_info() == &dial_info { - idx = Some(i); - break; - } - } - match idx { - None => { - self.dial_info_entries - .push_front(DialInfoEntry::try_new(dial_info)?); - } - Some(idx) => { - let die = self.dial_info_entries.remove(idx).unwrap(); - self.dial_info_entries.push_front(die); - } - } - Ok(()) + pub fn update_dial_infos(&mut self, dial_infos: &[DialInfo]) { + self.dial_infos = dial_infos.to_vec(); + self.dial_infos.sort(); } - pub fn best_dial_info(&self) -> Option { - self.dial_info_entries - .front() - .map(|die| die.dial_info().clone()) - } - - pub fn filtered_dial_info(&self, filter: F) -> Option + pub fn first_filtered_dial_info(&self, filter: F) -> Option where - F: Fn(&DialInfoEntry) -> bool, + F: Fn(&DialInfo) -> bool, { - for die in &self.dial_info_entries { - if filter(die) { - return Some(die.dial_info().clone()); + for di in &self.dial_infos { + if filter(di) { + return Some(di.clone()); } } None } - - pub fn dial_info_entries_as_ref(&self) -> &VecDeque { - &self.dial_info_entries + pub fn all_filtered_dial_infos(&self, filter: F) -> Vec + where + F: Fn(&DialInfo) -> bool, + { + let ret = Vec::new(); + for di in &self.dial_infos { + if filter(di) { + ret.push(di.clone()); + } + } + ret } - pub fn dial_info(&self) -> Vec { - self.dial_info_entries - .iter() - .map(|e| e.dial_info().clone()) - .collect() - } - - pub fn global_dial_info(&self) -> Vec { - self.dial_info_entries - .iter() - .filter_map(|e| { - if e.is_public() { - Some(e.dial_info().clone()) - } else { - None - } - }) - .collect() - } - - pub fn global_dial_info_for_protocol(&self, protocol_type: ProtocolType) -> Vec { - self.dial_info_entries - .iter() - .filter_map(|e| { - if e.dial_info().protocol_type() != protocol_type { - None - } else if e.is_public() { - Some(e.dial_info().clone()) - } else { - None - } - }) - .collect() - } - - pub fn local_dial_info(&self) -> Vec { - self.dial_info_entries - .iter() - .filter_map(|e| { - if e.is_private() { - Some(e.dial_info().clone()) - } else { - None - } - }) - .collect() - } - - pub fn local_dial_info_for_protocol(&mut self, protocol_type: ProtocolType) -> Vec { - self.dial_info_entries - .iter_mut() - .filter_map(|e| { - if e.dial_info().protocol_type() != protocol_type { - None - } else if e.is_private() { - Some(e.dial_info().clone()) - } else { - None - } - }) - .collect() + pub fn dial_infos(&self) -> &[DialInfo] { + &self.dial_infos.clone() } pub fn get_peer_info(&self, key: DHTKey, scope: PeerScope) -> PeerInfo { PeerInfo { node_id: NodeId::new(key), - dial_infos: match scope { - PeerScope::All => self.dial_info(), - PeerScope::Global => self.global_dial_info(), - PeerScope::Local => self.local_dial_info(), - }, + dial_infos: self.all_filtered_dial_infos(|di| di.matches_peer_scope(scope)), } } pub fn set_last_connection(&mut self, last_connection: ConnectionDescriptor, timestamp: u64) { self.last_connection = Some((last_connection, timestamp)); - - // sort the dialinfoentries by the last peer address if we have a match - // if one particular peer address is being used and matches a dialinfoentry - // then we should prefer it - for i in 0..self.dial_info_entries.len() { - let die = &mut self.dial_info_entries[i]; - - // see if we have a matching address - if RoutingTable::dial_info_peer_address_match( - die.dial_info(), - &self.last_connection.as_ref().unwrap().0.remote, - ) { - // push the most recent dialinfo to the front - let dies = &mut self.dial_info_entries; - let die = dies.remove(i).unwrap(); - dies.push_front(die); - - break; - } - } } pub fn last_connection(&self) -> Option { diff --git a/veilid-core/src/routing_table/dial_info_entry.rs b/veilid-core/src/routing_table/dial_info_entry.rs deleted file mode 100644 index a97bdb97..00000000 --- a/veilid-core/src/routing_table/dial_info_entry.rs +++ /dev/null @@ -1,60 +0,0 @@ -use super::*; - -#[derive(Debug, Clone)] -pub struct DialInfoEntry { - dial_info: DialInfo, - resolved_address: IpAddr, -} - -impl DialInfoEntry { - pub fn try_new(dial_info: DialInfo) -> Result { - let addr = dial_info - .resolve() - .map_err(|e| format!("failed to resolve address: {:?}", e))?; - Ok(Self { - dial_info, - resolved_address: addr, - }) - } - - pub fn dial_info(&self) -> &DialInfo { - &self.dial_info - } - - pub fn address(&self) -> IpAddr { - self.resolved_address - } - - pub fn resolve(&mut self) -> Result { - let addr = match self.dial_info.resolve() { - Ok(a) => a, - Err(_) => return Err("failed to resolve address".to_owned()), - }; - self.resolved_address = addr; - Ok(addr) - } - - pub fn matches_peer_scope(&self, scope: PeerScope) -> bool { - match scope { - PeerScope::All => true, - PeerScope::Global => self.is_public(), - PeerScope::Local => self.is_private(), - } - } - - pub fn is_public(&self) -> bool { - ipaddr_is_global(&self.resolved_address) - } - pub fn is_private(&self) -> bool { - match self.resolved_address { - IpAddr::V4(a) => ipv4addr_is_private(&a), - IpAddr::V6(a) => ipv6addr_is_unicast_site_local(&a), - } - } - pub fn is_valid(&self) -> bool { - self.is_public() || self.is_private() - } - pub fn is_loopback(&self) -> bool { - ipaddr_is_loopback(&self.resolved_address) - } -} diff --git a/veilid-core/src/routing_table/mod.rs b/veilid-core/src/routing_table/mod.rs index e0831219..de7b64f7 100644 --- a/veilid-core/src/routing_table/mod.rs +++ b/veilid-core/src/routing_table/mod.rs @@ -482,9 +482,7 @@ impl RoutingTable { ) -> Result { let nr = self.create_node_ref(node_id)?; nr.operate(move |e| -> Result<(), String> { - for di in dial_infos { - e.add_dial_info(di.clone())?; - } + e.update_dial_info(dial_infos); Ok(()) })?; diff --git a/veilid-core/src/routing_table/node_ref.rs b/veilid-core/src/routing_table/node_ref.rs index 2552a19c..c7c670f0 100644 --- a/veilid-core/src/routing_table/node_ref.rs +++ b/veilid-core/src/routing_table/node_ref.rs @@ -5,7 +5,9 @@ use alloc::fmt; pub struct NodeRef { routing_table: RoutingTable, node_id: DHTKey, - protocol_address_type: Option, + // Filters + protocol_type: Option, + address_type: Option, } impl NodeRef { @@ -14,20 +16,23 @@ impl NodeRef { Self { routing_table, node_id: key, - protocol_address_type: None, + protocol_type: None, + address_type: None, } } pub fn new_filtered( routing_table: RoutingTable, key: DHTKey, entry: &mut BucketEntry, - protocol_address_type: ProtocolAddressType, + protocol_type: Option, + address_type: Option, ) -> Self { entry.ref_count += 1; Self { routing_table, node_id: key, - protocol_address_type: Some(protocol_address_type), + protocol_type, + address_type, } } @@ -35,15 +40,20 @@ impl NodeRef { self.node_id } - pub fn protocol_address_type(&self) -> Option { - self.protocol_address_type + pub fn protocol_type(&self) -> Option { + self.protocol_type } - pub fn set_protocol_address_type( - &mut self, - protocol_address_type: Option, - ) { - self.protocol_address_type = protocol_address_type; + pub fn set_protocol_type(&mut self, protocol_type: Option) { + self.protocol_type = protocol_type; + } + + pub fn address_type(&self) -> Option { + self.address_type + } + + pub fn set_address_type(&mut self, address_type: Option) { + self.address_type = address_type; } pub fn operate(&self, f: F) -> T @@ -53,8 +63,9 @@ impl NodeRef { self.routing_table.operate_on_bucket_entry(self.node_id, f) } + xxx fix the notion of 'best dial info' to sort by capability and udp/tcp/ws/wss preference order pub fn dial_info(&self) -> Option { - match self.protocol_address_type { + if self.protocol_type || self. { None => self.operate(|e| e.best_dial_info()), Some(pat) => self.operate(|e| { e.filtered_dial_info(|die| die.dial_info().protocol_address_type() == pat) diff --git a/veilid-core/src/rpc_processor/coders/address.rs b/veilid-core/src/rpc_processor/coders/address.rs index a51a1e98..7dfac2e8 100644 --- a/veilid-core/src/rpc_processor/coders/address.rs +++ b/veilid-core/src/rpc_processor/coders/address.rs @@ -35,14 +35,6 @@ pub fn encode_address( .expect("slice with incorrect length"), )); } - Address::Hostname(h) => { - let mut tb = builder.reborrow().init_hostname( - h.len() - .try_into() - .map_err(map_error_internal!("hostname too long"))?, - ); - tb.push_str(h.as_str()); - } }; Ok(()) } @@ -63,7 +55,6 @@ pub fn decode_address(reader: &veilid_capnp::address::Reader) -> Result Ok(Address::Hostname(tr.to_owned())), - _ => Err(rpc_error_internal("invalid address type")), + _ => Err(rpc_error_protocol("invalid address type")), } } diff --git a/veilid-core/src/rpc_processor/coders/dial_info.rs b/veilid-core/src/rpc_processor/coders/dial_info.rs index c428779a..12362859 100644 --- a/veilid-core/src/rpc_processor/coders/dial_info.rs +++ b/veilid-core/src/rpc_processor/coders/dial_info.rs @@ -6,40 +6,40 @@ use rpc_processor::*; pub fn decode_dial_info(reader: &veilid_capnp::dial_info::Reader) -> Result { match reader.reborrow().which() { Ok(veilid_capnp::dial_info::Which::Udp(Ok(udp))) => { - let address_reader = udp - .get_address() - .map_err(map_error_internal!("missing udp address"))?; - let address = decode_address(&address_reader)?; - let port = udp.get_port(); - Ok(DialInfo::udp(address, port)) + let socket_address_reader = udp + .get_socket_address() + .map_err(map_error_protocol!("missing UDP socketAddress"))?; + let socket_address = decode_socket_address(&socket_address_reader)?; + Ok(DialInfo::udp(socket_address)) } Ok(veilid_capnp::dial_info::Which::Tcp(Ok(tcp))) => { - let address_reader = tcp - .get_address() - .map_err(map_error_internal!("missing tcp address"))?; - let address = decode_address(&address_reader)?; - let port = tcp.get_port(); - Ok(DialInfo::tcp(address, port)) + let socket_address_reader = tcp + .get_socket_address() + .map_err(map_error_protocol!("missing TCP socketAddress"))?; + let socket_address = decode_socket_address(&socket_address_reader)?; + Ok(DialInfo::tcp(socket_address)) } Ok(veilid_capnp::dial_info::Which::Ws(Ok(ws))) => { - let host = ws - .get_host() - .map_err(map_error_internal!("missing ws host"))?; - let port = ws.get_port(); - let path = ws - .get_path() - .map_err(map_error_internal!("missing ws path"))?; - Ok(DialInfo::ws(host.to_owned(), port, path.to_owned())) + let socket_address_reader = ws + .get_socket_address() + .map_err(map_error_protocol!("missing WS socketAddress"))?; + let socket_address = decode_socket_address(&socket_address_reader)?; + let request = ws + .get_request() + .map_err(map_error_protocol!("missing WS request"))?; + DialInfo::try_ws(socket_address, request.to_owned()) + .map_err(map_error_protocol!("invalid WS dial info")) } Ok(veilid_capnp::dial_info::Which::Wss(Ok(wss))) => { - let host = wss - .get_host() - .map_err(map_error_internal!("missing wss host"))?; - let port = wss.get_port(); - let path = wss - .get_path() - .map_err(map_error_internal!("missing wss path"))?; - Ok(DialInfo::wss(host.to_owned(), port, path.to_owned())) + let socket_address_reader = wss + .get_socket_address() + .map_err(map_error_protocol!("missing WSS socketAddress"))?; + let socket_address = decode_socket_address(&socket_address_reader)?; + let request = wss + .get_request() + .map_err(map_error_protocol!("missing WSS request"))?; + DialInfo::try_wss(socket_address, request.to_owned()) + .map_err(map_error_protocol!("invalid WSS dial info")) } _ => Err(rpc_error_internal("invalid dial info type")), } @@ -52,49 +52,45 @@ pub fn encode_dial_info( match dial_info { DialInfo::UDP(udp) => { let mut di_udp_builder = builder.reborrow().init_udp(); - encode_address(&udp.address, &mut di_udp_builder.reborrow().init_address())?; - di_udp_builder.set_port(udp.port); + encode_socket_address( + &udp.socket_address, + &mut di_udp_builder.reborrow().init_socket_address(), + )?; } DialInfo::TCP(tcp) => { let mut di_tcp_builder = builder.reborrow().init_tcp(); - encode_address(&tcp.address, &mut di_tcp_builder.reborrow().init_address())?; - di_tcp_builder.set_port(tcp.port); + encode_socket_address( + &tcp.socket_address, + &mut di_tcp_builder.reborrow().init_socket_address(), + )?; } DialInfo::WS(ws) => { let mut di_ws_builder = builder.reborrow().init_ws(); - let mut hostb = di_ws_builder.reborrow().init_host( - ws.host + encode_socket_address( + &ws.socket_address, + &mut di_ws_builder.reborrow().init_socket_address(), + )?; + let mut requestb = di_ws_builder.init_request( + ws.request .len() .try_into() - .map_err(map_error_internal!("host too long"))?, + .map_err(map_error_protocol!("request too long"))?, ); - hostb.push_str(ws.host.as_str()); - di_ws_builder.set_port(ws.port); - let mut pathb = di_ws_builder.init_path( - ws.path - .len() - .try_into() - .map_err(map_error_internal!("path too long"))?, - ); - pathb.push_str(ws.path.as_str()); + requestb.push_str(ws.request.as_str()); } DialInfo::WSS(wss) => { let mut di_wss_builder = builder.reborrow().init_wss(); - let mut hostb = di_wss_builder.reborrow().init_host( - wss.host + encode_socket_address( + &wss.socket_address, + &mut di_wss_builder.reborrow().init_socket_address(), + )?; + let mut requestb = di_wss_builder.init_request( + wss.request .len() .try_into() - .map_err(map_error_internal!("host too long"))?, + .map_err(map_error_protocol!("request too long"))?, ); - hostb.push_str(wss.host.as_str()); - di_wss_builder.set_port(wss.port); - let mut pathb = di_wss_builder.init_path( - wss.path - .len() - .try_into() - .map_err(map_error_internal!("path too long"))?, - ); - pathb.push_str(wss.path.as_str()); + requestb.push_str(wss.request.as_str()); } }; Ok(()) diff --git a/veilid-core/src/rpc_processor/coders/node_dial_info_single.rs b/veilid-core/src/rpc_processor/coders/node_dial_info_single.rs index 3711921b..c35dbaa4 100644 --- a/veilid-core/src/rpc_processor/coders/node_dial_info_single.rs +++ b/veilid-core/src/rpc_processor/coders/node_dial_info_single.rs @@ -15,10 +15,10 @@ pub fn encode_node_dial_info_single( pub fn decode_node_dial_info_single( reader: &veilid_capnp::node_dial_info_single::Reader, ) -> Result { - let node_id = decode_public_key(&reader.get_node_id().map_err(map_error_internal!( + let node_id = decode_public_key(&reader.get_node_id().map_err(map_error_protocol!( "invalid public key in node_dial_info_single" ))?); - let dial_info = decode_dial_info(&reader.get_dial_info().map_err(map_error_internal!( + let dial_info = decode_dial_info(&reader.get_dial_info().map_err(map_error_protocol!( "invalid dial_info in node_dial_info_single" ))?)?; diff --git a/veilid-core/src/rpc_processor/coders/peer_info.rs b/veilid-core/src/rpc_processor/coders/peer_info.rs index 144d99fe..77eec87a 100644 --- a/veilid-core/src/rpc_processor/coders/peer_info.rs +++ b/veilid-core/src/rpc_processor/coders/peer_info.rs @@ -15,7 +15,7 @@ pub fn encode_peer_info( .dial_infos .len() .try_into() - .map_err(map_error_internal!("too many dial infos in peer info"))?, + .map_err(map_error_protocol!("too many dial infos in peer info"))?, ); for idx in 0..peer_info.dial_infos.len() { @@ -38,7 +38,7 @@ pub fn decode_peer_info(reader: &veilid_capnp::peer_info::Reader) -> Result Result { - return Err(rpc_error_internal("invalid hops in safety route")); + return Err(rpc_error_protocol("invalid hops in safety route")); } }; diff --git a/veilid-core/src/rpc_processor/coders/public_key.rs b/veilid-core/src/rpc_processor/coders/public_key.rs index 858c73d7..aaa24217 100644 --- a/veilid-core/src/rpc_processor/coders/public_key.rs +++ b/veilid-core/src/rpc_processor/coders/public_key.rs @@ -23,27 +23,27 @@ pub fn encode_public_key( builder: &mut veilid_capnp::curve25519_public_key::Builder, ) -> Result<(), RPCError> { if !key.valid { - return Err(rpc_error_internal("invalid key")); + return Err(rpc_error_protocol("invalid key")); } builder.set_u0(u64::from_be_bytes( key.bytes[0..8] .try_into() - .map_err(map_error_internal!("slice with incorrect length"))?, + .map_err(map_error_protocol!("slice with incorrect length"))?, )); builder.set_u1(u64::from_be_bytes( key.bytes[8..16] .try_into() - .map_err(map_error_internal!("slice with incorrect length"))?, + .map_err(map_error_protocol!("slice with incorrect length"))?, )); builder.set_u2(u64::from_be_bytes( key.bytes[16..24] .try_into() - .map_err(map_error_internal!("slice with incorrect length"))?, + .map_err(map_error_protocol!("slice with incorrect length"))?, )); builder.set_u3(u64::from_be_bytes( key.bytes[24..32] .try_into() - .map_err(map_error_internal!("slice with incorrect length"))?, + .map_err(map_error_protocol!("slice with incorrect length"))?, )); Ok(()) } diff --git a/veilid-core/src/rpc_processor/coders/socket_address.rs b/veilid-core/src/rpc_processor/coders/socket_address.rs index f99e1482..ec9ae510 100644 --- a/veilid-core/src/rpc_processor/coders/socket_address.rs +++ b/veilid-core/src/rpc_processor/coders/socket_address.rs @@ -1,72 +1,25 @@ -use crate::xx::*; use crate::*; -use core::convert::TryInto; use rpc_processor::*; pub fn encode_socket_address( - address: &SocketAddr, + socket_address: &SocketAddress, builder: &mut veilid_capnp::socket_address::Builder, ) -> Result<(), RPCError> { - match address { - SocketAddr::V4(v4) => { - let mut v4b = builder.reborrow().init_ipv4(); - v4b.set_addr(u32::from_be_bytes(v4.ip().octets())); - builder.set_port(v4.port()); - } - SocketAddr::V6(v6) => { - let mut v6b = builder.reborrow().init_ipv6(); - v6b.set_addr0(u32::from_be_bytes( - v6.ip().octets()[0..4] - .try_into() - .expect("slice with incorrect length"), - )); - v6b.set_addr1(u32::from_be_bytes( - v6.ip().octets()[4..8] - .try_into() - .expect("slice with incorrect length"), - )); - v6b.set_addr2(u32::from_be_bytes( - v6.ip().octets()[8..12] - .try_into() - .expect("slice with incorrect length"), - )); - v6b.set_addr3(u32::from_be_bytes( - v6.ip().octets()[12..16] - .try_into() - .expect("slice with incorrect length"), - )); - builder.set_port(v6.port()); - } - }; + let mut ab = builder.reborrow().init_address(); + encode_address(&socket_address.address(), &mut ab)?; + builder.set_port(socket_address.port()); Ok(()) } pub fn decode_socket_address( reader: &veilid_capnp::socket_address::Reader, -) -> Result { - match reader.reborrow().which() { - Ok(veilid_capnp::socket_address::Which::Ipv4(Ok(v4))) => { - let v4b = v4.get_addr().to_be_bytes(); - Ok(SocketAddr::V4(SocketAddrV4::new( - Ipv4Addr::new(v4b[0], v4b[1], v4b[2], v4b[3]), - reader.get_port(), - ))) - } - Ok(veilid_capnp::socket_address::Which::Ipv6(Ok(v6))) => { - let v6b0 = v6.get_addr0().to_be_bytes(); - let v6b1 = v6.get_addr1().to_be_bytes(); - let v6b2 = v6.get_addr2().to_be_bytes(); - let v6b3 = v6.get_addr3().to_be_bytes(); - Ok(SocketAddr::V6(SocketAddrV6::new( - Ipv6Addr::from([ - v6b0[0], v6b0[1], v6b0[2], v6b0[3], v6b1[0], v6b1[1], v6b1[2], v6b1[3], - v6b2[0], v6b2[1], v6b2[2], v6b2[3], v6b3[0], v6b3[1], v6b3[2], v6b3[3], - ]), - reader.get_port(), - 0, - 0, - ))) - } - _ => Err(rpc_error_internal("invalid socket address type")), - } +) -> Result { + let ar = reader + .reborrow() + .get_address() + .map_err(map_error_internal!("missing socketAddress"))?; + let address = decode_address(&ar)?; + let port = reader.get_port(); + + Ok(SocketAddress::new(address, port)) } diff --git a/veilid-core/src/rpc_processor/debug.rs b/veilid-core/src/rpc_processor/debug.rs index b63c1fab..b1a8d7ac 100644 --- a/veilid-core/src/rpc_processor/debug.rs +++ b/veilid-core/src/rpc_processor/debug.rs @@ -12,8 +12,12 @@ pub fn rpc_error_internal>(x: T) -> RPCError { error!("RPCError Internal: {}", x.as_ref()); RPCError::Internal(x.as_ref().to_owned()) } +pub fn rpc_error_protocol>(x: T) -> RPCError { + error!("RPCError Protocol: {}", x.as_ref()); + RPCError::Protocol(x.as_ref().to_owned()) +} pub fn rpc_error_capnp_error(e: capnp::Error) -> RPCError { - error!("RPCError Protocol: {}", &e.description); + error!("RPCError Protocol: capnp error: {}", &e.description); RPCError::Protocol(e.description) } pub fn rpc_error_capnp_notinschema(e: capnp::NotInSchema) -> RPCError { @@ -44,12 +48,17 @@ macro_rules! map_error_internal { }; } #[macro_export] +macro_rules! map_error_protocol { + ($x:expr) => { + |_| rpc_error_protocol($x) + }; +} +#[macro_export] macro_rules! map_error_string { () => { |s| rpc_error_internal(&s) }; } - #[macro_export] macro_rules! map_error_capnp_error { () => { diff --git a/veilid-core/src/rpc_processor/mod.rs b/veilid-core/src/rpc_processor/mod.rs index c9f56d00..8786c147 100644 --- a/veilid-core/src/rpc_processor/mod.rs +++ b/veilid-core/src/rpc_processor/mod.rs @@ -779,7 +779,7 @@ impl RPCProcessor { .peer_noderef .operate(|entry| match entry.last_connection() { None => None, - Some(c) => c.remote.to_socket_addr().ok(), + Some(c) => Some(c.remote.to_socket_addr()), }); SenderInfo { socket_address } } @@ -955,7 +955,7 @@ impl RPCProcessor { let address_filter = self.config.get().network.address_filter; if address_filter { for di in &peer_info.dial_infos { - if !di.is_public().map_err(map_error_string!())? { + if !di.is_global() { // non-public address causes rejection return Err(RPCError::InvalidFormat); } @@ -1508,7 +1508,7 @@ impl RPCProcessor { // reject attempts to include non-public addresses in results if address_filter { for di in &peer_info.dial_infos { - if !di.is_public().map_err(map_error_string!())? { + if !di.is_global() { // non-public address causes rejection return Err(RPCError::InvalidFormat); } diff --git a/veilid-core/src/tests/common/test_connection_table.rs b/veilid-core/src/tests/common/test_connection_table.rs index 2df26e2e..4b589054 100644 --- a/veilid-core/src/tests/common/test_connection_table.rs +++ b/veilid-core/src/tests/common/test_connection_table.rs @@ -11,53 +11,48 @@ pub async fn test_add_get_remove() { let c3 = NetworkConnection::Dummy(DummyNetworkConnection {}); let a1 = ConnectionDescriptor::new_no_local(PeerAddress::new( - Address::IPV4(Ipv4Addr::new(127, 0, 0, 1)), - 8080, + SocketAddress::new(Address::IPV4(Ipv4Addr::new(127, 0, 0, 1)), 8080), ProtocolType::TCP, )); let a2 = ConnectionDescriptor::new_no_local(PeerAddress::new( - Address::IPV4(Ipv4Addr::new(127, 0, 0, 1)), - 8080, + SocketAddress::new(Address::IPV4(Ipv4Addr::new(127, 0, 0, 1)), 8080), ProtocolType::TCP, )); let a3 = ConnectionDescriptor::new( PeerAddress::new( - Address::IPV6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), - 8090, + SocketAddress::new(Address::IPV6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), 8090), ProtocolType::TCP, ), - SocketAddr::V6(SocketAddrV6::new( + SocketAddress::from_socket_addr(SocketAddr::V6(SocketAddrV6::new( Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0, - )), + ))), ); let a4 = ConnectionDescriptor::new( PeerAddress::new( - Address::IPV6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), - 8090, + SocketAddress::new(Address::IPV6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), 8090), ProtocolType::TCP, ), - SocketAddr::V6(SocketAddrV6::new( + SocketAddress::from_socket_addr(SocketAddr::V6(SocketAddrV6::new( Ipv6Addr::new(1, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0, - )), + ))), ); let a5 = ConnectionDescriptor::new( PeerAddress::new( - Address::Hostname("example.com".to_owned()), - 8090, + SocketAddress::new(Address::IPV6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), 8090), ProtocolType::WSS, ), - SocketAddr::V6(SocketAddrV6::new( + SocketAddress::from_socket_addr(SocketAddr::V6(SocketAddrV6::new( Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0, - )), + ))), ); assert_eq!(a1, a2); diff --git a/veilid-core/src/veilid_api/mod.rs b/veilid-core/src/veilid_api/mod.rs index e04ef010..152b5726 100644 --- a/veilid-core/src/veilid_api/mod.rs +++ b/veilid-core/src/veilid_api/mod.rs @@ -155,7 +155,7 @@ impl BlockId { #[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash, Default)] pub struct SenderInfo { - pub socket_address: Option, + pub socket_address: Option, } #[derive(Clone, Debug, Default)] @@ -173,6 +173,8 @@ pub struct NodeInfo { } #[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)] +// The derived ordering here is the order of preference, lower is preferred for connections +// Must match DialInfo order pub enum ProtocolType { UDP, TCP, @@ -181,11 +183,9 @@ pub enum ProtocolType { } #[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)] -pub enum ProtocolNetworkType { - UDPv4, - UDPv6, - TCPv4, - TCPv6, +pub enum AddressType { + IPV4, + IPV6, } #[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)] @@ -207,6 +207,12 @@ impl Address { SocketAddr::V6(v6) => Address::IPV6(*v6.ip()), } } + pub fn address_type(&self) -> AddressType { + match self { + Address::IPV4(v4) => AddressType::IPV4, + Address::IPV6(v6) => AddressType::IPV6, + } + } pub fn address_string(&self) -> String { match self { Address::IPV4(v4) => v4.to_string(), @@ -219,13 +225,13 @@ impl Address { Address::IPV6(v6) => format!("[{}]:{}", v6.to_string(), port), } } - pub fn is_public(&self) -> bool { + pub fn is_global(&self) -> bool { match self { Address::IPV4(v4) => ipv4addr_is_global(&v4), Address::IPV6(v6) => ipv6addr_is_global(&v6), } } - pub fn is_private(&self) -> bool { + pub fn is_local(&self) -> bool { match self { Address::IPV4(v4) => ipv4addr_is_private(&v4), Address::IPV6(v6) => ipv6addr_is_unicast_site_local(&v6), @@ -283,6 +289,9 @@ impl SocketAddress { pub fn address(&self) -> Address { self.address } + pub fn address_type(&self) -> AddressType { + self.address.address_type() + } pub fn port(&self) -> u16 { self.port } @@ -346,6 +355,8 @@ pub struct DialInfoWSS { } #[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq)] +// The derived ordering here is the order of preference, lower is preferred for connections +// Must match ProtocolType order pub enum DialInfo { UDP(DialInfoUDP), TCP(DialInfoTCP), @@ -479,25 +490,8 @@ impl DialInfo { Self::WSS(_) => ProtocolType::WSS, } } - pub fn protocol_network_type(&self) -> ProtocolNetworkType { - match self { - Self::UDP(di) => match di.socket_address.address() { - Address::IPV4(_) => ProtocolNetworkType::UDPv4, - Address::IPV6(_) => ProtocolNetworkType::UDPv6, - }, - Self::TCP(di) => match di.socket_address.address() { - Address::IPV4(_) => ProtocolNetworkType::TCPv4, - Address::IPV6(_) => ProtocolNetworkType::TCPv6, - }, - Self::WS(di) => match di.socket_address.address() { - Address::IPV4(_) => ProtocolNetworkType::TCPv4, - Address::IPV6(_) => ProtocolNetworkType::TCPv6, - }, - Self::WSS(di) => match di.socket_address.address() { - Address::IPV4(_) => ProtocolNetworkType::TCPv4, - Address::IPV6(_) => ProtocolNetworkType::TCPv6, - }, - } + pub fn address_type(&self) -> AddressType { + self.socket_address().address_type() } pub fn socket_address(&self) -> SocketAddress { match self { @@ -539,19 +533,24 @@ impl DialInfo { Self::WSS(di) => Some(format!("wss://{}", di.request)), } } - pub fn is_public(&self) -> bool { - self.socket_address().address().is_public() + pub fn is_global(&self) -> bool { + self.socket_address().address().is_global() } - - pub fn is_private(&self) -> bool { - self.socket_address().address().is_private() + pub fn is_local(&self) -> bool { + self.socket_address().address().is_local() } - pub fn is_valid(&self) -> bool { let socket_address = self.socket_address(); let address = socket_address.address(); let port = socket_address.port(); - (address.is_public() || address.is_private()) && port > 0 + (address.is_global() || address.is_local()) && port > 0 + } + pub fn matches_peer_scope(&self, scope: PeerScope) -> bool { + match scope { + PeerScope::All => true, + PeerScope::Global => self.is_global(), + PeerScope::Local => self.is_local(), + } } } @@ -579,7 +578,7 @@ pub struct PeerAddress { impl PeerAddress { pub fn new(socket_address: SocketAddress, protocol_type: ProtocolType) -> Self { Self { - socket_address, + socket_address: socket_address.to_canonical(), protocol_type, } } @@ -588,36 +587,19 @@ impl PeerAddress { self.socket_address.to_socket_addr() } - pub fn protocol_network_type(&self) -> ProtocolNetworkType { - match self.protocol_type { - ProtocolType::UDP => match self.socket_address.address() { - Address::IPV4(_) => ProtocolNetworkType::UDPv4, - Address::IPV6(_) => ProtocolNetworkType::UDPv6, - }, - ProtocolType::TCP => match self.socket_address.address() { - Address::IPV4(_) => ProtocolNetworkType::TCPv4, - Address::IPV6(_) => ProtocolNetworkType::TCPv6, - }, - ProtocolType::WS => match self.socket_address.address() { - Address::IPV4(_) => ProtocolNetworkType::TCPv4, - Address::IPV6(_) => ProtocolNetworkType::TCPv6, - }, - ProtocolType::WSS => match self.socket_address.address() { - Address::IPV4(_) => ProtocolNetworkType::TCPv4, - Address::IPV6(_) => ProtocolNetworkType::TCPv6, - }, - } + pub fn address_type(&self) -> AddressType { + self.socket_address.address_type() } } #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct ConnectionDescriptor { pub remote: PeerAddress, - pub local: Option, + pub local: Option, } impl ConnectionDescriptor { - pub fn new(remote: PeerAddress, local: SocketAddr) -> Self { + pub fn new(remote: PeerAddress, local: SocketAddress) -> Self { Self { remote, local: Some(local), @@ -632,8 +614,8 @@ impl ConnectionDescriptor { pub fn protocol_type(&self) -> ProtocolType { self.remote.protocol_type } - pub fn protocol_network_type(&self) -> ProtocolNetworkType { - self.remote.protocol_network_type() + pub fn address_type(&self) -> AddressType { + self.remote.address_type() } } @@ -1074,7 +1056,7 @@ impl VeilidAPI { let answer = node_ref.operate(|e| SearchDHTAnswer { node_id: NodeId::new(node_ref.node_id()), - dial_info: e.dial_info(), + dial_info: e.dial_infos().to_vec(), }); Ok(answer) @@ -1104,7 +1086,7 @@ impl VeilidAPI { for nr in node_refs { let a = nr.operate(|e| SearchDHTAnswer { node_id: NodeId::new(nr.node_id()), - dial_info: e.dial_info(), + dial_info: e.dial_infos().to_vec(), }); answer.push(a); }