Skip to content

Commit

Permalink
feat(s2n-quic-transport): dc Manager (#2218)
Browse files Browse the repository at this point in the history
* feat(s2n-quic-transport): dc Manager

* wire up dc manager

* expose new method in `Flag`

* add publisher to frame handling

* dc mod

* create dc manager in session_context.rs

* update select_version to use tp

* add events

* dc manager tests

* dc manager

* dc integration test

* cleanup snapshots

* move flag to manager and use state transition macro

* move application_params

* add assertion for path secrets ready

* add test for not mtls

* return vec from trait and simplify trait

* add new state

* add use

* use ensure

* use test_transitions
  • Loading branch information
WesleyRosenblum authored May 23, 2024
1 parent c96e57c commit 391068e
Show file tree
Hide file tree
Showing 33 changed files with 1,300 additions and 59 deletions.
17 changes: 16 additions & 1 deletion quic/s2n-quic-core/src/crypto/tls/testing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::{
crypto::{
header_crypto::{LONG_HEADER_MASK, SHORT_HEADER_MASK},
scatter, tls,
tls::ApplicationParameters,
tls::{ApplicationParameters, CipherSuite, TlsExportError, TlsSession},
CryptoSuite, HeaderKey, Key,
},
endpoint, transport,
Expand Down Expand Up @@ -110,6 +110,21 @@ impl CryptoSuite for Session {
type RetryKey = crate::crypto::key::testing::Key;
}

impl TlsSession for Session {
fn tls_exporter(
&self,
_label: &[u8],
_context: &[u8],
_output: &mut [u8],
) -> Result<(), TlsExportError> {
Ok(())
}

fn cipher_suite(&self) -> CipherSuite {
CipherSuite::TLS_AES_128_GCM_SHA256
}
}

#[derive(Debug)]
pub struct TlsEndpoint<S: tls::Session, State: Debug, Params>
where
Expand Down
14 changes: 10 additions & 4 deletions quic/s2n-quic-core/src/dc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,30 @@ use crate::{
event::{api::SocketAddress, IntoEvent as _},
inet,
path::MaxMtu,
transport::parameters::InitialFlowControlLimits,
transport::parameters::{DcSupportedVersions, InitialFlowControlLimits},
varint::VarInt,
};
use core::time::Duration;

mod disabled;
mod traits;

#[cfg(any(test, feature = "testing"))]
pub mod testing;

pub use disabled::*;
pub use traits::*;

pub type Version = u32;

// dc versions supported by this code, in order of preference (SUPPORTED_VERSIONS[0] is most preferred)
const SUPPORTED_VERSIONS: &[u32] = &[0x0];
pub const SUPPORTED_VERSIONS: [Version; 1] = [0x0];

/// Called on the server to select the dc version to use (if any)
///
/// The server's version preference takes precedence
pub fn select_version(client_supported_versions: &[u32]) -> Option<u32> {
pub fn select_version(client_supported_versions: DcSupportedVersions) -> Option<Version> {
let client_supported_versions = client_supported_versions.into_iter().as_slice();
SUPPORTED_VERSIONS
.iter()
.find(|&supported_version| client_supported_versions.contains(supported_version))
Expand All @@ -48,7 +54,7 @@ impl<'a> ConnectionInfo<'a> {
#[doc(hidden)]
pub fn new(
remote_address: &'a inet::SocketAddress,
dc_version: u32,
dc_version: Version,
application_params: ApplicationParams,
) -> Self {
Self {
Expand Down
11 changes: 4 additions & 7 deletions quic/s2n-quic-core/src/dc/disabled.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
use crate::{
crypto::tls::TlsSession,
dc::{ConnectionInfo, Endpoint, Path},
stateless_reset::Token,
stateless_reset,
};
use alloc::vec::Vec;

#[derive(Debug, Default)]
pub struct Disabled(());
Expand All @@ -22,18 +23,14 @@ impl Endpoint for Disabled {

// The Disabled Endpoint returns `None`, so this is not used
impl Path for () {
fn on_path_secrets_ready(&mut self, _session: &impl TlsSession) {
fn on_path_secrets_ready(&mut self, _session: &impl TlsSession) -> Vec<stateless_reset::Token> {
unimplemented!()
}

fn on_peer_stateless_reset_tokens<'a>(
&mut self,
_stateless_reset_tokens: impl Iterator<Item = &'a Token>,
_stateless_reset_tokens: impl Iterator<Item = &'a stateless_reset::Token>,
) {
unimplemented!()
}

fn stateless_reset_tokens(&mut self) -> &[Token] {
unimplemented!()
}
}
51 changes: 51 additions & 0 deletions quic/s2n-quic-core/src/dc/testing.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use crate::{crypto::tls::TlsSession, dc, dc::ConnectionInfo, stateless_reset};

pub struct MockDcEndpoint {
stateless_reset_tokens: Vec<stateless_reset::Token>,
}

impl MockDcEndpoint {
pub fn new(tokens: &[stateless_reset::Token]) -> Self {
Self {
stateless_reset_tokens: tokens.to_vec(),
}
}
}

#[derive(Default)]
pub struct MockDcPath {
pub on_path_secrets_ready_count: u8,
pub on_peer_stateless_reset_tokens_count: u8,
pub stateless_reset_tokens: Vec<stateless_reset::Token>,
pub peer_stateless_reset_tokens: Vec<stateless_reset::Token>,
}

impl dc::Endpoint for MockDcEndpoint {
type Path = MockDcPath;

fn new_path(&mut self, _connection_info: &ConnectionInfo) -> Option<Self::Path> {
Some(MockDcPath {
stateless_reset_tokens: self.stateless_reset_tokens.clone(),
..Default::default()
})
}
}

impl dc::Path for MockDcPath {
fn on_path_secrets_ready(&mut self, _session: &impl TlsSession) -> Vec<stateless_reset::Token> {
self.on_path_secrets_ready_count += 1;
self.stateless_reset_tokens.clone()
}

fn on_peer_stateless_reset_tokens<'a>(
&mut self,
stateless_reset_tokens: impl Iterator<Item = &'a stateless_reset::Token>,
) {
self.on_peer_stateless_reset_tokens_count += 1;
self.peer_stateless_reset_tokens
.extend(stateless_reset_tokens);
}
}
23 changes: 8 additions & 15 deletions quic/s2n-quic-core/src/dc/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

use crate::{crypto::tls::TlsSession, dc, stateless_reset};
use alloc::vec::Vec;

/// The `dc::Endpoint` trait provides a way to support dc functionality
pub trait Endpoint: 'static + Send {
Expand All @@ -21,24 +22,25 @@ pub trait Endpoint: 'static + Send {
/// A dc path
pub trait Path: 'static + Send {
/// Called when path secrets are ready to be derived from the given `TlsSession`
fn on_path_secrets_ready(&mut self, session: &impl TlsSession);
///
/// Returns the stateless reset tokens to include in a `DC_STATELESS_RESET_TOKENS`
/// frame sent to the peer.
fn on_path_secrets_ready(&mut self, session: &impl TlsSession) -> Vec<stateless_reset::Token>;

/// Called when a `DC_STATELESS_RESET_TOKENS` frame has been received from the peer
fn on_peer_stateless_reset_tokens<'a>(
&mut self,
stateless_reset_tokens: impl Iterator<Item = &'a stateless_reset::Token>,
);

/// Returns the stateless reset tokens to include in a `DC_STATELESS_RESET_TOKENS`
/// frame sent to the peer.
fn stateless_reset_tokens(&mut self) -> &[stateless_reset::Token];
}

impl<P: Path> Path for Option<P> {
#[inline]
fn on_path_secrets_ready(&mut self, session: &impl TlsSession) {
fn on_path_secrets_ready(&mut self, session: &impl TlsSession) -> Vec<stateless_reset::Token> {
if let Some(path) = self {
path.on_path_secrets_ready(session)
} else {
Vec::default()
}
}

Expand All @@ -51,13 +53,4 @@ impl<P: Path> Path for Option<P> {
path.on_peer_stateless_reset_tokens(stateless_reset_tokens)
}
}

#[inline]
fn stateless_reset_tokens(&mut self) -> &[stateless_reset::Token] {
if let Some(path) = self {
path.stateless_reset_tokens()
} else {
&[]
}
}
}
Loading

0 comments on commit 391068e

Please sign in to comment.