aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeon Camus <[email protected]>2023-03-06 17:50:57 +0100
committerLeon Camus <[email protected]>2023-03-06 18:43:37 +0100
commitc22218c72e4940a0aef3fc180ba18b557713cf40 (patch)
tree4ca355fa30267a7d4022fea1cf9b99924599b3bf
parent18fe398673f55b07159d01a230910bb9689c1525 (diff)
feat: Add multicast to udp socket
-rw-r--r--embassy-net/Cargo.toml3
-rw-r--r--embassy-net/src/lib.rs37
-rw-r--r--embassy-net/src/udp.rs45
3 files changed, 72 insertions, 13 deletions
diff --git a/embassy-net/Cargo.toml b/embassy-net/Cargo.toml
index ca34262df..1854d2043 100644
--- a/embassy-net/Cargo.toml
+++ b/embassy-net/Cargo.toml
@@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0"
8[package.metadata.embassy_docs] 8[package.metadata.embassy_docs]
9src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-v$VERSION/embassy-net/src/" 9src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-v$VERSION/embassy-net/src/"
10src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-net/src/" 10src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-net/src/"
11features = ["nightly", "unstable-traits", "defmt", "tcp", "udp", "dns", "dhcpv4", "proto-ipv6", "medium-ethernet", "medium-ip"] 11features = ["nightly", "unstable-traits", "defmt", "tcp", "udp", "dns", "dhcpv4", "proto-ipv6", "medium-ethernet", "medium-ip", "igmp"]
12target = "thumbv7em-none-eabi" 12target = "thumbv7em-none-eabi"
13 13
14[features] 14[features]
@@ -27,6 +27,7 @@ dhcpv4 = ["medium-ethernet", "smoltcp/socket-dhcpv4"]
27proto-ipv6 = ["smoltcp/proto-ipv6"] 27proto-ipv6 = ["smoltcp/proto-ipv6"]
28medium-ethernet = ["smoltcp/medium-ethernet"] 28medium-ethernet = ["smoltcp/medium-ethernet"]
29medium-ip = ["smoltcp/medium-ip"] 29medium-ip = ["smoltcp/medium-ip"]
30igmp = ["smoltcp/proto-igmp"]
30 31
31[dependencies] 32[dependencies]
32 33
diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs
index 4ec1b5a77..57055bd77 100644
--- a/embassy-net/src/lib.rs
+++ b/embassy-net/src/lib.rs
@@ -304,6 +304,43 @@ impl<D: Driver + 'static> Stack<D> {
304 } 304 }
305} 305}
306 306
307#[cfg(feature = "igmp")]
308impl<D: Driver + smoltcp::phy::Device + 'static> Stack<D> {
309 pub(crate) fn join_multicast_group<T>(&self, addr: T) -> Result<bool, smoltcp::iface::MulticastError>
310 where
311 T: Into<IpAddress>
312 {
313 let addr = addr.into();
314
315 self.with_mut(|s, i| {
316 s.iface.join_multicast_group(
317 &mut i.device,
318 addr,
319 instant_to_smoltcp(Instant::now()),
320 )
321 })
322 }
323
324 pub(crate) fn leave_multicast_group<T>(&self, addr: T) -> Result<bool, smoltcp::iface::MulticastError>
325 where
326 T: Into<IpAddress>
327 {
328 let addr = addr.into();
329
330 self.with_mut(|s, i| {
331 s.iface.leave_multicast_group(
332 &mut i.device,
333 addr,
334 instant_to_smoltcp(Instant::now()),
335 )
336 })
337 }
338
339 pub(crate) fn has_multicast_group<T: Into<IpAddress>>(&self, addr: T) -> bool {
340 self.socket.borrow().iface.has_multicast_group(addr)
341 }
342}
343
307impl SocketStack { 344impl SocketStack {
308 #[allow(clippy::absurd_extreme_comparisons, dead_code)] 345 #[allow(clippy::absurd_extreme_comparisons, dead_code)]
309 pub fn get_local_port(&mut self) -> u16 { 346 pub fn get_local_port(&mut self) -> u16 {
diff --git a/embassy-net/src/udp.rs b/embassy-net/src/udp.rs
index 0ee8c6e19..c840eeaa2 100644
--- a/embassy-net/src/udp.rs
+++ b/embassy-net/src/udp.rs
@@ -6,9 +6,9 @@ use core::task::Poll;
6use embassy_net_driver::Driver; 6use embassy_net_driver::Driver;
7use smoltcp::iface::{Interface, SocketHandle}; 7use smoltcp::iface::{Interface, SocketHandle};
8use smoltcp::socket::udp::{self, PacketMetadata}; 8use smoltcp::socket::udp::{self, PacketMetadata};
9use smoltcp::wire::{IpEndpoint, IpListenEndpoint}; 9use smoltcp::wire::{IpAddress, IpEndpoint, IpListenEndpoint};
10 10
11use crate::{SocketStack, Stack}; 11use crate::Stack;
12 12
13#[derive(PartialEq, Eq, Clone, Copy, Debug)] 13#[derive(PartialEq, Eq, Clone, Copy, Debug)]
14#[cfg_attr(feature = "defmt", derive(defmt::Format))] 14#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -26,13 +26,13 @@ pub enum Error {
26 NoRoute, 26 NoRoute,
27} 27}
28 28
29pub struct UdpSocket<'a> { 29pub struct UdpSocket<'a, D: Driver> {
30 stack: &'a RefCell<SocketStack>, 30 stack: &'a Stack<D>,
31 handle: SocketHandle, 31 handle: SocketHandle,
32} 32}
33 33
34impl<'a> UdpSocket<'a> { 34impl<'a, D: Driver> UdpSocket<'a, D> {
35 pub fn new<D: Driver>( 35 pub fn new(
36 stack: &'a Stack<D>, 36 stack: &'a Stack<D>,
37 rx_meta: &'a mut [PacketMetadata], 37 rx_meta: &'a mut [PacketMetadata],
38 rx_buffer: &'a mut [u8], 38 rx_buffer: &'a mut [u8],
@@ -51,7 +51,7 @@ impl<'a> UdpSocket<'a> {
51 )); 51 ));
52 52
53 Self { 53 Self {
54 stack: &stack.socket, 54 stack,
55 handle, 55 handle,
56 } 56 }
57 } 57 }
@@ -64,7 +64,7 @@ impl<'a> UdpSocket<'a> {
64 64
65 if endpoint.port == 0 { 65 if endpoint.port == 0 {
66 // If user didn't specify port allocate a dynamic port. 66 // If user didn't specify port allocate a dynamic port.
67 endpoint.port = self.stack.borrow_mut().get_local_port(); 67 endpoint.port = self.stack.socket.borrow_mut().get_local_port();
68 } 68 }
69 69
70 match self.with_mut(|s, _| s.bind(endpoint)) { 70 match self.with_mut(|s, _| s.bind(endpoint)) {
@@ -75,13 +75,13 @@ impl<'a> UdpSocket<'a> {
75 } 75 }
76 76
77 fn with<R>(&self, f: impl FnOnce(&udp::Socket, &Interface) -> R) -> R { 77 fn with<R>(&self, f: impl FnOnce(&udp::Socket, &Interface) -> R) -> R {
78 let s = &*self.stack.borrow(); 78 let s = &*self.stack.socket.borrow();
79 let socket = s.sockets.get::<udp::Socket>(self.handle); 79 let socket = s.sockets.get::<udp::Socket>(self.handle);
80 f(socket, &s.iface) 80 f(socket, &s.iface)
81 } 81 }
82 82
83 fn with_mut<R>(&self, f: impl FnOnce(&mut udp::Socket, &mut Interface) -> R) -> R { 83 fn with_mut<R>(&self, f: impl FnOnce(&mut udp::Socket, &mut Interface) -> R) -> R {
84 let s = &mut *self.stack.borrow_mut(); 84 let s = &mut *self.stack.socket.borrow_mut();
85 let socket = s.sockets.get_mut::<udp::Socket>(self.handle); 85 let socket = s.sockets.get_mut::<udp::Socket>(self.handle);
86 let res = f(socket, &mut s.iface); 86 let res = f(socket, &mut s.iface);
87 s.waker.wake(); 87 s.waker.wake();
@@ -143,8 +143,29 @@ impl<'a> UdpSocket<'a> {
143 } 143 }
144} 144}
145 145
146impl Drop for UdpSocket<'_> { 146#[cfg(feature = "igmp")]
147impl<'a, D: Driver + smoltcp::phy::Device + 'static> UdpSocket<'a, D> {
148 pub fn join_multicast_group<T>(&self, addr: T) -> Result<bool, smoltcp::iface::MulticastError>
149 where
150 T: Into<IpAddress>
151 {
152 self.stack.join_multicast_group(addr)
153 }
154
155 pub fn leave_multicast_group<T>(&self, addr: T) -> Result<bool, smoltcp::iface::MulticastError>
156 where
157 T: Into<IpAddress>
158 {
159 self.stack.leave_multicast_group(addr)
160 }
161
162 pub fn has_multicast_group<T: Into<IpAddress>>(&self, addr: T) -> bool {
163 self.stack.has_multicast_group(addr)
164 }
165}
166
167impl<D: Driver> Drop for UdpSocket<'_, D> {
147 fn drop(&mut self) { 168 fn drop(&mut self) {
148 self.stack.borrow_mut().sockets.remove(self.handle); 169 self.stack.socket.borrow_mut().sockets.remove(self.handle);
149 } 170 }
150} 171}