use std::sync::Arc;
use env_logger::init;
#[cfg(not(feature = "tokio"))]
use futures::executor::block_on;
use log::debug;
#[cfg(feature = "tokio")]
use tokio::runtime::Runtime;
use typhoon::bytes::StaticByteBuffer;
use typhoon::certificate::ServerKeyPair;
use typhoon::debug::{DebugClientConnectionHandler, DebugMode, DebugServerConnectionHandler, run_debug};
use typhoon::defaults::{AsyncExecutor, DefaultExecutor};
use typhoon::flow::{FakeBodyMode, FakeHeaderConfig, FlowConfig};
use typhoon::settings::SettingsBuilder;
use typhoon::socket::{ListenerBuilder, ServerFlowConfiguration};
#[cfg(feature = "tokio")]
fn main() {
Runtime::new().expect("failed to create tokio runtime").block_on(run());
}
#[cfg(not(feature = "tokio"))]
fn main() {
block_on(run());
}
async fn run() {
init();
let settings = Arc::new(SettingsBuilder::<DefaultExecutor>::new().build().expect("default settings should be valid"));
let server_addr = "127.0.0.1:19998".parse().expect("valid address");
let key_pair = ServerKeyPair::generate();
let certificate = key_pair.to_client_certificate(vec![server_addr]);
let flow_config = FlowConfig::new(FakeBodyMode::Empty, FakeHeaderConfig::new(vec![]));
let server_flow = ServerFlowConfiguration::with_address(flow_config, server_addr);
let listener: Arc<_> = Arc::new(ListenerBuilder::<StaticByteBuffer, DefaultExecutor, DebugServerConnectionHandler>::new(key_pair, DebugServerConnectionHandler).add_flow(server_flow).with_settings(settings.clone()).build().await.expect("listener should build"));
listener.start().await;
println!("Debug echo server listening on {}", server_addr);
let listener_handle = listener.clone();
let inner_settings = settings.clone();
settings.executor().spawn(async move {
loop {
let Ok(client) = listener_handle.accept().await else {
break;
};
inner_settings.executor().spawn(async move {
let mut echo_count = 0usize;
loop {
let data = match client.receive_bytes().await {
Ok(d) => d,
Err(e) => {
debug!("echo loop: receive error after {} echo(es): {}", echo_count, e);
break;
}
};
echo_count += 1;
debug!("echo loop: received #{} ({} bytes), forwarding", echo_count, data.len());
if let Err(e) = client.send_bytes(&data).await {
debug!("echo loop: send error on echo #{}: {}", echo_count, e);
break;
}
}
debug!("echo loop: exited after {} echo(es)", echo_count);
});
}
});
println!("\n=== Reachability ===");
let result = run_debug(certificate.clone(), DebugMode::Reachability, settings.clone()).await;
println!(" reachable: {:?}", result.reachable);
println!(" packets sent: {}", result.packets_sent);
println!(" packets received: {}", result.packets_received);
println!("\n=== Return Time ===");
let result = run_debug(certificate.clone(), DebugMode::ReturnTime, settings.clone()).await;
println!(" rtt_ms: {:?}", result.rtt_ms);
println!(" packets sent: {}", result.packets_sent);
println!(" packets received: {}", result.packets_received);
println!("\n=== Throughput ===");
let result = run_debug(certificate.clone(), DebugMode::Throughput, settings.clone()).await;
println!(" throughput_bps: {:?}", result.throughput_bps);
println!(" packets sent: {}", result.packets_sent);
println!(" packets received: {}", result.packets_received);
}
#[allow(dead_code)]
fn _require_debug_handler(_: DebugClientConnectionHandler) {}