Skip to content

Commit 13e82ce

Browse files
Zeki SherifThomasdezeeuw
authored andcommitted
Support setting SO_LINGER
1 parent f5017fa commit 13e82ce

File tree

5 files changed

+67
-2
lines changed

5 files changed

+67
-2
lines changed

src/net/tcp/socket.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,11 @@ impl TcpSocket {
106106
sys::tcp::set_linger(self.sys, dur)
107107
}
108108

109+
/// Gets the value of `SO_LINGER` on this socket
110+
pub fn get_linger(&self) -> io::Result<Option<Duration>> {
111+
sys::tcp::get_linger(self.sys)
112+
}
113+
109114
/// Sets the value of `SO_RCVBUF` on this socket.
110115
pub fn set_recv_buffer_size(&self, size: u32) -> io::Result<()> {
111116
sys::tcp::set_recv_buffer_size(self.sys, size)

src/sys/shell/tcp.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ pub(crate) fn set_linger(_: TcpSocket, _: Option<Duration>) -> io::Result<()> {
5050
os_required!();
5151
}
5252

53+
pub(crate) fn get_linger(_: TcpSocket) -> io::Result<Option<Duration>> {
54+
os_required!();
55+
}
56+
5357
pub(crate) fn set_recv_buffer_size(_: TcpSocket, _: u32) -> io::Result<()> {
5458
os_required!();
5559
}

src/sys/unix/tcp.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,25 @@ pub(crate) fn set_linger(socket: TcpSocket, dur: Option<Duration>) -> io::Result
129129
)).map(|_| ())
130130
}
131131

132+
pub(crate) fn get_linger(socket: TcpSocket) -> io::Result<Option<Duration>> {
133+
let mut val: libc::linger = unsafe { std::mem::zeroed() };
134+
let mut len = mem::size_of::<libc::linger>() as libc::socklen_t;
135+
136+
syscall!(getsockopt(
137+
socket,
138+
libc::SOL_SOCKET,
139+
libc::SO_LINGER,
140+
&mut val as *mut _ as *mut _,
141+
&mut len,
142+
))?;
143+
144+
if val.l_onoff == 0 {
145+
Ok(None)
146+
} else {
147+
Ok(Some(Duration::from_secs(val.l_linger as u64)))
148+
}
149+
}
150+
132151
pub(crate) fn set_recv_buffer_size(socket: TcpSocket, size: u32) -> io::Result<()> {
133152
let size = size.try_into().ok().unwrap_or_else(i32::max_value);
134153
syscall!(setsockopt(

src/sys/windows/tcp.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,6 @@ pub(crate) fn get_localaddr(socket: TcpSocket) -> io::Result<SocketAddr> {
128128
}
129129
},
130130
}
131-
132-
133131
}
134132

135133
pub(crate) fn set_linger(socket: TcpSocket, dur: Option<Duration>) -> io::Result<()> {
@@ -150,6 +148,28 @@ pub(crate) fn set_linger(socket: TcpSocket, dur: Option<Duration>) -> io::Result
150148
}
151149
}
152150

151+
pub(crate) fn get_linger(socket: TcpSocket) -> io::Result<Option<Duration>> {
152+
let mut val: linger = unsafe { std::mem::zeroed() };
153+
let mut len = size_of::<linger>() as c_int;
154+
155+
match unsafe { getsockopt(
156+
socket,
157+
SOL_SOCKET,
158+
SO_LINGER,
159+
&mut val as *mut _ as *mut _,
160+
&mut len,
161+
) } {
162+
SOCKET_ERROR => Err(io::Error::last_os_error()),
163+
_ => {
164+
if val.l_onoff == 0 {
165+
Ok(None)
166+
} else {
167+
Ok(Some(Duration::from_secs(val.l_linger as u64)))
168+
}
169+
},
170+
}
171+
}
172+
153173

154174
pub(crate) fn set_recv_buffer_size(socket: TcpSocket, size: u32) -> io::Result<()> {
155175
let size = size.try_into().ok().unwrap_or_else(i32::max_value);

tests/tcp_socket.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
use mio::net::TcpSocket;
44
use std::io;
5+
use std::time::Duration;
56

67
#[test]
78
fn is_send_and_sync() {
@@ -58,6 +59,22 @@ fn get_localaddr() {
5859
let _ = socket.listen(128).unwrap();
5960
}
6061

62+
#[test]
63+
fn set_linger() {
64+
let addr = "127.0.0.1:0".parse().unwrap();
65+
66+
let socket = TcpSocket::new_v4().unwrap();
67+
socket.set_linger(Some(Duration::from_secs(1))).unwrap();
68+
assert_eq!(socket.get_linger().unwrap().unwrap().as_secs(), 1);
69+
70+
let _ = socket.set_linger(None);
71+
assert_eq!(socket.get_linger().unwrap(), None);
72+
73+
socket.bind(addr).unwrap();
74+
75+
let _ = socket.listen(128).unwrap();
76+
}
77+
6178
#[test]
6279
fn send_buffer_size_roundtrips() {
6380
test_buffer_sizes(

0 commit comments

Comments
 (0)