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