Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions src/async_impl/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,12 @@ struct Config {
error: Option<crate::Error>,
https_only: bool,
#[cfg(feature = "http3")]
quic_local_port: Option<u16>,
#[cfg(feature = "http3")]
tls_enable_early_data: bool,
#[cfg(feature = "http3")]
quic_keep_alive_interval: Option<Duration>,
#[cfg(feature = "http3")]
quic_max_idle_timeout: Option<Duration>,
#[cfg(feature = "http3")]
quic_stream_receive_window: Option<VarInt>,
Expand Down Expand Up @@ -344,6 +348,10 @@ impl ClientBuilder {
#[cfg(feature = "http2")]
http2_keep_alive_while_idle: false,
local_address: None,
#[cfg(feature = "http3")]
quic_local_port: None,
#[cfg(feature = "http3")]
quic_keep_alive_interval: None,
#[cfg(any(
target_os = "android",
target_os = "fuchsia",
Expand Down Expand Up @@ -447,9 +455,11 @@ impl ClientBuilder {
quic_receive_window,
quic_send_window,
quic_congestion_bbr,
quic_keep_alive_interval,
h3_max_field_section_size,
h3_send_grease,
local_address,
local_port,
http_version_pref: &HttpVersionPref| {
let mut transport_config = TransportConfig::default();

Expand All @@ -471,6 +481,8 @@ impl ClientBuilder {
transport_config.send_window(send_window);
}

transport_config.keep_alive_interval(quic_keep_alive_interval);

if quic_congestion_bbr {
let factory = Arc::new(quinn::congestion::BbrConfig::default());
transport_config.congestion_controller_factory(factory);
Expand All @@ -490,6 +502,7 @@ impl ClientBuilder {
resolver,
tls,
local_address,
local_port,
transport_config,
h3_client_config,
);
Expand Down Expand Up @@ -633,9 +646,11 @@ impl ClientBuilder {
config.quic_receive_window,
config.quic_send_window,
config.quic_congestion_bbr,
config.quic_keep_alive_interval,
config.h3_max_field_section_size,
config.h3_send_grease,
config.local_address,
config.quic_local_port,
&config.http_version_pref,
)?;
}
Expand Down Expand Up @@ -838,9 +853,11 @@ impl ClientBuilder {
config.quic_receive_window,
config.quic_send_window,
config.quic_congestion_bbr,
config.quic_keep_alive_interval,
config.h3_max_field_section_size,
config.h3_send_grease,
config.local_address,
config.quic_local_port,
&config.http_version_pref,
)?;
}
Expand Down Expand Up @@ -2184,6 +2201,40 @@ impl ClientBuilder {
self
}

/// Bind to a local Port for QUIC connection.
///
/// # Example
///
/// ```
/// # fn doc() -> Result<(), reqwest::Error> {
/// let port = 12345;
/// let client = reqwest::Client::builder()
/// .http3_local_port(port)
/// .build()?;
/// # Ok(())
/// # }
/// ```
#[cfg(feature = "http3")]
pub fn http3_local_port(mut self, port: u16) -> ClientBuilder {
self.config.quic_local_port = Some(port);
self
}

/// Period of inactivity before sending a keep-alive packet
///
/// Keep-alive packets prevent an inactive but otherwise healthy connection from timing out.
///
/// Pass `None` to disable QUIC keep-alive. Only one side of any given connection needs keep-alive
/// enabled for the connection to be preserved. Must be set lower than the idle_timeout of both
/// peers to be effective.
/// Default is currently disabled.
#[cfg(feature = "http3")]
#[cfg_attr(docsrs, doc(cfg(feature = "http3")))]
pub fn http3_keep_alive_interval(mut self, timeout: Duration) -> ClientBuilder {
self.config.quic_keep_alive_interval = Some(timeout);
self
}

/// Maximum duration of inactivity to accept before timing out the QUIC connection.
///
/// Please see docs in [`TransportConfig`] in [`quinn`].
Expand Down
7 changes: 5 additions & 2 deletions src/async_impl/h3_client/connect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ impl H3Connector {
resolver: DynResolver,
tls: rustls::ClientConfig,
local_addr: Option<IpAddr>,
local_port: Option<u16>,
transport_config: TransportConfig,
client_config: H3ClientConfig,
) -> Result<H3Connector, BoxError> {
Expand All @@ -75,8 +76,10 @@ impl H3Connector {
config.transport_config(Arc::new(transport_config));

let socket_addr = match local_addr {
Some(ip) => SocketAddr::new(ip, 0),
None => "[::]:0".parse::<SocketAddr>().unwrap(),
Some(ip) => SocketAddr::new(ip, local_port.unwrap_or(0)),
None => format!("[::]:{}", local_port.unwrap_or(0))
.parse::<SocketAddr>()
.unwrap(),
};

let mut endpoint = Endpoint::client(socket_addr)?;
Expand Down
Loading