diff --git a/doc/config/sample.config b/doc/config/sample.config index 4073e2c3..9310aef8 100644 --- a/doc/config/sample.config +++ b/doc/config/sample.config @@ -136,4 +136,6 @@ core: max_connections: 16 listen_address: ':5150' path: 'ws' - # url: '' \ No newline at end of file + # url: '' + privacy: + require_inbound_relay: false diff --git a/veilid-core/src/network_manager/address_check.rs b/veilid-core/src/network_manager/address_check.rs index 2fe10819..54bb9f4b 100644 --- a/veilid-core/src/network_manager/address_check.rs +++ b/veilid-core/src/network_manager/address_check.rs @@ -29,6 +29,7 @@ pub const ADDRESS_CHECK_CACHE_SIZE: usize = 10; pub struct AddressCheckConfig { pub detect_address_changes: bool, pub ip6_prefix_size: usize, + pub require_inbound_relay: bool, } #[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)] @@ -70,15 +71,18 @@ impl AddressCheck { pub fn new(net: Network) -> Self { let registry = net.registry(); - let (detect_address_changes, ip6_prefix_size) = registry.config().with(|c| { - ( - c.network.detect_address_changes, - c.network.max_connections_per_ip6_prefix_size as usize, - ) - }); + let (detect_address_changes, ip6_prefix_size, require_inbound_relay) = + registry.config().with(|c| { + ( + c.network.detect_address_changes, + c.network.max_connections_per_ip6_prefix_size as usize, + c.network.privacy.require_inbound_relay, + ) + }); let config = AddressCheckConfig { detect_address_changes, ip6_prefix_size, + require_inbound_relay, }; Self { @@ -202,6 +206,11 @@ impl AddressCheck { return; } + // Configured to only use relays for inbound connections. Thus, skip address detection. + if self.config.require_inbound_relay { + return; + } + // Process the state of the address checker and see if we need to // perform a full address check for this routing domain let needs_address_detection = match peer_info.signed_node_info().node_info().network_class() @@ -225,7 +234,7 @@ impl AddressCheck { }; if needs_address_detection { - if self.config.detect_address_changes { + if self.config.detect_address_changes && !self.config.require_inbound_relay { // Reset the address check cache now so we can start detecting fresh veilid_log!(self info "{:?} address has changed, detecting dial info", diff --git a/veilid-core/src/network_manager/connection_manager.rs b/veilid-core/src/network_manager/connection_manager.rs index c3134ea0..5047a18a 100644 --- a/veilid-core/src/network_manager/connection_manager.rs +++ b/veilid-core/src/network_manager/connection_manager.rs @@ -17,7 +17,7 @@ const NEW_CONNECTION_RETRY_DELAY_MS: u32 = 500; #[derive(Debug)] enum ConnectionManagerEvent { Accepted(ProtocolNetworkConnection), - Dead(NetworkConnection), + Dead(Box), } #[derive(Debug)] @@ -330,12 +330,16 @@ impl ConnectionManager { // Send it to be terminated #[cfg(feature = "verbose-tracing")] veilid_log!(self debug "== LRU kill connection due to limit: {:?}", conn.debug_print(Timestamp::now())); - let _ = inner.sender.send(ConnectionManagerEvent::Dead(conn)); + let _ = inner + .sender + .send(ConnectionManagerEvent::Dead(Box::new(conn))); } Err(ConnectionTableAddError::AddressFilter(conn, e)) => { // Connection filtered let desc = conn.flow(); - let _ = inner.sender.send(ConnectionManagerEvent::Dead(conn)); + let _ = inner + .sender + .send(ConnectionManagerEvent::Dead(Box::new(conn))); return Ok(NetworkResult::no_connection_other(format!( "connection filtered: {:?} ({})", desc, e @@ -345,7 +349,9 @@ impl ConnectionManager { // Connection already exists let desc = conn.flow(); veilid_log!(self debug "== Connection already exists: {:?}", conn.debug_print(Timestamp::now())); - let _ = inner.sender.send(ConnectionManagerEvent::Dead(conn)); + let _ = inner + .sender + .send(ConnectionManagerEvent::Dead(Box::new(conn))); return Ok(NetworkResult::no_connection_other(format!( "connection already exists: {:?}", desc @@ -355,7 +361,9 @@ impl ConnectionManager { // Connection table is full let desc = conn.flow(); veilid_log!(self debug "== Connection table full: {:?}", conn.debug_print(Timestamp::now())); - let _ = inner.sender.send(ConnectionManagerEvent::Dead(conn)); + let _ = inner + .sender + .send(ConnectionManagerEvent::Dead(Box::new(conn))); return Ok(NetworkResult::no_connection_other(format!( "connection table is full: {:?}", desc @@ -687,7 +695,7 @@ impl ConnectionManager { } } } - let _ = sender.send(ConnectionManagerEvent::Dead(conn)); + let _ = sender.send(ConnectionManagerEvent::Dead(Box::new(conn))); } } diff --git a/veilid-core/src/network_manager/native/discovery_context.rs b/veilid-core/src/network_manager/native/discovery_context.rs index 7f8b87fc..6707245e 100644 --- a/veilid-core/src/network_manager/native/discovery_context.rs +++ b/veilid-core/src/network_manager/native/discovery_context.rs @@ -884,7 +884,9 @@ impl DiscoveryContext { // UPNP Automatic Mapping /////////// - let enable_upnp = self.config().with(|c| c.network.upnp); + let enable_upnp = self + .config() + .with(|c| c.network.upnp && !c.network.privacy.require_inbound_relay); if enable_upnp { // Attempt a port mapping via all available and enabled mechanisms // Try this before the direct mapping in the event that we are restarting diff --git a/veilid-core/src/network_manager/native/mod.rs b/veilid-core/src/network_manager/native/mod.rs index e13a0aec..308957fb 100644 --- a/veilid-core/src/network_manager/native/mod.rs +++ b/veilid-core/src/network_manager/native/mod.rs @@ -768,7 +768,9 @@ impl Network { true, ); - let confirmed_public_internet = !self.config().with(|c| c.network.detect_address_changes); + let confirmed_public_internet = self + .config() + .with(|c| !c.network.detect_address_changes || c.network.privacy.require_inbound_relay); editor_public_internet.setup_network( network_state.protocol_config.outbound, network_state.protocol_config.inbound, @@ -836,9 +838,18 @@ impl Network { self.trigger_update_network_class(RoutingDomain::PublicInternet); } else { // Warn if we have no public dialinfo, because we're not going to magically find some - // with detect address changes turned off + // with detect_address_changes turned off. Skip the warning if require_inbound_relay is + // enabled, this option intentionally disables publishing any dialinfo. let pi = routing_table.get_current_peer_info(RoutingDomain::PublicInternet); - if !pi.signed_node_info().has_any_dial_info() { + if !pi.signed_node_info().has_any_dial_info() + && !self + .registry + .config() + .get() + .network + .privacy + .require_inbound_relay + { veilid_log!(self warn "This node has no valid public dial info.\nConfigure this node with a static public IP address and correct firewall rules." ); diff --git a/veilid-core/src/network_manager/native/start_protocols.rs b/veilid-core/src/network_manager/native/start_protocols.rs index a8e82c53..6536f90d 100644 --- a/veilid-core/src/network_manager/native/start_protocols.rs +++ b/veilid-core/src/network_manager/native/start_protocols.rs @@ -140,13 +140,15 @@ impl Network { #[instrument(level = "trace", skip_all)] pub(super) async fn bind_udp_protocol_handlers(&self) -> EyreResult { veilid_log!(self trace "UDP: binding protocol handlers"); - let (listen_address, public_address, detect_address_changes) = self.config().with(|c| { - ( - c.network.protocol.udp.listen_address.clone(), - c.network.protocol.udp.public_address.clone(), - c.network.detect_address_changes, - ) - }); + let (listen_address, public_address, detect_address_changes, require_inbound_relay) = + self.config().with(|c| { + ( + c.network.protocol.udp.listen_address.clone(), + c.network.protocol.udp.public_address.clone(), + c.network.detect_address_changes, + c.network.privacy.require_inbound_relay, + ) + }); // Get the binding parameters from the user-specified listen address let bind_set = self @@ -175,7 +177,7 @@ impl Network { { let mut inner = self.inner.lock(); - if public_address.is_some() && !detect_address_changes { + if public_address.is_some() && !detect_address_changes && !require_inbound_relay { inner.static_public_dial_info.insert(ProtocolType::UDP); } } @@ -191,12 +193,14 @@ impl Network { ) -> EyreResult<()> { veilid_log!(self trace "UDP: registering dial info"); - let (public_address, detect_address_changes) = self.config().with(|c| { - ( - c.network.protocol.udp.public_address.clone(), - c.network.detect_address_changes, - ) - }); + let (public_address, detect_address_changes, require_inbound_relay) = + self.config().with(|c| { + ( + c.network.protocol.udp.public_address.clone(), + c.network.detect_address_changes, + c.network.privacy.require_inbound_relay, + ) + }); let local_dial_info_list = { let mut out = vec![]; @@ -220,7 +224,7 @@ impl Network { }; // Add static public dialinfo if it's configured - if let Some(public_address) = public_address.as_ref() { + if let (Some(public_address), false) = (public_address.as_ref(), require_inbound_relay) { // Resolve statically configured public dialinfo let mut public_sockaddrs = public_address .to_socket_addrs() @@ -247,7 +251,11 @@ impl Network { for di in &local_dial_info_list { // If the local interface address is global, then register global dial info // if no other public address is specified - if !detect_address_changes && public_address.is_none() && di.address().is_global() { + if !detect_address_changes + && !require_inbound_relay + && public_address.is_none() + && di.address().is_global() + { editor_public_internet.add_dial_info(di.clone(), DialInfoClass::Direct); } @@ -261,13 +269,15 @@ impl Network { #[instrument(level = "trace", skip_all)] pub(super) async fn start_ws_listeners(&self) -> EyreResult { veilid_log!(self trace "WS: binding protocol handlers"); - let (listen_address, url, detect_address_changes) = self.config().with(|c| { - ( - c.network.protocol.ws.listen_address.clone(), - c.network.protocol.ws.url.clone(), - c.network.detect_address_changes, - ) - }); + let (listen_address, url, detect_address_changes, require_inbound_relay) = + self.config().with(|c| { + ( + c.network.protocol.ws.listen_address.clone(), + c.network.protocol.ws.url.clone(), + c.network.detect_address_changes, + c.network.privacy.require_inbound_relay, + ) + }); // Get the binding parameters from the user-specified listen address let bind_set = self @@ -299,7 +309,7 @@ impl Network { { let mut inner = self.inner.lock(); - if url.is_some() && !detect_address_changes { + if url.is_some() && !detect_address_changes && !require_inbound_relay { inner.static_public_dial_info.insert(ProtocolType::WS); } } @@ -314,11 +324,12 @@ impl Network { editor_local_network: &mut RoutingDomainEditorLocalNetwork<'_>, ) -> EyreResult<()> { veilid_log!(self trace "WS: registering dial info"); - let (url, path, detect_address_changes) = self.config().with(|c| { + let (url, path, detect_address_changes, require_inbound_relay) = self.config().with(|c| { ( c.network.protocol.ws.url.clone(), c.network.protocol.ws.path.clone(), c.network.detect_address_changes, + c.network.privacy.require_inbound_relay, ) }); @@ -389,7 +400,11 @@ impl Network { let local_di = DialInfo::try_ws(*socket_address, local_url).wrap_err("try_ws failed")?; - if !detect_address_changes && url.is_none() && local_di.address().is_global() { + if !detect_address_changes + && !require_inbound_relay + && url.is_none() + && local_di.address().is_global() + { // Register public dial info editor_public_internet.add_dial_info(local_di.clone(), DialInfoClass::Direct); } @@ -405,13 +420,15 @@ impl Network { pub(super) async fn start_wss_listeners(&self) -> EyreResult { veilid_log!(self trace "WSS: binding protocol handlers"); - let (listen_address, url, detect_address_changes) = self.config().with(|c| { - ( - c.network.protocol.wss.listen_address.clone(), - c.network.protocol.wss.url.clone(), - c.network.detect_address_changes, - ) - }); + let (listen_address, url, detect_address_changes, require_inbound_relay) = + self.config().with(|c| { + ( + c.network.protocol.wss.listen_address.clone(), + c.network.protocol.wss.url.clone(), + c.network.detect_address_changes, + c.network.privacy.require_inbound_relay, + ) + }); // Get the binding parameters from the user-specified listen address let bind_set = self @@ -444,7 +461,7 @@ impl Network { { let mut inner = self.inner.lock(); - if url.is_some() && !detect_address_changes { + if url.is_some() && !detect_address_changes && !require_inbound_relay { inner.static_public_dial_info.insert(ProtocolType::WSS); } } @@ -514,13 +531,15 @@ impl Network { pub(super) async fn start_tcp_listeners(&self) -> EyreResult { veilid_log!(self trace "TCP: binding protocol handlers"); - let (listen_address, public_address, detect_address_changes) = self.config().with(|c| { - ( - c.network.protocol.tcp.listen_address.clone(), - c.network.protocol.tcp.public_address.clone(), - c.network.detect_address_changes, - ) - }); + let (listen_address, public_address, detect_address_changes, require_inbound_relay) = + self.config().with(|c| { + ( + c.network.protocol.tcp.listen_address.clone(), + c.network.protocol.tcp.public_address.clone(), + c.network.detect_address_changes, + c.network.privacy.require_inbound_relay, + ) + }); // Get the binding parameters from the user-specified listen address let bind_set = self @@ -552,7 +571,7 @@ impl Network { { let mut inner = self.inner.lock(); - if public_address.is_some() && !detect_address_changes { + if public_address.is_some() && !detect_address_changes && !require_inbound_relay { inner.static_public_dial_info.insert(ProtocolType::TCP); } } @@ -568,12 +587,14 @@ impl Network { ) -> EyreResult<()> { veilid_log!(self trace "TCP: registering dialinfo"); - let (public_address, detect_address_changes) = self.config().with(|c| { - ( - c.network.protocol.tcp.public_address.clone(), - c.network.detect_address_changes, - ) - }); + let (public_address, detect_address_changes, require_inbound_relay) = + self.config().with(|c| { + ( + c.network.protocol.tcp.public_address.clone(), + c.network.detect_address_changes, + c.network.privacy.require_inbound_relay, + ) + }); let mut registered_addresses: HashSet = HashSet::new(); @@ -602,7 +623,7 @@ impl Network { }; // Add static public dialinfo if it's configured - if let Some(public_address) = public_address.as_ref() { + if let (Some(public_address), false) = (public_address.as_ref(), require_inbound_relay) { // Resolve statically configured public dialinfo let mut public_sockaddrs = public_address .to_socket_addrs() @@ -629,7 +650,11 @@ impl Network { let di = DialInfo::tcp(*socket_address); // Register global dial info if no public address is specified - if !detect_address_changes && public_address.is_none() && di.address().is_global() { + if !detect_address_changes + && !require_inbound_relay + && public_address.is_none() + && di.address().is_global() + { editor_public_internet.add_dial_info(di.clone(), DialInfoClass::Direct); } // Register interface dial info diff --git a/veilid-core/src/network_manager/native/tasks/mod.rs b/veilid-core/src/network_manager/native/tasks/mod.rs index cecbb075..bfb15abb 100644 --- a/veilid-core/src/network_manager/native/tasks/mod.rs +++ b/veilid-core/src/network_manager/native/tasks/mod.rs @@ -87,12 +87,22 @@ impl Network { return Ok(()); } - let (detect_address_changes, upnp) = { + let (detect_address_changes, upnp, require_inbound_relay) = { let config = self.network_manager().config(); let c = config.get(); - (c.network.detect_address_changes, c.network.upnp) + ( + c.network.detect_address_changes, + c.network.upnp, + c.network.privacy.require_inbound_relay, + ) }; + if require_inbound_relay { + // Configured to only use relays for inbound connections. + // This implicitly turns off address detection and upnp. + return Ok(()); + } + // If we need to figure out our network class, tick the task for it if detect_address_changes { // Check our network interfaces to see if they have changed diff --git a/veilid-core/src/routing_table/route_spec_store/mod.rs b/veilid-core/src/routing_table/route_spec_store/mod.rs index 26b2e23a..8de3d89b 100644 --- a/veilid-core/src/routing_table/route_spec_store/mod.rs +++ b/veilid-core/src/routing_table/route_spec_store/mod.rs @@ -287,60 +287,46 @@ impl RouteSpecStore { let geolocation_info = sni.get_geolocation_info(RoutingDomain::PublicInternet); - // Since denylist is used, consider nodes with unknown countries to be automatically - // excluded as well - if geolocation_info.country_code().is_none() { + // Since denylist is used, consider nodes with unknown countries to be automatically excluded + let Some(node_country_code) = geolocation_info.country_code() else { veilid_log!(self - debug "allocate_route_inner: skipping node {} from unknown country", + debug "allocate_route_inner: skipping node {:?} from unknown country", e.best_node_id() ); return false; - } - // Same thing applies to relays used by the node - if geolocation_info - .relay_country_codes() - .iter() - .any(Option::is_none) - { + }; + // The same thing applies to relays used by the node + // They must all be from a known country + let relay_country_codes: Option> = geolocation_info.relay_country_codes().iter().cloned().collect(); + let Some(relay_country_codes) = relay_country_codes else { veilid_log!(self - debug "allocate_route_inner: skipping node {} using relay from unknown country", + debug "allocate_route_inner: skipping node {:?} using relay from unknown country", e.best_node_id() ); return false; - } + }; // Ensure that node is not excluded - // Safe to unwrap here, checked above - if country_code_denylist.contains(&geolocation_info.country_code().unwrap()) + if country_code_denylist.contains(&node_country_code) { veilid_log!(self - debug "allocate_route_inner: skipping node {} from excluded country {}", + debug "allocate_route_inner: skipping node {:?} from excluded country {}", e.best_node_id(), - geolocation_info.country_code().unwrap() + node_country_code ); return false; } // Ensure that node relays are not excluded - // Safe to unwrap here, checked above - if geolocation_info - .relay_country_codes() + if let Some(cc) = relay_country_codes .iter() - .cloned() - .map(Option::unwrap) - .any(|cc| country_code_denylist.contains(&cc)) + .filter(|cc| country_code_denylist.contains(cc)) + .next() { veilid_log!(self - debug "allocate_route_inner: skipping node {} using relay from excluded country {:?}", + debug "allocate_route_inner: skipping node {:?} using relay from excluded country {}", e.best_node_id(), - geolocation_info - .relay_country_codes() - .iter() - .cloned() - .map(Option::unwrap) - .filter(|cc| country_code_denylist.contains(&cc)) - .next() - .unwrap() + cc ); return false; } diff --git a/veilid-core/src/table_store/table_db.rs b/veilid-core/src/table_store/table_db.rs index 5c9fb132..b3467cbc 100644 --- a/veilid-core/src/table_store/table_db.rs +++ b/veilid-core/src/table_store/table_db.rs @@ -178,11 +178,9 @@ impl TableDB { &Nonce::try_from(&data[0..NONCE_LENGTH]).unwrap(), &di.typed_key.value, ); - decompress_size_prepended(&out, None) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string())) + decompress_size_prepended(&out, None).map_err(|e| std::io::Error::other(e.to_string())) } else { - decompress_size_prepended(data, None) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string())) + decompress_size_prepended(data, None).map_err(|e| std::io::Error::other(e.to_string())) } } diff --git a/veilid-core/src/tests/common/test_veilid_config.rs b/veilid-core/src/tests/common/test_veilid_config.rs index 951f7618..7ae509c8 100644 --- a/veilid-core/src/tests/common/test_veilid_config.rs +++ b/veilid-core/src/tests/common/test_veilid_config.rs @@ -289,6 +289,7 @@ pub fn config_callback(key: String) -> ConfigCallbackReturn { "network.protocol.wss.listen_address" => Ok(Box::new("".to_owned())), "network.protocol.wss.path" => Ok(Box::new(String::from("ws"))), "network.protocol.wss.url" => Ok(Box::new(Option::::None)), + "network.privacy.require_inbound_relay" => Ok(Box::new(false)), #[cfg(feature = "geolocation")] "network.privacy.country_code_denylist" => Ok(Box::new(Vec::::new())), #[cfg(feature = "virtual-network")] @@ -436,6 +437,7 @@ pub fn test_config() { assert_eq!(inner.network.protocol.wss.path, "ws"); assert_eq!(inner.network.protocol.wss.url, None); + assert!(!inner.network.privacy.require_inbound_relay); #[cfg(feature = "geolocation")] assert_eq!(inner.network.privacy.country_code_denylist, Vec::new()); #[cfg(feature = "virtual-network")] diff --git a/veilid-core/src/veilid_api/tests/fixtures.rs b/veilid-core/src/veilid_api/tests/fixtures.rs index 00a23521..ce91e54a 100644 --- a/veilid-core/src/veilid_api/tests/fixtures.rs +++ b/veilid-core/src/veilid_api/tests/fixtures.rs @@ -280,8 +280,9 @@ pub fn fix_veilidconfig() -> VeilidConfig { url: Some("https://veilid.com/wss".to_string()), }, }, - #[cfg(feature = "geolocation")] privacy: VeilidConfigPrivacy { + require_inbound_relay: false, + #[cfg(feature = "geolocation")] country_code_denylist: vec![CountryCode::from_str("NZ").unwrap()], }, #[cfg(feature = "virtual-network")] diff --git a/veilid-core/src/veilid_config.rs b/veilid-core/src/veilid_config.rs index 1ac82af2..2295037c 100644 --- a/veilid-core/src/veilid_config.rs +++ b/veilid-core/src/veilid_config.rs @@ -285,25 +285,18 @@ pub struct VeilidConfigProtocol { /// /// ```yaml /// privacy: -/// country_code_denylist: [] +/// require_inbound_relay: false +/// country_code_denylist: [] # only with `--features=geolocation` /// ``` -#[cfg(feature = "geolocation")] -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] +#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] #[cfg_attr(target_arch = "wasm32", derive(Tsify))] #[must_use] pub struct VeilidConfigPrivacy { + pub require_inbound_relay: bool, + #[cfg(feature = "geolocation")] pub country_code_denylist: Vec, } -#[cfg(feature = "geolocation")] -impl Default for VeilidConfigPrivacy { - fn default() -> Self { - Self { - country_code_denylist: Vec::new(), - } - } -} - /// Virtual networking client support for testing/simulation purposes /// /// ```yaml @@ -568,7 +561,6 @@ pub struct VeilidConfigNetwork { pub tls: VeilidConfigTLS, pub application: VeilidConfigApplication, pub protocol: VeilidConfigProtocol, - #[cfg(feature = "geolocation")] pub privacy: VeilidConfigPrivacy, #[cfg(feature = "virtual-network")] pub virtual_network: VeilidConfigVirtualNetwork, @@ -596,7 +588,6 @@ impl Default for VeilidConfigNetwork { tls: VeilidConfigTLS::default(), application: VeilidConfigApplication::default(), protocol: VeilidConfigProtocol::default(), - #[cfg(feature = "geolocation")] privacy: VeilidConfigPrivacy::default(), #[cfg(feature = "virtual-network")] virtual_network: VeilidConfigVirtualNetwork::default(), @@ -1049,6 +1040,7 @@ impl VeilidStartupOptions { get_config!(inner.network.protocol.wss.listen_address); get_config!(inner.network.protocol.wss.path); get_config!(inner.network.protocol.wss.url); + get_config!(inner.network.privacy.require_inbound_relay); #[cfg(feature = "geolocation")] get_config!(inner.network.privacy.country_code_denylist); #[cfg(feature = "virtual-network")] diff --git a/veilid-python/veilid/config.py b/veilid-python/veilid/config.py index e7fdd28b..64a90fd4 100644 --- a/veilid-python/veilid/config.py +++ b/veilid-python/veilid/config.py @@ -189,6 +189,11 @@ class VeilidConfigProtocol(ConfigBase): wss: VeilidConfigWSS +@dataclass +class VeilidConfigPrivacy(ConfigBase): + require_inbound_relay: bool + + @dataclass class VeilidConfigNetwork(ConfigBase): connection_initial_timeout_ms: int @@ -210,6 +215,7 @@ class VeilidConfigNetwork(ConfigBase): tls: VeilidConfigTLS application: VeilidConfigApplication protocol: VeilidConfigProtocol + privacy: VeilidConfigPrivacy @dataclass diff --git a/veilid-python/veilid/schema/RecvMessage.json b/veilid-python/veilid/schema/RecvMessage.json index 0b22cae9..b51fd5c6 100644 --- a/veilid-python/veilid/schema/RecvMessage.json +++ b/veilid-python/veilid/schema/RecvMessage.json @@ -4267,6 +4267,7 @@ "max_connections_per_ip4", "max_connections_per_ip6_prefix", "max_connections_per_ip6_prefix_size", + "privacy", "protocol", "restricted_nat_retries", "reverse_connection_receipt_time_ms", @@ -4331,6 +4332,9 @@ "null" ] }, + "privacy": { + "$ref": "#/definitions/VeilidConfigPrivacy" + }, "protocol": { "$ref": "#/definitions/VeilidConfigProtocol" }, @@ -4358,6 +4362,18 @@ } } }, + "VeilidConfigPrivacy": { + "description": "Privacy preferences for routes.\n\n```yaml privacy: require_inbound_relay: false country_code_denylist: [] # only with `--features=geolocation` ```", + "type": "object", + "required": [ + "require_inbound_relay" + ], + "properties": { + "require_inbound_relay": { + "type": "boolean" + } + } + }, "VeilidConfigProtectedStore": { "type": "object", "required": [ diff --git a/veilid-server/src/settings.rs b/veilid-server/src/settings.rs index c835ea79..2c6b5369 100644 --- a/veilid-server/src/settings.rs +++ b/veilid-server/src/settings.rs @@ -35,10 +35,9 @@ pub const PROGRAM_NAME: &str = "veilid-server"; pub fn load_default_config() -> EyreResult { #[cfg(not(feature = "geolocation"))] - let privacy_section = ""; + let privacy_geolocation_section = ""; #[cfg(feature = "geolocation")] - let privacy_section = r#" - privacy: + let privacy_geolocation_section = r#" country_code_denylist: [] "#; @@ -224,8 +223,10 @@ core: listen_address: ':5150' path: 'ws' # url: '' + privacy: + require_inbound_relay: false + %PRIVACY_GEOLOCATION_SECTION% %VIRTUAL_NETWORK_SECTION% - %PRIVACY_SECTION% "#, ) .replace( @@ -256,7 +257,7 @@ core: "%REMOTE_MAX_SUBKEY_CACHE_MEMORY_MB%", &Settings::get_default_remote_max_subkey_cache_memory_mb().to_string(), ) - .replace("%PRIVACY_SECTION%", privacy_section) + .replace("%PRIVACY_GEOLOCATION_SECTION%", privacy_geolocation_section) .replace("%VIRTUAL_NETWORK_SECTION%", virtual_network_section) .replace( "%VIRTUAL_NETWORK_SERVER_SECTION%", @@ -646,9 +647,10 @@ pub struct Protocol { pub wss: Wss, } -#[cfg(feature = "geolocation")] #[derive(Debug, Deserialize, Serialize)] pub struct Privacy { + pub require_inbound_relay: bool, + #[cfg(feature = "geolocation")] pub country_code_denylist: Vec, } @@ -730,7 +732,6 @@ pub struct Network { pub tls: Tls, pub application: Application, pub protocol: Protocol, - #[cfg(feature = "geolocation")] pub privacy: Privacy, #[cfg(feature = "virtual-network")] pub virtual_network: VirtualNetwork, @@ -1252,6 +1253,7 @@ impl Settings { set_config_value!(inner.core.network.protocol.wss.listen_address, value); set_config_value!(inner.core.network.protocol.wss.path, value); set_config_value!(inner.core.network.protocol.wss.url, value); + set_config_value!(inner.core.network.privacy.require_inbound_relay, value); #[cfg(feature = "geolocation")] set_config_value!(inner.core.network.privacy.country_code_denylist, value); #[cfg(feature = "virtual-network")] @@ -1689,6 +1691,9 @@ impl Settings { None => None, })) } + "network.privacy.require_inbound_relay" => { + Ok(Box::new(inner.core.network.privacy.require_inbound_relay)) + } #[cfg(feature = "geolocation")] "network.privacy.country_code_denylist" => Ok(Box::new( inner.core.network.privacy.country_code_denylist.clone(), @@ -1981,6 +1986,7 @@ mod tests { ); assert_eq!(s.core.network.protocol.wss.url, None); // + assert_eq!(s.core.network.privacy.require_inbound_relay, false); #[cfg(feature = "geolocation")] assert_eq!(s.core.network.privacy.country_code_denylist, &[]); #[cfg(feature = "virtual-network")] diff --git a/veilid-tools/src/async_peek_stream.rs b/veilid-tools/src/async_peek_stream.rs index 19bd490d..07fa7a0d 100644 --- a/veilid-tools/src/async_peek_stream.rs +++ b/veilid-tools/src/async_peek_stream.rs @@ -157,11 +157,7 @@ impl AsyncRead for AsyncPeekStream { // let buflen = buf.len(); let bufcopylen = core::cmp::min(buflen, inner.peekbuf_len); - let bufreadlen = if buflen > inner.peekbuf_len { - buflen - inner.peekbuf_len - } else { - 0 - }; + let bufreadlen = buflen.saturating_sub(inner.peekbuf_len); if bufreadlen > 0 { match Pin::new(&mut inner.stream).poll_read(cx, &mut buf[bufcopylen..buflen]) { diff --git a/veilid-tools/src/network_result.rs b/veilid-tools/src/network_result.rs index 89ccf1f8..14ce4c7b 100644 --- a/veilid-tools/src/network_result.rs +++ b/veilid-tools/src/network_result.rs @@ -131,7 +131,7 @@ impl NetworkResult { Self::NoConnection(e) } pub fn no_connection_other(s: S) -> Self { - Self::NoConnection(io::Error::new(io::ErrorKind::Other, s.to_string())) + Self::NoConnection(io::Error::other(s.to_string())) } pub fn invalid_message(s: S) -> Self { Self::InvalidMessage(s.to_string()) diff --git a/veilid-tools/src/tools.rs b/veilid-tools/src/tools.rs index fdf51408..c92ab07d 100644 --- a/veilid-tools/src/tools.rs +++ b/veilid-tools/src/tools.rs @@ -22,7 +22,7 @@ macro_rules! io_error_other { } pub fn to_io_error_other(x: E) -> io::Error { - io::Error::new(io::ErrorKind::Other, x) + io::Error::other(x) } #[macro_export]