refactor(client): use tokio's TcpSocket for more sockopts (#2335)
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
This commit is contained in:
@@ -35,7 +35,7 @@ itoa = "0.4.1"
|
|||||||
tracing = { version = "0.1", default-features = false, features = ["log", "std"] }
|
tracing = { version = "0.1", default-features = false, features = ["log", "std"] }
|
||||||
pin-project = "1.0"
|
pin-project = "1.0"
|
||||||
tower-service = "0.3"
|
tower-service = "0.3"
|
||||||
tokio = { version = "0.3", features = ["sync", "stream"] }
|
tokio = { version = "0.3.4", features = ["sync", "stream"] }
|
||||||
want = "0.3"
|
want = "0.3"
|
||||||
|
|
||||||
# Optional
|
# Optional
|
||||||
|
|||||||
@@ -569,10 +569,11 @@ fn connect(
|
|||||||
connect_timeout: Option<Duration>,
|
connect_timeout: Option<Duration>,
|
||||||
) -> Result<impl Future<Output = Result<TcpStream, ConnectError>>, ConnectError> {
|
) -> Result<impl Future<Output = Result<TcpStream, ConnectError>>, ConnectError> {
|
||||||
// TODO(eliza): if Tokio's `TcpSocket` gains support for setting the
|
// TODO(eliza): if Tokio's `TcpSocket` gains support for setting the
|
||||||
// keepalive timeout and send/recv buffer size, it would be nice to use that
|
// keepalive timeout, it would be nice to use that instead of socket2,
|
||||||
// instead of socket2, and avoid the unsafe `into_raw_fd`/`from_raw_fd`
|
// and avoid the unsafe `into_raw_fd`/`from_raw_fd` dance...
|
||||||
// dance...
|
|
||||||
use socket2::{Domain, Protocol, Socket, Type};
|
use socket2::{Domain, Protocol, Socket, Type};
|
||||||
|
use std::convert::TryInto;
|
||||||
|
|
||||||
let domain = match *addr {
|
let domain = match *addr {
|
||||||
SocketAddr::V4(_) => Domain::ipv4(),
|
SocketAddr::V4(_) => Domain::ipv4(),
|
||||||
SocketAddr::V6(_) => Domain::ipv6(),
|
SocketAddr::V6(_) => Domain::ipv6(),
|
||||||
@@ -580,18 +581,18 @@ fn connect(
|
|||||||
let socket = Socket::new(domain, Type::stream(), Some(Protocol::tcp()))
|
let socket = Socket::new(domain, Type::stream(), Some(Protocol::tcp()))
|
||||||
.map_err(ConnectError::m("tcp open error"))?;
|
.map_err(ConnectError::m("tcp open error"))?;
|
||||||
|
|
||||||
if config.reuse_address {
|
|
||||||
socket
|
|
||||||
.set_reuse_address(true)
|
|
||||||
.map_err(ConnectError::m("tcp set_reuse_address error"))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
// When constructing a Tokio `TcpSocket` from a raw fd/socket, the user is
|
// When constructing a Tokio `TcpSocket` from a raw fd/socket, the user is
|
||||||
// responsible for ensuring O_NONBLOCK is set.
|
// responsible for ensuring O_NONBLOCK is set.
|
||||||
socket
|
socket
|
||||||
.set_nonblocking(true)
|
.set_nonblocking(true)
|
||||||
.map_err(ConnectError::m("tcp set_nonblocking error"))?;
|
.map_err(ConnectError::m("tcp set_nonblocking error"))?;
|
||||||
|
|
||||||
|
if let Some(dur) = config.keep_alive_timeout {
|
||||||
|
socket
|
||||||
|
.set_keepalive(Some(dur))
|
||||||
|
.map_err(ConnectError::m("tcp set_keepalive error"))?;
|
||||||
|
}
|
||||||
|
|
||||||
bind_local_address(
|
bind_local_address(
|
||||||
&socket,
|
&socket,
|
||||||
addr,
|
addr,
|
||||||
@@ -600,24 +601,6 @@ fn connect(
|
|||||||
)
|
)
|
||||||
.map_err(ConnectError::m("tcp bind local error"))?;
|
.map_err(ConnectError::m("tcp bind local error"))?;
|
||||||
|
|
||||||
if let Some(dur) = config.keep_alive_timeout {
|
|
||||||
socket
|
|
||||||
.set_keepalive(Some(dur))
|
|
||||||
.map_err(ConnectError::m("tcp set_keepalive error"))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(size) = config.send_buffer_size {
|
|
||||||
socket
|
|
||||||
.set_send_buffer_size(size)
|
|
||||||
.map_err(ConnectError::m("tcp set_send_buffer_size error"))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(size) = config.recv_buffer_size {
|
|
||||||
socket
|
|
||||||
.set_recv_buffer_size(size)
|
|
||||||
.map_err(ConnectError::m("tcp set_recv_buffer_size error"))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
let socket = unsafe {
|
let socket = unsafe {
|
||||||
// Safety: `from_raw_fd` is only safe to call if ownership of the raw
|
// Safety: `from_raw_fd` is only safe to call if ownership of the raw
|
||||||
@@ -636,6 +619,25 @@ fn connect(
|
|||||||
use std::os::windows::io::{FromRawSocket, IntoRawSocket};
|
use std::os::windows::io::{FromRawSocket, IntoRawSocket};
|
||||||
TcpSocket::from_raw_socket(socket.into_raw_socket())
|
TcpSocket::from_raw_socket(socket.into_raw_socket())
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if config.reuse_address {
|
||||||
|
socket
|
||||||
|
.set_reuseaddr(true)
|
||||||
|
.map_err(ConnectError::m("tcp set_reuse_address error"))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(size) = config.send_buffer_size {
|
||||||
|
socket
|
||||||
|
.set_send_buffer_size(size.try_into().unwrap_or(std::u32::MAX))
|
||||||
|
.map_err(ConnectError::m("tcp set_send_buffer_size error"))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(size) = config.recv_buffer_size {
|
||||||
|
socket
|
||||||
|
.set_recv_buffer_size(size.try_into().unwrap_or(std::u32::MAX))
|
||||||
|
.map_err(ConnectError::m("tcp set_recv_buffer_size error"))?;
|
||||||
|
}
|
||||||
|
|
||||||
let connect = socket.connect(*addr);
|
let connect = socket.connect(*addr);
|
||||||
Ok(async move {
|
Ok(async move {
|
||||||
match connect_timeout {
|
match connect_timeout {
|
||||||
|
|||||||
Reference in New Issue
Block a user