xref: /third_party/rust/crates/rustix/src/net/socket.rs (revision b8a62b91)
1use crate::fd::OwnedFd;
2use crate::net::{SocketAddr, SocketAddrAny, SocketAddrV4, SocketAddrV6};
3use crate::{backend, io};
4use backend::fd::{AsFd, BorrowedFd};
5
6#[cfg(unix)]
7pub use backend::net::addr::SocketAddrUnix;
8pub use backend::net::types::{
9    AcceptFlags, AddressFamily, Protocol, Shutdown, SocketFlags, SocketType,
10};
11
12impl Default for Protocol {
13    #[inline]
14    fn default() -> Self {
15        Self::IP
16    }
17}
18
19/// `socket(domain, type_, protocol)`—Creates a socket.
20///
21/// POSIX guarantees that `socket` will use the lowest unused file descriptor,
22/// however it is not safe in general to rely on this, as file descriptors
23/// may be unexpectedly allocated on other threads or in libraries.
24///
25/// To pass extra flags such as [`SocketFlags::CLOEXEC`], use [`socket_with`].
26///
27/// # References
28///  - [POSIX]
29///  - [Linux]
30///  - [Apple]
31///  - [Winsock2]
32///
33/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/socket.html
34/// [Linux]: https://man7.org/linux/man-pages/man2/socket.2.html
35/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/socket.2.html
36/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-socket
37#[inline]
38pub fn socket(domain: AddressFamily, type_: SocketType, protocol: Protocol) -> io::Result<OwnedFd> {
39    backend::net::syscalls::socket(domain, type_, protocol)
40}
41
42/// `socket_with(domain, type_ | flags, protocol)`—Creates a socket, with
43/// flags.
44///
45/// POSIX guarantees that `socket` will use the lowest unused file descriptor,
46/// however it is not safe in general to rely on this, as file descriptors
47/// may be unexpectedly allocated on other threads or in libraries.
48///
49/// `socket_with` is the same as [`socket`] but adds an additional flags
50/// operand.
51///
52/// # References
53///  - [POSIX]
54///  - [Linux]
55///  - [Apple]
56///  - [Winsock2]
57///
58/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/socket.html
59/// [Linux]: https://man7.org/linux/man-pages/man2/socket.2.html
60/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/socket.2.html
61/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-socket
62#[inline]
63pub fn socket_with(
64    domain: AddressFamily,
65    type_: SocketType,
66    flags: SocketFlags,
67    protocol: Protocol,
68) -> io::Result<OwnedFd> {
69    backend::net::syscalls::socket_with(domain, type_, flags, protocol)
70}
71
72/// `bind(sockfd, addr)`—Binds a socket to an IP address.
73///
74/// # References
75///  - [POSIX]
76///  - [Linux]
77///  - [Apple]
78///  - [Winsock2]
79///
80/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html
81/// [Linux]: https://man7.org/linux/man-pages/man2/bind.2.html
82/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/bind.2.html
83/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-bind
84pub fn bind<Fd: AsFd>(sockfd: Fd, addr: &SocketAddr) -> io::Result<()> {
85    _bind(sockfd.as_fd(), addr)
86}
87
88fn _bind(sockfd: BorrowedFd<'_>, addr: &SocketAddr) -> io::Result<()> {
89    match addr {
90        SocketAddr::V4(v4) => backend::net::syscalls::bind_v4(sockfd, v4),
91        SocketAddr::V6(v6) => backend::net::syscalls::bind_v6(sockfd, v6),
92    }
93}
94
95/// `bind(sockfd, addr)`—Binds a socket to an address.
96///
97/// # References
98///  - [POSIX]
99///  - [Linux]
100///  - [Apple]
101///  - [Winsock2]
102///
103/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html
104/// [Linux]: https://man7.org/linux/man-pages/man2/bind.2.html
105/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/bind.2.html
106/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-bind
107#[doc(alias = "bind")]
108pub fn bind_any<Fd: AsFd>(sockfd: Fd, addr: &SocketAddrAny) -> io::Result<()> {
109    _bind_any(sockfd.as_fd(), addr)
110}
111
112fn _bind_any(sockfd: BorrowedFd<'_>, addr: &SocketAddrAny) -> io::Result<()> {
113    match addr {
114        SocketAddrAny::V4(v4) => backend::net::syscalls::bind_v4(sockfd, v4),
115        SocketAddrAny::V6(v6) => backend::net::syscalls::bind_v6(sockfd, v6),
116        #[cfg(unix)]
117        SocketAddrAny::Unix(unix) => backend::net::syscalls::bind_unix(sockfd, unix),
118    }
119}
120
121/// `bind(sockfd, addr, sizeof(struct sockaddr_in))`—Binds a socket to an
122/// IPv4 address.
123///
124/// # References
125///  - [POSIX]
126///  - [Linux]
127///  - [Apple]
128///  - [Winsock2]
129///
130/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html
131/// [Linux]: https://man7.org/linux/man-pages/man2/bind.2.html
132/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/bind.2.html
133/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-bind
134#[inline]
135#[doc(alias = "bind")]
136pub fn bind_v4<Fd: AsFd>(sockfd: Fd, addr: &SocketAddrV4) -> io::Result<()> {
137    backend::net::syscalls::bind_v4(sockfd.as_fd(), addr)
138}
139
140/// `bind(sockfd, addr, sizeof(struct sockaddr_in6))`—Binds a socket to an
141/// IPv6 address.
142///
143/// # References
144///  - [POSIX]
145///  - [Linux]
146///  - [Apple]
147///  - [Winsock2]
148///
149/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html
150/// [Linux]: https://man7.org/linux/man-pages/man2/bind.2.html
151/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/bind.2.html
152/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-bind
153#[inline]
154#[doc(alias = "bind")]
155pub fn bind_v6<Fd: AsFd>(sockfd: Fd, addr: &SocketAddrV6) -> io::Result<()> {
156    backend::net::syscalls::bind_v6(sockfd.as_fd(), addr)
157}
158
159/// `bind(sockfd, addr, sizeof(struct sockaddr_un))`—Binds a socket to a
160/// Unix-domain address.
161///
162/// # References
163///  - [POSIX]
164///  - [Linux]
165///  - [Apple]
166///  - [Winsock2]
167///
168/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html
169/// [Linux]: https://man7.org/linux/man-pages/man2/bind.2.html
170/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/bind.2.html
171/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-bind
172#[cfg(unix)]
173#[inline]
174#[doc(alias = "bind")]
175pub fn bind_unix<Fd: AsFd>(sockfd: Fd, addr: &SocketAddrUnix) -> io::Result<()> {
176    backend::net::syscalls::bind_unix(sockfd.as_fd(), addr)
177}
178
179/// `connect(sockfd, addr)`—Initiates a connection to an IP address.
180///
181/// # References
182///  - [POSIX]
183///  - [Linux]
184///  - [Apple]
185///  - [Winsock2]
186///
187/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html
188/// [Linux]: https://man7.org/linux/man-pages/man2/connect.2.html
189/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/connect.2.html
190/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-connect
191pub fn connect<Fd: AsFd>(sockfd: Fd, addr: &SocketAddr) -> io::Result<()> {
192    _connect(sockfd.as_fd(), addr)
193}
194
195fn _connect(sockfd: BorrowedFd<'_>, addr: &SocketAddr) -> io::Result<()> {
196    match addr {
197        SocketAddr::V4(v4) => backend::net::syscalls::connect_v4(sockfd, v4),
198        SocketAddr::V6(v6) => backend::net::syscalls::connect_v6(sockfd, v6),
199    }
200}
201
202/// `connect(sockfd, addr)`—Initiates a connection.
203///
204/// # References
205///  - [POSIX]
206///  - [Linux]
207///  - [Apple]
208///  - [Winsock2]
209///
210/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html
211/// [Linux]: https://man7.org/linux/man-pages/man2/connect.2.html
212/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/connect.2.html
213/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-connect
214#[doc(alias = "connect")]
215pub fn connect_any<Fd: AsFd>(sockfd: Fd, addr: &SocketAddrAny) -> io::Result<()> {
216    _connect_any(sockfd.as_fd(), addr)
217}
218
219fn _connect_any(sockfd: BorrowedFd<'_>, addr: &SocketAddrAny) -> io::Result<()> {
220    match addr {
221        SocketAddrAny::V4(v4) => backend::net::syscalls::connect_v4(sockfd, v4),
222        SocketAddrAny::V6(v6) => backend::net::syscalls::connect_v6(sockfd, v6),
223        #[cfg(unix)]
224        SocketAddrAny::Unix(unix) => backend::net::syscalls::connect_unix(sockfd, unix),
225    }
226}
227
228/// `connect(sockfd, addr, sizeof(struct sockaddr_in))`—Initiates a
229/// connection to an IPv4 address.
230///
231/// # References
232///  - [POSIX]
233///  - [Linux]
234///  - [Apple]
235///  - [Winsock2]
236///
237/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html
238/// [Linux]: https://man7.org/linux/man-pages/man2/connect.2.html
239/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/connect.2.html
240/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-connect
241#[inline]
242#[doc(alias = "connect")]
243pub fn connect_v4<Fd: AsFd>(sockfd: Fd, addr: &SocketAddrV4) -> io::Result<()> {
244    backend::net::syscalls::connect_v4(sockfd.as_fd(), addr)
245}
246
247/// `connect(sockfd, addr, sizeof(struct sockaddr_in6))`—Initiates a
248/// connection to an IPv6 address.
249///
250/// # References
251///  - [POSIX]
252///  - [Linux]
253///  - [Apple]
254///  - [Winsock2]
255///
256/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html
257/// [Linux]: https://man7.org/linux/man-pages/man2/connect.2.html
258/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/connect.2.html
259/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-connect
260#[inline]
261#[doc(alias = "connect")]
262pub fn connect_v6<Fd: AsFd>(sockfd: Fd, addr: &SocketAddrV6) -> io::Result<()> {
263    backend::net::syscalls::connect_v6(sockfd.as_fd(), addr)
264}
265
266/// `connect(sockfd, addr, sizeof(struct sockaddr_un))`—Initiates a
267/// connection to a Unix-domain address.
268///
269/// # References
270///  - [POSIX]
271///  - [Linux]
272///  - [Apple]
273///  - [Winsock2]
274///
275/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html
276/// [Linux]: https://man7.org/linux/man-pages/man2/connect.2.html
277/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/connect.2.html
278/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-connect
279#[cfg(unix)]
280#[inline]
281#[doc(alias = "connect")]
282pub fn connect_unix<Fd: AsFd>(sockfd: Fd, addr: &SocketAddrUnix) -> io::Result<()> {
283    backend::net::syscalls::connect_unix(sockfd.as_fd(), addr)
284}
285
286/// `listen(fd, backlog)`—Enables listening for incoming connections.
287///
288/// # References
289///  - [POSIX]
290///  - [Linux]
291///  - [Apple]
292///  - [Winsock2]
293///
294/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html
295/// [Linux]: https://man7.org/linux/man-pages/man2/listen.2.html
296/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/listen.2.html
297/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-listen
298#[inline]
299pub fn listen<Fd: AsFd>(sockfd: Fd, backlog: i32) -> io::Result<()> {
300    backend::net::syscalls::listen(sockfd.as_fd(), backlog)
301}
302
303/// `accept(fd, NULL, NULL)`—Accepts an incoming connection.
304///
305/// Use [`acceptfrom`] to retrieve the peer address.
306///
307/// POSIX guarantees that `accept` will use the lowest unused file descriptor,
308/// however it is not safe in general to rely on this, as file descriptors may
309/// be unexpectedly allocated on other threads or in libraries.
310///
311/// # References
312///  - [POSIX]
313///  - [Linux]
314///  - [Apple]
315///  - [Winsock2]
316///
317/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.html
318/// [Linux]: https://man7.org/linux/man-pages/man2/accept.2.html
319/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/accept.2.html
320/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-accept
321#[inline]
322#[doc(alias = "accept4")]
323pub fn accept<Fd: AsFd>(sockfd: Fd) -> io::Result<OwnedFd> {
324    backend::net::syscalls::accept(sockfd.as_fd())
325}
326
327/// `accept4(fd, NULL, NULL, flags)`—Accepts an incoming connection, with
328/// flags.
329///
330/// Use [`acceptfrom_with`] to retrieve the peer address.
331///
332/// Even though POSIX guarantees that this will use the lowest unused file
333/// descriptor, it is not safe in general to rely on this, as file descriptors
334/// may be unexpectedly allocated on other threads or in libraries.
335///
336/// `accept_with` is the same as [`accept`] but adds an additional flags
337/// operand.
338///
339/// # References
340///  - [Linux]
341///
342/// [Linux]: https://man7.org/linux/man-pages/man2/accept4.2.html
343#[inline]
344#[doc(alias = "accept4")]
345pub fn accept_with<Fd: AsFd>(sockfd: Fd, flags: AcceptFlags) -> io::Result<OwnedFd> {
346    backend::net::syscalls::accept_with(sockfd.as_fd(), flags)
347}
348
349/// `accept(fd, &addr, &len)`—Accepts an incoming connection and returns the
350/// peer address.
351///
352/// Use [`accept`] if the peer address isn't needed.
353///
354/// # References
355///  - [POSIX]
356///  - [Linux]
357///  - [Apple]
358///  - [Winsock2]
359///
360/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.html
361/// [Linux]: https://man7.org/linux/man-pages/man2/accept.2.html
362/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/accept.2.html
363/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-accept
364#[inline]
365#[doc(alias = "accept4")]
366pub fn acceptfrom<Fd: AsFd>(sockfd: Fd) -> io::Result<(OwnedFd, Option<SocketAddrAny>)> {
367    backend::net::syscalls::acceptfrom(sockfd.as_fd())
368}
369
370/// `accept4(fd, &addr, &len, flags)`—Accepts an incoming connection and
371/// returns the peer address, with flags.
372///
373/// Use [`accept_with`] if the peer address isn't needed.
374///
375/// `acceptfrom_with` is the same as [`acceptfrom`] but adds an additional
376/// flags operand.
377///
378/// # References
379///  - [Linux]
380///
381/// [Linux]: https://man7.org/linux/man-pages/man2/accept4.2.html
382#[inline]
383#[doc(alias = "accept4")]
384pub fn acceptfrom_with<Fd: AsFd>(
385    sockfd: Fd,
386    flags: AcceptFlags,
387) -> io::Result<(OwnedFd, Option<SocketAddrAny>)> {
388    backend::net::syscalls::acceptfrom_with(sockfd.as_fd(), flags)
389}
390
391/// `shutdown(fd, how)`—Closes the read and/or write sides of a stream.
392///
393/// # References
394///  - [POSIX]
395///  - [Linux]
396///  - [Apple]
397///  - [Winsock2]
398///
399/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/shutdown.html
400/// [Linux]: https://man7.org/linux/man-pages/man2/shutdown.2.html
401/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/shutdown.2.html
402/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-shutdown
403#[inline]
404pub fn shutdown<Fd: AsFd>(sockfd: Fd, how: Shutdown) -> io::Result<()> {
405    backend::net::syscalls::shutdown(sockfd.as_fd(), how)
406}
407
408/// `getsockname(fd, addr, len)`—Returns the address a socket is bound to.
409///
410/// # References
411///  - [POSIX]
412///  - [Linux]
413///  - [Apple]
414///  - [Winsock2]
415///
416/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockname.html
417/// [Linux]: https://man7.org/linux/man-pages/man2/getsockname.2.html
418/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getsockname.2.html
419/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockname
420#[inline]
421pub fn getsockname<Fd: AsFd>(sockfd: Fd) -> io::Result<SocketAddrAny> {
422    backend::net::syscalls::getsockname(sockfd.as_fd())
423}
424
425/// `getpeername(fd, addr, len)`—Returns the address a socket is connected
426/// to.
427///
428/// # References
429///  - [POSIX]
430///  - [Linux]
431///  - [Apple]
432///  - [Winsock2]
433///
434/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpeername.html
435/// [Linux]: https://man7.org/linux/man-pages/man2/getpeername.2.html
436/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getpeername.2.html
437/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getpeername
438#[inline]
439pub fn getpeername<Fd: AsFd>(sockfd: Fd) -> io::Result<Option<SocketAddrAny>> {
440    backend::net::syscalls::getpeername(sockfd.as_fd())
441}
442