| use super::*; |
| use crate::io::prelude::*; |
| use crate::io::{self, ErrorKind, IoSlice, IoSliceMut}; |
| #[cfg(any( |
| target_os = "android", |
| target_os = "dragonfly", |
| target_os = "emscripten", |
| target_os = "freebsd", |
| target_os = "linux", |
| target_os = "netbsd", |
| target_os = "openbsd", |
| ))] |
| #[cfg(any( |
| target_os = "android", |
| target_os = "dragonfly", |
| target_os = "emscripten", |
| target_os = "freebsd", |
| target_os = "linux", |
| target_os = "netbsd", |
| target_os = "openbsd", |
| ))] |
| use crate::os::unix::io::AsRawFd; |
| use crate::sys_common::io::test::tmpdir; |
| use crate::thread; |
| use crate::time::Duration; |
| |
| macro_rules! or_panic { |
| ($e:expr) => { |
| match $e { |
| Ok(e) => e, |
| Err(e) => panic!("{e}"), |
| } |
| }; |
| } |
| |
| #[test] |
| fn basic() { |
| let dir = tmpdir(); |
| let socket_path = dir.path().join("sock"); |
| let msg1 = b"hello"; |
| let msg2 = b"world!"; |
| |
| let listener = or_panic!(UnixListener::bind(&socket_path)); |
| let thread = thread::spawn(move || { |
| let mut stream = or_panic!(listener.accept()).0; |
| let mut buf = [0; 5]; |
| or_panic!(stream.read(&mut buf)); |
| assert_eq!(&msg1[..], &buf[..]); |
| or_panic!(stream.write_all(msg2)); |
| }); |
| |
| 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)); |
| assert_eq!(&msg2[..], &buf[..]); |
| drop(stream); |
| |
| thread.join().unwrap(); |
| } |
| |
| #[test] |
| fn vectored() { |
| let (mut s1, mut s2) = or_panic!(UnixStream::pair()); |
| |
| let len = or_panic!(s1.write_vectored(&[ |
| IoSlice::new(b"hello"), |
| IoSlice::new(b" "), |
| IoSlice::new(b"world!") |
| ],)); |
| assert_eq!(len, 12); |
| |
| let mut buf1 = [0; 6]; |
| let mut buf2 = [0; 7]; |
| let len = |
| or_panic!(s2.read_vectored(&mut [IoSliceMut::new(&mut buf1), IoSliceMut::new(&mut buf2)],)); |
| assert_eq!(len, 12); |
| assert_eq!(&buf1, b"hello "); |
| assert_eq!(&buf2, b"world!\0"); |
| } |
| |
| #[test] |
| fn pair() { |
| let msg1 = b"hello"; |
| let msg2 = b"world!"; |
| |
| 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]; |
| or_panic!(s1.read(&mut buf)); |
| assert_eq!(&msg1[..], &buf[..]); |
| or_panic!(s1.write_all(msg2)); |
| }); |
| |
| or_panic!(s2.write_all(msg1)); |
| let mut buf = vec![]; |
| or_panic!(s2.read_to_end(&mut buf)); |
| assert_eq!(&msg2[..], &buf[..]); |
| drop(s2); |
| |
| thread.join().unwrap(); |
| } |
| |
| #[test] |
| fn try_clone() { |
| let dir = tmpdir(); |
| let socket_path = dir.path().join("sock"); |
| let msg1 = b"hello"; |
| let msg2 = b"world"; |
| |
| let listener = or_panic!(UnixListener::bind(&socket_path)); |
| let thread = thread::spawn(move || { |
| let mut stream = or_panic!(listener.accept()).0; |
| or_panic!(stream.write_all(msg1)); |
| or_panic!(stream.write_all(msg2)); |
| }); |
| |
| let mut stream = or_panic!(UnixStream::connect(&socket_path)); |
| let mut stream2 = or_panic!(stream.try_clone()); |
| |
| let mut buf = [0; 5]; |
| or_panic!(stream.read(&mut buf)); |
| assert_eq!(&msg1[..], &buf[..]); |
| or_panic!(stream2.read(&mut buf)); |
| assert_eq!(&msg2[..], &buf[..]); |
| |
| thread.join().unwrap(); |
| } |
| |
| #[test] |
| fn iter() { |
| let dir = tmpdir(); |
| let socket_path = dir.path().join("sock"); |
| |
| let listener = or_panic!(UnixListener::bind(&socket_path)); |
| let thread = thread::spawn(move || { |
| for stream in listener.incoming().take(2) { |
| let mut stream = or_panic!(stream); |
| let mut buf = [0]; |
| or_panic!(stream.read(&mut buf)); |
| } |
| }); |
| |
| for _ in 0..2 { |
| let mut stream = or_panic!(UnixStream::connect(&socket_path)); |
| or_panic!(stream.write_all(&[0])); |
| } |
| |
| thread.join().unwrap(); |
| } |
| |
| #[test] |
| fn long_path() { |
| let dir = tmpdir(); |
| 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}"), |
| Ok(_) => panic!("unexpected success"), |
| } |
| |
| match UnixListener::bind(&socket_path) { |
| Err(ref e) if e.kind() == io::ErrorKind::InvalidInput => {} |
| 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] |
| fn timeouts() { |
| let dir = tmpdir(); |
| let socket_path = dir.path().join("sock"); |
| |
| let _listener = or_panic!(UnixListener::bind(&socket_path)); |
| |
| let stream = or_panic!(UnixStream::connect(&socket_path)); |
| let dur = Duration::new(15410, 0); |
| |
| assert_eq!(None, or_panic!(stream.read_timeout())); |
| |
| or_panic!(stream.set_read_timeout(Some(dur))); |
| assert_eq!(Some(dur), or_panic!(stream.read_timeout())); |
| |
| assert_eq!(None, or_panic!(stream.write_timeout())); |
| |
| or_panic!(stream.set_write_timeout(Some(dur))); |
| assert_eq!(Some(dur), or_panic!(stream.write_timeout())); |
| |
| or_panic!(stream.set_read_timeout(None)); |
| assert_eq!(None, or_panic!(stream.read_timeout())); |
| |
| or_panic!(stream.set_write_timeout(None)); |
| assert_eq!(None, or_panic!(stream.write_timeout())); |
| } |
| |
| #[test] |
| fn test_read_timeout() { |
| let dir = tmpdir(); |
| let socket_path = dir.path().join("sock"); |
| |
| let _listener = or_panic!(UnixListener::bind(&socket_path)); |
| |
| let mut stream = or_panic!(UnixStream::connect(&socket_path)); |
| or_panic!(stream.set_read_timeout(Some(Duration::from_millis(1000)))); |
| |
| let mut buf = [0; 10]; |
| let kind = stream.read_exact(&mut buf).err().expect("expected error").kind(); |
| assert!( |
| kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut, |
| "unexpected_error: {:?}", |
| kind |
| ); |
| } |
| |
| #[test] |
| fn test_read_with_timeout() { |
| let dir = tmpdir(); |
| let socket_path = dir.path().join("sock"); |
| |
| let listener = or_panic!(UnixListener::bind(&socket_path)); |
| |
| 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()).0; |
| or_panic!(other_end.write_all(b"hello world")); |
| |
| let mut buf = [0; 11]; |
| or_panic!(stream.read(&mut buf)); |
| assert_eq!(b"hello world", &buf[..]); |
| |
| let kind = stream.read_exact(&mut buf).err().expect("expected error").kind(); |
| assert!( |
| kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut, |
| "unexpected_error: {:?}", |
| kind |
| ); |
| } |
| |
| // Ensure the `set_read_timeout` and `set_write_timeout` calls return errors |
| // when passed zero Durations |
| #[test] |
| fn test_unix_stream_timeout_zero_duration() { |
| let dir = tmpdir(); |
| let socket_path = dir.path().join("sock"); |
| |
| let listener = or_panic!(UnixListener::bind(&socket_path)); |
| let stream = or_panic!(UnixStream::connect(&socket_path)); |
| |
| let result = stream.set_write_timeout(Some(Duration::new(0, 0))); |
| let err = result.unwrap_err(); |
| assert_eq!(err.kind(), ErrorKind::InvalidInput); |
| |
| let result = stream.set_read_timeout(Some(Duration::new(0, 0))); |
| let err = result.unwrap_err(); |
| assert_eq!(err.kind(), ErrorKind::InvalidInput); |
| |
| drop(listener); |
| } |
| |
| #[test] |
| fn test_unix_datagram() { |
| let dir = tmpdir(); |
| let path1 = dir.path().join("sock1"); |
| let path2 = dir.path().join("sock2"); |
| |
| let sock1 = or_panic!(UnixDatagram::bind(&path1)); |
| let sock2 = or_panic!(UnixDatagram::bind(&path2)); |
| |
| let msg = b"hello world"; |
| or_panic!(sock1.send_to(msg, &path2)); |
| let mut buf = [0; 11]; |
| or_panic!(sock2.recv_from(&mut buf)); |
| assert_eq!(msg, &buf[..]); |
| } |
| |
| #[test] |
| fn test_unnamed_unix_datagram() { |
| let dir = tmpdir(); |
| let path1 = dir.path().join("sock1"); |
| |
| let sock1 = or_panic!(UnixDatagram::bind(&path1)); |
| let sock2 = or_panic!(UnixDatagram::unbound()); |
| |
| let msg = b"hello world"; |
| or_panic!(sock2.send_to(msg, &path1)); |
| let mut buf = [0; 11]; |
| let (usize, addr) = or_panic!(sock1.recv_from(&mut buf)); |
| assert_eq!(usize, 11); |
| assert!(addr.is_unnamed()); |
| assert_eq!(msg, &buf[..]); |
| } |
| |
| #[test] |
| fn test_unix_datagram_connect_to_recv_addr() { |
| let dir = tmpdir(); |
| let path1 = dir.path().join("sock1"); |
| let path2 = dir.path().join("sock2"); |
| |
| let sock1 = or_panic!(UnixDatagram::bind(&path1)); |
| let sock2 = or_panic!(UnixDatagram::bind(&path2)); |
| |
| let msg = b"hello world"; |
| let sock1_addr = or_panic!(sock1.local_addr()); |
| or_panic!(sock2.send_to_addr(msg, &sock1_addr)); |
| let mut buf = [0; 11]; |
| let (_, addr) = or_panic!(sock1.recv_from(&mut buf)); |
| |
| let new_msg = b"hello back"; |
| let mut new_buf = [0; 10]; |
| or_panic!(sock2.connect_addr(&addr)); |
| or_panic!(sock2.send(new_msg)); // set by connect_addr |
| let usize = or_panic!(sock2.recv(&mut new_buf)); |
| assert_eq!(usize, 10); |
| assert_eq!(new_msg, &new_buf[..]); |
| } |
| |
| #[test] |
| fn test_connect_unix_datagram() { |
| let dir = tmpdir(); |
| let path1 = dir.path().join("sock1"); |
| let path2 = dir.path().join("sock2"); |
| |
| let bsock1 = or_panic!(UnixDatagram::bind(&path1)); |
| let bsock2 = or_panic!(UnixDatagram::bind(&path2)); |
| let sock = or_panic!(UnixDatagram::unbound()); |
| or_panic!(sock.connect(&path1)); |
| |
| // Check send() |
| let msg = b"hello there"; |
| or_panic!(sock.send(msg)); |
| let mut buf = [0; 11]; |
| let (usize, addr) = or_panic!(bsock1.recv_from(&mut buf)); |
| assert_eq!(usize, 11); |
| assert!(addr.is_unnamed()); |
| assert_eq!(msg, &buf[..]); |
| |
| // Changing default socket works too |
| or_panic!(sock.connect(&path2)); |
| or_panic!(sock.send(msg)); |
| or_panic!(bsock2.recv_from(&mut buf)); |
| } |
| |
| #[test] |
| fn test_unix_datagram_recv() { |
| let dir = tmpdir(); |
| let path1 = dir.path().join("sock1"); |
| |
| let sock1 = or_panic!(UnixDatagram::bind(&path1)); |
| let sock2 = or_panic!(UnixDatagram::unbound()); |
| or_panic!(sock2.connect(&path1)); |
| |
| let msg = b"hello world"; |
| 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(); |
| } |
| |
| // Ensure the `set_read_timeout` and `set_write_timeout` calls return errors |
| // when passed zero Durations |
| #[test] |
| fn test_unix_datagram_timeout_zero_duration() { |
| let dir = tmpdir(); |
| let path = dir.path().join("sock"); |
| |
| let datagram = or_panic!(UnixDatagram::bind(&path)); |
| |
| let result = datagram.set_write_timeout(Some(Duration::new(0, 0))); |
| let err = result.unwrap_err(); |
| assert_eq!(err.kind(), ErrorKind::InvalidInput); |
| |
| let result = datagram.set_read_timeout(Some(Duration::new(0, 0))); |
| let err = result.unwrap_err(); |
| assert_eq!(err.kind(), ErrorKind::InvalidInput); |
| } |
| |
| #[test] |
| fn abstract_namespace_not_allowed_connect() { |
| assert!(UnixStream::connect("\0asdf").is_err()); |
| } |
| |
| #[cfg(any(target_os = "android", target_os = "linux"))] |
| #[test] |
| fn test_abstract_stream_connect() { |
| let msg1 = b"hello"; |
| let msg2 = b"world"; |
| |
| let socket_addr = or_panic!(SocketAddr::from_abstract_namespace(b"namespace")); |
| let listener = or_panic!(UnixListener::bind_addr(&socket_addr)); |
| |
| let thread = thread::spawn(move || { |
| let mut stream = or_panic!(listener.accept()).0; |
| let mut buf = [0; 5]; |
| or_panic!(stream.read(&mut buf)); |
| assert_eq!(&msg1[..], &buf[..]); |
| or_panic!(stream.write_all(msg2)); |
| }); |
| |
| let mut stream = or_panic!(UnixStream::connect_addr(&socket_addr)); |
| |
| let peer = or_panic!(stream.peer_addr()); |
| assert_eq!(peer.as_abstract_namespace().unwrap(), b"namespace"); |
| |
| or_panic!(stream.write_all(msg1)); |
| let mut buf = vec![]; |
| or_panic!(stream.read_to_end(&mut buf)); |
| assert_eq!(&msg2[..], &buf[..]); |
| drop(stream); |
| |
| thread.join().unwrap(); |
| } |
| |
| #[cfg(any(target_os = "android", target_os = "linux"))] |
| #[test] |
| fn test_abstract_stream_iter() { |
| let addr = or_panic!(SocketAddr::from_abstract_namespace(b"hidden")); |
| let listener = or_panic!(UnixListener::bind_addr(&addr)); |
| |
| let thread = thread::spawn(move || { |
| for stream in listener.incoming().take(2) { |
| let mut stream = or_panic!(stream); |
| let mut buf = [0]; |
| or_panic!(stream.read(&mut buf)); |
| } |
| }); |
| |
| for _ in 0..2 { |
| let mut stream = or_panic!(UnixStream::connect_addr(&addr)); |
| or_panic!(stream.write_all(&[0])); |
| } |
| |
| thread.join().unwrap(); |
| } |
| |
| #[cfg(any(target_os = "android", target_os = "linux"))] |
| #[test] |
| fn test_abstract_datagram_bind_send_to_addr() { |
| let addr1 = or_panic!(SocketAddr::from_abstract_namespace(b"ns1")); |
| let sock1 = or_panic!(UnixDatagram::bind_addr(&addr1)); |
| |
| let local = or_panic!(sock1.local_addr()); |
| assert_eq!(local.as_abstract_namespace().unwrap(), b"ns1"); |
| |
| let addr2 = or_panic!(SocketAddr::from_abstract_namespace(b"ns2")); |
| let sock2 = or_panic!(UnixDatagram::bind_addr(&addr2)); |
| |
| let msg = b"hello world"; |
| or_panic!(sock1.send_to_addr(msg, &addr2)); |
| let mut buf = [0; 11]; |
| let (len, addr) = or_panic!(sock2.recv_from(&mut buf)); |
| assert_eq!(msg, &buf[..]); |
| assert_eq!(len, 11); |
| assert_eq!(addr.as_abstract_namespace().unwrap(), b"ns1"); |
| } |
| |
| #[cfg(any(target_os = "android", target_os = "linux"))] |
| #[test] |
| fn test_abstract_datagram_connect_addr() { |
| let addr1 = or_panic!(SocketAddr::from_abstract_namespace(b"ns3")); |
| let bsock1 = or_panic!(UnixDatagram::bind_addr(&addr1)); |
| |
| let sock = or_panic!(UnixDatagram::unbound()); |
| or_panic!(sock.connect_addr(&addr1)); |
| |
| let msg = b"hello world"; |
| or_panic!(sock.send(msg)); |
| let mut buf = [0; 11]; |
| let (len, addr) = or_panic!(bsock1.recv_from(&mut buf)); |
| assert_eq!(len, 11); |
| assert_eq!(addr.is_unnamed(), true); |
| assert_eq!(msg, &buf[..]); |
| |
| let addr2 = or_panic!(SocketAddr::from_abstract_namespace(b"ns4")); |
| let bsock2 = or_panic!(UnixDatagram::bind_addr(&addr2)); |
| |
| or_panic!(sock.connect_addr(&addr2)); |
| or_panic!(sock.send(msg)); |
| or_panic!(bsock2.recv_from(&mut buf)); |
| } |
| |
| #[cfg(any(target_os = "android", target_os = "linux"))] |
| #[test] |
| fn test_abstract_namespace_too_long() { |
| match SocketAddr::from_abstract_namespace( |
| b"abcdefghijklmnopqrstuvwxyzabcdefghijklmn\ |
| opqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghi\ |
| jklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz", |
| ) { |
| Err(ref e) if e.kind() == io::ErrorKind::InvalidInput => {} |
| Err(e) => panic!("unexpected error {e}"), |
| Ok(_) => panic!("unexpected success"), |
| } |
| } |
| |
| #[cfg(any(target_os = "android", target_os = "linux"))] |
| #[test] |
| fn test_abstract_namespace_no_pathname_and_not_unnamed() { |
| let namespace = b"local"; |
| let addr = or_panic!(SocketAddr::from_abstract_namespace(&namespace[..])); |
| assert_eq!(addr.as_pathname(), None); |
| assert_eq!(addr.as_abstract_namespace(), Some(&namespace[..])); |
| assert_eq!(addr.is_unnamed(), false); |
| } |
| |
| #[test] |
| fn test_unix_stream_peek() { |
| let (txdone, rxdone) = crate::sync::mpsc::channel(); |
| |
| let dir = tmpdir(); |
| let path = dir.path().join("sock"); |
| |
| let listener = or_panic!(UnixListener::bind(&path)); |
| let thread = thread::spawn(move || { |
| let mut stream = or_panic!(listener.accept()).0; |
| or_panic!(stream.write_all(&[1, 3, 3, 7])); |
| or_panic!(rxdone.recv()); |
| }); |
| |
| let mut stream = or_panic!(UnixStream::connect(&path)); |
| let mut buf = [0; 10]; |
| for _ in 0..2 { |
| assert_eq!(or_panic!(stream.peek(&mut buf)), 4); |
| } |
| assert_eq!(or_panic!(stream.read(&mut buf)), 4); |
| |
| or_panic!(stream.set_nonblocking(true)); |
| match stream.peek(&mut buf) { |
| Ok(_) => panic!("expected error"), |
| Err(ref e) if e.kind() == ErrorKind::WouldBlock => {} |
| Err(e) => panic!("unexpected error: {e}"), |
| } |
| |
| or_panic!(txdone.send(())); |
| thread.join().unwrap(); |
| } |
| |
| #[test] |
| fn test_unix_datagram_peek() { |
| let dir = tmpdir(); |
| let path1 = dir.path().join("sock"); |
| |
| let sock1 = or_panic!(UnixDatagram::bind(&path1)); |
| let sock2 = or_panic!(UnixDatagram::unbound()); |
| or_panic!(sock2.connect(&path1)); |
| |
| let msg = b"hello world"; |
| or_panic!(sock2.send(msg)); |
| for _ in 0..2 { |
| let mut buf = [0; 11]; |
| let size = or_panic!(sock1.peek(&mut buf)); |
| assert_eq!(size, 11); |
| assert_eq!(msg, &buf[..]); |
| } |
| |
| let mut buf = [0; 11]; |
| let size = or_panic!(sock1.recv(&mut buf)); |
| assert_eq!(size, 11); |
| assert_eq!(msg, &buf[..]); |
| } |
| |
| #[test] |
| fn test_unix_datagram_peek_from() { |
| let dir = tmpdir(); |
| let path1 = dir.path().join("sock"); |
| |
| let sock1 = or_panic!(UnixDatagram::bind(&path1)); |
| let sock2 = or_panic!(UnixDatagram::unbound()); |
| or_panic!(sock2.connect(&path1)); |
| |
| let msg = b"hello world"; |
| or_panic!(sock2.send(msg)); |
| for _ in 0..2 { |
| let mut buf = [0; 11]; |
| let (size, _) = or_panic!(sock1.peek_from(&mut buf)); |
| assert_eq!(size, 11); |
| assert_eq!(msg, &buf[..]); |
| } |
| |
| let mut buf = [0; 11]; |
| let size = or_panic!(sock1.recv(&mut buf)); |
| assert_eq!(size, 11); |
| assert_eq!(msg, &buf[..]); |
| } |
| |
| #[cfg(any( |
| target_os = "android", |
| target_os = "dragonfly", |
| target_os = "emscripten", |
| target_os = "freebsd", |
| target_os = "linux", |
| target_os = "netbsd", |
| target_os = "openbsd", |
| ))] |
| #[test] |
| fn test_send_vectored_fds_unix_stream() { |
| let (s1, s2) = or_panic!(UnixStream::pair()); |
| |
| let buf1 = [1; 8]; |
| let bufs_send = &[IoSlice::new(&buf1[..])][..]; |
| |
| let mut ancillary1_buffer = [0; 128]; |
| let mut ancillary1 = SocketAncillary::new(&mut ancillary1_buffer[..]); |
| assert!(ancillary1.add_fds(&[s1.as_raw_fd()][..])); |
| |
| let usize = or_panic!(s1.send_vectored_with_ancillary(&bufs_send, &mut ancillary1)); |
| assert_eq!(usize, 8); |
| |
| let mut buf2 = [0; 8]; |
| let mut bufs_recv = &mut [IoSliceMut::new(&mut buf2[..])][..]; |
| |
| let mut ancillary2_buffer = [0; 128]; |
| let mut ancillary2 = SocketAncillary::new(&mut ancillary2_buffer[..]); |
| |
| let usize = or_panic!(s2.recv_vectored_with_ancillary(&mut bufs_recv, &mut ancillary2)); |
| assert_eq!(usize, 8); |
| assert_eq!(buf1, buf2); |
| |
| let mut ancillary_data_vec = Vec::from_iter(ancillary2.messages()); |
| assert_eq!(ancillary_data_vec.len(), 1); |
| if let AncillaryData::ScmRights(scm_rights) = ancillary_data_vec.pop().unwrap().unwrap() { |
| let fd_vec = Vec::from_iter(scm_rights); |
| assert_eq!(fd_vec.len(), 1); |
| unsafe { |
| libc::close(fd_vec[0]); |
| } |
| } else { |
| unreachable!("must be ScmRights"); |
| } |
| } |
| |
| #[cfg(any(target_os = "android", target_os = "emscripten", target_os = "linux",))] |
| #[test] |
| fn test_send_vectored_with_ancillary_to_unix_datagram() { |
| fn getpid() -> libc::pid_t { |
| unsafe { libc::getpid() } |
| } |
| |
| fn getuid() -> libc::uid_t { |
| unsafe { libc::getuid() } |
| } |
| |
| fn getgid() -> libc::gid_t { |
| unsafe { libc::getgid() } |
| } |
| |
| let dir = tmpdir(); |
| let path1 = dir.path().join("sock1"); |
| let path2 = dir.path().join("sock2"); |
| |
| let bsock1 = or_panic!(UnixDatagram::bind(&path1)); |
| let bsock2 = or_panic!(UnixDatagram::bind(&path2)); |
| |
| or_panic!(bsock2.set_passcred(true)); |
| |
| let buf1 = [1; 8]; |
| let bufs_send = &[IoSlice::new(&buf1[..])][..]; |
| |
| let mut ancillary1_buffer = [0; 128]; |
| let mut ancillary1 = SocketAncillary::new(&mut ancillary1_buffer[..]); |
| let mut cred1 = SocketCred::new(); |
| cred1.set_pid(getpid()); |
| cred1.set_uid(getuid()); |
| cred1.set_gid(getgid()); |
| assert!(ancillary1.add_creds(&[cred1.clone()][..])); |
| |
| let usize = |
| or_panic!(bsock1.send_vectored_with_ancillary_to(&bufs_send, &mut ancillary1, &path2)); |
| assert_eq!(usize, 8); |
| |
| let mut buf2 = [0; 8]; |
| let mut bufs_recv = &mut [IoSliceMut::new(&mut buf2[..])][..]; |
| |
| let mut ancillary2_buffer = [0; 128]; |
| let mut ancillary2 = SocketAncillary::new(&mut ancillary2_buffer[..]); |
| |
| let (usize, truncated, _addr) = |
| or_panic!(bsock2.recv_vectored_with_ancillary_from(&mut bufs_recv, &mut ancillary2)); |
| assert_eq!(ancillary2.truncated(), false); |
| assert_eq!(usize, 8); |
| assert_eq!(truncated, false); |
| assert_eq!(buf1, buf2); |
| |
| let mut ancillary_data_vec = Vec::from_iter(ancillary2.messages()); |
| assert_eq!(ancillary_data_vec.len(), 1); |
| if let AncillaryData::ScmCredentials(scm_credentials) = |
| ancillary_data_vec.pop().unwrap().unwrap() |
| { |
| let cred_vec = Vec::from_iter(scm_credentials); |
| assert_eq!(cred_vec.len(), 1); |
| assert_eq!(cred1.get_pid(), cred_vec[0].get_pid()); |
| assert_eq!(cred1.get_uid(), cred_vec[0].get_uid()); |
| assert_eq!(cred1.get_gid(), cred_vec[0].get_gid()); |
| } else { |
| unreachable!("must be ScmCredentials"); |
| } |
| } |
| |
| #[cfg(any( |
| target_os = "android", |
| target_os = "dragonfly", |
| target_os = "emscripten", |
| target_os = "freebsd", |
| target_os = "linux", |
| target_os = "netbsd", |
| target_os = "openbsd", |
| ))] |
| #[test] |
| fn test_send_vectored_with_ancillary_unix_datagram() { |
| let dir = tmpdir(); |
| let path1 = dir.path().join("sock1"); |
| let path2 = dir.path().join("sock2"); |
| |
| let bsock1 = or_panic!(UnixDatagram::bind(&path1)); |
| let bsock2 = or_panic!(UnixDatagram::bind(&path2)); |
| |
| let buf1 = [1; 8]; |
| let bufs_send = &[IoSlice::new(&buf1[..])][..]; |
| |
| let mut ancillary1_buffer = [0; 128]; |
| let mut ancillary1 = SocketAncillary::new(&mut ancillary1_buffer[..]); |
| assert!(ancillary1.add_fds(&[bsock1.as_raw_fd()][..])); |
| |
| or_panic!(bsock1.connect(&path2)); |
| let usize = or_panic!(bsock1.send_vectored_with_ancillary(&bufs_send, &mut ancillary1)); |
| assert_eq!(usize, 8); |
| |
| let mut buf2 = [0; 8]; |
| let mut bufs_recv = &mut [IoSliceMut::new(&mut buf2[..])][..]; |
| |
| let mut ancillary2_buffer = [0; 128]; |
| let mut ancillary2 = SocketAncillary::new(&mut ancillary2_buffer[..]); |
| |
| let (usize, truncated) = |
| or_panic!(bsock2.recv_vectored_with_ancillary(&mut bufs_recv, &mut ancillary2)); |
| assert_eq!(usize, 8); |
| assert_eq!(truncated, false); |
| assert_eq!(buf1, buf2); |
| |
| let mut ancillary_data_vec = Vec::from_iter(ancillary2.messages()); |
| assert_eq!(ancillary_data_vec.len(), 1); |
| if let AncillaryData::ScmRights(scm_rights) = ancillary_data_vec.pop().unwrap().unwrap() { |
| let fd_vec = Vec::from_iter(scm_rights); |
| assert_eq!(fd_vec.len(), 1); |
| unsafe { |
| libc::close(fd_vec[0]); |
| } |
| } else { |
| unreachable!("must be ScmRights"); |
| } |
| } |