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/// Iterator type for EID cache table entries.
22#[allow(missing_debug_implementations)]
23pub struct CacheEntryIterator<'a, T: ?Sized> {
24    ot_instance: &'a T,
25    ot_iter: otCacheEntryIterator,
26}
27
28impl<T: ?Sized + Thread> Iterator for CacheEntryIterator<'_, T> {
29    type Item = CacheEntryInfo;
30    fn next(&mut self) -> Option<Self::Item> {
31        self.ot_instance.iter_next_cache_entry_info(&mut self.ot_iter)
32    }
33}
34
35/// Methods from the [OpenThread "Thread General" Module][1].
36///
37/// [1]: https://openthread.io/reference/group/api-thread-general
38pub trait Thread {
39    /// Functional equivalent of
40    /// [`otsys::otThreadBecomeLeader`](crate::otsys::otThreadBecomeLeader).
41    fn become_leader(&self) -> Result;
42
43    /// Functional equivalent of
44    /// [`otsys::otThreadBecomeRouter`](crate::otsys::otThreadBecomeRouter).
45    fn become_router(&self) -> Result;
46
47    /// Functional equivalent of
48    /// [`otsys::otThreadGetChildInfoById`](crate::otsys::otThreadGetChildInfoById).
49    fn get_child_info_by_id(&self, child_id: u16) -> Result<otChildInfo>;
50
51    /// Functional equivalent of
52    /// [`otsys::otThreadGetLeaderData`](crate::otsys::otThreadGetLeaderData).
53    fn get_leader_data(&self) -> Result<LeaderData>;
54
55    /// Functional equivalent of
56    /// [`otsys::otThreadGetLeaderWeight`](crate::otsys::otThreadGetLeaderWeight).
57    fn get_leader_weight(&self) -> u8;
58
59    /// Functional equivalent of
60    /// [`otsys::otThreadGetNetworkKey`](crate::otsys::otThreadGetNetworkKey).
61    #[must_use]
62    fn get_network_key(&self) -> NetworkKey;
63
64    /// Functional equivalent of
65    /// [`otsys::otThreadSetNetworkKey`](crate::otsys::otThreadSetNetworkKey).
66    fn set_network_key(&self, key: &NetworkKey) -> Result;
67
68    /// Similar to [`get_network_name_as_slice`], but returns
69    /// an [`ot::NetworkName`](crate::ot::NetworkName).
70    #[must_use]
71    fn get_network_name(&self) -> NetworkName {
72        NetworkName::try_from_slice(self.get_network_name_as_slice()).unwrap()
73    }
74
75    /// Functional equivalent of
76    /// [`otsys::otThreadGetNetworkName`](crate::otsys::otThreadGetNetworkName).
77    #[must_use]
78    fn get_network_name_as_slice(&self) -> &[u8];
79
80    /// Functional equivalent of
81    /// [`otsys::otThreadSetNetworkName`](crate::otsys::otThreadSetNetworkName).
82    fn set_network_name(&self, name: &NetworkName) -> Result;
83
84    /// Functional equivalent of
85    /// [`otsys::otThreadIsSingleton`](crate::otsys::otThreadIsSingleton).
86    #[must_use]
87    fn is_singleton(&self) -> bool;
88
89    /// Functional equivalent of
90    /// [`otsys::otThreadGetExtendedPanId`](crate::otsys::otThreadGetExtendedPanId).
91    #[must_use]
92    fn get_extended_pan_id(&self) -> &ExtendedPanId;
93
94    /// Functional equivalent of
95    /// [`otsys::otThreadSetExtendedPanId`](crate::otsys::otThreadSetExtendedPanId).
96    fn set_extended_pan_id(&self, xpanid: &ExtendedPanId) -> Result;
97
98    /// Functional equivalent of [`otsys::otThreadSetEnabled`](crate::otsys::otThreadSetEnabled).
99    fn thread_set_enabled(&self, enabled: bool) -> Result;
100
101    /// Functional equivalent of
102    /// [`otsys::otThreadGetDeviceRole`](crate::otsys::otThreadGetDeviceRole).
103    #[must_use]
104    fn get_device_role(&self) -> DeviceRole;
105
106    /// Functional equivalent of
107    /// [`otsys::otThreadGetPartitionId`](crate::otsys::otThreadGetPartitionId).
108    fn get_partition_id(&self) -> u32;
109
110    /// Functional equivalent of [`otsys::otThreadGetRloc16`](crate::otsys::otThreadGetRloc16).
111    fn get_rloc16(&self) -> u16;
112
113    /// Functional equivalent of [`otsys::otThreadGetLinkMode`](crate::otsys::otThreadGetLinkMode).
114    fn get_link_mode(&self) -> ot::LinkModeConfig;
115
116    /// Functional equivalent of [`otsys::otThreadSetLinkMode`](crate::otsys::otThreadSetLinkMode).
117    fn set_link_mode(&self, link_mode_config: ot::LinkModeConfig) -> Result;
118
119    /// Gets the full RLOC address.
120    fn get_rloc(&self) -> std::net::Ipv6Addr;
121
122    /// Functional equivalent of
123    /// [`otsys::otThreadGetMeshLocalEid`](crate::otsys::otThreadGetMeshLocalEid).
124    fn get_mesh_local_eid(&self) -> std::net::Ipv6Addr;
125
126    /// Functional equivalent of
127    /// [`otsys::otThreadGetLinkLocalIp6Address`](crate::otsys::otThreadGetLinkLocalIp6Address).
128    fn get_link_local_addr(&self) -> std::net::Ipv6Addr;
129
130    /// Functional equivalent of
131    /// [`otsys::otThreadGetLinkLocalAllThreadNodesMulticastAddress`](crate::otsys::otThreadGetLinkLocalAllThreadNodesMulticastAddress).
132    fn get_link_local_all_nodes_multicast_addr(&self) -> std::net::Ipv6Addr;
133
134    /// Functional equivalent of
135    /// [`otsys::otThreadGetMeshLocalPrefix`](crate::otsys::otThreadGetMeshLocalPrefix).
136    fn get_mesh_local_prefix(&self) -> &MeshLocalPrefix;
137
138    /// Functional equivalent of
139    /// [`otsys::otThreadGetRouterInfo`](crate::otsys::otThreadGetRouterInfo).
140    fn get_router_info(&self, router_id: u16) -> Result<RouterInfo>;
141
142    /// Functional equivalent of
143    /// [`otsys::otThreadGetMaxRouterId`](crate::otsys::otThreadGetMaxRouterId).
144    fn get_max_router_id(&self) -> u8;
145
146    /// Functional equivalent of
147    /// [`otsys::otThreadGetIp6Counters`](crate::otsys::otThreadGetIp6Counters).
148    fn get_ip6_counters(&self) -> &IpCounters;
149
150    /// Functional equivalent of
151    /// [`otsys::otThreadGetNextNeighborInfo`](crate::otsys::otThreadGetNextNeighborInfo).
152    // TODO: Determine if the underlying implementation of
153    //       this method has undefined behavior when network data
154    //       is being mutated while iterating. If it is undefined,
155    //       we may need to make it unsafe and provide a safe method
156    //       that collects the results.
157    fn iter_next_neighbor_info(&self, ot_iter: &mut otNeighborInfoIterator)
158    -> Option<NeighborInfo>;
159
160    /// Returns an iterator for iterating over external routes.
161    fn iter_neighbor_info(&self) -> NeighborInfoIterator<'_, Self> {
162        NeighborInfoIterator {
163            ot_instance: self,
164            ot_iter: OT_NEIGHBOR_INFO_ITERATOR_INIT.try_into().unwrap(),
165        }
166    }
167
168    /// Functional equivalent of
169    /// [`otsys::otThreadSetVendorName`](crate::otsys::otThreadSetVendorName).
170    fn set_vendor_name(&self, name: &str) -> Result;
171
172    /// Functional equivalent of
173    /// [`otsys::otThreadSetVendorModel`](crate::otsys::otThreadSetVendorModel).
174    fn set_vendor_model(&self, model: &str) -> Result;
175
176    /// Functional equivalent of
177    /// [`otsys::otThreadSetVendorSwVersion`](crate::otsys::otThreadSetVendorSwVersion).
178    fn set_vendor_sw_version(&self, version: &str) -> Result;
179
180    /// Functional equivalent of
181    /// [`otsys::otThreadGetMleCounters`](crate::otsys::otThreadGetMleCounters).
182    fn get_mle_counters(&self) -> &MleCounters;
183
184    /// [`otsys::otThreadGetNextCacheEntry`](crate::otsys::otThreadGetNextCacheEntry).
185    fn iter_next_cache_entry_info(
186        &self,
187        ot_iter: &mut otCacheEntryIterator,
188    ) -> Option<CacheEntryInfo>;
189
190    /// Returns an iterator for iterating through the EID cache table entries.
191    fn iter_cache_entry_info(&self) -> CacheEntryIterator<'_, Self> {
192        CacheEntryIterator { ot_instance: self, ot_iter: otCacheEntryIterator::default() }
193    }
194}
195
196impl<T: Thread + Boxable> Thread for ot::Box<T> {
197    fn become_leader(&self) -> Result<()> {
198        self.as_ref().become_leader()
199    }
200    fn become_router(&self) -> Result<()> {
201        self.as_ref().become_router()
202    }
203    fn get_child_info_by_id(&self, child_id: u16) -> Result<otChildInfo> {
204        self.as_ref().get_child_info_by_id(child_id)
205    }
206    fn get_leader_data(&self) -> Result<LeaderData> {
207        self.as_ref().get_leader_data()
208    }
209
210    fn get_leader_weight(&self) -> u8 {
211        self.as_ref().get_leader_weight()
212    }
213
214    fn get_network_key(&self) -> NetworkKey {
215        self.as_ref().get_network_key()
216    }
217
218    fn set_network_key(&self, key: &NetworkKey) -> Result {
219        self.as_ref().set_network_key(key)
220    }
221    fn get_network_name_as_slice(&self) -> &[u8] {
222        self.as_ref().get_network_name_as_slice()
223    }
224
225    fn set_network_name(&self, name: &NetworkName) -> Result {
226        self.as_ref().set_network_name(name)
227    }
228
229    fn is_singleton(&self) -> bool {
230        self.as_ref().is_singleton()
231    }
232
233    fn get_extended_pan_id(&self) -> &ExtendedPanId {
234        self.as_ref().get_extended_pan_id()
235    }
236
237    fn set_extended_pan_id(&self, xpanid: &ExtendedPanId) -> Result {
238        self.as_ref().set_extended_pan_id(xpanid)
239    }
240
241    fn thread_set_enabled(&self, enabled: bool) -> Result {
242        self.as_ref().thread_set_enabled(enabled)
243    }
244
245    fn get_device_role(&self) -> DeviceRole {
246        self.as_ref().get_device_role()
247    }
248
249    fn get_partition_id(&self) -> u32 {
250        self.as_ref().get_partition_id()
251    }
252
253    fn get_rloc16(&self) -> u16 {
254        self.as_ref().get_rloc16()
255    }
256
257    fn get_link_mode(&self) -> ot::LinkModeConfig {
258        self.as_ref().get_link_mode()
259    }
260
261    fn set_link_mode(&self, link_mode_config: ot::LinkModeConfig) -> Result {
262        self.as_ref().set_link_mode(link_mode_config)
263    }
264
265    fn get_rloc(&self) -> std::net::Ipv6Addr {
266        self.as_ref().get_rloc()
267    }
268
269    fn get_mesh_local_eid(&self) -> std::net::Ipv6Addr {
270        self.as_ref().get_mesh_local_eid()
271    }
272
273    fn get_link_local_addr(&self) -> std::net::Ipv6Addr {
274        self.as_ref().get_link_local_addr()
275    }
276
277    fn get_link_local_all_nodes_multicast_addr(&self) -> std::net::Ipv6Addr {
278        self.as_ref().get_link_local_all_nodes_multicast_addr()
279    }
280
281    fn get_mesh_local_prefix(&self) -> &MeshLocalPrefix {
282        self.as_ref().get_mesh_local_prefix()
283    }
284
285    fn get_router_info(&self, router_id: u16) -> Result<RouterInfo> {
286        self.as_ref().get_router_info(router_id)
287    }
288
289    fn get_max_router_id(&self) -> u8 {
290        self.as_ref().get_max_router_id()
291    }
292
293    fn get_ip6_counters(&self) -> &IpCounters {
294        self.as_ref().get_ip6_counters()
295    }
296
297    fn iter_next_neighbor_info(
298        &self,
299        ot_iter: &mut otNeighborInfoIterator,
300    ) -> Option<NeighborInfo> {
301        self.as_ref().iter_next_neighbor_info(ot_iter)
302    }
303
304    fn set_vendor_name(&self, name: &str) -> Result {
305        self.as_ref().set_vendor_name(name)
306    }
307
308    fn set_vendor_model(&self, model: &str) -> Result {
309        self.as_ref().set_vendor_model(model)
310    }
311
312    fn set_vendor_sw_version(&self, version: &str) -> Result {
313        self.as_ref().set_vendor_sw_version(version)
314    }
315
316    fn get_mle_counters(&self) -> &MleCounters {
317        self.as_ref().get_mle_counters()
318    }
319
320    fn iter_next_cache_entry_info(
321        &self,
322        ot_iter: &mut otCacheEntryIterator,
323    ) -> Option<CacheEntryInfo> {
324        self.as_ref().iter_next_cache_entry_info(ot_iter)
325    }
326}
327
328impl Thread for Instance {
329    fn become_leader(&self) -> Result<()> {
330        Error::from(unsafe { otThreadBecomeLeader(self.as_ot_ptr()) }).into()
331    }
332
333    fn become_router(&self) -> Result<()> {
334        Error::from(unsafe { otThreadBecomeRouter(self.as_ot_ptr()) }).into()
335    }
336
337    fn get_child_info_by_id(&self, child_id: u16) -> Result<otChildInfo> {
338        let mut ret: otChildInfo = Default::default();
339        Error::from(unsafe { otThreadGetChildInfoById(self.as_ot_ptr(), child_id, &mut ret) })
340            .into_result()?;
341        Ok(ret)
342    }
343
344    fn get_leader_data(&self) -> Result<LeaderData> {
345        let mut ret = LeaderData::default();
346        Error::from(unsafe { otThreadGetLeaderData(self.as_ot_ptr(), ret.as_ot_mut_ptr()) })
347            .into_result()?;
348        Ok(ret)
349    }
350
351    fn get_leader_weight(&self) -> u8 {
352        unsafe { otThreadGetLeaderWeight(self.as_ot_ptr()) }
353    }
354
355    fn get_network_key(&self) -> NetworkKey {
356        let mut ret = NetworkKey::default();
357        unsafe { otThreadGetNetworkKey(self.as_ot_ptr(), ret.as_ot_mut_ptr()) }
358        ret
359    }
360
361    fn set_network_key(&self, key: &NetworkKey) -> Result {
362        Error::from(unsafe { otThreadSetNetworkKey(self.as_ot_ptr(), key.as_ot_ptr()) })
363            .into_result()
364    }
365
366    #[allow(clippy::unnecessary_cast)]
367    fn get_network_name_as_slice(&self) -> &[u8] {
368        unsafe {
369            let slice = std::slice::from_raw_parts(
370                otThreadGetNetworkName(self.as_ot_ptr()) as *const u8,
371                OT_NETWORK_NAME_MAX_SIZE as usize,
372            );
373            let first_zero_index =
374                slice.iter().position(|&x| x == 0).unwrap_or(OT_NETWORK_NAME_MAX_SIZE as usize);
375            &slice[0..first_zero_index]
376        }
377    }
378
379    fn set_network_name(&self, name: &NetworkName) -> Result {
380        Error::from(unsafe { otThreadSetNetworkName(self.as_ot_ptr(), name.as_c_str()) })
381            .into_result()
382    }
383
384    fn is_singleton(&self) -> bool {
385        unsafe { otThreadIsSingleton(self.as_ot_ptr()) }
386    }
387
388    fn get_extended_pan_id(&self) -> &ExtendedPanId {
389        unsafe {
390            let xpanid = otThreadGetExtendedPanId(self.as_ot_ptr());
391            ExtendedPanId::ref_from_ot_ptr(xpanid)
392        }
393        .unwrap()
394    }
395
396    fn set_extended_pan_id(&self, xpanid: &ExtendedPanId) -> Result {
397        Error::from(unsafe { otThreadSetExtendedPanId(self.as_ot_ptr(), xpanid.as_ot_ptr()) })
398            .into_result()
399    }
400
401    fn thread_set_enabled(&self, enabled: bool) -> Result {
402        Error::from(unsafe { otThreadSetEnabled(self.as_ot_ptr(), enabled) }).into_result()
403    }
404
405    fn get_device_role(&self) -> ot::DeviceRole {
406        unsafe { otThreadGetDeviceRole(self.as_ot_ptr()) }.into()
407    }
408
409    fn get_partition_id(&self) -> u32 {
410        unsafe { otThreadGetPartitionId(self.as_ot_ptr()) }
411    }
412
413    fn get_rloc16(&self) -> u16 {
414        unsafe { otThreadGetRloc16(self.as_ot_ptr()) }
415    }
416
417    fn get_link_mode(&self) -> ot::LinkModeConfig {
418        unsafe { otThreadGetLinkMode(self.as_ot_ptr()) }.into()
419    }
420
421    fn set_link_mode(&self, link_mode_config: ot::LinkModeConfig) -> Result {
422        Error::from(unsafe { otThreadSetLinkMode(self.as_ot_ptr(), link_mode_config.into()) })
423            .into_result()
424    }
425
426    fn get_rloc(&self) -> std::net::Ipv6Addr {
427        std::net::Ipv6Addr::from_ot(unsafe { *otThreadGetRloc(self.as_ot_ptr()) })
428    }
429
430    fn get_mesh_local_eid(&self) -> std::net::Ipv6Addr {
431        std::net::Ipv6Addr::from_ot(unsafe { *otThreadGetMeshLocalEid(self.as_ot_ptr()) })
432    }
433
434    fn get_link_local_addr(&self) -> std::net::Ipv6Addr {
435        std::net::Ipv6Addr::from_ot(unsafe { *otThreadGetLinkLocalIp6Address(self.as_ot_ptr()) })
436    }
437
438    fn get_link_local_all_nodes_multicast_addr(&self) -> std::net::Ipv6Addr {
439        std::net::Ipv6Addr::from_ot(unsafe {
440            *otThreadGetLinkLocalAllThreadNodesMulticastAddress(self.as_ot_ptr())
441        })
442    }
443
444    fn get_mesh_local_prefix(&self) -> &MeshLocalPrefix {
445        unsafe { MeshLocalPrefix::ref_from_ot_ptr(otThreadGetMeshLocalPrefix(self.as_ot_ptr())) }
446            .unwrap()
447    }
448
449    fn get_router_info(&self, router_id: u16) -> Result<RouterInfo> {
450        let mut ret = RouterInfo::default();
451        Error::from(unsafe {
452            otThreadGetRouterInfo(self.as_ot_ptr(), router_id, ret.as_ot_mut_ptr())
453        })
454        .into_result()?;
455        Ok(ret)
456    }
457
458    fn get_max_router_id(&self) -> u8 {
459        unsafe { otThreadGetMaxRouterId(self.as_ot_ptr()) }
460    }
461
462    fn get_ip6_counters(&self) -> &IpCounters {
463        unsafe { IpCounters::ref_from_ot_ptr(otThreadGetIp6Counters(self.as_ot_ptr())) }.unwrap()
464    }
465
466    fn iter_next_neighbor_info(
467        &self,
468        ot_iter: &mut otNeighborInfoIterator,
469    ) -> Option<NeighborInfo> {
470        unsafe {
471            let mut ret = NeighborInfo::default();
472            match Error::from(otThreadGetNextNeighborInfo(
473                self.as_ot_ptr(),
474                ot_iter as *mut otNeighborInfoIterator,
475                ret.as_ot_mut_ptr(),
476            )) {
477                Error::NotFound => None,
478                Error::None => Some(ret),
479                err => unreachable!("Unexpected error from otThreadGetNextNeighborInfo: {:?}", err),
480            }
481        }
482    }
483
484    fn set_vendor_name(&self, name: &str) -> Result {
485        let vendor_name = CString::new(name).expect("Vendor name must not contain null bytes");
486        Error::from(unsafe {
487            otThreadSetVendorName(
488                self.as_ot_ptr(),
489                vendor_name.as_ptr() as *const ::std::os::raw::c_char,
490            )
491        })
492        .into_result()
493    }
494
495    fn set_vendor_model(&self, model: &str) -> Result {
496        let vendor_model = CString::new(model).expect("Vendor model must not contain null bytes");
497        Error::from(unsafe {
498            otThreadSetVendorModel(
499                self.as_ot_ptr(),
500                vendor_model.as_ptr() as *const ::std::os::raw::c_char,
501            )
502        })
503        .into_result()
504    }
505
506    fn set_vendor_sw_version(&self, version: &str) -> Result {
507        let vendor_sw_version =
508            CString::new(version).expect("Vendor SW Version must not contain null bytes");
509        Error::from(unsafe {
510            otThreadSetVendorSwVersion(
511                self.as_ot_ptr(),
512                vendor_sw_version.as_ptr() as *const ::std::os::raw::c_char,
513            )
514        })
515        .into_result()
516    }
517
518    fn get_mle_counters(&self) -> &MleCounters {
519        unsafe { MleCounters::ref_from_ot_ptr(otThreadGetMleCounters(self.as_ot_ptr())) }.unwrap()
520    }
521
522    fn iter_next_cache_entry_info(
523        &self,
524        ot_iter: &mut otCacheEntryIterator,
525    ) -> Option<CacheEntryInfo> {
526        unsafe {
527            let mut ret = CacheEntryInfo::default();
528            match Error::from(otThreadGetNextCacheEntry(
529                self.as_ot_ptr(),
530                ret.as_ot_mut_ptr(),
531                ot_iter as *mut otCacheEntryIterator,
532            )) {
533                Error::NotFound => None,
534                Error::None => Some(ret),
535                err => unreachable!("Unexpected error from otThreadGetNextCacheEntry: {:?}", err),
536            }
537        }
538    }
539}