clone

a self-hosted sync node for lofi apps: jazz sync over iroh, ticket-gated, with no static ip or cloud needed

feat/write-verdict-foundations
lofi-node / native / iroh-js / src / path.rs
path.rs 5.1K
1use iroh::endpoint::LocalTransportAddr;2use iroh_base::TransportAddr;3use napi_derive::napi;45/// Flattened headline numbers from `noq::PathStats`.6#[derive(Debug, Clone)]7#[napi(object)]8pub struct PathStatsRecord {9 pub rtt_ms: i64,10 pub udp_tx_datagrams: i64,11 pub udp_tx_bytes: i64,12 pub udp_rx_datagrams: i64,13 pub udp_rx_bytes: i64,14 pub cwnd: i64,15 pub congestion_events: i64,16 pub lost_packets: i64,17 pub lost_bytes: i64,18 pub current_mtu: u32,19}2021impl From<iroh::endpoint::PathStats> for PathStatsRecord {22 fn from(s: iroh::endpoint::PathStats) -> Self {23 Self {24 rtt_ms: s.rtt.as_millis() as i64,25 udp_tx_datagrams: s.udp_tx.datagrams as i64,26 udp_tx_bytes: s.udp_tx.bytes as i64,27 udp_rx_datagrams: s.udp_rx.datagrams as i64,28 udp_rx_bytes: s.udp_rx.bytes as i64,29 cwnd: s.cwnd as i64,30 congestion_events: s.congestion_events as i64,31 lost_packets: s.lost_packets as i64,32 lost_bytes: s.lost_bytes as i64,33 current_mtu: s.current_mtu as u32,34 }35 }36}3738/// A flat snapshot of an open path's state.39#[derive(Debug, Clone)]40#[napi(object)]41pub struct PathSnapshot {42 pub id: String,43 pub is_selected: bool,44 pub remote_addr: String,45 pub is_ip: bool,46 pub is_relay: bool,47 pub rtt_ms: i64,48 pub stats: PathStatsRecord,49}5051pub(crate) fn transport_addr_to_string(addr: &TransportAddr) -> String {52 match addr {53 TransportAddr::Ip(socket) => socket.to_string(),54 TransportAddr::Relay(url) => url.to_string(),55 _ => "unknown".to_string(),56 }57}5859pub(crate) fn local_transport_addr_to_string(addr: &LocalTransportAddr) -> String {60 match addr {61 LocalTransportAddr::Ip(Some(ip)) => ip.to_string(),62 LocalTransportAddr::Ip(None) => "unknown".to_string(),63 LocalTransportAddr::Relay(url) => url.to_string(),64 LocalTransportAddr::Custom(Some(c)) => format!("{c:?}"),65 _ => "unknown".to_string(),66 }67}6869/// An event from `Connection::watchPathEvents`.70#[derive(Debug, Clone)]71#[napi(string_enum)]72pub enum PathEventKind {73 Opened,74 Closed,75 Selected,76 Lagged,77}7879/// A path event with its associated data.80#[derive(Debug, Clone)]81#[napi(object)]82pub struct PathEvent {83 pub kind: PathEventKind,84 pub id: Option<String>,85 pub remote_addr: Option<String>,86 pub local_addr: Option<String>,87 pub last_stats: Option<PathStatsRecord>,88 pub missed: Option<i64>,89}9091impl From<iroh::endpoint::PathEvent> for PathEvent {92 fn from(e: iroh::endpoint::PathEvent) -> Self {93 match e {94 iroh::endpoint::PathEvent::Opened {95 id,96 remote_addr,97 local_addr,98 ..99 } => PathEvent {100 kind: PathEventKind::Opened,101 id: Some(id.to_string()),102 remote_addr: Some(transport_addr_to_string(&remote_addr)),103 local_addr: Some(local_transport_addr_to_string(&local_addr)),104 last_stats: None,105 missed: None,106 },107 iroh::endpoint::PathEvent::Closed {108 id,109 remote_addr,110 local_addr,111 last_stats,112 ..113 } => PathEvent {114 kind: PathEventKind::Closed,115 id: Some(id.to_string()),116 remote_addr: Some(transport_addr_to_string(&remote_addr)),117 local_addr: Some(local_transport_addr_to_string(&local_addr)),118 last_stats: Some((*last_stats).into()),119 missed: None,120 },121 iroh::endpoint::PathEvent::Selected {122 id,123 remote_addr,124 local_addr,125 ..126 } => PathEvent {127 kind: PathEventKind::Selected,128 id: Some(id.to_string()),129 remote_addr: Some(transport_addr_to_string(&remote_addr)),130 local_addr: Some(local_transport_addr_to_string(&local_addr)),131 last_stats: None,132 missed: None,133 },134 iroh::endpoint::PathEvent::Lagged { missed, .. } => PathEvent {135 kind: PathEventKind::Lagged,136 id: None,137 remote_addr: None,138 local_addr: None,139 last_stats: None,140 missed: Some(missed as i64),141 },142 _ => PathEvent {143 kind: PathEventKind::Lagged,144 id: None,145 remote_addr: None,146 local_addr: None,147 last_stats: None,148 missed: Some(0),149 },150 }151 }152}153154pub(crate) fn snapshot_paths(conn: &iroh::endpoint::Connection) -> Vec<PathSnapshot> {155 conn.paths()156 .iter()157 .map(|p| PathSnapshot {158 id: p.id().to_string(),159 is_selected: p.is_selected(),160 remote_addr: transport_addr_to_string(p.remote_addr()),161 is_ip: p.is_ip(),162 is_relay: p.is_relay(),163 rtt_ms: p.rtt().as_millis() as i64,164 stats: p.stats().into(),165 })166 .collect()167}