Skip to content

Commit d8601a8

Browse files
committed
Refactor Socket::recv_from
1 parent 70040ea commit d8601a8

File tree

4 files changed

+73
-48
lines changed

4 files changed

+73
-48
lines changed

src/sockaddr.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ impl SockAddr {
3939
}
4040
}
4141

42+
/// Constructs a `SockAddr` from its raw components.
43+
pub(crate) const fn from_raw(storage: sockaddr_storage, len: socklen_t) -> SockAddr {
44+
SockAddr { storage, len }
45+
}
46+
4247
/// Returns this address's family.
4348
pub fn family(&self) -> sa_family_t {
4449
self.storage.ss_family

src/socket.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -352,19 +352,19 @@ impl Socket {
352352
/// Receives data from the socket. On success, returns the number of bytes
353353
/// read and the address from whence the data came.
354354
pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SockAddr)> {
355-
self.inner().recv_from(buf, 0)
355+
self.recv_from_with_flags(buf, 0)
356356
}
357357

358-
/// Identical to [`recv_from`] but allows for specification of arbitrary flags to the underlying
359-
/// `recvfrom` call.
358+
/// Identical to [`recv_from`] but allows for specification of arbitrary
359+
/// flags to the underlying `recvfrom` call.
360360
///
361-
/// [`recv_from`]: #method.recv_from
361+
/// [`recv_from`]: Socket::recv_from
362362
pub fn recv_from_with_flags(
363363
&self,
364364
buf: &mut [u8],
365365
flags: i32,
366366
) -> io::Result<(usize, SockAddr)> {
367-
self.inner().recv_from(buf, flags)
367+
sys::recv_from(self.inner, buf, flags)
368368
}
369369

370370
/// Identical to [`recv_from_with_flags`] but reads into a slice of buffers.

src/sys/unix.rs

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,7 @@ pub(crate) fn shutdown(fd: SysSocket, how: Shutdown) -> io::Result<()> {
390390
};
391391
syscall!(shutdown(fd, how)).map(|_| ())
392392
}
393+
393394
pub(crate) fn recv(fd: SysSocket, buf: &mut [u8], flags: c_int) -> io::Result<usize> {
394395
syscall!(recv(
395396
fd,
@@ -400,6 +401,30 @@ pub(crate) fn recv(fd: SysSocket, buf: &mut [u8], flags: c_int) -> io::Result<us
400401
.map(|n| n as usize)
401402
}
402403

404+
pub(crate) fn recv_from(
405+
fd: SysSocket,
406+
buf: &mut [u8],
407+
flags: c_int,
408+
) -> io::Result<(usize, SockAddr)> {
409+
let mut storage: MaybeUninit<libc::sockaddr_storage> = MaybeUninit::zeroed();
410+
let mut addrlen = size_of_val(&storage) as socklen_t;
411+
syscall!(recvfrom(
412+
fd,
413+
buf.as_mut_ptr().cast(),
414+
min(buf.len(), MAX_BUF_LEN),
415+
flags,
416+
storage.as_mut_ptr().cast(),
417+
&mut addrlen,
418+
))
419+
.map(|n| {
420+
// Safety: `recvfrom` wrote an address of `addrlen` bytes for us. The
421+
// remaining bytes are initialised to zero (which is valid for
422+
// `sockaddr_storage`).
423+
let addr = SockAddr::from_raw(unsafe { storage.assume_init() }, addrlen);
424+
(n as usize, addr)
425+
})
426+
}
427+
403428
#[cfg(not(target_os = "redox"))]
404429
pub(crate) fn recv_vectored(
405430
fd: SysSocket,
@@ -554,23 +579,7 @@ pub struct Socket {
554579

555580
impl Socket {
556581
pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SockAddr)> {
557-
self.recv_from(buf, libc::MSG_PEEK)
558-
}
559-
560-
pub fn recv_from(&self, buf: &mut [u8], flags: c_int) -> io::Result<(usize, SockAddr)> {
561-
let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() };
562-
let mut addrlen = mem::size_of_val(&storage) as socklen_t;
563-
564-
let n = syscall!(recvfrom(
565-
self.fd,
566-
buf.as_mut_ptr() as *mut c_void,
567-
cmp::min(buf.len(), max_len()),
568-
flags,
569-
&mut storage as *mut _ as *mut _,
570-
&mut addrlen,
571-
))?;
572-
let addr = unsafe { SockAddr::from_raw_parts(&storage as *const _ as *const _, addrlen) };
573-
Ok((n as usize, addr))
582+
recv_from(self.fd, buf, libc::MSG_PEEK)
574583
}
575584

576585
#[cfg(not(target_os = "redox"))]

src/sys/windows.rs

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,42 @@ pub(crate) fn recv_vectored(
325325
}
326326
}
327327

328+
pub(crate) fn recv_from(
329+
socket: SysSocket,
330+
buf: &mut [u8],
331+
flags: c_int,
332+
) -> io::Result<(usize, SockAddr)> {
333+
let mut storage: MaybeUninit<SOCKADDR_STORAGE> = MaybeUninit::zeroed();
334+
let mut addrlen = size_of_val(&storage) as socklen_t;
335+
let res = syscall!(
336+
recvfrom(
337+
socket,
338+
buf.as_mut_ptr().cast(),
339+
min(buf.len(), MAX_BUF_LEN) as c_int,
340+
flags,
341+
storage.as_mut_ptr().cast(),
342+
&mut addrlen,
343+
),
344+
PartialEq::eq,
345+
sock::SOCKET_ERROR
346+
);
347+
match res {
348+
Ok(n) => {
349+
// Safety: `recvfrom` wrote an address of `addrlen` bytes for us. The
350+
// remaining bytes are initialised to zero (which is valid for
351+
// `sockaddr_storage`).
352+
let addr = SockAddr::from_raw(unsafe { storage.assume_init() }, addrlen);
353+
Ok((n as usize, addr))
354+
}
355+
Err(ref err) if err.raw_os_error() == Some(sock::WSAESHUTDOWN as i32) => {
356+
// Safety: see above.
357+
let addr = SockAddr::from_raw(unsafe { storage.assume_init() }, addrlen);
358+
Ok((0, addr))
359+
}
360+
Err(err) => Err(err),
361+
}
362+
}
363+
328364
/// Caller must ensure `T` is the correct type for `opt` and `val`.
329365
unsafe fn getsockopt<T>(socket: SysSocket, opt: c_int, val: c_int) -> io::Result<T> {
330366
let mut payload: MaybeUninit<T> = MaybeUninit::uninit();
@@ -379,32 +415,7 @@ pub struct Socket {
379415

380416
impl Socket {
381417
pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SockAddr)> {
382-
self.recv_from(buf, MSG_PEEK)
383-
}
384-
385-
pub fn recv_from(&self, buf: &mut [u8], flags: c_int) -> io::Result<(usize, SockAddr)> {
386-
unsafe {
387-
let mut storage: SOCKADDR_STORAGE = mem::zeroed();
388-
let mut addrlen = mem::size_of_val(&storage) as c_int;
389-
390-
let n = {
391-
sock::recvfrom(
392-
self.socket,
393-
buf.as_mut_ptr() as *mut c_char,
394-
clamp(buf.len()),
395-
flags,
396-
&mut storage as *mut _ as *mut _,
397-
&mut addrlen,
398-
)
399-
};
400-
let n = match n {
401-
sock::SOCKET_ERROR if sock::WSAGetLastError() == sock::WSAESHUTDOWN as i32 => 0,
402-
sock::SOCKET_ERROR => return Err(last_error()),
403-
n => n as usize,
404-
};
405-
let addr = SockAddr::from_raw_parts(&storage as *const _ as *const _, addrlen);
406-
Ok((n, addr))
407-
}
418+
recv_from(self.socket, buf, MSG_PEEK)
408419
}
409420

410421
pub fn recv_from_vectored(

0 commit comments

Comments
 (0)