diff options
-rw-r--r-- | src/sys/socket/ffi.rs | 7 | ||||
-rw-r--r-- | src/sys/socket/mod.rs | 34 | ||||
-rw-r--r-- | test/sys/test_socket.rs | 15 |
3 files changed, 56 insertions, 0 deletions
diff --git a/src/sys/socket/ffi.rs b/src/sys/socket/ffi.rs index 612854de..c445c8c9 100644 --- a/src/sys/socket/ffi.rs +++ b/src/sys/socket/ffi.rs @@ -8,4 +8,11 @@ extern { optname: c_int, optval: *mut c_void, optlen: *mut socklen_t) -> c_int; + + pub fn socketpair( + domain: c_int, + typ: c_int, + protocol: c_int, + sv: *mut c_int + ) -> c_int; } diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs index 72bc4ccf..33f02ee7 100644 --- a/src/sys/socket/mod.rs +++ b/src/sys/socket/mod.rs @@ -105,6 +105,40 @@ pub fn socket(domain: AddressFamily, ty: SockType, flags: SockFlag) -> Result<Fd Ok(res) } +/// Create a pair of connected sockets +/// +/// [Further reading](http://man7.org/linux/man-pages/man2/socketpair.2.html) +pub fn socketpair(domain: AddressFamily, ty: SockType, protocol: c_int, + flags: SockFlag) -> Result<(Fd, Fd)> { + let mut ty = ty as c_int; + let feat_atomic = features::socket_atomic_cloexec(); + + if feat_atomic { + ty = ty | flags.bits(); + } + let mut fds = [-1, -1]; + let res = unsafe { + ffi::socketpair(domain as c_int, ty, protocol, fds.as_mut_ptr()) + }; + + if res < 0 { + return Err(Error::Sys(Errno::last())); + } + + if !feat_atomic { + if flags.contains(SOCK_CLOEXEC) { + try!(fcntl(fds[0], F_SETFD(FD_CLOEXEC))); + try!(fcntl(fds[1], F_SETFD(FD_CLOEXEC))); + } + + if flags.contains(SOCK_NONBLOCK) { + try!(fcntl(fds[0], F_SETFL(O_NONBLOCK))); + try!(fcntl(fds[1], F_SETFL(O_NONBLOCK))); + } + } + Ok((fds[0], fds[1])) +} + /// Listen for connections on a socket /// /// [Further reading](http://man7.org/linux/man-pages/man2/listen.2.html) diff --git a/test/sys/test_socket.rs b/test/sys/test_socket.rs index 1983e7b5..e8cb4bed 100644 --- a/test/sys/test_socket.rs +++ b/test/sys/test_socket.rs @@ -48,3 +48,18 @@ pub fn test_getsockname() { assert_eq!(addr, res.to_str()); } + +#[test] +pub fn test_socketpair() { + use nix::unistd::{read, write}; + use nix::sys::socket::{socketpair, AddressFamily, SockType, SockFlag}; + + let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, 0, + SockFlag::empty()) + .unwrap(); + write(fd1, b"hello").unwrap(); + let mut buf = [0;5]; + read(fd2, &mut buf).unwrap(); + + assert_eq!(&buf[..], b"hello"); +} |