Simplify. NFC.

v0.7.x
whitequark 2017-12-27 00:09:46 +00:00
parent 0d7a6255f6
commit 7c0bae7d36
2 changed files with 33 additions and 39 deletions

View File

@ -382,52 +382,44 @@ impl<'b, 'c, DeviceT> Interface<'b, 'c, DeviceT>
let mut neighbor_addr = None;
let mut device_result = Ok(());
let &mut Self { ref mut device, ref mut inner } = self;
macro_rules! respond {
($response:expr) => ({
let response = $response;
neighbor_addr = response.neighbor_addr();
let tx_token = device.transmit().ok_or(Error::Exhausted)?;
device_result = inner.dispatch(tx_token, timestamp, response);
device_result
})
}
let socket_result =
match *socket {
#[cfg(feature = "socket-raw")]
Socket::Raw(ref mut socket) =>
socket.dispatch(|response| {
let response = Packet::Raw(response);
neighbor_addr = response.neighbor_addr();
let tx_token = device.transmit().ok_or(Error::Exhausted)?;
device_result = inner.dispatch(tx_token, timestamp, response);
device_result
}, &caps.checksum),
socket.dispatch(&caps.checksum, |response|
respond!(Packet::Raw(response))),
#[cfg(all(feature = "socket-icmp", feature = "proto-ipv4"))]
Socket::Icmp(ref mut socket) =>
socket.dispatch(&caps, |response| {
let tx_token = device.transmit().ok_or(Error::Exhausted)?;
device_result = match response {
match response {
#[cfg(feature = "proto-ipv4")]
(IpRepr::Ipv4(ipv4_repr), icmpv4_repr) => {
let response = Packet::Icmpv4((ipv4_repr, icmpv4_repr));
neighbor_addr = response.neighbor_addr();
inner.dispatch(tx_token, timestamp, response)
}
_ => Err(Error::Unaddressable),
};
device_result
(IpRepr::Ipv4(ipv4_repr), icmpv4_repr) =>
respond!(Packet::Icmpv4((ipv4_repr, icmpv4_repr))),
_ => Err(Error::Unaddressable)
}
}),
#[cfg(feature = "socket-udp")]
Socket::Udp(ref mut socket) =>
socket.dispatch(|response| {
let response = Packet::Udp(response);
neighbor_addr = response.neighbor_addr();
let tx_token = device.transmit().ok_or(Error::Exhausted)?;
device_result = inner.dispatch(tx_token, timestamp, response);
device_result
}),
socket.dispatch(|response|
respond!(Packet::Udp(response))),
#[cfg(feature = "socket-tcp")]
Socket::Tcp(ref mut socket) =>
socket.dispatch(timestamp, &caps, |response| {
let response = Packet::Tcp(response);
neighbor_addr = response.neighbor_addr();
let tx_token = device.transmit().ok_or(Error::Exhausted)?;
device_result = inner.dispatch(tx_token, timestamp, response);
device_result
}),
socket.dispatch(timestamp, &caps, |response|
respond!(Packet::Tcp(response))),
Socket::__Nonexhaustive(_) => unreachable!()
};
match (device_result, socket_result) {
(Err(Error::Exhausted), _) => break, // nowhere to transmit
(Ok(()), Err(Error::Exhausted)) => (), // nothing to transmit

View File

@ -183,7 +183,7 @@ impl<'a, 'b> RawSocket<'a, 'b> {
Ok(())
}
pub(crate) fn dispatch<F>(&mut self, emit: F, checksum_caps: &ChecksumCapabilities) ->
pub(crate) fn dispatch<F>(&mut self, checksum_caps: &ChecksumCapabilities, emit: F) ->
Result<()>
where F: FnOnce((IpRepr, &[u8])) -> Result<()> {
fn prepare<'a>(protocol: IpProtocol, buffer: &'a mut [u8],
@ -301,48 +301,50 @@ mod test {
#[test]
#[cfg(feature = "proto-ipv4")]
fn test_send_dispatch() {
let checksum_caps = &ChecksumCapabilities::default();
let mut socket = ipv4_locals::socket(buffer(0), buffer(1));
assert!(socket.can_send());
assert_eq!(socket.dispatch(|_| unreachable!(), &ChecksumCapabilities::default()),
assert_eq!(socket.dispatch(&checksum_caps, |_| unreachable!()),
Err(Error::Exhausted));
assert_eq!(socket.send_slice(&ipv4_locals::PACKET_BYTES[..]), Ok(()));
assert_eq!(socket.send_slice(b""), Err(Error::Exhausted));
assert!(!socket.can_send());
assert_eq!(socket.dispatch(|(ip_repr, ip_payload)| {
assert_eq!(socket.dispatch(&checksum_caps, |(ip_repr, ip_payload)| {
assert_eq!(ip_repr, ipv4_locals::HEADER_REPR);
assert_eq!(ip_payload, &ipv4_locals::PACKET_PAYLOAD);
Err(Error::Unaddressable)
}, &ChecksumCapabilities::default()), Err(Error::Unaddressable));
}), Err(Error::Unaddressable));
assert!(!socket.can_send());
assert_eq!(socket.dispatch(|(ip_repr, ip_payload)| {
assert_eq!(socket.dispatch(&checksum_caps, |(ip_repr, ip_payload)| {
assert_eq!(ip_repr, ipv4_locals::HEADER_REPR);
assert_eq!(ip_payload, &ipv4_locals::PACKET_PAYLOAD);
Ok(())
}, &ChecksumCapabilities::default()), Ok(()));
}), Ok(()));
assert!(socket.can_send());
}
#[test]
#[cfg(feature = "proto-ipv4")]
fn test_send_illegal() {
let checksum_caps = &ChecksumCapabilities::default();
let mut socket = ipv4_locals::socket(buffer(0), buffer(1));
let mut wrong_version = ipv4_locals::PACKET_BYTES.clone();
Ipv4Packet::new(&mut wrong_version).set_version(5);
assert_eq!(socket.send_slice(&wrong_version[..]), Ok(()));
assert_eq!(socket.dispatch(|_| unreachable!(), &ChecksumCapabilities::default()),
assert_eq!(socket.dispatch(&checksum_caps, |_| unreachable!()),
Ok(()));
let mut wrong_protocol = ipv4_locals::PACKET_BYTES.clone();
Ipv4Packet::new(&mut wrong_protocol).set_protocol(IpProtocol::Tcp);
assert_eq!(socket.send_slice(&wrong_protocol[..]), Ok(()));
assert_eq!(socket.dispatch(|_| unreachable!(), &ChecksumCapabilities::default()),
assert_eq!(socket.dispatch(&checksum_caps, |_| unreachable!()),
Ok(()));
}