use std::{ net::SocketAddr, path::Path, sync::{Once, OnceLock}, }; use futures::{executor::ThreadPool, AsyncReadExt, AsyncWriteExt, Future}; use rasi::net::{TcpListener, TcpStream}; use futures_boring::{connect, ssl, SslListener, SslStream}; use rasi_mio::{net::register_mio_network, timer::register_mio_timer}; fn spawn(fut: Fut) where Fut: Future + Send + 'static, { static THREAD_POOL: OnceLock = OnceLock::new(); let thread_pool = THREAD_POOL.get_or_init(|| ThreadPool::builder().pool_size(10).create().unwrap()); thread_pool.spawn_ok(fut) } fn init() { static INIT: Once = Once::new(); INIT.call_once(|| { register_mio_network(); register_mio_timer(); }) } async fn create_echo_server() -> SocketAddr { let root_path = Path::new(env!("CARGO_MANIFEST_DIR")); let mut acceptor = ssl::SslAcceptor::mozilla_intermediate(ssl::SslMethod::tls()).unwrap(); acceptor .set_private_key_file( root_path.join("../../cert/server.key"), ssl::SslFiletype::PEM, ) .unwrap(); acceptor .set_certificate_chain_file(root_path.join("../../cert/server.crt")) .unwrap(); acceptor.check_private_key().unwrap(); let acceptor = acceptor.build(); let listener = TcpListener::bind("127.0.0.1:0").await.unwrap(); let raddr = listener.local_addr().unwrap(); let mut listener = SslListener::on(listener, acceptor); spawn(async move { loop { match listener.accept().await { Ok(stream) => { spawn(handle_echo_stream(stream)); } Err(_) => break, } } }); raddr } async fn handle_echo_stream(mut stream: SslStream) { let mut buf = vec![0; 1370]; loop { let read_size = stream.read(&mut buf).await.unwrap(); if read_size == 0 { break; } stream.write_all(&buf[..read_size]).await.unwrap(); } } #[futures_test::test] async fn test_echo() { init(); let root_path = Path::new(env!("CARGO_MANIFEST_DIR")); let raddr = create_echo_server().await; let stream = TcpStream::connect(raddr).await.unwrap(); let mut config = ssl::SslConnector::builder(ssl::SslMethod::tls()).unwrap(); config .set_ca_file(root_path.join("../../cert/rasi_ca.pem")) .unwrap(); let config = config.build().configure().unwrap(); let mut stream = connect(config, "rasi.quic", stream).await.unwrap(); for i in 0..10000 { let send_data = format!("Hello world, {}", i); stream.write(send_data.as_bytes()).await.unwrap(); let mut buf = [0; 1024]; let read_size = stream.read(&mut buf).await.unwrap(); assert_eq!(&buf[..read_size], send_data.as_bytes()); } }