From 6ee2fc4353e5d7747068ebd29cbe141e3de93f18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Kr=C3=BCger?= Date: Wed, 27 Nov 2024 15:37:23 +0100 Subject: [PATCH 1/3] refactor: Move `iroh-router` & examples into `iroh-net`, remove `iroh` --- Cargo.lock | 36 +----------- Cargo.toml | 3 - iroh-net/Cargo.toml | 30 ++++++++-- {iroh-router => iroh-net}/examples/echo.rs | 5 +- {iroh-router => iroh-net}/examples/search.rs | 3 +- {iroh => iroh-net}/examples/transfer.rs | 1 - iroh-net/src/lib.rs | 2 + {iroh-router => iroh-net}/src/protocol.rs | 5 +- {iroh-router => iroh-net}/src/router.rs | 17 +++++- iroh-router/Cargo.toml | 41 -------------- iroh-router/README.md | 20 ------- iroh-router/src/lib.rs | 5 -- iroh/Cargo.toml | 59 -------------------- iroh/README.md | 39 ------------- iroh/release.toml | 1 - iroh/src/lib.rs | 19 ------- 16 files changed, 53 insertions(+), 233 deletions(-) rename {iroh-router => iroh-net}/examples/echo.rs (96%) rename {iroh-router => iroh-net}/examples/search.rs (99%) rename {iroh => iroh-net}/examples/transfer.rs (99%) rename {iroh-router => iroh-net}/src/protocol.rs (96%) rename {iroh-router => iroh-net}/src/router.rs (94%) delete mode 100644 iroh-router/Cargo.toml delete mode 100644 iroh-router/README.md delete mode 100644 iroh-router/src/lib.rs delete mode 100644 iroh/Cargo.toml delete mode 100644 iroh/README.md delete mode 100644 iroh/release.toml delete mode 100644 iroh/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 95227a4017..5a208cc887 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2399,24 +2399,6 @@ dependencies = [ "serde", ] -[[package]] -name = "iroh" -version = "0.28.1" -dependencies = [ - "anyhow", - "bytes", - "clap", - "futures-lite 2.5.0", - "indicatif", - "iroh-base", - "iroh-net", - "iroh-router", - "parse-size", - "tokio", - "tracing", - "tracing-subscriber", -] - [[package]] name = "iroh-base" version = "0.28.0" @@ -2557,6 +2539,7 @@ dependencies = [ "hyper", "hyper-util", "igd-next", + "indicatif", "iroh-base", "iroh-metrics", "iroh-net", @@ -2576,6 +2559,7 @@ dependencies = [ "num_enum", "once_cell", "parking_lot", + "parse-size", "pin-project", "pkarr", "portmapper", @@ -2811,22 +2795,6 @@ dependencies = [ "webpki-roots", ] -[[package]] -name = "iroh-router" -version = "0.28.0" -dependencies = [ - "anyhow", - "clap", - "futures-buffered", - "futures-lite 2.5.0", - "futures-util", - "iroh-net", - "tokio", - "tokio-util", - "tracing", - "tracing-subscriber", -] - [[package]] name = "iroh-test" version = "0.28.0" diff --git a/Cargo.toml b/Cargo.toml index 2574ed852a..5f99bf11d8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,5 @@ [workspace] members = [ - "iroh", "iroh-base", "iroh-dns-server", "iroh-metrics", @@ -8,7 +7,6 @@ members = [ "iroh-test", "iroh-net/bench", "iroh-relay", - "iroh-router", "net-tools/netwatch", "net-tools/portmapper", "iroh-net-report", @@ -54,4 +52,3 @@ iroh-base = { path = "./iroh-base" } iroh-net = { path = "./iroh-net" } iroh-metrics = { path = "./iroh-metrics" } iroh-test = { path = "./iroh-test" } -iroh-router = { path = "./iroh-router" } diff --git a/iroh-net/Cargo.toml b/iroh-net/Cargo.toml index 7e4ed8836c..f7c7fdd855 100644 --- a/iroh-net/Cargo.toml +++ b/iroh-net/Cargo.toml @@ -21,7 +21,6 @@ axum = { version = "0.7", optional = true } backoff = "0.4.0" base64 = "0.22.1" bytes = "1.7" -clap = { version = "4", features = ["derive"], optional = true } der = { version = "0.7", features = ["alloc", "derive"] } derive_more = { version = "1.0.0", features = [ "debug", @@ -102,9 +101,6 @@ tokio-tungstenite = "0.24" tokio-tungstenite-wasm = "0.3" tokio-util = { version = "0.7", features = ["io-util", "io", "codec", "rt"] } tracing = "0.1" -tracing-subscriber = { version = "0.3", features = [ - "env-filter", -], optional = true } url = { version = "2.5", features = ["serde"] } watchable = "1.1.2" webpki = { package = "rustls-webpki", version = "0.102" } @@ -123,6 +119,14 @@ swarm-discovery = { version = "0.2.1", optional = true } # dht_discovery genawaiter = { version = "0.99", features = ["futures03"], optional = true } +# Examples +clap = { version = "4", features = ["derive"], optional = true } +tracing-subscriber = { version = "0.3", features = [ + "env-filter", +], optional = true } +indicatif = { version = "0.17", features = ["tokio"], optional = true } +parse-size = { version = "=1.0.0", optional = true } # pinned version to avoid bumping msrv to 1.81 + [target.'cfg(all(target_os = "linux", not(target_os = "android")))'.dependencies] netlink-packet-core = "0.7.0" netlink-packet-route = "0.21" @@ -178,6 +182,12 @@ metrics = ["iroh-metrics/metrics"] test-utils = ["iroh-relay/test-utils", "iroh-relay/server", "dep:axum"] discovery-local-network = ["dep:swarm-discovery"] discovery-pkarr-dht = ["pkarr/dht", "dep:genawaiter"] +examples = [ + "dep:clap", + "dep:tracing-subscriber", + "dep:indicatif", + "dep:parse-size", +] [package.metadata.docs.rs] all-features = true @@ -202,3 +212,15 @@ required-features = ["discovery-pkarr-dht"] [[example]] name = "locally-discovered-nodes" required-features = ["discovery-local-network"] + +[[example]] +name = "search" +required-features = ["examples"] + +[[example]] +name = "echo" +required-features = ["examples"] + +[[example]] +name = "transfer" +required-features = ["examples"] diff --git a/iroh-router/examples/echo.rs b/iroh-net/examples/echo.rs similarity index 96% rename from iroh-router/examples/echo.rs rename to iroh-net/examples/echo.rs index 1ace2cc628..71fb6c6f28 100644 --- a/iroh-router/examples/echo.rs +++ b/iroh-net/examples/echo.rs @@ -10,8 +10,9 @@ use std::sync::Arc; use anyhow::Result; use futures_lite::future::Boxed as BoxedFuture; -use iroh_net::{endpoint::Connecting, Endpoint, NodeAddr}; -use iroh_router::{ProtocolHandler, Router}; +use iroh_net::{ + endpoint::Connecting, protocol::ProtocolHandler, router::Router, Endpoint, NodeAddr, +}; /// Each protocol is identified by its ALPN string. /// diff --git a/iroh-router/examples/search.rs b/iroh-net/examples/search.rs similarity index 99% rename from iroh-router/examples/search.rs rename to iroh-net/examples/search.rs index 9d281ff16e..9ff5fdf0cb 100644 --- a/iroh-router/examples/search.rs +++ b/iroh-net/examples/search.rs @@ -36,9 +36,10 @@ use clap::Parser; use futures_lite::future::Boxed as BoxedFuture; use iroh_net::{ endpoint::{get_remote_node_id, Connecting}, + protocol::ProtocolHandler, + router::Router, Endpoint, NodeId, }; -use iroh_router::{ProtocolHandler, Router}; use tokio::sync::Mutex; use tracing_subscriber::{prelude::*, EnvFilter}; diff --git a/iroh/examples/transfer.rs b/iroh-net/examples/transfer.rs similarity index 99% rename from iroh/examples/transfer.rs rename to iroh-net/examples/transfer.rs index c1ca5c90e2..c4ed19d9c8 100644 --- a/iroh/examples/transfer.rs +++ b/iroh-net/examples/transfer.rs @@ -13,7 +13,6 @@ use iroh_net::{ RelayMode, RelayUrl, }; use tracing::info; - // Transfer ALPN that we are using to communicate over the `Endpoint` const TRANSFER_ALPN: &[u8] = b"n0/iroh/transfer/example/0"; diff --git a/iroh-net/src/lib.rs b/iroh-net/src/lib.rs index 478fb69e53..61c1fcb274 100644 --- a/iroh-net/src/lib.rs +++ b/iroh-net/src/lib.rs @@ -241,6 +241,8 @@ pub mod dns; pub mod endpoint; mod magicsock; pub mod metrics; +pub mod protocol; +pub mod router; pub mod ticket; pub mod tls; diff --git a/iroh-router/src/protocol.rs b/iroh-net/src/protocol.rs similarity index 96% rename from iroh-router/src/protocol.rs rename to iroh-net/src/protocol.rs index 6ced048992..6b3c7f90d4 100644 --- a/iroh-router/src/protocol.rs +++ b/iroh-net/src/protocol.rs @@ -1,9 +1,11 @@ +//! TODO(matheus23) docs use std::{any::Any, collections::BTreeMap, sync::Arc}; use anyhow::Result; use futures_buffered::join_all; use futures_lite::future::Boxed as BoxedFuture; -use iroh_net::endpoint::Connecting; + +use crate::endpoint::Connecting; /// Handler for incoming connections. /// @@ -30,6 +32,7 @@ pub trait ProtocolHandler: Send + Sync + IntoArcAny + std::fmt::Debug + 'static /// /// This trait has a blanket implementation so there is no need to implement this yourself. pub trait IntoArcAny { + /// TODO(matheus23): docs fn into_arc_any(self: Arc) -> Arc; } diff --git a/iroh-router/src/router.rs b/iroh-net/src/router.rs similarity index 94% rename from iroh-router/src/router.rs rename to iroh-net/src/router.rs index bd39e9b5b0..8094cbee3f 100644 --- a/iroh-router/src/router.rs +++ b/iroh-net/src/router.rs @@ -1,3 +1,4 @@ +//! TODO(matheus23) docs use std::sync::Arc; use anyhow::{anyhow, Result}; @@ -5,13 +6,16 @@ use futures_util::{ future::{MapErr, Shared}, FutureExt, TryFutureExt, }; -use iroh_net::Endpoint; use tokio::task::{JoinError, JoinSet}; use tokio_util::{sync::CancellationToken, task::AbortOnDropHandle}; use tracing::{debug, error, warn}; -use crate::{ProtocolHandler, ProtocolMap}; +use crate::{ + protocol::{ProtocolHandler, ProtocolMap}, + Endpoint, +}; +/// TODO(matheus23): docs #[derive(Clone, Debug)] pub struct Router { endpoint: Endpoint, @@ -29,6 +33,7 @@ pub struct Router { type JoinErrToStr = Box String + Send + Sync + 'static>; impl Router { + /// TODO(matheus23): docs pub fn builder(endpoint: Endpoint) -> RouterBuilder { RouterBuilder::new(endpoint) } @@ -41,10 +46,12 @@ impl Router { self.protocols.get_typed(alpn) } + /// TODO(matheus23): docs pub fn endpoint(&self) -> &Endpoint { &self.endpoint } + /// TODO(matheus23): docs pub async fn shutdown(self) -> Result<()> { // Trigger shutdown of the main run task by activating the cancel token. self.cancel_token.cancel(); @@ -56,6 +63,7 @@ impl Router { } } +/// TODO(matheus23): docs #[derive(Debug)] pub struct RouterBuilder { endpoint: Endpoint, @@ -63,6 +71,7 @@ pub struct RouterBuilder { } impl RouterBuilder { + /// TODO(matheus23): docs pub fn new(endpoint: Endpoint) -> Self { Self { endpoint, @@ -70,6 +79,7 @@ impl RouterBuilder { } } + /// TODO(matheus23): docs pub fn accept(mut self, alpn: impl AsRef<[u8]>, handler: Arc) -> Self { self.protocols.insert(alpn.as_ref().to_vec(), handler); self @@ -88,6 +98,7 @@ impl RouterBuilder { self.protocols.get_typed(alpn) } + /// TODO(matheus23): docs pub async fn spawn(self) -> Result { // Update the endpoint with our alpns. let alpns = self @@ -187,7 +198,7 @@ async fn shutdown(endpoint: &Endpoint, protocols: Arc) { ); } -async fn handle_connection(incoming: iroh_net::endpoint::Incoming, protocols: Arc) { +async fn handle_connection(incoming: crate::endpoint::Incoming, protocols: Arc) { let mut connecting = match incoming.accept() { Ok(conn) => conn, Err(err) => { diff --git a/iroh-router/Cargo.toml b/iroh-router/Cargo.toml deleted file mode 100644 index a0b2a39b92..0000000000 --- a/iroh-router/Cargo.toml +++ /dev/null @@ -1,41 +0,0 @@ -[package] -name = "iroh-router" -version = "0.28.0" -edition = "2021" -readme = "README.md" -description = "protocol router support for iroh" -license = "MIT OR Apache-2.0" -authors = ["dignifiedquire ", "n0 team"] -repository = "https://github.com/n0-computer/iroh" -keywords = ["quic", "networking", "holepunching", "p2p"] - - -[dependencies] -anyhow = "1.0.91" -futures-buffered = "0.2.9" -futures-lite = "2.5" -futures-util = "0.3.31" -iroh-net = { version = "0.28.1", path = "../iroh-net" } -tokio = "1" -tokio-util = "0.7" -tracing = "0.1" - -# Examples -clap = { version = "4", features = ["derive"], optional = true } -tracing-subscriber = { version = "0.3", features = ["env-filter"], optional = true } - -[lints] -workspace = true - - -[features] -default = [] -examples = ["dep:clap", "dep:tracing-subscriber"] - -[[example]] -name = "search" -required-features = ["examples"] - -[[example]] -name = "echo" -required-features = ["examples"] diff --git a/iroh-router/README.md b/iroh-router/README.md deleted file mode 100644 index 54639b5f9f..0000000000 --- a/iroh-router/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# iroh-router - -This crate contains the definitions for custom protocols for `iroh`. - -# License - -This project is licensed under either of - - * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or - http://www.apache.org/licenses/LICENSE-2.0) - * MIT license ([LICENSE-MIT](LICENSE-MIT) or - http://opensource.org/licenses/MIT) - -at your option. - -### Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted -for inclusion in this project by you, as defined in the Apache-2.0 license, -shall be dual licensed as above, without any additional terms or conditions. diff --git a/iroh-router/src/lib.rs b/iroh-router/src/lib.rs deleted file mode 100644 index 6bdd6cd565..0000000000 --- a/iroh-router/src/lib.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod protocol; -mod router; - -pub use protocol::{ProtocolHandler, ProtocolMap}; -pub use router::{Router, RouterBuilder}; diff --git a/iroh/Cargo.toml b/iroh/Cargo.toml deleted file mode 100644 index 33c797151c..0000000000 --- a/iroh/Cargo.toml +++ /dev/null @@ -1,59 +0,0 @@ -[package] -name = "iroh" -version = "0.28.1" -edition = "2021" -readme = "README.md" -description = "A toolkit for building distributed applications" -license = "MIT OR Apache-2.0" -authors = ["dignifiedquire ", "n0 team"] -repository = "https://github.com/n0-computer/iroh" -keywords = ["networking", "p2p", "holepunching", "ipfs"] - -# Sadly this also needs to be updated in .github/workflows/ci.yml -rust-version = "1.76" - -[lints] -workspace = true - -[dependencies] -iroh-base = { version = "0.28.0", features = ["key"] } -iroh-net = { version = "0.28.1", default-features = false } -iroh-router = { version = "0.28.0" } - -# Examples -anyhow = { version = "1", optional = true } -clap = { version = "4", features = ["derive"], optional = true } -indicatif = { version = "0.17", features = ["tokio"], optional = true } -parse-size = { version = "=1.0.0", optional = true } # pinned version to avoid bumping msrv to 1.81 -tokio = { version = "1", features = ["full"], optional = true } -tracing-subscriber = { version = "0.3", features = ["env-filter"], optional = true } -futures-lite = { version = "2.5", optional = true } -tracing = { version = "0.1", optional = true } -bytes = { version = "1.8", optional = true } - - -[features] -default = ["metrics", "discovery-pkarr-dht"] -metrics = ["iroh-net/metrics"] -discovery-local-network = ["iroh-net/discovery-local-network"] -discovery-pkarr-dht = ["iroh-net/discovery-pkarr-dht"] - -examples = [ - "dep:anyhow", - "dep:clap", - "dep:indicatif", - "dep:parse-size", - "dep:tokio", - "dep:tracing-subscriber", - "dep:futures-lite", - "dep:tracing", - "dep:bytes", -] - -[package.metadata.docs.rs] -all-features = true -rustdoc-args = ["--cfg", "iroh_docsrs"] - -[[example]] -name = "transfer" -required-features = ["examples"] diff --git a/iroh/README.md b/iroh/README.md deleted file mode 100644 index c725f3c4de..0000000000 --- a/iroh/README.md +++ /dev/null @@ -1,39 +0,0 @@ -# iroh - -The iroh crate defines both the `iroh` library and `iroh` command-line interface (CLI). - -For more details on Iroh, see https://iroh.computer. - -## Building the CLI - -Simply run `cargo build` from the project root, it produces the `iroh` CLI by default. - -## Using as a rust crate - -Because iroh builds the CLI by default, you should disable `default-features` when importing the `iroh` crate via cargo: - -```toml -[dependencies] -iroh = { version = "...", default-features = false } -``` - -## Running Examples - -Examples are located in `iroh/examples`. Run them with `cargo run --features=examples --example`. eg: `cargo run --features=examples --example hello-world`. At the top of each example file is a comment describing how to run the example. - -# License - -This project is licensed under either of - - * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or - http://www.apache.org/licenses/LICENSE-2.0) - * MIT license ([LICENSE-MIT](LICENSE-MIT) or - http://opensource.org/licenses/MIT) - -at your option. - -### Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted -for inclusion in this project by you, as defined in the Apache-2.0 license, -shall be dual licensed as above, without any additional terms or conditions. diff --git a/iroh/release.toml b/iroh/release.toml deleted file mode 100644 index bbd33641dd..0000000000 --- a/iroh/release.toml +++ /dev/null @@ -1 +0,0 @@ -pre-release-hook = ["git", "cliff", "--workdir", "../", "-o", "../CHANGELOG.md", "--tag", "{{version}}" ] \ No newline at end of file diff --git a/iroh/src/lib.rs b/iroh/src/lib.rs deleted file mode 100644 index c1fae16f90..0000000000 --- a/iroh/src/lib.rs +++ /dev/null @@ -1,19 +0,0 @@ -//! Send data over the internet. -//! -//! -//! ## Reexports -//! -//! The iroh crate re-exports the following crates: -//! - [iroh_base] as [`base`] -//! - [iroh_net] as [`net`] -//! - [iroh_router] as [`router`] -#![cfg_attr(iroh_docsrs, feature(doc_cfg))] -#![deny(missing_docs, rustdoc::broken_intra_doc_links)] - -// re-export the iroh crates -#[doc(inline)] -pub use iroh_base as base; -#[doc(inline)] -pub use iroh_net as net; -#[doc(inline)] -pub use iroh_router as router; From fdcb28cb1c1c444877d3d913606e803f369b2bd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Kr=C3=BCger?= Date: Thu, 28 Nov 2024 10:47:43 +0100 Subject: [PATCH 2/3] refactor: Rename `iroh-net` to `iroh` --- .github/workflows/ci.yml | 2 +- .github/workflows/tests.yaml | 2 +- Cargo.lock | 288 +++++++++++++++--- Cargo.toml | 6 +- iroh-base/src/node_addr.rs | 12 +- iroh-net-report/src/reportgen.rs | 6 +- iroh-node-util/Cargo.toml | 4 +- iroh-node-util/src/cli/net.rs | 2 +- iroh-node-util/src/fs.rs | 2 +- iroh-node-util/src/lib.rs | 2 +- iroh-node-util/src/rpc/client/net.rs | 14 +- iroh-node-util/src/rpc/proto/net.rs | 2 +- iroh-node-util/src/rpc/server.rs | 2 +- iroh-relay/src/main.rs | 2 +- {iroh-net => iroh}/Cargo.toml | 4 +- {iroh-net => iroh}/LICENSE-BSD3 | 0 {iroh-net => iroh}/README.md | 0 {iroh-net => iroh}/bench/Cargo.toml | 4 +- {iroh-net => iroh}/bench/src/bin/bulk.rs | 18 +- {iroh-net => iroh}/bench/src/iroh.rs | 2 +- {iroh-net => iroh}/bench/src/lib.rs | 4 +- {iroh-net => iroh}/bench/src/quinn.rs | 9 +- {iroh-net => iroh}/bench/src/s2n.rs | 0 {iroh-net => iroh}/bench/src/stats.rs | 0 {iroh-net => iroh}/benches/key.rs | 2 +- {iroh-net => iroh}/docs/local_relay_node.md | 0 {iroh-net => iroh}/docs/relay_nodes.md | 0 .../examples/connect-unreliable.rs | 6 +- {iroh-net => iroh}/examples/connect.rs | 6 +- {iroh-net => iroh}/examples/dht_discovery.rs | 10 +- {iroh-net => iroh}/examples/echo.rs | 6 +- .../examples/listen-unreliable.rs | 6 +- {iroh-net => iroh}/examples/listen.rs | 6 +- .../examples/locally-discovered-nodes.rs | 10 +- {iroh-net => iroh}/examples/search.rs | 2 +- {iroh-net => iroh}/examples/transfer.rs | 8 +- {iroh-net => iroh}/src/defaults.rs | 0 {iroh-net => iroh}/src/dialer.rs | 0 {iroh-net => iroh}/src/disco.rs | 0 {iroh-net => iroh}/src/discovery.rs | 12 +- {iroh-net => iroh}/src/discovery/dns.rs | 0 .../src/discovery/local_swarm_discovery.rs | 4 +- {iroh-net => iroh}/src/discovery/pkarr.rs | 0 {iroh-net => iroh}/src/discovery/pkarr/dht.rs | 0 .../src/discovery/static_provider.rs | 2 +- {iroh-net => iroh}/src/dns.rs | 0 {iroh-net => iroh}/src/dns/node_info.rs | 0 {iroh-net => iroh}/src/endpoint.rs | 2 +- {iroh-net => iroh}/src/endpoint/rtt_actor.rs | 0 {iroh-net => iroh}/src/lib.rs | 8 +- {iroh-net => iroh}/src/magicsock.rs | 0 {iroh-net => iroh}/src/magicsock/metrics.rs | 0 {iroh-net => iroh}/src/magicsock/node_map.rs | 0 .../src/magicsock/node_map/best_addr.rs | 0 .../src/magicsock/node_map/node_state.rs | 0 .../src/magicsock/node_map/path_state.rs | 0 .../src/magicsock/node_map/udp_paths.rs | 0 .../src/magicsock/relay_actor.rs | 0 {iroh-net => iroh}/src/magicsock/timer.rs | 0 {iroh-net => iroh}/src/magicsock/udp_conn.rs | 0 {iroh-net => iroh}/src/metrics.rs | 0 {iroh-net => iroh}/src/protocol.rs | 2 +- {iroh-net => iroh}/src/router.rs | 0 {iroh-net => iroh}/src/test_utils.rs | 0 {iroh-net => iroh}/src/ticket.rs | 0 {iroh-net => iroh}/src/tls.rs | 0 {iroh-net => iroh}/src/tls/certificate.rs | 0 {iroh-net => iroh}/src/tls/verifier.rs | 0 {iroh-net => iroh}/src/util.rs | 0 69 files changed, 341 insertions(+), 138 deletions(-) rename {iroh-net => iroh}/Cargo.toml (99%) rename {iroh-net => iroh}/LICENSE-BSD3 (100%) rename {iroh-net => iroh}/README.md (100%) rename {iroh-net => iroh}/bench/Cargo.toml (92%) rename {iroh-net => iroh}/bench/src/bin/bulk.rs (89%) rename {iroh-net => iroh}/bench/src/iroh.rs (99%) rename {iroh-net => iroh}/bench/src/lib.rs (99%) rename {iroh-net => iroh}/bench/src/quinn.rs (96%) rename {iroh-net => iroh}/bench/src/s2n.rs (100%) rename {iroh-net => iroh}/bench/src/stats.rs (100%) rename {iroh-net => iroh}/benches/key.rs (99%) rename {iroh-net => iroh}/docs/local_relay_node.md (100%) rename {iroh-net => iroh}/docs/relay_nodes.md (100%) rename {iroh-net => iroh}/examples/connect-unreliable.rs (94%) rename {iroh-net => iroh}/examples/connect.rs (95%) rename {iroh-net => iroh}/examples/dht_discovery.rs (93%) rename {iroh-net => iroh}/examples/echo.rs (94%) rename {iroh-net => iroh}/examples/listen-unreliable.rs (94%) rename {iroh-net => iroh}/examples/listen.rs (95%) rename {iroh-net => iroh}/examples/locally-discovered-nodes.rs (84%) rename {iroh-net => iroh}/examples/search.rs (99%) rename {iroh-net => iroh}/examples/transfer.rs (98%) rename {iroh-net => iroh}/src/defaults.rs (100%) rename {iroh-net => iroh}/src/dialer.rs (100%) rename {iroh-net => iroh}/src/disco.rs (100%) rename {iroh-net => iroh}/src/discovery.rs (99%) rename {iroh-net => iroh}/src/discovery/dns.rs (100%) rename {iroh-net => iroh}/src/discovery/local_swarm_discovery.rs (99%) rename {iroh-net => iroh}/src/discovery/pkarr.rs (100%) rename {iroh-net => iroh}/src/discovery/pkarr/dht.rs (100%) rename {iroh-net => iroh}/src/discovery/static_provider.rs (98%) rename {iroh-net => iroh}/src/dns.rs (100%) rename {iroh-net => iroh}/src/dns/node_info.rs (100%) rename {iroh-net => iroh}/src/endpoint.rs (99%) rename {iroh-net => iroh}/src/endpoint/rtt_actor.rs (100%) rename {iroh-net => iroh}/src/lib.rs (98%) rename {iroh-net => iroh}/src/magicsock.rs (100%) rename {iroh-net => iroh}/src/magicsock/metrics.rs (100%) rename {iroh-net => iroh}/src/magicsock/node_map.rs (100%) rename {iroh-net => iroh}/src/magicsock/node_map/best_addr.rs (100%) rename {iroh-net => iroh}/src/magicsock/node_map/node_state.rs (100%) rename {iroh-net => iroh}/src/magicsock/node_map/path_state.rs (100%) rename {iroh-net => iroh}/src/magicsock/node_map/udp_paths.rs (100%) rename {iroh-net => iroh}/src/magicsock/relay_actor.rs (100%) rename {iroh-net => iroh}/src/magicsock/timer.rs (100%) rename {iroh-net => iroh}/src/magicsock/udp_conn.rs (100%) rename {iroh-net => iroh}/src/metrics.rs (100%) rename {iroh-net => iroh}/src/protocol.rs (98%) rename {iroh-net => iroh}/src/router.rs (100%) rename {iroh-net => iroh}/src/test_utils.rs (100%) rename {iroh-net => iroh}/src/ticket.rs (100%) rename {iroh-net => iroh}/src/tls.rs (100%) rename {iroh-net => iroh}/src/tls/certificate.rs (100%) rename {iroh-net => iroh}/src/tls/verifier.rs (100%) rename {iroh-net => iroh}/src/util.rs (100%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7235d7b95d..42bbece15f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -189,7 +189,7 @@ jobs: # uses: obi1kenobi/cargo-semver-checks-action@v2 uses: n0-computer/cargo-semver-checks-action@feat-baseline with: - package: iroh, iroh-base, iroh-dns-server, iroh-metrics, iroh-net, iroh-net-bench, iroh-node-util, iroh-router, netwatch, portmapper, iroh-relay, iroh-net-report + package: iroh, iroh-base, iroh-dns-server, iroh-metrics, iroh-net-bench, iroh-node-util, netwatch, portmapper, iroh-relay, iroh-net-report baseline-rev: ${{ env.HEAD_COMMIT_SHA }} use-cache: false diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 98efa3dba1..aba094418f 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -23,7 +23,7 @@ env: RUSTFLAGS: -Dwarnings RUSTDOCFLAGS: -Dwarnings SCCACHE_CACHE_SIZE: "50G" - CRATES_LIST: "iroh,iroh-node-util,iroh-metrics,iroh-net,iroh-net-bench,iroh-test,iroh-dns-server,iroh-router,netwatch,portmapper,iroh-relay,iroh-net-report" + CRATES_LIST: "iroh,iroh-node-util,iroh-metrics,,iroh-net-bench,iroh-test,iroh-dns-server,netwatch,portmapper,iroh-relay,iroh-net-report" IROH_FORCE_STAGING_RELAYS: "1" jobs: diff --git a/Cargo.lock b/Cargo.lock index 5a208cc887..72c43c7627 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2399,6 +2399,100 @@ dependencies = [ "serde", ] +[[package]] +name = "iroh" +version = "0.28.1" +dependencies = [ + "anyhow", + "axum", + "backoff", + "base64", + "bytes", + "clap", + "criterion", + "crypto_box", + "der", + "derive_more", + "futures-buffered", + "futures-concurrency", + "futures-lite 2.5.0", + "futures-sink", + "futures-util", + "genawaiter", + "governor 0.7.0", + "hex", + "hickory-proto 0.25.0-alpha.2", + "hickory-resolver", + "hostname 0.4.0", + "http 1.1.0", + "http-body-util", + "hyper", + "hyper-util", + "igd-next", + "indicatif", + "iroh", + "iroh-base", + "iroh-metrics", + "iroh-net-report", + "iroh-quinn", + "iroh-quinn-proto", + "iroh-quinn-udp", + "iroh-relay", + "iroh-test", + "libc", + "netdev 0.31.0", + "netlink-packet-core", + "netlink-packet-route 0.19.0", + "netlink-packet-route 0.21.0", + "netlink-sys", + "netwatch 0.1.0", + "num_enum", + "once_cell", + "parking_lot", + "parse-size", + "pin-project", + "pkarr", + "portmapper 0.1.0", + "postcard", + "pretty_assertions", + "rand", + "rand_chacha", + "rcgen 0.13.1", + "regex", + "reqwest", + "ring", + "rtnetlink 0.13.1", + "rtnetlink 0.14.1", + "rustls", + "rustls-webpki", + "serde", + "serde_json", + "smallvec", + "socket2", + "strum", + "stun-rs", + "surge-ping", + "swarm-discovery", + "testresult", + "thiserror 2.0.3", + "time", + "tokio", + "tokio-rustls", + "tokio-stream", + "tokio-tungstenite 0.24.0", + "tokio-tungstenite-wasm", + "tokio-util", + "tracing", + "tracing-subscriber", + "url", + "watchable", + "webpki-roots", + "windows 0.58.0", + "wmi 0.14.1", + "x509-parser", + "z32", +] + [[package]] name = "iroh-base" version = "0.28.0" @@ -2467,7 +2561,7 @@ dependencies = [ "lru", "parking_lot", "pkarr", - "rcgen", + "rcgen 0.13.1", "redb", "regex", "rustls", @@ -2512,93 +2606,78 @@ dependencies = [ [[package]] name = "iroh-net" version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b40e1f1f9029e198c6d05bd232d3239814b0a66ac4668978729b709aeb6a44e2" dependencies = [ "anyhow", - "axum", "backoff", "base64", "bytes", - "clap", - "criterion", - "crypto_box", "der", "derive_more", + "duct", "futures-buffered", "futures-concurrency", "futures-lite 2.5.0", "futures-sink", "futures-util", "genawaiter", - "governor 0.7.0", + "governor 0.6.3", "hex", "hickory-proto 0.25.0-alpha.2", "hickory-resolver", - "hostname 0.4.0", + "hostname 0.3.1", "http 1.1.0", "http-body-util", "hyper", "hyper-util", "igd-next", - "indicatif", "iroh-base", "iroh-metrics", - "iroh-net", - "iroh-net-report", "iroh-quinn", "iroh-quinn-proto", "iroh-quinn-udp", - "iroh-relay", - "iroh-test", "libc", - "netdev", + "netdev 0.30.0", "netlink-packet-core", - "netlink-packet-route 0.19.0", - "netlink-packet-route 0.21.0", + "netlink-packet-route 0.17.1", "netlink-sys", - "netwatch", + "netwatch 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "num_enum", "once_cell", "parking_lot", - "parse-size", "pin-project", "pkarr", - "portmapper", + "portmapper 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "postcard", - "pretty_assertions", "rand", - "rand_chacha", - "rcgen", - "regex", + "rcgen 0.12.1", "reqwest", "ring", "rtnetlink 0.13.1", - "rtnetlink 0.14.1", "rustls", "rustls-webpki", "serde", - "serde_json", "smallvec", "socket2", "strum", "stun-rs", "surge-ping", - "swarm-discovery", - "testresult", - "thiserror 2.0.3", + "thiserror 1.0.69", "time", "tokio", "tokio-rustls", "tokio-stream", - "tokio-tungstenite 0.24.0", + "tokio-tungstenite 0.21.0", "tokio-tungstenite-wasm", "tokio-util", "tracing", - "tracing-subscriber", + "tungstenite 0.21.0", "url", "watchable", "webpki-roots", - "windows 0.58.0", - "wmi", + "windows 0.51.1", + "wmi 0.13.4", "x509-parser", "z32", ] @@ -2612,10 +2691,10 @@ dependencies = [ "clap", "futures-lite 2.5.0", "hdrhistogram", + "iroh", "iroh-metrics", - "iroh-net", "iroh-quinn", - "rcgen", + "rcgen 0.13.1", "rustls", "socket2", "tokio", @@ -2637,9 +2716,9 @@ dependencies = [ "iroh-metrics", "iroh-relay", "iroh-test", - "netwatch", + "netwatch 0.1.0", "once_cell", - "portmapper", + "portmapper 0.1.0", "pretty_assertions", "rand", "reqwest", @@ -2665,7 +2744,7 @@ dependencies = [ "dirs-next", "futures-lite 2.5.0", "human-time", - "iroh-net", + "iroh", "nested_enum_utils", "quic-rpc", "quic-rpc-derive", @@ -2767,7 +2846,7 @@ dependencies = [ "proptest", "rand", "rand_chacha", - "rcgen", + "rcgen 0.13.1", "regex", "reqwest", "ring", @@ -3015,6 +3094,12 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" +[[package]] +name = "memalloc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df39d232f5c40b0891c10216992c2f250c054105cb1e56f0fc9032db6203ecc1" + [[package]] name = "memchr" version = "2.7.4" @@ -3075,6 +3160,23 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "netdev" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7516ad2c46cc25da098ed7d6b9a0cbe9e1fbffbd04b1596148b95f2841179c83" +dependencies = [ + "dlopen2", + "libc", + "memalloc", + "netlink-packet-core", + "netlink-packet-route 0.17.1", + "netlink-sys", + "once_cell", + "system-configuration", + "windows-sys 0.52.0", +] + [[package]] name = "netdev" version = "0.31.0" @@ -3199,7 +3301,7 @@ dependencies = [ "futures-util", "iroh-quinn-udp", "libc", - "netdev", + "netdev 0.31.0", "netlink-packet-core", "netlink-packet-route 0.19.0", "netlink-sys", @@ -3214,7 +3316,36 @@ dependencies = [ "tokio-util", "tracing", "windows 0.58.0", - "wmi", + "wmi 0.14.1", +] + +[[package]] +name = "netwatch" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a639d52c0996ac640e2a7052a5265c8f71efdbdadc83188435ffc358b7ca931" +dependencies = [ + "anyhow", + "bytes", + "derive_more", + "futures-lite 2.5.0", + "futures-sink", + "futures-util", + "libc", + "netdev 0.30.0", + "netlink-packet-core", + "netlink-packet-route 0.17.1", + "netlink-sys", + "once_cell", + "rtnetlink 0.13.1", + "serde", + "socket2", + "thiserror 1.0.69", + "time", + "tokio", + "tracing", + "windows 0.51.1", + "wmi 0.13.4", ] [[package]] @@ -3811,7 +3942,7 @@ dependencies = [ "igd-next", "iroh-metrics", "libc", - "netwatch", + "netwatch 0.1.0", "ntest", "num_enum", "rand", @@ -3827,6 +3958,35 @@ dependencies = [ "url", ] +[[package]] +name = "portmapper" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d60045fdcfe8ff6b781cf1027fdbb08ed319d93aff7da4bedc018e3bc92226" +dependencies = [ + "anyhow", + "base64", + "bytes", + "derive_more", + "futures-lite 2.5.0", + "futures-util", + "igd-next", + "iroh-metrics", + "libc", + "netwatch 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_enum", + "rand", + "serde", + "smallvec", + "socket2", + "thiserror 1.0.69", + "time", + "tokio", + "tokio-util", + "tracing", + "url", +] + [[package]] name = "postcard" version = "1.0.10" @@ -4226,6 +4386,18 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "rcgen" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48406db8ac1f3cbc7dcdb56ec355343817958a356ff430259bb07baf7607e1e1" +dependencies = [ + "pem", + "ring", + "time", + "yasna", +] + [[package]] name = "rcgen" version = "0.13.1" @@ -5439,7 +5611,7 @@ dependencies = [ "num-bigint", "pem", "proc-macro2", - "rcgen", + "rcgen 0.13.1", "reqwest", "ring", "rustls", @@ -6102,6 +6274,16 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "windows" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" +dependencies = [ + "windows-core 0.51.1", + "windows-targets 0.48.5", +] + [[package]] name = "windows" version = "0.52.0" @@ -6122,6 +6304,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-core" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-core" version = "0.52.0" @@ -6363,6 +6554,21 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "wmi" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff00ac1309d4c462be86f03a55e409509e8bf4323ec296aeb4b381dd9aabe6ec" +dependencies = [ + "chrono", + "futures", + "log", + "serde", + "thiserror 1.0.69", + "windows 0.58.0", + "windows-core 0.58.0", +] + [[package]] name = "wmi" version = "0.14.1" diff --git a/Cargo.toml b/Cargo.toml index 5f99bf11d8..fd102bb875 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,9 +3,9 @@ members = [ "iroh-base", "iroh-dns-server", "iroh-metrics", - "iroh-net", + "iroh", "iroh-test", - "iroh-net/bench", + "iroh/bench", "iroh-relay", "net-tools/netwatch", "net-tools/portmapper", @@ -48,7 +48,7 @@ unused-async = "warn" # Temporary fix for dependencies [patch.crates-io] +iroh = { path = "./iroh" } iroh-base = { path = "./iroh-base" } -iroh-net = { path = "./iroh-net" } iroh-metrics = { path = "./iroh-metrics" } iroh-test = { path = "./iroh-test" } diff --git a/iroh-base/src/node_addr.rs b/iroh-base/src/node_addr.rs index c084f15f55..6387fb9b59 100644 --- a/iroh-base/src/node_addr.rs +++ b/iroh-base/src/node_addr.rs @@ -34,9 +34,9 @@ pub use crate::relay_url::RelayUrl; /// 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 +/// [discovery]: https://docs.rs/iroh/*/iroh/index.html#node-discovery +/// [home relay]: https://docs.rs/iroh/*/iroh/relay/index.html +/// [Relay server]: https://docs.rs/iroh/*/iroh/index.html#relay-servers #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] pub struct NodeAddr { /// The node's identifier. @@ -90,7 +90,7 @@ impl 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 + /// [discovery]: https://docs.rs/iroh/*/iroh/index.html#node-discovery pub fn apply_options(&mut self, opts: AddrInfoOptions) { self.info.apply_options(opts); } @@ -131,7 +131,7 @@ impl From for NodeAddr { /// 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 +/// [discovery]: https://docs.rs/iroh/*/iroh/index.html#node-discovery #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default, PartialOrd, Ord)] pub struct AddrInfo { /// The node's home relay url. @@ -152,7 +152,7 @@ impl 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 + /// [discovery]: https://docs.rs/iroh/*/iroh/index.html#node-discovery pub fn apply_options(&mut self, opts: AddrInfoOptions) { match opts { AddrInfoOptions::Id => { diff --git a/iroh-net-report/src/reportgen.rs b/iroh-net-report/src/reportgen.rs index 307a806777..0ffcac7119 100644 --- a/iroh-net-report/src/reportgen.rs +++ b/iroh-net-report/src/reportgen.rs @@ -1358,7 +1358,7 @@ mod tests { // // Build the test binary: // - // cargo nextest run -p iroh_net net_report::reportgen::tests --no-run + // cargo nextest run -p iroh net_report::reportgen::tests --no-run // // Find out the test binary location: // @@ -1368,11 +1368,11 @@ mod tests { // Set the CAP_NET_RAW permission, note that nextest runs each test in a child process // so the capabilities need to be inherited: // - // sudo setcap CAP_NET_RAW=eip target/debug/deps/iroh_net-abc123 + // sudo setcap CAP_NET_RAW=eip target/debug/deps/iroh-abc123 // // Finally run the test: // - // cargo nextest run -p iroh_net net_report::reportgen::tests + // cargo nextest run -p iroh net_report::reportgen::tests // // This allows the pinger to create a SOCK_RAW socket for IPPROTO_ICMP. // diff --git a/iroh-node-util/Cargo.toml b/iroh-node-util/Cargo.toml index 7398b5d7d3..a3df0145cc 100644 --- a/iroh-node-util/Cargo.toml +++ b/iroh-node-util/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "iroh-node-util" -description = "Utilities to build binaries containing an iroh-net endpoint" +description = "Utilities to build binaries containing an iroh endpoint" readme = "README.md" license = "MIT OR Apache-2.0" version = "0.28.0" @@ -19,7 +19,7 @@ workspace = true anyhow = "1" clap = { version = "4", features = ["derive"], optional = true } tokio = "1" -iroh-net = { path = "../iroh-net" } +iroh = { path = "../iroh" } tempfile = "3" strum = "0.26" nested_enum_utils = "0.1.0" diff --git a/iroh-node-util/src/cli/net.rs b/iroh-node-util/src/cli/net.rs index 9e004f4208..deedbca1e7 100644 --- a/iroh-node-util/src/cli/net.rs +++ b/iroh-node-util/src/cli/net.rs @@ -7,7 +7,7 @@ use colored::Colorize; use comfy_table::{presets::NOTHING, Cell, Table}; use futures_lite::{Stream, StreamExt}; use human_time::ToHumanTimeString; -use iroh_net::{ +use iroh::{ endpoint::{DirectAddrInfo, RemoteInfo}, NodeAddr, NodeId, RelayUrl, }; diff --git a/iroh-node-util/src/fs.rs b/iroh-node-util/src/fs.rs index a773797085..575ddcead8 100644 --- a/iroh-node-util/src/fs.rs +++ b/iroh-node-util/src/fs.rs @@ -3,7 +3,7 @@ use std::path::PathBuf; use anyhow::Context; -use iroh_net::key::SecretKey; +use iroh::key::SecretKey; use tokio::io::AsyncWriteExt; /// Loads a [`SecretKey`] from the provided file, or stores a newly generated one diff --git a/iroh-node-util/src/lib.rs b/iroh-node-util/src/lib.rs index 709b430bad..f8c8853d68 100644 --- a/iroh-node-util/src/lib.rs +++ b/iroh-node-util/src/lib.rs @@ -17,7 +17,7 @@ pub mod fs; use std::path::PathBuf; use anyhow::Context; -use iroh_net::key::SecretKey; +use iroh::key::SecretKey; use tokio::io::AsyncWriteExt; /// Loads a [`SecretKey`] from the provided file, or stores a newly generated one diff --git a/iroh-node-util/src/rpc/client/net.rs b/iroh-node-util/src/rpc/client/net.rs index 19438f0d07..cf25c7642e 100644 --- a/iroh-node-util/src/rpc/client/net.rs +++ b/iroh-node-util/src/rpc/client/net.rs @@ -11,7 +11,7 @@ use std::net::SocketAddr; use anyhow::Result; use futures_lite::{Stream, StreamExt}; -use iroh_net::{endpoint::RemoteInfo, relay::RelayUrl, NodeAddr, NodeId}; +use iroh::{endpoint::RemoteInfo, relay::RelayUrl, NodeAddr, NodeId}; use quic_rpc::RpcClient; use serde::{Deserialize, Serialize}; @@ -49,7 +49,7 @@ impl Client { /// This streams a *current snapshot*. It does not keep the stream open after finishing /// transferring the snapshot. /// - /// See also [`Endpoint::remote_info_iter`](iroh_net::Endpoint::remote_info_iter). + /// See also [`Endpoint::remote_info_iter`](iroh::Endpoint::remote_info_iter). pub async fn remote_info_iter(&self) -> Result>> { let stream = self.rpc.server_streaming(RemoteInfosIterRequest {}).await?; Ok(flatten(stream).map(|res| res.map(|res| res.info))) @@ -57,7 +57,7 @@ impl Client { /// Fetches node information about a remote iroh node identified by its [`NodeId`]. /// - /// See also [`Endpoint::remote_info`](iroh_net::Endpoint::remote_info). + /// See also [`Endpoint::remote_info`](iroh::Endpoint::remote_info). pub async fn remote_info(&self, node_id: NodeId) -> Result> { let RemoteInfoResponse { info } = self.rpc.rpc(RemoteInfoRequest { node_id }).await??; Ok(info) @@ -65,7 +65,7 @@ impl Client { /// Fetches the node id of this node. /// - /// See also [`Endpoint::node_id`](iroh_net::Endpoint::node_id). + /// See also [`Endpoint::node_id`](iroh::Endpoint::node_id). pub async fn node_id(&self) -> Result { let id = self.rpc.rpc(IdRequest).await??; Ok(id) @@ -73,7 +73,7 @@ impl Client { /// Fetches the [`NodeAddr`] for this node. /// - /// See also [`Endpoint::node_addr`](iroh_net::Endpoint::node_addr). + /// See also [`Endpoint::node_addr`](iroh::Endpoint::node_addr). pub async fn node_addr(&self) -> Result { let addr = self.rpc.rpc(AddrRequest).await??; Ok(addr) @@ -81,7 +81,7 @@ impl Client { /// Adds a known node address to this node. /// - /// See also [`Endpoint::add_node_addr`](iroh_net::Endpoint::add_node_addr). + /// See also [`Endpoint::add_node_addr`](iroh::Endpoint::add_node_addr). pub async fn add_node_addr(&self, addr: NodeAddr) -> Result<()> { self.rpc.rpc(AddAddrRequest { addr }).await??; Ok(()) @@ -89,7 +89,7 @@ impl Client { /// Returns the relay server we are connected to. /// - /// See also [`Endpoint::home_relay`](iroh_net::Endpoint::home_relay). + /// See also [`Endpoint::home_relay`](iroh::Endpoint::home_relay). pub async fn home_relay(&self) -> Result> { let relay = self.rpc.rpc(RelayRequest).await??; Ok(relay) diff --git a/iroh-node-util/src/rpc/proto/net.rs b/iroh-node-util/src/rpc/proto/net.rs index 75d79f6654..177cc6424c 100644 --- a/iroh-node-util/src/rpc/proto/net.rs +++ b/iroh-node-util/src/rpc/proto/net.rs @@ -1,6 +1,6 @@ //! RPC calls to control an iroh-net endpoint. #![allow(missing_docs)] -use iroh_net::{endpoint::RemoteInfo, key::PublicKey, relay::RelayUrl, NodeAddr, NodeId}; +use iroh::{endpoint::RemoteInfo, key::PublicKey, relay::RelayUrl, NodeAddr, NodeId}; use nested_enum_utils::enum_conversions; use quic_rpc_derive::rpc_requests; use serde::{Deserialize, Serialize}; diff --git a/iroh-node-util/src/rpc/server.rs b/iroh-node-util/src/rpc/server.rs index dfdbce0efd..fc7681e671 100644 --- a/iroh-node-util/src/rpc/server.rs +++ b/iroh-node-util/src/rpc/server.rs @@ -3,7 +3,7 @@ use std::{collections::BTreeMap, net::SocketAddr, sync::Arc, time::Duration}; use anyhow::{anyhow, Result}; use futures_lite::{Stream, StreamExt}; -use iroh_net::{Endpoint, NodeAddr, NodeId, RelayUrl}; +use iroh::{Endpoint, NodeAddr, NodeId, RelayUrl}; use quic_rpc::server::{ChannelTypes, RpcChannel, RpcServerError}; use tracing::{debug, info}; diff --git a/iroh-relay/src/main.rs b/iroh-relay/src/main.rs index 94d81f095f..092e56da68 100644 --- a/iroh-relay/src/main.rs +++ b/iroh-relay/src/main.rs @@ -1,7 +1,7 @@ //! A simple relay server for iroh-net. //! //! This handles only the CLI and config file loading, the server implementation lives in -//! [`iroh_net::relay::server`]. +//! [`iroh::relay::server`]. use std::{ net::{Ipv6Addr, SocketAddr}, diff --git a/iroh-net/Cargo.toml b/iroh/Cargo.toml similarity index 99% rename from iroh-net/Cargo.toml rename to iroh/Cargo.toml index f7c7fdd855..14cf3c9933 100644 --- a/iroh-net/Cargo.toml +++ b/iroh/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "iroh-net" +name = "iroh" version = "0.28.1" edition = "2021" readme = "README.md" @@ -167,7 +167,7 @@ tokio = { version = "1", features = [ ] } tracing-subscriber = { version = "0.3", features = ["env-filter"] } iroh-test = "0.28.0" -iroh-net = { path = "." } +iroh = { path = "." } serde_json = "1" testresult = "0.4.0" iroh-relay = { version = "0.28", path = "../iroh-relay", features = ["test-utils", "server"] } diff --git a/iroh-net/LICENSE-BSD3 b/iroh/LICENSE-BSD3 similarity index 100% rename from iroh-net/LICENSE-BSD3 rename to iroh/LICENSE-BSD3 diff --git a/iroh-net/README.md b/iroh/README.md similarity index 100% rename from iroh-net/README.md rename to iroh/README.md diff --git a/iroh-net/bench/Cargo.toml b/iroh/bench/Cargo.toml similarity index 92% rename from iroh-net/bench/Cargo.toml rename to iroh/bench/Cargo.toml index 6c9d609241..72268a5b17 100644 --- a/iroh-net/bench/Cargo.toml +++ b/iroh/bench/Cargo.toml @@ -9,7 +9,7 @@ publish = false anyhow = "1.0.22" bytes = "1.7" hdrhistogram = { version = "7.2", default-features = false } -iroh-net = { path = ".." } +iroh = { path = ".." } iroh-metrics = { path = "../../iroh-metrics" } quinn = { package = "iroh-quinn", version = "0.12" } rcgen = "0.13" @@ -29,4 +29,4 @@ futures-lite = "2.5" [features] default = [] -local-relay = ["iroh-net/test-utils"] +local-relay = ["iroh/test-utils"] diff --git a/iroh-net/bench/src/bin/bulk.rs b/iroh/bench/src/bin/bulk.rs similarity index 89% rename from iroh-net/bench/src/bin/bulk.rs rename to iroh/bench/src/bin/bulk.rs index 83f039439d..d28215ba93 100644 --- a/iroh-net/bench/src/bin/bulk.rs +++ b/iroh/bench/src/bin/bulk.rs @@ -35,12 +35,12 @@ pub fn run_iroh(opt: Opt) -> Result<()> { // enable recording metrics iroh_metrics::core::Core::try_init(|reg, metrics| { use iroh_metrics::core::Metric; - metrics.insert(iroh_net::metrics::MagicsockMetrics::new(reg)); - metrics.insert(iroh_net::metrics::NetReportMetrics::new(reg)); - metrics.insert(iroh_net::metrics::PortmapMetrics::new(reg)); + metrics.insert(::iroh::metrics::MagicsockMetrics::new(reg)); + metrics.insert(::iroh::metrics::NetReportMetrics::new(reg)); + metrics.insert(::iroh::metrics::PortmapMetrics::new(reg)); #[cfg(feature = "local-relay")] if opt.with_relay { - metrics.insert(iroh_net::metrics::RelayMetrics::new(reg)); + metrics.insert(::iroh::metrics::RelayMetrics::new(reg)); } })?; } @@ -57,7 +57,7 @@ pub fn run_iroh(opt: Opt) -> Result<()> { #[cfg(feature = "local-relay")] let (relay_url, _guard) = if opt.with_relay { - let (_, relay_url, _guard) = runtime.block_on(iroh_net::test_utils::run_relay_server())?; + let (_, relay_url, _guard) = runtime.block_on(::iroh::test_utils::run_relay_server())?; (Some(relay_url), Some(_guard)) } else { @@ -110,21 +110,21 @@ pub fn run_iroh(opt: Opt) -> Result<()> { println!("\nMetrics:"); collect_and_print( "MagicsockMetrics", - core.get_collector::(), + core.get_collector::<::iroh::metrics::MagicsockMetrics>(), ); collect_and_print( "NetReportMetrics", - core.get_collector::(), + core.get_collector::<::iroh::metrics::NetReportMetrics>(), ); collect_and_print( "PortmapMetrics", - core.get_collector::(), + core.get_collector::<::iroh::metrics::PortmapMetrics>(), ); // if None, (this is the case if opt.with_relay is false), then this is skipped internally: #[cfg(feature = "local-relay")] collect_and_print( "RelayMetrics", - core.get_collector::(), + core.get_collector::<::iroh::metrics::RelayMetrics>(), ); } diff --git a/iroh-net/bench/src/iroh.rs b/iroh/bench/src/iroh.rs similarity index 99% rename from iroh-net/bench/src/iroh.rs rename to iroh/bench/src/iroh.rs index 702d8dc3f8..063a59bd63 100644 --- a/iroh-net/bench/src/iroh.rs +++ b/iroh/bench/src/iroh.rs @@ -6,7 +6,7 @@ use std::{ use anyhow::{Context, Result}; use bytes::Bytes; use futures_lite::StreamExt as _; -use iroh_net::{ +use iroh::{ endpoint::{Connection, ConnectionError, RecvStream, SendStream, TransportConfig}, Endpoint, NodeAddr, RelayMap, RelayMode, RelayUrl, }; diff --git a/iroh-net/bench/src/lib.rs b/iroh/bench/src/lib.rs similarity index 99% rename from iroh-net/bench/src/lib.rs rename to iroh/bench/src/lib.rs index 93e0c91e51..6938101538 100644 --- a/iroh-net/bench/src/lib.rs +++ b/iroh/bench/src/lib.rs @@ -78,7 +78,7 @@ pub struct Opt { } pub enum EndpointSelector { - Iroh(iroh_net::Endpoint), + Iroh(::iroh::Endpoint), #[cfg(not(any(target_os = "freebsd", target_os = "openbsd", target_os = "netbsd")))] Quinn(::quinn::Endpoint), } @@ -99,7 +99,7 @@ impl EndpointSelector { } pub enum ConnectionSelector { - Iroh(iroh_net::endpoint::Connection), + Iroh(::iroh::endpoint::Connection), #[cfg(not(any(target_os = "freebsd", target_os = "openbsd", target_os = "netbsd")))] Quinn(::quinn::Connection), } diff --git a/iroh-net/bench/src/quinn.rs b/iroh/bench/src/quinn.rs similarity index 96% rename from iroh-net/bench/src/quinn.rs rename to iroh/bench/src/quinn.rs index fb579bf0f0..c5ce39d119 100644 --- a/iroh-net/bench/src/quinn.rs +++ b/iroh/bench/src/quinn.rs @@ -20,9 +20,8 @@ pub const ALPN: &[u8] = b"n0/quinn-bench/0"; /// Creates a server endpoint which runs on the given runtime pub fn server_endpoint(rt: &tokio::runtime::Runtime, opt: &Opt) -> (SocketAddr, quinn::Endpoint) { - let secret_key = iroh_net::key::SecretKey::generate(); - let crypto = - iroh_net::tls::make_server_config(&secret_key, vec![ALPN.to_vec()], false).unwrap(); + let secret_key = iroh::key::SecretKey::generate(); + let crypto = iroh::tls::make_server_config(&secret_key, vec![ALPN.to_vec()], false).unwrap(); let transport = transport_config(opt.max_streams, opt.initial_mtu); @@ -67,9 +66,9 @@ pub async fn connect_client( server_addr: SocketAddr, opt: Opt, ) -> Result<(::quinn::Endpoint, Connection)> { - let secret_key = iroh_net::key::SecretKey::generate(); + let secret_key = iroh::key::SecretKey::generate(); let quic_client_config = - iroh_net::tls::make_client_config(&secret_key, None, vec![ALPN.to_vec()], false)?; + iroh::tls::make_client_config(&secret_key, None, vec![ALPN.to_vec()], false)?; let mut config = quinn::ClientConfig::new(Arc::new(quic_client_config)); let transport = transport_config(opt.max_streams, opt.initial_mtu); diff --git a/iroh-net/bench/src/s2n.rs b/iroh/bench/src/s2n.rs similarity index 100% rename from iroh-net/bench/src/s2n.rs rename to iroh/bench/src/s2n.rs diff --git a/iroh-net/bench/src/stats.rs b/iroh/bench/src/stats.rs similarity index 100% rename from iroh-net/bench/src/stats.rs rename to iroh/bench/src/stats.rs diff --git a/iroh-net/benches/key.rs b/iroh/benches/key.rs similarity index 99% rename from iroh-net/benches/key.rs rename to iroh/benches/key.rs index 091984d032..f208efd612 100644 --- a/iroh-net/benches/key.rs +++ b/iroh/benches/key.rs @@ -1,6 +1,6 @@ use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion}; use crypto_box::aead::{AeadCore, AeadInPlace, OsRng}; -use iroh_net::key::SecretKey; +use iroh::key::SecretKey; use rand::RngCore; pub fn seal_to(c: &mut Criterion) { diff --git a/iroh-net/docs/local_relay_node.md b/iroh/docs/local_relay_node.md similarity index 100% rename from iroh-net/docs/local_relay_node.md rename to iroh/docs/local_relay_node.md diff --git a/iroh-net/docs/relay_nodes.md b/iroh/docs/relay_nodes.md similarity index 100% rename from iroh-net/docs/relay_nodes.md rename to iroh/docs/relay_nodes.md diff --git a/iroh-net/examples/connect-unreliable.rs b/iroh/examples/connect-unreliable.rs similarity index 94% rename from iroh-net/examples/connect-unreliable.rs rename to iroh/examples/connect-unreliable.rs index 188d4b0365..8bff12e470 100644 --- a/iroh-net/examples/connect-unreliable.rs +++ b/iroh/examples/connect-unreliable.rs @@ -1,4 +1,4 @@ -//! The smallest example showing how to use iroh-net and [`iroh_net::Endpoint`] to connect to a remote node and pass bytes using unreliable datagrams. +//! The smallest example showing how to use iroh-net and [`iroh::Endpoint`] to connect to a remote node and pass bytes using unreliable datagrams. //! //! We use the node ID (the PublicKey of the remote node), the direct UDP addresses, and the relay url to achieve a connection. //! @@ -10,7 +10,7 @@ use std::net::SocketAddr; use anyhow::Context; use clap::Parser; use futures_lite::StreamExt; -use iroh_net::{key::SecretKey, Endpoint, NodeAddr, RelayMode, RelayUrl}; +use iroh::{key::SecretKey, Endpoint, NodeAddr, RelayMode, RelayUrl}; use tracing::info; // An example ALPN that we are using to communicate over the `Endpoint` @@ -20,7 +20,7 @@ const EXAMPLE_ALPN: &[u8] = b"n0/iroh/examples/magic/0"; struct Cli { /// The id of the remote node. #[clap(long)] - node_id: iroh_net::NodeId, + node_id: iroh::NodeId, /// The list of direct UDP addresses for the remote node. #[clap(long, value_parser, num_args = 1.., value_delimiter = ' ')] addrs: Vec, diff --git a/iroh-net/examples/connect.rs b/iroh/examples/connect.rs similarity index 95% rename from iroh-net/examples/connect.rs rename to iroh/examples/connect.rs index b20a12289e..1ba2063fe0 100644 --- a/iroh-net/examples/connect.rs +++ b/iroh/examples/connect.rs @@ -1,4 +1,4 @@ -//! The smallest example showing how to use iroh-net and [`iroh_net::Endpoint`] to connect to a remote node. +//! The smallest example showing how to use iroh-net and [`iroh::Endpoint`] to connect to a remote node. //! //! We use the node ID (the PublicKey of the remote node), the direct UDP addresses, and the relay url to achieve a connection. //! @@ -10,7 +10,7 @@ use std::net::SocketAddr; use anyhow::Context; use clap::Parser; use futures_lite::StreamExt; -use iroh_net::{key::SecretKey, Endpoint, NodeAddr, RelayMode, RelayUrl}; +use iroh::{key::SecretKey, Endpoint, NodeAddr, RelayMode, RelayUrl}; use tracing::info; // An example ALPN that we are using to communicate over the `Endpoint` @@ -20,7 +20,7 @@ const EXAMPLE_ALPN: &[u8] = b"n0/iroh/examples/magic/0"; struct Cli { /// The id of the remote node. #[clap(long)] - node_id: iroh_net::NodeId, + node_id: iroh::NodeId, /// The list of direct UDP addresses for the remote node. #[clap(long, value_parser, num_args = 1.., value_delimiter = ' ')] addrs: Vec, diff --git a/iroh-net/examples/dht_discovery.rs b/iroh/examples/dht_discovery.rs similarity index 93% rename from iroh-net/examples/dht_discovery.rs rename to iroh/examples/dht_discovery.rs index bb7eecfdb7..924d588cc2 100644 --- a/iroh-net/examples/dht_discovery.rs +++ b/iroh/examples/dht_discovery.rs @@ -11,7 +11,7 @@ use std::str::FromStr; use clap::Parser; -use iroh_net::{endpoint::get_remote_node_id, Endpoint, NodeId}; +use iroh::{endpoint::get_remote_node_id, Endpoint, NodeId}; use tracing::warn; use url::Url; @@ -51,8 +51,8 @@ impl FromStr for PkarrRelay { } } -fn build_discovery(args: Args) -> iroh_net::discovery::pkarr::dht::Builder { - let builder = iroh_net::discovery::pkarr::dht::DhtDiscovery::builder().dht(!args.disable_dht); +fn build_discovery(args: Args) -> iroh::discovery::pkarr::dht::Builder { + let builder = iroh::discovery::pkarr::dht::DhtDiscovery::builder().dht(!args.disable_dht); match args.pkarr_relay { PkarrRelay::Disabled => builder, PkarrRelay::Iroh => builder.n0_dns_pkarr_relay(), @@ -61,7 +61,7 @@ fn build_discovery(args: Args) -> iroh_net::discovery::pkarr::dht::Builder { } async fn chat_server(args: Args) -> anyhow::Result<()> { - let secret_key = iroh_net::key::SecretKey::generate(); + let secret_key = iroh::key::SecretKey::generate(); let node_id = secret_key.public(); let discovery = build_discovery(args) .secret_key(secret_key.clone()) @@ -107,7 +107,7 @@ async fn chat_server(args: Args) -> anyhow::Result<()> { async fn chat_client(args: Args) -> anyhow::Result<()> { let remote_node_id = args.node_id.unwrap(); - let secret_key = iroh_net::key::SecretKey::generate(); + let secret_key = iroh::key::SecretKey::generate(); let node_id = secret_key.public(); // note: we don't pass a secret key here, because we don't need to publish our address, don't spam the DHT let discovery = build_discovery(args).build()?; diff --git a/iroh-net/examples/echo.rs b/iroh/examples/echo.rs similarity index 94% rename from iroh-net/examples/echo.rs rename to iroh/examples/echo.rs index 71fb6c6f28..d2ce681138 100644 --- a/iroh-net/examples/echo.rs +++ b/iroh/examples/echo.rs @@ -10,9 +10,7 @@ use std::sync::Arc; use anyhow::Result; use futures_lite::future::Boxed as BoxedFuture; -use iroh_net::{ - endpoint::Connecting, protocol::ProtocolHandler, router::Router, Endpoint, NodeAddr, -}; +use iroh::{endpoint::Connecting, protocol::ProtocolHandler, router::Router, Endpoint, NodeAddr}; /// Each protocol is identified by its ALPN string. /// @@ -83,7 +81,7 @@ impl ProtocolHandler for Echo { // Wait for the connection to be fully established. let connection = connecting.await?; // We can get the remote's node id from the connection. - let node_id = iroh_net::endpoint::get_remote_node_id(&connection)?; + let node_id = iroh::endpoint::get_remote_node_id(&connection)?; println!("accepted connection from {node_id}"); // Our protocol is a simple request-response protocol, so we expect the diff --git a/iroh-net/examples/listen-unreliable.rs b/iroh/examples/listen-unreliable.rs similarity index 94% rename from iroh-net/examples/listen-unreliable.rs rename to iroh/examples/listen-unreliable.rs index a963d44554..0ac43bc21e 100644 --- a/iroh-net/examples/listen-unreliable.rs +++ b/iroh/examples/listen-unreliable.rs @@ -1,11 +1,11 @@ -//! The smallest example showing how to use iroh-net and [`iroh_net::Endpoint`] to connect two devices and pass bytes using unreliable datagrams. +//! The smallest example showing how to use iroh-net and [`iroh::Endpoint`] to connect two devices and pass bytes using unreliable datagrams. //! //! This example uses the default relay servers to attempt to holepunch, and will use that relay server to relay packets if the two devices cannot establish a direct UDP connection. //! run this example from the project root: //! $ cargo run --example listen-unreliable use anyhow::Context; use futures_lite::StreamExt; -use iroh_net::{key::SecretKey, Endpoint, RelayMode}; +use iroh::{key::SecretKey, Endpoint, RelayMode}; use tracing::{info, warn}; // An example ALPN that we are using to communicate over the `Endpoint` @@ -74,7 +74,7 @@ async fn main() -> anyhow::Result<()> { }; let alpn = connecting.alpn().await?; let conn = connecting.await?; - let node_id = iroh_net::endpoint::get_remote_node_id(&conn)?; + let node_id = iroh::endpoint::get_remote_node_id(&conn)?; info!( "new (unreliable) connection from {node_id} with ALPN {} (coming from {})", String::from_utf8_lossy(&alpn), diff --git a/iroh-net/examples/listen.rs b/iroh/examples/listen.rs similarity index 95% rename from iroh-net/examples/listen.rs rename to iroh/examples/listen.rs index e0c2f25f80..3612665e1a 100644 --- a/iroh-net/examples/listen.rs +++ b/iroh/examples/listen.rs @@ -1,4 +1,4 @@ -//! The smallest example showing how to use iroh-net and [`iroh_net::Endpoint`] to connect two devices. +//! The smallest example showing how to use iroh-net and [`iroh::Endpoint`] to connect two devices. //! //! This example uses the default relay servers to attempt to holepunch, and will use that relay server to relay packets if the two devices cannot establish a direct UDP connection. //! run this example from the project root: @@ -7,7 +7,7 @@ use std::time::Duration; use anyhow::Context; use futures_lite::StreamExt; -use iroh_net::{endpoint::ConnectionError, key::SecretKey, Endpoint, RelayMode}; +use iroh::{endpoint::ConnectionError, key::SecretKey, Endpoint, RelayMode}; use tracing::{debug, info, warn}; // An example ALPN that we are using to communicate over the `Endpoint` @@ -75,7 +75,7 @@ async fn main() -> anyhow::Result<()> { }; let alpn = connecting.alpn().await?; let conn = connecting.await?; - let node_id = iroh_net::endpoint::get_remote_node_id(&conn)?; + let node_id = iroh::endpoint::get_remote_node_id(&conn)?; info!( "new connection from {node_id} with ALPN {} (coming from {})", String::from_utf8_lossy(&alpn), diff --git a/iroh-net/examples/locally-discovered-nodes.rs b/iroh/examples/locally-discovered-nodes.rs similarity index 84% rename from iroh-net/examples/locally-discovered-nodes.rs rename to iroh/examples/locally-discovered-nodes.rs index a2217adfe8..45c9b924e4 100644 --- a/iroh-net/examples/locally-discovered-nodes.rs +++ b/iroh/examples/locally-discovered-nodes.rs @@ -1,11 +1,11 @@ -//! A small example showing how to get a list of nodes that were discovered via [`iroh_net::discovery::LocalSwarmDiscovery`]. LocalSwarmDiscovery uses [`swarm-discovery`](https://crates.io/crates/swarm-discovery) to discover other nodes in the local network ala mDNS. +//! A small example showing how to get a list of nodes that were discovered via [`iroh::discovery::LocalSwarmDiscovery`]. LocalSwarmDiscovery uses [`swarm-discovery`](https://crates.io/crates/swarm-discovery) to discover other nodes in the local network ala mDNS. //! -//! This example creates an iroh endpoint, a few additional iroh endpoints to discover, waits a few seconds, and reports all of the iroh NodeIds (also called `[iroh_net::key::PublicKey]`s) it has discovered. +//! This example creates an iroh endpoint, a few additional iroh endpoints to discover, waits a few seconds, and reports all of the iroh NodeIds (also called `[iroh::key::PublicKey]`s) it has discovered. //! //! This is an async, non-determinate process, so the number of NodeIDs discovered each time may be different. If you have other iroh endpoints or iroh nodes with [`LocalSwarmDiscovery`] enabled, it may discover those nodes as well. use std::time::Duration; -use iroh_net::{ +use iroh::{ discovery::local_swarm_discovery::LocalSwarmDiscovery, endpoint::Source, key::SecretKey, Endpoint, }; @@ -45,7 +45,7 @@ async fn main() -> anyhow::Result<()> { // get an iterator of all the remote nodes this endpoint knows about let remotes = ep.remote_info_iter(); // filter that list down to the nodes that have a `Source::Discovery` with - // the `service` name [`iroh_net::discovery::local_swarm_discovery::NAME`] + // the `service` name [`iroh::discovery::local_swarm_discovery::NAME`] // If you have a long running node and want to only get the nodes that were // discovered recently, you can also filter on the `Duration` of the source, // which indicates how long ago we got information from that source. @@ -53,7 +53,7 @@ async fn main() -> anyhow::Result<()> { .filter(|remote| { remote.sources().iter().any(|(source, _duration)| { if let Source::Discovery { name } = source { - name == iroh_net::discovery::local_swarm_discovery::NAME + name == iroh::discovery::local_swarm_discovery::NAME } else { false } diff --git a/iroh-net/examples/search.rs b/iroh/examples/search.rs similarity index 99% rename from iroh-net/examples/search.rs rename to iroh/examples/search.rs index 9ff5fdf0cb..b6e9fdd393 100644 --- a/iroh-net/examples/search.rs +++ b/iroh/examples/search.rs @@ -34,7 +34,7 @@ use std::{collections::BTreeSet, sync::Arc}; use anyhow::Result; use clap::Parser; use futures_lite::future::Boxed as BoxedFuture; -use iroh_net::{ +use iroh::{ endpoint::{get_remote_node_id, Connecting}, protocol::ProtocolHandler, router::Router, diff --git a/iroh-net/examples/transfer.rs b/iroh/examples/transfer.rs similarity index 98% rename from iroh-net/examples/transfer.rs rename to iroh/examples/transfer.rs index c4ed19d9c8..45aec76ebe 100644 --- a/iroh-net/examples/transfer.rs +++ b/iroh/examples/transfer.rs @@ -8,7 +8,7 @@ use bytes::Bytes; use clap::{Parser, Subcommand}; use futures_lite::StreamExt; use indicatif::HumanBytes; -use iroh_net::{ +use iroh::{ endpoint::ConnectionError, key::SecretKey, ticket::NodeTicket, Endpoint, NodeAddr, RelayMap, RelayMode, RelayUrl, }; @@ -109,7 +109,7 @@ async fn provide(size: u64, relay_url: Option) -> anyhow::Result<()> { } }; let conn = connecting.await?; - let node_id = iroh_net::endpoint::get_remote_node_id(&conn)?; + let node_id = iroh::endpoint::get_remote_node_id(&conn)?; info!( "new connection from {node_id} with ALPN {} (coming from {})", String::from_utf8_lossy(TRANSFER_ALPN), @@ -232,7 +232,7 @@ async fn fetch(ticket: &str, relay_url: Option) -> anyhow::Result<()> { } async fn drain_stream( - stream: &mut iroh_net::endpoint::RecvStream, + stream: &mut iroh::endpoint::RecvStream, read_unordered: bool, ) -> Result<(usize, Duration, u64)> { let mut read = 0; @@ -280,7 +280,7 @@ async fn drain_stream( } async fn send_data_on_stream( - stream: &mut iroh_net::endpoint::SendStream, + stream: &mut iroh::endpoint::SendStream, stream_size: u64, ) -> Result<()> { const DATA: &[u8] = &[0xAB; 1024 * 1024]; diff --git a/iroh-net/src/defaults.rs b/iroh/src/defaults.rs similarity index 100% rename from iroh-net/src/defaults.rs rename to iroh/src/defaults.rs diff --git a/iroh-net/src/dialer.rs b/iroh/src/dialer.rs similarity index 100% rename from iroh-net/src/dialer.rs rename to iroh/src/dialer.rs diff --git a/iroh-net/src/disco.rs b/iroh/src/disco.rs similarity index 100% rename from iroh-net/src/disco.rs rename to iroh/src/disco.rs diff --git a/iroh-net/src/discovery.rs b/iroh/src/discovery.rs similarity index 99% rename from iroh-net/src/discovery.rs rename to iroh/src/discovery.rs index d05e07eb13..c1e6fe2fc5 100644 --- a/iroh-net/src/discovery.rs +++ b/iroh/src/discovery.rs @@ -46,7 +46,7 @@ //! [`PkarrPublisher`] and [`DnsDiscovery`]: //! //! ```no_run -//! use iroh_net::{ +//! use iroh::{ //! discovery::{dns::DnsDiscovery, pkarr::PkarrPublisher, ConcurrentDiscovery}, //! key::SecretKey, //! Endpoint, @@ -71,11 +71,11 @@ //! [`ConcurrentDiscovery`]: //! //! ```no_run -//! # use iroh_net::discovery::dns::DnsDiscovery; -//! # use iroh_net::discovery::local_swarm_discovery::LocalSwarmDiscovery; -//! # use iroh_net::discovery::pkarr::PkarrPublisher; -//! # use iroh_net::discovery::ConcurrentDiscovery; -//! # use iroh_net::key::SecretKey; +//! # use iroh::discovery::dns::DnsDiscovery; +//! # use iroh::discovery::local_swarm_discovery::LocalSwarmDiscovery; +//! # use iroh::discovery::pkarr::PkarrPublisher; +//! # use iroh::discovery::ConcurrentDiscovery; +//! # use iroh::key::SecretKey; //! # //! # async fn wrapper() -> anyhow::Result<()> { //! # let secret_key = SecretKey::generate(); diff --git a/iroh-net/src/discovery/dns.rs b/iroh/src/discovery/dns.rs similarity index 100% rename from iroh-net/src/discovery/dns.rs rename to iroh/src/discovery/dns.rs diff --git a/iroh-net/src/discovery/local_swarm_discovery.rs b/iroh/src/discovery/local_swarm_discovery.rs similarity index 99% rename from iroh-net/src/discovery/local_swarm_discovery.rs rename to iroh/src/discovery/local_swarm_discovery.rs index 6d7dc79110..fe9dfa45af 100644 --- a/iroh-net/src/discovery/local_swarm_discovery.rs +++ b/iroh/src/discovery/local_swarm_discovery.rs @@ -8,7 +8,7 @@ //! ``` //! use std::time::Duration; //! -//! use iroh_net::endpoint::{Endpoint, Source}; +//! use iroh::endpoint::{Endpoint, Source}; //! //! #[tokio::main] //! async fn main() { @@ -20,7 +20,7 @@ //! .filter(|remote| { //! remote.sources().iter().any(|(source, duration)| { //! if let Source::Discovery { name } = source { -//! name == iroh_net::discovery::local_swarm_discovery::NAME +//! name == iroh::discovery::local_swarm_discovery::NAME //! && *duration <= recent //! } else { //! false diff --git a/iroh-net/src/discovery/pkarr.rs b/iroh/src/discovery/pkarr.rs similarity index 100% rename from iroh-net/src/discovery/pkarr.rs rename to iroh/src/discovery/pkarr.rs diff --git a/iroh-net/src/discovery/pkarr/dht.rs b/iroh/src/discovery/pkarr/dht.rs similarity index 100% rename from iroh-net/src/discovery/pkarr/dht.rs rename to iroh/src/discovery/pkarr/dht.rs diff --git a/iroh-net/src/discovery/static_provider.rs b/iroh/src/discovery/static_provider.rs similarity index 98% rename from iroh-net/src/discovery/static_provider.rs rename to iroh/src/discovery/static_provider.rs index a6169d2b1d..acff8ac41a 100644 --- a/iroh-net/src/discovery/static_provider.rs +++ b/iroh/src/discovery/static_provider.rs @@ -42,7 +42,7 @@ impl StaticProvider { /// use std::str::FromStr; /// /// use iroh_base::ticket::NodeTicket; - /// use iroh_net::{Endpoint, discovery::static_provider::StaticProvider}; + /// use iroh::{Endpoint, discovery::static_provider::StaticProvider}; /// /// # async fn example() -> anyhow::Result<()> { /// # #[derive(Default)] struct Args { tickets: Vec } diff --git a/iroh-net/src/dns.rs b/iroh/src/dns.rs similarity index 100% rename from iroh-net/src/dns.rs rename to iroh/src/dns.rs diff --git a/iroh-net/src/dns/node_info.rs b/iroh/src/dns/node_info.rs similarity index 100% rename from iroh-net/src/dns/node_info.rs rename to iroh/src/dns/node_info.rs diff --git a/iroh-net/src/endpoint.rs b/iroh/src/endpoint.rs similarity index 99% rename from iroh-net/src/endpoint.rs rename to iroh/src/endpoint.rs index d194892f74..7b23967824 100644 --- a/iroh-net/src/endpoint.rs +++ b/iroh/src/endpoint.rs @@ -841,7 +841,7 @@ impl Endpoint { /// To get the current endpoints, drop the stream after the first item was received: /// ``` /// use futures_lite::StreamExt; - /// use iroh_net::Endpoint; + /// use iroh::Endpoint; /// /// # let rt = tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap(); /// # rt.block_on(async move { diff --git a/iroh-net/src/endpoint/rtt_actor.rs b/iroh/src/endpoint/rtt_actor.rs similarity index 100% rename from iroh-net/src/endpoint/rtt_actor.rs rename to iroh/src/endpoint/rtt_actor.rs diff --git a/iroh-net/src/lib.rs b/iroh/src/lib.rs similarity index 98% rename from iroh-net/src/lib.rs rename to iroh/src/lib.rs index 61c1fcb274..c112c025d4 100644 --- a/iroh-net/src/lib.rs +++ b/iroh/src/lib.rs @@ -8,7 +8,7 @@ //! another node: //! //! ```no_run -//! # use iroh_net::{Endpoint, NodeAddr}; +//! # use iroh::{Endpoint, NodeAddr}; //! # async fn wrapper() -> testresult::TestResult { //! let addr: NodeAddr = todo!(); //! let ep = Endpoint::builder().bind().await?; @@ -22,7 +22,7 @@ //! The other node can accept incoming connections using the [`Endpoint`] as well: //! //! ```no_run -//! # use iroh_net::{Endpoint, NodeAddr}; +//! # use iroh::{Endpoint, NodeAddr}; //! # async fn wrapper() -> testresult::TestResult { //! let ep = Endpoint::builder() //! .alpns(vec![b"my-alpn".to_vec()]) @@ -158,7 +158,7 @@ //! //! ```no_run //! use anyhow::Result; -//! use iroh_net::{Endpoint, NodeAddr}; +//! use iroh::{Endpoint, NodeAddr}; //! //! async fn connect(addr: NodeAddr) -> Result<()> { //! // The Endpoint is the central object that manages an iroh-net node. @@ -184,7 +184,7 @@ //! ```no_run //! use anyhow::{Context, Result}; //! use futures_lite::StreamExt; -//! use iroh_net::{ticket::NodeTicket, Endpoint, NodeAddr}; +//! use iroh::{ticket::NodeTicket, Endpoint, NodeAddr}; //! //! async fn accept() -> Result<()> { //! // To accept connections at least one ALPN must be configured. diff --git a/iroh-net/src/magicsock.rs b/iroh/src/magicsock.rs similarity index 100% rename from iroh-net/src/magicsock.rs rename to iroh/src/magicsock.rs diff --git a/iroh-net/src/magicsock/metrics.rs b/iroh/src/magicsock/metrics.rs similarity index 100% rename from iroh-net/src/magicsock/metrics.rs rename to iroh/src/magicsock/metrics.rs diff --git a/iroh-net/src/magicsock/node_map.rs b/iroh/src/magicsock/node_map.rs similarity index 100% rename from iroh-net/src/magicsock/node_map.rs rename to iroh/src/magicsock/node_map.rs diff --git a/iroh-net/src/magicsock/node_map/best_addr.rs b/iroh/src/magicsock/node_map/best_addr.rs similarity index 100% rename from iroh-net/src/magicsock/node_map/best_addr.rs rename to iroh/src/magicsock/node_map/best_addr.rs diff --git a/iroh-net/src/magicsock/node_map/node_state.rs b/iroh/src/magicsock/node_map/node_state.rs similarity index 100% rename from iroh-net/src/magicsock/node_map/node_state.rs rename to iroh/src/magicsock/node_map/node_state.rs diff --git a/iroh-net/src/magicsock/node_map/path_state.rs b/iroh/src/magicsock/node_map/path_state.rs similarity index 100% rename from iroh-net/src/magicsock/node_map/path_state.rs rename to iroh/src/magicsock/node_map/path_state.rs diff --git a/iroh-net/src/magicsock/node_map/udp_paths.rs b/iroh/src/magicsock/node_map/udp_paths.rs similarity index 100% rename from iroh-net/src/magicsock/node_map/udp_paths.rs rename to iroh/src/magicsock/node_map/udp_paths.rs diff --git a/iroh-net/src/magicsock/relay_actor.rs b/iroh/src/magicsock/relay_actor.rs similarity index 100% rename from iroh-net/src/magicsock/relay_actor.rs rename to iroh/src/magicsock/relay_actor.rs diff --git a/iroh-net/src/magicsock/timer.rs b/iroh/src/magicsock/timer.rs similarity index 100% rename from iroh-net/src/magicsock/timer.rs rename to iroh/src/magicsock/timer.rs diff --git a/iroh-net/src/magicsock/udp_conn.rs b/iroh/src/magicsock/udp_conn.rs similarity index 100% rename from iroh-net/src/magicsock/udp_conn.rs rename to iroh/src/magicsock/udp_conn.rs diff --git a/iroh-net/src/metrics.rs b/iroh/src/metrics.rs similarity index 100% rename from iroh-net/src/metrics.rs rename to iroh/src/metrics.rs diff --git a/iroh-net/src/protocol.rs b/iroh/src/protocol.rs similarity index 98% rename from iroh-net/src/protocol.rs rename to iroh/src/protocol.rs index 6b3c7f90d4..bbce8ca214 100644 --- a/iroh-net/src/protocol.rs +++ b/iroh/src/protocol.rs @@ -15,7 +15,7 @@ use crate::endpoint::Connecting; /// /// Implement this trait on a struct that should handle incoming connections. /// The protocol handler must then be registered on the node for an ALPN protocol with -/// [`crate::RouterBuilder::accept`]. +/// [`crate::router::RouterBuilder::accept`]. pub trait ProtocolHandler: Send + Sync + IntoArcAny + std::fmt::Debug + 'static { /// Handle an incoming connection. /// diff --git a/iroh-net/src/router.rs b/iroh/src/router.rs similarity index 100% rename from iroh-net/src/router.rs rename to iroh/src/router.rs diff --git a/iroh-net/src/test_utils.rs b/iroh/src/test_utils.rs similarity index 100% rename from iroh-net/src/test_utils.rs rename to iroh/src/test_utils.rs diff --git a/iroh-net/src/ticket.rs b/iroh/src/ticket.rs similarity index 100% rename from iroh-net/src/ticket.rs rename to iroh/src/ticket.rs diff --git a/iroh-net/src/tls.rs b/iroh/src/tls.rs similarity index 100% rename from iroh-net/src/tls.rs rename to iroh/src/tls.rs diff --git a/iroh-net/src/tls/certificate.rs b/iroh/src/tls/certificate.rs similarity index 100% rename from iroh-net/src/tls/certificate.rs rename to iroh/src/tls/certificate.rs diff --git a/iroh-net/src/tls/verifier.rs b/iroh/src/tls/verifier.rs similarity index 100% rename from iroh-net/src/tls/verifier.rs rename to iroh/src/tls/verifier.rs diff --git a/iroh-net/src/util.rs b/iroh/src/util.rs similarity index 100% rename from iroh-net/src/util.rs rename to iroh/src/util.rs From db7e26bd53422469b0cffdc8dbd954f93cf66901 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Kr=C3=BCger?= Date: Thu, 28 Nov 2024 09:44:45 +0100 Subject: [PATCH 3/3] refactor: move `Router` and `RouterBuilder` into `protocol.rs` --- iroh/src/discovery/local_swarm_discovery.rs | 3 +- iroh/src/lib.rs | 1 - iroh/src/protocol.rs | 218 ++++++++++++++++++- iroh/src/router.rs | 223 -------------------- 4 files changed, 217 insertions(+), 228 deletions(-) delete mode 100644 iroh/src/router.rs diff --git a/iroh/src/discovery/local_swarm_discovery.rs b/iroh/src/discovery/local_swarm_discovery.rs index fe9dfa45af..753848b212 100644 --- a/iroh/src/discovery/local_swarm_discovery.rs +++ b/iroh/src/discovery/local_swarm_discovery.rs @@ -20,8 +20,7 @@ //! .filter(|remote| { //! remote.sources().iter().any(|(source, duration)| { //! if let Source::Discovery { name } = source { -//! name == iroh::discovery::local_swarm_discovery::NAME -//! && *duration <= recent +//! name == iroh::discovery::local_swarm_discovery::NAME && *duration <= recent //! } else { //! false //! } diff --git a/iroh/src/lib.rs b/iroh/src/lib.rs index c112c025d4..db2a46203b 100644 --- a/iroh/src/lib.rs +++ b/iroh/src/lib.rs @@ -242,7 +242,6 @@ pub mod endpoint; mod magicsock; pub mod metrics; pub mod protocol; -pub mod router; pub mod ticket; pub mod tls; diff --git a/iroh/src/protocol.rs b/iroh/src/protocol.rs index bbce8ca214..91feecf3da 100644 --- a/iroh/src/protocol.rs +++ b/iroh/src/protocol.rs @@ -1,11 +1,42 @@ //! TODO(matheus23) docs use std::{any::Any, collections::BTreeMap, sync::Arc}; -use anyhow::Result; +use anyhow::{anyhow, Result}; use futures_buffered::join_all; use futures_lite::future::Boxed as BoxedFuture; +use futures_util::{ + future::{MapErr, Shared}, + FutureExt, TryFutureExt, +}; +use tokio::task::{JoinError, JoinSet}; +use tokio_util::{sync::CancellationToken, task::AbortOnDropHandle}; +use tracing::{debug, error, warn}; -use crate::endpoint::Connecting; +use crate::{endpoint::Connecting, Endpoint}; + +/// TODO(matheus23): docs +#[derive(Clone, Debug)] +pub struct Router { + endpoint: Endpoint, + protocols: Arc, + // `Router` needs to be `Clone + Send`, and we need to `task.await` in its `shutdown()` impl. + // So we need + // - `Shared` so we can `task.await` from all `Node` clones + // - `MapErr` to map the `JoinError` to a `String`, because `JoinError` is `!Clone` + // - `AbortOnDropHandle` to make sure that the `task` is cancelled when all `Node`s are dropped + // (`Shared` acts like an `Arc` around its inner future). + task: Shared, JoinErrToStr>>, + cancel_token: CancellationToken, +} + +type JoinErrToStr = Box String + Send + Sync + 'static>; + +/// TODO(matheus23): docs +#[derive(Debug)] +pub struct RouterBuilder { + endpoint: Endpoint, + protocols: ProtocolMap, +} /// Handler for incoming connections. /// @@ -78,3 +109,186 @@ impl ProtocolMap { join_all(handlers).await; } } + +impl Router { + /// TODO(matheus23): docs + pub fn builder(endpoint: Endpoint) -> RouterBuilder { + RouterBuilder::new(endpoint) + } + + /// Returns a protocol handler for an ALPN. + /// + /// This downcasts to the concrete type and returns `None` if the handler registered for `alpn` + /// does not match the passed type. + pub fn get_protocol(&self, alpn: &[u8]) -> Option> { + self.protocols.get_typed(alpn) + } + + /// TODO(matheus23): docs + pub fn endpoint(&self) -> &Endpoint { + &self.endpoint + } + + /// TODO(matheus23): docs + pub async fn shutdown(self) -> Result<()> { + // Trigger shutdown of the main run task by activating the cancel token. + self.cancel_token.cancel(); + + // Wait for the main task to terminate. + self.task.await.map_err(|err| anyhow!(err))?; + + Ok(()) + } +} + +impl RouterBuilder { + /// TODO(matheus23): docs + pub fn new(endpoint: Endpoint) -> Self { + Self { + endpoint, + protocols: ProtocolMap::default(), + } + } + + /// TODO(matheus23): docs + pub fn accept(mut self, alpn: impl AsRef<[u8]>, handler: Arc) -> Self { + self.protocols.insert(alpn.as_ref().to_vec(), handler); + self + } + + /// Returns the [`Endpoint`] of the node. + pub fn endpoint(&self) -> &Endpoint { + &self.endpoint + } + + /// Returns a protocol handler for an ALPN. + /// + /// This downcasts to the concrete type and returns `None` if the handler registered for `alpn` + /// does not match the passed type. + pub fn get_protocol(&self, alpn: &[u8]) -> Option> { + self.protocols.get_typed(alpn) + } + + /// TODO(matheus23): docs + pub async fn spawn(self) -> Result { + // Update the endpoint with our alpns. + let alpns = self + .protocols + .alpns() + .map(|alpn| alpn.to_vec()) + .collect::>(); + + let protocols = Arc::new(self.protocols); + if let Err(err) = self.endpoint.set_alpns(alpns) { + shutdown(&self.endpoint, protocols.clone()).await; + return Err(err); + } + + let mut join_set = JoinSet::new(); + let endpoint = self.endpoint.clone(); + let protos = protocols.clone(); + let cancel = CancellationToken::new(); + let cancel_token = cancel.clone(); + + let run_loop_fut = async move { + let protocols = protos; + loop { + tokio::select! { + biased; + _ = cancel_token.cancelled() => { + break; + }, + // handle incoming p2p connections. + incoming = endpoint.accept() => { + let Some(incoming) = incoming else { + break; + }; + + let protocols = protocols.clone(); + join_set.spawn(async move { + handle_connection(incoming, protocols).await; + anyhow::Ok(()) + }); + }, + // handle task terminations and quit on panics. + res = join_set.join_next(), if !join_set.is_empty() => { + match res { + Some(Err(outer)) => { + if outer.is_panic() { + error!("Task panicked: {outer:?}"); + break; + } else if outer.is_cancelled() { + debug!("Task cancelled: {outer:?}"); + } else { + error!("Task failed: {outer:?}"); + break; + } + } + Some(Ok(Err(inner))) => { + debug!("Task errored: {inner:?}"); + } + _ => {} + } + }, + } + } + + shutdown(&endpoint, protocols).await; + + // Abort remaining tasks. + tracing::info!("Shutting down remaining tasks"); + join_set.shutdown().await; + }; + let task = tokio::task::spawn(run_loop_fut); + let task = AbortOnDropHandle::new(task) + .map_err(Box::new(|e: JoinError| e.to_string()) as JoinErrToStr) + .shared(); + + Ok(Router { + endpoint: self.endpoint, + protocols, + task, + cancel_token: cancel, + }) + } +} + +/// Shutdown the different parts of the router concurrently. +async fn shutdown(endpoint: &Endpoint, protocols: Arc) { + let error_code = 1u16; + + // We ignore all errors during shutdown. + let _ = tokio::join!( + // Close the endpoint. + // Closing the Endpoint is the equivalent of calling Connection::close on all + // connections: Operations will immediately fail with ConnectionError::LocallyClosed. + // All streams are interrupted, this is not graceful. + endpoint.close(error_code.into(), b"provider terminating"), + // Shutdown protocol handlers. + protocols.shutdown(), + ); +} + +async fn handle_connection(incoming: crate::endpoint::Incoming, protocols: Arc) { + let mut connecting = match incoming.accept() { + Ok(conn) => conn, + Err(err) => { + warn!("Ignoring connection: accepting failed: {err:#}"); + return; + } + }; + let alpn = match connecting.alpn().await { + Ok(alpn) => alpn, + Err(err) => { + warn!("Ignoring connection: invalid handshake: {err:#}"); + return; + } + }; + let Some(handler) = protocols.get(&alpn) else { + warn!("Ignoring connection: unsupported ALPN protocol"); + return; + }; + if let Err(err) = handler.accept(connecting).await { + warn!("Handling incoming connection ended with error: {err}"); + } +} diff --git a/iroh/src/router.rs b/iroh/src/router.rs deleted file mode 100644 index 8094cbee3f..0000000000 --- a/iroh/src/router.rs +++ /dev/null @@ -1,223 +0,0 @@ -//! TODO(matheus23) docs -use std::sync::Arc; - -use anyhow::{anyhow, Result}; -use futures_util::{ - future::{MapErr, Shared}, - FutureExt, TryFutureExt, -}; -use tokio::task::{JoinError, JoinSet}; -use tokio_util::{sync::CancellationToken, task::AbortOnDropHandle}; -use tracing::{debug, error, warn}; - -use crate::{ - protocol::{ProtocolHandler, ProtocolMap}, - Endpoint, -}; - -/// TODO(matheus23): docs -#[derive(Clone, Debug)] -pub struct Router { - endpoint: Endpoint, - protocols: Arc, - // `Router` needs to be `Clone + Send`, and we need to `task.await` in its `shutdown()` impl. - // So we need - // - `Shared` so we can `task.await` from all `Node` clones - // - `MapErr` to map the `JoinError` to a `String`, because `JoinError` is `!Clone` - // - `AbortOnDropHandle` to make sure that the `task` is cancelled when all `Node`s are dropped - // (`Shared` acts like an `Arc` around its inner future). - task: Shared, JoinErrToStr>>, - cancel_token: CancellationToken, -} - -type JoinErrToStr = Box String + Send + Sync + 'static>; - -impl Router { - /// TODO(matheus23): docs - pub fn builder(endpoint: Endpoint) -> RouterBuilder { - RouterBuilder::new(endpoint) - } - - /// Returns a protocol handler for an ALPN. - /// - /// This downcasts to the concrete type and returns `None` if the handler registered for `alpn` - /// does not match the passed type. - pub fn get_protocol(&self, alpn: &[u8]) -> Option> { - self.protocols.get_typed(alpn) - } - - /// TODO(matheus23): docs - pub fn endpoint(&self) -> &Endpoint { - &self.endpoint - } - - /// TODO(matheus23): docs - pub async fn shutdown(self) -> Result<()> { - // Trigger shutdown of the main run task by activating the cancel token. - self.cancel_token.cancel(); - - // Wait for the main task to terminate. - self.task.await.map_err(|err| anyhow!(err))?; - - Ok(()) - } -} - -/// TODO(matheus23): docs -#[derive(Debug)] -pub struct RouterBuilder { - endpoint: Endpoint, - protocols: ProtocolMap, -} - -impl RouterBuilder { - /// TODO(matheus23): docs - pub fn new(endpoint: Endpoint) -> Self { - Self { - endpoint, - protocols: ProtocolMap::default(), - } - } - - /// TODO(matheus23): docs - pub fn accept(mut self, alpn: impl AsRef<[u8]>, handler: Arc) -> Self { - self.protocols.insert(alpn.as_ref().to_vec(), handler); - self - } - - /// Returns the [`Endpoint`] of the node. - pub fn endpoint(&self) -> &Endpoint { - &self.endpoint - } - - /// Returns a protocol handler for an ALPN. - /// - /// This downcasts to the concrete type and returns `None` if the handler registered for `alpn` - /// does not match the passed type. - pub fn get_protocol(&self, alpn: &[u8]) -> Option> { - self.protocols.get_typed(alpn) - } - - /// TODO(matheus23): docs - pub async fn spawn(self) -> Result { - // Update the endpoint with our alpns. - let alpns = self - .protocols - .alpns() - .map(|alpn| alpn.to_vec()) - .collect::>(); - - let protocols = Arc::new(self.protocols); - if let Err(err) = self.endpoint.set_alpns(alpns) { - shutdown(&self.endpoint, protocols.clone()).await; - return Err(err); - } - - let mut join_set = JoinSet::new(); - let endpoint = self.endpoint.clone(); - let protos = protocols.clone(); - let cancel = CancellationToken::new(); - let cancel_token = cancel.clone(); - - let run_loop_fut = async move { - let protocols = protos; - loop { - tokio::select! { - biased; - _ = cancel_token.cancelled() => { - break; - }, - // handle incoming p2p connections. - incoming = endpoint.accept() => { - let Some(incoming) = incoming else { - break; - }; - - let protocols = protocols.clone(); - join_set.spawn(async move { - handle_connection(incoming, protocols).await; - anyhow::Ok(()) - }); - }, - // handle task terminations and quit on panics. - res = join_set.join_next(), if !join_set.is_empty() => { - match res { - Some(Err(outer)) => { - if outer.is_panic() { - error!("Task panicked: {outer:?}"); - break; - } else if outer.is_cancelled() { - debug!("Task cancelled: {outer:?}"); - } else { - error!("Task failed: {outer:?}"); - break; - } - } - Some(Ok(Err(inner))) => { - debug!("Task errored: {inner:?}"); - } - _ => {} - } - }, - } - } - - shutdown(&endpoint, protocols).await; - - // Abort remaining tasks. - tracing::info!("Shutting down remaining tasks"); - join_set.shutdown().await; - }; - let task = tokio::task::spawn(run_loop_fut); - let task = AbortOnDropHandle::new(task) - .map_err(Box::new(|e: JoinError| e.to_string()) as JoinErrToStr) - .shared(); - - Ok(Router { - endpoint: self.endpoint, - protocols, - task, - cancel_token: cancel, - }) - } -} - -/// Shutdown the different parts of the router concurrently. -async fn shutdown(endpoint: &Endpoint, protocols: Arc) { - let error_code = 1u16; - - // We ignore all errors during shutdown. - let _ = tokio::join!( - // Close the endpoint. - // Closing the Endpoint is the equivalent of calling Connection::close on all - // connections: Operations will immediately fail with ConnectionError::LocallyClosed. - // All streams are interrupted, this is not graceful. - endpoint.close(error_code.into(), b"provider terminating"), - // Shutdown protocol handlers. - protocols.shutdown(), - ); -} - -async fn handle_connection(incoming: crate::endpoint::Incoming, protocols: Arc) { - let mut connecting = match incoming.accept() { - Ok(conn) => conn, - Err(err) => { - warn!("Ignoring connection: accepting failed: {err:#}"); - return; - } - }; - let alpn = match connecting.alpn().await { - Ok(alpn) => alpn, - Err(err) => { - warn!("Ignoring connection: invalid handshake: {err:#}"); - return; - } - }; - let Some(handler) = protocols.get(&alpn) else { - warn!("Ignoring connection: unsupported ALPN protocol"); - return; - }; - if let Err(err) = handler.accept(connecting).await { - warn!("Handling incoming connection ended with error: {err}"); - } -}