mod auth; mod metrics; mod messages; mod pipes; use std::fs; use std::path::Path; use std::time::Duration; use mtp::client::ClientConfig; use mtp::files::load_public_key_bundle; fn dev_cert_path() -> String { std::env::var("MTP_DEV_CERT").unwrap_or_else(|_| { if Path::new("example/dev-cert/cert.pem").exists() { "example/dev-cert/cert.pem".to_string() } else { "dev-cert/cert.pem".to_string() } }) } #[tokio::main] async fn main() -> Result<(), Box> { tracing_subscriber::fmt::init(); let cert_path = dev_cert_path(); let cert_pem = fs::read(&cert_path).unwrap_or_else(|e| { panic!( "Missing TLS certificate at {cert_path}: enter the Nix shell first or run the server to generate it: {e}" ) }); let host_public_key = match load_public_key_bundle("host.mpkb") { Ok(bundle) => bundle, Err(e) => { return Err( format!("Missing host.mpkb: run the server first to export it ({e})").into(), ); } }; let mut client_metrics = metrics::ClientMetrics::load("metrics/client_sessions.json"); println!("Connecting to 127.0.0.1:8080 ..."); let config = ClientConfig::new("https://127.0.0.1:8080") .with_pinned_pem(cert_pem) .with_description("MTP example client"); let server_bundle = host_public_key.clone(); let (conn, keyring, auth_method, auth_duration) = match auth::connect_or_register(config, host_public_key, "client").await { Ok(result) => result, Err(e) => { let mut builder = metrics::SessionBuilder::new("failed", Duration::from_secs(0)); builder.set_error(e.to_string()); client_metrics.record_session(builder.build()); client_metrics.save("metrics/client_sessions.json"); client_metrics.build_overview("metrics/client_overview.json"); return Err(e); } }; let mut builder = metrics::SessionBuilder::new(&auth_method, auth_duration); let roundtrip = messages::send_and_receive(&conn, &keyring, &server_bundle).await?; builder.set_message_roundtrip(roundtrip); println!("\n--- Pipe demo ---"); let pipe_results = pipes::run_pipe_demo(&conn, 1).await?; for result in &pipe_results { builder.add_pipe_result(result.clone()); } let session_record = builder.build(); println!( "\nSession {} complete: auth={}ms, msg_roundtrip={}ms, pipes={} results, pipe_bytes={}", session_record.session_id, session_record.auth_duration_ms, session_record.message_roundtrip_ms, session_record.pipe_results.len(), session_record.total_pipe_bytes, ); client_metrics.record_session(session_record); client_metrics.save("metrics/client_sessions.json"); client_metrics.build_overview("metrics/client_overview.json"); conn.sender.close().await; println!("\nDone"); Ok(()) }