diff --git a/noq-proto/src/config/mod.rs b/noq-proto/src/config/mod.rs index 32b944223..6c1bacc8d 100644 --- a/noq-proto/src/config/mod.rs +++ b/noq-proto/src/config/mod.rs @@ -13,8 +13,6 @@ use thiserror::Error; #[cfg(feature = "bloom")] use crate::BloomTokenLog; -#[cfg(not(feature = "bloom"))] -use crate::NoneTokenLog; #[cfg(all(feature = "rustls", any(feature = "aws-lc-rs", feature = "ring")))] use crate::crypto::rustls::{QuicServerConfig, configured_provider}; use crate::{ @@ -475,7 +473,7 @@ impl fmt::Debug for ServerConfig { #[derive(Clone)] pub struct ValidationTokenConfig { pub(crate) lifetime: Duration, - pub(crate) log: Arc, + pub(crate) log: Option>, pub(crate) sent: u32, } @@ -500,7 +498,13 @@ impl ValidationTokenConfig { /// which makes the server ignore all address validation tokens (that is, tokens originating /// from NEW_TOKEN frames--retry tokens are not affected). pub fn log(&mut self, log: Arc) -> &mut Self { - self.log = log; + self.log = Some(log); + self + } + + /// Disable the [`TokenLog`], making the server ignore all address validation tokens + pub fn disable_token_log(&mut self) -> &mut Self { + self.log = None; self } @@ -519,9 +523,9 @@ impl ValidationTokenConfig { impl Default for ValidationTokenConfig { fn default() -> Self { #[cfg(feature = "bloom")] - let log = Arc::new(BloomTokenLog::default()); + let log = Some(Arc::new(BloomTokenLog::default()) as Arc); #[cfg(not(feature = "bloom"))] - let log = Arc::new(NoneTokenLog); + let log = None; Self { lifetime: Duration::from_secs(2 * 7 * 24 * 60 * 60), log, @@ -553,7 +557,7 @@ pub struct ClientConfig { pub(crate) crypto: Arc, /// Validation token store to use - pub(crate) token_store: Arc, + pub(crate) token_store: Option>, /// Provider that populates the destination connection ID of Initial Packets pub(crate) initial_dst_cid_provider: Arc ConnectionId + Send + Sync>, @@ -568,7 +572,7 @@ impl ClientConfig { Self { transport: Default::default(), crypto, - token_store: Arc::new(TokenMemoryCache::default()), + token_store: Some(Arc::new(TokenMemoryCache::default())), initial_dst_cid_provider: Arc::new(|| { RandomConnectionIdGenerator::new(MAX_CID_SIZE).generate_cid() }), @@ -602,7 +606,13 @@ impl ClientConfig { /// /// Defaults to [`TokenMemoryCache`], which is suitable for most internet applications. pub fn token_store(&mut self, store: Arc) -> &mut Self { - self.token_store = store; + self.token_store = Some(store); + self + } + + /// Disable the [`TokenStore`], so that no validation tokens are stored + pub fn disable_token_store(&mut self) -> &mut Self { + self.token_store = None; self } diff --git a/noq-proto/src/connection/mod.rs b/noq-proto/src/connection/mod.rs index 967a2f08f..e3690a41a 100644 --- a/noq-proto/src/connection/mod.rs +++ b/noq-proto/src/connection/mod.rs @@ -5275,7 +5275,9 @@ impl Connection { return Err(TransportError::FRAME_ENCODING_ERROR("empty token")); } trace!("got new token"); - token_store.insert(server_name, token); + if let Some(token_store) = token_store { + token_store.insert(server_name, token); + } } Frame::Datagram(datagram) => { if self @@ -7361,7 +7363,7 @@ enum ConnectionSide { Client { /// Sent in every outgoing Initial packet. Always empty after Initial keys are discarded token: Bytes, - token_store: Arc, + token_store: Option>, server_name: String, }, Server { @@ -7393,7 +7395,10 @@ impl From for ConnectionSide { token_store, server_name, } => Self::Client { - token: token_store.take(&server_name).unwrap_or_default(), + token: token_store + .as_ref() + .and_then(|token_store| token_store.take(&server_name)) + .unwrap_or_default(), token_store, server_name, }, @@ -7409,7 +7414,7 @@ impl From for ConnectionSide { /// Parameters to `Connection::new` specific to it being client-side or server-side pub(crate) enum SideArgs { Client { - token_store: Arc, + token_store: Option>, server_name: String, }, Server { diff --git a/noq-proto/src/lib.rs b/noq-proto/src/lib.rs index 85bfdcf9e..1a81886e4 100644 --- a/noq-proto/src/lib.rs +++ b/noq-proto/src/lib.rs @@ -101,7 +101,9 @@ pub use crate::cid_generator::{ mod token; use token::ResetToken; -pub use token::{NoneTokenLog, NoneTokenStore, TokenLog, TokenReuseError, TokenStore}; +#[allow(deprecated)] +pub use token::{NoneTokenLog, NoneTokenStore}; +pub use token::{TokenLog, TokenReuseError, TokenStore}; mod address_discovery; diff --git a/noq-proto/src/token.rs b/noq-proto/src/token.rs index 8de2b5d6f..dbb30da0a 100644 --- a/noq-proto/src/token.rs +++ b/noq-proto/src/token.rs @@ -66,8 +66,10 @@ pub trait TokenLog: Send + Sync { pub struct TokenReuseError; /// Null implementation of [`TokenLog`], which never accepts tokens +#[deprecated(note = "use `ValidationTokenConfig::disable_token_log` instead")] pub struct NoneTokenLog; +#[allow(deprecated)] impl TokenLog for NoneTokenLog { fn check_and_insert(&self, _: u128, _: SystemTime, _: Duration) -> Result<(), TokenReuseError> { Err(TokenReuseError) @@ -92,8 +94,10 @@ pub trait TokenStore: Send + Sync { } /// Null implementation of [`TokenStore`], which does not store any tokens +#[deprecated(note = "use `ClientConfig::disable_token_store` instead")] pub struct NoneTokenStore; +#[allow(deprecated)] impl TokenStore for NoneTokenStore { fn insert(&self, _: &str, _: Bytes) {} fn take(&self, _: &str) -> Option { @@ -170,9 +174,10 @@ impl IncomingToken { { return Ok(unvalidated); } - if server_config - .validation_token - .log + let Some(log) = &server_config.validation_token.log else { + return Ok(unvalidated); + }; + if log .check_and_insert(retry.nonce, issued, server_config.validation_token.lifetime) .is_err() { diff --git a/noq/src/lib.rs b/noq/src/lib.rs index ac43d2ee6..b9eb063a7 100644 --- a/noq/src/lib.rs +++ b/noq/src/lib.rs @@ -65,12 +65,13 @@ pub use proto::{ ClosedStream, ConfigError, ConnectError, ConnectionClose, ConnectionError, ConnectionId, ConnectionIdGenerator, ConnectionStats, DecryptedInitial, Dir, EcnCodepoint, EndpointConfig, FourTuple, FrameStats, FrameType, IdleTimeout, InvalidCid, MtuDiscoveryConfig, - NetworkChangeHint, NoneTokenLog, NoneTokenStore, PathError, PathEvent, PathId, PathStats, - PathStatus, ServerConfig, SetPathStatusError, Side, StdSystemTime, StreamId, TimeSource, - TokenLog, TokenMemoryCache, TokenReuseError, TokenStore, Transmit, TransportConfig, - TransportErrorCode, UdpStats, ValidationTokenConfig, VarInt, VarIntBoundsExceeded, congestion, - crypto, + NetworkChangeHint, PathError, PathEvent, PathId, PathStats, PathStatus, ServerConfig, + SetPathStatusError, Side, StdSystemTime, StreamId, TimeSource, TokenLog, TokenMemoryCache, + TokenReuseError, TokenStore, Transmit, TransportConfig, TransportErrorCode, UdpStats, + ValidationTokenConfig, VarInt, VarIntBoundsExceeded, congestion, crypto, }; +#[allow(deprecated)] +pub use proto::{NoneTokenLog, NoneTokenStore}; #[cfg(feature = "qlog")] pub use proto::{QlogConfig, QlogFactory, QlogFileFactory}; #[cfg(feature = "rustls")]