Skip to content

Commit

Permalink
TcpSocket: add set_linger method
Browse files Browse the repository at this point in the history
inspired by how it was done in net2

Signed-off-by: Marc-Antoine Perennou <Marc-Antoine@Perennou.com>
  • Loading branch information
Keruspe authored and Thomasdezeeuw committed Oct 14, 2020
1 parent a5381b3 commit 3b40965
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 0 deletions.
6 changes: 6 additions & 0 deletions src/net/tcp/socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::sys;
use std::io;
use std::mem;
use std::net::SocketAddr;
use std::time::Duration;
#[cfg(unix)]
use std::os::unix::io::{AsRawFd, RawFd, FromRawFd};
#[cfg(windows)]
Expand Down Expand Up @@ -80,6 +81,11 @@ impl TcpSocket {
pub fn set_reuseaddr(&self, reuseaddr: bool) -> io::Result<()> {
sys::tcp::set_reuseaddr(self.sys, reuseaddr)
}

/// Sets the value of `SO_LINGER` on this socket.
pub fn set_linger(&self, dur: Option<Duration>) -> io::Result<()> {
sys::tcp::set_linger(self.sys, dur)
}
}

impl Drop for TcpSocket {
Expand Down
5 changes: 5 additions & 0 deletions src/sys/shell/tcp.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::io;
use std::net::{self, SocketAddr};
use std::time::Duration;

pub(crate) type TcpSocket = i32;

Expand Down Expand Up @@ -31,6 +32,10 @@ pub(crate) fn set_reuseaddr(_: TcpSocket, _: bool) -> io::Result<()> {
os_required!();
}

pub(crate) fn set_linger(_: TcpSocket, _: Option<Duration>) -> io::Result<()> {
os_required!();
}

pub fn accept(_: &net::TcpListener) -> io::Result<(net::TcpStream, SocketAddr)> {
os_required!();
}
16 changes: 16 additions & 0 deletions src/sys/unix/tcp.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::io;
use std::mem::{size_of, MaybeUninit};
use std::net::{self, SocketAddr};
use std::time::Duration;
use std::os::unix::io::{AsRawFd, FromRawFd};

use crate::sys::unix::net::{new_socket, socket_addr, to_socket_addr};
Expand Down Expand Up @@ -58,6 +59,21 @@ pub(crate) fn set_reuseaddr(socket: TcpSocket, reuseaddr: bool) -> io::Result<()
Ok(())
}

pub(crate) fn set_linger(socket: TcpSocket, dur: Option<Duration>) -> io::Result<()> {
let val: libc::linger = libc::linger {
l_onoff: if dur.is_some() { 1 } else { 0 },
l_linger: dur.map(|dur| dur.as_secs() as libc::c_int).unwrap_or_default(),
};
syscall!(setsockopt(
socket,
libc::SOL_SOCKET,
libc::SO_LINGER,
&val as *const libc::linger as *const libc::c_void,
size_of::<libc::linger>() as libc::socklen_t,
))?;
Ok(())
}

pub fn accept(listener: &net::TcpListener) -> io::Result<(net::TcpStream, SocketAddr)> {
let mut addr: MaybeUninit<libc::sockaddr_storage> = MaybeUninit::uninit();
let mut length = size_of::<libc::sockaddr_storage>() as libc::socklen_t;
Expand Down
24 changes: 24 additions & 0 deletions src/sys/windows/tcp.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::io;
use std::net::{self, SocketAddr};
use std::time::Duration;
use std::os::windows::io::FromRawSocket;
use std::os::windows::raw::SOCKET as StdSocket; // winapi uses usize, stdlib uses u32/u64.

Expand Down Expand Up @@ -89,6 +90,29 @@ pub(crate) fn set_reuseaddr(socket: TcpSocket, reuseaddr: bool) -> io::Result<()
}
}

pub(crate) fn set_linger(socket: TcpSocket, dur: Option<Duration>) -> io::Result<()> {
use winapi::ctypes::{c_char, c_int, c_ushort};
use winapi::um::winsock2::{linger, setsockopt, SOCKET_ERROR, SO_LINGER, SOL_SOCKET};
use std::mem::size_of;

let val: linger = linger {
l_onoff: if dur.is_some() { 1 } else { 0 },
l_linger: dur.map(|dur| dur.as_secs() as c_ushort).unwrap_or_default(),
};

match unsafe { setsockopt(
socket,
SOL_SOCKET,
SO_LINGER,
&val as *const _ as *const c_char,
size_of::<linger>() as c_int,
) } {
0 => Ok(()),
SOCKET_ERROR => Err(io::Error::last_os_error()),
_ => panic!("unexpected return value"),
}
}

pub(crate) fn accept(listener: &net::TcpListener) -> io::Result<(net::TcpStream, SocketAddr)> {
// The non-blocking state of `listener` is inherited. See
// https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-accept#remarks.
Expand Down

0 comments on commit 3b40965

Please sign in to comment.