1//! `recv`, `send`, and variants.
2
3#![allow(unsafe_code)]
4
5use crate::buffer::split_init;
6#[cfg(target_os = "linux")]
7use crate::net::xdp::SocketAddrXdp;
8#[cfg(unix)]
9use crate::net::SocketAddrUnix;
10use crate::net::{SocketAddr, SocketAddrAny, SocketAddrV4, SocketAddrV6};
11use crate::{backend, io};
12use backend::fd::{AsFd, BorrowedFd};
13use core::mem::MaybeUninit;
14
15pub use backend::net::send_recv::{RecvFlags, SendFlags};
16
17#[cfg(not(any(
18 windows,
19 target_os = "espidf",
20 target_os = "redox",
21 target_os = "vita",
22 target_os = "wasi"
23)))]
24mod msg;
25
26#[cfg(not(any(
27 windows,
28 target_os = "espidf",
29 target_os = "redox",
30 target_os = "vita",
31 target_os = "wasi"
32)))]
33pub use msg::*;
34
35/// `recv(fd, buf, flags)`—Reads data from a socket.
36///
37/// # References
38/// - [Beej's Guide to Network Programming]
39/// - [POSIX]
40/// - [Linux]
41/// - [Apple]
42/// - [Winsock]
43/// - [FreeBSD]
44/// - [NetBSD]
45/// - [OpenBSD]
46/// - [DragonFly BSD]
47/// - [illumos]
48/// - [glibc]
49///
50/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendrecv
51/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html
52/// [Linux]: https://man7.org/linux/man-pages/man2/recv.2.html
53/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/recv.2.html
54/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-recv
55/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=recv&sektion=2
56/// [NetBSD]: https://man.netbsd.org/recv.2
57/// [OpenBSD]: https://man.openbsd.org/recv.2
58/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=recv&section=2
59/// [illumos]: https://illumos.org/man/3SOCKET/recv
60/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Receiving-Data.html
61#[inline]
62pub fn recv<Fd: AsFd>(fd: Fd, buf: &mut [u8], flags: RecvFlags) -> io::Result<usize> {
63 unsafe { backend::net::syscalls::recv(fd.as_fd(), buf:buf.as_mut_ptr(), buf.len(), flags) }
64}
65
66/// `recv(fd, buf, flags)`—Reads data from a socket.
67///
68/// This is equivalent to [`recv`], except that it can read into uninitialized
69/// memory. It returns the slice that was initialized by this function and the
70/// slice that remains uninitialized.
71#[inline]
72pub fn recv_uninit<Fd: AsFd>(
73 fd: Fd,
74 buf: &mut [MaybeUninit<u8>],
75 flags: RecvFlags,
76) -> io::Result<(&mut [u8], &mut [MaybeUninit<u8>])> {
77 let length: Result = unsafe {
78 backend::net::syscalls::recv(fd.as_fd(), buf:buf.as_mut_ptr() as *mut u8, buf.len(), flags)
79 };
80
81 Ok(unsafe { split_init(buf, init:length?) })
82}
83
84/// `send(fd, buf, flags)`—Writes data to a socket.
85///
86/// # References
87/// - [Beej's Guide to Network Programming]
88/// - [POSIX]
89/// - [Linux]
90/// - [Apple]
91/// - [Winsock]
92/// - [FreeBSD]
93/// - [NetBSD]
94/// - [OpenBSD]
95/// - [DragonFly BSD]
96/// - [illumos]
97/// - [glibc]
98///
99/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendrecv
100/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html
101/// [Linux]: https://man7.org/linux/man-pages/man2/send.2.html
102/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/send.2.html
103/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-send
104/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=send&sektion=2
105/// [NetBSD]: https://man.netbsd.org/send.2
106/// [OpenBSD]: https://man.openbsd.org/send.2
107/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=send&section=2
108/// [illumos]: https://illumos.org/man/3SOCKET/send
109/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Sending-Data.html
110#[inline]
111pub fn send<Fd: AsFd>(fd: Fd, buf: &[u8], flags: SendFlags) -> io::Result<usize> {
112 backend::net::syscalls::send(fd.as_fd(), buf, flags)
113}
114
115/// `recvfrom(fd, buf, flags, addr, len)`—Reads data from a socket and
116/// returns the sender address.
117///
118/// # References
119/// - [Beej's Guide to Network Programming]
120/// - [POSIX]
121/// - [Linux]
122/// - [Apple]
123/// - [Winsock]
124/// - [FreeBSD]
125/// - [NetBSD]
126/// - [OpenBSD]
127/// - [DragonFly BSD]
128/// - [illumos]
129/// - [glibc]
130///
131/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendtorecv
132/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvfrom.html
133/// [Linux]: https://man7.org/linux/man-pages/man2/recvfrom.2.html
134/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/recvfrom.2.html
135/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-recvfrom
136/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=recvfrom&sektion=2
137/// [NetBSD]: https://man.netbsd.org/recvfrom.2
138/// [OpenBSD]: https://man.openbsd.org/recvfrom.2
139/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=recvfrom&section=2
140/// [illumos]: https://illumos.org/man/3SOCKET/recvfrom
141/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Receiving-Datagrams.html
142#[inline]
143pub fn recvfrom<Fd: AsFd>(
144 fd: Fd,
145 buf: &mut [u8],
146 flags: RecvFlags,
147) -> io::Result<(usize, Option<SocketAddrAny>)> {
148 unsafe { backend::net::syscalls::recvfrom(fd.as_fd(), buf:buf.as_mut_ptr(), buf.len(), flags) }
149}
150
151/// `recvfrom(fd, buf, flags, addr, len)`—Reads data from a socket and
152/// returns the sender address.
153///
154/// This is equivalent to [`recvfrom`], except that it can read into
155/// uninitialized memory. It returns the slice that was initialized by this
156/// function and the slice that remains uninitialized.
157#[allow(clippy::type_complexity)]
158#[inline]
159pub fn recvfrom_uninit<Fd: AsFd>(
160 fd: Fd,
161 buf: &mut [MaybeUninit<u8>],
162 flags: RecvFlags,
163) -> io::Result<(&mut [u8], &mut [MaybeUninit<u8>], Option<SocketAddrAny>)> {
164 let (length: usize, addr: Option) = unsafe {
165 backend::net::syscalls::recvfrom(fd.as_fd(), buf:buf.as_mut_ptr() as *mut u8, buf.len(), flags)?
166 };
167 let (init: &mut [u8], uninit: &mut [MaybeUninit]) = unsafe { split_init(buf, init:length) };
168 Ok((init, uninit, addr))
169}
170
171/// `sendto(fd, buf, flags, addr)`—Writes data to a socket to a specific IP
172/// address.
173///
174/// # References
175/// - [Beej's Guide to Network Programming]
176/// - [POSIX]
177/// - [Linux]
178/// - [Apple]
179/// - [Winsock]
180/// - [FreeBSD]
181/// - [NetBSD]
182/// - [OpenBSD]
183/// - [DragonFly BSD]
184/// - [illumos]
185/// - [glibc]
186///
187/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendtorecv
188/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html
189/// [Linux]: https://man7.org/linux/man-pages/man2/sendto.2.html
190/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendto.2.html
191/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-sendto
192/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendto&sektion=2
193/// [NetBSD]: https://man.netbsd.org/sendto.2
194/// [OpenBSD]: https://man.openbsd.org/sendto.2
195/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendto&section=2
196/// [illumos]: https://illumos.org/man/3SOCKET/sendto
197/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Sending-Datagrams.html
198pub fn sendto<Fd: AsFd>(
199 fd: Fd,
200 buf: &[u8],
201 flags: SendFlags,
202 addr: &SocketAddr,
203) -> io::Result<usize> {
204 _sendto(fd.as_fd(), buf, flags, addr)
205}
206
207fn _sendto(
208 fd: BorrowedFd<'_>,
209 buf: &[u8],
210 flags: SendFlags,
211 addr: &SocketAddr,
212) -> io::Result<usize> {
213 match addr {
214 SocketAddr::V4(v4: &SocketAddrV4) => backend::net::syscalls::sendto_v4(fd, buf, flags, addr:v4),
215 SocketAddr::V6(v6: &SocketAddrV6) => backend::net::syscalls::sendto_v6(fd, buf, flags, addr:v6),
216 }
217}
218
219/// `sendto(fd, buf, flags, addr)`—Writes data to a socket to a specific
220/// address.
221///
222/// # References
223/// - [Beej's Guide to Network Programming]
224/// - [POSIX]
225/// - [Linux]
226/// - [Apple]
227/// - [Winsock]
228/// - [FreeBSD]
229/// - [NetBSD]
230/// - [OpenBSD]
231/// - [DragonFly BSD]
232/// - [illumos]
233/// - [glibc]
234///
235/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendtorecv
236/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html
237/// [Linux]: https://man7.org/linux/man-pages/man2/sendto.2.html
238/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendto.2.html
239/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-sendto
240/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendto&sektion=2
241/// [NetBSD]: https://man.netbsd.org/sendto.2
242/// [OpenBSD]: https://man.openbsd.org/sendto.2
243/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendto&section=2
244/// [illumos]: https://illumos.org/man/3SOCKET/sendto
245/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Sending-Datagrams.html
246pub fn sendto_any<Fd: AsFd>(
247 fd: Fd,
248 buf: &[u8],
249 flags: SendFlags,
250 addr: &SocketAddrAny,
251) -> io::Result<usize> {
252 _sendto_any(fd.as_fd(), buf, flags, addr)
253}
254
255fn _sendto_any(
256 fd: BorrowedFd<'_>,
257 buf: &[u8],
258 flags: SendFlags,
259 addr: &SocketAddrAny,
260) -> io::Result<usize> {
261 match addr {
262 SocketAddrAny::V4(v4: &SocketAddrV4) => backend::net::syscalls::sendto_v4(fd, buf, flags, addr:v4),
263 SocketAddrAny::V6(v6: &SocketAddrV6) => backend::net::syscalls::sendto_v6(fd, buf, flags, addr:v6),
264 #[cfg(unix)]
265 SocketAddrAny::Unix(unix: &SocketAddrUnix) => backend::net::syscalls::sendto_unix(fd, buf, flags, addr:unix),
266 #[cfg(target_os = "linux")]
267 SocketAddrAny::Xdp(xdp: &SocketAddrXdp) => backend::net::syscalls::sendto_xdp(fd, buf, flags, addr:xdp),
268 }
269}
270
271/// `sendto(fd, buf, flags, addr, sizeof(struct sockaddr_in))`—Writes data to
272/// a socket to a specific IPv4 address.
273///
274/// # References
275/// - [Beej's Guide to Network Programming]
276/// - [POSIX]
277/// - [Linux]
278/// - [Apple]
279/// - [Winsock]
280/// - [FreeBSD]
281/// - [NetBSD]
282/// - [OpenBSD]
283/// - [DragonFly BSD]
284/// - [illumos]
285/// - [glibc]
286///
287/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendtorecv
288/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html
289/// [Linux]: https://man7.org/linux/man-pages/man2/sendto.2.html
290/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendto.2.html
291/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-sendto
292/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendto&sektion=2
293/// [NetBSD]: https://man.netbsd.org/sendto.2
294/// [OpenBSD]: https://man.openbsd.org/sendto.2
295/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendto&section=2
296/// [illumos]: https://illumos.org/man/3SOCKET/sendto
297/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Sending-Datagrams.html
298#[inline]
299#[doc(alias = "sendto")]
300pub fn sendto_v4<Fd: AsFd>(
301 fd: Fd,
302 buf: &[u8],
303 flags: SendFlags,
304 addr: &SocketAddrV4,
305) -> io::Result<usize> {
306 backend::net::syscalls::sendto_v4(fd.as_fd(), buf, flags, addr)
307}
308
309/// `sendto(fd, buf, flags, addr, sizeof(struct sockaddr_in6))`—Writes data
310/// to a socket to a specific IPv6 address.
311///
312/// # References
313/// - [Beej's Guide to Network Programming]
314/// - [POSIX]
315/// - [Linux]
316/// - [Apple]
317/// - [Winsock]
318/// - [FreeBSD]
319/// - [NetBSD]
320/// - [OpenBSD]
321/// - [DragonFly BSD]
322/// - [illumos]
323/// - [glibc]
324///
325/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendtorecv
326/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html
327/// [Linux]: https://man7.org/linux/man-pages/man2/sendto.2.html
328/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendto.2.html
329/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-sendto
330/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendto&sektion=2
331/// [NetBSD]: https://man.netbsd.org/sendto.2
332/// [OpenBSD]: https://man.openbsd.org/sendto.2
333/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendto&section=2
334/// [illumos]: https://illumos.org/man/3SOCKET/sendto
335/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Sending-Datagrams.html
336#[inline]
337#[doc(alias = "sendto")]
338pub fn sendto_v6<Fd: AsFd>(
339 fd: Fd,
340 buf: &[u8],
341 flags: SendFlags,
342 addr: &SocketAddrV6,
343) -> io::Result<usize> {
344 backend::net::syscalls::sendto_v6(fd.as_fd(), buf, flags, addr)
345}
346
347/// `sendto(fd, buf, flags, addr, sizeof(struct sockaddr_un))`—Writes data to
348/// a socket to a specific Unix-domain socket address.
349///
350/// # References
351/// - [Beej's Guide to Network Programming]
352/// - [POSIX]
353/// - [Linux]
354/// - [Apple]
355/// - [Winsock]
356/// - [FreeBSD]
357/// - [NetBSD]
358/// - [OpenBSD]
359/// - [DragonFly BSD]
360/// - [illumos]
361/// - [glibc]
362///
363/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendtorecv
364/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html
365/// [Linux]: https://man7.org/linux/man-pages/man2/sendto.2.html
366/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendto.2.html
367/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-sendto
368/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendto&sektion=2
369/// [NetBSD]: https://man.netbsd.org/sendto.2
370/// [OpenBSD]: https://man.openbsd.org/sendto.2
371/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendto&section=2
372/// [illumos]: https://illumos.org/man/3SOCKET/sendto
373/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Sending-Datagrams.html
374#[cfg(unix)]
375#[inline]
376#[doc(alias = "sendto")]
377pub fn sendto_unix<Fd: AsFd>(
378 fd: Fd,
379 buf: &[u8],
380 flags: SendFlags,
381 addr: &SocketAddrUnix,
382) -> io::Result<usize> {
383 backend::net::syscalls::sendto_unix(fd.as_fd(), buf, flags, addr)
384}
385
386/// `sendto(fd, buf, flags, addr, sizeof(struct sockaddr_xdp))`—Writes data
387/// to a socket to a specific XDP address.
388///
389/// # References
390/// - [Linux]
391///
392/// [Linux]: https://man7.org/linux/man-pages/man2/sendto.2.html
393#[cfg(target_os = "linux")]
394#[inline]
395#[doc(alias = "sendto")]
396pub fn sendto_xdp<Fd: AsFd>(
397 fd: Fd,
398 buf: &[u8],
399 flags: SendFlags,
400 addr: &SocketAddrXdp,
401) -> io::Result<usize> {
402 backend::net::syscalls::sendto_xdp(fd.as_fd(), buf, flags, addr)
403}
404