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 use std::fmt;
12 use std::io;
13 use std::mem;
14 use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
15 #[cfg(any(unix, target_os = "redox", target_os = "wasi"))]
16 use libc::c_int;
17 #[cfg(windows)]
18 use winapi::ctypes::c_int;
19 
20 use sys;
21 use sys::c;
22 
23 pub struct Socket {
24     inner: sys::Socket,
25 }
26 
27 impl Socket {
new(family: c_int, ty: c_int) -> io::Result<Socket>28     pub fn new(family: c_int, ty: c_int) -> io::Result<Socket> {
29         Ok(Socket { inner: try!(sys::Socket::new(family, ty)) })
30     }
31 
bind(&self, addr: &SocketAddr) -> io::Result<()>32     pub fn bind(&self, addr: &SocketAddr) -> io::Result<()> {
33         let (addr, len) = addr2raw(addr);
34         unsafe {
35             ::cvt(c::bind(self.inner.raw(), addr.as_ptr(), len as c::socklen_t)).map(|_| ())
36         }
37     }
38 
listen(&self, backlog: i32) -> io::Result<()>39     pub fn listen(&self, backlog: i32) -> io::Result<()> {
40         unsafe {
41             ::cvt(c::listen(self.inner.raw(), backlog)).map(|_| ())
42         }
43     }
44 
connect(&self, addr: &SocketAddr) -> io::Result<()>45     pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> {
46         let (addr, len) = addr2raw(addr);
47         unsafe {
48             ::cvt(c::connect(self.inner.raw(), addr.as_ptr(), len)).map(|_| ())
49         }
50     }
51 
getsockname(&self) -> io::Result<SocketAddr>52     pub fn getsockname(&self) -> io::Result<SocketAddr> {
53         unsafe {
54             let mut storage: c::sockaddr_storage = mem::zeroed();
55             let mut len = mem::size_of_val(&storage) as c::socklen_t;
56             try!(::cvt(c::getsockname(self.inner.raw(),
57                                       &mut storage as *mut _ as *mut _,
58                                       &mut len)));
59             raw2addr(&storage, len)
60         }
61     }
62 }
63 
64 impl fmt::Debug for Socket {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result65     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
66         self.inner.raw().fmt(f)
67     }
68 }
69 
70 impl ::AsInner for Socket {
71     type Inner = sys::Socket;
as_inner(&self) -> &sys::Socket72     fn as_inner(&self) -> &sys::Socket { &self.inner }
73 }
74 
75 impl ::FromInner for Socket {
76     type Inner = sys::Socket;
from_inner(sock: sys::Socket) -> Socket77     fn from_inner(sock: sys::Socket) -> Socket {
78         Socket { inner: sock }
79     }
80 }
81 
82 impl ::IntoInner for Socket {
83     type Inner = sys::Socket;
into_inner(self) -> sys::Socket84     fn into_inner(self) -> sys::Socket { self.inner }
85 }
86 
87 /// A type with the same memory layout as `c::sockaddr`. Used in converting Rust level
88 /// SocketAddr* types into their system representation. The benefit of this specific
89 /// type over using `c::sockaddr_storage` is that this type is exactly as large as it
90 /// needs to be and not a lot larger.
91 #[repr(C)]
92 pub(crate) union SocketAddrCRepr {
93     v4: c::sockaddr_in,
94     v6: c::sockaddr_in6,
95 }
96 
97 impl SocketAddrCRepr {
as_ptr(&self) -> *const c::sockaddr98     pub(crate) fn as_ptr(&self) -> *const c::sockaddr {
99         self as *const _ as *const c::sockaddr
100     }
101 }
102 
addr2raw(addr: &SocketAddr) -> (SocketAddrCRepr, c::socklen_t)103 fn addr2raw(addr: &SocketAddr) -> (SocketAddrCRepr, c::socklen_t) {
104     match addr {
105         &SocketAddr::V4(ref v4) => addr2raw_v4(v4),
106         &SocketAddr::V6(ref v6) => addr2raw_v6(v6),
107     }
108 }
109 
110 #[cfg(unix)]
addr2raw_v4(addr: &SocketAddrV4) -> (SocketAddrCRepr, c::socklen_t)111 fn addr2raw_v4(addr: &SocketAddrV4) -> (SocketAddrCRepr, c::socklen_t) {
112     let sin_addr = c::in_addr {
113         s_addr: u32::from(*addr.ip()).to_be(),
114     };
115 
116     let sockaddr = SocketAddrCRepr {
117         v4: c::sockaddr_in {
118             sin_family: c::AF_INET as c::sa_family_t,
119             sin_port: addr.port().to_be(),
120             sin_addr,
121             #[cfg(not(target_os = "haiku"))]
122             sin_zero: [0; 8],
123             #[cfg(target_os = "haiku")]
124             sin_zero: [0; 24],
125             #[cfg(any(
126                 target_os = "dragonfly",
127                 target_os = "freebsd",
128                 target_os = "ios",
129                 target_os = "macos",
130                 target_os = "netbsd",
131                 target_os = "openbsd",
132                 target_os = "haiku",
133             ))]
134             sin_len: 0,
135         },
136     };
137     (sockaddr, mem::size_of::<c::sockaddr_in>() as c::socklen_t)
138 }
139 
140 #[cfg(windows)]
addr2raw_v4(addr: &SocketAddrV4) -> (SocketAddrCRepr, c::socklen_t)141 fn addr2raw_v4(addr: &SocketAddrV4) -> (SocketAddrCRepr, c::socklen_t) {
142     let sin_addr = unsafe {
143         let mut s_un = mem::zeroed::<c::in_addr_S_un>();
144         *s_un.S_addr_mut() = u32::from(*addr.ip()).to_be();
145         c::IN_ADDR { S_un: s_un }
146     };
147 
148     let sockaddr = SocketAddrCRepr {
149         v4: c::sockaddr_in {
150             sin_family: c::AF_INET as c::sa_family_t,
151             sin_port: addr.port().to_be(),
152             sin_addr,
153             sin_zero: [0; 8],
154         },
155     };
156     (sockaddr, mem::size_of::<c::sockaddr_in>() as c::socklen_t)
157 }
158 
159 #[cfg(unix)]
addr2raw_v6(addr: &SocketAddrV6) -> (SocketAddrCRepr, c::socklen_t)160 fn addr2raw_v6(addr: &SocketAddrV6) -> (SocketAddrCRepr, c::socklen_t) {
161     let sin6_addr = {
162         let mut sin6_addr = unsafe { mem::zeroed::<c::in6_addr>() };
163         sin6_addr.s6_addr = addr.ip().octets();
164         sin6_addr
165     };
166 
167     let sockaddr = SocketAddrCRepr {
168         v6: c::sockaddr_in6 {
169             sin6_family: c::AF_INET6 as c::sa_family_t,
170             sin6_port: addr.port().to_be(),
171             sin6_addr,
172             sin6_flowinfo: addr.flowinfo(),
173             sin6_scope_id: addr.scope_id(),
174             #[cfg(any(
175                 target_os = "dragonfly",
176                 target_os = "freebsd",
177                 target_os = "ios",
178                 target_os = "macos",
179                 target_os = "netbsd",
180                 target_os = "openbsd",
181                 target_os = "haiku",
182             ))]
183             sin6_len: 0,
184             #[cfg(any(target_os = "solaris", target_os = "illumos"))]
185             __sin6_src_id: 0,
186         },
187     };
188     (sockaddr, mem::size_of::<c::sockaddr_in6>() as c::socklen_t)
189 }
190 
191 #[cfg(windows)]
addr2raw_v6(addr: &SocketAddrV6) -> (SocketAddrCRepr, c::socklen_t)192 fn addr2raw_v6(addr: &SocketAddrV6) -> (SocketAddrCRepr, c::socklen_t) {
193     let sin6_addr = unsafe {
194         let mut u = mem::zeroed::<c::in6_addr_u>();
195         *u.Byte_mut() = addr.ip().octets();
196         c::IN6_ADDR { u }
197     };
198     let scope_id = unsafe {
199         let mut u = mem::zeroed::<c::SOCKADDR_IN6_LH_u>();
200         *u.sin6_scope_id_mut() = addr.scope_id();
201         u
202     };
203 
204     let sockaddr = SocketAddrCRepr {
205         v6: c::sockaddr_in6 {
206             sin6_family: c::AF_INET6 as c::sa_family_t,
207             sin6_port: addr.port().to_be(),
208             sin6_addr,
209             sin6_flowinfo: addr.flowinfo(),
210             u: scope_id,
211         },
212     };
213     (sockaddr, mem::size_of::<c::sockaddr_in6>() as c::socklen_t)
214 }
215 
raw2addr(storage: &c::sockaddr_storage, len: c::socklen_t) -> io::Result<SocketAddr>216 fn raw2addr(storage: &c::sockaddr_storage, len: c::socklen_t) -> io::Result<SocketAddr> {
217     match storage.ss_family as c_int {
218         c::AF_INET => {
219             unsafe {
220                 assert!(len as usize >= mem::size_of::<c::sockaddr_in>());
221                 let sa = storage as *const _ as *const c::sockaddr_in;
222                 let bits = c::sockaddr_in_u32(&(*sa));
223                 let ip = Ipv4Addr::new((bits >> 24) as u8,
224                                        (bits >> 16) as u8,
225                                        (bits >> 8) as u8,
226                                        bits as u8);
227                 Ok(SocketAddr::V4(SocketAddrV4::new(ip, ::ntoh((*sa).sin_port))))
228             }
229         }
230         c::AF_INET6 => {
231             unsafe {
232                 assert!(len as usize >= mem::size_of::<c::sockaddr_in6>());
233 
234                 let sa = storage as *const _ as *const c::sockaddr_in6;
235                 #[cfg(windows)]      let arr = (*sa).sin6_addr.u.Byte();
236                 #[cfg(not(windows))] let arr = (*sa).sin6_addr.s6_addr;
237 
238                 let ip = Ipv6Addr::new(
239                     (arr[0] as u16) << 8 | (arr[1] as u16),
240                     (arr[2] as u16) << 8 | (arr[3] as u16),
241                     (arr[4] as u16) << 8 | (arr[5] as u16),
242                     (arr[6] as u16) << 8 | (arr[7] as u16),
243                     (arr[8] as u16) << 8 | (arr[9] as u16),
244                     (arr[10] as u16) << 8 | (arr[11] as u16),
245                     (arr[12] as u16) << 8 | (arr[13] as u16),
246                     (arr[14] as u16) << 8 | (arr[15] as u16),
247                 );
248 
249                 #[cfg(windows)]      let sin6_scope_id = *(*sa).u.sin6_scope_id();
250                 #[cfg(not(windows))] let sin6_scope_id = (*sa).sin6_scope_id;
251 
252                 Ok(SocketAddr::V6(SocketAddrV6::new(ip,
253                                                     ::ntoh((*sa).sin6_port),
254                                                     (*sa).sin6_flowinfo,
255                                                     sin6_scope_id)))
256             }
257         }
258         _ => Err(io::Error::new(io::ErrorKind::InvalidInput, "invalid argument")),
259     }
260 }
261