diff options
| author | Leon Camus <[email protected]> | 2023-03-06 17:50:57 +0100 |
|---|---|---|
| committer | Leon Camus <[email protected]> | 2023-03-06 18:43:37 +0100 |
| commit | c22218c72e4940a0aef3fc180ba18b557713cf40 (patch) | |
| tree | 4ca355fa30267a7d4022fea1cf9b99924599b3bf | |
| parent | 18fe398673f55b07159d01a230910bb9689c1525 (diff) | |
feat: Add multicast to udp socket
| -rw-r--r-- | embassy-net/Cargo.toml | 3 | ||||
| -rw-r--r-- | embassy-net/src/lib.rs | 37 | ||||
| -rw-r--r-- | embassy-net/src/udp.rs | 45 |
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] |
| 9 | src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-v$VERSION/embassy-net/src/" | 9 | src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-v$VERSION/embassy-net/src/" |
| 10 | src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-net/src/" | 10 | src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-net/src/" |
| 11 | features = ["nightly", "unstable-traits", "defmt", "tcp", "udp", "dns", "dhcpv4", "proto-ipv6", "medium-ethernet", "medium-ip"] | 11 | features = ["nightly", "unstable-traits", "defmt", "tcp", "udp", "dns", "dhcpv4", "proto-ipv6", "medium-ethernet", "medium-ip", "igmp"] |
| 12 | target = "thumbv7em-none-eabi" | 12 | target = "thumbv7em-none-eabi" |
| 13 | 13 | ||
| 14 | [features] | 14 | [features] |
| @@ -27,6 +27,7 @@ dhcpv4 = ["medium-ethernet", "smoltcp/socket-dhcpv4"] | |||
| 27 | proto-ipv6 = ["smoltcp/proto-ipv6"] | 27 | proto-ipv6 = ["smoltcp/proto-ipv6"] |
| 28 | medium-ethernet = ["smoltcp/medium-ethernet"] | 28 | medium-ethernet = ["smoltcp/medium-ethernet"] |
| 29 | medium-ip = ["smoltcp/medium-ip"] | 29 | medium-ip = ["smoltcp/medium-ip"] |
| 30 | igmp = ["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")] | ||
| 308 | impl<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 | |||
| 307 | impl SocketStack { | 344 | impl 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; | |||
| 6 | use embassy_net_driver::Driver; | 6 | use embassy_net_driver::Driver; |
| 7 | use smoltcp::iface::{Interface, SocketHandle}; | 7 | use smoltcp::iface::{Interface, SocketHandle}; |
| 8 | use smoltcp::socket::udp::{self, PacketMetadata}; | 8 | use smoltcp::socket::udp::{self, PacketMetadata}; |
| 9 | use smoltcp::wire::{IpEndpoint, IpListenEndpoint}; | 9 | use smoltcp::wire::{IpAddress, IpEndpoint, IpListenEndpoint}; |
| 10 | 10 | ||
| 11 | use crate::{SocketStack, Stack}; | 11 | use 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 | ||
| 29 | pub struct UdpSocket<'a> { | 29 | pub 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 | ||
| 34 | impl<'a> UdpSocket<'a> { | 34 | impl<'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 | ||
| 146 | impl Drop for UdpSocket<'_> { | 146 | #[cfg(feature = "igmp")] |
| 147 | impl<'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 | |||
| 167 | impl<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 | } |
