rustix/net/send_recv/
mod.rs

1//! `recv`, `send`, and variants.
2
3#![allow(unsafe_code)]
4
5use crate::buffer::Buffer;
6use crate::net::addr::SocketAddrArg;
7use crate::net::SocketAddrAny;
8use crate::{backend, io};
9use backend::fd::AsFd;
10use core::cmp::min;
11
12pub use backend::net::send_recv::{RecvFlags, ReturnFlags, SendFlags};
13
14#[cfg(not(any(
15    windows,
16    target_os = "espidf",
17    target_os = "horizon",
18    target_os = "vita"
19)))]
20mod msg;
21
22#[cfg(not(any(
23    windows,
24    target_os = "espidf",
25    target_os = "horizon",
26    target_os = "vita"
27)))]
28pub use msg::*;
29
30/// `recv(fd, buf, flags)`—Reads data from a socket.
31///
32/// In addition to the `Buffer::Output` return value, this also returns the
33/// number of bytes received before any truncation due to the
34/// [`RecvFlags::TRUNC`] flag.
35///
36/// # References
37///  - [Beej's Guide to Network Programming]
38///  - [POSIX]
39///  - [Linux]
40///  - [Apple]
41///  - [Winsock]
42///  - [FreeBSD]
43///  - [NetBSD]
44///  - [OpenBSD]
45///  - [DragonFly BSD]
46///  - [illumos]
47///  - [glibc]
48///
49/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendrecv
50/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/recv.html
51/// [Linux]: https://man7.org/linux/man-pages/man2/recv.2.html
52/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/recv.2.html
53/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-recv
54/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=recv&sektion=2
55/// [NetBSD]: https://man.netbsd.org/recv.2
56/// [OpenBSD]: https://man.openbsd.org/recv.2
57/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=recv&section=2
58/// [illumos]: https://illumos.org/man/3SOCKET/recv
59/// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Receiving-Data.html
60#[inline]
61#[allow(clippy::type_complexity)]
62pub fn recv<Fd: AsFd, Buf: Buffer<u8>>(
63    fd: Fd,
64    mut buf: Buf,
65    flags: RecvFlags,
66) -> io::Result<(Buf::Output, usize)> {
67    let (ptr, len) = buf.parts_mut();
68    // SAFETY: `recv` behaves.
69    let recv_len = unsafe { backend::net::syscalls::recv(fd.as_fd(), (ptr, len), flags)? };
70    // If the `TRUNC` flag is set, the returned `length` may be longer than the
71    // buffer length.
72    let min_len = min(len, recv_len);
73    // SAFETY: `recv` behaves.
74    unsafe { Ok((buf.assume_init(min_len), recv_len)) }
75}
76
77/// `send(fd, buf, flags)`—Writes data to a socket.
78///
79/// # References
80///  - [Beej's Guide to Network Programming]
81///  - [POSIX]
82///  - [Linux]
83///  - [Apple]
84///  - [Winsock]
85///  - [FreeBSD]
86///  - [NetBSD]
87///  - [OpenBSD]
88///  - [DragonFly BSD]
89///  - [illumos]
90///  - [glibc]
91///
92/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendrecv
93/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/send.html
94/// [Linux]: https://man7.org/linux/man-pages/man2/send.2.html
95/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/send.2.html
96/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-send
97/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=send&sektion=2
98/// [NetBSD]: https://man.netbsd.org/send.2
99/// [OpenBSD]: https://man.openbsd.org/send.2
100/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=send&section=2
101/// [illumos]: https://illumos.org/man/3SOCKET/send
102/// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Sending-Data.html
103#[inline]
104pub fn send<Fd: AsFd>(fd: Fd, buf: &[u8], flags: SendFlags) -> io::Result<usize> {
105    backend::net::syscalls::send(fd.as_fd(), buf, flags)
106}
107
108/// `recvfrom(fd, buf, flags, addr, len)`—Reads data from a socket and
109/// returns the sender address.
110///
111/// In addition to the `Buffer::Output` return value, this also returns the
112/// number of bytes received before any truncation due to the
113/// [`RecvFlags::TRUNC`] flag.
114///
115/// # References
116///  - [Beej's Guide to Network Programming]
117///  - [POSIX]
118///  - [Linux]
119///  - [Apple]
120///  - [Winsock]
121///  - [FreeBSD]
122///  - [NetBSD]
123///  - [OpenBSD]
124///  - [DragonFly BSD]
125///  - [illumos]
126///  - [glibc]
127///
128/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendtorecv
129/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/recvfrom.html
130/// [Linux]: https://man7.org/linux/man-pages/man2/recvfrom.2.html
131/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/recvfrom.2.html
132/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-recvfrom
133/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=recvfrom&sektion=2
134/// [NetBSD]: https://man.netbsd.org/recvfrom.2
135/// [OpenBSD]: https://man.openbsd.org/recvfrom.2
136/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=recvfrom&section=2
137/// [illumos]: https://illumos.org/man/3SOCKET/recvfrom
138/// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Receiving-Datagrams.html
139#[inline]
140pub fn recvfrom<Fd: AsFd, Buf: Buffer<u8>>(
141    fd: Fd,
142    mut buf: Buf,
143    flags: RecvFlags,
144) -> io::Result<(Buf::Output, usize, Option<SocketAddrAny>)> {
145    let (ptr, len) = buf.parts_mut();
146    // SAFETY: `recvfrom` behaves.
147    let (recv_len, addr) =
148        unsafe { backend::net::syscalls::recvfrom(fd.as_fd(), (ptr, len), flags)? };
149    // If the `TRUNC` flag is set, the returned `length` may be longer than the
150    // buffer length.
151    let min_len = min(len, recv_len);
152    // SAFETY: `recvfrom` behaves.
153    unsafe { Ok((buf.assume_init(min_len), recv_len, addr)) }
154}
155
156/// `sendto(fd, buf, flags, addr)`—Writes data to a socket to a specific IP
157/// address.
158///
159/// # References
160///  - [Beej's Guide to Network Programming]
161///  - [POSIX]
162///  - [Linux]
163///  - [Apple]
164///  - [Winsock]
165///  - [FreeBSD]
166///  - [NetBSD]
167///  - [OpenBSD]
168///  - [DragonFly BSD]
169///  - [illumos]
170///  - [glibc]
171///
172/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendtorecv
173/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/sendto.html
174/// [Linux]: https://man7.org/linux/man-pages/man2/sendto.2.html
175/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendto.2.html
176/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-sendto
177/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendto&sektion=2
178/// [NetBSD]: https://man.netbsd.org/sendto.2
179/// [OpenBSD]: https://man.openbsd.org/sendto.2
180/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendto&section=2
181/// [illumos]: https://illumos.org/man/3SOCKET/sendto
182/// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Sending-Datagrams.html
183pub fn sendto<Fd: AsFd>(
184    fd: Fd,
185    buf: &[u8],
186    flags: SendFlags,
187    addr: &impl SocketAddrArg,
188) -> io::Result<usize> {
189    backend::net::syscalls::sendto(fd.as_fd(), buf, flags, addr)
190}