use core::fmt::{self, Debug, Display};
use core::future::Future;
use core::pin::pin;
pub use core::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
use embassy_futures::select::{select, Either};
use crate::error::{Error, ErrorCode};
pub mod btp;
pub mod mdns;
pub mod tcp;
pub mod udp;
pub mod wifi;
pub const MAX_RX_PACKET_SIZE: usize = 1583;
pub const MAX_TX_PACKET_SIZE: usize = 1280 - 40 - 8;
pub const MAX_RX_LARGE_PACKET_SIZE: usize = 1024 * 1024;
pub const MAX_TX_LARGE_PACKET_SIZE: usize = MAX_RX_LARGE_PACKET_SIZE;
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum MatterLocalService {
Commissioned {
compressed_fabric_id: u64,
node_id: u64,
},
Commissionable {
id: u64,
discriminator: u16,
enhanced: bool,
},
}
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum MatterRemoteService {
Operational {
compressed_fabric_id: u64,
node_id: u64,
},
Commissionable { id: u64 },
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub struct BtAddr(pub [u8; 6]);
impl Display for BtAddr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}",
self.0[0], self.0[1], self.0[2], self.0[3], self.0[4], self.0[5]
)
}
}
#[cfg(feature = "defmt")]
impl defmt::Format for BtAddr {
fn format(&self, f: defmt::Formatter<'_>) {
defmt::write!(
f,
"{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}",
self.0[0],
self.0[1],
self.0[2],
self.0[3],
self.0[4],
self.0[5]
)
}
}
#[derive(Eq, PartialEq, Copy, Clone)]
pub enum Address {
Udp(SocketAddr),
Tcp(SocketAddr),
Btp(BtAddr),
}
impl Address {
pub const fn new() -> Self {
Self::Udp(SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0))
}
pub const fn is_reliable(&self) -> bool {
matches!(self, Self::Tcp(_) | Self::Btp(_))
}
pub const fn is_udp(&self) -> bool {
matches!(self, Self::Udp(_))
}
pub const fn is_tcp(&self) -> bool {
matches!(self, Self::Tcp(_))
}
pub const fn is_btp(&self) -> bool {
matches!(self, Self::Btp(_))
}
pub fn canonical(self) -> Self {
match self {
Self::Udp(addr) => Self::Udp(canonical_sockaddr(addr)),
Self::Tcp(addr) => Self::Tcp(canonical_sockaddr(addr)),
other => other,
}
}
pub const fn udp(self) -> Option<SocketAddr> {
match self {
Self::Udp(addr) => Some(addr),
_ => None,
}
}
pub const fn tcp(self) -> Option<SocketAddr> {
match self {
Self::Tcp(addr) => Some(addr),
_ => None,
}
}
pub const fn btp(self) -> Option<BtAddr> {
match self {
Self::Btp(addr) => Some(addr),
_ => None,
}
}
}
fn canonical_sockaddr(addr: SocketAddr) -> SocketAddr {
match addr {
SocketAddr::V6(v6) => match v6.ip().to_canonical() {
IpAddr::V4(v4) => SocketAddr::new(IpAddr::V4(v4), v6.port()),
IpAddr::V6(_) => addr,
},
SocketAddr::V4(_) => addr,
}
}
impl Default for Address {
fn default() -> Self {
Self::new()
}
}
impl Display for Address {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Address::Udp(addr) => write!(f, "UDP {}", addr),
Address::Tcp(addr) => write!(f, "TCP {}", addr),
Address::Btp(addr) => write!(f, "BTP {}", addr),
}
}
}
impl Debug for Address {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Address::Udp(addr) => writeln!(f, "{}", addr),
Address::Tcp(addr) => writeln!(f, "{}", addr),
Address::Btp(addr) => writeln!(f, "{:?}", addr),
}
}
}
#[cfg(feature = "defmt")]
impl defmt::Format for Address {
fn format(&self, f: defmt::Formatter<'_>) {
match self {
Address::Udp(addr) => defmt::write!(f, "UDP {}", addr),
Address::Tcp(addr) => defmt::write!(f, "TCP {}", addr),
Address::Btp(addr) => defmt::write!(f, "BTP {}", addr),
}
}
}
pub trait NetworkSend {
async fn send_to(&mut self, data: &[u8], addr: Address) -> Result<(), Error>;
}
impl<T> NetworkSend for &mut T
where
T: NetworkSend,
{
fn send_to(&mut self, data: &[u8], addr: Address) -> impl Future<Output = Result<(), Error>> {
(*self).send_to(data, addr)
}
}
pub trait NetworkReceive {
async fn wait_available(&mut self) -> Result<(), Error>;
async fn recv_from(&mut self, buffer: &mut [u8]) -> Result<(usize, Address), Error>;
}
impl<T> NetworkReceive for &mut T
where
T: NetworkReceive,
{
fn wait_available(&mut self) -> impl Future<Output = Result<(), Error>> {
(*self).wait_available()
}
fn recv_from(
&mut self,
buffer: &mut [u8],
) -> impl Future<Output = Result<(usize, Address), Error>> {
(*self).recv_from(buffer)
}
}
pub trait NetworkMulticast {
async fn join(&mut self, addr: IpAddr) -> Result<(), Error>;
async fn leave(&mut self, addr: IpAddr) -> Result<(), Error>;
}
impl<T> NetworkMulticast for &mut T
where
T: NetworkMulticast,
{
fn join(&mut self, addr: IpAddr) -> impl Future<Output = Result<(), Error>> {
(*self).join(addr)
}
fn leave(&mut self, addr: IpAddr) -> impl Future<Output = Result<(), Error>> {
(*self).leave(addr)
}
}
pub struct NoNetwork;
impl NetworkSend for NoNetwork {
async fn send_to(&mut self, _data: &[u8], _addr: Address) -> Result<(), Error> {
Err(ErrorCode::NoNetworkInterface.into())
}
}
impl NetworkReceive for NoNetwork {
async fn wait_available(&mut self) -> Result<(), Error> {
core::future::pending().await
}
async fn recv_from(&mut self, _buffer: &mut [u8]) -> Result<(usize, Address), Error> {
core::future::pending().await
}
}
impl NetworkMulticast for NoNetwork {
async fn join(&mut self, _addr: IpAddr) -> Result<(), Error> {
Ok(())
}
async fn leave(&mut self, _addr: IpAddr) -> Result<(), Error> {
Ok(())
}
}
#[derive(Clone)]
pub struct ChainedNetwork<H, T, F> {
pub handler_can_send: F,
pub handler: H,
pub next: T,
}
impl<H, T, F> ChainedNetwork<H, T, F> {
pub const fn new(handler_can_send: F, handler: H, next: T) -> Self {
Self {
handler_can_send,
handler,
next,
}
}
pub const fn chain<H2, F2>(
self,
handler_can_send: F2,
handler: H2,
) -> ChainedNetwork<H2, Self, F2> {
ChainedNetwork::new(handler_can_send, handler, self)
}
}
impl<H, T, F> NetworkReceive for ChainedNetwork<H, T, F>
where
H: NetworkReceive,
T: NetworkReceive,
{
async fn wait_available(&mut self) -> Result<(), Error> {
let mut first = pin!(self.handler.wait_available());
let mut second = pin!(self.next.wait_available());
select(&mut first, &mut second).await;
Ok(())
}
async fn recv_from(&mut self, buffer: &mut [u8]) -> Result<(usize, Address), Error> {
let first = {
let mut first_available = pin!(self.handler.wait_available());
let mut second_available = pin!(self.next.wait_available());
matches!(
select(&mut first_available, &mut second_available).await,
Either::First(_)
)
};
if first {
self.handler.recv_from(buffer).await
} else {
self.next.recv_from(buffer).await
}
}
}
impl<H, T, F> NetworkSend for ChainedNetwork<H, T, F>
where
H: NetworkSend,
T: NetworkSend,
F: Fn(&Address) -> bool,
{
async fn send_to(&mut self, data: &[u8], addr: Address) -> Result<(), Error> {
if (self.handler_can_send)(&addr) {
self.handler.send_to(data, addr).await
} else {
self.next.send_to(data, addr).await
}
}
}
impl<H, T, F> NetworkMulticast for ChainedNetwork<H, T, F>
where
H: NetworkMulticast,
T: NetworkMulticast,
{
async fn join(&mut self, addr: IpAddr) -> Result<(), Error> {
self.handler.join(addr).await?;
self.next.join(addr).await
}
async fn leave(&mut self, addr: IpAddr) -> Result<(), Error> {
self.handler.leave(addr).await?;
self.next.leave(addr).await
}
}