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

Commit 43ef565

Browse files
committed
Merge branch 'release-v0.4.4' into release
2 parents 621700e + 1a5023e commit 43ef565

File tree

3 files changed

+139
-12
lines changed

3 files changed

+139
-12
lines changed

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
[package]
22
name = "unix_socket"
3-
version = "0.4.3"
3+
version = "0.4.4"
44
authors = ["Steven Fackler <[email protected]>"]
55
license = "MIT"
66
description = "Unix domain socket bindings"
77
repository = "https://github.com/sfackler/rust-unix-socket"
8-
documentation = "https://sfackler.github.io/rust-unix-socket/doc/v0.4.3/unix_socket"
8+
documentation = "https://sfackler.github.io/rust-unix-socket/doc/v0.4.4/unix_socket"
99
readme = "README.md"
1010
keywords = ["posix", "unix", "socket", "domain"]
1111

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44

55
Support for Unix domain socket clients and servers.
66

7-
[Documentation](https://sfackler.github.io/rust-unix-socket/doc/v0.4.2/unix_socket)
7+
[Documentation](https://sfackler.github.io/rust-unix-socket/doc/v0.4.4/unix_socket)

src/lib.rs

Lines changed: 136 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Support for Unix domain socket clients and servers.
22
#![warn(missing_docs)]
3-
#![doc(html_root_url="https://sfackler.github.io/rust-unix-socket/doc/v0.4.3")]
3+
#![doc(html_root_url="https://sfackler.github.io/rust-unix-socket/doc/v0.4.4")]
44
#![cfg_attr(feature = "socket_timeout", feature(duration))]
55
#![cfg_attr(all(test, feature = "socket_timeout"), feature(duration_span))]
66

@@ -20,6 +20,7 @@ use std::os::unix::io::{RawFd, AsRawFd};
2020
use std::os::unix::ffi::OsStrExt;
2121
use std::fmt;
2222
use std::path::Path;
23+
use std::mem::size_of;
2324

2425
extern "C" {
2526
fn socketpair(domain: libc::c_int,
@@ -202,7 +203,7 @@ unsafe fn sockaddr_un<P: AsRef<Path>>(path: P)
202203
}
203204

204205
/// The kind of an address associated with a Unix socket.
205-
#[derive(Debug, Clone, Copy)]
206+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
206207
pub enum AddressKind<'a> {
207208
/// An unnamed address.
208209
Unnamed,
@@ -237,7 +238,13 @@ impl SocketAddr {
237238
let mut len = mem::size_of::<libc::sockaddr_un>() as libc::socklen_t;
238239
try!(cvt(f(&mut addr as *mut _ as *mut _, &mut len)));
239240

240-
if addr.sun_family != libc::AF_UNIX as libc::sa_family_t {
241+
if len == 0 {
242+
// When there is a datagram from unnamed unix socket
243+
// linux returns zero bytes of address
244+
len = sun_path_offset() as libc::socklen_t; // i.e. zero-length address
245+
} else if (len as usize) < size_of::<libc::sa_family_t>() ||
246+
addr.sun_family != libc::AF_UNIX as libc::sa_family_t
247+
{
241248
return Err(io::Error::new(io::ErrorKind::InvalidInput,
242249
"file descriptor did not correspond to a Unix socket"));
243250
}
@@ -472,8 +479,8 @@ impl AsRawFd for UnixStream {
472479
}
473480

474481
#[cfg(feature = "from_raw_fd")]
482+
/// Requires the `from_raw_fd` feature.
475483
impl std::os::unix::io::FromRawFd for UnixStream {
476-
/// Requires the `from_raw_fd` feature.
477484
unsafe fn from_raw_fd(fd: RawFd) -> UnixStream {
478485
UnixStream {
479486
inner: Inner(fd)
@@ -591,8 +598,8 @@ impl AsRawFd for UnixListener {
591598
}
592599

593600
#[cfg(feature = "from_raw_fd")]
601+
/// Requires the `from_raw_fd` feature.
594602
impl std::os::unix::io::FromRawFd for UnixListener {
595-
/// Requires the `from_raw_fd` feature.
596603
unsafe fn from_raw_fd(fd: RawFd) -> UnixListener {
597604
UnixListener {
598605
inner: Inner(fd)
@@ -658,7 +665,7 @@ impl fmt::Debug for UnixDatagram {
658665
}
659666

660667
impl UnixDatagram {
661-
/// Creates a Unix datagram socket from the given path.
668+
/// Creates a Unix datagram socket bound to the given path.
662669
pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixDatagram> {
663670
unsafe {
664671
let inner = try!(Inner::new(libc::SOCK_DGRAM));
@@ -672,6 +679,30 @@ impl UnixDatagram {
672679
}
673680
}
674681

682+
/// Creates a Unix Datagram socket which is not bound to any address.
683+
pub fn unbound() -> io::Result<UnixDatagram> {
684+
let inner = try!(Inner::new(libc::SOCK_DGRAM));
685+
Ok(UnixDatagram {
686+
inner: inner,
687+
})
688+
}
689+
690+
/// Connect the socket to the specified address.
691+
///
692+
/// The `send` method may be used to send data to the specified address.
693+
/// `recv` and `recv_from` will only receive data from that address.
694+
pub fn connect<P: AsRef<Path>>(&self, path: P)
695+
-> io::Result<()>
696+
{
697+
unsafe {
698+
let (addr, len) = try!(sockaddr_un(path));
699+
700+
try!(cvt(libc::connect(self.inner.0, &addr as *const _ as *const _, len)));
701+
702+
Ok(())
703+
}
704+
}
705+
675706
/// Returns the address of this socket.
676707
pub fn local_addr(&self) -> io::Result<SocketAddr> {
677708
SocketAddr::new(|addr, len| unsafe { libc::getsockname(self.inner.0, addr, len) })
@@ -698,7 +729,20 @@ impl UnixDatagram {
698729
Ok((count as usize, addr))
699730
}
700731

701-
/// Sends data on the socket to the given address.
732+
/// Receives data from the socket.
733+
///
734+
/// On success, returns the number of bytes read.
735+
pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
736+
unsafe {
737+
let count = try!(cvt_s(libc::recv(self.inner.0,
738+
buf.as_mut_ptr() as *mut _,
739+
calc_len(buf),
740+
0)));
741+
Ok(count as usize)
742+
}
743+
}
744+
745+
/// Sends data on the socket to the specified address.
702746
///
703747
/// On success, returns the number of bytes written.
704748
pub fn send_to<P: AsRef<Path>>(&self, buf: &[u8], path: P) -> io::Result<usize> {
@@ -715,6 +759,22 @@ impl UnixDatagram {
715759
}
716760
}
717761

762+
/// Sends data on the socket to the socket's peer.
763+
///
764+
/// The peer address may be set by the `connect` method, and this method
765+
/// will return an error if the socket has not already been connected.
766+
///
767+
/// On success, returns the number of bytes written.
768+
pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
769+
unsafe {
770+
let count = try!(cvt_s(libc::send(self.inner.0,
771+
buf.as_ptr() as *const _,
772+
calc_len(buf),
773+
0)));
774+
Ok(count as usize)
775+
}
776+
}
777+
718778
/// Sets the read timeout for the socket.
719779
///
720780
/// If the provided value is `None`, then `recv_from` calls will block
@@ -772,8 +832,8 @@ impl AsRawFd for UnixDatagram {
772832
}
773833

774834
#[cfg(feature = "from_raw_fd")]
835+
/// Requires the `from_raw_fd` feature.
775836
impl std::os::unix::io::FromRawFd for UnixDatagram {
776-
/// Requires the `from_raw_fd` feature.
777837
unsafe fn from_raw_fd(fd: RawFd) -> UnixDatagram {
778838
UnixDatagram {
779839
inner: Inner(fd)
@@ -790,7 +850,7 @@ mod test {
790850
use std::io::prelude::*;
791851
use self::tempdir::TempDir;
792852

793-
use {UnixListener, UnixStream, UnixDatagram};
853+
use {UnixListener, UnixStream, UnixDatagram, AddressKind};
794854

795855
macro_rules! or_panic {
796856
($e:expr) => {
@@ -1037,4 +1097,71 @@ mod test {
10371097
or_panic!(sock2.recv_from(&mut buf));
10381098
assert_eq!(msg, &buf[..]);
10391099
}
1100+
1101+
#[test]
1102+
fn test_unnamed_unix_datagram() {
1103+
let dir = or_panic!(TempDir::new("unix_socket"));
1104+
let path1 = dir.path().join("sock1");
1105+
1106+
let sock1 = or_panic!(UnixDatagram::bind(&path1));
1107+
let sock2 = or_panic!(UnixDatagram::unbound());
1108+
1109+
let msg = b"hello world";
1110+
or_panic!(sock2.send_to(msg, &path1));
1111+
let mut buf = [0; 11];
1112+
let (usize, addr) = or_panic!(sock1.recv_from(&mut buf));
1113+
assert_eq!(usize, 11);
1114+
assert_eq!(addr.address(), AddressKind::Unnamed);
1115+
assert_eq!(msg, &buf[..]);
1116+
}
1117+
1118+
#[test]
1119+
fn test_connect_unix_datagram() {
1120+
let dir = or_panic!(TempDir::new("unix_socket"));
1121+
let path1 = dir.path().join("sock1");
1122+
let path2 = dir.path().join("sock2");
1123+
1124+
let bsock1 = or_panic!(UnixDatagram::bind(&path1));
1125+
let bsock2 = or_panic!(UnixDatagram::bind(&path2));
1126+
let sock = or_panic!(UnixDatagram::unbound());
1127+
or_panic!(sock.connect(&path1));
1128+
1129+
// Check send()
1130+
let msg = b"hello there";
1131+
or_panic!(sock.send(msg));
1132+
let mut buf = [0; 11];
1133+
let (usize, addr) = or_panic!(bsock1.recv_from(&mut buf));
1134+
assert_eq!(usize, 11);
1135+
assert_eq!(addr.address(), AddressKind::Unnamed);
1136+
assert_eq!(msg, &buf[..]);
1137+
1138+
1139+
// Send to should still work too
1140+
let msg = b"hello world";
1141+
or_panic!(sock.send_to(msg, &path2));
1142+
or_panic!(bsock2.recv_from(&mut buf));
1143+
assert_eq!(msg, &buf[..]);
1144+
1145+
// Changing default socket works too
1146+
or_panic!(sock.connect(&path2));
1147+
or_panic!(sock.send(msg));
1148+
or_panic!(bsock2.recv_from(&mut buf));
1149+
}
1150+
1151+
#[test]
1152+
fn test_unix_datagram_recv() {
1153+
let dir = or_panic!(TempDir::new("unix_socket"));
1154+
let path1 = dir.path().join("sock1");
1155+
1156+
let sock1 = or_panic!(UnixDatagram::bind(&path1));
1157+
let sock2 = or_panic!(UnixDatagram::unbound());
1158+
or_panic!(sock2.connect(&path1));
1159+
1160+
let msg = b"hello world";
1161+
or_panic!(sock2.send_to(msg, &path1));
1162+
let mut buf = [0; 11];
1163+
let size = or_panic!(sock1.recv(&mut buf));
1164+
assert_eq!(size, 11);
1165+
assert_eq!(msg, &buf[..]);
1166+
}
10401167
}

0 commit comments

Comments
 (0)