use ant_quic::{
auth::AuthConfig,
crypto::pqc::{PqcConfig, PqcMode},
crypto::raw_public_keys::key_utils::{
derive_peer_id_from_public_key, generate_ed25519_keypair,
},
nat_traversal_api::EndpointRole,
quic_node::{QuicNodeConfig, QuicP2PNode},
};
use std::{net::SocketAddr, sync::Arc, time::Duration};
use tracing::{error, info, warn};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
tracing_subscriber::fmt()
.with_env_filter(
tracing_subscriber::EnvFilter::from_default_env().add_directive(
"info"
.parse()
.map_err(|e| format!("Failed to parse log directive: {}", e))?,
),
)
.init();
{
println!("Error: PQC is always enabled in this repository.");
println!("Run with: cargo run --example pqc_basic -- <server|client>");
std::process::exit(1);
}
{
let args: Vec<String> = std::env::args().collect();
if args.len() < 2 {
println!("Usage: {} <server|client> [server_addr]", args[0]);
println!("\nExamples:");
println!(
" {} server # Start a PQC-enabled server",
args[0]
);
println!(
" {} client 127.0.0.1:5000 # Connect to a PQC server",
args[0]
);
return Ok(());
}
let mode = &args[1];
match mode.as_str() {
"server" => run_server().await,
"client" => {
if args.len() < 3 {
eprintln!("Error: Client mode requires server address");
return Ok(());
}
let server_addr: SocketAddr = args[2].parse()?;
run_client(server_addr).await
}
_ => {
eprintln!("Error: Unknown mode '{mode}'. Use 'server' or 'client'");
Ok(())
}
}
}
}
async fn run_server() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
println!("🚀 Starting PQC-enabled QUIC server...");
let (_private_key, public_key) = generate_ed25519_keypair();
let peer_id = derive_peer_id_from_public_key(&public_key);
println!("📋 Server PeerID: {peer_id:?}");
let pqc_config = PqcConfig::builder()
.mode(PqcMode::Hybrid)
.build()
.map_err(|e| format!("Failed to build PQC config: {}", e))?;
println!("🔐 PQC Mode: {:?}", pqc_config.mode);
println!("🔐 PQC disabled - using classical cryptography only");
let config = QuicNodeConfig {
role: EndpointRole::Bootstrap,
bootstrap_nodes: vec![],
enable_coordinator: false,
max_connections: 50,
connection_timeout: Duration::from_secs(30),
stats_interval: Duration::from_secs(60),
auth_config: AuthConfig::default(), bind_addr: Some("0.0.0.0:5001".parse()?),
};
let node = Arc::new(QuicP2PNode::new(config).await?);
println!("🎧 Listening on 0.0.0.0:5000");
println!("🔐 PQC protection enabled!");
println!("🎧 Server ready and waiting for connections...");
loop {
println!("🔄 Waiting for incoming connection...");
match node.accept().await {
Ok((remote_addr, peer_id)) => {
println!("✅ Accepted connection from {remote_addr} (peer: {peer_id:?})");
loop {
match node.receive().await {
Ok((recv_peer_id, data)) => {
if recv_peer_id == peer_id {
let message = String::from_utf8_lossy(&data);
println!("📩 Message from {peer_id:?}: {message}");
let response = format!("Server received: {message}");
if let Err(e) =
node.send_to_peer(&peer_id, response.as_bytes()).await
{
warn!("Failed to send response: {}", e);
}
break; }
}
Err(_) => {
tokio::time::sleep(Duration::from_millis(100)).await;
}
}
}
}
Err(e) => {
error!("Failed to accept connection: {}", e);
tokio::time::sleep(Duration::from_millis(100)).await;
}
}
}
}
async fn run_client(
server_addr: SocketAddr,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
println!("🚀 Starting PQC-enabled QUIC client...");
let (_private_key, public_key) = generate_ed25519_keypair();
let peer_id = derive_peer_id_from_public_key(&public_key);
println!("📋 Client PeerID: {peer_id:?}");
let pqc_config = PqcConfig::builder()
.mode(PqcMode::Hybrid)
.build()
.map_err(|e| format!("Failed to build PQC config: {}", e))?;
println!("🔐 PQC Mode: {:?}", pqc_config.mode);
println!("🔐 PQC disabled - using classical cryptography only");
let config = QuicNodeConfig {
role: EndpointRole::Bootstrap,
bootstrap_nodes: vec!["127.0.0.1:5001".parse()?],
enable_coordinator: false,
max_connections: 10,
connection_timeout: Duration::from_secs(30),
stats_interval: Duration::from_secs(60),
auth_config: AuthConfig::default(), bind_addr: None,
};
let node = Arc::new(QuicP2PNode::new(config).await?);
println!("🔗 Connecting to {server_addr} with PQC...");
println!("🔄 Attempting to connect to server...");
tokio::time::sleep(Duration::from_secs(1)).await; let server_peer_id = loop {
match node.connect_to_bootstrap(server_addr).await {
Ok(peer_id) => {
break peer_id;
}
Err(e) => {
warn!("Connection attempt failed: {}. Retrying in 2 seconds...", e);
tokio::time::sleep(Duration::from_secs(2)).await;
}
}
};
println!("✅ Connected to server with PQC protection!");
println!(" Server PeerID: {server_peer_id:?}");
let message = "Hello from PQC-protected client!";
info!("Sending message: {}", message);
node.send_to_peer(&server_peer_id, message.as_bytes())
.await?;
let timeout = tokio::time::timeout(Duration::from_secs(5), async {
loop {
match node.receive().await {
Ok((peer_id, data)) => {
if peer_id == server_peer_id {
let response = String::from_utf8_lossy(&data);
println!("📨 Response: {response}");
return Ok::<(), Box<dyn std::error::Error + Send + Sync>>(());
}
}
Err(_) => {
tokio::time::sleep(Duration::from_millis(100)).await;
}
}
}
})
.await;
match timeout {
Ok(Ok(())) => println!("✅ Communication successful with PQC protection!"),
Ok(Err(_)) => warn!("Failed to receive response"),
Err(_) => warn!("Timeout waiting for response"),
}
drop(node);
println!("👋 Client shutdown complete");
Ok(())
}