aboutsummaryrefslogtreecommitdiff
path: root/embassy-net
diff options
context:
space:
mode:
authorchrysn <[email protected]>2024-04-19 15:22:57 +0200
committerchrysn <[email protected]>2024-04-19 15:22:57 +0200
commite6bf6c7a49fbcf16253343fb2fbc4bdb1693c908 (patch)
tree94e8da7dac3a6430af70b8b1aeca04265d563f0c /embassy-net
parent8fe88847d81afceaa55aa68662d4162d5c12f804 (diff)
parentda86c086510490602ffdd688760fb59cc7a1e524 (diff)
Merge branch 'main' into prep-embedded-nal-async-udp
Diffstat (limited to 'embassy-net')
-rw-r--r--embassy-net/Cargo.toml6
-rw-r--r--embassy-net/README.md4
-rw-r--r--embassy-net/src/lib.rs2
-rw-r--r--embassy-net/src/raw.rs120
4 files changed, 128 insertions, 4 deletions
diff --git a/embassy-net/Cargo.toml b/embassy-net/Cargo.toml
index be9f1d784..ee7289ad8 100644
--- a/embassy-net/Cargo.toml
+++ b/embassy-net/Cargo.toml
@@ -16,11 +16,11 @@ categories = [
16[package.metadata.embassy_docs] 16[package.metadata.embassy_docs]
17src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-v$VERSION/embassy-net/src/" 17src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-v$VERSION/embassy-net/src/"
18src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-net/src/" 18src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-net/src/"
19features = ["defmt", "tcp", "udp", "dns", "dhcpv4", "proto-ipv6", "medium-ethernet", "medium-ip", "medium-ieee802154", "igmp", "dhcpv4-hostname"] 19features = ["defmt", "tcp", "udp", "raw", "dns", "dhcpv4", "proto-ipv6", "medium-ethernet", "medium-ip", "medium-ieee802154", "igmp", "dhcpv4-hostname"]
20target = "thumbv7em-none-eabi" 20target = "thumbv7em-none-eabi"
21 21
22[package.metadata.docs.rs] 22[package.metadata.docs.rs]
23features = ["defmt", "tcp", "udp", "dns", "dhcpv4", "proto-ipv6", "medium-ethernet", "medium-ip", "medium-ieee802154", "igmp", "dhcpv4-hostname"] 23features = ["defmt", "tcp", "udp", "raw", "dns", "dhcpv4", "proto-ipv6", "medium-ethernet", "medium-ip", "medium-ieee802154", "igmp", "dhcpv4-hostname"]
24 24
25[features] 25[features]
26default = [] 26default = []
@@ -38,6 +38,8 @@ packet-trace = []
38 38
39## Enable UDP support 39## Enable UDP support
40udp = ["smoltcp/socket-udp"] 40udp = ["smoltcp/socket-udp"]
41## Enable Raw support
42raw = ["smoltcp/socket-raw"]
41## Enable TCP support 43## Enable TCP support
42tcp = ["smoltcp/socket-tcp"] 44tcp = ["smoltcp/socket-tcp"]
43## Enable DNS support 45## Enable DNS support
diff --git a/embassy-net/README.md b/embassy-net/README.md
index 94aa6f550..ce59ea34a 100644
--- a/embassy-net/README.md
+++ b/embassy-net/README.md
@@ -13,8 +13,8 @@ memory management designed to work well for embedded systems, aiming for a more
13- TCP, UDP, DNS, DHCPv4, IGMPv4 13- TCP, UDP, DNS, DHCPv4, IGMPv4
14- TCP sockets implement the `embedded-io` async traits. 14- TCP sockets implement the `embedded-io` async traits.
15 15
16See the [`smoltcp`](https://github.com/smoltcp-rs/smoltcp) README for a detailed list of implemented and 16See the [`smoltcp`](https://github.com/smoltcp-rs/smoltcp) README for a detailed list of implemented and
17unimplemented features of the network protocols. 17unimplemented features of the network protocols.
18 18
19## Hardware support 19## Hardware support
20 20
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;
15mod device; 15mod device;
16#[cfg(feature = "dns")] 16#[cfg(feature = "dns")]
17pub mod dns; 17pub mod dns;
18#[cfg(feature = "raw")]
19pub mod raw;
18#[cfg(feature = "tcp")] 20#[cfg(feature = "tcp")]
19pub mod tcp; 21pub mod tcp;
20mod time; 22mod 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
3use core::cell::RefCell;
4use core::future::poll_fn;
5use core::mem;
6use core::task::{Context, Poll};
7
8use embassy_net_driver::Driver;
9use smoltcp::iface::{Interface, SocketHandle};
10use smoltcp::socket::raw;
11pub use smoltcp::socket::raw::PacketMetadata;
12use smoltcp::wire::{IpProtocol, IpVersion};
13
14use 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))]
19pub enum RecvError {
20 /// Provided buffer was smaller than the received packet.
21 Truncated,
22}
23
24/// An Raw socket.
25pub struct RawSocket<'a> {
26 stack: &'a RefCell<SocketStack>,
27 handle: SocketHandle,
28}
29
30impl<'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
116impl Drop for RawSocket<'_> {
117 fn drop(&mut self) {
118 self.stack.borrow_mut().sockets.remove(self.handle);
119 }
120}