diff options
| author | Steven Fackler <sfackler@gmail.com> | 2016-03-16 20:50:45 -0700 |
|---|---|---|
| committer | Steven Fackler <sfackler@gmail.com> | 2016-03-20 18:57:58 -0700 |
| commit | c0d989ed6b4b840a290a80ec0cdbc8edbce2ee57 (patch) | |
| tree | af07033b95415a5b27a5717fe4d9e2f3e3463d9d /src/libstd/sys/unix/net.rs | |
| parent | 173676efdc8a9f1f2a86d37c08a104e2e505f9e4 (diff) | |
| download | rust-c0d989ed6b4b840a290a80ec0cdbc8edbce2ee57.tar.gz rust-c0d989ed6b4b840a290a80ec0cdbc8edbce2ee57.zip | |
Add unix socket support to the standard library
Diffstat (limited to 'src/libstd/sys/unix/net.rs')
| -rw-r--r-- | src/libstd/sys/unix/net.rs | 43 |
1 files changed, 42 insertions, 1 deletions
diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs index acf501d5fda..d7b353c9b2a 100644 --- a/src/libstd/sys/unix/net.rs +++ b/src/libstd/sys/unix/net.rs @@ -57,13 +57,17 @@ impl Socket { SocketAddr::V4(..) => libc::AF_INET, SocketAddr::V6(..) => libc::AF_INET6, }; + Socket::new_raw(fam, ty) + } + + pub fn new_raw(fam: c_int, ty: c_int) -> io::Result<Socket> { unsafe { // On linux we first attempt to pass the SOCK_CLOEXEC flag to // atomically create the socket and set it as CLOEXEC. Support for // this option, however, was added in 2.6.27, and we still support // 2.6.18 as a kernel, so if the returned error is EINVAL we // fallthrough to the fallback. - if cfg!(target_os = "linux") { + if cfg!(linux) { match cvt(libc::socket(fam, ty | SOCK_CLOEXEC, 0)) { Ok(fd) => return Ok(Socket(FileDesc::new(fd))), Err(ref e) if e.raw_os_error() == Some(libc::EINVAL) => {} @@ -78,6 +82,30 @@ impl Socket { } } + pub fn new_pair(fam: c_int, ty: c_int) -> io::Result<(Socket, Socket)> { + unsafe { + let mut fds = [0, 0]; + + // Like above, see if we can set cloexec atomically + if cfg!(linux) { + match cvt(libc::socketpair(fam, ty | SOCK_CLOEXEC, 0, fds.as_mut_ptr())) { + Ok(_) => { + return Ok((Socket(FileDesc::new(fds[0])), Socket(FileDesc::new(fds[1])))); + } + Err(ref e) if e.raw_os_error() == Some(libc::EINVAL) => {}, + Err(e) => return Err(e), + } + } + + try!(cvt(libc::socketpair(fam, ty, 0, fds.as_mut_ptr()))); + let a = FileDesc::new(fds[0]); + a.set_cloexec(); + let b = FileDesc::new(fds[1]); + b.set_cloexec(); + Ok((Socket(a), Socket(b))) + } + } + pub fn accept(&self, storage: *mut sockaddr, len: *mut socklen_t) -> io::Result<Socket> { // Unfortunately the only known way right now to accept a socket and @@ -120,6 +148,10 @@ impl Socket { self.0.read_to_end(buf) } + pub fn write(&self, buf: &[u8]) -> io::Result<usize> { + self.0.write(buf) + } + pub fn set_timeout(&self, dur: Option<Duration>, kind: libc::c_int) -> io::Result<()> { let timeout = match dur { Some(dur) => { @@ -186,6 +218,15 @@ impl Socket { let mut nonblocking = nonblocking as libc::c_ulong; cvt(unsafe { libc::ioctl(*self.as_inner(), libc::FIONBIO, &mut nonblocking) }).map(|_| ()) } + + pub fn take_error(&self) -> io::Result<Option<io::Error>> { + let raw: c_int = try!(getsockopt(self, libc::SOL_SOCKET, libc::SO_ERROR)); + if raw == 0 { + Ok(None) + } else { + Ok(Some(io::Error::from_raw_os_error(raw as i32))) + } + } } impl AsInner<c_int> for Socket { |
