1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10 
11 //! Utilities for handling sockets
12 //!
13 //! This crate is sort of an evolution of the `net2` crate after seeing the
14 //! issues on it over time. The intention of this crate is to provide as direct
15 //! as possible access to the system's functionality for sockets as possible. No
16 //! extra fluff (e.g. multiple syscalls or builders) provided in this crate. As
17 //! a result using this crate can be a little wordy, but it should give you
18 //! maximal flexibility over configuration of sockets.
19 //!
20 //! # Examples
21 //!
22 //! ```no_run
23 //! use std::net::SocketAddr;
24 //! use socket2::{Socket, Domain, Type};
25 //!
26 //! // create a TCP listener bound to two addresses
27 //! let socket = Socket::new(Domain::ipv6(), Type::stream(), None).unwrap();
28 //!
29 //! socket.bind(&"[::1]:12345".parse::<SocketAddr>().unwrap().into()).unwrap();
30 //! socket.set_only_v6(false);
31 //! socket.listen(128).unwrap();
32 //!
33 //! let listener = socket.into_tcp_listener();
34 //! // ...
35 //! ```
36 
37 #![doc(html_root_url = "https://docs.rs/socket2/0.3")]
38 #![deny(missing_docs)]
39 
40 use crate::utils::NetInt;
41 
42 /// Macro to implement `fmt::Debug` for a type, printing the constant names
43 /// rather than a number.
44 ///
45 /// Note this is used in the `sys` module and thus must be defined before
46 /// defining the modules.
47 macro_rules! impl_debug {
48     (
49         // Type name for which to implement `fmt::Debug`.
50         $type: path,
51         $(
52             $(#[$target: meta])*
53             // The flag(s) to check.
54             // Need to specific the libc crate because Windows doesn't use
55             // `libc` but `winapi`.
56             $libc: ident :: $flag: ident
57         ),+ $(,)*
58     ) => {
59         impl std::fmt::Debug for $type {
60             fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
61                 let string = match self.0 {
62                     $(
63                         $(#[$target])*
64                         $libc :: $flag => stringify!($flag),
65                     )+
66                     n => return write!(f, "{}", n),
67                 };
68                 f.write_str(string)
69             }
70         }
71     };
72 }
73 
74 mod sockaddr;
75 mod socket;
76 mod utils;
77 
78 #[cfg(test)]
79 mod tests;
80 
81 #[cfg(unix)]
82 #[path = "sys/unix.rs"]
83 mod sys;
84 #[cfg(windows)]
85 #[path = "sys/windows.rs"]
86 mod sys;
87 
88 use sys::c_int;
89 
90 pub use sockaddr::SockAddr;
91 pub use socket::Socket;
92 
93 /// Specification of the communication domain for a socket.
94 ///
95 /// This is a newtype wrapper around an integer which provides a nicer API in
96 /// addition to an injection point for documentation. Convenience constructors
97 /// such as `Domain::ipv4`, `Domain::ipv6`, etc, are provided to avoid reaching
98 /// into libc for various constants.
99 ///
100 /// This type is freely interconvertible with C's `int` type, however, if a raw
101 /// value needs to be provided.
102 #[derive(Copy, Clone)]
103 pub struct Domain(c_int);
104 
105 impl Domain {
106     /// Domain for IPv4 communication, corresponding to `AF_INET`.
ipv4() -> Domain107     pub fn ipv4() -> Domain {
108         Domain(sys::AF_INET)
109     }
110 
111     /// Domain for IPv6 communication, corresponding to `AF_INET6`.
ipv6() -> Domain112     pub fn ipv6() -> Domain {
113         Domain(sys::AF_INET6)
114     }
115 }
116 
117 impl From<c_int> for Domain {
from(d: c_int) -> Domain118     fn from(d: c_int) -> Domain {
119         Domain(d)
120     }
121 }
122 
123 impl From<Domain> for c_int {
from(d: Domain) -> c_int124     fn from(d: Domain) -> c_int {
125         d.0
126     }
127 }
128 
129 /// Specification of communication semantics on a socket.
130 ///
131 /// This is a newtype wrapper around an integer which provides a nicer API in
132 /// addition to an injection point for documentation. Convenience constructors
133 /// such as `Type::stream`, `Type::dgram`, etc, are provided to avoid reaching
134 /// into libc for various constants.
135 ///
136 /// This type is freely interconvertible with C's `int` type, however, if a raw
137 /// value needs to be provided.
138 #[derive(Copy, Clone)]
139 pub struct Type(c_int);
140 
141 impl Type {
142     /// Type corresponding to `SOCK_STREAM`.
143     ///
144     /// Used for protocols such as TCP.
stream() -> Type145     pub fn stream() -> Type {
146         Type(sys::SOCK_STREAM)
147     }
148 
149     /// Type corresponding to `SOCK_DGRAM`.
150     ///
151     /// Used for protocols such as UDP.
dgram() -> Type152     pub fn dgram() -> Type {
153         Type(sys::SOCK_DGRAM)
154     }
155 
156     /// Type corresponding to `SOCK_SEQPACKET`.
seqpacket() -> Type157     pub fn seqpacket() -> Type {
158         Type(sys::SOCK_SEQPACKET)
159     }
160 
161     /// Type corresponding to `SOCK_RAW`.
162     #[cfg(not(target_os = "redox"))]
raw() -> Type163     pub fn raw() -> Type {
164         Type(sys::SOCK_RAW)
165     }
166 }
167 
168 impl From<c_int> for Type {
from(t: c_int) -> Type169     fn from(t: c_int) -> Type {
170         Type(t)
171     }
172 }
173 
174 impl From<Type> for c_int {
from(t: Type) -> c_int175     fn from(t: Type) -> c_int {
176         t.0
177     }
178 }
179 
180 /// Protocol specification used for creating sockets via `Socket::new`.
181 ///
182 /// This is a newtype wrapper around an integer which provides a nicer API in
183 /// addition to an injection point for documentation.
184 ///
185 /// This type is freely interconvertible with C's `int` type, however, if a raw
186 /// value needs to be provided.
187 #[derive(Copy, Clone)]
188 pub struct Protocol(c_int);
189 
190 impl Protocol {
191     /// Protocol corresponding to `ICMPv4`.
icmpv4() -> Self192     pub fn icmpv4() -> Self {
193         Protocol(sys::IPPROTO_ICMP)
194     }
195 
196     /// Protocol corresponding to `ICMPv6`.
icmpv6() -> Self197     pub fn icmpv6() -> Self {
198         Protocol(sys::IPPROTO_ICMPV6)
199     }
200 
201     /// Protocol corresponding to `TCP`.
tcp() -> Self202     pub fn tcp() -> Self {
203         Protocol(sys::IPPROTO_TCP)
204     }
205 
206     /// Protocol corresponding to `UDP`.
udp() -> Self207     pub fn udp() -> Self {
208         Protocol(sys::IPPROTO_UDP)
209     }
210 }
211 
212 impl From<c_int> for Protocol {
from(p: c_int) -> Protocol213     fn from(p: c_int) -> Protocol {
214         Protocol(p)
215     }
216 }
217 
218 impl From<Protocol> for c_int {
from(p: Protocol) -> c_int219     fn from(p: Protocol) -> c_int {
220         p.0
221     }
222 }
223 
hton<I: NetInt>(i: I) -> I224 fn hton<I: NetInt>(i: I) -> I {
225     i.to_be()
226 }
227 
ntoh<I: NetInt>(i: I) -> I228 fn ntoh<I: NetInt>(i: I) -> I {
229     I::from_be(i)
230 }
231