]>
Commit | Line | Data |
---|---|---|
487cf647 FG |
1 | //! Extensions and types for the standard networking primitives. |
2 | //! | |
3 | //! This module contains a number of extension traits for the types in | |
4 | //! `std::net` for Windows-specific functionality. | |
5 | ||
6 | use crate::{FALSE, TRUE}; | |
7 | use std::cmp; | |
8 | use std::io; | |
9 | use std::mem; | |
10 | use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6}; | |
11 | use std::net::{SocketAddr, TcpListener, TcpStream, UdpSocket}; | |
12 | use std::os::windows::io::AsRawSocket; | |
13 | use std::sync::atomic::{AtomicUsize, Ordering}; | |
14 | ||
15 | use windows_sys::core::GUID; | |
16 | use windows_sys::Win32::Networking::WinSock::{ | |
17 | setsockopt, WSAGetLastError, WSAGetOverlappedResult, WSAIoctl, WSARecv, WSARecvFrom, WSASend, | |
18 | WSASendTo, AF_INET, AF_INET6, IN6_ADDR, IN6_ADDR_0, IN_ADDR, IN_ADDR_0, LPFN_ACCEPTEX, | |
19 | LPFN_CONNECTEX, LPFN_GETACCEPTEXSOCKADDRS, SOCKADDR, SOCKADDR_IN, SOCKADDR_IN6, SOCKADDR_IN6_0, | |
20 | SOCKADDR_STORAGE, SOCKET, SOCKET_ERROR, SOL_SOCKET, WSABUF, WSA_IO_PENDING, | |
21 | }; | |
22 | use windows_sys::Win32::System::IO::OVERLAPPED; | |
23 | ||
24 | /// A type to represent a buffer in which a socket address will be stored. | |
25 | /// | |
26 | /// This type is used with the `recv_from_overlapped` function on the | |
27 | /// `UdpSocketExt` trait to provide space for the overlapped I/O operation to | |
28 | /// fill in the address upon completion. | |
29 | #[derive(Clone, Copy)] | |
30 | pub struct SocketAddrBuf { | |
31 | buf: SOCKADDR_STORAGE, | |
32 | len: i32, | |
33 | } | |
34 | ||
35 | /// A type to represent a buffer in which an accepted socket's address will be | |
36 | /// stored. | |
37 | /// | |
38 | /// This type is used with the `accept_overlapped` method on the | |
39 | /// `TcpListenerExt` trait to provide space for the overlapped I/O operation to | |
40 | /// fill in the socket addresses upon completion. | |
41 | #[repr(C)] | |
42 | pub struct AcceptAddrsBuf { | |
43 | // For AcceptEx we've got the restriction that the addresses passed in that | |
44 | // buffer need to be at least 16 bytes more than the maximum address length | |
45 | // for the protocol in question, so add some extra here and there | |
46 | local: SOCKADDR_STORAGE, | |
47 | _pad1: [u8; 16], | |
48 | remote: SOCKADDR_STORAGE, | |
49 | _pad2: [u8; 16], | |
50 | } | |
51 | ||
52 | /// The parsed return value of `AcceptAddrsBuf`. | |
53 | pub struct AcceptAddrs<'a> { | |
54 | local: *mut SOCKADDR, | |
55 | local_len: i32, | |
56 | remote: *mut SOCKADDR, | |
57 | remote_len: i32, | |
58 | _data: &'a AcceptAddrsBuf, | |
59 | } | |
60 | ||
61 | struct WsaExtension { | |
62 | guid: GUID, | |
63 | val: AtomicUsize, | |
64 | } | |
65 | ||
66 | /// Additional methods for the `TcpStream` type in the standard library. | |
67 | pub trait TcpStreamExt { | |
68 | /// Execute an overlapped read I/O operation on this TCP stream. | |
69 | /// | |
70 | /// This function will issue an overlapped I/O read (via `WSARecv`) on this | |
71 | /// socket. The provided buffer will be filled in when the operation | |
72 | /// completes and the given `OVERLAPPED` instance is used to track the | |
73 | /// overlapped operation. | |
74 | /// | |
75 | /// If the operation succeeds, `Ok(Some(n))` is returned indicating how | |
76 | /// many bytes were read. If the operation returns an error indicating that | |
77 | /// the I/O is currently pending, `Ok(None)` is returned. Otherwise, the | |
78 | /// error associated with the operation is returned and no overlapped | |
79 | /// operation is enqueued. | |
80 | /// | |
81 | /// The number of bytes read will be returned as part of the completion | |
82 | /// notification when the I/O finishes. | |
83 | /// | |
84 | /// # Unsafety | |
85 | /// | |
86 | /// This function is unsafe because the kernel requires that the `buf` and | |
87 | /// `overlapped` pointers are valid until the end of the I/O operation. The | |
88 | /// kernel also requires that `overlapped` is unique for this I/O operation | |
89 | /// and is not in use for any other I/O. | |
90 | /// | |
91 | /// To safely use this function callers must ensure that these two input | |
92 | /// pointers are valid until the I/O operation is completed, typically via | |
93 | /// completion ports and waiting to receive the completion notification on | |
94 | /// the port. | |
95 | unsafe fn read_overlapped( | |
96 | &self, | |
97 | buf: &mut [u8], | |
98 | overlapped: *mut OVERLAPPED, | |
99 | ) -> io::Result<Option<usize>>; | |
100 | ||
101 | /// Execute an overlapped write I/O operation on this TCP stream. | |
102 | /// | |
103 | /// This function will issue an overlapped I/O write (via `WSASend`) on this | |
104 | /// socket. The provided buffer will be written when the operation completes | |
105 | /// and the given `OVERLAPPED` instance is used to track the overlapped | |
106 | /// operation. | |
107 | /// | |
108 | /// If the operation succeeds, `Ok(Some(n))` is returned where `n` is the | |
109 | /// number of bytes that were written. If the operation returns an error | |
110 | /// indicating that the I/O is currently pending, `Ok(None)` is returned. | |
111 | /// Otherwise, the error associated with the operation is returned and no | |
112 | /// overlapped operation is enqueued. | |
113 | /// | |
114 | /// The number of bytes written will be returned as part of the completion | |
115 | /// notification when the I/O finishes. | |
116 | /// | |
117 | /// # Unsafety | |
118 | /// | |
119 | /// This function is unsafe because the kernel requires that the `buf` and | |
120 | /// `overlapped` pointers are valid until the end of the I/O operation. The | |
121 | /// kernel also requires that `overlapped` is unique for this I/O operation | |
122 | /// and is not in use for any other I/O. | |
123 | /// | |
124 | /// To safely use this function callers must ensure that these two input | |
125 | /// pointers are valid until the I/O operation is completed, typically via | |
126 | /// completion ports and waiting to receive the completion notification on | |
127 | /// the port. | |
128 | unsafe fn write_overlapped( | |
129 | &self, | |
130 | buf: &[u8], | |
131 | overlapped: *mut OVERLAPPED, | |
132 | ) -> io::Result<Option<usize>>; | |
133 | ||
134 | /// Attempt to consume the internal socket in this builder by executing an | |
135 | /// overlapped connect operation. | |
136 | /// | |
137 | /// This function will issue a connect operation to the address specified on | |
138 | /// the underlying socket, flagging it as an overlapped operation which will | |
139 | /// complete asynchronously. If successful this function will return the | |
140 | /// corresponding TCP stream. | |
141 | /// | |
142 | /// The `buf` argument provided is an initial buffer of data that should be | |
143 | /// sent after the connection is initiated. It's acceptable to | |
144 | /// pass an empty slice here. | |
145 | /// | |
146 | /// This function will also return whether the connect immediately | |
147 | /// succeeded or not. If `None` is returned then the I/O operation is still | |
148 | /// pending and will complete at a later date, and if `Some(bytes)` is | |
149 | /// returned then that many bytes were transferred. | |
150 | /// | |
151 | /// Note that to succeed this requires that the underlying socket has | |
152 | /// previously been bound via a call to `bind` to a local address. | |
153 | /// | |
154 | /// # Unsafety | |
155 | /// | |
156 | /// This function is unsafe because the kernel requires that the | |
157 | /// `overlapped` and `buf` pointers to be valid until the end of the I/O | |
158 | /// operation. The kernel also requires that `overlapped` is unique for | |
159 | /// this I/O operation and is not in use for any other I/O. | |
160 | /// | |
161 | /// To safely use this function callers must ensure that this pointer is | |
162 | /// valid until the I/O operation is completed, typically via completion | |
163 | /// ports and waiting to receive the completion notification on the port. | |
164 | unsafe fn connect_overlapped( | |
165 | &self, | |
166 | addr: &SocketAddr, | |
167 | buf: &[u8], | |
168 | overlapped: *mut OVERLAPPED, | |
169 | ) -> io::Result<Option<usize>>; | |
170 | ||
171 | /// Once a `connect_overlapped` has finished, this function needs to be | |
172 | /// called to finish the connect operation. | |
173 | /// | |
174 | /// Currently this just calls `setsockopt` with `SO_UPDATE_CONNECT_CONTEXT` | |
175 | /// to ensure that further functions like `getpeername` and `getsockname` | |
176 | /// work correctly. | |
177 | fn connect_complete(&self) -> io::Result<()>; | |
178 | ||
179 | /// Calls the `GetOverlappedResult` function to get the result of an | |
180 | /// overlapped operation for this handle. | |
181 | /// | |
182 | /// This function takes the `OVERLAPPED` argument which must have been used | |
183 | /// to initiate an overlapped I/O operation, and returns either the | |
184 | /// successful number of bytes transferred during the operation or an error | |
185 | /// if one occurred, along with the results of the `lpFlags` parameter of | |
186 | /// the relevant operation, if applicable. | |
187 | /// | |
188 | /// # Unsafety | |
189 | /// | |
190 | /// This function is unsafe as `overlapped` must have previously been used | |
191 | /// to execute an operation for this handle, and it must also be a valid | |
192 | /// pointer to an `OVERLAPPED` instance. | |
193 | /// | |
194 | /// # Panics | |
195 | /// | |
196 | /// This function will panic | |
197 | unsafe fn result(&self, overlapped: *mut OVERLAPPED) -> io::Result<(usize, u32)>; | |
198 | } | |
199 | ||
200 | /// Additional methods for the `UdpSocket` type in the standard library. | |
201 | pub trait UdpSocketExt { | |
202 | /// Execute an overlapped receive I/O operation on this UDP socket. | |
203 | /// | |
204 | /// This function will issue an overlapped I/O read (via `WSARecvFrom`) on | |
205 | /// this socket. The provided buffer will be filled in when the operation | |
206 | /// completes, the source from where the data came from will be written to | |
207 | /// `addr`, and the given `OVERLAPPED` instance is used to track the | |
208 | /// overlapped operation. | |
209 | /// | |
210 | /// If the operation succeeds, `Ok(Some(n))` is returned where `n` is the | |
211 | /// number of bytes that were read. If the operation returns an error | |
212 | /// indicating that the I/O is currently pending, `Ok(None)` is returned. | |
213 | /// Otherwise, the error associated with the operation is returned and no | |
214 | /// overlapped operation is enqueued. | |
215 | /// | |
216 | /// The number of bytes read will be returned as part of the completion | |
217 | /// notification when the I/O finishes. | |
218 | /// | |
219 | /// # Unsafety | |
220 | /// | |
221 | /// This function is unsafe because the kernel requires that the `buf`, | |
222 | /// `addr`, and `overlapped` pointers are valid until the end of the I/O | |
223 | /// operation. The kernel also requires that `overlapped` is unique for this | |
224 | /// I/O operation and is not in use for any other I/O. | |
225 | /// | |
226 | /// To safely use this function callers must ensure that these two input | |
227 | /// pointers are valid until the I/O operation is completed, typically via | |
228 | /// completion ports and waiting to receive the completion notification on | |
229 | /// the port. | |
230 | unsafe fn recv_from_overlapped( | |
231 | &self, | |
232 | buf: &mut [u8], | |
233 | addr: *mut SocketAddrBuf, | |
234 | overlapped: *mut OVERLAPPED, | |
235 | ) -> io::Result<Option<usize>>; | |
236 | ||
237 | /// Execute an overlapped receive I/O operation on this UDP socket. | |
238 | /// | |
239 | /// This function will issue an overlapped I/O read (via `WSARecv`) on | |
240 | /// this socket. The provided buffer will be filled in when the operation | |
241 | /// completes, the source from where the data came from will be written to | |
242 | /// `addr`, and the given `OVERLAPPED` instance is used to track the | |
243 | /// overlapped operation. | |
244 | /// | |
245 | /// If the operation succeeds, `Ok(Some(n))` is returned where `n` is the | |
246 | /// number of bytes that were read. If the operation returns an error | |
247 | /// indicating that the I/O is currently pending, `Ok(None)` is returned. | |
248 | /// Otherwise, the error associated with the operation is returned and no | |
249 | /// overlapped operation is enqueued. | |
250 | /// | |
251 | /// The number of bytes read will be returned as part of the completion | |
252 | /// notification when the I/O finishes. | |
253 | /// | |
254 | /// # Unsafety | |
255 | /// | |
256 | /// This function is unsafe because the kernel requires that the `buf`, | |
257 | /// and `overlapped` pointers are valid until the end of the I/O | |
258 | /// operation. The kernel also requires that `overlapped` is unique for this | |
259 | /// I/O operation and is not in use for any other I/O. | |
260 | /// | |
261 | /// To safely use this function callers must ensure that these two input | |
262 | /// pointers are valid until the I/O operation is completed, typically via | |
263 | /// completion ports and waiting to receive the completion notification on | |
264 | /// the port. | |
265 | unsafe fn recv_overlapped( | |
266 | &self, | |
267 | buf: &mut [u8], | |
268 | overlapped: *mut OVERLAPPED, | |
269 | ) -> io::Result<Option<usize>>; | |
270 | ||
271 | /// Execute an overlapped send I/O operation on this UDP socket. | |
272 | /// | |
273 | /// This function will issue an overlapped I/O write (via `WSASendTo`) on | |
274 | /// this socket to the address specified by `addr`. The provided buffer will | |
275 | /// be written when the operation completes and the given `OVERLAPPED` | |
276 | /// instance is used to track the overlapped operation. | |
277 | /// | |
278 | /// If the operation succeeds, `Ok(Some(n0)` is returned where `n` byte | |
279 | /// were written. If the operation returns an error indicating that the I/O | |
280 | /// is currently pending, `Ok(None)` is returned. Otherwise, the error | |
281 | /// associated with the operation is returned and no overlapped operation | |
282 | /// is enqueued. | |
283 | /// | |
284 | /// The number of bytes written will be returned as part of the completion | |
285 | /// notification when the I/O finishes. | |
286 | /// | |
287 | /// # Unsafety | |
288 | /// | |
289 | /// This function is unsafe because the kernel requires that the `buf` and | |
290 | /// `overlapped` pointers are valid until the end of the I/O operation. The | |
291 | /// kernel also requires that `overlapped` is unique for this I/O operation | |
292 | /// and is not in use for any other I/O. | |
293 | /// | |
294 | /// To safely use this function callers must ensure that these two input | |
295 | /// pointers are valid until the I/O operation is completed, typically via | |
296 | /// completion ports and waiting to receive the completion notification on | |
297 | /// the port. | |
298 | unsafe fn send_to_overlapped( | |
299 | &self, | |
300 | buf: &[u8], | |
301 | addr: &SocketAddr, | |
302 | overlapped: *mut OVERLAPPED, | |
303 | ) -> io::Result<Option<usize>>; | |
304 | ||
305 | /// Execute an overlapped send I/O operation on this UDP socket. | |
306 | /// | |
307 | /// This function will issue an overlapped I/O write (via `WSASend`) on | |
308 | /// this socket to the address it was previously connected to. The provided | |
309 | /// buffer will be written when the operation completes and the given `OVERLAPPED` | |
310 | /// instance is used to track the overlapped operation. | |
311 | /// | |
312 | /// If the operation succeeds, `Ok(Some(n0)` is returned where `n` byte | |
313 | /// were written. If the operation returns an error indicating that the I/O | |
314 | /// is currently pending, `Ok(None)` is returned. Otherwise, the error | |
315 | /// associated with the operation is returned and no overlapped operation | |
316 | /// is enqueued. | |
317 | /// | |
318 | /// The number of bytes written will be returned as part of the completion | |
319 | /// notification when the I/O finishes. | |
320 | /// | |
321 | /// # Unsafety | |
322 | /// | |
323 | /// This function is unsafe because the kernel requires that the `buf` and | |
324 | /// `overlapped` pointers are valid until the end of the I/O operation. The | |
325 | /// kernel also requires that `overlapped` is unique for this I/O operation | |
326 | /// and is not in use for any other I/O. | |
327 | /// | |
328 | /// To safely use this function callers must ensure that these two input | |
329 | /// pointers are valid until the I/O operation is completed, typically via | |
330 | /// completion ports and waiting to receive the completion notification on | |
331 | /// the port. | |
332 | unsafe fn send_overlapped( | |
333 | &self, | |
334 | buf: &[u8], | |
335 | overlapped: *mut OVERLAPPED, | |
336 | ) -> io::Result<Option<usize>>; | |
337 | ||
338 | /// Calls the `GetOverlappedResult` function to get the result of an | |
339 | /// overlapped operation for this handle. | |
340 | /// | |
341 | /// This function takes the `OVERLAPPED` argument which must have been used | |
342 | /// to initiate an overlapped I/O operation, and returns either the | |
343 | /// successful number of bytes transferred during the operation or an error | |
344 | /// if one occurred, along with the results of the `lpFlags` parameter of | |
345 | /// the relevant operation, if applicable. | |
346 | /// | |
347 | /// # Unsafety | |
348 | /// | |
349 | /// This function is unsafe as `overlapped` must have previously been used | |
350 | /// to execute an operation for this handle, and it must also be a valid | |
351 | /// pointer to an `OVERLAPPED` instance. | |
352 | /// | |
353 | /// # Panics | |
354 | /// | |
355 | /// This function will panic | |
356 | unsafe fn result(&self, overlapped: *mut OVERLAPPED) -> io::Result<(usize, u32)>; | |
357 | } | |
358 | ||
359 | /// Additional methods for the `TcpListener` type in the standard library. | |
360 | pub trait TcpListenerExt { | |
361 | /// Perform an accept operation on this listener, accepting a connection in | |
362 | /// an overlapped fashion. | |
363 | /// | |
364 | /// This function will issue an I/O request to accept an incoming connection | |
365 | /// with the specified overlapped instance. The `socket` provided must be a | |
366 | /// configured but not bound or connected socket, and if successful this | |
367 | /// will consume the internal socket of the builder to return a TCP stream. | |
368 | /// | |
369 | /// The `addrs` buffer provided will be filled in with the local and remote | |
370 | /// addresses of the connection upon completion. | |
371 | /// | |
372 | /// If the accept succeeds immediately, `Ok(true)` is returned. If | |
373 | /// the connect indicates that the I/O is currently pending, `Ok(false)` is | |
374 | /// returned. Otherwise, the error associated with the operation is | |
375 | /// returned and no overlapped operation is enqueued. | |
376 | /// | |
377 | /// # Unsafety | |
378 | /// | |
379 | /// This function is unsafe because the kernel requires that the | |
380 | /// `addrs` and `overlapped` pointers are valid until the end of the I/O | |
381 | /// operation. The kernel also requires that `overlapped` is unique for this | |
382 | /// I/O operation and is not in use for any other I/O. | |
383 | /// | |
384 | /// To safely use this function callers must ensure that the pointers are | |
385 | /// valid until the I/O operation is completed, typically via completion | |
386 | /// ports and waiting to receive the completion notification on the port. | |
387 | unsafe fn accept_overlapped( | |
388 | &self, | |
389 | socket: &TcpStream, | |
390 | addrs: &mut AcceptAddrsBuf, | |
391 | overlapped: *mut OVERLAPPED, | |
392 | ) -> io::Result<bool>; | |
393 | ||
394 | /// Once an `accept_overlapped` has finished, this function needs to be | |
395 | /// called to finish the accept operation. | |
396 | /// | |
397 | /// Currently this just calls `setsockopt` with `SO_UPDATE_ACCEPT_CONTEXT` | |
398 | /// to ensure that further functions like `getpeername` and `getsockname` | |
399 | /// work correctly. | |
400 | fn accept_complete(&self, socket: &TcpStream) -> io::Result<()>; | |
401 | ||
402 | /// Calls the `GetOverlappedResult` function to get the result of an | |
403 | /// overlapped operation for this handle. | |
404 | /// | |
405 | /// This function takes the `OVERLAPPED` argument which must have been used | |
406 | /// to initiate an overlapped I/O operation, and returns either the | |
407 | /// successful number of bytes transferred during the operation or an error | |
408 | /// if one occurred, along with the results of the `lpFlags` parameter of | |
409 | /// the relevant operation, if applicable. | |
410 | /// | |
411 | /// # Unsafety | |
412 | /// | |
413 | /// This function is unsafe as `overlapped` must have previously been used | |
414 | /// to execute an operation for this handle, and it must also be a valid | |
415 | /// pointer to an `OVERLAPPED` instance. | |
416 | /// | |
417 | /// # Panics | |
418 | /// | |
419 | /// This function will panic | |
420 | unsafe fn result(&self, overlapped: *mut OVERLAPPED) -> io::Result<(usize, u32)>; | |
421 | } | |
422 | ||
423 | #[doc(hidden)] | |
424 | trait NetInt { | |
425 | fn from_be(i: Self) -> Self; | |
426 | fn to_be(&self) -> Self; | |
427 | } | |
428 | macro_rules! doit { | |
429 | ($($t:ident)*) => ($(impl NetInt for $t { | |
430 | fn from_be(i: Self) -> Self { <$t>::from_be(i) } | |
431 | fn to_be(&self) -> Self { <$t>::to_be(*self) } | |
432 | })*) | |
433 | } | |
434 | doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize } | |
435 | ||
436 | // fn hton<I: NetInt>(i: I) -> I { i.to_be() } | |
437 | fn ntoh<I: NetInt>(i: I) -> I { | |
438 | I::from_be(i) | |
439 | } | |
440 | ||
441 | fn last_err() -> io::Result<Option<usize>> { | |
442 | let err = unsafe { WSAGetLastError() }; | |
443 | if err == WSA_IO_PENDING as i32 { | |
444 | Ok(None) | |
445 | } else { | |
446 | Err(io::Error::from_raw_os_error(err)) | |
447 | } | |
448 | } | |
449 | ||
450 | fn cvt(i: i32, size: u32) -> io::Result<Option<usize>> { | |
451 | if i == SOCKET_ERROR { | |
452 | last_err() | |
453 | } else { | |
454 | Ok(Some(size as usize)) | |
455 | } | |
456 | } | |
457 | ||
458 | /// A type with the same memory layout as `SOCKADDR`. Used in converting Rust level | |
459 | /// SocketAddr* types into their system representation. The benefit of this specific | |
460 | /// type over using `SOCKADDR_STORAGE` is that this type is exactly as large as it | |
461 | /// needs to be and not a lot larger. And it can be initialized cleaner from Rust. | |
462 | #[repr(C)] | |
463 | pub(crate) union SocketAddrCRepr { | |
464 | v4: SOCKADDR_IN, | |
465 | v6: SOCKADDR_IN6, | |
466 | } | |
467 | ||
468 | impl SocketAddrCRepr { | |
469 | pub(crate) fn as_ptr(&self) -> *const SOCKADDR { | |
470 | self as *const _ as *const SOCKADDR | |
471 | } | |
472 | } | |
473 | ||
474 | fn socket_addr_to_ptrs(addr: &SocketAddr) -> (SocketAddrCRepr, i32) { | |
475 | match *addr { | |
476 | SocketAddr::V4(ref a) => { | |
477 | let sin_addr = IN_ADDR { | |
478 | S_un: IN_ADDR_0 { | |
479 | S_addr: u32::from_ne_bytes(a.ip().octets()), | |
480 | }, | |
481 | }; | |
482 | ||
483 | let sockaddr_in = SOCKADDR_IN { | |
484 | sin_family: AF_INET as _, | |
485 | sin_port: a.port().to_be(), | |
486 | sin_addr, | |
487 | sin_zero: [0; 8], | |
488 | }; | |
489 | ||
490 | let sockaddr = SocketAddrCRepr { v4: sockaddr_in }; | |
491 | (sockaddr, mem::size_of::<SOCKADDR_IN>() as i32) | |
492 | } | |
493 | SocketAddr::V6(ref a) => { | |
494 | let sockaddr_in6 = SOCKADDR_IN6 { | |
495 | sin6_family: AF_INET6 as _, | |
496 | sin6_port: a.port().to_be(), | |
497 | sin6_addr: IN6_ADDR { | |
498 | u: IN6_ADDR_0 { | |
499 | Byte: a.ip().octets(), | |
500 | }, | |
501 | }, | |
502 | sin6_flowinfo: a.flowinfo(), | |
503 | Anonymous: SOCKADDR_IN6_0 { | |
504 | sin6_scope_id: a.scope_id(), | |
505 | }, | |
506 | }; | |
507 | ||
508 | let sockaddr = SocketAddrCRepr { v6: sockaddr_in6 }; | |
509 | (sockaddr, mem::size_of::<SOCKADDR_IN6>() as i32) | |
510 | } | |
511 | } | |
512 | } | |
513 | ||
514 | unsafe fn ptrs_to_socket_addr(ptr: *const SOCKADDR, len: i32) -> Option<SocketAddr> { | |
515 | if (len as usize) < mem::size_of::<i32>() { | |
516 | return None; | |
517 | } | |
518 | match (*ptr).sa_family as _ { | |
519 | AF_INET if len as usize >= mem::size_of::<SOCKADDR_IN>() => { | |
520 | let b = &*(ptr as *const SOCKADDR_IN); | |
521 | let ip = ntoh(b.sin_addr.S_un.S_addr); | |
522 | let ip = Ipv4Addr::new( | |
523 | (ip >> 24) as u8, | |
524 | (ip >> 16) as u8, | |
525 | (ip >> 8) as u8, | |
526 | ip as u8, | |
527 | ); | |
528 | Some(SocketAddr::V4(SocketAddrV4::new(ip, ntoh(b.sin_port)))) | |
529 | } | |
530 | AF_INET6 if len as usize >= mem::size_of::<SOCKADDR_IN6>() => { | |
531 | let b = &*(ptr as *const SOCKADDR_IN6); | |
532 | let arr = &b.sin6_addr.u.Byte; | |
533 | let ip = Ipv6Addr::new( | |
534 | ((arr[0] as u16) << 8) | (arr[1] as u16), | |
535 | ((arr[2] as u16) << 8) | (arr[3] as u16), | |
536 | ((arr[4] as u16) << 8) | (arr[5] as u16), | |
537 | ((arr[6] as u16) << 8) | (arr[7] as u16), | |
538 | ((arr[8] as u16) << 8) | (arr[9] as u16), | |
539 | ((arr[10] as u16) << 8) | (arr[11] as u16), | |
540 | ((arr[12] as u16) << 8) | (arr[13] as u16), | |
541 | ((arr[14] as u16) << 8) | (arr[15] as u16), | |
542 | ); | |
543 | let addr = SocketAddrV6::new( | |
544 | ip, | |
545 | ntoh(b.sin6_port), | |
546 | ntoh(b.sin6_flowinfo), | |
547 | ntoh(b.Anonymous.sin6_scope_id), | |
548 | ); | |
549 | Some(SocketAddr::V6(addr)) | |
550 | } | |
551 | _ => None, | |
552 | } | |
553 | } | |
554 | ||
555 | unsafe fn slice2buf(slice: &[u8]) -> WSABUF { | |
556 | WSABUF { | |
557 | len: cmp::min(slice.len(), <u32>::max_value() as usize) as u32, | |
558 | buf: slice.as_ptr() as *mut _, | |
559 | } | |
560 | } | |
561 | ||
562 | unsafe fn result(socket: SOCKET, overlapped: *mut OVERLAPPED) -> io::Result<(usize, u32)> { | |
563 | let mut transferred = 0; | |
564 | let mut flags = 0; | |
565 | let r = WSAGetOverlappedResult(socket, overlapped, &mut transferred, FALSE, &mut flags); | |
566 | if r == 0 { | |
567 | Err(io::Error::last_os_error()) | |
568 | } else { | |
569 | Ok((transferred as usize, flags)) | |
570 | } | |
571 | } | |
572 | ||
573 | impl TcpStreamExt for TcpStream { | |
574 | unsafe fn read_overlapped( | |
575 | &self, | |
576 | buf: &mut [u8], | |
577 | overlapped: *mut OVERLAPPED, | |
578 | ) -> io::Result<Option<usize>> { | |
579 | let mut buf = slice2buf(buf); | |
580 | let mut flags = 0; | |
581 | let mut bytes_read: u32 = 0; | |
582 | let r = WSARecv( | |
583 | self.as_raw_socket() as SOCKET, | |
584 | &mut buf, | |
585 | 1, | |
586 | &mut bytes_read, | |
587 | &mut flags, | |
588 | overlapped, | |
589 | None, | |
590 | ); | |
591 | cvt(r, bytes_read) | |
592 | } | |
593 | ||
594 | unsafe fn write_overlapped( | |
595 | &self, | |
596 | buf: &[u8], | |
597 | overlapped: *mut OVERLAPPED, | |
598 | ) -> io::Result<Option<usize>> { | |
599 | let mut buf = slice2buf(buf); | |
600 | let mut bytes_written = 0; | |
601 | ||
602 | // Note here that we capture the number of bytes written. The | |
603 | // documentation on MSDN, however, states: | |
604 | // | |
605 | // > Use NULL for this parameter if the lpOverlapped parameter is not | |
606 | // > NULL to avoid potentially erroneous results. This parameter can be | |
607 | // > NULL only if the lpOverlapped parameter is not NULL. | |
608 | // | |
609 | // If we're not passing a null overlapped pointer here, then why are we | |
610 | // then capturing the number of bytes! Well so it turns out that this is | |
611 | // clearly faster to learn the bytes here rather than later calling | |
612 | // `WSAGetOverlappedResult`, and in practice almost all implementations | |
613 | // use this anyway [1]. | |
614 | // | |
615 | // As a result we use this to and report back the result. | |
616 | // | |
617 | // [1]: https://github.com/carllerche/mio/pull/520#issuecomment-273983823 | |
618 | let r = WSASend( | |
619 | self.as_raw_socket() as SOCKET, | |
620 | &mut buf, | |
621 | 1, | |
622 | &mut bytes_written, | |
623 | 0, | |
624 | overlapped, | |
625 | None, | |
626 | ); | |
627 | cvt(r, bytes_written) | |
628 | } | |
629 | ||
630 | unsafe fn connect_overlapped( | |
631 | &self, | |
632 | addr: &SocketAddr, | |
633 | buf: &[u8], | |
634 | overlapped: *mut OVERLAPPED, | |
635 | ) -> io::Result<Option<usize>> { | |
636 | connect_overlapped(self.as_raw_socket() as SOCKET, addr, buf, overlapped) | |
637 | } | |
638 | ||
639 | fn connect_complete(&self) -> io::Result<()> { | |
640 | const SO_UPDATE_CONNECT_CONTEXT: i32 = 0x7010; | |
641 | let result = unsafe { | |
642 | setsockopt( | |
643 | self.as_raw_socket() as SOCKET, | |
644 | SOL_SOCKET as _, | |
645 | SO_UPDATE_CONNECT_CONTEXT, | |
646 | 0 as *mut _, | |
647 | 0, | |
648 | ) | |
649 | }; | |
650 | if result == 0 { | |
651 | Ok(()) | |
652 | } else { | |
653 | Err(io::Error::last_os_error()) | |
654 | } | |
655 | } | |
656 | ||
657 | unsafe fn result(&self, overlapped: *mut OVERLAPPED) -> io::Result<(usize, u32)> { | |
658 | result(self.as_raw_socket() as SOCKET, overlapped) | |
659 | } | |
660 | } | |
661 | ||
662 | unsafe fn connect_overlapped( | |
663 | socket: SOCKET, | |
664 | addr: &SocketAddr, | |
665 | buf: &[u8], | |
666 | overlapped: *mut OVERLAPPED, | |
667 | ) -> io::Result<Option<usize>> { | |
668 | static CONNECTEX: WsaExtension = WsaExtension { | |
669 | guid: GUID { | |
670 | data1: 0x25a207b9, | |
671 | data2: 0xddf3, | |
672 | data3: 0x4660, | |
673 | data4: [0x8e, 0xe9, 0x76, 0xe5, 0x8c, 0x74, 0x06, 0x3e], | |
674 | }, | |
675 | val: AtomicUsize::new(0), | |
676 | }; | |
677 | ||
678 | let ptr = CONNECTEX.get(socket)?; | |
679 | assert!(ptr != 0); | |
680 | let connect_ex = mem::transmute::<_, LPFN_CONNECTEX>(ptr).unwrap(); | |
681 | ||
682 | let (addr_buf, addr_len) = socket_addr_to_ptrs(addr); | |
683 | let mut bytes_sent: u32 = 0; | |
684 | let r = connect_ex( | |
685 | socket, | |
686 | addr_buf.as_ptr(), | |
687 | addr_len, | |
688 | buf.as_ptr() as *mut _, | |
689 | buf.len() as u32, | |
690 | &mut bytes_sent, | |
691 | overlapped, | |
692 | ); | |
693 | if r == TRUE { | |
694 | Ok(Some(bytes_sent as usize)) | |
695 | } else { | |
696 | last_err() | |
697 | } | |
698 | } | |
699 | ||
700 | impl UdpSocketExt for UdpSocket { | |
701 | unsafe fn recv_from_overlapped( | |
702 | &self, | |
703 | buf: &mut [u8], | |
704 | addr: *mut SocketAddrBuf, | |
705 | overlapped: *mut OVERLAPPED, | |
706 | ) -> io::Result<Option<usize>> { | |
707 | let mut buf = slice2buf(buf); | |
708 | let mut flags = 0; | |
709 | let mut received_bytes: u32 = 0; | |
710 | let r = WSARecvFrom( | |
711 | self.as_raw_socket() as SOCKET, | |
712 | &mut buf, | |
713 | 1, | |
714 | &mut received_bytes, | |
715 | &mut flags, | |
716 | &mut (*addr).buf as *mut _ as *mut _, | |
717 | &mut (*addr).len, | |
718 | overlapped, | |
719 | None, | |
720 | ); | |
721 | cvt(r, received_bytes) | |
722 | } | |
723 | ||
724 | unsafe fn recv_overlapped( | |
725 | &self, | |
726 | buf: &mut [u8], | |
727 | overlapped: *mut OVERLAPPED, | |
728 | ) -> io::Result<Option<usize>> { | |
729 | let mut buf = slice2buf(buf); | |
730 | let mut flags = 0; | |
731 | let mut received_bytes: u32 = 0; | |
732 | let r = WSARecv( | |
733 | self.as_raw_socket() as SOCKET, | |
734 | &mut buf, | |
735 | 1, | |
736 | &mut received_bytes, | |
737 | &mut flags, | |
738 | overlapped, | |
739 | None, | |
740 | ); | |
741 | cvt(r, received_bytes) | |
742 | } | |
743 | ||
744 | unsafe fn send_to_overlapped( | |
745 | &self, | |
746 | buf: &[u8], | |
747 | addr: &SocketAddr, | |
748 | overlapped: *mut OVERLAPPED, | |
749 | ) -> io::Result<Option<usize>> { | |
750 | let (addr_buf, addr_len) = socket_addr_to_ptrs(addr); | |
751 | let mut buf = slice2buf(buf); | |
752 | let mut sent_bytes = 0; | |
753 | let r = WSASendTo( | |
754 | self.as_raw_socket() as SOCKET, | |
755 | &mut buf, | |
756 | 1, | |
757 | &mut sent_bytes, | |
758 | 0, | |
759 | addr_buf.as_ptr() as *const _, | |
760 | addr_len, | |
761 | overlapped, | |
762 | None, | |
763 | ); | |
764 | cvt(r, sent_bytes) | |
765 | } | |
766 | ||
767 | unsafe fn send_overlapped( | |
768 | &self, | |
769 | buf: &[u8], | |
770 | overlapped: *mut OVERLAPPED, | |
771 | ) -> io::Result<Option<usize>> { | |
772 | let mut buf = slice2buf(buf); | |
773 | let mut sent_bytes = 0; | |
774 | let r = WSASend( | |
775 | self.as_raw_socket() as SOCKET, | |
776 | &mut buf, | |
777 | 1, | |
778 | &mut sent_bytes, | |
779 | 0, | |
780 | overlapped, | |
781 | None, | |
782 | ); | |
783 | cvt(r, sent_bytes) | |
784 | } | |
785 | ||
786 | unsafe fn result(&self, overlapped: *mut OVERLAPPED) -> io::Result<(usize, u32)> { | |
787 | result(self.as_raw_socket() as SOCKET, overlapped) | |
788 | } | |
789 | } | |
790 | ||
791 | impl TcpListenerExt for TcpListener { | |
792 | unsafe fn accept_overlapped( | |
793 | &self, | |
794 | socket: &TcpStream, | |
795 | addrs: &mut AcceptAddrsBuf, | |
796 | overlapped: *mut OVERLAPPED, | |
797 | ) -> io::Result<bool> { | |
798 | static ACCEPTEX: WsaExtension = WsaExtension { | |
799 | guid: GUID { | |
800 | data1: 0xb5367df1, | |
801 | data2: 0xcbac, | |
802 | data3: 0x11cf, | |
803 | data4: [0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92], | |
804 | }, | |
805 | val: AtomicUsize::new(0), | |
806 | }; | |
807 | ||
808 | let ptr = ACCEPTEX.get(self.as_raw_socket() as SOCKET)?; | |
809 | assert!(ptr != 0); | |
810 | let accept_ex = mem::transmute::<_, LPFN_ACCEPTEX>(ptr).unwrap(); | |
811 | ||
812 | let mut bytes = 0; | |
813 | let (a, b, c, d) = (*addrs).args(); | |
814 | let r = accept_ex( | |
815 | self.as_raw_socket() as SOCKET, | |
816 | socket.as_raw_socket() as SOCKET, | |
817 | a, | |
818 | b, | |
819 | c, | |
820 | d, | |
821 | &mut bytes, | |
822 | overlapped, | |
823 | ); | |
824 | let succeeded = if r == TRUE { | |
825 | true | |
826 | } else { | |
827 | last_err()?; | |
828 | false | |
829 | }; | |
830 | Ok(succeeded) | |
831 | } | |
832 | ||
833 | fn accept_complete(&self, socket: &TcpStream) -> io::Result<()> { | |
834 | const SO_UPDATE_ACCEPT_CONTEXT: i32 = 0x700B; | |
835 | let me = self.as_raw_socket(); | |
836 | let result = unsafe { | |
837 | setsockopt( | |
838 | socket.as_raw_socket() as SOCKET, | |
839 | SOL_SOCKET as _, | |
840 | SO_UPDATE_ACCEPT_CONTEXT, | |
841 | &me as *const _ as *mut _, | |
842 | mem::size_of_val(&me) as i32, | |
843 | ) | |
844 | }; | |
845 | if result == 0 { | |
846 | Ok(()) | |
847 | } else { | |
848 | Err(io::Error::last_os_error()) | |
849 | } | |
850 | } | |
851 | ||
852 | unsafe fn result(&self, overlapped: *mut OVERLAPPED) -> io::Result<(usize, u32)> { | |
853 | result(self.as_raw_socket() as SOCKET, overlapped) | |
854 | } | |
855 | } | |
856 | ||
857 | impl SocketAddrBuf { | |
858 | /// Creates a new blank socket address buffer. | |
859 | /// | |
860 | /// This should be used before a call to `recv_from_overlapped` overlapped | |
861 | /// to create an instance to pass down. | |
862 | pub fn new() -> SocketAddrBuf { | |
863 | SocketAddrBuf { | |
864 | buf: unsafe { mem::zeroed() }, | |
865 | len: mem::size_of::<SOCKADDR_STORAGE>() as i32, | |
866 | } | |
867 | } | |
868 | ||
869 | /// Parses this buffer to return a standard socket address. | |
870 | /// | |
871 | /// This function should be called after the buffer has been filled in with | |
872 | /// a call to `recv_from_overlapped` being completed. It will interpret the | |
873 | /// address filled in and return the standard socket address type. | |
874 | /// | |
875 | /// If an error is encountered then `None` is returned. | |
876 | pub fn to_socket_addr(&self) -> Option<SocketAddr> { | |
877 | unsafe { ptrs_to_socket_addr(&self.buf as *const _ as *const _, self.len) } | |
878 | } | |
879 | } | |
880 | ||
881 | static GETACCEPTEXSOCKADDRS: WsaExtension = WsaExtension { | |
882 | guid: GUID { | |
883 | data1: 0xb5367df2, | |
884 | data2: 0xcbac, | |
885 | data3: 0x11cf, | |
886 | data4: [0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92], | |
887 | }, | |
888 | val: AtomicUsize::new(0), | |
889 | }; | |
890 | ||
891 | impl AcceptAddrsBuf { | |
892 | /// Creates a new blank buffer ready to be passed to a call to | |
893 | /// `accept_overlapped`. | |
894 | pub fn new() -> AcceptAddrsBuf { | |
895 | unsafe { mem::zeroed() } | |
896 | } | |
897 | ||
898 | /// Parses the data contained in this address buffer, returning the parsed | |
899 | /// result if successful. | |
900 | /// | |
901 | /// This function can be called after a call to `accept_overlapped` has | |
902 | /// succeeded to parse out the data that was written in. | |
903 | pub fn parse(&self, socket: &TcpListener) -> io::Result<AcceptAddrs> { | |
904 | let mut ret = AcceptAddrs { | |
905 | local: 0 as *mut _, | |
906 | local_len: 0, | |
907 | remote: 0 as *mut _, | |
908 | remote_len: 0, | |
909 | _data: self, | |
910 | }; | |
911 | let ptr = GETACCEPTEXSOCKADDRS.get(socket.as_raw_socket() as SOCKET)?; | |
912 | assert!(ptr != 0); | |
913 | unsafe { | |
914 | let get_sockaddrs = mem::transmute::<_, LPFN_GETACCEPTEXSOCKADDRS>(ptr).unwrap(); | |
915 | let (a, b, c, d) = self.args(); | |
916 | get_sockaddrs( | |
917 | a, | |
918 | b, | |
919 | c, | |
920 | d, | |
921 | &mut ret.local, | |
922 | &mut ret.local_len, | |
923 | &mut ret.remote, | |
924 | &mut ret.remote_len, | |
925 | ); | |
926 | Ok(ret) | |
927 | } | |
928 | } | |
929 | ||
930 | #[allow(deref_nullptr)] | |
931 | fn args(&self) -> (*mut std::ffi::c_void, u32, u32, u32) { | |
932 | let remote_offset = unsafe { &(*(0 as *const AcceptAddrsBuf)).remote as *const _ as usize }; | |
933 | ( | |
934 | self as *const _ as *mut _, | |
935 | 0, | |
936 | remote_offset as u32, | |
937 | (mem::size_of_val(self) - remote_offset) as u32, | |
938 | ) | |
939 | } | |
940 | } | |
941 | ||
942 | impl<'a> AcceptAddrs<'a> { | |
943 | /// Returns the local socket address contained in this buffer. | |
944 | pub fn local(&self) -> Option<SocketAddr> { | |
945 | unsafe { ptrs_to_socket_addr(self.local, self.local_len) } | |
946 | } | |
947 | ||
948 | /// Returns the remote socket address contained in this buffer. | |
949 | pub fn remote(&self) -> Option<SocketAddr> { | |
950 | unsafe { ptrs_to_socket_addr(self.remote, self.remote_len) } | |
951 | } | |
952 | } | |
953 | ||
954 | impl WsaExtension { | |
955 | fn get(&self, socket: SOCKET) -> io::Result<usize> { | |
956 | let prev = self.val.load(Ordering::SeqCst); | |
957 | if prev != 0 && !cfg!(debug_assertions) { | |
958 | return Ok(prev); | |
959 | } | |
960 | let mut ret = 0 as usize; | |
961 | let mut bytes = 0; | |
962 | ||
963 | // https://github.com/microsoft/win32metadata/issues/671 | |
964 | const SIO_GET_EXTENSION_FUNCTION_POINTER: u32 = 33_5544_3206u32; | |
965 | ||
966 | let r = unsafe { | |
967 | WSAIoctl( | |
968 | socket, | |
969 | SIO_GET_EXTENSION_FUNCTION_POINTER, | |
970 | &self.guid as *const _ as *mut _, | |
971 | mem::size_of_val(&self.guid) as u32, | |
972 | &mut ret as *mut _ as *mut _, | |
973 | mem::size_of_val(&ret) as u32, | |
974 | &mut bytes, | |
975 | 0 as *mut _, | |
976 | None, | |
977 | ) | |
978 | }; | |
979 | cvt(r, 0).map(|_| { | |
980 | debug_assert_eq!(bytes as usize, mem::size_of_val(&ret)); | |
981 | debug_assert!(prev == 0 || prev == ret); | |
982 | self.val.store(ret, Ordering::SeqCst); | |
983 | ret | |
984 | }) | |
985 | } | |
986 | } | |
987 | ||
988 | #[cfg(test)] | |
989 | mod tests { | |
990 | use std::io::prelude::*; | |
991 | use std::net::{ | |
992 | IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV6, TcpListener, TcpStream, UdpSocket, | |
993 | }; | |
994 | use std::slice; | |
995 | use std::thread; | |
996 | ||
997 | use socket2::{Domain, Socket, Type}; | |
998 | ||
999 | use crate::iocp::CompletionPort; | |
1000 | use crate::net::{AcceptAddrsBuf, TcpListenerExt}; | |
1001 | use crate::net::{SocketAddrBuf, TcpStreamExt, UdpSocketExt}; | |
1002 | use crate::Overlapped; | |
1003 | ||
1004 | fn each_ip(f: &mut dyn FnMut(SocketAddr)) { | |
1005 | f(t!("127.0.0.1:0".parse())); | |
1006 | f(t!("[::1]:0".parse())); | |
1007 | } | |
1008 | ||
1009 | #[test] | |
1010 | fn tcp_read() { | |
1011 | each_ip(&mut |addr| { | |
1012 | let l = t!(TcpListener::bind(addr)); | |
1013 | let addr = t!(l.local_addr()); | |
1014 | let t = thread::spawn(move || { | |
1015 | let mut a = t!(l.accept()).0; | |
1016 | t!(a.write_all(&[1, 2, 3])); | |
1017 | }); | |
1018 | ||
1019 | let cp = t!(CompletionPort::new(1)); | |
1020 | let s = t!(TcpStream::connect(addr)); | |
1021 | t!(cp.add_socket(1, &s)); | |
1022 | ||
1023 | let mut b = [0; 10]; | |
1024 | let a = Overlapped::zero(); | |
1025 | unsafe { | |
1026 | t!(s.read_overlapped(&mut b, a.raw())); | |
1027 | } | |
1028 | let status = t!(cp.get(None)); | |
1029 | assert_eq!(status.bytes_transferred(), 3); | |
1030 | assert_eq!(status.token(), 1); | |
1031 | assert_eq!(status.overlapped(), a.raw()); | |
1032 | assert_eq!(&b[0..3], &[1, 2, 3]); | |
1033 | ||
1034 | t!(t.join()); | |
1035 | }) | |
1036 | } | |
1037 | ||
1038 | #[test] | |
1039 | fn tcp_write() { | |
1040 | each_ip(&mut |addr| { | |
1041 | let l = t!(TcpListener::bind(addr)); | |
1042 | let addr = t!(l.local_addr()); | |
1043 | let t = thread::spawn(move || { | |
1044 | let mut a = t!(l.accept()).0; | |
1045 | let mut b = [0; 10]; | |
1046 | let n = t!(a.read(&mut b)); | |
1047 | assert_eq!(n, 3); | |
1048 | assert_eq!(&b[0..3], &[1, 2, 3]); | |
1049 | }); | |
1050 | ||
1051 | let cp = t!(CompletionPort::new(1)); | |
1052 | let s = t!(TcpStream::connect(addr)); | |
1053 | t!(cp.add_socket(1, &s)); | |
1054 | ||
1055 | let b = [1, 2, 3]; | |
1056 | let a = Overlapped::zero(); | |
1057 | unsafe { | |
1058 | t!(s.write_overlapped(&b, a.raw())); | |
1059 | } | |
1060 | let status = t!(cp.get(None)); | |
1061 | assert_eq!(status.bytes_transferred(), 3); | |
1062 | assert_eq!(status.token(), 1); | |
1063 | assert_eq!(status.overlapped(), a.raw()); | |
1064 | ||
1065 | t!(t.join()); | |
1066 | }) | |
1067 | } | |
1068 | ||
1069 | #[test] | |
1070 | fn tcp_connect() { | |
1071 | each_ip(&mut |addr_template| { | |
1072 | let l = t!(TcpListener::bind(addr_template)); | |
1073 | let addr = t!(l.local_addr()); | |
1074 | let t = thread::spawn(move || { | |
1075 | t!(l.accept()); | |
1076 | }); | |
1077 | ||
1078 | let cp = t!(CompletionPort::new(1)); | |
1079 | let domain = Domain::for_address(addr); | |
1080 | let socket = t!(Socket::new(domain, Type::STREAM, None)); | |
1081 | t!(socket.bind(&addr_template.into())); | |
1082 | let socket = TcpStream::from(socket); | |
1083 | t!(cp.add_socket(1, &socket)); | |
1084 | ||
1085 | let a = Overlapped::zero(); | |
1086 | unsafe { | |
1087 | t!(socket.connect_overlapped(&addr, &[], a.raw())); | |
1088 | } | |
1089 | let status = t!(cp.get(None)); | |
1090 | assert_eq!(status.bytes_transferred(), 0); | |
1091 | assert_eq!(status.token(), 1); | |
1092 | assert_eq!(status.overlapped(), a.raw()); | |
1093 | t!(socket.connect_complete()); | |
1094 | ||
1095 | t!(t.join()); | |
1096 | }) | |
1097 | } | |
1098 | ||
1099 | #[test] | |
1100 | fn udp_recv_from() { | |
1101 | each_ip(&mut |addr| { | |
1102 | let a = t!(UdpSocket::bind(addr)); | |
1103 | let b = t!(UdpSocket::bind(addr)); | |
1104 | let a_addr = t!(a.local_addr()); | |
1105 | let b_addr = t!(b.local_addr()); | |
1106 | let t = thread::spawn(move || { | |
1107 | t!(a.send_to(&[1, 2, 3], b_addr)); | |
1108 | }); | |
1109 | ||
1110 | let cp = t!(CompletionPort::new(1)); | |
1111 | t!(cp.add_socket(1, &b)); | |
1112 | ||
1113 | let mut buf = [0; 10]; | |
1114 | let a = Overlapped::zero(); | |
1115 | let mut addr = SocketAddrBuf::new(); | |
1116 | unsafe { | |
1117 | t!(b.recv_from_overlapped(&mut buf, &mut addr, a.raw())); | |
1118 | } | |
1119 | let status = t!(cp.get(None)); | |
1120 | assert_eq!(status.bytes_transferred(), 3); | |
1121 | assert_eq!(status.token(), 1); | |
1122 | assert_eq!(status.overlapped(), a.raw()); | |
1123 | assert_eq!(&buf[..3], &[1, 2, 3]); | |
1124 | assert_eq!(addr.to_socket_addr(), Some(a_addr)); | |
1125 | ||
1126 | t!(t.join()); | |
1127 | }) | |
1128 | } | |
1129 | ||
1130 | #[test] | |
1131 | fn udp_recv() { | |
1132 | each_ip(&mut |addr| { | |
1133 | let a = t!(UdpSocket::bind(addr)); | |
1134 | let b = t!(UdpSocket::bind(addr)); | |
1135 | let a_addr = t!(a.local_addr()); | |
1136 | let b_addr = t!(b.local_addr()); | |
1137 | assert!(b.connect(a_addr).is_ok()); | |
1138 | assert!(a.connect(b_addr).is_ok()); | |
1139 | let t = thread::spawn(move || { | |
1140 | t!(a.send_to(&[1, 2, 3], b_addr)); | |
1141 | }); | |
1142 | ||
1143 | let cp = t!(CompletionPort::new(1)); | |
1144 | t!(cp.add_socket(1, &b)); | |
1145 | ||
1146 | let mut buf = [0; 10]; | |
1147 | let a = Overlapped::zero(); | |
1148 | unsafe { | |
1149 | t!(b.recv_overlapped(&mut buf, a.raw())); | |
1150 | } | |
1151 | let status = t!(cp.get(None)); | |
1152 | assert_eq!(status.bytes_transferred(), 3); | |
1153 | assert_eq!(status.token(), 1); | |
1154 | assert_eq!(status.overlapped(), a.raw()); | |
1155 | assert_eq!(&buf[..3], &[1, 2, 3]); | |
1156 | ||
1157 | t!(t.join()); | |
1158 | }) | |
1159 | } | |
1160 | ||
1161 | #[test] | |
1162 | fn udp_send_to() { | |
1163 | each_ip(&mut |addr| { | |
1164 | let a = t!(UdpSocket::bind(addr)); | |
1165 | let b = t!(UdpSocket::bind(addr)); | |
1166 | let a_addr = t!(a.local_addr()); | |
1167 | let b_addr = t!(b.local_addr()); | |
1168 | let t = thread::spawn(move || { | |
1169 | let mut b = [0; 100]; | |
1170 | let (n, addr) = t!(a.recv_from(&mut b)); | |
1171 | assert_eq!(n, 3); | |
1172 | assert_eq!(addr, b_addr); | |
1173 | assert_eq!(&b[..3], &[1, 2, 3]); | |
1174 | }); | |
1175 | ||
1176 | let cp = t!(CompletionPort::new(1)); | |
1177 | t!(cp.add_socket(1, &b)); | |
1178 | ||
1179 | let a = Overlapped::zero(); | |
1180 | unsafe { | |
1181 | t!(b.send_to_overlapped(&[1, 2, 3], &a_addr, a.raw())); | |
1182 | } | |
1183 | let status = t!(cp.get(None)); | |
1184 | assert_eq!(status.bytes_transferred(), 3); | |
1185 | assert_eq!(status.token(), 1); | |
1186 | assert_eq!(status.overlapped(), a.raw()); | |
1187 | ||
1188 | t!(t.join()); | |
1189 | }) | |
1190 | } | |
1191 | ||
1192 | #[test] | |
1193 | fn udp_send() { | |
1194 | each_ip(&mut |addr| { | |
1195 | let a = t!(UdpSocket::bind(addr)); | |
1196 | let b = t!(UdpSocket::bind(addr)); | |
1197 | let a_addr = t!(a.local_addr()); | |
1198 | let b_addr = t!(b.local_addr()); | |
1199 | assert!(b.connect(a_addr).is_ok()); | |
1200 | assert!(a.connect(b_addr).is_ok()); | |
1201 | let t = thread::spawn(move || { | |
1202 | let mut b = [0; 100]; | |
1203 | let (n, addr) = t!(a.recv_from(&mut b)); | |
1204 | assert_eq!(n, 3); | |
1205 | assert_eq!(addr, b_addr); | |
1206 | assert_eq!(&b[..3], &[1, 2, 3]); | |
1207 | }); | |
1208 | ||
1209 | let cp = t!(CompletionPort::new(1)); | |
1210 | t!(cp.add_socket(1, &b)); | |
1211 | ||
1212 | let a = Overlapped::zero(); | |
1213 | unsafe { | |
1214 | t!(b.send_overlapped(&[1, 2, 3], a.raw())); | |
1215 | } | |
1216 | let status = t!(cp.get(None)); | |
1217 | assert_eq!(status.bytes_transferred(), 3); | |
1218 | assert_eq!(status.token(), 1); | |
1219 | assert_eq!(status.overlapped(), a.raw()); | |
1220 | ||
1221 | t!(t.join()); | |
1222 | }) | |
1223 | } | |
1224 | ||
1225 | #[test] | |
1226 | fn tcp_accept() { | |
1227 | each_ip(&mut |addr_template| { | |
1228 | let l = t!(TcpListener::bind(addr_template)); | |
1229 | let addr = t!(l.local_addr()); | |
1230 | let t = thread::spawn(move || { | |
1231 | let socket = t!(TcpStream::connect(addr)); | |
1232 | (socket.local_addr().unwrap(), socket.peer_addr().unwrap()) | |
1233 | }); | |
1234 | ||
1235 | let cp = t!(CompletionPort::new(1)); | |
1236 | let domain = Domain::for_address(addr); | |
1237 | let socket = TcpStream::from(t!(Socket::new(domain, Type::STREAM, None))); | |
1238 | t!(cp.add_socket(1, &l)); | |
1239 | ||
1240 | let a = Overlapped::zero(); | |
1241 | let mut addrs = AcceptAddrsBuf::new(); | |
1242 | unsafe { | |
1243 | t!(l.accept_overlapped(&socket, &mut addrs, a.raw())); | |
1244 | } | |
1245 | let status = t!(cp.get(None)); | |
1246 | assert_eq!(status.bytes_transferred(), 0); | |
1247 | assert_eq!(status.token(), 1); | |
1248 | assert_eq!(status.overlapped(), a.raw()); | |
1249 | t!(l.accept_complete(&socket)); | |
1250 | ||
1251 | let (remote, local) = t!(t.join()); | |
1252 | let addrs = addrs.parse(&l).unwrap(); | |
1253 | assert_eq!(addrs.local(), Some(local)); | |
1254 | assert_eq!(addrs.remote(), Some(remote)); | |
1255 | }) | |
1256 | } | |
1257 | ||
1258 | #[test] | |
1259 | fn sockaddr_convert_4() { | |
1260 | let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(3, 4, 5, 6)), 0xabcd); | |
1261 | let (raw_addr, addr_len) = super::socket_addr_to_ptrs(&addr); | |
1262 | assert_eq!(addr_len, 16); | |
1263 | let addr_bytes = | |
1264 | unsafe { slice::from_raw_parts(raw_addr.as_ptr() as *const u8, addr_len as usize) }; | |
1265 | assert_eq!( | |
1266 | addr_bytes, | |
1267 | &[2, 0, 0xab, 0xcd, 3, 4, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0] | |
1268 | ); | |
1269 | } | |
1270 | ||
1271 | #[test] | |
1272 | fn sockaddr_convert_v6() { | |
1273 | let port = 0xabcd; | |
1274 | let flowinfo = 0x12345678; | |
1275 | let scope_id = 0x87654321; | |
1276 | let addr = SocketAddr::V6(SocketAddrV6::new( | |
1277 | Ipv6Addr::new( | |
1278 | 0x0102, 0x0304, 0x0506, 0x0708, 0x090a, 0x0b0c, 0x0d0e, 0x0f10, | |
1279 | ), | |
1280 | port, | |
1281 | flowinfo, | |
1282 | scope_id, | |
1283 | )); | |
1284 | let (raw_addr, addr_len) = super::socket_addr_to_ptrs(&addr); | |
1285 | assert_eq!(addr_len, 28); | |
1286 | let addr_bytes = | |
1287 | unsafe { slice::from_raw_parts(raw_addr.as_ptr() as *const u8, addr_len as usize) }; | |
1288 | assert_eq!( | |
1289 | addr_bytes, | |
1290 | &[ | |
1291 | 23, 0, // AF_INET6 | |
1292 | 0xab, 0xcd, // Port | |
1293 | 0x78, 0x56, 0x34, 0x12, // flowinfo | |
1294 | 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, | |
1295 | 0x0f, 0x10, // IP | |
1296 | 0x21, 0x43, 0x65, 0x87, // scope_id | |
1297 | ] | |
1298 | ); | |
1299 | } | |
1300 | } |