feat: works
This commit is contained in:
@@ -1,12 +1,38 @@
|
||||
use std::net::SocketAddr;
|
||||
use quinn::{Incoming, Endpoint, ServerConfig, PrivateKey, TransportConfig, ServerConfigBuilder, Certificate, CertificateChain};
|
||||
use std::error::Error;
|
||||
use std::{error::Error, net::SocketAddr};
|
||||
use std::sync::Arc;
|
||||
use std::str::FromStr;
|
||||
use futures_util::StreamExt;
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let addr = SocketAddr::from_str("127.0.0.1:8888").unwrap();
|
||||
use futures_util::stream::StreamExt;
|
||||
use quinn::{ClientConfig, Endpoint, Incoming, ServerConfig};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn Error>> {
|
||||
let addr1 = "127.0.0.1:5000".parse().unwrap();
|
||||
let addr2 = "127.0.0.1:5001".parse().unwrap();
|
||||
let addr3 = "127.0.0.1:5002".parse().unwrap();
|
||||
let server1_cert = run_server(addr1)?;
|
||||
let server2_cert = run_server(addr2)?;
|
||||
let server3_cert = run_server(addr3)?;
|
||||
|
||||
let client = make_client_endpoint(
|
||||
"127.0.0.1:0".parse().unwrap(),
|
||||
&[&server1_cert, &server2_cert, &server3_cert],
|
||||
)?;
|
||||
|
||||
// connect to multiple endpoints using the same socket/endpoint
|
||||
tokio::join!(
|
||||
run_client(&client, addr1),
|
||||
run_client(&client, addr2),
|
||||
run_client(&client, addr3),
|
||||
);
|
||||
|
||||
// Make sure the server has a chance to clean up
|
||||
client.wait_idle().await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Runs a QUIC server bound to given address and returns server certificate.
|
||||
fn run_server(addr: SocketAddr) -> Result<Vec<u8>, Box<dyn Error>> {
|
||||
let (mut incoming, server_cert) = make_server_endpoint(addr)?;
|
||||
// accept a single connection
|
||||
tokio::spawn(async move {
|
||||
@@ -16,31 +42,53 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
connection.remote_address()
|
||||
);
|
||||
});
|
||||
Ok(())
|
||||
|
||||
Ok(server_cert)
|
||||
}
|
||||
|
||||
/// Attempt QUIC connection with the given server address.
|
||||
async fn run_client(endpoint: &Endpoint, server_addr: SocketAddr) {
|
||||
let connect = endpoint.connect(server_addr, "localhost").unwrap();
|
||||
let quinn::NewConnection { connection, .. } = connect.await.unwrap();
|
||||
println!("[client] connected: addr={}", connection.remote_address());
|
||||
}
|
||||
|
||||
pub fn make_client_endpoint(
|
||||
bind_addr: SocketAddr,
|
||||
server_certs: &[&[u8]],
|
||||
) -> Result<Endpoint, Box<dyn Error>> {
|
||||
let client_cfg = configure_client(server_certs)?;
|
||||
let mut endpoint = Endpoint::client(bind_addr)?;
|
||||
endpoint.set_default_client_config(client_cfg);
|
||||
Ok(endpoint)
|
||||
}
|
||||
|
||||
pub fn make_server_endpoint(bind_addr: SocketAddr) -> Result<(Incoming, Vec<u8>), Box<dyn Error>> {
|
||||
let (server_config, server_cert) = configure_server()?;
|
||||
let mut endpoint_builder = Endpoint::builder();
|
||||
endpoint_builder.listen(server_config);
|
||||
let (_endpoint, incoming) = endpoint_builder.bind(&bind_addr)?;
|
||||
let (_endpoint, incoming) = Endpoint::server(server_config, bind_addr)?;
|
||||
Ok((incoming, server_cert))
|
||||
}
|
||||
|
||||
fn configure_client(server_certs: &[&[u8]]) -> Result<ClientConfig, Box<dyn Error>> {
|
||||
let mut certs = rustls::RootCertStore::empty();
|
||||
for cert in server_certs {
|
||||
certs.add(&rustls::Certificate(cert.to_vec()))?;
|
||||
}
|
||||
|
||||
Ok(ClientConfig::with_root_certificates(certs))
|
||||
}
|
||||
|
||||
fn configure_server() -> Result<(ServerConfig, Vec<u8>), Box<dyn Error>> {
|
||||
let cert = rcgen::generate_simple_self_signed(vec!["localhost".into()]).unwrap();
|
||||
let cert_der = cert.serialize_der().unwrap();
|
||||
let priv_key = cert.serialize_private_key_der();
|
||||
let priv_key = PrivateKey::from_der(&priv_key)?;
|
||||
let priv_key = rustls::PrivateKey(priv_key);
|
||||
let cert_chain = vec![rustls::Certificate(cert_der.clone())];
|
||||
|
||||
let mut transport_config = TransportConfig::default();
|
||||
transport_config.max_concurrent_uni_streams(0).unwrap();
|
||||
let mut server_config = ServerConfig::default();
|
||||
server_config.transport = Arc::new(transport_config);
|
||||
let mut cfg_builder = ServerConfigBuilder::new(server_config);
|
||||
let cert = Certificate::from_der(&cert_der)?;
|
||||
cfg_builder.certificate(CertificateChain::from_certs(vec![cert]), priv_key)?;
|
||||
let mut server_config = ServerConfig::with_single_cert(cert_chain, priv_key)?;
|
||||
Arc::get_mut(&mut server_config.transport)
|
||||
.unwrap()
|
||||
.max_concurrent_uni_streams(0_u8.into());
|
||||
|
||||
Ok((cfg_builder.build(), cert_der))
|
||||
}
|
||||
Ok((server_config, cert_der))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user