diff --git a/edge-nal-embassy/Cargo.toml b/edge-nal-embassy/Cargo.toml index d3a4f37..63a3c83 100644 --- a/edge-nal-embassy/Cargo.toml +++ b/edge-nal-embassy/Cargo.toml @@ -11,13 +11,21 @@ categories = [ "embedded", "no-std::no-alloc", "asynchronous", - "network-programming" + "network-programming", ] [dependencies] embedded-io-async = { workspace = true } edge-nal = { workspace = true } heapless = { workspace = true } -# TODO: Do not require these features and conditionalize the code instead -embassy-net = { version = "0.4", features = ["tcp", "udp", "dns", "proto-ipv6", "medium-ethernet", "proto-ipv4", "igmp"] } +# Do not require these features and conditionalize the code instead +embassy-net = { version = "0.5", features = [ + "tcp", + "udp", + "dns", + "proto-ipv6", + "medium-ethernet", + "proto-ipv4", + "multicast", +] } embassy-futures = { workspace = true } diff --git a/edge-nal-embassy/README.md b/edge-nal-embassy/README.md index 3df5501..bde536b 100644 --- a/edge-nal-embassy/README.md +++ b/edge-nal-embassy/README.md @@ -14,9 +14,8 @@ All traits except `Readable` which - while implemented - panics if called. ### UDP -* All traits except `UdpConnect`. +* All traits except `UdpConnect`. * `MulticastV6` - while implemented - panics if `join_v6` / `leave_v6` are called. -* `Readable` - while implemented - panics if called. ### Raw sockets diff --git a/edge-nal-embassy/src/dns.rs b/edge-nal-embassy/src/dns.rs index 1d16cbb..c27af8c 100644 --- a/edge-nal-embassy/src/dns.rs +++ b/edge-nal-embassy/src/dns.rs @@ -4,37 +4,25 @@ use edge_nal::AddrType; use embassy_net::{ dns::{DnsQueryType, Error}, - driver::Driver, Stack, }; use embedded_io_async::ErrorKind; -use crate::to_net_addr; - /// A struct that implements the `Dns` trait from `edge-nal` -pub struct Dns<'a, D> -where - D: Driver + 'static, -{ - stack: &'a Stack, +pub struct Dns<'a> { + stack: Stack<'a>, } -impl<'a, D> Dns<'a, D> -where - D: Driver + 'static, -{ +impl<'a> Dns<'a> { /// Create a new `Dns` instance for the provided Embassy networking stack /// /// NOTE: If using DHCP, make sure it has reconfigured the stack to ensure the DNS servers are updated - pub fn new(stack: &'a Stack) -> Self { + pub fn new(stack: Stack<'a>) -> Self { Self { stack } } } -impl<'a, D> edge_nal::Dns for Dns<'a, D> -where - D: Driver + 'static, -{ +impl<'a> edge_nal::Dns for Dns<'a> { type Error = DnsError; async fn get_host_by_name( @@ -48,7 +36,7 @@ where }; let addrs = self.stack.dns_query(host, qtype).await?; if let Some(first) = addrs.first() { - Ok(to_net_addr(*first)) + Ok((*first).into()) } else { Err(Error::Failed.into()) } diff --git a/edge-nal-embassy/src/lib.rs b/edge-nal-embassy/src/lib.rs index 6761a3f..32db23e 100644 --- a/edge-nal-embassy/src/lib.rs +++ b/edge-nal-embassy/src/lib.rs @@ -4,10 +4,10 @@ use core::cell::{Cell, UnsafeCell}; use core::mem::MaybeUninit; -use core::net::{IpAddr, SocketAddr}; +use core::net::SocketAddr; use core::ptr::NonNull; -use embassy_net::{IpAddress, IpEndpoint, IpListenEndpoint}; +use embassy_net::IpEndpoint; pub use dns::*; pub use tcp::*; @@ -59,7 +59,7 @@ impl Pool { } pub(crate) fn to_net_socket(socket: IpEndpoint) -> SocketAddr { - SocketAddr::new(to_net_addr(socket.addr), socket.port) + SocketAddr::new(socket.addr.into(), socket.port) } // pub(crate) fn to_net_socket2(socket: IpListenEndpoint) -> SocketAddr { @@ -71,43 +71,3 @@ pub(crate) fn to_net_socket(socket: IpEndpoint) -> SocketAddr { // socket.port, // ) // } - -pub(crate) fn to_emb_socket(socket: SocketAddr) -> IpEndpoint { - 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(|| to_emb_addr(socket.ip())), - port: socket.port(), - } -} - -pub(crate) fn to_net_addr(addr: IpAddress) -> IpAddr { - match addr { - //#[cfg(feature = "proto-ipv4")] - IpAddress::Ipv4(addr) => addr.0.into(), - // #[cfg(not(feature = "proto-ipv4"))] - // IpAddr::V4(_) => panic!("ipv4 support not enabled"), - //#[cfg(feature = "proto-ipv6")] - IpAddress::Ipv6(addr) => addr.0.into(), - // #[cfg(not(feature = "proto-ipv6"))] - // IpAddr::V6(_) => panic!("ipv6 support not enabled"), - } -} - -pub(crate) fn to_emb_addr(addr: IpAddr) -> IpAddress { - match addr { - //#[cfg(feature = "proto-ipv4")] - IpAddr::V4(addr) => IpAddress::Ipv4(embassy_net::Ipv4Address::from_bytes(&addr.octets())), - // #[cfg(not(feature = "proto-ipv4"))] - // IpAddr::V4(_) => panic!("ipv4 support not enabled"), - //#[cfg(feature = "proto-ipv6")] - IpAddr::V6(addr) => IpAddress::Ipv6(embassy_net::Ipv6Address::from_bytes(&addr.octets())), - // #[cfg(not(feature = "proto-ipv6"))] - // IpAddr::V6(_) => panic!("ipv6 support not enabled"), - } -} diff --git a/edge-nal-embassy/src/tcp.rs b/edge-nal-embassy/src/tcp.rs index 8e86906..594e97b 100644 --- a/edge-nal-embassy/src/tcp.rs +++ b/edge-nal-embassy/src/tcp.rs @@ -6,37 +6,33 @@ use edge_nal::{Close, Readable, TcpBind, TcpConnect, TcpShutdown, TcpSplit}; use embassy_futures::join::join; -use embassy_net::driver::Driver; use embassy_net::tcp::{AcceptError, ConnectError, Error, TcpReader, TcpWriter}; use embassy_net::Stack; use embedded_io_async::{ErrorKind, ErrorType, Read, Write}; -use crate::{to_emb_bind_socket, to_emb_socket, to_net_socket, Pool}; +use crate::{to_net_socket, Pool}; /// A struct that implements the `TcpConnect` and `TcpBind` factory traits from `edge-nal` /// Capable of managing up to N concurrent connections with TX and RX buffers according to TX_SZ and RX_SZ. -pub struct Tcp<'d, D: Driver, const N: usize, const TX_SZ: usize = 1024, const RX_SZ: usize = 1024> -{ - stack: &'d Stack, +pub struct Tcp<'d, const N: usize, const TX_SZ: usize = 1024, const RX_SZ: usize = 1024> { + stack: Stack<'d>, buffers: &'d TcpBuffers, } -impl<'d, D: Driver, const N: usize, const TX_SZ: usize, const RX_SZ: usize> - Tcp<'d, D, N, TX_SZ, RX_SZ> -{ +impl<'d, const N: usize, const TX_SZ: usize, const RX_SZ: usize> Tcp<'d, N, TX_SZ, RX_SZ> { /// Create a new `Tcp` instance for the provided Embassy networking stack, using the provided TCP buffers /// /// Ensure that the number of buffers `N` fits within StackResources of /// [embassy_net::Stack], while taking into account the sockets used for DHCP, DNS, etc. else /// [smoltcp::iface::SocketSet] will panic with `adding a socket to a full SocketSet`. - pub fn new(stack: &'d Stack, buffers: &'d TcpBuffers) -> Self { + pub fn new(stack: Stack<'d>, buffers: &'d TcpBuffers) -> Self { Self { stack, buffers } } } -impl<'d, D: Driver, const N: usize, const TX_SZ: usize, const RX_SZ: usize> TcpConnect - for Tcp<'d, D, N, TX_SZ, RX_SZ> +impl<'d, const N: usize, const TX_SZ: usize, const RX_SZ: usize> TcpConnect + for Tcp<'d, N, TX_SZ, RX_SZ> { type Error = TcpError; @@ -48,19 +44,19 @@ impl<'d, D: Driver, const N: usize, const TX_SZ: usize, const RX_SZ: usize> TcpC async fn connect(&self, remote: SocketAddr) -> Result, Self::Error> { let mut socket = TcpSocket::new(self.stack, self.buffers)?; - socket.socket.connect(to_emb_socket(remote)).await?; + socket.socket.connect(remote).await?; Ok(socket) } } -impl<'d, D: Driver, const N: usize, const TX_SZ: usize, const RX_SZ: usize> TcpBind - for Tcp<'d, D, N, TX_SZ, RX_SZ> +impl<'d, const N: usize, const TX_SZ: usize, const RX_SZ: usize> TcpBind + for Tcp<'d, N, TX_SZ, RX_SZ> { type Error = TcpError; type Accept<'a> - = TcpAccept<'a, D, N, TX_SZ, RX_SZ> + = TcpAccept<'a, N, TX_SZ, RX_SZ> where Self: 'a; @@ -70,19 +66,13 @@ impl<'d, D: Driver, const N: usize, const TX_SZ: usize, const RX_SZ: usize> TcpB } /// Represents an acceptor for incoming TCP client connections. Implements the `TcpAccept` factory trait from `edge-nal` -pub struct TcpAccept< - 'd, - D: Driver, - const N: usize, - const TX_SZ: usize = 1024, - const RX_SZ: usize = 1024, -> { - stack: &'d Tcp<'d, D, N, TX_SZ, RX_SZ>, +pub struct TcpAccept<'d, const N: usize, const TX_SZ: usize = 1024, const RX_SZ: usize = 1024> { + stack: &'d Tcp<'d, N, TX_SZ, RX_SZ>, local: SocketAddr, } -impl<'d, D: Driver, const N: usize, const TX_SZ: usize, const RX_SZ: usize> edge_nal::TcpAccept - for TcpAccept<'d, D, N, TX_SZ, RX_SZ> +impl<'d, const N: usize, const TX_SZ: usize, const RX_SZ: usize> edge_nal::TcpAccept + for TcpAccept<'d, N, TX_SZ, RX_SZ> { type Error = TcpError; @@ -94,7 +84,7 @@ impl<'d, D: Driver, const N: usize, const TX_SZ: usize, const RX_SZ: usize> edge 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(self.local).await?; let local_endpoint = socket.socket.local_endpoint().unwrap(); @@ -111,8 +101,8 @@ pub struct TcpSocket<'d, const N: usize, const TX_SZ: usize, const RX_SZ: usize> } impl<'d, const N: usize, const TX_SZ: usize, const RX_SZ: usize> TcpSocket<'d, N, TX_SZ, RX_SZ> { - fn new( - stack: &'d Stack, + fn new( + stack: Stack<'d>, stack_buffers: &'d TcpBuffers, ) -> Result { let mut socket_buffers = stack_buffers.pool.alloc().ok_or(TcpError::NoBuffers)?; @@ -214,7 +204,7 @@ impl<'d, const N: usize, const TX_SZ: usize, const RX_SZ: usize> Readable for TcpSocket<'d, N, TX_SZ, RX_SZ> { async fn readable(&mut self) -> Result<(), Self::Error> { - panic!("Not implemented yet") + Ok(self.socket.wait_read_ready().await) } } @@ -246,7 +236,7 @@ impl<'a> Read for TcpSocketRead<'a> { impl<'a> Readable for TcpSocketRead<'a> { async fn readable(&mut self) -> Result<(), Self::Error> { - panic!("Not implemented yet") + Ok(self.0.wait_read_ready().await) } } diff --git a/edge-nal-embassy/src/udp.rs b/edge-nal-embassy/src/udp.rs index 9f4f89f..3d106f6 100644 --- a/edge-nal-embassy/src/udp.rs +++ b/edge-nal-embassy/src/udp.rs @@ -3,55 +3,53 @@ use core::ptr::NonNull; use edge_nal::{MulticastV4, MulticastV6, Readable, UdpBind, UdpReceive, UdpSend, UdpSplit}; -use embassy_net::driver::Driver; use embassy_net::udp::{BindError, PacketMetadata, RecvError, SendError}; use embassy_net::{MulticastError, Stack}; use embedded_io_async::{ErrorKind, ErrorType}; -use crate::{to_emb_addr, to_emb_bind_socket, to_emb_socket, to_net_socket, Pool}; +use crate::{to_net_socket, Pool}; /// A struct that implements the `UdpBind` factory trait from `edge-nal` /// Capable of managing up to N concurrent connections with TX and RX buffers according to TX_SZ and RX_SZ, and packet metadata according to `M`. pub struct Udp< 'd, - D: Driver, const N: usize, const TX_SZ: usize = 1500, const RX_SZ: usize = 1500, const M: usize = 2, > { - stack: &'d Stack, + stack: Stack<'d>, buffers: &'d UdpBuffers, } -impl<'d, D: Driver, const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> - Udp<'d, D, N, TX_SZ, RX_SZ, M> +impl<'d, const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> + Udp<'d, N, TX_SZ, RX_SZ, M> { /// Create a new `Udp` instance for the provided Embassy networking stack using the provided UDP buffers. /// /// Ensure that the number of buffers `N` fits within StackResources of /// [embassy_net::Stack], while taking into account the sockets used for DHCP, DNS, etc. else /// [smoltcp::iface::SocketSet] will panic with `adding a socket to a full SocketSet`. - pub fn new(stack: &'d Stack, buffers: &'d UdpBuffers) -> Self { + pub fn new(stack: Stack<'d>, buffers: &'d UdpBuffers) -> Self { Self { stack, buffers } } } -impl<'d, D: Driver, const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> UdpBind - for Udp<'d, D, N, TX_SZ, RX_SZ, M> +impl<'d, const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> UdpBind + for Udp<'d, N, TX_SZ, RX_SZ, M> { type Error = UdpError; type Socket<'a> - = UdpSocket<'a, D, N, TX_SZ, RX_SZ, M> + = UdpSocket<'a, N, TX_SZ, RX_SZ, M> where Self: 'a; async fn bind(&self, local: SocketAddr) -> Result, Self::Error> { let mut socket = UdpSocket::new(self.stack, self.buffers)?; - socket.socket.bind(to_emb_bind_socket(local))?; + socket.socket.bind(local)?; Ok(socket) } @@ -59,26 +57,19 @@ impl<'d, D: Driver, const N: usize, const TX_SZ: usize, const RX_SZ: usize, cons /// A UDP socket /// Implements the `UdpReceive` `UdpSend` and `UdpSplit` traits from `edge-nal` -pub struct UdpSocket< - 'd, - D: Driver, - const N: usize, - const TX_SZ: usize, - const RX_SZ: usize, - const M: usize, -> { - stack: &'d embassy_net::Stack, +pub struct UdpSocket<'d, const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> { + stack: embassy_net::Stack<'d>, socket: embassy_net::udp::UdpSocket<'d>, stack_buffers: &'d UdpBuffers, socket_buffers: NonNull<([u8; TX_SZ], [u8; RX_SZ])>, socket_meta_buffers: NonNull<([PacketMetadata; M], [PacketMetadata; M])>, } -impl<'d, D: Driver, const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> - UdpSocket<'d, D, N, TX_SZ, RX_SZ, M> +impl<'d, const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> + UdpSocket<'d, N, TX_SZ, RX_SZ, M> { fn new( - stack: &'d Stack, + stack: Stack<'d>, stack_buffers: &'d UdpBuffers, ) -> Result { let mut socket_buffers = stack_buffers.pool.alloc().ok_or(UdpError::NoBuffers)?; @@ -102,8 +93,8 @@ impl<'d, D: Driver, const N: usize, const TX_SZ: usize, const RX_SZ: usize, cons } } -impl<'d, D: Driver, const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> Drop - for UdpSocket<'d, D, N, TX_SZ, RX_SZ, M> +impl<'d, const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> Drop + for UdpSocket<'d, N, TX_SZ, RX_SZ, M> { fn drop(&mut self) { unsafe { @@ -114,68 +105,68 @@ impl<'d, D: Driver, const N: usize, const TX_SZ: usize, const RX_SZ: usize, cons } } -impl<'d, D: Driver, const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> - ErrorType for UdpSocket<'d, D, N, TX_SZ, RX_SZ, M> +impl<'d, const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> ErrorType + for UdpSocket<'d, N, TX_SZ, RX_SZ, M> { type Error = UdpError; } -impl<'d, D: Driver, const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> - UdpReceive for UdpSocket<'d, D, N, TX_SZ, RX_SZ, M> +impl<'d, const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> UdpReceive + for UdpSocket<'d, N, TX_SZ, RX_SZ, M> { async fn receive(&mut self, buffer: &mut [u8]) -> Result<(usize, SocketAddr), Self::Error> { let (len, remote_endpoint) = self.socket.recv_from(buffer).await?; - Ok((len, to_net_socket(remote_endpoint))) + Ok((len, to_net_socket(remote_endpoint.endpoint))) } } -impl<'d, D: Driver, const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> UdpSend - for UdpSocket<'d, D, N, TX_SZ, RX_SZ, M> +impl<'d, const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> UdpSend + for UdpSocket<'d, 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, remote).await?; Ok(()) } } -impl<'d, D: Driver, const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> - ErrorType for &UdpSocket<'d, D, N, TX_SZ, RX_SZ, M> +impl<'d, const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> ErrorType + for &UdpSocket<'d, N, TX_SZ, RX_SZ, M> { type Error = UdpError; } -impl<'d, D: Driver, const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> - UdpReceive for &UdpSocket<'d, D, N, TX_SZ, RX_SZ, M> +impl<'d, const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> UdpReceive + for &UdpSocket<'d, N, TX_SZ, RX_SZ, M> { async fn receive(&mut self, buffer: &mut [u8]) -> Result<(usize, SocketAddr), Self::Error> { let (len, remote_endpoint) = self.socket.recv_from(buffer).await?; - Ok((len, to_net_socket(remote_endpoint))) + Ok((len, to_net_socket(remote_endpoint.endpoint))) } } -impl<'d, D: Driver, const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> UdpSend - for &UdpSocket<'d, D, N, TX_SZ, RX_SZ, M> +impl<'d, const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> UdpSend + for &UdpSocket<'d, 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, remote).await?; Ok(()) } } -impl<'d, D: Driver, const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> Readable - for &UdpSocket<'d, D, N, TX_SZ, RX_SZ, M> +impl<'d, const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> Readable + for &UdpSocket<'d, N, TX_SZ, RX_SZ, M> { async fn readable(&mut self) -> Result<(), Self::Error> { - panic!("Not implemented yet") + Ok(self.socket.wait_recv_ready().await) } } -impl<'d, D: Driver, const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> UdpSplit - for UdpSocket<'d, D, N, TX_SZ, RX_SZ, M> +impl<'d, const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> UdpSplit + for UdpSocket<'d, N, TX_SZ, RX_SZ, M> { type Receive<'a> = &'a Self @@ -192,8 +183,8 @@ impl<'d, D: Driver, const N: usize, const TX_SZ: usize, const RX_SZ: usize, cons } } -impl<'d, D: Driver, const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> - MulticastV4 for UdpSocket<'d, D, N, TX_SZ, RX_SZ, M> +impl<'d, const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> MulticastV4 + for UdpSocket<'d, N, TX_SZ, RX_SZ, M> { async fn join_v4( &mut self, @@ -201,8 +192,7 @@ impl<'d, D: Driver, const N: usize, const TX_SZ: usize, const RX_SZ: usize, cons _interface: Ipv4Addr, ) -> Result<(), Self::Error> { self.stack - .join_multicast_group(to_emb_addr(IpAddr::V4(multicast_addr))) - .await?; + .join_multicast_group(IpAddr::V4(multicast_addr))?; Ok(()) } @@ -213,15 +203,14 @@ impl<'d, D: Driver, const N: usize, const TX_SZ: usize, const RX_SZ: usize, cons _interface: Ipv4Addr, ) -> Result<(), Self::Error> { self.stack - .leave_multicast_group(to_emb_addr(IpAddr::V4(multicast_addr))) - .await?; + .leave_multicast_group(IpAddr::V4(multicast_addr))?; Ok(()) } } -impl<'d, D: Driver, const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> - MulticastV6 for UdpSocket<'d, D, N, TX_SZ, RX_SZ, M> +impl<'d, const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> MulticastV6 + for UdpSocket<'d, N, TX_SZ, RX_SZ, M> { async fn join_v6( &mut self, @@ -240,11 +229,11 @@ impl<'d, D: Driver, const N: usize, const TX_SZ: usize, const RX_SZ: usize, cons } } -impl<'d, D: Driver, const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> Readable - for UdpSocket<'d, D, N, TX_SZ, RX_SZ, M> +impl<'d, const N: usize, const TX_SZ: usize, const RX_SZ: usize, const M: usize> Readable + for UdpSocket<'d, N, TX_SZ, RX_SZ, M> { async fn readable(&mut self) -> Result<(), Self::Error> { - panic!("Not implemented yet") + Ok(self.socket.wait_recv_ready().await) } }