use std::{error::Error, net::SocketAddr, sync::Arc};
use quinn::{ClientConfig, Endpoint};
mod common;
use common::make_server_endpoint;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let addr = "127.0.0.1:5000".parse().unwrap();
tokio::spawn(run_server(addr));
run_client(addr).await?;
Ok(())
}
async fn run_server(addr: SocketAddr) {
let (endpoint, _server_cert) = make_server_endpoint(addr).unwrap();
let incoming_conn = endpoint.accept().await.unwrap();
let conn = incoming_conn.await.unwrap();
println!(
"[server] connection accepted: addr={}",
conn.remote_address()
);
}
async fn run_client(server_addr: SocketAddr) -> Result<(), Box<dyn Error>> {
let client_cfg = configure_client();
let mut endpoint = Endpoint::client("127.0.0.1:0".parse().unwrap())?;
endpoint.set_default_client_config(client_cfg);
let connection = endpoint
.connect(server_addr, "localhost")
.unwrap()
.await
.unwrap();
println!("[client] connected: addr={}", connection.remote_address());
drop(connection);
endpoint.wait_idle().await;
Ok(())
}
struct SkipServerVerification;
impl SkipServerVerification {
fn new() -> Arc<Self> {
Arc::new(Self)
}
}
impl rustls::client::ServerCertVerifier for SkipServerVerification {
fn verify_server_cert(
&self,
_end_entity: &rustls::Certificate,
_intermediates: &[rustls::Certificate],
_server_name: &rustls::ServerName,
_scts: &mut dyn Iterator<Item = &[u8]>,
_ocsp_response: &[u8],
_now: std::time::SystemTime,
) -> Result<rustls::client::ServerCertVerified, rustls::Error> {
Ok(rustls::client::ServerCertVerified::assertion())
}
}
fn configure_client() -> ClientConfig {
let crypto = rustls::ClientConfig::builder()
.with_safe_defaults()
.with_custom_certificate_verifier(SkipServerVerification::new())
.with_no_client_auth();
ClientConfig::new(Arc::new(crypto))
}