diff options
| author | Corey Farwell <coreyf@rwell.org> | 2017-02-05 09:14:38 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-02-05 09:14:38 -0500 |
| commit | ca202fe181ec52998fe8843e87528bbd920605d5 (patch) | |
| tree | 2115c96bc477901cb36370ee25f3b1407423c524 /src/libstd/sys/unix | |
| parent | c4c6c49e526d39d8cdc8eb8072d2e45b4086dc82 (diff) | |
| parent | a40be0857c7bf48e39f815417b0b5293cd8ed1aa (diff) | |
| download | rust-ca202fe181ec52998fe8843e87528bbd920605d5.tar.gz rust-ca202fe181ec52998fe8843e87528bbd920605d5.zip | |
Rollup merge of #38983 - APTy:udp-peek, r=aturon
Add peek APIs to std::net Adds "peek" APIs to `std::net` sockets, including: - `UdpSocket.peek()` - `UdpSocket.peek_from()` - `TcpStream.peek()` These methods enable socket reads without side-effects. That is, repeated calls to `peek()` return identical data. This is accomplished by providing the POSIX flag `MSG_PEEK` to the underlying socket read operations. This also moves the current implementation of `recv_from` out of the platform-independent `sys_common` and into respective `sys/windows` and `sys/unix` implementations. This allows for more platform-dependent implementations where necessary. Fixes #38980
Diffstat (limited to 'src/libstd/sys/unix')
| -rw-r--r-- | src/libstd/sys/unix/net.rs | 45 |
1 files changed, 42 insertions, 3 deletions
diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs index ad287bbec38..5efddca110f 100644 --- a/src/libstd/sys/unix/net.rs +++ b/src/libstd/sys/unix/net.rs @@ -10,12 +10,13 @@ use ffi::CStr; use io; -use libc::{self, c_int, size_t, sockaddr, socklen_t, EAI_SYSTEM}; +use libc::{self, c_int, c_void, size_t, sockaddr, socklen_t, EAI_SYSTEM, MSG_PEEK}; +use mem; use net::{SocketAddr, Shutdown}; use str; use sys::fd::FileDesc; use sys_common::{AsInner, FromInner, IntoInner}; -use sys_common::net::{getsockopt, setsockopt}; +use sys_common::net::{getsockopt, setsockopt, sockaddr_to_addr}; use time::Duration; pub use sys::{cvt, cvt_r}; @@ -155,8 +156,46 @@ impl Socket { self.0.duplicate().map(Socket) } + fn recv_with_flags(&self, buf: &mut [u8], flags: c_int) -> io::Result<usize> { + let ret = cvt(unsafe { + libc::recv(self.0.raw(), + buf.as_mut_ptr() as *mut c_void, + buf.len(), + flags) + })?; + Ok(ret as usize) + } + pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> { - self.0.read(buf) + self.recv_with_flags(buf, 0) + } + + pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> { + self.recv_with_flags(buf, MSG_PEEK) + } + + fn recv_from_with_flags(&self, buf: &mut [u8], flags: c_int) + -> io::Result<(usize, SocketAddr)> { + let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() }; + let mut addrlen = mem::size_of_val(&storage) as libc::socklen_t; + + let n = cvt(unsafe { + libc::recvfrom(self.0.raw(), + buf.as_mut_ptr() as *mut c_void, + buf.len(), + flags, + &mut storage as *mut _ as *mut _, + &mut addrlen) + })?; + Ok((n as usize, sockaddr_to_addr(&storage, addrlen as usize)?)) + } + + pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { + self.recv_from_with_flags(buf, 0) + } + + pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { + self.recv_from_with_flags(buf, MSG_PEEK) } pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> { |
