libstd/net: Add peek
APIs to UdpSocket and TcpStream
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.
This commit is contained in:
parent
9749df52b7
commit
a40be0857c
8 changed files with 251 additions and 17 deletions
|
@ -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> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue