Skip to main content

openthread/ot/
trel.rs

1// Copyright 2022 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::prelude_internal::*;
6
7use core::fmt::{Debug, Formatter};
8
9/// DNS-SD Service Name for TREL
10pub const TREL_DNSSD_SERVICE_NAME: &str = "_trel._udp";
11
12/// DNS-SD Service Name for TREL, with a dot at the end.
13pub const TREL_DNSSD_SERVICE_NAME_WITH_DOT: &str = "_trel._udp.";
14
15/// Iterator type for iterating over TREL peer table entries.
16#[allow(missing_debug_implementations)]
17pub struct TrelPeerIterator<'a, T: ?Sized> {
18    ot_instance: &'a T,
19    ot_iter: otTrelPeerIterator,
20}
21
22impl<T: ?Sized + Trel> Iterator for TrelPeerIterator<'_, T> {
23    type Item = TrelPeer;
24    fn next(&mut self) -> Option<Self::Item> {
25        self.ot_instance.iter_next_trel_peer(&mut self.ot_iter)
26    }
27}
28
29/// This structure represents a Thread TREL Peer.
30///
31/// Functional equivalent of [`otsys::otTrelPeer`](crate::otsys::otTrelPeer).
32#[derive(Default, Clone)]
33#[repr(transparent)]
34pub struct TrelPeer(pub otTrelPeer);
35
36impl_ot_castable!(TrelPeer, otTrelPeer);
37
38impl Debug for TrelPeer {
39    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
40        f.debug_struct("TrelPeer")
41            .field("ext_address", &self.ext_address())
42            .field("ext_pan_id", &self.ext_pan_id())
43            .field("sock_addr", &self.sock_address())
44            .finish()
45    }
46}
47
48impl TrelPeer {
49    /// Returns the Extended MAC Address of TREL peer.
50    pub fn ext_address(&self) -> ExtAddress {
51        self.0.mExtAddress.into()
52    }
53
54    /// Returns the Extended PAN Identifier of TREL peer.
55    pub fn ext_pan_id(&self) -> ExtendedPanId {
56        self.0.mExtPanId.into()
57    }
58
59    /// Returns the IPv6 socket address of TREL peer.
60    pub fn sock_address(&self) -> SockAddr {
61        SockAddr::from_ot(self.0.mSockAddr)
62    }
63}
64
65/// Methods from the [OpenThread TREL Module][1].
66///
67/// [1]: https://openthread.io/reference/group/api-trel
68pub trait Trel {
69    /// Enables or disables TREL operation.
70    fn trel_set_enabled(&self, enabled: bool);
71
72    /// Returns true if TREL is enabled.
73    fn trel_is_enabled(&self) -> bool;
74
75    /// Return all the TREL counters
76    fn trel_get_counters(&self) -> Option<&TrelCounters>;
77
78    /// Reset TREL counters
79    fn trel_reset_counters(&self);
80
81    /// Return the count of TREL peer
82    fn trel_get_number_of_peers(&self) -> u16;
83
84    /// Functional equivalent of [`otsys::otTrelInitPeerIterator`]
85    /// (crate::otsys::otTrelInitPeerIterator).
86    fn trel_init_peer_iterator(&self, iter: &mut otTrelPeerIterator);
87
88    /// Get the trel peer iterator instance.
89    fn trel_peer_get_iterator(&self) -> TrelPeerIterator<'_, Self> {
90        let mut ot_iter = otTrelPeerIterator::default();
91        self.trel_init_peer_iterator(&mut ot_iter);
92        TrelPeerIterator { ot_instance: self, ot_iter }
93    }
94
95    /// Functional equivalent of
96    /// [`otsys::otTrelGetNextPeer`](crate::otsys::otTrelGetNextPeer).
97    fn iter_next_trel_peer(&self, ot_iter: &mut otTrelPeerIterator) -> Option<TrelPeer>;
98}
99
100impl<T: Trel + Boxable> Trel for ot::Box<T> {
101    fn trel_set_enabled(&self, enabled: bool) {
102        self.as_ref().trel_set_enabled(enabled);
103    }
104
105    fn trel_is_enabled(&self) -> bool {
106        self.as_ref().trel_is_enabled()
107    }
108
109    fn trel_get_counters(&self) -> Option<&TrelCounters> {
110        self.as_ref().trel_get_counters()
111    }
112
113    fn trel_reset_counters(&self) {
114        self.as_ref().trel_reset_counters()
115    }
116
117    fn trel_get_number_of_peers(&self) -> u16 {
118        self.as_ref().trel_get_number_of_peers()
119    }
120
121    fn trel_init_peer_iterator(&self, iter: &mut otTrelPeerIterator) {
122        self.as_ref().trel_init_peer_iterator(iter)
123    }
124
125    fn iter_next_trel_peer(&self, ot_iter: &mut otTrelPeerIterator) -> Option<TrelPeer> {
126        self.as_ref().iter_next_trel_peer(ot_iter)
127    }
128}
129
130impl Trel for Instance {
131    fn trel_set_enabled(&self, enabled: bool) {
132        unsafe { otTrelSetEnabled(self.as_ot_ptr(), enabled) }
133    }
134
135    fn trel_is_enabled(&self) -> bool {
136        unsafe { otTrelIsEnabled(self.as_ot_ptr()) }
137    }
138
139    fn trel_get_counters(&self) -> Option<&TrelCounters> {
140        unsafe { TrelCounters::ref_from_ot_ptr(otTrelGetCounters(self.as_ot_ptr())) }
141    }
142
143    fn trel_reset_counters(&self) {
144        unsafe { otTrelResetCounters(self.as_ot_ptr()) }
145    }
146
147    fn trel_get_number_of_peers(&self) -> u16 {
148        unsafe { otTrelGetNumberOfPeers(self.as_ot_ptr()) }
149    }
150
151    fn trel_init_peer_iterator(&self, iter: &mut otTrelPeerIterator) {
152        unsafe { otTrelInitPeerIterator(self.as_ot_ptr(), iter) }
153    }
154
155    fn iter_next_trel_peer(&self, ot_iter: &mut otTrelPeerIterator) -> Option<TrelPeer> {
156        unsafe {
157            let peer_ptr = otTrelGetNextPeer(self.as_ot_ptr(), ot_iter as *mut otTrelPeerIterator);
158
159            peer_ptr.as_ref().map(|raw| TrelPeer(*raw))
160        }
161    }
162}
163
164/// Functional equivalent of [`otsys::otPlatTrelPeerInfo`](crate::otsys::otPlatTrelPeerInfo).
165#[derive(Clone)]
166#[repr(transparent)]
167pub struct PlatTrelPeerInfo<'a>(
168    otPlatTrelPeerInfo,
169    PhantomData<*mut otMessage>,
170    PhantomData<&'a ()>,
171);
172impl_ot_castable!(
173    lifetime
174    PlatTrelPeerInfo<'_>,
175    otPlatTrelPeerInfo,
176    PhantomData,
177    PhantomData
178);
179
180impl std::fmt::Debug for PlatTrelPeerInfo<'_> {
181    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
182        f.debug_struct("PlatTrelPeerInfo")
183            .field("removed", &self.is_removed())
184            .field("txt", &self.txt_escaped())
185            .field("sockaddr", &self.sockaddr())
186            .finish()
187    }
188}
189
190impl<'a> PlatTrelPeerInfo<'a> {
191    /// Creates a new instance of `PlatTrelPeerInfo`.
192    pub fn new(removed: bool, txt: &[u8], sockaddr: ot::SockAddr) -> PlatTrelPeerInfo<'_> {
193        PlatTrelPeerInfo::from_ot(otPlatTrelPeerInfo {
194            mRemoved: removed,
195            mTxtData: txt.as_ptr(),
196            mTxtLength: txt.len().try_into().unwrap(),
197            mSockAddr: sockaddr.into_ot(),
198        })
199    }
200
201    /// Returns true if this peer is being removed.
202    pub fn is_removed(&self) -> bool {
203        self.0.mRemoved
204    }
205
206    /// Returns the raw value of the TXT field.
207    pub fn txt(&self) -> &'a [u8] {
208        unsafe { core::slice::from_raw_parts(self.0.mTxtData, self.0.mTxtLength.into()) }
209    }
210
211    /// Returns the TXT field as an escaped ASCII string.
212    pub fn txt_escaped(&self) -> String {
213        self.txt()
214            .iter()
215            .map(Clone::clone)
216            .flat_map(std::ascii::escape_default)
217            .map(char::from)
218            .collect::<String>()
219    }
220
221    /// Returns the SockAddr for this peer.
222    pub fn sockaddr(&self) -> SockAddr {
223        SockAddr::from_ot(self.0.mSockAddr)
224    }
225}
226
227/// Platform methods from the [OpenThread TREL Module][1].
228///
229/// [1]: https://openthread.io/reference/group/plat-trel
230pub trait PlatTrel {
231    /// This function is a callback from platform to notify of a received TREL UDP packet.
232    fn plat_trel_handle_received(&self, packet: &[u8], sock_addr: &ot::SockAddr);
233
234    /// This is a callback function from platform layer to report a discovered TREL peer info.
235    fn plat_trel_handle_discovered_peer_info(&self, peer_info: &PlatTrelPeerInfo<'_>);
236}
237
238impl<T: PlatTrel + Boxable> PlatTrel for ot::Box<T> {
239    fn plat_trel_handle_received(&self, packet: &[u8], sock_addr: &ot::SockAddr) {
240        self.as_ref().plat_trel_handle_received(packet, sock_addr);
241    }
242
243    fn plat_trel_handle_discovered_peer_info(&self, peer_info: &PlatTrelPeerInfo<'_>) {
244        self.as_ref().plat_trel_handle_discovered_peer_info(peer_info);
245    }
246}
247
248impl PlatTrel for Instance {
249    fn plat_trel_handle_received(&self, packet: &[u8], sock_addr: &ot::SockAddr) {
250        unsafe {
251            otPlatTrelHandleReceived(
252                self.as_ot_ptr(),
253                // TODO(https://fxbug.dev/42175496): Make sure they won't actually mutate.
254                packet.as_ptr() as *mut u8,
255                packet.len().try_into().unwrap(),
256                sock_addr.as_ot_ptr(),
257            )
258        }
259    }
260
261    fn plat_trel_handle_discovered_peer_info(&self, peer_info: &PlatTrelPeerInfo<'_>) {
262        unsafe { otPlatTrelHandleDiscoveredPeerInfo(self.as_ot_ptr(), peer_info.as_ot_ptr()) }
263    }
264}