use std::net::SocketAddr;
use clap::Parser;
use iroh::{Endpoint, EndpointAddr, RelayMode, RelayUrl, SecretKey};
use iroh_base::TransportAddr;
use n0_error::{Result, StdResultExt};
use tracing::info;
const EXAMPLE_ALPN: &[u8] = b"n0/iroh/examples/0";
#[derive(Debug, Parser)]
struct Cli {
#[clap(long)]
endpoint_id: iroh::EndpointId,
#[clap(long, value_parser, num_args = 1.., value_delimiter = ' ')]
addrs: Vec<SocketAddr>,
#[clap(long)]
relay_url: RelayUrl,
}
#[tokio::main]
async fn main() -> Result<()> {
tracing_subscriber::fmt::init();
println!("\nconnect (unreliable) example!\n");
let args = Cli::parse();
let secret_key = SecretKey::generate(&mut rand::rng());
println!("public key: {}", secret_key.public());
let endpoint = Endpoint::builder()
.secret_key(secret_key)
.alpns(vec![EXAMPLE_ALPN.to_vec()])
.relay_mode(RelayMode::Default)
.bind()
.await?;
endpoint.online().await;
let endpoint_addr = endpoint.addr();
let me = endpoint_addr.id;
println!("endpoint id: {me}");
println!("endpoint listening addresses:");
endpoint_addr
.ip_addrs()
.for_each(|addr| println!("\t{addr}"));
let relay_url = endpoint_addr
.relay_urls()
.next()
.expect("Should have a relay URL, assuming a default endpoint setup.");
println!("endpoint relay server url: {relay_url}\n");
let addrs = args
.addrs
.into_iter()
.map(TransportAddr::Ip)
.chain(std::iter::once(TransportAddr::Relay(args.relay_url)));
let addr = EndpointAddr::from_parts(args.endpoint_id, addrs);
let conn = endpoint.connect(addr, EXAMPLE_ALPN).await?;
info!("connected");
let message = format!("{me} is saying 'hello!'");
conn.send_datagram(message.as_bytes().to_vec().into())
.anyerr()?;
let message = conn.read_datagram().await.anyerr()?;
let message = String::from_utf8(message.into()).anyerr()?;
println!("received: {message}");
Ok(())
}