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(target_os = "redox")]
16 use libc::c_int;
17 #[cfg(unix)]
18 use libc::c_int;
19 #[cfg(windows)]
20 use winapi::ctypes::c_int;
21 
22 use sys;
23 use sys::c;
24 
dlopen(const char * file,int mode)25 pub struct Socket {
26     inner: sys::Socket,
27 }
28 
29 impl Socket {
30     pub fn new(family: c_int, ty: c_int) -> io::Result<Socket> {
31         Ok(Socket { inner: try!(sys::Socket::new(family, ty)) })
32     }
33 
34     pub fn bind(&self, addr: &SocketAddr) -> io::Result<()> {
35         let (addr, len) = addr2raw(addr);
36         unsafe {
37             ::cvt(c::bind(self.inner.raw(), addr, len as c::socklen_t)).map(|_| ())
38         }
39     }
dlsym(void * handle,const char * symbol)40 
41     pub fn listen(&self, backlog: i32) -> io::Result<()> {
42         unsafe {
43             ::cvt(c::listen(self.inner.raw(), backlog)).map(|_| ())
44         }
45     }
46 
47     pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> {
48         let (addr, len) = addr2raw(addr);
49         unsafe {
dlclose(void * handle)50             ::cvt(c::connect(self.inner.raw(), addr, len)).map(|_| ())
51         }
52     }
53 
54     pub fn getsockname(&self) -> io::Result<SocketAddr> {
55         unsafe {
56             let mut storage: c::sockaddr_storage = mem::zeroed();
57             let mut len = mem::size_of_val(&storage) as c::socklen_t;
58             try!(::cvt(c::getsockname(self.inner.raw(),
59                                       &mut storage as *mut _ as *mut _,
60                                       &mut len)));
61             raw2addr(&storage, len)
62         }
63     }
64 }
65 
66 impl fmt::Debug for Socket {
67     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
68         self.inner.raw().fmt(f)
69     }
70 }
set_dl_error(void)71 
72 impl ::AsInner for Socket {
73     type Inner = sys::Socket;
74     fn as_inner(&self) -> &sys::Socket { &self.inner }
75 }
76 
77 impl ::FromInner for Socket {
78     type Inner = sys::Socket;
79     fn from_inner(sock: sys::Socket) -> Socket {
80         Socket { inner: sock }
81     }
82 }
83 
84 impl ::IntoInner for Socket {
85     type Inner = sys::Socket;
86     fn into_inner(self) -> sys::Socket { self.inner }
87 }
88 
89 fn addr2raw(addr: &SocketAddr) -> (*const c::sockaddr, c::socklen_t) {
dlerror(void)90     match *addr {
91         SocketAddr::V4(ref a) => {
92             (a as *const _ as *const _, mem::size_of_val(a) as c::socklen_t)
93         }
94         SocketAddr::V6(ref a) => {
95             (a as *const _ as *const _, mem::size_of_val(a) as c::socklen_t)
96         }
97     }
98 }
dlclose(void * handle)99 
100 fn raw2addr(storage: &c::sockaddr_storage, len: c::socklen_t) -> io::Result<SocketAddr> {
101     match storage.ss_family as c_int {
102         c::AF_INET => {
103             unsafe {
104                 assert!(len as usize >= mem::size_of::<c::sockaddr_in>());
105                 let sa = storage as *const _ as *const c::sockaddr_in;
106                 let bits = c::sockaddr_in_u32(&(*sa));
107                 let ip = Ipv4Addr::new((bits >> 24) as u8,
108                                        (bits >> 16) as u8,
109                                        (bits >> 8) as u8,
110                                        bits as u8);
111                 Ok(SocketAddr::V4(SocketAddrV4::new(ip, ::ntoh((*sa).sin_port))))
112             }
113         }
114         c::AF_INET6 => {
115             unsafe {
116                 assert!(len as usize >= mem::size_of::<c::sockaddr_in6>());
117 
118                 let sa = storage as *const _ as *const c::sockaddr_in6;
119                 #[cfg(windows)]      let arr = (*sa).sin6_addr.u.Byte();
120                 #[cfg(not(windows))] let arr = (*sa).sin6_addr.s6_addr;
121 
122                 let ip = Ipv6Addr::new(
123                     (arr[0] as u16) << 8 | (arr[1] as u16),
124                     (arr[2] as u16) << 8 | (arr[3] as u16),
125                     (arr[4] as u16) << 8 | (arr[5] as u16),
126                     (arr[6] as u16) << 8 | (arr[7] as u16),
127                     (arr[8] as u16) << 8 | (arr[9] as u16),
128                     (arr[10] as u16) << 8 | (arr[11] as u16),
129                     (arr[12] as u16) << 8 | (arr[13] as u16),
130                     (arr[14] as u16) << 8 | (arr[15] as u16),
131                 );
132 
133                 #[cfg(windows)]      let sin6_scope_id = *(*sa).u.sin6_scope_id();
134                 #[cfg(not(windows))] let sin6_scope_id = (*sa).sin6_scope_id;
135 
136                 Ok(SocketAddr::V6(SocketAddrV6::new(ip,
137                                                     ::ntoh((*sa).sin6_port),
138                                                     (*sa).sin6_flowinfo,
139                                                     sin6_scope_id)))
140             }
141         }
142         _ => Err(io::Error::new(io::ErrorKind::InvalidInput, "invalid argument")),
143     }
144 }
145