]> git.proxmox.com Git - rustc.git/blame - vendor/miow/src/net.rs
New upstream version 1.67.1+dfsg1
[rustc.git] / vendor / miow / src / net.rs
CommitLineData
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
6use crate::{FALSE, TRUE};
7use std::cmp;
8use std::io;
9use std::mem;
10use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6};
11use std::net::{SocketAddr, TcpListener, TcpStream, UdpSocket};
12use std::os::windows::io::AsRawSocket;
13use std::sync::atomic::{AtomicUsize, Ordering};
14
15use windows_sys::core::GUID;
16use 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};
22use 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)]
30pub 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)]
42pub 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`.
53pub 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
61struct WsaExtension {
62 guid: GUID,
63 val: AtomicUsize,
64}
65
66/// Additional methods for the `TcpStream` type in the standard library.
67pub 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.
201pub 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.
360pub 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)]
424trait NetInt {
425 fn from_be(i: Self) -> Self;
426 fn to_be(&self) -> Self;
427}
428macro_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}
434doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }
435
436// fn hton<I: NetInt>(i: I) -> I { i.to_be() }
437fn ntoh<I: NetInt>(i: I) -> I {
438 I::from_be(i)
439}
440
441fn 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
450fn 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)]
463pub(crate) union SocketAddrCRepr {
464 v4: SOCKADDR_IN,
465 v6: SOCKADDR_IN6,
466}
467
468impl SocketAddrCRepr {
469 pub(crate) fn as_ptr(&self) -> *const SOCKADDR {
470 self as *const _ as *const SOCKADDR
471 }
472}
473
474fn 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
514unsafe 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
555unsafe 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
562unsafe 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
573impl 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
662unsafe 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
700impl 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
791impl 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
857impl 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
881static 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
891impl 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
942impl<'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
954impl 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)]
989mod 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}