pub trait Udp: Registers {
// Provided methods
fn udp_bind(&mut self, sn: Sn, port: u16) -> Result<(), Self::Error> { ... }
fn udp_recv_from(
&mut self,
sn: Sn,
buf: &mut [u8]
) -> Result<(u16, SocketAddrV4), Error<Self::Error>> { ... }
fn udp_peek_from(
&mut self,
sn: Sn,
buf: &mut [u8]
) -> Result<(u16, UdpHeader), Error<Self::Error>> { ... }
fn udp_peek_from_header(
&mut self,
sn: Sn
) -> Result<UdpHeader, Error<Self::Error>> { ... }
fn udp_send_to(
&mut self,
sn: Sn,
buf: &[u8],
addr: &SocketAddrV4
) -> Result<u16, Self::Error> { ... }
fn udp_send_to_if_free(
&mut self,
sn: Sn,
buf: &[u8],
addr: &SocketAddrV4
) -> Result<u16, Self::Error> { ... }
fn udp_send(&mut self, sn: Sn, buf: &[u8]) -> Result<u16, Self::Error> { ... }
fn udp_send_if_free(
&mut self,
sn: Sn,
buf: &[u8]
) -> Result<u16, Self::Error> { ... }
fn udp_reader(
&mut self,
sn: Sn
) -> Result<UdpReader<'_, Self>, Error<Self::Error>>
where Self: Sized { ... }
fn udp_writer(&mut self, sn: Sn) -> Result<UdpWriter<'_, Self>, Self::Error>
where Self: Sized { ... }
}
Expand description
A W5500 UDP socket trait.
After creating a UdpSocket
by bind
ing it to a socket address,
data can be sent to and received from any other socket address.
As stated in the User Datagram Protocol’s specification in IETF RFC 768,
UDP is an unordered, unreliable protocol; refer to Tcp
for the TCP trait.
Comparison to std::net::UdpSocket
- Everything is non-blocking.
- There is no socket struct, you must pass a socket number as the first argument to the methods. This was simply the cleanest solution to the ownership problem after some experimentation; though it certainly is not the safest.
Provided Methods§
sourcefn udp_bind(&mut self, sn: Sn, port: u16) -> Result<(), Self::Error>
fn udp_bind(&mut self, sn: Sn, port: u16) -> Result<(), Self::Error>
Binds the socket to the given port.
This will close the socket, which will reset the RX and TX buffers.
Comparison to std::net::UdpSocket::bind
This method accepts a port instead of a net::SocketAddrV4
, this is
because the IP address is global for the device, set by the
source IP register, and cannot be set on a per-socket basis.
Additionally you can only provide one port, instead of iterable addresses to bind.
Panics
- (debug) The port must not be in use by any other socket on the W5500.
Example
Bind the first socket to port 8080.
use w5500_hl::ll::{Registers, Sn::Sn0};
use w5500_hl::Udp;
w5500.udp_bind(Sn0, 8080)?;
sourcefn udp_recv_from(
&mut self,
sn: Sn,
buf: &mut [u8]
) -> Result<(u16, SocketAddrV4), Error<Self::Error>>
fn udp_recv_from( &mut self, sn: Sn, buf: &mut [u8] ) -> Result<(u16, SocketAddrV4), Error<Self::Error>>
Receives a single datagram message on the socket. On success, returns the number of bytes read and the origin.
The function must be called with valid byte array buf
of sufficient
size to hold the message bytes.
If a message is too long to fit in the supplied buffer, excess bytes
will be discarded.
Comparison to std::net::UdpSocket::recv_from
- This method will always discard excess bytes from the socket buffer.
- This method is non-blocking, use
block
to treat it as blocking.
Errors
This method can only return:
Panics
- (debug) The socket must be opened as a UDP socket.
Example
use w5500_hl::{
block,
ll::{Registers, Sn::Sn0},
Udp,
};
w5500.udp_bind(Sn0, 8080)?;
let mut buf = [0; 10];
let (number_of_bytes, src_addr) = block!(w5500.udp_recv_from(Sn0, &mut buf))?;
// panics if bytes were discarded
assert!(
usize::from(number_of_bytes) < buf.len(),
"Buffer was too small to receive all data"
);
let filled_buf = &mut buf[..number_of_bytes.into()];
sourcefn udp_peek_from(
&mut self,
sn: Sn,
buf: &mut [u8]
) -> Result<(u16, UdpHeader), Error<Self::Error>>
fn udp_peek_from( &mut self, sn: Sn, buf: &mut [u8] ) -> Result<(u16, UdpHeader), Error<Self::Error>>
Receives a single datagram message on the socket, without removing it from the queue. On success, returns the number of bytes read and the UDP header.
Comparison to std::net::UdpSocket::peek_from
- This method will never discard excess bytes from the socket buffer.
- This method is non-blocking, use
block
to treat it as blocking.
Errors
This method can only return:
Panics
- (debug) The socket must be opened as a UDP socket.
Example
use w5500_hl::{
block,
ll::{Registers, Sn::Sn0},
Udp,
};
w5500.udp_bind(Sn0, 8080)?;
let mut buf = [0; 10];
let (number_of_bytes, udp_header) = block!(w5500.udp_peek_from(Sn0, &mut buf))?;
// panics if buffer was too small
assert!(
usize::from(number_of_bytes) > buf.len(),
"Buffer was of len {} too small to receive all data: {} / {} bytes read",
buf.len(),
number_of_bytes,
udp_header.len
);
let filled_buf = &mut buf[..number_of_bytes.into()];
sourcefn udp_peek_from_header(
&mut self,
sn: Sn
) -> Result<UdpHeader, Error<Self::Error>>
fn udp_peek_from_header( &mut self, sn: Sn ) -> Result<UdpHeader, Error<Self::Error>>
Receives the origin and size of the next datagram available on the socket, without removing it from the queue.
There is no std::net
equivalent
for this method.
Errors
This method can only return:
Panics
- (debug) The socket must be opened as a UDP socket.
Example
use w5500_hl::{
block,
ll::{Registers, Sn::Sn0},
Udp, UdpHeader,
};
// global_allocator is currently available on nightly for embedded rust
extern crate alloc;
use alloc::vec::{self, Vec};
w5500.udp_bind(Sn0, 8080)?;
let udp_header: UdpHeader = block!(w5500.udp_peek_from_header(Sn0))?;
let mut buf: Vec<u8> = vec![0; udp_header.len.into()];
let (number_of_bytes, source) = block!(w5500.udp_recv_from(Sn0, &mut buf))?;
// this can assert if the UDP datagram was truncated
// e.g. due to an insufficient socket buffer size
assert_eq!(udp_header.len, number_of_bytes);
sourcefn udp_send_to(
&mut self,
sn: Sn,
buf: &[u8],
addr: &SocketAddrV4
) -> Result<u16, Self::Error>
fn udp_send_to( &mut self, sn: Sn, buf: &[u8], addr: &SocketAddrV4 ) -> Result<u16, Self::Error>
Sends data on the socket to the given address. On success, returns the number of bytes written.
Comparison to std::net::UdpSocket::send_to
- You cannot transmit more than
u16::MAX
bytes at once. - You can only provide one destination.
Panics
- (debug) The socket must be opened as a UDP socket.
Example
use w5500_hl::{
ll::{Registers, Sn::Sn0},
net::{Ipv4Addr, SocketAddrV4},
Udp,
};
const DEST: SocketAddrV4 = SocketAddrV4::new(Ipv4Addr::new(192, 0, 2, 1), 8081);
w5500.udp_bind(Sn0, 8080)?;
let buf: [u8; 10] = [0; 10];
let tx_bytes: u16 = w5500.udp_send_to(Sn0, &buf, &DEST)?;
assert_eq!(usize::from(tx_bytes), buf.len());
sourcefn udp_send_to_if_free(
&mut self,
sn: Sn,
buf: &[u8],
addr: &SocketAddrV4
) -> Result<u16, Self::Error>
fn udp_send_to_if_free( &mut self, sn: Sn, buf: &[u8], addr: &SocketAddrV4 ) -> Result<u16, Self::Error>
Sends data on the socket to the given address. On success, returns the number of bytes written.
This will transmit only if there is enough free space in the W5500 transmit buffer.
Comparison to std::net::UdpSocket::send_to
- You cannot transmit more than
u16::MAX
bytes at once. - You can only provide one destination.
Panics
- (debug) The socket must be opened as a UDP socket.
Example
use w5500_hl::{
ll::{Registers, Sn::Sn0},
net::{Ipv4Addr, SocketAddrV4},
Udp,
};
const DEST: SocketAddrV4 = SocketAddrV4::new(Ipv4Addr::new(192, 0, 2, 1), 8081);
w5500.udp_bind(Sn0, 8080)?;
let buf: [u8; 10] = [0; 10];
let tx_bytes: u16 = w5500.udp_send_to_if_free(Sn0, &buf, &DEST)?;
assert_eq!(usize::from(tx_bytes), buf.len());
sourcefn udp_send(&mut self, sn: Sn, buf: &[u8]) -> Result<u16, Self::Error>
fn udp_send(&mut self, sn: Sn, buf: &[u8]) -> Result<u16, Self::Error>
Sends data to the currently configured destination. On success, returns the number of bytes written.
The destination is set by the last call to Registers::set_sn_dest
,
Udp::udp_send_to
, or UdpWriter::udp_send_to
.
Panics
- (debug) The socket must be opened as a UDP socket.
Example
use w5500_hl::{
ll::{Registers, Sn::Sn0},
net::{Ipv4Addr, SocketAddrV4},
Udp,
};
const DEST: SocketAddrV4 = SocketAddrV4::new(Ipv4Addr::new(192, 0, 2, 1), 8081);
w5500.udp_bind(Sn0, 8080)?;
let buf: [u8; 10] = [0; 10];
let tx_bytes: u16 = w5500.udp_send_to(Sn0, &buf, &DEST)?;
assert_eq!(usize::from(tx_bytes), buf.len());
// send the same to the same destination
let tx_bytes: u16 = w5500.udp_send(Sn0, &buf)?;
assert_eq!(usize::from(tx_bytes), buf.len());
sourcefn udp_send_if_free(&mut self, sn: Sn, buf: &[u8]) -> Result<u16, Self::Error>
fn udp_send_if_free(&mut self, sn: Sn, buf: &[u8]) -> Result<u16, Self::Error>
Sends data to the currently configured destination. On success, returns the number of bytes written.
The destination is set by the last call to Registers::set_sn_dest
,
Udp::udp_send_to
, or UdpWriter::udp_send_to
.
This will transmit only if there is enough free space in the W5500 transmit buffer.
Panics
- (debug) The socket must be opened as a UDP socket.
Example
use w5500_hl::{
ll::{Registers, Sn::Sn0},
net::{Ipv4Addr, SocketAddrV4},
Udp,
};
const DEST: SocketAddrV4 = SocketAddrV4::new(Ipv4Addr::new(192, 0, 2, 1), 8081);
w5500.udp_bind(Sn0, 8080)?;
let buf: [u8; 10] = [0; 10];
let tx_bytes: u16 = w5500.udp_send_to_if_free(Sn0, &buf, &DEST)?;
assert_eq!(usize::from(tx_bytes), buf.len());
// send the same to the same destination
let tx_bytes: u16 = w5500.udp_send_if_free(Sn0, &buf)?;
assert_eq!(usize::from(tx_bytes), buf.len());
sourcefn udp_reader(
&mut self,
sn: Sn
) -> Result<UdpReader<'_, Self>, Error<Self::Error>>where
Self: Sized,
fn udp_reader( &mut self, sn: Sn ) -> Result<UdpReader<'_, Self>, Error<Self::Error>>where Self: Sized,
Create a UDP reader.
This returns a UdpReader
structure, which contains functions to
stream data from the W5500 socket buffers incrementally.
This will return Error::WouldBlock
if there is no data to read.
Errors
This method can only return:
Example
See UdpReader
.
Object Safety§
Implementors§
impl<T> Udp for Twhere T: Registers,
Implement the UDP trait for any structure that implements w5500_ll::Registers
.