1 //! Extensions and types for the standard networking primitives.
3 //! This module contains a number of extension traits for the types in
4 //! `std::net` for Windows-specific functionality.
9 use std
::sync
::atomic
::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}
;
10 use std
::net
::{TcpStream, UdpSocket, SocketAddr, TcpListener}
;
11 use std
::net
::{SocketAddrV4, Ipv4Addr, SocketAddrV6, Ipv6Addr}
;
12 use std
::os
::windows
::prelude
::*;
18 /// A type to represent a buffer in which a socket address will be stored.
20 /// This type is used with the `recv_from_overlapped` function on the
21 /// `UdpSocketExt` trait to provide space for the overlapped I/O operation to
22 /// fill in the address upon completion.
23 #[derive(Clone, Copy)]
24 pub struct SocketAddrBuf
{
25 buf
: SOCKADDR_STORAGE
,
29 /// A type to represent a buffer in which an accepted socket's address will be
32 /// This type is used with the `accept_overlapped` method on the
33 /// `TcpListenerExt` trait to provide space for the overlapped I/O operation to
34 /// fill in the socket addresses upon completion.
36 pub struct AcceptAddrsBuf
{
37 // For AcceptEx we've got the restriction that the addresses passed in that
38 // buffer need to be at least 16 bytes more than the maximum address length
39 // for the protocol in question, so add some extra here and there
40 local
: SOCKADDR_STORAGE
,
42 remote
: SOCKADDR_STORAGE
,
46 /// The parsed return value of `AcceptAddrsBuf`.
47 pub struct AcceptAddrs
<'a
> {
52 _data
: &'a AcceptAddrsBuf
,
60 /// Additional methods for the `TcpStream` type in the standard library.
61 pub trait TcpStreamExt
{
62 /// Execute an overlapped read I/O operation on this TCP stream.
64 /// This function will issue an overlapped I/O read (via `WSARecv`) on this
65 /// socket. The provided buffer will be filled in when the operation
66 /// completes and the given `OVERLAPPED` instance is used to track the
67 /// overlapped operation.
69 /// If the operation succeeds, `Ok(Some(n))` is returned indicating how
70 /// many bytes were read. If the operation returns an error indicating that
71 /// the I/O is currently pending, `Ok(None)` is returned. Otherwise, the
72 /// error associated with the operation is returned and no overlapped
73 /// operation is enqueued.
75 /// The number of bytes read will be returned as part of the completion
76 /// notification when the I/O finishes.
80 /// This function is unsafe because the kernel requires that the `buf` and
81 /// `overlapped` pointers are valid until the end of the I/O operation. The
82 /// kernel also requires that `overlapped` is unique for this I/O operation
83 /// and is not in use for any other I/O.
85 /// To safely use this function callers must ensure that these two input
86 /// pointers are valid until the I/O operation is completed, typically via
87 /// completion ports and waiting to receive the completion notification on
89 unsafe fn read_overlapped(&self,
91 overlapped
: *mut OVERLAPPED
)
92 -> io
::Result
<Option
<usize>>;
94 /// Execute an overlapped write I/O operation on this TCP stream.
96 /// This function will issue an overlapped I/O write (via `WSASend`) on this
97 /// socket. The provided buffer will be written when the operation completes
98 /// and the given `OVERLAPPED` instance is used to track the overlapped
101 /// If the operation succeeds, `Ok(Some(n))` is returned where `n` is the
102 /// number of bytes that were written. If the operation returns an error
103 /// indicating that the I/O is currently pending, `Ok(None)` is returned.
104 /// Otherwise, the error associated with the operation is returned and no
105 /// overlapped operation is enqueued.
107 /// The number of bytes written will be returned as part of the completion
108 /// notification when the I/O finishes.
112 /// This function is unsafe because the kernel requires that the `buf` and
113 /// `overlapped` pointers are valid until the end of the I/O operation. The
114 /// kernel also requires that `overlapped` is unique for this I/O operation
115 /// and is not in use for any other I/O.
117 /// To safely use this function callers must ensure that these two input
118 /// pointers are valid until the I/O operation is completed, typically via
119 /// completion ports and waiting to receive the completion notification on
121 unsafe fn write_overlapped(&self,
123 overlapped
: *mut OVERLAPPED
)
124 -> io
::Result
<Option
<usize>>;
126 /// Execute a connection operation for this socket.
128 /// For more information about this method, see the
129 /// [`TcpBuilderExt::connect_overlapped`][link] documentation.
131 /// [link]: trait.TcpBuilderExt.html#tymethod.connect_overlapped
132 unsafe fn connect_overlapped(&self,
135 overlapped
: *mut OVERLAPPED
)
136 -> io
::Result
<Option
<usize>>;
138 /// Once a `connect_overlapped` has finished, this function needs to be
139 /// called to finish the connect operation.
141 /// Currently this just calls `setsockopt` with `SO_UPDATE_CONNECT_CONTEXT`
142 /// to ensure that further functions like `getpeername` and `getsockname`
144 fn connect_complete(&self) -> io
::Result
<()>;
146 /// Calls the `GetOverlappedResult` function to get the result of an
147 /// overlapped operation for this handle.
149 /// This function takes the `OVERLAPPED` argument which must have been used
150 /// to initiate an overlapped I/O operation, and returns either the
151 /// successful number of bytes transferred during the operation or an error
152 /// if one occurred, along with the results of the `lpFlags` parameter of
153 /// the relevant operation, if applicable.
157 /// This function is unsafe as `overlapped` must have previously been used
158 /// to execute an operation for this handle, and it must also be a valid
159 /// pointer to an `OVERLAPPED` instance.
163 /// This function will panic
164 unsafe fn result(&self, overlapped
: *mut OVERLAPPED
)
165 -> io
::Result
<(usize, u32)>;
168 /// Additional methods for the `UdpSocket` type in the standard library.
169 pub trait UdpSocketExt
{
170 /// Execute an overlapped receive I/O operation on this UDP socket.
172 /// This function will issue an overlapped I/O read (via `WSARecvFrom`) on
173 /// this socket. The provided buffer will be filled in when the operation
174 /// completes, the source from where the data came from will be written to
175 /// `addr`, and the given `OVERLAPPED` instance is used to track the
176 /// overlapped operation.
178 /// If the operation succeeds, `Ok(Some(n))` is returned where `n` is the
179 /// number of bytes that were read. If the operation returns an error
180 /// indicating that the I/O is currently pending, `Ok(None)` is returned.
181 /// Otherwise, the error associated with the operation is returned and no
182 /// overlapped operation is enqueued.
184 /// The number of bytes read will be returned as part of the completion
185 /// notification when the I/O finishes.
189 /// This function is unsafe because the kernel requires that the `buf`,
190 /// `addr`, and `overlapped` pointers are valid until the end of the I/O
191 /// operation. The kernel also requires that `overlapped` is unique for this
192 /// I/O operation and is not in use for any other I/O.
194 /// To safely use this function callers must ensure that these two input
195 /// pointers are valid until the I/O operation is completed, typically via
196 /// completion ports and waiting to receive the completion notification on
198 unsafe fn recv_from_overlapped(&self,
200 addr
: *mut SocketAddrBuf
,
201 overlapped
: *mut OVERLAPPED
)
202 -> io
::Result
<Option
<usize>>;
204 /// Execute an overlapped receive I/O operation on this UDP socket.
206 /// This function will issue an overlapped I/O read (via `WSARecv`) on
207 /// this socket. The provided buffer will be filled in when the operation
208 /// completes, the source from where the data came from will be written to
209 /// `addr`, and the given `OVERLAPPED` instance is used to track the
210 /// overlapped operation.
212 /// If the operation succeeds, `Ok(Some(n))` is returned where `n` is the
213 /// number of bytes that were read. If the operation returns an error
214 /// indicating that the I/O is currently pending, `Ok(None)` is returned.
215 /// Otherwise, the error associated with the operation is returned and no
216 /// overlapped operation is enqueued.
218 /// The number of bytes read will be returned as part of the completion
219 /// notification when the I/O finishes.
223 /// This function is unsafe because the kernel requires that the `buf`,
224 /// and `overlapped` pointers are valid until the end of the I/O
225 /// operation. The kernel also requires that `overlapped` is unique for this
226 /// I/O operation and is not in use for any other I/O.
228 /// To safely use this function callers must ensure that these two input
229 /// pointers are valid until the I/O operation is completed, typically via
230 /// completion ports and waiting to receive the completion notification on
232 unsafe fn recv_overlapped(&self,
234 overlapped
: *mut OVERLAPPED
)
235 -> io
::Result
<Option
<usize>>;
237 /// Execute an overlapped send I/O operation on this UDP socket.
239 /// This function will issue an overlapped I/O write (via `WSASendTo`) on
240 /// this socket to the address specified by `addr`. The provided buffer will
241 /// be written when the operation completes and the given `OVERLAPPED`
242 /// instance is used to track the overlapped operation.
244 /// If the operation succeeds, `Ok(Some(n0)` is returned where `n` byte
245 /// were written. If the operation returns an error indicating that the I/O
246 /// is currently pending, `Ok(None)` is returned. Otherwise, the error
247 /// associated with the operation is returned and no overlapped operation
250 /// The number of bytes written will be returned as part of the completion
251 /// notification when the I/O finishes.
255 /// This function is unsafe because the kernel requires that the `buf` and
256 /// `overlapped` pointers are valid until the end of the I/O operation. The
257 /// kernel also requires that `overlapped` is unique for this I/O operation
258 /// and is not in use for any other I/O.
260 /// To safely use this function callers must ensure that these two input
261 /// pointers are valid until the I/O operation is completed, typically via
262 /// completion ports and waiting to receive the completion notification on
264 unsafe fn send_to_overlapped(&self,
267 overlapped
: *mut OVERLAPPED
)
268 -> io
::Result
<Option
<usize>>;
270 /// Execute an overlapped send I/O operation on this UDP socket.
272 /// This function will issue an overlapped I/O write (via `WSASend`) on
273 /// this socket to the address it was previously connected to. The provided
274 /// buffer will be written when the operation completes and the given `OVERLAPPED`
275 /// instance is used to track the overlapped operation.
277 /// If the operation succeeds, `Ok(Some(n0)` is returned where `n` byte
278 /// were written. If the operation returns an error indicating that the I/O
279 /// is currently pending, `Ok(None)` is returned. Otherwise, the error
280 /// associated with the operation is returned and no overlapped operation
283 /// The number of bytes written will be returned as part of the completion
284 /// notification when the I/O finishes.
288 /// This function is unsafe because the kernel requires that the `buf` and
289 /// `overlapped` pointers are valid until the end of the I/O operation. The
290 /// kernel also requires that `overlapped` is unique for this I/O operation
291 /// and is not in use for any other I/O.
293 /// To safely use this function callers must ensure that these two input
294 /// pointers are valid until the I/O operation is completed, typically via
295 /// completion ports and waiting to receive the completion notification on
297 unsafe fn send_overlapped(&self,
299 overlapped
: *mut OVERLAPPED
)
300 -> io
::Result
<Option
<usize>>;
302 /// Calls the `GetOverlappedResult` function to get the result of an
303 /// overlapped operation for this handle.
305 /// This function takes the `OVERLAPPED` argument which must have been used
306 /// to initiate an overlapped I/O operation, and returns either the
307 /// successful number of bytes transferred during the operation or an error
308 /// if one occurred, along with the results of the `lpFlags` parameter of
309 /// the relevant operation, if applicable.
313 /// This function is unsafe as `overlapped` must have previously been used
314 /// to execute an operation for this handle, and it must also be a valid
315 /// pointer to an `OVERLAPPED` instance.
319 /// This function will panic
320 unsafe fn result(&self, overlapped
: *mut OVERLAPPED
)
321 -> io
::Result
<(usize, u32)>;
324 /// Additional methods for the `TcpBuilder` type in the `net2` library.
325 pub trait TcpBuilderExt
{
326 /// Attempt to consume the internal socket in this builder by executing an
327 /// overlapped connect operation.
329 /// This function will issue a connect operation to the address specified on
330 /// the underlying socket, flagging it as an overlapped operation which will
331 /// complete asynchronously. If successful this function will return the
332 /// corresponding TCP stream.
334 /// The `buf` argument provided is an initial buffer of data that should be
335 /// sent after the connection is initiated. It's acceptable to
336 /// pass an empty slice here.
338 /// This function will also return whether the connect immediately
339 /// succeeded or not. If `None` is returned then the I/O operation is still
340 /// pending and will complete at a later date, and if `Some(bytes)` is
341 /// returned then that many bytes were transferred.
343 /// Note that to succeed this requires that the underlying socket has
344 /// previously been bound via a call to `bind` to a local address.
348 /// This function is unsafe because the kernel requires that the
349 /// `overlapped` and `buf` pointers to be valid until the end of the I/O
350 /// operation. The kernel also requires that `overlapped` is unique for
351 /// this I/O operation and is not in use for any other I/O.
353 /// To safely use this function callers must ensure that this pointer is
354 /// valid until the I/O operation is completed, typically via completion
355 /// ports and waiting to receive the completion notification on the port.
356 unsafe fn connect_overlapped(&self,
359 overlapped
: *mut OVERLAPPED
)
360 -> io
::Result
<(TcpStream
, Option
<usize>)>;
362 /// Calls the `GetOverlappedResult` function to get the result of an
363 /// overlapped operation for this handle.
365 /// This function takes the `OVERLAPPED` argument which must have been used
366 /// to initiate an overlapped I/O operation, and returns either the
367 /// successful number of bytes transferred during the operation or an error
368 /// if one occurred, along with the results of the `lpFlags` parameter of
369 /// the relevant operation, if applicable.
373 /// This function is unsafe as `overlapped` must have previously been used
374 /// to execute an operation for this handle, and it must also be a valid
375 /// pointer to an `OVERLAPPED` instance.
379 /// This function will panic
380 unsafe fn result(&self, overlapped
: *mut OVERLAPPED
)
381 -> io
::Result
<(usize, u32)>;
384 /// Additional methods for the `TcpListener` type in the standard library.
385 pub trait TcpListenerExt
{
386 /// Perform an accept operation on this listener, accepting a connection in
387 /// an overlapped fashion.
389 /// This function will issue an I/O request to accept an incoming connection
390 /// with the specified overlapped instance. The `socket` provided must be a
391 /// configured but not bound or connected socket, and if successful this
392 /// will consume the internal socket of the builder to return a TCP stream.
394 /// The `addrs` buffer provided will be filled in with the local and remote
395 /// addresses of the connection upon completion.
397 /// If the accept succeeds immediately, `Ok(stream, true)` is returned. If
398 /// the connect indicates that the I/O is currently pending, `Ok(stream,
399 /// false)` is returned. Otherwise, the error associated with the operation
400 /// is returned and no overlapped operation is enqueued.
404 /// This function is unsafe because the kernel requires that the
405 /// `addrs` and `overlapped` pointers are valid until the end of the I/O
406 /// operation. The kernel also requires that `overlapped` is unique for this
407 /// I/O operation and is not in use for any other I/O.
409 /// To safely use this function callers must ensure that the pointers are
410 /// valid until the I/O operation is completed, typically via completion
411 /// ports and waiting to receive the completion notification on the port.
412 unsafe fn accept_overlapped(&self,
414 addrs
: &mut AcceptAddrsBuf
,
415 overlapped
: *mut OVERLAPPED
)
416 -> io
::Result
<(TcpStream
, bool
)>;
418 /// Once an `accept_overlapped` has finished, this function needs to be
419 /// called to finish the accept operation.
421 /// Currently this just calls `setsockopt` with `SO_UPDATE_ACCEPT_CONTEXT`
422 /// to ensure that further functions like `getpeername` and `getsockname`
424 fn accept_complete(&self, socket
: &TcpStream
) -> io
::Result
<()>;
426 /// Calls the `GetOverlappedResult` function to get the result of an
427 /// overlapped operation for this handle.
429 /// This function takes the `OVERLAPPED` argument which must have been used
430 /// to initiate an overlapped I/O operation, and returns either the
431 /// successful number of bytes transferred during the operation or an error
432 /// if one occurred, along with the results of the `lpFlags` parameter of
433 /// the relevant operation, if applicable.
437 /// This function is unsafe as `overlapped` must have previously been used
438 /// to execute an operation for this handle, and it must also be a valid
439 /// pointer to an `OVERLAPPED` instance.
443 /// This function will panic
444 unsafe fn result(&self, overlapped
: *mut OVERLAPPED
)
445 -> io
::Result
<(usize, u32)>;
450 fn from_be(i
: Self) -> Self;
451 fn to_be(&self) -> Self;
454 ($
($t
:ident
)*) => ($
(impl NetInt
for $t
{
455 fn from_be(i
: Self) -> Self { <$t>::from_be(i) }
456 fn to_be(&self) -> Self { <$t>::to_be(*self) }
459 doit
! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }
461 // fn hton<I: NetInt>(i: I) -> I { i.to_be() }
462 fn ntoh
<I
: NetInt
>(i
: I
) -> I { I::from_be(i) }
464 fn last_err() -> io
::Result
<Option
<usize>> {
465 let err
= unsafe { WSAGetLastError() }
;
466 if err
== WSA_IO_PENDING
as i32 {
469 Err(io
::Error
::from_raw_os_error(err
))
473 fn cvt(i
: c_int
, size
: DWORD
) -> io
::Result
<Option
<usize>> {
474 if i
== SOCKET_ERROR
{
477 Ok(Some(size
as usize))
481 fn socket_addr_to_ptrs(addr
: &SocketAddr
) -> (*const SOCKADDR
, c_int
) {
483 SocketAddr
::V4(ref a
) => {
484 (a
as *const _
as *const _
, mem
::size_of
::<SOCKADDR_IN
>() as c_int
)
486 SocketAddr
::V6(ref a
) => {
487 (a
as *const _
as *const _
, mem
::size_of
::<sockaddr_in6
>() as c_int
)
492 unsafe fn ptrs_to_socket_addr(ptr
: *const SOCKADDR
,
493 len
: c_int
) -> Option
<SocketAddr
> {
494 if (len
as usize) < mem
::size_of
::<c_int
>() {
497 match (*ptr
).sa_family
as i32 {
498 AF_INET
if len
as usize >= mem
::size_of
::<SOCKADDR_IN
>() => {
499 let b
= &*(ptr
as *const SOCKADDR_IN
);
500 let ip
= ntoh(b
.sin_addr
.S_un
);
501 let ip
= Ipv4Addr
::new((ip
>> 24) as u8,
505 Some(SocketAddr
::V4(SocketAddrV4
::new(ip
, ntoh(b
.sin_port
))))
507 AF_INET6
if len
as usize >= mem
::size_of
::<sockaddr_in6
>() => {
508 let b
= &*(ptr
as *const sockaddr_in6
);
509 let arr
= &b
.sin6_addr
.s6_addr
;
510 let ip
= Ipv6Addr
::new(
511 ((arr
[0] as u16) << 8) | (arr
[1] as u16),
512 ((arr
[2] as u16) << 8) | (arr
[3] as u16),
513 ((arr
[4] as u16) << 8) | (arr
[5] as u16),
514 ((arr
[6] as u16) << 8) | (arr
[7] as u16),
515 ((arr
[8] as u16) << 8) | (arr
[9] as u16),
516 ((arr
[10] as u16) << 8) | (arr
[11] as u16),
517 ((arr
[12] as u16) << 8) | (arr
[13] as u16),
518 ((arr
[14] as u16) << 8) | (arr
[15] as u16));
519 let addr
= SocketAddrV6
::new(ip
, ntoh(b
.sin6_port
),
520 ntoh(b
.sin6_flowinfo
),
521 ntoh(b
.sin6_scope_id
));
522 Some(SocketAddr
::V6(addr
))
528 unsafe fn slice2buf(slice
: &[u8]) -> WSABUF
{
530 len
: cmp
::min(slice
.len(), <u_long
>::max_value() as usize) as u_long
,
531 buf
: slice
.as_ptr() as *mut _
,
535 unsafe fn result(socket
: SOCKET
, overlapped
: *mut OVERLAPPED
)
536 -> io
::Result
<(usize, u32)> {
537 let mut transferred
= 0;
539 let r
= WSAGetOverlappedResult(socket
,
545 Err(io
::Error
::last_os_error())
547 Ok((transferred
as usize, flags
))
551 impl TcpStreamExt
for TcpStream
{
552 unsafe fn read_overlapped(&self,
554 overlapped
: *mut OVERLAPPED
)
555 -> io
::Result
<Option
<usize>> {
556 let mut buf
= slice2buf(buf
);
558 let mut bytes_read
: DWORD
= 0;
559 let r
= WSARecv(self.as_raw_socket(), &mut buf
, 1,
560 &mut bytes_read
, &mut flags
, overlapped
, None
);
564 unsafe fn write_overlapped(&self,
566 overlapped
: *mut OVERLAPPED
)
567 -> io
::Result
<Option
<usize>> {
568 let mut buf
= slice2buf(buf
);
569 let mut bytes_written
= 0;
571 // Note here that we capture the number of bytes written. The
572 // documentation on MSDN, however, states:
574 // > Use NULL for this parameter if the lpOverlapped parameter is not
575 // > NULL to avoid potentially erroneous results. This parameter can be
576 // > NULL only if the lpOverlapped parameter is not NULL.
578 // If we're not passing a null overlapped pointer here, then why are we
579 // then capturing the number of bytes! Well so it turns out that this is
580 // clearly faster to learn the bytes here rather than later calling
581 // `WSAGetOverlappedResult`, and in practice almost all implementations
582 // use this anyway [1].
584 // As a result we use this to and report back the result.
586 // [1]: https://github.com/carllerche/mio/pull/520#issuecomment-273983823
587 let r
= WSASend(self.as_raw_socket(), &mut buf
, 1,
588 &mut bytes_written
, 0, overlapped
, None
);
589 cvt(r
, bytes_written
)
592 unsafe fn connect_overlapped(&self,
595 overlapped
: *mut OVERLAPPED
)
596 -> io
::Result
<Option
<usize>> {
597 connect_overlapped(self.as_raw_socket(), addr
, buf
, overlapped
)
600 fn connect_complete(&self) -> io
::Result
<()> {
601 const SO_UPDATE_CONNECT_CONTEXT
: c_int
= 0x7010;
602 let result
= unsafe {
603 setsockopt(self.as_raw_socket(),
605 SO_UPDATE_CONNECT_CONTEXT
,
612 Err(io
::Error
::last_os_error())
616 unsafe fn result(&self, overlapped
: *mut OVERLAPPED
)
617 -> io
::Result
<(usize, u32)> {
618 result(self.as_raw_socket(), overlapped
)
622 unsafe fn connect_overlapped(socket
: SOCKET
,
625 overlapped
: *mut OVERLAPPED
)
626 -> io
::Result
<Option
<usize>> {
627 static CONNECTEX
: WsaExtension
= WsaExtension
{
632 Data4
: [0x8e, 0xe9, 0x76, 0xe5, 0x8c, 0x74, 0x06, 0x3e],
634 val
: ATOMIC_USIZE_INIT
,
636 type ConnectEx
= unsafe extern "system" fn(SOCKET
, *const SOCKADDR
,
637 c_int
, PVOID
, DWORD
, LPDWORD
,
638 LPOVERLAPPED
) -> BOOL
;
640 let ptr
= try
!(CONNECTEX
.get(socket
));
642 let connect_ex
= mem
::transmute
::<_
, ConnectEx
>(ptr
);
644 let (addr_buf
, addr_len
) = socket_addr_to_ptrs(addr
);
645 let mut bytes_sent
: DWORD
= 0;
646 let r
= connect_ex(socket
, addr_buf
, addr_len
,
647 buf
.as_ptr() as *mut _
,
649 &mut bytes_sent
, overlapped
);
651 Ok(Some(bytes_sent
as usize))
657 impl UdpSocketExt
for UdpSocket
{
658 unsafe fn recv_from_overlapped(&self,
660 addr
: *mut SocketAddrBuf
,
661 overlapped
: *mut OVERLAPPED
)
662 -> io
::Result
<Option
<usize>> {
663 let mut buf
= slice2buf(buf
);
665 let mut received_bytes
: DWORD
= 0;
666 let r
= WSARecvFrom(self.as_raw_socket(), &mut buf
, 1,
667 &mut received_bytes
, &mut flags
,
668 &mut (*addr
).buf
as *mut _
as *mut _
,
671 cvt(r
, received_bytes
)
674 unsafe fn recv_overlapped(&self,
676 overlapped
: *mut OVERLAPPED
)
677 -> io
::Result
<Option
<usize>> {
678 let mut buf
= slice2buf(buf
);
680 let mut received_bytes
: DWORD
= 0;
681 let r
= WSARecv(self.as_raw_socket(), &mut buf
, 1,
682 &mut received_bytes
, &mut flags
,
684 cvt(r
, received_bytes
)
687 unsafe fn send_to_overlapped(&self,
690 overlapped
: *mut OVERLAPPED
)
691 -> io
::Result
<Option
<usize>> {
692 let (addr_buf
, addr_len
) = socket_addr_to_ptrs(addr
);
693 let mut buf
= slice2buf(buf
);
694 let mut sent_bytes
= 0;
695 let r
= WSASendTo(self.as_raw_socket(), &mut buf
, 1,
697 addr_buf
as *const _
, addr_len
,
702 unsafe fn send_overlapped(&self,
704 overlapped
: *mut OVERLAPPED
)
705 -> io
::Result
<Option
<usize>> {
706 let mut buf
= slice2buf(buf
);
707 let mut sent_bytes
= 0;
708 let r
= WSASend(self.as_raw_socket(), &mut buf
, 1,
714 unsafe fn result(&self, overlapped
: *mut OVERLAPPED
)
715 -> io
::Result
<(usize, u32)> {
716 result(self.as_raw_socket(), overlapped
)
720 impl TcpBuilderExt
for TcpBuilder
{
721 unsafe fn connect_overlapped(&self,
724 overlapped
: *mut OVERLAPPED
)
725 -> io
::Result
<(TcpStream
, Option
<usize>)> {
726 connect_overlapped(self.as_raw_socket(), addr
, buf
, overlapped
).map(|s
| {
727 (self.to_tcp_stream().unwrap(), s
)
731 unsafe fn result(&self, overlapped
: *mut OVERLAPPED
)
732 -> io
::Result
<(usize, u32)> {
733 result(self.as_raw_socket(), overlapped
)
737 impl TcpListenerExt
for TcpListener
{
738 unsafe fn accept_overlapped(&self,
740 addrs
: &mut AcceptAddrsBuf
,
741 overlapped
: *mut OVERLAPPED
)
742 -> io
::Result
<(TcpStream
, bool
)> {
743 static ACCEPTEX
: WsaExtension
= WsaExtension
{
748 Data4
: [0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92],
750 val
: ATOMIC_USIZE_INIT
,
752 type AcceptEx
= unsafe extern "system" fn(SOCKET
, SOCKET
, PVOID
,
753 DWORD
, DWORD
, DWORD
, LPDWORD
,
754 LPOVERLAPPED
) -> BOOL
;
756 let ptr
= try
!(ACCEPTEX
.get(self.as_raw_socket()));
758 let accept_ex
= mem
::transmute
::<_
, AcceptEx
>(ptr
);
761 let (a
, b
, c
, d
) = (*addrs
).args();
762 let r
= accept_ex(self.as_raw_socket(), socket
.as_raw_socket(),
763 a
, b
, c
, d
, &mut bytes
, overlapped
);
764 let succeeded
= if r
== TRUE
{
770 // NB: this unwrap() should be guaranteed to succeed, and this is an
771 // assert that it does indeed succeed.
772 Ok((socket
.to_tcp_stream().unwrap(), succeeded
))
775 fn accept_complete(&self, socket
: &TcpStream
) -> io
::Result
<()> {
776 const SO_UPDATE_ACCEPT_CONTEXT
: c_int
= 0x700B;
777 let me
= self.as_raw_socket();
778 let result
= unsafe {
779 setsockopt(socket
.as_raw_socket(),
781 SO_UPDATE_ACCEPT_CONTEXT
,
782 &me
as *const _
as *const _
,
783 mem
::size_of_val(&me
) as c_int
)
788 Err(io
::Error
::last_os_error())
792 unsafe fn result(&self, overlapped
: *mut OVERLAPPED
)
793 -> io
::Result
<(usize, u32)> {
794 result(self.as_raw_socket(), overlapped
)
799 /// Creates a new blank socket address buffer.
801 /// This should be used before a call to `recv_from_overlapped` overlapped
802 /// to create an instance to pass down.
803 pub fn new() -> SocketAddrBuf
{
805 buf
: unsafe { mem::zeroed() }
,
806 len
: mem
::size_of
::<SOCKADDR_STORAGE
>() as c_int
,
810 /// Parses this buffer to return a standard socket address.
812 /// This function should be called after the buffer has been filled in with
813 /// a call to `recv_from_overlapped` being completed. It will interpret the
814 /// address filled in and return the standard socket address type.
816 /// If an error is encountered then `None` is returned.
817 pub fn to_socket_addr(&self) -> Option
<SocketAddr
> {
819 ptrs_to_socket_addr(&self.buf
as *const _
as *const _
, self.len
)
824 static GETACCEPTEXSOCKADDRS
: WsaExtension
= WsaExtension
{
829 Data4
: [0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92],
831 val
: ATOMIC_USIZE_INIT
,
833 type GetAcceptExSockaddrs
= unsafe extern "system" fn(PVOID
, DWORD
, DWORD
, DWORD
,
834 *mut LPSOCKADDR
, LPINT
,
835 *mut LPSOCKADDR
, LPINT
);
837 impl AcceptAddrsBuf
{
838 /// Creates a new blank buffer ready to be passed to a call to
839 /// `accept_overlapped`.
840 pub fn new() -> AcceptAddrsBuf
{
841 unsafe { mem::zeroed() }
844 /// Parses the data contained in this address buffer, returning the parsed
845 /// result if successful.
847 /// This function can be called after a call to `accept_overlapped` has
848 /// succeeded to parse out the data that was written in.
849 pub fn parse(&self, socket
: &TcpListener
) -> io
::Result
<AcceptAddrs
> {
850 let mut ret
= AcceptAddrs
{
851 local
: 0 as *mut _
, local_len
: 0,
852 remote
: 0 as *mut _
, remote_len
: 0,
855 let ptr
= try
!(GETACCEPTEXSOCKADDRS
.get(socket
.as_raw_socket()));
858 let get_sockaddrs
= mem
::transmute
::<_
, GetAcceptExSockaddrs
>(ptr
);
859 let (a
, b
, c
, d
) = self.args();
860 get_sockaddrs(a
, b
, c
, d
,
861 &mut ret
.local
, &mut ret
.local_len
,
862 &mut ret
.remote
, &mut ret
.remote_len
);
867 fn args(&self) -> (PVOID
, DWORD
, DWORD
, DWORD
) {
868 let remote_offset
= unsafe {
869 &(*(0 as *const AcceptAddrsBuf
)).remote
as *const _
as usize
871 (self as *const _
as *mut _
, 0, remote_offset
as DWORD
,
872 (mem
::size_of_val(self) - remote_offset
) as DWORD
)
876 impl<'a
> AcceptAddrs
<'a
> {
877 /// Returns the local socket address contained in this buffer.
878 pub fn local(&self) -> Option
<SocketAddr
> {
879 unsafe { ptrs_to_socket_addr(self.local, self.local_len) }
882 /// Returns the remote socket address contained in this buffer.
883 pub fn remote(&self) -> Option
<SocketAddr
> {
884 unsafe { ptrs_to_socket_addr(self.remote, self.remote_len) }
889 fn get(&self, socket
: SOCKET
) -> io
::Result
<usize> {
890 let prev
= self.val
.load(Ordering
::SeqCst
);
891 if prev
!= 0 && !cfg
!(debug_assertions
) {
894 let mut ret
= 0 as usize;
897 WSAIoctl(socket
, SIO_GET_EXTENSION_FUNCTION_POINTER
,
898 &self.guid
as *const _
as *mut _
,
899 mem
::size_of_val(&self.guid
) as DWORD
,
900 &mut ret
as *mut _
as *mut _
,
901 mem
::size_of_val(&ret
) as DWORD
,
906 debug_assert_eq
!(bytes
as usize, mem
::size_of_val(&ret
));
907 debug_assert
!(prev
== 0 || prev
== ret
);
908 self.val
.store(ret
, Ordering
::SeqCst
);
917 use std
::net
::{TcpListener, UdpSocket, TcpStream, SocketAddr}
;
919 use std
::io
::prelude
::*;
922 use iocp
::CompletionPort
;
923 use net
::{TcpStreamExt, UdpSocketExt, SocketAddrBuf}
;
924 use net
::{TcpBuilderExt, TcpListenerExt, AcceptAddrsBuf}
;
925 use net2
::TcpBuilder
;
927 fn each_ip(f
: &mut FnMut(SocketAddr
)) {
928 f(t
!("127.0.0.1:0".parse()));
929 f(t
!("[::1]:0".parse()));
934 each_ip(&mut |addr
| {
935 let l
= t
!(TcpListener
::bind(addr
));
936 let addr
= t
!(l
.local_addr());
937 let t
= thread
::spawn(move || {
938 let mut a
= t
!(l
.accept()).0;
939 t
!(a
.write_all(&[1, 2, 3]));
942 let cp
= t
!(CompletionPort
::new(1));
943 let s
= t
!(TcpStream
::connect(addr
));
944 t
!(cp
.add_socket(1, &s
));
947 let a
= Overlapped
::zero();
949 t
!(s
.read_overlapped(&mut b
, a
.raw()));
951 let status
= t
!(cp
.get(None
));
952 assert_eq
!(status
.bytes_transferred(), 3);
953 assert_eq
!(status
.token(), 1);
954 assert_eq
!(status
.overlapped(), a
.raw());
955 assert_eq
!(&b
[0..3], &[1, 2, 3]);
963 each_ip(&mut |addr
| {
964 let l
= t
!(TcpListener
::bind(addr
));
965 let addr
= t
!(l
.local_addr());
966 let t
= thread
::spawn(move || {
967 let mut a
= t
!(l
.accept()).0;
969 let n
= t
!(a
.read(&mut b
));
971 assert_eq
!(&b
[0..3], &[1, 2, 3]);
974 let cp
= t
!(CompletionPort
::new(1));
975 let s
= t
!(TcpStream
::connect(addr
));
976 t
!(cp
.add_socket(1, &s
));
979 let a
= Overlapped
::zero();
981 t
!(s
.write_overlapped(&b
, a
.raw()));
983 let status
= t
!(cp
.get(None
));
984 assert_eq
!(status
.bytes_transferred(), 3);
985 assert_eq
!(status
.token(), 1);
986 assert_eq
!(status
.overlapped(), a
.raw());
994 each_ip(&mut |addr_template
| {
995 let l
= t
!(TcpListener
::bind(addr_template
));
996 let addr
= t
!(l
.local_addr());
997 let t
= thread
::spawn(move || {
1001 let cp
= t
!(CompletionPort
::new(1));
1002 let builder
= match addr
{
1003 SocketAddr
::V4(..) => t
!(TcpBuilder
::new_v4()),
1004 SocketAddr
::V6(..) => t
!(TcpBuilder
::new_v6()),
1006 t
!(cp
.add_socket(1, &builder
));
1008 let a
= Overlapped
::zero();
1009 t
!(builder
.bind(addr_template
));
1010 let (s
, _
) = unsafe {
1011 t
!(builder
.connect_overlapped(&addr
, &[], a
.raw()))
1013 let status
= t
!(cp
.get(None
));
1014 assert_eq
!(status
.bytes_transferred(), 0);
1015 assert_eq
!(status
.token(), 1);
1016 assert_eq
!(status
.overlapped(), a
.raw());
1017 t
!(s
.connect_complete());
1024 fn udp_recv_from() {
1025 each_ip(&mut |addr
| {
1026 let a
= t
!(UdpSocket
::bind(addr
));
1027 let b
= t
!(UdpSocket
::bind(addr
));
1028 let a_addr
= t
!(a
.local_addr());
1029 let b_addr
= t
!(b
.local_addr());
1030 let t
= thread
::spawn(move || {
1031 t
!(a
.send_to(&[1, 2, 3], b_addr
));
1034 let cp
= t
!(CompletionPort
::new(1));
1035 t
!(cp
.add_socket(1, &b
));
1037 let mut buf
= [0; 10];
1038 let a
= Overlapped
::zero();
1039 let mut addr
= SocketAddrBuf
::new();
1041 t
!(b
.recv_from_overlapped(&mut buf
, &mut addr
, a
.raw()));
1043 let status
= t
!(cp
.get(None
));
1044 assert_eq
!(status
.bytes_transferred(), 3);
1045 assert_eq
!(status
.token(), 1);
1046 assert_eq
!(status
.overlapped(), a
.raw());
1047 assert_eq
!(&buf
[..3], &[1, 2, 3]);
1048 assert_eq
!(addr
.to_socket_addr(), Some(a_addr
));
1056 each_ip(&mut |addr
| {
1057 let a
= t
!(UdpSocket
::bind(addr
));
1058 let b
= t
!(UdpSocket
::bind(addr
));
1059 let a_addr
= t
!(a
.local_addr());
1060 let b_addr
= t
!(b
.local_addr());
1061 assert
!(b
.connect(a_addr
).is_ok());
1062 assert
!(a
.connect(b_addr
).is_ok());
1063 let t
= thread
::spawn(move || {
1064 t
!(a
.send_to(&[1, 2, 3], b_addr
));
1067 let cp
= t
!(CompletionPort
::new(1));
1068 t
!(cp
.add_socket(1, &b
));
1070 let mut buf
= [0; 10];
1071 let a
= Overlapped
::zero();
1073 t
!(b
.recv_overlapped(&mut buf
, a
.raw()));
1075 let status
= t
!(cp
.get(None
));
1076 assert_eq
!(status
.bytes_transferred(), 3);
1077 assert_eq
!(status
.token(), 1);
1078 assert_eq
!(status
.overlapped(), a
.raw());
1079 assert_eq
!(&buf
[..3], &[1, 2, 3]);
1087 each_ip(&mut |addr
| {
1088 let a
= t
!(UdpSocket
::bind(addr
));
1089 let b
= t
!(UdpSocket
::bind(addr
));
1090 let a_addr
= t
!(a
.local_addr());
1091 let b_addr
= t
!(b
.local_addr());
1092 let t
= thread
::spawn(move || {
1093 let mut b
= [0; 100];
1094 let (n
, addr
) = t
!(a
.recv_from(&mut b
));
1096 assert_eq
!(addr
, b_addr
);
1097 assert_eq
!(&b
[..3], &[1, 2, 3]);
1100 let cp
= t
!(CompletionPort
::new(1));
1101 t
!(cp
.add_socket(1, &b
));
1103 let a
= Overlapped
::zero();
1105 t
!(b
.send_to_overlapped(&[1, 2, 3], &a_addr
, a
.raw()));
1107 let status
= t
!(cp
.get(None
));
1108 assert_eq
!(status
.bytes_transferred(), 3);
1109 assert_eq
!(status
.token(), 1);
1110 assert_eq
!(status
.overlapped(), a
.raw());
1118 each_ip(&mut |addr
| {
1119 let a
= t
!(UdpSocket
::bind(addr
));
1120 let b
= t
!(UdpSocket
::bind(addr
));
1121 let a_addr
= t
!(a
.local_addr());
1122 let b_addr
= t
!(b
.local_addr());
1123 assert
!(b
.connect(a_addr
).is_ok());
1124 assert
!(a
.connect(b_addr
).is_ok());
1125 let t
= thread
::spawn(move || {
1126 let mut b
= [0; 100];
1127 let (n
, addr
) = t
!(a
.recv_from(&mut b
));
1129 assert_eq
!(addr
, b_addr
);
1130 assert_eq
!(&b
[..3], &[1, 2, 3]);
1133 let cp
= t
!(CompletionPort
::new(1));
1134 t
!(cp
.add_socket(1, &b
));
1136 let a
= Overlapped
::zero();
1138 t
!(b
.send_overlapped(&[1, 2, 3], a
.raw()));
1140 let status
= t
!(cp
.get(None
));
1141 assert_eq
!(status
.bytes_transferred(), 3);
1142 assert_eq
!(status
.token(), 1);
1143 assert_eq
!(status
.overlapped(), a
.raw());
1151 each_ip(&mut |addr_template
| {
1152 let l
= t
!(TcpListener
::bind(addr_template
));
1153 let addr
= t
!(l
.local_addr());
1154 let t
= thread
::spawn(move || {
1155 let socket
= t
!(TcpStream
::connect(addr
));
1156 (socket
.local_addr().unwrap(), socket
.peer_addr().unwrap())
1159 let cp
= t
!(CompletionPort
::new(1));
1160 let builder
= match addr
{
1161 SocketAddr
::V4(..) => t
!(TcpBuilder
::new_v4()),
1162 SocketAddr
::V6(..) => t
!(TcpBuilder
::new_v6()),
1164 t
!(cp
.add_socket(1, &l
));
1166 let a
= Overlapped
::zero();
1167 let mut addrs
= AcceptAddrsBuf
::new();
1168 let (s
, _
) = unsafe {
1169 t
!(l
.accept_overlapped(&builder
, &mut addrs
, a
.raw()))
1171 let status
= t
!(cp
.get(None
));
1172 assert_eq
!(status
.bytes_transferred(), 0);
1173 assert_eq
!(status
.token(), 1);
1174 assert_eq
!(status
.overlapped(), a
.raw());
1175 t
!(l
.accept_complete(&s
));
1177 let (remote
, local
) = t
!(t
.join());
1178 let addrs
= addrs
.parse(&l
).unwrap();
1179 assert_eq
!(addrs
.local(), Some(local
));
1180 assert_eq
!(addrs
.remote(), Some(remote
));