1use 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#[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#[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#[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#[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
69pub trait BorderRouter {
73 fn add_external_route(&self, route: &ExternalRouteConfig) -> Result;
76
77 fn add_on_mesh_prefix(&self, route: &BorderRouterConfig) -> Result;
80
81 fn remove_external_route(&self, prefix: &Ip6Prefix) -> Result;
84
85 fn remove_on_mesh_prefix(&self, prefix: &Ip6Prefix) -> Result;
88
89 fn border_router_register(&self) -> Result;
92
93 fn border_routing_init(&self, infra_if: u32, infra_is_running: bool) -> Result;
96
97 fn border_routing_set_enabled(&self, enabled: bool) -> Result;
100
101 fn border_routing_dhcp6_pd_set_enabled(&self, enabled: bool);
104
105 fn border_routing_dhcp6_pd_get_state(&self) -> BorderRoutingDhcp6PdState;
108
109 fn border_routing_dhcp6_pd_set_request_fn<'a, F>(&'a self, f: Option<F>)
112 where
113 F: FnMut(BorderRoutingDhcp6PdState) + 'a;
114
115 fn border_routing_dhcp6_pd_state_change_stream(&self)
117 -> BorderRoutingDhcp6PdStateChangedStream;
118
119 fn border_routing_get_pd_omr_prefix(&self) -> Result<ot::BorderRoutingPrefixTableEntry>;
122
123 fn border_routing_get_omr_prefix(&self) -> Result<ot::Ip6Prefix>;
126
127 fn border_routing_get_on_link_prefix(&self) -> Result<ot::Ip6Prefix>;
130
131 fn border_routing_process_icmp6_ra(&self, message: &[u8]) -> Result<(), WrongSize>;
134
135 fn border_routing_get_pd_processed_ra_info(&self) -> PdProcessedRaInfo;
138
139 fn border_routing_is_multi_ail_detected(&self) -> bool;
142
143 fn border_routing_prefix_table_init_iterator(
146 &self,
147 iter: &mut otBorderRoutingPrefixTableIterator,
148 );
149
150 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 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 fn iter_next_local_external_route(
172 &self,
173 ot_iter: &mut otNetworkDataIterator,
174 ) -> Option<ExternalRouteConfig>;
175
176 fn iter_next_local_on_mesh_prefix(
184 &self,
185 ot_iter: &mut otNetworkDataIterator,
186 ) -> Option<BorderRouterConfig>;
187
188 fn iter_next_border_routing_peer(
191 &self,
192 ot_iter: &mut otBorderRoutingPrefixTableIterator,
193 ) -> Option<BorderRoutingPeer>;
194
195 fn iter_next_border_routing_router(
198 &self,
199 ot_iter: &mut otBorderRoutingPrefixTableIterator,
200 ) -> Option<BorderRoutingRouter>;
201
202 fn iter_local_external_routes(&self) -> LocalExternalRouteIterator<'_, Self> {
204 LocalExternalRouteIterator { ot_instance: self, ot_iter: OT_NETWORK_DATA_ITERATOR_INIT }
205 }
206
207 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 let state = BorderRoutingDhcp6PdState::from(state);
384
385 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 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#[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}