1 //! `recv`, `send`, and variants.
2
3 #![allow(unsafe_code)]
4
5 use crate::buffer::split_init;
6 #[cfg(target_os = "linux")]
7 use crate::net::xdp::SocketAddrXdp;
8 #[cfg(unix)]
9 use crate::net::SocketAddrUnix;
10 use crate::net::{SocketAddr, SocketAddrAny, SocketAddrV4, SocketAddrV6};
11 use crate::{backend, io};
12 use backend::fd::{AsFd, BorrowedFd};
13 use core::mem::MaybeUninit;
14
15 pub 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 )))]
24 mod 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 )))]
33 pub 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§ion=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]
recv<Fd: AsFd>(fd: Fd, buf: &mut [u8], flags: RecvFlags) -> io::Result<usize>62 pub fn recv<Fd: AsFd>(fd: Fd, buf: &mut [u8], flags: RecvFlags) -> io::Result<usize> {
63 unsafe { backend::net::syscalls::recv(fd.as_fd(), 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]
recv_uninit<Fd: AsFd>( fd: Fd, buf: &mut [MaybeUninit<u8>], flags: RecvFlags, ) -> io::Result<(&mut [u8], &mut [MaybeUninit<u8>])>72 pub 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 = unsafe {
78 backend::net::syscalls::recv(fd.as_fd(), buf.as_mut_ptr() as *mut u8, buf.len(), flags)
79 };
80
81 Ok(unsafe { split_init(buf, 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§ion=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]
send<Fd: AsFd>(fd: Fd, buf: &[u8], flags: SendFlags) -> io::Result<usize>111 pub 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§ion=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]
recvfrom<Fd: AsFd>( fd: Fd, buf: &mut [u8], flags: RecvFlags, ) -> io::Result<(usize, Option<SocketAddrAny>)>143 pub 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.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]
recvfrom_uninit<Fd: AsFd>( fd: Fd, buf: &mut [MaybeUninit<u8>], flags: RecvFlags, ) -> io::Result<(&mut [u8], &mut [MaybeUninit<u8>], Option<SocketAddrAny>)>159 pub 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, addr) = unsafe {
165 backend::net::syscalls::recvfrom(fd.as_fd(), buf.as_mut_ptr() as *mut u8, buf.len(), flags)?
166 };
167 let (init, uninit) = unsafe { split_init(buf, 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§ion=2
196 /// [illumos]: https://illumos.org/man/3SOCKET/sendto
197 /// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Sending-Datagrams.html
sendto<Fd: AsFd>( fd: Fd, buf: &[u8], flags: SendFlags, addr: &SocketAddr, ) -> io::Result<usize>198 pub 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
_sendto( fd: BorrowedFd<'_>, buf: &[u8], flags: SendFlags, addr: &SocketAddr, ) -> io::Result<usize>207 fn _sendto(
208 fd: BorrowedFd<'_>,
209 buf: &[u8],
210 flags: SendFlags,
211 addr: &SocketAddr,
212 ) -> io::Result<usize> {
213 match addr {
214 SocketAddr::V4(v4) => backend::net::syscalls::sendto_v4(fd, buf, flags, v4),
215 SocketAddr::V6(v6) => backend::net::syscalls::sendto_v6(fd, buf, flags, 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§ion=2
244 /// [illumos]: https://illumos.org/man/3SOCKET/sendto
245 /// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Sending-Datagrams.html
sendto_any<Fd: AsFd>( fd: Fd, buf: &[u8], flags: SendFlags, addr: &SocketAddrAny, ) -> io::Result<usize>246 pub 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
_sendto_any( fd: BorrowedFd<'_>, buf: &[u8], flags: SendFlags, addr: &SocketAddrAny, ) -> io::Result<usize>255 fn _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) => backend::net::syscalls::sendto_v4(fd, buf, flags, v4),
263 SocketAddrAny::V6(v6) => backend::net::syscalls::sendto_v6(fd, buf, flags, v6),
264 #[cfg(unix)]
265 SocketAddrAny::Unix(unix) => backend::net::syscalls::sendto_unix(fd, buf, flags, unix),
266 #[cfg(target_os = "linux")]
267 SocketAddrAny::Xdp(xdp) => backend::net::syscalls::sendto_xdp(fd, buf, flags, 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§ion=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")]
sendto_v4<Fd: AsFd>( fd: Fd, buf: &[u8], flags: SendFlags, addr: &SocketAddrV4, ) -> io::Result<usize>300 pub 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§ion=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")]
sendto_v6<Fd: AsFd>( fd: Fd, buf: &[u8], flags: SendFlags, addr: &SocketAddrV6, ) -> io::Result<usize>338 pub 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§ion=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")]
sendto_unix<Fd: AsFd>( fd: Fd, buf: &[u8], flags: SendFlags, addr: &SocketAddrUnix, ) -> io::Result<usize>377 pub 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")]
sendto_xdp<Fd: AsFd>( fd: Fd, buf: &[u8], flags: SendFlags, addr: &SocketAddrXdp, ) -> io::Result<usize>396 pub 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