summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/sys/socket/ffi.rs7
-rw-r--r--src/sys/socket/mod.rs34
-rw-r--r--test/sys/test_socket.rs15
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");
+}