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