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

Commit 65cd124

Browse files
committed
Merge pull request #14 from tailhook/unix_datagram_new
Implement UnixDatagram::new()
2 parents d0f47ae + 232823d commit 65cd124

File tree

1 file changed

+36
-3
lines changed

1 file changed

+36
-3
lines changed

src/lib.rs

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -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
}
@@ -672,6 +679,15 @@ impl UnixDatagram {
672679
}
673680
}
674681

682+
/// Creates a Unix Datagram socket which is not bound to any address
683+
/// you may use send_to to send message (but probably can't receive)
684+
pub fn new() -> io::Result<UnixDatagram> {
685+
let inner = try!(Inner::new(libc::SOCK_DGRAM));
686+
Ok(UnixDatagram {
687+
inner: inner,
688+
})
689+
}
690+
675691
/// Returns the address of this socket.
676692
pub fn local_addr(&self) -> io::Result<SocketAddr> {
677693
SocketAddr::new(|addr, len| unsafe { libc::getsockname(self.inner.0, addr, len) })
@@ -790,7 +806,7 @@ mod test {
790806
use std::io::prelude::*;
791807
use self::tempdir::TempDir;
792808

793-
use {UnixListener, UnixStream, UnixDatagram};
809+
use {UnixListener, UnixStream, UnixDatagram, AddressKind};
794810

795811
macro_rules! or_panic {
796812
($e:expr) => {
@@ -1037,4 +1053,21 @@ mod test {
10371053
or_panic!(sock2.recv_from(&mut buf));
10381054
assert_eq!(msg, &buf[..]);
10391055
}
1056+
1057+
#[test]
1058+
fn test_unnamed_unix_datagram() {
1059+
let dir = or_panic!(TempDir::new("unix_socket"));
1060+
let path1 = dir.path().join("sock1");
1061+
1062+
let sock1 = or_panic!(UnixDatagram::bind(&path1));
1063+
let sock2 = or_panic!(UnixDatagram::new());
1064+
1065+
let msg = b"hello world";
1066+
or_panic!(sock2.send_to(msg, &path1));
1067+
let mut buf = [0; 11];
1068+
let (usize, addr) = or_panic!(sock1.recv_from(&mut buf));
1069+
assert_eq!(usize, 11);
1070+
assert_eq!(addr.address(), AddressKind::Unnamed);
1071+
assert_eq!(msg, &buf[..]);
1072+
}
10401073
}

0 commit comments

Comments
 (0)