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 ] |
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: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 ] |
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: 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§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 ] |
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 ] |
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: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 ] |
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: 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§ion=2 |
196 | /// [illumos]: https://illumos.org/man/3SOCKET/sendto |
197 | /// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Sending-Datagrams.html |
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 | |
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: &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§ion=2 |
244 | /// [illumos]: https://illumos.org/man/3SOCKET/sendto |
245 | /// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Sending-Datagrams.html |
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 | |
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: &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§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" )] |
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" )] |
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" )] |
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" )] |
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 | |