summaryrefslogtreecommitdiff
path: root/src/sys/socket
diff options
context:
space:
mode:
Diffstat (limited to 'src/sys/socket')
-rw-r--r--src/sys/socket/ffi.rs7
-rw-r--r--src/sys/socket/mod.rs34
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)