From 30a383100753351a6e42c451b11de78f3f1f4770 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Wed, 21 Oct 2015 21:39:25 -0700 Subject: [PATCH 01/16] Add set_nonblocking and take_error methods In line with net2 conventions --- Cargo.toml | 1 + src/lib.rs | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 7366106..b0fe101 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ keywords = ["posix", "unix", "socket", "domain"] [dependencies] libc = "0.1" debug-builders = "0.1" +cfg-if = "0.1" [dev-dependencies] tempdir = "0.3" diff --git a/src/lib.rs b/src/lib.rs index 266af43..88756b2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,6 +3,8 @@ #![doc(html_root_url="https://doc.rust-lang.org/unix-socket/doc/v0.4.6")] #![cfg_attr(all(test, feature = "socket_timeout"), feature(duration_span))] +#[macro_use] +extern crate cfg_if; extern crate debug_builders; extern crate libc; @@ -21,6 +23,14 @@ use std::fmt; use std::path::Path; use std::mem::size_of; +cfg_if! { + if #[cfg(any(target_os = "linux", target_os = "android"))] { + const FIONBIO: libc::c_int = 0x5421; + } else { + const FIONBIO: libc::c_ulong = 0x8004667e; + } +} + extern "C" { fn socketpair(domain: libc::c_int, ty: libc::c_int, @@ -28,7 +38,6 @@ extern "C" { sv: *mut [libc::c_int; 2]) -> libc::c_int; - #[cfg(feature = "socket_timeout")] fn getsockopt(socket: libc::c_int, level: libc::c_int, option_name: libc::c_int, @@ -167,6 +176,31 @@ impl Inner { .map(|_| ()) } } + + fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { + let mut nonblocking = nonblocking as libc::c_ulong; + unsafe { + cvt(libc::funcs::bsd44::ioctl(self.0, FIONBIO, &mut nonblocking)).map(|_| ()) + } + } + + fn take_error(&self) -> io::Result> { + let mut errno: libc::c_int = 0; + + unsafe { + try!(cvt(getsockopt(self.0, + libc::SOL_SOCKET, + libc::SO_ERROR, + &mut errno as *mut _ as *mut _, + &mut mem::size_of_val(&errno) as *mut _ as *mut _))); + } + + if errno == 0 { + Ok(None) + } else { + Ok(Some(io::Error::from_raw_os_error(errno))) + } + } } unsafe fn sockaddr_un>(path: P) @@ -424,6 +458,16 @@ impl UnixStream { self.inner.timeout(libc::SO_SNDTIMEO) } + /// Moves the socket into or out of nonblocking mode. + pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { + self.inner.set_nonblocking(nonblocking) + } + + /// Returns the value of the `SO_ERROR` option. + pub fn take_error(&self) -> io::Result> { + self.inner.take_error() + } + /// Shut down the read, write, or both halves of this connection. /// /// This function will cause all pending and future I/O calls on the @@ -585,6 +629,16 @@ impl UnixListener { SocketAddr::new(|addr, len| unsafe { libc::getsockname(self.inner.0, addr, len) }) } + /// Moves the socket into or out of nonblocking mode. + pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { + self.inner.set_nonblocking(nonblocking) + } + + /// Returns the value of the `SO_ERROR` option. + pub fn take_error(&self) -> io::Result> { + self.inner.take_error() + } + /// Returns an iterator over incoming connections. /// /// The iterator will never return `None`. @@ -843,6 +897,16 @@ impl UnixDatagram { self.inner.timeout(libc::SO_SNDTIMEO) } + /// Moves the socket into or out of nonblocking mode. + pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { + self.inner.set_nonblocking(nonblocking) + } + + /// Returns the value of the `SO_ERROR` option. + pub fn take_error(&self) -> io::Result> { + self.inner.take_error() + } + /// Shut down the read, write, or both halves of this connection. /// /// This function will cause all pending and future I/O calls on the From 5636dd389235cffa447d9662714fa57420e50af1 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Wed, 21 Oct 2015 21:59:26 -0700 Subject: [PATCH 02/16] Use libstd debug builders Also test on 1.2.0 expicitly to avoid surprise rustc version bumps --- .travis.yml | 2 +- Cargo.toml | 1 - src/lib.rs | 24 +++++++++++------------- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2c28d60..9cc3a1d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ language: rust rust: - nightly - beta -- stable +- 1.2.0 script: - cargo test - test $TRAVIS_RUST_VERSION != "nightly" || cargo test --features "from_raw_fd socket_timeout" diff --git a/Cargo.toml b/Cargo.toml index b0fe101..bf543dc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,6 @@ keywords = ["posix", "unix", "socket", "domain"] [dependencies] libc = "0.1" -debug-builders = "0.1" cfg-if = "0.1" [dev-dependencies] diff --git a/src/lib.rs b/src/lib.rs index 88756b2..7f452c5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,10 +5,8 @@ #[macro_use] extern crate cfg_if; -extern crate debug_builders; extern crate libc; -use debug_builders::DebugStruct; use std::ascii; use std::convert::AsRef; use std::cmp::{self, Ordering}; @@ -345,13 +343,13 @@ pub struct UnixStream { impl fmt::Debug for UnixStream { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - let mut builder = DebugStruct::new(fmt, "UnixStream") - .field("fd", &self.inner.0); + let mut builder = fmt.debug_struct("UnixStream"); + builder.field("fd", &self.inner.0); if let Ok(addr) = self.local_addr() { - builder = builder.field("local", &addr); + builder.field("local", &addr); } if let Ok(addr) = self.peer_addr() { - builder = builder.field("peer", &addr); + builder.field("peer", &addr); } builder.finish() } @@ -573,10 +571,10 @@ pub struct UnixListener { impl fmt::Debug for UnixListener { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - let mut builder = DebugStruct::new(fmt, "UnixListener") - .field("fd", &self.inner.0); + let mut builder = fmt.debug_struct("UnixListener"); + builder.field("fd", &self.inner.0); if let Ok(addr) = self.local_addr() { - builder = builder.field("local", &addr); + builder.field("local", &addr); } builder.finish() } @@ -713,13 +711,13 @@ pub struct UnixDatagram { impl fmt::Debug for UnixDatagram { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - let mut builder = DebugStruct::new(fmt, "UnixDatagram") - .field("fd", &self.inner.0); + let mut builder = fmt.debug_struct("UnixDatagram"); + builder.field("fd", &self.inner.0); if let Ok(addr) = self.local_addr() { - builder = builder.field("local", &addr); + builder.field("local", &addr); } if let Ok(addr) = self.peer_addr() { - builder = builder.field("peer", &addr); + builder.field("peer", &addr); } builder.finish() } From fd4a492311290f2b512f528753537e4e717ec875 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Tue, 3 Nov 2015 20:53:54 -0800 Subject: [PATCH 03/16] Update to libc 0.2 ioctl module location means we can't support both at the same time. --- Cargo.toml | 2 +- src/lib.rs | 37 +++++++++++-------------------------- 2 files changed, 12 insertions(+), 27 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index bf543dc..ad86ad9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ readme = "README.md" keywords = ["posix", "unix", "socket", "domain"] [dependencies] -libc = "0.1" +libc = "0.2" cfg-if = "0.1" [dev-dependencies] diff --git a/src/lib.rs b/src/lib.rs index 7f452c5..94e0129 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -21,27 +21,12 @@ use std::fmt; use std::path::Path; use std::mem::size_of; -cfg_if! { - if #[cfg(any(target_os = "linux", target_os = "android"))] { - const FIONBIO: libc::c_int = 0x5421; - } else { - const FIONBIO: libc::c_ulong = 0x8004667e; - } -} - extern "C" { fn socketpair(domain: libc::c_int, ty: libc::c_int, proto: libc::c_int, sv: *mut [libc::c_int; 2]) -> libc::c_int; - - fn getsockopt(socket: libc::c_int, - level: libc::c_int, - option_name: libc::c_int, - option_value: *mut libc::c_void, - option_len: *mut libc::c_void) - -> libc::c_int; } fn sun_path_offset() -> usize { @@ -118,11 +103,11 @@ impl Inner { let timeout = unsafe { let mut timeout: libc::timeval = mem::zeroed(); let mut size = mem::size_of::() as libc::socklen_t; - try!(cvt(getsockopt(self.0, - libc::SOL_SOCKET, - kind, - &mut timeout as *mut _ as *mut _, - &mut size as *mut _ as *mut _))); + try!(cvt(libc::getsockopt(self.0, + libc::SOL_SOCKET, + kind, + &mut timeout as *mut _ as *mut _, + &mut size as *mut _ as *mut _))); timeout }; @@ -178,7 +163,7 @@ impl Inner { fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { let mut nonblocking = nonblocking as libc::c_ulong; unsafe { - cvt(libc::funcs::bsd44::ioctl(self.0, FIONBIO, &mut nonblocking)).map(|_| ()) + cvt(libc::ioctl(self.0, libc::FIONBIO, &mut nonblocking)).map(|_| ()) } } @@ -186,11 +171,11 @@ impl Inner { let mut errno: libc::c_int = 0; unsafe { - try!(cvt(getsockopt(self.0, - libc::SOL_SOCKET, - libc::SO_ERROR, - &mut errno as *mut _ as *mut _, - &mut mem::size_of_val(&errno) as *mut _ as *mut _))); + try!(cvt(libc::getsockopt(self.0, + libc::SOL_SOCKET, + libc::SO_ERROR, + &mut errno as *mut _ as *mut _, + &mut mem::size_of_val(&errno) as *mut _ as *mut _))); } if errno == 0 { From 80cadbf74747b816d30295c5d181cdb9ffa65198 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Wed, 4 Nov 2015 19:31:36 -0800 Subject: [PATCH 04/16] Use socketpair from libc --- Cargo.toml | 2 +- src/lib.rs | 10 +--------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ad86ad9..4332cb7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ readme = "README.md" keywords = ["posix", "unix", "socket", "domain"] [dependencies] -libc = "0.2" +libc = "0.2.1" cfg-if = "0.1" [dev-dependencies] diff --git a/src/lib.rs b/src/lib.rs index 94e0129..5dc1e43 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -21,14 +21,6 @@ use std::fmt; use std::path::Path; use std::mem::size_of; -extern "C" { - fn socketpair(domain: libc::c_int, - ty: libc::c_int, - proto: libc::c_int, - sv: *mut [libc::c_int; 2]) - -> libc::c_int; -} - fn sun_path_offset() -> usize { unsafe { // Work with an actual instance of the type since using a null pointer is UB @@ -75,7 +67,7 @@ impl Inner { fn new_pair(kind: libc::c_int) -> io::Result<(Inner, Inner)> { unsafe { let mut fds = [0, 0]; - try!(cvt(socketpair(libc::AF_UNIX, kind, 0, &mut fds))); + try!(cvt(libc::socketpair(libc::AF_UNIX, kind, 0, fds.as_mut_ptr()))); Ok((Inner(fds[0]), Inner(fds[1]))) } } From 78d82dbb9e0b2fa8550e659ea429fc27f958d96c Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 5 Nov 2015 22:32:37 -0800 Subject: [PATCH 05/16] Get rid of calc_len size_t is not defined as usize so we don't need to cast anymore. --- src/lib.rs | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 5dc1e43..cd64c1b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,18 +8,18 @@ extern crate cfg_if; extern crate libc; use std::ascii; +use std::cmp::Ordering; use std::convert::AsRef; -use std::cmp::{self, Ordering}; use std::ffi::OsStr; +use std::fmt; use std::io; -use std::net::Shutdown; use std::iter::IntoIterator; use std::mem; -use std::os::unix::io::{RawFd, AsRawFd}; +use std::mem::size_of; +use std::net::Shutdown; use std::os::unix::ffi::OsStrExt; -use std::fmt; +use std::os::unix::io::{RawFd, AsRawFd}; use std::path::Path; -use std::mem::size_of; fn sun_path_offset() -> usize { unsafe { @@ -453,10 +453,6 @@ impl UnixStream { } } -fn calc_len(buf: &[u8]) -> libc::size_t { - cmp::min(libc::size_t::max_value() as usize, buf.len()) as libc::size_t -} - impl io::Read for UnixStream { fn read(&mut self, buf: &mut [u8]) -> io::Result { io::Read::read(&mut &*self, buf) @@ -466,7 +462,7 @@ impl io::Read for UnixStream { impl<'a> io::Read for &'a UnixStream { fn read(&mut self, buf: &mut [u8]) -> io::Result { unsafe { - cvt_s(libc::recv(self.inner.0, buf.as_mut_ptr() as *mut _, calc_len(buf), 0)) + cvt_s(libc::recv(self.inner.0, buf.as_mut_ptr() as *mut _, buf.len(), 0)) .map(|r| r as usize) } } @@ -485,7 +481,7 @@ impl io::Write for UnixStream { impl<'a> io::Write for &'a UnixStream { fn write(&mut self, buf: &[u8]) -> io::Result { unsafe { - cvt_s(libc::send(self.inner.0, buf.as_ptr() as *const _, calc_len(buf), 0)) + cvt_s(libc::send(self.inner.0, buf.as_ptr() as *const _, buf.len(), 0)) .map(|r| r as usize) } } @@ -775,7 +771,7 @@ impl UnixDatagram { unsafe { count = libc::recvfrom(self.inner.0, buf.as_mut_ptr() as *mut _, - calc_len(buf), + buf.len(), 0, addr, len); @@ -793,7 +789,7 @@ impl UnixDatagram { unsafe { let count = try!(cvt_s(libc::recv(self.inner.0, buf.as_mut_ptr() as *mut _, - calc_len(buf), + buf.len(), 0))); Ok(count as usize) } @@ -808,7 +804,7 @@ impl UnixDatagram { let count = try!(cvt_s(libc::sendto(self.inner.0, buf.as_ptr() as *const _, - calc_len(buf), + buf.len(), 0, &addr as *const _ as *const _, len))); @@ -826,7 +822,7 @@ impl UnixDatagram { unsafe { let count = try!(cvt_s(libc::send(self.inner.0, buf.as_ptr() as *const _, - calc_len(buf), + buf.len(), 0))); Ok(count as usize) } From 39ba6c724f1180c6e607e423f4dcb42a916e427c Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Wed, 4 Nov 2015 20:59:47 -0800 Subject: [PATCH 06/16] Refactor SocketAddr Turn it into an opaque struct with accessors for the various address flavors and move abstract path support to a linux-only extension trait. --- src/lib.rs | 162 +++++++++++++++++++++++++++++------------------------ 1 file changed, 90 insertions(+), 72 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index cd64c1b..4fa815c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -59,9 +59,7 @@ impl Drop for Inner { impl Inner { fn new(kind: libc::c_int) -> io::Result { - unsafe { - cvt(libc::socket(libc::AF_UNIX, kind, 0)).map(Inner) - } + unsafe { cvt(libc::socket(libc::AF_UNIX, kind, 0)).map(Inner) } } fn new_pair(kind: libc::c_int) -> io::Result<(Inner, Inner)> { @@ -73,9 +71,7 @@ impl Inner { } fn try_clone(&self) -> io::Result { - unsafe { - cvt(libc::dup(self.0)).map(Inner) - } + unsafe { cvt(libc::dup(self.0)).map(Inner) } } fn shutdown(&self, how: Shutdown) -> io::Result<()> { @@ -85,9 +81,7 @@ impl Inner { Shutdown::Both => libc::SHUT_RDWR, }; - unsafe { - cvt(libc::shutdown(self.0, how)).map(|_| ()) - } + unsafe { cvt(libc::shutdown(self.0, how)).map(|_| ()) } } #[cfg(feature = "socket_timeout")] @@ -154,9 +148,7 @@ impl Inner { fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { let mut nonblocking = nonblocking as libc::c_ulong; - unsafe { - cvt(libc::ioctl(self.0, libc::FIONBIO, &mut nonblocking)).map(|_| ()) - } + unsafe { cvt(libc::ioctl(self.0, libc::FIONBIO, &mut nonblocking)).map(|_| ()) } } fn take_error(&self) -> io::Result> { @@ -178,8 +170,7 @@ impl Inner { } } -unsafe fn sockaddr_un>(path: P) - -> io::Result<(libc::sockaddr_un, libc::socklen_t)> { +unsafe fn sockaddr_un>(path: P) -> io::Result<(libc::sockaddr_un, libc::socklen_t)> { let mut addr: libc::sockaddr_un = mem::zeroed(); addr.sun_family = libc::AF_UNIX as libc::sa_family_t; @@ -189,7 +180,7 @@ unsafe fn sockaddr_un>(path: P) // Abstract paths don't need a null terminator (Some(&0), Ordering::Greater) => { return Err(io::Error::new(io::ErrorKind::InvalidInput, - "path must be no longer than SUN_LEN")) + "path must be no longer than SUN_LEN")); } (_, Ordering::Greater) | (_, Ordering::Equal) => { return Err(io::Error::new(io::ErrorKind::InvalidInput, @@ -200,26 +191,20 @@ unsafe fn sockaddr_un>(path: P) for (dst, src) in addr.sun_path.iter_mut().zip(bytes.iter()) { *dst = *src as libc::c_char; } - // null byte for pathname addresses is already there because we zeroed the struct + // null byte for pathname addresses is already there because we zeroed the + // struct let mut len = sun_path_offset() + bytes.len(); match bytes.get(0) { Some(&0) | None => {} - Some(_) => len += 1 + Some(_) => len += 1, } Ok((addr, len as libc::socklen_t)) } -/// The kind of an address associated with a Unix socket. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum AddressKind<'a> { - /// An unnamed address. +enum AddressKind<'a> { Unnamed, - /// An address corresponding to a path on the filesystem. Pathname(&'a Path), - /// An address in an abstract namespace unrelated to the filesystem. - /// - /// Abstract addresses are a nonportable Linux extension. Abstract(&'a [u8]), } @@ -240,7 +225,8 @@ impl Clone for SocketAddr { impl SocketAddr { fn new(f: F) -> io::Result - where F: FnOnce(*mut libc::sockaddr, *mut libc::socklen_t) -> libc::c_int { + where F: FnOnce(*mut libc::sockaddr, *mut libc::socklen_t) -> libc::c_int + { unsafe { let mut addr: libc::sockaddr_un = mem::zeroed(); let mut len = mem::size_of::() as libc::socklen_t; @@ -262,8 +248,25 @@ impl SocketAddr { } } - /// Returns the value of the address. - pub fn address<'a>(&'a self) -> AddressKind<'a> { + /// Returns true iff the address is unnamed. + pub fn is_unnamed(&self) -> bool { + if let AddressKind::Unnamed = self.address() { + true + } else { + false + } + } + + /// Returns the contents of this address if it is a `pathname` address. + pub fn as_pathname(&self) -> Option<&Path> { + if let AddressKind::Pathname(path) = self.address() { + Some(path) + } else { + None + } + } + + fn address<'a>(&'a self) -> AddressKind<'a> { let len = self.len as usize - sun_path_offset(); let path = unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.addr.sun_path) }; @@ -283,7 +286,7 @@ impl fmt::Debug for SocketAddr { match self.address() { AddressKind::Unnamed => write!(fmt, "(unnamed)"), AddressKind::Abstract(name) => write!(fmt, "{} (abstract)", AsciiEscaped(name)), - AddressKind::Pathname(path) => write!(fmt, "{:?} (pathname)", path) + AddressKind::Pathname(path) => write!(fmt, "{:?} (pathname)", path), } } } @@ -300,6 +303,32 @@ impl<'a> fmt::Display for AsciiEscaped<'a> { } } +/// OS specific extension traits. +pub mod os { + /// Linux specific extension traits. + #[cfg(target_os = "linux")] + pub mod linux { + use ::{AddressKind, SocketAddr}; + + /// Linux specific extensions for the `SocketAddr` type. + pub trait SocketAddrExt { + /// Returns the contents of this address (without the leading + /// null byte) if it is an `abstract` address. + fn as_abstract(&self) -> Option<&[u8]>; + } + + impl SocketAddrExt for SocketAddr { + fn as_abstract(&self) -> Option<&[u8]> { + if let AddressKind::Abstract(path) = self.address() { + Some(path) + } else { + None + } + } + } + } +} + /// A Unix stream socket. /// /// # Examples @@ -349,9 +378,7 @@ impl UnixStream { if ret < 0 { Err(io::Error::last_os_error()) } else { - Ok(UnixStream { - inner: inner, - }) + Ok(UnixStream { inner: inner }) } } } @@ -378,9 +405,7 @@ impl UnixStream { /// data, and options set on one stream will be propogated to the other /// stream. pub fn try_clone(&self) -> io::Result { - Ok(UnixStream { - inner: try!(self.inner.try_clone()) - }) + Ok(UnixStream { inner: try!(self.inner.try_clone()) }) } /// Returns the socket address of the local half of this connection. @@ -501,9 +526,7 @@ impl AsRawFd for UnixStream { /// Requires the `from_raw_fd` feature (enabled by default). impl std::os::unix::io::FromRawFd for UnixStream { unsafe fn from_raw_fd(fd: RawFd) -> UnixStream { - UnixStream { - inner: Inner(fd) - } + UnixStream { inner: Inner(fd) } } } @@ -570,9 +593,7 @@ impl UnixListener { try!(cvt(libc::bind(inner.0, &addr as *const _ as *const _, len))); try!(cvt(libc::listen(inner.0, 128))); - Ok(UnixListener { - inner: inner, - }) + Ok(UnixListener { inner: inner }) } } @@ -590,9 +611,7 @@ impl UnixListener { /// object references. Both handles can be used to accept incoming /// connections and options set on one listener will affect the other. pub fn try_clone(&self) -> io::Result { - Ok(UnixListener { - inner: try!(self.inner.try_clone()) - }) + Ok(UnixListener { inner: try!(self.inner.try_clone()) }) } /// Returns the socket address of the local half of this connection. @@ -614,9 +633,7 @@ impl UnixListener { /// /// The iterator will never return `None`. pub fn incoming<'a>(&'a self) -> Incoming<'a> { - Incoming { - listener: self - } + Incoming { listener: self } } } @@ -630,9 +647,7 @@ impl AsRawFd for UnixListener { /// Requires the `from_raw_fd` feature (enabled by default). impl std::os::unix::io::FromRawFd for UnixListener { unsafe fn from_raw_fd(fd: RawFd) -> UnixListener { - UnixListener { - inner: Inner(fd) - } + UnixListener { inner: Inner(fd) } } } @@ -711,18 +726,14 @@ impl UnixDatagram { try!(cvt(libc::bind(inner.0, &addr as *const _ as *const _, len))); - Ok(UnixDatagram { - inner: inner, - }) + Ok(UnixDatagram { inner: inner }) } } /// Creates a Unix Datagram socket which is not bound to any address. pub fn unbound() -> io::Result { let inner = try!(Inner::new(libc::SOCK_DGRAM)); - Ok(UnixDatagram { - inner: inner, - }) + Ok(UnixDatagram { inner: inner }) } /// Create an unnamed pair of connected sockets. @@ -737,9 +748,7 @@ impl UnixDatagram { /// /// The `send` method may be used to send data to the specified address. /// `recv` and `recv_from` will only receive data from that address. - pub fn connect>(&self, path: P) - -> io::Result<()> - { + pub fn connect>(&self, path: P) -> io::Result<()> { unsafe { let (addr, len) = try!(sockaddr_un(path)); @@ -775,7 +784,13 @@ impl UnixDatagram { 0, addr, len); - if count > 0 { 1 } else if count == 0 { 0 } else { -1 } + if count > 0 { + 1 + } else if count == 0 { + 0 + } else { + -1 + } } })); @@ -821,9 +836,9 @@ impl UnixDatagram { pub fn send(&self, buf: &[u8]) -> io::Result { unsafe { let count = try!(cvt_s(libc::send(self.inner.0, - buf.as_ptr() as *const _, - buf.len(), - 0))); + buf.as_ptr() as *const _, + buf.len(), + 0))); Ok(count as usize) } } @@ -898,9 +913,7 @@ impl AsRawFd for UnixDatagram { /// Requires the `from_raw_fd` feature (enabled by default). impl std::os::unix::io::FromRawFd for UnixDatagram { unsafe fn from_raw_fd(fd: RawFd) -> UnixDatagram { - UnixDatagram { - inner: Inner(fd) - } + UnixDatagram { inner: Inner(fd) } } } @@ -913,7 +926,7 @@ mod test { use std::io::prelude::*; use self::tempdir::TempDir; - use {UnixListener, UnixStream, UnixDatagram, AddressKind}; + use super::*; macro_rules! or_panic { ($e:expr) => { @@ -941,6 +954,7 @@ mod test { }); let mut stream = or_panic!(UnixStream::connect(&socket_path)); + assert_eq!(Some(&*socket_path), stream.peer_addr().unwrap().as_pathname()); or_panic!(stream.write_all(msg1)); let mut buf = vec![]; or_panic!(stream.read_to_end(&mut buf)); @@ -974,8 +988,10 @@ mod test { } #[test] - #[cfg_attr(not(target_os = "linux"), ignore)] + #[cfg(target_os = "linux")] fn abstract_address() { + use ::os::linux::SocketAddrExt; + let socket_path = "\0the path"; let msg1 = b"hello"; let msg2 = b"world!"; @@ -990,6 +1006,7 @@ mod test { }); let mut stream = or_panic!(UnixStream::connect(&socket_path)); + assert_eq!(Some(&b"the path"[..]), stream.peer_addr().unwrap().as_abstract()); or_panic!(stream.write_all(msg1)); let mut buf = vec![]; or_panic!(stream.read_to_end(&mut buf)); @@ -1050,8 +1067,9 @@ mod test { #[test] fn long_path() { let dir = or_panic!(TempDir::new("unix_socket")); - let socket_path = dir.path().join("asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasd\ - fasdfasasdfasdfasdasdfasdfasdfadfasdfasdfasdfasdfasdf"); + let socket_path = dir.path() + .join("asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfa\ + sasdfasdfasdasdfasdfasdfadfasdfasdfasdfasdfasdf"); match UnixStream::connect(&socket_path) { Err(ref e) if e.kind() == io::ErrorKind::InvalidInput => {} Err(e) => panic!("unexpected error {}", e), @@ -1180,7 +1198,7 @@ mod test { let mut buf = [0; 11]; let (usize, addr) = or_panic!(sock1.recv_from(&mut buf)); assert_eq!(usize, 11); - assert_eq!(addr.address(), AddressKind::Unnamed); + assert!(addr.is_unnamed()); assert_eq!(msg, &buf[..]); } @@ -1201,7 +1219,7 @@ mod test { let mut buf = [0; 11]; let (usize, addr) = or_panic!(bsock1.recv_from(&mut buf)); assert_eq!(usize, 11); - assert_eq!(addr.address(), AddressKind::Unnamed); + assert!(addr.is_unnamed()); assert_eq!(msg, &buf[..]); // Changing default socket works too From c109d3daa95620a0b82532ab1c2eca3003329549 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 5 Nov 2015 22:49:07 -0800 Subject: [PATCH 07/16] Clean up stuff for breaking release --- .travis.yml | 1 - Cargo.toml | 6 ------ src/lib.rs | 60 +++++++---------------------------------------------- 3 files changed, 8 insertions(+), 59 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9cc3a1d..0f61743 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,4 +5,3 @@ rust: - 1.2.0 script: - cargo test -- test $TRAVIS_RUST_VERSION != "nightly" || cargo test --features "from_raw_fd socket_timeout" diff --git a/Cargo.toml b/Cargo.toml index 4332cb7..5cf8a8d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,9 +15,3 @@ cfg-if = "0.1" [dev-dependencies] tempdir = "0.3" - -[features] -default = ["from_raw_fd"] - -from_raw_fd = [] -socket_timeout = [] diff --git a/src/lib.rs b/src/lib.rs index 4fa815c..012ea1c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,6 @@ //! Support for Unix domain socket clients and servers. #![warn(missing_docs)] #![doc(html_root_url="https://doc.rust-lang.org/unix-socket/doc/v0.4.6")] -#![cfg_attr(all(test, feature = "socket_timeout"), feature(duration_span))] #[macro_use] extern crate cfg_if; @@ -18,7 +17,7 @@ use std::mem; use std::mem::size_of; use std::net::Shutdown; use std::os::unix::ffi::OsStrExt; -use std::os::unix::io::{RawFd, AsRawFd}; +use std::os::unix::io::{RawFd, AsRawFd, FromRawFd}; use std::path::Path; fn sun_path_offset() -> usize { @@ -84,7 +83,6 @@ impl Inner { unsafe { cvt(libc::shutdown(self.0, how)).map(|_| ()) } } - #[cfg(feature = "socket_timeout")] fn timeout(&self, kind: libc::c_int) -> io::Result> { let timeout = unsafe { let mut timeout: libc::timeval = mem::zeroed(); @@ -105,7 +103,6 @@ impl Inner { } } - #[cfg(feature = "socket_timeout")] fn set_timeout(&self, dur: Option, kind: libc::c_int) -> io::Result<()> { let timeout = match dur { Some(dur) => { @@ -423,9 +420,6 @@ impl UnixStream { /// If the provided value is `None`, then `read` calls will block /// indefinitely. It is an error to pass the zero `Duration` to this /// method. - /// - /// Requires the `socket_timeout` feature. - #[cfg(feature = "socket_timeout")] pub fn set_read_timeout(&self, timeout: Option) -> io::Result<()> { self.inner.set_timeout(timeout, libc::SO_RCVTIMEO) } @@ -435,25 +429,16 @@ impl UnixStream { /// If the provided value is `None`, then `write` calls will block /// indefinitely. It is an error to pass the zero `Duration` to this /// method. - /// - /// Requires the `socket_timeout` feature. - #[cfg(feature = "socket_timeout")] pub fn set_write_timeout(&self, timeout: Option) -> io::Result<()> { self.inner.set_timeout(timeout, libc::SO_SNDTIMEO) } /// Returns the read timeout of this socket. - /// - /// Requires the `socket_timeout` feature. - #[cfg(feature = "socket_timeout")] pub fn read_timeout(&self) -> io::Result> { self.inner.timeout(libc::SO_RCVTIMEO) } /// Returns the write timeout of this socket. - /// - /// Requires the `socket_timeout` feature. - #[cfg(feature = "socket_timeout")] pub fn write_timeout(&self) -> io::Result> { self.inner.timeout(libc::SO_SNDTIMEO) } @@ -522,9 +507,7 @@ impl AsRawFd for UnixStream { } } -#[cfg(feature = "from_raw_fd")] -/// Requires the `from_raw_fd` feature (enabled by default). -impl std::os::unix::io::FromRawFd for UnixStream { +impl FromRawFd for UnixStream { unsafe fn from_raw_fd(fd: RawFd) -> UnixStream { UnixStream { inner: Inner(fd) } } @@ -643,9 +626,7 @@ impl AsRawFd for UnixListener { } } -#[cfg(feature = "from_raw_fd")] -/// Requires the `from_raw_fd` feature (enabled by default). -impl std::os::unix::io::FromRawFd for UnixListener { +impl FromRawFd for UnixListener { unsafe fn from_raw_fd(fd: RawFd) -> UnixListener { UnixListener { inner: Inner(fd) } } @@ -848,9 +829,6 @@ impl UnixDatagram { /// If the provided value is `None`, then `recv` and `recv_from` calls will /// block indefinitely. It is an error to pass the zero `Duration` to this /// method. - /// - /// Requires the `socket_timeout` feature. - #[cfg(feature = "socket_timeout")] pub fn set_read_timeout(&self, timeout: Option) -> io::Result<()> { self.inner.set_timeout(timeout, libc::SO_RCVTIMEO) } @@ -860,25 +838,16 @@ impl UnixDatagram { /// If the provided value is `None`, then `send` and `send_to` calls will /// block indefinitely. It is an error to pass the zero `Duration` to this /// method. - /// - /// Requires the `socket_timeout` feature. - #[cfg(feature = "socket_timeout")] pub fn set_write_timeout(&self, timeout: Option) -> io::Result<()> { self.inner.set_timeout(timeout, libc::SO_SNDTIMEO) } /// Returns the read timeout of this socket. - /// - /// Requires the `socket_timeout` feature. - #[cfg(feature = "socket_timeout")] pub fn read_timeout(&self) -> io::Result> { self.inner.timeout(libc::SO_RCVTIMEO) } /// Returns the write timeout of this socket. - /// - /// Requires the `socket_timeout` feature. - #[cfg(feature = "socket_timeout")] pub fn write_timeout(&self) -> io::Result> { self.inner.timeout(libc::SO_SNDTIMEO) } @@ -909,9 +878,7 @@ impl AsRawFd for UnixDatagram { } } -#[cfg(feature = "from_raw_fd")] -/// Requires the `from_raw_fd` feature (enabled by default). -impl std::os::unix::io::FromRawFd for UnixDatagram { +impl FromRawFd for UnixDatagram { unsafe fn from_raw_fd(fd: RawFd) -> UnixDatagram { UnixDatagram { inner: Inner(fd) } } @@ -1090,7 +1057,6 @@ mod test { } #[test] - #[cfg(feature = "socket_timeout")] fn timeouts() { use std::time::Duration; @@ -1120,7 +1086,6 @@ mod test { } #[test] - #[cfg(feature = "socket_timeout")] fn test_read_timeout() { use std::time::Duration; @@ -1133,16 +1098,11 @@ mod test { or_panic!(stream.set_read_timeout(Some(Duration::from_millis(1000)))); let mut buf = [0; 10]; - let wait = Duration::span(|| { - let kind = stream.read(&mut buf).err().expect("expected error").kind(); - assert!(kind == io::ErrorKind::WouldBlock || kind == io::ErrorKind::TimedOut); - }); - assert!(wait > Duration::from_millis(400)); - assert!(wait < Duration::from_millis(1600)); + let kind = stream.read(&mut buf).err().expect("expected error").kind(); + assert!(kind == io::ErrorKind::WouldBlock || kind == io::ErrorKind::TimedOut); } #[test] - #[cfg(feature = "socket_timeout")] fn test_read_with_timeout() { use std::time::Duration; @@ -1161,12 +1121,8 @@ mod test { or_panic!(stream.read(&mut buf)); assert_eq!(b"hello world", &buf[..]); - let wait = Duration::span(|| { - let kind = stream.read(&mut buf).err().expect("expected error").kind(); - assert!(kind == io::ErrorKind::WouldBlock || kind == io::ErrorKind::TimedOut); - }); - assert!(wait > Duration::from_millis(400)); - assert!(wait < Duration::from_millis(1600)); + let kind = stream.read(&mut buf).err().expect("expected error").kind(); + assert!(kind == io::ErrorKind::WouldBlock || kind == io::ErrorKind::TimedOut); } #[test] From c9d3141f0caff279ab64775ae12dc8b677998793 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 5 Nov 2015 22:52:04 -0800 Subject: [PATCH 08/16] Implement IntoRawFd for the relevant types --- .travis.yml | 2 +- src/lib.rs | 26 +++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0f61743..d406dad 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,6 @@ language: rust rust: - nightly - beta -- 1.2.0 +- 1.4.0 script: - cargo test diff --git a/src/lib.rs b/src/lib.rs index 012ea1c..6955417 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,7 +17,7 @@ use std::mem; use std::mem::size_of; use std::net::Shutdown; use std::os::unix::ffi::OsStrExt; -use std::os::unix::io::{RawFd, AsRawFd, FromRawFd}; +use std::os::unix::io::{RawFd, AsRawFd, FromRawFd, IntoRawFd}; use std::path::Path; fn sun_path_offset() -> usize { @@ -513,6 +513,14 @@ impl FromRawFd for UnixStream { } } +impl IntoRawFd for UnixStream { + fn into_raw_fd(self) -> RawFd { + let fd = self.inner.0; + mem::forget(self); + fd + } +} + /// A structure representing a Unix domain socket server. /// /// # Examples @@ -632,6 +640,14 @@ impl FromRawFd for UnixListener { } } +impl IntoRawFd for UnixListener { + fn into_raw_fd(self) -> RawFd { + let fd = self.inner.0; + mem::forget(self); + fd + } +} + impl<'a> IntoIterator for &'a UnixListener { type Item = io::Result; type IntoIter = Incoming<'a>; @@ -884,6 +900,14 @@ impl FromRawFd for UnixDatagram { } } +impl IntoRawFd for UnixDatagram { + fn into_raw_fd(self) -> RawFd { + let fd = self.inner.0; + mem::forget(self); + fd + } +} + #[cfg(test)] mod test { extern crate tempdir; From 8f021886629b38e0422d2cb3251cb2fb8ca73e9d Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 5 Nov 2015 23:06:27 -0800 Subject: [PATCH 09/16] Remove deprecated method --- src/lib.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 6955417..88ce8b2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -388,13 +388,6 @@ impl UnixStream { Ok((UnixStream { inner: i1 }, UnixStream { inner: i2 })) } - /// # Deprecated - /// - /// Use `UnixStream::pair` instead. - pub fn unnamed() -> io::Result<(UnixStream, UnixStream)> { - UnixStream::pair() - } - /// Create a new independently owned handle to the underlying socket. /// /// The returned `UnixStream` is a reference to the same stream that this From b37f2c6722e3b1261790e2afdf905d15b7cbab19 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 5 Nov 2015 23:18:41 -0800 Subject: [PATCH 10/16] Adjust UnixListener::accept in line with TcpListener --- src/lib.rs | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 88ce8b2..990e0c7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -582,10 +582,19 @@ impl UnixListener { } /// Accepts a new incoming connection to this listener. - pub fn accept(&self) -> io::Result { + /// + /// This function will block the calling thread until a new Unix connection + /// is established. When established, the corersponding `UnixStream` and + /// the remote peer's address will be returned. + pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> { unsafe { - cvt(libc::accept(self.inner.0, 0 as *mut _, 0 as *mut _)) - .map(|fd| UnixStream { inner: Inner(fd) }) + let mut fd = 0; + let addr = try!(SocketAddr::new(|addr, len| { + fd = libc::accept(self.inner.0, addr, len); + fd + })); + + Ok((UnixStream { inner: Inner(fd) }, addr)) } } @@ -615,7 +624,8 @@ impl UnixListener { /// Returns an iterator over incoming connections. /// - /// The iterator will never return `None`. + /// The iterator will never return `None` and will also not yield the + /// peer's `SocketAddr` structure. pub fn incoming<'a>(&'a self) -> Incoming<'a> { Incoming { listener: self } } @@ -662,7 +672,7 @@ impl<'a> Iterator for Incoming<'a> { type Item = io::Result; fn next(&mut self) -> Option> { - Some(self.listener.accept()) + Some(self.listener.accept().map(|s| s.0)) } fn size_hint(&self) -> (usize, Option) { @@ -930,7 +940,7 @@ mod test { let listener = or_panic!(UnixListener::bind(&socket_path)); let thread = thread::spawn(move || { - let mut stream = or_panic!(listener.accept()); + let mut stream = or_panic!(listener.accept()).0; let mut buf = [0; 5]; or_panic!(stream.read(&mut buf)); assert_eq!(&msg1[..], &buf[..]); @@ -982,7 +992,7 @@ mod test { let listener = or_panic!(UnixListener::bind(&socket_path)); let thread = thread::spawn(move || { - let mut stream = or_panic!(listener.accept()); + let mut stream = or_panic!(listener.accept()).0; let mut buf = [0; 5]; or_panic!(stream.read(&mut buf)); assert_eq!(&msg1[..], &buf[..]); @@ -1009,7 +1019,7 @@ mod test { let listener = or_panic!(UnixListener::bind(&socket_path)); let thread = thread::spawn(move || { - let mut stream = or_panic!(listener.accept()); + let mut stream = or_panic!(listener.accept()).0; or_panic!(stream.write_all(msg1)); or_panic!(stream.write_all(msg2)); }); @@ -1131,7 +1141,7 @@ mod test { let mut stream = or_panic!(UnixStream::connect(&socket_path)); or_panic!(stream.set_read_timeout(Some(Duration::from_millis(1000)))); - let mut other_end = or_panic!(listener.accept()); + let mut other_end = or_panic!(listener.accept()).0; or_panic!(other_end.write_all(b"hello world")); let mut buf = [0; 11]; From 435556d9c57919f9e2694cf857f16d23f6e58193 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 5 Nov 2015 23:20:42 -0800 Subject: [PATCH 11/16] Doc fix --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 990e0c7..061263d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -607,7 +607,7 @@ impl UnixListener { Ok(UnixListener { inner: try!(self.inner.try_clone()) }) } - /// Returns the socket address of the local half of this connection. + /// Returns the local socket address of this listener. pub fn local_addr(&self) -> io::Result { SocketAddr::new(|addr, len| unsafe { libc::getsockname(self.inner.0, addr, len) }) } From 8f8c34e60ef832b6ed2e0bce1a9b110576221d93 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 5 Nov 2015 23:26:19 -0800 Subject: [PATCH 12/16] Derive clone --- src/lib.rs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 061263d..9c7ebd7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -206,20 +206,12 @@ enum AddressKind<'a> { } /// An address associated with a Unix socket. +#[derive(Clone)] pub struct SocketAddr { addr: libc::sockaddr_un, len: libc::socklen_t, } -impl Clone for SocketAddr { - fn clone(&self) -> SocketAddr { - SocketAddr { - addr: self.addr, - len: self.len, - } - } -} - impl SocketAddr { fn new(f: F) -> io::Result where F: FnOnce(*mut libc::sockaddr, *mut libc::socklen_t) -> libc::c_int From c186bcdb36b872d3498ba40cb1d5dba671a14435 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Fri, 6 Nov 2015 19:04:41 -0800 Subject: [PATCH 13/16] Import Duration --- src/lib.rs | 41 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 9c7ebd7..1cdf1c5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,6 +19,7 @@ use std::net::Shutdown; use std::os::unix::ffi::OsStrExt; use std::os::unix::io::{RawFd, AsRawFd, FromRawFd, IntoRawFd}; use std::path::Path; +use std::time::Duration; fn sun_path_offset() -> usize { unsafe { @@ -83,7 +84,7 @@ impl Inner { unsafe { cvt(libc::shutdown(self.0, how)).map(|_| ()) } } - fn timeout(&self, kind: libc::c_int) -> io::Result> { + fn timeout(&self, kind: libc::c_int) -> io::Result> { let timeout = unsafe { let mut timeout: libc::timeval = mem::zeroed(); let mut size = mem::size_of::() as libc::socklen_t; @@ -98,12 +99,11 @@ impl Inner { if timeout.tv_sec == 0 && timeout.tv_usec == 0 { Ok(None) } else { - Ok(Some(std::time::Duration::new(timeout.tv_sec as u64, - (timeout.tv_usec as u32) * 1000))) + Ok(Some(Duration::new(timeout.tv_sec as u64, (timeout.tv_usec as u32) * 1000))) } } - fn set_timeout(&self, dur: Option, kind: libc::c_int) -> io::Result<()> { + fn set_timeout(&self, dur: Option, kind: libc::c_int) -> io::Result<()> { let timeout = match dur { Some(dur) => { if dur.as_secs() == 0 && dur.subsec_nanos() == 0 { @@ -297,7 +297,7 @@ pub mod os { /// Linux specific extension traits. #[cfg(target_os = "linux")] pub mod linux { - use ::{AddressKind, SocketAddr}; + use {AddressKind, SocketAddr}; /// Linux specific extensions for the `SocketAddr` type. pub trait SocketAddrExt { @@ -405,7 +405,7 @@ impl UnixStream { /// If the provided value is `None`, then `read` calls will block /// indefinitely. It is an error to pass the zero `Duration` to this /// method. - pub fn set_read_timeout(&self, timeout: Option) -> io::Result<()> { + pub fn set_read_timeout(&self, timeout: Option) -> io::Result<()> { self.inner.set_timeout(timeout, libc::SO_RCVTIMEO) } @@ -414,17 +414,17 @@ impl UnixStream { /// If the provided value is `None`, then `write` calls will block /// indefinitely. It is an error to pass the zero `Duration` to this /// method. - pub fn set_write_timeout(&self, timeout: Option) -> io::Result<()> { + pub fn set_write_timeout(&self, timeout: Option) -> io::Result<()> { self.inner.set_timeout(timeout, libc::SO_SNDTIMEO) } /// Returns the read timeout of this socket. - pub fn read_timeout(&self) -> io::Result> { + pub fn read_timeout(&self) -> io::Result> { self.inner.timeout(libc::SO_RCVTIMEO) } /// Returns the write timeout of this socket. - pub fn write_timeout(&self) -> io::Result> { + pub fn write_timeout(&self) -> io::Result> { self.inner.timeout(libc::SO_SNDTIMEO) } @@ -840,7 +840,7 @@ impl UnixDatagram { /// If the provided value is `None`, then `recv` and `recv_from` calls will /// block indefinitely. It is an error to pass the zero `Duration` to this /// method. - pub fn set_read_timeout(&self, timeout: Option) -> io::Result<()> { + pub fn set_read_timeout(&self, timeout: Option) -> io::Result<()> { self.inner.set_timeout(timeout, libc::SO_RCVTIMEO) } @@ -849,17 +849,17 @@ impl UnixDatagram { /// If the provided value is `None`, then `send` and `send_to` calls will /// block indefinitely. It is an error to pass the zero `Duration` to this /// method. - pub fn set_write_timeout(&self, timeout: Option) -> io::Result<()> { + pub fn set_write_timeout(&self, timeout: Option) -> io::Result<()> { self.inner.set_timeout(timeout, libc::SO_SNDTIMEO) } /// Returns the read timeout of this socket. - pub fn read_timeout(&self) -> io::Result> { + pub fn read_timeout(&self) -> io::Result> { self.inner.timeout(libc::SO_RCVTIMEO) } /// Returns the write timeout of this socket. - pub fn write_timeout(&self) -> io::Result> { + pub fn write_timeout(&self) -> io::Result> { self.inner.timeout(libc::SO_SNDTIMEO) } @@ -910,6 +910,7 @@ mod test { use std::thread; use std::io; use std::io::prelude::*; + use std::time::Duration; use self::tempdir::TempDir; use super::*; @@ -940,7 +941,8 @@ mod test { }); let mut stream = or_panic!(UnixStream::connect(&socket_path)); - assert_eq!(Some(&*socket_path), stream.peer_addr().unwrap().as_pathname()); + assert_eq!(Some(&*socket_path), + stream.peer_addr().unwrap().as_pathname()); or_panic!(stream.write_all(msg1)); let mut buf = vec![]; or_panic!(stream.read_to_end(&mut buf)); @@ -976,7 +978,7 @@ mod test { #[test] #[cfg(target_os = "linux")] fn abstract_address() { - use ::os::linux::SocketAddrExt; + use os::linux::SocketAddrExt; let socket_path = "\0the path"; let msg1 = b"hello"; @@ -992,7 +994,8 @@ mod test { }); let mut stream = or_panic!(UnixStream::connect(&socket_path)); - assert_eq!(Some(&b"the path"[..]), stream.peer_addr().unwrap().as_abstract()); + assert_eq!(Some(&b"the path"[..]), + stream.peer_addr().unwrap().as_abstract()); or_panic!(stream.write_all(msg1)); let mut buf = vec![]; or_panic!(stream.read_to_end(&mut buf)); @@ -1077,8 +1080,6 @@ mod test { #[test] fn timeouts() { - use std::time::Duration; - let dir = or_panic!(TempDir::new("unix_socket")); let socket_path = dir.path().join("sock"); @@ -1106,8 +1107,6 @@ mod test { #[test] fn test_read_timeout() { - use std::time::Duration; - let dir = or_panic!(TempDir::new("unix_socket")); let socket_path = dir.path().join("sock"); @@ -1123,8 +1122,6 @@ mod test { #[test] fn test_read_with_timeout() { - use std::time::Duration; - let dir = or_panic!(TempDir::new("unix_socket")); let socket_path = dir.path().join("sock"); From f7989fcd8d242517a159f5cea67bdb4fa386e497 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Fri, 6 Nov 2015 19:08:49 -0800 Subject: [PATCH 14/16] Handle duration overflow a bit more properly --- src/lib.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 1cdf1c5..aecac89 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -111,14 +111,15 @@ impl Inner { "cannot set a 0 duration timeout")); } - let secs = if dur.as_secs() > libc::time_t::max_value() as u64 { - libc::time_t::max_value() + let (secs, usecs) = if dur.as_secs() > libc::time_t::max_value() as u64 { + (libc::time_t::max_value(), 999_999) } else { - dur.as_secs() as libc::time_t + (dur.as_secs() as libc::time_t, + (dur.subsec_nanos() / 1000) as libc::suseconds_t) }; let mut timeout = libc::timeval { tv_sec: secs, - tv_usec: (dur.subsec_nanos() / 1000) as libc::suseconds_t, + tv_usec: usecs, }; if timeout.tv_sec == 0 && timeout.tv_usec == 0 { timeout.tv_usec = 1; From 4930da1fa186c8571c2efbffb4433cdc4d56f1c5 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 7 Nov 2015 15:48:24 -0800 Subject: [PATCH 15/16] More doc cleanup --- src/lib.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index aecac89..b078413 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -352,7 +352,7 @@ impl fmt::Debug for UnixStream { } impl UnixStream { - /// Connect to the socket named by `path`. + /// Connects to the socket named by `path`. /// /// Linux provides, as a nonportable extension, a separate "abstract" /// address namespace as opposed to filesystem-based addressing. If `path` @@ -373,7 +373,7 @@ impl UnixStream { } } - /// Create an unnamed pair of connected sockets. + /// Creates an unnamed pair of connected sockets. /// /// Returns two `UnixStream`s which are connected to each other. pub fn pair() -> io::Result<(UnixStream, UnixStream)> { @@ -381,7 +381,7 @@ impl UnixStream { Ok((UnixStream { inner: i1 }, UnixStream { inner: i2 })) } - /// Create a new independently owned handle to the underlying socket. + /// Creates a new independently owned handle to the underlying socket. /// /// The returned `UnixStream` is a reference to the same stream that this /// object references. Both handles will read and write the same stream of @@ -439,7 +439,7 @@ impl UnixStream { self.inner.take_error() } - /// Shut down the read, write, or both halves of this connection. + /// Shuts down the read, write, or both halves of this connection. /// /// This function will cause all pending and future I/O calls on the /// specified portions to immediately return with an appropriate value @@ -554,8 +554,7 @@ impl fmt::Debug for UnixListener { } impl UnixListener { - /// Creates a new `UnixListener` which will be bound to the specified - /// socket. + /// Creates a new `UnixListener` bound to the specified socket. /// /// Linux provides, as a nonportable extension, a separate "abstract" /// address namespace as opposed to filesystem-based addressing. If `path` @@ -591,7 +590,7 @@ impl UnixListener { } } - /// Create a new independently owned handle to the underlying socket. + /// Creates a new independently owned handle to the underlying socket. /// /// The returned `UnixListener` is a reference to the same socket that this /// object references. Both handles can be used to accept incoming @@ -737,7 +736,7 @@ impl UnixDatagram { Ok((UnixDatagram { inner: i1 }, UnixDatagram { inner: i2 })) } - /// Connect the socket to the specified address. + /// Connects the socket to the specified address. /// /// The `send` method may be used to send data to the specified address. /// `recv` and `recv_from` will only receive data from that address. From 7545f68568ae25be9c109c129a069b3b093ea123 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Mon, 16 Nov 2015 22:06:19 -0800 Subject: [PATCH 16/16] Release v0.5.0 --- Cargo.toml | 4 ++-- src/lib.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5cf8a8d..5cc12fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,11 +1,11 @@ [package] name = "unix_socket" -version = "0.4.6" +version = "0.5.0" authors = ["Steven Fackler "] license = "MIT/Apache-2.0" description = "Unix domain socket bindings" repository = "https://github.com/rust-lang-nursery/unix-socket" -documentation = "https://doc.rust-lang.org/unix-socket/doc/v0.4.6/unix_socket" +documentation = "https://doc.rust-lang.org/unix-socket/doc/v0.5.0/unix_socket" readme = "README.md" keywords = ["posix", "unix", "socket", "domain"] diff --git a/src/lib.rs b/src/lib.rs index b078413..1b75ecd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,6 @@ //! Support for Unix domain socket clients and servers. #![warn(missing_docs)] -#![doc(html_root_url="https://doc.rust-lang.org/unix-socket/doc/v0.4.6")] +#![doc(html_root_url="https://doc.rust-lang.org/unix-socket/doc/v0.5.0")] #[macro_use] extern crate cfg_if;