openthread/ot/
border_router.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::ot::WrongSize;
6use crate::prelude_internal::*;
7use core::pin::Pin;
8use core::task::{Context, Poll};
9use fuchsia_sync::Mutex;
10use std::sync::Arc;
11use std::task::Waker;
12
13/// Iterator type for external routes.
14#[allow(missing_debug_implementations)]
15pub struct LocalExternalRouteIterator<'a, T: ?Sized> {
16    ot_instance: &'a T,
17    ot_iter: otNetworkDataIterator,
18}
19
20impl<T: ?Sized + BorderRouter> Iterator for LocalExternalRouteIterator<'_, T> {
21    type Item = ExternalRouteConfig;
22    fn next(&mut self) -> Option<Self::Item> {
23        self.ot_instance.iter_next_local_external_route(&mut self.ot_iter)
24    }
25}
26
27/// Iterator type for on-mesh prefixes.
28#[allow(missing_debug_implementations)]
29pub struct LocalOnMeshPrefixIterator<'a, T: ?Sized> {
30    ot_instance: &'a T,
31    ot_iter: otNetworkDataIterator,
32}
33
34impl<T: ?Sized + BorderRouter> Iterator for LocalOnMeshPrefixIterator<'_, T> {
35    type Item = BorderRouterConfig;
36    fn next(&mut self) -> Option<Self::Item> {
37        self.ot_instance.iter_next_local_on_mesh_prefix(&mut self.ot_iter)
38    }
39}
40
41/// Iterator type for border routing peer border router.
42#[allow(missing_debug_implementations)]
43pub struct BorderRoutingPeerIterator<'a, T: ?Sized> {
44    ot_instance: &'a T,
45    ot_iter: otBorderRoutingPrefixTableIterator,
46}
47
48impl<T: ?Sized + BorderRouter> Iterator for BorderRoutingPeerIterator<'_, T> {
49    type Item = BorderRoutingPeer;
50    fn next(&mut self) -> Option<Self::Item> {
51        self.ot_instance.iter_next_border_routing_peer(&mut self.ot_iter)
52    }
53}
54
55/// Iterator type for border routing router.
56#[allow(missing_debug_implementations)]
57pub struct BorderRoutingRouterIterator<'a, T: ?Sized> {
58    ot_instance: &'a T,
59    ot_iter: otBorderRoutingPrefixTableIterator,
60}
61
62impl<T: ?Sized + BorderRouter> Iterator for BorderRoutingRouterIterator<'_, T> {
63    type Item = BorderRoutingRouter;
64    fn next(&mut self) -> Option<Self::Item> {
65        self.ot_instance.iter_next_border_routing_router(&mut self.ot_iter)
66    }
67}
68
69/// Methods from the [OpenThread "Border Router" Module][1].
70///
71/// [1]: https://openthread.io/reference/group/api-border-router
72pub trait BorderRouter {
73    /// Functional equivalent of
74    /// [`otsys::otBorderRouterAddRoute`](crate::otsys::otBorderRouterAddRoute).
75    fn add_external_route(&self, route: &ExternalRouteConfig) -> Result;
76
77    /// Functional equivalent of
78    /// [`otsys::otBorderRouterAddOnMeshPrefix`](crate::otsys::otBorderRouterAddOnMeshPrefix).
79    fn add_on_mesh_prefix(&self, route: &BorderRouterConfig) -> Result;
80
81    /// Functional equivalent of
82    /// [`otsys::otBorderRouterRemoveRoute`](crate::otsys::otBorderRouterRemoveRoute).
83    fn remove_external_route(&self, prefix: &Ip6Prefix) -> Result;
84
85    /// Functional equivalent of
86    /// [`otsys::otBorderRouterRemoveOnMeshPrefix`](crate::otsys::otBorderRouterRemoveOnMeshPrefix).
87    fn remove_on_mesh_prefix(&self, prefix: &Ip6Prefix) -> Result;
88
89    /// Functional equivalent of
90    /// [`otsys::otBorderRouterRegister`](crate::otsys::otBorderRouterRegister).
91    fn border_router_register(&self) -> Result;
92
93    /// Functional equivalent of
94    /// [`otsys::otBorderRoutingInit`](crate::otsys::otBorderRoutingInit).
95    fn border_routing_init(&self, infra_if: u32, infra_is_running: bool) -> Result;
96
97    /// Functional equivalent of
98    /// [`otsys::otBorderRoutingSetEnabled`](crate::otsys::otBorderRoutingSetEnabled).
99    fn border_routing_set_enabled(&self, enabled: bool) -> Result;
100
101    /// Functional equivalent of
102    /// [`otsys::otBorderRoutingDhcp6PdSetEnabled`](crate::otsys::otBorderRoutingDhcp6PdSetEnabled).
103    fn border_routing_dhcp6_pd_set_enabled(&self, enabled: bool);
104
105    /// Functional equivalent of
106    /// [`otsys::otBorderRoutingDhcp6PdGetState`](crate::otsys::otBorderRoutingDhcp6PdGetState).
107    fn border_routing_dhcp6_pd_get_state(&self) -> BorderRoutingDhcp6PdState;
108
109    /// Functional equivalent of
110    /// [`otsys::otBorderRoutingDhcp6PdSetRequestCallback`](crate::otsys::otBorderRoutingDhcp6PdSetRequestCallback).
111    fn border_routing_dhcp6_pd_set_request_fn<'a, F>(&'a self, f: Option<F>)
112    where
113        F: FnMut(BorderRoutingDhcp6PdState) + 'a;
114
115    /// Get the DHCPv6 PD state change stream
116    fn border_routing_dhcp6_pd_state_change_stream(&self)
117    -> BorderRoutingDhcp6PdStateChangedStream;
118
119    /// Functional equivalent of
120    /// [`otsys::otBorderRoutingGetPdOmrPrefix`](crate::otsys::otBorderRoutingGetPdOmrPrefix).
121    fn border_routing_get_pd_omr_prefix(&self) -> Result<ot::BorderRoutingPrefixTableEntry>;
122
123    /// Functional equivalent of
124    /// [`otsys::otBorderRoutingGetOmrPrefix`](crate::otsys::otBorderRoutingGetOmrPrefix).
125    fn border_routing_get_omr_prefix(&self) -> Result<ot::Ip6Prefix>;
126
127    /// Functional equivalent of
128    /// [`otsys::otBorderRoutingGetOnLinkPrefix`](crate::otsys::otBorderRoutingGetOnLinkPrefix).
129    fn border_routing_get_on_link_prefix(&self) -> Result<ot::Ip6Prefix>;
130
131    /// Functional equivalent of
132    /// [`otsys::otPlatBorderRoutingProcessIcmp6Ra`](crate::otsys::otPlatBorderRoutingProcessIcmp6Ra).
133    fn border_routing_process_icmp6_ra(&self, message: &[u8]) -> Result<(), WrongSize>;
134
135    /// Functional equivalent of
136    /// [`otsys::otBorderRoutingGetPdProcessedRaInfo`](crate::otsys::otBorderRoutingGetPdProcessedRaInfo).
137    fn border_routing_get_pd_processed_ra_info(&self) -> PdProcessedRaInfo;
138
139    /// Functional equivalent of
140    /// [`otsys::otBorderRoutingIsMultiAilDetected`](crate::otsys::otBorderRoutingIsMultiAilDetected).
141    fn border_routing_is_multi_ail_detected(&self) -> bool;
142
143    /// Functional equivalent of
144    /// [`otsys::otBorderRoutingPrefixTableInitIterator`](crate::otsys::otBorderRoutingPrefixTableInitIterator).
145    fn border_routing_prefix_table_init_iterator(
146        &self,
147        iter: &mut otBorderRoutingPrefixTableIterator,
148    );
149
150    /// Get the border routing peer iterator instance.
151    fn border_routing_peer_get_iterator(&self) -> BorderRoutingPeerIterator<'_, Self> {
152        let mut ot_iter = otBorderRoutingPrefixTableIterator::default();
153        self.border_routing_prefix_table_init_iterator(&mut ot_iter);
154        BorderRoutingPeerIterator { ot_instance: self, ot_iter }
155    }
156
157    /// Get the border routing router iterator instance.
158    fn border_routing_router_get_iterator(&self) -> BorderRoutingRouterIterator<'_, Self> {
159        let mut ot_iter = otBorderRoutingPrefixTableIterator::default();
160        self.border_routing_prefix_table_init_iterator(&mut ot_iter);
161        BorderRoutingRouterIterator { ot_instance: self, ot_iter }
162    }
163
164    /// Functional equivalent of
165    /// [`otsys::otBorderRouterGetNextRoute`](crate::otsys::otBorderRouterGetNextRoute).
166    // TODO: Determine if the underlying implementation of
167    //       this method has undefined behavior when network data
168    //       is being mutated while iterating. If it is undefined,
169    //       we may need to make it unsafe and provide a safe method
170    //       that collects the results.
171    fn iter_next_local_external_route(
172        &self,
173        ot_iter: &mut otNetworkDataIterator,
174    ) -> Option<ExternalRouteConfig>;
175
176    /// Functional equivalent of
177    /// [`otsys::otBorderRouterGetNextOnMeshPrefix`](crate::otsys::otBorderRouterGetNextOnMeshPrefix).
178    // TODO: Determine if the underlying implementation of
179    //       this method has undefined behavior when network data
180    //       is being mutated while iterating. If it is undefined,
181    //       we may need to make it unsafe and provide a safe method
182    //       that collects the results.
183    fn iter_next_local_on_mesh_prefix(
184        &self,
185        ot_iter: &mut otNetworkDataIterator,
186    ) -> Option<BorderRouterConfig>;
187
188    /// Functional equivalent of
189    /// [`otsys::otBorderRoutingGetNextPeerBrEntry`](crate::otsys::otBorderRoutingGetNextPeerBrEntry).
190    fn iter_next_border_routing_peer(
191        &self,
192        ot_iter: &mut otBorderRoutingPrefixTableIterator,
193    ) -> Option<BorderRoutingPeer>;
194
195    /// Functional equivalent of
196    /// [`otsys::otBorderRoutingGetNextRouterEntry`](crate::otsys::otBorderRoutingGetNextRouterEntry).
197    fn iter_next_border_routing_router(
198        &self,
199        ot_iter: &mut otBorderRoutingPrefixTableIterator,
200    ) -> Option<BorderRoutingRouter>;
201
202    /// Returns an iterator for iterating over external routes.
203    fn iter_local_external_routes(&self) -> LocalExternalRouteIterator<'_, Self> {
204        LocalExternalRouteIterator { ot_instance: self, ot_iter: OT_NETWORK_DATA_ITERATOR_INIT }
205    }
206
207    /// Returns an iterator for iterating over on-mesh prefixes
208    fn iter_local_on_mesh_prefixes(&self) -> LocalOnMeshPrefixIterator<'_, Self> {
209        LocalOnMeshPrefixIterator { ot_instance: self, ot_iter: OT_NETWORK_DATA_ITERATOR_INIT }
210    }
211}
212
213impl<T: BorderRouter + Boxable> BorderRouter for ot::Box<T> {
214    fn add_external_route(&self, route: &ExternalRouteConfig) -> Result {
215        self.as_ref().add_external_route(route)
216    }
217
218    fn add_on_mesh_prefix(&self, route: &BorderRouterConfig) -> Result {
219        self.as_ref().add_on_mesh_prefix(route)
220    }
221
222    fn remove_external_route(&self, prefix: &Ip6Prefix) -> Result {
223        self.as_ref().remove_external_route(prefix)
224    }
225
226    fn remove_on_mesh_prefix(&self, prefix: &Ip6Prefix) -> Result {
227        self.as_ref().remove_on_mesh_prefix(prefix)
228    }
229
230    fn border_router_register(&self) -> Result {
231        self.as_ref().border_router_register()
232    }
233
234    fn border_routing_init(&self, infra_if: u32, infra_is_running: bool) -> Result {
235        self.as_ref().border_routing_init(infra_if, infra_is_running)
236    }
237
238    fn border_routing_set_enabled(&self, enabled: bool) -> Result {
239        self.as_ref().border_routing_set_enabled(enabled)
240    }
241
242    fn border_routing_dhcp6_pd_set_enabled(&self, enabled: bool) {
243        self.as_ref().border_routing_dhcp6_pd_set_enabled(enabled)
244    }
245
246    fn border_routing_dhcp6_pd_get_state(&self) -> BorderRoutingDhcp6PdState {
247        self.as_ref().border_routing_dhcp6_pd_get_state()
248    }
249
250    fn border_routing_dhcp6_pd_set_request_fn<'a, F>(&'a self, f: Option<F>)
251    where
252        F: FnMut(BorderRoutingDhcp6PdState) + 'a,
253    {
254        self.as_ref().border_routing_dhcp6_pd_set_request_fn(f)
255    }
256
257    fn border_routing_dhcp6_pd_state_change_stream(
258        &self,
259    ) -> BorderRoutingDhcp6PdStateChangedStream {
260        self.as_ref().border_routing_dhcp6_pd_state_change_stream()
261    }
262
263    fn border_routing_get_pd_omr_prefix(&self) -> Result<ot::BorderRoutingPrefixTableEntry> {
264        self.as_ref().border_routing_get_pd_omr_prefix()
265    }
266
267    fn border_routing_get_omr_prefix(&self) -> Result<ot::Ip6Prefix> {
268        self.as_ref().border_routing_get_omr_prefix()
269    }
270
271    fn border_routing_get_on_link_prefix(&self) -> Result<ot::Ip6Prefix> {
272        self.as_ref().border_routing_get_on_link_prefix()
273    }
274
275    fn border_routing_process_icmp6_ra(&self, message: &[u8]) -> Result<(), WrongSize> {
276        self.as_ref().border_routing_process_icmp6_ra(message)
277    }
278
279    fn border_routing_get_pd_processed_ra_info(&self) -> PdProcessedRaInfo {
280        self.as_ref().border_routing_get_pd_processed_ra_info()
281    }
282
283    fn border_routing_is_multi_ail_detected(&self) -> bool {
284        self.as_ref().border_routing_is_multi_ail_detected()
285    }
286
287    fn border_routing_prefix_table_init_iterator(
288        &self,
289        iter: &mut otBorderRoutingPrefixTableIterator,
290    ) {
291        self.as_ref().border_routing_prefix_table_init_iterator(iter)
292    }
293
294    fn iter_next_local_external_route(
295        &self,
296        ot_iter: &mut otNetworkDataIterator,
297    ) -> Option<ExternalRouteConfig> {
298        self.as_ref().iter_next_local_external_route(ot_iter)
299    }
300
301    fn iter_next_local_on_mesh_prefix(
302        &self,
303        ot_iter: &mut otNetworkDataIterator,
304    ) -> Option<BorderRouterConfig> {
305        self.as_ref().iter_next_local_on_mesh_prefix(ot_iter)
306    }
307
308    fn iter_next_border_routing_peer(
309        &self,
310        ot_iter: &mut otBorderRoutingPrefixTableIterator,
311    ) -> Option<BorderRoutingPeer> {
312        self.as_ref().iter_next_border_routing_peer(ot_iter)
313    }
314
315    fn iter_next_border_routing_router(
316        &self,
317        ot_iter: &mut otBorderRoutingPrefixTableIterator,
318    ) -> Option<BorderRoutingRouter> {
319        self.as_ref().iter_next_border_routing_router(ot_iter)
320    }
321}
322
323impl BorderRouter for Instance {
324    fn add_external_route(&self, route: &ExternalRouteConfig) -> Result {
325        Error::from(unsafe { otBorderRouterAddRoute(self.as_ot_ptr(), route.as_ot_ptr()) }).into()
326    }
327
328    fn add_on_mesh_prefix(&self, route: &BorderRouterConfig) -> Result {
329        Error::from(unsafe { otBorderRouterAddOnMeshPrefix(self.as_ot_ptr(), route.as_ot_ptr()) })
330            .into()
331    }
332
333    fn remove_external_route(&self, prefix: &Ip6Prefix) -> Result {
334        Error::from(unsafe { otBorderRouterRemoveRoute(self.as_ot_ptr(), prefix.as_ot_ptr()) })
335            .into()
336    }
337
338    fn remove_on_mesh_prefix(&self, prefix: &Ip6Prefix) -> Result {
339        Error::from(unsafe {
340            otBorderRouterRemoveOnMeshPrefix(self.as_ot_ptr(), prefix.as_ot_ptr())
341        })
342        .into()
343    }
344
345    fn border_router_register(&self) -> Result {
346        Error::from(unsafe { otBorderRouterRegister(self.as_ot_ptr()) }).into()
347    }
348
349    fn border_routing_init(&self, infra_if: u32, infra_is_running: bool) -> Result {
350        Error::from(unsafe { otBorderRoutingInit(self.as_ot_ptr(), infra_if, infra_is_running) })
351            .into()
352    }
353
354    fn border_routing_set_enabled(&self, enabled: bool) -> Result {
355        Error::from(unsafe { otBorderRoutingSetEnabled(self.as_ot_ptr(), enabled) }).into()
356    }
357
358    fn border_routing_dhcp6_pd_set_enabled(&self, enabled: bool) {
359        unsafe { otBorderRoutingDhcp6PdSetEnabled(self.as_ot_ptr(), enabled) }
360    }
361
362    fn border_routing_dhcp6_pd_get_state(&self) -> BorderRoutingDhcp6PdState {
363        BorderRoutingDhcp6PdState::from_isize(unsafe {
364            otBorderRoutingDhcp6PdGetState(self.as_ot_ptr())
365        } as isize)
366        .unwrap_or(BorderRoutingDhcp6PdState::Disabled)
367    }
368
369    fn border_routing_dhcp6_pd_set_request_fn<'a, F>(&'a self, f: Option<F>)
370    where
371        F: FnMut(BorderRoutingDhcp6PdState) + 'a,
372    {
373        unsafe extern "C" fn _ot_border_routing_dhcp6_pd_state_change_callback<
374            'a,
375            F: FnMut(BorderRoutingDhcp6PdState) + 'a,
376        >(
377            state: otBorderRoutingDhcp6PdState,
378            context: *mut ::std::os::raw::c_void,
379        ) {
380            trace!("_ot_border_routing_dhcp6_pd_state_change_callback");
381
382            // Convert `otBorderRoutingDhcp6PdState` to `BorderRoutingDhcp6PdState`
383            let state = BorderRoutingDhcp6PdState::from(state);
384
385            // Reconstitute a reference to our closure.
386            let sender = unsafe { &mut *(context as *mut F) };
387
388            sender(state)
389        }
390
391        let (fn_ptr, fn_box, cb): (_, _, otBorderRoutingRequestDhcp6PdCallback) = if let Some(f) = f
392        {
393            let mut x = Box::new(f);
394
395            (
396                x.as_mut() as *mut F as *mut ::std::os::raw::c_void,
397                Some(x as Box<dyn FnMut(BorderRoutingDhcp6PdState) + 'a>),
398                Some(_ot_border_routing_dhcp6_pd_state_change_callback::<F>),
399            )
400        } else {
401            (std::ptr::null_mut() as *mut ::std::os::raw::c_void, None, None)
402        };
403
404        unsafe {
405            otBorderRoutingDhcp6PdSetRequestCallback(self.as_ot_ptr(), cb, fn_ptr);
406
407            // Make sure our object eventually gets cleaned up.
408            // Here we must also transmute our closure to have a 'static lifetime.
409            // We need to do this because the borrow checker cannot infer the
410            // proper lifetime for the singleton instance backing, but
411            // this is guaranteed by the API.
412            self.borrow_backing().dhcp6pd_state_change_callback_fn.set(std::mem::transmute::<
413                Option<Box<dyn FnMut(BorderRoutingDhcp6PdState) + 'a>>,
414                Option<Box<dyn FnMut(BorderRoutingDhcp6PdState) + 'static>>,
415            >(fn_box));
416        }
417    }
418
419    fn border_routing_dhcp6_pd_state_change_stream(
420        &self,
421    ) -> BorderRoutingDhcp6PdStateChangedStream {
422        let state = Arc::new(Mutex::new((None, futures::task::noop_waker())));
423
424        let state_copy = state.clone();
425
426        self.border_routing_dhcp6_pd_set_request_fn(Some(
427            move |pd_state: BorderRoutingDhcp6PdState| {
428                let mut borrowed = state_copy.lock();
429                borrowed.0 = Some(pd_state);
430                borrowed.1.wake_by_ref();
431            },
432        ));
433
434        BorderRoutingDhcp6PdStateChangedStream(state)
435    }
436
437    fn border_routing_get_pd_omr_prefix(&self) -> Result<ot::BorderRoutingPrefixTableEntry> {
438        let mut ret: BorderRoutingPrefixTableEntry = Default::default();
439        Error::from(unsafe {
440            otBorderRoutingGetPdOmrPrefix(self.as_ot_ptr(), ret.as_ot_mut_ptr())
441        })
442        .into_result()?;
443        Ok(ret)
444    }
445
446    fn border_routing_get_omr_prefix(&self) -> Result<ot::Ip6Prefix> {
447        let mut ret: Ip6Prefix = Default::default();
448        Error::from(unsafe { otBorderRoutingGetOmrPrefix(self.as_ot_ptr(), ret.as_ot_mut_ptr()) })
449            .into_result()?;
450        Ok(ret)
451    }
452
453    fn border_routing_get_on_link_prefix(&self) -> Result<ot::Ip6Prefix> {
454        let mut ret: Ip6Prefix = Default::default();
455        Error::from(unsafe {
456            otBorderRoutingGetOnLinkPrefix(self.as_ot_ptr(), ret.as_ot_mut_ptr())
457        })
458        .into_result()?;
459        Ok(ret)
460    }
461
462    fn border_routing_process_icmp6_ra(&self, message: &[u8]) -> Result<(), WrongSize> {
463        unsafe {
464            otPlatBorderRoutingProcessIcmp6Ra(
465                self.as_ot_ptr(),
466                message.as_ptr(),
467                message.len().try_into().map_err(|_| WrongSize)?,
468            )
469        }
470        Ok(())
471    }
472
473    fn border_routing_get_pd_processed_ra_info(&self) -> PdProcessedRaInfo {
474        let mut info = PdProcessedRaInfo::default();
475        unsafe {
476            otBorderRoutingGetPdProcessedRaInfo(self.as_ot_ptr(), info.as_ot_mut_ptr());
477        }
478        info
479    }
480
481    fn border_routing_is_multi_ail_detected(&self) -> bool {
482        unsafe { otBorderRoutingIsMultiAilDetected(self.as_ot_ptr()) }
483    }
484
485    fn border_routing_prefix_table_init_iterator(
486        &self,
487        iter: &mut otBorderRoutingPrefixTableIterator,
488    ) {
489        unsafe { otBorderRoutingPrefixTableInitIterator(self.as_ot_ptr(), iter) }
490    }
491
492    fn iter_next_local_external_route(
493        &self,
494        ot_iter: &mut otNetworkDataIterator,
495    ) -> Option<ExternalRouteConfig> {
496        unsafe {
497            let mut ret = ExternalRouteConfig::default();
498            match Error::from(otBorderRouterGetNextRoute(
499                self.as_ot_ptr(),
500                ot_iter as *mut otNetworkDataIterator,
501                ret.as_ot_mut_ptr(),
502            )) {
503                Error::NotFound => None,
504                Error::None => Some(ret),
505                err => panic!("Unexpected error from otBorderRouterGetNextRoute: {err:?}"),
506            }
507        }
508    }
509
510    fn iter_next_local_on_mesh_prefix(
511        &self,
512        ot_iter: &mut otNetworkDataIterator,
513    ) -> Option<BorderRouterConfig> {
514        unsafe {
515            let mut ret = BorderRouterConfig::default();
516            match Error::from(otBorderRouterGetNextOnMeshPrefix(
517                self.as_ot_ptr(),
518                ot_iter as *mut otNetworkDataIterator,
519                ret.as_ot_mut_ptr(),
520            )) {
521                Error::NotFound => None,
522                Error::None => Some(ret),
523                err => panic!("Unexpected error from otBorderRouterGetNextOnMeshPrefix: {err:?}"),
524            }
525        }
526    }
527
528    fn iter_next_border_routing_peer(
529        &self,
530        ot_iter: &mut otBorderRoutingPrefixTableIterator,
531    ) -> Option<BorderRoutingPeer> {
532        unsafe {
533            let mut ret = BorderRoutingPeer::default();
534            match Error::from(otBorderRoutingGetNextPeerBrEntry(
535                self.as_ot_ptr(),
536                ot_iter as *mut otBorderRoutingPrefixTableIterator,
537                ret.as_ot_mut_ptr(),
538            )) {
539                Error::NotFound => None,
540                Error::None => Some(ret),
541                err => panic!("Unexpected error from otBorderRoutingGetNextPeerBrEntry: {err:?}"),
542            }
543        }
544    }
545
546    fn iter_next_border_routing_router(
547        &self,
548        ot_iter: &mut otBorderRoutingPrefixTableIterator,
549    ) -> Option<BorderRoutingRouter> {
550        unsafe {
551            let mut ret = BorderRoutingRouter::default();
552            match Error::from(otBorderRoutingGetNextRouterEntry(
553                self.as_ot_ptr(),
554                ot_iter as *mut otBorderRoutingPrefixTableIterator,
555                ret.as_ot_mut_ptr(),
556            )) {
557                Error::NotFound => None,
558                Error::None => Some(ret),
559                err => panic!("Unexpected error from otBorderRoutingGetNextRouterEntry: {err:?}"),
560            }
561        }
562    }
563}
564
565/// Stream for getting state changed events.
566#[derive(Debug, Clone)]
567pub struct BorderRoutingDhcp6PdStateChangedStream(
568    Arc<Mutex<(Option<BorderRoutingDhcp6PdState>, Waker)>>,
569);
570
571impl Stream for BorderRoutingDhcp6PdStateChangedStream {
572    type Item = BorderRoutingDhcp6PdState;
573
574    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
575        let mut state = self.0.lock();
576
577        state.1 = cx.waker().clone();
578
579        if let Some(pd_state) = state.0.take() {
580            Poll::Ready(Some(pd_state))
581        } else {
582            Poll::Pending
583        }
584    }
585}