diff --git a/CHANGELOG.md b/CHANGELOG.md index 4bcbb4d..0d907da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,10 +7,19 @@ Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Added + +- Added `CloseStreamError` to `PublishError` to handle error types added by `quinn` + version update. + ### Changed - Modified tls event structure to store: `client_cipher_suites`, `client_extensions`, `extensions` +- Bump dependencies. + - Update quinn to version 0.11. + - Update rustls to version 0.23. + - Update rcgen to version 0.13. ## [0.16.0] - 2024-02-16 diff --git a/Cargo.toml b/Cargo.toml index 32a37d1..ce37e79 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ chrono = { version = ">=0.4.35", default_features = false, features = [ "serde", ] } num_enum = "0.7" -quinn = "0.10" +quinn = "0.11" semver = "1" serde = { version = "1", features = ["derive"] } strum = "0.26" @@ -30,6 +30,10 @@ tracing-subscriber = { version = "0.3", features = [ [dev-dependencies] futures = "0.3" lazy_static = "1" -rcgen = "0.11" -rustls = "0.21" +quinn = { version = "0.11", features = ["ring"] } +rcgen = "0.13" +rustls = { version = "0.23", default-features = false, features = [ + "ring", + "std", +] } tokio = { version = "1", features = ["macros", "rt", "sync"] } diff --git a/README.md b/README.md index ad99596..8b2303d 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ for data processing and high-speed data transfer. ## License -Copyright 2022-2023 ClumL Inc. +Copyright 2022-2024 ClumL Inc. Licensed under [Apache License, Version 2.0][apache-license] (the "License"); you may not use this crate except in compliance with the License. diff --git a/src/connection.rs b/src/connection.rs index 8d3ac20..7b46498 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -59,7 +59,7 @@ pub async fn client_handshake( match frame::recv_handshake(&mut recv, &mut buf).await { Err(RecvError::ReadError(error)) => match error { - quinn::ReadExactError::FinishedEarly => { + quinn::ReadExactError::FinishedEarly(_) => { return Err(HandshakeError::ConnectionClosed); } quinn::ReadExactError::ReadError(e) => { @@ -114,7 +114,7 @@ pub async fn server_handshake( send_handshake(&mut send, &resp_data) .await .map_err(HandshakeError::from)?; - send.finish().await.ok(); + send.finish().ok(); Err(HandshakeError::IncompatibleProtocol( protocol_version.to_string(), )) diff --git a/src/publish.rs b/src/publish.rs index 7a591f1..701cf3f 100644 --- a/src/publish.rs +++ b/src/publish.rs @@ -26,6 +26,8 @@ pub enum PublishError { ReadError(#[from] quinn::ReadError), #[error("Cannot send a publish message")] WriteError(#[from] quinn::WriteError), + #[error("Cannot call close request redundantly")] + CloseStreamError(#[from] quinn::ClosedStream), #[error("Cannot serialize/deserialize a publish message")] SerialDeserialFailure(#[from] bincode::Error), #[error("Message is too large, so type casting failed")] @@ -43,7 +45,7 @@ impl From for PublishError { match e { RecvError::DeserializationFailure(e) => PublishError::SerialDeserialFailure(e), RecvError::ReadError(e) => match e { - quinn::ReadExactError::FinishedEarly => PublishError::ConnectionClosed, + quinn::ReadExactError::FinishedEarly(_) => PublishError::ConnectionClosed, quinn::ReadExactError::ReadError(e) => PublishError::ReadError(e), }, RecvError::MessageTooLarge(_) => PublishError::MessageTooLarge, @@ -344,6 +346,7 @@ pub async fn receive_raw_events( /// * `PublishError::ReadError`: if the extract request ack data could not be read /// * `PublishError::SerialDeserialFailure`: if the extract request ack data could not be deserialized /// * `PublishError::RequestFail`: if the extract request ack data is Err +/// * `PublishError::CloseStreamError`: if duplicate stream close calls are requested. pub async fn pcap_extract_request( conn: &Connection, pcap_filter: &PcapFilter, @@ -356,7 +359,7 @@ pub async fn pcap_extract_request( // send pacp extract request to piglet send_raw(&mut send, &filter).await?; - send.finish().await?; + send.finish()?; // receive pcap extract acknowledge from piglet recv_ack_response(&mut recv).await?; diff --git a/src/test.rs b/src/test.rs index 97652ff..de25d69 100644 --- a/src/test.rs +++ b/src/test.rs @@ -22,19 +22,20 @@ lazy_static! { /// Creates a bidirectional channel, returning server's send and receive and /// client's send and receive streams. pub(crate) async fn channel() -> Channel { - use std::net::{IpAddr, Ipv6Addr, SocketAddr}; - + use rustls::pki_types::{CertificateDer, PrivatePkcs8KeyDer}; + use std::{ + net::{IpAddr, Ipv6Addr, SocketAddr}, + sync::Arc, + }; const TEST_SERVER_NAME: &str = "test-server"; const TEST_PORT: u16 = 60190; let cert = rcgen::generate_simple_self_signed([TEST_SERVER_NAME.to_string()]).expect("infallible"); - let cert_chain = vec![rustls::Certificate( - cert.serialize_der().expect("infallible"), - )]; - let key_der = rustls::PrivateKey(cert.serialize_private_key_der()); - let server_config = - quinn::ServerConfig::with_single_cert(cert_chain, key_der).expect("infallible"); + let cert_der = vec![CertificateDer::from(cert.cert)]; + let key_der = PrivatePkcs8KeyDer::from(cert.key_pair.serialize_der()); + let server_config = quinn::ServerConfig::with_single_cert(cert_der.clone(), key_der.into()) + .expect("infallible"); let server_addr = SocketAddr::new(IpAddr::V6(Ipv6Addr::LOCALHOST), TEST_PORT); let server_endpoint = { @@ -53,30 +54,35 @@ pub(crate) async fn channel() -> Channel { } }; + let handle = tokio::spawn(async move { + let server_connection = match server_endpoint.accept().await { + Some(conn) => match conn.await { + Ok(conn) => conn, + Err(e) => panic!("{}", e.to_string()), + }, + None => panic!("connection closed"), + }; + let (server_send, mut server_recv) = server_connection.accept_bi().await.unwrap(); + let mut server_buf = [0; 5]; + server_recv.read_exact(&mut server_buf).await.unwrap(); + (server_connection, server_send, server_recv) + }); + let mut root_cert_store = rustls::RootCertStore::empty(); - root_cert_store.add_parsable_certificates(&[cert.serialize_der().expect("infallible")]); + root_cert_store.add_parsable_certificates(cert_der); + let client_config = quinn::ClientConfig::with_root_certificates(Arc::new(root_cert_store)) + .expect("invalid client config"); let client_endpoint = quinn::Endpoint::client(SocketAddr::new(IpAddr::V6(Ipv6Addr::UNSPECIFIED), 0)).unwrap(); - let client_config = quinn::ClientConfig::with_root_certificates(root_cert_store); let client_connecting = client_endpoint .connect_with(client_config, server_addr, TEST_SERVER_NAME) .unwrap(); let client_connection = client_connecting.await.unwrap(); - let (mut client_send, client_recv) = client_connection.open_bi().await.unwrap(); client_send.write_all(b"ready").await.unwrap(); - let server_connection = match server_endpoint.accept().await { - Some(conn) => match conn.await { - Ok(conn) => conn, - Err(e) => panic!("{}", e.to_string()), - }, - None => panic!("connection closed"), - }; - let (server_send, mut server_recv) = server_connection.accept_bi().await.unwrap(); - let mut server_buf = [0; 5]; - server_recv.read_exact(&mut server_buf).await.unwrap(); + let (server_connection, server_send, server_recv) = handle.await.unwrap(); Channel { server: self::Endpoint {