Source code

Revision control

Copy as Markdown

Other Tools

//! `recv`, `send`, and variants.
#![allow(unsafe_code)]
use crate::buffer::split_init;
#[cfg(target_os = "linux")]
use crate::net::xdp::SocketAddrXdp;
#[cfg(unix)]
use crate::net::SocketAddrUnix;
use crate::net::{SocketAddr, SocketAddrAny, SocketAddrV4, SocketAddrV6};
use crate::{backend, io};
use backend::fd::{AsFd, BorrowedFd};
use core::mem::MaybeUninit;
pub use backend::net::send_recv::{RecvFlags, SendFlags};
#[cfg(not(any(
windows,
target_os = "espidf",
target_os = "redox",
target_os = "vita",
target_os = "wasi"
)))]
mod msg;
#[cfg(not(any(
windows,
target_os = "espidf",
target_os = "redox",
target_os = "vita",
target_os = "wasi"
)))]
pub use msg::*;
/// `recv(fd, buf, flags)`—Reads data from a socket.
///
/// # References
/// - [Beej's Guide to Network Programming]
/// - [POSIX]
/// - [Linux]
/// - [Apple]
/// - [Winsock]
/// - [FreeBSD]
/// - [NetBSD]
/// - [OpenBSD]
/// - [DragonFly BSD]
/// - [illumos]
/// - [glibc]
///
#[inline]
pub fn recv<Fd: AsFd>(fd: Fd, buf: &mut [u8], flags: RecvFlags) -> io::Result<usize> {
unsafe { backend::net::syscalls::recv(fd.as_fd(), buf.as_mut_ptr(), buf.len(), flags) }
}
/// `recv(fd, buf, flags)`—Reads data from a socket.
///
/// This is equivalent to [`recv`], except that it can read into uninitialized
/// memory. It returns the slice that was initialized by this function and the
/// slice that remains uninitialized.
#[inline]
pub fn recv_uninit<Fd: AsFd>(
fd: Fd,
buf: &mut [MaybeUninit<u8>],
flags: RecvFlags,
) -> io::Result<(&mut [u8], &mut [MaybeUninit<u8>])> {
let length = unsafe {
backend::net::syscalls::recv(fd.as_fd(), buf.as_mut_ptr() as *mut u8, buf.len(), flags)
};
Ok(unsafe { split_init(buf, length?) })
}
/// `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]
///
#[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.
///
/// # References
/// - [Beej's Guide to Network Programming]
/// - [POSIX]
/// - [Linux]
/// - [Apple]
/// - [Winsock]
/// - [FreeBSD]
/// - [NetBSD]
/// - [OpenBSD]
/// - [DragonFly BSD]
/// - [illumos]
/// - [glibc]
///
#[inline]
pub fn recvfrom<Fd: AsFd>(
fd: Fd,
buf: &mut [u8],
flags: RecvFlags,
) -> io::Result<(usize, Option<SocketAddrAny>)> {
unsafe { backend::net::syscalls::recvfrom(fd.as_fd(), buf.as_mut_ptr(), buf.len(), flags) }
}
/// `recvfrom(fd, buf, flags, addr, len)`—Reads data from a socket and
/// returns the sender address.
///
/// This is equivalent to [`recvfrom`], except that it can read into
/// uninitialized memory. It returns the slice that was initialized by this
/// function and the slice that remains uninitialized.
#[allow(clippy::type_complexity)]
#[inline]
pub fn recvfrom_uninit<Fd: AsFd>(
fd: Fd,
buf: &mut [MaybeUninit<u8>],
flags: RecvFlags,
) -> io::Result<(&mut [u8], &mut [MaybeUninit<u8>], Option<SocketAddrAny>)> {
let (length, addr) = unsafe {
backend::net::syscalls::recvfrom(fd.as_fd(), buf.as_mut_ptr() as *mut u8, buf.len(), flags)?
};
let (init, uninit) = unsafe { split_init(buf, length) };
Ok((init, uninit, 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]
///
pub fn sendto<Fd: AsFd>(
fd: Fd,
buf: &[u8],
flags: SendFlags,
addr: &SocketAddr,
) -> io::Result<usize> {
_sendto(fd.as_fd(), buf, flags, addr)
}
fn _sendto(
fd: BorrowedFd<'_>,
buf: &[u8],
flags: SendFlags,
addr: &SocketAddr,
) -> io::Result<usize> {
match addr {
SocketAddr::V4(v4) => backend::net::syscalls::sendto_v4(fd, buf, flags, v4),
SocketAddr::V6(v6) => backend::net::syscalls::sendto_v6(fd, buf, flags, v6),
}
}
/// `sendto(fd, buf, flags, addr)`—Writes data to a socket to a specific
/// address.
///
/// # References
/// - [Beej's Guide to Network Programming]
/// - [POSIX]
/// - [Linux]
/// - [Apple]
/// - [Winsock]
/// - [FreeBSD]
/// - [NetBSD]
/// - [OpenBSD]
/// - [DragonFly BSD]
/// - [illumos]
/// - [glibc]
///
pub fn sendto_any<Fd: AsFd>(
fd: Fd,
buf: &[u8],
flags: SendFlags,
addr: &SocketAddrAny,
) -> io::Result<usize> {
_sendto_any(fd.as_fd(), buf, flags, addr)
}
fn _sendto_any(
fd: BorrowedFd<'_>,
buf: &[u8],
flags: SendFlags,
addr: &SocketAddrAny,
) -> io::Result<usize> {
match addr {
SocketAddrAny::V4(v4) => backend::net::syscalls::sendto_v4(fd, buf, flags, v4),
SocketAddrAny::V6(v6) => backend::net::syscalls::sendto_v6(fd, buf, flags, v6),
#[cfg(unix)]
SocketAddrAny::Unix(unix) => backend::net::syscalls::sendto_unix(fd, buf, flags, unix),
#[cfg(target_os = "linux")]
SocketAddrAny::Xdp(xdp) => backend::net::syscalls::sendto_xdp(fd, buf, flags, xdp),
}
}
/// `sendto(fd, buf, flags, addr, sizeof(struct sockaddr_in))`—Writes data to
/// a socket to a specific IPv4 address.
///
/// # References
/// - [Beej's Guide to Network Programming]
/// - [POSIX]
/// - [Linux]
/// - [Apple]
/// - [Winsock]
/// - [FreeBSD]
/// - [NetBSD]
/// - [OpenBSD]
/// - [DragonFly BSD]
/// - [illumos]
/// - [glibc]
///
#[inline]
#[doc(alias = "sendto")]
pub fn sendto_v4<Fd: AsFd>(
fd: Fd,
buf: &[u8],
flags: SendFlags,
addr: &SocketAddrV4,
) -> io::Result<usize> {
backend::net::syscalls::sendto_v4(fd.as_fd(), buf, flags, addr)
}
/// `sendto(fd, buf, flags, addr, sizeof(struct sockaddr_in6))`—Writes data
/// to a socket to a specific IPv6 address.
///
/// # References
/// - [Beej's Guide to Network Programming]
/// - [POSIX]
/// - [Linux]
/// - [Apple]
/// - [Winsock]
/// - [FreeBSD]
/// - [NetBSD]
/// - [OpenBSD]
/// - [DragonFly BSD]
/// - [illumos]
/// - [glibc]
///
#[inline]
#[doc(alias = "sendto")]
pub fn sendto_v6<Fd: AsFd>(
fd: Fd,
buf: &[u8],
flags: SendFlags,
addr: &SocketAddrV6,
) -> io::Result<usize> {
backend::net::syscalls::sendto_v6(fd.as_fd(), buf, flags, addr)
}
/// `sendto(fd, buf, flags, addr, sizeof(struct sockaddr_un))`—Writes data to
/// a socket to a specific Unix-domain socket address.
///
/// # References
/// - [Beej's Guide to Network Programming]
/// - [POSIX]
/// - [Linux]
/// - [Apple]
/// - [Winsock]
/// - [FreeBSD]
/// - [NetBSD]
/// - [OpenBSD]
/// - [DragonFly BSD]
/// - [illumos]
/// - [glibc]
///
#[cfg(unix)]
#[inline]
#[doc(alias = "sendto")]
pub fn sendto_unix<Fd: AsFd>(
fd: Fd,
buf: &[u8],
flags: SendFlags,
addr: &SocketAddrUnix,
) -> io::Result<usize> {
backend::net::syscalls::sendto_unix(fd.as_fd(), buf, flags, addr)
}
/// `sendto(fd, buf, flags, addr, sizeof(struct sockaddr_xdp))`—Writes data
/// to a socket to a specific XDP address.
///
/// # References
/// - [Linux]
///
#[cfg(target_os = "linux")]
#[inline]
#[doc(alias = "sendto")]
pub fn sendto_xdp<Fd: AsFd>(
fd: Fd,
buf: &[u8],
flags: SendFlags,
addr: &SocketAddrXdp,
) -> io::Result<usize> {
backend::net::syscalls::sendto_xdp(fd.as_fd(), buf, flags, addr)
}