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]
70 pub unsafe fn view_as<T>(&mut self) -> &mut T {
71 assert!(size_of::<T>() <= size_of::<Self>());
72 &mut *(self as *mut Self as *mut T)
75 }
76}
77
78impl std::fmt::Debug for SockAddrStorage {
79 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
80 f.debug_struct("sockaddr_storage")
81 .field("ss_family", &self.storage.ss_family)
82 .finish_non_exhaustive()
83 }
84}
85
86#[derive(Clone)]
91pub struct SockAddr {
92 storage: sockaddr_storage,
93 len: socklen_t,
94}
95
96#[allow(clippy::len_without_is_empty)]
97impl SockAddr {
98 pub const unsafe fn new(storage: SockAddrStorage, len: socklen_t) -> SockAddr {
143 SockAddr {
144 storage: storage.storage,
145 len: len as socklen_t,
146 }
147 }
148
149 pub unsafe fn try_init<F, T>(init: F) -> io::Result<(T, SockAddr)>
195 where
196 F: FnOnce(*mut SockAddrStorage, *mut socklen_t) -> io::Result<T>,
197 {
198 const STORAGE_SIZE: socklen_t = size_of::<sockaddr_storage>() as socklen_t;
199 let mut storage = SockAddrStorage::zeroed();
205 let mut len = STORAGE_SIZE;
206 init(&mut storage, &mut len).map(|res| {
207 debug_assert!(len <= STORAGE_SIZE, "overflown address storage");
208 (res, SockAddr::new(storage, len))
209 })
210 }
211
212 pub fn unix<P>(path: P) -> io::Result<SockAddr>
216 where
217 P: AsRef<Path>,
218 {
219 crate::sys::unix_sockaddr(path.as_ref())
220 }
221
222 pub unsafe fn set_length(&mut self, length: socklen_t) {
229 self.len = length;
230 }
231
232 pub const fn family(&self) -> sa_family_t {
234 self.storage.ss_family
235 }
236
237 pub const fn domain(&self) -> Domain {
239 Domain(self.storage.ss_family as c_int)
240 }
241
242 pub const fn len(&self) -> socklen_t {
244 self.len
245 }
246
247 pub const fn as_ptr(&self) -> *const SockAddrStorage {
249 &self.storage as *const sockaddr_storage as *const SockAddrStorage
250 }
251
252 pub const fn as_storage(self) -> SockAddrStorage {
254 SockAddrStorage {
255 storage: self.storage,
256 }
257 }
258
259 pub const fn is_ipv4(&self) -> bool {
261 self.storage.ss_family == AF_INET as sa_family_t
262 }
263
264 pub const fn is_ipv6(&self) -> bool {
267 self.storage.ss_family == AF_INET6 as sa_family_t
268 }
269
270 pub fn is_unix(&self) -> bool {
273 self.storage.ss_family == AF_UNIX as sa_family_t
274 }
275
276 pub fn as_socket(&self) -> Option<SocketAddr> {
279 if self.storage.ss_family == AF_INET as sa_family_t {
280 let addr = unsafe { &*(ptr::addr_of!(self.storage).cast::<sockaddr_in>()) };
283 let ip = crate::sys::from_in_addr(addr.sin_addr);
284 let port = u16::from_be(addr.sin_port);
285 Some(SocketAddr::V4(SocketAddrV4::new(ip, port)))
286 } else if self.storage.ss_family == AF_INET6 as sa_family_t {
287 let addr = unsafe { &*(ptr::addr_of!(self.storage).cast::<sockaddr_in6>()) };
290 let ip = crate::sys::from_in6_addr(addr.sin6_addr);
291 let port = u16::from_be(addr.sin6_port);
292 Some(SocketAddr::V6(SocketAddrV6::new(
293 ip,
294 port,
295 addr.sin6_flowinfo,
296 #[cfg(unix)]
297 addr.sin6_scope_id,
298 #[cfg(windows)]
299 unsafe {
300 addr.Anonymous.sin6_scope_id
301 },
302 )))
303 } else {
304 None
305 }
306 }
307
308 pub fn as_socket_ipv4(&self) -> Option<SocketAddrV4> {
311 match self.as_socket() {
312 Some(SocketAddr::V4(addr)) => Some(addr),
313 _ => None,
314 }
315 }
316
317 pub fn as_socket_ipv6(&self) -> Option<SocketAddrV6> {
320 match self.as_socket() {
321 Some(SocketAddr::V6(addr)) => Some(addr),
322 _ => None,
323 }
324 }
325
326 fn as_bytes(&self) -> &[u8] {
328 unsafe { std::slice::from_raw_parts(self.as_ptr().cast(), self.len as usize) }
332 }
333}
334
335impl From<SocketAddr> for SockAddr {
336 fn from(addr: SocketAddr) -> SockAddr {
337 match addr {
338 SocketAddr::V4(addr) => addr.into(),
339 SocketAddr::V6(addr) => addr.into(),
340 }
341 }
342}
343
344impl From<SocketAddrV4> for SockAddr {
345 fn from(addr: SocketAddrV4) -> SockAddr {
346 let mut storage = unsafe { mem::zeroed::<sockaddr_storage>() };
348 let len = {
349 let storage = unsafe { &mut *ptr::addr_of_mut!(storage).cast::<sockaddr_in>() };
350 storage.sin_family = AF_INET as sa_family_t;
351 storage.sin_port = addr.port().to_be();
352 storage.sin_addr = crate::sys::to_in_addr(addr.ip());
353 storage.sin_zero = Default::default();
354 mem::size_of::<sockaddr_in>() as socklen_t
355 };
356 #[cfg(any(
357 target_os = "dragonfly",
358 target_os = "freebsd",
359 target_os = "haiku",
360 target_os = "hermit",
361 target_os = "ios",
362 target_os = "visionos",
363 target_os = "macos",
364 target_os = "netbsd",
365 target_os = "nto",
366 target_os = "openbsd",
367 target_os = "tvos",
368 target_os = "vxworks",
369 target_os = "watchos",
370 ))]
371 {
372 storage.ss_len = len as u8;
373 }
374 SockAddr { storage, len }
375 }
376}
377
378impl From<SocketAddrV6> for SockAddr {
379 fn from(addr: SocketAddrV6) -> SockAddr {
380 let mut storage = unsafe { mem::zeroed::<sockaddr_storage>() };
382 let len = {
383 let storage = unsafe { &mut *ptr::addr_of_mut!(storage).cast::<sockaddr_in6>() };
384 storage.sin6_family = AF_INET6 as sa_family_t;
385 storage.sin6_port = addr.port().to_be();
386 storage.sin6_addr = crate::sys::to_in6_addr(addr.ip());
387 storage.sin6_flowinfo = addr.flowinfo();
388 #[cfg(unix)]
389 {
390 storage.sin6_scope_id = addr.scope_id();
391 }
392 #[cfg(windows)]
393 {
394 storage.Anonymous = SOCKADDR_IN6_0 {
395 sin6_scope_id: addr.scope_id(),
396 };
397 }
398 mem::size_of::<sockaddr_in6>() as socklen_t
399 };
400 #[cfg(any(
401 target_os = "dragonfly",
402 target_os = "freebsd",
403 target_os = "haiku",
404 target_os = "hermit",
405 target_os = "ios",
406 target_os = "visionos",
407 target_os = "macos",
408 target_os = "netbsd",
409 target_os = "nto",
410 target_os = "openbsd",
411 target_os = "tvos",
412 target_os = "vxworks",
413 target_os = "watchos",
414 ))]
415 {
416 storage.ss_len = len as u8;
417 }
418 SockAddr { storage, len }
419 }
420}
421
422impl fmt::Debug for SockAddr {
423 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
424 let mut f = fmt.debug_struct("SockAddr");
425 #[cfg(any(
426 target_os = "dragonfly",
427 target_os = "freebsd",
428 target_os = "haiku",
429 target_os = "hermit",
430 target_os = "ios",
431 target_os = "visionos",
432 target_os = "macos",
433 target_os = "netbsd",
434 target_os = "nto",
435 target_os = "openbsd",
436 target_os = "tvos",
437 target_os = "vxworks",
438 target_os = "watchos",
439 ))]
440 f.field("ss_len", &self.storage.ss_len);
441 f.field("ss_family", &self.storage.ss_family)
442 .field("len", &self.len)
443 .finish()
444 }
445}
446
447impl PartialEq for SockAddr {
448 fn eq(&self, other: &Self) -> bool {
449 self.as_bytes() == other.as_bytes()
450 }
451}
452
453impl Eq for SockAddr {}
454
455impl Hash for SockAddr {
456 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
457 self.as_bytes().hash(state);
458 }
459}
460
461#[cfg(test)]
462mod tests {
463 use super::*;
464
465 #[test]
466 fn ipv4() {
467 use std::net::Ipv4Addr;
468 let std = SocketAddrV4::new(Ipv4Addr::new(1, 2, 3, 4), 9876);
469 let addr = SockAddr::from(std);
470 assert!(addr.is_ipv4());
471 assert!(!addr.is_ipv6());
472 assert!(!addr.is_unix());
473 assert_eq!(addr.family(), AF_INET as sa_family_t);
474 assert_eq!(addr.domain(), Domain::IPV4);
475 assert_eq!(addr.len(), size_of::<sockaddr_in>() as socklen_t);
476 assert_eq!(addr.as_socket(), Some(SocketAddr::V4(std)));
477 assert_eq!(addr.as_socket_ipv4(), Some(std));
478 assert!(addr.as_socket_ipv6().is_none());
479
480 let addr = SockAddr::from(SocketAddr::from(std));
481 assert_eq!(addr.family(), AF_INET as sa_family_t);
482 assert_eq!(addr.len(), size_of::<sockaddr_in>() as socklen_t);
483 assert_eq!(addr.as_socket(), Some(SocketAddr::V4(std)));
484 assert_eq!(addr.as_socket_ipv4(), Some(std));
485 assert!(addr.as_socket_ipv6().is_none());
486 #[cfg(unix)]
487 {
488 assert!(addr.as_pathname().is_none());
489 assert!(addr.as_abstract_namespace().is_none());
490 }
491 }
492
493 #[test]
494 fn ipv6() {
495 use std::net::Ipv6Addr;
496 let std = SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9876, 11, 12);
497 let addr = SockAddr::from(std);
498 assert!(addr.is_ipv6());
499 assert!(!addr.is_ipv4());
500 assert!(!addr.is_unix());
501 assert_eq!(addr.family(), AF_INET6 as sa_family_t);
502 assert_eq!(addr.domain(), Domain::IPV6);
503 assert_eq!(addr.len(), size_of::<sockaddr_in6>() as socklen_t);
504 assert_eq!(addr.as_socket(), Some(SocketAddr::V6(std)));
505 assert!(addr.as_socket_ipv4().is_none());
506 assert_eq!(addr.as_socket_ipv6(), Some(std));
507
508 let addr = SockAddr::from(SocketAddr::from(std));
509 assert_eq!(addr.family(), AF_INET6 as sa_family_t);
510 assert_eq!(addr.len(), size_of::<sockaddr_in6>() as socklen_t);
511 assert_eq!(addr.as_socket(), Some(SocketAddr::V6(std)));
512 assert!(addr.as_socket_ipv4().is_none());
513 assert_eq!(addr.as_socket_ipv6(), Some(std));
514 #[cfg(unix)]
515 {
516 assert!(addr.as_pathname().is_none());
517 assert!(addr.as_abstract_namespace().is_none());
518 }
519 }
520
521 #[test]
522 fn ipv4_eq() {
523 use std::net::Ipv4Addr;
524
525 let std1 = SocketAddrV4::new(Ipv4Addr::new(1, 2, 3, 4), 9876);
526 let std2 = SocketAddrV4::new(Ipv4Addr::new(5, 6, 7, 8), 8765);
527
528 test_eq(
529 SockAddr::from(std1),
530 SockAddr::from(std1),
531 SockAddr::from(std2),
532 );
533 }
534
535 #[test]
536 fn ipv4_hash() {
537 use std::net::Ipv4Addr;
538
539 let std1 = SocketAddrV4::new(Ipv4Addr::new(1, 2, 3, 4), 9876);
540 let std2 = SocketAddrV4::new(Ipv4Addr::new(5, 6, 7, 8), 8765);
541
542 test_hash(
543 SockAddr::from(std1),
544 SockAddr::from(std1),
545 SockAddr::from(std2),
546 );
547 }
548
549 #[test]
550 fn ipv6_eq() {
551 use std::net::Ipv6Addr;
552
553 let std1 = SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9876, 11, 12);
554 let std2 = SocketAddrV6::new(Ipv6Addr::new(3, 4, 5, 6, 7, 8, 9, 0), 7654, 13, 14);
555
556 test_eq(
557 SockAddr::from(std1),
558 SockAddr::from(std1),
559 SockAddr::from(std2),
560 );
561 }
562
563 #[test]
564 fn ipv6_hash() {
565 use std::net::Ipv6Addr;
566
567 let std1 = SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9876, 11, 12);
568 let std2 = SocketAddrV6::new(Ipv6Addr::new(3, 4, 5, 6, 7, 8, 9, 0), 7654, 13, 14);
569
570 test_hash(
571 SockAddr::from(std1),
572 SockAddr::from(std1),
573 SockAddr::from(std2),
574 );
575 }
576
577 #[test]
578 fn ipv4_ipv6_eq() {
579 use std::net::Ipv4Addr;
580 use std::net::Ipv6Addr;
581
582 let std1 = SocketAddrV4::new(Ipv4Addr::new(1, 2, 3, 4), 9876);
583 let std2 = SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9876, 11, 12);
584
585 test_eq(
586 SockAddr::from(std1),
587 SockAddr::from(std1),
588 SockAddr::from(std2),
589 );
590
591 test_eq(
592 SockAddr::from(std2),
593 SockAddr::from(std2),
594 SockAddr::from(std1),
595 );
596 }
597
598 #[test]
599 fn ipv4_ipv6_hash() {
600 use std::net::Ipv4Addr;
601 use std::net::Ipv6Addr;
602
603 let std1 = SocketAddrV4::new(Ipv4Addr::new(1, 2, 3, 4), 9876);
604 let std2 = SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9876, 11, 12);
605
606 test_hash(
607 SockAddr::from(std1),
608 SockAddr::from(std1),
609 SockAddr::from(std2),
610 );
611
612 test_hash(
613 SockAddr::from(std2),
614 SockAddr::from(std2),
615 SockAddr::from(std1),
616 );
617 }
618
619 #[allow(clippy::eq_op)] fn test_eq(a0: SockAddr, a1: SockAddr, b: SockAddr) {
621 assert!(a0 == a0);
622 assert!(a0 == a1);
623 assert!(a1 == a0);
624 assert!(a0 != b);
625 assert!(b != a0);
626 }
627
628 fn test_hash(a0: SockAddr, a1: SockAddr, b: SockAddr) {
629 assert!(calculate_hash(&a0) == calculate_hash(&a0));
630 assert!(calculate_hash(&a0) == calculate_hash(&a1));
631 assert!(calculate_hash(&a0) != calculate_hash(&b));
633 }
634
635 fn calculate_hash(x: &SockAddr) -> u64 {
636 use std::collections::hash_map::DefaultHasher;
637 use std::hash::Hasher;
638
639 let mut hasher = DefaultHasher::new();
640 x.hash(&mut hasher);
641 hasher.finish()
642 }
643}