Skip to content

Commit 2ea1052

Browse files
authored
feat(client): expose TCP socket send/recv buffer APIs (#843)
1 parent 0c40c3a commit 2ea1052

2 files changed

Lines changed: 56 additions & 24 deletions

File tree

src/client/http/mod.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,8 @@ struct Config {
132132
tcp_keepalive: Option<Duration>,
133133
tcp_keepalive_interval: Option<Duration>,
134134
tcp_keepalive_retries: Option<u32>,
135+
tcp_send_buffer_size: Option<usize>,
136+
tcp_recv_buffer_size: Option<usize>,
135137
tcp_connect_options: Option<TcpConnectOptions>,
136138
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
137139
tcp_user_timeout: Option<Duration>,
@@ -199,6 +201,8 @@ impl ClientBuilder {
199201
tcp_connect_options: None,
200202
tcp_nodelay: true,
201203
tcp_reuse_address: false,
204+
tcp_send_buffer_size: None,
205+
tcp_recv_buffer_size: None,
202206
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
203207
tcp_user_timeout: None,
204208
proxies: Vec::new(),
@@ -284,6 +288,8 @@ impl ClientBuilder {
284288
http.set_connect_options(config.tcp_connect_options);
285289
http.set_connect_timeout(config.connect_timeout);
286290
http.set_nodelay(config.tcp_nodelay);
291+
http.set_send_buffer_size(config.tcp_send_buffer_size);
292+
http.set_recv_buffer_size(config.tcp_recv_buffer_size);
287293
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
288294
http.set_tcp_user_timeout(config.tcp_user_timeout);
289295
};
@@ -947,6 +953,30 @@ impl ClientBuilder {
947953
self
948954
}
949955

956+
/// Sets the size of the TCP send buffer on this client socket.
957+
///
958+
/// On most operating systems, this sets the `SO_SNDBUF` socket option.
959+
#[inline]
960+
pub fn tcp_send_buffer_size<S>(mut self, size: S) -> ClientBuilder
961+
where
962+
S: Into<Option<usize>>,
963+
{
964+
self.config.tcp_send_buffer_size = size.into();
965+
self
966+
}
967+
968+
/// Sets the size of the TCP receive buffer on this client socket.
969+
///
970+
/// On most operating systems, this sets the `SO_RCVBUF` socket option.
971+
#[inline]
972+
pub fn tcp_recv_buffer_size<S>(mut self, size: S) -> ClientBuilder
973+
where
974+
S: Into<Option<usize>>,
975+
{
976+
self.config.tcp_recv_buffer_size = size.into();
977+
self
978+
}
979+
950980
/// Bind to a local IP Address.
951981
///
952982
/// # Example

src/core/client/connect/http.rs

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
#![allow(unused)]
21
use std::{
32
error::Error as StdError,
43
fmt,
@@ -131,13 +130,13 @@ impl TcpKeepaliveConfig {
131130
dirty = true
132131
}
133132

134-
/// Set the value of the `TCP_KEEPINTVL` option. On Windows, this sets the
135-
/// value of the `tcp_keepalive` struct's `keepaliveinterval` field.
136-
///
137-
/// Sets the time interval between TCP keepalive probes.
138-
///
139-
/// Some platforms specify this value in seconds, so sub-second
140-
/// specifications may be omitted.
133+
// Set the value of the `TCP_KEEPINTVL` option. On Windows, this sets the
134+
// value of the `tcp_keepalive` struct's `keepaliveinterval` field.
135+
//
136+
// Sets the time interval between TCP keepalive probes.
137+
//
138+
// Some platforms specify this value in seconds, so sub-second
139+
// specifications may be omitted.
141140
#[cfg(any(
142141
target_os = "android",
143142
target_os = "dragonfly",
@@ -161,10 +160,10 @@ impl TcpKeepaliveConfig {
161160
};
162161
}
163162

164-
/// Set the value of the `TCP_KEEPCNT` option.
165-
///
166-
/// Set the maximum number of TCP keepalive probes that will be sent before
167-
/// dropping a connection, if TCP keepalive is enabled on this socket.
163+
// Set the value of the `TCP_KEEPCNT` option.
164+
//
165+
// Set the maximum number of TCP keepalive probes that will be sent before
166+
// dropping a connection, if TCP keepalive is enabled on this socket.
168167
#[cfg(any(
169168
target_os = "android",
170169
target_os = "dragonfly",
@@ -311,6 +310,7 @@ impl<R> HttpConnector<R> {
311310
/// Default is 300 milliseconds.
312311
///
313312
/// [RFC 6555]: https://tools.ietf.org/html/rfc6555
313+
#[allow(unused)]
314314
#[inline]
315315
pub fn set_happy_eyeballs_timeout(&mut self, dur: Option<Duration>) {
316316
self.config_mut().happy_eyeballs_timeout = dur;
@@ -456,8 +456,8 @@ where
456456

457457
let sock = c.connect().await?;
458458

459-
if let Err(e) = sock.set_nodelay(config.nodelay) {
460-
warn!("tcp set_nodelay error: {}", e);
459+
if let Err(_e) = sock.set_nodelay(config.nodelay) {
460+
warn!("tcp set_nodelay error: {_e}");
461461
}
462462

463463
Ok(TokioIo::new(sock))
@@ -731,8 +731,8 @@ fn connect(
731731
.map_err(ConnectError::m("tcp set_nonblocking error"))?;
732732

733733
if let Some(tcp_keepalive) = &config.tcp_keepalive_config.into_tcpkeepalive() {
734-
if let Err(e) = socket.set_tcp_keepalive(tcp_keepalive) {
735-
warn!("tcp set_keepalive error: {}", e);
734+
if let Err(_e) = socket.set_tcp_keepalive(tcp_keepalive) {
735+
warn!("tcp set_keepalive error: {_e}");
736736
}
737737
}
738738

@@ -783,6 +783,7 @@ fn connect(
783783
io::Error::last_os_error(),
784784
)
785785
})?;
786+
786787
// Different setsockopt calls are necessary depending on whether the
787788
// address is IPv4 or IPv6.
788789
match addr {
@@ -795,8 +796,8 @@ fn connect(
795796

796797
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
797798
if let Some(tcp_user_timeout) = &config.tcp_user_timeout {
798-
if let Err(e) = socket.set_tcp_user_timeout(Some(*tcp_user_timeout)) {
799-
warn!("tcp set_tcp_user_timeout error: {}", e);
799+
if let Err(_e) = socket.set_tcp_user_timeout(Some(*tcp_user_timeout)) {
800+
warn!("tcp set_tcp_user_timeout error: {_e}");
800801
}
801802
}
802803

@@ -823,6 +824,7 @@ fn connect(
823824
use std::os::unix::io::{FromRawFd, IntoRawFd};
824825
TcpSocket::from_raw_fd(socket.into_raw_fd())
825826
};
827+
826828
#[cfg(windows)]
827829
let socket = unsafe {
828830
// Safety: `from_raw_socket` is only safe to call if ownership of the raw
@@ -834,20 +836,20 @@ fn connect(
834836
};
835837

836838
if config.reuse_address {
837-
if let Err(e) = socket.set_reuseaddr(true) {
838-
warn!("tcp set_reuse_address error: {}", e);
839+
if let Err(_e) = socket.set_reuseaddr(true) {
840+
warn!("tcp set_reuse_address error: {_e}");
839841
}
840842
}
841843

842844
if let Some(size) = config.send_buffer_size {
843-
if let Err(e) = socket.set_send_buffer_size(size.try_into().unwrap_or(u32::MAX)) {
844-
warn!("tcp set_buffer_size error: {}", e);
845+
if let Err(_e) = socket.set_send_buffer_size(size.try_into().unwrap_or(u32::MAX)) {
846+
warn!("tcp set_buffer_size error: {_e}");
845847
}
846848
}
847849

848850
if let Some(size) = config.recv_buffer_size {
849-
if let Err(e) = socket.set_recv_buffer_size(size.try_into().unwrap_or(u32::MAX)) {
850-
warn!("tcp set_recv_buffer_size error: {}", e);
851+
if let Err(_e) = socket.set_recv_buffer_size(size.try_into().unwrap_or(u32::MAX)) {
852+
warn!("tcp set_recv_buffer_size error: {_e}");
851853
}
852854
}
853855

0 commit comments

Comments
 (0)