diff options
| author | chrysn <[email protected]> | 2024-04-19 15:22:57 +0200 |
|---|---|---|
| committer | chrysn <[email protected]> | 2024-04-19 15:22:57 +0200 |
| commit | e6bf6c7a49fbcf16253343fb2fbc4bdb1693c908 (patch) | |
| tree | 94e8da7dac3a6430af70b8b1aeca04265d563f0c /embassy-net/src | |
| parent | 8fe88847d81afceaa55aa68662d4162d5c12f804 (diff) | |
| parent | da86c086510490602ffdd688760fb59cc7a1e524 (diff) | |
Merge branch 'main' into prep-embedded-nal-async-udp
Diffstat (limited to 'embassy-net/src')
| -rw-r--r-- | embassy-net/src/lib.rs | 2 | ||||
| -rw-r--r-- | embassy-net/src/raw.rs | 120 |
2 files changed, 122 insertions, 0 deletions
diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index 1c0cf1a12..86ced1ded 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs | |||
| @@ -15,6 +15,8 @@ pub(crate) mod fmt; | |||
| 15 | mod device; | 15 | mod device; |
| 16 | #[cfg(feature = "dns")] | 16 | #[cfg(feature = "dns")] |
| 17 | pub mod dns; | 17 | pub mod dns; |
| 18 | #[cfg(feature = "raw")] | ||
| 19 | pub mod raw; | ||
| 18 | #[cfg(feature = "tcp")] | 20 | #[cfg(feature = "tcp")] |
| 19 | pub mod tcp; | 21 | pub mod tcp; |
| 20 | mod time; | 22 | mod time; |
diff --git a/embassy-net/src/raw.rs b/embassy-net/src/raw.rs new file mode 100644 index 000000000..7ecd913e7 --- /dev/null +++ b/embassy-net/src/raw.rs | |||
| @@ -0,0 +1,120 @@ | |||
| 1 | //! Raw sockets. | ||
| 2 | |||
| 3 | use core::cell::RefCell; | ||
| 4 | use core::future::poll_fn; | ||
| 5 | use core::mem; | ||
| 6 | use core::task::{Context, Poll}; | ||
| 7 | |||
| 8 | use embassy_net_driver::Driver; | ||
| 9 | use smoltcp::iface::{Interface, SocketHandle}; | ||
| 10 | use smoltcp::socket::raw; | ||
| 11 | pub use smoltcp::socket::raw::PacketMetadata; | ||
| 12 | use smoltcp::wire::{IpProtocol, IpVersion}; | ||
| 13 | |||
| 14 | use crate::{SocketStack, Stack}; | ||
| 15 | |||
| 16 | /// Error returned by [`RawSocket::recv`] and [`RawSocket::send`]. | ||
| 17 | #[derive(PartialEq, Eq, Clone, Copy, Debug)] | ||
| 18 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 19 | pub enum RecvError { | ||
| 20 | /// Provided buffer was smaller than the received packet. | ||
| 21 | Truncated, | ||
| 22 | } | ||
| 23 | |||
| 24 | /// An Raw socket. | ||
| 25 | pub struct RawSocket<'a> { | ||
| 26 | stack: &'a RefCell<SocketStack>, | ||
| 27 | handle: SocketHandle, | ||
| 28 | } | ||
| 29 | |||
| 30 | impl<'a> RawSocket<'a> { | ||
| 31 | /// Create a new Raw socket using the provided stack and buffers. | ||
| 32 | pub fn new<D: Driver>( | ||
| 33 | stack: &'a Stack<D>, | ||
| 34 | ip_version: IpVersion, | ||
| 35 | ip_protocol: IpProtocol, | ||
| 36 | rx_meta: &'a mut [PacketMetadata], | ||
| 37 | rx_buffer: &'a mut [u8], | ||
| 38 | tx_meta: &'a mut [PacketMetadata], | ||
| 39 | tx_buffer: &'a mut [u8], | ||
| 40 | ) -> Self { | ||
| 41 | let s = &mut *stack.socket.borrow_mut(); | ||
| 42 | |||
| 43 | let rx_meta: &'static mut [PacketMetadata] = unsafe { mem::transmute(rx_meta) }; | ||
| 44 | let rx_buffer: &'static mut [u8] = unsafe { mem::transmute(rx_buffer) }; | ||
| 45 | let tx_meta: &'static mut [PacketMetadata] = unsafe { mem::transmute(tx_meta) }; | ||
| 46 | let tx_buffer: &'static mut [u8] = unsafe { mem::transmute(tx_buffer) }; | ||
| 47 | let handle = s.sockets.add(raw::Socket::new( | ||
| 48 | ip_version, | ||
| 49 | ip_protocol, | ||
| 50 | raw::PacketBuffer::new(rx_meta, rx_buffer), | ||
| 51 | raw::PacketBuffer::new(tx_meta, tx_buffer), | ||
| 52 | )); | ||
| 53 | |||
| 54 | Self { | ||
| 55 | stack: &stack.socket, | ||
| 56 | handle, | ||
| 57 | } | ||
| 58 | } | ||
| 59 | |||
| 60 | fn with_mut<R>(&self, f: impl FnOnce(&mut raw::Socket, &mut Interface) -> R) -> R { | ||
| 61 | let s = &mut *self.stack.borrow_mut(); | ||
| 62 | let socket = s.sockets.get_mut::<raw::Socket>(self.handle); | ||
| 63 | let res = f(socket, &mut s.iface); | ||
| 64 | s.waker.wake(); | ||
| 65 | res | ||
| 66 | } | ||
| 67 | |||
| 68 | /// Receive a datagram. | ||
| 69 | /// | ||
| 70 | /// This method will wait until a datagram is received. | ||
| 71 | pub async fn recv(&self, buf: &mut [u8]) -> Result<usize, RecvError> { | ||
| 72 | poll_fn(move |cx| self.poll_recv(buf, cx)).await | ||
| 73 | } | ||
| 74 | |||
| 75 | /// Receive a datagram. | ||
| 76 | /// | ||
| 77 | /// When no datagram is available, this method will return `Poll::Pending` and | ||
| 78 | /// register the current task to be notified when a datagram is received. | ||
| 79 | pub fn poll_recv(&self, buf: &mut [u8], cx: &mut Context<'_>) -> Poll<Result<usize, RecvError>> { | ||
| 80 | self.with_mut(|s, _| match s.recv_slice(buf) { | ||
| 81 | Ok(n) => Poll::Ready(Ok(n)), | ||
| 82 | // No data ready | ||
| 83 | Err(raw::RecvError::Truncated) => Poll::Ready(Err(RecvError::Truncated)), | ||
| 84 | Err(raw::RecvError::Exhausted) => { | ||
| 85 | s.register_recv_waker(cx.waker()); | ||
| 86 | Poll::Pending | ||
| 87 | } | ||
| 88 | }) | ||
| 89 | } | ||
| 90 | |||
| 91 | /// Send a datagram. | ||
| 92 | /// | ||
| 93 | /// This method will wait until the datagram has been sent.` | ||
| 94 | pub async fn send(&self, buf: &[u8]) { | ||
| 95 | poll_fn(move |cx| self.poll_send(buf, cx)).await | ||
| 96 | } | ||
| 97 | |||
| 98 | /// Send a datagram. | ||
| 99 | /// | ||
| 100 | /// When the datagram has been sent, this method will return `Poll::Ready(Ok())`. | ||
| 101 | /// | ||
| 102 | /// When the socket's send buffer is full, this method will return `Poll::Pending` | ||
| 103 | /// and register the current task to be notified when the buffer has space available. | ||
| 104 | pub fn poll_send(&self, buf: &[u8], cx: &mut Context<'_>) -> Poll<()> { | ||
| 105 | self.with_mut(|s, _| match s.send_slice(buf) { | ||
| 106 | // Entire datagram has been sent | ||
| 107 | Ok(()) => Poll::Ready(()), | ||
| 108 | Err(raw::SendError::BufferFull) => { | ||
| 109 | s.register_send_waker(cx.waker()); | ||
| 110 | Poll::Pending | ||
| 111 | } | ||
| 112 | }) | ||
| 113 | } | ||
| 114 | } | ||
| 115 | |||
| 116 | impl Drop for RawSocket<'_> { | ||
| 117 | fn drop(&mut self) { | ||
| 118 | self.stack.borrow_mut().sockets.remove(self.handle); | ||
| 119 | } | ||
| 120 | } | ||
