Skip to content

Commit

Permalink
Merge pull request #824 from andrewdavidmackenzie/iroh_crate
Browse files Browse the repository at this point in the history
Switch to iroh crate
  • Loading branch information
andrewdavidmackenzie authored Jan 27, 2025
2 parents dbcb340 + 375b866 commit 7f86d8c
Show file tree
Hide file tree
Showing 11 changed files with 506 additions and 722 deletions.
1,066 changes: 463 additions & 603 deletions Cargo.lock

Large diffs are not rendered by default.

5 changes: 2 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,14 @@ path = "src/piglet.rs"

[features]
default = ["iroh", "tcp", "usb", "discovery"]
iroh = ["iroh-net"]
tcp = ["portpicker", "local-ip-address"]
discovery = ["iroh-net/discovery-local-network", "mdns-sd"]
discovery = ["iroh/discovery-local-network", "mdns-sd"]
no_std = []
usb = ["nusb"]

[dependencies]
# Optional Dependencies
iroh-net = { version = "0.28.2", default-features = false, optional = true }
iroh = { version = "0.31", default-features = false, optional = true }
portpicker = { version = "0.1.1", default-features = false, optional = true }
local-ip-address = { version = "0.6.3", default-features = false, optional = true }
nusb = { version = "0.1.12", default-features = false, optional = true }
Expand Down
25 changes: 7 additions & 18 deletions src/device_net/iroh_device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,9 @@ use crate::hw_definition::{pin_function::PinFunction, BCMPinNumber, PinLevel};
use crate::net::PIGLET_ALPN;
use crate::persistence;
use anyhow::{anyhow, bail, Context};
use futures::StreamExt;
use iroh::endpoint::Connection;
use iroh::{Endpoint, NodeId, RelayMode, RelayUrl, SecretKey};
#[cfg(feature = "discovery")]
use iroh_net::discovery::local_swarm_discovery::LocalSwarmDiscovery;
use iroh_net::endpoint::Connection;
use iroh_net::key::SecretKey;
use iroh_net::relay::{RelayMode, RelayUrl};
use iroh_net::{Endpoint, NodeId};
use log::{debug, info, trace};
use std::fmt;
use std::fmt::{Display, Formatter};
Expand All @@ -38,9 +34,8 @@ impl Display for IrohDevice {
}

