Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/tcp updates #42

Merged
merged 12 commits into from
Jun 22, 2023
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
This document describes the changes to smoltcp-nal between releases.

# [Unreleased]

## Added
* Implemented full UDP socket
* Updated to smoltcp 0.9
* [breaking] Updated to smoltcp 0.9

## Fixed
## Changed
* [breaking] embedded-nal updated to 0.7

# [0.2.1]
## Added
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ repository = "https://github.com/quartiq/smoltcp-nal.git"

[dependencies]
heapless = "0.7"
embedded-nal = "0.6"
embedded-nal = "0.7"
embedded-time = "0.12"

[dependencies.nanorand]
Expand Down
83 changes: 46 additions & 37 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,25 @@ pub enum SmoltcpError {
pub enum NetworkError {
NoSocket,
ConnectionFailure,
ReadFailure,
WriteFailure,
TcpReadFailure(smoltcp::socket::tcp::RecvError),
TcpWriteFailure(smoltcp::socket::tcp::SendError),
UdpReadFailure(smoltcp::socket::udp::RecvError),
UdpWriteFailure(smoltcp::socket::udp::SendError),
Unsupported,
NoIpAddress,
NotConnected,
}

impl embedded_nal::TcpError for NetworkError {
fn kind(&self) -> embedded_nal::TcpErrorKind {
match self {
NetworkError::TcpReadFailure(_) => embedded_nal::TcpErrorKind::PipeClosed,
NetworkError::TcpWriteFailure(_) => embedded_nal::TcpErrorKind::PipeClosed,
_ => embedded_nal::TcpErrorKind::Other,
}
}
}

impl From<smoltcp::iface::RouteTableFull> for SmoltcpError {
fn from(_: smoltcp::iface::RouteTableFull) -> SmoltcpError {
SmoltcpError::RouteTableFull
Expand Down Expand Up @@ -424,45 +436,42 @@ where
return Err(embedded_nal::nb::Error::Other(NetworkError::NoIpAddress));
ryan-summers marked this conversation as resolved.
Show resolved Hide resolved
}

{
let internal_socket = self.sockets.get::<smoltcp::socket::tcp::Socket>(*socket);

// If we're already in the process of connecting, ignore the request silently.
if internal_socket.is_open() {
return Ok(());
}
}

match remote.ip() {
let dest_addr = match remote.ip() {
embedded_nal::IpAddr::V4(addr) => {
let octets = addr.octets();
let address =
smoltcp::wire::Ipv4Address::new(octets[0], octets[1], octets[2], octets[3]);

let local_port = self.get_ephemeral_port();
let internal_socket = self
.sockets
.get_mut::<smoltcp::socket::tcp::Socket>(*socket);
let context = self.network_interface.context();
internal_socket
.connect(context, (address, remote.port()), local_port)
.map_err(|_| embedded_nal::nb::Error::Other(NetworkError::ConnectionFailure))
smoltcp::wire::Ipv4Address::new(octets[0], octets[1], octets[2], octets[3])
}

// We only support IPv4.
_ => Err(embedded_nal::nb::Error::Other(NetworkError::Unsupported)),
_ => return Err(embedded_nal::nb::Error::Other(NetworkError::Unsupported)),
};

let local_port = self.get_ephemeral_port();
jordens marked this conversation as resolved.
Show resolved Hide resolved
let internal_socket = self
.sockets
.get_mut::<smoltcp::socket::tcp::Socket>(*socket);

// Check that a connected peer is who is being requested.
if internal_socket
.remote_endpoint()
.map(|endpoint| endpoint.addr != dest_addr.into())
.unwrap_or(false)
{
internal_socket.abort();
ryan-summers marked this conversation as resolved.
Show resolved Hide resolved
}
}

fn is_connected(&mut self, socket: &SocketHandle) -> Result<bool, NetworkError> {
// If there is no longer an IP address assigned to the interface, do not allow usage of the
// socket.
if self.is_ip_unspecified() {
return Err(NetworkError::NoIpAddress);
if !internal_socket.is_open() {
ryan-summers marked this conversation as resolved.
Show resolved Hide resolved
let context = self.network_interface.context();
internal_socket
.connect(context, (dest_addr, remote.port()), local_port)
.map_err(|_| embedded_nal::nb::Error::Other(NetworkError::ConnectionFailure))?;
}

let socket: &mut smoltcp::socket::tcp::Socket = self.sockets.get_mut(*socket);
Ok(socket.may_send() && socket.may_recv())
if internal_socket.state() == smoltcp::socket::tcp::State::Established {
Ok(())
} else {
Err(embedded_nal::nb::Error::WouldBlock)
}
}

fn send(
Expand All @@ -479,7 +488,7 @@ where
let socket: &mut smoltcp::socket::tcp::Socket = self.sockets.get_mut(*socket);
socket
.send_slice(buffer)
.map_err(|_| embedded_nal::nb::Error::Other(NetworkError::WriteFailure))
.map_err(|e| embedded_nal::nb::Error::Other(NetworkError::TcpWriteFailure(e)))
}

fn receive(
Expand All @@ -496,7 +505,7 @@ where
let socket: &mut smoltcp::socket::tcp::Socket = self.sockets.get_mut(*socket);
socket
.recv_slice(buffer)
.map_err(|_| embedded_nal::nb::Error::Other(NetworkError::ReadFailure))
.map_err(|e| embedded_nal::nb::Error::Other(NetworkError::TcpReadFailure(e)))
}

fn close(&mut self, socket: SocketHandle) -> Result<(), NetworkError> {
Expand Down Expand Up @@ -596,7 +605,7 @@ where
let destination = socket.destination.ok_or(NetworkError::NotConnected)?;
internal_socket
.send_slice(buffer, destination)
.map_err(|_| embedded_nal::nb::Error::Other(NetworkError::WriteFailure))
.map_err(|e| embedded_nal::nb::Error::Other(NetworkError::UdpWriteFailure(e)))
}

fn receive(
Expand All @@ -612,7 +621,7 @@ where
self.sockets.get_mut(socket.handle);
let (size, source) = internal_socket
.recv_slice(buffer)
.map_err(|_| embedded_nal::nb::Error::Other(NetworkError::ReadFailure))?;
.map_err(|e| embedded_nal::nb::Error::Other(NetworkError::UdpReadFailure(e)))?;

let source = {
let octets = source.addr.as_bytes();
Expand Down Expand Up @@ -699,6 +708,6 @@ where
self.sockets.get_mut(socket.handle);
internal_socket
.send_slice(buffer, destination)
.map_err(|_| embedded_nal::nb::Error::Other(NetworkError::WriteFailure))
.map_err(|e| embedded_nal::nb::Error::Other(NetworkError::UdpWriteFailure(e)))
}
}
1 change: 0 additions & 1 deletion src/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ where

forward! {socket() -> Result<S::TcpSocket, S::Error>}
forward! {connect(socket: &mut S::TcpSocket, remote: embedded_nal::SocketAddr) -> embedded_nal::nb::Result<(), S::Error>}
forward! {is_connected(socket: &S::TcpSocket) -> Result<bool, S::Error>}
forward! {send(socket: &mut S::TcpSocket, buffer: &[u8]) -> embedded_nal::nb::Result<usize, S::Error>}
forward! {receive(socket: &mut S::TcpSocket, buffer: &mut [u8]) -> embedded_nal::nb::Result<usize, S::Error>}
forward! {close(socket: S::TcpSocket) -> Result<(), S::Error>}
Expand Down