//! End-to-end integration test over genuine QUIC on loopback. //! //! Proves that aura-crypto + aura-pki + aura-proto + aura-transport integrate: we mint a real CA, //! issue a server cert (SAN "localhost") and a client cert, bind an [`AuraServer`] on an //! OS-assigned loopback port, connect an [`AuraClient`] (with a camouflage SNI distinct from the //! verified server name), run accept + connect concurrently, then push packets both directions //! through the [`PacketConnection`] API and assert payload integrity. use std::sync::Arc; use aura_pki::AuraCa; use aura_proto::{ClientConfig, PacketConnection, ServerConfig}; use aura_transport::{AuraClient, AuraConnection, AuraServer}; /// The DNS name baked into the server cert SAN and verified by the inner Aura handshake. const SERVER_NAME: &str = "localhost"; /// A deliberately different outer SNI, to prove the mimicry hostname is independent of the /// inner-verified server name. const CAMOUFLAGE_SNI: &str = "cdn.example.com"; #[tokio::test] async fn end_to_end_quic_loopback() { // --- PKI: CA + server cert + client cert ------------------------------------------------ let ca = AuraCa::generate("Aura Test CA").expect("generate CA"); let server_cert = ca .issue_server_cert(SERVER_NAME) .expect("issue server cert"); let client_cert = ca .issue_client_cert("client-001") .expect("issue client cert"); let ca_pem = ca.ca_cert_pem(); let server_cfg = ServerConfig { ca_cert_pem: ca_pem.clone(), server_cert_pem: server_cert.cert_pem.clone(), server_key_pem: server_cert.key_pem.clone(), }; let client_cfg = ClientConfig { ca_cert_pem: ca_pem.clone(), client_cert_pem: client_cert.cert_pem.clone(), client_key_pem: client_cert.key_pem.clone(), server_name: SERVER_NAME.to_string(), }; // --- Bind the server on 127.0.0.1:0 and read the OS-assigned port ----------------------- // The outer QUIC (mimicry) cert reuses the Aura server cert PEM, as the brief suggests. let server = AuraServer::bind( "127.0.0.1:0".parse().unwrap(), &server_cert.cert_pem, &server_cert.key_pem, server_cfg, ) .expect("bind server"); let server_addr = server.local_addr().expect("server local_addr"); assert_ne!(server_addr.port(), 0, "OS should assign a real port"); // --- Run accept + connect concurrently -------------------------------------------------- let accept_task = tokio::spawn(async move { server.accept().await }); let connect_task = tokio::spawn( async move { AuraClient::connect(server_addr, CAMOUFLAGE_SNI, client_cfg).await }, ); let server_conn: AuraConnection = accept_task .await .expect("accept task join") .expect("server accept"); let client_conn: AuraConnection = connect_task .await .expect("connect task join") .expect("client connect"); // The mutual-auth handshake should have established peer identities both ways. assert_eq!( server_conn.peer_id(), Some("client-001"), "server should learn the client's verified CN" ); // Share both ends as trait objects, proving `Arc` usability. let server_conn: Arc = Arc::new(server_conn); let client_conn: Arc = Arc::new(client_conn); // --- Client -> Server: several packets, assert integrity -------------------------------- let c2s: Vec> = vec![ b"hello server".to_vec(), vec![0u8; 1500], // larger-than-bucket payload (0..=255u8).collect(), // every byte value b"".to_vec(), // empty packet ]; for pkt in &c2s { client_conn.send_packet(pkt).await.expect("client send"); let got = server_conn.recv_packet().await.expect("server recv"); assert_eq!(&got, pkt, "client->server payload mismatch"); } // --- Server -> Client: several packets, assert integrity -------------------------------- let s2c: Vec> = vec![ b"hello client".to_vec(), vec![0xABu8; 777], b"final packet".to_vec(), ]; for pkt in &s2c { server_conn.send_packet(pkt).await.expect("server send"); let got = client_conn.recv_packet().await.expect("client recv"); assert_eq!(&got, pkt, "server->client payload mismatch"); } // --- Concurrent full-duplex: both directions in flight at once -------------------------- let s = server_conn.clone(); let c = client_conn.clone(); let dup_server = tokio::spawn(async move { s.send_packet(b"duplex-from-server").await.unwrap(); s.recv_packet().await.unwrap() }); let dup_client = tokio::spawn(async move { c.send_packet(b"duplex-from-client").await.unwrap(); c.recv_packet().await.unwrap() }); let server_got = dup_server.await.expect("dup server join"); let client_got = dup_client.await.expect("dup client join"); assert_eq!(server_got, b"duplex-from-client"); assert_eq!(client_got, b"duplex-from-server"); }