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