pub async fn get_device() -> anyhow::Result<IrohDevice> {
let secret_key = SecretKey::generate();
#[cfg(feature = "discovery")]
let id = secret_key.public();
let rng = rand::rngs::OsRng;
let secret_key = SecretKey::generate(rng);

// Build a `Endpoint`, which uses PublicKeys as node identifiers, uses QUIC for directly
// connecting to other nodes, and uses the relay protocol and relay servers to holepunch direct
Expand All @@ -61,18 +56,14 @@ pub async fn get_device() -> anyhow::Result<IrohDevice> {
// you must pass in the same custom relay url to both the `listen` code AND the `connect` code
.relay_mode(RelayMode::Default);

#[cfg(feature = "discovery")]
{
builder = builder.discovery(Box::new(LocalSwarmDiscovery::new(id)?));
}
let endpoint = builder.bind().await?;

let nodeid = endpoint.node_id();
println!("nodeid: {nodeid}"); // Don't remove - required by integration tests

let local_addrs = endpoint
.direct_addresses()
.next()
.initialized()
.await
.context("no endpoints")?
.into_iter()
Expand All @@ -81,9 +72,7 @@ pub async fn get_device() -> anyhow::Result<IrohDevice> {
.join(" ");
info!("local Addresses: {local_addrs}");

let relay_url = endpoint
.home_relay()
.expect("should be connected to a relay server, try calling `endpoint.local_endpoints()` or `endpoint.connect()` first, to ensure the endpoint has actually attempted a connection before checking for the connected relay server");
let relay_url = endpoint.home_relay().initialized().await?;
println!("Relay URL: {relay_url}"); // Don't remove - required by integration tests

Ok(IrohDevice {
Expand All @@ -102,7 +91,7 @@ pub async fn accept_connection(
debug!("Waiting for connection");
if let Some(connecting) = endpoint.accept().await {
let connection = connecting.await?;
let node_id = iroh_net::endpoint::get_remote_node_id(&connection)?;
let node_id = iroh::endpoint::get_remote_node_id(&connection)?;
debug!("New connection from nodeid: '{node_id}'",);
trace!("Sending hardware description");
let mut gui_sender = connection.open_uni().await?;
Expand Down
4 changes: 1 addition & 3 deletions src/discovery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ use futures::SinkExt;
#[cfg(any(feature = "usb", feature = "tcp"))]
use iced_futures::stream;
#[cfg(all(feature = "iroh", feature = "tcp"))]
use iroh_net::relay::RelayUrl;
#[cfg(all(feature = "iroh", feature = "tcp"))]
use iroh_net::NodeId;
use iroh::{NodeId, RelayUrl};
#[cfg(feature = "tcp")]
use mdns_sd::{ServiceDaemon, ServiceEvent};
use std::collections::HashMap;
Expand Down
2 changes: 1 addition & 1 deletion src/hardware_subscription.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ enum HWState {
ConnectedUsb(UsbConnection),
#[cfg(feature = "iroh")]
/// The subscription is ready and will listen for config events on the channel contained
ConnectedIroh(iroh_net::endpoint::Connection),
ConnectedIroh(iroh::endpoint::Connection),
#[cfg(feature = "tcp")]
/// The subscription is ready and will listen for config events on the channel contained
ConnectedTcp(async_std::net::TcpStream),
Expand Down
92 changes: 14 additions & 78 deletions src/host_net/iroh_host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,12 @@ use crate::hw_definition::config::HardwareConfigMessage::Disconnect;
use crate::hw_definition::config::{HardwareConfig, HardwareConfigMessage};
use crate::hw_definition::description::HardwareDescription;
use crate::net::PIGLET_ALPN;
use anyhow::ensure;
use anyhow::Context;
use iced::futures::StreamExt;
use iroh_net::{
use anyhow::{ensure, Context};
use iroh::{
endpoint::Connection,
key::SecretKey,
relay::{RelayMode, RelayUrl},
{Endpoint, NodeAddr, NodeId},
RelayMode, RelayUrl, SecretKey, {Endpoint, NodeAddr, NodeId},
};
use log::info;
use std::io;

/// Wait until we receive a message from remote hardware
Expand Down Expand Up @@ -48,7 +45,8 @@ pub async fn connect(
nodeid: &NodeId,
relay: Option<RelayUrl>,
) -> anyhow::Result<(HardwareDescription, HardwareConfig, Connection)> {
let secret_key = SecretKey::generate();
let rng = rand::rngs::OsRng;
let secret_key = SecretKey::generate(rng);

// Build a `Endpoint`, which uses PublicKeys as node identifiers
let endpoint = Endpoint::builder()
Expand All @@ -61,19 +59,20 @@ pub async fn connect(
.bind()
.await?;

for _local_endpoint in endpoint
let local_addrs = endpoint
.direct_addresses()
.next()
.initialized()
.await
.context("no endpoints")?
{}
.into_iter()
.map(|endpoint| endpoint.addr.to_string())
.collect::<Vec<_>>()
.join(" ");
info!("local Addresses: {local_addrs}");

// find my closest relay - maybe set this as a default in the UI but allow used to
// override it in a text entry box. Leave black for user if fails to fetch it.
let relay_url = relay.unwrap_or(endpoint.home_relay().ok_or(io::Error::new(
io::ErrorKind::Other,
"Could not get home relay",
))?);
let relay_url = relay.unwrap_or(endpoint.home_relay().initialized().await?);

// Build a `NodeAddr` from the node_id, relay url, and UDP addresses.
let addr = NodeAddr::from_parts(*nodeid, Some(relay_url), vec![]);
Expand All @@ -93,66 +92,3 @@ pub async fn connect(
pub async fn disconnect(connection: &mut Connection) -> anyhow::Result<()> {
send_config_message(connection, &Disconnect).await
}

/*
#[cfg(feature = "discovery")]
use crate::discovery::DiscoveredDevice;
#[cfg(feature = "discovery")]
use crate::discovery::DiscoveryMethod::IrohLocalSwarm;
#[cfg(feature = "discovery")]
use crate::hw;
#[cfg(feature = "discovery")]
use crate::views::hardware_view::HardwareConnection;
#[cfg(feature = "discovery")]
use iroh_net::discovery::local_swarm_discovery::LocalSwarmDiscovery;
#[cfg(feature = "discovery")]
use std::collections::HashMap;
use std::collections::HashSet;
#[cfg(feature = "discovery")]
/// Create an iroh-net [Endpoint] for use in discovery
pub async fn iroh_endpoint() -> anyhow::Result<Endpoint> {
let key = SecretKey::generate();
let id = key.public();
Endpoint::builder()
.secret_key(key)
.discovery(Box::new(LocalSwarmDiscovery::new(id)?))
.bind()
.await
}
#[cfg(feature = "discovery")]
/// Try and find devices visible over iroh net
pub async fn find_piglets(endpoint: &Endpoint) -> HashMap<String, DiscoveredDevice> {
let mut map = HashMap::<String, DiscoveredDevice>::new();
// get an iterator of all the remote nodes this endpoint knows about
let remotes = endpoint.remote_info_iter();
for remote in remotes {
let trunc = remote
.node_id
.to_string()
.chars()
.take(16)
.collect::<String>();
let mut hardware_connections = HashSet::new();
hardware_connections.insert(HardwareConnection::Iroh(
remote.node_id,
remote.relay_url.map(|ri| ri.relay_url),
));
map.insert(
trunc, // TODO substitute for real serial_number when Iroh discovery supports it
DiscoveredDevice {
discovery_method: IrohLocalSwarm,
hardware_details: hw::driver::get().description().unwrap().details, // TODO show the real hardware description when Iroh discovery supports it
ssid_spec: None,
hardware_connections,
},
);
}
map
}
*/
18 changes: 8 additions & 10 deletions src/persistence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,22 +78,21 @@ pub(crate) fn write_info_file(
#[cfg(feature = "iroh")]
#[cfg(test)]
mod test {
use crate::{persistence, ListenerInfo};
use iroh::RelayUrl;
use std::fs;
use std::path::PathBuf;
use std::str::FromStr;

use crate::{persistence, ListenerInfo};
use tempfile::tempdir;

#[cfg(feature = "iroh")]
#[test]
fn write_info_file() {
let output_dir = tempdir().expect("Could not create a tempdir").into_path();
let test_file = output_dir.join("test.info");
let nodeid =
iroh_net::NodeId::from_str("rxci3kuuxljxqej7hau727aaemcjo43zvf2zefnqla4p436sqwhq")
.expect("Could not create nodeid");
let relay_url = iroh_net::relay::RelayUrl::from_str("https://euw1-1.relay.iroh.network./ ")
let nodeid = iroh::NodeId::from_str("rxci3kuuxljxqej7hau727aaemcjo43zvf2zefnqla4p436sqwhq")
.expect("Could not create nodeid");
let relay_url = RelayUrl::from_str("https://euw1-1.relay.iroh.network./ ")
.expect("Could not create Relay URL");

let info = ListenerInfo {
Expand Down Expand Up @@ -121,10 +120,9 @@ mod test {
fn write_info_file_non_existent() {
let output_dir = PathBuf::from("/foo");
let test_file = output_dir.join("test.info");
let nodeid =
iroh_net::NodeId::from_str("rxci3kuuxljxqej7hau727aaemcjo43zvf2zefnqla4p436sqwhq")
.expect("Could not create nodeid");
let relay_url = iroh_net::relay::RelayUrl::from_str("https://euw1-1.relay.iroh.network./ ")
let nodeid = iroh::NodeId::from_str("rxci3kuuxljxqej7hau727aaemcjo43zvf2zefnqla4p436sqwhq")
.expect("Could not create nodeid");
let relay_url = RelayUrl::from_str("https://euw1-1.relay.iroh.network./ ")
.expect("Could not create Relay URL");
let info = ListenerInfo {
iroh_info: crate::iroh_device::IrohDevice {
Expand Down
2 changes: 1 addition & 1 deletion src/piggui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ use crate::views::ssid_dialog::SsidDialogMessage::HideSsidDialog;
#[cfg(feature = "usb")]
use host_net::usb_host;
#[cfg(feature = "iroh")]
use iroh_net::NodeId;
use iroh::NodeId;
#[cfg(any(feature = "iroh", feature = "tcp"))]
use std::str::FromStr;

Expand Down
6 changes: 3 additions & 3 deletions src/views/connect_dialog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ use iced::keyboard::key;
use iced::widget::{self, column, container, text, text_input, Button, Row, Text};
use iced::{keyboard, Element, Event, Length, Task};
use iced_futures::Subscription;
#[cfg(feature = "iroh")]
use iroh_net::{relay::RelayUrl, NodeId};
#[cfg(any(feature = "iroh", feature = "tcp"))]
use std::str::FromStr;
use std::time::Duration;
Expand All @@ -42,6 +40,8 @@ use crate::views::dialog_styles::{
};
use iced::widget::button::Status::Hovered;
use iced::widget::horizontal_space;
#[cfg(feature = "iroh")]
use iroh::{NodeId, RelayUrl};
use std::sync::LazyLock;

#[cfg(feature = "tcp")]
Expand Down Expand Up @@ -665,7 +665,7 @@ mod tests {
#[test]
fn test_connect_button_pressed_invalid_node_id() {
let mut connect_dialog = ConnectDialog::new();
let invalid_node_id = "invalid_node_id".to_string();
let invalid_node_id = "".to_string();

let _ = connect_dialog.update(ConnectButtonPressedIroh(invalid_node_id, "".to_string()));
assert!(!connect_dialog.iroh_connection_error.is_empty());
Expand Down
2 changes: 1 addition & 1 deletion src/views/hardware_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ use iced::Color;
use iced::{Alignment, Center, Element, Length, Task};
use iced_futures::Subscription;
#[cfg(feature = "iroh")]
use iroh_net::{relay::RelayUrl, NodeId};
use iroh::{NodeId, RelayUrl};
use std::cmp::PartialEq;
use std::collections::HashMap;
use std::fmt::{Display, Formatter};
Expand Down
6 changes: 5 additions & 1 deletion tests/integration/iroh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ use serial_test::serial;
fn connect_via_iroh() {
let mut piglet = run("piglet", vec![], None);
let line = wait_for_stdout(&mut piglet, "nodeid:").expect("Could not get IP address");
let nodeid = line.split_once(":").expect("Couldn't fine ':'").1;
let nodeid = line
.split_once("nodeid:")
.expect("Couldn't find 'nodeid:'")
.1
.trim();

let mut piggui = run(
"piggui",
Expand Down

0 comments on commit 7f86d8c

Please sign in to comment.