use std::net::SocketAddr;
use clap::Parser;
use iroh::{Endpoint, NodeAddr, RelayMode, RelayUrl, SecretKey};
use n0_snafu::{Result, ResultExt};
use n0_watcher::Watcher as _;
use tracing::info;
const EXAMPLE_ALPN: &[u8] = b"n0/iroh/examples/magic/0";
#[derive(Debug, Parser)]
struct Cli {
#[clap(long)]
node_id: iroh::NodeId,
#[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 example!\n");
let args = Cli::parse();
let secret_key = SecretKey::generate(rand::rngs::OsRng);
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?;
let me = endpoint.node_id();
println!("node id: {me}");
println!("node listening addresses:");
for local_endpoint in endpoint.direct_addresses().initialized().await {
println!("\t{}", local_endpoint.addr)
}
let relay_url = endpoint
.home_relay()
.get()
.first()
.cloned()
.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");
println!("node relay server url: {relay_url}\n");
let addr = NodeAddr::from_parts(args.node_id, Some(args.relay_url), args.addrs);
let conn = endpoint.connect(addr, EXAMPLE_ALPN).await?;
info!("connected");
let (mut send, mut recv) = conn.open_bi().await.e()?;
let message = format!("{me} is saying 'hello!'");
send.write_all(message.as_bytes()).await.e()?;
send.finish().e()?;
let message = recv.read_to_end(100).await.e()?;
let message = String::from_utf8(message).e()?;
println!("received: {message}");
endpoint.close().await;
Ok(())
}