]> git.lizzy.rs Git - rust.git/blobdiff - library/std/src/sys/unix/net.rs
add `TcpStream::set_linger` and `TcpStream::linger`
[rust.git] / library / std / src / sys / unix / net.rs
index c2f5da1dbbb1180cb785cf6691709172a6a065b2..d2e8c43a665954f57500935b5f508a73574a9cc0 100644 (file)
 
 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 @@ pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
         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)
     }