2017-07-27 22:53:06 +08:00
|
|
|
use core::cmp::min;
|
2017-01-10 19:04:00 +08:00
|
|
|
use managed::Managed;
|
|
|
|
|
2017-07-27 21:51:02 +08:00
|
|
|
use {Error, Result};
|
2017-03-07 18:56:48 +08:00
|
|
|
use phy::DeviceLimits;
|
2016-12-26 18:06:49 +08:00
|
|
|
use wire::{IpProtocol, IpEndpoint};
|
2016-12-15 13:15:00 +08:00
|
|
|
use wire::{UdpPacket, UdpRepr};
|
2016-12-26 18:06:49 +08:00
|
|
|
use socket::{Socket, IpRepr, IpPayload};
|
2017-06-18 18:11:21 +08:00
|
|
|
use storage::{Resettable, RingBuffer};
|
2016-12-15 01:39:44 +08:00
|
|
|
|
2016-12-16 01:07:56 +08:00
|
|
|
/// A buffered UDP packet.
|
2016-12-17 12:15:12 +08:00
|
|
|
#[derive(Debug)]
|
2016-12-20 21:56:59 +08:00
|
|
|
pub struct PacketBuffer<'a> {
|
2016-12-20 21:54:11 +08:00
|
|
|
endpoint: IpEndpoint,
|
2016-12-16 01:07:56 +08:00
|
|
|
size: usize,
|
2016-12-17 12:15:12 +08:00
|
|
|
payload: Managed<'a, [u8]>
|
2016-12-16 01:07:56 +08:00
|
|
|
}
|
2016-12-15 01:39:44 +08:00
|
|
|
|
2016-12-20 21:56:59 +08:00
|
|
|
impl<'a> PacketBuffer<'a> {
|
2016-12-16 01:07:56 +08:00
|
|
|
/// Create a buffered packet.
|
2016-12-20 21:56:59 +08:00
|
|
|
pub fn new<T>(payload: T) -> PacketBuffer<'a>
|
2016-12-17 12:15:12 +08:00
|
|
|
where T: Into<Managed<'a, [u8]>> {
|
2016-12-20 21:56:59 +08:00
|
|
|
PacketBuffer {
|
2016-12-28 08:12:15 +08:00
|
|
|
endpoint: IpEndpoint::default(),
|
2016-12-16 01:07:56 +08:00
|
|
|
size: 0,
|
2016-12-17 12:15:12 +08:00
|
|
|
payload: payload.into()
|
2016-12-16 01:07:56 +08:00
|
|
|
}
|
|
|
|
}
|
2016-12-17 13:12:45 +08:00
|
|
|
|
|
|
|
fn as_ref<'b>(&'b self) -> &'b [u8] {
|
|
|
|
&self.payload[..self.size]
|
|
|
|
}
|
|
|
|
|
|
|
|
fn as_mut<'b>(&'b mut self) -> &'b mut [u8] {
|
|
|
|
&mut self.payload[..self.size]
|
|
|
|
}
|
2017-07-27 22:53:06 +08:00
|
|
|
|
|
|
|
fn resize<'b>(&'b mut self, size: usize) -> Result<&'b mut Self> {
|
|
|
|
if self.payload.len() >= size {
|
|
|
|
self.size = size;
|
|
|
|
Ok(self)
|
|
|
|
} else {
|
|
|
|
Err(Error::Truncated)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> Resettable for PacketBuffer<'a> {
|
|
|
|
fn reset(&mut self) {
|
|
|
|
self.endpoint = Default::default();
|
|
|
|
self.size = 0;
|
|
|
|
}
|
2016-12-15 01:39:44 +08:00
|
|
|
}
|
|
|
|
|
2016-12-19 03:40:11 +08:00
|
|
|
/// An UDP packet ring buffer.
|
2017-06-18 18:11:21 +08:00
|
|
|
pub type SocketBuffer<'a, 'b : 'a> = RingBuffer<'a, PacketBuffer<'b>>;
|
2016-12-15 01:39:44 +08:00
|
|
|
|
|
|
|
/// An User Datagram Protocol socket.
|
2016-12-15 13:15:00 +08:00
|
|
|
///
|
|
|
|
/// An UDP socket is bound to a specific endpoint, and owns transmit and receive
|
|
|
|
/// packet buffers.
|
2017-01-12 12:28:34 +08:00
|
|
|
#[derive(Debug)]
|
2016-12-17 14:27:08 +08:00
|
|
|
pub struct UdpSocket<'a, 'b: 'a> {
|
2017-07-28 06:55:30 +08:00
|
|
|
debug_id: usize,
|
2016-12-20 21:54:11 +08:00
|
|
|
endpoint: IpEndpoint,
|
2016-12-20 21:56:59 +08:00
|
|
|
rx_buffer: SocketBuffer<'a, 'b>,
|
2017-01-17 07:35:21 +08:00
|
|
|
tx_buffer: SocketBuffer<'a, 'b>,
|
2016-12-15 01:39:44 +08:00
|
|
|
}
|
|
|
|
|
2016-12-17 14:27:08 +08:00
|
|
|
impl<'a, 'b> UdpSocket<'a, 'b> {
|
2016-12-15 01:39:44 +08:00
|
|
|
/// Create an UDP socket with the given buffers.
|
2017-01-11 13:25:54 +08:00
|
|
|
pub fn new(rx_buffer: SocketBuffer<'a, 'b>,
|
|
|
|
tx_buffer: SocketBuffer<'a, 'b>) -> Socket<'a, 'b> {
|
2016-12-23 15:30:57 +08:00
|
|
|
Socket::Udp(UdpSocket {
|
2017-07-28 06:55:30 +08:00
|
|
|
debug_id: 0,
|
2017-01-11 12:44:42 +08:00
|
|
|
endpoint: IpEndpoint::default(),
|
2016-12-15 01:39:44 +08:00
|
|
|
rx_buffer: rx_buffer,
|
2017-01-17 07:35:21 +08:00
|
|
|
tx_buffer: tx_buffer,
|
2016-12-17 13:12:45 +08:00
|
|
|
})
|
2016-12-15 01:39:44 +08:00
|
|
|
}
|
|
|
|
|
2017-01-17 07:35:21 +08:00
|
|
|
/// Return the debug identifier.
|
2017-07-05 02:46:36 +08:00
|
|
|
#[inline]
|
2017-01-17 07:35:21 +08:00
|
|
|
pub fn debug_id(&self) -> usize {
|
|
|
|
self.debug_id
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Set the debug identifier.
|
|
|
|
///
|
|
|
|
/// The debug identifier is a number printed in socket trace messages.
|
|
|
|
/// It could as well be used by the user code.
|
|
|
|
pub fn set_debug_id(&mut self, id: usize) {
|
|
|
|
self.debug_id = id
|
|
|
|
}
|
|
|
|
|
2017-01-11 12:44:42 +08:00
|
|
|
/// Return the bound endpoint.
|
|
|
|
#[inline]
|
|
|
|
pub fn endpoint(&self) -> IpEndpoint {
|
|
|
|
self.endpoint
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Bind the socket to the given endpoint.
|
2017-07-27 22:53:06 +08:00
|
|
|
///
|
2017-07-30 09:17:48 +08:00
|
|
|
/// 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.
|
2017-07-27 22:53:06 +08:00
|
|
|
pub fn bind<T: Into<IpEndpoint>>(&mut self, endpoint: T) -> Result<()> {
|
|
|
|
let endpoint = endpoint.into();
|
|
|
|
if endpoint.port == 0 { return Err(Error::Unaddressable) }
|
|
|
|
|
2017-07-30 09:17:48 +08:00
|
|
|
if self.is_open() { return Err(Error::Illegal) }
|
2017-07-27 22:53:06 +08:00
|
|
|
|
|
|
|
self.endpoint = endpoint;
|
|
|
|
Ok(())
|
2017-01-11 12:44:42 +08:00
|
|
|
}
|
|
|
|
|
2017-07-30 09:17:48 +08:00
|
|
|
/// Check whether the socket is open.
|
|
|
|
#[inline]
|
|
|
|
pub fn is_open(&self) -> bool {
|
|
|
|
self.endpoint.port != 0
|
|
|
|
}
|
|
|
|
|
2017-01-11 14:33:51 +08:00
|
|
|
/// Check whether the transmit buffer is full.
|
2017-07-05 02:46:36 +08:00
|
|
|
#[inline]
|
2017-01-11 14:33:51 +08:00
|
|
|
pub fn can_send(&self) -> bool {
|
|
|
|
!self.tx_buffer.full()
|
|
|
|
}
|
|
|
|
|
2017-01-14 14:51:29 +08:00
|
|
|
/// Check whether the receive buffer is not empty.
|
2017-07-05 02:46:36 +08:00
|
|
|
#[inline]
|
2017-01-14 14:51:29 +08:00
|
|
|
pub fn can_recv(&self) -> bool {
|
|
|
|
!self.rx_buffer.empty()
|
|
|
|
}
|
|
|
|
|
2016-12-16 01:07:56 +08:00
|
|
|
/// Enqueue a packet to be sent to a given remote endpoint, and return a pointer
|
|
|
|
/// to its payload.
|
2016-12-15 01:39:44 +08:00
|
|
|
///
|
2017-07-27 22:53:06 +08:00
|
|
|
/// 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 local or remote port, or remote address,
|
|
|
|
/// are unspecified.
|
2017-07-27 21:51:02 +08:00
|
|
|
pub fn send(&mut self, size: usize, endpoint: IpEndpoint) -> Result<&mut [u8]> {
|
2017-07-27 22:53:06 +08:00
|
|
|
if self.endpoint.port == 0 { return Err(Error::Unaddressable) }
|
|
|
|
if !endpoint.is_specified() { return Err(Error::Unaddressable) }
|
|
|
|
|
|
|
|
let packet_buf = self.tx_buffer.try_enqueue(|buf| buf.resize(size))?;
|
2016-12-16 01:07:56 +08:00
|
|
|
packet_buf.endpoint = endpoint;
|
2017-01-17 07:35:21 +08:00
|
|
|
net_trace!("[{}]{}:{}: buffer to send {} octets",
|
2017-07-27 22:53:06 +08:00
|
|
|
self.debug_id, self.endpoint, packet_buf.endpoint, size);
|
2016-12-17 13:12:45 +08:00
|
|
|
Ok(&mut packet_buf.as_mut()[..size])
|
|
|
|
}
|
|
|
|
|
2016-12-26 22:50:12 +08:00
|
|
|
/// Enqueue a packet to be sent to a given remote endpoint, and fill it from a slice.
|
2016-12-17 13:12:45 +08:00
|
|
|
///
|
|
|
|
/// See also [send](#method.send).
|
2017-07-29 16:19:32 +08:00
|
|
|
pub fn send_slice(&mut self, data: &[u8], endpoint: IpEndpoint) -> Result<()> {
|
2017-07-27 22:53:06 +08:00
|
|
|
self.send(data.len(), endpoint)?.copy_from_slice(data);
|
2017-07-29 16:19:32 +08:00
|
|
|
Ok(())
|
2016-12-15 01:39:44 +08:00
|
|
|
}
|
|
|
|
|
2016-12-16 01:07:56 +08:00
|
|
|
/// Dequeue a packet received from a remote endpoint, and return the endpoint as well
|
|
|
|
/// as a pointer to the payload.
|
2016-12-15 01:39:44 +08:00
|
|
|
///
|
2017-07-27 21:51:02 +08:00
|
|
|
/// This function returns `Err(Error::Exhausted)` if the receive buffer is empty.
|
|
|
|
pub fn recv(&mut self) -> Result<(&[u8], IpEndpoint)> {
|
2017-06-25 00:34:32 +08:00
|
|
|
let packet_buf = self.rx_buffer.dequeue()?;
|
2017-01-17 07:35:21 +08:00
|
|
|
net_trace!("[{}]{}:{}: receive {} buffered octets",
|
|
|
|
self.debug_id, self.endpoint,
|
|
|
|
packet_buf.endpoint, packet_buf.size);
|
2017-07-27 22:53:06 +08:00
|
|
|
Ok((&packet_buf.as_ref(), packet_buf.endpoint))
|
2016-12-17 13:12:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Dequeue a packet received from a remote endpoint, and return the endpoint as well
|
|
|
|
/// as copy the payload into the given slice.
|
|
|
|
///
|
2017-01-12 12:18:18 +08:00
|
|
|
/// See also [recv](#method.recv).
|
2017-07-27 21:51:02 +08:00
|
|
|
pub fn recv_slice(&mut self, data: &mut [u8]) -> Result<(usize, IpEndpoint)> {
|
2017-06-25 00:34:32 +08:00
|
|
|
let (buffer, endpoint) = self.recv()?;
|
2017-07-27 22:53:06 +08:00
|
|
|
let length = min(data.len(), buffer.len());
|
|
|
|
data[..length].copy_from_slice(&buffer[..length]);
|
|
|
|
Ok((length, endpoint))
|
2016-12-15 01:39:44 +08:00
|
|
|
}
|
2016-12-15 13:15:00 +08:00
|
|
|
|
2017-07-01 04:54:58 +08:00
|
|
|
pub(crate) fn process(&mut self, _timestamp: u64, ip_repr: &IpRepr,
|
2017-07-27 21:51:02 +08:00
|
|
|
payload: &[u8]) -> Result<()> {
|
2017-07-01 03:17:14 +08:00
|
|
|
debug_assert!(ip_repr.protocol() == IpProtocol::Udp);
|
2016-12-15 13:15:00 +08:00
|
|
|
|
2017-06-25 00:34:32 +08:00
|
|
|
let packet = UdpPacket::new_checked(&payload[..ip_repr.payload_len()])?;
|
|
|
|
let repr = UdpRepr::parse(&packet, &ip_repr.src_addr(), &ip_repr.dst_addr())?;
|
2016-12-15 01:39:44 +08:00
|
|
|
|
2017-07-27 22:53:06 +08:00
|
|
|
let endpoint = IpEndpoint { addr: ip_repr.src_addr(), port: repr.src_port };
|
|
|
|
if !self.endpoint.accepts(&endpoint) { return Err(Error::Rejected) }
|
2016-12-15 13:15:00 +08:00
|
|
|
|
2017-07-27 22:53:06 +08:00
|
|
|
let packet_buf = self.rx_buffer.try_enqueue(|buf| buf.resize(repr.payload.len()))?;
|
|
|
|
packet_buf.as_mut().copy_from_slice(repr.payload);
|
|
|
|
packet_buf.endpoint = endpoint;
|
2017-01-17 07:35:21 +08:00
|
|
|
net_trace!("[{}]{}:{}: receiving {} octets",
|
|
|
|
self.debug_id, self.endpoint,
|
|
|
|
packet_buf.endpoint, packet_buf.size);
|
2016-12-16 01:07:56 +08:00
|
|
|
Ok(())
|
2016-12-15 01:39:44 +08:00
|
|
|
}
|
|
|
|
|
2017-07-01 04:54:58 +08:00
|
|
|
pub(crate) fn dispatch<F, R>(&mut self, _timestamp: u64, _limits: &DeviceLimits,
|
2017-07-27 21:51:02 +08:00
|
|
|
emit: &mut F) -> Result<R>
|
|
|
|
where F: FnMut(&IpRepr, &IpPayload) -> Result<R> {
|
|
|
|
let packet_buf = self.tx_buffer.dequeue()?;
|
2017-01-17 07:35:21 +08:00
|
|
|
net_trace!("[{}]{}:{}: sending {} octets",
|
|
|
|
self.debug_id, self.endpoint,
|
|
|
|
packet_buf.endpoint, packet_buf.size);
|
2017-07-27 22:53:06 +08:00
|
|
|
|
2017-01-14 19:07:06 +08:00
|
|
|
let repr = UdpRepr {
|
2016-12-26 19:20:20 +08:00
|
|
|
src_port: self.endpoint.port,
|
|
|
|
dst_port: packet_buf.endpoint.port,
|
|
|
|
payload: &packet_buf.as_ref()[..]
|
|
|
|
};
|
2017-01-14 19:07:06 +08:00
|
|
|
let ip_repr = IpRepr::Unspecified {
|
|
|
|
src_addr: self.endpoint.addr,
|
|
|
|
dst_addr: packet_buf.endpoint.addr,
|
|
|
|
protocol: IpProtocol::Udp,
|
|
|
|
payload_len: repr.buffer_len()
|
|
|
|
};
|
|
|
|
emit(&ip_repr, &repr)
|
2016-12-15 01:39:44 +08:00
|
|
|
}
|
|
|
|
}
|
2016-12-15 13:15:00 +08:00
|
|
|
|
2016-12-26 18:06:49 +08:00
|
|
|
impl<'a> IpPayload for UdpRepr<'a> {
|
2016-12-20 07:50:04 +08:00
|
|
|
fn buffer_len(&self) -> usize {
|
|
|
|
self.buffer_len()
|
2016-12-15 13:15:00 +08:00
|
|
|
}
|
|
|
|
|
2016-12-26 19:20:20 +08:00
|
|
|
fn emit(&self, repr: &IpRepr, payload: &mut [u8]) {
|
Do not attempt to validate length of packets being emitted.
This is a form of an uninitialized read bug; although safe it caused
panics. In short, transmit buffers received from the network stack
should be considered uninitialized (in practice they will often
contain previously transmitted packets or parts thereof). Wrapping
them with the only method we had (e.g. Ipv4Packet) treated the buffer
as if it contained a valid incoming packet, which can easily fail
with Error::Truncated.
This commit splits every `fn new(buffer: T) -> Result<Self, Error>`
method on a `Packet` into three smaller ones:
* `fn check_len(&self) -> Result<(), Error>`, purely a validator;
* `fn new(T) -> Self`, purely a wrapper;
* `fn new_checked(T) -> Result<Self, Error>`, a validating wrapper.
This makes it easy to process ingress packets (using `new_checked`),
egress packets (using `new`), and, if needed, maintain the invariants
at any point during packet construction (using `check_len`).
Fixes #17.
2017-06-24 17:15:22 +08:00
|
|
|
let mut packet = UdpPacket::new(payload);
|
2016-12-26 19:20:20 +08:00
|
|
|
self.emit(&mut packet, &repr.src_addr(), &repr.dst_addr())
|
2016-12-15 13:15:00 +08:00
|
|
|
}
|
|
|
|
}
|
2017-07-27 22:53:06 +08:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
|
|
|
use std::vec::Vec;
|
|
|
|
use wire::{IpAddress, Ipv4Address, IpRepr, Ipv4Repr, UdpRepr};
|
|
|
|
use socket::AsSocket;
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
fn buffer(packets: usize) -> SocketBuffer<'static, 'static> {
|
|
|
|
let mut storage = vec![];
|
|
|
|
for _ in 0..packets {
|
|
|
|
storage.push(PacketBuffer::new(vec![0; 16]))
|
|
|
|
}
|
|
|
|
SocketBuffer::new(storage)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn socket(rx_buffer: SocketBuffer<'static, 'static>,
|
|
|
|
tx_buffer: SocketBuffer<'static, 'static>)
|
|
|
|
-> UdpSocket<'static, 'static> {
|
|
|
|
match UdpSocket::new(rx_buffer, tx_buffer) {
|
|
|
|
Socket::Udp(socket) => socket,
|
|
|
|
_ => unreachable!()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const LOCAL_IP: IpAddress = IpAddress::Ipv4(Ipv4Address([10, 0, 0, 1]));
|
|
|
|
const REMOTE_IP: IpAddress = IpAddress::Ipv4(Ipv4Address([10, 0, 0, 2]));
|
|
|
|
const LOCAL_PORT: u16 = 53;
|
|
|
|
const REMOTE_PORT: u16 = 49500;
|
|
|
|
const LOCAL_END: IpEndpoint = IpEndpoint { addr: LOCAL_IP, port: LOCAL_PORT };
|
|
|
|
const REMOTE_END: IpEndpoint = IpEndpoint { addr: REMOTE_IP, port: REMOTE_PORT };
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_bind_unaddressable() {
|
|
|
|
let mut socket = socket(buffer(0), buffer(0));
|
|
|
|
assert_eq!(socket.bind(0), Err(Error::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));
|
|
|
|
}
|
|
|
|
|
|
|
|
const LOCAL_IP_REPR: IpRepr = IpRepr::Unspecified {
|
|
|
|
src_addr: LOCAL_IP,
|
|
|
|
dst_addr: REMOTE_IP,
|
|
|
|
protocol: IpProtocol::Udp,
|
|
|
|
payload_len: 8 + 6
|
|
|
|
};
|
|
|
|
const LOCAL_UDP_REPR: UdpRepr = UdpRepr {
|
|
|
|
src_port: LOCAL_PORT,
|
|
|
|
dst_port: REMOTE_PORT,
|
|
|
|
payload: b"abcdef"
|
|
|
|
};
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_send_unaddressable() {
|
|
|
|
let mut socket = socket(buffer(0), buffer(1));
|
|
|
|
assert_eq!(socket.send_slice(b"abcdef", REMOTE_END), Err(Error::Unaddressable));
|
|
|
|
socket.bind(LOCAL_PORT);
|
|
|
|
assert_eq!(socket.send_slice(b"abcdef",
|
|
|
|
IpEndpoint { addr: IpAddress::Unspecified, ..REMOTE_END }),
|
|
|
|
Err(Error::Unaddressable));
|
|
|
|
assert_eq!(socket.send_slice(b"abcdef",
|
|
|
|
IpEndpoint { port: 0, ..REMOTE_END }),
|
|
|
|
Err(Error::Unaddressable));
|
2017-07-29 16:19:32 +08:00
|
|
|
assert_eq!(socket.send_slice(b"abcdef", REMOTE_END), Ok(()));
|
2017-07-27 22:53:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_send_truncated() {
|
|
|
|
let mut socket = socket(buffer(0), buffer(1));
|
|
|
|
socket.bind(LOCAL_END);
|
|
|
|
assert_eq!(socket.send_slice(&[0; 32][..], REMOTE_END), Err(Error::Truncated));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_send_dispatch() {
|
|
|
|
let limits = DeviceLimits::default();
|
|
|
|
|
|
|
|
let mut socket = socket(buffer(0), buffer(1));
|
|
|
|
socket.bind(LOCAL_END);
|
|
|
|
|
|
|
|
assert!(socket.can_send());
|
|
|
|
assert_eq!(socket.dispatch(0, &limits, &mut |ip_repr, ip_payload| {
|
|
|
|
unreachable!()
|
|
|
|
}), Err(Error::Exhausted) as Result<()>);
|
|
|
|
|
2017-07-29 16:19:32 +08:00
|
|
|
assert_eq!(socket.send_slice(b"abcdef", REMOTE_END), Ok(()));
|
2017-07-27 22:53:06 +08:00
|
|
|
assert_eq!(socket.send_slice(b"123456", REMOTE_END), Err(Error::Exhausted));
|
|
|
|
assert!(!socket.can_send());
|
|
|
|
|
|
|
|
macro_rules! assert_payload_eq {
|
|
|
|
($ip_repr:expr, $ip_payload:expr, $expected:expr) => {{
|
|
|
|
let mut buffer = vec![0; $ip_payload.buffer_len()];
|
|
|
|
$ip_payload.emit($ip_repr, &mut buffer);
|
|
|
|
let udp_packet = UdpPacket::new_checked(&buffer).unwrap();
|
|
|
|
let udp_repr = UdpRepr::parse(&udp_packet, &LOCAL_IP, &REMOTE_IP).unwrap();
|
|
|
|
assert_eq!(&udp_repr, $expected)
|
|
|
|
}}
|
|
|
|
}
|
|
|
|
|
|
|
|
assert_eq!(socket.dispatch(0, &limits, &mut |ip_repr, ip_payload| {
|
|
|
|
assert_eq!(ip_repr, &LOCAL_IP_REPR);
|
|
|
|
assert_payload_eq!(ip_repr, ip_payload, &LOCAL_UDP_REPR);
|
|
|
|
Err(Error::Unaddressable)
|
|
|
|
}), Err(Error::Unaddressable) as Result<()>);
|
|
|
|
/*assert!(!socket.can_send());*/
|
|
|
|
|
|
|
|
assert_eq!(socket.dispatch(0, &limits, &mut |ip_repr, ip_payload| {
|
|
|
|
assert_eq!(ip_repr, &LOCAL_IP_REPR);
|
|
|
|
assert_payload_eq!(ip_repr, ip_payload, &LOCAL_UDP_REPR);
|
|
|
|
Ok(())
|
|
|
|
}), /*Ok(())*/ Err(Error::Exhausted));
|
|
|
|
assert!(socket.can_send());
|
|
|
|
}
|
|
|
|
|
|
|
|
const REMOTE_IP_REPR: IpRepr = IpRepr::Ipv4(Ipv4Repr {
|
|
|
|
src_addr: Ipv4Address([10, 0, 0, 2]),
|
|
|
|
dst_addr: Ipv4Address([10, 0, 0, 1]),
|
|
|
|
protocol: IpProtocol::Udp,
|
|
|
|
payload_len: 8 + 6
|
|
|
|
});
|
|
|
|
const REMOTE_UDP_REPR: UdpRepr = UdpRepr {
|
|
|
|
src_port: REMOTE_PORT,
|
|
|
|
dst_port: LOCAL_PORT,
|
|
|
|
payload: b"abcdef"
|
|
|
|
};
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_recv_process() {
|
|
|
|
let mut socket = socket(buffer(1), buffer(0));
|
|
|
|
socket.bind(LOCAL_PORT);
|
|
|
|
assert!(!socket.can_recv());
|
|
|
|
|
|
|
|
let mut buffer = vec![0; REMOTE_UDP_REPR.buffer_len()];
|
|
|
|
REMOTE_UDP_REPR.emit(&mut UdpPacket::new(&mut buffer), &LOCAL_IP, &REMOTE_IP);
|
|
|
|
|
|
|
|
assert_eq!(socket.recv(), Err(Error::Exhausted));
|
|
|
|
assert_eq!(socket.process(0, &REMOTE_IP_REPR, &buffer),
|
|
|
|
Ok(()));
|
|
|
|
assert!(socket.can_recv());
|
|
|
|
|
|
|
|
assert_eq!(socket.process(0, &REMOTE_IP_REPR, &buffer),
|
|
|
|
Err(Error::Exhausted));
|
|
|
|
assert_eq!(socket.recv(), Ok((&b"abcdef"[..], REMOTE_END)));
|
|
|
|
assert!(!socket.can_recv());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_recv_truncated_slice() {
|
|
|
|
let mut socket = socket(buffer(1), buffer(0));
|
|
|
|
socket.bind(LOCAL_PORT);
|
|
|
|
|
|
|
|
let mut buffer = vec![0; REMOTE_UDP_REPR.buffer_len()];
|
|
|
|
REMOTE_UDP_REPR.emit(&mut UdpPacket::new(&mut buffer), &LOCAL_IP, &REMOTE_IP);
|
|
|
|
assert_eq!(socket.process(0, &REMOTE_IP_REPR, &buffer), Ok(()));
|
|
|
|
|
|
|
|
let mut slice = [0; 4];
|
|
|
|
assert_eq!(socket.recv_slice(&mut slice[..]), Ok((4, REMOTE_END)));
|
|
|
|
assert_eq!(&slice, b"abcd");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_recv_truncated_packet() {
|
|
|
|
let mut socket = socket(buffer(1), buffer(0));
|
|
|
|
socket.bind(LOCAL_PORT);
|
|
|
|
|
|
|
|
let udp_repr = UdpRepr { payload: &[0; 100][..], ..REMOTE_UDP_REPR };
|
|
|
|
let mut buffer = vec![0; udp_repr.buffer_len()];
|
|
|
|
udp_repr.emit(&mut UdpPacket::new(&mut buffer), &LOCAL_IP, &REMOTE_IP);
|
|
|
|
assert_eq!(socket.process(0, &REMOTE_IP_REPR, &buffer),
|
|
|
|
Err(Error::Truncated));
|
|
|
|
}
|
|
|
|
}
|