]>
Commit | Line | Data |
---|---|---|
f035d41b XL |
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 | #![allow(bad_style)] | |
12 | ||
13 | use std::io; | |
14 | use std::mem; | |
15 | use std::net::{TcpListener, TcpStream, UdpSocket}; | |
16 | use std::os::windows::io::{RawSocket, FromRawSocket}; | |
17 | use std::sync::{Once, ONCE_INIT}; | |
18 | ||
19 | const HANDLE_FLAG_INHERIT: DWORD = 0x00000001; | |
20 | ||
21 | pub mod c { | |
22 | pub use winapi::ctypes::*; | |
23 | pub use winapi::um::handleapi::*; | |
24 | pub use winapi::um::winbase::*; | |
25 | pub use winapi::um::winsock2::*; | |
26 | pub use winapi::um::ws2tcpip::*; | |
27 | ||
28 | pub use winapi::shared::inaddr::*; | |
29 | pub use winapi::shared::in6addr::*; | |
30 | pub use winapi::shared::minwindef::*; | |
31 | pub use winapi::shared::ntdef::*; | |
32 | pub use winapi::shared::ws2def::*; | |
33 | pub use winapi::shared::ws2def::{SOCK_STREAM, SOCK_DGRAM}; | |
34 | pub use winapi::shared::ws2def::SOCKADDR as sockaddr; | |
35 | pub use winapi::shared::ws2def::SOCKADDR_STORAGE as sockaddr_storage; | |
36 | pub use winapi::shared::ws2def::SOCKADDR_IN as sockaddr_in; | |
37 | pub use winapi::shared::ws2ipdef::*; | |
38 | pub use winapi::shared::ws2ipdef::SOCKADDR_IN6_LH as sockaddr_in6; | |
39 | pub use winapi::shared::ws2ipdef::IP_MREQ as ip_mreq; | |
40 | pub use winapi::shared::ws2ipdef::IPV6_MREQ as ipv6_mreq; | |
41 | ||
42 | pub fn sockaddr_in_u32(sa: &sockaddr_in) -> u32 { | |
43 | ::ntoh(unsafe { *sa.sin_addr.S_un.S_addr() }) | |
44 | } | |
45 | ||
46 | pub fn in_addr_to_u32(addr: &in_addr) -> u32 { | |
47 | ::ntoh(unsafe { *addr.S_un.S_addr() }) | |
48 | } | |
49 | } | |
50 | ||
51 | use self::c::*; | |
52 | ||
53 | mod impls; | |
54 | ||
55 | fn init() { | |
56 | static INIT: Once = ONCE_INIT; | |
57 | ||
58 | INIT.call_once(|| { | |
59 | // Initialize winsock through the standard library by just creating a | |
60 | // dummy socket. Whether this is successful or not we drop the result as | |
61 | // libstd will be sure to have initialized winsock. | |
62 | let _ = UdpSocket::bind("127.0.0.1:34254"); | |
63 | }); | |
64 | } | |
65 | ||
66 | pub struct Socket { | |
67 | socket: SOCKET, | |
68 | } | |
69 | ||
70 | impl Socket { | |
71 | pub fn new(family: c_int, ty: c_int) -> io::Result<Socket> { | |
72 | init(); | |
73 | let socket = try!(unsafe { | |
74 | match WSASocketW(family, ty, 0, 0 as *mut _, 0, | |
75 | WSA_FLAG_OVERLAPPED) { | |
76 | INVALID_SOCKET => Err(io::Error::last_os_error()), | |
77 | n => Ok(Socket { socket: n }), | |
78 | } | |
79 | }); | |
80 | try!(socket.set_no_inherit()); | |
81 | Ok(socket) | |
82 | } | |
83 | ||
84 | pub fn raw(&self) -> SOCKET { self.socket } | |
85 | ||
86 | fn into_socket(self) -> SOCKET { | |
87 | let socket = self.socket; | |
88 | mem::forget(self); | |
89 | socket | |
90 | } | |
91 | ||
92 | pub fn into_tcp_listener(self) -> TcpListener { | |
93 | unsafe { TcpListener::from_raw_socket(self.into_socket() as RawSocket) } | |
94 | } | |
95 | ||
96 | pub fn into_tcp_stream(self) -> TcpStream { | |
97 | unsafe { TcpStream::from_raw_socket(self.into_socket() as RawSocket) } | |
98 | } | |
99 | ||
100 | pub fn into_udp_socket(self) -> UdpSocket { | |
101 | unsafe { UdpSocket::from_raw_socket(self.into_socket() as RawSocket) } | |
102 | } | |
103 | ||
104 | fn set_no_inherit(&self) -> io::Result<()> { | |
105 | ::cvt_win(unsafe { | |
106 | SetHandleInformation(self.socket as HANDLE, HANDLE_FLAG_INHERIT, 0) | |
107 | }).map(|_| ()) | |
108 | } | |
109 | } | |
110 | ||
111 | impl ::FromInner for Socket { | |
112 | type Inner = SOCKET; | |
113 | fn from_inner(socket: SOCKET) -> Socket { | |
114 | Socket { socket: socket } | |
115 | } | |
116 | } | |
117 | ||
118 | impl Drop for Socket { | |
119 | fn drop(&mut self) { | |
120 | unsafe { | |
121 | let _ = closesocket(self.socket); | |
122 | } | |
123 | } | |
124 | } |