rice_c/
lib.rs

1// Copyright (C) 2025 Matthew Waters <matthew@centricular.com>
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9#![deny(missing_debug_implementations)]
10//#![deny(missing_docs)]
11
12use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
13
14pub mod ffi;
15
16pub mod agent;
17pub mod candidate;
18pub mod component;
19pub mod stream;
20
21/// Prelude module.
22pub mod prelude {
23    pub use crate::candidate::CandidateApi;
24}
25
26/// A network address.
27pub struct Address {
28    ffi: *mut crate::ffi::RiceAddress,
29}
30
31unsafe impl Send for Address {}
32unsafe impl Sync for Address {}
33
34impl core::fmt::Debug for Address {
35    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36        if self.ffi.is_null() {
37            f.debug_struct("Address").field("ffi", &self.ffi).finish()
38        } else {
39            f.debug_struct("Address")
40                .field("ffi", &self.ffi)
41                .field("value", &self.as_socket())
42                .finish()
43        }
44    }
45}
46
47impl Clone for Address {
48    fn clone(&self) -> Self {
49        Self {
50            ffi: unsafe { crate::ffi::rice_address_copy(self.ffi) },
51        }
52    }
53}
54
55impl Drop for Address {
56    fn drop(&mut self) {
57        unsafe { crate::ffi::rice_address_free(self.ffi) }
58    }
59}
60
61impl Address {
62    pub(crate) fn as_c(&self) -> *mut crate::ffi::RiceAddress {
63        self.ffi
64    }
65
66    pub(crate) fn into_c_full(self) -> *mut crate::ffi::RiceAddress {
67        let ret = self.ffi;
68        core::mem::forget(self);
69        ret
70    }
71
72    pub(crate) fn from_c_none(ffi: *const crate::ffi::RiceAddress) -> Self {
73        Self {
74            ffi: unsafe { crate::ffi::rice_address_copy(ffi) },
75        }
76    }
77
78    pub(crate) fn from_c_full(ffi: *mut crate::ffi::RiceAddress) -> Self {
79        Self { ffi }
80    }
81
82    /// Convert this [`Address`] into a `SocketAddr`.
83    pub fn as_socket(&self) -> SocketAddr {
84        self.into()
85    }
86}
87
88impl From<SocketAddr> for Address {
89    fn from(addr: SocketAddr) -> Self {
90        match addr.ip() {
91            IpAddr::V4(v4) => Self {
92                ffi: unsafe {
93                    crate::ffi::rice_address_new_from_bytes(
94                        crate::ffi::RICE_ADDRESS_FAMILY_IPV4,
95                        v4.octets().as_ptr(),
96                        addr.port(),
97                    )
98                },
99            },
100            IpAddr::V6(v6) => Self {
101                ffi: unsafe {
102                    crate::ffi::rice_address_new_from_bytes(
103                        crate::ffi::RICE_ADDRESS_FAMILY_IPV6,
104                        v6.octets().as_ptr(),
105                        addr.port(),
106                    )
107                },
108            },
109        }
110    }
111}
112
113impl From<&Address> for SocketAddr {
114    fn from(value: &Address) -> Self {
115        unsafe {
116            let port = crate::ffi::rice_address_get_port(value.ffi);
117            let ip = match crate::ffi::rice_address_get_family(value.ffi) {
118                crate::ffi::RICE_ADDRESS_FAMILY_IPV4 => {
119                    let mut octets = [0; 4];
120                    crate::ffi::rice_address_get_address_bytes(value.ffi, octets.as_mut_ptr());
121                    IpAddr::V4(Ipv4Addr::from(octets))
122                }
123                crate::ffi::RICE_ADDRESS_FAMILY_IPV6 => {
124                    let mut octets = [0; 16];
125                    crate::ffi::rice_address_get_address_bytes(value.ffi, octets.as_mut_ptr());
126                    IpAddr::V6(Ipv6Addr::from(octets))
127                }
128                val => panic!("Unknown address family value {val:x?}"),
129            };
130            SocketAddr::new(ip, port)
131        }
132    }
133}
134
135impl std::str::FromStr for Address {
136    type Err = std::net::AddrParseError;
137
138    fn from_str(s: &str) -> Result<Self, Self::Err> {
139        let addr: SocketAddr = s.parse()?;
140        Ok(Self::from(addr))
141    }
142}
143
144impl PartialEq<Address> for Address {
145    fn eq(&self, other: &Address) -> bool {
146        unsafe { crate::ffi::rice_address_cmp(self.ffi, other.ffi) == 0 }
147    }
148}
149
150fn mut_override<T>(val: *const T) -> *mut T {
151    val as *mut T
152}
153
154fn const_override<T>(val: *mut T) -> *const T {
155    val as *const T
156}
157
158#[cfg(test)]
159pub(crate) mod tests {
160    use tracing::subscriber::DefaultGuard;
161    use tracing_subscriber::layer::SubscriberExt;
162    use tracing_subscriber::Layer;
163
164    use super::*;
165
166    pub fn test_init_log() -> DefaultGuard {
167        let level_filter = std::env::var("RICE_LOG")
168            .or(std::env::var("RUST_LOG"))
169            .ok()
170            .and_then(|var| var.parse::<tracing_subscriber::filter::Targets>().ok())
171            .unwrap_or(
172                tracing_subscriber::filter::Targets::new().with_default(tracing::Level::TRACE),
173            );
174        let registry = tracing_subscriber::registry().with(
175            tracing_subscriber::fmt::layer()
176                .with_file(true)
177                .with_line_number(true)
178                .with_level(true)
179                .with_target(false)
180                .with_test_writer()
181                .with_filter(level_filter),
182        );
183        tracing::subscriber::set_default(registry)
184    }
185}