use shared_bus::{AtomicCheckMutex, BusMutex};
pub struct NetworkManager<'a, Device, Clock>
where
Device: smoltcp::phy::Device,
Clock: embedded_time::Clock,
u32: From<Clock::T>,
{
mutex: AtomicCheckMutex<crate::NetworkStack<'a, Device, Clock>>,
}
pub struct NetworkStackProxy<'a, S> {
mutex: &'a AtomicCheckMutex<S>,
}
impl<'a, S> NetworkStackProxy<'a, S> {
pub fn lock<R, F: FnOnce(&mut S) -> R>(&mut self, f: F) -> R {
self.mutex.lock(|stack| f(stack))
}
}
macro_rules! forward {
($func:ident($($v:ident: $IT:ty),*) -> $T:ty) => {
fn $func(&mut self, $($v: $IT),*) -> $T {
self.mutex.lock(|stack| stack.$func($($v),*))
}
}
}
impl<'a, S> embedded_nal::TcpClientStack for NetworkStackProxy<'a, S>
where
S: embedded_nal::TcpClientStack,
{
type TcpSocket = S::TcpSocket;
type Error = S::Error;
forward! {socket() -> Result<S::TcpSocket, S::Error>}
forward! {connect(socket: &mut S::TcpSocket, remote: core::net::SocketAddr) -> embedded_nal::nb::Result<(), S::Error>}
forward! {send(socket: &mut S::TcpSocket, buffer: &[u8]) -> embedded_nal::nb::Result<usize, S::Error>}
forward! {receive(socket: &mut S::TcpSocket, buffer: &mut [u8]) -> embedded_nal::nb::Result<usize, S::Error>}
forward! {close(socket: S::TcpSocket) -> Result<(), S::Error>}
}
impl<'a, S> embedded_nal::UdpClientStack for NetworkStackProxy<'a, S>
where
S: embedded_nal::UdpClientStack,
{
type UdpSocket = S::UdpSocket;
type Error = S::Error;
forward! {socket() -> Result<S::UdpSocket, S::Error>}
forward! {connect(socket: &mut S::UdpSocket, remote: core::net::SocketAddr) -> Result<(), S::Error>}
forward! {send(socket: &mut S::UdpSocket, buffer: &[u8]) -> embedded_nal::nb::Result<(), S::Error>}
forward! {receive(socket: &mut S::UdpSocket, buffer: &mut [u8]) -> embedded_nal::nb::Result<(usize, core::net::SocketAddr), S::Error>}
forward! {close(socket: S::UdpSocket) -> Result<(), S::Error>}
}
impl<'a, S> embedded_nal::UdpFullStack for NetworkStackProxy<'a, S>
where
S: embedded_nal::UdpFullStack,
{
forward! {send_to(socket: &mut S::UdpSocket, remote: core::net::SocketAddr, buffer: &[u8]) -> embedded_nal::nb::Result<(), S::Error>}
forward! {bind(socket: &mut S::UdpSocket, local_port: u16) -> Result<(), S::Error>}
}
impl<'a, S> embedded_nal::Dns for NetworkStackProxy<'a, S>
where
S: embedded_nal::Dns,
{
type Error = S::Error;
forward! {get_host_by_name(hostname: &str, addr_type: embedded_nal::AddrType) -> embedded_nal::nb::Result<core::net::IpAddr, Self::Error>}
fn get_host_by_address(
&mut self,
addr: core::net::IpAddr,
buf: &mut [u8],
) -> Result<usize, embedded_nal::nb::Error<Self::Error>> {
self.mutex
.lock(|stack| stack.get_host_by_address(addr, buf))
}
}
impl<'a, Device, Clock> NetworkManager<'a, Device, Clock>
where
Device: smoltcp::phy::Device,
Clock: embedded_time::Clock,
u32: From<Clock::T>,
{
pub fn new(stack: crate::NetworkStack<'a, Device, Clock>) -> Self {
Self {
mutex: AtomicCheckMutex::create(stack),
}
}
pub fn acquire_stack(
&'_ self,
) -> NetworkStackProxy<'_, crate::NetworkStack<'a, Device, Clock>> {
NetworkStackProxy { mutex: &self.mutex }
}
}