use crate::layer::{self, FnHandler};
use crate::layer::{Error, Result};
use crate::managed::Slice;
use crate::wire::{ip, ethernet, Payload, PayloadMut};
use crate::time::Instant;
use super::{Recv, Send};
use super::packet::{self, Controller, IpPacket, Route};
use super::route::Routes;
pub struct Endpoint<'a> {
routing: Routing<'a>,
arp: layer::arp::Endpoint<'a>,
}
pub(crate) struct Routing<'data> {
addr: Slice<'data, ip::Cidr>,
routes: Routes<'data>,
}
pub struct Receiver<'a, 'data, H> {
endpoint: IpEndpoint<'a, 'data>,
handler: H,
}
pub struct Sender<'a, 'data, H> {
endpoint: IpEndpoint<'a, 'data>,
handler: H,
}
pub struct Layer<'a, 'data> {
endpoint: IpEndpoint<'a, 'data>,
}
pub(crate) struct IpEndpoint<'a, 'data> {
pub(crate) inner: &'a mut Endpoint<'data>,
}
impl<'a> Endpoint<'a> {
pub fn new<A, C, N>(addr: A, routes: C, neighbors: N) -> Self
where
A: Into<Slice<'a, ip::Cidr>>,
C: Into<Routes<'a>>,
N: Into<layer::arp::NeighborCache<'a>>,
{
let addresses = addr.into();
for addr in addresses.iter() {
assert!(addr.address().is_unicast());
}
Endpoint {
routing: Routing {
addr: addresses,
routes: routes.into(),
},
arp: layer::arp::Endpoint::new(neighbors.into()),
}
}
pub fn recv<H>(&mut self, handler: H) -> Receiver<'_, 'a, H> {
Receiver { endpoint: self.ip(), handler, }
}
pub fn recv_with<H>(&mut self, handler: H) -> Receiver<'_, 'a, FnHandler<H>> {
self.recv(FnHandler(handler))
}
pub fn send<H>(&mut self, handler: H) -> Sender<'_, 'a, H> {
Sender { endpoint: self.ip(), handler, }
}
pub fn send_with<H>(&mut self, handler: H) -> Sender<'_, 'a, FnHandler<H>> {
self.send(FnHandler(handler))
}
pub fn layer_internal(&mut self) -> Layer<'_, 'a> {
Layer { endpoint: self.ip() }
}
fn ip(&mut self) -> IpEndpoint<'_, 'a> {
IpEndpoint {
inner: self,
}
}
pub fn accepts(&self, dst_addr: ip::Address) -> bool {
self.routing.accepts(dst_addr)
}
pub(crate) fn routing(&mut self) -> &mut Routing<'a> {
&mut self.routing
}
}
impl Routing<'_> {
pub(crate) fn accepts(&self, dst_addr: ip::Address) -> bool {
self.addr.iter().any(|own_addr| own_addr.accepts(dst_addr))
}
pub(crate) fn route(&self, dst_addr: ip::Address, time: Instant) -> Option<Route> {
if let Some(route) = self.find_local_route(dst_addr, time) {
return Some(route)
}
self.find_outer_route(dst_addr, time)
}
pub(crate) fn find_local_route(&self, dst_addr: ip::Address, _: Instant) -> Option<Route> {
let matching_src = self.addr
.iter()
.filter(|addr| addr.subnet().contains(dst_addr))
.nth(0)?;
Some(Route {
src_addr: matching_src.address(),
next_hop: dst_addr,
})
}
pub(crate) fn find_outer_route(&self, dst_addr: ip::Address, time: Instant) -> Option<Route> {
let next_hop = self.routes.lookup(dst_addr, time)?;
let src_addr = self.addr
.iter()
.filter(|addr| addr.subnet().contains(next_hop))
.nth(0)?;
Some(Route {
next_hop,
src_addr: src_addr.address(),
})
}
}
impl<'data> IpEndpoint<'_, 'data> {
pub(crate) fn neighbors(&self) -> &layer::arp::NeighborCache<'data> {
self.inner.arp.neighbors()
}
pub(crate) fn neighbors_mut(&mut self) -> &mut layer::arp::NeighborCache<'data> {
self.inner.arp.neighbors_mut()
}
fn into_arp_receiver(&mut self) -> layer::arp::Receiver<'_, 'data> {
let Endpoint { routing, arp } = self.inner;
arp.answer_for(routing)
}
fn into_arp_sender(&mut self) -> layer::arp::Sender<'_, 'data> {
let Endpoint { routing, arp } = self.inner;
arp.query_for(routing)
}
}
impl packet::Endpoint for IpEndpoint<'_, '_> {
fn local_ip(&self, subnet: ip::Subnet) -> Option<ip::Address> {
self.inner.routing.addr
.iter()
.cloned()
.map(|cidr| cidr.address())
.filter(|&addr| subnet.contains(addr))
.nth(0)
}
fn route(&self, dst_addr: ip::Address, time: Instant) -> Option<Route> {
self.inner.routing.route(dst_addr, time)
}
fn resolve(&mut self, addr: ip::Address, time: Instant, look: bool) -> Result<ethernet::Address> {
match self.neighbors().lookup_pure(addr, time) {
Some(addr) => return Ok(addr),
None if !look => return Err(Error::Unreachable),
None => (),
}
match self.neighbors_mut().fill_looking(addr, Some(time)) {
Ok(()) => Err(Error::Unreachable),
Err(_) => Err(Error::Exhausted),
}
}
}
impl<P, T> layer::eth::Recv<P> for Receiver<'_, '_, T>
where
P: PayloadMut,
T: Recv<P>,
{
fn receive(&mut self, layer::eth::InPacket { mut control, frame }: layer::eth::InPacket<P>) {
let capabilities = control.info().capabilities();
let packet = match frame.repr().ethertype {
ethernet::EtherType::Ipv4 => {
match ip::v4::Packet::new_checked(frame, capabilities.ipv4().rx_checksum()) {
Ok(packet) => IpPacket::V4(packet),
Err(_) => return,
}
},
ethernet::EtherType::Ipv6 => {
match ip::v6::Packet::new_checked(frame) {
Ok(packet) => IpPacket::V6(packet),
Err(_) => return,
}
},
ethernet::EtherType::Arp => {
return self.endpoint.into_arp_receiver().receive(
layer::eth::InPacket { control, frame, });
}
_ => return,
};
if !self.endpoint.inner.accepts(packet.repr().dst_addr()) {
return
}
self.handler.receive(packet::In {
control: Controller {
eth: control.borrow_mut(),
endpoint: &mut self.endpoint,
},
packet,
})
}
}
impl<P, T> layer::eth::Send<P> for Sender<'_, '_, T>
where
P: Payload + PayloadMut,
T: Send<P>,
{
fn send(&mut self, packet: layer::eth::RawPacket<P>) {
if self.endpoint.neighbors().missing().count() > 0 {
return self.endpoint.into_arp_sender().send(packet);
}
let layer::eth::RawPacket { control: mut eth_handle, payload } = packet;
self.handler.send(packet::Raw {
control: Controller {
eth: eth_handle.borrow_mut(),
endpoint: &mut self.endpoint
},
payload,
});
}
}
impl<P> layer::eth::Recv<P> for Layer<'_, '_>
where P: PayloadMut,
{
fn receive(&mut self, packet: layer::eth::InPacket<P>) {
Receiver {
endpoint: IpEndpoint {
inner: self.endpoint.inner,
},
handler: FnHandler(recv_nothing),
}.receive(packet)
}
}
impl<P> layer::eth::Send<P> for Layer<'_, '_>
where P: PayloadMut,
{
fn send(&mut self, packet: layer::eth::RawPacket<P>) {
Sender {
endpoint: IpEndpoint {
inner: self.endpoint.inner,
},
handler: FnHandler(send_nothing),
}.send(packet)
}
}
fn recv_nothing<P: PayloadMut>(_: packet::In<P>) { }
fn send_nothing<P: PayloadMut>(_: packet::Raw<P>) { }
impl<P: Payload, F> Recv<P> for FnHandler<F>
where F: FnMut(packet::In<P>)
{
fn receive(&mut self, frame: packet::In<P>) {
self.0(frame)
}
}
impl<P: Payload, F> Send<P> for FnHandler<F>
where F: FnMut(packet::Raw<P>)
{
fn send(&mut self, frame: packet::Raw<P>) {
self.0(frame)
}
}