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