1use std::{collections::BTreeSet, net::SocketAddr, str::FromStr};23use iroh_base::{RelayUrl, TransportAddr};4use napi_derive::napi;56use crate::EndpointId;78/// An endpoint's id together with the network-level addresses where it can be9/// reached. Mirrors the uniffi `EndpointAddr` object surface.101112pub struct EndpointAddr {13 pub(crate) id: [u8; 32],14 pub(crate) relay_url: Option<String>,15 pub(crate) addresses: Vec<String>,16}171819impl EndpointAddr {20 /// Create a new [`EndpointAddr`].21 22 pub fn new(id: &EndpointId, relay_url: Option<String>, addresses: Option<Vec<String>>) -> Self {23 Self {24 id: id.raw_bytes(),25 relay_url,26 addresses: addresses.unwrap_or_default(),27 }28 }2930 /// The endpoint id.31 32 pub fn id(&self) -> EndpointId {33 EndpointId::from_raw_bytes(self.id)34 }3536 /// The direct (ip:port) addresses of this peer.37 38 pub fn direct_addresses(&self) -> Vec<String> {39 self.addresses.clone()40 }4142 /// The home relay URL for this peer, if known.43 44 pub fn relay_url(&self) -> Option<String> {45 self.relay_url.clone()46 }4748 /// Returns true if both [`EndpointAddr`]s have the same values.49 50 pub fn equal(&self, other: &EndpointAddr) -> bool {51 self == other52 }5354 /// Clean string representation.55 56 pub fn to_string(&self) -> String {57 let id = iroh::EndpointId::from_bytes(&self.id)58 .map(|i| i.to_string())59 .unwrap_or_else(|_| "<invalid>".to_string());60 let mut s = id;61 if let Some(relay) = &self.relay_url {62 s.push_str(&format!(" relay={relay}"));63 }64 if !self.addresses.is_empty() {65 s.push_str(&format!(" addrs=[{}]", self.addresses.join(", ")));66 }67 s68 }69}7071impl TryFrom<&EndpointAddr> for iroh::EndpointAddr {72 type Error = anyhow::Error;7374 fn try_from(value: &EndpointAddr) -> anyhow::Result<Self> {75 let id = iroh::EndpointId::from_bytes(&value.id)?;76 let mut addrs: BTreeSet<TransportAddr> = BTreeSet::new();77 for addr in &value.addresses {78 let socket = SocketAddr::from_str(addr)?;79 addrs.insert(TransportAddr::Ip(socket));80 }81 if let Some(relay) = &value.relay_url {82 let url = RelayUrl::from_str(relay)?;83 addrs.insert(TransportAddr::Relay(url));84 }85 Ok(iroh::EndpointAddr { id, addrs })86 }87}8889impl From<iroh::EndpointAddr> for EndpointAddr {90 fn from(value: iroh::EndpointAddr) -> Self {91 let mut relay_url = None;92 let mut addresses = Vec::new();93 for addr in &value.addrs {94 match addr {95 TransportAddr::Relay(url) => relay_url = Some(url.to_string()),96 TransportAddr::Ip(socket) => addresses.push(socket.to_string()),97 _ => {}98 }99 }100 EndpointAddr {101 id: *value.id.as_bytes(),102 relay_url,103 addresses,104 }105 }106}