#![allow(dead_code)]
use std::{io::Write, sync::Arc, time::Duration};
use axum::{
Router,
routing::{get, post},
};
use pocketscion::util::{
dev_auth_token,
topologies::{IA132, IA212, PsSetup, UnderlayType, minimal::minimal_topology},
};
use scion_http3::{Config, scion_quic::quic::config::QuicConfig};
use scion_stack::ScionStackBuilder;
use sciparse::address::{ip_addr::ScionIpAddr, ip_socket_addr::ScionSocketIpAddr};
use tempfile::NamedTempFile;
use tokio_util::sync::CancellationToken;
pub const SERVER_NAME: &str = "localhost";
pub struct E2eSetup {
pub ps: PsSetup,
pub server_addr: ScionSocketIpAddr,
pub cert_file: NamedTempFile,
shutdown: CancellationToken,
}
impl E2eSetup {
pub fn server_ip(&self) -> ScionIpAddr {
self.server_addr.host()
}
pub fn url(&self, path: &str) -> String {
format!("https://{SERVER_NAME}:{}{path}", self.server_addr.port())
}
pub fn client_config(&self) -> Config {
Config::new(self.ps.endhost_api(IA132).expect("endhost API for IA132"))
.with_auth_token(dev_auth_token())
.with_quic_config(
QuicConfig::builder()
.ca_certs_file(self.cert_file.path().to_str().expect("UTF-8 path"))
.build(),
)
}
}
impl Drop for E2eSetup {
fn drop(&mut self) {
self.shutdown.cancel();
}
}
pub async fn e2e_setup() -> E2eSetup {
scion_sdk_utils::rustls::select_ring_crypto_provider();
let ps = minimal_topology(UnderlayType::Udp).await;
let server_stack = ScionStackBuilder::new()
.with_endhost_api(ps.endhost_api(IA212).expect("endhost API for IA212"))
.with_auth_token(dev_auth_token())
.build()
.await
.expect("building server stack");
let server_socket = Arc::new(
server_stack
.bind(None)
.await
.expect("binding server socket"),
);
let server_addr = server_socket.local_addr();
let cert = rcgen::generate_simple_self_signed(vec![SERVER_NAME.to_string()]).unwrap();
let mut cert_file = NamedTempFile::new().unwrap();
let mut key_file = NamedTempFile::new().unwrap();
cert_file
.as_file_mut()
.write_all(cert.cert.pem().as_bytes())
.unwrap();
key_file
.as_file_mut()
.write_all(cert.signing_key.serialize_pem().as_bytes())
.unwrap();
let mut server_config = QuicConfig::builder()
.build()
.to_quiche_config()
.expect("building quiche server config");
server_config
.load_cert_chain_from_pem_file(cert_file.path().to_str().unwrap())
.unwrap();
server_config
.load_priv_key_from_pem_file(key_file.path().to_str().unwrap())
.unwrap();
let shutdown = CancellationToken::new();
tokio::spawn({
let shutdown = shutdown.clone();
let router = test_router();
async move {
let _stack = server_stack;
let _key_file = key_file;
let _ = scion_h3_axum::ScionH3AxumServer::serve_with_graceful_shutdown(
server_socket,
router,
server_config,
shutdown,
)
.await;
}
});
E2eSetup {
ps,
server_addr,
cert_file,
shutdown,
}
}
fn test_router() -> Router {
Router::new()
.route("/hello", get(|| async { "world" }))
.route("/echo", post(|body: String| async move { body }))
.route(
"/slow",
get(|| {
async {
tokio::time::sleep(Duration::from_secs(2)).await;
"slow"
}
}),
)
}