1 #![unstable(issue = "none", feature = "windows_net")]
4 use crate::io
::{self, IoSlice, IoSliceMut, Read}
;
6 use crate::net
::{Shutdown, SocketAddr}
;
11 use crate::sys_common
::net
;
12 use crate::sys_common
::{AsInner, FromInner, IntoInner}
;
13 use crate::time
::Duration
;
15 use libc
::{c_int, c_long, c_ulong}
;
17 pub type wrlen_t
= i32;
20 pub use crate::sys
::c
::ADDRESS_FAMILY
as sa_family_t
;
21 pub use crate::sys
::c
::ADDRINFOA
as addrinfo
;
22 pub use crate::sys
::c
::SOCKADDR
as sockaddr
;
23 pub use crate::sys
::c
::SOCKADDR_STORAGE_LH
as sockaddr_storage
;
24 pub use crate::sys
::c
::*;
27 pub struct Socket(c
::SOCKET
);
29 static INIT
: Once
= Once
::new();
31 /// Checks whether the Windows socket interface has been started already, and
32 /// if not, starts it.
34 INIT
.call_once(|| unsafe {
35 let mut data
: c
::WSADATA
= mem
::zeroed();
36 let ret
= c
::WSAStartup(
45 if INIT
.is_completed() {
46 // only close the socket interface if it has actually been started
53 /// Returns the last error from the Windows socket interface.
54 fn last_error() -> io
::Error
{
55 io
::Error
::from_raw_os_error(unsafe { c::WSAGetLastError() }
)
59 pub trait IsMinusOne
{
60 fn is_minus_one(&self) -> bool
;
63 macro_rules
! impl_is_minus_one
{
64 ($
($t
:ident
)*) => ($
(impl IsMinusOne
for $t
{
65 fn is_minus_one(&self) -> bool
{
71 impl_is_minus_one
! { i8 i16 i32 i64 isize }
73 /// Checks if the signed integer is the Windows constant `SOCKET_ERROR` (-1)
74 /// and if so, returns the last error from the Windows socket interface. This
75 /// function must be called before another call to the socket API is made.
76 pub fn cvt
<T
: IsMinusOne
>(t
: T
) -> io
::Result
<T
> {
77 if t
.is_minus_one() { Err(last_error()) }
else { Ok(t) }
80 /// A variant of `cvt` for `getaddrinfo` which return 0 for a success.
81 pub fn cvt_gai(err
: c_int
) -> io
::Result
<()> {
82 if err
== 0 { Ok(()) }
else { Err(last_error()) }
85 /// Just to provide the same interface as sys/unix/net.rs
86 pub fn cvt_r
<T
, F
>(mut f
: F
) -> io
::Result
<T
>
95 pub fn new(addr
: &SocketAddr
, ty
: c_int
) -> io
::Result
<Socket
> {
96 let family
= match *addr
{
97 SocketAddr
::V4(..) => c
::AF_INET
,
98 SocketAddr
::V6(..) => c
::AF_INET6
,
100 let socket
= unsafe {
107 c
::WSA_FLAG_OVERLAPPED
| c
::WSA_FLAG_NO_HANDLE_INHERIT
,
111 if socket
!= c
::INVALID_SOCKET
{
114 let error
= unsafe { c::WSAGetLastError() }
;
116 if error
!= c
::WSAEPROTOTYPE
&& error
!= c
::WSAEINVAL
{
117 return Err(io
::Error
::from_raw_os_error(error
));
121 unsafe { c::WSASocketW(family, ty, 0, ptr::null_mut(), 0, c::WSA_FLAG_OVERLAPPED) }
;
123 if socket
== c
::INVALID_SOCKET
{
124 return Err(last_error());
127 let socket
= Self(socket
);
128 socket
.set_no_inherit()?
;
133 pub fn connect_timeout(&self, addr
: &SocketAddr
, timeout
: Duration
) -> io
::Result
<()> {
134 self.set_nonblocking(true)?
;
136 let (addrp
, len
) = addr
.into_inner();
137 let result
= unsafe { c::connect(self.0, addrp, len) }
;
138 cvt(result
).map(drop
)
140 self.set_nonblocking(false)?
;
143 Err(ref error
) if error
.kind() == io
::ErrorKind
::WouldBlock
=> {
144 if timeout
.as_secs() == 0 && timeout
.subsec_nanos() == 0 {
145 return Err(io
::Error
::new_const(
146 io
::ErrorKind
::InvalidInput
,
147 &"cannot set a 0 duration timeout",
151 let mut timeout
= c
::timeval
{
152 tv_sec
: timeout
.as_secs() as c_long
,
153 tv_usec
: (timeout
.subsec_nanos() / 1000) as c_long
,
156 if timeout
.tv_sec
== 0 && timeout
.tv_usec
== 0 {
161 let mut fds
= unsafe { mem::zeroed::<c::fd_set>() }
;
163 fds
.fd_array
[0] = self.0;
167 let mut writefds
= fds
;
168 let mut errorfds
= fds
;
171 let result
= unsafe {
172 c
::select(1, ptr
::null_mut(), &mut writefds
, &mut errorfds
, &timeout
)
179 Err(io
::Error
::new_const(io
::ErrorKind
::TimedOut
, &"connection timed out"))
182 if writefds
.fd_count
!= 1 {
183 if let Some(e
) = self.take_error()?
{
196 pub fn accept(&self, storage
: *mut c
::SOCKADDR
, len
: *mut c_int
) -> io
::Result
<Socket
> {
197 let socket
= unsafe { c::accept(self.0, storage, len) }
;
200 c
::INVALID_SOCKET
=> Err(last_error()),
201 _
=> Ok(Self(socket
)),
205 pub fn duplicate(&self) -> io
::Result
<Socket
> {
206 let mut info
= unsafe { mem::zeroed::<c::WSAPROTOCOL_INFO>() }
;
207 let result
= unsafe { c::WSADuplicateSocketW(self.0, c::GetCurrentProcessId(), &mut info) }
;
209 let socket
= unsafe {
216 c
::WSA_FLAG_OVERLAPPED
| c
::WSA_FLAG_NO_HANDLE_INHERIT
,
220 if socket
!= c
::INVALID_SOCKET
{
223 let error
= unsafe { c::WSAGetLastError() }
;
225 if error
!= c
::WSAEPROTOTYPE
&& error
!= c
::WSAEINVAL
{
226 return Err(io
::Error
::from_raw_os_error(error
));
229 let socket
= unsafe {
236 c
::WSA_FLAG_OVERLAPPED
,
240 if socket
== c
::INVALID_SOCKET
{
241 return Err(last_error());
244 let socket
= Self(socket
);
245 socket
.set_no_inherit()?
;
250 fn recv_with_flags(&self, buf
: &mut [u8], flags
: c_int
) -> io
::Result
<usize> {
251 // On unix when a socket is shut down all further reads return 0, so we
252 // do the same on windows to map a shut down socket to returning EOF.
253 let length
= cmp
::min(buf
.len(), i32::MAX
as usize) as i32;
254 let result
= unsafe { c::recv(self.0, buf.as_mut_ptr() as *mut _, length, flags) }
;
258 let error
= unsafe { c::WSAGetLastError() }
;
260 if error
== c
::WSAESHUTDOWN
{
263 Err(io
::Error
::from_raw_os_error(error
))
266 _
=> Ok(result
as usize),
270 pub fn read(&self, buf
: &mut [u8]) -> io
::Result
<usize> {
271 self.recv_with_flags(buf
, 0)
274 pub fn read_vectored(&self, bufs
: &mut [IoSliceMut
<'_
>]) -> io
::Result
<usize> {
275 // On unix when a socket is shut down all further reads return 0, so we
276 // do the same on windows to map a shut down socket to returning EOF.
277 let length
= cmp
::min(bufs
.len(), c
::DWORD
::MAX
as usize) as c
::DWORD
;
280 let result
= unsafe {
283 bufs
.as_mut_ptr() as *mut c
::WSABUF
,
293 0 => Ok(nread
as usize),
295 let error
= unsafe { c::WSAGetLastError() }
;
297 if error
== c
::WSAESHUTDOWN
{
300 Err(io
::Error
::from_raw_os_error(error
))
307 pub fn is_read_vectored(&self) -> bool
{
311 pub fn peek(&self, buf
: &mut [u8]) -> io
::Result
<usize> {
312 self.recv_with_flags(buf
, c
::MSG_PEEK
)
315 fn recv_from_with_flags(
319 ) -> io
::Result
<(usize, SocketAddr
)> {
320 let mut storage
= unsafe { mem::zeroed::<c::SOCKADDR_STORAGE_LH>() }
;
321 let mut addrlen
= mem
::size_of_val(&storage
) as c
::socklen_t
;
322 let length
= cmp
::min(buf
.len(), <wrlen_t
>::MAX
as usize) as wrlen_t
;
324 // On unix when a socket is shut down all further reads return 0, so we
325 // do the same on windows to map a shut down socket to returning EOF.
326 let result
= unsafe {
329 buf
.as_mut_ptr() as *mut _
,
332 &mut storage
as *mut _
as *mut _
,
339 let error
= unsafe { c::WSAGetLastError() }
;
341 if error
== c
::WSAESHUTDOWN
{
342 Ok((0, net
::sockaddr_to_addr(&storage
, addrlen
as usize)?
))
344 Err(io
::Error
::from_raw_os_error(error
))
347 _
=> Ok((result
as usize, net
::sockaddr_to_addr(&storage
, addrlen
as usize)?
)),
351 pub fn recv_from(&self, buf
: &mut [u8]) -> io
::Result
<(usize, SocketAddr
)> {
352 self.recv_from_with_flags(buf
, 0)
355 pub fn peek_from(&self, buf
: &mut [u8]) -> io
::Result
<(usize, SocketAddr
)> {
356 self.recv_from_with_flags(buf
, c
::MSG_PEEK
)
359 pub fn write_vectored(&self, bufs
: &[IoSlice
<'_
>]) -> io
::Result
<usize> {
360 let length
= cmp
::min(bufs
.len(), c
::DWORD
::MAX
as usize) as c
::DWORD
;
361 let mut nwritten
= 0;
362 let result
= unsafe {
365 bufs
.as_ptr() as *const c
::WSABUF
as *mut _
,
373 cvt(result
).map(|_
| nwritten
as usize)
377 pub fn is_write_vectored(&self) -> bool
{
381 pub fn set_timeout(&self, dur
: Option
<Duration
>, kind
: c_int
) -> io
::Result
<()> {
382 let timeout
= match dur
{
384 let timeout
= sys
::dur2timeout(dur
);
386 return Err(io
::Error
::new_const(
387 io
::ErrorKind
::InvalidInput
,
388 &"cannot set a 0 duration timeout",
395 net
::setsockopt(self, c
::SOL_SOCKET
, kind
, timeout
)
398 pub fn timeout(&self, kind
: c_int
) -> io
::Result
<Option
<Duration
>> {
399 let raw
: c
::DWORD
= net
::getsockopt(self, c
::SOL_SOCKET
, kind
)?
;
403 let secs
= raw
/ 1000;
404 let nsec
= (raw
% 1000) * 1000000;
405 Ok(Some(Duration
::new(secs
as u64, nsec
as u32)))
409 #[cfg(not(target_vendor = "uwp"))]
410 fn set_no_inherit(&self) -> io
::Result
<()> {
411 sys
::cvt(unsafe { c::SetHandleInformation(self.0 as c::HANDLE, c::HANDLE_FLAG_INHERIT, 0) }
)
415 #[cfg(target_vendor = "uwp")]
416 fn set_no_inherit(&self) -> io
::Result
<()> {
417 Err(io
::Error
::new_const(io
::ErrorKind
::Unsupported
, &"Unavailable on UWP"))
420 pub fn shutdown(&self, how
: Shutdown
) -> io
::Result
<()> {
421 let how
= match how
{
422 Shutdown
::Write
=> c
::SD_SEND
,
423 Shutdown
::Read
=> c
::SD_RECEIVE
,
424 Shutdown
::Both
=> c
::SD_BOTH
,
426 let result
= unsafe { c::shutdown(self.0, how) }
;
427 cvt(result
).map(drop
)
430 pub fn set_nonblocking(&self, nonblocking
: bool
) -> io
::Result
<()> {
431 let mut nonblocking
= nonblocking
as c_ulong
;
432 let result
= unsafe { c::ioctlsocket(self.0, c::FIONBIO as c_int, &mut nonblocking) }
;
433 cvt(result
).map(drop
)
436 pub fn set_nodelay(&self, nodelay
: bool
) -> io
::Result
<()> {
437 net
::setsockopt(self, c
::IPPROTO_TCP
, c
::TCP_NODELAY
, nodelay
as c
::BYTE
)
440 pub fn nodelay(&self) -> io
::Result
<bool
> {
441 let raw
: c
::BYTE
= net
::getsockopt(self, c
::IPPROTO_TCP
, c
::TCP_NODELAY
)?
;
445 pub fn take_error(&self) -> io
::Result
<Option
<io
::Error
>> {
446 let raw
: c_int
= net
::getsockopt(self, c
::SOL_SOCKET
, c
::SO_ERROR
)?
;
447 if raw
== 0 { Ok(None) }
else { Ok(Some(io::Error::from_raw_os_error(raw as i32))) }
451 #[unstable(reason = "not public", issue = "none", feature = "fd_read")]
452 impl<'a
> Read
for &'a Socket
{
453 fn read(&mut self, buf
: &mut [u8]) -> io
::Result
<usize> {
458 impl Drop
for Socket
{
460 let _
= unsafe { c::closesocket(self.0) }
;
464 impl AsInner
<c
::SOCKET
> for Socket
{
465 fn as_inner(&self) -> &c
::SOCKET
{
470 impl FromInner
<c
::SOCKET
> for Socket
{
471 fn from_inner(sock
: c
::SOCKET
) -> Socket
{
476 impl IntoInner
<c
::SOCKET
> for Socket
{
477 fn into_inner(self) -> c
::SOCKET
{