use std::net::{IpAddr, Ipv4Addr}; use mtp_client::{ClientConfig, MTPClient}; use mtp_host::{HostConfig, MTPHost}; async fn generate_self_signed_cert() -> Result<(Vec, Vec), Box> { let key_pair = rcgen::KeyPair::generate()?; let params = rcgen::CertificateParams::new(vec!["localhost".into(), "127.0.0.1".into()])?; let cert = params.self_signed(&key_pair)?; let cert_pem = cert.pem(); let key_pem = key_pair.serialize_pem(); Ok((cert_pem.into_bytes(), key_pem.into_bytes())) } async fn start_host(send_pongs: bool) -> Result<(MTPHost, Vec), Box> { let (cert_pem, key_pem) = generate_self_signed_cert().await?; let host = MTPHost::new( HostConfig::new( IpAddr::V4(Ipv4Addr::LOCALHOST), 0, cert_pem.clone(), key_pem, ) .with_pongs(send_pongs), ) .await?; Ok((host, cert_pem)) } #[tokio::test] async fn test_ping_rtt_and_missed_ping_teardown() -> Result<(), Box> { let (mut host, cert_pem) = start_host(true).await?; let url = format!("https://127.0.0.1:{}", host.local_addr().port()); let client_connect = MTPClient::connect( ClientConfig::new(url) .with_pinned_pem(cert_pem) .with_ping_interval(std::time::Duration::from_millis(25)) .with_max_missed_pings(3), ); let (client, accepted) = tokio::join!(client_connect, host.accept()); let client = client?; let _accepted = accepted?; let ping = tokio::time::timeout(std::time::Duration::from_secs(5), async { loop { if let Some(ping) = client.get_ping() { return ping; } tokio::time::sleep(std::time::Duration::from_millis(10)).await; } }) .await?; assert!(ping > std::time::Duration::ZERO); let (mut silent_host, silent_cert_pem) = start_host(false).await?; let silent_url = format!("https://127.0.0.1:{}", silent_host.local_addr().port()); let silent_connect = MTPClient::connect( ClientConfig::new(silent_url) .with_pinned_pem(silent_cert_pem) .with_ping_interval(std::time::Duration::from_millis(25)) .with_max_missed_pings(2), ); let (silent_client, accepted) = tokio::join!(silent_connect, silent_host.accept()); let silent_client = silent_client?; let _accepted = accepted?; let closed = tokio::time::timeout(std::time::Duration::from_secs(5), async { loop { if silent_client.sender.is_closed() { return; } tokio::time::sleep(std::time::Duration::from_millis(10)).await; } }) .await; assert!(closed.is_ok(), "client should close after missed pings"); Ok(()) }