|
1 | 1 | use std::io;
|
2 | 2 | use std::mem::size_of;
|
3 |
| -use std::net::{self, SocketAddr, SocketAddrV4, SocketAddrV6}; |
| 3 | +use std::net::{self, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; |
4 | 4 | use std::time::Duration;
|
5 | 5 | use std::convert::TryInto;
|
6 | 6 | use std::os::windows::io::FromRawSocket;
|
7 | 7 | use std::os::windows::raw::SOCKET as StdSocket; // winapi uses usize, stdlib uses u32/u64.
|
8 | 8 |
|
9 | 9 | use winapi::ctypes::{c_char, c_int, c_ushort};
|
10 |
| -use winapi::shared::ws2def::{SOCKADDR_STORAGE, AF_INET, SOCKADDR_IN}; |
| 10 | +use winapi::shared::ws2def::{SOCKADDR_STORAGE, AF_INET, AF_INET6, SOCKADDR_IN}; |
11 | 11 | use winapi::shared::ws2ipdef::SOCKADDR_IN6_LH;
|
12 | 12 |
|
13 | 13 | use winapi::shared::minwindef::{BOOL, TRUE, FALSE};
|
@@ -108,28 +108,33 @@ pub(crate) fn get_reuseaddr(socket: TcpSocket) -> io::Result<bool> {
|
108 | 108 | }
|
109 | 109 |
|
110 | 110 | pub(crate) fn get_localaddr(socket: TcpSocket) -> io::Result<SocketAddr> {
|
111 |
| - let mut addr: SOCKADDR_STORAGE = unsafe { std::mem::zeroed() }; |
112 |
| - let mut length = std::mem::size_of_val(&addr) as c_int; |
| 111 | + let mut storage: SOCKADDR_STORAGE = unsafe { std::mem::zeroed() }; |
| 112 | + let mut length = std::mem::size_of_val(&storage) as c_int; |
113 | 113 |
|
114 | 114 | match unsafe { getsockname(
|
115 | 115 | socket,
|
116 |
| - &mut addr as *mut _ as *mut _, |
| 116 | + &mut storage as *mut _ as *mut _, |
117 | 117 | &mut length
|
118 | 118 | ) } {
|
119 | 119 | SOCKET_ERROR => Err(io::Error::last_os_error()),
|
120 | 120 | _ => {
|
121 |
| - let storage: *const SOCKADDR_STORAGE = (&addr) as *const _; |
122 |
| - if addr.ss_family as c_int == AF_INET { |
123 |
| - let sock_addr : SocketAddrV4 = unsafe { *(storage as *const SOCKADDR_IN as *const _) }; |
124 |
| - Ok(sock_addr.into()) |
| 121 | + if storage.ss_family as c_int == AF_INET { |
| 122 | + let addr: &SOCKADDR_IN = unsafe { &*(&storage as *const _ as *const SOCKADDR_IN) }; |
| 123 | + let ip_bytes = unsafe { addr.sin_addr.S_un.S_un_b() }; |
| 124 | + let ip = Ipv4Addr::from([ip_bytes.s_b1, ip_bytes.s_b2, ip_bytes.s_b3, ip_bytes.s_b4]); |
| 125 | + let port = u16::from_be(addr.sin_port); |
| 126 | + Ok(SocketAddr::V4(SocketAddrV4::new(ip, port))) |
| 127 | + } else if storage.ss_family as c_int == AF_INET6 { |
| 128 | + let addr: &SOCKADDR_IN6_LH = unsafe { &*(&storage as *const _ as *const SOCKADDR_IN6_LH) }; |
| 129 | + let ip = Ipv6Addr::from(*unsafe { addr.sin6_addr.u.Byte() }); |
| 130 | + let port = u16::from_be(addr.sin6_port); |
| 131 | + let scope_id = unsafe { *addr.u.sin6_scope_id() }; |
| 132 | + Ok(SocketAddr::V6(SocketAddrV6::new(ip, port, addr.sin6_flowinfo, scope_id))) |
125 | 133 | } else {
|
126 |
| - let sock_addr : SocketAddrV6 = unsafe { *(storage as *const SOCKADDR_IN6_LH as *const _) }; |
127 |
| - Ok(sock_addr.into()) |
| 134 | + panic!("Invalid ss_family"); |
128 | 135 | }
|
129 | 136 | },
|
130 | 137 | }
|
131 |
| - |
132 |
| - |
133 | 138 | }
|
134 | 139 |
|
135 | 140 | pub(crate) fn set_linger(socket: TcpSocket, dur: Option<Duration>) -> io::Result<()> {
|
|
0 commit comments