Skip to content

Option to only select a subset of the embassy-net/smoltcp features #71

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions edge-nal-embassy/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,22 @@ categories = [
]

[features]
default = ["proto-ipv4", "proto-ipv6", "medium-ethernet", "dns", "udp", "tcp", "multicast"]
defmt = ["dep:defmt", "heapless/defmt-03", "embassy-net/defmt"]
proto-ipv4 = ["embassy-net/proto-ipv4"]
proto-ipv6 = ["embassy-net/proto-ipv6"]
medium-ethernet = ["embassy-net/medium-ethernet"]
medium-ip = ["embassy-net/medium-ip"]
dns = ["embassy-net/dns"]
udp = ["embassy-net/udp"]
tcp = ["embassy-net/tcp"]
multicast = ["embassy-net/multicast"]

[dependencies]
log = { version = "0.4", default-features = false, optional = true }
defmt = { version = "0.3", optional = true }
embedded-io-async = { workspace = true }
edge-nal = { workspace = true }
heapless = { workspace = true }
# Do not require these features and conditionalize the code instead
embassy-net = { version = "0.6", features = [
"tcp",
"udp",
"dns",
"proto-ipv6",
"medium-ethernet",
"proto-ipv4",
"multicast",
] }
embassy-net = "0.6"
embassy-futures = { workspace = true }
51 changes: 32 additions & 19 deletions edge-nal-embassy/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,26 @@

use core::cell::{Cell, UnsafeCell};
use core::mem::MaybeUninit;
use core::net::SocketAddr;
use core::net::{IpAddr, SocketAddr};
use core::ptr::NonNull;

use embassy_net::{IpEndpoint, IpListenEndpoint};
use embassy_net::{IpAddress, IpEndpoint, IpListenEndpoint};

#[cfg(feature = "dns")]
pub use dns::*;
#[cfg(feature = "tcp")]
pub use tcp::*;
#[cfg(feature = "udp")]
pub use udp::*;

// This mod MUST go first, so that the others see its macros.
pub(crate) mod fmt;

#[cfg(feature = "dns")]
mod dns;
#[cfg(feature = "tcp")]
mod tcp;
#[cfg(feature = "udp")]
mod udp;

