use std::net::SocketAddr;
use clap::Parser;
use iroh::{
Endpoint, EndpointAddr, RelayMode, RelayUrl, SecretKey, TransportAddr, endpoint::presets,
};
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 example!\n");
let args = Cli::parse();
let secret_key = SecretKey::generate();
println!("public key: {}", secret_key.public());
let endpoint = Endpoint::builder(presets::N0)
.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.id();
println!("endpoint id: {me}");
println!("endpoint listening addresses:");
for addr in endpoint_addr.ip_addrs() {
println!("\t{addr}")
}
let relay_url = endpoint_addr
.relay_urls()
.next()
.expect("should be connected to a relay server");
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 (mut send, mut recv) = conn.open_bi().await.anyerr()?;
let message = format!("{me} is saying 'hello!'");
send.write_all(message.as_bytes()).await.anyerr()?;
send.finish().anyerr()?;
let message = recv.read_to_end(100).await.anyerr()?;
let message = String::from_utf8(message).anyerr()?;
println!("received: {message}");
endpoint.close().await;
Ok(())
}