Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/third_party/rust/rustix/src/net/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 5 kB image not shown  

Quelle  addr.rs

  Sprache: Rust
 

//! Types for implementers of socket address types or code that is generic over
//! address types.
//!
//! The concrete address types and [`SocketAddrAny`] are in
//! [the parent module][`super`].

#![allow(unsafe_code)]
use core::mem::{size_of, MaybeUninit};
use core::ptr;

use crate::backend::net::write_sockaddr::{encode_sockaddr_v4, encode_sockaddr_v6};
use crate::utils::as_ptr;

use super::{SocketAddr, SocketAddrAny, SocketAddrV4, SocketAddrV6};

pub use crate::backend::net::addr::SocketAddrStorage;

#[cfg(unix)]
use super::SocketAddrUnix;

/// Opaque type equivalent to `sockaddr` in C.
///
/// This is always used behind a raw pointer that is cast from a pointer to a
/// `sockaddr`-compatible C type, and then cast back to a `sockaddr` pointer to
/// be passed to a system call.
#[repr(C)]
pub struct SocketAddrOpaque {
    _data: [u8; 0],
}

/// A type for the length of a socket address.
///
/// This type will always be big enough to hold any socket address, but never
/// bigger than `usize`.
#[doc(alias = "socklen_t")]
pub type SocketAddrLen = u32;

/// A trait abstracting over the types that can be passed as a `sockaddr`.
///
/// # Safety
///
/// Implementers of this trait must ensure that `with_sockaddr` calls `f` with
/// a pointer that is readable for the passed length, and points to data that
/// is a valid socket address for the system calls that accept `sockaddr` as a
/// const pointer.
pub unsafe trait SocketAddrArg {
    /// Call a closure with the pointer and length to the corresponding C type.
    ///
    /// The memory pointed to by the pointer of size length is guaranteed to be
    /// valid only for the duration of the call.
    ///
    /// The API uses a closure so that:
    ///  - The libc types are not exposed in the rustix API.
    ///  - Types like `SocketAddrUnix` that contain their corresponding C type
    ///    can pass it directly without a copy.
    ///  - Other socket types can construct their C-compatible struct on the
    ///    stack and call the closure with a pointer to it.
    ///
    /// # Safety
    ///
    /// For `f` to use its pointer argument, it'll contain an `unsafe` block.
    /// The caller of `with_sockaddr` here is responsible for ensuring that the
    /// safety condition for that `unsafe` block is satisfied by the guarantee
    /// that `with_sockaddr` here provides.
    unsafe fn with_sockaddr<R>(
        &self,
        f: impl FnOnce(*const SocketAddrOpaque, SocketAddrLen) -> R,
    ) -> R;

    /// Convert to `SocketAddrAny`.
    fn as_any(&self) -> SocketAddrAny {
        let mut storage = MaybeUninit::<SocketAddrStorage>::uninit();
        // SAFETY: We've allocated `storage` here, we're writing to it, and
        // we're using the number of bytes written.
        unsafe {
            let len = self.write_sockaddr(storage.as_mut_ptr());
            SocketAddrAny::new(storage, len)
        }
    }

    /// Encode an address into a `SocketAddrStorage`.
    ///
    /// Returns the number of bytes that were written.
    ///
    /// For a safe interface to this functionality, use [`as_any`].
    ///
    /// [`as_any`]: Self::as_any
    ///
    /// # Safety
    ///
    /// `storage` must be valid to write up to `size_of<SocketAddrStorage>()`
    /// bytes to.
    unsafe fn write_sockaddr(&self, storage: *mut SocketAddrStorage) -> SocketAddrLen {
        // The closure dereferences exactly `len` bytes at `ptr`.
        self.with_sockaddr(|ptr, len| {
            ptr::copy_nonoverlapping(ptr.cast::<u8>(), storage.cast::<u8>(), len as usize);
            len
        })
    }
}

/// Helper for implementing `SocketAddrArg::with_sockaddr`.
///
/// # Safety
///
/// This calls `f` with a pointer to an object it has a reference to, with the
/// and the length of that object, so they'll be valid for the duration of the
/// call.
pub(crateunsafe fn call_with_sockaddr<A, R>(
    addr: &A,
    f: impl FnOnce(*const SocketAddrOpaque, SocketAddrLen) -> R,
) -> R {
    let ptr = as_ptr(addr).cast();
    let len = size_of::<A>() as SocketAddrLen;
    f(ptr, len)
}

// SAFETY: This just forwards to the inner `SocketAddrArg` implementations.
unsafe impl SocketAddrArg for SocketAddr {
    unsafe fn with_sockaddr<R>(
        &self,
        f: impl FnOnce(*const SocketAddrOpaque, SocketAddrLen) -> R,
    ) -> R {
        match self {
            Self::V4(v4) => v4.with_sockaddr(f),
            Self::V6(v6) => v6.with_sockaddr(f),
        }
    }
}

// SAFETY: `with_sockaddr` calls `f` using `call_with_sockaddr`, which handles
// calling `f` with the needed preconditions.
unsafe impl SocketAddrArg for SocketAddrV4 {
    unsafe fn with_sockaddr<R>(
        &self,
        f: impl FnOnce(*const SocketAddrOpaque, SocketAddrLen) -> R,
    ) -> R {
        call_with_sockaddr(&encode_sockaddr_v4(self), f)
    }
}

// SAFETY: `with_sockaddr` calls `f` using `call_with_sockaddr`, which handles
// calling `f` with the needed preconditions.
unsafe impl SocketAddrArg for SocketAddrV6 {
    unsafe fn with_sockaddr<R>(
        &self,
        f: impl FnOnce(*const SocketAddrOpaque, SocketAddrLen) -> R,
    ) -> R {
        call_with_sockaddr(&encode_sockaddr_v6(self), f)
    }
}

#[cfg(unix)]
// SAFETY: `with_sockaddr` calls `f` using `call_with_sockaddr`, which handles
// calling `f` with the needed preconditions.
unsafe impl SocketAddrArg for SocketAddrUnix {
    unsafe fn with_sockaddr<R>(
        &self,
        f: impl FnOnce(*const SocketAddrOpaque, SocketAddrLen) -> R,
    ) -> R {
        f(as_ptr(&self.unix).cast(), self.addr_len())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::backend::c;

    #[test]
    fn test_layouts() {
        assert_eq_size!(SocketAddrLen, c::socklen_t);

        #[cfg(not(any(windows, target_os = "redox")))]
        assert_eq!(
            memoffset::span_of!(c::msghdr, msg_namelen).len(),
            size_of::<SocketAddrLen>()
        );

        assert!(size_of::<SocketAddrLen>() <= size_of::<usize>());
    }
}

Messung V0.5 in Prozent
C=62 H=73 G=67

¤ Dauer der Verarbeitung: 0.13 Sekunden  (vorverarbeitet am  2026-08-25) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.