Trait w5500_hl::Udp

source ·
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 binding 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§

source

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)?;
source

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()];
source

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()];
source

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);
source

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());
source

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());
source

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());
source

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());
source

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.

source

fn udp_writer(&mut self, sn: Sn) -> Result<UdpWriter<'_, Self>, Self::Error>where Self: Sized,

Create a UDP writer.

This returns a UdpWriter structure, which contains functions to stream data to the W5500 socket buffers incrementally.

Example

See UdpWriter.

Object Safety§

This trait is not object safe.

Implementors§

source§

impl<T> Udp for Twhere T: Registers,

Implement the UDP trait for any structure that implements w5500_ll::Registers.