]> git.proxmox.com Git - rustc.git/blob - src/libstd/sys/windows/net.rs
Imported Upstream version 1.3.0+dfsg1
[rustc.git] / src / libstd / sys / windows / net.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 prelude::v1::*;
12
13 use io;
14 use libc::consts::os::extra::INVALID_SOCKET;
15 use libc::{self, c_int, c_void};
16 use mem;
17 use net::SocketAddr;
18 use num::One;
19 use ops::Neg;
20 use rt;
21 use sync::Once;
22 use sys;
23 use sys::c;
24 use sys_common::{AsInner, FromInner, IntoInner};
25 use sys_common::net::{setsockopt, getsockopt};
26 use time::Duration;
27
28 pub type wrlen_t = i32;
29
30 pub struct Socket(libc::SOCKET);
31
32 /// Checks whether the Windows socket interface has been started already, and
33 /// if not, starts it.
34 pub fn init() {
35 static START: Once = Once::new();
36
37 START.call_once(|| unsafe {
38 let mut data: c::WSADATA = mem::zeroed();
39 let ret = c::WSAStartup(0x202, // version 2.2
40 &mut data);
41 assert_eq!(ret, 0);
42
43 let _ = rt::at_exit(|| { c::WSACleanup(); });
44 });
45 }
46
47 /// Returns the last error from the Windows socket interface.
48 fn last_error() -> io::Error {
49 io::Error::from_raw_os_error(unsafe { c::WSAGetLastError() })
50 }
51
52 /// Checks if the signed integer is the Windows constant `SOCKET_ERROR` (-1)
53 /// and if so, returns the last error from the Windows socket interface. . This
54 /// function must be called before another call to the socket API is made.
55 pub fn cvt<T: One + Neg<Output=T> + PartialEq>(t: T) -> io::Result<T> {
56 let one: T = T::one();
57 if t == -one {
58 Err(last_error())
59 } else {
60 Ok(t)
61 }
62 }
63
64 /// Provides the functionality of `cvt` for the return values of `getaddrinfo`
65 /// and similar, meaning that they return an error if the return value is 0.
66 pub fn cvt_gai(err: c_int) -> io::Result<()> {
67 if err == 0 { return Ok(()) }
68 cvt(err).map(|_| ())
69 }
70
71 /// Provides the functionality of `cvt` for a closure.
72 #[allow(deprecated)]
73 pub fn cvt_r<T, F>(mut f: F) -> io::Result<T>
74 where F: FnMut() -> T, T: One + Neg<Output=T> + PartialEq
75 {
76 cvt(f())
77 }
78
79 impl Socket {
80 pub fn new(addr: &SocketAddr, ty: c_int) -> io::Result<Socket> {
81 let fam = match *addr {
82 SocketAddr::V4(..) => libc::AF_INET,
83 SocketAddr::V6(..) => libc::AF_INET6,
84 };
85 let socket = try!(unsafe {
86 match c::WSASocketW(fam, ty, 0, 0 as *mut _, 0,
87 c::WSA_FLAG_OVERLAPPED) {
88 INVALID_SOCKET => Err(last_error()),
89 n => Ok(Socket(n)),
90 }
91 });
92 try!(socket.set_no_inherit());
93 Ok(socket)
94 }
95
96 pub fn accept(&self, storage: *mut libc::sockaddr,
97 len: *mut libc::socklen_t) -> io::Result<Socket> {
98 let socket = try!(unsafe {
99 match libc::accept(self.0, storage, len) {
100 INVALID_SOCKET => Err(last_error()),
101 n => Ok(Socket(n)),
102 }
103 });
104 try!(socket.set_no_inherit());
105 Ok(socket)
106 }
107
108 pub fn duplicate(&self) -> io::Result<Socket> {
109 let socket = try!(unsafe {
110 let mut info: c::WSAPROTOCOL_INFO = mem::zeroed();
111 try!(cvt(c::WSADuplicateSocketW(self.0,
112 c::GetCurrentProcessId(),
113 &mut info)));
114 match c::WSASocketW(info.iAddressFamily,
115 info.iSocketType,
116 info.iProtocol,
117 &mut info, 0,
118 c::WSA_FLAG_OVERLAPPED) {
119 INVALID_SOCKET => Err(last_error()),
120 n => Ok(Socket(n)),
121 }
122 });
123 try!(socket.set_no_inherit());
124 Ok(socket)
125 }
126
127 pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
128 // On unix when a socket is shut down all further reads return 0, so we
129 // do the same on windows to map a shut down socket to returning EOF.
130 unsafe {
131 match libc::recv(self.0, buf.as_mut_ptr() as *mut c_void,
132 buf.len() as i32, 0) {
133 -1 if c::WSAGetLastError() == c::WSAESHUTDOWN => Ok(0),
134 -1 => Err(last_error()),
135 n => Ok(n as usize)
136 }
137 }
138 }
139
140 pub fn set_timeout(&self, dur: Option<Duration>, kind: libc::c_int) -> io::Result<()> {
141 let timeout = match dur {
142 Some(dur) => {
143 let timeout = sys::dur2timeout(dur);
144 if timeout == 0 {
145 return Err(io::Error::new(io::ErrorKind::InvalidInput,
146 "cannot set a 0 duration timeout"));
147 }
148 timeout
149 }
150 None => 0
151 };
152 setsockopt(self, libc::SOL_SOCKET, kind, timeout)
153 }
154
155 pub fn timeout(&self, kind: libc::c_int) -> io::Result<Option<Duration>> {
156 let raw: libc::DWORD = try!(getsockopt(self, libc::SOL_SOCKET, kind));
157 if raw == 0 {
158 Ok(None)
159 } else {
160 let secs = raw / 1000;
161 let nsec = (raw % 1000) * 1000000;
162 Ok(Some(Duration::new(secs as u64, nsec as u32)))
163 }
164 }
165
166 fn set_no_inherit(&self) -> io::Result<()> {
167 sys::cvt(unsafe {
168 c::SetHandleInformation(self.0 as libc::HANDLE,
169 c::HANDLE_FLAG_INHERIT, 0)
170 }).map(|_| ())
171 }
172 }
173
174 impl Drop for Socket {
175 fn drop(&mut self) {
176 let _ = unsafe { libc::closesocket(self.0) };
177 }
178 }
179
180 impl AsInner<libc::SOCKET> for Socket {
181 fn as_inner(&self) -> &libc::SOCKET { &self.0 }
182 }
183
184 impl FromInner<libc::SOCKET> for Socket {
185 fn from_inner(sock: libc::SOCKET) -> Socket { Socket(sock) }
186 }
187
188 impl IntoInner<libc::SOCKET> for Socket {
189 fn into_inner(self) -> libc::SOCKET {
190 let ret = self.0;
191 mem::forget(self);
192 ret
193 }
194 }