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}