2017-01-10 19:04:00 +08:00
|
|
|
use managed::Managed;
|
|
|
|
|
2016-12-15 01:39:44 +08:00
|
|
|
use Error;
|
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
|
|
|
|
2017-06-18 18:11:21 +08:00
|
|
|
impl<'a> Resettable for PacketBuffer<'a> {
|
|
|
|
fn reset(&mut self) {
|
|
|
|
self.endpoint = Default::default();
|
|
|
|
self.size = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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]
|
|
|
|
}
|
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> {
|
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>,
|
|
|
|
debug_id: usize
|
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-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,
|
|
|
|
debug_id: 0
|
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.
|
|
|
|
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.
|
|
|
|
pub fn bind<T: Into<IpEndpoint>>(&mut self, endpoint: T) {
|
|
|
|
self.endpoint = endpoint.into()
|
|
|
|
}
|
|
|
|
|
2017-01-11 14:33:51 +08:00
|
|
|
/// Check whether the transmit buffer is full.
|
|
|
|
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.
|
|
|
|
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-01-12 12:18:18 +08:00
|
|
|
/// This function returns `Err(())` if the size is greater than what
|
2016-12-16 01:07:56 +08:00
|
|
|
/// the transmit buffer can accomodate.
|
2017-01-12 12:18:18 +08:00
|
|
|
pub fn send(&mut self, size: usize, endpoint: IpEndpoint) -> Result<&mut [u8], ()> {
|
2016-12-16 01:07:56 +08:00
|
|
|
let packet_buf = try!(self.tx_buffer.enqueue());
|
|
|
|
packet_buf.endpoint = endpoint;
|
|
|
|
packet_buf.size = size;
|
2017-01-17 07:35:21 +08:00
|
|
|
net_trace!("[{}]{}:{}: buffer to send {} octets",
|
|
|
|
self.debug_id, self.endpoint,
|
|
|
|
packet_buf.endpoint, packet_buf.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-01-12 12:18:18 +08:00
|
|
|
pub fn send_slice(&mut self, data: &[u8], endpoint: IpEndpoint) -> Result<usize, ()> {
|
2017-01-11 14:23:17 +08:00
|
|
|
let buffer = try!(self.send(data.len(), endpoint));
|
2017-01-11 14:37:00 +08:00
|
|
|
let data = &data[..buffer.len()];
|
|
|
|
buffer.copy_from_slice(data);
|
|
|
|
Ok(data.len())
|
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-01-12 12:18:18 +08:00
|
|
|
/// This function returns `Err(())` if the receive buffer is empty.
|
|
|
|
pub fn recv(&mut self) -> Result<(&[u8], IpEndpoint), ()> {
|
2016-12-16 01:07:56 +08:00
|
|
|
let packet_buf = try!(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-01-11 14:23:17 +08:00
|
|
|
Ok((&packet_buf.as_ref()[..packet_buf.size], 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).
|
|
|
|
pub fn recv_slice(&mut self, data: &mut [u8]) -> Result<(usize, IpEndpoint), ()> {
|
2017-01-11 14:23:17 +08:00
|
|
|
let (buffer, endpoint) = try!(self.recv());
|
2016-12-17 13:12:45 +08:00
|
|
|
data[..buffer.len()].copy_from_slice(buffer);
|
2017-01-11 14:23:17 +08:00
|
|
|
Ok((buffer.len(), endpoint))
|
2016-12-15 01:39:44 +08:00
|
|
|
}
|
2016-12-15 13:15:00 +08:00
|
|
|
|
2016-12-28 01:49:40 +08:00
|
|
|
/// See [Socket::process](enum.Socket.html#method.process).
|
2016-12-31 16:35:07 +08:00
|
|
|
pub fn process(&mut self, _timestamp: u64, ip_repr: &IpRepr,
|
|
|
|
payload: &[u8]) -> Result<(), Error> {
|
2016-12-26 19:20:20 +08:00
|
|
|
if ip_repr.protocol() != IpProtocol::Udp { return Err(Error::Rejected) }
|
2016-12-15 13:15:00 +08:00
|
|
|
|
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 packet = try!(UdpPacket::new_checked(&payload[..ip_repr.payload_len()]));
|
2016-12-26 19:20:20 +08:00
|
|
|
let repr = try!(UdpRepr::parse(&packet, &ip_repr.src_addr(), &ip_repr.dst_addr()));
|
2016-12-15 01:39:44 +08:00
|
|
|
|
|
|
|
if repr.dst_port != self.endpoint.port { return Err(Error::Rejected) }
|
|
|
|
if !self.endpoint.addr.is_unspecified() {
|
2016-12-26 19:20:20 +08:00
|
|
|
if self.endpoint.addr != ip_repr.dst_addr() { return Err(Error::Rejected) }
|
2016-12-15 01:39:44 +08:00
|
|
|
}
|
2016-12-15 13:15:00 +08:00
|
|
|
|
2017-01-12 12:18:18 +08:00
|
|
|
let packet_buf = try!(self.rx_buffer.enqueue().map_err(|()| Error::Exhausted));
|
2016-12-26 19:20:20 +08:00
|
|
|
packet_buf.endpoint = IpEndpoint { addr: ip_repr.src_addr(), port: repr.src_port };
|
2016-12-16 01:07:56 +08:00
|
|
|
packet_buf.size = repr.payload.len();
|
2016-12-17 13:12:45 +08:00
|
|
|
packet_buf.as_mut()[..repr.payload.len()].copy_from_slice(repr.payload);
|
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
|
|
|
}
|
|
|
|
|
2016-12-17 13:12:45 +08:00
|
|
|
/// See [Socket::dispatch](enum.Socket.html#method.dispatch).
|
2017-03-07 18:56:48 +08:00
|
|
|
pub fn dispatch<F, R>(&mut self, _timestamp: u64, _limits: &DeviceLimits,
|
2017-01-27 10:49:06 +08:00
|
|
|
emit: &mut F) -> Result<R, Error>
|
2016-12-26 20:38:40 +08:00
|
|
|
where F: FnMut(&IpRepr, &IpPayload) -> Result<R, Error> {
|
2017-01-12 12:18:18 +08:00
|
|
|
let packet_buf = try!(self.tx_buffer.dequeue().map_err(|()| Error::Exhausted));
|
2017-01-17 07:35:21 +08:00
|
|
|
net_trace!("[{}]{}:{}: sending {} octets",
|
|
|
|
self.debug_id, self.endpoint,
|
|
|
|
packet_buf.endpoint, packet_buf.size);
|
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
|
|
|
}
|
|
|
|
}
|
2016-12-16 01:07:56 +08:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
pub fn test_buffer() {
|
|
|
|
let mut storage = vec![];
|
|
|
|
for _ in 0..5 {
|
2016-12-20 21:56:59 +08:00
|
|
|
storage.push(PacketBuffer::new(vec![0]))
|
2016-12-16 01:07:56 +08:00
|
|
|
}
|
2016-12-20 21:56:59 +08:00
|
|
|
let mut buffer = SocketBuffer::new(&mut storage[..]);
|
2016-12-16 01:07:56 +08:00
|
|
|
|
|
|
|
assert_eq!(buffer.empty(), true);
|
|
|
|
assert_eq!(buffer.full(), false);
|
|
|
|
buffer.enqueue().unwrap().size = 1;
|
|
|
|
assert_eq!(buffer.empty(), false);
|
|
|
|
assert_eq!(buffer.full(), false);
|
|
|
|
buffer.enqueue().unwrap().size = 2;
|
|
|
|
buffer.enqueue().unwrap().size = 3;
|
|
|
|
assert_eq!(buffer.dequeue().unwrap().size, 1);
|
|
|
|
assert_eq!(buffer.dequeue().unwrap().size, 2);
|
|
|
|
buffer.enqueue().unwrap().size = 4;
|
|
|
|
buffer.enqueue().unwrap().size = 5;
|
|
|
|
buffer.enqueue().unwrap().size = 6;
|
|
|
|
buffer.enqueue().unwrap().size = 7;
|
2017-01-12 12:18:18 +08:00
|
|
|
assert_eq!(buffer.enqueue().unwrap_err(), ());
|
2016-12-16 01:07:56 +08:00
|
|
|
assert_eq!(buffer.empty(), false);
|
|
|
|
assert_eq!(buffer.full(), true);
|
|
|
|
assert_eq!(buffer.dequeue().unwrap().size, 3);
|
|
|
|
assert_eq!(buffer.dequeue().unwrap().size, 4);
|
|
|
|
assert_eq!(buffer.dequeue().unwrap().size, 5);
|
|
|
|
assert_eq!(buffer.dequeue().unwrap().size, 6);
|
|
|
|
assert_eq!(buffer.dequeue().unwrap().size, 7);
|
2017-01-12 12:18:18 +08:00
|
|
|
assert_eq!(buffer.dequeue().unwrap_err(), ());
|
2016-12-16 01:07:56 +08:00
|
|
|
assert_eq!(buffer.empty(), true);
|
|
|
|
assert_eq!(buffer.full(), false);
|
|
|
|
}
|
|
|
|
}
|