Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add MagicEndpoint to iroh-net #1133

Merged
merged 29 commits into from
Jul 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
8d3009b
feat: add MagicEndpoint to iroh-net
Frando Jun 26, 2023
134b360
chore: fmt
Frando Jun 26, 2023
7cf871c
fix: address review comments
Frando Jun 26, 2023
86a06db
fix: call endpoint an endpoint
Frando Jun 26, 2023
0d88b75
chore: fmt
Frando Jun 26, 2023
df02fde
docs: magic endpoint
Frando Jun 26, 2023
f087d8d
test: magic endpoint end-to-end
Frando Jun 26, 2023
5deca05
feat: add MagicEndpoint::close and test
Frando Jun 26, 2023
57e6c37
examples(iroh-net): set derp addr from cli
Frando Jun 26, 2023
36f1978
change(net): add MagicEndpointBuilder
Frando Jun 27, 2023
203dcf9
chore: fmt
Frando Jun 27, 2023
929f65c
fix: MagicEndpoint rebase and cleanup
Frando Jun 28, 2023
d7da7cb
fix: typos
Frando Jun 28, 2023
f263e05
fix: typos
Frando Jun 28, 2023
d5b6fe9
feat: convert iroh to use the MagicEndpoint
Frando Jun 28, 2023
b0a800e
chore: clippy
Frando Jun 28, 2023
0f50598
fix: derp url in tests
Frando Jun 28, 2023
fa0fec0
change: use default derp region from iroh-net
Frando Jun 28, 2023
7b75589
fix(iroh): actually pass keypair into magic endpoint
Frando Jun 28, 2023
787b97f
tests: use magic endpoint in magicsock tests
Frando Jun 28, 2023
4d1158f
change(net): cleanups and renames
Frando Jun 29, 2023
dc88c85
chore: fmt
Frando Jun 29, 2023
bc2c44f
fix: adjust after rebase
Frando Jun 29, 2023
699374d
fix: make MagicEndpoint::add_known_addrs additive
Frando Jun 30, 2023
015c4ed
docs: improve
Frando Jun 30, 2023
0129484
chore: cleanup
Frando Jun 30, 2023
64fe3fc
chore: fmt
Frando Jun 30, 2023
f309d09
docs: improve MagicEndpoint docs
Frando Jul 3, 2023
87253d2
change(net): MagicEndpoint::bind takes port, not addr
Frando Jul 3, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions iroh-bytes/src/get.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,12 @@ pub async fn run_ticket(
keylog: bool,
derp_map: Option<DerpMap>,
) -> Result<get_response_machine::AtInitial> {
let connection = iroh_net::client::dial_peer(
ticket.addrs(),
let connection = iroh_net::MagicEndpoint::dial_peer(
ticket.peer(),
&crate::P2P_ALPN,
keylog,
ticket.addrs(),
derp_map,
keylog,
)
.await?;

Expand Down Expand Up @@ -624,12 +624,12 @@ pub async fn run(
request: AnyGetRequest,
opts: Options,
) -> anyhow::Result<get_response_machine::AtInitial> {
let connection = iroh_net::client::dial_peer(
&opts.addrs,
let connection = iroh_net::MagicEndpoint::dial_peer(
opts.peer_id,
&crate::P2P_ALPN,
opts.keylog,
&opts.addrs,
opts.derp_map,
opts.keylog,
)
.await?;
Ok(run_connection(connection, request))
Expand Down
1 change: 1 addition & 0 deletions iroh-net/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ rtnetlink = "0.12.0"
wmi = "0.13"

[dev-dependencies]
clap = { version = "4", features = ["derive"] }
tokio = { version = "1", features = ["io-util", "sync", "rt", "net", "fs", "macros", "time", "test-util"] }
tracing-subscriber = { version = "0.3", features = ["env-filter"] }

Expand Down
137 changes: 137 additions & 0 deletions iroh-net/examples/magic.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
use std::net::SocketAddr;

use clap::Parser;
use ed25519_dalek::SigningKey as SecretKey;
use iroh_net::{
defaults::default_derp_map,
hp::derp::{DerpMap, UseIpv4, UseIpv6},
magic_endpoint::accept_conn,
tls::{Keypair, PeerId},
MagicEndpoint,
};
use tracing::{debug, info};
use url::Url;

const EXAMPLE_ALPN: &[u8] = b"n0/iroh/examples/magic/0";
Frando marked this conversation as resolved.
Show resolved Hide resolved

#[derive(Debug, Parser)]
struct Cli {
#[clap(short, long)]
secret: Option<String>,
#[clap(short, long, default_value = "n0/iroh/examples/magic/0")]
alpn: String,
#[clap(short, long, default_value = "0")]
bind_port: u16,
#[clap(short, long)]
derp_url: Option<Url>,
#[clap(subcommand)]
command: Command,
}

#[derive(Debug, Parser)]
enum Command {
Listen,
Connect {
peer_id: String,
addrs: Option<Vec<SocketAddr>>,
},
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
tracing_subscriber::fmt::init();
let args = Cli::parse();
let keypair = match args.secret {
None => {
let keypair = Keypair::generate();
println!("our secret key: {}", fmt_secret(&keypair));
keypair
}
Some(key) => parse_secret(&key)?,
};

let derp_map = match args.derp_url {
None => default_derp_map(),
Some(url) => {
// TODO: This should be done by the DERP client.
let derp_port = match url.port() {
Some(port) => port,
None => match url.scheme() {
"http" => 80,
"https" => 443,
_ => anyhow::bail!(
"Invalid scheme in DERP URL, only http: and https: schemes are supported."
),
Frando marked this conversation as resolved.
Show resolved Hide resolved
},
};
DerpMap::default_from_node(url, 3478, derp_port, UseIpv4::None, UseIpv6::None)
}
};

let endpoint = MagicEndpoint::builder()
.keypair(keypair)
.alpns(vec![args.alpn.to_string().into_bytes()])
.derp_map(Some(derp_map))
.bind(args.bind_port)
.await?;

let me = endpoint.peer_id();
let local_addr = endpoint.local_addr()?;
println!("magic socket listening on {local_addr:?}");
println!("our peer id: {me}");

match args.command {
Command::Listen => {
while let Some(conn) = endpoint.accept().await {
let (peer_id, alpn, conn) = accept_conn(conn).await?;
info!(
"new connection from {peer_id} with ALPN {alpn} (coming from {})",
conn.remote_address()
);
tokio::spawn(async move {
let (mut send, mut recv) = conn.accept_bi().await?;
debug!("accepted bi stream, waiting for data...");
let message = recv.read_to_end(1000).await?;
let message = String::from_utf8(message)?;
println!("received: {message}");

let message = format!("hi! you connected to {me}. bye bye");
send.write_all(message.as_bytes()).await?;
send.finish().await?;

Ok::<_, anyhow::Error>(())
});
}
}
Command::Connect { peer_id, addrs } => {
let peer_id: PeerId = peer_id.parse()?;
let addrs = addrs.unwrap_or_default();
let conn = endpoint.connect(peer_id, EXAMPLE_ALPN, &addrs).await?;
info!("connected");

let (mut send, mut recv) = conn.open_bi().await?;

let message = format!("hello here's {me}");
send.write_all(message.as_bytes()).await?;
send.finish().await?;
let message = recv.read_to_end(100).await?;
let message = String::from_utf8(message)?;
println!("received: {message}");
}
}
Ok(())
}

fn fmt_secret(keypair: &Keypair) -> String {
let mut text = data_encoding::BASE32_NOPAD.encode(&keypair.secret().to_bytes());
text.make_ascii_lowercase();
text
}
fn parse_secret(secret: &str) -> anyhow::Result<Keypair> {
let bytes: [u8; 32] = data_encoding::BASE32_NOPAD
.decode(secret.to_ascii_uppercase().as_bytes())?
.try_into()
.map_err(|_| anyhow::anyhow!("Invalid secret"))?;
let key = SecretKey::from_bytes(&bytes);
Ok(key.into())
}
145 changes: 0 additions & 145 deletions iroh-net/src/client.rs

This file was deleted.

30 changes: 30 additions & 0 deletions iroh-net/src/defaults.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use std::collections::HashMap;

use crate::hp::derp::{DerpMap, DerpNode, DerpRegion, UseIpv4, UseIpv6};

pub fn default_derp_map() -> DerpMap {
DerpMap {
regions: HashMap::from_iter([(1, default_derp_region())].into_iter()),
}
}

pub fn default_derp_region() -> DerpRegion {
// The default derper run by number0.
let default_n0_derp = DerpNode {
name: "default-1".into(),
region_id: 1,
host_name: "https://derp.iroh.network".parse().unwrap(),
stun_only: false,
stun_port: 3478,
ipv4: UseIpv4::Some([35, 175, 99, 113].into()),
ipv6: UseIpv6::None,
derp_port: 443,
stun_test_ip: None,
};
DerpRegion {
region_id: 1,
nodes: vec![default_n0_derp],
avoid: false,
region_code: "default-1".into(),
}
}
2 changes: 1 addition & 1 deletion iroh-net/src/hp/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ pub struct PingResult {
/// A node or peer in the iroh network.
///
/// Nodes are primarily identified by their [`Node::key`].
#[derive(Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq)]
pub struct Node {
/// The public key or PeerID, the primary identifier of this node.
pub key: key::node::PublicKey,
Expand Down
2 changes: 1 addition & 1 deletion iroh-net/src/hp/hostinfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const RUST_VERSION: &str = env!("RUSTC_VERSION");
const GIT_COMMIT: &str = env!("GIT_COMMIT");

/// Contains a summary of the host we are running on.
#[derive(Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq)]
pub struct Hostinfo {
/// Version of this code.
pub version: String,
Expand Down
5 changes: 4 additions & 1 deletion iroh-net/src/hp/magicsock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ mod rebinding_conn;
mod timer;
mod udp_actor;

pub use self::conn::{Conn, Options};
pub use self::conn::{Callbacks, Conn, Options};
pub use self::endpoint::EndpointInfo;
pub use self::timer::Timer;

#[cfg(test)]
pub(crate) use conn::tests as conn_tests;
Loading