1use std::hash::Hash;
2use std::mem::{self, size_of};
3use std::net::{SocketAddr, SocketAddrV4, SocketAddrV6};
4use std::path::Path;
5use std::{fmt, io, ptr};
6
7#[cfg(windows)]
8use windows_sys::Win32::Networking::WinSock::SOCKADDR_IN6_0;
9
10use crate::sys::{c_int, sockaddr_in, sockaddr_in6, sockaddr_storage, AF_INET, AF_INET6, AF_UNIX};
11use crate::Domain;
12
13#[allow(non_camel_case_types)]
15pub type socklen_t = crate::sys::socklen_t;
16
17#[allow(non_camel_case_types)]
19pub type sa_family_t = crate::sys::sa_family_t;
20
21#[repr(transparent)]
29pub struct SockAddrStorage {
30 storage: sockaddr_storage,
31}
32
33impl SockAddrStorage {
34 #[inline]
36 pub fn zeroed() -> Self {
37 unsafe { mem::zeroed() }
39 }
40
41 #[inline]
43 pub fn size_of(&self) -> socklen_t {
44 size_of::<Self>() as socklen_t
45 }
46
47 #[inline]
53 pub unsafe fn view_as<T>(&mut self) -> &mut T {
54 assert!(size_of::<T>() <= size_of::<Self>());
55 &mut *(self as *mut Self as *mut T)
58 }
59}
60
61impl std::fmt::Debug for SockAddrStorage {
62 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
63 f.debug_struct("sockaddr_storage")
64 .field("ss_family", &self.storage.ss_family)
65 .finish_non_exhaustive()
66 }
67}
68
69#[derive(Clone)]
74pub struct SockAddr {
75 storage: sockaddr_storage,
76 len: socklen_t,
77}
78
79#[allow(clippy::len_without_is_empty)]
80impl SockAddr {
81 pub const unsafe fn new(storage: SockAddrStorage, len: socklen_t) -> SockAddr {
126 SockAddr {
127 storage: storage.storage,
128 len: len as socklen_t,
129 }
130 }
131
132 pub unsafe fn try_init<F, T>(init: F) -> io::Result<(T, SockAddr)>
178 where
179 F: FnOnce(*mut SockAddrStorage, *mut socklen_t) -> io::Result<T>,
180 {
181 const STORAGE_SIZE: socklen_t = size_of::<sockaddr_storage>() as socklen_t;
182 let mut storage = SockAddrStorage::zeroed();
188 let mut len = STORAGE_SIZE;
189 init(&mut storage, &mut len).map(|res| {
190 debug_assert!(len <= STORAGE_SIZE, "overflown address storage");
191 (res, SockAddr::new(storage, len))
192 })
193 }
194
195 pub fn unix<P>(path: P) -> io::Result<SockAddr>
199 where
200 P: AsRef<Path>,
201 {
202 crate::sys::unix_sockaddr(path.as_ref())
203 }
204
205 pub unsafe fn set_length(&mut self, length: socklen_t) {
212 self.len = length;
213 }
214
215 pub const fn family(&self) -> sa_family_t {
217 self.storage.ss_family
218 }
219
220 pub const fn domain(&self) -> Domain {
222 Domain(self.storage.ss_family as c_int)
223 }
224
225 pub const fn len(&self) -> socklen_t {
227 self.len
228 }
229
230 pub const fn as_ptr(&self) -> *const SockAddrStorage {
232 &self.storage as *const sockaddr_storage as *const SockAddrStorage
233 }
234
235 pub const fn as_storage(self) -> SockAddrStorage {
237 SockAddrStorage {
238 storage: self.storage,
239 }
240 }
241
242 pub const fn is_ipv4(&self) -> bool {
244 self.storage.ss_family == AF_INET as sa_family_t
245 }
246
247 pub const fn is_ipv6(&self) -> bool {
250 self.storage.ss_family == AF_INET6 as sa_family_t
251 }
252
253 pub fn is_unix(&self) -> bool {
256 self.storage.ss_family == AF_UNIX as sa_family_t
257 }
258
259 pub fn as_socket(&self) -> Option<SocketAddr> {
262 if self.storage.ss_family == AF_INET as sa_family_t {
263 let addr = unsafe { &*(ptr::addr_of!(self.storage).cast::<sockaddr_in>()) };
266 let ip = crate::sys::from_in_addr(addr.sin_addr);
267 let port = u16::from_be(addr.sin_port);
268 Some(SocketAddr::V4(SocketAddrV4::new(ip, port)))
269 } else if self.storage.ss_family == AF_INET6 as sa_family_t {
270 let addr = unsafe { &*(ptr::addr_of!(self.storage).cast::<sockaddr_in6>()) };
273 let ip = crate::sys::from_in6_addr(addr.sin6_addr);
274 let port = u16::from_be(addr.sin6_port);
275 Some(SocketAddr::V6(SocketAddrV6::new(
276 ip,
277 port,
278 addr.sin6_flowinfo,
279 #[cfg(unix)]
280 addr.sin6_scope_id,
281 #[cfg(windows)]
282 unsafe {
283 addr.Anonymous.sin6_scope_id
284 },
285 )))
286 } else {
287 None
288 }
289 }
290
291 pub fn as_socket_ipv4(&self) -> Option<SocketAddrV4> {
294 match self.as_socket() {
295 Some(SocketAddr::V4(addr)) => Some(addr),
296 _ => None,
297 }
298 }
299
300 pub fn as_socket_ipv6(&self) -> Option<SocketAddrV6> {
303 match self.as_socket() {
304 Some(SocketAddr::V6(addr)) => Some(addr),
305 _ => None,
306 }
307 }
308
309 fn as_bytes(&self) -> &[u8] {
311 unsafe { std::slice::from_raw_parts(self.as_ptr().cast(), self.len as usize) }
315 }
316}
317
318impl From<SocketAddr> for SockAddr {
319 fn from(addr: SocketAddr) -> SockAddr {
320 match addr {
321 SocketAddr::V4(addr) => addr.into(),
322 SocketAddr::V6(addr) => addr.into(),
323 }
324 }
325}
326
327impl From<SocketAddrV4> for SockAddr {
328 fn from(addr: SocketAddrV4) -> SockAddr {
329 let mut storage = unsafe { mem::zeroed::<sockaddr_storage>() };
331 let len = {
332 let storage = unsafe { &mut *ptr::addr_of_mut!(storage).cast::<sockaddr_in>() };
333 storage.sin_family = AF_INET as sa_family_t;
334 storage.sin_port = addr.port().to_be();
335 storage.sin_addr = crate::sys::to_in_addr(addr.ip());
336 storage.sin_zero = Default::default();
337 mem::size_of::<sockaddr_in>() as socklen_t
338 };
339 #[cfg(any(
340 target_os = "dragonfly",
341 target_os = "freebsd",
342 target_os = "haiku",
343 target_os = "hermit",
344 target_os = "ios",
345 target_os = "visionos",
346 target_os = "macos",
347 target_os = "netbsd",
348 target_os = "nto",
349 target_os = "openbsd",
350 target_os = "tvos",
351 target_os = "vxworks",
352 target_os = "watchos",
353 ))]
354 {
355 storage.ss_len = len as u8;
356 }
357 SockAddr { storage, len }
358 }
359}
360
361impl From<SocketAddrV6> for SockAddr {
362 fn from(addr: SocketAddrV6) -> SockAddr {
363 let mut storage = unsafe { mem::zeroed::<sockaddr_storage>() };
365 let len = {
366 let storage = unsafe { &mut *ptr::addr_of_mut!(storage).cast::<sockaddr_in6>() };
367 storage.sin6_family = AF_INET6 as sa_family_t;
368 storage.sin6_port = addr.port().to_be();
369 storage.sin6_addr = crate::sys::to_in6_addr(addr.ip());
370 storage.sin6_flowinfo = addr.flowinfo();
371 #[cfg(unix)]
372 {
373 storage.sin6_scope_id = addr.scope_id();
374 }
375 #[cfg(windows)]
376 {
377 storage.Anonymous = SOCKADDR_IN6_0 {
378 sin6_scope_id: addr.scope_id(),
379 };
380 }
381 mem::size_of::<sockaddr_in6>() as socklen_t
382 };
383 #[cfg(any(
384 target_os = "dragonfly",
385 target_os = "freebsd",
386 target_os = "haiku",
387 target_os = "hermit",
388 target_os = "ios",
389 target_os = "visionos",
390 target_os = "macos",
391 target_os = "netbsd",
392 target_os = "nto",
393 target_os = "openbsd",
394 target_os = "tvos",
395 target_os = "vxworks",
396 target_os = "watchos",
397 ))]
398 {
399 storage.ss_len = len as u8;
400 }
401 SockAddr { storage, len }
402 }
403}
404
405impl fmt::Debug for SockAddr {
406 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
407 let mut f = fmt.debug_struct("SockAddr");
408 #[cfg(any(
409 target_os = "dragonfly",
410 target_os = "freebsd",
411 target_os = "haiku",
412 target_os = "hermit",
413 target_os = "ios",
414 target_os = "visionos",
415 target_os = "macos",
416 target_os = "netbsd",
417 target_os = "nto",
418 target_os = "openbsd",
419 target_os = "tvos",
420 target_os = "vxworks",
421 target_os = "watchos",
422 ))]
423 f.field("ss_len", &self.storage.ss_len);
424 f.field("ss_family", &self.storage.ss_family)
425 .field("len", &self.len)
426 .finish()
427 }
428}
429
430impl PartialEq for SockAddr {
431 fn eq(&self, other: &Self) -> bool {
432 self.as_bytes() == other.as_bytes()
433 }
434}
435
436impl Eq for SockAddr {}
437
438impl Hash for SockAddr {
439 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
440 self.as_bytes().hash(state);
441 }
442}
443
444#[cfg(test)]
445mod tests {
446 use super::*;
447
448 #[test]
449 fn ipv4() {
450 use std::net::Ipv4Addr;
451 let std = SocketAddrV4::new(Ipv4Addr::new(1, 2, 3, 4), 9876);
452 let addr = SockAddr::from(std);
453 assert!(addr.is_ipv4());
454 assert!(!addr.is_ipv6());
455 assert!(!addr.is_unix());
456 assert_eq!(addr.family(), AF_INET as sa_family_t);
457 assert_eq!(addr.domain(), Domain::IPV4);
458 assert_eq!(addr.len(), size_of::<sockaddr_in>() as socklen_t);
459 assert_eq!(addr.as_socket(), Some(SocketAddr::V4(std)));
460 assert_eq!(addr.as_socket_ipv4(), Some(std));
461 assert!(addr.as_socket_ipv6().is_none());
462
463 let addr = SockAddr::from(SocketAddr::from(std));
464 assert_eq!(addr.family(), AF_INET as sa_family_t);
465 assert_eq!(addr.len(), size_of::<sockaddr_in>() as socklen_t);
466 assert_eq!(addr.as_socket(), Some(SocketAddr::V4(std)));
467 assert_eq!(addr.as_socket_ipv4(), Some(std));
468 assert!(addr.as_socket_ipv6().is_none());
469 #[cfg(unix)]
470 {
471 assert!(addr.as_pathname().is_none());
472 assert!(addr.as_abstract_namespace().is_none());
473 }
474 }
475
476 #[test]
477 fn ipv6() {
478 use std::net::Ipv6Addr;
479 let std = SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9876, 11, 12);
480 let addr = SockAddr::from(std);
481 assert!(addr.is_ipv6());
482 assert!(!addr.is_ipv4());
483 assert!(!addr.is_unix());
484 assert_eq!(addr.family(), AF_INET6 as sa_family_t);
485 assert_eq!(addr.domain(), Domain::IPV6);
486 assert_eq!(addr.len(), size_of::<sockaddr_in6>() as socklen_t);
487 assert_eq!(addr.as_socket(), Some(SocketAddr::V6(std)));
488 assert!(addr.as_socket_ipv4().is_none());
489 assert_eq!(addr.as_socket_ipv6(), Some(std));
490
491 let addr = SockAddr::from(SocketAddr::from(std));
492 assert_eq!(addr.family(), AF_INET6 as sa_family_t);
493 assert_eq!(addr.len(), size_of::<sockaddr_in6>() as socklen_t);
494 assert_eq!(addr.as_socket(), Some(SocketAddr::V6(std)));
495 assert!(addr.as_socket_ipv4().is_none());
496 assert_eq!(addr.as_socket_ipv6(), Some(std));
497 #[cfg(unix)]
498 {
499 assert!(addr.as_pathname().is_none());
500 assert!(addr.as_abstract_namespace().is_none());
501 }
502 }
503
504 #[test]
505 fn ipv4_eq() {
506 use std::net::Ipv4Addr;
507
508 let std1 = SocketAddrV4::new(Ipv4Addr::new(1, 2, 3, 4), 9876);
509 let std2 = SocketAddrV4::new(Ipv4Addr::new(5, 6, 7, 8), 8765);
510
511 test_eq(
512 SockAddr::from(std1),
513 SockAddr::from(std1),
514 SockAddr::from(std2),
515 );
516 }
517
518 #[test]
519 fn ipv4_hash() {
520 use std::net::Ipv4Addr;
521
522 let std1 = SocketAddrV4::new(Ipv4Addr::new(1, 2, 3, 4), 9876);
523 let std2 = SocketAddrV4::new(Ipv4Addr::new(5, 6, 7, 8), 8765);
524
525 test_hash(
526 SockAddr::from(std1),
527 SockAddr::from(std1),
528 SockAddr::from(std2),
529 );
530 }
531
532 #[test]
533 fn ipv6_eq() {
534 use std::net::Ipv6Addr;
535
536 let std1 = SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9876, 11, 12);
537 let std2 = SocketAddrV6::new(Ipv6Addr::new(3, 4, 5, 6, 7, 8, 9, 0), 7654, 13, 14);
538
539 test_eq(
540 SockAddr::from(std1),
541 SockAddr::from(std1),
542 SockAddr::from(std2),
543 );
544 }
545
546 #[test]
547 fn ipv6_hash() {
548 use std::net::Ipv6Addr;
549
550 let std1 = SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9876, 11, 12);
551 let std2 = SocketAddrV6::new(Ipv6Addr::new(3, 4, 5, 6, 7, 8, 9, 0), 7654, 13, 14);
552
553 test_hash(
554 SockAddr::from(std1),
555 SockAddr::from(std1),
556 SockAddr::from(std2),
557 );
558 }
559
560 #[test]
561 fn ipv4_ipv6_eq() {
562 use std::net::Ipv4Addr;
563 use std::net::Ipv6Addr;
564
565 let std1 = SocketAddrV4::new(Ipv4Addr::new(1, 2, 3, 4), 9876);
566 let std2 = SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9876, 11, 12);
567
568 test_eq(
569 SockAddr::from(std1),
570 SockAddr::from(std1),
571 SockAddr::from(std2),
572 );
573
574 test_eq(
575 SockAddr::from(std2),
576 SockAddr::from(std2),
577 SockAddr::from(std1),
578 );
579 }
580
581 #[test]
582 fn ipv4_ipv6_hash() {
583 use std::net::Ipv4Addr;
584 use std::net::Ipv6Addr;
585
586 let std1 = SocketAddrV4::new(Ipv4Addr::new(1, 2, 3, 4), 9876);
587 let std2 = SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9876, 11, 12);
588
589 test_hash(
590 SockAddr::from(std1),
591 SockAddr::from(std1),
592 SockAddr::from(std2),
593 );
594
595 test_hash(
596 SockAddr::from(std2),
597 SockAddr::from(std2),
598 SockAddr::from(std1),
599 );
600 }
601
602 #[allow(clippy::eq_op)] fn test_eq(a0: SockAddr, a1: SockAddr, b: SockAddr) {
604 assert!(a0 == a0);
605 assert!(a0 == a1);
606 assert!(a1 == a0);
607 assert!(a0 != b);
608 assert!(b != a0);
609 }
610
611 fn test_hash(a0: SockAddr, a1: SockAddr, b: SockAddr) {
612 assert!(calculate_hash(&a0) == calculate_hash(&a0));
613 assert!(calculate_hash(&a0) == calculate_hash(&a1));
614 assert!(calculate_hash(&a0) != calculate_hash(&b));
616 }
617
618 fn calculate_hash(x: &SockAddr) -> u64 {
619 use std::collections::hash_map::DefaultHasher;
620 use std::hash::Hasher;
621
622 let mut hasher = DefaultHasher::new();
623 x.hash(&mut hasher);
624 hasher.finish()
625 }
626}