use std::sync::Arc;
use env_logger::init;
use futures::channel::oneshot::channel;
#[cfg(not(feature = "tokio"))]
use futures::executor::block_on;
#[cfg(feature = "tokio")]
use tokio::runtime::Runtime;
use typhoon::bytes::StaticByteBuffer;
use typhoon::certificate::ServerKeyPair;
use typhoon::defaults::{AsyncExecutor, DefaultClientConnectionHandler, DefaultExecutor, DefaultServerConnectionHandler};
use typhoon::flow::{FakeBodyMode, FakeHeaderConfig, FlowConfig};
use typhoon::settings::SettingsBuilder;
use typhoon::socket::{ClientSocketBuilder, 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:19999".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, DefaultServerConnectionHandler>::new(key_pair, DefaultServerConnectionHandler).add_flow(server_flow).with_settings(settings.clone()).build().await.expect("listener should build"));
listener.start().await;
println!("Server listening on {server_addr}");
let listener_handle = listener.clone();
let (done_tx, done_rx) = channel::<String>();
settings.executor().spawn(async move {
let client = listener_handle.accept().await.expect("accept should succeed");
println!("Server: client connected");
let received = client.receive_bytes().await.expect("receive should succeed");
let msg = String::from_utf8_lossy(&received).to_string();
println!("Server: received '{msg}'");
client.send_bytes(format!("echo: {}", msg).as_bytes()).await.expect("send should succeed");
println!("Server: sent echo response");
let _ = done_tx.send(msg);
});
let socket = ClientSocketBuilder::<StaticByteBuffer, DefaultExecutor, DefaultClientConnectionHandler>::new(certificate, DefaultClientConnectionHandler).with_settings(settings.clone()).build().await.expect("client socket should build");
println!("Client: connected to {}", server_addr);
socket.send_bytes(b"hello world").await.expect("send should succeed");
println!("Client: sent 'hello world'");
let response = socket.receive_bytes().await.expect("receive should succeed");
println!("Client: received '{}'", String::from_utf8_lossy(&response));
let server_received = done_rx.await.expect("server task should complete");
assert_eq!(server_received, "hello world");
println!("Success! Round-trip verified.");
}