embedded_nal/stack/udp.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
use crate::SocketAddr;
/// This trait is implemented by UDP/IP stacks. You could, for example, have
/// an implementation which knows how to send AT commands to an ESP8266 WiFi
/// module. You could have another implementation which knows how to driver the
/// Rust Standard Library's `std::net` module. Given this trait, you can how
/// write a portable CoAP client which can work with either implementation.
pub trait UdpClientStack {
/// The type returned when we create a new UDP socket
type UdpSocket;
/// The type returned when we have an error
type Error: core::fmt::Debug;
/// Allocate a socket for further use.
fn socket(&mut self) -> Result<Self::UdpSocket, Self::Error>;
/// Connect a UDP socket with a peer using a dynamically selected port.
///
/// Selects a port number automatically and initializes for read/writing.
fn connect(
&mut self,
socket: &mut Self::UdpSocket,
remote: SocketAddr,
) -> Result<(), Self::Error>;
/// Send a datagram to the remote host.
///
/// The remote host used is either the one specified in `UdpStack::connect`
/// or the last one used in `UdpServerStack::write_to`.
fn send(&mut self, socket: &mut Self::UdpSocket, buffer: &[u8]) -> nb::Result<(), Self::Error>;
/// Read a datagram the remote host has sent to us.
///
/// Returns `Ok((n, remote))`, which means a datagram of size `n` has been
/// received from `remote` and been placed in `&buffer[0..n]`, or an error.
/// If a packet has not been received when called, then [`nb::Error::WouldBlock`]
/// should be returned.
fn receive(
&mut self,
socket: &mut Self::UdpSocket,
buffer: &mut [u8],
) -> nb::Result<(usize, SocketAddr), Self::Error>;
/// Close an existing UDP socket.
fn close(&mut self, socket: Self::UdpSocket) -> Result<(), Self::Error>;
}
/// This trait is implemented by UDP/IP stacks. It provides the ability to
/// listen for packets on a specified port and send replies.
pub trait UdpFullStack: UdpClientStack {
/// Bind a UDP socket with a specified port
fn bind(&mut self, socket: &mut Self::UdpSocket, local_port: u16) -> Result<(), Self::Error>;
/// Send a packet to a remote host/port.
fn send_to(
&mut self,
socket: &mut Self::UdpSocket,
remote: SocketAddr,
buffer: &[u8],
) -> nb::Result<(), Self::Error>;
}
impl<T: UdpClientStack> UdpClientStack for &mut T {
type Error = T::Error;
type UdpSocket = T::UdpSocket;
fn socket(&mut self) -> Result<Self::UdpSocket, Self::Error> {
T::socket(self)
}
fn connect(
&mut self,
socket: &mut Self::UdpSocket,
remote: SocketAddr,
) -> Result<(), Self::Error> {
T::connect(self, socket, remote)
}
fn send(&mut self, socket: &mut Self::UdpSocket, buffer: &[u8]) -> nb::Result<(), Self::Error> {
T::send(self, socket, buffer)
}
fn receive(
&mut self,
socket: &mut Self::UdpSocket,
buffer: &mut [u8],
) -> nb::Result<(usize, SocketAddr), Self::Error> {
T::receive(self, socket, buffer)
}
fn close(&mut self, socket: Self::UdpSocket) -> Result<(), Self::Error> {
T::close(self, socket)
}
}
impl<T: UdpFullStack> UdpFullStack for &mut T {
fn bind(&mut self, socket: &mut Self::UdpSocket, local_port: u16) -> Result<(), Self::Error> {
T::bind(self, socket, local_port)
}
fn send_to(
&mut self,
socket: &mut Self::UdpSocket,
remote: SocketAddr,
buffer: &[u8],
) -> nb::Result<(), Self::Error> {
T::send_to(self, socket, remote, buffer)
}
}