Source code
Revision control
Copy as Markdown
Other Tools
//! `recv`, `send`, and variants.
#![allow(unsafe_code)]
use crate::buffer::Buffer;
use crate::net::addr::SocketAddrArg;
use crate::net::SocketAddrAny;
use crate::{backend, io};
use backend::fd::AsFd;
use core::cmp::min;
pub use backend::net::send_recv::{RecvFlags, ReturnFlags, SendFlags};
#[cfg(not(any(
windows,
target_os = "espidf",
target_os = "horizon",
target_os = "vita"
)))]
mod msg;
#[cfg(not(any(
windows,
target_os = "espidf",
target_os = "horizon",
target_os = "vita"
)))]
pub use msg::*;
/// `recv(fd, buf, flags)`—Reads data from a socket.
///
/// In addition to the `Buffer::Output` return value, this also returns the
/// number of bytes received before any truncation due to the
/// [`RecvFlags::TRUNC`] flag.
///
/// # References
/// - [Beej's Guide to Network Programming]
/// - [POSIX]
/// - [Linux]
/// - [Apple]
/// - [Winsock]
/// - [FreeBSD]
/// - [NetBSD]
/// - [OpenBSD]
/// - [DragonFly BSD]
/// - [illumos]
/// - [glibc]
///
/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendrecv
/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/recv.2.html
#[inline]
#[allow(clippy::type_complexity)]
pub fn recv<Fd: AsFd, Buf: Buffer<u8>>(
fd: Fd,
mut buf: Buf,
flags: RecvFlags,
) -> io::Result<(Buf::Output, usize)> {
let (ptr, len) = buf.parts_mut();
// SAFETY: `recv` behaves.
let recv_len = unsafe { backend::net::syscalls::recv(fd.as_fd(), (ptr, len), flags)? };
// If the `TRUNC` flag is set, the returned `length` may be longer than the
// buffer length.
let min_len = min(len, recv_len);
// SAFETY: `recv` behaves.
unsafe { Ok((buf.assume_init(min_len), recv_len)) }
}
/// `send(fd, buf, flags)`—Writes data to a socket.
///
/// # References
/// - [Beej's Guide to Network Programming]
/// - [POSIX]
/// - [Linux]
/// - [Apple]
/// - [Winsock]
/// - [FreeBSD]
/// - [NetBSD]
/// - [OpenBSD]
/// - [DragonFly BSD]
/// - [illumos]
/// - [glibc]
///
/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendrecv
/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/send.2.html
#[inline]
pub fn send<Fd: AsFd>(fd: Fd, buf: &[u8], flags: SendFlags) -> io::Result<usize> {
backend::net::syscalls::send(fd.as_fd(), buf, flags)
}
/// `recvfrom(fd, buf, flags, addr, len)`—Reads data from a socket and
/// returns the sender address.
///
/// In addition to the `Buffer::Output` return value, this also returns the
/// number of bytes received before any truncation due to the
/// [`RecvFlags::TRUNC`] flag.
///
/// # References
/// - [Beej's Guide to Network Programming]
/// - [POSIX]
/// - [Linux]
/// - [Apple]
/// - [Winsock]
/// - [FreeBSD]
/// - [NetBSD]
/// - [OpenBSD]
/// - [DragonFly BSD]
/// - [illumos]
/// - [glibc]
///
/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendtorecv
/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/recvfrom.2.html
#[inline]
pub fn recvfrom<Fd: AsFd, Buf: Buffer<u8>>(
fd: Fd,
mut buf: Buf,
flags: RecvFlags,
) -> io::Result<(Buf::Output, usize, Option<SocketAddrAny>)> {
let (ptr, len) = buf.parts_mut();
// SAFETY: `recvfrom` behaves.
let (recv_len, addr) =
unsafe { backend::net::syscalls::recvfrom(fd.as_fd(), (ptr, len), flags)? };
// If the `TRUNC` flag is set, the returned `length` may be longer than the
// buffer length.
let min_len = min(len, recv_len);
// SAFETY: `recvfrom` behaves.
unsafe { Ok((buf.assume_init(min_len), recv_len, addr)) }
}
/// `sendto(fd, buf, flags, addr)`—Writes data to a socket to a specific IP
/// address.
///
/// # References
/// - [Beej's Guide to Network Programming]
/// - [POSIX]
/// - [Linux]
/// - [Apple]
/// - [Winsock]
/// - [FreeBSD]
/// - [NetBSD]
/// - [OpenBSD]
/// - [DragonFly BSD]
/// - [illumos]
/// - [glibc]
///
/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendtorecv
/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendto.2.html
pub fn sendto<Fd: AsFd>(
fd: Fd,
buf: &[u8],
flags: SendFlags,
addr: &impl SocketAddrArg,
) -> io::Result<usize> {
backend::net::syscalls::sendto(fd.as_fd(), buf, flags, addr)
}