#![allow(deprecated)]
use std::time::Duration;
use anyhow::Context;
use futures_lite::StreamExt;
use iroh_net::{endpoint::ConnectionError, key::SecretKey, relay::RelayMode, Endpoint};
use tracing::{debug, info, warn};
const EXAMPLE_ALPN: &[u8] = b"n0/iroh/examples/magic/0";
#[tokio::main]
async fn main() -> anyhow::Result<()> {
tracing_subscriber::fmt::init();
println!("\nlisten example!\n");
let secret_key = SecretKey::generate();
println!("secret key: {secret_key}");
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:");
let local_addrs = endpoint
.direct_addresses()
.next()
.await
.context("no endpoints")?
.into_iter()
.map(|endpoint| {
let addr = endpoint.addr.to_string();
println!("\t{addr}");
addr
})
.collect::<Vec<_>>()
.join(" ");
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");
println!("node relay server url: {relay_url}");
println!("\nin a separate terminal run:");
println!(
"\tcargo run --example connect -- --node-id {me} --addrs \"{local_addrs}\" --relay-url {relay_url}\n"
);
while let Some(incoming) = endpoint.accept().await {
let mut connecting = match incoming.accept() {
Ok(connecting) => connecting,
Err(err) => {
warn!("incoming connection failed: {err:#}");
continue;
}
};
let alpn = connecting.alpn().await?;
let conn = connecting.await?;
let node_id = iroh_net::endpoint::get_remote_node_id(&conn)?;
info!(
"new connection from {node_id} with ALPN {} (coming from {})",
String::from_utf8_lossy(&alpn),
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(100).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()?;
let res = tokio::time::timeout(Duration::from_secs(3), async move {
let closed = conn.closed().await;
if !matches!(closed, ConnectionError::ApplicationClosed(_)) {
println!("node {node_id} disconnected with an error: {closed:#}");
}
})
.await;
if res.is_err() {
println!("node {node_id} did not disconnect within 3 seconds");
}
Ok::<_, anyhow::Error>(())
});
}
Ok(())
}