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    /// Functional equivalent of
155    /// [`otsys::otThreadSetVendorName`](crate::otsys::otThreadSetVendorName).
156    fn set_vendor_name(&self, name: &str) -> Result;
157
158    /// Functional equivalent of
159    /// [`otsys::otThreadSetVendorModel`](crate::otsys::otThreadSetVendorModel).
160    fn set_vendor_model(&self, model: &str) -> Result;
161
162    /// Functional equivalent of
163    /// [`otsys::otThreadSetVendorSwVersion`](crate::otsys::otThreadSetVendorSwVersion).
164    fn set_vendor_sw_version(&self, version: &str) -> Result;
165
166    /// Functional equivalent of
167    /// [`otsys::otThreadGetMleCounters`](crate::otsys::otThreadGetMleCounters).
168    fn get_mle_counters(&self) -> &MleCounters;
169}
170
171impl<T: Thread + Boxable> Thread for ot::Box<T> {
172    fn become_leader(&self) -> Result<()> {
173        self.as_ref().become_leader()
174    }
175    fn become_router(&self) -> Result<()> {
176        self.as_ref().become_router()
177    }
178    fn get_child_info_by_id(&self, child_id: u16) -> Result<otChildInfo> {
179        self.as_ref().get_child_info_by_id(child_id)
180    }
181    fn get_leader_data(&self) -> Result<LeaderData> {
182        self.as_ref().get_leader_data()
183    }
184
185    fn get_leader_weight(&self) -> u8 {
186        self.as_ref().get_leader_weight()
187    }
188
189    fn get_network_key(&self) -> NetworkKey {
190        self.as_ref().get_network_key()
191    }
192
193    fn set_network_key(&self, key: &NetworkKey) -> Result {
194        self.as_ref().set_network_key(key)
195    }
196    fn get_network_name_as_slice(&self) -> &[u8] {
197        self.as_ref().get_network_name_as_slice()
198    }
199
200    fn set_network_name(&self, name: &NetworkName) -> Result {
201        self.as_ref().set_network_name(name)
202    }
203
204    fn is_singleton(&self) -> bool {
205        self.as_ref().is_singleton()
206    }
207
208    fn get_extended_pan_id(&self) -> &ExtendedPanId {
209        self.as_ref().get_extended_pan_id()
210    }
211
212    fn set_extended_pan_id(&self, xpanid: &ExtendedPanId) -> Result {
213        self.as_ref().set_extended_pan_id(xpanid)
214    }
215
216    fn thread_set_enabled(&self, enabled: bool) -> Result {
217        self.as_ref().thread_set_enabled(enabled)
218    }
219
220    fn get_device_role(&self) -> DeviceRole {
221        self.as_ref().get_device_role()
222    }
223
224    fn get_partition_id(&self) -> u32 {
225        self.as_ref().get_partition_id()
226    }
227
228    fn get_rloc16(&self) -> u16 {
229        self.as_ref().get_rloc16()
230    }
231
232    fn get_link_mode(&self) -> ot::LinkModeConfig {
233        self.as_ref().get_link_mode()
234    }
235
236    fn set_link_mode(&self, link_mode_config: ot::LinkModeConfig) -> Result {
237        self.as_ref().set_link_mode(link_mode_config)
238    }
239
240    fn get_rloc(&self) -> std::net::Ipv6Addr {
241        self.as_ref().get_rloc()
242    }
243
244    fn get_mesh_local_eid(&self) -> std::net::Ipv6Addr {
245        self.as_ref().get_mesh_local_eid()
246    }
247
248    fn get_link_local_addr(&self) -> std::net::Ipv6Addr {
249        self.as_ref().get_link_local_addr()
250    }
251
252    fn get_link_local_all_nodes_multicast_addr(&self) -> std::net::Ipv6Addr {
253        self.as_ref().get_link_local_all_nodes_multicast_addr()
254    }
255
256    fn get_mesh_local_prefix(&self) -> &MeshLocalPrefix {
257        self.as_ref().get_mesh_local_prefix()
258    }
259
260    fn get_router_info(&self, router_id: u16) -> Result<RouterInfo> {
261        self.as_ref().get_router_info(router_id)
262    }
263
264    fn get_max_router_id(&self) -> u8 {
265        self.as_ref().get_max_router_id()
266    }
267
268    fn get_ip6_counters(&self) -> &IpCounters {
269        self.as_ref().get_ip6_counters()
270    }
271
272    fn iter_next_neighbor_info(
273        &self,
274        ot_iter: &mut otNeighborInfoIterator,
275    ) -> Option<NeighborInfo> {
276        self.as_ref().iter_next_neighbor_info(ot_iter)
277    }
278
279    fn set_vendor_name(&self, name: &str) -> Result {
280        self.as_ref().set_vendor_name(name)
281    }
282
283    fn set_vendor_model(&self, model: &str) -> Result {
284        self.as_ref().set_vendor_model(model)
285    }
286
287    fn set_vendor_sw_version(&self, version: &str) -> Result {
288        self.as_ref().set_vendor_sw_version(version)
289    }
290
291    fn get_mle_counters(&self) -> &MleCounters {
292        self.as_ref().get_mle_counters()
293    }
294}
295
296impl Thread for Instance {
297    fn become_leader(&self) -> Result<()> {
298        Error::from(unsafe { otThreadBecomeLeader(self.as_ot_ptr()) }).into()
299    }
300
301    fn become_router(&self) -> Result<()> {
302        Error::from(unsafe { otThreadBecomeRouter(self.as_ot_ptr()) }).into()
303    }
304
305    fn get_child_info_by_id(&self, child_id: u16) -> Result<otChildInfo> {
306        let mut ret: otChildInfo = Default::default();
307        Error::from(unsafe { otThreadGetChildInfoById(self.as_ot_ptr(), child_id, &mut ret) })
308            .into_result()?;
309        Ok(ret)
310    }
311
312    fn get_leader_data(&self) -> Result<LeaderData> {
313        let mut ret = LeaderData::default();
314        Error::from(unsafe { otThreadGetLeaderData(self.as_ot_ptr(), ret.as_ot_mut_ptr()) })
315            .into_result()?;
316        Ok(ret)
317    }
318
319    fn get_leader_weight(&self) -> u8 {
320        unsafe { otThreadGetLeaderWeight(self.as_ot_ptr()) }
321    }
322
323    fn get_network_key(&self) -> NetworkKey {
324        let mut ret = NetworkKey::default();
325        unsafe { otThreadGetNetworkKey(self.as_ot_ptr(), ret.as_ot_mut_ptr()) }
326        ret
327    }
328
329    fn set_network_key(&self, key: &NetworkKey) -> Result {
330        Error::from(unsafe { otThreadSetNetworkKey(self.as_ot_ptr(), key.as_ot_ptr()) })
331            .into_result()
332    }
333
334    #[allow(clippy::unnecessary_cast)]
335    fn get_network_name_as_slice(&self) -> &[u8] {
336        unsafe {
337            let slice = std::slice::from_raw_parts(
338                otThreadGetNetworkName(self.as_ot_ptr()) as *const u8,
339                OT_NETWORK_NAME_MAX_SIZE as usize,
340            );
341            let first_zero_index =
342                slice.iter().position(|&x| x == 0).unwrap_or(OT_NETWORK_NAME_MAX_SIZE as usize);
343            &slice[0..first_zero_index]
344        }
345    }
346
347    fn set_network_name(&self, name: &NetworkName) -> Result {
348        Error::from(unsafe { otThreadSetNetworkName(self.as_ot_ptr(), name.as_c_str()) })
349            .into_result()
350    }
351
352    fn is_singleton(&self) -> bool {
353        unsafe { otThreadIsSingleton(self.as_ot_ptr()) }
354    }
355
356    fn get_extended_pan_id(&self) -> &ExtendedPanId {
357        unsafe {
358            let xpanid = otThreadGetExtendedPanId(self.as_ot_ptr());
359            ExtendedPanId::ref_from_ot_ptr(xpanid)
360        }
361        .unwrap()
362    }
363
364    fn set_extended_pan_id(&self, xpanid: &ExtendedPanId) -> Result {
365        Error::from(unsafe { otThreadSetExtendedPanId(self.as_ot_ptr(), xpanid.as_ot_ptr()) })
366            .into_result()
367    }
368
369    fn thread_set_enabled(&self, enabled: bool) -> Result {
370        Error::from(unsafe { otThreadSetEnabled(self.as_ot_ptr(), enabled) }).into_result()
371    }
372
373    fn get_device_role(&self) -> ot::DeviceRole {
374        unsafe { otThreadGetDeviceRole(self.as_ot_ptr()) }.into()
375    }
376
377    fn get_partition_id(&self) -> u32 {
378        unsafe { otThreadGetPartitionId(self.as_ot_ptr()) }
379    }
380
381    fn get_rloc16(&self) -> u16 {
382        unsafe { otThreadGetRloc16(self.as_ot_ptr()) }
383    }
384
385    fn get_link_mode(&self) -> ot::LinkModeConfig {
386        unsafe { otThreadGetLinkMode(self.as_ot_ptr()) }.into()
387    }
388
389    fn set_link_mode(&self, link_mode_config: ot::LinkModeConfig) -> Result {
390        Error::from(unsafe { otThreadSetLinkMode(self.as_ot_ptr(), link_mode_config.into()) })
391            .into_result()
392    }
393
394    fn get_rloc(&self) -> std::net::Ipv6Addr {
395        std::net::Ipv6Addr::from_ot(unsafe { *otThreadGetRloc(self.as_ot_ptr()) })
396    }
397
398    fn get_mesh_local_eid(&self) -> std::net::Ipv6Addr {
399        std::net::Ipv6Addr::from_ot(unsafe { *otThreadGetMeshLocalEid(self.as_ot_ptr()) })
400    }
401
402    fn get_link_local_addr(&self) -> std::net::Ipv6Addr {
403        std::net::Ipv6Addr::from_ot(unsafe { *otThreadGetLinkLocalIp6Address(self.as_ot_ptr()) })
404    }
405
406    fn get_link_local_all_nodes_multicast_addr(&self) -> std::net::Ipv6Addr {
407        std::net::Ipv6Addr::from_ot(unsafe {
408            *otThreadGetLinkLocalAllThreadNodesMulticastAddress(self.as_ot_ptr())
409        })
410    }
411
412    fn get_mesh_local_prefix(&self) -> &MeshLocalPrefix {
413        unsafe { MeshLocalPrefix::ref_from_ot_ptr(otThreadGetMeshLocalPrefix(self.as_ot_ptr())) }
414            .unwrap()
415    }
416
417    fn get_router_info(&self, router_id: u16) -> Result<RouterInfo> {
418        let mut ret = RouterInfo::default();
419        Error::from(unsafe {
420            otThreadGetRouterInfo(self.as_ot_ptr(), router_id, ret.as_ot_mut_ptr())
421        })
422        .into_result()?;
423        Ok(ret)
424    }
425
426    fn get_max_router_id(&self) -> u8 {
427        unsafe { otThreadGetMaxRouterId(self.as_ot_ptr()) }
428    }
429
430    fn get_ip6_counters(&self) -> &IpCounters {
431        unsafe { IpCounters::ref_from_ot_ptr(otThreadGetIp6Counters(self.as_ot_ptr())) }.unwrap()
432    }
433
434    fn iter_next_neighbor_info(
435        &self,
436        ot_iter: &mut otNeighborInfoIterator,
437    ) -> Option<NeighborInfo> {
438        unsafe {
439            let mut ret = NeighborInfo::default();
440            match Error::from(otThreadGetNextNeighborInfo(
441                self.as_ot_ptr(),
442                ot_iter as *mut otNeighborInfoIterator,
443                ret.as_ot_mut_ptr(),
444            )) {
445                Error::NotFound => None,
446                Error::None => Some(ret),
447                err => unreachable!("Unexpected error from otThreadGetNextNeighborInfo: {:?}", err),
448            }
449        }
450    }
451
452    fn set_vendor_name(&self, name: &str) -> Result {
453        let vendor_name = CString::new(name).expect("Vendor name must not contain null bytes");
454        Error::from(unsafe {
455            otThreadSetVendorName(
456                self.as_ot_ptr(),
457                vendor_name.as_ptr() as *const ::std::os::raw::c_char,
458            )
459        })
460        .into_result()
461    }
462
463    fn set_vendor_model(&self, model: &str) -> Result {
464        let vendor_model = CString::new(model).expect("Vendor model must not contain null bytes");
465        Error::from(unsafe {
466            otThreadSetVendorModel(
467                self.as_ot_ptr(),
468                vendor_model.as_ptr() as *const ::std::os::raw::c_char,
469            )
470        })
471        .into_result()
472    }
473
474    fn set_vendor_sw_version(&self, version: &str) -> Result {
475        let vendor_sw_version =
476            CString::new(version).expect("Vendor SW Version must not contain null bytes");
477        Error::from(unsafe {
478            otThreadSetVendorSwVersion(
479                self.as_ot_ptr(),
480                vendor_sw_version.as_ptr() as *const ::std::os::raw::c_char,
481            )
482        })
483        .into_result()
484    }
485
486    fn get_mle_counters(&self) -> &MleCounters {
487        unsafe { MleCounters::ref_from_ot_ptr(otThreadGetMleCounters(self.as_ot_ptr())) }.unwrap()
488    }
489}