diff --git a/prototypes/quic_demo/src/bin/quic_demo_end_server.rs b/prototypes/quic_demo/src/bin/quic_demo_end_server.rs new file mode 100644 index 0000000..dcfc6df --- /dev/null +++ b/prototypes/quic_demo/src/bin/quic_demo_end_server.rs @@ -0,0 +1,29 @@ +use quic_demo::prelude::*; + +#[tokio::main] +async fn main () -> anyhow::Result <()> { + tracing_subscriber::fmt::init (); + + let server_cert = tokio::fs::read ("quic_server.crt").await?; + let server_addr = "127.0.0.1:30380".parse ()?; + let endpoint = make_client_endpoint ("0.0.0.0:0".parse ()?, &[&server_cert])?; + + debug! ("Connecting to relay server"); + + let quinn::NewConnection { + mut bi_streams, + .. + } = endpoint.connect (&server_addr, "localhost")?.await?; + + debug! ("Waiting for incoming bi stream"); + + let (mut send, mut recv) = bi_streams.next ().await.ok_or_else (|| anyhow::anyhow! ("Relay server didn't open a bi stream"))??; + + let mut buf = vec! [0u8; 65_536]; + while let Some (bytes_read) = recv.read (&mut buf).await? { + let s = format! ("bytes_read: {}\n", bytes_read); + send.write_all (s.as_bytes ()).await?; + } + + Ok (()) +} diff --git a/prototypes/quic_demo/src/bin/quic_demo_server.rs b/prototypes/quic_demo/src/bin/quic_demo_relay_server.rs similarity index 89% rename from prototypes/quic_demo/src/bin/quic_demo_server.rs rename to prototypes/quic_demo/src/bin/quic_demo_relay_server.rs index f28f873..01d934e 100644 --- a/prototypes/quic_demo/src/bin/quic_demo_server.rs +++ b/prototypes/quic_demo/src/bin/quic_demo_relay_server.rs @@ -1,18 +1,10 @@ -use futures_util::StreamExt; -use tracing::{ - debug, - error, - info, - warn, -}; - -use quic_demo::quinn_utils::*; +use quic_demo::prelude::*; #[tokio::main] async fn main () -> anyhow::Result <()> { tracing_subscriber::fmt::init (); - let server_addr = "0.0.0.0:5000".parse ()?; + let server_addr = "0.0.0.0:30380".parse ()?; let (mut incoming, server_cert) = make_server_endpoint (server_addr)?; tokio::fs::write ("quic_server.crt", &server_cert).await?; @@ -57,7 +49,7 @@ async fn main () -> anyhow::Result <()> { let mut buf = vec! [0u8; 65_536]; while let Some (bytes_read) = client_recv.read (&mut buf).await? { let buf_slice = &buf [0..bytes_read]; - server_send.write (buf_slice).await?; + server_send.write_all (buf_slice).await?; } debug! ("Uplink closed"); @@ -71,7 +63,7 @@ async fn main () -> anyhow::Result <()> { let mut buf = vec! [0u8; 65_536]; while let Some (bytes_read) = server_recv.read (&mut buf).await? { let buf_slice = &buf [0..bytes_read]; - client_send.write (buf_slice).await?; + client_send.write_all (buf_slice).await?; } debug! ("Downlink closed"); diff --git a/prototypes/quic_demo/src/lib.rs b/prototypes/quic_demo/src/lib.rs index fdfefeb..d102ef4 100644 --- a/prototypes/quic_demo/src/lib.rs +++ b/prototypes/quic_demo/src/lib.rs @@ -1 +1,2 @@ +pub mod prelude; pub mod quinn_utils; diff --git a/prototypes/quic_demo/src/prelude.rs b/prototypes/quic_demo/src/prelude.rs new file mode 100644 index 0000000..2ab0c75 --- /dev/null +++ b/prototypes/quic_demo/src/prelude.rs @@ -0,0 +1,9 @@ +pub use futures_util::StreamExt; +pub use tracing::{ + debug, + error, + info, + warn, +}; + +pub use crate::quinn_utils::*; diff --git a/prototypes/quic_demo/src/quinn_utils.rs b/prototypes/quic_demo/src/quinn_utils.rs index 727110f..2a34319 100644 --- a/prototypes/quic_demo/src/quinn_utils.rs +++ b/prototypes/quic_demo/src/quinn_utils.rs @@ -7,6 +7,23 @@ use quinn::{ }; use std::{error::Error, net::SocketAddr, sync::Arc}; +/// Constructs a QUIC endpoint configured for use a client only. +/// +/// ## Args +/// +/// - server_certs: list of trusted certificates. +#[allow(unused)] +pub fn make_client_endpoint( + bind_addr: SocketAddr, + server_certs: &[&[u8]], +) -> anyhow::Result { + let client_cfg = configure_client(server_certs)?; + let mut endpoint_builder = Endpoint::builder(); + endpoint_builder.default_client_config(client_cfg); + let (endpoint, _incoming) = endpoint_builder.bind(&bind_addr)?; + Ok(endpoint) +} + /// Constructs a QUIC endpoint configured to listen for incoming connections /// on a certain address and port. /// @@ -23,6 +40,19 @@ pub fn make_server_endpoint(bind_addr: SocketAddr) -> anyhow::Result<(Incoming, Ok((incoming, server_cert)) } +/// Builds default quinn client config and trusts given certificates. +/// +/// ## Args +/// +/// - server_certs: a list of trusted certificates in DER format. +fn configure_client(server_certs: &[&[u8]]) -> anyhow::Result { + let mut cfg_builder = ClientConfigBuilder::default(); + for cert in server_certs { + cfg_builder.add_certificate_authority(Certificate::from_der(&cert)?)?; + } + Ok(cfg_builder.build()) +} + /// Returns default server configuration along with its certificate. #[allow(clippy::field_reassign_with_default)] // https://github.com/rust-lang/rust-clippy/issues/6527 fn configure_server() -> anyhow::Result<(ServerConfig, Vec)> {