feat: works

This commit is contained in:
2022-08-25 00:52:26 +08:00
parent 8e29384cb2
commit 60eb54ca49
4 changed files with 257 additions and 131 deletions

View File

@@ -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))
}