]> git.proxmox.com Git - rustc.git/blob - src/libstd/sys/windows/net.rs
Imported Upstream version 1.9.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 #![unstable(issue = "0", feature = "windows_net")]
12
13 use prelude::v1::*;
14
15 use cmp;
16 use io::{self, Read};
17 use libc::{c_int, c_void, c_ulong};
18 use mem;
19 use net::{SocketAddr, Shutdown};
20 use num::One;
21 use ops::Neg;
22 use ptr;
23 use sync::Once;
24 use sys::c;
25 use sys;
26 use sys_common::{self, AsInner, FromInner, IntoInner};
27 use sys_common::io::read_to_end_uninitialized;
28 use sys_common::net;
29 use time::Duration;
30
31 pub type wrlen_t = i32;
32
33 pub mod netc {
34 pub use sys::c::*;
35 pub use sys::c::SOCKADDR as sockaddr;
36 pub use sys::c::SOCKADDR_STORAGE_LH as sockaddr_storage;
37 pub use sys::c::ADDRINFOA as addrinfo;
38 pub use sys::c::ADDRESS_FAMILY as sa_family_t;
39 }
40
41 pub struct Socket(c::SOCKET);
42
43 /// Checks whether the Windows socket interface has been started already, and
44 /// if not, starts it.
45 pub fn init() {
46 static START: Once = Once::new();
47
48 START.call_once(|| unsafe {
49 let mut data: c::WSADATA = mem::zeroed();
50 let ret = c::WSAStartup(0x202, // version 2.2
51 &mut data);
52 assert_eq!(ret, 0);
53
54 let _ = sys_common::at_exit(|| { c::WSACleanup(); });
55 });
56 }
57
58 /// Returns the last error from the Windows socket interface.
59 fn last_error() -> io::Error {
60 io::Error::from_raw_os_error(unsafe { c::WSAGetLastError() })
61 }
62
63 /// Checks if the signed integer is the Windows constant `SOCKET_ERROR` (-1)
64 /// and if so, returns the last error from the Windows socket interface. This
65 /// function must be called before another call to the socket API is made.
66 pub fn cvt<T: One + PartialEq + Neg<Output=T>>(t: T) -> io::Result<T> {
67 if t == -T::one() {
68 Err(last_error())
69 } else {
70 Ok(t)
71 }
72 }
73
74 /// A variant of `cvt` for `getaddrinfo` which return 0 for a success.
75 pub fn cvt_gai(err: c_int) -> io::Result<()> {
76 if err == 0 {
77 Ok(())
78 } else {
79 Err(last_error())
80 }
81 }
82
83 /// Just to provide the same interface as sys/unix/net.rs
84 pub fn cvt_r<T, F>(mut f: F) -> io::Result<T>
85 where T: One + PartialEq + Neg<Output=T>, F: FnMut() -> T
86 {
87 cvt(f())
88 }
89
90 impl Socket {
91 pub fn new(addr: &SocketAddr, ty: c_int) -> io::Result<Socket> {
92 let fam = match *addr {
93 SocketAddr::V4(..) => c::AF_INET,
94 SocketAddr::V6(..) => c::AF_INET6,
95 };
96 let socket = unsafe {
97 match c::WSASocketW(fam, ty, 0, ptr::null_mut(), 0,
98 c::WSA_FLAG_OVERLAPPED) {
99 c::INVALID_SOCKET => Err(last_error()),
100 n => Ok(Socket(n)),
101 }
102 }?;
103 socket.set_no_inherit()?;
104 Ok(socket)
105 }
106
107 pub fn accept(&self, storage: *mut c::SOCKADDR,
108 len: *mut c_int) -> io::Result<Socket> {
109 let socket = unsafe {
110 match c::accept(self.0, storage, len) {
111 c::INVALID_SOCKET => Err(last_error()),
112 n => Ok(Socket(n)),
113 }
114 }?;
115 socket.set_no_inherit()?;
116 Ok(socket)
117 }
118
119 pub fn duplicate(&self) -> io::Result<Socket> {
120 let socket = unsafe {
121 let mut info: c::WSAPROTOCOL_INFO = mem::zeroed();
122 cvt(c::WSADuplicateSocketW(self.0,
123 c::GetCurrentProcessId(),
124 &mut info))?;
125 match c::WSASocketW(info.iAddressFamily,
126 info.iSocketType,
127 info.iProtocol,
128 &mut info, 0,
129 c::WSA_FLAG_OVERLAPPED) {
130 c::INVALID_SOCKET => Err(last_error()),
131 n => Ok(Socket(n)),
132 }
133 }?;
134 socket.set_no_inherit()?;
135 Ok(socket)
136 }
137
138 pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
139 // On unix when a socket is shut down all further reads return 0, so we
140 // do the same on windows to map a shut down socket to returning EOF.
141 let len = cmp::min(buf.len(), i32::max_value() as usize) as i32;
142 unsafe {
143 match c::recv(self.0, buf.as_mut_ptr() as *mut c_void, len, 0) {
144 -1 if c::WSAGetLastError() == c::WSAESHUTDOWN => Ok(0),
145 -1 => Err(last_error()),
146 n => Ok(n as usize)
147 }
148 }
149 }
150
151 pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
152 let mut me = self;
153 (&mut me).read_to_end(buf)
154 }
155
156 pub fn set_timeout(&self, dur: Option<Duration>,
157 kind: c_int) -> io::Result<()> {
158 let timeout = match dur {
159 Some(dur) => {
160 let timeout = sys::dur2timeout(dur);
161 if timeout == 0 {
162 return Err(io::Error::new(io::ErrorKind::InvalidInput,
163 "cannot set a 0 duration timeout"));
164 }
165 timeout
166 }
167 None => 0
168 };
169 net::setsockopt(self, c::SOL_SOCKET, kind, timeout)
170 }
171
172 pub fn timeout(&self, kind: c_int) -> io::Result<Option<Duration>> {
173 let raw: c::DWORD = net::getsockopt(self, c::SOL_SOCKET, kind)?;
174 if raw == 0 {
175 Ok(None)
176 } else {
177 let secs = raw / 1000;
178 let nsec = (raw % 1000) * 1000000;
179 Ok(Some(Duration::new(secs as u64, nsec as u32)))
180 }
181 }
182
183 fn set_no_inherit(&self) -> io::Result<()> {
184 sys::cvt(unsafe {
185 c::SetHandleInformation(self.0 as c::HANDLE,
186 c::HANDLE_FLAG_INHERIT, 0)
187 }).map(|_| ())
188 }
189
190 pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
191 let how = match how {
192 Shutdown::Write => c::SD_SEND,
193 Shutdown::Read => c::SD_RECEIVE,
194 Shutdown::Both => c::SD_BOTH,
195 };
196 cvt(unsafe { c::shutdown(self.0, how) })?;
197 Ok(())
198 }
199
200 pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
201 let mut nonblocking = nonblocking as c_ulong;
202 let r = unsafe { c::ioctlsocket(self.0, c::FIONBIO as c_int, &mut nonblocking) };
203 if r == 0 {
204 Ok(())
205 } else {
206 Err(io::Error::last_os_error())
207 }
208 }
209
210 pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
211 net::setsockopt(self, c::IPPROTO_TCP, c::TCP_NODELAY, nodelay as c::BYTE)
212 }
213
214 pub fn nodelay(&self) -> io::Result<bool> {
215 let raw: c::BYTE = net::getsockopt(self, c::IPPROTO_TCP, c::TCP_NODELAY)?;
216 Ok(raw != 0)
217 }
218
219 pub fn take_error(&self) -> io::Result<Option<io::Error>> {
220 let raw: c_int = net::getsockopt(self, c::SOL_SOCKET, c::SO_ERROR)?;
221 if raw == 0 {
222 Ok(None)
223 } else {
224 Ok(Some(io::Error::from_raw_os_error(raw as i32)))
225 }
226 }
227 }
228
229 #[unstable(reason = "not public", issue = "0", feature = "fd_read")]
230 impl<'a> Read for &'a Socket {
231 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
232 (**self).read(buf)
233 }
234
235 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
236 unsafe { read_to_end_uninitialized(self, buf) }
237 }
238 }
239
240 impl Drop for Socket {
241 fn drop(&mut self) {
242 let _ = unsafe { c::closesocket(self.0) };
243 }
244 }
245
246 impl AsInner<c::SOCKET> for Socket {
247 fn as_inner(&self) -> &c::SOCKET { &self.0 }
248 }
249
250 impl FromInner<c::SOCKET> for Socket {
251 fn from_inner(sock: c::SOCKET) -> Socket { Socket(sock) }
252 }
253
254 impl IntoInner<c::SOCKET> for Socket {
255 fn into_inner(self) -> c::SOCKET {
256 let ret = self.0;
257 mem::forget(self);
258 ret
259 }
260 }