From b51e14783baee4d5b7f5a91e5a0f4ad7b4d2f3bb Mon Sep 17 00:00:00 2001 From: Christien Rioux Date: Sun, 10 Sep 2023 11:56:50 -0400 Subject: [PATCH 1/9] resolve node --- veilid-core/src/veilid_api/debug.rs | 193 ++++++++++++++++++---------- 1 file changed, 128 insertions(+), 65 deletions(-) diff --git a/veilid-core/src/veilid_api/debug.rs b/veilid-core/src/veilid_api/debug.rs index 38ee02f6..524c0cd8 100644 --- a/veilid-core/src/veilid_api/debug.rs +++ b/veilid-core/src/veilid_api/debug.rs @@ -165,82 +165,89 @@ fn get_node_ref_modifiers(mut node_ref: NodeRef) -> impl FnOnce(&str) -> Option< } } -fn get_destination(routing_table: RoutingTable) -> impl FnOnce(&str) -> Option { +fn get_destination( + routing_table: RoutingTable, +) -> impl FnOnce(&str) -> SendPinBoxFuture> { move |text| { - // Safety selection - let (text, ss) = if let Some((first, second)) = text.split_once('+') { - let ss = get_safety_selection(routing_table.clone())(second)?; - (first, Some(ss)) - } else { - (text, None) - }; - if text.len() == 0 { - return None; - } - if &text[0..1] == "#" { - let rss = routing_table.route_spec_store(); + let text = text.to_owned(); + Box::pin(async move { + // Safety selection + let (text, ss) = if let Some((first, second)) = text.split_once('+') { + let ss = get_safety_selection(routing_table.clone())(second)?; + (first, Some(ss)) + } else { + (text.as_str(), None) + }; + if text.len() == 0 { + return None; + } + if &text[0..1] == "#" { + let rss = routing_table.route_spec_store(); - // Private route - let text = &text[1..]; + // Private route + let text = &text[1..]; - let private_route = if let Some(prid) = get_route_id(rss.clone(), false, true)(text) { - let Some(private_route) = rss.best_remote_private_route(&prid) else { + let private_route = if let Some(prid) = get_route_id(rss.clone(), false, true)(text) + { + let Some(private_route) = rss.best_remote_private_route(&prid) else { return None; }; - private_route - } else { - let mut dc = DEBUG_CACHE.lock(); - let n = get_number(text)?; - let prid = dc.imported_routes.get(n)?.clone(); - let Some(private_route) = rss.best_remote_private_route(&prid) else { + private_route + } else { + let mut dc = DEBUG_CACHE.lock(); + let n = get_number(text)?; + let prid = dc.imported_routes.get(n)?.clone(); + let Some(private_route) = rss.best_remote_private_route(&prid) else { // Remove imported route dc.imported_routes.remove(n); info!("removed dead imported route {}", n); return None; }; - private_route - }; + private_route + }; - Some(Destination::private_route( - private_route, - ss.unwrap_or(SafetySelection::Unsafe(Sequencing::default())), - )) - } else { - let (text, mods) = text - .split_once('/') - .map(|x| (x.0, Some(x.1))) - .unwrap_or((text, None)); - if let Some((first, second)) = text.split_once('@') { - // Relay - let mut relay_nr = get_node_ref(routing_table.clone())(second)?; - let target_nr = get_node_ref(routing_table)(first)?; - - if let Some(mods) = mods { - relay_nr = get_node_ref_modifiers(relay_nr)(mods)?; - } - - let mut d = Destination::relay(relay_nr, target_nr); - if let Some(ss) = ss { - d = d.with_safety(ss) - } - - Some(d) + Some(Destination::private_route( + private_route, + ss.unwrap_or(SafetySelection::Unsafe(Sequencing::default())), + )) } else { - // Direct - let mut target_nr = get_node_ref(routing_table)(text)?; + let (text, mods) = text + .split_once('/') + .map(|x| (x.0, Some(x.1))) + .unwrap_or((text, None)); + if let Some((first, second)) = text.split_once('@') { + // Relay + let mut relay_nr = get_node_ref(routing_table.clone())(second)?; + let target_nr = get_node_ref(routing_table)(first)?; - if let Some(mods) = mods { - target_nr = get_node_ref_modifiers(target_nr)(mods)?; + if let Some(mods) = mods { + relay_nr = get_node_ref_modifiers(relay_nr)(mods)?; + } + + let mut d = Destination::relay(relay_nr, target_nr); + if let Some(ss) = ss { + d = d.with_safety(ss) + } + + Some(d) + } else { + // Direct + let mut target_nr = + resolve_node_ref(routing_table, ss.unwrap_or_default())(text).await?; + + if let Some(mods) = mods { + target_nr = get_node_ref_modifiers(target_nr)(mods)?; + } + + let mut d = Destination::direct(target_nr); + if let Some(ss) = ss { + d = d.with_safety(ss) + } + + Some(d) } - - let mut d = Destination::direct(target_nr); - if let Some(ss) = ss { - d = d.with_safety(ss) - } - - Some(d) } - } + }) } } @@ -292,6 +299,44 @@ fn get_dht_key( } } +fn resolve_node_ref( + routing_table: RoutingTable, + safety_selection: SafetySelection, +) -> impl FnOnce(&str) -> SendPinBoxFuture> { + move |text| { + let text = text.to_owned(); + Box::pin(async move { + let (text, mods) = text + .split_once('/') + .map(|x| (x.0, Some(x.1))) + .unwrap_or((&text, None)); + + let mut nr = if let Some(key) = get_public_key(text) { + let node_id = TypedKey::new(best_crypto_kind(), key); + routing_table + .rpc_processor() + .resolve_node(node_id, safety_selection) + .await + .ok() + .flatten()? + } else if let Some(node_id) = get_typed_key(text) { + routing_table + .rpc_processor() + .resolve_node(node_id, safety_selection) + .await + .ok() + .flatten()? + } else { + return None; + }; + if let Some(mods) = mods { + nr = get_node_ref_modifiers(nr)(mods)?; + } + Some(nr) + }) + } +} + fn get_node_ref(routing_table: RoutingTable) -> impl FnOnce(&str) -> Option { move |text| { let (text, mods) = text @@ -301,8 +346,8 @@ fn get_node_ref(routing_table: RoutingTable) -> impl FnOnce(&str) -> Option Option>( Ok(val) } +async fn async_get_debug_argument_at SendPinBoxFuture>>( + debug_args: &[String], + pos: usize, + context: &str, + argument: &str, + getter: G, +) -> VeilidAPIResult { + if pos >= debug_args.len() { + apibail_missing_argument!(context, argument); + } + let value = &debug_args[pos]; + let Some(val) = getter(value).await else { + apibail_invalid_argument!(context, argument, value); + }; + Ok(val) +} + pub fn print_data(data: &[u8], truncate_len: Option) -> String { // check is message body is ascii printable let mut printable = true; @@ -749,13 +811,14 @@ impl VeilidAPI { let args: Vec = args.split_whitespace().map(|s| s.to_owned()).collect(); - let dest = get_debug_argument_at( + let dest = async_get_debug_argument_at( &args, 0, "debug_ping", "destination", get_destination(routing_table), - )?; + ) + .await?; // Dump routing table entry let out = match rpc From 28b08034f5c0fc97ef90b959ac0a70910b13c042 Mon Sep 17 00:00:00 2001 From: Christien Rioux Date: Sun, 10 Sep 2023 15:53:19 -0400 Subject: [PATCH 2/9] appmessage/call commands --- veilid-core/src/routing_table/debug.rs | 1 + veilid-core/src/veilid_api/debug.rs | 93 +++++++++++++++++++++++++- 2 files changed, 93 insertions(+), 1 deletion(-) diff --git a/veilid-core/src/routing_table/debug.rs b/veilid-core/src/routing_table/debug.rs index 8f3875d9..64207987 100644 --- a/veilid-core/src/routing_table/debug.rs +++ b/veilid-core/src/routing_table/debug.rs @@ -73,6 +73,7 @@ impl RoutingTable { " Self Transfer Stats: {:#?}\n\n", inner.self_transfer_stats ); + out += &format!(" Version: {}\n\n", veilid_version_string()); out } diff --git a/veilid-core/src/veilid_api/debug.rs b/veilid-core/src/veilid_api/debug.rs index 524c0cd8..81920b38 100644 --- a/veilid-core/src/veilid_api/debug.rs +++ b/veilid-core/src/veilid_api/debug.rs @@ -439,6 +439,19 @@ fn get_debug_argument Option>( }; Ok(val) } + +async fn async_get_debug_argument SendPinBoxFuture>>( + value: &str, + context: &str, + argument: &str, + getter: G, +) -> VeilidAPIResult { + let Some(val) = getter(value).await else { + apibail_invalid_argument!(context, argument, value); + }; + Ok(val) +} + fn get_debug_argument_at Option>( debug_args: &[String], pos: usize, @@ -820,7 +833,7 @@ impl VeilidAPI { ) .await?; - // Dump routing table entry + // Send a StatusQ let out = match rpc .rpc_call_status(dest) .await @@ -835,6 +848,78 @@ impl VeilidAPI { Ok(format!("{:#?}", out)) } + async fn debug_app_message(&self, args: String) -> VeilidAPIResult { + let netman = self.network_manager()?; + let routing_table = netman.routing_table(); + let rpc = netman.rpc_processor(); + + let (arg, rest) = args.split_once(' ').unwrap_or((&args, "")); + let rest = rest.trim_start().to_owned(); + + let dest = async_get_debug_argument( + arg, + "debug_app_message", + "destination", + get_destination(routing_table), + ) + .await?; + + let data = get_debug_argument(&rest, "debug_app_message", "data", get_data)?; + let data_len = data.len(); + + // Send a AppMessage + let out = match rpc + .rpc_call_app_message(dest, data) + .await + .map_err(VeilidAPIError::internal)? + { + NetworkResult::Value(_) => format!("Sent {} bytes", data_len), + r => { + return Ok(r.to_string()); + } + }; + + Ok(out) + } + + async fn debug_app_call(&self, args: String) -> VeilidAPIResult { + let netman = self.network_manager()?; + let routing_table = netman.routing_table(); + let rpc = netman.rpc_processor(); + + let (arg, rest) = args.split_once(' ').unwrap_or((&args, "")); + let rest = rest.trim_start().to_owned(); + + let dest = async_get_debug_argument( + arg, + "debug_app_call", + "destination", + get_destination(routing_table), + ) + .await?; + + let data = get_debug_argument(&rest, "debug_app_call", "data", get_data)?; + let data_len = data.len(); + + // Send a AppMessage + let out = match rpc + .rpc_call_app_call(dest, data) + .await + .map_err(VeilidAPIError::internal)? + { + NetworkResult::Value(v) => format!( + "Sent {} bytes, received: {}", + data_len, + print_data(&v.answer, Some(512)) + ), + r => { + return Ok(r.to_string()); + } + }; + + Ok(out) + } + async fn debug_route_allocate(&self, args: Vec) -> VeilidAPIResult { // [ord|*ord] [rel] [] [in|out] [avoid_node_id] @@ -1451,6 +1536,8 @@ detach restart network contact [] ping +appmessage +appcall relay [public|local] punish list route allocate [ord|*ord] [rel] [] [in|out] @@ -1528,6 +1615,10 @@ record list self.debug_relay(rest).await } else if arg == "ping" { self.debug_ping(rest).await + } else if arg == "appmessage" { + self.debug_app_message(rest).await + } else if arg == "appcall" { + self.debug_app_call(rest).await } else if arg == "contact" { self.debug_contact(rest).await } else if arg == "nodeinfo" { From a5e17a0d650140dba059d8cf5624626098d6a4a7 Mon Sep 17 00:00:00 2001 From: Christien Rioux Date: Sun, 10 Sep 2023 17:07:22 -0400 Subject: [PATCH 3/9] appreply --- veilid-core/src/rpc_processor/mod.rs | 5 +++ .../src/rpc_processor/operation_waiter.rs | 14 ++++++++ veilid-core/src/veilid_api/debug.rs | 34 +++++++++++++++++++ 3 files changed, 53 insertions(+) diff --git a/veilid-core/src/rpc_processor/mod.rs b/veilid-core/src/rpc_processor/mod.rs index 8f4baea8..38a38ed8 100644 --- a/veilid-core/src/rpc_processor/mod.rs +++ b/veilid-core/src/rpc_processor/mod.rs @@ -434,6 +434,11 @@ impl RPCProcessor { ////////////////////////////////////////////////////////////////////// + /// Get waiting app call id for debugging purposes + pub fn get_app_call_ids(&self) -> Vec { + self.unlocked_inner.waiting_app_call_table.get_operation_ids() + } + /// Determine if a SignedNodeInfo can be placed into the specified routing domain fn verify_node_info( &self, diff --git a/veilid-core/src/rpc_processor/operation_waiter.rs b/veilid-core/src/rpc_processor/operation_waiter.rs index 3588e10e..f7c7bd00 100644 --- a/veilid-core/src/rpc_processor/operation_waiter.rs +++ b/veilid-core/src/rpc_processor/operation_waiter.rs @@ -30,6 +30,7 @@ where C: Unpin + Clone, { context: C, + timestamp: Timestamp, eventual: EventualValue<(Option, T)>, } @@ -82,6 +83,7 @@ where let e = EventualValue::new(); let waiting_op = OperationWaitingOp { context, + timestamp: get_aligned_timestamp(), eventual: e.clone(), }; if inner.waiting_op_table.insert(op_id, waiting_op).is_some() { @@ -98,6 +100,18 @@ where } } + /// Get all waiting operation ids + pub fn get_operation_ids(&self) -> Vec { + let inner = self.inner.lock(); + let mut opids: Vec<(OperationId, Timestamp)> = inner + .waiting_op_table + .iter() + .map(|x| (*x.0, x.1.timestamp)) + .collect(); + opids.sort_by(|a, b| a.1.cmp(&b.1)); + opids.into_iter().map(|x| x.0).collect() + } + /// Get operation context pub fn get_op_context(&self, op_id: OperationId) -> Result { let inner = self.inner.lock(); diff --git a/veilid-core/src/veilid_api/debug.rs b/veilid-core/src/veilid_api/debug.rs index 81920b38..90c144c0 100644 --- a/veilid-core/src/veilid_api/debug.rs +++ b/veilid-core/src/veilid_api/debug.rs @@ -920,6 +920,37 @@ impl VeilidAPI { Ok(out) } + async fn debug_app_reply(&self, args: String) -> VeilidAPIResult { + let netman = self.network_manager()?; + let rpc = netman.rpc_processor(); + + let (call_id, data) = if args.starts_with("#") { + let (arg, rest) = args[1..].split_once(' ').unwrap_or((&args, "")); + let call_id = + OperationId::new(u64::from_str_radix(arg, 16).map_err(VeilidAPIError::generic)?); + let rest = rest.trim_start().to_owned(); + let data = get_debug_argument(&rest, "debug_app_reply", "data", get_data)?; + (call_id, data) + } else { + let call_id = rpc + .get_app_call_ids() + .first() + .cloned() + .ok_or_else(|| VeilidAPIError::generic("no app calls waiting"))?; + let data = get_debug_argument(&args, "debug_app_reply", "data", get_data)?; + (call_id, data) + }; + + let data_len = data.len(); + + // Send a AppCall Reply + self.app_call_reply(call_id, data) + .await + .map_err(VeilidAPIError::internal)?; + + Ok(format!("Replied with {} bytes", data_len)) + } + async fn debug_route_allocate(&self, args: Vec) -> VeilidAPIResult { // [ord|*ord] [rel] [] [in|out] [avoid_node_id] @@ -1538,6 +1569,7 @@ contact [] ping appmessage appcall +appreply [#id] relay [public|local] punish list route allocate [ord|*ord] [rel] [] [in|out] @@ -1619,6 +1651,8 @@ record list self.debug_app_message(rest).await } else if arg == "appcall" { self.debug_app_call(rest).await + } else if arg == "appreply" { + self.debug_app_reply(rest).await } else if arg == "contact" { self.debug_contact(rest).await } else if arg == "nodeinfo" { From 6e26fb4c8fe0b58362c6830dc6763272c9586d1e Mon Sep 17 00:00:00 2001 From: Christien Rioux Date: Sun, 10 Sep 2023 20:16:57 -0400 Subject: [PATCH 4/9] more nodeinfo --- veilid-core/src/veilid_api/debug.rs | 47 +++++++++++++++++++++++++- veilid-flutter/lib/default_config.dart | 4 +-- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/veilid-core/src/veilid_api/debug.rs b/veilid-core/src/veilid_api/debug.rs index 90c144c0..29d6ad3d 100644 --- a/veilid-core/src/veilid_api/debug.rs +++ b/veilid-core/src/veilid_api/debug.rs @@ -15,6 +15,35 @@ static DEBUG_CACHE: Mutex = Mutex::new(DebugCache { imported_routes: Vec::new(), }); +fn format_opt_ts(ts: Option) -> String { + let Some(ts) = ts else { + return "---".to_owned(); + }; + let ts = ts.as_u64(); + let secs = timestamp_to_secs(ts); + if secs >= 1.0 { + format!("{:.2}s", timestamp_to_secs(ts)) + } else { + format!("{:.2}ms", timestamp_to_secs(ts) * 1000.0) + } +} + +fn format_opt_bps(bps: Option) -> String { + let Some(bps) = bps else { + return "---".to_owned(); + }; + let bps = bps.as_u64(); + if bps >= 1024u64 * 1024u64 * 1024u64 { + format!("{:.2}GB/s", (bps / (1024u64 * 1024u64)) as f64 / 1024.0) + } else if bps >= 1024u64 * 1024u64 { + format!("{:.2}MB/s", (bps / 1024u64) as f64 / 1024.0) + } else if bps >= 1024u64 { + format!("{:.2}KB/s", bps as f64 / 1024.0) + } else { + format!("{:.2}B/s", bps as f64) + } +} + fn get_bucket_entry_state(text: &str) -> Option { if text == "dead" { Some(BucketEntryState::Dead) @@ -653,7 +682,23 @@ impl VeilidAPI { async fn debug_nodeinfo(&self, _args: String) -> VeilidAPIResult { // Dump routing table entry let routing_table = self.network_manager()?.routing_table(); - Ok(routing_table.debug_info_nodeinfo()) + let nodeinfo = routing_table.debug_info_nodeinfo(); + + // Dump core state + let state = self.get_state().await?; + + let mut peertable = format!("Connections: {}\n", state.network.peers.len()); + for peer in state.network.peers { + peertable += &format!( + " {} | {} | {} | {} down | {} up\n", + peer.node_ids.first().unwrap(), + peer.peer_address, + format_opt_ts(peer.peer_stats.latency.map(|l| l.average)), + format_opt_bps(Some(peer.peer_stats.transfer.down.average)), + format_opt_bps(Some(peer.peer_stats.transfer.up.average)), + ); + } + Ok(format!("{}\n\n{}\n\n", nodeinfo, peertable)) } async fn debug_config(&self, args: String) -> VeilidAPIResult { diff --git a/veilid-flutter/lib/default_config.dart b/veilid-flutter/lib/default_config.dart index eac855bc..a10787f3 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: 32, + maxConnections: 1024, listenAddress: '', path: 'ws', ), wss: VeilidConfigWSS( connect: true, listen: false, - maxConnections: 32, + maxConnections: 1024, listenAddress: '', path: 'ws', ), From 5acf024cdbb1205b50d66854268299463f8d15d3 Mon Sep 17 00:00:00 2001 From: Christien Rioux Date: Sun, 10 Sep 2023 20:20:03 -0400 Subject: [PATCH 5/9] oops --- 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 a10787f3..eac855bc 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: 1024, + maxConnections: 32, listenAddress: '', path: 'ws', ), wss: VeilidConfigWSS( connect: true, listen: false, - maxConnections: 1024, + maxConnections: 32, listenAddress: '', path: 'ws', ), From b3294d905d685e99e31bcc347982bddf090dcfb8 Mon Sep 17 00:00:00 2001 From: Christien Rioux Date: Sun, 10 Sep 2023 20:30:29 -0400 Subject: [PATCH 6/9] rename --- veilid-core/src/veilid_api/debug.rs | 2 +- veilid-flutter/lib/default_config.dart | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/veilid-core/src/veilid_api/debug.rs b/veilid-core/src/veilid_api/debug.rs index 29d6ad3d..cc7ed02f 100644 --- a/veilid-core/src/veilid_api/debug.rs +++ b/veilid-core/src/veilid_api/debug.rs @@ -687,7 +687,7 @@ impl VeilidAPI { // Dump core state let state = self.get_state().await?; - let mut peertable = format!("Connections: {}\n", state.network.peers.len()); + let mut peertable = format!("Recent Peers: {}\n", state.network.peers.len()); for peer in state.network.peers { peertable += &format!( " {} | {} | {} | {} down | {} up\n", diff --git a/veilid-flutter/lib/default_config.dart b/veilid-flutter/lib/default_config.dart index eac855bc..a10787f3 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: 32, + maxConnections: 1024, listenAddress: '', path: 'ws', ), wss: VeilidConfigWSS( connect: true, listen: false, - maxConnections: 32, + maxConnections: 1024, listenAddress: '', path: 'ws', ), From 5b3d589bf2478d9448c34e2d3bc11c0f1dc07dba Mon Sep 17 00:00:00 2001 From: Christien Rioux Date: Sun, 10 Sep 2023 20:36:39 -0400 Subject: [PATCH 7/9] print max --- veilid-core/src/routing_table/routing_table_inner.rs | 2 +- veilid-core/src/veilid_api/debug.rs | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/veilid-core/src/routing_table/routing_table_inner.rs b/veilid-core/src/routing_table/routing_table_inner.rs index 6da5cefa..c2cfc291 100644 --- a/veilid-core/src/routing_table/routing_table_inner.rs +++ b/veilid-core/src/routing_table/routing_table_inner.rs @@ -1,7 +1,7 @@ use super::*; use weak_table::PtrWeakHashSet; -const RECENT_PEERS_TABLE_SIZE: usize = 64; +pub const RECENT_PEERS_TABLE_SIZE: usize = 64; pub type EntryCounts = BTreeMap<(RoutingDomain, CryptoKind), usize>; ////////////////////////////////////////////////////////////////////////// diff --git a/veilid-core/src/veilid_api/debug.rs b/veilid-core/src/veilid_api/debug.rs index cc7ed02f..633f77f4 100644 --- a/veilid-core/src/veilid_api/debug.rs +++ b/veilid-core/src/veilid_api/debug.rs @@ -687,7 +687,11 @@ impl VeilidAPI { // Dump core state let state = self.get_state().await?; - let mut peertable = format!("Recent Peers: {}\n", state.network.peers.len()); + let mut peertable = format!( + "Recent Peers: {} (max {})\n", + state.network.peers.len(), + RECENT_PEERS_TABLE_SIZE + ); for peer in state.network.peers { peertable += &format!( " {} | {} | {} | {} down | {} up\n", From 671f3495786cb859c45e2eaabdcd02c3217e33a6 Mon Sep 17 00:00:00 2001 From: Christien Rioux Date: Tue, 12 Sep 2023 21:40:13 -0400 Subject: [PATCH 8/9] conn table --- .../src/network_manager/connection_manager.rs | 8 ++++++ .../src/network_manager/connection_table.rs | 28 +++++++++++++++++++ .../src/network_manager/network_connection.rs | 11 ++++++++ veilid-core/src/veilid_api/debug.rs | 7 ++++- 4 files changed, 53 insertions(+), 1 deletion(-) diff --git a/veilid-core/src/network_manager/connection_manager.rs b/veilid-core/src/network_manager/connection_manager.rs index febad51c..9ea09d34 100644 --- a/veilid-core/src/network_manager/connection_manager.rs +++ b/veilid-core/src/network_manager/connection_manager.rs @@ -404,4 +404,12 @@ impl ConnectionManager { let _ = sender.send_async(ConnectionManagerEvent::Dead(conn)).await; } } + + pub async fn debug_print(&self) -> String { + //let inner = self.arc.inner.lock(); + format!( + "Connection Table:\n\n{}", + self.arc.connection_table.debug_print_table() + ) + } } diff --git a/veilid-core/src/network_manager/connection_table.rs b/veilid-core/src/network_manager/connection_table.rs index be39fb3b..d2d13bcb 100644 --- a/veilid-core/src/network_manager/connection_table.rs +++ b/veilid-core/src/network_manager/connection_table.rs @@ -72,6 +72,15 @@ impl ConnectionTable { } } + fn index_to_protocol(idx: usize) -> ProtocolType { + match idx { + 0 => ProtocolType::TCP, + 1 => ProtocolType::WS, + 2 => ProtocolType::WSS, + _ => panic!("not a connection-oriented protocol"), + } + } + #[instrument(level = "trace", skip(self))] pub async fn join(&self) { let mut unord = { @@ -331,4 +340,23 @@ impl ConnectionTable { let conn = Self::remove_connection_records(&mut *inner, id); Some(conn) } + + pub fn debug_print_table(&self) -> String { + let mut out = String::new(); + let inner = self.inner.lock(); + let cur_ts = get_aligned_timestamp(); + for t in 0..inner.conn_by_id.len() { + out += &format!( + " {} Connections: ({}/{})\n", + Self::index_to_protocol(t).to_string(), + inner.conn_by_id[t].len(), + inner.max_connections[t] + ); + + for (_, conn) in &inner.conn_by_id[t] { + out += &format!(" {}\n", conn.debug_print(cur_ts)); + } + } + out + } } diff --git a/veilid-core/src/network_manager/network_connection.rs b/veilid-core/src/network_manager/network_connection.rs index b96a36e3..76b4e13d 100644 --- a/veilid-core/src/network_manager/network_connection.rs +++ b/veilid-core/src/network_manager/network_connection.rs @@ -391,6 +391,17 @@ impl NetworkConnection { .await; }.instrument(trace_span!("process_connection"))) } + + pub fn debug_print(&self, cur_ts: Timestamp) -> String { + format!("{} <- {} | {:x} | est {} sent {} rcvd {}", + self.descriptor.remote_address(), + self.descriptor.local().map(|x| x.to_string()).unwrap_or("---".to_owned()), + self.connection_id.as_u64(), + debug_duration(cur_ts.as_u64().saturating_sub(self.established_time.as_u64())), + self.stats().last_message_sent_time.map(|ts| debug_duration(cur_ts.as_u64().saturating_sub(ts.as_u64())) ).unwrap_or("---".to_owned()), + self.stats().last_message_recv_time.map(|ts| debug_duration(cur_ts.as_u64().saturating_sub(ts.as_u64())) ).unwrap_or("---".to_owned()), + ) + } } // Resolves ready when the connection loop has terminated diff --git a/veilid-core/src/veilid_api/debug.rs b/veilid-core/src/veilid_api/debug.rs index 633f77f4..2ef953de 100644 --- a/veilid-core/src/veilid_api/debug.rs +++ b/veilid-core/src/veilid_api/debug.rs @@ -682,6 +682,7 @@ impl VeilidAPI { async fn debug_nodeinfo(&self, _args: String) -> VeilidAPIResult { // Dump routing table entry let routing_table = self.network_manager()?.routing_table(); + let connection_manager = self.network_manager()?.connection_manager(); let nodeinfo = routing_table.debug_info_nodeinfo(); // Dump core state @@ -702,7 +703,11 @@ impl VeilidAPI { format_opt_bps(Some(peer.peer_stats.transfer.up.average)), ); } - Ok(format!("{}\n\n{}\n\n", nodeinfo, peertable)) + + // Dump connection table + let connman = connection_manager.debug_print().await; + + Ok(format!("{}\n\n{}\n\n{}\n\n", nodeinfo, peertable, connman)) } async fn debug_config(&self, args: String) -> VeilidAPIResult { From 86aae741e0fdcfa8b0fb6317a3ba898d09cb4122 Mon Sep 17 00:00:00 2001 From: Christien Rioux Date: Wed, 13 Sep 2023 17:00:39 -0400 Subject: [PATCH 9/9] reverse connect for wasm nodes --- .../src/routing_table/routing_domains.rs | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/veilid-core/src/routing_table/routing_domains.rs b/veilid-core/src/routing_table/routing_domains.rs index 55bcef67..ba120369 100644 --- a/veilid-core/src/routing_table/routing_domains.rs +++ b/veilid-core/src/routing_table/routing_domains.rs @@ -470,7 +470,7 @@ impl RoutingDomainDetail for PublicInternetRoutingDomainDetail { return ContactMethod::Unreachable; }; - // Can we reach the full relay? + // Can we reach the inbound relay? if first_filtered_dial_info_detail_between_nodes( node_a, &node_b_relay, @@ -480,11 +480,30 @@ impl RoutingDomainDetail for PublicInternetRoutingDomainDetail { ) .is_some() { + ///////// Reverse connection + + // Get the best match dial info for an reverse inbound connection from node B to node A + if let Some(reverse_did) = first_filtered_dial_info_detail_between_nodes( + node_b, + node_a, + &dial_info_filter, + sequencing, + dif_sort.clone() + ) { + // Can we receive a direct reverse connection? + if !reverse_did.class.requires_signal() { + return ContactMethod::SignalReverse( + node_b_relay_id, + node_b_id, + ); + } + } + return ContactMethod::InboundRelay(node_b_relay_id); } } - // If node A can't reach the node by other means, it may need to use its own relay + // If node A can't reach the node by other means, it may need to use its outbound relay if peer_a.signed_node_info().node_info().network_class().outbound_wants_relay() { if let Some(node_a_relay_id) = peer_a.signed_node_info().relay_ids().get(best_ck) { // Ensure it's not our relay we're trying to reach