use crate::layer::{self, FnHandler, Result};
use crate::wire::{icmpv4, ip, Error, Payload, PayloadMut};
use super::packet::{Controller, In, Raw};
use super::{Recv, Send};
pub struct NoHandler { _private: Empty, }
enum Empty { }
#[derive(Default)]
pub struct Endpoint {
deny_echo: bool,
manual_echo: bool,
}
pub struct Receiver<'a, H=NoHandler> {
endpoint: EndpointRef<'a>,
handler: Option<H>,
}
pub struct Sender<'a, H> {
_endpoint: EndpointRef<'a>,
handler: H,
}
struct EndpointRef<'a> {
inner: &'a Endpoint,
}
enum HandlingKind<'a, P: PayloadMut> {
Internal,
ToUpperLayer(In<'a, P>),
}
impl Endpoint {
pub fn new() -> Self {
Self::default()
}
pub fn manual(&mut self, manual: bool) {
self.manual_echo = manual;
}
pub fn silent(&mut self, silent: bool) {
self.deny_echo = silent;
}
pub fn answer(&mut self) -> Receiver {
Receiver { endpoint: self.get_mut(), handler: None, }
}
pub fn recv<H>(&mut self, handler: H) -> Receiver<H> {
Receiver { endpoint: self.get_mut(), handler: Some(handler), }
}
pub fn recv_with<H>(&mut self, handler: H) -> Receiver<FnHandler<H>> {
self.recv(FnHandler(handler))
}
pub fn send<H>(&mut self, handler: H) -> Sender<H> {
Sender { _endpoint: self.get_mut(), handler, }
}
pub fn send_with<H>(&mut self, handler: H) -> Sender<FnHandler<H>> {
self.send(FnHandler(handler))
}
fn get_mut(&mut self) -> EndpointRef {
EndpointRef { inner: self }
}
}
impl EndpointRef<'_> {
fn handle_internally<'a, P: PayloadMut>(&mut self, packet: In<'a, P>)
-> Result<HandlingKind<'a, P>>
{
match packet.packet.repr() {
icmpv4::Repr::EchoRequest { .. } if self.inner.manual_echo => {
Ok(HandlingKind::ToUpperLayer(packet))
},
icmpv4::Repr::EchoRequest { .. } => {
if self.inner.deny_echo {
return Ok(HandlingKind::Internal)
}
packet
.answer()?
.send()?;
Ok(HandlingKind::Internal)
},
_ => Ok(HandlingKind::ToUpperLayer(packet)),
}
}
}
impl<P, H> layer::ip::Recv<P> for Receiver<'_, H>
where
P: PayloadMut,
H: Recv<P>,
{
fn receive(&mut self, layer::ip::InPacket { control, packet }: layer::ip::InPacket<P>) {
let capabilities = control.info().capabilities();
let icmp = match packet {
layer::ip::IpPacket::V4(packet) => {
if packet.repr().protocol != ip::Protocol::Icmp {
return;
}
match icmpv4::Packet::new_checked(packet, capabilities.icmpv4().rx_checksum()) {
Ok(packet) => packet,
Err(Error::Unsupported) => unimplemented!("Forward to upper layer"),
Err(_) => return,
}
},
_ => return,
};
let control = Controller { inner: control };
let packet = In { control, packet: icmp };
let how_to_handle = match self.endpoint.handle_internally(packet) {
Ok(handling) => handling,
Err(_) => return,
};
match (how_to_handle, self.handler.as_mut()) {
(HandlingKind::Internal, _) => (),
(HandlingKind::ToUpperLayer(packet), Some(handler)) => {
handler.receive(packet)
},
_ => (),
}
}
}
impl<P, T> layer::ip::Send<P> for Sender<'_, T>
where
P: PayloadMut,
T: Send<P>,
{
fn send(&mut self, packet: layer::ip::RawPacket<P>) {
let layer::ip::RawPacket { control: mut eth_handle, payload } = packet;
self.handler.send(Raw {
control: Controller {
inner: eth_handle.borrow_mut()
},
payload,
})
}
}
impl<P: PayloadMut> Recv<P> for NoHandler {
fn receive(&mut self, _: In<P>) {
match self._private { }
}
}
impl<P: Payload, F> Recv<P> for FnHandler<F>
where F: FnMut(In<P>)
{
fn receive(&mut self, frame: In<P>) {
self.0(frame)
}
}
impl<P: Payload, F> Send<P> for FnHandler<F>
where F: FnMut(Raw<P>)
{
fn send(&mut self, frame: Raw<P>) {
self.0(frame)
}
}