Skip to content

Commit

Permalink
Expose max_idle_timeout setting
Browse files Browse the repository at this point in the history
  • Loading branch information
daxpedda committed Dec 10, 2021
1 parent 456dc3a commit 4debce0
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 25 deletions.
3 changes: 3 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@ pub enum Config {
/// Error aquiring or parsing root certificates from the OS.
#[error(transparent)]
NativeCert(#[from] OsStore),
/// Returned when timeout chosen is equal or bigger than 2^62 ms.
#[error("Invalid timeout, can't exceed 2^62 ms")]
MaxIdleTimeout,
}

/// Error aquiring or parsing root certs from OS.
Expand Down
82 changes: 59 additions & 23 deletions src/quic/endpoint/builder/config.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
//! Persistent configuration shared between [`Builder`](crate::Builder) and
//! [`Endpoint`](crate::Endpoint).
use std::{sync::Arc, time::SystemTime};
use std::{
sync::Arc,
time::{Duration, SystemTime},
};

use quinn::{ClientConfig, TransportConfig};
use quinn::{ClientConfig, IdleTimeout, TransportConfig};
use rustls::{
client::{
CertificateTransparencyPolicy, ResolvesClientCert, ServerCertVerified, ServerCertVerifier,
Expand All @@ -24,10 +27,10 @@ use crate::{
/// [`Endpoint`](crate::Endpoint).
#[derive(Clone, Debug)]
pub(in crate::quic::endpoint) struct Config {
/// Storing the default [`TransportConfig`].
transport: Arc<TransportConfig>,
/// Protocols used.
protocols: Vec<Vec<u8>>,
/// Store maximum idle timeout.
max_idle_timeout: Option<Duration>,
/// Enable [`trust-dns`](trust_dns_resolver).
#[cfg(feature = "trust-dns")]
#[cfg_attr(doc, doc(cfg(feature = "trust-dns")))]
Expand All @@ -44,23 +47,11 @@ pub(in crate::quic::endpoint) struct Config {

impl Config {
/// Builds a new [`Config`].
pub(super) fn new() -> Self {
let mut transport = TransportConfig::default();

// set transport defaults
// TODO: research other settings
let _ = transport
// TODO: research if this is necessary, it improves privacy, but may hurt network
// providers?
.allow_spin(false)
// we don't support unordered for now
.datagram_receive_buffer_size(None)
// for compatibility with WebRTC, we won't be using uni-directional streams
.max_concurrent_uni_streams(quinn::VarInt::from_u32(0));

pub(super) const fn new() -> Self {
Self {
transport: Arc::new(transport),
protocols: Vec::new(),
// default set by quinn
max_idle_timeout: Some(Duration::from_secs(10)),
#[cfg(feature = "trust-dns")]
trust_dns: true,
#[cfg(feature = "trust-dns")]
Expand All @@ -70,9 +61,26 @@ impl Config {
}
}

/// Returns the default [`TransportConfig`].
pub(super) fn transport(&self) -> Arc<TransportConfig> {
Arc::clone(&self.transport)
/// Creates a with the correct settings [`TransportConfig`].
pub(super) fn transport(&self) -> TransportConfig {
let mut transport = TransportConfig::default();

// set transport defaults
// TODO: research other settings
let _ =
transport
// TODO: research if this is necessary, it improves privacy, but may hurt network
// providers?
.allow_spin(false)
// we don't support unordered for now
.datagram_receive_buffer_size(None)
// for compatibility with WebRTC, we won't be using uni-directional streams
.max_concurrent_uni_streams(quinn::VarInt::from_u32(0))
.max_idle_timeout(self.max_idle_timeout.map(|time| {
IdleTimeout::try_from(time).expect("unexpected failure conversion")
}));

transport
}

/// Set the application-layer protocols.
Expand Down Expand Up @@ -146,6 +154,34 @@ impl Config {
self.hosts_file
}

/// Set's the maximum idle timeout a client can have before getting
/// automatically disconnected. Set [`None`] to disable automatic
/// disconnecting completely.
///
/// # Errors
/// [`Config::MaxIdleTimeout`](error::Config::MaxIdleTimeout) if time
/// exceeds 2^62 ms.
pub(in crate::quic::endpoint) fn set_max_idle_timeout(
&mut self,
time: Option<Duration>,
) -> Result<(), error::Config> {
if let Some(time) = time {
let _ = IdleTimeout::try_from(time).map_err(|_error| error::Config::MaxIdleTimeout)?;
}

self.max_idle_timeout = time;

Ok(())
}

/// Returns the set [`Duration`] specified for idle clients to automatically
/// get disconnected. [`None`] means clients don't get automatically
/// disconnected.
#[must_use]
pub(in crate::quic::endpoint) const fn max_idle_timeout(&self) -> Option<Duration> {
self.max_idle_timeout
}

/// Builds a new [`ClientConfig`] with this [`Config`] and adds
/// [`Certificate`]s to the CA store.
///
Expand Down Expand Up @@ -254,7 +290,7 @@ impl Config {
crypto.alpn_protocols = self.protocols.clone();

let mut client = ClientConfig::new(Arc::new(crypto));
client.transport = self.transport();
client.transport = Arc::new(self.transport());

Ok(client)
}
Expand Down
62 changes: 60 additions & 2 deletions src/quic/endpoint/builder/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
//! [`Endpoint`] builder.
mod config;
use std::{fmt::Debug, net::SocketAddr, sync::Arc, time::SystemTime};
use std::{
fmt::Debug,
net::SocketAddr,
sync::Arc,
time::{Duration, SystemTime},
};

pub(super) use config::Config;
use rustls::{
Expand Down Expand Up @@ -416,6 +421,59 @@ impl Builder {
self.store
}

/// Set's the maximum idle timeout a client can have before getting
/// automatically disconnected. Set [`None`] to disable automatic
/// disconnecting completely.
///
/// # Default
/// 10s
///
/// # Examples
/// ```
/// use std::time::Duration;
///
/// use fabruic::{Builder, Store};
///
/// let mut builder = Builder::new();
/// builder.set_max_idle_timeout(Some(Duration::from_millis(1000)));
/// ```
///
/// # Errors
/// [`Config::MaxIdleTimeout`](error::Config::MaxIdleTimeout) if time
/// exceeds 2^62 ms.
#[allow(clippy::unwrap_in_result)]
pub fn set_max_idle_timeout(&mut self, time: Option<Duration>) -> Result<(), error::Config> {
self.config.set_max_idle_timeout(time)
}

/// Returns the set [`Duration`] specified for idle clients to automatically
/// get disconnected. [`None`] means clients don't get automatically
/// disconnected.
///
/// See [`set_max_idle_timeout`](Self::set_max_idle_timeout).
///
/// # Examples
/// ```
/// use std::time::Duration;
///
/// use fabruic::{Builder, Store};
///
/// let mut builder = Builder::new();
///
/// // default
/// assert_eq!(builder.max_idle_timeout(), Some(Duration::from_secs(10)));
///
/// builder.set_max_idle_timeout(None);
/// assert_eq!(builder.max_idle_timeout(), None);
///
/// builder.set_max_idle_timeout(Some(Duration::from_secs(30)));
/// assert_eq!(builder.max_idle_timeout(), Some(Duration::from_secs(30)));
/// ```
#[must_use]
pub const fn max_idle_timeout(&self) -> Option<Duration> {
self.config.max_idle_timeout()
}

/// Consumes [`Builder`] to build [`Endpoint`]. Must be called from inside a
/// Tokio [`Runtime`](tokio::runtime::Runtime).
///
Expand Down Expand Up @@ -474,7 +532,7 @@ impl Builder {
let mut server = quinn::ServerConfig::with_crypto(Arc::new(crypto));

// set transport
server.transport = self.config.transport();
server.transport = Arc::new(self.config.transport());

server
});
Expand Down

0 comments on commit 4debce0

Please sign in to comment.