use crate::error::{Result, TransportError};
use iroh::{Endpoint, EndpointAddr, RelayMode, SecretKey};
pub(crate) const BASE_ALPN: &[u8] = b"irosh/1";
pub fn derive_alpn(secret: Option<&str>) -> Vec<u8> {
match secret {
None => BASE_ALPN.to_vec(),
Some(s) => {
use sha2::{Digest, Sha256};
let mut hasher = Sha256::new();
hasher.update(s.as_bytes());
let hash = hex::encode(&hasher.finalize()[..8]); format!("{}/{}", String::from_utf8_lossy(BASE_ALPN), hash).into_bytes()
}
}
}
#[derive(Debug, Clone)]
pub struct ServerEndpoint {
pub endpoint: Endpoint,
pub addr: EndpointAddr,
pub endpoint_id: String,
pub relay_urls: Vec<String>,
pub direct_addresses: Vec<String>,
}
pub async fn bind_server_endpoint(secret_key: SecretKey, alpn: Vec<u8>) -> Result<ServerEndpoint> {
let endpoint = Endpoint::builder(iroh::endpoint::presets::N0)
.secret_key(secret_key)
.alpns(vec![alpn.clone()])
.relay_mode(RelayMode::Default)
.bind()
.await
.map_err(|source| TransportError::EndpointBind { source })?;
endpoint.online().await;
let endpoint_addr = endpoint.addr();
let node_id = endpoint.id();
let direct_addresses = endpoint_addr
.ip_addrs()
.map(|addr| addr.to_string())
.collect::<Vec<_>>();
let relay_urls = endpoint_addr
.relay_urls()
.map(|url| url.to_string())
.collect::<Vec<_>>();
Ok(ServerEndpoint {
endpoint_id: node_id.to_string(),
endpoint,
addr: endpoint_addr,
relay_urls,
direct_addresses,
})
}
pub async fn bind_client_endpoint(secret_key: SecretKey, alpn: Vec<u8>) -> Result<Endpoint> {
let endpoint = Endpoint::builder(iroh::endpoint::presets::N0)
.secret_key(secret_key)
.alpns(vec![alpn])
.relay_mode(RelayMode::Default)
.bind()
.await
.map_err(|source| TransportError::EndpointBind { source })?;
endpoint.online().await;
Ok(endpoint)
}