pub trait Tcp: Registers {
// Provided methods
fn tcp_connect(
&mut self,
sn: Sn,
port: u16,
addr: &SocketAddrV4
) -> Result<(), Self::Error> { ... }
fn tcp_listen(&mut self, sn: Sn, port: u16) -> Result<(), Self::Error> { ... }
fn tcp_read(&mut self, sn: Sn, buf: &mut [u8]) -> Result<u16, Self::Error> { ... }
fn tcp_write(&mut self, sn: Sn, buf: &[u8]) -> Result<u16, Self::Error> { ... }
fn tcp_disconnect(&mut self, sn: Sn) -> Result<(), Self::Error> { ... }
fn tcp_reader(
&mut self,
sn: Sn
) -> Result<TcpReader<'_, Self>, Error<Self::Error>>
where Self: Sized { ... }
fn tcp_writer(&mut self, sn: Sn) -> Result<TcpWriter<'_, Self>, Self::Error>
where Self: Sized { ... }
}
Expand description
A W5500 TCP trait.
Provided Methods§
sourcefn tcp_connect(
&mut self,
sn: Sn,
port: u16,
addr: &SocketAddrV4
) -> Result<(), Self::Error>
fn tcp_connect( &mut self, sn: Sn, port: u16, addr: &SocketAddrV4 ) -> Result<(), Self::Error>
Starts the 3-way TCP handshake with the remote host.
This method is used to create and interact with a TCP stream between a local host and a remote socket.
After initiating a connection with tcp_connect
and receiving the
con
interrupt data can be transmitting by using tcp_read
and
tcp_write
.
Calling this method does not mean the socket will be connected afterwards, this simply starts the three way handshake.
After calling this method you will eventually get one of 3 interrupts on the socket:
Arguments
socket
- The socket number to use for this TCP stream.port
- The local port to use for the TCP connection.addr
- Address of the remote host to connect to.
Panics
- (debug) The port must not be in use by any other socket on the W5500.
Example
use w5500_hl::{
ll::{Registers, Sn, SocketInterrupt},
net::{Ipv4Addr, SocketAddrV4},
Tcp,
};
const MQTT_SOCKET: Sn = Sn::Sn0;
const MQTT_SOURCE_PORT: u16 = 33650;
const MQTT_SERVER: SocketAddrV4 = SocketAddrV4::new(Ipv4Addr::new(192, 168, 2, 10), 1883);
w5500.tcp_connect(MQTT_SOCKET, MQTT_SOURCE_PORT, &MQTT_SERVER)?;
// wait for a socket interrupt
// you should use the actual interrupt pin, polling is just for demonstration
loop {
let sn_ir: SocketInterrupt = w5500.sn_ir(MQTT_SOCKET)?;
// in reality you will want to handle disconnections gracefully with retries
assert!(!sn_ir.discon_raised());
assert!(!sn_ir.timeout_raised());
// connection succeded
if sn_ir.con_raised() {
break;
}
}
sourcefn tcp_listen(&mut self, sn: Sn, port: u16) -> Result<(), Self::Error>
fn tcp_listen(&mut self, sn: Sn, port: u16) -> Result<(), Self::Error>
Open a TCP listener on the given port.
After opening a listener with tcp_listen
and receiving the
con
interrupt data can be transmitting by using tcp_read
and
tcp_write
.
Arguments
socket
- The socket number to use for this TCP listener.port
- The local port to listen for remote connections on.
Panics
- (debug) The port must not be in use by any other socket on the W5500.
Example
Create an HTTP server.
use w5500_hl::{
ll::{Registers, Sn, SocketInterrupt},
net::{Ipv4Addr, SocketAddrV4},
Tcp,
};
// global_allocator is currently avaliable on nightly for embedded rust
extern crate alloc;
use alloc::vec::{self, Vec};
const HTTP_SOCKET: Sn = Sn::Sn1;
const HTTP_PORT: u16 = 80;
// start serving
w5500.tcp_listen(HTTP_SOCKET, HTTP_PORT)?;
// wait for the RECV interrupt, indicating there is data to read from a client
loop {
let sn_ir = w5500.sn_ir(HTTP_SOCKET).unwrap();
if sn_ir.recv_raised() {
w5500.set_sn_ir(HTTP_SOCKET, sn_ir).unwrap();
break;
}
if sn_ir.discon_raised() | sn_ir.timeout_raised() {
panic!("Socket disconnected while waiting for RECV");
}
}
let mut buf: Vec<u8> = vec![0; 256];
let rx_bytes: u16 = w5500.tcp_read(HTTP_SOCKET, &mut buf)?;
// Truncate the buffer to the number of bytes read
// Safety: BUF is only borrowed mutably in one location
let filled_buf: &[u8] = &buf[..rx_bytes.into()];
// parse HTTP request here using filled_buf
sourcefn tcp_read(&mut self, sn: Sn, buf: &mut [u8]) -> Result<u16, Self::Error>
fn tcp_read(&mut self, sn: Sn, buf: &mut [u8]) -> Result<u16, Self::Error>
Read data from the remote host, returning the number of bytes read.
You should wait for the socket recv
interrupt before calling this method.
Panics
- (debug) The socket must be an
Established
TCP socket.
Example
Send a MQTT CONNECT packet and read a CONNACK.
use w5500_hl::{
ll::{Registers, Sn, SocketInterrupt},
net::{Ipv4Addr, SocketAddrV4},
Tcp,
};
const MQTT_SOCKET: Sn = Sn::Sn0;
const MQTT_SOURCE_PORT: u16 = 33650;
const MQTT_SERVER: SocketAddrV4 = SocketAddrV4::new(Ipv4Addr::new(192, 168, 2, 10), 1883);
w5500.tcp_connect(MQTT_SOCKET, MQTT_SOURCE_PORT, &MQTT_SERVER)?;
// ... wait for a CON interrupt
const CONNECT: [u8; 14] = [
0x10, 0x0C, 0x00, 0x04, b'M', b'Q', b'T', b'T', 0x04, 0x02, 0x0E, 0x10, 0x00, 0x00,
];
let tx_bytes: u16 = w5500.tcp_write(MQTT_SOCKET, &CONNECT)?;
assert_eq!(usize::from(tx_bytes), CONNECT.len());
// ... wait for a RECV interrupt
let mut buf = [0; 10];
let rx_bytes: u16 = w5500.tcp_read(MQTT_SOCKET, &mut buf)?;
let filled_buf = &buf[..rx_bytes.into()];
sourcefn tcp_write(&mut self, sn: Sn, buf: &[u8]) -> Result<u16, Self::Error>
fn tcp_write(&mut self, sn: Sn, buf: &[u8]) -> Result<u16, Self::Error>
Send data to the remote host, returning the number of bytes written.
Panics
- (debug) The socket must be an
Established
TCP socket.
Example
Send a MQTT CONNECT packet.
use w5500_hl::{
ll::{Registers, Sn, SocketInterrupt},
net::{Ipv4Addr, SocketAddrV4},
Tcp,
};
const MQTT_SOCKET: Sn = Sn::Sn0;
const MQTT_SOURCE_PORT: u16 = 33650;
const MQTT_SERVER: SocketAddrV4 = SocketAddrV4::new(Ipv4Addr::new(192, 168, 2, 10), 1883);
w5500.tcp_connect(MQTT_SOCKET, MQTT_SOURCE_PORT, &MQTT_SERVER)?;
// ... wait for a CON interrupt
const CONNECT: [u8; 14] = [
0x10, 0x0C, 0x00, 0x04, b'M', b'Q', b'T', b'T', 0x04, 0x02, 0x0E, 0x10, 0x00, 0x00,
];
let tx_bytes: u16 = w5500.tcp_write(MQTT_SOCKET, &CONNECT)?;
assert_eq!(usize::from(tx_bytes), CONNECT.len());
sourcefn tcp_disconnect(&mut self, sn: Sn) -> Result<(), Self::Error>
fn tcp_disconnect(&mut self, sn: Sn) -> Result<(), Self::Error>
Disconnect from the peer.
If the disconnect is successful (FIN/ACK packet is received) the socket
status changes to Closed
, otherwise TCPTO occurs, the
timeout interrupt is raised, and the socket status changes to
Closed
.
Panics
- (debug) The socket must be an
Established
TCP socket.
Example
Connect and disconnect from a MQTT server.
use w5500_hl::{
ll::{Registers, Sn, SocketInterrupt},
net::{Ipv4Addr, SocketAddrV4},
Tcp,
};
const MQTT_SOCKET: Sn = Sn::Sn0;
const MQTT_SOURCE_PORT: u16 = 33650;
const MQTT_SERVER: SocketAddrV4 = SocketAddrV4::new(Ipv4Addr::new(192, 168, 2, 10), 1883);
w5500.tcp_connect(MQTT_SOCKET, MQTT_SOURCE_PORT, &MQTT_SERVER)?;
// ... wait for a CON interrupt
w5500.tcp_disconnect(MQTT_SOCKET)?;
sourcefn tcp_reader(
&mut self,
sn: Sn
) -> Result<TcpReader<'_, Self>, Error<Self::Error>>where
Self: Sized,
fn tcp_reader( &mut self, sn: Sn ) -> Result<TcpReader<'_, Self>, Error<Self::Error>>where Self: Sized,
Create a TCP reader.
This returns a TcpReader
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 TcpReader
.
Object Safety§
Implementors§
impl<T> Tcp for Twhere T: Registers,
Implement the TCP trait for any structure that implements w5500_ll::Registers
.