Skip to content

Commit

Permalink
Merge remote-tracking branch 'n0/main' into do-not-dial-self
Browse files Browse the repository at this point in the history
  • Loading branch information
divagant-martian committed Jun 18, 2024
2 parents 9a077e0 + a5e5939 commit acf09c3
Show file tree
Hide file tree
Showing 27 changed files with 203 additions and 175 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions deny.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
[bans]
multiple-versions = "allow"
deny = [
"openssl",
"native-tls",
]

[licenses]
allow = [
Expand Down
4 changes: 4 additions & 0 deletions iroh-base/src/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ pub struct PublicKey([u8; 32]);

/// The identifier for a node in the (iroh) network.
///
/// Each node in iroh has a unique identifier created as a cryptographic key. This can be
/// used to globally identify a node. Since it is also a cryptographic key it is also the
/// mechanism by which all traffic is always encrypted for a specific node only.
///
/// This is equivalent to [`PublicKey`]. By convention we will (or should) use `PublicKey`
/// as type name when performing cryptographic operations, but use `NodeId` when referencing
/// a node. E.g.:
Expand Down
119 changes: 83 additions & 36 deletions iroh-base/src/node_addr.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
//! Addressing for iroh nodes.
//!
//! This module contains some common addressing types for iroh. A node is uniquely
//! identified by the [`NodeId`] but that does not make it addressable on the network layer.
//! For this the addition of a [`RelayUrl`] and/or direct addresses are required.
//!
//! The primary way of addressing a node is by using the [`NodeAddr`].
use std::{collections::BTreeSet, fmt, net::SocketAddr, ops::Deref, str::FromStr};

use anyhow::Context;
Expand All @@ -6,31 +14,54 @@ use url::Url;

use crate::key::{NodeId, PublicKey};

/// A peer and it's addressing information.
/// Network-level addressing information for an iroh-net node.
///
/// This combines a node's identifier with network-level addressing information of how to
/// contact the node.
///
/// To establish a network connection to a node both the [`NodeId`] and one or more network
/// paths are needed. The network paths can come from various sources:
///
/// - A [discovery] service which can provide routing information for a given [`NodeId`].
///
/// - A [`RelayUrl`] of the node's [home relay], this allows establishing the connection via
/// the Relay server and is very reliable.
///
/// - One or more *direct addresses* on which the node might be reachable. Depending on the
/// network location of both nodes it might not be possible to establish a direct
/// connection without the help of a [Relay server].
///
/// This structure will always contain the required [`NodeId`] and will contain an optional
/// number of network-level addressing information. It is a generic addressing type used
/// whenever a connection to other nodes needs to be established.
///
/// [discovery]: https://docs.rs/iroh_net/*/iroh_net/index.html#node-discovery
/// [home relay]: https://docs.rs/iroh_net/*/iroh_net/relay/index.html
/// [Relay server]: https://docs.rs/iroh_net/*/iroh_net/index.html#relay-servers
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct NodeAddr {
/// The node's public key.
pub node_id: PublicKey,
/// The node's identifier.
pub node_id: NodeId,
/// Addressing information to connect to [`Self::node_id`].
pub info: AddrInfo,
}

impl NodeAddr {
/// Create a new [`NodeAddr`] with empty [`AddrInfo`].
/// Creates a new [`NodeAddr`] with empty [`AddrInfo`].
pub fn new(node_id: PublicKey) -> Self {
NodeAddr {
node_id,
info: Default::default(),
}
}

/// Add a relay url to the peer's [`AddrInfo`].
/// Adds a relay url to the node's [`AddrInfo`].
pub fn with_relay_url(mut self, relay_url: RelayUrl) -> Self {
self.info.relay_url = Some(relay_url);
self
}

/// Add the given direct addresses to the peer's [`AddrInfo`].
/// Adds the given direct addresses to the peer's [`AddrInfo`].
pub fn with_direct_addresses(
mut self,
addresses: impl IntoIterator<Item = SocketAddr>,
Expand All @@ -39,17 +70,38 @@ impl NodeAddr {
self
}

/// Apply the options to `self`.
/// Creates a new [`NodeAddr`] from its parts.
pub fn from_parts(
node_id: PublicKey,
relay_url: Option<RelayUrl>,
direct_addresses: Vec<SocketAddr>,
) -> Self {
Self {
node_id,
info: AddrInfo {
relay_url,
direct_addresses: direct_addresses.into_iter().collect(),
},
}
}

/// Applies the options to `self`.
///
/// This is used to more tightly control the information stored in a [`NodeAddr`]
/// received from another API. E.g. to ensure a [discovery] service is used the
/// `AddrInfoOptions::Id`] option could be used to remove all other addressing details.
///
/// [discovery]: https://docs.rs/iroh_net/*/iroh_net/index.html#node-discovery
pub fn apply_options(&mut self, opts: AddrInfoOptions) {
self.info.apply_options(opts);
}

/// Get the direct addresses of this peer.
/// Returns the direct addresses of this peer.
pub fn direct_addresses(&self) -> impl Iterator<Item = &SocketAddr> {
self.info.direct_addresses.iter()
}

/// Get the relay url of this peer.
/// Returns the relay url of this peer.
pub fn relay_url(&self) -> Option<&RelayUrl> {
self.info.relay_url.as_ref()
}
Expand All @@ -74,22 +126,34 @@ impl From<NodeId> for NodeAddr {
}
}

/// Addressing information to connect to a peer.
/// Network paths to contact an iroh-net node.
///
/// This contains zero or more network paths to establish a connection to an iroh-net node.
/// Unless a [discovery service] is used at least one path is required to connect to an
/// other node, see [`NodeAddr`] for details.
///
/// [discovery]: https://docs.rs/iroh_net/*/iroh_net/index.html#node-discovery
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
pub struct AddrInfo {
/// The peer's home relay url.
/// The node's home relay url.
pub relay_url: Option<RelayUrl>,
/// Socket addresses where the peer might be reached directly.
pub direct_addresses: BTreeSet<SocketAddr>,
}

impl AddrInfo {
/// Return whether this addressing information is empty.
/// Returns whether this addressing information is empty.
pub fn is_empty(&self) -> bool {
self.relay_url.is_none() && self.direct_addresses.is_empty()
}

/// Apply the options to `self`.
/// Applies the options to `self`.
///
/// This is used to more tightly control the information stored in ab [`AddrInfo`]
/// received from another API. E.g. to ensure a [discovery] service is used the
/// `AddrInfoOptions::Id`] option could be used to remove all other addressing details.
///
/// [discovery]: https://docs.rs/iroh_net/*/iroh_net/index.html#node-discovery
pub fn apply_options(&mut self, opts: AddrInfoOptions) {
match opts {
AddrInfoOptions::Id => {
Expand All @@ -109,24 +173,7 @@ impl AddrInfo {
}
}

impl NodeAddr {
/// Create a new [`NodeAddr`] from its parts.
pub fn from_parts(
node_id: PublicKey,
relay_url: Option<RelayUrl>,
direct_addresses: Vec<SocketAddr>,
) -> Self {
Self {
node_id,
info: AddrInfo {
relay_url,
direct_addresses: direct_addresses.into_iter().collect(),
},
}
}
}

/// Options to configure what is included in a `NodeAddr`.
/// Options to configure what is included in a [`NodeAddr`] and [`AddrInfo`].
#[derive(
Copy,
Clone,
Expand All @@ -145,11 +192,11 @@ pub enum AddrInfoOptions {
/// This usually means that iroh-dns discovery is used to find address information.
#[default]
Id,
/// Include both the relay URL and the direct addresses.
/// Includes both the relay URL and the direct addresses.
RelayAndAddresses,
/// Only include the relay URL.
/// Only includes the relay URL.
Relay,
/// Only include the direct addresses.
/// Only includes the direct addresses.
Addresses,
}

Expand Down Expand Up @@ -186,7 +233,7 @@ impl From<Url> for RelayUrl {
}
}

/// This is a convenience only to directly parse strings.
/// Support for parsing strings directly.
///
/// If you need more control over the error first create a [`Url`] and use [`RelayUrl::from`]
/// instead.
Expand All @@ -205,7 +252,7 @@ impl From<RelayUrl> for Url {
}
}

/// Dereference to the wrapped [`Url`].
/// Dereferences to the wrapped [`Url`].
///
/// Note that [`DerefMut`] is not implemented on purpose, so this type has more flexibility
/// to change the inner later.
Expand Down
6 changes: 3 additions & 3 deletions iroh-cli/src/commands/doctor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -692,7 +692,7 @@ async fn connect(
let conn = endpoint.connect(node_addr, &DR_RELAY_ALPN).await;
match conn {
Ok(connection) => {
let maybe_stream = endpoint.conn_type_stream(&node_id);
let maybe_stream = endpoint.conn_type_stream(node_id);
let gui = Gui::new(endpoint, node_id);
if let Ok(stream) = maybe_stream {
log_connection_changes(gui.mp.clone(), node_id, stream);
Expand Down Expand Up @@ -742,7 +742,7 @@ async fn accept(
secret_key.public(),
remote_addrs,
);
if let Some(relay_url) = endpoint.my_relay() {
if let Some(relay_url) = endpoint.home_relay() {
println!(
"\tUsing just the relay url:\niroh doctor connect {} --relay-url {}\n",
secret_key.public(),
Expand Down Expand Up @@ -770,7 +770,7 @@ async fn accept(
println!("Accepted connection from {}", remote_peer_id);
let t0 = Instant::now();
let gui = Gui::new(endpoint.clone(), remote_peer_id);
if let Ok(stream) = endpoint.conn_type_stream(&remote_peer_id) {
if let Ok(stream) = endpoint.conn_type_stream(remote_peer_id) {
log_connection_changes(gui.mp.clone(), remote_peer_id, stream);
}
let res = active_side(connection, &config, Some(&gui)).await;
Expand Down
4 changes: 2 additions & 2 deletions iroh-gossip/examples/chat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,13 +108,13 @@ async fn main() -> anyhow::Result<()> {
.await?;
println!("> our node id: {}", endpoint.node_id());

let my_addr = endpoint.my_addr().await?;
let my_addr = endpoint.node_addr().await?;
// create the gossip protocol
let gossip = Gossip::from_endpoint(endpoint.clone(), Default::default(), &my_addr.info);

// print a ticket that includes our own node id and endpoint addresses
let ticket = {
let me = endpoint.my_addr().await?;
let me = endpoint.node_addr().await?;
let peers = peers.iter().cloned().chain([me]).collect();
Ticket { topic, peers }
};
Expand Down
6 changes: 5 additions & 1 deletion iroh-gossip/src/net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,11 @@ impl Actor {
new_endpoints = self.on_endpoints_rx.recv() => {
match new_endpoints {
Some(endpoints) => {
let addr = self.endpoint.my_addr_with_endpoints(endpoints)?;
let addr = NodeAddr::from_parts(
self.endpoint.node_id(),
self.endpoint.home_relay(),
endpoints.into_iter().map(|x| x.addr).collect(),
);
let peer_data = encode_peer_data(&addr.info)?;
self.handle_in_event(InEvent::UpdatePeerData(peer_data), Instant::now()).await?;
}
Expand Down
2 changes: 1 addition & 1 deletion iroh-net/bench/src/iroh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pub fn server_endpoint(rt: &tokio::runtime::Runtime, opt: &Opt) -> (NodeAddr, En
.bind(0)
.await
.unwrap();
let addr = ep.local_addr();
let addr = ep.bound_sockets();
let addr = SocketAddr::new("127.0.0.1".parse().unwrap(), addr.0.port());
let addr = NodeAddr::new(ep.node_id()).with_direct_addresses([addr]);
(addr, ep)
Expand Down
2 changes: 1 addition & 1 deletion iroh-net/examples/connect-unreliable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ async fn main() -> anyhow::Result<()> {
}

let relay_url = endpoint
.my_relay()
.home_relay()
.expect("should be connected to a relay server, try calling `endpoint.local_endpoints()` or `endpoint.connect()` first, to ensure the endpoint has actually attempted a connection before checking for the connected relay server");
println!("node relay server url: {relay_url}\n");
// Build a `NodeAddr` from the node_id, relay url, and UDP addresses.
Expand Down
2 changes: 1 addition & 1 deletion iroh-net/examples/connect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ async fn main() -> anyhow::Result<()> {
}

let relay_url = endpoint
.my_relay()
.home_relay()
.expect("should be connected to a relay server, try calling `endpoint.local_endpoints()` or `endpoint.connect()` first, to ensure the endpoint has actually attempted a connection before checking for the connected relay server");
println!("node relay server url: {relay_url}\n");
// Build a `NodeAddr` from the node_id, relay url, and UDP addresses.
Expand Down
2 changes: 1 addition & 1 deletion iroh-net/examples/listen-unreliable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ async fn main() -> anyhow::Result<()> {
.join(" ");

let relay_url = endpoint
.my_relay()
.home_relay()
.expect("should be connected to a relay server, try calling `endpoint.local_endpoints()` or `endpoint.connect()` first, to ensure the endpoint has actually attempted a connection before checking for the connected relay server");
println!("node relay server url: {relay_url}");
println!("\nin a separate terminal run:");
Expand Down
2 changes: 1 addition & 1 deletion iroh-net/examples/listen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ async fn main() -> anyhow::Result<()> {
.join(" ");

let relay_url = endpoint
.my_relay()
.home_relay()
.expect("should be connected to a relay server, try calling `endpoint.local_endpoints()` or `endpoint.connect()` first, to ensure the endpoint has actually attempted a connection before checking for the connected relay server");
println!("node relay server url: {relay_url}");
println!("\nin a separate terminal run:");
Expand Down
10 changes: 5 additions & 5 deletions iroh-net/src/discovery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ mod tests {
};
let ep1_addr = NodeAddr::new(ep1.node_id());
// wait for out address to be updated and thus published at least once
ep1.my_addr().await?;
ep1.node_addr().await?;
let _conn = ep2.connect(ep1_addr, TEST_ALPN).await?;
Ok(())
}
Expand All @@ -445,7 +445,7 @@ mod tests {
};
let ep1_addr = NodeAddr::new(ep1.node_id());
// wait for out address to be updated and thus published at least once
ep1.my_addr().await?;
ep1.node_addr().await?;
let _conn = ep2.connect(ep1_addr, TEST_ALPN).await?;
Ok(())
}
Expand Down Expand Up @@ -475,7 +475,7 @@ mod tests {
};
let ep1_addr = NodeAddr::new(ep1.node_id());
// wait for out address to be updated and thus published at least once
ep1.my_addr().await?;
ep1.node_addr().await?;
let _conn = ep2.connect(ep1_addr, TEST_ALPN).await?;
Ok(())
}
Expand All @@ -498,7 +498,7 @@ mod tests {
};
let ep1_addr = NodeAddr::new(ep1.node_id());
// wait for out address to be updated and thus published at least once
ep1.my_addr().await?;
ep1.node_addr().await?;
let res = ep2.connect(ep1_addr, TEST_ALPN).await;
assert!(res.is_err());
Ok(())
Expand All @@ -521,7 +521,7 @@ mod tests {
new_endpoint(secret, disco).await
};
// wait for out address to be updated and thus published at least once
ep1.my_addr().await?;
ep1.node_addr().await?;
let ep1_wrong_addr = NodeAddr {
node_id: ep1.node_id(),
info: AddrInfo {
Expand Down
Loading

0 comments on commit acf09c3

Please sign in to comment.