@@ -20,6 +20,7 @@ use std::os::unix::io::{RawFd, AsRawFd};
20
20
use std:: os:: unix:: ffi:: OsStrExt ;
21
21
use std:: fmt;
22
22
use std:: path:: Path ;
23
+ use std:: mem:: size_of;
23
24
24
25
extern "C" {
25
26
fn socketpair ( domain : libc:: c_int ,
@@ -202,7 +203,7 @@ unsafe fn sockaddr_un<P: AsRef<Path>>(path: P)
202
203
}
203
204
204
205
/// The kind of an address associated with a Unix socket.
205
- #[ derive( Debug , Clone , Copy ) ]
206
+ #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
206
207
pub enum AddressKind < ' a > {
207
208
/// An unnamed address.
208
209
Unnamed ,
@@ -237,7 +238,13 @@ impl SocketAddr {
237
238
let mut len = mem:: size_of :: < libc:: sockaddr_un > ( ) as libc:: socklen_t ;
238
239
try!( cvt ( f ( & mut addr as * mut _ as * mut _ , & mut len) ) ) ;
239
240
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
+ {
241
248
return Err ( io:: Error :: new ( io:: ErrorKind :: InvalidInput ,
242
249
"file descriptor did not correspond to a Unix socket" ) ) ;
243
250
}
@@ -672,6 +679,15 @@ impl UnixDatagram {
672
679
}
673
680
}
674
681
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
+
675
691
/// Returns the address of this socket.
676
692
pub fn local_addr ( & self ) -> io:: Result < SocketAddr > {
677
693
SocketAddr :: new ( |addr, len| unsafe { libc:: getsockname ( self . inner . 0 , addr, len) } )
@@ -790,7 +806,7 @@ mod test {
790
806
use std:: io:: prelude:: * ;
791
807
use self :: tempdir:: TempDir ;
792
808
793
- use { UnixListener , UnixStream , UnixDatagram } ;
809
+ use { UnixListener , UnixStream , UnixDatagram , AddressKind } ;
794
810
795
811
macro_rules! or_panic {
796
812
( $e: expr) => {
@@ -1037,4 +1053,21 @@ mod test {
1037
1053
or_panic ! ( sock2. recv_from( & mut buf) ) ;
1038
1054
assert_eq ! ( msg, & buf[ ..] ) ;
1039
1055
}
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
+ }
1040
1073
}
0 commit comments