diff options
Diffstat (limited to 'src/sys/socket')
-rw-r--r-- | src/sys/socket/ffi.rs | 7 | ||||
-rw-r--r-- | src/sys/socket/mod.rs | 34 |
2 files changed, 41 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) |