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