Skip to content

Commit 666f5bd

Browse files
committed
Introduce a RawSocketAddr type
It wraps SockAddrStorage, but includes a length, for when a sockaddr has to be stored for a longer lifetime.
1 parent 22e9043 commit 666f5bd

File tree

3 files changed

+63
-1
lines changed

3 files changed

+63
-1
lines changed

src/net/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pub use crate::maybe_polyfill::net::{
2525
};
2626
pub use send_recv::*;
2727
pub use socket::*;
28-
pub use socket_addr_any::{SocketAddrAny, SocketAddrStorage};
28+
pub use socket_addr_any::{RawSocketAddr, SocketAddrAny, SocketAddrStorage};
2929
#[cfg(not(any(windows, target_os = "wasi")))]
3030
pub use socketpair::socketpair;
3131
pub use types::*;

src/net/socket_addr_any.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use crate::net::xdp::SocketAddrXdp;
1414
#[cfg(unix)]
1515
use crate::net::SocketAddrUnix;
1616
use crate::net::{AddressFamily, SocketAddr, SocketAddrV4, SocketAddrV6};
17+
use crate::utils::{as_mut_ptr, as_ptr};
1718
use crate::{backend, io};
1819
#[cfg(feature = "std")]
1920
use core::fmt;
@@ -83,6 +84,23 @@ impl SocketAddrAny {
8384
}
8485
}
8586

87+
/// Creates a platform-specific encoding of this socket address,
88+
/// and returns it.
89+
pub fn to_raw(&self) -> RawSocketAddr {
90+
let mut raw = RawSocketAddr {
91+
storage: unsafe { std::mem::zeroed() },
92+
len: 0,
93+
};
94+
95+
raw.len = unsafe { self.write(raw.as_mut_ptr()) };
96+
raw
97+
}
98+
99+
/// Reads a platform-specific encoding of a socket address.
100+
pub fn from_raw(raw: RawSocketAddr) -> io::Result<Self> {
101+
unsafe { Self::read(raw.as_ptr(), raw.len) }
102+
}
103+
86104
/// Writes a platform-specific encoding of this socket address to
87105
/// the memory pointed to by `storage`, and returns the number of
88106
/// bytes used.
@@ -107,6 +125,35 @@ impl SocketAddrAny {
107125
}
108126
}
109127

128+
/// A raw sockaddr and its length.
129+
#[repr(C)]
130+
pub struct RawSocketAddr {
131+
pub(crate) storage: SocketAddrStorage,
132+
pub(crate) len: usize,
133+
}
134+
135+
impl RawSocketAddr {
136+
/// Creates a raw encoded sockaddr from the given address.
137+
pub fn new(addr: impl Into<SocketAddrAny>) -> Self {
138+
addr.into().to_raw()
139+
}
140+
141+
/// Returns a raw pointer to the sockaddr.
142+
pub fn as_ptr(&self) -> *const SocketAddrStorage {
143+
as_ptr(&self.storage)
144+
}
145+
146+
/// Returns a raw mutable pointer to the sockaddr.
147+
pub fn as_mut_ptr(&mut self) -> *mut SocketAddrStorage {
148+
as_mut_ptr(&mut self.storage)
149+
}
150+
151+
/// Returns the length of the encoded sockaddr.
152+
pub fn namelen(&self) -> usize {
153+
self.len
154+
}
155+
}
156+
110157
#[cfg(feature = "std")]
111158
impl fmt::Debug for SocketAddrAny {
112159
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {

tests/net/addr.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,34 @@ fn encode_decode() {
1313
let decoded = SocketAddrAny::read(encoded.as_ptr(), len).unwrap();
1414
assert_eq!(decoded, SocketAddrAny::V4(orig));
1515

16+
let orig = SocketAddrV4::new(Ipv4Addr::new(2, 3, 5, 6), 33);
17+
let encoded = SocketAddrAny::V4(orig).to_raw();
18+
let decoded = SocketAddrAny::from_raw(encoded).unwrap();
19+
assert_eq!(decoded, SocketAddrAny::V4(orig));
20+
1621
let orig = SocketAddrV6::new(Ipv6Addr::new(2, 3, 5, 6, 8, 9, 11, 12), 33, 34, 36);
1722
let mut encoded = std::mem::MaybeUninit::<SocketAddrStorage>::uninit();
1823
let len = SocketAddrAny::V6(orig).write(encoded.as_mut_ptr());
1924
let decoded = SocketAddrAny::read(encoded.as_ptr(), len).unwrap();
2025
assert_eq!(decoded, SocketAddrAny::V6(orig));
2126

27+
let orig = SocketAddrV6::new(Ipv6Addr::new(2, 3, 5, 6, 8, 9, 11, 12), 33, 34, 36);
28+
let encoded = SocketAddrAny::V6(orig).to_raw();
29+
let decoded = SocketAddrAny::from_raw(encoded).unwrap();
30+
assert_eq!(decoded, SocketAddrAny::V6(orig));
31+
2232
#[cfg(not(windows))]
2333
{
2434
let orig = SocketAddrUnix::new("/path/to/socket").unwrap();
2535
let mut encoded = std::mem::MaybeUninit::<SocketAddrStorage>::uninit();
2636
let len = SocketAddrAny::Unix(orig.clone()).write(encoded.as_mut_ptr());
2737
let decoded = SocketAddrAny::read(encoded.as_ptr(), len).unwrap();
2838
assert_eq!(decoded, SocketAddrAny::Unix(orig));
39+
40+
let orig = SocketAddrUnix::new("/path/to/socket").unwrap();
41+
let encoded = SocketAddrAny::Unix(orig.clone()).to_raw();
42+
let decoded = SocketAddrAny::from_raw(encoded).unwrap();
43+
assert_eq!(decoded, SocketAddrAny::Unix(orig));
2944
}
3045
}
3146
}

0 commit comments

Comments
 (0)