Get rid of Result<_, ()>.

The use of this type has several drawbacks:
  * It does not allow distinguishing between different error
    conditions. In fact, we wrongly conflated some of them
    before this commit.
  * It does not allow propagation via ? and requires manual use
    of map_err, which is especially tiresome for downstream code.
  * It prevents us from expanding the set of error conditions
    even if right now we have only one.
  * It prevents us from blanket using Result<T> everywhere
    (a nitpick at most).

Instead, use Result<T, Error> everywhere, and differentiate error
conditions where applicable.
This commit is contained in:
whitequark 2017-07-27 13:51:02 +00:00
parent 7838434165
commit 8d8a4ea583
21 changed files with 134 additions and 118 deletions

View File

@ -1,6 +1,6 @@
use managed::{Managed, ManagedSlice};
use Error;
use {Error, Result};
use phy::Device;
use wire::{EthernetAddress, EthernetProtocol, EthernetFrame};
use wire::{ArpPacket, ArpRepr, ArpOperation};
@ -109,7 +109,7 @@ impl<'a, 'b, 'c, DeviceT: Device + 'a> Interface<'a, 'b, 'c, DeviceT> {
/// handling the given set of sockets.
///
/// The timestamp is a monotonically increasing number of milliseconds.
pub fn poll(&mut self, sockets: &mut SocketSet, timestamp: u64) -> Result<(), Error> {
pub fn poll(&mut self, sockets: &mut SocketSet, timestamp: u64) -> Result<()> {
// First, transmit any outgoing packets.
loop {
if self.emit(sockets, timestamp)? { break }
@ -140,7 +140,7 @@ impl<'a, 'b, 'c, DeviceT: Device + 'a> Interface<'a, 'b, 'c, DeviceT> {
// Snoop all ARP traffic, and respond to ARP packets directed at us.
fn process_arp<'frame, T: AsRef<[u8]>>
(&mut self, eth_frame: &EthernetFrame<&'frame T>) ->
Result<Response<'frame>, Error> {
Result<Response<'frame>> {
let arp_packet = ArpPacket::new_checked(eth_frame.payload())?;
let arp_repr = ArpRepr::parse(&arp_packet)?;
@ -189,7 +189,7 @@ impl<'a, 'b, 'c, DeviceT: Device + 'a> Interface<'a, 'b, 'c, DeviceT> {
fn process_ipv4<'frame, T: AsRef<[u8]>>
(&mut self, sockets: &mut SocketSet, timestamp: u64,
eth_frame: &EthernetFrame<&'frame T>) ->
Result<Response<'frame>, Error> {
Result<Response<'frame>> {
let ipv4_packet = Ipv4Packet::new_checked(eth_frame.payload())?;
let ipv4_repr = Ipv4Repr::parse(&ipv4_packet)?;
@ -251,7 +251,7 @@ impl<'a, 'b, 'c, DeviceT: Device + 'a> Interface<'a, 'b, 'c, DeviceT> {
}
fn process_icmpv4<'frame>(ipv4_repr: Ipv4Repr, ip_payload: &'frame [u8]) ->
Result<Response<'frame>, Error> {
Result<Response<'frame>> {
let icmp_packet = Icmpv4Packet::new_checked(ip_payload)?;
let icmp_repr = Icmpv4Repr::parse(&icmp_packet)?;
@ -284,7 +284,7 @@ impl<'a, 'b, 'c, DeviceT: Device + 'a> Interface<'a, 'b, 'c, DeviceT> {
fn process_udpv4<'frame>(sockets: &mut SocketSet, timestamp: u64,
ipv4_repr: Ipv4Repr, ip_payload: &'frame [u8]) ->
Result<Response<'frame>, Error> {
Result<Response<'frame>> {
let ip_repr = IpRepr::Ipv4(ipv4_repr);
for udp_socket in sockets.iter_mut().filter_map(
@ -316,7 +316,7 @@ impl<'a, 'b, 'c, DeviceT: Device + 'a> Interface<'a, 'b, 'c, DeviceT> {
fn process_tcpv4<'frame>(sockets: &mut SocketSet, timestamp: u64,
ipv4_repr: Ipv4Repr, ip_payload: &'frame [u8]) ->
Result<Response<'frame>, Error> {
Result<Response<'frame>> {
let ip_repr = IpRepr::Ipv4(ipv4_repr);
for tcp_socket in sockets.iter_mut().filter_map(
@ -359,7 +359,7 @@ impl<'a, 'b, 'c, DeviceT: Device + 'a> Interface<'a, 'b, 'c, DeviceT> {
Ok(Response::Tcpv4(ipv4_reply_repr, tcp_reply_repr))
}
fn send_response(&mut self, timestamp: u64, response: Response) -> Result<(), Error> {
fn send_response(&mut self, timestamp: u64, response: Response) -> Result<()> {
macro_rules! ip_response {
($tx_buffer:ident, $frame:ident, $ip_repr:ident) => ({
let dst_hardware_addr =
@ -428,7 +428,7 @@ impl<'a, 'b, 'c, DeviceT: Device + 'a> Interface<'a, 'b, 'c, DeviceT> {
}
}
fn emit(&mut self, sockets: &mut SocketSet, timestamp: u64) -> Result<bool, Error> {
fn emit(&mut self, sockets: &mut SocketSet, timestamp: u64) -> Result<bool> {
// Borrow checker is being overly careful around closures, so we have
// to hack around that.
let src_hardware_addr = self.hardware_addr;

View File

@ -134,6 +134,9 @@ pub enum Error {
__Nonexhaustive
}
/// The result type for the networking stack.
pub type Result<T> = core::result::Result<T, Error>;
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {

View File

@ -1,4 +1,4 @@
use Error;
use {Error, Result};
use super::{DeviceLimits, Device};
// We use our own RNG to stay compatible with #![no_std].
@ -196,7 +196,7 @@ impl<D: Device> Device for FaultInjector<D>
limits
}
fn receive(&mut self, timestamp: u64) -> Result<Self::RxBuffer, Error> {
fn receive(&mut self, timestamp: u64) -> Result<Self::RxBuffer> {
let mut buffer = self.inner.receive(timestamp)?;
if self.state.maybe(self.config.drop_pct) {
net_trace!("rx: randomly dropping a packet");
@ -217,7 +217,7 @@ impl<D: Device> Device for FaultInjector<D>
Ok(buffer)
}
fn transmit(&mut self, timestamp: u64, length: usize) -> Result<Self::TxBuffer, Error> {
fn transmit(&mut self, timestamp: u64, length: usize) -> Result<Self::TxBuffer> {
let buffer;
if self.state.maybe(self.config.drop_pct) {
net_trace!("tx: randomly dropping a packet");

View File

@ -11,7 +11,7 @@ use std::collections::VecDeque;
#[cfg(feature = "collections")]
use collections::{Vec, VecDeque};
use Error;
use {Error, Result};
use super::{Device, DeviceLimits};
/// A loopback device.
@ -39,14 +39,14 @@ impl Device for Loopback {
}
}
fn receive(&mut self, _timestamp: u64) -> Result<Self::RxBuffer, Error> {
fn receive(&mut self, _timestamp: u64) -> Result<Self::RxBuffer> {
match self.0.borrow_mut().pop_front() {
Some(packet) => Ok(packet),
None => Err(Error::Exhausted)
}
}
fn transmit(&mut self, _timestamp: u64, length: usize) -> Result<Self::TxBuffer, Error> {
fn transmit(&mut self, _timestamp: u64, length: usize) -> Result<Self::TxBuffer> {
let mut buffer = Vec::new();
buffer.resize(length, 0);
Ok(TxBuffer {

View File

@ -20,7 +20,7 @@
/*!
```rust
use std::slice;
use smoltcp::Error;
use smoltcp::{Error, Result};
use smoltcp::phy::{DeviceLimits, Device};
const TX_BUFFERS: [*mut u8; 2] = [0x10000000 as *mut u8, 0x10001000 as *mut u8];
@ -61,7 +61,7 @@ impl Device for EthernetDevice {
limits
}
fn receive(&mut self, _timestamp: u64) -> Result<Self::RxBuffer, Error> {
fn receive(&mut self, _timestamp: u64) -> Result<Self::RxBuffer> {
if rx_full() {
let index = self.rx_next;
self.rx_next = (self.rx_next + 1) % RX_BUFFERS.len();
@ -75,7 +75,7 @@ impl Device for EthernetDevice {
}
}
fn transmit(&mut self, _timestamp: u64, length: usize) -> Result<Self::TxBuffer, Error> {
fn transmit(&mut self, _timestamp: u64, length: usize) -> Result<Self::TxBuffer> {
if tx_empty() {
let index = self.tx_next;
self.tx_next = (self.tx_next + 1) % TX_BUFFERS.len();
@ -104,7 +104,7 @@ impl Drop for EthernetTxBuffer {
```
*/
use Error;
use {Error, Result};
#[cfg(any(feature = "raw_socket", feature = "tap_interface"))]
mod sys;
@ -177,12 +177,12 @@ pub trait Device {
/// It is expected that a `receive` implementation, once a packet is written to memory
/// through DMA, would gain ownership of the underlying buffer, provide it for parsing,
/// and return it to the network device once it is dropped.
fn receive(&mut self, timestamp: u64) -> Result<Self::RxBuffer, Error>;
fn receive(&mut self, timestamp: u64) -> Result<Self::RxBuffer>;
/// Transmit a frame.
///
/// It is expected that a `transmit` implementation would gain ownership of a buffer with
/// the requested length, provide it for emission, and schedule it to be read from
/// memory by the network device once it is dropped.
fn transmit(&mut self, timestamp: u64, length: usize) -> Result<Self::TxBuffer, Error>;
fn transmit(&mut self, timestamp: u64, length: usize) -> Result<Self::TxBuffer>;
}

View File

@ -3,7 +3,7 @@ use core::cell::RefCell;
use std::io::Write;
use byteorder::{ByteOrder, NativeEndian};
use Error;
use {Error, Result};
use super::{DeviceLimits, Device};
enum_with_unknown! {
@ -136,7 +136,7 @@ impl<D: Device, S: PcapSink + Clone> Device for PcapWriter<D, S> {
fn limits(&self) -> DeviceLimits { self.lower.limits() }
fn receive(&mut self, timestamp: u64) -> Result<Self::RxBuffer, Error> {
fn receive(&mut self, timestamp: u64) -> Result<Self::RxBuffer> {
let buffer = self.lower.receive(timestamp)?;
match self.mode {
PcapMode::Both | PcapMode::RxOnly =>
@ -146,7 +146,7 @@ impl<D: Device, S: PcapSink + Clone> Device for PcapWriter<D, S> {
Ok(buffer)
}
fn transmit(&mut self, timestamp: u64, length: usize) -> Result<Self::TxBuffer, Error> {
fn transmit(&mut self, timestamp: u64, length: usize) -> Result<Self::TxBuffer> {
let buffer = self.lower.transmit(timestamp, length)?;
Ok(TxBuffer { buffer, timestamp, sink: self.sink.clone(), mode: self.mode })
}

View File

@ -3,7 +3,7 @@ use std::vec::Vec;
use std::rc::Rc;
use std::io;
use Error;
use {Error, Result};
use super::{sys, DeviceLimits, Device};
/// A socket that captures or transmits the complete frame.
@ -40,7 +40,7 @@ impl Device for RawSocket {
}
}
fn receive(&mut self, _timestamp: u64) -> Result<Self::RxBuffer, Error> {
fn receive(&mut self, _timestamp: u64) -> Result<Self::RxBuffer> {
let mut lower = self.lower.borrow_mut();
let mut buffer = vec![0; self.mtu];
let size = lower.recv(&mut buffer[..]).unwrap();
@ -48,7 +48,7 @@ impl Device for RawSocket {
Ok(buffer)
}
fn transmit(&mut self, _timestamp: u64, length: usize) -> Result<Self::TxBuffer, Error> {
fn transmit(&mut self, _timestamp: u64, length: usize) -> Result<Self::TxBuffer> {
Ok(TxBuffer {
lower: self.lower.clone(),
buffer: vec![0; length]

View File

@ -3,7 +3,7 @@ use std::vec::Vec;
use std::rc::Rc;
use std::io;
use Error;
use {Error, Result};
use super::{sys, DeviceLimits, Device};
/// A virtual Ethernet interface.
@ -41,7 +41,7 @@ impl Device for TapInterface {
}
}
fn receive(&mut self, _timestamp: u64) -> Result<Self::RxBuffer, Error> {
fn receive(&mut self, _timestamp: u64) -> Result<Self::RxBuffer> {
let mut lower = self.lower.borrow_mut();
let mut buffer = vec![0; self.mtu];
match lower.recv(&mut buffer[..]) {
@ -56,7 +56,7 @@ impl Device for TapInterface {
}
}
fn transmit(&mut self, _timestamp: u64, length: usize) -> Result<Self::TxBuffer, Error> {
fn transmit(&mut self, _timestamp: u64, length: usize) -> Result<Self::TxBuffer> {
Ok(TxBuffer {
lower: self.lower.clone(),
buffer: vec![0; length]

View File

@ -1,4 +1,4 @@
use Error;
use {Error, Result};
use wire::pretty_print::{PrettyPrint, PrettyPrinter};
use super::{DeviceLimits, Device};
@ -33,13 +33,13 @@ impl<D: Device, P: PrettyPrint> Device for Tracer<D, P> {
fn limits(&self) -> DeviceLimits { self.inner.limits() }
fn receive(&mut self, timestamp: u64) -> Result<Self::RxBuffer, Error> {
fn receive(&mut self, timestamp: u64) -> Result<Self::RxBuffer> {
let buffer = self.inner.receive(timestamp)?;
(self.writer)(timestamp, PrettyPrinter::<P>::new("<- ", &buffer));
Ok(buffer)
}
fn transmit(&mut self, timestamp: u64, length: usize) -> Result<Self::TxBuffer, Error> {
fn transmit(&mut self, timestamp: u64, length: usize) -> Result<Self::TxBuffer> {
let buffer = self.inner.transmit(timestamp, length)?;
Ok(TxBuffer { buffer, timestamp, writer: self.writer })
}

View File

@ -10,7 +10,7 @@
//! The interface implemented by this module uses explicit buffering: you decide on the good
//! size for a buffer, allocate it, and let the networking stack use it.
use Error;
use {Error, Result};
use phy::DeviceLimits;
use wire::IpRepr;
@ -82,8 +82,8 @@ impl<'a, 'b> Socket<'a, 'b> {
}
pub(crate) fn dispatch<F, R>(&mut self, timestamp: u64, limits: &DeviceLimits,
emit: &mut F) -> Result<R, Error>
where F: FnMut(&IpRepr, &IpPayload) -> Result<R, Error> {
emit: &mut F) -> Result<R>
where F: FnMut(&IpRepr, &IpPayload) -> Result<R> {
dispatch_socket!(self, |socket [mut]| socket.dispatch(timestamp, limits, emit))
}
}

View File

@ -1,6 +1,6 @@
use managed::Managed;
use Error;
use {Error, Result};
use phy::DeviceLimits;
use wire::{IpVersion, IpProtocol, Ipv4Repr, Ipv4Packet};
use socket::{IpRepr, IpPayload, Socket};
@ -109,9 +109,9 @@ impl<'a, 'b> RawSocket<'a, 'b> {
/// Enqueue a packet to send, and return a pointer to its payload.
///
/// This function returns `Err(())` if the size is greater than what
/// the transmit buffer can accomodate.
pub fn send(&mut self, size: usize) -> Result<&mut [u8], ()> {
/// This function returns `Err(Error::Exhausted)` if the size is greater than
/// the transmit packet buffer size.
pub fn send(&mut self, size: usize) -> Result<&mut [u8]> {
let packet_buf = self.tx_buffer.enqueue()?;
packet_buf.size = size;
net_trace!("[{}]:{}:{}: buffer to send {} octets",
@ -123,7 +123,7 @@ impl<'a, 'b> RawSocket<'a, 'b> {
/// 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<usize, ()> {
pub fn send_slice(&mut self, data: &[u8]) -> Result<usize> {
let buffer = self.send(data.len())?;
let data = &data[..buffer.len()];
buffer.copy_from_slice(data);
@ -132,8 +132,8 @@ impl<'a, 'b> RawSocket<'a, 'b> {
/// Dequeue a packet, and return a pointer to the payload.
///
/// This function returns `Err(())` if the receive buffer is empty.
pub fn recv(&mut self) -> Result<&[u8], ()> {
/// This function returns `Err(Error::Exhausted)` if the receive buffer is empty.
pub fn recv(&mut self) -> Result<&[u8]> {
let packet_buf = self.rx_buffer.dequeue()?;
net_trace!("[{}]:{}:{}: receive {} buffered octets",
self.debug_id, self.ip_version, self.ip_protocol,
@ -144,21 +144,21 @@ impl<'a, 'b> RawSocket<'a, 'b> {
/// 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> {
let buffer = self.recv()?;
data[..buffer.len()].copy_from_slice(buffer);
Ok(buffer.len())
}
pub(crate) fn process(&mut self, _timestamp: u64, ip_repr: &IpRepr,
payload: &[u8]) -> Result<(), Error> {
payload: &[u8]) -> Result<()> {
match self.ip_version {
IpVersion::Ipv4 => {
if ip_repr.protocol() != self.ip_protocol {
return Err(Error::Rejected);
}
let header_len = ip_repr.buffer_len();
let packet_buf = self.rx_buffer.enqueue().map_err(|()| Error::Exhausted)?;
let packet_buf = self.rx_buffer.enqueue()?;
packet_buf.size = header_len + payload.len();
ip_repr.emit(&mut packet_buf.as_mut()[..header_len]);
packet_buf.as_mut()[header_len..header_len + payload.len()]
@ -174,9 +174,9 @@ impl<'a, 'b> RawSocket<'a, 'b> {
/// See [Socket::dispatch](enum.Socket.html#method.dispatch).
pub(crate) fn dispatch<F, R>(&mut self, _timestamp: u64, _limits: &DeviceLimits,
emit: &mut F) -> Result<R, Error>
where F: FnMut(&IpRepr, &IpPayload) -> Result<R, Error> {
let mut packet_buf = self.tx_buffer.dequeue().map_err(|()| Error::Exhausted)?;
emit: &mut F) -> Result<R>
where F: FnMut(&IpRepr, &IpPayload) -> Result<R> {
let mut packet_buf = self.tx_buffer.dequeue()?;
net_trace!("[{}]:{}:{}: sending {} octets",
self.debug_id, self.ip_version, self.ip_protocol,
packet_buf.size);

View File

@ -4,7 +4,7 @@
use core::fmt;
use managed::Managed;
use Error;
use {Error, Result};
use phy::DeviceLimits;
use wire::{IpProtocol, IpAddress, IpEndpoint};
use wire::{TcpSeqNumber, TcpPacket, TcpRepr, TcpControl};
@ -350,12 +350,12 @@ impl<'a> TcpSocket<'a> {
///
/// This function returns an error if the socket was open; see [is_open](#method.is_open).
/// It also returns an error if the specified port is zero.
pub fn listen<T>(&mut self, local_endpoint: T) -> Result<(), ()>
pub fn listen<T>(&mut self, local_endpoint: T) -> Result<()>
where T: Into<IpEndpoint> {
let local_endpoint = local_endpoint.into();
if self.is_open() { return Err(()) }
if local_endpoint.port == 0 { return Err(()) }
if self.is_open() { return Err(Error::Illegal) }
if local_endpoint.port == 0 { return Err(Error::Unaddressable) }
self.reset();
self.listen_address = local_endpoint.addr;
@ -379,7 +379,7 @@ impl<'a> TcpSocket<'a> {
/// This function returns an error if the socket was open; see [is_open](#method.is_open).
/// It also returns an error if the local or remote port is zero, or if the remote address
/// is unspecified.
pub fn connect<T, U>(&mut self, remote_endpoint: T, local_endpoint: U) -> Result<(), Error>
pub fn connect<T, U>(&mut self, remote_endpoint: T, local_endpoint: U) -> Result<()>
where T: Into<IpEndpoint>, U: Into<IpEndpoint> {
let remote_endpoint = remote_endpoint.into();
let local_endpoint = local_endpoint.into();
@ -565,10 +565,10 @@ impl<'a> TcpSocket<'a> {
/// there is not enough contiguous free space in the transmit buffer, down to
/// an empty slice.
///
/// This function returns an error if the transmit half of the connection is not open;
/// see [can_send](#method.can_send).
pub fn send(&mut self, size: usize) -> Result<&mut [u8], ()> {
if !self.may_send() { return Err(()) }
/// This function returns `Err(Error::Illegal) if the transmit half of
/// the connection is not open; see [may_send](#method.may_send).
pub fn send(&mut self, size: usize) -> Result<&mut [u8]> {
if !self.may_send() { return Err(Error::Illegal) }
#[cfg(any(test, feature = "verbose"))]
let old_length = self.tx_buffer.len();
@ -589,7 +589,7 @@ impl<'a> TcpSocket<'a> {
/// by the amount of free space in the transmit buffer; down to zero.
///
/// See also [send](#method.send).
pub fn send_slice(&mut self, data: &[u8]) -> Result<usize, ()> {
pub fn send_slice(&mut self, data: &[u8]) -> Result<usize> {
let buffer = self.send(data.len())?;
let data = &data[..buffer.len()];
buffer.copy_from_slice(data);
@ -601,11 +601,14 @@ impl<'a> TcpSocket<'a> {
/// This function may return a slice smaller than the requested size in case
/// there are not enough octets queued in the receive buffer, down to
/// an empty slice.
pub fn recv(&mut self, size: usize) -> Result<&[u8], ()> {
///
/// This function returns `Err(Error::Illegal) if the receive half of
/// the connection is not open; see [may_recv](#method.may_recv).
pub fn recv(&mut self, size: usize) -> Result<&[u8]> {
// We may have received some data inside the initial SYN, but until the connection
// is fully open we must not dequeue any data, as it may be overwritten by e.g.
// another (stale) SYN.
if !self.may_recv() { return Err(()) }
if !self.may_recv() { return Err(Error::Illegal) }
#[cfg(any(test, feature = "verbose"))]
let old_length = self.rx_buffer.len();
@ -626,7 +629,7 @@ impl<'a> TcpSocket<'a> {
/// by the amount of free space in the transmit buffer; down to zero.
///
/// 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> {
let buffer = self.recv(data.len())?;
let data = &mut data[..buffer.len()];
data.copy_from_slice(buffer);
@ -649,7 +652,7 @@ impl<'a> TcpSocket<'a> {
}
pub(crate) fn process(&mut self, timestamp: u64, ip_repr: &IpRepr,
payload: &[u8]) -> Result<(), Error> {
payload: &[u8]) -> Result<()> {
debug_assert!(ip_repr.protocol() == IpProtocol::Tcp);
if self.state == State::Closed { return Err(Error::Rejected) }
@ -980,8 +983,8 @@ impl<'a> TcpSocket<'a> {
}
pub(crate) fn dispatch<F, R>(&mut self, timestamp: u64, limits: &DeviceLimits,
emit: &mut F) -> Result<R, Error>
where F: FnMut(&IpRepr, &IpPayload) -> Result<R, Error> {
emit: &mut F) -> Result<R>
where F: FnMut(&IpRepr, &IpPayload) -> Result<R> {
if !self.remote_endpoint.is_specified() { return Err(Error::Exhausted) }
let mut repr = TcpRepr {
@ -1266,7 +1269,7 @@ mod test {
payload: &[]
};
fn send(socket: &mut TcpSocket, timestamp: u64, repr: &TcpRepr) -> Result<(), Error> {
fn send(socket: &mut TcpSocket, timestamp: u64, repr: &TcpRepr) -> Result<()> {
trace!("send: {}", repr);
let mut buffer = vec![0; repr.buffer_len()];
let mut packet = TcpPacket::new(&mut buffer);
@ -1281,7 +1284,7 @@ mod test {
}
fn recv<F>(socket: &mut TcpSocket, timestamp: u64, mut f: F)
where F: FnMut(Result<TcpRepr, Error>) {
where F: FnMut(Result<TcpRepr>) {
let mut buffer = vec![];
let mut limits = DeviceLimits::default();
limits.max_transmission_unit = 1520;
@ -1446,7 +1449,14 @@ mod test {
#[test]
fn test_listen_validation() {
let mut s = socket();
assert_eq!(s.listen(0), Err(()));
assert_eq!(s.listen(0), Err(Error::Unaddressable));
}
#[test]
fn test_listen_twice() {
let mut s = socket();
assert_eq!(s.listen(80), Ok(()));
assert_eq!(s.listen(80), Err(Error::Illegal));
}
#[test]

View File

@ -1,6 +1,6 @@
use managed::Managed;
use Error;
use {Error, Result};
use phy::DeviceLimits;
use wire::{IpProtocol, IpEndpoint};
use wire::{UdpPacket, UdpRepr};
@ -109,9 +109,9 @@ impl<'a, 'b> UdpSocket<'a, 'b> {
/// Enqueue a packet to be sent to a given remote endpoint, and return a pointer
/// to its payload.
///
/// This function returns `Err(())` if the size is greater than what
/// the transmit buffer can accomodate.
pub fn send(&mut self, size: usize, endpoint: IpEndpoint) -> Result<&mut [u8], ()> {
/// This function returns `Err(Error::Exhausted)` if the size is greater than
/// the transmit packet buffer size.
pub fn send(&mut self, size: usize, endpoint: IpEndpoint) -> Result<&mut [u8]> {
let packet_buf = self.tx_buffer.enqueue()?;
packet_buf.endpoint = endpoint;
packet_buf.size = size;
@ -124,7 +124,7 @@ impl<'a, 'b> UdpSocket<'a, 'b> {
/// 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], endpoint: IpEndpoint) -> Result<usize, ()> {
pub fn send_slice(&mut self, data: &[u8], endpoint: IpEndpoint) -> Result<usize> {
let buffer = self.send(data.len(), endpoint)?;
let data = &data[..buffer.len()];
buffer.copy_from_slice(data);
@ -134,8 +134,8 @@ impl<'a, 'b> UdpSocket<'a, 'b> {
/// Dequeue a packet received from a remote endpoint, and return the endpoint as well
/// as a pointer to the payload.
///
/// This function returns `Err(())` if the receive buffer is empty.
pub fn recv(&mut self) -> Result<(&[u8], IpEndpoint), ()> {
/// This function returns `Err(Error::Exhausted)` if the receive buffer is empty.
pub fn recv(&mut self) -> Result<(&[u8], IpEndpoint)> {
let packet_buf = self.rx_buffer.dequeue()?;
net_trace!("[{}]{}:{}: receive {} buffered octets",
self.debug_id, self.endpoint,
@ -147,14 +147,14 @@ impl<'a, 'b> UdpSocket<'a, 'b> {
/// as copy the payload into the given slice.
///
/// See also [recv](#method.recv).
pub fn recv_slice(&mut self, data: &mut [u8]) -> Result<(usize, IpEndpoint), ()> {
pub fn recv_slice(&mut self, data: &mut [u8]) -> Result<(usize, IpEndpoint)> {
let (buffer, endpoint) = self.recv()?;
data[..buffer.len()].copy_from_slice(buffer);
Ok((buffer.len(), endpoint))
}
pub(crate) fn process(&mut self, _timestamp: u64, ip_repr: &IpRepr,
payload: &[u8]) -> Result<(), Error> {
payload: &[u8]) -> Result<()> {
debug_assert!(ip_repr.protocol() == IpProtocol::Udp);
let packet = UdpPacket::new_checked(&payload[..ip_repr.payload_len()])?;
@ -165,7 +165,7 @@ impl<'a, 'b> UdpSocket<'a, 'b> {
if self.endpoint.addr != ip_repr.dst_addr() { return Err(Error::Rejected) }
}
let packet_buf = self.rx_buffer.enqueue().map_err(|()| Error::Exhausted)?;
let packet_buf = self.rx_buffer.enqueue()?;
packet_buf.endpoint = IpEndpoint { addr: ip_repr.src_addr(), port: repr.src_port };
packet_buf.size = repr.payload.len();
packet_buf.as_mut()[..repr.payload.len()].copy_from_slice(repr.payload);
@ -176,9 +176,9 @@ impl<'a, 'b> UdpSocket<'a, 'b> {
}
pub(crate) fn dispatch<F, R>(&mut self, _timestamp: u64, _limits: &DeviceLimits,
emit: &mut F) -> Result<R, Error>
where F: FnMut(&IpRepr, &IpPayload) -> Result<R, Error> {
let packet_buf = self.tx_buffer.dequeue().map_err(|()| Error::Exhausted)?;
emit: &mut F) -> Result<R>
where F: FnMut(&IpRepr, &IpPayload) -> Result<R> {
let packet_buf = self.tx_buffer.dequeue()?;
net_trace!("[{}]{}:{}: sending {} octets",
self.debug_id, self.endpoint,
packet_buf.endpoint, packet_buf.size);

View File

@ -1,5 +1,7 @@
use managed::Managed;
use storage::Resettable;
use {Error, Result};
use super::Resettable;
/// A ring buffer.
#[derive(Debug)]
@ -47,10 +49,10 @@ impl<'a, T: 'a> RingBuffer<'a, T> {
}
/// Enqueue an element into the buffer, and return a pointer to it, or return
/// `Err(())` if the buffer is full.
pub fn enqueue(&mut self) -> Result<&mut T, ()> {
/// `Err(Error::Exhausted)` if the buffer is full.
pub fn enqueue(&mut self) -> Result<&mut T> {
if self.full() {
Err(())
Err(Error::Exhausted)
} else {
let index = self.mask(self.read_at + self.length);
let result = &mut self.storage[index];
@ -60,10 +62,10 @@ impl<'a, T: 'a> RingBuffer<'a, T> {
}
/// Dequeue an element from the buffer, and return a mutable reference to it, or return
/// `Err(())` if the buffer is empty.
pub fn dequeue(&mut self) -> Result<&mut T, ()> {
/// `Err(Error::Exhausted)` if the buffer is empty.
pub fn dequeue(&mut self) -> Result<&mut T> {
if self.empty() {
Err(())
Err(Error::Exhausted)
} else {
self.length -= 1;
let read_at = self.read_at;
@ -95,7 +97,7 @@ mod test {
let mut ring_buffer = RingBuffer::new(&mut storage[..]);
assert!(ring_buffer.empty());
assert!(!ring_buffer.full());
assert_eq!(ring_buffer.dequeue(), Err(()));
assert_eq!(ring_buffer.dequeue(), Err(Error::Exhausted));
ring_buffer.enqueue().unwrap();
assert!(!ring_buffer.empty());
assert!(!ring_buffer.full());
@ -104,13 +106,13 @@ mod test {
assert!(!ring_buffer.empty());
}
assert!(ring_buffer.full());
assert_eq!(ring_buffer.enqueue(), Err(()));
assert_eq!(ring_buffer.enqueue(), Err(Error::Exhausted));
for i in 0..TEST_BUFFER_SIZE {
assert_eq!(*ring_buffer.dequeue().unwrap(), i);
assert!(!ring_buffer.full());
}
assert_eq!(ring_buffer.dequeue(), Err(()));
assert_eq!(ring_buffer.dequeue(), Err(Error::Exhausted));
assert!(ring_buffer.empty());
}
}

View File

@ -1,6 +1,7 @@
use core::fmt;
use byteorder::{ByteOrder, NetworkEndian};
use Error;
use {Error, Result};
pub use super::EthernetProtocol as Protocol;
@ -71,7 +72,7 @@ impl<T: AsRef<[u8]>> Packet<T> {
///
/// [new]: #method.new
/// [check_len]: #method.check_len
pub fn new_checked(buffer: T) -> Result<Packet<T>, Error> {
pub fn new_checked(buffer: T) -> Result<Packet<T>> {
let packet = Self::new(buffer);
packet.check_len()?;
Ok(packet)
@ -85,7 +86,7 @@ impl<T: AsRef<[u8]>> Packet<T> {
///
/// [set_hardware_len]: #method.set_hardware_len
/// [set_protocol_len]: #method.set_protocol_len
pub fn check_len(&self) -> Result<(), Error> {
pub fn check_len(&self) -> Result<()> {
let len = self.buffer.as_ref().len();
if len < field::OPER.end {
Err(Error::Truncated)
@ -260,8 +261,8 @@ pub enum Repr {
impl Repr {
/// Parse an Address Resolution Protocol packet and return a high-level representation,
/// or return `Err(())` if the packet is not recognized.
pub fn parse<T: AsRef<[u8]>>(packet: &Packet<T>) -> Result<Repr, Error> {
/// or return `Err(Error::Unrecognized)` if the packet is not recognized.
pub fn parse<T: AsRef<[u8]>>(packet: &Packet<T>) -> Result<Repr> {
match (packet.hardware_type(), packet.protocol_type(),
packet.hardware_len(), packet.protocol_len()) {
(Hardware::Ethernet, Protocol::Ipv4, 6, 4) => {

View File

@ -1,7 +1,7 @@
use core::fmt;
use byteorder::{ByteOrder, NetworkEndian};
use Error;
use {Error, Result};
enum_with_unknown! {
/// Ethernet protocol type.
@ -100,7 +100,7 @@ impl<T: AsRef<[u8]>> Frame<T> {
///
/// [new]: #method.new
/// [check_len]: #method.check_len
pub fn new_checked(buffer: T) -> Result<Frame<T>, Error> {
pub fn new_checked(buffer: T) -> Result<Frame<T>> {
let packet = Self::new(buffer);
packet.check_len()?;
Ok(packet)
@ -108,7 +108,7 @@ 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.
pub fn check_len(&self) -> Result<(), Error> {
pub fn check_len(&self) -> Result<()> {
let len = self.buffer.as_ref().len();
if len < field::PAYLOAD.start {
Err(Error::Truncated)

View File

@ -1,7 +1,7 @@
use core::{cmp, fmt};
use byteorder::{ByteOrder, NetworkEndian};
use Error;
use {Error, Result};
use super::ip::checksum;
use super::{Ipv4Packet, Ipv4Repr};
@ -193,7 +193,7 @@ impl<T: AsRef<[u8]>> Packet<T> {
///
/// [new]: #method.new
/// [check_len]: #method.check_len
pub fn new_checked(buffer: T) -> Result<Packet<T>, Error> {
pub fn new_checked(buffer: T) -> Result<Packet<T>> {
let packet = Self::new(buffer);
packet.check_len()?;
Ok(packet)
@ -205,7 +205,7 @@ impl<T: AsRef<[u8]>> Packet<T> {
/// The result of this check is invalidated by calling [set_header_len].
///
/// [set_header_len]: #method.set_header_len
pub fn check_len(&self) -> Result<(), Error> {
pub fn check_len(&self) -> Result<()> {
let len = self.buffer.as_ref().len();
if len < field::CHECKSUM.end {
Err(Error::Truncated)
@ -384,7 +384,7 @@ pub enum Repr<'a> {
impl<'a> Repr<'a> {
/// Parse an Internet Control Message Protocol version 4 packet and return
/// a high-level representation.
pub fn parse<T: AsRef<[u8]> + ?Sized>(packet: &Packet<&'a T>) -> Result<Repr<'a>, Error> {
pub fn parse<T: AsRef<[u8]> + ?Sized>(packet: &Packet<&'a T>) -> Result<Repr<'a>> {
match (packet.msg_type(), packet.msg_code()) {
(Message::EchoRequest, 0) => {
Ok(Repr::EchoRequest {

View File

@ -1,6 +1,6 @@
use core::fmt;
use Error;
use {Error, Result};
use super::{Ipv4Address, Ipv4Packet, Ipv4Repr};
/// Internet protocol version.
@ -205,7 +205,7 @@ impl IpRepr {
/// # Panics
/// This function panics if source and destination addresses belong to different families,
/// or the destination address is unspecified, since this indicates a logic error.
pub fn lower(&self, fallback_src_addrs: &[Address]) -> Result<IpRepr, Error> {
pub fn lower(&self, fallback_src_addrs: &[Address]) -> Result<IpRepr> {
match self {
&IpRepr::Unspecified {
src_addr: Address::Ipv4(src_addr),

View File

@ -1,7 +1,7 @@
use core::fmt;
use byteorder::{ByteOrder, NetworkEndian};
use Error;
use {Error, Result};
use super::ip::checksum;
use super::IpAddress;
@ -106,7 +106,7 @@ impl<T: AsRef<[u8]>> Packet<T> {
///
/// [new]: #method.new
/// [check_len]: #method.check_len
pub fn new_checked(buffer: T) -> Result<Packet<T>, Error> {
pub fn new_checked(buffer: T) -> Result<Packet<T>> {
let packet = Self::new(buffer);
packet.check_len()?;
Ok(packet)
@ -118,7 +118,7 @@ impl<T: AsRef<[u8]>> Packet<T> {
/// The result of this check is invalidated by calling [set_header_len].
///
/// [set_header_len]: #method.set_header_len
pub fn check_len(&self) -> Result<(), Error> {
pub fn check_len(&self) -> Result<()> {
let len = self.buffer.as_ref().len();
if len < field::DST_ADDR.end {
Err(Error::Truncated)
@ -398,7 +398,7 @@ pub struct Repr {
impl Repr {
/// Parse an Internet Protocol version 4 packet and return a high-level representation.
pub fn parse<T: AsRef<[u8]> + ?Sized>(packet: &Packet<&T>) -> Result<Repr, Error> {
pub fn parse<T: AsRef<[u8]> + ?Sized>(packet: &Packet<&T>) -> Result<Repr> {
// Version 4 is expected.
if packet.version() != 4 { return Err(Error::Malformed) }
// Valid checksum is expected.

View File

@ -1,7 +1,7 @@
use core::{i32, ops, cmp, fmt};
use byteorder::{ByteOrder, NetworkEndian};
use Error;
use {Error, Result};
use super::{IpProtocol, IpAddress};
use super::ip::checksum;
@ -110,7 +110,7 @@ impl<T: AsRef<[u8]>> Packet<T> {
///
/// [new]: #method.new
/// [check_len]: #method.check_len
pub fn new_checked(buffer: T) -> Result<Packet<T>, Error> {
pub fn new_checked(buffer: T) -> Result<Packet<T>> {
let packet = Self::new(buffer);
packet.check_len()?;
Ok(packet)
@ -124,7 +124,7 @@ impl<T: AsRef<[u8]>> Packet<T> {
/// The result of this check is invalidated by calling [set_header_len].
///
/// [set_header_len]: #method.set_header_len
pub fn check_len(&self) -> Result<(), Error> {
pub fn check_len(&self) -> Result<()> {
let len = self.buffer.as_ref().len();
if len < field::URGENT.end {
Err(Error::Truncated)
@ -519,7 +519,7 @@ pub enum TcpOption<'a> {
}
impl<'a> TcpOption<'a> {
pub fn parse(buffer: &'a [u8]) -> Result<(&'a [u8], TcpOption<'a>), Error> {
pub fn parse(buffer: &'a [u8]) -> Result<(&'a [u8], TcpOption<'a>)> {
let (length, option);
match *buffer.get(0).ok_or(Error::Truncated)? {
field::OPT_END => {
@ -627,7 +627,7 @@ impl<'a> Repr<'a> {
/// Parse a Transmission Control Protocol packet and return a high-level representation.
pub fn parse<T: ?Sized>(packet: &Packet<&'a T>,
src_addr: &IpAddress,
dst_addr: &IpAddress) -> Result<Repr<'a>, Error>
dst_addr: &IpAddress) -> Result<Repr<'a>>
where T: AsRef<[u8]> {
// Source and destination ports must be present.
if packet.src_port() == 0 { return Err(Error::Malformed) }

View File

@ -1,7 +1,7 @@
use core::fmt;
use byteorder::{ByteOrder, NetworkEndian};
use Error;
use {Error, Result};
use super::{IpProtocol, IpAddress};
use super::ip::checksum;
@ -36,7 +36,7 @@ impl<T: AsRef<[u8]>> Packet<T> {
///
/// [new]: #method.new
/// [check_len]: #method.check_len
pub fn new_checked(buffer: T) -> Result<Packet<T>, Error> {
pub fn new_checked(buffer: T) -> Result<Packet<T>> {
let packet = Self::new(buffer);
packet.check_len()?;
Ok(packet)
@ -50,7 +50,7 @@ impl<T: AsRef<[u8]>> Packet<T> {
/// The result of this check is invalidated by calling [set_len].
///
/// [set_len]: #method.set_len
pub fn check_len(&self) -> Result<(), Error> {
pub fn check_len(&self) -> Result<()> {
let buffer_len = self.buffer.as_ref().len();
if buffer_len < field::CHECKSUM.end {
Err(Error::Truncated)
@ -203,7 +203,7 @@ impl<'a> Repr<'a> {
/// Parse an User Datagram Protocol packet and return a high-level representation.
pub fn parse<T: ?Sized>(packet: &Packet<&'a T>,
src_addr: &IpAddress,
dst_addr: &IpAddress) -> Result<Repr<'a>, Error>
dst_addr: &IpAddress) -> Result<Repr<'a>>
where T: AsRef<[u8]> {
// Destination port cannot be omitted (but source port can be).
if packet.dst_port() == 0 { return Err(Error::Malformed) }