Эх сурвалжийг харах

Merge pull request #617 from smoltcp-rs/error-refactor

Error refactor, part 1
Dario Nieuwenhuis 2 жил өмнө
parent
commit
e7772a46bb

+ 9 - 9
examples/benchmark.rs

@@ -13,7 +13,7 @@ use std::thread;
 
 use smoltcp::iface::{InterfaceBuilder, NeighborCache};
 use smoltcp::phy::{wait as phy_wait, Device, Medium};
-use smoltcp::socket::{TcpSocket, TcpSocketBuffer};
+use smoltcp::socket::tcp;
 use smoltcp::time::{Duration, Instant};
 use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr};
 
@@ -85,13 +85,13 @@ fn main() {
 
     let neighbor_cache = NeighborCache::new(BTreeMap::new());
 
-    let tcp1_rx_buffer = TcpSocketBuffer::new(vec![0; 65535]);
-    let tcp1_tx_buffer = TcpSocketBuffer::new(vec![0; 65535]);
-    let tcp1_socket = TcpSocket::new(tcp1_rx_buffer, tcp1_tx_buffer);
+    let tcp1_rx_buffer = tcp::SocketBuffer::new(vec![0; 65535]);
+    let tcp1_tx_buffer = tcp::SocketBuffer::new(vec![0; 65535]);
+    let tcp1_socket = tcp::Socket::new(tcp1_rx_buffer, tcp1_tx_buffer);
 
-    let tcp2_rx_buffer = TcpSocketBuffer::new(vec![0; 65535]);
-    let tcp2_tx_buffer = TcpSocketBuffer::new(vec![0; 65535]);
-    let tcp2_socket = TcpSocket::new(tcp2_rx_buffer, tcp2_tx_buffer);
+    let tcp2_rx_buffer = tcp::SocketBuffer::new(vec![0; 65535]);
+    let tcp2_tx_buffer = tcp::SocketBuffer::new(vec![0; 65535]);
+    let tcp2_socket = tcp::Socket::new(tcp2_rx_buffer, tcp2_tx_buffer);
 
     let ethernet_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]);
     let ip_addrs = [IpCidr::new(IpAddress::v4(192, 168, 69, 1), 24)];
@@ -119,7 +119,7 @@ fn main() {
         }
 
         // tcp:1234: emit data
-        let socket = iface.get_socket::<TcpSocket>(tcp1_handle);
+        let socket = iface.get_socket::<tcp::Socket>(tcp1_handle);
         if !socket.is_open() {
             socket.listen(1234).unwrap();
         }
@@ -137,7 +137,7 @@ fn main() {
         }
 
         // tcp:1235: sink data
-        let socket = iface.get_socket::<TcpSocket>(tcp2_handle);
+        let socket = iface.get_socket::<tcp::Socket>(tcp2_handle);
         if !socket.is_open() {
             socket.listen(1235).unwrap();
         }

+ 6 - 6
examples/client.rs

@@ -7,7 +7,7 @@ use std::str::{self, FromStr};
 
 use smoltcp::iface::{InterfaceBuilder, NeighborCache, Routes};
 use smoltcp::phy::{wait as phy_wait, Device, Medium};
-use smoltcp::socket::{TcpSocket, TcpSocketBuffer};
+use smoltcp::socket::tcp;
 use smoltcp::time::Instant;
 use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr, Ipv4Address};
 
@@ -30,9 +30,9 @@ fn main() {
 
     let neighbor_cache = NeighborCache::new(BTreeMap::new());
 
-    let tcp_rx_buffer = TcpSocketBuffer::new(vec![0; 64]);
-    let tcp_tx_buffer = TcpSocketBuffer::new(vec![0; 128]);
-    let tcp_socket = TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer);
+    let tcp_rx_buffer = tcp::SocketBuffer::new(vec![0; 64]);
+    let tcp_tx_buffer = tcp::SocketBuffer::new(vec![0; 128]);
+    let tcp_socket = tcp::Socket::new(tcp_rx_buffer, tcp_tx_buffer);
 
     let ethernet_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x02]);
     let ip_addrs = [IpCidr::new(IpAddress::v4(192, 168, 69, 2), 24)];
@@ -54,7 +54,7 @@ fn main() {
 
     let tcp_handle = iface.add_socket(tcp_socket);
 
-    let (socket, cx) = iface.get_socket_and_context::<TcpSocket>(tcp_handle);
+    let (socket, cx) = iface.get_socket_and_context::<tcp::Socket>(tcp_handle);
     socket.connect(cx, (address, port), 49500).unwrap();
 
     let mut tcp_active = false;
@@ -67,7 +67,7 @@ fn main() {
             }
         }
 
-        let socket = iface.get_socket::<TcpSocket>(tcp_handle);
+        let socket = iface.get_socket::<tcp::Socket>(tcp_handle);
         if socket.is_active() && !tcp_active {
             debug!("connected");
         } else if !socket.is_active() && tcp_active {

+ 5 - 5
examples/dhcp_client.rs

@@ -6,7 +6,7 @@ use std::collections::BTreeMap;
 use std::os::unix::io::AsRawFd;
 
 use smoltcp::iface::{Interface, InterfaceBuilder, NeighborCache, Routes};
-use smoltcp::socket::{Dhcpv4Event, Dhcpv4Socket};
+use smoltcp::socket::dhcpv4;
 use smoltcp::time::Instant;
 use smoltcp::wire::{EthernetAddress, IpCidr, Ipv4Address, Ipv4Cidr};
 use smoltcp::{
@@ -44,7 +44,7 @@ fn main() {
     }
     let mut iface = builder.finalize();
 
-    let mut dhcp_socket = Dhcpv4Socket::new();
+    let mut dhcp_socket = dhcpv4::Socket::new();
 
     // Set a ridiculously short max lease time to show DHCP renews work properly.
     // This will cause the DHCP client to start renewing after 5 seconds, and give up the
@@ -60,10 +60,10 @@ fn main() {
             debug!("poll error: {}", e);
         }
 
-        let event = iface.get_socket::<Dhcpv4Socket>(dhcp_handle).poll();
+        let event = iface.get_socket::<dhcpv4::Socket>(dhcp_handle).poll();
         match event {
             None => {}
-            Some(Dhcpv4Event::Configured(config)) => {
+            Some(dhcpv4::Event::Configured(config)) => {
                 debug!("DHCP config acquired!");
 
                 debug!("IP address:      {}", config.address);
@@ -83,7 +83,7 @@ fn main() {
                     }
                 }
             }
-            Some(Dhcpv4Event::Deconfigured) => {
+            Some(dhcpv4::Event::Deconfigured) => {
                 debug!("DHCP lost config!");
                 set_ipv4_addr(&mut iface, Ipv4Cidr::new(Ipv4Address::UNSPECIFIED, 0));
                 iface.routes_mut().remove_default_ipv4_route();

+ 5 - 6
examples/dns.rs

@@ -10,12 +10,11 @@ mod utils;
 use smoltcp::iface::{InterfaceBuilder, NeighborCache, Routes};
 use smoltcp::phy::Device;
 use smoltcp::phy::{wait as phy_wait, Medium};
-use smoltcp::socket::DnsSocket;
+use smoltcp::socket::dns::{self, GetQueryResultError};
 use smoltcp::time::Instant;
 use smoltcp::wire::{
     EthernetAddress, HardwareAddress, IpAddress, IpCidr, Ipv4Address, Ipv6Address,
 };
-use smoltcp::Error;
 use std::collections::BTreeMap;
 use std::os::unix::io::AsRawFd;
 
@@ -39,7 +38,7 @@ fn main() {
         Ipv4Address::new(8, 8, 4, 4).into(),
         Ipv4Address::new(8, 8, 8, 8).into(),
     ];
-    let dns_socket = DnsSocket::new(servers, vec![]);
+    let dns_socket = dns::Socket::new(servers, vec![]);
 
     let ethernet_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x02]);
     let src_ipv6 = IpAddress::v6(0xfdaa, 0, 0, 0, 0, 0, 0, 1);
@@ -68,7 +67,7 @@ fn main() {
 
     let dns_handle = iface.add_socket(dns_socket);
 
-    let (socket, cx) = iface.get_socket_and_context::<DnsSocket>(dns_handle);
+    let (socket, cx) = iface.get_socket_and_context::<dns::Socket>(dns_handle);
     let query = socket.start_query(cx, name).unwrap();
 
     loop {
@@ -83,14 +82,14 @@ fn main() {
         }
 
         match iface
-            .get_socket::<DnsSocket>(dns_handle)
+            .get_socket::<dns::Socket>(dns_handle)
             .get_query_result(query)
         {
             Ok(addrs) => {
                 println!("Query done: {:?}", addrs);
                 break;
             }
-            Err(Error::Exhausted) => {} // not done yet
+            Err(GetQueryResultError::Pending) => {} // not done yet
             Err(e) => panic!("query failed: {:?}", e),
         }
 

+ 5 - 5
examples/httpclient.rs

@@ -8,7 +8,7 @@ use url::Url;
 
 use smoltcp::iface::{InterfaceBuilder, NeighborCache, Routes};
 use smoltcp::phy::{wait as phy_wait, Device, Medium};
-use smoltcp::socket::{TcpSocket, TcpSocketBuffer};
+use smoltcp::socket::tcp;
 use smoltcp::time::Instant;
 use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr, Ipv4Address, Ipv6Address};
 
@@ -30,9 +30,9 @@ fn main() {
 
     let neighbor_cache = NeighborCache::new(BTreeMap::new());
 
-    let tcp_rx_buffer = TcpSocketBuffer::new(vec![0; 1024]);
-    let tcp_tx_buffer = TcpSocketBuffer::new(vec![0; 1024]);
-    let tcp_socket = TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer);
+    let tcp_rx_buffer = tcp::SocketBuffer::new(vec![0; 1024]);
+    let tcp_tx_buffer = tcp::SocketBuffer::new(vec![0; 1024]);
+    let tcp_socket = tcp::Socket::new(tcp_rx_buffer, tcp_tx_buffer);
 
     let ethernet_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x02]);
     let ip_addrs = [
@@ -76,7 +76,7 @@ fn main() {
             }
         }
 
-        let (socket, cx) = iface.get_socket_and_context::<TcpSocket>(tcp_handle);
+        let (socket, cx) = iface.get_socket_and_context::<tcp::Socket>(tcp_handle);
 
         state = match state {
             State::Connect if !socket.is_active() => {

+ 9 - 9
examples/loopback.rs

@@ -11,7 +11,7 @@ use log::{debug, error, info};
 
 use smoltcp::iface::{InterfaceBuilder, NeighborCache};
 use smoltcp::phy::{Loopback, Medium};
-use smoltcp::socket::{TcpSocket, TcpSocketBuffer};
+use smoltcp::socket::tcp;
 use smoltcp::time::{Duration, Instant};
 use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr};
 
@@ -100,17 +100,17 @@ fn main() {
         // when stack overflows.
         static mut TCP_SERVER_RX_DATA: [u8; 1024] = [0; 1024];
         static mut TCP_SERVER_TX_DATA: [u8; 1024] = [0; 1024];
-        let tcp_rx_buffer = TcpSocketBuffer::new(unsafe { &mut TCP_SERVER_RX_DATA[..] });
-        let tcp_tx_buffer = TcpSocketBuffer::new(unsafe { &mut TCP_SERVER_TX_DATA[..] });
-        TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer)
+        let tcp_rx_buffer = tcp::SocketBuffer::new(unsafe { &mut TCP_SERVER_RX_DATA[..] });
+        let tcp_tx_buffer = tcp::SocketBuffer::new(unsafe { &mut TCP_SERVER_TX_DATA[..] });
+        tcp::Socket::new(tcp_rx_buffer, tcp_tx_buffer)
     };
 
     let client_socket = {
         static mut TCP_CLIENT_RX_DATA: [u8; 1024] = [0; 1024];
         static mut TCP_CLIENT_TX_DATA: [u8; 1024] = [0; 1024];
-        let tcp_rx_buffer = TcpSocketBuffer::new(unsafe { &mut TCP_CLIENT_RX_DATA[..] });
-        let tcp_tx_buffer = TcpSocketBuffer::new(unsafe { &mut TCP_CLIENT_TX_DATA[..] });
-        TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer)
+        let tcp_rx_buffer = tcp::SocketBuffer::new(unsafe { &mut TCP_CLIENT_RX_DATA[..] });
+        let tcp_tx_buffer = tcp::SocketBuffer::new(unsafe { &mut TCP_CLIENT_TX_DATA[..] });
+        tcp::Socket::new(tcp_rx_buffer, tcp_tx_buffer)
     };
 
     let server_handle = iface.add_socket(server_socket);
@@ -127,7 +127,7 @@ fn main() {
             }
         }
 
