about summary refs log tree commit diff
path: root/src/libstd/sys/unix/net.rs
diff options
context:
space:
mode:
authorSteven Fackler <sfackler@gmail.com>2015-05-26 23:47:03 -0700
committerSteven Fackler <sfackler@gmail.com>2015-05-28 20:03:20 -0700
commit69a0e1af9553ad50ee2d9c9176470ddeef70717c (patch)
tree96d0888e821b7787c5387b1c1c55a162c07f9be7 /src/libstd/sys/unix/net.rs
parent1a3cffbddfa21aac6fabd2f07f86703fbf1f26a5 (diff)
downloadrust-69a0e1af9553ad50ee2d9c9176470ddeef70717c.tar.gz
rust-69a0e1af9553ad50ee2d9c9176470ddeef70717c.zip
Implement RFC 1047 - socket timeouts
Closes #25619
Diffstat (limited to 'src/libstd/sys/unix/net.rs')
-rw-r--r--src/libstd/sys/unix/net.rs45
1 files changed, 45 insertions, 0 deletions
diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs
index 2e1cbb2a1e1..1f40c18be2f 100644
--- a/src/libstd/sys/unix/net.rs
+++ b/src/libstd/sys/unix/net.rs
@@ -18,6 +18,8 @@ use sys::c;
 use net::SocketAddr;
 use sys::fd::FileDesc;
 use sys_common::{AsInner, FromInner};
+use sys_common::net::{getsockopt, setsockopt};
+use time::Duration;
 
 pub use sys::{cvt, cvt_r};
 
@@ -73,6 +75,49 @@ impl Socket {
     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
         self.0.read(buf)
     }
+
+    pub fn set_timeout(&self, dur: Option<Duration>, kind: libc::c_int) -> io::Result<()> {
+        let timeout = match dur {
+            Some(dur) => {
+                if dur.secs() == 0 && dur.extra_nanos() == 0 {
+                    return Err(io::Error::new(io::ErrorKind::InvalidInput,
+                                              "cannot set a 0 duration timeout"));
+                }
+
+                let secs = if dur.secs() > libc::time_t::max_value() as u64 {
+                    libc::time_t::max_value()
+                } else {
+                    dur.secs() as libc::time_t
+                };
+                let mut timeout = libc::timeval {
+                    tv_sec: secs,
+                    tv_usec: (dur.extra_nanos() / 1000) as libc::suseconds_t,
+                };
+                if timeout.tv_sec == 0 && timeout.tv_usec == 0 {
+                    timeout.tv_usec = 1;
+                }
+                timeout
+            }
+            None => {
+                libc::timeval {
+                    tv_sec: 0,
+                    tv_usec: 0,
+                }
+            }
+        };
+        setsockopt(self, libc::SOL_SOCKET, kind, timeout)
+    }
+
+    pub fn timeout(&self, kind: libc::c_int) -> io::Result<Option<Duration>> {
+        let raw: libc::timeval = try!(getsockopt(self, libc::SOL_SOCKET, kind));
+        if raw.tv_sec == 0 && raw.tv_usec == 0 {
+            Ok(None)
+        } else {
+            let sec = raw.tv_sec as u64;
+            let nsec = (raw.tv_usec as u32) * 1000;
+            Ok(Some(Duration::new(sec, nsec)))
+        }
+    }
 }
 
 impl AsInner<c_int> for Socket {