feat: Add multicast to udp socket
This commit is contained in:
parent
18fe398673
commit
c22218c72e
@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0"
|
|||||||
[package.metadata.embassy_docs]
|
[package.metadata.embassy_docs]
|
||||||
src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-v$VERSION/embassy-net/src/"
|
src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-v$VERSION/embassy-net/src/"
|
||||||
src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-net/src/"
|
src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-net/src/"
|
||||||
features = ["nightly", "unstable-traits", "defmt", "tcp", "udp", "dns", "dhcpv4", "proto-ipv6", "medium-ethernet", "medium-ip"]
|
features = ["nightly", "unstable-traits", "defmt", "tcp", "udp", "dns", "dhcpv4", "proto-ipv6", "medium-ethernet", "medium-ip", "igmp"]
|
||||||
target = "thumbv7em-none-eabi"
|
target = "thumbv7em-none-eabi"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
@ -27,6 +27,7 @@ dhcpv4 = ["medium-ethernet", "smoltcp/socket-dhcpv4"]
|
|||||||
proto-ipv6 = ["smoltcp/proto-ipv6"]
|
proto-ipv6 = ["smoltcp/proto-ipv6"]
|
||||||
medium-ethernet = ["smoltcp/medium-ethernet"]
|
medium-ethernet = ["smoltcp/medium-ethernet"]
|
||||||
medium-ip = ["smoltcp/medium-ip"]
|
medium-ip = ["smoltcp/medium-ip"]
|
||||||
|
igmp = ["smoltcp/proto-igmp"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|
||||||
|
@ -304,6 +304,43 @@ impl<D: Driver + 'static> Stack<D> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "igmp")]
|
||||||
|
impl<D: Driver + smoltcp::phy::Device + 'static> Stack<D> {
|
||||||
|
pub(crate) fn join_multicast_group<T>(&self, addr: T) -> Result<bool, smoltcp::iface::MulticastError>
|
||||||
|
where
|
||||||
|
T: Into<IpAddress>
|
||||||
|
{
|
||||||
|
let addr = addr.into();
|
||||||
|
|
||||||
|
self.with_mut(|s, i| {
|
||||||
|
s.iface.join_multicast_group(
|
||||||
|
&mut i.device,
|
||||||
|
addr,
|
||||||
|
instant_to_smoltcp(Instant::now()),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn leave_multicast_group<T>(&self, addr: T) -> Result<bool, smoltcp::iface::MulticastError>
|
||||||
|
where
|
||||||
|
T: Into<IpAddress>
|
||||||
|
{
|
||||||
|
let addr = addr.into();
|
||||||
|
|
||||||
|
self.with_mut(|s, i| {
|
||||||
|
s.iface.leave_multicast_group(
|
||||||
|
&mut i.device,
|
||||||
|
addr,
|
||||||
|
instant_to_smoltcp(Instant::now()),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn has_multicast_group<T: Into<IpAddress>>(&self, addr: T) -> bool {
|
||||||
|
self.socket.borrow().iface.has_multicast_group(addr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl SocketStack {
|
impl SocketStack {
|
||||||
#[allow(clippy::absurd_extreme_comparisons, dead_code)]
|
#[allow(clippy::absurd_extreme_comparisons, dead_code)]
|
||||||
pub fn get_local_port(&mut self) -> u16 {
|
pub fn get_local_port(&mut self) -> u16 {
|
||||||
|
@ -6,9 +6,9 @@ use core::task::Poll;
|
|||||||
use embassy_net_driver::Driver;
|
use embassy_net_driver::Driver;
|
||||||
use smoltcp::iface::{Interface, SocketHandle};
|
use smoltcp::iface::{Interface, SocketHandle};
|
||||||
use smoltcp::socket::udp::{self, PacketMetadata};
|
use smoltcp::socket::udp::{self, PacketMetadata};
|
||||||
use smoltcp::wire::{IpEndpoint, IpListenEndpoint};
|
use smoltcp::wire::{IpAddress, IpEndpoint, IpListenEndpoint};
|
||||||
|
|
||||||
use crate::{SocketStack, Stack};
|
use crate::Stack;
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
@ -26,13 +26,13 @@ pub enum Error {
|
|||||||
NoRoute,
|
NoRoute,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct UdpSocket<'a> {
|
pub struct UdpSocket<'a, D: Driver> {
|
||||||
stack: &'a RefCell<SocketStack>,
|
stack: &'a Stack<D>,
|
||||||
handle: SocketHandle,
|
handle: SocketHandle,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> UdpSocket<'a> {
|
impl<'a, D: Driver> UdpSocket<'a, D> {
|
||||||
pub fn new<D: Driver>(
|
pub fn new(
|
||||||
stack: &'a Stack<D>,
|
stack: &'a Stack<D>,
|
||||||
rx_meta: &'a mut [PacketMetadata],
|
rx_meta: &'a mut [PacketMetadata],
|
||||||
rx_buffer: &'a mut [u8],
|
rx_buffer: &'a mut [u8],
|
||||||
@ -51,7 +51,7 @@ impl<'a> UdpSocket<'a> {
|
|||||||
));
|
));
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
stack: &stack.socket,
|
stack,
|
||||||
handle,
|
handle,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -64,7 +64,7 @@ impl<'a> UdpSocket<'a> {
|
|||||||
|
|
||||||
if endpoint.port == 0 {
|
if endpoint.port == 0 {
|
||||||
// If user didn't specify port allocate a dynamic port.
|
// If user didn't specify port allocate a dynamic port.
|
||||||
endpoint.port = self.stack.borrow_mut().get_local_port();
|
endpoint.port = self.stack.socket.borrow_mut().get_local_port();
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.with_mut(|s, _| s.bind(endpoint)) {
|
match self.with_mut(|s, _| s.bind(endpoint)) {
|
||||||
@ -75,13 +75,13 @@ impl<'a> UdpSocket<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn with<R>(&self, f: impl FnOnce(&udp::Socket, &Interface) -> R) -> R {
|
fn with<R>(&self, f: impl FnOnce(&udp::Socket, &Interface) -> R) -> R {
|
||||||
let s = &*self.stack.borrow();
|
let s = &*self.stack.socket.borrow();
|
||||||
let socket = s.sockets.get::<udp::Socket>(self.handle);
|
let socket = s.sockets.get::<udp::Socket>(self.handle);
|
||||||
f(socket, &s.iface)
|
f(socket, &s.iface)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_mut<R>(&self, f: impl FnOnce(&mut udp::Socket, &mut Interface) -> R) -> R {
|
fn with_mut<R>(&self, f: impl FnOnce(&mut udp::Socket, &mut Interface) -> R) -> R {
|
||||||
let s = &mut *self.stack.borrow_mut();
|
let s = &mut *self.stack.socket.borrow_mut();
|
||||||
let socket = s.sockets.get_mut::<udp::Socket>(self.handle);
|
let socket = s.sockets.get_mut::<udp::Socket>(self.handle);
|
||||||
let res = f(socket, &mut s.iface);
|
let res = f(socket, &mut s.iface);
|
||||||
s.waker.wake();
|
s.waker.wake();
|
||||||
@ -143,8 +143,29 @@ impl<'a> UdpSocket<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for UdpSocket<'_> {
|
#[cfg(feature = "igmp")]
|
||||||
fn drop(&mut self) {
|
impl<'a, D: Driver + smoltcp::phy::Device + 'static> UdpSocket<'a, D> {
|
||||||
self.stack.borrow_mut().sockets.remove(self.handle);
|
pub fn join_multicast_group<T>(&self, addr: T) -> Result<bool, smoltcp::iface::MulticastError>
|
||||||
|
where
|
||||||
|
T: Into<IpAddress>
|
||||||
|
{
|
||||||
|
self.stack.join_multicast_group(addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn leave_multicast_group<T>(&self, addr: T) -> Result<bool, smoltcp::iface::MulticastError>
|
||||||
|
where
|
||||||
|
T: Into<IpAddress>
|
||||||
|
{
|
||||||
|
self.stack.leave_multicast_group(addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn has_multicast_group<T: Into<IpAddress>>(&self, addr: T) -> bool {
|
||||||
|
self.stack.has_multicast_group(addr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D: Driver> Drop for UdpSocket<'_, D> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.stack.socket.borrow_mut().sockets.remove(self.handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user