blob: c0354f1251256715882c07aaa3eb2d6a46ad2b00 [file] [log] [blame]
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Utilities for handling sockets
//!
//! This crate is sort of an evolution of the `net2` crate after seeing the
//! issues on it over time. The intention of this crate is to provide as direct
//! as possible access to the system's functionality for sockets as possible. No
//! extra fluff (e.g. multiple syscalls or builders) provided in this crate. As
//! a result using this crate can be a little wordy, but it should give you
//! maximal flexibility over configuration of sockets.
//!
//! # Examples
//!
//! ```no_run
//! use std::net::SocketAddr;
//! use socket2::{Socket, Domain, Type};
//!
//! // create a TCP listener bound to two addresses
//! let socket = Socket::new(Domain::ipv6(), Type::stream(), None).unwrap();
//!
//! socket.bind(&"[::1]:12345".parse::<SocketAddr>().unwrap().into()).unwrap();
//! socket.set_only_v6(false);
//! socket.listen(128).unwrap();
//!
//! let listener = socket.into_tcp_listener();
//! // ...
//! ```
#![doc(html_root_url = "https://docs.rs/socket2/0.3")]
#![deny(missing_docs)]
use crate::utils::NetInt;
/// Macro to implement `fmt::Debug` for a type, printing the constant names
/// rather than a number.
///
/// Note this is used in the `sys` module and thus must be defined before
/// defining the modules.
macro_rules! impl_debug {
(
// Type name for which to implement `fmt::Debug`.
$type: path,
$(
$(#[$target: meta])*
// The flag(s) to check.
// Need to specific the libc crate because Windows doesn't use
// `libc` but `winapi`.
$libc: ident :: $flag: ident
),+ $(,)*
) => {
impl std::fmt::Debug for $type {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let string = match self.0 {
$(
$(#[$target])*
$libc :: $flag => stringify!($flag),
)+
n => return write!(f, "{}", n),
};
f.write_str(string)
}
}
};
}
mod sockaddr;
mod socket;
mod utils;
#[cfg(test)]
mod tests;
#[cfg(unix)]
#[path = "sys/unix.rs"]
mod sys;
#[cfg(windows)]
#[path = "sys/windows.rs"]
mod sys;
use sys::c_int;
pub use sockaddr::SockAddr;
pub use socket::Socket;
/// Specification of the communication domain for a socket.
///
/// This is a newtype wrapper around an integer which provides a nicer API in
/// addition to an injection point for documentation. Convenience constructors
/// such as `Domain::ipv4`, `Domain::ipv6`, etc, are provided to avoid reaching
/// into libc for various constants.
///
/// This type is freely interconvertible with C's `int` type, however, if a raw
/// value needs to be provided.
#[derive(Copy, Clone)]
pub struct Domain(c_int);
impl Domain {
/// Domain for IPv4 communication, corresponding to `AF_INET`.
pub fn ipv4() -> Domain {
Domain(sys::AF_INET)
}
/// Domain for IPv6 communication, corresponding to `AF_INET6`.
pub fn ipv6() -> Domain {
Domain(sys::AF_INET6)
}
}
impl From<c_int> for Domain {
fn from(d: c_int) -> Domain {
Domain(d)
}
}
impl From<Domain> for c_int {
fn from(d: Domain) -> c_int {
d.0
}
}
/// Specification of communication semantics on a socket.
///
/// This is a newtype wrapper around an integer which provides a nicer API in
/// addition to an injection point for documentation. Convenience constructors
/// such as `Type::stream`, `Type::dgram`, etc, are provided to avoid reaching
/// into libc for various constants.
///
/// This type is freely interconvertible with C's `int` type, however, if a raw
/// value needs to be provided.
#[derive(Copy, Clone)]
pub struct Type(c_int);
impl Type {
/// Type corresponding to `SOCK_STREAM`.
///
/// Used for protocols such as TCP.
pub fn stream() -> Type {
Type(sys::SOCK_STREAM)
}
/// Type corresponding to `SOCK_DGRAM`.
///
/// Used for protocols such as UDP.
pub fn dgram() -> Type {
Type(sys::SOCK_DGRAM)
}
/// Type corresponding to `SOCK_SEQPACKET`.
pub fn seqpacket() -> Type {
Type(sys::SOCK_SEQPACKET)
}
/// Type corresponding to `SOCK_RAW`.
#[cfg(not(target_os = "redox"))]
pub fn raw() -> Type {
Type(sys::SOCK_RAW)
}
}
impl From<c_int> for Type {
fn from(t: c_int) -> Type {
Type(t)
}
}
impl From<Type> for c_int {
fn from(t: Type) -> c_int {
t.0
}
}
/// Protocol specification used for creating sockets via `Socket::new`.
///
/// This is a newtype wrapper around an integer which provides a nicer API in
/// addition to an injection point for documentation.
///
/// This type is freely interconvertible with C's `int` type, however, if a raw
/// value needs to be provided.
#[derive(Copy, Clone)]
pub struct Protocol(c_int);
impl Protocol {
/// Protocol corresponding to `ICMPv4`.
pub fn icmpv4() -> Self {
Protocol(sys::IPPROTO_ICMP)
}
/// Protocol corresponding to `ICMPv6`.
pub fn icmpv6() -> Self {
Protocol(sys::IPPROTO_ICMPV6)
}
/// Protocol corresponding to `TCP`.
pub fn tcp() -> Self {
Protocol(sys::IPPROTO_TCP)
}
/// Protocol corresponding to `UDP`.
pub fn udp() -> Self {
Protocol(sys::IPPROTO_UDP)
}
}
impl From<c_int> for Protocol {
fn from(p: c_int) -> Protocol {
Protocol(p)
}
}
impl From<Protocol> for c_int {
fn from(p: Protocol) -> c_int {
p.0
}
}
fn hton<I: NetInt>(i: I) -> I {
i.to_be()
}
fn ntoh<I: NetInt>(i: I) -> I {
I::from_be(i)
}