Source code
Revision control
Copy as Markdown
Other Tools
use crate::fd::OwnedFd;
use crate::net::{SocketAddr, SocketAddrAny, SocketAddrV4, SocketAddrV6};
use crate::{backend, io};
use backend::fd::{AsFd, BorrowedFd};
#[cfg(target_os = "linux")]
use crate::net::xdp::SocketAddrXdp;
pub use crate::net::{AddressFamily, Protocol, Shutdown, SocketFlags, SocketType};
#[cfg(unix)]
pub use backend::net::addr::SocketAddrUnix;
/// `socket(domain, type_, protocol)`—Creates a socket.
///
/// POSIX guarantees that `socket` will use the lowest unused file descriptor,
/// however it is not safe in general to rely on this, as file descriptors may
/// be unexpectedly allocated on other threads or in libraries.
///
/// To pass extra flags such as [`SocketFlags::CLOEXEC`] or
/// [`SocketFlags::NONBLOCK`], use [`socket_with`].
///
/// # References
/// - [Beej's Guide to Network Programming]
/// - [POSIX]
/// - [Linux]
/// - [Apple]
/// - [Winsock]
/// - [FreeBSD]
/// - [NetBSD]
/// - [OpenBSD]
/// - [DragonFly BSD]
/// - [illumos]
/// - [glibc]
///
/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#socket
/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/socket.2.html
#[inline]
pub fn socket(
domain: AddressFamily,
type_: SocketType,
protocol: Option<Protocol>,
) -> io::Result<OwnedFd> {
backend::net::syscalls::socket(domain, type_, protocol)
}
/// `socket_with(domain, type_ | flags, protocol)`—Creates a socket, with
/// flags.
///
/// POSIX guarantees that `socket` will use the lowest unused file descriptor,
/// however it is not safe in general to rely on this, as file descriptors may
/// be unexpectedly allocated on other threads or in libraries.
///
/// `socket_with` is the same as [`socket`] but adds an additional flags
/// operand.
///
/// # References
/// - [Beej's Guide to Network Programming]
/// - [POSIX]
/// - [Linux]
/// - [Apple]
/// - [Winsock]
/// - [FreeBSD]
/// - [NetBSD]
/// - [OpenBSD]
/// - [DragonFly BSD]
/// - [illumos]
/// - [glibc]
///
/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#socket
/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/socket.2.html
#[doc(alias("socket"))]
#[inline]
pub fn socket_with(
domain: AddressFamily,
type_: SocketType,
flags: SocketFlags,
protocol: Option<Protocol>,
) -> io::Result<OwnedFd> {
backend::net::syscalls::socket_with(domain, type_, flags, protocol)
}
/// `bind(sockfd, addr)`—Binds a socket to an IP address.
///
/// # References
/// - [Beej's Guide to Network Programming]
/// - [POSIX]
/// - [Linux]
/// - [Apple]
/// - [Winsock]
/// - [FreeBSD]
/// - [NetBSD]
/// - [OpenBSD]
/// - [DragonFly BSD]
/// - [illumos]
/// - [glibc]
///
/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#bind
/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/bind.2.html
pub fn bind<Fd: AsFd>(sockfd: Fd, addr: &SocketAddr) -> io::Result<()> {
_bind(sockfd.as_fd(), addr)
}
fn _bind(sockfd: BorrowedFd<'_>, addr: &SocketAddr) -> io::Result<()> {
match addr {
SocketAddr::V4(v4) => backend::net::syscalls::bind_v4(sockfd, v4),
SocketAddr::V6(v6) => backend::net::syscalls::bind_v6(sockfd, v6),
}
}
/// `bind(sockfd, addr)`—Binds a socket to an address.
///
/// # References
/// - [Beej's Guide to Network Programming]
/// - [POSIX]
/// - [Linux]
/// - [Apple]
/// - [Winsock]
/// - [FreeBSD]
/// - [NetBSD]
/// - [OpenBSD]
/// - [DragonFly BSD]
/// - [illumos]
/// - [glibc]
///
/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#bind
/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/bind.2.html
#[doc(alias = "bind")]
pub fn bind_any<Fd: AsFd>(sockfd: Fd, addr: &SocketAddrAny) -> io::Result<()> {
_bind_any(sockfd.as_fd(), addr)
}
fn _bind_any(sockfd: BorrowedFd<'_>, addr: &SocketAddrAny) -> io::Result<()> {
match addr {
SocketAddrAny::V4(v4) => backend::net::syscalls::bind_v4(sockfd, v4),
SocketAddrAny::V6(v6) => backend::net::syscalls::bind_v6(sockfd, v6),
#[cfg(unix)]
SocketAddrAny::Unix(unix) => backend::net::syscalls::bind_unix(sockfd, unix),
#[cfg(target_os = "linux")]
SocketAddrAny::Xdp(xdp) => backend::net::syscalls::bind_xdp(sockfd, xdp),
}
}
/// `bind(sockfd, addr, sizeof(struct sockaddr_in))`—Binds a socket to an
/// IPv4 address.
///
/// # References
/// - [Beej's Guide to Network Programming]
/// - [POSIX]
/// - [Linux]
/// - [Apple]
/// - [Winsock]
/// - [FreeBSD]
/// - [NetBSD]
/// - [OpenBSD]
/// - [DragonFly BSD]
/// - [illumos]
/// - [glibc]
///
/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#bind
/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/bind.2.html
#[inline]
#[doc(alias = "bind")]
pub fn bind_v4<Fd: AsFd>(sockfd: Fd, addr: &SocketAddrV4) -> io::Result<()> {
backend::net::syscalls::bind_v4(sockfd.as_fd(), addr)
}
/// `bind(sockfd, addr, sizeof(struct sockaddr_in6))`—Binds a socket to an
/// IPv6 address.
///
/// # References
/// - [Beej's Guide to Network Programming]
/// - [POSIX]
/// - [Linux]
/// - [Apple]
/// - [Winsock]
/// - [FreeBSD]
/// - [NetBSD]
/// - [OpenBSD]
/// - [DragonFly BSD]
/// - [illumos]
/// - [glibc]
///
/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#bind
/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/bind.2.html
#[inline]
#[doc(alias = "bind")]
pub fn bind_v6<Fd: AsFd>(sockfd: Fd, addr: &SocketAddrV6) -> io::Result<()> {
backend::net::syscalls::bind_v6(sockfd.as_fd(), addr)
}
/// `bind(sockfd, addr, sizeof(struct sockaddr_un))`—Binds a socket to a
/// Unix-domain address.
///
/// # References
/// - [Beej's Guide to Network Programming]
/// - [POSIX]
/// - [Linux]
/// - [Apple]
/// - [Winsock]
/// - [FreeBSD]
/// - [NetBSD]
/// - [OpenBSD]
/// - [DragonFly BSD]
/// - [illumos]
/// - [glibc]
///
/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#bind
/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/bind.2.html
#[cfg(unix)]
#[inline]
#[doc(alias = "bind")]
pub fn bind_unix<Fd: AsFd>(sockfd: Fd, addr: &SocketAddrUnix) -> io::Result<()> {
backend::net::syscalls::bind_unix(sockfd.as_fd(), addr)
}
/// `bind(sockfd, addr, sizeof(struct sockaddr_un))`—Binds a socket to a XDP
/// address.
///
/// # References
/// - [Linux]
///
#[cfg(target_os = "linux")]
#[inline]
#[doc(alias = "bind")]
pub fn bind_xdp<Fd: AsFd>(sockfd: Fd, addr: &SocketAddrXdp) -> io::Result<()> {
backend::net::syscalls::bind_xdp(sockfd.as_fd(), addr)
}
/// `connect(sockfd, addr)`—Initiates a connection to an IP address.
///
/// On Windows, a non-blocking socket returns [`Errno::WOULDBLOCK`] if the
/// connection cannot be completed immediately, rather than
/// `Errno::INPROGRESS`.
///
/// # References
/// - [Beej's Guide to Network Programming]
/// - [POSIX]
/// - [Linux]
/// - [Apple]
/// - [Winsock]
/// - [FreeBSD]
/// - [NetBSD]
/// - [OpenBSD]
/// - [DragonFly BSD]
/// - [illumos]
/// - [glibc]
///
/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#connect
/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/connect.2.html
/// [`Errno::WOULDBLOCK`]: io::Errno::WOULDBLOCK
pub fn connect<Fd: AsFd>(sockfd: Fd, addr: &SocketAddr) -> io::Result<()> {
_connect(sockfd.as_fd(), addr)
}
fn _connect(sockfd: BorrowedFd<'_>, addr: &SocketAddr) -> io::Result<()> {
match addr {
SocketAddr::V4(v4) => backend::net::syscalls::connect_v4(sockfd, v4),
SocketAddr::V6(v6) => backend::net::syscalls::connect_v6(sockfd, v6),
}
}
/// `connect(sockfd, addr)`—Initiates a connection.
///
/// # References
/// - [Beej's Guide to Network Programming]
/// - [POSIX]
/// - [Linux]
/// - [Apple]
/// - [Winsock]
/// - [FreeBSD]
/// - [NetBSD]
/// - [OpenBSD]
/// - [DragonFly BSD]
/// - [illumos]
/// - [glibc]
///
/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#connect
/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/connect.2.html
#[doc(alias = "connect")]
pub fn connect_any<Fd: AsFd>(sockfd: Fd, addr: &SocketAddrAny) -> io::Result<()> {
_connect_any(sockfd.as_fd(), addr)
}
fn _connect_any(sockfd: BorrowedFd<'_>, addr: &SocketAddrAny) -> io::Result<()> {
match addr {
SocketAddrAny::V4(v4) => backend::net::syscalls::connect_v4(sockfd, v4),
SocketAddrAny::V6(v6) => backend::net::syscalls::connect_v6(sockfd, v6),
#[cfg(unix)]
SocketAddrAny::Unix(unix) => backend::net::syscalls::connect_unix(sockfd, unix),
#[cfg(target_os = "linux")]
SocketAddrAny::Xdp(_) => Err(io::Errno::OPNOTSUPP),
}
}
/// `connect(sockfd, addr, sizeof(struct sockaddr_in))`—Initiates a
/// connection to an IPv4 address.
///
/// # References
/// - [Beej's Guide to Network Programming]
/// - [POSIX]
/// - [Linux]
/// - [Apple]
/// - [Winsock]
/// - [FreeBSD]
/// - [NetBSD]
/// - [OpenBSD]
/// - [DragonFly BSD]
/// - [illumos]
/// - [glibc]
///
/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#connect
/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/connect.2.html
#[inline]
#[doc(alias = "connect")]
pub fn connect_v4<Fd: AsFd>(sockfd: Fd, addr: &SocketAddrV4) -> io::Result<()> {
backend::net::syscalls::connect_v4(sockfd.as_fd(), addr)
}
/// `connect(sockfd, addr, sizeof(struct sockaddr_in6))`—Initiates a
/// connection to an IPv6 address.
///
/// # References
/// - [Beej's Guide to Network Programming]
/// - [POSIX]
/// - [Linux]
/// - [Apple]
/// - [Winsock]
/// - [FreeBSD]
/// - [NetBSD]
/// - [OpenBSD]
/// - [DragonFly BSD]
/// - [illumos]
/// - [glibc]
///
/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#connect
/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/connect.2.html
#[inline]
#[doc(alias = "connect")]
pub fn connect_v6<Fd: AsFd>(sockfd: Fd, addr: &SocketAddrV6) -> io::Result<()> {
backend::net::syscalls::connect_v6(sockfd.as_fd(), addr)
}
/// `connect(sockfd, addr, sizeof(struct sockaddr_un))`—Initiates a
/// connection to a Unix-domain address.
///
/// # References
/// - [Beej's Guide to Network Programming]
/// - [POSIX]
/// - [Linux]
/// - [Apple]
/// - [Winsock]
/// - [FreeBSD]
/// - [NetBSD]
/// - [OpenBSD]
/// - [DragonFly BSD]
/// - [illumos]
/// - [glibc]
///
/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#connect
/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/connect.2.html
#[cfg(unix)]
#[inline]
#[doc(alias = "connect")]
pub fn connect_unix<Fd: AsFd>(sockfd: Fd, addr: &SocketAddrUnix) -> io::Result<()> {
backend::net::syscalls::connect_unix(sockfd.as_fd(), addr)
}
/// `connect(sockfd, {.sa_family = AF_UNSPEC}, sizeof(struct sockaddr))`
/// — Dissolve the socket's association.
///
/// On UDP sockets, BSD platforms report [`Errno::AFNOSUPPORT`] or
/// [`Errno::INVAL`] even if the disconnect was successful.
///
/// # References
/// - [Beej's Guide to Network Programming]
/// - [POSIX]
/// - [Linux]
/// - [Apple]
/// - [Winsock]
/// - [FreeBSD]
/// - [NetBSD]
/// - [OpenBSD]
/// - [DragonFly BSD]
/// - [illumos]
/// - [glibc]
///
/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#connect
/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/connect.2.html
/// [`Errno::AFNOSUPPORT`]: io::Errno::AFNOSUPPORT
/// [`Errno::INVAL`]: io::Errno::INVAL
#[inline]
#[doc(alias = "connect")]
pub fn connect_unspec<Fd: AsFd>(sockfd: Fd) -> io::Result<()> {
backend::net::syscalls::connect_unspec(sockfd.as_fd())
}
/// `listen(fd, backlog)`—Enables listening for incoming connections.
///
/// # References
/// - [Beej's Guide to Network Programming]
/// - [POSIX]
/// - [Linux]
/// - [Apple]
/// - [Winsock]
/// - [FreeBSD]
/// - [NetBSD]
/// - [OpenBSD]
/// - [DragonFly BSD]
/// - [illumos]
/// - [glibc]
///
/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#listen
/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/listen.2.html
#[inline]
pub fn listen<Fd: AsFd>(sockfd: Fd, backlog: i32) -> io::Result<()> {
backend::net::syscalls::listen(sockfd.as_fd(), backlog)
}
/// `accept(fd, NULL, NULL)`—Accepts an incoming connection.
///
/// Use [`acceptfrom`] to retrieve the peer address.
///
/// POSIX guarantees that `accept` will use the lowest unused file descriptor,
/// however it is not safe in general to rely on this, as file descriptors may
/// be unexpectedly allocated on other threads or in libraries.
///
/// # References
/// - [Beej's Guide to Network Programming]
/// - [POSIX]
/// - [Linux]
/// - [Apple]
/// - [Winsock]
/// - [FreeBSD]
/// - [NetBSD]
/// - [OpenBSD]
/// - [DragonFly BSD]
/// - [illumos]
/// - [glibc]
///
/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#acceptthank-you-for-calling-port-3490.
/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/accept.2.html
#[inline]
pub fn accept<Fd: AsFd>(sockfd: Fd) -> io::Result<OwnedFd> {
backend::net::syscalls::accept(sockfd.as_fd())
}
/// `accept4(fd, NULL, NULL, flags)`—Accepts an incoming connection, with
/// flags.
///
/// Use [`acceptfrom_with`] to retrieve the peer address.
///
/// Even though POSIX guarantees that this will use the lowest unused file
/// descriptor, it is not safe in general to rely on this, as file descriptors
/// may be unexpectedly allocated on other threads or in libraries.
///
/// `accept_with` is the same as [`accept`] but adds an additional flags
/// operand.
///
/// # References
/// - [Linux]
/// - [FreeBSD]
/// - [NetBSD]
/// - [OpenBSD]
/// - [DragonFly BSD]
/// - [illumos]
///
#[inline]
#[doc(alias = "accept4")]
pub fn accept_with<Fd: AsFd>(sockfd: Fd, flags: SocketFlags) -> io::Result<OwnedFd> {
backend::net::syscalls::accept_with(sockfd.as_fd(), flags)
}
/// `accept(fd, &addr, &len)`—Accepts an incoming connection and returns the
/// peer address.
///
/// Use [`accept`] if the peer address isn't needed.
///
/// # References
/// - [Beej's Guide to Network Programming]
/// - [POSIX]
/// - [Linux]
/// - [Apple]
/// - [Winsock]
/// - [FreeBSD]
/// - [NetBSD]
/// - [OpenBSD]
/// - [DragonFly BSD]
/// - [illumos]
/// - [glibc]
///
/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#acceptthank-you-for-calling-port-3490.
/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/accept.2.html
#[inline]
#[doc(alias = "accept")]
pub fn acceptfrom<Fd: AsFd>(sockfd: Fd) -> io::Result<(OwnedFd, Option<SocketAddrAny>)> {
backend::net::syscalls::acceptfrom(sockfd.as_fd())
}
/// `accept4(fd, &addr, &len, flags)`—Accepts an incoming connection and
/// returns the peer address, with flags.
///
/// Use [`accept_with`] if the peer address isn't needed.
///
/// `acceptfrom_with` is the same as [`acceptfrom`] but adds an additional
/// flags operand.
///
/// # References
/// - [Linux]
/// - [FreeBSD]
/// - [NetBSD]
/// - [OpenBSD]
/// - [DragonFly BSD]
/// - [illumos]
///
#[inline]
#[doc(alias = "accept4")]
pub fn acceptfrom_with<Fd: AsFd>(
sockfd: Fd,
flags: SocketFlags,
) -> io::Result<(OwnedFd, Option<SocketAddrAny>)> {
backend::net::syscalls::acceptfrom_with(sockfd.as_fd(), flags)
}
/// `shutdown(fd, how)`—Closes the read and/or write sides of a stream.
///
/// # References
/// - [Beej's Guide to Network Programming]
/// - [POSIX]
/// - [Linux]
/// - [Apple]
/// - [Winsock]
/// - [FreeBSD]
/// - [NetBSD]
/// - [OpenBSD]
/// - [DragonFly BSD]
/// - [illumos]
/// - [glibc]
///
/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#close-and-shutdownget-outta-my-face
/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/shutdown.2.html
#[inline]
pub fn shutdown<Fd: AsFd>(sockfd: Fd, how: Shutdown) -> io::Result<()> {
backend::net::syscalls::shutdown(sockfd.as_fd(), how)
}
/// `getsockname(fd, addr, len)`—Returns the address a socket is bound to.
///
/// # References
/// - [POSIX]
/// - [Linux]
/// - [Apple]
/// - [Winsock]
/// - [FreeBSD]
/// - [NetBSD]
/// - [OpenBSD]
/// - [DragonFly BSD]
/// - [illumos]
/// - [glibc]
///
/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getsockname.2.html
#[inline]
pub fn getsockname<Fd: AsFd>(sockfd: Fd) -> io::Result<SocketAddrAny> {
backend::net::syscalls::getsockname(sockfd.as_fd())
}
/// `getpeername(fd, addr, len)`—Returns the address a socket is connected
/// to.
///
/// # References
/// - [Beej's Guide to Network Programming]
/// - [POSIX]
/// - [Linux]
/// - [Apple]
/// - [Winsock]
/// - [FreeBSD]
/// - [NetBSD]
/// - [OpenBSD]
/// - [DragonFly BSD]
/// - [illumos]
/// - [glibc]
///
/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#getpeernamewho-are-you
/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getpeername.2.html
#[inline]
pub fn getpeername<Fd: AsFd>(sockfd: Fd) -> io::Result<Option<SocketAddrAny>> {
backend::net::syscalls::getpeername(sockfd.as_fd())
}