openrtc 3.0.1

OpenRTC: a Rust-first P2P runtime for device discovery, signaling, and iroh/QUIC networking.
Documentation
//! Native constructor policy reaches the existing endpoint owner.
use super::{ClientBuilder, TransportConfig};

fn builder() -> ClientBuilder {
    ClientBuilder::new_provider_neutral("udp-initializer-proof".into(), Box::new(|| None))
        .transport_config(TransportConfig {
            relay: false,
            ..Default::default()
        })
}

#[cfg(feature = "native-udp-socket-initializer")]
#[tokio::test]
async fn constructor_udp_initializer_refusal_prevents_native_publication() {
    let client = builder()
        .native_udp_socket_initializer(|_, _| {
            Err(std::io::Error::new(
                std::io::ErrorKind::PermissionDenied,
                "sdk-initializer-refusal",
            ))
        })
        .build();
    let error = client
        .init_iroh_without_internal_router(None, Vec::new())
        .await
        .unwrap_err();
    assert!(format!("{error:#}").contains("sdk-initializer-refusal"));
    assert!(
        client.iroh_endpoint.read().await.is_none(),
        "failed native policy must not publish an endpoint"
    );
    assert!(
        client.current_node_id().await.is_none(),
        "failed native policy must not publish node identity"
    );
}

#[tokio::test]
async fn constructor_socket_initializers_cannot_be_claimed_for_an_already_bound_host_endpoint() {
    let endpoint = iroh::Endpoint::builder(iroh::endpoint::presets::Minimal)
        .bind_addr("127.0.0.1:0")
        .unwrap()
        .bind()
        .await
        .unwrap();
    let mut policies = Vec::new();
    #[cfg(feature = "native-udp-socket-initializer")]
    policies.push(builder().native_udp_socket_initializer(|_, _| Ok(())));
    #[cfg(feature = "native-relay-tcp-socket-initializer")]
    policies.push(builder().native_relay_tcp_socket_initializer(|_| Ok(())));
    #[cfg(feature = "native-dns-socket-initializer")]
    policies.push(builder().native_dns_socket_initializer(|_, _| Ok(())));
    for policy in policies {
        let client = policy.build();
        let error = client
            .adopt_endpoint_with_router_mode(endpoint.clone(), false)
            .await
            .unwrap_err();
        assert!(error
            .to_string()
            .contains("requires SDK-owned endpoint construction"));
        assert!(client.iroh_endpoint.read().await.is_none());
        assert!(client.current_node_id().await.is_none());
        assert!(
            !endpoint.is_closed(),
            "refused host policy must preserve the external owner's endpoint"
        );
    }
    // Unspecified input preserves host ownership and remains usable.
    let ordinary = builder().build();
    ordinary
        .adopt_endpoint_with_router_mode(endpoint.clone(), false)
        .await
        .unwrap();
    assert_eq!(
        ordinary.current_node_id().await,
        Some(endpoint.id().to_string())
    );
    endpoint.close().await;
}

#[cfg(all(
    unix,
    feature = "native-relay-tcp-socket-initializer",
    feature = "test-harness"
))]
#[tokio::test]
async fn constructor_relay_tcp_policy_reaches_live_sdk_relay() {
    use std::{
        os::fd::AsFd,
        sync::{
            atomic::{AtomicUsize, Ordering},
            Arc,
        },
    };
    let (_map, relay_url, _server) = iroh::test_utils::run_relay_server_with(false)
        .await
        .unwrap();
    let url = relay_url.to_string();
    let calls = Arc::new(AtomicUsize::new(0));
    let observed = calls.clone();
    let client = builder()
        .transport_config(TransportConfig {
            relay: true,
            iroh_relay_only: true,
            ..Default::default()
        })
        .native_relay_tcp_socket_initializer(move |socket| {
            let duplicate = std::net::TcpStream::from(socket.as_fd().try_clone_to_owned()?);
            assert!(
                duplicate.peer_addr().is_err(),
                "SDK policy ran after relay TCP connect"
            );
            duplicate.set_ttl(31)?;
            assert_eq!(duplicate.ttl()?, 31);
            observed.fetch_add(1, Ordering::SeqCst);
            Ok(())
        })
        .build();
    client
        .init_test_endpoint(None, Vec::new(), Some(&url))
        .await
        .unwrap();
    let endpoint = client.get_endpoint().await.unwrap();
    let online = tokio::time::timeout(std::time::Duration::from_secs(3), endpoint.online()).await;
    endpoint.close().await;
    online.expect("SDK-owned endpoint must complete its actual local relay handshake");
    assert!(
        calls.load(Ordering::SeqCst) > 0,
        "SDK constructor policy did not reach the live relay TCP factory"
    );
}

#[cfg(feature = "native-dns-socket-initializer")]
#[tokio::test]
async fn constructor_dns_policy_reaches_sdk_owned_resolver() {
    use std::sync::{
        atomic::{AtomicUsize, Ordering},
        Arc,
    };
    let calls = Arc::new(AtomicUsize::new(0));
    let observed = calls.clone();
    let client = builder()
        .native_dns_socket_initializer(move |_, _| {
            observed.fetch_add(1, Ordering::SeqCst);
            Err(std::io::Error::new(
                std::io::ErrorKind::PermissionDenied,
                "sdk-dns-policy-refusal",
            ))
        })
        .build();
    client
        .init_iroh_without_internal_router(None, Vec::new())
        .await
        .unwrap();
    let endpoint = client.get_endpoint().await.unwrap();
    let result = endpoint
        .dns_resolver()
        .unwrap()
        .lookup_ipv4("refused.invalid.", std::time::Duration::from_secs(1))
        .await;
    endpoint.close().await;
    assert!(matches!(
        result,
        Err(iroh::dns::DnsError::SocketPolicy { .. })
    ));
    assert!(
        calls.load(Ordering::SeqCst) > 0,
        "SDK policy must reach actual resolver socket construction"
    );
}