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}