pub(crate) struct Pool<T, const N: usize> {
Expand Down Expand Up @@ -66,26 +72,33 @@ pub(crate) fn to_net_socket(socket: IpEndpoint) -> SocketAddr {
SocketAddr::new(socket.addr.into(), socket.port)
}

// pub(crate) fn to_net_socket2(socket: IpListenEndpoint) -> SocketAddr {
// SocketAddr::new(
// socket
// .addr
// .map(to_net_addr)
// .unwrap_or(IpAddr::V6(Ipv6Addr::UNSPECIFIED)),
// socket.port,
// )
// }

pub(crate) fn to_emb_socket(socket: SocketAddr) -> IpEndpoint {
IpEndpoint {
addr: socket.ip().into(),
pub(crate) fn to_emb_socket(socket: SocketAddr) -> Option<IpEndpoint> {
Some(IpEndpoint {
addr: to_emb_addr(socket.ip())?,
port: socket.port(),
}
})
}

pub(crate) fn to_emb_bind_socket(socket: SocketAddr) -> IpListenEndpoint {
IpListenEndpoint {
addr: (!socket.ip().is_unspecified()).then(|| socket.ip().into()),
pub(crate) fn to_emb_bind_socket(socket: SocketAddr) -> Option<IpListenEndpoint> {
let addr = if socket.ip().is_unspecified() {
None
} else {
Some(to_emb_addr(socket.ip())?)
};

Some(IpListenEndpoint {
addr,
port: socket.port(),
})
}

pub(crate) fn to_emb_addr(addr: IpAddr) -> Option<IpAddress> {
match addr {
#[cfg(feature = "proto-ipv4")]
IpAddr::V4(addr) => Some(addr.into()),
#[cfg(feature = "proto-ipv6")]
IpAddr::V6(addr) => Some(addr.into()),
#[allow(unreachable_patterns)]
_ => None,
}
}
12 changes: 10 additions & 2 deletions edge-nal-embassy/src/tcp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ impl<const N: usize, const TX_SZ: usize, const RX_SZ: usize> TcpConnect
async fn connect(&self, remote: SocketAddr) -> Result<Self::Socket<'_>, Self::Error> {
let mut socket = TcpSocket::new(self.stack, self.buffers)?;

socket.socket.connect(to_emb_socket(remote)).await?;
socket
.socket
.connect(to_emb_socket(remote).ok_or(TcpError::UnsupportedProto)?)
.await?;

Ok(socket)
}
Expand Down Expand Up @@ -82,7 +85,10 @@ impl<const N: usize, const TX_SZ: usize, const RX_SZ: usize> edge_nal::TcpAccept
async fn accept(&self) -> Result<(SocketAddr, Self::Socket<'_>), Self::Error> {
let mut socket = TcpSocket::new(self.stack.stack, self.stack.buffers)?;

socket.socket.accept(to_emb_bind_socket(self.local)).await?;
socket
.socket
.accept(to_emb_bind_socket(self.local).ok_or(TcpError::UnsupportedProto)?)
.await?;

let local_endpoint = unwrap!(socket.socket.local_endpoint());

Expand Down Expand Up @@ -286,6 +292,7 @@ pub enum TcpError {
Connect(ConnectError),
Accept(AcceptError),
NoBuffers,
UnsupportedProto,
}

impl From<Error> for TcpError {
Expand Down Expand Up @@ -314,6 +321,7 @@ impl embedded_io_async::Error for TcpError {
TcpError::Connect(_) => ErrorKind::Other,
TcpError::Accept(_) => ErrorKind::Other,
TcpError::NoBuffers => ErrorKind::OutOfMemory,
TcpError::UnsupportedProto => ErrorKind::InvalidInput,
}
}
}
Expand Down
110 changes: 88 additions & 22 deletions edge-nal-embassy/src/udp.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use core::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
use core::net::{Ipv4Addr, Ipv6Addr, SocketAddr};
use core::ptr::NonNull;

use edge_nal::{MulticastV4, MulticastV6, Readable, UdpBind, UdpReceive, UdpSend, UdpSplit};

use embassy_net::udp::{BindError, PacketMetadata, RecvError, SendError};
use embassy_net::{MulticastError, Stack};
use embassy_net::Stack;

use embedded_io_async::{ErrorKind, ErrorType};

Expand Down Expand Up @@ -49,7 +49,9 @@ impl<const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> Udp
async fn bind(&self, local: SocketAddr) -> Result<Self::Socket<'_>, Self::Error> {
let mut socket = UdpSocket::new(self.stack, self.buffers)?;

socket.socket.bind(to_emb_bind_socket(local))?;
socket
.socket
.bind(to_emb_bind_socket(local).ok_or(UdpError::UnsupportedProto)?)?;

Ok(socket)
}
Expand All @@ -58,6 +60,7 @@ impl<const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> Udp
/// A UDP socket
/// Implements the `UdpReceive` `UdpSend` and `UdpSplit` traits from `edge-nal`
pub struct UdpSocket<'d, const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> {
#[allow(unused)]
stack: embassy_net::Stack<'d>,
socket: embassy_net::udp::UdpSocket<'d>,
stack_buffers: &'d UdpBuffers<N, TX_SZ, RX_SZ, M>,
Expand Down Expand Up @@ -125,7 +128,12 @@ impl<const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> Udp
for UdpSocket<'_, N, TX_SZ, RX_SZ, M>
{
async fn send(&mut self, remote: SocketAddr, data: &[u8]) -> Result<(), Self::Error> {
self.socket.send_to(data, to_emb_socket(remote)).await?;
self.socket
.send_to(
data,
to_emb_socket(remote).ok_or(UdpError::UnsupportedProto)?,
)
.await?;

Ok(())
}
Expand All @@ -151,7 +159,12 @@ impl<const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> Udp
for &UdpSocket<'_, N, TX_SZ, RX_SZ, M>
{
async fn send(&mut self, remote: SocketAddr, data: &[u8]) -> Result<(), Self::Error> {
self.socket.send_to(data, remote).await?;
self.socket
.send_to(
data,
to_emb_socket(remote).ok_or(UdpError::UnsupportedProto)?,
)
.await?;

Ok(())
}
Expand Down Expand Up @@ -189,22 +202,42 @@ impl<const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> Mul
{
async fn join_v4(
&mut self,
multicast_addr: Ipv4Addr,
#[allow(unused)] multicast_addr: Ipv4Addr,
_interface: Ipv4Addr,
) -> Result<(), Self::Error> {
self.stack
.join_multicast_group(IpAddr::V4(multicast_addr))?;
#[cfg(feature = "multicast")]
{
self.stack.join_multicast_group(
crate::to_emb_addr(core::net::IpAddr::V4(multicast_addr))
.ok_or(UdpError::UnsupportedProto)?,
)?;
}

#[cfg(not(feature = "multicast"))]
{
Err(UdpError::UnsupportedProto)?;
}

Ok(())
}

async fn leave_v4(
&mut self,
multicast_addr: Ipv4Addr,
#[allow(unused)] multicast_addr: Ipv4Addr,
_interface: Ipv4Addr,
) -> Result<(), Self::Error> {
self.stack
.leave_multicast_group(IpAddr::V4(multicast_addr))?;
#[cfg(feature = "multicast")]
{
self.stack.leave_multicast_group(
crate::to_emb_addr(core::net::IpAddr::V4(multicast_addr))
.ok_or(UdpError::UnsupportedProto)?,
)?;
}

#[cfg(not(feature = "multicast"))]
{
Err(UdpError::UnsupportedProto)?;
}

Ok(())
}
Expand All @@ -215,22 +248,42 @@ impl<const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> Mul
{
async fn join_v6(
&mut self,
multicast_addr: Ipv6Addr,
#[allow(unused)] multicast_addr: Ipv6Addr,
_interface: u32,
) -> Result<(), Self::Error> {
self.stack
.join_multicast_group(IpAddr::V6(multicast_addr))?;
#[cfg(feature = "multicast")]
{
self.stack.join_multicast_group(
crate::to_emb_addr(core::net::IpAddr::V6(multicast_addr))
.ok_or(UdpError::UnsupportedProto)?,
)?;
}

#[cfg(not(feature = "multicast"))]
{
Err(UdpError::UnsupportedProto)?;
}

Ok(())
}

async fn leave_v6(
&mut self,
multicast_addr: Ipv6Addr,
#[allow(unused)] multicast_addr: Ipv6Addr,
_interface: u32,
) -> Result<(), Self::Error> {
self.stack
.leave_multicast_group(IpAddr::V6(multicast_addr))?;
#[cfg(feature = "multicast")]
{
self.stack.leave_multicast_group(
crate::to_emb_addr(core::net::IpAddr::V6(multicast_addr))
.ok_or(UdpError::UnsupportedProto)?,
)?;
}

#[cfg(not(feature = "multicast"))]
{
Err(UdpError::UnsupportedProto)?;
}

Ok(())
}
Expand All @@ -252,8 +305,12 @@ pub enum UdpError {
Recv(RecvError),
Send(SendError),
Bind(BindError),
Multicast(MulticastError),
/// The table of joined multicast groups is already full.
MulticastGroupTableFull,
/// Cannot join/leave the given multicast group.
MulticastUnaddressable,
NoBuffers,
UnsupportedProto,
}

impl From<RecvError> for UdpError {
Expand All @@ -274,9 +331,16 @@ impl From<BindError> for UdpError {
}
}

impl From<MulticastError> for UdpError {
fn from(e: MulticastError) -> Self {
UdpError::Multicast(e)
#[cfg(all(
feature = "multicast",
any(feature = "proto-ipv4", feature = "proto-ipv6")
))]
impl From<embassy_net::MulticastError> for UdpError {
fn from(e: embassy_net::MulticastError) -> Self {
match e {
embassy_net::MulticastError::GroupTableFull => UdpError::MulticastGroupTableFull,
embassy_net::MulticastError::Unaddressable => UdpError::MulticastUnaddressable,
}
}
}

Expand All @@ -287,8 +351,10 @@ impl embedded_io_async::Error for UdpError {
UdpError::Recv(_) => ErrorKind::Other,
UdpError::Send(_) => ErrorKind::Other,
UdpError::Bind(_) => ErrorKind::Other,
UdpError::Multicast(_) => ErrorKind::Other,
UdpError::MulticastGroupTableFull => ErrorKind::Other,
UdpError::MulticastUnaddressable => ErrorKind::Other,
UdpError::NoBuffers => ErrorKind::OutOfMemory,
UdpError::UnsupportedProto => ErrorKind::InvalidInput,
}
}
}
Expand Down