embedded_nal/stack/
share.rs

1use crate::{nb, TcpClientStack, TcpFullStack, UdpClientStack, UdpFullStack};
2use core::cell::RefCell;
3use core::net::SocketAddr;
4
5/// Sharable wrapper for a network stack implementation.
6///
7/// An implementation of the stack traits that can contain (and provide provide
8/// single-threaded shared access to) another stack implementation. A direct
9/// implementation can only be used when owned or with a mutable reference.
10/// This implementation will store another implementation internally, and yield
11/// an arbitrary number of shared references to it, which themselves implement
12/// the stack traits.
13///
14/// ```
15/// use embedded_nal::SharableStack;
16/// use core::net::{SocketAddr, SocketAddrV4, Ipv4Addr};
17/// # use embedded_nal::{UdpClientStack, nb};
18/// # struct SomeNalDriver {}
19/// # impl SomeNalDriver {
20/// #   fn new() -> Self { Self {} }
21/// # }
22/// # impl UdpClientStack for SomeNalDriver {
23/// #   type Error = ();
24/// #   type UdpSocket = ();
25/// #   fn socket(&mut self) -> Result<Self::UdpSocket, Self::Error> {
26/// #     Ok(())
27/// #   }
28/// #   fn connect(
29/// #       &mut self,
30/// #       socket: &mut Self::UdpSocket,
31/// #       remote: SocketAddr,
32/// #   ) -> Result<(), Self::Error> {
33/// #     Ok(())
34/// #   }
35/// #   fn send(&mut self, socket: &mut Self::UdpSocket, buffer: &[u8]) -> nb::Result<(), Self::Error> {
36/// #     Ok(())
37/// #   }
38/// #   fn receive(
39/// #       &mut self,
40/// #       socket: &mut Self::UdpSocket,
41/// #       buffer: &mut [u8],
42/// #   ) -> nb::Result<(usize, SocketAddr), Self::Error> {
43/// #     Ok((0, SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 0))))
44/// #   }
45/// #   fn close(&mut self, socket: Self::UdpSocket) -> Result<(), Self::Error> {
46/// #     Ok(())
47/// #   }
48/// # }
49/// let mut driver = SomeNalDriver::new();
50/// // Driver can only be used in one place at a time.
51/// let mut sharable_driver = SharableStack::new(driver);
52/// // Sharable driver can't do anything on its own, but it can create many usable copies.
53/// let mut shared_driver0 = sharable_driver.acquire();
54/// let mut shared_driver1 = sharable_driver.acquire();
55/// // These shared copies can be passed around to other parts of an application's code, and used
56/// // independently.
57/// let mut socket0 = shared_driver0.socket()?;
58/// shared_driver0.connect(&mut socket0, SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080)));
59/// // ...
60///
61/// // ... and somewhere else
62/// let mut socket1 = shared_driver1.socket()?;
63/// shared_driver1.connect(&mut socket1, SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8443)));
64/// // ...
65/// # Ok::<(), ()>(())
66/// ```
67pub struct SharableStack<T> {
68	stack: RefCell<T>,
69}
70
71impl<T> SharableStack<T> {
72	/// Create a new SharedStack that contains and uses some other stack implementation.
73	pub fn new(stack: T) -> Self {
74		SharableStack {
75			stack: RefCell::new(stack),
76		}
77	}
78
79	/// Returns a shared reference to the driver that can be used as a first-class implementation.
80	pub fn acquire(&self) -> SharedStack<T> {
81		SharedStack { stack: &self.stack }
82	}
83}
84
85/// Single-thread shared reference to an internal network stack implementation.
86///
87/// This can only be created by calling [`SharableStack::acquire()`]
88pub struct SharedStack<'a, T> {
89	stack: &'a RefCell<T>,
90}
91
92macro_rules! forward {
93    ($func:ident($($v:ident: $IT:ty),*) -> $T:ty) => {
94        fn $func(&mut self, $($v: $IT),*) -> $T {
95            self.stack.borrow_mut().$func($($v),*)
96        }
97    }
98}
99
100impl<'a, T> UdpClientStack for SharedStack<'a, T>
101where
102	T: UdpClientStack,
103{
104	type Error = T::Error;
105	type UdpSocket = T::UdpSocket;
106
107	forward! {socket() -> Result<Self::UdpSocket, Self::Error>}
108	forward! {connect(socket: &mut Self::UdpSocket, address: SocketAddr) -> Result<(), Self::Error>}
109	forward! {send(socket: &mut Self::UdpSocket, data: &[u8]) -> Result<(), nb::Error<<T as UdpClientStack>::Error>>}
110	forward! {receive(socket: &mut Self::UdpSocket, data: &mut [u8]) -> Result<(usize, SocketAddr), nb::Error<<T as UdpClientStack>::Error>>}
111	forward! {close(socket: Self::UdpSocket) -> Result<(), Self::Error>}
112}
113
114impl<'a, T> UdpFullStack for SharedStack<'a, T>
115where
116	T: UdpFullStack,
117{
118	forward! {bind(socket: &mut Self::UdpSocket, local_port: u16) -> Result<(), Self::Error>}
119	forward! {send_to(socket: &mut Self::UdpSocket, remote: SocketAddr, buffer: &[u8]) -> Result<(), nb::Error<<T as UdpClientStack>::Error>>}
120}
121
122impl<'a, T> TcpClientStack for SharedStack<'a, T>
123where
124	T: TcpClientStack,
125{
126	type TcpSocket = T::TcpSocket;
127	type Error = T::Error;
128
129	forward! {socket() -> Result<Self::TcpSocket, Self::Error>}
130	forward! {connect(socket: &mut Self::TcpSocket, address: SocketAddr) -> Result<(), nb::Error<<T as TcpClientStack>::Error>>}
131	forward! {send(socket: &mut Self::TcpSocket, data: &[u8]) -> Result<usize, nb::Error<<T as TcpClientStack>::Error>>}
132	forward! {receive(socket: &mut Self::TcpSocket, data: &mut [u8]) -> Result<usize, nb::Error<<T as TcpClientStack>::Error>>}
133	forward! {close(socket: Self::TcpSocket) -> Result<(), Self::Error>}
134}
135
136impl<'a, T> TcpFullStack for SharedStack<'a, T>
137where
138	T: TcpFullStack,
139{
140	forward! {bind(socket: &mut Self::TcpSocket, port: u16) -> Result<(), <T as TcpClientStack>::Error>}
141	forward! {listen(socket: &mut Self::TcpSocket) -> Result<(), <T as TcpClientStack>::Error>}
142	forward! {accept(socket: &mut Self::TcpSocket) -> Result<(<T as TcpClientStack>::TcpSocket, SocketAddr), nb::Error<<T as TcpClientStack>::Error>>}
143}