Group IP header parts in the socket layer as struct IpRepr.

v0.7.x
whitequark 2016-12-26 10:06:49 +00:00
parent b5a9917950
commit ea07e79bdf
5 changed files with 160 additions and 132 deletions

View File

@ -6,10 +6,10 @@ use wire::{EthernetAddress, IpAddress};
/// This interface maps protocol addresses to hardware addresses.
pub trait Cache {
/// Update the cache to map given protocol address to given hardware address.
fn fill(&mut self, protocol_addr: IpAddress, hardware_addr: EthernetAddress);
fn fill(&mut self, protocol_addr: &IpAddress, hardware_addr: &EthernetAddress);
/// Look up the hardware address corresponding for the given protocol address.
fn lookup(&mut self, protocol_addr: IpAddress) -> Option<EthernetAddress>;
fn lookup(&mut self, protocol_addr: &IpAddress) -> Option<EthernetAddress>;
}
/// An Address Resolution Protocol cache backed by a slice.
@ -59,10 +59,10 @@ impl<'a> SliceCache<'a> {
}
/// Find an entry for the given protocol address, if any.
fn find(&self, protocol_addr: IpAddress) -> Option<usize> {
fn find(&self, protocol_addr: &IpAddress) -> Option<usize> {
// The order of comparison is important: any valid IpAddress should
// sort before IpAddress::Invalid.
self.storage.binary_search_by_key(&protocol_addr, |&(key, _, _)| key).ok()
self.storage.binary_search_by_key(protocol_addr, |&(key, _, _)| key).ok()
}
/// Sort entries in an order suitable for `find`.
@ -94,16 +94,16 @@ impl<'a> SliceCache<'a> {
}
impl<'a> Cache for SliceCache<'a> {
fn fill(&mut self, protocol_addr: IpAddress, hardware_addr: EthernetAddress) {
fn fill(&mut self, protocol_addr: &IpAddress, hardware_addr: &EthernetAddress) {
if let None = self.find(protocol_addr) {
let lru_index = self.lru();
self.storage[lru_index] =
(protocol_addr, hardware_addr, self.counter);
(*protocol_addr, *hardware_addr, self.counter);
self.sort()
}
}
fn lookup(&mut self, protocol_addr: IpAddress) -> Option<EthernetAddress> {
fn lookup(&mut self, protocol_addr: &IpAddress) -> Option<EthernetAddress> {
if let Some(index) = self.find(protocol_addr) {
let (_protocol_addr, hardware_addr, ref mut counter) =
self.storage[index];
@ -135,24 +135,24 @@ mod test {
let mut cache_storage = [Default::default(); 3];
let mut cache = SliceCache::new(&mut cache_storage[..]);
cache.fill(PADDR_A, HADDR_A);
assert_eq!(cache.lookup(PADDR_A), Some(HADDR_A));
assert_eq!(cache.lookup(PADDR_B), None);
cache.fill(&PADDR_A, &HADDR_A);
assert_eq!(cache.lookup(&PADDR_A), Some(HADDR_A));
assert_eq!(cache.lookup(&PADDR_B), None);
cache.fill(PADDR_B, HADDR_B);
cache.fill(PADDR_C, HADDR_C);
assert_eq!(cache.lookup(PADDR_A), Some(HADDR_A));
assert_eq!(cache.lookup(PADDR_B), Some(HADDR_B));
assert_eq!(cache.lookup(PADDR_C), Some(HADDR_C));
cache.fill(&PADDR_B, &HADDR_B);
cache.fill(&PADDR_C, &HADDR_C);
assert_eq!(cache.lookup(&PADDR_A), Some(HADDR_A));
assert_eq!(cache.lookup(&PADDR_B), Some(HADDR_B));
assert_eq!(cache.lookup(&PADDR_C), Some(HADDR_C));
cache.lookup(PADDR_B);
cache.lookup(PADDR_A);
cache.lookup(PADDR_C);
cache.fill(PADDR_D, HADDR_D);
assert_eq!(cache.lookup(PADDR_A), Some(HADDR_A));
assert_eq!(cache.lookup(PADDR_B), None);
assert_eq!(cache.lookup(PADDR_C), Some(HADDR_C));
assert_eq!(cache.lookup(PADDR_D), Some(HADDR_D));
cache.lookup(&PADDR_B);
cache.lookup(&PADDR_A);
cache.lookup(&PADDR_C);
cache.fill(&PADDR_D, &HADDR_D);
assert_eq!(cache.lookup(&PADDR_A), Some(HADDR_A));
assert_eq!(cache.lookup(&PADDR_B), None);
assert_eq!(cache.lookup(&PADDR_C), Some(HADDR_C));
assert_eq!(cache.lookup(&PADDR_D), Some(HADDR_D));
}
}

View File

@ -9,7 +9,7 @@ use wire::{IpAddress, IpProtocol};
use wire::{Ipv4Address, Ipv4Packet, Ipv4Repr};
use wire::{Icmpv4Packet, Icmpv4Repr, Icmpv4DstUnreachable};
use wire::{TcpPacket, TcpRepr, TcpControl};
use socket::Socket;
use socket::{Socket, IpRepr};
use super::{ArpCache};
/// An Ethernet network interface.
@ -142,7 +142,7 @@ impl<'a, 'b: 'a,
source_hardware_addr, source_protocol_addr,
target_protocol_addr, ..
} => {
self.arp_cache.fill(source_protocol_addr.into(), source_hardware_addr);
self.arp_cache.fill(&source_protocol_addr.into(), &source_hardware_addr);
if self.has_protocol_addr(target_protocol_addr) {
response = Response::Arp(ArpRepr::EthernetIpv4 {
@ -160,7 +160,7 @@ impl<'a, 'b: 'a,
operation: ArpOperation::Reply,
source_hardware_addr, source_protocol_addr, ..
} => {
self.arp_cache.fill(source_protocol_addr.into(), source_hardware_addr)
self.arp_cache.fill(&source_protocol_addr.into(), &source_hardware_addr)
},
_ => return Err(Error::Unrecognized)
@ -169,26 +169,26 @@ impl<'a, 'b: 'a,
// Handle IP packets directed at us.
EthernetProtocol::Ipv4 => {
let ip_packet = try!(Ipv4Packet::new(eth_frame.payload()));
let ip_repr = try!(Ipv4Repr::parse(&ip_packet));
let ipv4_packet = try!(Ipv4Packet::new(eth_frame.payload()));
let ipv4_repr = try!(Ipv4Repr::parse(&ipv4_packet));
// Fill the ARP cache from IP header.
self.arp_cache.fill(IpAddress::Ipv4(ip_repr.src_addr), eth_frame.src_addr());
self.arp_cache.fill(&IpAddress::Ipv4(ipv4_repr.src_addr), &eth_frame.src_addr());
match ip_repr {
match ipv4_repr {
// Ignore IP packets not directed at us.
Ipv4Repr { dst_addr, .. } if !self.has_protocol_addr(dst_addr) => (),
// Respond to ICMP packets.
Ipv4Repr { protocol: IpProtocol::Icmp, src_addr, dst_addr } => {
let icmp_packet = try!(Icmpv4Packet::new(ip_packet.payload()));
let icmp_packet = try!(Icmpv4Packet::new(ipv4_packet.payload()));
let icmp_repr = try!(Icmpv4Repr::parse(&icmp_packet));
match icmp_repr {
// Respond to echo requests.
Icmpv4Repr::EchoRequest {
ident, seq_no, data
} => {
let ip_reply_repr = Ipv4Repr {
let ipv4_reply_repr = Ipv4Repr {
src_addr: dst_addr,
dst_addr: src_addr,
protocol: IpProtocol::Icmp
@ -198,7 +198,7 @@ impl<'a, 'b: 'a,
seq_no: seq_no,
data: data
};
response = Response::Icmpv4(ip_reply_repr, icmp_reply_repr)
response = Response::Icmpv4(ipv4_reply_repr, icmp_reply_repr)
}
// Ignore any echo replies.
@ -213,8 +213,13 @@ impl<'a, 'b: 'a,
Ipv4Repr { src_addr, dst_addr, protocol } => {
let mut handled = false;
for socket in self.sockets.borrow_mut() {
match socket.collect(&src_addr.into(), &dst_addr.into(),
protocol, ip_packet.payload()) {
let ip_repr = IpRepr {
src_addr: src_addr.into(),
dst_addr: dst_addr.into(),
protocol: protocol,
payload: ipv4_packet.payload()
};
match socket.collect(&ip_repr) {
Ok(()) => {
// The packet was valid and handled by socket.
handled = true;
@ -236,9 +241,9 @@ impl<'a, 'b: 'a,
}
if !handled && protocol == IpProtocol::Tcp {
let tcp_packet = try!(TcpPacket::new(ip_packet.payload()));
let tcp_packet = try!(TcpPacket::new(ipv4_packet.payload()));
let ip_reply_repr = Ipv4Repr {
let ipv4_reply_repr = Ipv4Repr {
src_addr: dst_addr,
dst_addr: src_addr,
protocol: IpProtocol::Tcp
@ -253,7 +258,7 @@ impl<'a, 'b: 'a,
window_len: 0,
payload: &[]
};
response = Response::Tcpv4(ip_reply_repr, tcp_reply_repr);
response = Response::Tcpv4(ipv4_reply_repr, tcp_reply_repr);
} else if !handled {
let reason;
if protocol == IpProtocol::Udp {
@ -263,20 +268,20 @@ impl<'a, 'b: 'a,
}
let mut data = [0; 8];
data.copy_from_slice(&ip_packet.payload()[0..8]);
data.copy_from_slice(&ipv4_packet.payload()[0..8]);
let ip_reply_repr = Ipv4Repr {
let ipv4_reply_repr = Ipv4Repr {
src_addr: dst_addr,
dst_addr: src_addr,
protocol: IpProtocol::Icmp
};
let icmp_reply_repr = Icmpv4Repr::DstUnreachable {
reason: reason,
header: ip_repr,
length: ip_packet.payload().len(),
header: ipv4_repr,
length: ipv4_packet.payload().len(),
data: data
};
response = Response::Icmpv4(ip_reply_repr, icmp_reply_repr)
response = Response::Icmpv4(ipv4_reply_repr, icmp_reply_repr)
}
},
}
@ -289,7 +294,7 @@ impl<'a, 'b: 'a,
macro_rules! ip_response {
($tx_buffer:ident, $frame:ident, $ip_repr:ident, $length:expr) => ({
let dst_hardware_addr =
match self.arp_cache.lookup($ip_repr.dst_addr.into()) {
match self.arp_cache.lookup(&$ip_repr.dst_addr.into()) {
None => return Err(Error::Unaddressable),
Some(hardware_addr) => hardware_addr
};
@ -365,9 +370,9 @@ impl<'a, 'b: 'a,
let mut nothing_to_transmit = true;
for socket in self.sockets.borrow_mut() {
let result = socket.dispatch(&mut |src_addr, dst_addr, protocol, payload| {
let result = socket.dispatch(&mut |repr| {
let src_addr =
try!(match src_addr {
try!(match &repr.src_addr {
&IpAddress::Unspecified |
&IpAddress::Ipv4(Ipv4Address([0, _, _, _])) => {
let mut assigned_addr = None;
@ -385,27 +390,27 @@ impl<'a, 'b: 'a,
addr => Ok(addr)
});
let ip_repr =
match (src_addr, dst_addr) {
let ipv4_repr =
match (src_addr, &repr.dst_addr) {
(&IpAddress::Ipv4(src_addr),
&IpAddress::Ipv4(dst_addr)) => {
Ipv4Repr {
src_addr: src_addr,
dst_addr: dst_addr,
protocol: protocol
protocol: repr.protocol
}
},
_ => unreachable!()
};
let dst_hardware_addr =
match arp_cache.lookup(*dst_addr) {
match arp_cache.lookup(&repr.dst_addr) {
None => return Err(Error::Unaddressable),
Some(hardware_addr) => hardware_addr
};
let tx_len = EthernetFrame::<&[u8]>::buffer_len(ip_repr.buffer_len() +
payload.buffer_len());
let tx_len = EthernetFrame::<&[u8]>::buffer_len(ipv4_repr.buffer_len() +
repr.payload.buffer_len());
let mut tx_buffer = try!(device.transmit(tx_len));
let mut frame = try!(EthernetFrame::new(&mut tx_buffer));
frame.set_src_addr(src_hardware_addr);
@ -413,9 +418,14 @@ impl<'a, 'b: 'a,
frame.set_ethertype(EthernetProtocol::Ipv4);
let mut ip_packet = try!(Ipv4Packet::new(frame.payload_mut()));
ip_repr.emit(&mut ip_packet, payload.buffer_len());
ipv4_repr.emit(&mut ip_packet, repr.payload.buffer_len());
payload.emit(src_addr, dst_addr, ip_packet.payload_mut());
repr.payload.emit(&mut IpRepr {
src_addr: repr.src_addr,
dst_addr: repr.dst_addr,
protocol: repr.protocol,
payload: ip_packet.payload_mut()
});
Ok(())
});

View File

@ -24,18 +24,6 @@ pub use self::tcp::SocketBuffer as TcpSocketBuffer;
pub use self::tcp::State as TcpState;
pub use self::tcp::TcpSocket;
/// A packet representation.
///
/// This interface abstracts the various types of packets layered under the IP protocol,
/// and serves as an accessory to [trait Socket](trait.Socket.html).
pub trait PacketRepr {
/// Return the length of the buffer required to serialize this high-level representation.
fn buffer_len(&self) -> usize;
/// Emit this high-level representation into a sequence of octets.
fn emit(&self, src_addr: &IpAddress, dst_addr: &IpAddress, payload: &mut [u8]);
}
/// A network socket.
///
/// This enumeration abstracts the various types of sockets based on the IP protocol.
@ -64,14 +52,12 @@ impl<'a, 'b> Socket<'a, 'b> {
/// is returned.
///
/// This function is used internally by the networking stack.
pub fn collect(&mut self, src_addr: &IpAddress, dst_addr: &IpAddress,
protocol: IpProtocol, payload: &[u8])
-> Result<(), Error> {
pub fn collect(&mut self, repr: &IpRepr<&[u8]>) -> Result<(), Error> {
match self {
&mut Socket::Udp(ref mut socket) =>
socket.collect(src_addr, dst_addr, protocol, payload),
socket.collect(repr),
&mut Socket::Tcp(ref mut socket) =>
socket.collect(src_addr, dst_addr, protocol, payload),
socket.collect(repr),
&mut Socket::__Nonexhaustive => unreachable!()
}
}
@ -83,19 +69,40 @@ impl<'a, 'b> Socket<'a, 'b> {
/// is returned.
///
/// This function is used internally by the networking stack.
pub fn dispatch(&mut self, f: &mut FnMut(&IpAddress, &IpAddress,
IpProtocol, &PacketRepr) -> Result<(), Error>)
-> Result<(), Error> {
pub fn dispatch<F>(&mut self, emit: &mut F) -> Result<(), Error>
where F: FnMut(&IpRepr<&IpPayload>) -> Result<(), Error> {
match self {
&mut Socket::Udp(ref mut socket) =>
socket.dispatch(f),
socket.dispatch(emit),
&mut Socket::Tcp(ref mut socket) =>
socket.dispatch(f),
socket.dispatch(emit),
&mut Socket::__Nonexhaustive => unreachable!()
}
}
}
/// An IP packet representation.
///
/// This struct abstracts the various versions of IP packets.
pub struct IpRepr<T> {
pub src_addr: IpAddress,
pub dst_addr: IpAddress,
pub protocol: IpProtocol,
pub payload: T
}
/// An IP-encapsulated packet representation.
///
/// This trait abstracts the various types of packets layered under the IP protocol,
/// and serves as an accessory to [trait Socket](trait.Socket.html).
pub trait IpPayload {
/// Return the length of the buffer required to serialize this high-level representation.
fn buffer_len(&self) -> usize;
/// Emit this high-level representation into a sequence of octets.
fn emit(&self, repr: &mut IpRepr<&mut [u8]>);
}
/// A conversion trait for network sockets.
///
/// This trait is used to concisely downcast [Socket](trait.Socket.html) values to their

View File

@ -2,9 +2,9 @@ use core::fmt;
use Error;
use Managed;
use wire::{IpProtocol, IpAddress, IpEndpoint};
use wire::{IpProtocol, IpEndpoint};
use wire::{TcpPacket, TcpRepr, TcpControl};
use socket::{Socket, PacketRepr};
use socket::{Socket, IpRepr, IpPayload};
/// A TCP stream ring buffer.
#[derive(Debug)]
@ -241,29 +241,27 @@ impl<'a> TcpSocket<'a> {
}
/// See [Socket::collect](enum.Socket.html#method.collect).
pub fn collect(&mut self, src_addr: &IpAddress, dst_addr: &IpAddress,
protocol: IpProtocol, payload: &[u8])
-> Result<(), Error> {
if protocol != IpProtocol::Tcp { return Err(Error::Rejected) }
pub fn collect(&mut self, ip_repr: &IpRepr<&[u8]>) -> Result<(), Error> {
if ip_repr.protocol != IpProtocol::Tcp { return Err(Error::Rejected) }
let packet = try!(TcpPacket::new(payload));
let repr = try!(TcpRepr::parse(&packet, src_addr, dst_addr));
let packet = try!(TcpPacket::new(ip_repr.payload));
let repr = try!(TcpRepr::parse(&packet, &ip_repr.src_addr, &ip_repr.dst_addr));
// Reject packets with a wrong destination.
if self.local_endpoint.port != repr.dst_port { return Err(Error::Rejected) }
if !self.local_endpoint.addr.is_unspecified() &&
self.local_endpoint.addr != *dst_addr { return Err(Error::Rejected) }
self.local_endpoint.addr != ip_repr.dst_addr { return Err(Error::Rejected) }
// Reject packets from a source to which we aren't connected.
if self.remote_endpoint.port != 0 &&
self.remote_endpoint.port != repr.src_port { return Err(Error::Rejected) }
if !self.remote_endpoint.addr.is_unspecified() &&
self.remote_endpoint.addr != *src_addr { return Err(Error::Rejected) }
self.remote_endpoint.addr != ip_repr.src_addr { return Err(Error::Rejected) }
// Reject packets addressed to a closed socket.
if self.state == State::Closed {
net_trace!("tcp:{}:{}:{}: packet sent to a closed socket",
self.local_endpoint, src_addr, repr.src_port);
self.local_endpoint, ip_repr.src_addr, repr.src_port);
return Err(Error::Malformed)
}
@ -317,8 +315,8 @@ impl<'a> TcpSocket<'a> {
(State::Listen, TcpRepr {
src_port, dst_port, control: TcpControl::Syn, seq_number, ack_number: None, ..
}) => {
self.local_endpoint = IpEndpoint::new(*dst_addr, dst_port);
self.remote_endpoint = IpEndpoint::new(*src_addr, src_port);
self.local_endpoint = IpEndpoint::new(ip_repr.dst_addr, dst_port);
self.remote_endpoint = IpEndpoint::new(ip_repr.src_addr, src_port);
self.local_seq_no = -seq_number; // FIXME: use something more secure
self.remote_seq_no = seq_number + 1;
self.set_state(State::SynReceived);
@ -370,9 +368,8 @@ impl<'a> TcpSocket<'a> {
}
/// See [Socket::dispatch](enum.Socket.html#method.dispatch).
pub fn dispatch(&mut self, f: &mut FnMut(&IpAddress, &IpAddress,
IpProtocol, &PacketRepr) -> Result<(), Error>)
-> Result<(), Error> {
pub fn dispatch<F>(&mut self, emit: &mut F) -> Result<(), Error>
where F: FnMut(&IpRepr<&IpPayload>) -> Result<(), Error> {
let mut repr = TcpRepr {
src_port: self.local_endpoint.port,
dst_port: self.remote_endpoint.port,
@ -416,23 +413,29 @@ impl<'a> TcpSocket<'a> {
_ => unreachable!()
}
f(&self.local_endpoint.addr, &self.remote_endpoint.addr, IpProtocol::Tcp, &repr)
emit(&IpRepr {
src_addr: self.local_endpoint.addr,
dst_addr: self.remote_endpoint.addr,
protocol: IpProtocol::Tcp,
payload: &repr as &IpPayload
})
}
}
impl<'a> PacketRepr for TcpRepr<'a> {
impl<'a> IpPayload for TcpRepr<'a> {
fn buffer_len(&self) -> usize {
self.buffer_len()
}
fn emit(&self, src_addr: &IpAddress, dst_addr: &IpAddress, payload: &mut [u8]) {
let mut packet = TcpPacket::new(payload).expect("undersized payload");
self.emit(&mut packet, src_addr, dst_addr)
fn emit(&self, repr: &mut IpRepr<&mut [u8]>) {
let mut packet = TcpPacket::new(&mut repr.payload).expect("undersized payload");
self.emit(&mut packet, &repr.src_addr, &repr.dst_addr)
}
}
#[cfg(test)]
mod test {
use wire::IpAddress;
use super::*;
#[test]
@ -483,28 +486,37 @@ mod test {
let mut buffer = vec![0; repr.buffer_len()];
let mut packet = TcpPacket::new(&mut buffer).unwrap();
repr.emit(&mut packet, &REMOTE_IP, &LOCAL_IP);
let result = $socket.collect(&REMOTE_IP, &LOCAL_IP, IpProtocol::Tcp,
&packet.into_inner()[..]);
let result = $socket.collect(&IpRepr {
src_addr: REMOTE_IP,
dst_addr: LOCAL_IP,
protocol: IpProtocol::Tcp,
payload: &packet.into_inner()[..]
});
result.expect("send error")
})
}
macro_rules! recv {
($socket:ident, $expected:expr) => ({
let result = $socket.dispatch(&mut |src_addr, dst_addr, protocol, payload| {
assert_eq!(protocol, IpProtocol::Tcp);
assert_eq!(src_addr, &LOCAL_IP);
assert_eq!(dst_addr, &REMOTE_IP);
let result = $socket.dispatch(&mut |repr| {
assert_eq!(repr.protocol, IpProtocol::Tcp);
assert_eq!(repr.src_addr, LOCAL_IP);
assert_eq!(repr.dst_addr, REMOTE_IP);
let mut buffer = vec![0; payload.buffer_len()];
payload.emit(src_addr, dst_addr, &mut buffer);
let mut buffer = vec![0; repr.payload.buffer_len()];
repr.payload.emit(&mut IpRepr {
src_addr: repr.src_addr,
dst_addr: repr.dst_addr,
protocol: repr.protocol,
payload: &mut buffer[..]
});
let packet = TcpPacket::new(&buffer[..]).unwrap();
let repr = TcpRepr::parse(&packet, src_addr, dst_addr).unwrap();
let repr = TcpRepr::parse(&packet, &repr.src_addr, &repr.dst_addr).unwrap();
assert_eq!(repr, $expected);
Ok(())
});
assert_eq!(result, Ok(()));
let result = $socket.dispatch(&mut |_src_addr, _dst_addr, _protocol, _payload| {
let result = $socket.dispatch(&mut |_repr| {
Ok(())
});
assert_eq!(result, Err(Error::Exhausted));

View File

@ -1,8 +1,8 @@
use Error;
use Managed;
use wire::{IpAddress, IpProtocol, IpEndpoint};
use wire::{IpProtocol, IpEndpoint};
use wire::{UdpPacket, UdpRepr};
use socket::{Socket, PacketRepr};
use socket::{Socket, IpRepr, IpPayload};
/// A buffered UDP packet.
#[derive(Debug)]
@ -168,21 +168,19 @@ impl<'a, 'b> UdpSocket<'a, 'b> {
}
/// See [Socket::collect](enum.Socket.html#method.collect).
pub fn collect(&mut self, src_addr: &IpAddress, dst_addr: &IpAddress,
protocol: IpProtocol, payload: &[u8])
-> Result<(), Error> {
if protocol != IpProtocol::Udp { return Err(Error::Rejected) }
pub fn collect(&mut self, ip_repr: &IpRepr<&[u8]>) -> Result<(), Error> {
if ip_repr.protocol != IpProtocol::Udp { return Err(Error::Rejected) }
let packet = try!(UdpPacket::new(payload));
let repr = try!(UdpRepr::parse(&packet, src_addr, dst_addr));
let packet = try!(UdpPacket::new(ip_repr.payload));
let repr = try!(UdpRepr::parse(&packet, &ip_repr.src_addr, &ip_repr.dst_addr));
if repr.dst_port != self.endpoint.port { return Err(Error::Rejected) }
if !self.endpoint.addr.is_unspecified() {
if self.endpoint.addr != *dst_addr { return Err(Error::Rejected) }
if self.endpoint.addr != ip_repr.dst_addr { return Err(Error::Rejected) }
}
let packet_buf = try!(self.rx_buffer.enqueue());
packet_buf.endpoint = IpEndpoint { addr: *src_addr, port: repr.src_port };
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);
net_trace!("udp:{}:{}: collect {} octets",
@ -191,31 +189,32 @@ impl<'a, 'b> UdpSocket<'a, 'b> {
}
/// See [Socket::dispatch](enum.Socket.html#method.dispatch).
pub fn dispatch(&mut self, f: &mut FnMut(&IpAddress, &IpAddress,
IpProtocol, &PacketRepr) -> Result<(), Error>)
-> Result<(), Error> {
pub fn dispatch<F>(&mut self, emit: &mut F) -> Result<(), Error>
where F: FnMut(&IpRepr<&IpPayload>) -> Result<(), Error> {
let packet_buf = try!(self.tx_buffer.dequeue());
net_trace!("udp:{}:{}: dispatch {} octets",
self.endpoint, packet_buf.endpoint, packet_buf.size);
f(&self.endpoint.addr,
&packet_buf.endpoint.addr,
IpProtocol::Udp,
&UdpRepr {
src_port: self.endpoint.port,
dst_port: packet_buf.endpoint.port,
payload: &packet_buf.as_ref()[..]
})
emit(&IpRepr {
src_addr: self.endpoint.addr,
dst_addr: packet_buf.endpoint.addr,
protocol: IpProtocol::Udp,
payload: &UdpRepr {
src_port: self.endpoint.port,
dst_port: packet_buf.endpoint.port,
payload: &packet_buf.as_ref()[..]
} as &IpPayload
})
}
}
impl<'a> PacketRepr for UdpRepr<'a> {
impl<'a> IpPayload for UdpRepr<'a> {
fn buffer_len(&self) -> usize {
self.buffer_len()
}
fn emit(&self, src_addr: &IpAddress, dst_addr: &IpAddress, payload: &mut [u8]) {
let mut packet = UdpPacket::new(payload).expect("undersized payload");
self.emit(&mut packet, src_addr, dst_addr)
fn emit(&self, repr: &mut IpRepr<&mut [u8]>) {
let mut packet = UdpPacket::new(&mut repr.payload).expect("undersized payload");
self.emit(&mut packet, &repr.src_addr, &repr.dst_addr)
}
}