-        let mut socket = iface.get_socket::<TcpSocket>(server_handle);
+        let mut socket = iface.get_socket::<tcp::Socket>(server_handle);
         if !socket.is_active() && !socket.is_listening() {
             if !did_listen {
                 debug!("listening");
@@ -145,7 +145,7 @@ fn main() {
             done = true;
         }
 
-        let (mut socket, cx) = iface.get_socket_and_context::<TcpSocket>(client_handle);
+        let (mut socket, cx) = iface.get_socket_and_context::<tcp::Socket>(client_handle);
         if !socket.is_open() {
             if !did_connect {
                 debug!("connecting");

+ 19 - 18
examples/multicast.rs

@@ -6,9 +6,7 @@ use std::os::unix::io::AsRawFd;
 
 use smoltcp::iface::{InterfaceBuilder, NeighborCache};
 use smoltcp::phy::wait as phy_wait;
-use smoltcp::socket::{
-    RawPacketMetadata, RawSocket, RawSocketBuffer, UdpPacketMetadata, UdpSocket, UdpSocketBuffer,
-};
+use smoltcp::socket::{raw, udp};
 use smoltcp::time::Instant;
 use smoltcp::wire::{
     EthernetAddress, IgmpPacket, IgmpRepr, IpAddress, IpCidr, IpProtocol, IpVersion, Ipv4Address,
@@ -50,10 +48,10 @@ fn main() {
         .unwrap();
 
     // Must fit at least one IGMP packet
-    let raw_rx_buffer = RawSocketBuffer::new(vec![RawPacketMetadata::EMPTY; 2], vec![0; 512]);
+    let raw_rx_buffer = raw::PacketBuffer::new(vec![raw::PacketMetadata::EMPTY; 2], vec![0; 512]);
     // Will not send IGMP
-    let raw_tx_buffer = RawSocketBuffer::new(vec![], vec![]);
-    let raw_socket = RawSocket::new(
+    let raw_tx_buffer = raw::PacketBuffer::new(vec![], vec![]);
+    let raw_socket = raw::Socket::new(
         IpVersion::Ipv4,
         IpProtocol::Igmp,
         raw_rx_buffer,
@@ -62,10 +60,10 @@ fn main() {
     let raw_handle = iface.add_socket(raw_socket);
 
     // Must fit mDNS payload of at least one packet
-    let udp_rx_buffer = UdpSocketBuffer::new(vec![UdpPacketMetadata::EMPTY; 4], vec![0; 1024]);
+    let udp_rx_buffer = udp::PacketBuffer::new(vec![udp::PacketMetadata::EMPTY; 4], vec![0; 1024]);
     // Will not send mDNS
-    let udp_tx_buffer = UdpSocketBuffer::new(vec![UdpPacketMetadata::EMPTY], vec![0; 0]);
-    let udp_socket = UdpSocket::new(udp_rx_buffer, udp_tx_buffer);
+    let udp_tx_buffer = udp::PacketBuffer::new(vec![udp::PacketMetadata::EMPTY], vec![0; 0]);
+    let udp_socket = udp::Socket::new(udp_rx_buffer, udp_tx_buffer);
     let udp_handle = iface.add_socket(udp_socket);
 
     loop {
@@ -77,21 +75,24 @@ fn main() {
             }
         }
 
-        let socket = iface.get_socket::<RawSocket>(raw_handle);
+        let socket = iface.get_socket::<raw::Socket>(raw_handle);
 
         if socket.can_recv() {
             // For display purposes only - normally we wouldn't process incoming IGMP packets
             // in the application layer
-            socket
-                .recv()
-                .and_then(Ipv4Packet::new_checked)
-                .and_then(|ipv4_packet| IgmpPacket::new_checked(ipv4_packet.payload()))
-                .and_then(|igmp_packet| IgmpRepr::parse(&igmp_packet))
-                .map(|igmp_repr| println!("IGMP packet: {:?}", igmp_repr))
-                .unwrap_or_else(|e| println!("Recv IGMP error: {:?}", e));
+            match socket.recv() {
+                Err(e) => println!("Recv IGMP error: {:?}", e),
+                Ok(buf) => {
+                    Ipv4Packet::new_checked(buf)
+                        .and_then(|ipv4_packet| IgmpPacket::new_checked(ipv4_packet.payload()))
+                        .and_then(|igmp_packet| IgmpRepr::parse(&igmp_packet))
+                        .map(|igmp_repr| println!("IGMP packet: {:?}", igmp_repr))
+                        .unwrap_or_else(|e| println!("parse IGMP error: {:?}", e));
+                }
+            }
         }
 
-        let socket = iface.get_socket::<UdpSocket>(udp_handle);
+        let socket = iface.get_socket::<udp::Socket>(udp_handle);
         if !socket.is_open() {
             socket.bind(MDNS_PORT).unwrap()
         }

+ 6 - 6
examples/ping.rs

@@ -11,7 +11,7 @@ use std::str::FromStr;
 use smoltcp::iface::{InterfaceBuilder, NeighborCache, Routes};
 use smoltcp::phy::wait as phy_wait;
 use smoltcp::phy::Device;
-use smoltcp::socket::{IcmpEndpoint, IcmpPacketMetadata, IcmpSocket, IcmpSocketBuffer};
+use smoltcp::socket::icmp;
 use smoltcp::wire::{
     EthernetAddress, Icmpv4Packet, Icmpv4Repr, Icmpv6Packet, Icmpv6Repr, IpAddress, IpCidr,
     Ipv4Address, Ipv6Address,
@@ -108,9 +108,9 @@ fn main() {
 
     let remote_addr = address;
 
-    let icmp_rx_buffer = IcmpSocketBuffer::new(vec![IcmpPacketMetadata::EMPTY], vec![0; 256]);
-    let icmp_tx_buffer = IcmpSocketBuffer::new(vec![IcmpPacketMetadata::EMPTY], vec![0; 256]);
-    let icmp_socket = IcmpSocket::new(icmp_rx_buffer, icmp_tx_buffer);
+    let icmp_rx_buffer = icmp::PacketBuffer::new(vec![icmp::PacketMetadata::EMPTY], vec![0; 256]);
+    let icmp_tx_buffer = icmp::PacketBuffer::new(vec![icmp::PacketMetadata::EMPTY], vec![0; 256]);
+    let icmp_socket = icmp::Socket::new(icmp_rx_buffer, icmp_tx_buffer);
 
     let ethernet_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x02]);
     let src_ipv6 = IpAddress::v6(0xfdaa, 0, 0, 0, 0, 0, 0, 1);
@@ -156,9 +156,9 @@ fn main() {
         }
 
         let timestamp = Instant::now();
-        let socket = iface.get_socket::<IcmpSocket>(icmp_handle);
+        let socket = iface.get_socket::<icmp::Socket>(icmp_handle);
         if !socket.is_open() {
-            socket.bind(IcmpEndpoint::Ident(ident)).unwrap();
+            socket.bind(icmp::Endpoint::Ident(ident)).unwrap();
             send_at = timestamp;
         }
 

+ 21 - 22
examples/server.rs

@@ -8,8 +8,7 @@ use std::str;
 
 use smoltcp::iface::{InterfaceBuilder, NeighborCache};
 use smoltcp::phy::{wait as phy_wait, Device, Medium};
-use smoltcp::socket::{TcpSocket, TcpSocketBuffer};
-use smoltcp::socket::{UdpPacketMetadata, UdpSocket, UdpSocketBuffer};
+use smoltcp::socket::{tcp, udp};
 use smoltcp::time::{Duration, Instant};
 use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr};
 
@@ -27,25 +26,25 @@ fn main() {
 
     let neighbor_cache = NeighborCache::new(BTreeMap::new());
 
-    let udp_rx_buffer = UdpSocketBuffer::new(vec![UdpPacketMetadata::EMPTY], vec![0; 64]);
-    let udp_tx_buffer = UdpSocketBuffer::new(vec![UdpPacketMetadata::EMPTY], vec![0; 128]);
-    let udp_socket = UdpSocket::new(udp_rx_buffer, udp_tx_buffer);
+    let udp_rx_buffer = udp::PacketBuffer::new(vec![udp::PacketMetadata::EMPTY], vec![0; 64]);
+    let udp_tx_buffer = udp::PacketBuffer::new(vec![udp::PacketMetadata::EMPTY], vec![0; 128]);
+    let udp_socket = udp::Socket::new(udp_rx_buffer, udp_tx_buffer);
 
-    let tcp1_rx_buffer = TcpSocketBuffer::new(vec![0; 64]);
-    let tcp1_tx_buffer = TcpSocketBuffer::new(vec![0; 128]);
-    let tcp1_socket = TcpSocket::new(tcp1_rx_buffer, tcp1_tx_buffer);
+    let tcp1_rx_buffer = tcp::SocketBuffer::new(vec![0; 64]);
+    let tcp1_tx_buffer = tcp::SocketBuffer::new(vec![0; 128]);
+    let tcp1_socket = tcp::Socket::new(tcp1_rx_buffer, tcp1_tx_buffer);
 
-    let tcp2_rx_buffer = TcpSocketBuffer::new(vec![0; 64]);
-    let tcp2_tx_buffer = TcpSocketBuffer::new(vec![0; 128]);
-    let tcp2_socket = TcpSocket::new(tcp2_rx_buffer, tcp2_tx_buffer);
+    let tcp2_rx_buffer = tcp::SocketBuffer::new(vec![0; 64]);
+    let tcp2_tx_buffer = tcp::SocketBuffer::new(vec![0; 128]);
+    let tcp2_socket = tcp::Socket::new(tcp2_rx_buffer, tcp2_tx_buffer);
 
-    let tcp3_rx_buffer = TcpSocketBuffer::new(vec![0; 65535]);
-    let tcp3_tx_buffer = TcpSocketBuffer::new(vec![0; 65535]);
-    let tcp3_socket = TcpSocket::new(tcp3_rx_buffer, tcp3_tx_buffer);
+    let tcp3_rx_buffer = tcp::SocketBuffer::new(vec![0; 65535]);
+    let tcp3_tx_buffer = tcp::SocketBuffer::new(vec![0; 65535]);
+    let tcp3_socket = tcp::Socket::new(tcp3_rx_buffer, tcp3_tx_buffer);
 
-    let tcp4_rx_buffer = TcpSocketBuffer::new(vec![0; 65535]);
-    let tcp4_tx_buffer = TcpSocketBuffer::new(vec![0; 65535]);
-    let tcp4_socket = TcpSocket::new(tcp4_rx_buffer, tcp4_tx_buffer);
+    let tcp4_rx_buffer = tcp::SocketBuffer::new(vec![0; 65535]);
+    let tcp4_tx_buffer = tcp::SocketBuffer::new(vec![0; 65535]);
+    let tcp4_socket = tcp::Socket::new(tcp4_rx_buffer, tcp4_tx_buffer);
 
     let ethernet_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]);
     let ip_addrs = [
@@ -80,7 +79,7 @@ fn main() {
         }
 
         // udp:6969: respond "hello"
-        let socket = iface.get_socket::<UdpSocket>(udp_handle);
+        let socket = iface.get_socket::<udp::Socket>(udp_handle);
         if !socket.is_open() {
             socket.bind(6969).unwrap()
         }
@@ -106,7 +105,7 @@ fn main() {
         }
 
         // tcp:6969: respond "hello"
-        let socket = iface.get_socket::<TcpSocket>(tcp1_handle);
+        let socket = iface.get_socket::<tcp::Socket>(tcp1_handle);
         if !socket.is_open() {
             socket.listen(6969).unwrap();
         }
@@ -119,7 +118,7 @@ fn main() {
         }
 
         // tcp:6970: echo with reverse
-        let socket = iface.get_socket::<TcpSocket>(tcp2_handle);
+        let socket = iface.get_socket::<tcp::Socket>(tcp2_handle);
         if !socket.is_open() {
             socket.listen(6970).unwrap()
         }
@@ -161,7 +160,7 @@ fn main() {
         }
 
         // tcp:6971: sinkhole
-        let socket = iface.get_socket::<TcpSocket>(tcp3_handle);
+        let socket = iface.get_socket::<tcp::Socket>(tcp3_handle);
         if !socket.is_open() {
             socket.listen(6971).unwrap();
             socket.set_keep_alive(Some(Duration::from_millis(1000)));
@@ -182,7 +181,7 @@ fn main() {
         }
 
         // tcp:6972: fountain
-        let socket = iface.get_socket::<TcpSocket>(tcp4_handle);
+        let socket = iface.get_socket::<tcp::Socket>(tcp4_handle);
         if !socket.is_open() {
             socket.listen(6972).unwrap()
         }

+ 5 - 5
examples/sixlowpan.rs

@@ -49,7 +49,7 @@ use std::str;
 
 use smoltcp::iface::{InterfaceBuilder, NeighborCache};
 use smoltcp::phy::{wait as phy_wait, Medium, RawSocket};
-use smoltcp::socket::{UdpPacketMetadata, UdpSocket, UdpSocketBuffer};
+use smoltcp::socket::udp;
 use smoltcp::time::Instant;
 use smoltcp::wire::{Ieee802154Pan, IpAddress, IpCidr};
 
@@ -68,9 +68,9 @@ fn main() {
 
     let neighbor_cache = NeighborCache::new(BTreeMap::new());
 
-    let udp_rx_buffer = UdpSocketBuffer::new(vec![UdpPacketMetadata::EMPTY], vec![0; 64]);
-    let udp_tx_buffer = UdpSocketBuffer::new(vec![UdpPacketMetadata::EMPTY], vec![0; 128]);
-    let udp_socket = UdpSocket::new(udp_rx_buffer, udp_tx_buffer);
+    let udp_rx_buffer = udp::PacketBuffer::new(vec![udp::PacketMetadata::EMPTY], vec![0; 64]);
+    let udp_tx_buffer = udp::PacketBuffer::new(vec![udp::PacketMetadata::EMPTY], vec![0; 128]);
+    let udp_socket = udp::Socket::new(udp_rx_buffer, udp_tx_buffer);
 
     let ieee802154_addr = smoltcp::wire::Ieee802154Address::Extended([
         0x1a, 0x0b, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
@@ -100,7 +100,7 @@ fn main() {
         }
 
         // udp:6969: respond "hello"
-        let socket = iface.get_socket::<UdpSocket>(udp_handle);
+        let socket = iface.get_socket::<udp::Socket>(udp_handle);
         if !socket.is_open() {
             socket.bind(6969).unwrap()
         }

+ 9 - 9
fuzz/fuzz_targets/tcp_headers.rs

@@ -2,7 +2,7 @@
 use libfuzzer_sys::fuzz_target;
 use smoltcp::iface::{InterfaceBuilder, NeighborCache};
 use smoltcp::phy::{Loopback, Medium};
-use smoltcp::socket::{SocketSet, TcpSocket, TcpSocketBuffer};
+use smoltcp::socket::tcp;
 use smoltcp::time::{Duration, Instant};
 use smoltcp::wire::{EthernetAddress, EthernetFrame, EthernetProtocol};
 use smoltcp::wire::{IpAddress, IpCidr, Ipv4Packet, Ipv6Packet, TcpPacket};
@@ -145,17 +145,17 @@ fuzz_target!(|data: &[u8]| {
         // when stack overflows.
         static mut TCP_SERVER_RX_DATA: [u8; 1024] = [0; 1024];
         static mut TCP_SERVER_TX_DATA: [u8; 1024] = [0; 1024];
-        let tcp_rx_buffer = TcpSocketBuffer::new(unsafe { &mut TCP_SERVER_RX_DATA[..] });
-        let tcp_tx_buffer = TcpSocketBuffer::new(unsafe { &mut TCP_SERVER_TX_DATA[..] });
-        TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer)
+        let tcp_rx_buffer = tcp::SocketBuffer::new(unsafe { &mut TCP_SERVER_RX_DATA[..] });
+        let tcp_tx_buffer = tcp::SocketBuffer::new(unsafe { &mut TCP_SERVER_TX_DATA[..] });
+        tcp::Socket::new(tcp_rx_buffer, tcp_tx_buffer)
     };
 
     let client_socket = {
         static mut TCP_CLIENT_RX_DATA: [u8; 1024] = [0; 1024];
         static mut TCP_CLIENT_TX_DATA: [u8; 1024] = [0; 1024];
-        let tcp_rx_buffer = TcpSocketBuffer::new(unsafe { &mut TCP_CLIENT_RX_DATA[..] });
-        let tcp_tx_buffer = TcpSocketBuffer::new(unsafe { &mut TCP_CLIENT_TX_DATA[..] });
-        TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer)
+        let tcp_rx_buffer = tcp::SocketBuffer::new(unsafe { &mut TCP_CLIENT_RX_DATA[..] });
+        let tcp_tx_buffer = tcp::SocketBuffer::new(unsafe { &mut TCP_CLIENT_TX_DATA[..] });
+        tcp::Socket::new(tcp_rx_buffer, tcp_tx_buffer)
     };
 
     let mut socket_set_entries: [_; 2] = Default::default();
@@ -170,7 +170,7 @@ fuzz_target!(|data: &[u8]| {
         let _ = iface.poll(&mut socket_set, clock.elapsed());
 
         {
-            let mut socket = socket_set.get::<TcpSocket>(server_handle);
+            let mut socket = socket_set.get::<tcp::Socket>(server_handle);
             if !socket.is_active() && !socket.is_listening() {
                 if !did_listen {
                     socket.listen(1234).unwrap();
@@ -185,7 +185,7 @@ fuzz_target!(|data: &[u8]| {
         }
 
         {
-            let mut socket = socket_set.get::<TcpSocket>(client_handle);
+            let mut socket = socket_set.get::<tcp::Socket>(client_handle);
             if !socket.is_open() {
                 if !did_connect {
                     socket

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 212 - 259
src/iface/interface.rs


+ 6 - 0
src/lib.rs

@@ -252,3 +252,9 @@ impl fmt::Display for Error {
         }
     }
 }
+
+impl From<wire::Error> for Error {
+    fn from(_: wire::Error) -> Self {
+        Error::Malformed
+    }
+}

+ 26 - 32
src/socket/dhcpv4.rs

@@ -6,7 +6,6 @@ use crate::wire::{
     DhcpMessageType, DhcpPacket, DhcpRepr, IpAddress, IpProtocol, Ipv4Address, Ipv4Cidr, Ipv4Repr,
     UdpRepr, DHCP_CLIENT_PORT, DHCP_MAX_DNS_SERVER_COUNT, DHCP_SERVER_PORT, UDP_HEADER_LEN,
 };
-use crate::{Error, Result};
 
 use super::PollAt;
 
@@ -110,7 +109,7 @@ pub enum Event {
 }
 
 #[derive(Debug)]
-pub struct Dhcpv4Socket {
+pub struct Socket {
     /// State of the DHCP client.
     state: ClientState,
     /// Set to true on config/state change, cleared back to false by the `config` function.
@@ -131,11 +130,11 @@ pub struct Dhcpv4Socket {
 /// The socket acquires an IP address configuration through DHCP autonomously.
 /// You must query the configuration with `.poll()` after every call to `Interface::poll()`,
 /// and apply the configuration to the `Interface`.
-impl Dhcpv4Socket {
+impl Socket {
     /// Create a DHCPv4 socket
     #[allow(clippy::new_without_default)]
     pub fn new() -> Self {
-        Dhcpv4Socket {
+        Socket {
             state: ClientState::Discovering(DiscoverState {
                 retry_at: Instant::from_millis(0),
             }),
@@ -196,7 +195,7 @@ impl Dhcpv4Socket {
         ip_repr: &Ipv4Repr,
         repr: &UdpRepr,
         payload: &[u8],
-    ) -> Result<()> {
+    ) {
         let src_ip = ip_repr.src_addr;
 
         // This is enforced in interface.rs.
@@ -206,27 +205,26 @@ impl Dhcpv4Socket {
             Ok(dhcp_packet) => dhcp_packet,
             Err(e) => {
                 net_debug!("DHCP invalid pkt from {}: {:?}", src_ip, e);
-                return Ok(());
+                return;
             }
         };
         let dhcp_repr = match DhcpRepr::parse(&dhcp_packet) {
             Ok(dhcp_repr) => dhcp_repr,
             Err(e) => {
                 net_debug!("DHCP error parsing pkt from {}: {:?}", src_ip, e);
-                return Ok(());
+                return;
             }
         };
-        let hardware_addr = if let Some(HardwareAddress::Ethernet(addr)) = cx.hardware_addr() {
-            addr
-        } else {
-            return Err(Error::Malformed);
+        let hardware_addr = match cx.hardware_addr() {
+            Some(HardwareAddress::Ethernet(addr)) => addr,
+            _ => return,
         };
 
         if dhcp_repr.client_hardware_address != hardware_addr {
-            return Ok(());
+            return;
         }
         if dhcp_repr.transaction_id != self.transaction_id {
-            return Ok(());
+            return;
         }
         let server_identifier = match dhcp_repr.server_identifier {
             Some(server_identifier) => server_identifier,
@@ -235,7 +233,7 @@ impl Dhcpv4Socket {
                     "DHCP ignoring {:?} because missing server_identifier",
                     dhcp_repr.message_type
                 );
-                return Ok(());
+                return;
             }
         };
 
@@ -250,7 +248,7 @@ impl Dhcpv4Socket {
             (ClientState::Discovering(_state), DhcpMessageType::Offer) => {
                 if !dhcp_repr.your_ip.is_unicast() {
                     net_debug!("DHCP ignoring OFFER because your_ip is not unicast");
-                    return Ok(());
+                    return;
                 }
 
                 self.state = ClientState::Requesting(RequestState {
@@ -305,8 +303,6 @@ impl Dhcpv4Socket {
                 );
             }
         }
-
-        Ok(())
     }
 
     fn parse_ack(
@@ -379,16 +375,16 @@ impl Dhcpv4Socket {
         0x12345678
     }
 
-    pub(crate) fn dispatch<F>(&mut self, cx: &mut Context, emit: F) -> Result<()>
+    pub(crate) fn dispatch<F, E>(&mut self, cx: &mut Context, emit: F) -> Result<(), E>
     where
-        F: FnOnce(&mut Context, (Ipv4Repr, UdpRepr, DhcpRepr)) -> Result<()>,
+        F: FnOnce(&mut Context, (Ipv4Repr, UdpRepr, DhcpRepr)) -> Result<(), E>,
     {
         // note: Dhcpv4Socket is only usable in ethernet mediums, so the
         // unwrap can never fail.
         let ethernet_addr = if let Some(HardwareAddress::Ethernet(addr)) = cx.hardware_addr() {
             addr
         } else {
-            return Err(Error::Malformed);
+            panic!("using DHCPv4 socket with a non-ethernet hardware address.");
         };
 
         // Worst case biggest IPv4 header length.
@@ -435,7 +431,7 @@ impl Dhcpv4Socket {
         match &mut self.state {
             ClientState::Discovering(state) => {
                 if cx.now() < state.retry_at {
-                    return Err(Error::Exhausted);
+                    return Ok(());
                 }
 
                 // send packet
@@ -454,13 +450,12 @@ impl Dhcpv4Socket {
             }
             ClientState::Requesting(state) => {
                 if cx.now() < state.retry_at {
-                    return Err(Error::Exhausted);
+                    return Ok(());
                 }
 
                 if state.retry >= REQUEST_RETRIES {
                     net_debug!("DHCP request retries exceeded, restarting discovery");
                     self.reset();
-                    // return Ok so we get polled again
                     return Ok(());
                 }
 
@@ -492,7 +487,7 @@ impl Dhcpv4Socket {
                 }
 
                 if cx.now() < state.renew_at {
-                    return Err(Error::Exhausted);
+                    return Ok(());
                 }
 
                 ipv4_repr.src_addr = state.config.address.address();
@@ -556,17 +551,18 @@ mod test {
 
     use super::*;
     use crate::wire::EthernetAddress;
+    use crate::Error;
 
     // =========================================================================================//
     // Helper functions
 
     struct TestSocket {
-        socket: Dhcpv4Socket,
+        socket: Socket,
         cx: Context<'static>,
     }
 
     impl Deref for TestSocket {
-        type Target = Dhcpv4Socket;
+        type Target = Socket;
         fn deref(&self) -> &Self::Target {
             &self.socket
         }
@@ -582,7 +578,7 @@ mod test {
         s: &mut TestSocket,
         timestamp: Instant,
         (ip_repr, udp_repr, dhcp_repr): (Ipv4Repr, UdpRepr, DhcpRepr),
-    ) -> Result<()> {
+    ) {
         s.cx.set_now(timestamp);
 
         net_trace!("send: {:?}", ip_repr);
@@ -625,7 +621,7 @@ mod test {
                         None => panic!("Too many reprs emitted"),
                     }
                     i += 1;
-                    Ok(())
+                    Ok::<_, Error>(())
                 });
         }
 
@@ -636,9 +632,7 @@ mod test {
         ($socket:ident, $repr:expr) =>
             (send!($socket, time 0, $repr));
         ($socket:ident, time $time:expr, $repr:expr) =>
-            (send!($socket, time $time, $repr, Ok(( ))));
-        ($socket:ident, time $time:expr, $repr:expr, $result:expr) =>
-            (assert_eq!(send(&mut $socket, Instant::from_millis($time), $repr), $result));
+            (send(&mut $socket, Instant::from_millis($time), $repr));
     }
 
     macro_rules! recv {
@@ -797,7 +791,7 @@ mod test {
     // Tests
 
     fn socket() -> TestSocket {
-        let mut s = Dhcpv4Socket::new();
+        let mut s = Socket::new();
         assert_eq!(s.poll(), Some(Event::Deconfigured));
         TestSocket {
             socket: s,

+ 146 - 73
src/socket/dns.rs

@@ -4,11 +4,10 @@ use core::task::Waker;
 use heapless::Vec;
 use managed::ManagedSlice;
 
-use crate::socket::{Context, PollAt, Socket};
+use crate::socket::{Context, PollAt};
 use crate::time::{Duration, Instant};
 use crate::wire::dns::{Flags, Opcode, Packet, Question, Rcode, Record, RecordData, Repr, Type};
-use crate::wire::{IpAddress, IpProtocol, IpRepr, UdpRepr};
-use crate::{Error, Result};
+use crate::wire::{self, IpAddress, IpProtocol, IpRepr, UdpRepr};
 
 #[cfg(feature = "async")]
 use super::WakerRegistration;
@@ -21,6 +20,25 @@ const RETRANSMIT_DELAY: Duration = Duration::from_millis(1_000);
 const MAX_RETRANSMIT_DELAY: Duration = Duration::from_millis(10_000);
 const RETRANSMIT_TIMEOUT: Duration = Duration::from_millis(10_000); // Should generally be 2-10 secs
 
+/// Error returned by [`Socket::start_query`]
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+#[cfg_attr(feature = "defmt", derive(defmt::Format))]
+pub enum StartQueryError {
+    NoFreeSlot,
+    InvalidName,
+    NameTooLong,
+}
+
+/// Error returned by [`Socket::get_query_result`]
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+#[cfg_attr(feature = "defmt", derive(defmt::Format))]
+pub enum GetQueryResultError {
+    /// Query is not done yet.
+    Pending,
+    /// Query failed.
+    Failed,
+}
+
 /// State for an in-progress DNS query.
 ///
 /// The only reason this struct is public is to allow the socket state
@@ -78,7 +96,7 @@ pub struct QueryHandle(usize);
 /// A UDP socket is bound to a specific endpoint, and owns transmit and receive
 /// packet buffers.
 #[derive(Debug)]
-pub struct DnsSocket<'a> {
+pub struct Socket<'a> {
     servers: Vec<IpAddress, MAX_SERVER_COUNT>,
     queries: ManagedSlice<'a, Option<DnsQuery>>,
 
@@ -86,17 +104,17 @@ pub struct DnsSocket<'a> {
     hop_limit: Option<u8>,
 }
 
-impl<'a> DnsSocket<'a> {
+impl<'a> Socket<'a> {
     /// Create a DNS socket.
     ///
     /// # Panics
     ///
     /// Panics if `servers.len() > MAX_SERVER_COUNT`
-    pub fn new<Q>(servers: &[IpAddress], queries: Q) -> DnsSocket<'a>
+    pub fn new<Q>(servers: &[IpAddress], queries: Q) -> Socket<'a>
     where
         Q: Into<ManagedSlice<'a, Option<DnsQuery>>>,
     {
-        DnsSocket {
+        Socket {
             servers: Vec::from_slice(servers).unwrap(),
             queries: queries.into(),
             hop_limit: None,
@@ -139,20 +157,20 @@ impl<'a> DnsSocket<'a> {
         self.hop_limit = hop_limit
     }
 
-    fn find_free_query(&mut self) -> Result<QueryHandle> {
+    fn find_free_query(&mut self) -> Option<QueryHandle> {
         for (i, q) in self.queries.iter().enumerate() {
             if q.is_none() {
-                return Ok(QueryHandle(i));
+                return Some(QueryHandle(i));
             }
         }
 
         match self.queries {
-            ManagedSlice::Borrowed(_) => Err(Error::Exhausted),
+            ManagedSlice::Borrowed(_) => None,
             #[cfg(any(feature = "std", feature = "alloc"))]
             ManagedSlice::Owned(ref mut queries) => {
                 queries.push(None);
                 let index = queries.len() - 1;
-                Ok(QueryHandle(index))
+                Some(QueryHandle(index))
             }
         }
     }
@@ -162,12 +180,16 @@ impl<'a> DnsSocket<'a> {
     /// `name` is specified in human-friendly format, such as `"rust-lang.org"`.
     /// It accepts names both with and without trailing dot, and they're treated
     /// the same (there's no support for DNS search path).
-    pub fn start_query(&mut self, cx: &mut Context, name: &str) -> Result<QueryHandle> {
+    pub fn start_query(
+        &mut self,
+        cx: &mut Context,
+        name: &str,
+    ) -> Result<QueryHandle, StartQueryError> {
         let mut name = name.as_bytes();
 
         if name.is_empty() {
             net_trace!("invalid name: zero length");
-            return Err(Error::Illegal);
+            return Err(StartQueryError::InvalidName);
         }
 
         // Remove trailing dot, if any
@@ -180,22 +202,26 @@ impl<'a> DnsSocket<'a> {
         for s in name.split(|&c| c == b'.') {
             if s.len() > 63 {
                 net_trace!("invalid name: too long label");
-                return Err(Error::Illegal);
+                return Err(StartQueryError::InvalidName);
             }
             if s.is_empty() {
                 net_trace!("invalid name: zero length label");
-                return Err(Error::Illegal);
+                return Err(StartQueryError::InvalidName);
             }
 
             // Push label
-            raw_name.push(s.len() as u8).map_err(|_| Error::Exhausted)?;
+            raw_name
+                .push(s.len() as u8)
+                .map_err(|_| StartQueryError::NameTooLong)?;
             raw_name
                 .extend_from_slice(s)
-                .map_err(|_| Error::Exhausted)?;
+                .map_err(|_| StartQueryError::NameTooLong)?;
         }
 
         // Push terminator.
-        raw_name.push(0x00).map_err(|_| Error::Exhausted)?;
+        raw_name
+            .push(0x00)
+            .map_err(|_| StartQueryError::NameTooLong)?;
 
         self.start_query_raw(cx, &raw_name)
     }
@@ -204,12 +230,16 @@ impl<'a> DnsSocket<'a> {
     /// `b"\x09rust-lang\x03org\x00"`
     ///
     /// You probably want to use [`start_query`] instead.
-    pub fn start_query_raw(&mut self, cx: &mut Context, raw_name: &[u8]) -> Result<QueryHandle> {
-        let handle = self.find_free_query()?;
+    pub fn start_query_raw(
+        &mut self,
+        cx: &mut Context,
+        raw_name: &[u8],
+    ) -> Result<QueryHandle, StartQueryError> {
+        let handle = self.find_free_query().ok_or(StartQueryError::NoFreeSlot)?;
 
         self.queries[handle.0] = Some(DnsQuery {
             state: State::Pending(PendingQuery {
-                name: Vec::from_slice(raw_name).map_err(|_| Error::Exhausted)?,
+                name: Vec::from_slice(raw_name).map_err(|_| StartQueryError::NameTooLong)?,
                 type_: Type::A,
                 txid: cx.rand().rand_u16(),
                 port: cx.rand().rand_source_port(),
@@ -224,15 +254,21 @@ impl<'a> DnsSocket<'a> {
         Ok(handle)
     }
 
+    /// Get the result of a query.
+    ///
+    /// If the query is completed, the query slot is automatically freed.
+    ///
+    /// # Panics
+    /// Panics if the QueryHandle corresponds to a free slot.
     pub fn get_query_result(
         &mut self,
         handle: QueryHandle,
-    ) -> Result<Vec<IpAddress, MAX_ADDRESS_COUNT>> {
-        let slot = self.queries.get_mut(handle.0).ok_or(Error::Illegal)?;
-        let q = slot.as_mut().ok_or(Error::Illegal)?;
+    ) -> Result<Vec<IpAddress, MAX_ADDRESS_COUNT>, GetQueryResultError> {
+        let slot = &mut self.queries[handle.0];
+        let q = slot.as_mut().unwrap();
         match &mut q.state {
             // Query is not done yet.
-            State::Pending(_) => Err(Error::Exhausted),
+            State::Pending(_) => Err(GetQueryResultError::Pending),
             // Query is done
             State::Completed(q) => {
                 let res = q.addresses.clone();
@@ -241,25 +277,38 @@ impl<'a> DnsSocket<'a> {
             }
             State::Failure => {
                 *slot = None; // Free up the slot for recycling.
-                Err(Error::Unaddressable)
+                Err(GetQueryResultError::Failed)
             }
         }
     }
 
-    pub fn cancel_query(&mut self, handle: QueryHandle) -> Result<()> {
-        let slot = self.queries.get_mut(handle.0).ok_or(Error::Illegal)?;
+    /// Cancels a query, freeing the slot.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the QueryHandle corresponds to an already free slot.
+    pub fn cancel_query(&mut self, handle: QueryHandle) {
+        let slot = &mut self.queries[handle.0];
         if slot.is_none() {
-            return Err(Error::Illegal);
+            panic!("Canceling query in a free slot.")
         }
         *slot = None; // Free up the slot for recycling.
-        Ok(())
     }
 
+    /// Assign a waker to a query slot
+    ///
+    /// The waker will be woken when the query completes, either successfully or failed.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the QueryHandle corresponds to an already free slot.
     #[cfg(feature = "async")]
-    pub fn register_query_waker(&mut self, handle: QueryHandle, waker: &Waker) -> Result<()> {
-        let slot = self.queries.get_mut(handle.0).ok_or(Error::Illegal)?;
-        slot.as_mut().ok_or(Error::Illegal)?.waker.register(waker);
-        Ok(())
+    pub fn register_query_waker(&mut self, handle: QueryHandle, waker: &Waker) {
+        self.queries[handle.0]
+            .as_mut()
+            .unwrap()
+            .waker
+            .register(waker);
     }
 
     pub(crate) fn accepts(&self, ip_repr: &IpRepr, udp_repr: &UdpRepr) -> bool {
@@ -276,7 +325,7 @@ impl<'a> DnsSocket<'a> {
         ip_repr: &IpRepr,
         udp_repr: &UdpRepr,
         payload: &[u8],
-    ) -> Result<()> {
+    ) {
         debug_assert!(self.accepts(ip_repr, udp_repr));
 
         let size = payload.len();
@@ -288,20 +337,26 @@ impl<'a> DnsSocket<'a> {
             udp_repr.dst_port
         );
 
-        let p = Packet::new_checked(payload)?;
+        let p = match Packet::new_checked(payload) {
+            Ok(x) => x,
+            Err(_) => {
+                net_trace!("dns packet malformed");
+                return;
+            }
+        };
         if p.opcode() != Opcode::Query {
             net_trace!("unwanted opcode {:?}", p.opcode());
-            return Err(Error::Malformed);
+            return;
         }
 
         if !p.flags().contains(Flags::RESPONSE) {
             net_trace!("packet doesn't have response bit set");
-            return Err(Error::Malformed);
+            return;
         }
 
         if p.question_count() != 1 {
             net_trace!("bad question count {:?}", p.question_count());
-            return Err(Error::Malformed);
+            return;
         }
 
         // Find pending query
@@ -318,27 +373,53 @@ impl<'a> DnsSocket<'a> {
                 }
 
                 let payload = p.payload();
-                let (mut payload, question) = Question::parse(payload)?;
+                let (mut payload, question) = match Question::parse(payload) {
+                    Ok(x) => x,
+                    Err(_) => {
+                        net_trace!("question malformed");
+                        return;
+                    }
+                };
 
                 if question.type_ != pq.type_ {
                     net_trace!("question type mismatch");
-                    return Err(Error::Malformed);
+                    return;
                 }
 
-                if !eq_names(p.parse_name(question.name), p.parse_name(&pq.name))? {
-                    net_trace!("question name mismatch");
-                    return Err(Error::Malformed);
+                match eq_names(p.parse_name(question.name), p.parse_name(&pq.name)) {
+                    Ok(true) => {}
+                    Ok(false) => {
+                        net_trace!("question name mismatch");
+                        return;
+                    }
+                    Err(_) => {
+                        net_trace!("dns question name malformed");
+                        return;
+                    }
                 }
 
                 let mut addresses = Vec::new();
 
                 for _ in 0..p.answer_record_count() {
-                    let (payload2, r) = Record::parse(payload)?;
+                    let (payload2, r) = match Record::parse(payload) {
+                        Ok(x) => x,
+                        Err(_) => {
+                            net_trace!("dns answer record malformed");
+                            return;
+                        }
+                    };
                     payload = payload2;
 
-                    if !eq_names(p.parse_name(r.name), p.parse_name(&pq.name))? {
-                        net_trace!("answer name mismatch: {:?}", r);
-                        continue;
+                    match eq_names(p.parse_name(r.name), p.parse_name(&pq.name)) {
+                        Ok(true) => {}
+                        Ok(false) => {
+                            net_trace!("answer name mismatch: {:?}", r);
+                            continue;
+                        }
+                        Err(_) => {
+                            net_trace!("dns answer record name malformed");
+                            return;
+                        }
                     }
 
                     match r.data {
@@ -366,7 +447,10 @@ impl<'a> DnsSocket<'a> {
                             // records for the CNAME when we parse them later.
                             // I believe it's mandatory the CNAME results MUST come *after* in the
                             // packet, so it's enough to do one linear pass over it.
-                            copy_name(&mut pq.name, p.parse_name(name))?;
+                            if copy_name(&mut pq.name, p.parse_name(name)).is_err() {
+                                net_trace!("dns answer cname malformed");
+                                return;
+                            }
                         }
                         RecordData::Other(type_, data) => {
                             net_trace!("unknown: {:?} {:?}", type_, data)
@@ -381,18 +465,17 @@ impl<'a> DnsSocket<'a> {
                 });
 
                 // If we get here, packet matched the current query, stop processing.
-                return Ok(());
+                return;
             }
         }
 
         // If we get here, packet matched with no query.
         net_trace!("no query matched");
-        Ok(())
     }
 
-    pub(crate) fn dispatch<F>(&mut self, cx: &mut Context, emit: F) -> Result<()>
+    pub(crate) fn dispatch<F, E>(&mut self, cx: &mut Context, emit: F) -> Result<(), E>
     where
-        F: FnOnce(&mut Context, (IpRepr, UdpRepr, &[u8])) -> Result<()>,
+        F: FnOnce(&mut Context, (IpRepr, UdpRepr, &[u8])) -> Result<(), E>,
     {
         let hop_limit = self.hop_limit.unwrap_or(64);
 
@@ -472,10 +555,7 @@ impl<'a> DnsSocket<'a> {
                     udp_repr.src_port
                 );
 
-                if let Err(e) = emit(cx, (ip_repr, udp_repr, payload)) {
-                    net_trace!("DNS emit error {:?}", e);
-                    return Ok(());
-                }
+                emit(cx, (ip_repr, udp_repr, payload))?;
 
                 pq.retransmit_at = cx.now() + pq.delay;
                 pq.delay = MAX_RETRANSMIT_DELAY.min(pq.delay * 2);
@@ -485,7 +565,7 @@ impl<'a> DnsSocket<'a> {
         }
 
         // Nothing to dispatch
-        Err(Error::Exhausted)
+        Ok(())
     }
 
     pub(crate) fn poll_at(&self, _cx: &Context) -> PollAt {
@@ -502,16 +582,10 @@ impl<'a> DnsSocket<'a> {
     }
 }
 
-impl<'a> From<DnsSocket<'a>> for Socket<'a> {
-    fn from(val: DnsSocket<'a>) -> Self {
-        Socket::Dns(val)
-    }
-}
-
 fn eq_names<'a>(
-    mut a: impl Iterator<Item = Result<&'a [u8]>>,
-    mut b: impl Iterator<Item = Result<&'a [u8]>>,
-) -> Result<bool> {
+    mut a: impl Iterator<Item = wire::Result<&'a [u8]>>,
+    mut b: impl Iterator<Item = wire::Result<&'a [u8]>>,
+) -> wire::Result<bool> {
     loop {
         match (a.next(), b.next()) {
             // Handle errors
@@ -537,19 +611,18 @@ fn eq_names<'a>(
 
 fn copy_name<'a, const N: usize>(
     dest: &mut Vec<u8, N>,
-    name: impl Iterator<Item = Result<&'a [u8]>>,
-) -> Result<()> {
+    name: impl Iterator<Item = wire::Result<&'a [u8]>>,
+) -> Result<(), wire::Error> {
     dest.truncate(0);
 
     for label in name {
         let label = label?;
-        dest.push(label.len() as u8).map_err(|_| Error::Truncated)?;
-        dest.extend_from_slice(label)
-            .map_err(|_| Error::Truncated)?;
+        dest.push(label.len() as u8).map_err(|_| wire::Error)?;
+        dest.extend_from_slice(label).map_err(|_| wire::Error)?;
     }
 
     // Write terminator 0x00
-    dest.push(0).map_err(|_| Error::Truncated)?;
+    dest.push(0).map_err(|_| wire::Error)?;
 
     Ok(())
 }

+ 159 - 122
src/socket/icmp.rs

@@ -6,9 +6,8 @@ use crate::phy::ChecksumCapabilities;
 #[cfg(feature = "async")]
 use crate::socket::WakerRegistration;
 use crate::socket::{Context, PollAt};
-use crate::storage::{PacketBuffer, PacketMetadata};
-use crate::{Error, Result};
 
+use crate::storage::Empty;
 use crate::wire::IcmpRepr;
 #[cfg(feature = "proto-ipv4")]
 use crate::wire::{Icmpv4Packet, Icmpv4Repr, Ipv4Repr};
@@ -17,6 +16,29 @@ use crate::wire::{Icmpv6Packet, Icmpv6Repr, Ipv6Repr};
 use crate::wire::{IpAddress, IpListenEndpoint, IpProtocol, IpRepr};
 use crate::wire::{UdpPacket, UdpRepr};
 
+/// Error returned by [`Socket::bind`]
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+#[cfg_attr(feature = "defmt", derive(defmt::Format))]
+pub enum BindError {
+    InvalidState,
+    Unaddressable,
+}
+
+/// Error returned by [`Socket::send`]
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+#[cfg_attr(feature = "defmt", derive(defmt::Format))]
+pub enum SendError {
+    Unaddressable,
+    BufferFull,
+}
+
+/// Error returned by [`Socket::recv`]
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+#[cfg_attr(feature = "defmt", derive(defmt::Format))]
+pub enum RecvError {
+    Exhausted,
+}
+
 /// Type of endpoint to bind the ICMP socket to. See [IcmpSocket::bind] for
 /// more details.
 ///
@@ -46,10 +68,10 @@ impl Default for Endpoint {
 }
 
 /// An ICMP packet metadata.
-pub type IcmpPacketMetadata = PacketMetadata<IpAddress>;
+pub type PacketMetadata = crate::storage::PacketMetadata<IpAddress>;
 
 /// An ICMP packet ring buffer.
-pub type IcmpSocketBuffer<'a> = PacketBuffer<'a, IpAddress>;
+pub type PacketBuffer<'a> = crate::storage::PacketBuffer<'a, IpAddress>;
 
 /// A ICMP socket
 ///
@@ -61,9 +83,9 @@ pub type IcmpSocketBuffer<'a> = PacketBuffer<'a, IpAddress>;
 /// [IcmpEndpoint]: enum.IcmpEndpoint.html
 /// [bind]: #method.bind
 #[derive(Debug)]
-pub struct IcmpSocket<'a> {
-    rx_buffer: IcmpSocketBuffer<'a>,
-    tx_buffer: IcmpSocketBuffer<'a>,
+pub struct Socket<'a> {
+    rx_buffer: PacketBuffer<'a>,
+    tx_buffer: PacketBuffer<'a>,
     /// The endpoint this socket is communicating with
     endpoint: Endpoint,
     /// The time-to-live (IPv4) or hop limit (IPv6) value used in outgoing packets.
@@ -74,10 +96,10 @@ pub struct IcmpSocket<'a> {
     tx_waker: WakerRegistration,
 }
 
-impl<'a> IcmpSocket<'a> {
+impl<'a> Socket<'a> {
     /// Create an ICMP socket with the given buffers.
-    pub fn new(rx_buffer: IcmpSocketBuffer<'a>, tx_buffer: IcmpSocketBuffer<'a>) -> IcmpSocket<'a> {
-        IcmpSocket {
+    pub fn new(rx_buffer: PacketBuffer<'a>, tx_buffer: PacketBuffer<'a>) -> Socket<'a> {
+        Socket {
             rx_buffer: rx_buffer,
             tx_buffer: tx_buffer,
             endpoint: Default::default(),
@@ -167,18 +189,17 @@ impl<'a> IcmpSocket<'a> {
     /// diagnose connection problems.
     ///
     /// ```
-    /// # use smoltcp::socket::{Socket, IcmpSocket, IcmpSocketBuffer, IcmpPacketMetadata};
-    /// # let rx_buffer = IcmpSocketBuffer::new(vec![IcmpPacketMetadata::EMPTY], vec![0; 20]);
-    /// # let tx_buffer = IcmpSocketBuffer::new(vec![IcmpPacketMetadata::EMPTY], vec![0; 20]);
     /// use smoltcp::wire::IpListenEndpoint;
-    /// use smoltcp::socket::IcmpEndpoint;
+    /// use smoltcp::socket::icmp;
+    /// # let rx_buffer = icmp::PacketBuffer::new(vec![icmp::PacketMetadata::EMPTY], vec![0; 20]);
+    /// # let tx_buffer = icmp::PacketBuffer::new(vec![icmp::PacketMetadata::EMPTY], vec![0; 20]);
     ///
     /// let mut icmp_socket = // ...
-    /// # IcmpSocket::new(rx_buffer, tx_buffer);
+    /// # icmp::Socket::new(rx_buffer, tx_buffer);
     ///
     /// // Bind to ICMP error responses for UDP packets sent from port 53.
     /// let endpoint = IpListenEndpoint::from(53);
-    /// icmp_socket.bind(IcmpEndpoint::Udp(endpoint)).unwrap();
+    /// icmp_socket.bind(icmp::Endpoint::Udp(endpoint)).unwrap();
     /// ```
     ///
     /// ## Bind to a specific ICMP identifier:
@@ -189,16 +210,16 @@ impl<'a> IcmpSocket<'a> {
     /// messages.
     ///
     /// ```
-    /// # use smoltcp::socket::{Socket, IcmpSocket, IcmpSocketBuffer, IcmpPacketMetadata};
-    /// # let rx_buffer = IcmpSocketBuffer::new(vec![IcmpPacketMetadata::EMPTY], vec![0; 20]);
-    /// # let tx_buffer = IcmpSocketBuffer::new(vec![IcmpPacketMetadata::EMPTY], vec![0; 20]);
-    /// use smoltcp::socket::IcmpEndpoint;
+    /// use smoltcp::wire::IpListenEndpoint;
+    /// use smoltcp::socket::icmp;
+    /// # let rx_buffer = icmp::PacketBuffer::new(vec![icmp::PacketMetadata::EMPTY], vec![0; 20]);
+    /// # let tx_buffer = icmp::PacketBuffer::new(vec![icmp::PacketMetadata::EMPTY], vec![0; 20]);
     ///
     /// let mut icmp_socket = // ...
-    /// # IcmpSocket::new(rx_buffer, tx_buffer);
+    /// # icmp::Socket::new(rx_buffer, tx_buffer);
     ///
     /// // Bind to ICMP messages with the ICMP identifier 0x1234
-    /// icmp_socket.bind(IcmpEndpoint::Ident(0x1234)).unwrap();
+    /// icmp_socket.bind(icmp::Endpoint::Ident(0x1234)).unwrap();
     /// ```
     ///
     /// [is_specified]: enum.IcmpEndpoint.html#method.is_specified
@@ -206,14 +227,14 @@ impl<'a> IcmpSocket<'a> {
     /// [IcmpEndpoint::Udp]: enum.IcmpEndpoint.html#variant.Udp
     /// [send]: #method.send
     /// [recv]: #method.recv
-    pub fn bind<T: Into<Endpoint>>(&mut self, endpoint: T) -> Result<()> {
+    pub fn bind<T: Into<Endpoint>>(&mut self, endpoint: T) -> Result<(), BindError> {
         let endpoint = endpoint.into();
         if !endpoint.is_specified() {
-            return Err(Error::Unaddressable);
+            return Err(BindError::Unaddressable);
         }
 
         if self.is_open() {
-            return Err(Error::Illegal);
+            return Err(BindError::InvalidState);
         }
 
         self.endpoint = endpoint;
@@ -275,12 +296,15 @@ impl<'a> IcmpSocket<'a> {
     /// This function returns `Err(Error::Exhausted)` if the transmit buffer is full,
     /// `Err(Error::Truncated)` if the requested size is larger than the packet buffer
     /// size, and `Err(Error::Unaddressable)` if the remote address is unspecified.
-    pub fn send(&mut self, size: usize, endpoint: IpAddress) -> Result<&mut [u8]> {
+    pub fn send(&mut self, size: usize, endpoint: IpAddress) -> Result<&mut [u8], SendError> {
         if endpoint.is_unspecified() {
-            return Err(Error::Unaddressable);
+            return Err(SendError::Unaddressable);
         }
 
-        let packet_buf = self.tx_buffer.enqueue(size, endpoint)?;
+        let packet_buf = self
+            .tx_buffer
+            .enqueue(size, endpoint)
+            .map_err(|_| SendError::BufferFull)?;
 
         net_trace!("icmp:{}: buffer to send {} octets", endpoint, size);
         Ok(packet_buf)
@@ -289,7 +313,7 @@ impl<'a> IcmpSocket<'a> {
     /// Enqueue a packet to be sent to a given remote address, and fill it from a slice.
     ///
     /// See also [send](#method.send).
-    pub fn send_slice(&mut self, data: &[u8], endpoint: IpAddress) -> Result<()> {
+    pub fn send_slice(&mut self, data: &[u8], endpoint: IpAddress) -> Result<(), SendError> {
         let packet_buf = self.send(data.len(), endpoint)?;
         packet_buf.copy_from_slice(data);
         Ok(())
@@ -299,8 +323,8 @@ impl<'a> IcmpSocket<'a> {
     /// as a pointer to the payload.
     ///
     /// This function returns `Err(Error::Exhausted)` if the receive buffer is empty.
-    pub fn recv(&mut self) -> Result<(&[u8], IpAddress)> {
-        let (endpoint, packet_buf) = self.rx_buffer.dequeue()?;
+    pub fn recv(&mut self) -> Result<(&[u8], IpAddress), RecvError> {
+        let (endpoint, packet_buf) = self.rx_buffer.dequeue().map_err(|_| RecvError::Exhausted)?;
 
         net_trace!(
             "icmp:{}: receive {} buffered octets",
@@ -314,7 +338,7 @@ impl<'a> IcmpSocket<'a> {
     /// and return the amount of octets copied as well as the `IpAddress`
     ///
     /// See also [recv](#method.recv).
-    pub fn recv_slice(&mut self, data: &mut [u8]) -> Result<(usize, IpAddress)> {
+    pub fn recv_slice(&mut self, data: &mut [u8]) -> Result<(usize, IpAddress), RecvError> {
         let (buffer, endpoint) = self.recv()?;
         let length = cmp::min(data.len(), buffer.len());
         data[..length].copy_from_slice(&buffer[..length]);
@@ -385,61 +409,54 @@ impl<'a> IcmpSocket<'a> {
         }
     }
 
-    pub(crate) fn process(
-        &mut self,
-        _cx: &mut Context,
-        ip_repr: &IpRepr,
-        icmp_repr: &IcmpRepr,
-    ) -> Result<()> {
+    pub(crate) fn process(&mut self, _cx: &mut Context, ip_repr: &IpRepr, icmp_repr: &IcmpRepr) {
         match *icmp_repr {
             #[cfg(feature = "proto-ipv4")]
             IcmpRepr::Ipv4(ref icmp_repr) => {
-                let packet_buf = self
-                    .rx_buffer
-                    .enqueue(icmp_repr.buffer_len(), ip_repr.src_addr())?;
-                icmp_repr.emit(
-                    &mut Icmpv4Packet::new_unchecked(packet_buf),
-                    &ChecksumCapabilities::default(),
-                );
+                net_trace!("icmp: receiving {} octets", icmp_repr.buffer_len());
 
-                net_trace!(
-                    "icmp:{}: receiving {} octets",
-                    icmp_repr.buffer_len(),
-                    packet_buf.len()
-                );
+                match self
+                    .rx_buffer
+                    .enqueue(icmp_repr.buffer_len(), ip_repr.src_addr())
+                {
+                    Ok(packet_buf) => {
+                        icmp_repr.emit(
+                            &mut Icmpv4Packet::new_unchecked(packet_buf),
+                            &ChecksumCapabilities::default(),
+                        );
+                    }
+                    Err(_) => net_trace!("icmp: buffer full, dropped incoming packet"),
+                }
             }
             #[cfg(feature = "proto-ipv6")]
             IcmpRepr::Ipv6(ref icmp_repr) => {
-                let packet_buf = self
-                    .rx_buffer
-                    .enqueue(icmp_repr.buffer_len(), ip_repr.src_addr())?;
-                icmp_repr.emit(
-                    &ip_repr.src_addr(),
-                    &ip_repr.dst_addr(),
-                    &mut Icmpv6Packet::new_unchecked(packet_buf),
-                    &ChecksumCapabilities::default(),
-                );
+                net_trace!("icmp: receiving {} octets", icmp_repr.buffer_len());
 
-                net_trace!(
-                    "icmp:{}: receiving {} octets",
-                    icmp_repr.buffer_len(),
-                    packet_buf.len()
-                );
+                match self
+                    .rx_buffer
+                    .enqueue(icmp_repr.buffer_len(), ip_repr.src_addr())
+                {
+                    Ok(packet_buf) => icmp_repr.emit(
+                        &ip_repr.src_addr(),
+                        &ip_repr.dst_addr(),
+                        &mut Icmpv6Packet::new_unchecked(packet_buf),
+                        &ChecksumCapabilities::default(),
+                    ),
+                    Err(_) => net_trace!("icmp: buffer full, dropped incoming packet"),
+                }
             }
         }
 
         #[cfg(feature = "async")]
         self.rx_waker.wake();
-
-        Ok(())
     }
 
-    pub(crate) fn dispatch<F>(&mut self, cx: &mut Context, emit: F) -> Result<()>
+    pub(crate) fn dispatch<F, E>(&mut self, cx: &mut Context, emit: F) -> Result<(), E>
     where
-        F: FnOnce(&mut Context, (IpRepr, IcmpRepr)) -> Result<()>,
+        F: FnOnce(&mut Context, (IpRepr, IcmpRepr)) -> Result<(), E>,
     {
         let hop_limit = self.hop_limit.unwrap_or(64);
-        self.tx_buffer.dequeue_with(|remote_endpoint, packet_buf| {
+        let res = self.tx_buffer.dequeue_with(|remote_endpoint, packet_buf| {
             net_trace!(
                 "icmp:{}: sending {} octets",
                 remote_endpoint,
@@ -450,10 +467,25 @@ impl<'a> IcmpSocket<'a> {
                 IpAddress::Ipv4(dst_addr) => {
                     let src_addr = match cx.get_source_address_ipv4(dst_addr) {
                         Some(addr) => addr,
-                        None => return Err(Error::Unaddressable),
+                        None => {
+                            net_trace!(
+                                "icmp:{}: not find suitable source address, dropping",
+                                remote_endpoint
+                            );
+                            return Ok(());
+                        }
                     };
                     let packet = Icmpv4Packet::new_unchecked(&*packet_buf);
-                    let repr = Icmpv4Repr::parse(&packet, &ChecksumCapabilities::ignored())?;
+                    let repr = match Icmpv4Repr::parse(&packet, &ChecksumCapabilities::ignored()) {
+                        Ok(x) => x,
+                        Err(_) => {
+                            net_trace!(
+                                "icmp:{}: malformed packet in queue, dropping",
+                                remote_endpoint
+                            );
+                            return Ok(());
+                        }
+                    };
                     let ip_repr = IpRepr::Ipv4(Ipv4Repr {
                         src_addr,
                         dst_addr,
@@ -467,15 +499,30 @@ impl<'a> IcmpSocket<'a> {
                 IpAddress::Ipv6(dst_addr) => {
                     let src_addr = match cx.get_source_address_ipv6(dst_addr) {
                         Some(addr) => addr,
-                        None => return Err(Error::Unaddressable),
+                        None => {
+                            net_trace!(
+                                "icmp:{}: not find suitable source address, dropping",
+                                remote_endpoint
+                            );
+                            return Ok(());
+                        }
                     };
                     let packet = Icmpv6Packet::new_unchecked(&*packet_buf);
-                    let repr = Icmpv6Repr::parse(
+                    let repr = match Icmpv6Repr::parse(
                         &src_addr.into(),
                         &dst_addr.into(),
                         &packet,
                         &ChecksumCapabilities::ignored(),
-                    )?;
+                    ) {
+                        Ok(x) => x,
+                        Err(_) => {
+                            net_trace!(
+                                "icmp:{}: malformed packet in queue, dropping",
+                                remote_endpoint
+                            );
+                            return Ok(());
+                        }
+                    };
                     let ip_repr = IpRepr::Ipv6(Ipv6Repr {
                         src_addr,
                         dst_addr,
@@ -486,12 +533,16 @@ impl<'a> IcmpSocket<'a> {
                     emit(cx, (ip_repr, IcmpRepr::Ipv6(repr)))
                 }
             }
-        })?;
-
-        #[cfg(feature = "async")]
-        self.tx_waker.wake();
-
-        Ok(())
+        });
+        match res {
+            Err(Empty) => Ok(()),
+            Ok(Err(e)) => Err(e),
+            Ok(Ok(())) => {
+                #[cfg(feature = "async")]
+                self.tx_waker.wake();
+                Ok(())
+            }
+        }
     }
 
     pub(crate) fn poll_at(&self, _cx: &mut Context) -> PollAt {
@@ -509,18 +560,15 @@ mod tests_common {
     pub use crate::phy::DeviceCapabilities;
     pub use crate::wire::IpAddress;
 
-    pub fn buffer(packets: usize) -> IcmpSocketBuffer<'static> {
-        IcmpSocketBuffer::new(
-            vec![IcmpPacketMetadata::EMPTY; packets],
-            vec![0; 66 * packets],
-        )
+    pub fn buffer(packets: usize) -> PacketBuffer<'static> {
+        PacketBuffer::new(vec![PacketMetadata::EMPTY; packets], vec![0; 66 * packets])
     }
 
     pub fn socket(
-        rx_buffer: IcmpSocketBuffer<'static>,
-        tx_buffer: IcmpSocketBuffer<'static>,
-    ) -> IcmpSocket<'static> {
-        IcmpSocket::new(rx_buffer, tx_buffer)
+        rx_buffer: PacketBuffer<'static>,
+        tx_buffer: PacketBuffer<'static>,
+    ) -> Socket<'static> {
+        Socket::new(rx_buffer, tx_buffer)
     }
 
     pub const LOCAL_PORT: u16 = 53;
@@ -536,8 +584,8 @@ mod tests_common {
 #[cfg(all(test, feature = "proto-ipv4"))]
 mod test_ipv4 {
     use super::tests_common::*;
-
     use crate::wire::{Icmpv4DstUnreachable, IpEndpoint, Ipv4Address};
+    use crate::Error;
 
     const REMOTE_IPV4: Ipv4Address = Ipv4Address([192, 168, 1, 2]);
     const LOCAL_IPV4: Ipv4Address = Ipv4Address([192, 168, 1, 1]);
@@ -573,7 +621,7 @@ mod test_ipv4 {
         let mut socket = socket(buffer(0), buffer(1));
         assert_eq!(
             socket.send_slice(b"abcdef", IpAddress::Ipv4(Ipv4Address::default())),
-            Err(Error::Unaddressable)
+            Err(SendError::Unaddressable)
         );
         assert_eq!(socket.send_slice(b"abcdef", REMOTE_IPV4.into()), Ok(()));
     }
@@ -586,13 +634,13 @@ mod test_ipv4 {
 
         assert_eq!(
             socket.dispatch(&mut cx, |_, _| unreachable!()),
-            Err(Error::Exhausted)
+            Ok::<_, ()>(())
         );
 
         // This buffer is too long
         assert_eq!(
             socket.send_slice(&[0xff; 67], REMOTE_IPV4.into()),
-            Err(Error::Truncated)
+            Err(SendError::BufferFull)
         );
         assert!(socket.can_send());
 
@@ -606,7 +654,7 @@ mod test_ipv4 {
         );
         assert_eq!(
             socket.send_slice(b"123456", REMOTE_IPV4.into()),
-            Err(Error::Exhausted)
+            Err(SendError::BufferFull)
         );
         assert!(!socket.can_send());
 
@@ -625,7 +673,7 @@ mod test_ipv4 {
             socket.dispatch(&mut cx, |_, (ip_repr, icmp_repr)| {
                 assert_eq!(ip_repr, LOCAL_IPV4_REPR);
                 assert_eq!(icmp_repr, ECHOV4_REPR.into());
-                Ok(())
+                Ok::<_, Error>(())
             }),
             Ok(())
         );
@@ -661,7 +709,7 @@ mod test_ipv4 {
                         hop_limit: 0x2a,
                     })
                 );
-                Ok(())
+                Ok::<_, Error>(())
             }),
             Ok(())
         );
@@ -674,7 +722,7 @@ mod test_ipv4 {
         assert_eq!(socket.bind(Endpoint::Ident(0x1234)), Ok(()));
 
         assert!(!socket.can_recv());
-        assert_eq!(socket.recv(), Err(Error::Exhausted));
+        assert_eq!(socket.recv(), Err(RecvError::Exhausted));
 
         let checksum = ChecksumCapabilities::default();
 
@@ -684,17 +732,11 @@ mod test_ipv4 {
         let data = &packet.into_inner()[..];
 
         assert!(socket.accepts(&mut cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into()));
-        assert_eq!(
-            socket.process(&mut cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into()),
-            Ok(())
-        );
+        socket.process(&mut cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into());
         assert!(socket.can_recv());
 
         assert!(socket.accepts(&mut cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into()));
-        assert_eq!(
-            socket.process(&mut cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into()),
-            Err(Error::Exhausted)
-        );
+        socket.process(&mut cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into());
 
         assert_eq!(socket.recv(), Ok((data, REMOTE_IPV4.into())));
         assert!(!socket.can_recv());
@@ -766,7 +808,7 @@ mod test_ipv4 {
         // Ensure we can accept ICMP error response to the bound
         // UDP port
         assert!(socket.accepts(&mut cx, &ip_repr, &icmp_repr.into()));
-        assert_eq!(socket.process(&mut cx, &ip_repr, &icmp_repr.into()), Ok(()));
+        socket.process(&mut cx, &ip_repr, &icmp_repr.into());
         assert!(socket.can_recv());
 
         let mut bytes = [0x00; 46];
@@ -785,6 +827,7 @@ mod test_ipv6 {
     use super::tests_common::*;
 
     use crate::wire::{Icmpv6DstUnreachable, IpEndpoint, Ipv6Address};
+    use crate::Error;
 
     const REMOTE_IPV6: Ipv6Address =
         Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]);
@@ -821,7 +864,7 @@ mod test_ipv6 {
         let mut socket = socket(buffer(0), buffer(1));
         assert_eq!(
             socket.send_slice(b"abcdef", IpAddress::Ipv6(Ipv6Address::default())),
-            Err(Error::Unaddressable)
+            Err(SendError::Unaddressable)
         );
         assert_eq!(socket.send_slice(b"abcdef", REMOTE_IPV6.into()), Ok(()));
     }
@@ -834,13 +877,13 @@ mod test_ipv6 {
 
         assert_eq!(
             socket.dispatch(&mut cx, |_, _| unreachable!()),
-            Err(Error::Exhausted)
+            Ok::<_, Error>(())
         );
 
         // This buffer is too long
         assert_eq!(
             socket.send_slice(&[0xff; 67], REMOTE_IPV6.into()),
-            Err(Error::Truncated)
+            Err(SendError::BufferFull)
         );
         assert!(socket.can_send());
 
@@ -859,7 +902,7 @@ mod test_ipv6 {
         );
         assert_eq!(
             socket.send_slice(b"123456", REMOTE_IPV6.into()),
-            Err(Error::Exhausted)
+            Err(SendError::BufferFull)
         );
         assert!(!socket.can_send());
 
@@ -878,7 +921,7 @@ mod test_ipv6 {
             socket.dispatch(&mut cx, |_, (ip_repr, icmp_repr)| {
                 assert_eq!(ip_repr, LOCAL_IPV6_REPR);
                 assert_eq!(icmp_repr, ECHOV6_REPR.into());
-                Ok(())
+                Ok::<_, Error>(())
             }),
             Ok(())
         );
@@ -919,7 +962,7 @@ mod test_ipv6 {
                         hop_limit: 0x2a,
                     })
                 );
-                Ok(())
+                Ok::<_, Error>(())
             }),
             Ok(())
         );
@@ -932,7 +975,7 @@ mod test_ipv6 {
         assert_eq!(socket.bind(Endpoint::Ident(0x1234)), Ok(()));
 
         assert!(!socket.can_recv());
-        assert_eq!(socket.recv(), Err(Error::Exhausted));
+        assert_eq!(socket.recv(), Err(RecvError::Exhausted));
 
         let checksum = ChecksumCapabilities::default();
 
@@ -947,17 +990,11 @@ mod test_ipv6 {
         let data = &packet.into_inner()[..];
 
         assert!(socket.accepts(&mut cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into()));
-        assert_eq!(
-            socket.process(&mut cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into()),
-            Ok(())
-        );
+        socket.process(&mut cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into());
         assert!(socket.can_recv());
 
         assert!(socket.accepts(&mut cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into()));
-        assert_eq!(
-            socket.process(&mut cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into()),
-            Err(Error::Exhausted)
-        );
+        socket.process(&mut cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into());
 
         assert_eq!(socket.recv(), Ok((data, REMOTE_IPV6.into())));
         assert!(!socket.can_recv());
@@ -1034,7 +1071,7 @@ mod test_ipv6 {
         // Ensure we can accept ICMP error response to the bound
         // UDP port
         assert!(socket.accepts(&mut cx, &ip_repr, &icmp_repr.into()));
-        assert_eq!(socket.process(&mut cx, &ip_repr, &icmp_repr.into()), Ok(()));
+        socket.process(&mut cx, &ip_repr, &icmp_repr.into());
         assert!(socket.can_recv());
 
         let mut bytes = [0x00; 66];

+ 19 - 32
src/socket/mod.rs

@@ -15,34 +15,21 @@ use crate::iface::Context;
 use crate::time::Instant;
 
 #[cfg(feature = "socket-dhcpv4")]
-mod dhcpv4;
+pub mod dhcpv4;
 #[cfg(feature = "socket-dns")]
-mod dns;
+pub mod dns;
 #[cfg(feature = "socket-icmp")]
-mod icmp;
+pub mod icmp;
 #[cfg(feature = "socket-raw")]
-mod raw;
+pub mod raw;
 #[cfg(feature = "socket-tcp")]
-mod tcp;
+pub mod tcp;
 #[cfg(feature = "socket-udp")]
-mod udp;
+pub mod udp;
 
 #[cfg(feature = "async")]
 mod waker;
 
-#[cfg(feature = "socket-dhcpv4")]
-pub use self::dhcpv4::{Config as Dhcpv4Config, Dhcpv4Socket, Event as Dhcpv4Event};
-#[cfg(feature = "socket-dns")]
-pub use self::dns::{DnsQuery, DnsSocket, QueryHandle as DnsQueryHandle};
-#[cfg(feature = "socket-icmp")]
-pub use self::icmp::{Endpoint as IcmpEndpoint, IcmpPacketMetadata, IcmpSocket, IcmpSocketBuffer};
-#[cfg(feature = "socket-raw")]
-pub use self::raw::{RawPacketMetadata, RawSocket, RawSocketBuffer};
-#[cfg(feature = "socket-tcp")]
-pub use self::tcp::{SocketBuffer as TcpSocketBuffer, State as TcpState, TcpSocket};
-#[cfg(feature = "socket-udp")]
-pub use self::udp::{UdpPacketMetadata, UdpSocket, UdpSocketBuffer};
-
 #[cfg(feature = "async")]
 pub(crate) use self::waker::WakerRegistration;
 
@@ -62,7 +49,7 @@ pub(crate) enum PollAt {
 ///
 /// This enumeration abstracts the various types of sockets based on the IP protocol.
 /// To downcast a `Socket` value to a concrete socket, use the [AnySocket] trait,
-/// e.g. to get `UdpSocket`, call `UdpSocket::downcast(socket)`.
+/// e.g. to get `udp::Socket`, call `udp::Socket::downcast(socket)`.
 ///
 /// It is usually more convenient to use [SocketSet::get] instead.
 ///
@@ -71,17 +58,17 @@ pub(crate) enum PollAt {
 #[derive(Debug)]
 pub enum Socket<'a> {
     #[cfg(feature = "socket-raw")]
-    Raw(RawSocket<'a>),
+    Raw(raw::Socket<'a>),
     #[cfg(feature = "socket-icmp")]
-    Icmp(IcmpSocket<'a>),
+    Icmp(icmp::Socket<'a>),
     #[cfg(feature = "socket-udp")]
-    Udp(UdpSocket<'a>),
+    Udp(udp::Socket<'a>),
     #[cfg(feature = "socket-tcp")]
-    Tcp(TcpSocket<'a>),
+    Tcp(tcp::Socket<'a>),
     #[cfg(feature = "socket-dhcpv4")]
-    Dhcpv4(Dhcpv4Socket),
+    Dhcpv4(dhcpv4::Socket),
     #[cfg(feature = "socket-dns")]
-    Dns(DnsSocket<'a>),
+    Dns(dns::Socket<'a>),
 }
 
 impl<'a> Socket<'a> {
@@ -128,14 +115,14 @@ macro_rules! from_socket {
 }
 
 #[cfg(feature = "socket-raw")]
-from_socket!(RawSocket<'a>, Raw);
+from_socket!(raw::Socket<'a>, Raw);
 #[cfg(feature = "socket-icmp")]
-from_socket!(IcmpSocket<'a>, Icmp);
+from_socket!(icmp::Socket<'a>, Icmp);
 #[cfg(feature = "socket-udp")]
-from_socket!(UdpSocket<'a>, Udp);
+from_socket!(udp::Socket<'a>, Udp);
 #[cfg(feature = "socket-tcp")]
-from_socket!(TcpSocket<'a>, Tcp);
+from_socket!(tcp::Socket<'a>, Tcp);
 #[cfg(feature = "socket-dhcpv4")]
-from_socket!(Dhcpv4Socket, Dhcpv4);
+from_socket!(dhcpv4::Socket, Dhcpv4);
 #[cfg(feature = "socket-dns")]
-from_socket!(DnsSocket<'a>, Dns);
+from_socket!(dns::Socket<'a>, Dns);

+ 170 - 140
src/socket/raw.rs

@@ -3,51 +3,71 @@ use core::cmp::min;
 use core::task::Waker;
 
 use crate::iface::Context;
-use crate::phy::ChecksumCapabilities;
 use crate::socket::PollAt;
 #[cfg(feature = "async")]
 use crate::socket::WakerRegistration;
-use crate::storage::{PacketBuffer, PacketMetadata};
-use crate::{Error, Result};
 
+use crate::storage::Empty;
 use crate::wire::{IpProtocol, IpRepr, IpVersion};
 #[cfg(feature = "proto-ipv4")]
 use crate::wire::{Ipv4Packet, Ipv4Repr};
 #[cfg(feature = "proto-ipv6")]
 use crate::wire::{Ipv6Packet, Ipv6Repr};
 
+/// Error returned by [`Socket::bind`]
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+#[cfg_attr(feature = "defmt", derive(defmt::Format))]
+pub enum BindError {
+    InvalidState,
+    Unaddressable,
+}
+
+/// Error returned by [`Socket::send`]
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+#[cfg_attr(feature = "defmt", derive(defmt::Format))]
+pub enum SendError {
+    BufferFull,
+}
+
+/// Error returned by [`Socket::recv`]
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+#[cfg_attr(feature = "defmt", derive(defmt::Format))]
+pub enum RecvError {
+    Exhausted,
+}
+
 /// A UDP packet metadata.
-pub type RawPacketMetadata = PacketMetadata<()>;
+pub type PacketMetadata = crate::storage::PacketMetadata<()>;
 
 /// A UDP packet ring buffer.
-pub type RawSocketBuffer<'a> = PacketBuffer<'a, ()>;
+pub type PacketBuffer<'a> = crate::storage::PacketBuffer<'a, ()>;
 
 /// A raw IP socket.
 ///
 /// A raw socket is bound to a specific IP protocol, and owns
 /// transmit and receive packet buffers.
 #[derive(Debug)]
-pub struct RawSocket<'a> {
+pub struct Socket<'a> {
     ip_version: IpVersion,
     ip_protocol: IpProtocol,
-    rx_buffer: RawSocketBuffer<'a>,
-    tx_buffer: RawSocketBuffer<'a>,
+    rx_buffer: PacketBuffer<'a>,
+    tx_buffer: PacketBuffer<'a>,
     #[cfg(feature = "async")]
     rx_waker: WakerRegistration,
     #[cfg(feature = "async")]
     tx_waker: WakerRegistration,
 }
 
-impl<'a> RawSocket<'a> {
+impl<'a> Socket<'a> {
     /// Create a raw IP socket bound to the given IP version and datagram protocol,
     /// with the given buffers.
     pub fn new(
         ip_version: IpVersion,
         ip_protocol: IpProtocol,
-        rx_buffer: RawSocketBuffer<'a>,
-        tx_buffer: RawSocketBuffer<'a>,
-    ) -> RawSocket<'a> {
-        RawSocket {
+        rx_buffer: PacketBuffer<'a>,
+        tx_buffer: PacketBuffer<'a>,
+    ) -> Socket<'a> {
+        Socket {
             ip_version,
             ip_protocol,
             rx_buffer,
@@ -153,8 +173,11 @@ impl<'a> RawSocket<'a> {
     ///
     /// **Note:** The IP header is parsed and re-serialized, and may not match
     /// the header actually transmitted bit for bit.
-    pub fn send(&mut self, size: usize) -> Result<&mut [u8]> {
-        let packet_buf = self.tx_buffer.enqueue(size, ())?;
+    pub fn send(&mut self, size: usize) -> Result<&mut [u8], SendError> {
+        let packet_buf = self
+            .tx_buffer
+            .enqueue(size, ())
+            .map_err(|_| SendError::BufferFull)?;
 
         net_trace!(
             "raw:{}:{}: buffer to send {} octets",
@@ -168,7 +191,7 @@ impl<'a> RawSocket<'a> {
     /// Enqueue a packet to send, and fill it from a slice.
     ///
     /// See also [send](#method.send).
-    pub fn send_slice(&mut self, data: &[u8]) -> Result<()> {
+    pub fn send_slice(&mut self, data: &[u8]) -> Result<(), SendError> {
         self.send(data.len())?.copy_from_slice(data);
         Ok(())
     }
@@ -179,8 +202,8 @@ impl<'a> RawSocket<'a> {
     ///
     /// **Note:** The IP header is parsed and re-serialized, and may not match
     /// the header actually received bit for bit.
-    pub fn recv(&mut self) -> Result<&[u8]> {
-        let ((), packet_buf) = self.rx_buffer.dequeue()?;
+    pub fn recv(&mut self) -> Result<&[u8], RecvError> {
+        let ((), packet_buf) = self.rx_buffer.dequeue().map_err(|_| RecvError::Exhausted)?;
 
         net_trace!(
             "raw:{}:{}: receive {} buffered octets",
@@ -194,7 +217,7 @@ impl<'a> RawSocket<'a> {
     /// Dequeue a packet, and copy the payload into the given slice.
     ///
     /// See also [recv](#method.recv).
-    pub fn recv_slice(&mut self, data: &mut [u8]) -> Result<usize> {
+    pub fn recv_slice(&mut self, data: &mut [u8]) -> Result<usize, RecvError> {
         let buffer = self.recv()?;
         let length = min(data.len(), buffer.len());
         data[..length].copy_from_slice(&buffer[..length]);
@@ -212,48 +235,56 @@ impl<'a> RawSocket<'a> {
         true
     }
 
-    pub(crate) fn process(
-        &mut self,
-        cx: &mut Context,
-        ip_repr: &IpRepr,
-        payload: &[u8],
-    ) -> Result<()> {
+    pub(crate) fn process(&mut self, cx: &mut Context, ip_repr: &IpRepr, payload: &[u8]) {
         debug_assert!(self.accepts(ip_repr));
 
         let header_len = ip_repr.buffer_len();
         let total_len = header_len + payload.len();
-        let packet_buf = self.rx_buffer.enqueue(total_len, ())?;
-        ip_repr.emit(&mut packet_buf[..header_len], &cx.checksum_caps());
-        packet_buf[header_len..].copy_from_slice(payload);
 
         net_trace!(
             "raw:{}:{}: receiving {} octets",
             self.ip_version,
             self.ip_protocol,
-            packet_buf.len()
+            total_len
         );
 
+        match self.rx_buffer.enqueue(total_len, ()) {
+            Ok(buf) => {
+                ip_repr.emit(&mut buf[..header_len], &cx.checksum_caps());
+                buf[header_len..].copy_from_slice(payload);
+            }
+            Err(_) => net_trace!(
+                "raw:{}:{}: buffer full, dropped incoming packet",
+                self.ip_version,
+                self.ip_protocol
+            ),
+        }
+
         #[cfg(feature = "async")]
         self.rx_waker.wake();
-
-        Ok(())
     }
 
-    pub(crate) fn dispatch<F>(&mut self, cx: &mut Context, emit: F) -> Result<()>
+    pub(crate) fn dispatch<F, E>(&mut self, cx: &mut Context, emit: F) -> Result<(), E>
     where
-        F: FnOnce(&mut Context, (IpRepr, &[u8])) -> Result<()>,
+        F: FnOnce(&mut Context, (IpRepr, &[u8])) -> Result<(), E>,
     {
-        fn prepare<'a>(
-            next_header: IpProtocol,
-            buffer: &'a mut [u8],
-            _checksum_caps: &ChecksumCapabilities,
-        ) -> Result<(IpRepr, &'a [u8])> {
-            match IpVersion::of_packet(buffer)? {
+        let ip_protocol = self.ip_protocol;
+        let ip_version = self.ip_version;
+        let _checksum_caps = &cx.checksum_caps();
+        let res = self.tx_buffer.dequeue_with(|&mut (), buffer| {
+            match IpVersion::of_packet(buffer) {
                 #[cfg(feature = "proto-ipv4")]
-                IpVersion::Ipv4 => {
-                    let mut packet = Ipv4Packet::new_checked(buffer)?;
-                    if packet.next_header() != next_header {
-                        return Err(Error::Unaddressable);
+                Ok(IpVersion::Ipv4) => {
+                    let mut packet = match Ipv4Packet::new_checked(buffer) {
+                        Ok(x) => x,
+                        Err(_) => {
+                            net_trace!("raw: malformed ipv6 packet in queue, dropping.");
+                            return Ok(());
+                        }
+                    };
+                    if packet.next_header() != ip_protocol {
+                        net_trace!("raw: sent packet with wrong ip protocol, dropping.");
+                        return Ok(());
                     }
                     if _checksum_caps.ipv4.tx() {
                         packet.fill_checksum();
@@ -263,53 +294,57 @@ impl<'a> RawSocket<'a> {
                         packet.set_checksum(0);
                     }
 
-                    let packet = Ipv4Packet::new_checked(&*packet.into_inner())?;
-                    let ipv4_repr = Ipv4Repr::parse(&packet, _checksum_caps)?;
-                    Ok((IpRepr::Ipv4(ipv4_repr), packet.payload()))
+                    let packet = Ipv4Packet::new_unchecked(&*packet.into_inner());
+                    let ipv4_repr = match Ipv4Repr::parse(&packet, _checksum_caps) {
+                        Ok(x) => x,
+                        Err(_) => {
+                            net_trace!("raw: malformed ipv4 packet in queue, dropping.");
+                            return Ok(());
+                        }
+                    };
+                    net_trace!("raw:{}:{}: sending", ip_version, ip_protocol);
+                    emit(cx, (IpRepr::Ipv4(ipv4_repr), packet.payload()))
                 }
                 #[cfg(feature = "proto-ipv6")]
-                IpVersion::Ipv6 => {
-                    let packet = Ipv6Packet::new_checked(buffer)?;
-                    if packet.next_header() != next_header {
-                        return Err(Error::Unaddressable);
+                Ok(IpVersion::Ipv6) => {
+                    let packet = match Ipv6Packet::new_checked(buffer) {
+                        Ok(x) => x,
+                        Err(_) => {
+                            net_trace!("raw: malformed ipv6 packet in queue, dropping.");
+                            return Ok(());
+                        }
+                    };
+                    if packet.next_header() != ip_protocol {
+                        net_trace!("raw: sent ipv6 packet with wrong ip protocol, dropping.");
+                        return Ok(());
                     }
                     let packet = Ipv6Packet::new_unchecked(&*packet.into_inner());
-                    let ipv6_repr = Ipv6Repr::parse(&packet)?;
-                    Ok((IpRepr::Ipv6(ipv6_repr), packet.payload()))
+                    let ipv6_repr = match Ipv6Repr::parse(&packet) {
+                        Ok(x) => x,
+                        Err(_) => {
+                            net_trace!("raw: malformed ipv6 packet in queue, dropping.");
+                            return Ok(());
+                        }
+                    };
+
+                    net_trace!("raw:{}:{}: sending", ip_version, ip_protocol);
+                    emit(cx, (IpRepr::Ipv6(ipv6_repr), packet.payload()))
                 }
-            }
-        }
-
-        let ip_protocol = self.ip_protocol;
-        let ip_version = self.ip_version;
-        self.tx_buffer.dequeue_with(|&mut (), packet_buf| {
-            match prepare(ip_protocol, packet_buf, &cx.checksum_caps()) {
-                Ok((ip_repr, raw_packet)) => {
-                    net_trace!(
-                        "raw:{}:{}: sending {} octets",
-                        ip_version,
-                        ip_protocol,
-                        ip_repr.buffer_len() + raw_packet.len()
-                    );
-                    emit(cx, (ip_repr, raw_packet))
-                }
-                Err(error) => {
-                    net_debug!(
-                        "raw:{}:{}: dropping outgoing packet ({})",
-                        ip_version,
-                        ip_protocol,
-                        error
-                    );
-                    // Return Ok(()) so the packet is dequeued.
+                Err(_) => {
+                    net_trace!("raw: sent packet with invalid IP version, dropping.");
                     Ok(())
                 }
             }
-        })?;
-
-        #[cfg(feature = "async")]
-        self.tx_waker.wake();
-
-        Ok(())
+        });
+        match res {
+            Err(Empty) => Ok(()),
+            Ok(Err(e)) => Err(e),
+            Ok(Ok(())) => {
+                #[cfg(feature = "async")]
+                self.tx_waker.wake();
+                Ok(())
+            }
+        }
     }
 
     pub(crate) fn poll_at(&self, _cx: &mut Context) -> PollAt {
@@ -329,12 +364,10 @@ mod test {
     use crate::wire::{Ipv4Address, Ipv4Repr};
     #[cfg(feature = "proto-ipv6")]
     use crate::wire::{Ipv6Address, Ipv6Repr};
+    use crate::Error;
 
-    fn buffer(packets: usize) -> RawSocketBuffer<'static> {
-        RawSocketBuffer::new(
-            vec![RawPacketMetadata::EMPTY; packets],
-            vec![0; 48 * packets],
-        )
+    fn buffer(packets: usize) -> PacketBuffer<'static> {
+        PacketBuffer::new(vec![PacketMetadata::EMPTY; packets], vec![0; 48 * packets])
     }
 
     #[cfg(feature = "proto-ipv4")]
@@ -342,10 +375,10 @@ mod test {
         use super::*;
 
         pub fn socket(
-            rx_buffer: RawSocketBuffer<'static>,
-            tx_buffer: RawSocketBuffer<'static>,
-        ) -> RawSocket<'static> {
-            RawSocket::new(
+            rx_buffer: PacketBuffer<'static>,
+            tx_buffer: PacketBuffer<'static>,
+        ) -> Socket<'static> {
+            Socket::new(
                 IpVersion::Ipv4,
                 IpProtocol::Unknown(IP_PROTO),
                 rx_buffer,
@@ -373,10 +406,10 @@ mod test {
         use super::*;
 
         pub fn socket(
-            rx_buffer: RawSocketBuffer<'static>,
-            tx_buffer: RawSocketBuffer<'static>,
-        ) -> RawSocket<'static> {
-            RawSocket::new(
+            rx_buffer: PacketBuffer<'static>,
+            tx_buffer: PacketBuffer<'static>,
+        ) -> Socket<'static> {
+            Socket::new(
                 IpVersion::Ipv6,
                 IpProtocol::Unknown(IP_PROTO),
                 rx_buffer,
@@ -417,7 +450,7 @@ mod test {
                 #[test]
                 fn test_send_truncated() {
                     let mut socket = $socket(buffer(0), buffer(1));
-                    assert_eq!(socket.send_slice(&[0; 56][..]), Err(Error::Truncated));
+                    assert_eq!(socket.send_slice(&[0; 56][..]), Err(SendError::BufferFull));
                 }
 
                 #[test]
@@ -428,11 +461,11 @@ mod test {
                     assert!(socket.can_send());
                     assert_eq!(
                         socket.dispatch(&mut cx, |_, _| unreachable!()),
-                        Err(Error::Exhausted)
+                        Ok::<_, Error>(())
                     );
 
                     assert_eq!(socket.send_slice(&$packet[..]), Ok(()));
-                    assert_eq!(socket.send_slice(b""), Err(Error::Exhausted));
+                    assert_eq!(socket.send_slice(b""), Err(SendError::BufferFull));
                     assert!(!socket.can_send());
 
                     assert_eq!(
@@ -449,7 +482,7 @@ mod test {
                         socket.dispatch(&mut cx, |_, (ip_repr, ip_payload)| {
                             assert_eq!(ip_repr, $hdr);
                             assert_eq!(ip_payload, &$payload);
-                            Ok(())
+                            Ok::<_, Error>(())
                         }),
                         Ok(())
                     );
@@ -462,7 +495,7 @@ mod test {
                     let mut cx = Context::mock();
 
                     assert!(socket.accepts(&$hdr));
-                    assert_eq!(socket.process(&mut cx, &$hdr, &$payload), Ok(()));
+                    socket.process(&mut cx, &$hdr, &$payload);
 
                     let mut slice = [0; 4];
                     assert_eq!(socket.recv_slice(&mut slice[..]), Ok(4));
@@ -478,10 +511,7 @@ mod test {
                     buffer[..$packet.len()].copy_from_slice(&$packet[..]);
 
                     assert!(socket.accepts(&$hdr));
-                    assert_eq!(
-                        socket.process(&mut cx, &$hdr, &buffer),
-                        Err(Error::Truncated)
-                    );
+                    socket.process(&mut cx, &$hdr, &buffer);
                 }
             }
         };
@@ -517,13 +547,19 @@ mod test {
             Ipv4Packet::new_unchecked(&mut wrong_version).set_version(6);
 
             assert_eq!(socket.send_slice(&wrong_version[..]), Ok(()));
-            assert_eq!(socket.dispatch(&mut cx, |_, _| unreachable!()), Ok(()));
+            assert_eq!(
+                socket.dispatch(&mut cx, |_, _| unreachable!()),
+                Ok::<_, Error>(())
+            );
 
             let mut wrong_protocol = ipv4_locals::PACKET_BYTES;
             Ipv4Packet::new_unchecked(&mut wrong_protocol).set_next_header(IpProtocol::Tcp);
 
             assert_eq!(socket.send_slice(&wrong_protocol[..]), Ok(()));
-            assert_eq!(socket.dispatch(&mut cx, |_, _| unreachable!()), Ok(()));
+            assert_eq!(
+                socket.dispatch(&mut cx, |_, _| unreachable!()),
+                Ok::<_, Error>(())
+            );
         }
         #[cfg(feature = "proto-ipv6")]
         {
@@ -534,13 +570,19 @@ mod test {
             Ipv6Packet::new_unchecked(&mut wrong_version[..]).set_version(4);
 
             assert_eq!(socket.send_slice(&wrong_version[..]), Ok(()));
-            assert_eq!(socket.dispatch(&mut cx, |_, _| unreachable!()), Ok(()));
+            assert_eq!(
+                socket.dispatch(&mut cx, |_, _| unreachable!()),
+                Ok::<_, Error>(())
+            );
 
             let mut wrong_protocol = ipv6_locals::PACKET_BYTES;
             Ipv6Packet::new_unchecked(&mut wrong_protocol[..]).set_next_header(IpProtocol::Tcp);
 
             assert_eq!(socket.send_slice(&wrong_protocol[..]), Ok(()));
-            assert_eq!(socket.dispatch(&mut cx, |_, _| unreachable!()), Ok(()));
+            assert_eq!(
+                socket.dispatch(&mut cx, |_, _| unreachable!()),
+                Ok::<_, Error>(())
+            );
         }
     }
 
@@ -555,26 +597,20 @@ mod test {
             let mut cksumd_packet = ipv4_locals::PACKET_BYTES;
             Ipv4Packet::new_unchecked(&mut cksumd_packet).fill_checksum();
 
-            assert_eq!(socket.recv(), Err(Error::Exhausted));
+            assert_eq!(socket.recv(), Err(RecvError::Exhausted));
             assert!(socket.accepts(&ipv4_locals::HEADER_REPR));
-            assert_eq!(
-                socket.process(
-                    &mut cx,
-                    &ipv4_locals::HEADER_REPR,
-                    &ipv4_locals::PACKET_PAYLOAD
-                ),
-                Ok(())
+            socket.process(
+                &mut cx,
+                &ipv4_locals::HEADER_REPR,
+                &ipv4_locals::PACKET_PAYLOAD,
             );
             assert!(socket.can_recv());
 
             assert!(socket.accepts(&ipv4_locals::HEADER_REPR));
-            assert_eq!(
-                socket.process(
-                    &mut cx,
-                    &ipv4_locals::HEADER_REPR,
-                    &ipv4_locals::PACKET_PAYLOAD
-                ),
-                Err(Error::Exhausted)
+            socket.process(
+                &mut cx,
+                &ipv4_locals::HEADER_REPR,
+                &ipv4_locals::PACKET_PAYLOAD,
             );
             assert_eq!(socket.recv(), Ok(&cksumd_packet[..]));
             assert!(!socket.can_recv());
@@ -585,26 +621,20 @@ mod test {
             assert!(!socket.can_recv());
             let mut cx = Context::mock();
 
-            assert_eq!(socket.recv(), Err(Error::Exhausted));
+            assert_eq!(socket.recv(), Err(RecvError::Exhausted));
             assert!(socket.accepts(&ipv6_locals::HEADER_REPR));
-            assert_eq!(
-                socket.process(
-                    &mut cx,
-                    &ipv6_locals::HEADER_REPR,
-                    &ipv6_locals::PACKET_PAYLOAD
-                ),
-                Ok(())
+            socket.process(
+                &mut cx,
+                &ipv6_locals::HEADER_REPR,
+                &ipv6_locals::PACKET_PAYLOAD,
             );
             assert!(socket.can_recv());
 
             assert!(socket.accepts(&ipv6_locals::HEADER_REPR));
-            assert_eq!(
-                socket.process(
-                    &mut cx,
-                    &ipv6_locals::HEADER_REPR,
-                    &ipv6_locals::PACKET_PAYLOAD
-                ),
-                Err(Error::Exhausted)
+            socket.process(
+                &mut cx,
+                &ipv6_locals::HEADER_REPR,
+                &ipv6_locals::PACKET_PAYLOAD,
             );
             assert_eq!(socket.recv(), Ok(&ipv6_locals::PACKET_BYTES[..]));
             assert!(!socket.can_recv());
@@ -615,7 +645,7 @@ mod test {
     fn test_doesnt_accept_wrong_proto() {
         #[cfg(feature = "proto-ipv4")]
         {
-            let socket = RawSocket::new(
+            let socket = Socket::new(
                 IpVersion::Ipv4,
                 IpProtocol::Unknown(ipv4_locals::IP_PROTO + 1),
                 buffer(1),
@@ -627,7 +657,7 @@ mod test {
         }
         #[cfg(feature = "proto-ipv6")]
         {
-            let socket = RawSocket::new(
+            let socket = Socket::new(
                 IpVersion::Ipv6,
                 IpProtocol::Unknown(ipv6_locals::IP_PROTO + 1),
                 buffer(1),

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 156 - 132
src/socket/tcp.rs


+ 154 - 120
src/socket/udp.rs

@@ -6,25 +6,47 @@ use crate::iface::Context;
 use crate::socket::PollAt;
 #[cfg(feature = "async")]
 use crate::socket::WakerRegistration;
-use crate::storage::{PacketBuffer, PacketMetadata};
+use crate::storage::Empty;
 use crate::wire::{IpEndpoint, IpListenEndpoint, IpProtocol, IpRepr, UdpRepr};
-use crate::{Error, Result};
 
 /// A UDP packet metadata.
-pub type UdpPacketMetadata = PacketMetadata<IpEndpoint>;
+pub type PacketMetadata = crate::storage::PacketMetadata<IpEndpoint>;
 
 /// A UDP packet ring buffer.
-pub type UdpSocketBuffer<'a> = PacketBuffer<'a, IpEndpoint>;
+pub type PacketBuffer<'a> = crate::storage::PacketBuffer<'a, IpEndpoint>;
+
+/// Error returned by [`Socket::bind`]
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+#[cfg_attr(feature = "defmt", derive(defmt::Format))]
+pub enum BindError {
+    InvalidState,
+    Unaddressable,
+}
+
+/// Error returned by [`Socket::send`]
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+#[cfg_attr(feature = "defmt", derive(defmt::Format))]
+pub enum SendError {
+    Unaddressable,
+    BufferFull,
+}
+
+/// Error returned by [`Socket::recv`]
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+#[cfg_attr(feature = "defmt", derive(defmt::Format))]
+pub enum RecvError {
+    Exhausted,
+}
 
 /// A User Datagram Protocol socket.
 ///
 /// A UDP socket is bound to a specific endpoint, and owns transmit and receive
 /// packet buffers.
 #[derive(Debug)]
-pub struct UdpSocket<'a> {
+pub struct Socket<'a> {
     endpoint: IpListenEndpoint,
-    rx_buffer: UdpSocketBuffer<'a>,
-    tx_buffer: UdpSocketBuffer<'a>,
+    rx_buffer: PacketBuffer<'a>,
+    tx_buffer: PacketBuffer<'a>,
     /// The time-to-live (IPv4) or hop limit (IPv6) value used in outgoing packets.
     hop_limit: Option<u8>,
     #[cfg(feature = "async")]
@@ -33,10 +55,10 @@ pub struct UdpSocket<'a> {
     tx_waker: WakerRegistration,
 }
 
-impl<'a> UdpSocket<'a> {
+impl<'a> Socket<'a> {
     /// Create an UDP socket with the given buffers.
-    pub fn new(rx_buffer: UdpSocketBuffer<'a>, tx_buffer: UdpSocketBuffer<'a>) -> UdpSocket<'a> {
-        UdpSocket {
+    pub fn new(rx_buffer: PacketBuffer<'a>, tx_buffer: PacketBuffer<'a>) -> Socket<'a> {
+        Socket {
             endpoint: IpListenEndpoint::default(),
             rx_buffer,
             tx_buffer,
@@ -121,14 +143,14 @@ impl<'a> UdpSocket<'a> {
     /// This function returns `Err(Error::Illegal)` if the socket was open
     /// (see [is_open](#method.is_open)), and `Err(Error::Unaddressable)`
     /// if the port in the given endpoint is zero.
-    pub fn bind<T: Into<IpListenEndpoint>>(&mut self, endpoint: T) -> Result<()> {
+    pub fn bind<T: Into<IpListenEndpoint>>(&mut self, endpoint: T) -> Result<(), BindError> {
         let endpoint = endpoint.into();
         if endpoint.port == 0 {
-            return Err(Error::Unaddressable);
+            return Err(BindError::Unaddressable);
         }
 
         if self.is_open() {
-            return Err(Error::Illegal);
+            return Err(BindError::InvalidState);
         }
 
         self.endpoint = endpoint;
@@ -207,18 +229,25 @@ impl<'a> UdpSocket<'a> {
     /// `Err(Error::Unaddressable)` if local or remote port, or remote address are unspecified,
     /// and `Err(Error::Truncated)` if there is not enough transmit buffer capacity
     /// to ever send this packet.
-    pub fn send(&mut self, size: usize, remote_endpoint: IpEndpoint) -> Result<&mut [u8]> {
+    pub fn send(
+        &mut self,
+        size: usize,
+        remote_endpoint: IpEndpoint,
+    ) -> Result<&mut [u8], SendError> {
         if self.endpoint.port == 0 {
-            return Err(Error::Unaddressable);
+            return Err(SendError::Unaddressable);
         }
         if remote_endpoint.addr.is_unspecified() {
-            return Err(Error::Unaddressable);
+            return Err(SendError::Unaddressable);
         }
         if remote_endpoint.port == 0 {
-            return Err(Error::Unaddressable);
+            return Err(SendError::Unaddressable);
         }
 
-        let payload_buf = self.tx_buffer.enqueue(size, remote_endpoint)?;
+        let payload_buf = self
+            .tx_buffer
+            .enqueue(size, remote_endpoint)
+            .map_err(|_| SendError::BufferFull)?;
 
         net_trace!(
             "udp:{}:{}: buffer to send {} octets",
@@ -232,7 +261,11 @@ impl<'a> UdpSocket<'a> {
     /// Enqueue a packet to be sent to a given remote endpoint, and fill it from a slice.
     ///
     /// See also [send](#method.send).
-    pub fn send_slice(&mut self, data: &[u8], remote_endpoint: IpEndpoint) -> Result<()> {
+    pub fn send_slice(
+        &mut self,
+        data: &[u8],
+        remote_endpoint: IpEndpoint,
+    ) -> Result<(), SendError> {
         self.send(data.len(), remote_endpoint)?
             .copy_from_slice(data);
         Ok(())
@@ -242,8 +275,9 @@ impl<'a> UdpSocket<'a> {
     /// as a pointer to the payload.
     ///
     /// This function returns `Err(Error::Exhausted)` if the receive buffer is empty.
-    pub fn recv(&mut self) -> Result<(&[u8], IpEndpoint)> {
-        let (remote_endpoint, payload_buf) = self.rx_buffer.dequeue()?;
+    pub fn recv(&mut self) -> Result<(&[u8], IpEndpoint), RecvError> {
+        let (remote_endpoint, payload_buf) =
+            self.rx_buffer.dequeue().map_err(|_| RecvError::Exhausted)?;
 
         net_trace!(
             "udp:{}:{}: receive {} buffered octets",
@@ -258,8 +292,8 @@ impl<'a> UdpSocket<'a> {
     /// and return the amount of octets copied as well as the endpoint.
     ///
     /// See also [recv](#method.recv).
-    pub fn recv_slice(&mut self, data: &mut [u8]) -> Result<(usize, IpEndpoint)> {
-        let (buffer, endpoint) = self.recv()?;
+    pub fn recv_slice(&mut self, data: &mut [u8]) -> Result<(usize, IpEndpoint), RecvError> {
+        let (buffer, endpoint) = self.recv().map_err(|_| RecvError::Exhausted)?;
         let length = min(data.len(), buffer.len());
         data[..length].copy_from_slice(&buffer[..length]);
         Ok((length, endpoint))
@@ -270,17 +304,19 @@ impl<'a> UdpSocket<'a> {
     /// This function otherwise behaves identically to [recv](#method.recv).
     ///
     /// It returns `Err(Error::Exhausted)` if the receive buffer is empty.
-    pub fn peek(&mut self) -> Result<(&[u8], &IpEndpoint)> {
+    pub fn peek(&mut self) -> Result<(&[u8], &IpEndpoint), RecvError> {
         let endpoint = self.endpoint;
-        self.rx_buffer.peek().map(|(remote_endpoint, payload_buf)| {
-            net_trace!(
-                "udp:{}:{}: peek {} buffered octets",
-                endpoint,
-                remote_endpoint,
-                payload_buf.len()
-            );
-            (payload_buf, remote_endpoint)
-        })
+        self.rx_buffer.peek().map_err(|_| RecvError::Exhausted).map(
+            |(remote_endpoint, payload_buf)| {
+                net_trace!(
+                    "udp:{}:{}: peek {} buffered octets",
+                    endpoint,
+                    remote_endpoint,
+                    payload_buf.len()
+                );
+                (payload_buf, remote_endpoint)
+            },
+        )
     }
 
     /// Peek at a packet received from a remote endpoint, copy the payload into the given slice,
@@ -289,7 +325,7 @@ impl<'a> UdpSocket<'a> {
     /// This function otherwise behaves identically to [recv_slice](#method.recv_slice).
     ///
     /// See also [peek](#method.peek).
-    pub fn peek_slice(&mut self, data: &mut [u8]) -> Result<(usize, &IpEndpoint)> {
+    pub fn peek_slice(&mut self, data: &mut [u8]) -> Result<(usize, &IpEndpoint), RecvError> {
         let (buffer, endpoint) = self.peek()?;
         let length = min(data.len(), buffer.len());
         data[..length].copy_from_slice(&buffer[..length]);
@@ -317,7 +353,7 @@ impl<'a> UdpSocket<'a> {
         ip_repr: &IpRepr,
         repr: &UdpRepr,
         payload: &[u8],
-    ) -> Result<()> {
+    ) {
         debug_assert!(self.accepts(cx, ip_repr, repr));
 
         let size = payload.len();
@@ -326,9 +362,6 @@ impl<'a> UdpSocket<'a> {
             addr: ip_repr.src_addr(),
             port: repr.src_port,
         };
-        self.rx_buffer
-            .enqueue(size, remote_endpoint)?
-            .copy_from_slice(payload);
 
         net_trace!(
             "udp:{}:{}: receiving {} octets",
@@ -337,54 +370,71 @@ impl<'a> UdpSocket<'a> {
             size
         );
 
+        match self.rx_buffer.enqueue(size, remote_endpoint) {
+            Ok(buf) => buf.copy_from_slice(payload),
+            Err(_) => net_trace!(
+                "udp:{}:{}: buffer full, dropped incoming packet",
+                self.endpoint,
+                remote_endpoint
+            ),
+        }
+
         #[cfg(feature = "async")]
         self.rx_waker.wake();
-
-        Ok(())
     }
 
-    pub(crate) fn dispatch<F>(&mut self, cx: &mut Context, emit: F) -> Result<()>
+    pub(crate) fn dispatch<F, E>(&mut self, cx: &mut Context, emit: F) -> Result<(), E>
     where
-        F: FnOnce(&mut Context, (IpRepr, UdpRepr, &[u8])) -> Result<()>,
+        F: FnOnce(&mut Context, (IpRepr, UdpRepr, &[u8])) -> Result<(), E>,
     {
         let endpoint = self.endpoint;
         let hop_limit = self.hop_limit.unwrap_or(64);
 
-        self.tx_buffer
-            .dequeue_with(|remote_endpoint, payload_buf| {
-                let src_addr = match endpoint.addr {
+        let res = self.tx_buffer.dequeue_with(|remote_endpoint, payload_buf| {
+            let src_addr = match endpoint.addr {
+                Some(addr) => addr,
+                None => match cx.get_source_address(remote_endpoint.addr) {
                     Some(addr) => addr,
-                    None => match cx.get_source_address(remote_endpoint.addr) {
-                        Some(addr) => addr,
-                        None => return Err(Error::Unaddressable),
-                    },
-                };
-
-                net_trace!(
-                    "udp:{}:{}: sending {} octets",
-                    endpoint,
-                    remote_endpoint,
-                    payload_buf.len()
-                );
-
-                let repr = UdpRepr {
-                    src_port: endpoint.port,
-                    dst_port: remote_endpoint.port,
-                };
-                let ip_repr = IpRepr::new(
-                    src_addr,
-                    remote_endpoint.addr,
-                    IpProtocol::Udp,
-                    repr.header_len() + payload_buf.len(),
-                    hop_limit,
-                );
-                emit(cx, (ip_repr, repr, payload_buf))
-            })?;
+                    None => {
+                        net_trace!(
+                            "udp:{}:{}: cannot find suitable source address, dropping.",
+                            endpoint,
+                            remote_endpoint
+                        );
+                        return Ok(());
+                    }
+                },
+            };
 
-        #[cfg(feature = "async")]
-        self.tx_waker.wake();
+            net_trace!(
+                "udp:{}:{}: sending {} octets",
+                endpoint,
+                remote_endpoint,
+                payload_buf.len()
+            );
 
-        Ok(())
+            let repr = UdpRepr {
+                src_port: endpoint.port,
+                dst_port: remote_endpoint.port,
+            };
+            let ip_repr = IpRepr::new(
+                src_addr,
+                remote_endpoint.addr,
+                IpProtocol::Udp,
+                repr.header_len() + payload_buf.len(),
+                hop_limit,
+            );
+            emit(cx, (ip_repr, repr, payload_buf))
+        });
+        match res {
+            Err(Empty) => Ok(()),
+            Ok(Err(e)) => Err(e),
+            Ok(Ok(())) => {
+                #[cfg(feature = "async")]
+                self.tx_waker.wake();
+                Ok(())
+            }
+        }
     }
 
     pub(crate) fn poll_at(&self, _cx: &mut Context) -> PollAt {
@@ -400,19 +450,17 @@ impl<'a> UdpSocket<'a> {
 mod test {
     use super::*;
     use crate::wire::{IpRepr, UdpRepr};
+    use crate::Error;
 
-    fn buffer(packets: usize) -> UdpSocketBuffer<'static> {
-        UdpSocketBuffer::new(
-            vec![UdpPacketMetadata::EMPTY; packets],
-            vec![0; 16 * packets],
-        )
+    fn buffer(packets: usize) -> PacketBuffer<'static> {
+        PacketBuffer::new(vec![PacketMetadata::EMPTY; packets], vec![0; 16 * packets])
     }
 
     fn socket(
-        rx_buffer: UdpSocketBuffer<'static>,
-        tx_buffer: UdpSocketBuffer<'static>,
-    ) -> UdpSocket<'static> {
-        UdpSocket::new(rx_buffer, tx_buffer)
+        rx_buffer: PacketBuffer<'static>,
+        tx_buffer: PacketBuffer<'static>,
+    ) -> Socket<'static> {
+        Socket::new(rx_buffer, tx_buffer)
     }
 
     const LOCAL_PORT: u16 = 53;
@@ -492,14 +540,14 @@ mod test {
     #[test]
     fn test_bind_unaddressable() {
         let mut socket = socket(buffer(0), buffer(0));
-        assert_eq!(socket.bind(0), Err(Error::Unaddressable));
+        assert_eq!(socket.bind(0), Err(BindError::Unaddressable));
     }
 
     #[test]
     fn test_bind_twice() {
         let mut socket = socket(buffer(0), buffer(0));
         assert_eq!(socket.bind(1), Ok(()));
-        assert_eq!(socket.bind(2), Err(Error::Illegal));
+        assert_eq!(socket.bind(2), Err(BindError::InvalidState));
     }
 
     #[test]
@@ -515,7 +563,7 @@ mod test {
 
         assert_eq!(
             socket.send_slice(b"abcdef", REMOTE_END),
-            Err(Error::Unaddressable)
+            Err(SendError::Unaddressable)
         );
         assert_eq!(socket.bind(LOCAL_PORT), Ok(()));
         assert_eq!(
@@ -526,7 +574,7 @@ mod test {
                     ..REMOTE_END
                 }
             ),
-            Err(Error::Unaddressable)
+            Err(SendError::Unaddressable)
         );
         assert_eq!(
             socket.send_slice(
@@ -536,7 +584,7 @@ mod test {
                     ..REMOTE_END
                 }
             ),
-            Err(Error::Unaddressable)
+            Err(SendError::Unaddressable)
         );
         assert_eq!(socket.send_slice(b"abcdef", REMOTE_END), Ok(()));
     }
@@ -551,13 +599,13 @@ mod test {
         assert!(socket.can_send());
         assert_eq!(
             socket.dispatch(&mut cx, |_, _| unreachable!()),
-            Err(Error::Exhausted)
+            Ok::<_, Error>(())
         );
 
         assert_eq!(socket.send_slice(b"abcdef", REMOTE_END), Ok(()));
         assert_eq!(
             socket.send_slice(b"123456", REMOTE_END),
-            Err(Error::Exhausted)
+            Err(SendError::BufferFull)
         );
         assert!(!socket.can_send());
 
@@ -577,7 +625,7 @@ mod test {
                 assert_eq!(ip_repr, LOCAL_IP_REPR);
                 assert_eq!(udp_repr, LOCAL_UDP_REPR);
                 assert_eq!(payload, PAYLOAD);
-                Ok(())
+                Ok::<_, Error>(())
             }),
             Ok(())
         );
@@ -592,20 +640,15 @@ mod test {
         assert_eq!(socket.bind(LOCAL_PORT), Ok(()));
 
         assert!(!socket.can_recv());
-        assert_eq!(socket.recv(), Err(Error::Exhausted));
+        assert_eq!(socket.recv(), Err(RecvError::Exhausted));
 
         assert!(socket.accepts(&mut cx, &REMOTE_IP_REPR, &REMOTE_UDP_REPR));
-        assert_eq!(
-            socket.process(&mut cx, &REMOTE_IP_REPR, &REMOTE_UDP_REPR, PAYLOAD),
-            Ok(())
-        );
+        socket.process(&mut cx, &REMOTE_IP_REPR, &REMOTE_UDP_REPR, PAYLOAD);
         assert!(socket.can_recv());
 
         assert!(socket.accepts(&mut cx, &REMOTE_IP_REPR, &REMOTE_UDP_REPR));
-        assert_eq!(
-            socket.process(&mut cx, &REMOTE_IP_REPR, &REMOTE_UDP_REPR, PAYLOAD),
-            Err(Error::Exhausted)
-        );
+        socket.process(&mut cx, &REMOTE_IP_REPR, &REMOTE_UDP_REPR, PAYLOAD);
+
         assert_eq!(socket.recv(), Ok((&b"abcdef"[..], REMOTE_END)));
         assert!(!socket.can_recv());
     }
@@ -617,15 +660,12 @@ mod test {
 
         assert_eq!(socket.bind(LOCAL_PORT), Ok(()));
 
-        assert_eq!(socket.peek(), Err(Error::Exhausted));
+        assert_eq!(socket.peek(), Err(RecvError::Exhausted));
 
-        assert_eq!(
-            socket.process(&mut cx, &REMOTE_IP_REPR, &REMOTE_UDP_REPR, PAYLOAD),
-            Ok(())
-        );
+        socket.process(&mut cx, &REMOTE_IP_REPR, &REMOTE_UDP_REPR, PAYLOAD);
         assert_eq!(socket.peek(), Ok((&b"abcdef"[..], &REMOTE_END)));
         assert_eq!(socket.recv(), Ok((&b"abcdef"[..], REMOTE_END)));
-        assert_eq!(socket.peek(), Err(Error::Exhausted));
+        assert_eq!(socket.peek(), Err(RecvError::Exhausted));
     }
 
     #[test]
@@ -636,10 +676,7 @@ mod test {
         assert_eq!(socket.bind(LOCAL_PORT), Ok(()));
 
         assert!(socket.accepts(&mut cx, &REMOTE_IP_REPR, &REMOTE_UDP_REPR));
-        assert_eq!(
-            socket.process(&mut cx, &REMOTE_IP_REPR, &REMOTE_UDP_REPR, PAYLOAD),
-            Ok(())
-        );
+        socket.process(&mut cx, &REMOTE_IP_REPR, &REMOTE_UDP_REPR, PAYLOAD);
 
         let mut slice = [0; 4];
         assert_eq!(socket.recv_slice(&mut slice[..]), Ok((4, REMOTE_END)));
@@ -653,17 +690,14 @@ mod test {
 
         assert_eq!(socket.bind(LOCAL_PORT), Ok(()));
 
-        assert_eq!(
-            socket.process(&mut cx, &REMOTE_IP_REPR, &REMOTE_UDP_REPR, PAYLOAD),
-            Ok(())
-        );
+        socket.process(&mut cx, &REMOTE_IP_REPR, &REMOTE_UDP_REPR, PAYLOAD);
 
         let mut slice = [0; 4];
         assert_eq!(socket.peek_slice(&mut slice[..]), Ok((4, &REMOTE_END)));
         assert_eq!(&slice, b"abcd");
         assert_eq!(socket.recv_slice(&mut slice[..]), Ok((4, REMOTE_END)));
         assert_eq!(&slice, b"abcd");
-        assert_eq!(socket.peek_slice(&mut slice[..]), Err(Error::Exhausted));
+        assert_eq!(socket.peek_slice(&mut slice[..]), Err(RecvError::Exhausted));
     }
 
     #[test]
@@ -687,7 +721,7 @@ mod test {
                         hop_limit: 0x2a,
                     })
                 );
-                Ok(())
+                Ok::<_, Error>(())
             }),
             Ok(())
         );
@@ -728,14 +762,14 @@ mod test {
         let too_large = b"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdefx";
         assert_eq!(
             socket.send_slice(too_large, REMOTE_END),
-            Err(Error::Truncated)
+            Err(SendError::BufferFull)
         );
         assert_eq!(socket.send_slice(&too_large[..16 * 4], REMOTE_END), Ok(()));
     }
 
     #[test]
     fn test_process_empty_payload() {
-        let recv_buffer = UdpSocketBuffer::new(vec![UdpPacketMetadata::EMPTY; 1], vec![]);
+        let recv_buffer = PacketBuffer::new(vec![PacketMetadata::EMPTY; 1], vec![]);
         let mut socket = socket(recv_buffer, buffer(0));
         let mut cx = Context::mock();
 
@@ -745,13 +779,13 @@ mod test {
             src_port: REMOTE_PORT,
             dst_port: LOCAL_PORT,
         };
-        assert_eq!(socket.process(&mut cx, &REMOTE_IP_REPR, &repr, &[]), Ok(()));
+        socket.process(&mut cx, &REMOTE_IP_REPR, &repr, &[]);
         assert_eq!(socket.recv(), Ok((&[][..], REMOTE_END)));
     }
 
     #[test]
     fn test_closing() {
-        let recv_buffer = UdpSocketBuffer::new(vec![UdpPacketMetadata::EMPTY; 1], vec![]);
+        let recv_buffer = PacketBuffer::new(vec![PacketMetadata::EMPTY; 1], vec![]);
         let mut socket = socket(recv_buffer, buffer(0));
         assert_eq!(socket.bind(LOCAL_PORT), Ok(()));
 

+ 1 - 1
src/storage/assembler.rs

@@ -192,7 +192,7 @@ impl Assembler {
     }
 
     /// Add a new contiguous range to the assembler, and return `Ok(bool)`,
-    /// or return `Err(())` if too many discontiguities are already recorded.
+    /// or return `Err(TooManyHolesError)` if too many discontiguities are already recorded.
     /// Returns `Ok(true)` when there was an overlap.
     pub fn add(&mut self, mut offset: usize, mut size: usize) -> Result<bool, TooManyHolesError> {
         let mut index = 0;

+ 10 - 0
src/storage/mod.rs

@@ -19,3 +19,13 @@ pub use self::ring_buffer::RingBuffer;
 pub trait Resettable {
     fn reset(&mut self);
 }
+
+/// Error returned when enqueuing into a full buffer.
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+#[cfg_attr(feature = "defmt", derive(defmt::Format))]
+pub struct Full;
+
+/// Error returned when dequeuing from an empty buffer.
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+#[cfg_attr(feature = "defmt", derive(defmt::Format))]
+pub struct Empty;

+ 30 - 33
src/storage/packet_buffer.rs

@@ -1,7 +1,8 @@
 use managed::ManagedSlice;
 
-use crate::storage::RingBuffer;
-use crate::{Error, Result};
+use crate::storage::{Full, RingBuffer};
+
+use super::Empty;
 
 /// Size and header of a packet.
 #[derive(Debug, Clone, Copy)]
@@ -74,30 +75,25 @@ impl<'a, H> PacketBuffer<'a, H> {
     // in case of failure.
 
     /// Enqueue a single packet with the given header into the buffer, and
-    /// return a reference to its payload, or return `Err(Error::Exhausted)`
-    /// if the buffer is full, or return `Err(Error::Truncated)` if the buffer
-    /// does not have enough spare payload space.
-    pub fn enqueue(&mut self, size: usize, header: H) -> Result<&mut [u8]> {
-        if self.payload_ring.capacity() < size {
-            return Err(Error::Truncated);
-        }
-
-        if self.metadata_ring.is_full() {
-            return Err(Error::Exhausted);
+    /// return a reference to its payload, or return `Err(Full)`
+    /// if the buffer is full.
+    pub fn enqueue(&mut self, size: usize, header: H) -> Result<&mut [u8], Full> {
+        if self.payload_ring.capacity() < size || self.metadata_ring.is_full() {
+            return Err(Full);
         }
 
         let window = self.payload_ring.window();
         let contig_window = self.payload_ring.contiguous_window();
 
         if window < size {
-            return Err(Error::Exhausted);
+            return Err(Full);
         } else if contig_window < size {
             if window - contig_window < size {
                 // The buffer length is larger than the current contiguous window
                 // and is larger than the contiguous window will be after adding
                 // the padding necessary to circle around to the beginning of the
                 // ring buffer.
-                return Err(Error::Exhausted);
+                return Err(Full);
             } else {
                 // Add padding to the end of the ring buffer so that the
                 // contiguous window is at the beginning of the ring buffer.
@@ -127,16 +123,16 @@ impl<'a, H> PacketBuffer<'a, H> {
                 let _buf_dequeued = payload_ring.dequeue_many(metadata.size);
                 Ok(()) // dequeue metadata
             } else {
-                Err(Error::Exhausted) // don't dequeue metadata
+                Err(()) // don't dequeue metadata
             }
         });
     }
 
     /// Call `f` with a single packet from the buffer, and dequeue the packet if `f`
-    /// returns successfully, or return `Err(Error::Exhausted)` if the buffer is empty.
-    pub fn dequeue_with<'c, R, F>(&'c mut self, f: F) -> Result<R>
+    /// returns successfully, or return `Err(EmptyError)` if the buffer is empty.
+    pub fn dequeue_with<'c, R, E, F>(&'c mut self, f: F) -> Result<Result<R, E>, Empty>
     where
-        F: FnOnce(&mut H, &'c mut [u8]) -> Result<R>,
+        F: FnOnce(&mut H, &'c mut [u8]) -> Result<R, E>,
     {
         self.dequeue_padding();
 
@@ -166,7 +162,7 @@ impl<'a, H> PacketBuffer<'a, H> {
 
     /// Dequeue a single packet from the buffer, and return a reference to its payload
     /// as well as its header, or return `Err(Error::Exhausted)` if the buffer is empty.
-    pub fn dequeue(&mut self) -> Result<(H, &mut [u8])> {
+    pub fn dequeue(&mut self) -> Result<(H, &mut [u8]), Empty> {
         self.dequeue_padding();
 
         let PacketMetadata {
@@ -183,7 +179,7 @@ impl<'a, H> PacketBuffer<'a, H> {
     /// its payload as well as its header, or return `Err(Error:Exhausted)` if the buffer is empty.
     ///
     /// This function otherwise behaves identically to [dequeue](#method.dequeue).
-    pub fn peek(&mut self) -> Result<(&H, &[u8])> {
+    pub fn peek(&mut self) -> Result<(&H, &[u8]), Empty> {
         self.dequeue_padding();
 
         if let Some(metadata) = self.metadata_ring.get_allocated(0, 1).first() {
@@ -192,7 +188,7 @@ impl<'a, H> PacketBuffer<'a, H> {
                 self.payload_ring.get_allocated(0, metadata.size),
             ))
         } else {
-            Err(Error::Exhausted)
+            Err(Empty)
         }
     }
 
@@ -226,21 +222,21 @@ mod test {
     fn test_simple() {
         let mut buffer = buffer();
         buffer.enqueue(6, ()).unwrap().copy_from_slice(b"abcdef");
-        assert_eq!(buffer.enqueue(16, ()), Err(Error::Exhausted));
+        assert_eq!(buffer.enqueue(16, ()), Err(Full));
         assert_eq!(buffer.metadata_ring.len(), 1);
         assert_eq!(buffer.dequeue().unwrap().1, &b"abcdef"[..]);
-        assert_eq!(buffer.dequeue(), Err(Error::Exhausted));
+        assert_eq!(buffer.dequeue(), Err(Empty));
     }
 
     #[test]
     fn test_peek() {
         let mut buffer = buffer();
-        assert_eq!(buffer.peek(), Err(Error::Exhausted));
+        assert_eq!(buffer.peek(), Err(Empty));
         buffer.enqueue(6, ()).unwrap().copy_from_slice(b"abcdef");
         assert_eq!(buffer.metadata_ring.len(), 1);
         assert_eq!(buffer.peek().unwrap().1, &b"abcdef"[..]);
         assert_eq!(buffer.dequeue().unwrap().1, &b"abcdef"[..]);
-        assert_eq!(buffer.peek(), Err(Error::Exhausted));
+        assert_eq!(buffer.peek(), Err(Empty));
     }
 
     #[test]
@@ -278,15 +274,16 @@ mod test {
         assert_eq!(buffer.metadata_ring.len(), 3);
         assert!(buffer.dequeue().is_ok());
 
-        assert!(buffer
-            .dequeue_with(|_, _| Err(Error::Unaddressable) as Result<()>)
-            .is_err());
+        assert!(matches!(
+            buffer.dequeue_with(|_, _| Result::<(), u32>::Err(123)),
+            Ok(Err(_))
+        ));
         assert_eq!(buffer.metadata_ring.len(), 1);
 
         assert!(buffer
             .dequeue_with(|&mut (), payload| {
                 assert_eq!(payload, &b"abcd"[..]);
-                Ok(())
+                Result::<(), ()>::Ok(())
             })
             .is_ok());
         assert_eq!(buffer.metadata_ring.len(), 0);
@@ -307,7 +304,7 @@ mod test {
         assert!(buffer.is_full());
         assert!(!buffer.is_empty());
         assert_eq!(buffer.metadata_ring.len(), 4);
-        assert_eq!(buffer.enqueue(1, ()), Err(Error::Exhausted));
+        assert_eq!(buffer.enqueue(1, ()), Err(Full));
     }
 
     #[test]
@@ -316,7 +313,7 @@ mod test {
         assert!(buffer.enqueue(4, ()).is_ok());
         assert!(buffer.enqueue(8, ()).is_ok());
         assert!(buffer.dequeue().is_ok());
-        assert_eq!(buffer.enqueue(16, ()), Err(Error::Exhausted));
+        assert_eq!(buffer.enqueue(16, ()), Err(Full));
         assert_eq!(buffer.metadata_ring.len(), 1);
     }
 
@@ -326,14 +323,14 @@ mod test {
         assert!(buffer.enqueue(4, ()).is_ok());
         assert!(buffer.enqueue(8, ()).is_ok());
         assert!(buffer.dequeue().is_ok());
-        assert_eq!(buffer.enqueue(8, ()), Err(Error::Exhausted));
+        assert_eq!(buffer.enqueue(8, ()), Err(Full));
         assert_eq!(buffer.metadata_ring.len(), 1);
     }
 
     #[test]
     fn test_capacity_too_small() {
         let mut buffer = buffer();
-        assert_eq!(buffer.enqueue(32, ()), Err(Error::Truncated));
+        assert_eq!(buffer.enqueue(32, ()), Err(Full));
     }
 
     #[test]

+ 44 - 41
src/storage/ring_buffer.rs

@@ -6,7 +6,8 @@ use core::cmp;
 use managed::ManagedSlice;
 
 use crate::storage::Resettable;
-use crate::{Error, Result};
+
+use super::{Empty, Full};
 
 /// A ring buffer.
 ///
@@ -114,60 +115,57 @@ impl<'a, T: 'a> RingBuffer<'a, T> {
 /// and boundary conditions (empty/full) are errors.
 impl<'a, T: 'a> RingBuffer<'a, T> {
     /// Call `f` with a single buffer element, and enqueue the element if `f`
-    /// returns successfully, or return `Err(Error::Exhausted)` if the buffer is full.
-    pub fn enqueue_one_with<'b, R, F>(&'b mut self, f: F) -> Result<R>
+    /// returns successfully, or return `Err(Full)` if the buffer is full.
+    pub fn enqueue_one_with<'b, R, E, F>(&'b mut self, f: F) -> Result<Result<R, E>, Full>
     where
-        F: FnOnce(&'b mut T) -> Result<R>,
+        F: FnOnce(&'b mut T) -> Result<R, E>,
     {
         if self.is_full() {
-            return Err(Error::Exhausted);
+            return Err(Full);
         }
 
         let index = self.get_idx_unchecked(self.length);
-        match f(&mut self.storage[index]) {
-            Ok(result) => {
-                self.length += 1;
-                Ok(result)
-            }
-            Err(error) => Err(error),
+        let res = f(&mut self.storage[index]);
+        if res.is_ok() {
+            self.length += 1;
         }
+        Ok(res)
     }
 
     /// Enqueue a single element into the buffer, and return a reference to it,
-    /// or return `Err(Error::Exhausted)` if the buffer is full.
+    /// or return `Err(Full)` if the buffer is full.
     ///
     /// This function is a shortcut for `ring_buf.enqueue_one_with(Ok)`.
-    pub fn enqueue_one(&mut self) -> Result<&mut T> {
-        self.enqueue_one_with(Ok)
+    pub fn enqueue_one(&mut self) -> Result<&mut T, Full> {
+        self.enqueue_one_with(Ok)?
     }
 
     /// Call `f` with a single buffer element, and dequeue the element if `f`
-    /// returns successfully, or return `Err(Error::Exhausted)` if the buffer is empty.
-    pub fn dequeue_one_with<'b, R, F>(&'b mut self, f: F) -> Result<R>
+    /// returns successfully, or return `Err(Empty)` if the buffer is empty.
+    pub fn dequeue_one_with<'b, R, E, F>(&'b mut self, f: F) -> Result<Result<R, E>, Empty>
     where
-        F: FnOnce(&'b mut T) -> Result<R>,
+        F: FnOnce(&'b mut T) -> Result<R, E>,
     {
         if self.is_empty() {
-            return Err(Error::Exhausted);
+            return Err(Empty);
         }
 
         let next_at = self.get_idx_unchecked(1);
-        match f(&mut self.storage[self.read_at]) {
-            Ok(result) => {
-                self.length -= 1;
-                self.read_at = next_at;
-                Ok(result)
-            }
-            Err(error) => Err(error),
+        let res = f(&mut self.storage[self.read_at]);
+
+        if res.is_ok() {
+            self.length -= 1;
+            self.read_at = next_at;
         }
+        Ok(res)
     }
 
     /// Dequeue an element from the buffer, and return a reference to it,
-    /// or return `Err(Error::Exhausted)` if the buffer is empty.
+    /// or return `Err(Empty)` if the buffer is empty.
     ///
     /// This function is a shortcut for `ring_buf.dequeue_one_with(Ok)`.
-    pub fn dequeue_one(&mut self) -> Result<&mut T> {
-        self.dequeue_one_with(Ok)
+    pub fn dequeue_one(&mut self) -> Result<&mut T, Empty> {
+        self.dequeue_one_with(Ok)?
     }
 }
 
@@ -441,31 +439,36 @@ mod test {
     fn test_buffer_enqueue_dequeue_one_with() {
         let mut ring = RingBuffer::new(vec![0; 5]);
         assert_eq!(
-            ring.dequeue_one_with(|_| unreachable!()) as Result<()>,
-            Err(Error::Exhausted)
+            ring.dequeue_one_with(|_| -> Result::<(), ()> { unreachable!() }),
+            Err(Empty)
         );
 
-        ring.enqueue_one_with(Ok).unwrap();
+        ring.enqueue_one_with(Ok::<_, ()>).unwrap().unwrap();
         assert!(!ring.is_empty());
         assert!(!ring.is_full());
 
         for i in 1..5 {
-            ring.enqueue_one_with(|e| Ok(*e = i)).unwrap();
+            ring.enqueue_one_with(|e| Ok::<_, ()>(*e = i))
+                .unwrap()
+                .unwrap();
             assert!(!ring.is_empty());
         }
         assert!(ring.is_full());
         assert_eq!(
-            ring.enqueue_one_with(|_| unreachable!()) as Result<()>,
-            Err(Error::Exhausted)
+            ring.enqueue_one_with(|_| -> Result::<(), ()> { unreachable!() }),
+            Err(Full)
         );
 
         for i in 0..5 {
-            assert_eq!(ring.dequeue_one_with(|e| Ok(*e)).unwrap(), i);
+            assert_eq!(
+                ring.dequeue_one_with(|e| Ok::<_, ()>(*e)).unwrap().unwrap(),
+                i
+            );
             assert!(!ring.is_full());
         }
         assert_eq!(
-            ring.dequeue_one_with(|_| unreachable!()) as Result<()>,
-            Err(Error::Exhausted)
+            ring.dequeue_one_with(|_| -> Result::<(), ()> { unreachable!() }),
+            Err(Empty)
         );
         assert!(ring.is_empty());
     }
@@ -473,7 +476,7 @@ mod test {
     #[test]
     fn test_buffer_enqueue_dequeue_one() {
         let mut ring = RingBuffer::new(vec![0; 5]);
-        assert_eq!(ring.dequeue_one(), Err(Error::Exhausted));
+        assert_eq!(ring.dequeue_one(), Err(Empty));
 
         ring.enqueue_one().unwrap();
         assert!(!ring.is_empty());
@@ -484,13 +487,13 @@ mod test {
             assert!(!ring.is_empty());
         }
         assert!(ring.is_full());
-        assert_eq!(ring.enqueue_one(), Err(Error::Exhausted));
+        assert_eq!(ring.enqueue_one(), Err(Full));
 
         for i in 0..5 {
             assert_eq!(*ring.dequeue_one().unwrap(), i);
             assert!(!ring.is_full());
         }
-        assert_eq!(ring.dequeue_one(), Err(Error::Exhausted));
+        assert_eq!(ring.dequeue_one(), Err(Empty));
         assert!(ring.is_empty());
     }
 
@@ -777,7 +780,7 @@ mod test {
         assert_eq!(no_capacity.get_allocated(0, 0), &[]);
         no_capacity.dequeue_allocated(0);
         assert_eq!(no_capacity.enqueue_many(0), &[]);
-        assert_eq!(no_capacity.enqueue_one(), Err(Error::Exhausted));
+        assert_eq!(no_capacity.enqueue_one(), Err(Full));
         assert_eq!(no_capacity.contiguous_window(), 0);
     }
 

+ 6 - 6
src/wire/arp.rs

@@ -1,7 +1,7 @@
 use byteorder::{ByteOrder, NetworkEndian};
 use core::fmt;
 
-use crate::{Error, Result};
+use super::{Error, Result};
 
 pub use super::EthernetProtocol as Protocol;
 
@@ -80,7 +80,7 @@ impl<T: AsRef<[u8]>> Packet<T> {
     }
 
     /// Ensure that no accessor method will panic if called.
-    /// Returns `Err(Error::Truncated)` if the buffer is too short.
+    /// Returns `Err(Error)` if the buffer is too short.
     ///
     /// The result of this check is invalidated by calling [set_hardware_len] or
     /// [set_protocol_len].
@@ -91,9 +91,9 @@ impl<T: AsRef<[u8]>> Packet<T> {
     pub fn check_len(&self) -> Result<()> {
         let len = self.buffer.as_ref().len();
         if len < field::OPER.end {
-            Err(Error::Truncated)
+            Err(Error)
         } else if len < field::TPA(self.hardware_len(), self.protocol_len()).end {
-            Err(Error::Truncated)
+            Err(Error)
         } else {
             Ok(())
         }
@@ -269,7 +269,7 @@ pub enum Repr {
 
 impl Repr {
     /// Parse an Address Resolution Protocol packet and return a high-level representation,
-    /// or return `Err(Error::Unrecognized)` if the packet is not recognized.
+    /// or return `Err(Error)` if the packet is not recognized.
     pub fn parse<T: AsRef<[u8]>>(packet: &Packet<T>) -> Result<Repr> {
         match (
             packet.hardware_type(),
@@ -284,7 +284,7 @@ impl Repr {
                 target_hardware_addr: EthernetAddress::from_bytes(packet.target_hardware_addr()),
                 target_protocol_addr: Ipv4Address::from_bytes(packet.target_protocol_addr()),
             }),
-            _ => Err(Error::Unrecognized),
+            _ => Err(Error),
         }
     }
 

+ 14 - 14
src/wire/dhcpv4.rs

@@ -3,9 +3,9 @@
 use bitflags::bitflags;
 use byteorder::{ByteOrder, NetworkEndian};
 
+use super::{Error, Result};
 use crate::wire::arp::Hardware;
 use crate::wire::{EthernetAddress, Ipv4Address};
-use crate::{Error, Result};
 
 pub const SERVER_PORT: u16 = 67;
 pub const CLIENT_PORT: u16 = 68;
@@ -77,7 +77,7 @@ impl<'a> DhcpOption<'a> {
         // See https://tools.ietf.org/html/rfc2132 for all possible DHCP options.
 
         let (skip_len, option);
-        match *buffer.get(0).ok_or(Error::Truncated)? {
+        match *buffer.get(0).ok_or(Error)? {
             field::OPT_END => {
                 skip_len = 1;
                 option = DhcpOption::EndOfList;
@@ -87,9 +87,9 @@ impl<'a> DhcpOption<'a> {
                 option = DhcpOption::Pad;
             }
             kind => {
-                let length = *buffer.get(1).ok_or(Error::Truncated)? as usize;
+                let length = *buffer.get(1).ok_or(Error)? as usize;
                 skip_len = length + 2;
-                let data = buffer.get(2..skip_len).ok_or(Error::Truncated)?;
+                let data = buffer.get(2..skip_len).ok_or(Error)?;
                 match (kind, length) {
                     (field::OPT_END, _) | (field::OPT_PAD, _) => unreachable!(),
                     (field::OPT_DHCP_MESSAGE_TYPE, 1) => {
@@ -101,7 +101,7 @@ impl<'a> DhcpOption<'a> {
                     (field::OPT_CLIENT_ID, 7) => {
                         let hardware_type = Hardware::from(u16::from(data[0]));
                         if hardware_type != Hardware::Ethernet {
-                            return Err(Error::Unrecognized);
+                            return Err(Error);
                         }
                         option =
                             DhcpOption::ClientIdentifier(EthernetAddress::from_bytes(&data[1..]));
@@ -354,13 +354,13 @@ impl<T: AsRef<[u8]>> Packet<T> {
     }
 
     /// Ensure that no accessor method will panic if called.
-    /// Returns `Err(Error::Truncated)` if the buffer is too short.
+    /// Returns `Err(Error)` if the buffer is too short.
     ///
     /// [set_header_len]: #method.set_header_len
     pub fn check_len(&self) -> Result<()> {
         let len = self.buffer.as_ref().len();
         if len < field::MAGIC_NUMBER.end {
-            Err(Error::Truncated)
+            Err(Error)
         } else {
             Ok(())
         }
@@ -470,7 +470,7 @@ impl<'a, T: AsRef<[u8]> + ?Sized> Packet<&'a T> {
     #[inline]
     pub fn options(&self) -> Result<&'a [u8]> {
         let data = self.buffer.as_ref();
-        data.get(field::OPTIONS).ok_or(Error::Malformed)
+        data.get(field::OPTIONS).ok_or(Error)
     }
 }
 
@@ -593,7 +593,7 @@ impl<'a, T: AsRef<[u8]> + AsMut<[u8]> + ?Sized> Packet<&'a mut T> {
     #[inline]
     pub fn options_mut(&mut self) -> Result<&mut [u8]> {
         let data = self.buffer.as_mut();
-        data.get_mut(field::OPTIONS).ok_or(Error::Truncated)
+        data.get_mut(field::OPTIONS).ok_or(Error)
     }
 }
 
@@ -760,17 +760,17 @@ impl<'a> Repr<'a> {
         match packet.hardware_type() {
             Hardware::Ethernet => {
                 if packet.hardware_len() != 6 {
-                    return Err(Error::Malformed);
+                    return Err(Error);
                 }
             }
-            Hardware::Unknown(_) => return Err(Error::Unrecognized), // unimplemented
+            Hardware::Unknown(_) => return Err(Error), // unimplemented
         }
 
         if packet.magic_number() != DHCP_MAGIC_NUMBER {
-            return Err(Error::Malformed);
+            return Err(Error);
         }
 
-        let mut message_type = Err(Error::Malformed);
+        let mut message_type = Err(Error);
         let mut requested_ip = None;
         let mut client_identifier = None;
         let mut server_identifier = None;
@@ -827,7 +827,7 @@ impl<'a> Repr<'a> {
                     let chunk_size = 4;
                     for (server, chunk) in servers.iter_mut().zip(data.chunks(chunk_size)) {
                         if chunk.len() != chunk_size {
-                            return Err(Error::Malformed);
+                            return Err(Error);
                         }
                         *server = Some(Ipv4Address::from_bytes(chunk));
                     }

+ 19 - 19
src/wire/dns.rs

@@ -5,11 +5,11 @@ use byteorder::{ByteOrder, NetworkEndian};
 use core::iter;
 use core::iter::Iterator;
 
+use super::{Error, Result};
 #[cfg(feature = "proto-ipv4")]
 use crate::wire::Ipv4Address;
 #[cfg(feature = "proto-ipv6")]
 use crate::wire::Ipv6Address;
-use crate::{Error, Result};
 
 enum_with_unknown! {
     /// DNS OpCodes
@@ -98,12 +98,12 @@ impl<T: AsRef<[u8]>> Packet<T> {
     }
 
     /// Ensure that no accessor method will panic if called.
-    /// Returns `Err(Error::Malformed)` if the buffer is smaller than
+    /// Returns `Err(Error)` if the buffer is smaller than
     /// the header length.
     pub fn check_len(&self) -> Result<()> {
         let len = self.buffer.as_ref().len();
         if len < field::HEADER_END {
-            Err(Error::Malformed)
+            Err(Error)
         } else {
             Ok(())
         }
@@ -166,14 +166,14 @@ impl<T: AsRef<[u8]>> Packet<T> {
 
         iter::from_fn(move || loop {
             if bytes.is_empty() {
-                return Some(Err(Error::Malformed));
+                return Some(Err(Error));
             }
             match bytes[0] {
                 0x00 => return None,
                 x if x & 0xC0 == 0x00 => {
                     let len = (x & 0x3F) as usize;
                     if bytes.len() < 1 + len {
-                        return Some(Err(Error::Malformed));
+                        return Some(Err(Error));
                     }
                     let label = &bytes[1..1 + len];
                     bytes = &bytes[1 + len..];
@@ -181,12 +181,12 @@ impl<T: AsRef<[u8]>> Packet<T> {
                 }
                 x if x & 0xC0 == 0xC0 => {
                     if bytes.len() < 2 {
-                        return Some(Err(Error::Malformed));
+                        return Some(Err(Error));
                     }
                     let y = bytes[1];
                     let ptr = ((x & 0x3F) as usize) << 8 | (y as usize);
                     if packet.len() <= ptr {
-                        return Some(Err(Error::Malformed));
+                        return Some(Err(Error));
                     }
 
                     // RFC1035 says: "In this scheme, an entire domain name or a list of labels at
@@ -204,7 +204,7 @@ impl<T: AsRef<[u8]>> Packet<T> {
                     bytes = &packet[ptr..];
                     packet = &packet[..ptr];
                 }
-                _ => return Some(Err(Error::Malformed)),
+                _ => return Some(Err(Error)),
             }
         })
     }
@@ -262,24 +262,24 @@ fn parse_name_part<'a>(
     mut f: impl FnMut(&'a [u8]),
 ) -> Result<(&'a [u8], Option<usize>)> {
     loop {
-        let x = *bytes.get(0).ok_or(Error::Malformed)?;
+        let x = *bytes.get(0).ok_or(Error)?;
         bytes = &bytes[1..];
         match x {
             0x00 => return Ok((bytes, None)),
             x if x & 0xC0 == 0x00 => {
                 let len = (x & 0x3F) as usize;
-                let label = bytes.get(..len).ok_or(Error::Malformed)?;
+                let label = bytes.get(..len).ok_or(Error)?;
                 bytes = &bytes[len..];
                 f(label);
             }
             x if x & 0xC0 == 0xC0 => {
-                let y = *bytes.get(0).ok_or(Error::Malformed)?;
+                let y = *bytes.get(0).ok_or(Error)?;
                 bytes = &bytes[1..];
 
                 let ptr = ((x & 0x3F) as usize) << 8 | (y as usize);
                 return Ok((bytes, Some(ptr)));
             }
-            _ => return Err(Error::Malformed),
+            _ => return Err(Error),
         }
     }
 }
@@ -297,14 +297,14 @@ impl<'a> Question<'a> {
         let name = &buffer[..buffer.len() - rest.len()];
 
         if rest.len() < 4 {
-            return Err(Error::Malformed);
+            return Err(Error);
         }
         let type_ = NetworkEndian::read_u16(&rest[0..2]).into();
         let class = NetworkEndian::read_u16(&rest[2..4]);
         let rest = &rest[4..];
 
         if class != CLASS_IN {
-            return Err(Error::Malformed);
+            return Err(Error);
         }
 
         Ok((rest, Question { name, type_ }))
@@ -338,14 +338,14 @@ impl<'a> RecordData<'a> {
             #[cfg(feature = "proto-ipv4")]
             Type::A => {
                 if data.len() != 4 {
-                    return Err(Error::Malformed);
+                    return Err(Error);
                 }
                 Ok(RecordData::A(Ipv4Address::from_bytes(data)))
             }
             #[cfg(feature = "proto-ipv6")]
             Type::Aaaa => {
                 if data.len() != 16 {
-                    return Err(Error::Malformed);
+                    return Err(Error);
                 }
                 Ok(RecordData::Aaaa(Ipv6Address::from_bytes(data)))
             }
@@ -372,7 +372,7 @@ impl<'a> Record<'a> {
         let name = &buffer[..buffer.len() - rest.len()];
 
         if rest.len() < 10 {
-            return Err(Error::Malformed);
+            return Err(Error);
         }
         let type_ = NetworkEndian::read_u16(&rest[0..2]).into();
         let class = NetworkEndian::read_u16(&rest[2..4]);
@@ -381,10 +381,10 @@ impl<'a> Record<'a> {
         let rest = &rest[10..];
 
         if class != CLASS_IN {
-            return Err(Error::Malformed);
+            return Err(Error);
         }
 
-        let data = rest.get(..len).ok_or(Error::Malformed)?;
+        let data = rest.get(..len).ok_or(Error)?;
         let rest = &rest[len..];
 
         Ok((

+ 3 - 3
src/wire/ethernet.rs

@@ -1,7 +1,7 @@
 use byteorder::{ByteOrder, NetworkEndian};
 use core::fmt;
 
-use crate::{Error, Result};
+use super::{Error, Result};
 
 enum_with_unknown! {
     /// Ethernet protocol type.
@@ -115,11 +115,11 @@ impl<T: AsRef<[u8]>> Frame<T> {
     }
 
     /// Ensure that no accessor method will panic if called.
-    /// Returns `Err(Error::Truncated)` if the buffer is too short.
+    /// Returns `Err(Error)` if the buffer is too short.
     pub fn check_len(&self) -> Result<()> {
         let len = self.buffer.as_ref().len();
         if len < HEADER_LEN {
-            Err(Error::Truncated)
+            Err(Error)
         } else {
             Ok(())
         }

+ 8 - 8
src/wire/icmpv4.rs

@@ -1,10 +1,10 @@
 use byteorder::{ByteOrder, NetworkEndian};
 use core::{cmp, fmt};
 
+use super::{Error, Result};
 use crate::phy::ChecksumCapabilities;
 use crate::wire::ip::checksum;
 use crate::wire::{Ipv4Packet, Ipv4Repr};
-use crate::{Error, Result};
 
 enum_with_unknown! {
     /// Internet protocol control message type.
@@ -189,7 +189,7 @@ impl<T: AsRef<[u8]>> Packet<T> {
     }
 
     /// Ensure that no accessor method will panic if called.
-    /// Returns `Err(Error::Truncated)` if the buffer is too short.
+    /// Returns `Err(Error)` if the buffer is too short.
     ///
     /// The result of this check is invalidated by calling [set_header_len].
     ///
@@ -197,7 +197,7 @@ impl<T: AsRef<[u8]>> Packet<T> {
     pub fn check_len(&self) -> Result<()> {
         let len = self.buffer.as_ref().len();
         if len < field::HEADER_END {
-            Err(Error::Truncated)
+            Err(Error)
         } else {
             Ok(())
         }
@@ -386,7 +386,7 @@ impl<'a> Repr<'a> {
     {
         // Valid checksum is expected.
         if checksum_caps.icmpv4.rx() && !packet.verify_checksum() {
-            return Err(Error::Checksum);
+            return Err(Error);
         }
 
         match (packet.msg_type(), packet.msg_code()) {
@@ -409,7 +409,7 @@ impl<'a> Repr<'a> {
                 // RFC 792 requires exactly eight bytes to be returned.
                 // We allow more, since there isn't a reason not to, but require at least eight.
                 if payload.len() < 8 {
-                    return Err(Error::Truncated);
+                    return Err(Error);
                 }
 
                 Ok(Repr::DstUnreachable {
@@ -424,7 +424,7 @@ impl<'a> Repr<'a> {
                     data: payload,
                 })
             }
-            _ => Err(Error::Unrecognized),
+            _ => Err(Error),
         }
     }
 
@@ -635,8 +635,8 @@ mod test {
     #[test]
     fn test_check_len() {
         let bytes = [0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
-        assert_eq!(Packet::new_checked(&[]), Err(Error::Truncated));
-        assert_eq!(Packet::new_checked(&bytes[..4]), Err(Error::Truncated));
+        assert_eq!(Packet::new_checked(&[]), Err(Error));
+        assert_eq!(Packet::new_checked(&bytes[..4]), Err(Error));
         assert!(Packet::new_checked(&bytes[..]).is_ok());
     }
 }

+ 6 - 6
src/wire/icmpv6.rs

@@ -1,13 +1,13 @@
 use byteorder::{ByteOrder, NetworkEndian};
 use core::{cmp, fmt};
 
+use super::{Error, Result};
 use crate::phy::ChecksumCapabilities;
 use crate::wire::ip::checksum;
 use crate::wire::MldRepr;
 #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
 use crate::wire::NdiscRepr;
 use crate::wire::{IpAddress, IpProtocol, Ipv6Packet, Ipv6Repr};
-use crate::{Error, Result};
 
 enum_with_unknown! {
     /// Internet protocol control message type.
@@ -262,11 +262,11 @@ impl<T: AsRef<[u8]>> Packet<T> {
     }
 
     /// Ensure that no accessor method will panic if called.
-    /// Returns `Err(Error::Truncated)` if the buffer is too short.
+    /// Returns `Err(Error)` if the buffer is too short.
     pub fn check_len(&self) -> Result<()> {
         let len = self.buffer.as_ref().len();
         if len < field::HEADER_END || len < self.header_len() {
-            Err(Error::Truncated)
+            Err(Error)
         } else {
             Ok(())
         }
@@ -557,7 +557,7 @@ impl<'a> Repr<'a> {
 
             let payload = &packet.payload()[ip_packet.header_len() as usize..];
             if payload.len() < 8 {
-                return Err(Error::Truncated);
+                return Err(Error);
             }
             let repr = Ipv6Repr {
                 src_addr: ip_packet.src_addr(),
@@ -570,7 +570,7 @@ impl<'a> Repr<'a> {
         }
         // Valid checksum is expected.
         if checksum_caps.icmpv6.rx() && !packet.verify_checksum(src_addr, dst_addr) {
-            return Err(Error::Checksum);
+            return Err(Error);
         }
 
         match (packet.msg_type(), packet.msg_code()) {
@@ -620,7 +620,7 @@ impl<'a> Repr<'a> {
             #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
             (msg_type, 0) if msg_type.is_ndisc() => NdiscRepr::parse(packet).map(Repr::Ndisc),
             (msg_type, 0) if msg_type.is_mld() => MldRepr::parse(packet).map(Repr::Mld),
-            _ => Err(Error::Unrecognized),
+            _ => Err(Error),
         }
     }
 

+ 6 - 7
src/wire/ieee802154.rs

@@ -2,9 +2,8 @@ use core::fmt;
 
 use byteorder::{ByteOrder, LittleEndian};
 
+use super::{Error, Result};
 use crate::wire::ipv6::Address as Ipv6Address;
-use crate::Error;
-use crate::Result;
 
 enum_with_unknown! {
     /// IEEE 802.15.4 frame type.
@@ -238,22 +237,22 @@ impl<T: AsRef<[u8]>> Frame<T> {
         packet.check_len()?;
 
         if matches!(packet.dst_addressing_mode(), AddressingMode::Unknown(_)) {
-            return Err(Error::Malformed);
+            return Err(Error);
         }
 
         if matches!(packet.src_addressing_mode(), AddressingMode::Unknown(_)) {
-            return Err(Error::Malformed);
+            return Err(Error);
         }
 
         Ok(packet)
     }
 
     /// Ensure that no accessor method will panic if called.
-    /// Returns `Err(Error::Truncated)` if the buffer is too short.
+    /// Returns `Err(Error)` if the buffer is too short.
     pub fn check_len(&self) -> Result<()> {
         // We need at least 3 bytes
         if self.buffer.as_ref().len() < 3 {
-            return Err(Error::Truncated);
+            return Err(Error);
         }
 
         let mut offset = field::ADDRESSING.start + 2;
@@ -267,7 +266,7 @@ impl<T: AsRef<[u8]>> Frame<T> {
         }
 
         if offset > self.buffer.as_ref().len() {
-            return Err(Error::Truncated);
+            return Err(Error);
         }
 
         Ok(())

+ 5 - 5
src/wire/igmp.rs

@@ -1,9 +1,9 @@
 use byteorder::{ByteOrder, NetworkEndian};
 use core::fmt;
 
+use super::{Error, Result};
 use crate::time::Duration;
 use crate::wire::ip::checksum;
-use crate::{Error, Result};
 
 use crate::wire::Ipv4Address;
 
@@ -69,11 +69,11 @@ impl<T: AsRef<[u8]>> Packet<T> {
     }
 
     /// Ensure that no accessor method will panic if called.
-    /// Returns `Err(Error::Truncated)` if the buffer is too short.
+    /// Returns `Err(Error)` if the buffer is too short.
     pub fn check_len(&self) -> Result<()> {
         let len = self.buffer.as_ref().len();
         if len < field::GROUP_ADDRESS.end as usize {
-            Err(Error::Truncated)
+            Err(Error)
         } else {
             Ok(())
         }
@@ -208,7 +208,7 @@ impl Repr {
         // Check if the address is 0.0.0.0 or multicast
         let addr = packet.group_addr();
         if !addr.is_unspecified() && !addr.is_multicast() {
-            return Err(Error::Malformed);
+            return Err(Error);
         }
 
         // construct a packet based on the Type field
@@ -241,7 +241,7 @@ impl Repr {
                     version: IgmpVersion::Version1,
                 })
             }
-            _ => Err(Error::Unrecognized),
+            _ => Err(Error),
         }
     }
 

+ 3 - 3
src/wire/ip.rs

@@ -1,12 +1,12 @@
 use core::convert::From;
 use core::fmt;
 
+use super::{Error, Result};
 use crate::phy::ChecksumCapabilities;
 #[cfg(feature = "proto-ipv4")]
 use crate::wire::{Ipv4Address, Ipv4Cidr, Ipv4Packet, Ipv4Repr};
 #[cfg(feature = "proto-ipv6")]
 use crate::wire::{Ipv6Address, Ipv6Cidr, Ipv6Packet, Ipv6Repr};
-use crate::{Error, Result};
 
 /// Internet protocol version.
 #[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
@@ -22,14 +22,14 @@ impl Version {
     /// Return the version of an IP packet stored in the provided buffer.
     ///
     /// This function never returns `Ok(IpVersion::Unspecified)`; instead,
-    /// unknown versions result in `Err(Error::Unrecognized)`.
+    /// unknown versions result in `Err(Error)`.
     pub fn of_packet(data: &[u8]) -> Result<Version> {
         match data[0] >> 4 {
             #[cfg(feature = "proto-ipv4")]
             4 => Ok(Version::Ipv4),
             #[cfg(feature = "proto-ipv6")]
             6 => Ok(Version::Ipv6),
-            _ => Err(Error::Unrecognized),
+            _ => Err(Error),
         }
     }
 }

+ 15 - 15
src/wire/ipv4.rs

@@ -1,9 +1,9 @@
 use byteorder::{ByteOrder, NetworkEndian};
 use core::fmt;
 
+use super::{Error, Result};
 use crate::phy::ChecksumCapabilities;
 use crate::wire::ip::{checksum, pretty_print_ip_payload};
-use crate::{Error, Result};
 
 pub use super::IpProtocol as Protocol;
 
@@ -164,7 +164,7 @@ impl Cidr {
                 prefix_len: netmask.count_ones() as u8,
             })
         } else {
-            Err(Error::Illegal)
+            Err(Error)
         }
     }
 
@@ -305,8 +305,8 @@ impl<T: AsRef<[u8]>> Packet<T> {
     }
 
     /// Ensure that no accessor method will panic if called.
-    /// Returns `Err(Error::Truncated)` if the buffer is too short.
-    /// Returns `Err(Error::Malformed)` if the header length is greater
+    /// Returns `Err(Error)` if the buffer is too short.
+    /// Returns `Err(Error)` if the header length is greater
     /// than total length.
     ///
     /// The result of this check is invalidated by calling [set_header_len]
@@ -318,13 +318,13 @@ impl<T: AsRef<[u8]>> Packet<T> {
     pub fn check_len(&self) -> Result<()> {
         let len = self.buffer.as_ref().len();
         if len < field::DST_ADDR.end {
-            Err(Error::Truncated)
+            Err(Error)
         } else if len < self.header_len() as usize {
-            Err(Error::Truncated)
+            Err(Error)
         } else if self.header_len() as u16 > self.total_len() {
-            Err(Error::Malformed)
+            Err(Error)
         } else if len < self.total_len() as usize {
-            Err(Error::Truncated)
+            Err(Error)
         } else {
             Ok(())
         }
@@ -611,20 +611,20 @@ impl Repr {
     ) -> Result<Repr> {
         // Version 4 is expected.
         if packet.version() != 4 {
-            return Err(Error::Malformed);
+            return Err(Error);
         }
         // Valid checksum is expected.
         if checksum_caps.ipv4.rx() && !packet.verify_checksum() {
-            return Err(Error::Checksum);
+            return Err(Error);
         }
         // We do not support fragmentation.
         if packet.more_frags() || packet.frag_offset() != 0 {
-            return Err(Error::Fragmented);
+            return Err(Error);
         }
         // Since the packet is not fragmented, it must include the entire payload.
         let payload_len = packet.total_len() as usize - packet.header_len() as usize;
         if packet.payload().len() < payload_len {
-            return Err(Error::Truncated);
+            return Err(Error);
         }
 
         // All DSCP values are acceptable, since they are of no concern to receiving endpoint.
@@ -837,7 +837,7 @@ mod test {
         bytes.extend(&PACKET_BYTES[..]);
         Packet::new_unchecked(&mut bytes).set_total_len(128);
 
-        assert_eq!(Packet::new_checked(&bytes).unwrap_err(), Error::Truncated);
+        assert_eq!(Packet::new_checked(&bytes).unwrap_err(), Error);
     }
 
     static REPR_PACKET_BYTES: [u8; 24] = [
@@ -874,7 +874,7 @@ mod test {
         let packet = Packet::new_unchecked(&*packet.into_inner());
         assert_eq!(
             Repr::parse(&packet, &ChecksumCapabilities::default()),
-            Err(Error::Malformed)
+            Err(Error)
         );
     }
 
@@ -882,7 +882,7 @@ mod test {
     fn test_parse_total_len_less_than_header_len() {
         let mut bytes = vec![0; 40];
         bytes[0] = 0x09;
-        assert_eq!(Packet::new_checked(&mut bytes), Err(Error::Malformed));
+        assert_eq!(Packet::new_checked(&mut bytes), Err(Error));
     }
 
     #[test]

+ 9 - 9
src/wire/ipv6.rs

@@ -3,10 +3,10 @@
 use byteorder::{ByteOrder, NetworkEndian};
 use core::fmt;
 
+use super::{Error, Result};
 use crate::wire::ip::pretty_print_ip_payload;
 #[cfg(feature = "proto-ipv4")]
 use crate::wire::ipv4;
-use crate::{Error, Result};
 
 pub use super::IpProtocol as Protocol;
 
@@ -422,7 +422,7 @@ impl<T: AsRef<[u8]>> Packet<T> {
     }
 
     /// Ensure that no accessor method will panic if called.
-    /// Returns `Err(Error::Truncated)` if the buffer is too short.
+    /// Returns `Err(Error)` if the buffer is too short.
     ///
     /// The result of this check is invalidated by calling [set_payload_len].
     ///
@@ -431,7 +431,7 @@ impl<T: AsRef<[u8]>> Packet<T> {
     pub fn check_len(&self) -> Result<()> {
         let len = self.buffer.as_ref().len();
         if len < field::DST_ADDR.end || len < self.total_len() {
-            Err(Error::Truncated)
+            Err(Error)
         } else {
             Ok(())
         }
@@ -639,7 +639,7 @@ impl Repr {
         // Ensure basic accessors will work
         packet.check_len()?;
         if packet.version() != 6 {
-            return Err(Error::Malformed);
+            return Err(Error);
         }
         Ok(Repr {
             src_addr: packet.src_addr(),
@@ -708,10 +708,10 @@ impl<T: AsRef<[u8]>> PrettyPrint for Packet<T> {
 
 #[cfg(test)]
 mod test {
+    use super::Error;
     use super::{Address, Cidr};
     use super::{Packet, Protocol, Repr};
     use crate::wire::pretty_print::PrettyPrinter;
-    use crate::Error;
 
     #[cfg(feature = "proto-ipv4")]
     use crate::wire::ipv4::Address as Ipv4Address;
@@ -1128,7 +1128,7 @@ mod test {
         bytes.extend(&REPR_PACKET_BYTES[..]);
         Packet::new_unchecked(&mut bytes).set_payload_len(0x80);
 
-        assert_eq!(Packet::new_checked(&bytes).unwrap_err(), Error::Truncated);
+        assert_eq!(Packet::new_checked(&bytes).unwrap_err(), Error);
     }
 
     #[test]
@@ -1145,7 +1145,7 @@ mod test {
         packet.set_version(4);
         packet.set_payload_len(0);
         let packet = Packet::new_unchecked(&*packet.into_inner());
-        assert_eq!(Repr::parse(&packet), Err(Error::Malformed));
+        assert_eq!(Repr::parse(&packet), Err(Error));
     }
 
     #[test]
@@ -1155,7 +1155,7 @@ mod test {
         packet.set_version(6);
         packet.set_payload_len(39);
         let packet = Packet::new_unchecked(&*packet.into_inner());
-        assert_eq!(Repr::parse(&packet), Err(Error::Truncated));
+        assert_eq!(Repr::parse(&packet), Err(Error));
     }
 
     #[test]
@@ -1165,7 +1165,7 @@ mod test {
         packet.set_version(6);
         packet.set_payload_len(1);
         let packet = Packet::new_unchecked(&*packet.into_inner());
-        assert_eq!(Repr::parse(&packet), Err(Error::Truncated));
+        assert_eq!(Repr::parse(&packet), Err(Error));
     }
 
     #[test]

+ 4 - 4
src/wire/ipv6fragment.rs

@@ -1,4 +1,4 @@
-use crate::{Error, Result};
+use super::{Error, Result};
 use core::fmt;
 
 use byteorder::{ByteOrder, NetworkEndian};
@@ -51,13 +51,13 @@ impl<T: AsRef<[u8]>> Header<T> {
     }
 
     /// Ensure that no accessor method will panic if called.
-    /// Returns `Err(Error::Truncated)` if the buffer is too short.
+    /// Returns `Err(Error)` if the buffer is too short.
     pub fn check_len(&self) -> Result<()> {
         let data = self.buffer.as_ref();
         let len = data.len();
 
         if len < field::IDENT.end {
-            Err(Error::Truncated)
+            Err(Error)
         } else {
             Ok(())
         }
@@ -226,7 +226,7 @@ mod test {
     fn test_check_len() {
         // less than 8 bytes
         assert_eq!(
-            Err(Error::Truncated),
+            Err(Error),
             Header::new_unchecked(&BYTES_HEADER_MORE_FRAG[..7]).check_len()
         );
         // valid

+ 10 - 13
src/wire/ipv6hopbyhop.rs

@@ -1,4 +1,4 @@
-use crate::{Error, Result};
+use super::{Error, Result};
 use core::fmt;
 
 pub use super::IpProtocol as Protocol;
@@ -65,7 +65,7 @@ impl<T: AsRef<[u8]>> Header<T> {
     }
 
     /// Ensure that no accessor method will panic if called.
-    /// Returns `Err(Error::Truncated)` if the buffer is too short.
+    /// Returns `Err(Error)` if the buffer is too short.
     ///
     /// The result of this check is invalidated by calling [set_header_len].
     ///
@@ -75,13 +75,13 @@ impl<T: AsRef<[u8]>> Header<T> {
         let len = data.len();
 
         if len < field::MIN_HEADER_SIZE {
-            return Err(Error::Truncated);
+            return Err(Error);
         }
 
         let of = field::OPTIONS(data[field::LENGTH]);
 
         if len < of.end {
-            return Err(Error::Truncated);
+            return Err(Error);
         }
 
         Ok(())
@@ -226,17 +226,17 @@ mod test {
     fn test_check_len() {
         // zero byte buffer
         assert_eq!(
-            Err(Error::Truncated),
+            Err(Error),
             Header::new_unchecked(&REPR_PACKET_PAD4[..0]).check_len()
         );
         // no length field
         assert_eq!(
-            Err(Error::Truncated),
+            Err(Error),
             Header::new_unchecked(&REPR_PACKET_PAD4[..1]).check_len()
         );
         // less than 8 bytes
         assert_eq!(
-            Err(Error::Truncated),
+            Err(Error),
             Header::new_unchecked(&REPR_PACKET_PAD4[..7]).check_len()
         );
         // valid
@@ -248,10 +248,7 @@ mod test {
         );
         // length field value greater than number of bytes
         let header: [u8; 8] = [0x06, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0];
-        assert_eq!(
-            Err(Error::Truncated),
-            Header::new_unchecked(&header).check_len()
-        );
+        assert_eq!(Err(Error), Header::new_unchecked(&header).check_len());
     }
 
     #[test]
@@ -303,14 +300,14 @@ mod test {
         let len = bytes.len() as u8;
         Header::new_unchecked(&mut bytes).set_header_len(len + 1);
 
-        assert_eq!(Header::new_checked(&bytes).unwrap_err(), Error::Truncated);
+        assert_eq!(Header::new_checked(&bytes).unwrap_err(), Error);
 
         let mut bytes = vec![];
         bytes.extend(&REPR_PACKET_PAD12);
         let len = bytes.len() as u8;
         Header::new_unchecked(&mut bytes).set_header_len(len + 1);
 
-        assert_eq!(Header::new_checked(&bytes).unwrap_err(), Error::Truncated);
+        assert_eq!(Header::new_checked(&bytes).unwrap_err(), Error);
     }
 
     #[test]

+ 11 - 11
src/wire/ipv6option.rs

@@ -1,4 +1,4 @@
-use crate::{Error, Result};
+use super::{Error, Result};
 use core::fmt;
 
 enum_with_unknown! {
@@ -103,7 +103,7 @@ impl<T: AsRef<[u8]>> Ipv6Option<T> {
     }
 
     /// Ensure that no accessor method will panic if called.
-    /// Returns `Err(Error::Truncated)` if the buffer is too short.
+    /// Returns `Err(Error)` if the buffer is too short.
     ///
     /// The result of this check is invalidated by calling [set_data_len].
     ///
@@ -113,7 +113,7 @@ impl<T: AsRef<[u8]>> Ipv6Option<T> {
         let len = data.len();
 
         if len < field::LENGTH {
-            return Err(Error::Truncated);
+            return Err(Error);
         }
 
         if self.option_type() == Type::Pad1 {
@@ -121,13 +121,13 @@ impl<T: AsRef<[u8]>> Ipv6Option<T> {
         }
 
         if len == field::LENGTH {
-            return Err(Error::Truncated);
+            return Err(Error);
         }
 
         let df = field::DATA(data[field::LENGTH]);
 
         if len < df.end {
-            return Err(Error::Truncated);
+            return Err(Error);
         }
 
         Ok(())
@@ -362,7 +362,7 @@ mod test {
         let bytes = [0u8];
         // zero byte buffer
         assert_eq!(
-            Err(Error::Truncated),
+            Err(Error),
             Ipv6Option::new_unchecked(&bytes[..0]).check_len()
         );
         // pad1
@@ -373,7 +373,7 @@ mod test {
 
         // padn with truncated data
         assert_eq!(
-            Err(Error::Truncated),
+            Err(Error),
             Ipv6Option::new_unchecked(&IPV6OPTION_BYTES_PADN[..2]).check_len()
         );
         // padn
@@ -384,11 +384,11 @@ mod test {
 
         // unknown option type with truncated data
         assert_eq!(
-            Err(Error::Truncated),
+            Err(Error),
             Ipv6Option::new_unchecked(&IPV6OPTION_BYTES_UNKNOWN[..4]).check_len()
         );
         assert_eq!(
-            Err(Error::Truncated),
+            Err(Error),
             Ipv6Option::new_unchecked(&IPV6OPTION_BYTES_UNKNOWN[..1]).check_len()
         );
         // unknown type
@@ -436,7 +436,7 @@ mod test {
         assert_eq!(opt.option_type(), Type::Unknown(255));
 
         // unrecognized option without length and data
-        assert_eq!(Ipv6Option::new_checked(&bytes), Err(Error::Truncated));
+        assert_eq!(Ipv6Option::new_checked(&bytes), Err(Error));
     }
 
     #[test]
@@ -533,7 +533,7 @@ mod test {
                         ..
                     }),
                 ) => continue,
-                (6, Err(Error::Truncated)) => continue,
+                (6, Err(Error)) => continue,
                 (i, res) => panic!("Unexpected option `{:?}` at index {}", res, i),
             }
         }

+ 11 - 29
src/wire/ipv6routing.rs

@@ -1,4 +1,4 @@
-use crate::{Error, Result};
+use super::{Error, Result};
 use core::fmt;
 
 use crate::wire::IpProtocol as Protocol;
@@ -158,7 +158,7 @@ impl<T: AsRef<[u8]>> Header<T> {
     }
 
     /// Ensure that no accessor method will panic if called.
-    /// Returns `Err(Error::Truncated)` if the buffer is too short.
+    /// Returns `Err(Error)` if the buffer is too short.
     ///
     /// The result of this check is invalidated by calling [set_header_len].
     ///
@@ -166,11 +166,11 @@ impl<T: AsRef<[u8]>> Header<T> {
     pub fn check_len(&self) -> Result<()> {
         let len = self.buffer.as_ref().len();
         if len < field::MIN_HEADER_SIZE {
-            return Err(Error::Truncated);
+            return Err(Error);
         }
 
         if len < field::DATA(self.header_len()).end as usize {
-            return Err(Error::Truncated);
+            return Err(Error);
         }
 
         Ok(())
@@ -444,7 +444,7 @@ impl<'a> Repr<'a> {
                 addresses: header.addresses(),
             }),
 
-            _ => Err(Error::Unrecognized),
+            _ => Err(Error),
         }
     }
 
@@ -588,31 +588,13 @@ mod test {
     #[test]
     fn test_check_len() {
         // less than min header size
-        assert_eq!(
-            Err(Error::Truncated),
-            Header::new(&BYTES_TYPE2[..3]).check_len()
-        );
-        assert_eq!(
-            Err(Error::Truncated),
-            Header::new(&BYTES_SRH_FULL[..3]).check_len()
-        );
-        assert_eq!(
-            Err(Error::Truncated),
-            Header::new(&BYTES_SRH_ELIDED[..3]).check_len()
-        );
+        assert_eq!(Err(Error), Header::new(&BYTES_TYPE2[..3]).check_len());
+        assert_eq!(Err(Error), Header::new(&BYTES_SRH_FULL[..3]).check_len());
+        assert_eq!(Err(Error), Header::new(&BYTES_SRH_ELIDED[..3]).check_len());
         // less than specified length field
-        assert_eq!(
-            Err(Error::Truncated),
-            Header::new(&BYTES_TYPE2[..23]).check_len()
-        );
-        assert_eq!(
-            Err(Error::Truncated),
-            Header::new(&BYTES_SRH_FULL[..39]).check_len()
-        );
-        assert_eq!(
-            Err(Error::Truncated),
-            Header::new(&BYTES_SRH_ELIDED[..11]).check_len()
-        );
+        assert_eq!(Err(Error), Header::new(&BYTES_TYPE2[..23]).check_len());
+        assert_eq!(Err(Error), Header::new(&BYTES_SRH_FULL[..39]).check_len());
+        assert_eq!(Err(Error), Header::new(&BYTES_SRH_ELIDED[..11]).check_len());
         // valid
         assert_eq!(Ok(()), Header::new(&BYTES_TYPE2[..]).check_len());
         assert_eq!(Ok(()), Header::new(&BYTES_SRH_FULL[..]).check_len());

+ 3 - 3
src/wire/mld.rs

@@ -6,9 +6,9 @@
 
 use byteorder::{ByteOrder, NetworkEndian};
 
+use super::{Error, Result};
 use crate::wire::icmpv6::{field, Message, Packet};
 use crate::wire::Ipv6Address;
-use crate::{Error, Result};
 
 enum_with_unknown! {
     /// MLDv2 Multicast Listener Report Record Type. See [RFC 3810 § 5.2.12] for
@@ -192,7 +192,7 @@ impl<T: AsRef<[u8]>> AddressRecord<T> {
     pub fn check_len(&self) -> Result<()> {
         let len = self.buffer.as_ref().len();
         if len < field::RECORD_MCAST_ADDR.end {
-            Err(Error::Truncated)
+            Err(Error)
         } else {
             Ok(())
         }
@@ -333,7 +333,7 @@ impl<'a> Repr<'a> {
                 nr_mcast_addr_rcrds: packet.nr_mcast_addr_rcrds(),
                 data: packet.payload(),
             }),
-            _ => Err(Error::Unrecognized),
+            _ => Err(Error),
         }
     }
 

+ 24 - 4
src/wire/mod.rs

@@ -125,7 +125,9 @@ mod sixlowpan;
 mod tcp;
 mod udp;
 
-use crate::{phy::Medium, Error};
+use core::fmt;
+
+use crate::phy::Medium;
 
 pub use self::pretty_print::PrettyPrinter;
 
@@ -245,6 +247,24 @@ pub use self::dhcpv4::{
     SERVER_PORT as DHCP_SERVER_PORT,
 };
 
+/// Parsing a packet failed.
+///
+/// Either it is malformed, or it is not supported by smoltcp.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[cfg_attr(feature = "defmt", derive(defmt::Format))]
+pub struct Error;
+
+#[cfg(feature = "std")]
+impl std::error::Error for Error {}
+
+impl fmt::Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "wire::Error")
+    }
+}
+
+pub type Result<T> = core::result::Result<T, Error>;
+
 /// Representation of an hardware address, such as an Ethernet address or an IEEE802.15.4 address.
 #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -354,12 +374,12 @@ impl RawHardwareAddress {
         self.len == 0
     }
 
-    pub fn parse(&self, medium: Medium) -> Result<HardwareAddress, Error> {
+    pub fn parse(&self, medium: Medium) -> Result<HardwareAddress> {
         match medium {
             #[cfg(feature = "medium-ethernet")]
             Medium::Ethernet => {
                 if self.len() < 6 {
-                    return Err(Error::Malformed);
+                    return Err(Error);
                 }
                 Ok(HardwareAddress::Ethernet(EthernetAddress::from_bytes(
                     self.as_bytes(),
@@ -368,7 +388,7 @@ impl RawHardwareAddress {
             #[cfg(feature = "medium-ieee802154")]
             Medium::Ieee802154 => {
                 if self.len() < 8 {
-                    return Err(Error::Malformed);
+                    return Err(Error);
                 }
                 Ok(HardwareAddress::Ieee802154(Ieee802154Address::from_bytes(
                     self.as_bytes(),

+ 8 - 8
src/wire/ndisc.rs

@@ -1,6 +1,7 @@
 use bitflags::bitflags;
 use byteorder::{ByteOrder, NetworkEndian};
 
+use super::{Error, Result};
 use crate::time::Duration;
 use crate::wire::icmpv6::{field, Message, Packet};
 use crate::wire::Ipv6Address;
@@ -8,7 +9,6 @@ use crate::wire::RawHardwareAddress;
 use crate::wire::{Ipv6Packet, Ipv6Repr};
 use crate::wire::{NdiscOption, NdiscOptionRepr, NdiscOptionType};
 use crate::wire::{NdiscPrefixInformation, NdiscRedirectedHeader};
-use crate::{Error, Result};
 
 bitflags! {
     #[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -237,7 +237,7 @@ impl<'a> Repr<'a> {
                     match opt.option_type() {
                         NdiscOptionType::SourceLinkLayerAddr => Some(opt.link_layer_addr()),
                         _ => {
-                            return Err(Error::Unrecognized);
+                            return Err(Error);
                         }
                     }
                 } else {
@@ -256,7 +256,7 @@ impl<'a> Repr<'a> {
                         NdiscOptionRepr::Mtu(val) => mtu = Some(val),
                         NdiscOptionRepr::PrefixInformation(info) => prefix_info = Some(info),
                         _ => {
-                            return Err(Error::Unrecognized);
+                            return Err(Error);
                         }
                     }
                     offset += opt.buffer_len();
@@ -278,7 +278,7 @@ impl<'a> Repr<'a> {
                     match opt.option_type() {
                         NdiscOptionType::SourceLinkLayerAddr => Some(opt.link_layer_addr()),
                         _ => {
-                            return Err(Error::Unrecognized);
+                            return Err(Error);
                         }
                     }
                 } else {
@@ -295,7 +295,7 @@ impl<'a> Repr<'a> {
                     match opt.option_type() {
                         NdiscOptionType::TargetLinkLayerAddr => Some(opt.link_layer_addr()),
                         _ => {
-                            return Err(Error::Unrecognized);
+                            return Err(Error);
                         }
                     }
                 } else {
@@ -319,7 +319,7 @@ impl<'a> Repr<'a> {
                         }
                         NdiscOptionType::RedirectedHeader => {
                             if opt.data_len() < 6 {
-                                return Err(Error::Truncated);
+                                return Err(Error);
                             } else {
                                 let ip_packet =
                                     Ipv6Packet::new_unchecked(&opt.data()[offset + 8..]);
@@ -333,7 +333,7 @@ impl<'a> Repr<'a> {
                             }
                         }
                         _ => {
-                            return Err(Error::Unrecognized);
+                            return Err(Error);
                         }
                     }
                 }
@@ -344,7 +344,7 @@ impl<'a> Repr<'a> {
                     redirected_hdr,
                 })
             }
-            _ => Err(Error::Unrecognized),
+            _ => Err(Error),
         }
     }
 

+ 13 - 16
src/wire/ndiscoption.rs

@@ -2,9 +2,9 @@ use bitflags::bitflags;
 use byteorder::{ByteOrder, NetworkEndian};
 use core::fmt;
 
+use super::{Error, Result};
 use crate::time::Duration;
 use crate::wire::{Ipv6Address, Ipv6Packet, Ipv6Repr, MAX_HARDWARE_ADDRESS_LEN};
-use crate::{Error, Result};
 
 use crate::wire::RawHardwareAddress;
 
@@ -162,7 +162,7 @@ impl<T: AsRef<[u8]>> NdiscOption<T> {
     }
 
     /// Ensure that no accessor method will panic if called.
-    /// Returns `Err(Error::Truncated)` if the buffer is too short.
+    /// Returns `Err(Error)` if the buffer is too short.
     ///
     /// The result of this check is invalidated by calling [set_data_len].
     ///
@@ -172,18 +172,18 @@ impl<T: AsRef<[u8]>> NdiscOption<T> {
         let len = data.len();
 
         if len < field::MIN_OPT_LEN {
-            Err(Error::Truncated)
+            Err(Error)
         } else {
             let data_range = field::DATA(data[field::LENGTH]);
             if len < data_range.end {
-                Err(Error::Truncated)
+                Err(Error)
             } else {
                 match self.option_type() {
                     Type::SourceLinkLayerAddr | Type::TargetLinkLayerAddr | Type::Mtu => Ok(()),
                     Type::PrefixInformation if data_range.end >= field::PREFIX.end => Ok(()),
                     Type::RedirectedHeader if data_range.end >= field::REDIR_MIN_SZ => Ok(()),
                     Type::Unknown(_) => Ok(()),
-                    _ => Err(Error::Truncated),
+                    _ => Err(Error),
                 }
             }
         }
@@ -432,14 +432,14 @@ impl<'a> Repr<'a> {
                 if opt.data_len() == 1 {
                     Ok(Repr::SourceLinkLayerAddr(opt.link_layer_addr()))
                 } else {
-                    Err(Error::Malformed)
+                    Err(Error)
                 }
             }
             Type::TargetLinkLayerAddr => {
                 if opt.data_len() == 1 {
                     Ok(Repr::TargetLinkLayerAddr(opt.link_layer_addr()))
                 } else {
-                    Err(Error::Malformed)
+                    Err(Error)
                 }
             }
             Type::PrefixInformation => {
@@ -452,7 +452,7 @@ impl<'a> Repr<'a> {
                         prefix: opt.prefix(),
                     }))
                 } else {
-                    Err(Error::Malformed)
+                    Err(Error)
                 }
             }
             Type::RedirectedHeader => {
@@ -460,7 +460,7 @@ impl<'a> Repr<'a> {
                 // does not have enough data to fill out the IP header
                 // and common option fields.
                 if opt.data_len() < 6 {
-                    Err(Error::Truncated)
+                    Err(Error)
                 } else {
                     let ip_packet = Ipv6Packet::new_unchecked(&opt.data()[field::IP_DATA..]);
                     let ip_repr = Ipv6Repr::parse(&ip_packet)?;
@@ -474,7 +474,7 @@ impl<'a> Repr<'a> {
                 if opt.data_len() == 1 {
                     Ok(Repr::Mtu(opt.mtu()))
                 } else {
-                    Err(Error::Malformed)
+                    Err(Error)
                 }
             }
             Type::Unknown(id) => Ok(Repr::Unknown {
@@ -617,10 +617,10 @@ impl<T: AsRef<[u8]>> PrettyPrint for NdiscOption<T> {
 
 #[cfg(test)]
 mod test {
+    use super::Error;
     use super::{NdiscOption, PrefixInfoFlags, PrefixInformation, Repr, Type};
     use crate::time::Duration;
     use crate::wire::{EthernetAddress, Ipv6Address};
-    use crate::Error;
 
     static PREFIX_OPT_BYTES: [u8; 32] = [
         0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x03, 0x84, 0x00, 0x00, 0x03, 0xe8, 0x00, 0x00, 0x00,
@@ -659,12 +659,9 @@ mod test {
 
     #[test]
     fn test_short_packet() {
-        assert_eq!(
-            NdiscOption::new_checked(&[0x00, 0x00]),
-            Err(Error::Truncated)
-        );
+        assert_eq!(NdiscOption::new_checked(&[0x00, 0x00]), Err(Error));
         let bytes = [0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
-        assert_eq!(NdiscOption::new_checked(&bytes), Err(Error::Truncated));
+        assert_eq!(NdiscOption::new_checked(&bytes), Err(Error));
     }
 
     #[test]

+ 27 - 30
src/wire/sixlowpan.rs

@@ -1,12 +1,11 @@
-/// Implementation of [RFC 6282] which specifies a compression format for IPv6 datagrams over
-/// IEEE802.154-based networks.
-///
-/// [RFC 6282]: https://datatracker.ietf.org/doc/html/rfc6282
+//! Implementation of [RFC 6282] which specifies a compression format for IPv6 datagrams over
+//! IEEE802.154-based networks.
+//!
+//! [RFC 6282]: https://datatracker.ietf.org/doc/html/rfc6282
+use super::{Error, Result};
 use crate::wire::ieee802154::Address as LlAddress;
 use crate::wire::ipv6;
 use crate::wire::IpProtocol;
-use crate::Error;
-use crate::Result;
 
 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -46,23 +45,22 @@ impl<'a> Address<'a> {
                     Some(LlAddress::Extended(ll)) => {
                         bytes[8..].copy_from_slice(&LlAddress::Extended(ll).as_eui_64().unwrap());
                     }
-                    _ => return Err(Error::Malformed),
+                    _ => return Err(Error),
                 }
 
                 Ok(ipv6::Address::from_bytes(&bytes))
             }
-            Address::WithContext(_) => Err(Error::NotSupported),
-            Address::Reserved => Err(Error::Malformed),
+            Address::WithContext(_) => Err(Error),
+            Address::Reserved => Err(Error),
         }
     }
 }
 
 pub mod iphc {
+    use super::{Error, Result};
     use crate::wire::ieee802154::Address as LlAddress;
     use crate::wire::ipv6;
     use crate::wire::IpProtocol;
-    use crate::Error;
-    use crate::Result;
     use byteorder::{ByteOrder, NetworkEndian};
 
     use super::Address;
@@ -124,11 +122,11 @@ pub mod iphc {
         }
 
         /// Ensure that no accessor method will panic if called.
-        /// Returns `Err(Error::Truncated)` if the buffer is too short.
+        /// Returns `Err(Error)` if the buffer is too short.
         pub fn check_len(&self) -> Result<()> {
             let buffer = self.buffer.as_ref();
             if buffer.len() < 2 {
-                return Err(Error::Truncated);
+                return Err(Error);
             }
 
             let mut offset = self.ip_fields_start()
@@ -139,7 +137,7 @@ pub mod iphc {
             offset += self.dst_address_size();
 
             if offset as usize > buffer.len() {
-                return Err(Error::Truncated);
+                return Err(Error);
             }
 
             Ok(())
@@ -290,7 +288,7 @@ pub mod iphc {
                     // Any remaining bits are zero.
                     Ok(Address::WithContext(&[]))
                 }
-                _ => Err(Error::Malformed),
+                _ => Err(Error),
             }
         }
 
@@ -428,10 +426,10 @@ pub mod iphc {
                     // P are octets used to encode the prefix itself.
                     // L are octets used to encode the prefix length.
                     // The prefix information P and L is taken from the specified context.
-                    Err(Error::NotSupported)
+                    Err(Error)
                 }
                 (1, 1, 0b01 | 0b10 | 0b11) => Ok(Address::Reserved),
-                _ => Err(Error::Malformed),
+                _ => Err(Error),
             }
         }
 
@@ -781,7 +779,7 @@ pub mod iphc {
 
             if packet.dispatch_field() != DISPATCH {
                 // This is not an LOWPAN_IPHC packet.
-                return Err(Error::Malformed);
+                return Err(Error);
             }
 
             let src_addr = packet.src_addr()?.resolve(ll_src_addr)?;
@@ -975,13 +973,12 @@ pub mod iphc {
 }
 
 pub mod nhc {
+    use super::{Error, Result};
     use crate::wire::ip::checksum;
     use crate::wire::ip::Address as IpAddress;
     use crate::wire::ipv6;
     use crate::wire::udp::Repr as UdpRepr;
     use crate::wire::IpProtocol;
-    use crate::Error;
-    use crate::Result;
     use byteorder::{ByteOrder, NetworkEndian};
     use ipv6::Address;
 
@@ -1032,7 +1029,7 @@ pub mod nhc {
                 // We have a compressed UDP header.
                 Ok(Packet::UdpHeader(UdpPacket::new_checked(buffer)?))
             } else {
-                Err(Error::Unrecognized)
+                Err(Error)
             }
         }
     }
@@ -1089,11 +1086,11 @@ pub mod nhc {
         }
 
         /// Ensure that no accessor method will panic if called.
-        /// Returns `Err(Error::Truncated)` if the buffer is too short.
+        /// Returns `Err(Error)` if the buffer is too short.
         pub fn check_len(&self) -> Result<()> {
             let buffer = self.buffer.as_ref();
             if buffer.is_empty() {
-                Err(Error::Truncated)
+                Err(Error)
             } else {
                 Ok(())
             }
@@ -1235,7 +1232,7 @@ pub mod nhc {
             packet.check_len()?;
 
             if packet.dispatch_field() != EXT_HEADER_DISPATCH {
-                return Err(Error::Malformed);
+                return Err(Error);
             }
 
             Ok(ExtensionHeaderRepr {
@@ -1293,17 +1290,17 @@ pub mod nhc {
         }
 
         /// Ensure that no accessor method will panic if called.
-        /// Returns `Err(Error::Truncated)` if the buffer is too short.
+        /// Returns `Err(Error)` if the buffer is too short.
         pub fn check_len(&self) -> Result<()> {
             let buffer = self.buffer.as_ref();
 
             if buffer.is_empty() {
-                return Err(Error::Truncated);
+                return Err(Error);
             }
 
             let index = 1 + self.ports_size() + self.checksum_size();
             if index > buffer.len() {
-                return Err(Error::Truncated);
+                return Err(Error);
             }
 
             Ok(())
@@ -1507,7 +1504,7 @@ pub mod nhc {
             packet.check_len()?;
 
             if packet.dispatch_field() != UDP_DISPATCH {
-                return Err(Error::Malformed);
+                return Err(Error);
             }
 
             let payload_len = packet.payload().len();
@@ -1526,11 +1523,11 @@ pub mod nhc {
 
             if let Some(checksum) = packet.checksum() {
                 if chk_sum != checksum {
-                    return Err(Error::Checksum);
+                    return Err(Error);
                 }
             } else {
                 net_trace!("Currently we do not support elided checksums.");
-                return Err(Error::Unrecognized);
+                return Err(Error);
             };
 
             Ok(UdpNhcRepr(UdpRepr {

+ 25 - 30
src/wire/tcp.rs

@@ -1,10 +1,10 @@
 use byteorder::{ByteOrder, NetworkEndian};
 use core::{cmp, fmt, i32, ops};
 
+use super::{Error, Result};
 use crate::phy::ChecksumCapabilities;
 use crate::wire::ip::checksum;
 use crate::wire::{IpAddress, IpProtocol};
-use crate::{Error, Result};
 
 /// A TCP sequence number.
 ///
@@ -128,8 +128,8 @@ impl<T: AsRef<[u8]>> Packet<T> {
     }
 
     /// Ensure that no accessor method will panic if called.
-    /// Returns `Err(Error::Truncated)` if the buffer is too short.
-    /// Returns `Err(Error::Malformed)` if the header length field has a value smaller
+    /// Returns `Err(Error)` if the buffer is too short.
+    /// Returns `Err(Error)` if the header length field has a value smaller
     /// than the minimal header length.
     ///
     /// The result of this check is invalidated by calling [set_header_len].
@@ -138,13 +138,11 @@ impl<T: AsRef<[u8]>> Packet<T> {
     pub fn check_len(&self) -> Result<()> {
         let len = self.buffer.as_ref().len();
         if len < field::URGENT.end {
-            Err(Error::Truncated)
+            Err(Error)
         } else {
             let header_len = self.header_len() as usize;
-            if len < header_len {
-                Err(Error::Truncated)
-            } else if header_len < field::URGENT.end {
-                Err(Error::Malformed)
+            if len < header_len || header_len < field::URGENT.end {
+                Err(Error)
             } else {
                 Ok(())
             }
@@ -608,7 +606,7 @@ pub enum TcpOption<'a> {
 impl<'a> TcpOption<'a> {
     pub fn parse(buffer: &'a [u8]) -> Result<(&'a [u8], TcpOption<'a>)> {
         let (length, option);
-        match *buffer.get(0).ok_or(Error::Truncated)? {
+        match *buffer.get(0).ok_or(Error)? {
             field::OPT_END => {
                 length = 1;
                 option = TcpOption::EndOfList;
@@ -618,21 +616,21 @@ impl<'a> TcpOption<'a> {
                 option = TcpOption::NoOperation;
             }
             kind => {
-                length = *buffer.get(1).ok_or(Error::Truncated)? as usize;
-                let data = buffer.get(2..length).ok_or(Error::Truncated)?;
+                length = *buffer.get(1).ok_or(Error)? as usize;
+                let data = buffer.get(2..length).ok_or(Error)?;
                 match (kind, length) {
                     (field::OPT_END, _) | (field::OPT_NOP, _) => unreachable!(),
                     (field::OPT_MSS, 4) => {
                         option = TcpOption::MaxSegmentSize(NetworkEndian::read_u16(data))
                     }
-                    (field::OPT_MSS, _) => return Err(Error::Malformed),
+                    (field::OPT_MSS, _) => return Err(Error),
                     (field::OPT_WS, 3) => option = TcpOption::WindowScale(data[0]),
-                    (field::OPT_WS, _) => return Err(Error::Malformed),
+                    (field::OPT_WS, _) => return Err(Error),
                     (field::OPT_SACKPERM, 2) => option = TcpOption::SackPermitted,
-                    (field::OPT_SACKPERM, _) => return Err(Error::Malformed),
+                    (field::OPT_SACKPERM, _) => return Err(Error),
                     (field::OPT_SACKRNG, n) => {
                         if n < 10 || (n - 2) % 8 != 0 {
-                            return Err(Error::Malformed);
+                            return Err(Error);
                         }
                         if n > 26 {
                             // It's possible for a remote to send 4 SACK blocks, but extremely rare.
@@ -801,14 +799,14 @@ impl<'a> Repr<'a> {
     {
         // Source and destination ports must be present.
         if packet.src_port() == 0 {
-            return Err(Error::Malformed);
+            return Err(Error);
         }
         if packet.dst_port() == 0 {
-            return Err(Error::Malformed);
+            return Err(Error);
         }
         // Valid checksum is expected.
         if checksum_caps.tcp.rx() && !packet.verify_checksum(src_addr, dst_addr) {
-            return Err(Error::Checksum);
+            return Err(Error);
         }
 
         let control = match (packet.syn(), packet.fin(), packet.rst(), packet.psh()) {
@@ -817,7 +815,7 @@ impl<'a> Repr<'a> {
             (true, false, false, _) => Control::Syn,
             (false, true, false, _) => Control::Fin,
             (false, false, true, _) => Control::Rst,
-            _ => return Err(Error::Malformed),
+            _ => return Err(Error),
         };
         let ack_number = match packet.ack() {
             true => Some(packet.ack_number()),
@@ -1157,7 +1155,7 @@ mod test {
     #[cfg(feature = "proto-ipv4")]
     fn test_truncated() {
         let packet = Packet::new_unchecked(&PACKET_BYTES[..23]);
-        assert_eq!(packet.check_len(), Err(Error::Truncated));
+        assert_eq!(packet.check_len(), Err(Error));
     }
 
     #[test]
@@ -1165,7 +1163,7 @@ mod test {
         let mut bytes = vec![0; 20];
         let mut packet = Packet::new_unchecked(&mut bytes);
         packet.set_header_len(10);
-        assert_eq!(packet.check_len(), Err(Error::Malformed));
+        assert_eq!(packet.check_len(), Err(Error));
     }
 
     #[cfg(feature = "proto-ipv4")]
@@ -1277,14 +1275,11 @@ mod test {
 
     #[test]
     fn test_malformed_tcp_options() {
-        assert_eq!(TcpOption::parse(&[]), Err(Error::Truncated));
-        assert_eq!(TcpOption::parse(&[0xc]), Err(Error::Truncated));
-        assert_eq!(
-            TcpOption::parse(&[0xc, 0x05, 0x01, 0x02]),
-            Err(Error::Truncated)
-        );
-        assert_eq!(TcpOption::parse(&[0xc, 0x01]), Err(Error::Truncated));
-        assert_eq!(TcpOption::parse(&[0x2, 0x02]), Err(Error::Malformed));
-        assert_eq!(TcpOption::parse(&[0x3, 0x02]), Err(Error::Malformed));
+        assert_eq!(TcpOption::parse(&[]), Err(Error));
+        assert_eq!(TcpOption::parse(&[0xc]), Err(Error));
+        assert_eq!(TcpOption::parse(&[0xc, 0x05, 0x01, 0x02]), Err(Error));
+        assert_eq!(TcpOption::parse(&[0xc, 0x01]), Err(Error));
+        assert_eq!(TcpOption::parse(&[0x2, 0x02]), Err(Error));
+        assert_eq!(TcpOption::parse(&[0x3, 0x02]), Err(Error));
     }
 }

+ 9 - 11
src/wire/udp.rs

@@ -1,10 +1,10 @@
 use byteorder::{ByteOrder, NetworkEndian};
 use core::fmt;
 
+use super::{Error, Result};
 use crate::phy::ChecksumCapabilities;
 use crate::wire::ip::checksum;
 use crate::wire::{IpAddress, IpProtocol};
-use crate::{Error, Result};
 
 /// A read/write wrapper around an User Datagram Protocol packet buffer.
 #[derive(Debug, PartialEq, Clone)]
@@ -48,8 +48,8 @@ impl<T: AsRef<[u8]>> Packet<T> {
     }
 
     /// Ensure that no accessor method will panic if called.
-    /// Returns `Err(Error::Truncated)` if the buffer is too short.
-    /// Returns `Err(Error::Malformed)` if the length field has a value smaller
+    /// Returns `Err(Error)` if the buffer is too short.
+    /// Returns `Err(Error)` if the length field has a value smaller
     /// than the header length.
     ///
     /// The result of this check is invalidated by calling [set_len].
@@ -58,13 +58,11 @@ impl<T: AsRef<[u8]>> Packet<T> {
     pub fn check_len(&self) -> Result<()> {
         let buffer_len = self.buffer.as_ref().len();
         if buffer_len < HEADER_LEN {
-            Err(Error::Truncated)
+            Err(Error)
         } else {
             let field_len = self.len() as usize;
-            if buffer_len < field_len {
-                Err(Error::Truncated)
-            } else if field_len < HEADER_LEN {
-                Err(Error::Malformed)
+            if buffer_len < field_len || field_len < HEADER_LEN {
+                Err(Error)
             } else {
                 Ok(())
             }
@@ -221,7 +219,7 @@ impl Repr {
     {
         // Destination port cannot be omitted (but source port can be).
         if packet.dst_port() == 0 {
-            return Err(Error::Malformed);
+            return Err(Error);
         }
         // Valid checksum is expected...
         if checksum_caps.udp.rx() && !packet.verify_checksum(src_addr, dst_addr) {
@@ -229,7 +227,7 @@ impl Repr {
                 // ... except on UDP-over-IPv4, where it can be omitted.
                 #[cfg(feature = "proto-ipv4")]
                 (&IpAddress::Ipv4(_), &IpAddress::Ipv4(_)) if packet.checksum() == 0 => (),
-                _ => return Err(Error::Checksum),
+                _ => return Err(Error),
             }
         }
 
@@ -360,7 +358,7 @@ mod test {
         let mut bytes = vec![0; 12];
         let mut packet = Packet::new_unchecked(&mut bytes);
         packet.set_len(4);
-        assert_eq!(packet.check_len(), Err(Error::Malformed));
+        assert_eq!(packet.check_len(), Err(Error));
     }
 
     #[test]

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно