From 6354e04f348dc4e0cc57411c0193880225d56141 Mon Sep 17 00:00:00 2001 From: Friedel Ziegelmayer Date: Mon, 19 Aug 2024 19:09:29 +0200 Subject: [PATCH] refactor(iroh)!: convert node to net module (#2642) ## Description Converts the `node` module to the `net` module (`iroh` and `iroh-cli`) Closes #2639 ## Breaking Changes - No more `deref` of `iroh::net::Client` to `iroh::client::node::Node` - `iroh::client::node` -> `iroh::client::net` - `iroh::client::node::Node::shutdown` -> `iroh::client::Client::shutdown` ## Notes & open questions ## Change checklist - [x] Self-review. - [x] Documentation updates following the [style guide](https://rust-lang.github.io/rfcs/1574-more-api-documentation-conventions.html#appendix-a-full-conventions-text), if relevant. - [ ] Tests if relevant. - [x] All breaking changes documented. --------- Co-authored-by: Kasey --- .github/workflows/ci.yml | 10 +-- iroh-cli/src/commands.rs | 3 +- iroh-cli/src/commands/{node.rs => net.rs} | 48 ++---------- iroh-cli/src/commands/rpc.rs | 48 ++++++++++-- iroh-cli/tests/cli.rs | 1 + iroh/examples/collection-fetch.rs | 2 +- iroh/examples/hello-world-fetch.rs | 2 +- iroh/examples/rpc.rs | 4 +- iroh/src/client.rs | 46 +++++++---- iroh/src/client/blobs.rs | 2 +- iroh/src/client/{node.rs => net.rs} | 93 ++++------------------ iroh/src/lib.rs | 4 +- iroh/src/node/rpc.rs | 27 +++++-- iroh/src/rpc_protocol.rs | 3 + iroh/src/rpc_protocol/net.rs | 95 +++++++++++++++++++++++ iroh/src/rpc_protocol/node.rs | 83 -------------------- iroh/tests/client.rs | 10 +-- 17 files changed, 233 insertions(+), 248 deletions(-) rename iroh-cli/src/commands/{node.rs => net.rs} (81%) rename iroh/src/client/{node.rs => net.rs} (57%) create mode 100644 iroh/src/rpc_protocol/net.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index db323dd57a..935cff4021 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -97,7 +97,7 @@ jobs: with: distribution: 'temurin' java-version: '17' - + - name: Setup Android SDK uses: android-actions/setup-android@v3 @@ -111,7 +111,7 @@ jobs: - name: Build env: ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }} - run: | + run: | cargo install --version 3.5.4 cargo-ndk cargo ndk --target ${{ matrix.target }} build @@ -446,11 +446,11 @@ jobs: target: iroh platforms: linux/amd64 file: docker/Dockerfile - - - name: Run Docker image & node stats test + + - name: Run Docker image & stats test run: | docker run -p 9090:9090 -p 4919:4919/udp -Pd n0computer/iroh-test:latest --rpc-addr 0.0.0.0:4919 start - cargo run --bin iroh -- --rpc-addr 127.0.0.1:4919 node stats + cargo run --bin iroh -- --rpc-addr 127.0.0.1:4919 stats codespell: runs-on: ubuntu-latest diff --git a/iroh-cli/src/commands.rs b/iroh-cli/src/commands.rs index ab1971d3c2..43cf2f5e82 100644 --- a/iroh-cli/src/commands.rs +++ b/iroh-cli/src/commands.rs @@ -17,7 +17,7 @@ pub(crate) mod console; pub(crate) mod docs; pub(crate) mod doctor; pub(crate) mod gossip; -pub(crate) mod node; +pub(crate) mod net; pub(crate) mod rpc; pub(crate) mod start; pub(crate) mod tags; @@ -190,6 +190,7 @@ impl Cli { ) .await } + Commands::Doctor { command } => { let config = Self::load_config(self.config, self.metrics_addr).await?; self::doctor::run(command, &config).await diff --git a/iroh-cli/src/commands/node.rs b/iroh-cli/src/commands/net.rs similarity index 81% rename from iroh-cli/src/commands/node.rs rename to iroh-cli/src/commands/net.rs index 74cd6af80d..ffb4c367ce 100644 --- a/iroh-cli/src/commands/node.rs +++ b/iroh-cli/src/commands/net.rs @@ -15,24 +15,11 @@ use iroh::net::{NodeAddr, NodeId}; #[derive(Subcommand, Debug, Clone)] #[allow(clippy::large_enum_variant)] -pub enum NodeCommands { +pub enum NetCommands { /// Get information about the different remote nodes. RemoteList, /// Get information about a particular remote node. Remote { node_id: NodeId }, - /// Get status of the running node. - Status, - /// Get statistics and metrics from the running node. - Stats, - /// Shutdown the running node. - Shutdown { - /// Shutdown mode. - /// - /// Hard shutdown will immediately terminate the process, soft shutdown will wait - /// for all connections to close. - #[clap(long, default_value_t = false)] - force: bool, - }, /// Get the node addr of this node. NodeAddr, /// Add this node addr to the known nodes. @@ -45,11 +32,11 @@ pub enum NodeCommands { HomeRelay, } -impl NodeCommands { +impl NetCommands { pub async fn run(self, iroh: &Iroh) -> Result<()> { match self { Self::RemoteList => { - let connections = iroh.remote_info_iter().await?; + let connections = iroh.net().remote_info_iter().await?; let timestamp = time::OffsetDateTime::now_utc() .format(&time::format_description::well_known::Rfc2822) .unwrap_or_else(|_| String::from("failed to get current time")); @@ -62,35 +49,14 @@ impl NodeCommands { ); } Self::Remote { node_id } => { - let info = iroh.remote_info(node_id).await?; + let info = iroh.net().remote_info(node_id).await?; match info { Some(info) => println!("{}", fmt_info(info)), None => println!("Not Found"), } } - Self::Shutdown { force } => { - iroh.shutdown(force).await?; - } - Self::Stats => { - let stats = iroh.stats().await?; - for (name, details) in stats.iter() { - println!( - "{:23} : {:>6} ({})", - name, details.value, details.description - ); - } - } - Self::Status => { - let response = iroh.status().await?; - println!("Listening addresses: {:#?}", response.listen_addrs); - println!("Node ID: {}", response.addr.node_id); - println!("Version: {}", response.version); - if let Some(addr) = response.rpc_addr { - println!("RPC Addr: {}", addr); - } - } Self::NodeAddr => { - let addr = iroh.node_addr().await?; + let addr = iroh.net().node_addr().await?; println!("Node ID: {}", addr.node_id); let relay = addr .info @@ -112,10 +78,10 @@ impl NodeCommands { if let Some(relay) = relay { addr = addr.with_relay_url(relay); } - iroh.add_node_addr(addr).await?; + iroh.net().add_node_addr(addr).await?; } Self::HomeRelay => { - let relay = iroh.home_relay().await?; + let relay = iroh.net().home_relay().await?; let relay = relay .map(|s| s.to_string()) .unwrap_or_else(|| "Not Available".to_string()); diff --git a/iroh-cli/src/commands/rpc.rs b/iroh-cli/src/commands/rpc.rs index da3594ad68..9ec3be570a 100644 --- a/iroh-cli/src/commands/rpc.rs +++ b/iroh-cli/src/commands/rpc.rs @@ -6,7 +6,7 @@ use crate::config::ConsoleEnv; use super::{ authors::AuthorCommands, blobs::BlobCommands, docs::DocCommands, gossip::GossipCommands, - node::NodeCommands, tags::TagCommands, + net::NetCommands, tags::TagCommands, }; #[derive(Subcommand, Debug, Clone)] @@ -42,10 +42,10 @@ pub enum RpcCommands { #[clap(subcommand)] command: BlobCommands, }, - /// Manage a running iroh node - Node { + /// Manage the iroh network + Net { #[clap(subcommand)] - command: NodeCommands, + command: NetCommands, }, /// Manage gossip /// @@ -71,17 +71,55 @@ pub enum RpcCommands { #[clap(subcommand)] command: TagCommands, }, + + /// Get statistics and metrics from the running node. + Stats, + /// Get status of the running node. + Status, + /// Shutdown the running node. + Shutdown { + /// Shutdown mode. + /// + /// Hard shutdown will immediately terminate the process, soft shutdown will wait + /// for all connections to close. + #[clap(long, default_value_t = false)] + force: bool, + }, } impl RpcCommands { pub async fn run(self, iroh: &Iroh, env: &ConsoleEnv) -> Result<()> { match self { - Self::Node { command } => command.run(iroh).await, + Self::Net { command } => command.run(iroh).await, Self::Blobs { command } => command.run(iroh).await, Self::Docs { command } => command.run(iroh, env).await, Self::Authors { command } => command.run(iroh, env).await, Self::Tags { command } => command.run(iroh).await, Self::Gossip { command } => command.run(iroh).await, + Self::Stats => { + let stats = iroh.stats().await?; + for (name, details) in stats.iter() { + println!( + "{:23} : {:>6} ({})", + name, details.value, details.description + ); + } + Ok(()) + } + Self::Shutdown { force } => { + iroh.shutdown(force).await?; + Ok(()) + } + Self::Status => { + let response = iroh.status().await?; + println!("Listening addresses: {:#?}", response.listen_addrs); + println!("Node ID: {}", response.addr.node_id); + println!("Version: {}", response.version); + if let Some(addr) = response.rpc_addr { + println!("RPC Addr: {}", addr); + } + Ok(()) + } } } } diff --git a/iroh-cli/tests/cli.rs b/iroh-cli/tests/cli.rs index 22e0822007..88cc7a232c 100644 --- a/iroh-cli/tests/cli.rs +++ b/iroh-cli/tests/cli.rs @@ -501,6 +501,7 @@ fn cli_provide_addresses() -> Result<()> { } #[test] +#[ignore = "flaky"] fn cli_rpc_lock_restart() -> Result<()> { let dir = testdir!(); let iroh_data_dir = dir.join("data-dir"); diff --git a/iroh/examples/collection-fetch.rs b/iroh/examples/collection-fetch.rs index 5ddaec3d29..98712a07f6 100644 --- a/iroh/examples/collection-fetch.rs +++ b/iroh/examples/collection-fetch.rs @@ -39,7 +39,7 @@ async fn main() -> Result<()> { println!("fetching hash: {}", ticket.hash()); println!("node id: {}", node.node_id()); println!("node listening addresses:"); - let addrs = node.node_addr().await?; + let addrs = node.net().node_addr().await?; for addr in addrs.direct_addresses() { println!("\t{:?}", addr); } diff --git a/iroh/examples/hello-world-fetch.rs b/iroh/examples/hello-world-fetch.rs index 49b4e5837f..06a62bbf23 100644 --- a/iroh/examples/hello-world-fetch.rs +++ b/iroh/examples/hello-world-fetch.rs @@ -39,7 +39,7 @@ async fn main() -> Result<()> { println!("fetching hash: {}", ticket.hash()); println!("node id: {}", node.node_id()); println!("node listening addresses:"); - let addrs = node.node_addr().await?; + let addrs = node.net().node_addr().await?; for addr in addrs.direct_addresses() { println!("\t{:?}", addr); } diff --git a/iroh/examples/rpc.rs b/iroh/examples/rpc.rs index a350e6780d..29e5a4773d 100644 --- a/iroh/examples/rpc.rs +++ b/iroh/examples/rpc.rs @@ -4,8 +4,8 @@ //! $ cargo run --features=examples --example rpc //! Then in another terminal, run any of the normal iroh CLI commands, which you can run from //! cargo as well: -//! $ cargo run node stats -//! The `node stats` command will reach out over RPC to the node constructed in the example +//! $ cargo run net stats +//! The `net stats` command will reach out over RPC to the node constructed in the example use clap::Parser; use iroh_blobs::store::Store; diff --git a/iroh/src/client.rs b/iroh/src/client.rs index 924221a2a5..8e8d9942df 100644 --- a/iroh/src/client.rs +++ b/iroh/src/client.rs @@ -2,17 +2,20 @@ //! //! See the documentation for [`Iroh`] for more information. +use std::collections::BTreeMap; + +use anyhow::Result; use futures_lite::{Stream, StreamExt}; use ref_cast::RefCast; -use std::ops::Deref; +use crate::rpc_protocol::node::{CounterStats, ShutdownRequest, StatsRequest, StatusRequest}; #[doc(inline)] pub use crate::rpc_protocol::RpcService; mod quic; pub use self::docs::Doc; -pub use self::node::NodeStatus; +pub use self::net::NodeStatus; pub(crate) use self::quic::{connect_raw as quic_connect_raw, RPC_ALPN}; @@ -20,7 +23,7 @@ pub mod authors; pub mod blobs; pub mod docs; pub mod gossip; -pub mod node; +pub mod net; pub mod tags; /// Iroh rpc connection - boxed so that we can have a concrete type. @@ -48,14 +51,6 @@ pub struct Iroh { rpc: RpcClient, } -impl Deref for Iroh { - type Target = node::Client; - - fn deref(&self) -> &Self::Target { - self.node() - } -} - impl Iroh { /// Creates a new high-level client to a Iroh node from the low-level RPC client. /// @@ -92,15 +87,36 @@ impl Iroh { gossip::Client::ref_cast(&self.rpc) } - /// Returns the node client. - pub fn node(&self) -> &node::Client { - node::Client::ref_cast(&self.rpc) + /// Returns the net client. + pub fn net(&self) -> &net::Client { + net::Client::ref_cast(&self.rpc) + } + + /// Shuts down the node. + /// + /// If `force` is true, the node will be shut down instantly without + /// waiting for things to stop gracefully. + pub async fn shutdown(&self, force: bool) -> Result<()> { + self.rpc.rpc(ShutdownRequest { force }).await?; + Ok(()) + } + + /// Fetches statistics of the running node. + pub async fn stats(&self) -> Result> { + let res = self.rpc.rpc(StatsRequest {}).await??; + Ok(res.stats) + } + + /// Fetches status information about this node. + pub async fn status(&self) -> Result { + let response = self.rpc.rpc(StatusRequest).await??; + Ok(response) } } fn flatten( s: impl Stream, E2>>, -) -> impl Stream> +) -> impl Stream> where E1: std::error::Error + Send + Sync + 'static, E2: std::error::Error + Send + Sync + 'static, diff --git a/iroh/src/client/blobs.rs b/iroh/src/client/blobs.rs index 1b12df08b3..d30518a7ed 100644 --- a/iroh/src/client/blobs.rs +++ b/iroh/src/client/blobs.rs @@ -1321,7 +1321,7 @@ mod tests { let import_outcome = node1.blobs().add_bytes(&b"hello world"[..]).await?; // Download in node2 - let node1_addr = node1.node_addr().await?; + let node1_addr = node1.net().node_addr().await?; let res = node2 .blobs() .download(import_outcome.hash, node1_addr) diff --git a/iroh/src/client/node.rs b/iroh/src/client/net.rs similarity index 57% rename from iroh/src/client/node.rs rename to iroh/src/client/net.rs index 6bdf052233..c3864f4962 100644 --- a/iroh/src/client/node.rs +++ b/iroh/src/client/net.rs @@ -1,20 +1,15 @@ -//! API to manage the iroh node itself. +//! API to manage the iroh networking stack. //! //! The main entry point is the [`Client`]. //! -//! You obtain a [`Client`] via [`Iroh::node()`](crate::client::Iroh::node), -//! or just use [`Iroh`](crate::client::Iroh) directly, -//! as it has a `Deref` implementation for this [`Client`]. +//! You obtain a [`Client`] via [`Iroh::net()`](crate::client::Iroh::net). //! //! The client can be used to get information about the node, such as the -//! [status](Client::status), [node id](Client::node_id) or -//! [node address](Client::node_addr). +//! [node id](Client::node_id) or [node address](Client::node_addr). //! //! It can also be used to provide additional information to the node, e.g. //! using the [add_node_addr](Client::add_node_addr) method. -//! -//! It provides a way to [shutdown](Client::shutdown) the entire node. -use std::{collections::BTreeMap, net::SocketAddr}; +use std::net::SocketAddr; use anyhow::Result; use futures_lite::{Stream, StreamExt}; @@ -22,17 +17,17 @@ use iroh_net::{endpoint::RemoteInfo, relay::RelayUrl, NodeAddr, NodeId}; use ref_cast::RefCast; use serde::{Deserialize, Serialize}; -use crate::rpc_protocol::node::{ - AddAddrRequest, AddrRequest, CounterStats, IdRequest, RelayRequest, RemoteInfoRequest, - RemoteInfoResponse, RemoteInfosIterRequest, ShutdownRequest, StatsRequest, StatusRequest, +use crate::rpc_protocol::net::{ + AddAddrRequest, AddrRequest, IdRequest, RelayRequest, RemoteInfoRequest, RemoteInfoResponse, + RemoteInfosIterRequest, }; use super::{flatten, RpcClient}; -/// Iroh node Client. +/// Iroh netx Client. /// -/// Cheaply clonable and threadsafe. Use the iroh `node::Client` to access the -/// iroh node methods from a different thread, process, or remote machine. +/// Cheaply clonable and threadsafe. Use the iroh `net::Client` to access the +/// iroh net methods from a different thread, process, or remote machine. /// The [`Iroh`](crate::client::Iroh) client dereferences to a `node::Client`, /// so you have access to this api from the [`Iroh`](crate::client::Iroh) client itself. /// @@ -40,9 +35,7 @@ use super::{flatten, RpcClient}; /// its status, and connection status to other nodes. It also allows you to /// provide address information about *other* nodes to your node. /// -/// Obtain an iroh `node::Client` via [`Iroh::node()`](crate::client::Iroh::node). -/// -/// It also provides a way to [shutdown](Client::shutdown) the entire iroh node. +/// Obtain an iroh `node::Client` via [`Iroh::net()`](crate::client::Iroh::net). /// /// # Examples /// ``` @@ -54,44 +47,7 @@ use super::{flatten, RpcClient}; /// // Create an iroh node: /// let iroh = iroh::node::Node::memory().spawn().await?; /// // Create a node client, a client that gives you access to `node` subsystem -/// let node_client = iroh.client().node(); -/// // Get the node status, including its node id, addresses, the version of iroh -/// // it is running, and more. -/// let status = node_client.status().await?; -/// println!("Node status: {status:?}"); -/// // Provide your node an address for another node -/// let relay_url = RelayUrl::from(Url::parse("https://example.com").unwrap()); -/// let addr = NodeAddr::from_parts( -/// // the node_id -/// NodeId::from_str("ae58ff8833241ac82d6ff7611046ed67b5072d142c588d0063e942d9a75502b6").unwrap(), -/// // the home relay -/// Some(relay_url), -/// // the direct addresses -/// vec!["120.0.0.1:0".parse().unwrap()], -/// ); -/// node_client.add_node_addr(addr).await?; -/// // Shut down the node. Passing `true` will force the shutdown, passing in -/// // `false` will allow the node to shut down gracefully. -/// node_client.shutdown(false).await?; -/// # Ok(()) -/// # } -/// ``` -/// You can also use the `node::Client` methods from the `Iroh` client: -/// -/// ``` -/// use std::str::FromStr; -/// use iroh_base::{key::NodeId, node_addr::{RelayUrl, NodeAddr}}; -/// use url::Url; -/// -/// # async fn run() -> anyhow::Result<()> { -/// // Create an iroh node: -/// let iroh = iroh::node::Node::memory().spawn().await?; -/// // Create a client: -/// let client = iroh.client(); -/// // Get the node status, including its node id, addresses, the version of iroh -/// // it is running, and more. -/// let status = client.status().await?; -/// println!("Node status: {status:?}"); +/// let net_client = iroh.client().net(); /// // Provide your node an address for another node /// let relay_url = RelayUrl::from(Url::parse("https://example.com").unwrap()); /// let addr = NodeAddr::from_parts( @@ -102,10 +58,10 @@ use super::{flatten, RpcClient}; /// // the direct addresses /// vec!["120.0.0.1:0".parse().unwrap()], /// ); -/// client.add_node_addr(addr).await?; +/// net_client.add_node_addr(addr).await?; /// // Shut down the node. Passing `true` will force the shutdown, passing in /// // `false` will allow the node to shut down gracefully. -/// client.shutdown(false).await?; +/// iroh.client().shutdown(false).await?; /// # Ok(()) /// # } /// ``` @@ -116,12 +72,6 @@ pub struct Client { } impl Client { - /// Fetches statistics of the running node. - pub async fn stats(&self) -> Result> { - let res = self.rpc.rpc(StatsRequest {}).await??; - Ok(res.stats) - } - /// Fetches information about currently known remote nodes. /// /// This streams a *current snapshot*. It does not keep the stream open after finishing @@ -141,12 +91,6 @@ impl Client { Ok(info) } - /// Fetches status information about this node. - pub async fn status(&self) -> Result { - let response = self.rpc.rpc(StatusRequest).await??; - Ok(response) - } - /// Fetches the node id of this node. /// /// See also [`Endpoint::node_id`](crate::net::Endpoint::node_id). @@ -178,15 +122,6 @@ impl Client { let relay = self.rpc.rpc(RelayRequest).await??; Ok(relay) } - - /// Shuts down the node. - /// - /// If `force` is true, the node will be shut down instantly without - /// waiting for things to stop gracefully. - pub async fn shutdown(&self, force: bool) -> Result<()> { - self.rpc.rpc(ShutdownRequest { force }).await?; - Ok(()) - } } /// The response to a version request diff --git a/iroh/src/lib.rs b/iroh/src/lib.rs index 59b5ce215c..72957bc66b 100644 --- a/iroh/src/lib.rs +++ b/iroh/src/lib.rs @@ -43,8 +43,8 @@ //! ## Subsystems //! //! The client provides access to various subsystems: -//! - [node](crate::client::node): -//! information and control of the iroh node itself +//! - [net](crate::client::net): +//! information and control of the iroh network //! - [blobs](crate::client::blobs): //! manage and share content-addressed blobs of data //! - [tags](crate::client::tags): diff --git a/iroh/src/node/rpc.rs b/iroh/src/node/rpc.rs index 7cbbecfded..4baf5c9d39 100644 --- a/iroh/src/node/rpc.rs +++ b/iroh/src/node/rpc.rs @@ -62,12 +62,13 @@ use crate::rpc_protocol::{ ExportFileRequest, ExportFileResponse, ImportFileRequest, ImportFileResponse, SetHashRequest, }, - gossip, node, - node::{ + gossip, net, + net::{ AddAddrRequest, AddrRequest, IdRequest, NodeWatchRequest, RelayRequest, RemoteInfoRequest, - RemoteInfoResponse, RemoteInfosIterRequest, RemoteInfosIterResponse, ShutdownRequest, - StatsRequest, StatsResponse, StatusRequest, WatchResponse, + RemoteInfoResponse, RemoteInfosIterRequest, RemoteInfosIterResponse, WatchResponse, }, + node, + node::{ShutdownRequest, StatsRequest, StatsResponse, StatusRequest}, tags, tags::{DeleteRequest as TagDeleteRequest, ListRequest as ListTagsRequest}, Request, RpcService, @@ -152,13 +153,24 @@ impl Handler { use node::Request::*; debug!("handling node request: {msg}"); match msg { - Watch(msg) => chan.server_streaming(msg, self, Self::node_watch).await, Status(msg) => chan.rpc(msg, self, Self::node_status).await, + Shutdown(msg) => chan.rpc(msg, self, Self::node_shutdown).await, + Stats(msg) => chan.rpc(msg, self, Self::node_stats).await, + } + } + + async fn handle_net_request( + self, + msg: net::Request, + chan: RpcChannel, + ) -> Result<(), RpcServerError> { + use net::Request::*; + debug!("handling node request: {msg}"); + match msg { + Watch(msg) => chan.server_streaming(msg, self, Self::node_watch).await, Id(msg) => chan.rpc(msg, self, Self::node_id).await, Addr(msg) => chan.rpc(msg, self, Self::node_addr).await, Relay(msg) => chan.rpc(msg, self, Self::node_relay).await, - Shutdown(msg) => chan.rpc(msg, self, Self::node_shutdown).await, - Stats(msg) => chan.rpc(msg, self, Self::node_stats).await, RemoteInfosIter(msg) => { chan.server_streaming(msg, self, Self::remote_infos_iter) .await @@ -444,6 +456,7 @@ impl Handler { use Request::*; debug!("handling rpc request: {msg}"); match msg { + Net(msg) => self.handle_net_request(msg, chan).await, Node(msg) => self.handle_node_request(msg, chan).await, Blobs(msg) => self.handle_blobs_request(msg, chan).await, Tags(msg) => self.handle_tags_request(msg, chan).await, diff --git a/iroh/src/rpc_protocol.rs b/iroh/src/rpc_protocol.rs index 59227dadca..b70e4b2e63 100644 --- a/iroh/src/rpc_protocol.rs +++ b/iroh/src/rpc_protocol.rs @@ -21,6 +21,7 @@ pub mod authors; pub mod blobs; pub mod docs; pub mod gossip; +pub mod net; pub mod node; pub mod tags; @@ -34,6 +35,7 @@ pub struct RpcService; #[nested_enum_utils::enum_conversions()] pub enum Request { Node(node::Request), + Net(net::Request), Blobs(blobs::Request), Docs(docs::Request), Tags(tags::Request), @@ -47,6 +49,7 @@ pub enum Request { #[nested_enum_utils::enum_conversions()] pub enum Response { Node(node::Response), + Net(net::Response), Blobs(blobs::Response), Tags(tags::Response), Docs(docs::Response), diff --git a/iroh/src/rpc_protocol/net.rs b/iroh/src/rpc_protocol/net.rs new file mode 100644 index 0000000000..d9cb4e1e40 --- /dev/null +++ b/iroh/src/rpc_protocol/net.rs @@ -0,0 +1,95 @@ +use iroh_base::rpc::RpcResult; +use iroh_net::{endpoint::RemoteInfo, key::PublicKey, relay::RelayUrl, NodeAddr, NodeId}; +use nested_enum_utils::enum_conversions; +use quic_rpc_derive::rpc_requests; +use serde::{Deserialize, Serialize}; + +use super::RpcService; + +#[allow(missing_docs)] +#[derive(strum::Display, Debug, Serialize, Deserialize)] +#[enum_conversions(super::Request)] +#[rpc_requests(RpcService)] +pub enum Request { + #[rpc(response = RpcResult)] + Id(IdRequest), + #[rpc(response = RpcResult)] + Addr(AddrRequest), + #[rpc(response = RpcResult<()>)] + AddAddr(AddAddrRequest), + #[rpc(response = RpcResult>)] + Relay(RelayRequest), + #[server_streaming(response = RpcResult)] + RemoteInfosIter(RemoteInfosIterRequest), + #[rpc(response = RpcResult)] + RemoteInfo(RemoteInfoRequest), + #[server_streaming(response = WatchResponse)] + Watch(NodeWatchRequest), +} + +#[allow(missing_docs)] +#[derive(strum::Display, Debug, Serialize, Deserialize)] +#[enum_conversions(super::Response)] +pub enum Response { + Id(RpcResult), + Addr(RpcResult), + Relay(RpcResult>), + RemoteInfosIter(RpcResult), + RemoteInfo(RpcResult), + Watch(WatchResponse), +} + +/// List network path information about all the remote nodes known by this node. +/// +/// There may never have been connections to these nodes, and connections may not even be +/// possible. Nodes can also become known due to discovery mechanisms +/// or be added manually. +#[derive(Debug, Serialize, Deserialize)] +pub struct RemoteInfosIterRequest; + +/// A response to a [`Request::RemoteInfosIter`]. +#[derive(Debug, Serialize, Deserialize)] +pub struct RemoteInfosIterResponse { + /// Information about a node. + pub info: RemoteInfo, +} + +/// Get information about a specific remote node. +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct RemoteInfoRequest { + /// The node identifier + pub node_id: PublicKey, +} + +/// A response to a [`Request::RemoteInfo`] request +#[derive(Debug, Serialize, Deserialize)] +pub struct RemoteInfoResponse { + /// Information about a node + pub info: Option, +} + +/// A request to get information the identity of the node. +#[derive(Serialize, Deserialize, Debug)] +pub struct IdRequest; + +#[derive(Serialize, Deserialize, Debug)] +pub struct AddrRequest; + +#[derive(Serialize, Deserialize, Debug)] +pub struct AddAddrRequest { + pub addr: NodeAddr, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct RelayRequest; + +/// A request to watch for the node status +#[derive(Serialize, Deserialize, Debug)] +pub struct NodeWatchRequest; + +/// The response to a watch request +#[derive(Serialize, Deserialize, Debug)] +pub struct WatchResponse { + /// The version of the node + pub version: String, +} diff --git a/iroh/src/rpc_protocol/node.rs b/iroh/src/rpc_protocol/node.rs index cfd6d44233..1f82403fb7 100644 --- a/iroh/src/rpc_protocol/node.rs +++ b/iroh/src/rpc_protocol/node.rs @@ -1,7 +1,6 @@ use std::collections::BTreeMap; use iroh_base::rpc::RpcResult; -use iroh_net::{endpoint::RemoteInfo, key::PublicKey, relay::RelayUrl, NodeAddr, NodeId}; use nested_enum_utils::enum_conversions; use quic_rpc_derive::rpc_requests; use serde::{Deserialize, Serialize}; @@ -17,24 +16,10 @@ use super::RpcService; pub enum Request { #[rpc(response = RpcResult)] Status(StatusRequest), - #[rpc(response = RpcResult)] - Id(IdRequest), - #[rpc(response = RpcResult)] - Addr(AddrRequest), - #[rpc(response = RpcResult<()>)] - AddAddr(AddAddrRequest), - #[rpc(response = RpcResult>)] - Relay(RelayRequest), #[rpc(response = RpcResult)] Stats(StatsRequest), #[rpc(response = ())] Shutdown(ShutdownRequest), - #[server_streaming(response = RpcResult)] - RemoteInfosIter(RemoteInfosIterRequest), - #[rpc(response = RpcResult)] - RemoteInfo(RemoteInfoRequest), - #[server_streaming(response = WatchResponse)] - Watch(NodeWatchRequest), } #[allow(missing_docs)] @@ -42,43 +27,8 @@ pub enum Request { #[enum_conversions(super::Response)] pub enum Response { Status(RpcResult), - Id(RpcResult), - Addr(RpcResult), - Relay(RpcResult>), Stats(RpcResult), - RemoteInfosIter(RpcResult), - RemoteInfo(RpcResult), Shutdown(()), - Watch(WatchResponse), -} - -/// List network path information about all the remote nodes known by this node. -/// -/// There may never have been connections to these nodes, and connections may not even be -/// possible. Nodes can also become known due to discovery mechanisms -/// or be added manually. -#[derive(Debug, Serialize, Deserialize)] -pub struct RemoteInfosIterRequest; - -/// A response to a [`Request::RemoteInfosIter`]. -#[derive(Debug, Serialize, Deserialize)] -pub struct RemoteInfosIterResponse { - /// Information about a node. - pub info: RemoteInfo, -} - -/// Get information about a specific remote node. -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct RemoteInfoRequest { - /// The node identifier - pub node_id: PublicKey, -} - -/// A response to a [`Request::RemoteInfo`] request -#[derive(Debug, Serialize, Deserialize)] -pub struct RemoteInfoResponse { - /// Information about a node - pub info: Option, } /// A request to shutdown the node @@ -92,39 +42,6 @@ pub struct ShutdownRequest { #[derive(Serialize, Deserialize, Debug)] pub struct StatusRequest; -/// A request to get information the identity of the node. -#[derive(Serialize, Deserialize, Debug)] -pub struct IdRequest; - -#[derive(Serialize, Deserialize, Debug)] -pub struct AddrRequest; - -#[derive(Serialize, Deserialize, Debug)] -pub struct AddAddrRequest { - pub addr: NodeAddr, -} - -#[derive(Serialize, Deserialize, Debug)] -pub struct RelayRequest; - -/// A request to watch for the node status -#[derive(Serialize, Deserialize, Debug)] -pub struct NodeWatchRequest; - -/// The response to a watch request -#[derive(Serialize, Deserialize, Debug)] -pub struct WatchResponse { - /// The version of the node - pub version: String, -} - -/// The response to a version request -#[derive(Serialize, Deserialize, Debug)] -pub struct VersionResponse { - /// The version of the node - pub version: String, -} - /// Get stats for the running Iroh node #[derive(Serialize, Deserialize, Debug)] pub struct StatsRequest {} diff --git a/iroh/tests/client.rs b/iroh/tests/client.rs index a22ce04eec..a250e5836e 100644 --- a/iroh/tests/client.rs +++ b/iroh/tests/client.rs @@ -25,7 +25,7 @@ async fn spawn_node() -> (NodeAddr, Iroh) { .node_discovery(iroh::node::DiscoveryConfig::None) .spawn() .await?; - let addr = node.node_addr().await?; + let addr = node.net().node_addr().await?; sender.send((addr, node.client().clone())).unwrap(); node.cancel_token().cancelled().await; anyhow::Ok(()) @@ -68,8 +68,8 @@ async fn gossip_smoke() -> TestResult { let (addr2, node2) = spawn_node().await; let gossip1 = node1.gossip(); let gossip2 = node2.gossip(); - node1.add_node_addr(addr2.clone()).await?; - node2.add_node_addr(addr1.clone()).await?; + node1.net().add_node_addr(addr2.clone()).await?; + node2.net().add_node_addr(addr1.clone()).await?; let topic = TopicId::from([0u8; 32]); let (mut sink1, mut stream1) = gossip1.subscribe(topic, [addr2.node_id]).await?; @@ -94,8 +94,8 @@ async fn gossip_drop_sink() -> TestResult { let (addr2, node2) = spawn_node().await; let gossip1 = node1.gossip(); let gossip2 = node2.gossip(); - node1.add_node_addr(addr2.clone()).await?; - node2.add_node_addr(addr1.clone()).await?; + node1.net().add_node_addr(addr2.clone()).await?; + node2.net().add_node_addr(addr1.clone()).await?; let topic = TopicId::from([0u8; 32]);