use crate::prelude_internal::*;
#[derive(Debug, Copy, Clone, Eq, Ord, PartialOrd, PartialEq, num_derive::FromPrimitive)]
pub enum Icmp6EchoMode {
HandleAll = OT_ICMP6_ECHO_HANDLER_ALL as isize,
HandleDisabled = OT_ICMP6_ECHO_HANDLER_DISABLED as isize,
HandleMulticastOnly = OT_ICMP6_ECHO_HANDLER_MULTICAST_ONLY as isize,
HandleUnicastOnly = OT_ICMP6_ECHO_HANDLER_UNICAST_ONLY as isize,
}
impl From<otIcmp6EchoMode> for Icmp6EchoMode {
fn from(x: otIcmp6EchoMode) -> Self {
use num::FromPrimitive;
Self::from_u32(x).unwrap_or_else(|| panic!("Unknown otIcmp6EchoMode value: {x}"))
}
}
impl From<Icmp6EchoMode> for otIcmp6EchoMode {
fn from(x: Icmp6EchoMode) -> Self {
x as otIcmp6EchoMode
}
}
#[derive(Default, Debug, Clone)]
pub struct NetifAddressIterator<'a>(Option<&'a NetifAddress>);
impl<'a> Iterator for NetifAddressIterator<'a> {
type Item = &'a NetifAddress;
fn next(&mut self) -> Option<Self::Item> {
if let Some(addr_ref) = self.0 {
self.0 = unsafe { NetifAddress::ref_from_ot_ptr(addr_ref.0.mNext) };
Some(addr_ref)
} else {
None
}
}
}
pub trait Ip6 {
fn ip6_send(&self, message: OtMessageBox<'_>) -> Result;
fn ip6_send_data(&self, data: &[u8]) -> Result;
fn ip6_send_data_direct(&self, data: &[u8]) -> Result;
fn ip6_is_enabled(&self) -> bool;
fn ip6_set_enabled(&self, enabled: bool) -> Result;
fn ip6_add_unicast_address(&self, addr: &NetifAddress) -> Result;
fn ip6_remove_unicast_address(&self, addr: &Ip6Address) -> Result;
fn ip6_join_multicast_group(&self, addr: &Ip6Address) -> Result;
fn ip6_leave_multicast_group(&self, addr: &Ip6Address) -> Result;
fn ip6_set_receive_fn<'a, F>(&'a self, f: Option<F>)
where
F: FnMut(OtMessageBox<'_>) + 'a;
fn ip6_set_address_fn<'a, F>(&'a self, f: Option<F>)
where
F: for<'r> FnMut(Ip6AddressInfo<'r>, bool) + 'a;
fn ip6_is_slaac_enabled(&self) -> bool;
fn ip6_set_slaac_enabled(&self, enabled: bool);
fn icmp6_get_echo_mode(&self) -> Icmp6EchoMode;
fn icmp6_set_echo_mode(&self, mode: Icmp6EchoMode);
fn ip6_set_receive_filter_enabled(&self, enabled: bool);
fn ip6_is_receive_filter_enabled(&self) -> bool;
fn ip6_get_border_routing_counters(&self) -> &BorderRoutingCounters;
fn ip6_get_unicast_addresses(&self) -> NetifAddressIterator<'_>;
}
impl<T: Ip6 + ot::Boxable> Ip6 for ot::Box<T> {
fn ip6_send(&self, message: OtMessageBox<'_>) -> Result<()> {
self.as_ref().ip6_send(message)
}
fn ip6_send_data(&self, data: &[u8]) -> Result {
self.as_ref().ip6_send_data(data)
}
fn ip6_send_data_direct(&self, data: &[u8]) -> Result {
self.as_ref().ip6_send_data_direct(data)
}
fn ip6_is_enabled(&self) -> bool {
self.as_ref().ip6_is_enabled()
}
fn ip6_set_enabled(&self, enabled: bool) -> Result {
self.as_ref().ip6_set_enabled(enabled)
}
fn ip6_add_unicast_address(&self, addr: &NetifAddress) -> Result {
self.as_ref().ip6_add_unicast_address(addr)
}
fn ip6_remove_unicast_address(&self, addr: &std::net::Ipv6Addr) -> Result {
self.as_ref().ip6_remove_unicast_address(addr)
}
fn ip6_join_multicast_group(&self, addr: &std::net::Ipv6Addr) -> Result {
self.as_ref().ip6_join_multicast_group(addr)
}
fn ip6_leave_multicast_group(&self, addr: &std::net::Ipv6Addr) -> Result {
self.as_ref().ip6_join_multicast_group(addr)
}
fn ip6_set_receive_fn<'a, F>(&'a self, f: Option<F>)
where
F: FnMut(OtMessageBox<'_>) + 'a,
{
self.as_ref().ip6_set_receive_fn(f)
}
fn ip6_set_address_fn<'a, F>(&'a self, f: Option<F>)
where
F: for<'r> FnMut(Ip6AddressInfo<'r>, bool) + 'a,
{
self.as_ref().ip6_set_address_fn(f)
}
fn ip6_is_slaac_enabled(&self) -> bool {
self.as_ref().ip6_is_slaac_enabled()
}
fn ip6_set_slaac_enabled(&self, enabled: bool) {
self.as_ref().ip6_set_slaac_enabled(enabled);
}
fn icmp6_get_echo_mode(&self) -> Icmp6EchoMode {
self.as_ref().icmp6_get_echo_mode()
}
fn icmp6_set_echo_mode(&self, mode: Icmp6EchoMode) {
self.as_ref().icmp6_set_echo_mode(mode)
}
fn ip6_set_receive_filter_enabled(&self, enabled: bool) {
self.as_ref().ip6_set_receive_filter_enabled(enabled);
}
fn ip6_is_receive_filter_enabled(&self) -> bool {
self.as_ref().ip6_is_receive_filter_enabled()
}
fn ip6_get_border_routing_counters(&self) -> &BorderRoutingCounters {
self.as_ref().ip6_get_border_routing_counters()
}
fn ip6_get_unicast_addresses(&self) -> NetifAddressIterator<'_> {
self.as_ref().ip6_get_unicast_addresses()
}
}
impl Ip6 for Instance {
fn ip6_send(&self, message: OtMessageBox<'_>) -> Result {
Error::from(unsafe { otIp6Send(self.as_ot_ptr(), message.take_ot_ptr()) }).into()
}
fn ip6_send_data(&self, data: &[u8]) -> Result {
if let Ok(msg) = Message::ip6_new_from_bytes(self, data, None) {
self.ip6_send(msg)
} else if self.get_buffer_info().0.mFreeBuffers == 0 {
Err(ot::Error::NoBufs)
} else {
Err(ot::Error::Failed)
}
}
fn ip6_send_data_direct(&self, data: &[u8]) -> Result {
if let Ok(mut msg) = Message::ip6_new_from_bytes(self, data, None) {
msg.set_direct_transmission(true);
self.ip6_send(msg)
} else if self.get_buffer_info().0.mFreeBuffers == 0 {
Err(ot::Error::NoBufs)
} else {
Err(ot::Error::Failed)
}
}
fn ip6_is_enabled(&self) -> bool {
unsafe { otIp6IsEnabled(self.as_ot_ptr()) }
}
fn ip6_set_enabled(&self, enabled: bool) -> Result {
Error::from(unsafe { otIp6SetEnabled(self.as_ot_ptr(), enabled) }).into()
}
fn ip6_add_unicast_address(&self, addr: &NetifAddress) -> Result {
Error::from(unsafe { otIp6AddUnicastAddress(self.as_ot_ptr(), addr.as_ot_ptr()) }).into()
}
fn ip6_remove_unicast_address(&self, addr: &std::net::Ipv6Addr) -> Result {
Error::from(unsafe { otIp6RemoveUnicastAddress(self.as_ot_ptr(), addr.as_ot_ptr()) }).into()
}
fn ip6_join_multicast_group(&self, addr: &std::net::Ipv6Addr) -> Result {
Error::from(unsafe { otIp6SubscribeMulticastAddress(self.as_ot_ptr(), addr.as_ot_ptr()) })
.into()
}
fn ip6_leave_multicast_group(&self, addr: &std::net::Ipv6Addr) -> Result {
Error::from(unsafe { otIp6UnsubscribeMulticastAddress(self.as_ot_ptr(), addr.as_ot_ptr()) })
.into()
}
fn ip6_set_receive_fn<'a, F>(&'a self, f: Option<F>)
where
F: FnMut(OtMessageBox<'_>) + 'a,
{
unsafe extern "C" fn _ot_ip6_receive_callback<'a, F: FnMut(OtMessageBox<'_>) + 'a>(
message: *mut otMessage,
context: *mut ::std::os::raw::c_void,
) {
trace!("_ot_ip6_receive_callback");
let message = OtMessageBox::from_ot_ptr(message)
.expect("_ot_ip6_receive_callback: Got NULL otMessage");
let sender = &mut *(context as *mut F);
sender(message)
}
let (fn_ptr, fn_box, cb): (_, _, otIp6ReceiveCallback) = if let Some(f) = f {
let mut x = Box::new(f);
(
x.as_mut() as *mut F as *mut ::std::os::raw::c_void,
Some(x as Box<dyn FnMut(OtMessageBox<'_>) + 'a>),
Some(_ot_ip6_receive_callback::<F>),
)
} else {
(std::ptr::null_mut() as *mut ::std::os::raw::c_void, None, None)
};
unsafe {
otIp6SetReceiveCallback(self.as_ot_ptr(), cb, fn_ptr);
self.borrow_backing().ip6_receive_fn.set(std::mem::transmute::<
Option<Box<dyn FnMut(OtMessageBox<'_>) + 'a>>,
Option<Box<dyn FnMut(OtMessageBox<'_>) + 'static>>,
>(fn_box));
}
}
fn ip6_set_address_fn<'a, F>(&'a self, f: Option<F>)
where
F: for<'r> FnMut(Ip6AddressInfo<'r>, bool) + 'a,
{
unsafe extern "C" fn _ot_ip6_address_callback<
'a,
F: FnMut(Ip6AddressInfo<'_>, bool) + 'a,
>(
info: *const otIp6AddressInfo,
is_added: bool,
context: *mut ::std::os::raw::c_void,
) {
trace!("_ot_ip6_address_callback");
let info = *Ip6AddressInfo::ref_from_ot_ptr(info).unwrap();
let sender = &mut *(context as *mut F);
sender(info, is_added)
}
let (fn_ptr, fn_box, cb): (_, _, otIp6AddressCallback) = if let Some(f) = f {
let mut x = Box::new(f);
(
x.as_mut() as *mut F as *mut ::std::os::raw::c_void,
Some(x as Box<dyn FnMut(Ip6AddressInfo<'_>, bool) + 'a>),
Some(_ot_ip6_address_callback::<F>),
)
} else {
(std::ptr::null_mut() as *mut ::std::os::raw::c_void, None, None)
};
unsafe {
otIp6SetAddressCallback(self.as_ot_ptr(), cb, fn_ptr);
self.borrow_backing().ip6_address_fn.set(std::mem::transmute::<
Option<Box<dyn FnMut(Ip6AddressInfo<'_>, bool) + 'a>>,
Option<Box<dyn FnMut(Ip6AddressInfo<'_>, bool) + 'static>>,
>(fn_box));
}
}
fn ip6_is_slaac_enabled(&self) -> bool {
unsafe { otIp6IsSlaacEnabled(self.as_ot_ptr()) }
}
fn ip6_set_slaac_enabled(&self, enabled: bool) {
unsafe { otIp6SetSlaacEnabled(self.as_ot_ptr(), enabled) }
}
fn icmp6_get_echo_mode(&self) -> Icmp6EchoMode {
unsafe { otIcmp6GetEchoMode(self.as_ot_ptr()) }.into()
}
fn icmp6_set_echo_mode(&self, mode: Icmp6EchoMode) {
unsafe { otIcmp6SetEchoMode(self.as_ot_ptr(), mode.into()) }
}
fn ip6_set_receive_filter_enabled(&self, enabled: bool) {
unsafe { otIp6SetReceiveFilterEnabled(self.as_ot_ptr(), enabled) }
}
fn ip6_is_receive_filter_enabled(&self) -> bool {
unsafe { otIp6IsReceiveFilterEnabled(self.as_ot_ptr()) }
}
fn ip6_get_border_routing_counters(&self) -> &BorderRoutingCounters {
unsafe {
BorderRoutingCounters::ref_from_ot_ptr(otIp6GetBorderRoutingCounters(self.as_ot_ptr()))
.unwrap()
}
}
fn ip6_get_unicast_addresses(&self) -> NetifAddressIterator<'_> {
NetifAddressIterator(unsafe {
NetifAddress::ref_from_ot_ptr(otIp6GetUnicastAddresses(self.as_ot_ptr()))
})
}
}