iroh_base/
node_addr.rs

1//! Addressing for iroh nodes.
2//!
3//! This module contains some common addressing types for iroh.  A node is uniquely
4//! identified by the [`NodeId`] but that does not make it addressable on the network layer.
5//! For this the addition of a [`RelayUrl`] and/or direct addresses are required.
6//!
7//! The primary way of addressing a node is by using the [`NodeAddr`].
8
9use std::{collections::BTreeSet, net::SocketAddr};
10
11use serde::{Deserialize, Serialize};
12
13use crate::{NodeId, PublicKey, RelayUrl};
14
15/// Network-level addressing information for an iroh node.
16///
17/// This combines a node's identifier with network-level addressing information of how to
18/// contact the node.
19///
20/// To establish a network connection to a node both the [`NodeId`] and one or more network
21/// paths are needed.  The network paths can come from various sources:
22///
23/// - A [discovery] service which can provide routing information for a given [`NodeId`].
24///
25/// - A [`RelayUrl`] of the node's [home relay], this allows establishing the connection via
26///   the Relay server and is very reliable.
27///
28/// - One or more *direct addresses* on which the node might be reachable.  Depending on the
29///   network location of both nodes it might not be possible to establish a direct
30///   connection without the help of a [Relay server].
31///
32/// This structure will always contain the required [`NodeId`] and will contain an optional
33/// number of network-level addressing information.  It is a generic addressing type used
34/// whenever a connection to other nodes needs to be established.
35///
36/// [discovery]: https://docs.rs/iroh/*/iroh/index.html#node-discovery
37/// [home relay]: https://docs.rs/iroh/*/iroh/relay/index.html
38/// [Relay server]: https://docs.rs/iroh/*/iroh/index.html#relay-servers
39#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
40pub struct NodeAddr {
41    /// The node's identifier.
42    pub node_id: NodeId,
43    /// The node's home relay url.
44    pub relay_url: Option<RelayUrl>,
45    /// Socket addresses where the peer might be reached directly.
46    pub direct_addresses: BTreeSet<SocketAddr>,
47}
48
49impl NodeAddr {
50    /// Creates a new [`NodeAddr`] with no `relay_url` and no `direct_addresses`.
51    pub fn new(node_id: PublicKey) -> Self {
52        NodeAddr {
53            node_id,
54            relay_url: None,
55            direct_addresses: Default::default(),
56        }
57    }
58
59    /// Adds a relay url.
60    pub fn with_relay_url(mut self, relay_url: RelayUrl) -> Self {
61        self.relay_url = Some(relay_url);
62        self
63    }
64
65    /// Adds the given direct addresses.
66    pub fn with_direct_addresses(
67        mut self,
68        addresses: impl IntoIterator<Item = SocketAddr>,
69    ) -> Self {
70        self.direct_addresses = addresses.into_iter().collect();
71        self
72    }
73
74    /// Creates a new [`NodeAddr`] from its parts.
75    pub fn from_parts(
76        node_id: PublicKey,
77        relay_url: Option<RelayUrl>,
78        direct_addresses: impl IntoIterator<Item = SocketAddr>,
79    ) -> Self {
80        Self {
81            node_id,
82            relay_url,
83            direct_addresses: direct_addresses.into_iter().collect(),
84        }
85    }
86
87    /// Returns true, if only a [`NodeId`] is present.
88    pub fn is_empty(&self) -> bool {
89        self.relay_url.is_none() && self.direct_addresses.is_empty()
90    }
91
92    /// Returns the direct addresses of this peer.
93    pub fn direct_addresses(&self) -> impl Iterator<Item = &SocketAddr> {
94        self.direct_addresses.iter()
95    }
96
97    /// Returns the relay url of this peer.
98    pub fn relay_url(&self) -> Option<&RelayUrl> {
99        self.relay_url.as_ref()
100    }
101}
102
103impl From<(PublicKey, Option<RelayUrl>, &[SocketAddr])> for NodeAddr {
104    fn from(value: (PublicKey, Option<RelayUrl>, &[SocketAddr])) -> Self {
105        let (node_id, relay_url, direct_addresses_iter) = value;
106        NodeAddr {
107            node_id,
108            relay_url,
109            direct_addresses: direct_addresses_iter.iter().copied().collect(),
110        }
111    }
112}
113
114impl From<NodeId> for NodeAddr {
115    fn from(node_id: NodeId) -> Self {
116        NodeAddr::new(node_id)
117    }
118}