Skip to main content

openthread/ot/
thread.rs

1// Copyright 2021 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
7/// Iterator type for neighbor info
8#[allow(missing_debug_implementations)]
9pub struct NeighborInfoIterator<'a, T: ?Sized> {
10    ot_instance: &'a T,
11    ot_iter: otNeighborInfoIterator,
12}
13
14impl<T: ?Sized + Thread> Iterator for NeighborInfoIterator<'_, T> {
15    type Item = NeighborInfo;
16    fn next(&mut self) -> Option<Self::Item> {
17        self.ot_instance.iter_next_neighbor_info(&mut self.ot_iter)
18    }
19}
20
21/// Methods from the [OpenThread "Thread General" Module][1].
22///
23/// [1]: https://openthread.io/reference/group/api-thread-general
24pub trait Thread {
25    /// Functional equivalent of
26    /// [`otsys::otThreadBecomeLeader`](crate::otsys::otThreadBecomeLeader).
27    fn become_leader(&self) -> Result;
28
29    /// Functional equivalent of
30    /// [`otsys::otThreadBecomeRouter`](crate::otsys::otThreadBecomeRouter).
31    fn become_router(&self) -> Result;
32
33    /// Functional equivalent of
34    /// [`otsys::otThreadGetChildInfoById`](crate::otsys::otThreadGetChildInfoById).
35    fn get_child_info_by_id(&self, child_id: u16) -> Result<otChildInfo>;
36
37    /// Functional equivalent of
38    /// [`otsys::otThreadGetLeaderData`](crate::otsys::otThreadGetLeaderData).
39    fn get_leader_data(&self) -> Result<LeaderData>;
40
41    /// Functional equivalent of
42    /// [`otsys::otThreadGetLeaderWeight`](crate::otsys::otThreadGetLeaderWeight).
43    fn get_leader_weight(&self) -> u8;
44
45    /// Functional equivalent of
46    /// [`otsys::otThreadGetNetworkKey`](crate::otsys::otThreadGetNetworkKey).
47    #[must_use]
48    fn get_network_key(&self) -> NetworkKey;
49
50    /// Functional equivalent of
51    /// [`otsys::otThreadSetNetworkKey`](crate::otsys::otThreadSetNetworkKey).
52    fn set_network_key(&self, key: &NetworkKey) -> Result;
53
54    /// Similar to [`get_network_name_as_slice`], but returns
55    /// an [`ot::NetworkName`](crate::ot::NetworkName).
56    #[must_use]
57    fn get_network_name(&self) -> NetworkName {
58        NetworkName::try_from_slice(self.get_network_name_as_slice()).unwrap()
59    }
60
61    /// Functional equivalent of
62    /// [`otsys::otThreadGetNetworkName`](crate::otsys::otThreadGetNetworkName).
63    #[must_use]
64    fn get_network_name_as_slice(&self) -> &[u8];
65
66    /// Functional equivalent of
67    /// [`otsys::otThreadSetNetworkName`](crate::otsys::otThreadSetNetworkName).
68    fn set_network_name(&self, name: &NetworkName) -> Result;
69
70    /// Functional equivalent of
71    /// [`otsys::otThreadIsSingleton`](crate::otsys::otThreadIsSingleton).
72    #[must_use]
73    fn is_singleton(&self) -> bool;
74
75    /// Functional equivalent of
76    /// [`otsys::otThreadGetExtendedPanId`](crate::otsys::otThreadGetExtendedPanId).
77    #[must_use]
78    fn get_extended_pan_id(&self) -> &ExtendedPanId;
79
80    /// Functional equivalent of
81    /// [`otsys::otThreadSetExtendedPanId`](crate::otsys::otThreadSetExtendedPanId).
82    fn set_extended_pan_id(&self, xpanid: &ExtendedPanId) -> Result;
83
84    /// Functional equivalent of [`otsys::otThreadSetEnabled`](crate::otsys::otThreadSetEnabled).
85    fn thread_set_enabled(&self, enabled: bool) -> Result;
86
87    /// Functional equivalent of
88    /// [`otsys::otThreadGetDeviceRole`](crate::otsys::otThreadGetDeviceRole).
89    #[must_use]
90    fn get_device_role(&self) -> DeviceRole;
91
92    /// Functional equivalent of
93    /// [`otsys::otThreadGetPartitionId`](crate::otsys::otThreadGetPartitionId).
94    fn get_partition_id(&self) -> u32;
95
96    /// Functional equivalent of [`otsys::otThreadGetRloc16`](crate::otsys::otThreadGetRloc16).
97    fn get_rloc16(&self) -> u16;
98
99    /// Functional equivalent of [`otsys::otThreadGetLinkMode`](crate::otsys::otThreadGetLinkMode).
100    fn get_link_mode(&self) -> ot::LinkModeConfig;
101
102    /// Functional equivalent of [`otsys::otThreadSetLinkMode`](crate::otsys::otThreadSetLinkMode).
103    fn set_link_mode(&self, link_mode_config: ot::LinkModeConfig) -> Result;
104
105    /// Gets the full RLOC address.
106    fn get_rloc(&self) -> std::net::Ipv6Addr;
107
108    /// Functional equivalent of
109    /// [`otsys::otThreadGetMeshLocalEid`](crate::otsys::otThreadGetMeshLocalEid).
110    fn get_mesh_local_eid(&self) -> std::net::Ipv6Addr;
111
112    /// Functional equivalent of
113    /// [`otsys::otThreadGetLinkLocalIp6Address`](crate::otsys::otThreadGetLinkLocalIp6Address).
114    fn get_link_local_addr(&self) -> std::net::Ipv6Addr;
115
116    /// Functional equivalent of
117    /// [`otsys::otThreadGetLinkLocalAllThreadNodesMulticastAddress`](crate::otsys::otThreadGetLinkLocalAllThreadNodesMulticastAddress).
118    fn get_link_local_all_nodes_multicast_addr(&self) -> std::net::Ipv6Addr;
119
120    /// Functional equivalent of
121    /// [`otsys::otThreadGetMeshLocalPrefix`](crate::otsys::otThreadGetMeshLocalPrefix).
122    fn get_mesh_local_prefix(&self) -> &MeshLocalPrefix;
123
124    /// Functional equivalent of
125    /// [`otsys::otThreadGetRouterInfo`](crate::otsys::otThreadGetRouterInfo).
126    fn get_router_info(&self, router_id: u16) -> Result<RouterInfo>;
127
128    /// Functional equivalent of
129    /// [`otsys::otThreadGetMaxRouterId`](crate::otsys::otThreadGetMaxRouterId).
130    fn get_max_router_id(&self) -> u8;
131
132    /// Functional equivalent of
133    /// [`otsys::otThreadGetIp6Counters`](crate::otsys::otThreadGetIp6Counters).
134    fn get_ip6_counters(&self) -> &IpCounters;
135
136    /// Functional equivalent of
137    /// [`otsys::otThreadGetNextNeighborInfo`](crate::otsys::otThreadGetNextNeighborInfo).
138    // TODO: Determine if the underlying implementation of
139    //       this method has undefined behavior when network data
140    //       is being mutated while iterating. If it is undefined,
141    //       we may need to make it unsafe and provide a safe method
142    //       that collects the results.
143    fn iter_next_neighbor_info(&self, ot_iter: &mut otNeighborInfoIterator)
144    -> Option<NeighborInfo>;
145
146    /// Returns an iterator for iterating over external routes.
147    fn iter_neighbor_info(&self) -> NeighborInfoIterator<'_, Self> {
148        NeighborInfoIterator {
149            ot_instance: self,
150            ot_iter: OT_NEIGHBOR_INFO_ITERATOR_INIT.try_into().unwrap(),
151        }
152    }
153}
154
155impl<T: Thread + Boxable> Thread for ot::Box<T> {
156    fn become_leader(&self) -> Result<()> {
157        self.as_ref().become_leader()
158    }
159    fn become_router(&self) -> Result<()> {
160        self.as_ref().become_router()
161    }
162    fn get_child_info_by_id(&self, child_id: u16) -> Result<otChildInfo> {
163        self.as_ref().get_child_info_by_id(child_id)
164    }
165    fn get_leader_data(&self) -> Result<LeaderData> {
166        self.as_ref().get_leader_data()
167    }
168
169    fn get_leader_weight(&self) -> u8 {
170        self.as_ref().get_leader_weight()
171    }
172
173    fn get_network_key(&self) -> NetworkKey {
174        self.as_ref().get_network_key()
175    }
176
177    fn set_network_key(&self, key: &NetworkKey) -> Result {
178        self.as_ref().set_network_key(key)
179    }
180    fn get_network_name_as_slice(&self) -> &[u8] {
181        self.as_ref().get_network_name_as_slice()
182    }
183
184    fn set_network_name(&self, name: &NetworkName) -> Result {
185        self.as_ref().set_network_name(name)
186    }
187
188    fn is_singleton(&self) -> bool {
189        self.as_ref().is_singleton()
190    }
191
192    fn get_extended_pan_id(&self) -> &ExtendedPanId {
193        self.as_ref().get_extended_pan_id()
194    }
195
196    fn set_extended_pan_id(&self, xpanid: &ExtendedPanId) -> Result {
197        self.as_ref().set_extended_pan_id(xpanid)
198    }
199
200    fn thread_set_enabled(&self, enabled: bool) -> Result {
201        self.as_ref().thread_set_enabled(enabled)
202    }
203
204    fn get_device_role(&self) -> DeviceRole {
205        self.as_ref().get_device_role()
206    }
207
208    fn get_partition_id(&self) -> u32 {
209        self.as_ref().get_partition_id()
210    }
211
212    fn get_rloc16(&self) -> u16 {
213        self.as_ref().get_rloc16()
214    }
215
216    fn get_link_mode(&self) -> ot::LinkModeConfig {
217        self.as_ref().get_link_mode()
218    }
219
220    fn set_link_mode(&self, link_mode_config: ot::LinkModeConfig) -> Result {
221        self.as_ref().set_link_mode(link_mode_config)
222    }
223
224    fn get_rloc(&self) -> std::net::Ipv6Addr {
225        self.as_ref().get_rloc()
226    }
227
228    fn get_mesh_local_eid(&self) -> std::net::Ipv6Addr {
229        self.as_ref().get_mesh_local_eid()
230    }
231
232    fn get_link_local_addr(&self) -> std::net::Ipv6Addr {
233        self.as_ref().get_link_local_addr()
234    }
235
236    fn get_link_local_all_nodes_multicast_addr(&self) -> std::net::Ipv6Addr {
237        self.as_ref().get_link_local_all_nodes_multicast_addr()
238    }
239
240    fn get_mesh_local_prefix(&self) -> &MeshLocalPrefix {
241        self.as_ref().get_mesh_local_prefix()
242    }
243
244    fn get_router_info(&self, router_id: u16) -> Result<RouterInfo> {
245        self.as_ref().get_router_info(router_id)
246    }
247
248    fn get_max_router_id(&self) -> u8 {
249        self.as_ref().get_max_router_id()
250    }
251
252    fn get_ip6_counters(&self) -> &IpCounters {
253        self.as_ref().get_ip6_counters()
254    }
255
256    fn iter_next_neighbor_info(
257        &self,
258        ot_iter: &mut otNeighborInfoIterator,
259    ) -> Option<NeighborInfo> {
260        self.as_ref().iter_next_neighbor_info(ot_iter)
261    }
262}
263
264impl Thread for Instance {
265    fn become_leader(&self) -> Result<()> {
266        Error::from(unsafe { otThreadBecomeLeader(self.as_ot_ptr()) }).into()
267    }
268
269    fn become_router(&self) -> Result<()> {
270        Error::from(unsafe { otThreadBecomeRouter(self.as_ot_ptr()) }).into()
271    }
272
273    fn get_child_info_by_id(&self, child_id: u16) -> Result<otChildInfo> {
274        let mut ret: otChildInfo = Default::default();
275        Error::from(unsafe { otThreadGetChildInfoById(self.as_ot_ptr(), child_id, &mut ret) })
276            .into_result()?;
277        Ok(ret)
278    }
279
280    fn get_leader_data(&self) -> Result<LeaderData> {
281        let mut ret = LeaderData::default();
282        Error::from(unsafe { otThreadGetLeaderData(self.as_ot_ptr(), ret.as_ot_mut_ptr()) })
283            .into_result()?;
284        Ok(ret)
285    }
286
287    fn get_leader_weight(&self) -> u8 {
288        unsafe { otThreadGetLeaderWeight(self.as_ot_ptr()) }
289    }
290
291    fn get_network_key(&self) -> NetworkKey {
292        let mut ret = NetworkKey::default();
293        unsafe { otThreadGetNetworkKey(self.as_ot_ptr(), ret.as_ot_mut_ptr()) }
294        ret
295    }
296
297    fn set_network_key(&self, key: &NetworkKey) -> Result {
298        Error::from(unsafe { otThreadSetNetworkKey(self.as_ot_ptr(), key.as_ot_ptr()) })
299            .into_result()
300    }
301
302    #[allow(clippy::unnecessary_cast)]
303    fn get_network_name_as_slice(&self) -> &[u8] {
304        unsafe {
305            let slice = std::slice::from_raw_parts(
306                otThreadGetNetworkName(self.as_ot_ptr()) as *const u8,
307                OT_NETWORK_NAME_MAX_SIZE as usize,
308            );
309            let first_zero_index =
310                slice.iter().position(|&x| x == 0).unwrap_or(OT_NETWORK_NAME_MAX_SIZE as usize);
311            &slice[0..first_zero_index]
312        }
313    }
314
315    fn set_network_name(&self, name: &NetworkName) -> Result {
316        Error::from(unsafe { otThreadSetNetworkName(self.as_ot_ptr(), name.as_c_str()) })
317            .into_result()
318    }
319
320    fn is_singleton(&self) -> bool {
321        unsafe { otThreadIsSingleton(self.as_ot_ptr()) }
322    }
323
324    fn get_extended_pan_id(&self) -> &ExtendedPanId {
325        unsafe {
326            let xpanid = otThreadGetExtendedPanId(self.as_ot_ptr());
327            ExtendedPanId::ref_from_ot_ptr(xpanid)
328        }
329        .unwrap()
330    }
331
332    fn set_extended_pan_id(&self, xpanid: &ExtendedPanId) -> Result {
333        Error::from(unsafe { otThreadSetExtendedPanId(self.as_ot_ptr(), xpanid.as_ot_ptr()) })
334            .into_result()
335    }
336
337    fn thread_set_enabled(&self, enabled: bool) -> Result {
338        Error::from(unsafe { otThreadSetEnabled(self.as_ot_ptr(), enabled) }).into_result()
339    }
340
341    fn get_device_role(&self) -> ot::DeviceRole {
342        unsafe { otThreadGetDeviceRole(self.as_ot_ptr()) }.into()
343    }
344
345    fn get_partition_id(&self) -> u32 {
346        unsafe { otThreadGetPartitionId(self.as_ot_ptr()) }
347    }
348
349    fn get_rloc16(&self) -> u16 {
350        unsafe { otThreadGetRloc16(self.as_ot_ptr()) }
351    }
352
353    fn get_link_mode(&self) -> ot::LinkModeConfig {
354        unsafe { otThreadGetLinkMode(self.as_ot_ptr()) }.into()
355    }
356
357    fn set_link_mode(&self, link_mode_config: ot::LinkModeConfig) -> Result {
358        Error::from(unsafe { otThreadSetLinkMode(self.as_ot_ptr(), link_mode_config.into()) })
359            .into_result()
360    }
361
362    fn get_rloc(&self) -> std::net::Ipv6Addr {
363        std::net::Ipv6Addr::from_ot(unsafe { *otThreadGetRloc(self.as_ot_ptr()) })
364    }
365
366    fn get_mesh_local_eid(&self) -> std::net::Ipv6Addr {
367        std::net::Ipv6Addr::from_ot(unsafe { *otThreadGetMeshLocalEid(self.as_ot_ptr()) })
368    }
369
370    fn get_link_local_addr(&self) -> std::net::Ipv6Addr {
371        std::net::Ipv6Addr::from_ot(unsafe { *otThreadGetLinkLocalIp6Address(self.as_ot_ptr()) })
372    }
373
374    fn get_link_local_all_nodes_multicast_addr(&self) -> std::net::Ipv6Addr {
375        std::net::Ipv6Addr::from_ot(unsafe {
376            *otThreadGetLinkLocalAllThreadNodesMulticastAddress(self.as_ot_ptr())
377        })
378    }
379
380    fn get_mesh_local_prefix(&self) -> &MeshLocalPrefix {
381        unsafe { MeshLocalPrefix::ref_from_ot_ptr(otThreadGetMeshLocalPrefix(self.as_ot_ptr())) }
382            .unwrap()
383    }
384
385    fn get_router_info(&self, router_id: u16) -> Result<RouterInfo> {
386        let mut ret = RouterInfo::default();
387        Error::from(unsafe {
388            otThreadGetRouterInfo(self.as_ot_ptr(), router_id, ret.as_ot_mut_ptr())
389        })
390        .into_result()?;
391        Ok(ret)
392    }
393
394    fn get_max_router_id(&self) -> u8 {
395        unsafe { otThreadGetMaxRouterId(self.as_ot_ptr()) }
396    }
397
398    fn get_ip6_counters(&self) -> &IpCounters {
399        unsafe { IpCounters::ref_from_ot_ptr(otThreadGetIp6Counters(self.as_ot_ptr())) }.unwrap()
400    }
401
402    fn iter_next_neighbor_info(
403        &self,
404        ot_iter: &mut otNeighborInfoIterator,
405    ) -> Option<NeighborInfo> {
406        unsafe {
407            let mut ret = NeighborInfo::default();
408            match Error::from(otThreadGetNextNeighborInfo(
409                self.as_ot_ptr(),
410                ot_iter as *mut otNeighborInfoIterator,
411                ret.as_ot_mut_ptr(),
412            )) {
413                Error::NotFound => None,
414                Error::None => Some(ret),
415                err => unreachable!("Unexpected error from otThreadGetNextNeighborInfo: {:?}", err),
416            }
417        }
418    }
419}