From 0249b7c7aebdf65e519477edcd4c1ec528e8772d Mon Sep 17 00:00:00 2001 From: Christien Rioux Date: Mon, 21 Aug 2023 21:04:21 -0400 Subject: [PATCH 1/5] dial info failure reprioritization --- veilid-core/src/lib.rs | 4 +- .../src/network_manager/address_filter.rs | 61 ++++ veilid-core/src/network_manager/mod.rs | 3 + veilid-core/src/network_manager/native/mod.rs | 327 ++++++++++-------- veilid-core/src/network_manager/send_data.rs | 19 + veilid-core/src/network_manager/wasm/mod.rs | 220 +++++++----- veilid-core/src/routing_table/mod.rs | 2 + .../route_spec_store/route_spec_store.rs | 4 + .../src/routing_table/routing_domains.rs | 71 +++- .../src/routing_table/routing_table_inner.rs | 3 +- veilid-flutter/example/pubspec.lock | 2 +- 11 files changed, 452 insertions(+), 264 deletions(-) diff --git a/veilid-core/src/lib.rs b/veilid-core/src/lib.rs index 2446cfe4..ce93567c 100644 --- a/veilid-core/src/lib.rs +++ b/veilid-core/src/lib.rs @@ -61,7 +61,7 @@ pub fn veilid_version() -> (u32, u32, u32) { #[cfg(target_os = "android")] pub use intf::android::veilid_core_setup_android; -pub static DEFAULT_LOG_IGNORE_LIST: [&str; 21] = [ +pub static DEFAULT_LOG_IGNORE_LIST: [&str; 23] = [ "mio", "h2", "hyper", @@ -83,6 +83,8 @@ pub static DEFAULT_LOG_IGNORE_LIST: [&str; 21] = [ "trust_dns_resolver", "trust_dns_proto", "attohttpc", + "ws_stream_wasm", + "keyvaluedb_web", ]; use cfg_if::*; diff --git a/veilid-core/src/network_manager/address_filter.rs b/veilid-core/src/network_manager/address_filter.rs index 417ebd4e..5b17e3d0 100644 --- a/veilid-core/src/network_manager/address_filter.rs +++ b/veilid-core/src/network_manager/address_filter.rs @@ -4,6 +4,8 @@ use alloc::collections::btree_map::Entry; // XXX: Move to config eventually? const PUNISHMENT_DURATION_MIN: usize = 60; const MAX_PUNISHMENTS_BY_NODE_ID: usize = 65536; +const DIAL_INFO_FAILURE_DURATION_MIN: usize = 10; +const MAX_DIAL_INFO_FAILURES: usize = 65536; #[derive(ThisError, Debug, Clone, Copy, PartialEq, Eq)] pub enum AddressFilterError { @@ -28,6 +30,7 @@ struct AddressFilterInner { punishments_by_ip4: BTreeMap, punishments_by_ip6_prefix: BTreeMap, punishments_by_node_id: BTreeMap, + dial_info_failures: BTreeMap, } struct AddressFilterUnlockedInner { @@ -36,6 +39,7 @@ struct AddressFilterUnlockedInner { max_connections_per_ip6_prefix_size: usize, max_connection_frequency_per_min: usize, punishment_duration_min: usize, + dial_info_failure_duration_min: usize, routing_table: RoutingTable, } @@ -56,6 +60,10 @@ impl fmt::Debug for AddressFilterUnlockedInner { &self.max_connection_frequency_per_min, ) .field("punishment_duration_min", &self.punishment_duration_min) + .field( + "dial_info_failure_duration_min", + &self.dial_info_failure_duration_min, + ) .finish() } } @@ -78,6 +86,7 @@ impl AddressFilter { max_connection_frequency_per_min: c.network.max_connection_frequency_per_min as usize, punishment_duration_min: PUNISHMENT_DURATION_MIN, + dial_info_failure_duration_min: DIAL_INFO_FAILURE_DURATION_MIN, routing_table, }), inner: Arc::new(Mutex::new(AddressFilterInner { @@ -88,10 +97,17 @@ impl AddressFilter { punishments_by_ip4: BTreeMap::new(), punishments_by_ip6_prefix: BTreeMap::new(), punishments_by_node_id: BTreeMap::new(), + dial_info_failures: BTreeMap::new(), })), } } + // When the network restarts, some of the address filter can be cleared + pub fn restart(&self) { + let mut inner = self.inner.lock(); + inner.dial_info_failures.clear(); + } + fn purge_old_timestamps(&self, inner: &mut AddressFilterInner, cur_ts: Timestamp) { // v4 { @@ -180,6 +196,22 @@ impl AddressFilter { } } } + // dial info + { + let mut dead_keys = Vec::::new(); + for (key, value) in &mut inner.dial_info_failures { + // Drop failures older than the failure duration + if cur_ts.as_u64().saturating_sub(value.as_u64()) + > self.unlocked_inner.dial_info_failure_duration_min as u64 * 60_000_000u64 + { + dead_keys.push(key.clone()); + } + } + for key in dead_keys { + log_net!(debug ">>> DIALINFO PERMIT: {}", key); + inner.dial_info_failures.remove(&key); + } + } } fn is_ip_addr_punished_inner(&self, inner: &AddressFilterInner, ipblock: IpAddr) -> bool { @@ -198,6 +230,14 @@ impl AddressFilter { false } + fn get_dial_info_failed_ts_inner( + &self, + inner: &AddressFilterInner, + dial_info: &DialInfo, + ) -> Option { + inner.dial_info_failures.get(dial_info).copied() + } + pub fn is_ip_addr_punished(&self, addr: IpAddr) -> bool { let inner = self.inner.lock(); let ipblock = ip_to_ipblock( @@ -207,6 +247,27 @@ impl AddressFilter { self.is_ip_addr_punished_inner(&*inner, ipblock) } + pub fn get_dial_info_failed_ts(&self, dial_info: &DialInfo) -> Option { + let inner = self.inner.lock(); + self.get_dial_info_failed_ts_inner(&*inner, dial_info) + } + + pub fn set_dial_info_failed(&self, dial_info: DialInfo) { + let ts = get_aligned_timestamp(); + + let mut inner = self.inner.lock(); + if inner.dial_info_failures.len() >= MAX_DIAL_INFO_FAILURES { + log_net!(debug ">>> DIALINFO FAILURE TABLE FULL: {}", dial_info); + return; + } + log_net!(debug ">>> DIALINFO FAILURE: {:?}", dial_info); + inner + .dial_info_failures + .entry(dial_info) + .and_modify(|v| *v = ts) + .or_insert(ts); + } + pub fn punish_ip_addr(&self, addr: IpAddr) { log_net!(debug ">>> PUNISHED: {}", addr); let ts = get_aligned_timestamp(); diff --git a/veilid-core/src/network_manager/mod.rs b/veilid-core/src/network_manager/mod.rs index a36569bb..6d36a8bd 100644 --- a/veilid-core/src/network_manager/mod.rs +++ b/veilid-core/src/network_manager/mod.rs @@ -380,6 +380,9 @@ impl NetworkManager { return Ok(()); } + // Clean address filter for things that should not be persistent + self.address_filter().restart(); + // Create network components let connection_manager = ConnectionManager::new(self.clone()); let net = Network::new( diff --git a/veilid-core/src/network_manager/native/mod.rs b/veilid-core/src/network_manager/native/mod.rs index e39220ed..1cc1e7b1 100644 --- a/veilid-core/src/network_manager/native/mod.rs +++ b/veilid-core/src/network_manager/native/mod.rs @@ -384,6 +384,21 @@ impl Network { //////////////////////////////////////////////////////////// + // Record DialInfo failures + pub async fn record_dial_info_failure>>>( + &self, + dial_info: DialInfo, + fut: F, + ) -> EyreResult> { + let network_result = fut.await?; + if matches!(network_result, NetworkResult::NoConnection(_)) { + self.network_manager() + .address_filter() + .set_dial_info_failed(dial_info); + } + Ok(network_result) + } + // Send data to a dial info, unbound, using a new connection from a random port // This creates a short-lived connection in the case of connection-oriented protocols // for the purpose of sending this one message. @@ -394,59 +409,62 @@ impl Network { dial_info: DialInfo, data: Vec, ) -> EyreResult> { - let data_len = data.len(); - let connect_timeout_ms = { - let c = self.config.get(); - c.network.connection_initial_timeout_ms - }; + self.record_dial_info_failure(dial_info.clone(), async move { + let data_len = data.len(); + let connect_timeout_ms = { + let c = self.config.get(); + c.network.connection_initial_timeout_ms + }; - if self - .network_manager() - .address_filter() - .is_ip_addr_punished(dial_info.address().to_ip_addr()) - { - return Ok(NetworkResult::no_connection_other("punished")); - } + if self + .network_manager() + .address_filter() + .is_ip_addr_punished(dial_info.address().to_ip_addr()) + { + return Ok(NetworkResult::no_connection_other("punished")); + } - match dial_info.protocol_type() { - ProtocolType::UDP => { - let peer_socket_addr = dial_info.to_socket_addr(); - let h = RawUdpProtocolHandler::new_unspecified_bound_handler(&peer_socket_addr) + match dial_info.protocol_type() { + ProtocolType::UDP => { + let peer_socket_addr = dial_info.to_socket_addr(); + let h = RawUdpProtocolHandler::new_unspecified_bound_handler(&peer_socket_addr) + .await + .wrap_err("create socket failure")?; + let _ = network_result_try!(h + .send_message(data, peer_socket_addr) + .await + .map(NetworkResult::Value) + .wrap_err("send message failure")?); + } + ProtocolType::TCP => { + let peer_socket_addr = dial_info.to_socket_addr(); + let pnc = network_result_try!(RawTcpProtocolHandler::connect( + None, + peer_socket_addr, + connect_timeout_ms + ) .await - .wrap_err("create socket failure")?; - let _ = network_result_try!(h - .send_message(data, peer_socket_addr) + .wrap_err("connect failure")?); + network_result_try!(pnc.send(data).await.wrap_err("send failure")?); + } + ProtocolType::WS | ProtocolType::WSS => { + let pnc = network_result_try!(WebsocketProtocolHandler::connect( + None, + &dial_info, + connect_timeout_ms + ) .await - .map(NetworkResult::Value) - .wrap_err("send message failure")?); + .wrap_err("connect failure")?); + network_result_try!(pnc.send(data).await.wrap_err("send failure")?); + } } - ProtocolType::TCP => { - let peer_socket_addr = dial_info.to_socket_addr(); - let pnc = network_result_try!(RawTcpProtocolHandler::connect( - None, - peer_socket_addr, - connect_timeout_ms - ) - .await - .wrap_err("connect failure")?); - network_result_try!(pnc.send(data).await.wrap_err("send failure")?); - } - ProtocolType::WS | ProtocolType::WSS => { - let pnc = network_result_try!(WebsocketProtocolHandler::connect( - None, - &dial_info, - connect_timeout_ms - ) - .await - .wrap_err("connect failure")?); - network_result_try!(pnc.send(data).await.wrap_err("send failure")?); - } - } - // Network accounting - self.network_manager() - .stats_packet_sent(dial_info.to_ip_addr(), ByteCount::new(data_len as u64)); + // Network accounting + self.network_manager() + .stats_packet_sent(dial_info.to_ip_addr(), ByteCount::new(data_len as u64)); - Ok(NetworkResult::Value(())) + Ok(NetworkResult::Value(())) + }) + .await } // Send data to a dial info, unbound, using a new connection from a random port @@ -461,85 +479,95 @@ impl Network { data: Vec, timeout_ms: u32, ) -> EyreResult>> { - let data_len = data.len(); - let connect_timeout_ms = { - let c = self.config.get(); - c.network.connection_initial_timeout_ms - }; + self.record_dial_info_failure(dial_info.clone(), async move { + let data_len = data.len(); + let connect_timeout_ms = { + let c = self.config.get(); + c.network.connection_initial_timeout_ms + }; - if self - .network_manager() - .address_filter() - .is_ip_addr_punished(dial_info.address().to_ip_addr()) - { - return Ok(NetworkResult::no_connection_other("punished")); - } - - match dial_info.protocol_type() { - ProtocolType::UDP => { - let peer_socket_addr = dial_info.to_socket_addr(); - let h = RawUdpProtocolHandler::new_unspecified_bound_handler(&peer_socket_addr) - .await - .wrap_err("create socket failure")?; - network_result_try!(h - .send_message(data, peer_socket_addr) - .await - .wrap_err("send message failure")?); - self.network_manager() - .stats_packet_sent(dial_info.to_ip_addr(), ByteCount::new(data_len as u64)); - - // receive single response - let mut out = vec![0u8; MAX_MESSAGE_SIZE]; - let (recv_len, recv_addr) = network_result_try!(timeout( - timeout_ms, - h.recv_message(&mut out).instrument(Span::current()) - ) - .await - .into_network_result()) - .wrap_err("recv_message failure")?; - - let recv_socket_addr = recv_addr.remote_address().to_socket_addr(); - self.network_manager() - .stats_packet_rcvd(recv_socket_addr.ip(), ByteCount::new(recv_len as u64)); - - // if the from address is not the same as the one we sent to, then drop this - if recv_socket_addr != peer_socket_addr { - bail!("wrong address"); - } - out.resize(recv_len, 0u8); - Ok(NetworkResult::Value(out)) + if self + .network_manager() + .address_filter() + .is_ip_addr_punished(dial_info.address().to_ip_addr()) + { + return Ok(NetworkResult::no_connection_other("punished")); } - ProtocolType::TCP | ProtocolType::WS | ProtocolType::WSS => { - let pnc = network_result_try!(match dial_info.protocol_type() { - ProtocolType::UDP => unreachable!(), - ProtocolType::TCP => { - let peer_socket_addr = dial_info.to_socket_addr(); - RawTcpProtocolHandler::connect(None, peer_socket_addr, connect_timeout_ms) - .await - .wrap_err("connect failure")? - } - ProtocolType::WS | ProtocolType::WSS => { - WebsocketProtocolHandler::connect(None, &dial_info, connect_timeout_ms) - .await - .wrap_err("connect failure")? - } - }); - network_result_try!(pnc.send(data).await.wrap_err("send failure")?); - self.network_manager() - .stats_packet_sent(dial_info.to_ip_addr(), ByteCount::new(data_len as u64)); + match dial_info.protocol_type() { + ProtocolType::UDP => { + let peer_socket_addr = dial_info.to_socket_addr(); + let h = RawUdpProtocolHandler::new_unspecified_bound_handler(&peer_socket_addr) + .await + .wrap_err("create socket failure")?; + network_result_try!(h + .send_message(data, peer_socket_addr) + .await + .wrap_err("send message failure")?); + self.network_manager() + .stats_packet_sent(dial_info.to_ip_addr(), ByteCount::new(data_len as u64)); - let out = network_result_try!(network_result_try!(timeout(timeout_ms, pnc.recv()) + // receive single response + let mut out = vec![0u8; MAX_MESSAGE_SIZE]; + let (recv_len, recv_addr) = network_result_try!(timeout( + timeout_ms, + h.recv_message(&mut out).instrument(Span::current()) + ) .await .into_network_result()) - .wrap_err("recv failure")?); + .wrap_err("recv_message failure")?; - self.network_manager() - .stats_packet_rcvd(dial_info.to_ip_addr(), ByteCount::new(out.len() as u64)); + let recv_socket_addr = recv_addr.remote_address().to_socket_addr(); + self.network_manager() + .stats_packet_rcvd(recv_socket_addr.ip(), ByteCount::new(recv_len as u64)); - Ok(NetworkResult::Value(out)) + // if the from address is not the same as the one we sent to, then drop this + if recv_socket_addr != peer_socket_addr { + bail!("wrong address"); + } + out.resize(recv_len, 0u8); + Ok(NetworkResult::Value(out)) + } + ProtocolType::TCP | ProtocolType::WS | ProtocolType::WSS => { + let pnc = network_result_try!(match dial_info.protocol_type() { + ProtocolType::UDP => unreachable!(), + ProtocolType::TCP => { + let peer_socket_addr = dial_info.to_socket_addr(); + RawTcpProtocolHandler::connect( + None, + peer_socket_addr, + connect_timeout_ms, + ) + .await + .wrap_err("connect failure")? + } + ProtocolType::WS | ProtocolType::WSS => { + WebsocketProtocolHandler::connect(None, &dial_info, connect_timeout_ms) + .await + .wrap_err("connect failure")? + } + }); + + network_result_try!(pnc.send(data).await.wrap_err("send failure")?); + self.network_manager() + .stats_packet_sent(dial_info.to_ip_addr(), ByteCount::new(data_len as u64)); + + let out = + network_result_try!(network_result_try!(timeout(timeout_ms, pnc.recv()) + .await + .into_network_result()) + .wrap_err("recv failure")?); + + self.network_manager().stats_packet_rcvd( + dial_info.to_ip_addr(), + ByteCount::new(out.len() as u64), + ); + + Ok(NetworkResult::Value(out)) + } } - } + }) + .await } #[cfg_attr(feature="verbose-tracing", instrument(level="trace", err, skip(self, data), fields(data.len = data.len())))] @@ -609,41 +637,44 @@ impl Network { dial_info: DialInfo, data: Vec, ) -> EyreResult> { - let data_len = data.len(); - let connection_descriptor; - if dial_info.protocol_type() == ProtocolType::UDP { - // Handle connectionless protocol - let peer_socket_addr = dial_info.to_socket_addr(); - let ph = match self.find_best_udp_protocol_handler(&peer_socket_addr, &None) { - Some(ph) => ph, - None => bail!("no appropriate UDP protocol handler for dial_info"), - }; - connection_descriptor = network_result_try!(ph - .send_message(data, peer_socket_addr) - .await - .wrap_err("failed to send data to dial info")?); - } else { - // Handle connection-oriented protocols - let conn = network_result_try!( - self.connection_manager() - .get_or_create_connection(dial_info.clone()) - .await? - ); + self.record_dial_info_failure(dial_info.clone(), async move { + let data_len = data.len(); + let connection_descriptor; + if dial_info.protocol_type() == ProtocolType::UDP { + // Handle connectionless protocol + let peer_socket_addr = dial_info.to_socket_addr(); + let ph = match self.find_best_udp_protocol_handler(&peer_socket_addr, &None) { + Some(ph) => ph, + None => bail!("no appropriate UDP protocol handler for dial_info"), + }; + connection_descriptor = network_result_try!(ph + .send_message(data, peer_socket_addr) + .await + .wrap_err("failed to send data to dial info")?); + } else { + // Handle connection-oriented protocols + let conn = network_result_try!( + self.connection_manager() + .get_or_create_connection(dial_info.clone()) + .await? + ); - if let ConnectionHandleSendResult::NotSent(_) = conn.send_async(data).await { - return Ok(NetworkResult::NoConnection(io::Error::new( - io::ErrorKind::ConnectionReset, - "failed to send", - ))); + if let ConnectionHandleSendResult::NotSent(_) = conn.send_async(data).await { + return Ok(NetworkResult::NoConnection(io::Error::new( + io::ErrorKind::ConnectionReset, + "failed to send", + ))); + } + connection_descriptor = conn.connection_descriptor(); } - connection_descriptor = conn.connection_descriptor(); - } - // Network accounting - self.network_manager() - .stats_packet_sent(dial_info.to_ip_addr(), ByteCount::new(data_len as u64)); + // Network accounting + self.network_manager() + .stats_packet_sent(dial_info.to_ip_addr(), ByteCount::new(data_len as u64)); - Ok(NetworkResult::value(connection_descriptor)) + Ok(NetworkResult::value(connection_descriptor)) + }) + .await } ///////////////////////////////////////////////////////////////// diff --git a/veilid-core/src/network_manager/send_data.rs b/veilid-core/src/network_manager/send_data.rs index 70d9ce90..64aa550f 100644 --- a/veilid-core/src/network_manager/send_data.rs +++ b/veilid-core/src/network_manager/send_data.rs @@ -357,6 +357,24 @@ impl NetworkManager { // log_net!(debug "Node contact failing over to Ordered for {}", target_node_ref.to_string().cyan()); // sequencing = Sequencing::PreferOrdered; // } + + // Deprioritize dial info that have recently failed + let address_filter = self.address_filter(); + let mut dial_info_failures_map = BTreeMap::::new(); + for did in peer_b.signed_node_info().node_info().all_filtered_dial_info_details(DialInfoDetail::NO_SORT, |_| true) { + if let Some(ts) = address_filter.get_dial_info_failed_ts(&did.dial_info) { + dial_info_failures_map.insert(did.dial_info, ts); + } + } + let dif_sort: Option core::cmp::Ordering>> = if dial_info_failures_map.is_empty() { + None + } else { + Some(Arc::new(move |a: &DialInfoDetail, b: &DialInfoDetail| { + let ats = dial_info_failures_map.get(&a.dial_info).copied().unwrap_or_default(); + let bts = dial_info_failures_map.get(&b.dial_info).copied().unwrap_or_default(); + ats.cmp(&bts) + })) + }; // Get the best contact method with these parameters from the routing domain let cm = routing_table.get_contact_method( @@ -365,6 +383,7 @@ impl NetworkManager { &peer_b, dial_info_filter, sequencing, + dif_sort, ); // Translate the raw contact method to a referenced contact method diff --git a/veilid-core/src/network_manager/wasm/mod.rs b/veilid-core/src/network_manager/wasm/mod.rs index 7c3b40e0..feb9c0da 100644 --- a/veilid-core/src/network_manager/wasm/mod.rs +++ b/veilid-core/src/network_manager/wasm/mod.rs @@ -118,47 +118,66 @@ impl Network { ///////////////////////////////////////////////////////////////// + // Record DialInfo failures + pub async fn record_dial_info_failure>>>( + &self, + dial_info: DialInfo, + fut: F, + ) -> EyreResult> { + let network_result = fut.await?; + if matches!(network_result, NetworkResult::NoConnection(_)) { + self.network_manager() + .address_filter() + .set_dial_info_failed(dial_info); + } + Ok(network_result) + } + #[cfg_attr(feature="verbose-tracing", instrument(level="trace", err, skip(self, data), fields(data.len = data.len())))] pub async fn send_data_unbound_to_dial_info( &self, dial_info: DialInfo, data: Vec, ) -> EyreResult> { - let data_len = data.len(); - let timeout_ms = { - let c = self.config.get(); - c.network.connection_initial_timeout_ms - }; + self.record_dial_info_failure(dial_info.clone(), async move { + let data_len = data.len(); + let timeout_ms = { + let c = self.config.get(); + c.network.connection_initial_timeout_ms + }; - if self - .network_manager() - .address_filter() - .is_ip_addr_punished(dial_info.address().to_ip_addr()) - { - return Ok(NetworkResult::no_connection_other("punished")); - } - - match dial_info.protocol_type() { - ProtocolType::UDP => { - bail!("no support for UDP protocol") + if self + .network_manager() + .address_filter() + .is_ip_addr_punished(dial_info.address().to_ip_addr()) + { + return Ok(NetworkResult::no_connection_other("punished")); } - ProtocolType::TCP => { - bail!("no support for TCP protocol") - } - ProtocolType::WS | ProtocolType::WSS => { - let pnc = - network_result_try!(WebsocketProtocolHandler::connect(&dial_info, timeout_ms) - .await - .wrap_err("connect failure")?); - network_result_try!(pnc.send(data).await.wrap_err("send failure")?); - } - }; - // Network accounting - self.network_manager() - .stats_packet_sent(dial_info.to_ip_addr(), ByteCount::new(data_len as u64)); + match dial_info.protocol_type() { + ProtocolType::UDP => { + bail!("no support for UDP protocol") + } + ProtocolType::TCP => { + bail!("no support for TCP protocol") + } + ProtocolType::WS | ProtocolType::WSS => { + let pnc = network_result_try!(WebsocketProtocolHandler::connect( + &dial_info, timeout_ms + ) + .await + .wrap_err("connect failure")?); + network_result_try!(pnc.send(data).await.wrap_err("send failure")?); + } + }; - Ok(NetworkResult::Value(())) + // Network accounting + self.network_manager() + .stats_packet_sent(dial_info.to_ip_addr(), ByteCount::new(data_len as u64)); + + Ok(NetworkResult::Value(())) + }) + .await } // Send data to a dial info, unbound, using a new connection from a random port @@ -173,53 +192,59 @@ impl Network { data: Vec, timeout_ms: u32, ) -> EyreResult>> { - let data_len = data.len(); - let connect_timeout_ms = { - let c = self.config.get(); - c.network.connection_initial_timeout_ms - }; + self.record_dial_info_failure(dial_info.clone(), async move { + let data_len = data.len(); + let connect_timeout_ms = { + let c = self.config.get(); + c.network.connection_initial_timeout_ms + }; - if self - .network_manager() - .address_filter() - .is_ip_addr_punished(dial_info.address().to_ip_addr()) - { - return Ok(NetworkResult::no_connection_other("punished")); - } + if self + .network_manager() + .address_filter() + .is_ip_addr_punished(dial_info.address().to_ip_addr()) + { + return Ok(NetworkResult::no_connection_other("punished")); + } - match dial_info.protocol_type() { - ProtocolType::UDP => { - bail!("no support for UDP protocol") - } - ProtocolType::TCP => { - bail!("no support for TCP protocol") - } - ProtocolType::WS | ProtocolType::WSS => { - let pnc = network_result_try!(match dial_info.protocol_type() { - ProtocolType::UDP => unreachable!(), - ProtocolType::TCP => unreachable!(), - ProtocolType::WS | ProtocolType::WSS => { - WebsocketProtocolHandler::connect(&dial_info, connect_timeout_ms) + match dial_info.protocol_type() { + ProtocolType::UDP => { + bail!("no support for UDP protocol") + } + ProtocolType::TCP => { + bail!("no support for TCP protocol") + } + ProtocolType::WS | ProtocolType::WSS => { + let pnc = network_result_try!(match dial_info.protocol_type() { + ProtocolType::UDP => unreachable!(), + ProtocolType::TCP => unreachable!(), + ProtocolType::WS | ProtocolType::WSS => { + WebsocketProtocolHandler::connect(&dial_info, connect_timeout_ms) + .await + .wrap_err("connect failure")? + } + }); + + network_result_try!(pnc.send(data).await.wrap_err("send failure")?); + self.network_manager() + .stats_packet_sent(dial_info.to_ip_addr(), ByteCount::new(data_len as u64)); + + let out = + network_result_try!(network_result_try!(timeout(timeout_ms, pnc.recv()) .await - .wrap_err("connect failure")? - } - }); + .into_network_result()) + .wrap_err("recv failure")?); - network_result_try!(pnc.send(data).await.wrap_err("send failure")?); - self.network_manager() - .stats_packet_sent(dial_info.to_ip_addr(), ByteCount::new(data_len as u64)); + self.network_manager().stats_packet_rcvd( + dial_info.to_ip_addr(), + ByteCount::new(out.len() as u64), + ); - let out = network_result_try!(network_result_try!(timeout(timeout_ms, pnc.recv()) - .await - .into_network_result()) - .wrap_err("recv failure")?); - - self.network_manager() - .stats_packet_rcvd(dial_info.to_ip_addr(), ByteCount::new(out.len() as u64)); - - Ok(NetworkResult::Value(out)) + Ok(NetworkResult::Value(out)) + } } - } + }) + .await } #[cfg_attr(feature="verbose-tracing", instrument(level="trace", err, skip(self, data), fields(data.len = data.len())))] @@ -273,34 +298,37 @@ impl Network { dial_info: DialInfo, data: Vec, ) -> EyreResult> { - let data_len = data.len(); - if dial_info.protocol_type() == ProtocolType::UDP { - bail!("no support for UDP protocol"); - } - if dial_info.protocol_type() == ProtocolType::TCP { - bail!("no support for TCP protocol"); - } + self.record_dial_info_failure(dial_info.clone(), async move { + let data_len = data.len(); + if dial_info.protocol_type() == ProtocolType::UDP { + bail!("no support for UDP protocol"); + } + if dial_info.protocol_type() == ProtocolType::TCP { + bail!("no support for TCP protocol"); + } - // Handle connection-oriented protocols - let conn = network_result_try!( - self.connection_manager() - .get_or_create_connection(dial_info.clone()) - .await? - ); + // Handle connection-oriented protocols + let conn = network_result_try!( + self.connection_manager() + .get_or_create_connection(dial_info.clone()) + .await? + ); - if let ConnectionHandleSendResult::NotSent(_) = conn.send_async(data).await { - return Ok(NetworkResult::NoConnection(io::Error::new( - io::ErrorKind::ConnectionReset, - "failed to send", - ))); - } - let connection_descriptor = conn.connection_descriptor(); + if let ConnectionHandleSendResult::NotSent(_) = conn.send_async(data).await { + return Ok(NetworkResult::NoConnection(io::Error::new( + io::ErrorKind::ConnectionReset, + "failed to send", + ))); + } + let connection_descriptor = conn.connection_descriptor(); - // Network accounting - self.network_manager() - .stats_packet_sent(dial_info.to_ip_addr(), ByteCount::new(data_len as u64)); + // Network accounting + self.network_manager() + .stats_packet_sent(dial_info.to_ip_addr(), ByteCount::new(data_len as u64)); - Ok(NetworkResult::value(connection_descriptor)) + Ok(NetworkResult::value(connection_descriptor)) + }) + .await } ///////////////////////////////////////////////////////////////// diff --git a/veilid-core/src/routing_table/mod.rs b/veilid-core/src/routing_table/mod.rs index 2f63df4a..82d9ed78 100644 --- a/veilid-core/src/routing_table/mod.rs +++ b/veilid-core/src/routing_table/mod.rs @@ -538,6 +538,7 @@ impl RoutingTable { peer_b: &PeerInfo, dial_info_filter: DialInfoFilter, sequencing: Sequencing, + dif_sort: Option core::cmp::Ordering>>, ) -> ContactMethod { self.inner.read().get_contact_method( routing_domain, @@ -545,6 +546,7 @@ impl RoutingTable { peer_b, dial_info_filter, sequencing, + dif_sort, ) } diff --git a/veilid-core/src/routing_table/route_spec_store/route_spec_store.rs b/veilid-core/src/routing_table/route_spec_store/route_spec_store.rs index fb85fcc9..1889abca 100644 --- a/veilid-core/src/routing_table/route_spec_store/route_spec_store.rs +++ b/veilid-core/src/routing_table/route_spec_store/route_spec_store.rs @@ -401,6 +401,7 @@ impl RouteSpecStore { current_node, DialInfoFilter::all(), sequencing, + None, ); if matches!(cm, ContactMethod::Unreachable) { reachable = false; @@ -415,6 +416,7 @@ impl RouteSpecStore { current_node, DialInfoFilter::all(), Sequencing::EnsureOrdered, + None, ); if matches!(cm, ContactMethod::Unreachable) { can_do_sequenced = false; @@ -438,6 +440,7 @@ impl RouteSpecStore { current_node, DialInfoFilter::all(), sequencing, + None, ); if matches!(cm, ContactMethod::Unreachable) { reachable = false; @@ -452,6 +455,7 @@ impl RouteSpecStore { current_node, DialInfoFilter::all(), Sequencing::EnsureOrdered, + None, ); if matches!(cm, ContactMethod::Unreachable) { can_do_sequenced = false; diff --git a/veilid-core/src/routing_table/routing_domains.rs b/veilid-core/src/routing_table/routing_domains.rs index 7f60cc04..d92dddc9 100644 --- a/veilid-core/src/routing_table/routing_domains.rs +++ b/veilid-core/src/routing_table/routing_domains.rs @@ -220,6 +220,7 @@ pub trait RoutingDomainDetail { peer_b: &PeerInfo, dial_info_filter: DialInfoFilter, sequencing: Sequencing, + dif_sort: Option core::cmp::Ordering>>, ) -> ContactMethod; } @@ -245,6 +246,7 @@ fn first_filtered_dial_info_detail_between_nodes( to_node: &NodeInfo, dial_info_filter: &DialInfoFilter, sequencing: Sequencing, + dif_sort: Option core::cmp::Ordering>> ) -> Option { let dial_info_filter = dial_info_filter.clone().filtered( &DialInfoFilter::all() @@ -253,11 +255,28 @@ fn first_filtered_dial_info_detail_between_nodes( ); // Apply sequencing and get sort + // Include sorting by external dial info sort for rotating through dialinfo + // based on an external preference table, for example the one kept by + // AddressFilter to deprioritize dialinfo that have recently failed to connect let (ordered, dial_info_filter) = dial_info_filter.with_sequencing(sequencing); - let sort = if ordered { - Some(DialInfoDetail::ordered_sequencing_sort) + let sort: Option core::cmp::Ordering>> = if ordered { + if let Some(dif_sort) = dif_sort { + Some(Box::new(move |a, b| { + let mut ord = dif_sort(a,b); + if ord == core::cmp::Ordering::Equal { + ord = DialInfoDetail::ordered_sequencing_sort(a,b); + } + ord + })) + } else { + Some(Box::new(move |a,b| { DialInfoDetail::ordered_sequencing_sort(a,b) })) + } } else { - None + if let Some(dif_sort) = dif_sort { + Some(Box::new(move |a,b| { dif_sort(a,b) })) + } else { + None + } }; // If the filter is dead then we won't be able to connect @@ -287,6 +306,7 @@ impl RoutingDomainDetail for PublicInternetRoutingDomainDetail { peer_b: &PeerInfo, dial_info_filter: DialInfoFilter, sequencing: Sequencing, + dif_sort: Option core::cmp::Ordering>>, ) -> ContactMethod { // Get the nodeinfos for convenience let node_a = peer_a.signed_node_info().node_info(); @@ -304,7 +324,7 @@ impl RoutingDomainDetail for PublicInternetRoutingDomainDetail { // Get the best match dial info for node B if we have it if let Some(target_did) = - first_filtered_dial_info_detail_between_nodes(node_a, node_b, &dial_info_filter, sequencing) + first_filtered_dial_info_detail_between_nodes(node_a, node_b, &dial_info_filter, sequencing, dif_sort.clone()) { // Do we need to signal before going inbound? if !target_did.class.requires_signal() { @@ -334,6 +354,7 @@ impl RoutingDomainDetail for PublicInternetRoutingDomainDetail { node_b_relay, &dial_info_filter, sequencing, + dif_sort.clone(), ) .is_some() { @@ -347,6 +368,7 @@ impl RoutingDomainDetail for PublicInternetRoutingDomainDetail { node_a, &dial_info_filter, sequencing, + dif_sort.clone() ) { // Ensure we aren't on the same public IP address (no hairpin nat) if reverse_did.dial_info.to_ip_addr() @@ -373,6 +395,7 @@ impl RoutingDomainDetail for PublicInternetRoutingDomainDetail { node_b, &udp_dial_info_filter, sequencing, + dif_sort.clone() ) { // Does node A have a direct udp dialinfo that node B can reach? if let Some(reverse_udp_did) = first_filtered_dial_info_detail_between_nodes( @@ -380,6 +403,7 @@ impl RoutingDomainDetail for PublicInternetRoutingDomainDetail { node_a, &udp_dial_info_filter, sequencing, + dif_sort.clone(), ) { // Ensure we aren't on the same public IP address (no hairpin nat) if reverse_udp_did.dial_info.to_ip_addr() @@ -422,6 +446,7 @@ impl RoutingDomainDetail for PublicInternetRoutingDomainDetail { &node_b_relay, &dial_info_filter, sequencing, + dif_sort.clone() ) .is_some() { @@ -496,6 +521,7 @@ impl RoutingDomainDetail for LocalNetworkRoutingDomainDetail { peer_b: &PeerInfo, dial_info_filter: DialInfoFilter, sequencing: Sequencing, + dif_sort: Option core::cmp::Ordering>>, ) -> ContactMethod { // Scope the filter down to protocols node A can do outbound let dial_info_filter = dial_info_filter.filtered( @@ -504,20 +530,31 @@ impl RoutingDomainDetail for LocalNetworkRoutingDomainDetail { .with_protocol_type_set(peer_a.signed_node_info().node_info().outbound_protocols()), ); - // Get first filtered dialinfo - let (sort, dial_info_filter) = match sequencing { - Sequencing::NoPreference => (None, dial_info_filter), - Sequencing::PreferOrdered => ( - Some(DialInfoDetail::ordered_sequencing_sort), - dial_info_filter, - ), - Sequencing::EnsureOrdered => ( - Some(DialInfoDetail::ordered_sequencing_sort), - dial_info_filter.filtered( - &DialInfoFilter::all().with_protocol_type_set(ProtocolType::all_ordered_set()), - ), - ), + // Apply sequencing and get sort + // Include sorting by external dial info sort for rotating through dialinfo + // based on an external preference table, for example the one kept by + // AddressFilter to deprioritize dialinfo that have recently failed to connect + let (ordered, dial_info_filter) = dial_info_filter.with_sequencing(sequencing); + let sort: Option core::cmp::Ordering>> = if ordered { + if let Some(dif_sort) = dif_sort { + Some(Box::new(move |a, b| { + let mut ord = dif_sort(a,b); + if ord == core::cmp::Ordering::Equal { + ord = DialInfoDetail::ordered_sequencing_sort(a,b); + } + ord + })) + } else { + Some(Box::new(move |a,b| { DialInfoDetail::ordered_sequencing_sort(a,b) })) + } + } else { + if let Some(dif_sort) = dif_sort { + Some(Box::new(move |a,b| { dif_sort(a,b) })) + } else { + None + } }; + // If the filter is dead then we won't be able to connect if dial_info_filter.is_dead() { return ContactMethod::Unreachable; diff --git a/veilid-core/src/routing_table/routing_table_inner.rs b/veilid-core/src/routing_table/routing_table_inner.rs index 029f5da8..b6f24908 100644 --- a/veilid-core/src/routing_table/routing_table_inner.rs +++ b/veilid-core/src/routing_table/routing_table_inner.rs @@ -226,9 +226,10 @@ impl RoutingTableInner { peer_b: &PeerInfo, dial_info_filter: DialInfoFilter, sequencing: Sequencing, + dif_sort: Option core::cmp::Ordering>>, ) -> ContactMethod { self.with_routing_domain(routing_domain, |rdd| { - rdd.get_contact_method(self, peer_a, peer_b, dial_info_filter, sequencing) + rdd.get_contact_method(self, peer_a, peer_b, dial_info_filter, sequencing, dif_sort) }) } diff --git a/veilid-flutter/example/pubspec.lock b/veilid-flutter/example/pubspec.lock index b3d588dd..73c75fc4 100644 --- a/veilid-flutter/example/pubspec.lock +++ b/veilid-flutter/example/pubspec.lock @@ -403,7 +403,7 @@ packages: path: ".." relative: true source: path - version: "0.1.9" + version: "0.1.10" web: dependency: transitive description: From e504da25648f77c2f53d4691e3e3593611faba9f Mon Sep 17 00:00:00 2001 From: Christien Rioux Date: Tue, 22 Aug 2023 13:19:59 -0400 Subject: [PATCH 2/5] xfer --- Cargo.lock | 30 +-- veilid-core/Cargo.toml | 90 ++++++-- veilid-core/src/network_manager/wasm/mod.rs | 4 +- veilid-flutter/example/reset_run.bat | 2 +- veilid-flutter/example/reset_run.sh | 2 +- veilid-flutter/lib/default_config.dart | 240 ++++++++++---------- veilid-wasm/wasm_build.sh | 4 +- 7 files changed, 211 insertions(+), 161 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ebd2d157..b94cb7d3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -854,9 +854,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.82" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ "libc", ] @@ -1533,9 +1533,9 @@ dependencies = [ [[package]] name = "dashmap" -version = "5.5.0" +version = "5.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6943ae99c34386c84a470c499d3414f66502a41340aa895406e0d2e4a207b91d" +checksum = "edd72493923899c6f10c641bdbdeddc7183d6396641d99c1a0d1597f37f92e28" dependencies = [ "cfg-if 1.0.0", "hashbrown 0.14.0", @@ -2249,9 +2249,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.20" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049" +checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" dependencies = [ "bytes 1.4.0", "fnv", @@ -3757,12 +3757,12 @@ dependencies = [ [[package]] name = "petgraph" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" +checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" dependencies = [ "fixedbitset", - "indexmap 1.9.3", + "indexmap 2.0.0", ] [[package]] @@ -4463,9 +4463,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.183" +version = "1.0.185" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c" +checksum = "be9b6f69f1dfd54c3b568ffa45c310d6973a5e5148fd40cf515acaf38cf5bc31" dependencies = [ "serde_derive", ] @@ -4491,9 +4491,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.183" +version = "1.0.185" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816" +checksum = "dc59dfdcbad1437773485e0367fea4b090a2e0a16d9ffc46af47764536a298ec" dependencies = [ "proc-macro2", "quote", @@ -4750,9 +4750,9 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg", ] diff --git a/veilid-core/Cargo.toml b/veilid-core/Cargo.toml index c337170b..2303fb00 100644 --- a/veilid-core/Cargo.toml +++ b/veilid-core/Cargo.toml @@ -13,8 +13,24 @@ crate-type = ["cdylib", "staticlib", "rlib"] # Common features default = ["enable-crypto-vld0"] -rt-async-std = ["async-std", "async-std-resolver", "async_executors/async_std", "rtnetlink/smol_socket", "veilid-tools/rt-async-std"] -rt-tokio = ["tokio", "tokio-util", "tokio-stream", "trust-dns-resolver/tokio-runtime", "async_executors/tokio_tp", "async_executors/tokio_io", "async_executors/tokio_timer", "rtnetlink/tokio_socket", "veilid-tools/rt-tokio"] +rt-async-std = [ + "async-std", + "async-std-resolver", + "async_executors/async_std", + "rtnetlink/smol_socket", + "veilid-tools/rt-async-std", +] +rt-tokio = [ + "tokio", + "tokio-util", + "tokio-stream", + "trust-dns-resolver/tokio-runtime", + "async_executors/tokio_tp", + "async_executors/tokio_io", + "async_executors/tokio_timer", + "rtnetlink/tokio_socket", + "veilid-tools/rt-tokio", +] rt-wasm-bindgen = ["veilid-tools/rt-wasm-bindgen", "async_executors/bindgen"] # Crypto support features @@ -36,7 +52,7 @@ network-result-extra = ["veilid-tools/network-result-extra"] [dependencies] # Tools -veilid-tools = { path = "../veilid-tools", features = [ "tracing" ] } +veilid-tools = { path = "../veilid-tools", features = ["tracing"] } paste = "1.0.14" once_cell = "1.18.0" owning_ref = "0.4.1" @@ -57,7 +73,7 @@ eyre = "0.6.8" thiserror = "1.0.47" # Data structures -enumset = { version= "1.1.2", features = ["serde"] } +enumset = { version = "1.1.2", features = ["serde"] } keyvaluedb = { path = "../external/keyvaluedb/keyvaluedb" } range-set-blaze = "0.1.9" weak-table = "0.3.2" @@ -65,15 +81,31 @@ generic-array = "0.14.7" hashlink = { path = "../external/hashlink", features = ["serde_impl"] } # System -futures-util = { version = "0.3.28", default_features = false, features = ["alloc"] } +futures-util = { version = "0.3.28", default_features = false, features = [ + "alloc", +] } flume = { version = "0.11.0", features = ["async"] } parking_lot = "0.12.1" stop-token = { version = "0.7.0", default-features = false } # Crypto -ed25519-dalek = { version = "2.0.0", default_features = false, features = ["alloc", "rand_core", "digest"] } -x25519-dalek = { version = "2.0.0", default_features = false, features = ["alloc", "static_secrets"] } -curve25519-dalek = { version = "4.0.0", default_features = false, features = ["alloc"] } +ed25519-dalek = { version = "2.0.0", default_features = false, features = [ + "alloc", + "rand_core", + "digest", + "zeroize", +] } +x25519-dalek = { version = "2.0.0", default_features = false, features = [ + "alloc", + "static_secrets", + "zeroize", + "precomputed-tables", +] } +curve25519-dalek = { version = "4.0.0", default_features = false, features = [ + "alloc", + "zeroize", + "precomputed-tables", +] } blake3 = { version = "1.4.1" } chacha20poly1305 = "0.10.1" chacha20 = "0.9.1" @@ -82,17 +114,20 @@ argon2 = "0.5.1" # Network async-std-resolver = { version = "0.22.0", optional = true } trust-dns-resolver = { version = "0.22.0", optional = true } -enum-as-inner = "=0.5.1" # temporary fix for trust-dns-resolver v0.22.0 +enum-as-inner = "=0.5.1" # temporary fix for trust-dns-resolver v0.22.0 # Serialization capnp = { version = "0.17.2", default_features = false } -serde = { version = "1.0.183", features = ["derive" ] } +serde = { version = "1.0.183", features = ["derive"] } serde_json = { version = "1.0.105" } serde-big-array = "0.5.1" json = "0.12.4" data-encoding = { version = "2.4.0" } schemars = "0.8.12" -lz4_flex = { version = "0.11.1", default-features = false, features = ["safe-encode", "safe-decode"] } +lz4_flex = { version = "0.11.1", default-features = false, features = [ + "safe-encode", + "safe-decode", +] } # Dependencies for native builds only # Linux, Windows, Mac, iOS, Android @@ -106,12 +141,17 @@ libc = "0.2.147" nix = "0.26.2" # System -async-std = { version = "1.12.0", features = ["unstable"], optional = true} -tokio = { version = "1.32.0", features = ["full"], optional = true} -tokio-util = { version = "0.7.8", features = ["compat"], optional = true} -tokio-stream = { version = "0.1.14", features = ["net"], optional = true} +async-std = { version = "1.12.0", features = ["unstable"], optional = true } +tokio = { version = "1.32.0", features = ["full"], optional = true } +tokio-util = { version = "0.7.8", features = ["compat"], optional = true } +tokio-stream = { version = "0.1.14", features = ["net"], optional = true } async-io = { version = "1.13.0" } -futures-util = { version = "0.3.28", default-features = false, features = ["async-await", "sink", "std", "io"] } +futures-util = { version = "0.3.28", default-features = false, features = [ + "async-await", + "sink", + "std", + "io", +] } # Data structures keyring-manager = { path = "../external/keyring-manager" } @@ -119,7 +159,7 @@ keyvaluedb-sqlite = { path = "../external/keyvaluedb/keyvaluedb-sqlite" } # Network async-tungstenite = { version = "0.23.0", features = ["async-tls"] } -igd = { path = "../external/rust-igd" } +igd = { path = "../external/rust-igd" } async-tls = "0.12.0" webpki = "0.22.0" webpki-roots = "0.25.2" @@ -134,7 +174,10 @@ socket2 = { version = "0.5.3", features = ["all"] } getrandom = { version = "0.2.4", features = ["js"] } # System -async_executors = { version = "0.7.0", default-features = false, features = [ "bindgen", "timer" ]} +async_executors = { version = "0.7.0", default-features = false, features = [ + "bindgen", + "timer", +] } async-lock = "2.8.0" wasm-bindgen = "0.2.87" js-sys = "0.3.64" @@ -181,14 +224,17 @@ ifstructs = "0.1.1" # Dependencies for Linux or Android [target.'cfg(any(target_os = "android", target_os = "linux"))'.dependencies] -rtnetlink = { version = "=0.13.0", default-features = false} +rtnetlink = { version = "=0.13.0", default-features = false } netlink-sys = { version = "=0.8.5" } netlink-packet-route = { version = "=0.17.0" } # Dependencies for Windows [target.'cfg(target_os = "windows")'.dependencies] -winapi = { version = "0.3.9", features = [ "iptypes", "iphlpapi" ] } -windows = { version = "0.51.1", features = [ "Win32_NetworkManagement_Dns", "Win32_Foundation" ]} +winapi = { version = "0.3.9", features = ["iptypes", "iphlpapi"] } +windows = { version = "0.51.1", features = [ + "Win32_NetworkManagement_Dns", + "Win32_Foundation", +] } windows-permissions = "0.2.4" # Dependencies for iOS @@ -207,7 +253,7 @@ features = ["bundled"] serial_test = "2.0.0" [target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] -simplelog = { version = "0.12.1", features=["test"] } +simplelog = { version = "0.12.1", features = ["test"] } [target.'cfg(target_arch = "wasm32")'.dev-dependencies] wasm-bindgen-test = "0.3.37" diff --git a/veilid-core/src/network_manager/wasm/mod.rs b/veilid-core/src/network_manager/wasm/mod.rs index feb9c0da..c9a0c445 100644 --- a/veilid-core/src/network_manager/wasm/mod.rs +++ b/veilid-core/src/network_manager/wasm/mod.rs @@ -348,8 +348,8 @@ impl Network { } // XXX: See issue #92 - let family_global = AddressTypeSet::all(); - let family_local = AddressTypeSet::all(); + let family_global = AddressTypeSet::from(AddressType::IPV4); + let family_local = AddressTypeSet::from(AddressType::IPV4); ProtocolConfig { outbound, diff --git a/veilid-flutter/example/reset_run.bat b/veilid-flutter/example/reset_run.bat index 3d53a241..c6bea309 100644 --- a/veilid-flutter/example/reset_run.bat +++ b/veilid-flutter/example/reset_run.bat @@ -1,2 +1,2 @@ @echo off -flutter run --dart-define=DELETE_TABLE_STORE=1 --dart-define=DELETE_PROTECTED_STORE=1 --dart-define=DELETE_BLOCK_STORE=1 +flutter run --dart-define=DELETE_TABLE_STORE=1 --dart-define=DELETE_PROTECTED_STORE=1 --dart-define=DELETE_BLOCK_STORE=1 %* diff --git a/veilid-flutter/example/reset_run.sh b/veilid-flutter/example/reset_run.sh index eb6fda85..7c9c0c73 100755 --- a/veilid-flutter/example/reset_run.sh +++ b/veilid-flutter/example/reset_run.sh @@ -1,2 +1,2 @@ #!/bin/bash -flutter run --dart-define=DELETE_TABLE_STORE=1 --dart-define=DELETE_PROTECTED_STORE=1 --dart-define=DELETE_BLOCK_STORE=1 +flutter run --dart-define=DELETE_TABLE_STORE=1 --dart-define=DELETE_PROTECTED_STORE=1 --dart-define=DELETE_BLOCK_STORE=1 $@ diff --git a/veilid-flutter/lib/default_config.dart b/veilid-flutter/lib/default_config.dart index 5ee45061..65b3dbeb 100644 --- a/veilid-flutter/lib/default_config.dart +++ b/veilid-flutter/lib/default_config.dart @@ -58,129 +58,133 @@ int getRemoteMaxStorageSpaceMb() { return 256; } -Future getDefaultVeilidConfig(String programName) async => - VeilidConfig( - programName: programName, - namespace: '', - capabilities: const VeilidConfigCapabilities(disable: []), - protectedStore: const VeilidConfigProtectedStore( - allowInsecureFallback: false, - alwaysUseInsecureStorage: false, - directory: '', - delete: false, - deviceEncryptionKeyPassword: '', +Future getDefaultVeilidConfig(String programName) async { + // ignore: do_not_use_environment + final bootstrap = const String.fromEnvironment('BOOTSTRAP').split(','); + return VeilidConfig( + programName: programName, + namespace: '', + capabilities: const VeilidConfigCapabilities(disable: []), + protectedStore: const VeilidConfigProtectedStore( + allowInsecureFallback: false, + alwaysUseInsecureStorage: false, + directory: '', + delete: false, + deviceEncryptionKeyPassword: '', + ), + tableStore: VeilidConfigTableStore( + directory: kIsWeb + ? '' + : p.join((await getApplicationSupportDirectory()).absolute.path, + 'table_store'), + delete: false, + ), + blockStore: VeilidConfigBlockStore( + directory: kIsWeb + ? '' + : p.join((await getApplicationSupportDirectory()).absolute.path, + 'block_store'), + delete: false, + ), + network: VeilidConfigNetwork( + connectionInitialTimeoutMs: 2000, + connectionInactivityTimeoutMs: 60000, + maxConnectionsPerIp4: 32, + maxConnectionsPerIp6Prefix: 32, + maxConnectionsPerIp6PrefixSize: 56, + maxConnectionFrequencyPerMin: 128, + clientWhitelistTimeoutMs: 300000, + reverseConnectionReceiptTimeMs: 5000, + holePunchReceiptTimeMs: 5000, + routingTable: VeilidConfigRoutingTable( + nodeId: [], + nodeIdSecret: [], + bootstrap: bootstrap.isNotEmpty + ? bootstrap + : (kIsWeb + ? ['ws://bootstrap.veilid.net:5150/ws'] + : ['bootstrap.veilid.net']), + limitOverAttached: 64, + limitFullyAttached: 32, + limitAttachedStrong: 16, + limitAttachedGood: 8, + limitAttachedWeak: 4, ), - tableStore: VeilidConfigTableStore( - directory: kIsWeb - ? '' - : p.join((await getApplicationSupportDirectory()).absolute.path, - 'table_store'), - delete: false, + rpc: const VeilidConfigRPC( + concurrency: 0, + queueSize: 1024, + maxTimestampBehindMs: 10000, + maxTimestampAheadMs: 10000, + timeoutMs: 5000, + maxRouteHopCount: 4, + defaultRouteHopCount: 1, ), - blockStore: VeilidConfigBlockStore( - directory: kIsWeb - ? '' - : p.join((await getApplicationSupportDirectory()).absolute.path, - 'block_store'), - delete: false, - ), - network: VeilidConfigNetwork( + dht: VeilidConfigDHT( + resolveNodeTimeoutMs: 10000, + resolveNodeCount: 1, + resolveNodeFanout: 4, + maxFindNodeCount: 20, + getValueTimeoutMs: 10000, + getValueCount: 3, + getValueFanout: 4, + setValueTimeoutMs: 10000, + setValueCount: 4, + setValueFanout: 6, + minPeerCount: 20, + minPeerRefreshTimeMs: 60000, + validateDialInfoReceiptTimeMs: 2000, + localSubkeyCacheSize: getLocalSubkeyCacheSize(), + localMaxSubkeyCacheMemoryMb: await getLocalMaxSubkeyCacheMemoryMb(), + remoteSubkeyCacheSize: getRemoteSubkeyCacheSize(), + remoteMaxRecords: getRemoteMaxRecords(), + remoteMaxSubkeyCacheMemoryMb: await getRemoteMaxSubkeyCacheMemoryMb(), + remoteMaxStorageSpaceMb: getRemoteMaxStorageSpaceMb()), + upnp: true, + detectAddressChanges: true, + restrictedNatRetries: 0, + tls: const VeilidConfigTLS( + certificatePath: '', + privateKeyPath: '', connectionInitialTimeoutMs: 2000, - connectionInactivityTimeoutMs: 60000, - maxConnectionsPerIp4: 32, - maxConnectionsPerIp6Prefix: 32, - maxConnectionsPerIp6PrefixSize: 56, - maxConnectionFrequencyPerMin: 128, - clientWhitelistTimeoutMs: 300000, - reverseConnectionReceiptTimeMs: 5000, - holePunchReceiptTimeMs: 5000, - routingTable: const VeilidConfigRoutingTable( - nodeId: [], - nodeIdSecret: [], - bootstrap: kIsWeb - ? ['ws://bootstrap.veilid.net:5150/ws'] - : ['bootstrap.veilid.net'], - limitOverAttached: 64, - limitFullyAttached: 32, - limitAttachedStrong: 16, - limitAttachedGood: 8, - limitAttachedWeak: 4, + ), + application: const VeilidConfigApplication( + https: VeilidConfigHTTPS( + enabled: false, + listenAddress: '', + path: '', + ), + http: VeilidConfigHTTP( + enabled: false, + listenAddress: '', + path: '', + )), + protocol: const VeilidConfigProtocol( + udp: VeilidConfigUDP( + enabled: !kIsWeb, + socketPoolSize: 0, + listenAddress: '', ), - rpc: const VeilidConfigRPC( - concurrency: 0, - queueSize: 1024, - maxTimestampBehindMs: 10000, - maxTimestampAheadMs: 10000, - timeoutMs: 5000, - maxRouteHopCount: 4, - defaultRouteHopCount: 1, + tcp: VeilidConfigTCP( + connect: !kIsWeb, + listen: !kIsWeb, + maxConnections: 32, + listenAddress: '', ), - dht: VeilidConfigDHT( - resolveNodeTimeoutMs: 10000, - resolveNodeCount: 1, - resolveNodeFanout: 4, - maxFindNodeCount: 20, - getValueTimeoutMs: 10000, - getValueCount: 3, - getValueFanout: 4, - setValueTimeoutMs: 10000, - setValueCount: 4, - setValueFanout: 6, - minPeerCount: 20, - minPeerRefreshTimeMs: 60000, - validateDialInfoReceiptTimeMs: 2000, - localSubkeyCacheSize: getLocalSubkeyCacheSize(), - localMaxSubkeyCacheMemoryMb: await getLocalMaxSubkeyCacheMemoryMb(), - remoteSubkeyCacheSize: getRemoteSubkeyCacheSize(), - remoteMaxRecords: getRemoteMaxRecords(), - remoteMaxSubkeyCacheMemoryMb: - await getRemoteMaxSubkeyCacheMemoryMb(), - remoteMaxStorageSpaceMb: getRemoteMaxStorageSpaceMb()), - upnp: true, - detectAddressChanges: true, - restrictedNatRetries: 0, - tls: const VeilidConfigTLS( - certificatePath: '', - privateKeyPath: '', - connectionInitialTimeoutMs: 2000, + ws: VeilidConfigWS( + connect: true, + listen: !kIsWeb, + maxConnections: 16, + listenAddress: '', + path: 'ws', ), - application: const VeilidConfigApplication( - https: VeilidConfigHTTPS( - enabled: false, - listenAddress: '', - path: '', - ), - http: VeilidConfigHTTP( - enabled: false, - listenAddress: '', - path: '', - )), - protocol: const VeilidConfigProtocol( - udp: VeilidConfigUDP( - enabled: !kIsWeb, - socketPoolSize: 0, - listenAddress: '', - ), - tcp: VeilidConfigTCP( - connect: !kIsWeb, - listen: !kIsWeb, - maxConnections: 32, - listenAddress: '', - ), - ws: VeilidConfigWS( - connect: true, - listen: !kIsWeb, - maxConnections: 16, - listenAddress: '', - path: 'ws', - ), - wss: VeilidConfigWSS( - connect: true, - listen: false, - maxConnections: 16, - listenAddress: '', - path: 'ws', - ), + wss: VeilidConfigWSS( + connect: true, + listen: false, + maxConnections: 16, + listenAddress: '', + path: 'ws', ), ), - ); + ), + ); +} diff --git a/veilid-wasm/wasm_build.sh b/veilid-wasm/wasm_build.sh index b450baeb..c38f8bff 100755 --- a/veilid-wasm/wasm_build.sh +++ b/veilid-wasm/wasm_build.sh @@ -34,7 +34,7 @@ else OUTPUTDIR=../target/wasm32-unknown-unknown/debug/pkg INPUTDIR=../target/wasm32-unknown-unknown/debug - RUSTFLAGS="-O -g" cargo build --target wasm32-unknown-unknown + RUSTFLAGS="-O -g $RUSTFLAGS" cargo build --target wasm32-unknown-unknown mkdir -p $OUTPUTDIR wasm-bindgen --out-dir $OUTPUTDIR --target web --keep-debug --debug $INPUTDIR/veilid_wasm.wasm ./wasm-sourcemap.py $OUTPUTDIR/veilid_wasm_bg.wasm -o $OUTPUTDIR/veilid_wasm_bg.wasm.map --dwarfdump $DWARFDUMP @@ -44,4 +44,4 @@ fi popd &> /dev/null # Print for use with scripts -echo SUCCESS:OUTPUTDIR=$(get_abs_filename $OUTPUTDIR) \ No newline at end of file +echo SUCCESS:OUTPUTDIR=$(get_abs_filename $OUTPUTDIR) From 1315766fa9100e55717f070e01c3f7ecf7596d8d Mon Sep 17 00:00:00 2001 From: Christien Rioux Date: Tue, 22 Aug 2023 13:41:50 -0400 Subject: [PATCH 3/5] eliminate network keying from bootstrap name --- veilid-core/src/network_manager/mod.rs | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/veilid-core/src/network_manager/mod.rs b/veilid-core/src/network_manager/mod.rs index 6d36a8bd..c0fb86d5 100644 --- a/veilid-core/src/network_manager/mod.rs +++ b/veilid-core/src/network_manager/mod.rs @@ -211,20 +211,7 @@ impl NetworkManager { // Make the network key let network_key = { let c = config.get(); - let network_key_password = if let Some(nkp) = c.network.network_key_password.clone() { - Some(nkp) - } else { - if c.network - .routing_table - .bootstrap - .contains(&"bootstrap.veilid.net".to_owned()) - { - None - } else { - Some(c.network.routing_table.bootstrap.join(",")) - } - }; - + let network_key_password = c.network.network_key_password.clone(); let network_key = if let Some(network_key_password) = network_key_password { if !network_key_password.is_empty() { info!("Using network key"); From a0d90fa09af527e8e52b16c5cb3b399db8a85bf6 Mon Sep 17 00:00:00 2001 From: Christien Rioux Date: Tue, 22 Aug 2023 14:40:31 -0400 Subject: [PATCH 4/5] bootstrap env var --- veilid-flutter/lib/default_config.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/veilid-flutter/lib/default_config.dart b/veilid-flutter/lib/default_config.dart index 65b3dbeb..2c495d74 100644 --- a/veilid-flutter/lib/default_config.dart +++ b/veilid-flutter/lib/default_config.dart @@ -60,7 +60,7 @@ int getRemoteMaxStorageSpaceMb() { Future getDefaultVeilidConfig(String programName) async { // ignore: do_not_use_environment - final bootstrap = const String.fromEnvironment('BOOTSTRAP').split(','); + const bootstrap = String.fromEnvironment('BOOTSTRAP'); return VeilidConfig( programName: programName, namespace: '', @@ -100,7 +100,7 @@ Future getDefaultVeilidConfig(String programName) async { nodeId: [], nodeIdSecret: [], bootstrap: bootstrap.isNotEmpty - ? bootstrap + ? bootstrap.split(',') : (kIsWeb ? ['ws://bootstrap.veilid.net:5150/ws'] : ['bootstrap.veilid.net']), From cb9b19fc9f4bb80eaf3cd8073bda8becebe5feff Mon Sep 17 00:00:00 2001 From: Christien Rioux Date: Tue, 22 Aug 2023 15:11:40 -0400 Subject: [PATCH 5/5] up connection limits for ws --- veilid-flutter/lib/default_config.dart | 4 ++-- veilid-server/src/settings.rs | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/veilid-flutter/lib/default_config.dart b/veilid-flutter/lib/default_config.dart index 2c495d74..660722cd 100644 --- a/veilid-flutter/lib/default_config.dart +++ b/veilid-flutter/lib/default_config.dart @@ -173,14 +173,14 @@ Future getDefaultVeilidConfig(String programName) async { ws: VeilidConfigWS( connect: true, listen: !kIsWeb, - maxConnections: 16, + maxConnections: 32, listenAddress: '', path: 'ws', ), wss: VeilidConfigWSS( connect: true, listen: false, - maxConnections: 16, + maxConnections: 32, listenAddress: '', path: 'ws', ), diff --git a/veilid-server/src/settings.rs b/veilid-server/src/settings.rs index 4066e59e..631e405a 100644 --- a/veilid-server/src/settings.rs +++ b/veilid-server/src/settings.rs @@ -143,14 +143,14 @@ core: ws: connect: true listen: true - max_connections: 16 + max_connections: 32 listen_address: '' path: 'ws' # url: 'ws://localhost:5150/ws' wss: connect: true listen: false - max_connections: 16 + max_connections: 32 listen_address: '' path: 'ws' # url: '' @@ -1686,7 +1686,7 @@ mod tests { // assert_eq!(s.core.network.protocol.ws.connect, true); assert_eq!(s.core.network.protocol.ws.listen, true); - assert_eq!(s.core.network.protocol.ws.max_connections, 16); + assert_eq!(s.core.network.protocol.ws.max_connections, 32); assert_eq!(s.core.network.protocol.ws.listen_address.name, ""); assert_eq!(s.core.network.protocol.ws.listen_address.addrs, vec![]); assert_eq!( @@ -1697,7 +1697,7 @@ mod tests { // assert_eq!(s.core.network.protocol.wss.connect, true); assert_eq!(s.core.network.protocol.wss.listen, false); - assert_eq!(s.core.network.protocol.wss.max_connections, 16); + assert_eq!(s.core.network.protocol.wss.max_connections, 32); assert_eq!(s.core.network.protocol.wss.listen_address.name, ""); assert_eq!(s.core.network.protocol.wss.listen_address.addrs, vec![]); assert_eq!(