Skip to content
This repository has been archived by the owner on May 17, 2018. It is now read-only.

Commit

Permalink
Merge branch 'release-v0.4.5' into release
Browse files Browse the repository at this point in the history
  • Loading branch information
sfackler committed Aug 14, 2015
2 parents 43ef565 + d866f70 commit 04fcc9e
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 32 deletions.
6 changes: 4 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
[package]
name = "unix_socket"
version = "0.4.4"
version = "0.4.5"
authors = ["Steven Fackler <[email protected]>"]
license = "MIT"
description = "Unix domain socket bindings"
repository = "https://github.com/sfackler/rust-unix-socket"
documentation = "https://sfackler.github.io/rust-unix-socket/doc/v0.4.4/unix_socket"
documentation = "https://sfackler.github.io/rust-unix-socket/doc/v0.4.5/unix_socket"
readme = "README.md"
keywords = ["posix", "unix", "socket", "domain"]

Expand All @@ -17,5 +17,7 @@ debug-builders = "0.1"
tempdir = "0.3"

[features]
default = ["from_raw_fd"]

from_raw_fd = []
socket_timeout = []
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@

Support for Unix domain socket clients and servers.

[Documentation](https://sfackler.github.io/rust-unix-socket/doc/v0.4.4/unix_socket)
[Documentation](https://sfackler.github.io/rust-unix-socket/doc/v0.4.5/unix_socket)
109 changes: 80 additions & 29 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Support for Unix domain socket clients and servers.
#![warn(missing_docs)]
#![doc(html_root_url="https://sfackler.github.io/rust-unix-socket/doc/v0.4.4")]
#![doc(html_root_url="https://sfackler.github.io/rust-unix-socket/doc/v0.4.5")]
#![cfg_attr(feature = "socket_timeout", feature(duration))]
#![cfg_attr(all(test, feature = "socket_timeout"), feature(duration_span))]

Expand Down Expand Up @@ -81,10 +81,10 @@ impl Inner {
}
}

fn new_pair() -> io::Result<(Inner, Inner)> {
fn new_pair(kind: libc::c_int) -> io::Result<(Inner, Inner)> {
unsafe {
let mut fds = [0, 0];
try!(cvt(socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, &mut fds)));
try!(cvt(socketpair(libc::AF_UNIX, kind, 0, &mut fds)));
Ok((Inner(fds[0]), Inner(fds[1])))
}
}
Expand Down Expand Up @@ -132,19 +132,19 @@ impl Inner {
fn set_timeout(&self, dur: Option<std::time::Duration>, kind: libc::c_int) -> io::Result<()> {
let timeout = match dur {
Some(dur) => {
if dur.secs() == 0 && dur.extra_nanos() == 0 {
if dur.as_secs() == 0 && dur.subsec_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 {
let secs = if dur.as_secs() > libc::time_t::max_value() as u64 {
libc::time_t::max_value()
} else {
dur.secs() as libc::time_t
dur.as_secs() as libc::time_t
};
let mut timeout = libc::timeval {
tv_sec: secs,
tv_usec: (dur.extra_nanos() / 1000) as libc::suseconds_t,
tv_usec: (dur.subsec_nanos() / 1000) as libc::suseconds_t,
};
if timeout.tv_sec == 0 && timeout.tv_usec == 0 {
timeout.tv_usec = 1;
Expand Down Expand Up @@ -242,9 +242,7 @@ impl SocketAddr {
// When there is a datagram from unnamed unix socket
// linux returns zero bytes of address
len = sun_path_offset() as libc::socklen_t; // i.e. zero-length address
} else if (len as usize) < size_of::<libc::sa_family_t>() ||
addr.sun_family != libc::AF_UNIX as libc::sa_family_t
{
} else if addr.sun_family != libc::AF_UNIX as libc::sa_family_t {
return Err(io::Error::new(io::ErrorKind::InvalidInput,
"file descriptor did not correspond to a Unix socket"));
}
Expand Down Expand Up @@ -353,11 +351,18 @@ impl UnixStream {
/// Create an unnamed pair of connected sockets.
///
/// Returns two `UnixStream`s which are connected to each other.
pub fn unnamed() -> io::Result<(UnixStream, UnixStream)> {
let (i1, i2) = try!(Inner::new_pair());
pub fn pair() -> io::Result<(UnixStream, UnixStream)> {
let (i1, i2) = try!(Inner::new_pair(libc::SOCK_STREAM));
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
Expand Down Expand Up @@ -479,7 +484,7 @@ impl AsRawFd for UnixStream {
}

#[cfg(feature = "from_raw_fd")]
/// Requires the `from_raw_fd` feature.
/// 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 {
Expand Down Expand Up @@ -598,7 +603,7 @@ impl AsRawFd for UnixListener {
}

#[cfg(feature = "from_raw_fd")]
/// Requires the `from_raw_fd` feature.
/// 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 {
Expand Down Expand Up @@ -660,12 +665,21 @@ impl fmt::Debug for UnixDatagram {
if let Ok(addr) = self.local_addr() {
builder = builder.field("local", &addr);
}
if let Ok(addr) = self.peer_addr() {
builder = builder.field("peer", &addr);
}
builder.finish()
}
}

impl UnixDatagram {
/// Creates a Unix datagram socket bound to the given path.
///
/// Linux provides, as a nonportable extension, a separate "abstract"
/// address namespace as opposed to filesystem-based addressing. If `path`
/// begins with a null byte, it will be interpreted as an "abstract"
/// address. Otherwise, it will be interpreted as a "pathname" address,
/// corresponding to a path on the filesystem.
pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixDatagram> {
unsafe {
let inner = try!(Inner::new(libc::SOCK_DGRAM));
Expand All @@ -687,6 +701,14 @@ impl UnixDatagram {
})
}

/// Create an unnamed pair of connected sockets.
///
/// Returns two `UnixDatagrams`s which are connected to each other.
pub fn pair() -> io::Result<(UnixDatagram, UnixDatagram)> {
let (i1, i2) = try!(Inner::new_pair(libc::SOCK_DGRAM));
Ok((UnixDatagram { inner: i1 }, UnixDatagram { inner: i2 }))
}

/// Connect the socket to the specified address.
///
/// The `send` method may be used to send data to the specified address.
Expand All @@ -708,6 +730,13 @@ impl UnixDatagram {
SocketAddr::new(|addr, len| unsafe { libc::getsockname(self.inner.0, addr, len) })
}

/// Returns the address of this socket's peer.
///
/// The `connect` method will connect the socket to a peer.
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
SocketAddr::new(|addr, len| unsafe { libc::getpeername(self.inner.0, addr, len) })
}

/// Receives data from the socket.
///
/// On success, returns the number of bytes read and the address from
Expand Down Expand Up @@ -777,8 +806,8 @@ impl UnixDatagram {

/// Sets the read timeout for the socket.
///
/// If the provided value is `None`, then `recv_from` calls will block
/// indefinitely. It is an error to pass the zero `Duration` to this
/// 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.
Expand All @@ -789,8 +818,8 @@ impl UnixDatagram {

/// Sets the write timeout for the socket.
///
/// If the provided value is `None`, then `send_to` calls will block
/// indefinitely. It is an error to pass the zero `Duration` to this
/// 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.
Expand Down Expand Up @@ -832,7 +861,7 @@ impl AsRawFd for UnixDatagram {
}

#[cfg(feature = "from_raw_fd")]
/// Requires the `from_raw_fd` feature.
/// 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 {
Expand Down Expand Up @@ -888,11 +917,11 @@ mod test {
}

#[test]
fn unnamed() {
fn pair() {
let msg1 = b"hello";
let msg2 = b"world!";

let (mut s1, mut s2) = or_panic!(UnixStream::unnamed());
let (mut s1, mut s2) = or_panic!(UnixStream::pair());
let thread = thread::spawn(move || {
// s1 must be moved in or the test will hang!
let mut buf = [0; 5];
Expand Down Expand Up @@ -1000,6 +1029,12 @@ mod test {
Err(e) => panic!("unexpected error {}", e),
Ok(_) => panic!("unexpected success"),
}

match UnixDatagram::bind(&socket_path) {
Err(ref e) if e.kind() == io::ErrorKind::InvalidInput => {}
Err(e) => panic!("unexpected error {}", e),
Ok(_) => panic!("unexpected success"),
}
}

#[test]
Expand Down Expand Up @@ -1135,13 +1170,6 @@ mod test {
assert_eq!(addr.address(), AddressKind::Unnamed);
assert_eq!(msg, &buf[..]);


// Send to should still work too
let msg = b"hello world";
or_panic!(sock.send_to(msg, &path2));
or_panic!(bsock2.recv_from(&mut buf));
assert_eq!(msg, &buf[..]);

// Changing default socket works too
or_panic!(sock.connect(&path2));
or_panic!(sock.send(msg));
Expand All @@ -1158,10 +1186,33 @@ mod test {
or_panic!(sock2.connect(&path1));

let msg = b"hello world";
or_panic!(sock2.send_to(msg, &path1));
or_panic!(sock2.send(msg));
let mut buf = [0; 11];
let size = or_panic!(sock1.recv(&mut buf));
assert_eq!(size, 11);
assert_eq!(msg, &buf[..]);
}

#[test]
fn datagram_pair() {
let msg1 = b"hello";
let msg2 = b"world!";

let (s1, s2) = or_panic!(UnixDatagram::pair());
let thread = thread::spawn(move || {
// s1 must be moved in or the test will hang!
let mut buf = [0; 5];
or_panic!(s1.recv(&mut buf));
assert_eq!(&msg1[..], &buf[..]);
or_panic!(s1.send(msg2));
});

or_panic!(s2.send(msg1));
let mut buf = [0; 6];
or_panic!(s2.recv(&mut buf));
assert_eq!(&msg2[..], &buf[..]);
drop(s2);

thread.join().unwrap();
}
}

0 comments on commit 04fcc9e

Please sign in to comment.