Harden live Iroh integration paths

This commit is contained in:
Eric Wendland 2026-05-29 15:27:45 +02:00
commit 0fdf5d0be7
6 changed files with 256 additions and 144 deletions

View file

@ -1,6 +1,6 @@
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
use std::net::{SocketAddrV4, SocketAddrV6};
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
use std::path::{Path, PathBuf};
pub const ALPN_CONTROL: &[u8] = b"/geth/control/1";
@ -278,14 +278,41 @@ impl GethIrohEndpoint {
}
pub async fn node_addr_snapshot(&self) -> Result<GethNodeAddr, IrohError> {
let endpoint_addr = self.endpoint.addr();
let mut endpoint_addr = self.endpoint.addr();
let mut direct_addresses = endpoint_addr
.ip_addrs()
.map(|addr| addr.to_string())
.collect::<Vec<_>>();
for _ in 0..20 {
if !direct_addresses.is_empty() {
break;
}
tokio::time::sleep(std::time::Duration::from_millis(25)).await;
endpoint_addr = self.endpoint.addr();
direct_addresses = endpoint_addr
.ip_addrs()
.map(|addr| addr.to_string())
.collect::<Vec<_>>();
}
if direct_addresses.is_empty() || self.status.relay_mode == "disabled" {
direct_addresses.extend(
self.endpoint
.bound_sockets()
.into_iter()
.map(normalize_bound_socket_for_peer_card)
.map(|addr| addr.to_string()),
);
}
direct_addresses.sort_by_key(|addr| (!is_loopback_socket_addr(addr), addr.clone()));
direct_addresses.dedup();
Ok(GethNodeAddr {
endpoint_id: endpoint_addr.id.to_string(),
relay_url: endpoint_addr.relay_urls().next().map(ToString::to_string),
direct_addresses: endpoint_addr
.ip_addrs()
.map(|addr| addr.to_string())
.collect(),
direct_addresses,
})
}
@ -301,6 +328,24 @@ pub struct GethNodeAddr {
pub direct_addresses: Vec<String>,
}
fn normalize_bound_socket_for_peer_card(addr: SocketAddr) -> SocketAddr {
match addr.ip() {
IpAddr::V4(ip) if ip.is_unspecified() => {
SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), addr.port())
}
IpAddr::V6(ip) if ip.is_unspecified() => {
SocketAddr::new(IpAddr::V6(Ipv6Addr::LOCALHOST), addr.port())
}
_ => addr,
}
}
fn is_loopback_socket_addr(addr: &str) -> bool {
addr.parse::<SocketAddr>()
.map(|addr| addr.ip().is_loopback())
.unwrap_or(false)
}
pub async fn start_endpoint(config: &GethIrohConfig) -> Result<GethIrohEndpoint, IrohError> {
let secret_key = load_or_create_secret_key(&config.secret_key_path)?;
let mut builder = iroh::Endpoint::builder()