about summary refs log tree commit diff
path: root/library/std/src/sys/unix/net.rs
diff options
context:
space:
mode:
Diffstat (limited to 'library/std/src/sys/unix/net.rs')
-rw-r--r--library/std/src/sys/unix/net.rs23
1 files changed, 23 insertions, 0 deletions
diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs
index c2f5da1dbbb..d2e8c43a665 100644
--- a/library/std/src/sys/unix/net.rs
+++ b/library/std/src/sys/unix/net.rs
@@ -12,6 +12,14 @@ use crate::time::{Duration, Instant};
 
 use libc::{c_int, c_void, size_t, sockaddr, socklen_t, MSG_PEEK};
 
+cfg_if::cfg_if! {
+    if #[cfg(target_vendor = "apple")] {
+        use libc::SO_LINGER_SEC as SO_LINGER;
+    } else {
+        use libc::SO_LINGER;
+    }
+}
+
 pub use crate::sys::{cvt, cvt_r};
 
 #[allow(unused_extern_crates)]
@@ -376,6 +384,21 @@ impl Socket {
         Ok(())
     }
 
+    pub fn set_linger(&self, linger: Option<Duration>) -> io::Result<()> {
+        let linger = libc::linger {
+            l_onoff: linger.is_some() as libc::c_int,
+            l_linger: linger.map(|dur| dur.as_secs() as libc::c_int).unwrap_or_default(),
+        };
+
+        setsockopt(self, libc::SOL_SOCKET, SO_LINGER, linger)
+    }
+
+    pub fn linger(&self) -> io::Result<Option<Duration>> {
+        let val: libc::linger = getsockopt(self, libc::SOL_SOCKET, SO_LINGER)?;
+
+        Ok((val.l_onoff != 0).then(|| Duration::from_secs(val.l_linger as u64)))
+    }
+
     pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
         setsockopt(self, libc::IPPROTO_TCP, libc::TCP_NODELAY, nodelay as c_int)
     }