Live video on the AT Protocol
1use std::{str::FromStr, sync::Arc};
2
3use crate::public_key::PublicKey;
4
5/// A peer and it's addressing information.
6#[derive(Debug, Clone, PartialEq, Eq, uniffi::Object)]
7pub struct NodeAddr {
8 node_id: Arc<PublicKey>,
9 relay_url: Option<String>,
10 addresses: Vec<String>,
11}
12
13#[uniffi::export]
14impl NodeAddr {
15 /// Create a new [`NodeAddr`] with empty [`AddrInfo`].
16 #[uniffi::constructor]
17 pub fn new(node_id: &PublicKey, derp_url: Option<String>, addresses: Vec<String>) -> Self {
18 Self {
19 node_id: Arc::new(node_id.clone()),
20 relay_url: derp_url,
21 addresses,
22 }
23 }
24
25 pub fn node_id(&self) -> PublicKey {
26 self.node_id.as_ref().clone()
27 }
28
29 /// Get the direct addresses of this peer.
30 pub fn direct_addresses(&self) -> Vec<String> {
31 self.addresses.clone()
32 }
33
34 /// Get the home relay URL for this peer
35 pub fn relay_url(&self) -> Option<String> {
36 self.relay_url.clone()
37 }
38
39 /// Returns true if both NodeAddr's have the same values
40 pub fn equal(&self, other: &NodeAddr) -> bool {
41 self == other
42 }
43}
44
45/// Error when converting from ffi NodeAddr to iroh::NodeAddr
46#[derive(Debug, snafu::Snafu, uniffi::Error)]
47#[uniffi(flat_error)]
48#[snafu(visibility(pub(crate)))]
49pub enum NodeAddrError {
50 #[snafu(display("Invalid URL"), context(false))]
51 InvalidUrl { source: url::ParseError },
52 #[snafu(display("Invalid network address"), context(false))]
53 InvalidNetworkAddress { source: std::net::AddrParseError },
54}
55
56impl TryFrom<NodeAddr> for iroh::NodeAddr {
57 type Error = NodeAddrError;
58
59 fn try_from(value: NodeAddr) -> Result<Self, Self::Error> {
60 let mut node_addr = iroh::NodeAddr::new((&*value.node_id).into());
61 let addresses = value
62 .direct_addresses()
63 .into_iter()
64 .map(|addr| std::net::SocketAddr::from_str(&addr))
65 .collect::<Result<Vec<_>, _>>()?;
66
67 if let Some(derp_url) = value.relay_url() {
68 let url = url::Url::parse(&derp_url)?;
69
70 node_addr = node_addr.with_relay_url(url.into());
71 }
72 node_addr = node_addr.with_direct_addresses(addresses);
73 Ok(node_addr)
74 }
75}
76
77impl From<iroh::NodeAddr> for NodeAddr {
78 fn from(value: iroh::NodeAddr) -> Self {
79 NodeAddr {
80 node_id: Arc::new(value.node_id.into()),
81 relay_url: value.relay_url.map(|url| url.to_string()),
82 addresses: value
83 .direct_addresses
84 .into_iter()
85 .map(|d| d.to_string())
86 .collect(),
87 }
88 }
89}