use core::marker::PhantomData;
use crate::layer::FnHandler;
use crate::wire::{ethernet, Payload, PayloadMut};
use crate::nic;
use super::{Recv, Send};
use super::packet::{self, Controller};
pub struct Endpoint<'a> {
addr: ethernet::Address,
data: PhantomData<&'a ()>,
}
pub struct Receiver<'a, 'e, H> {
endpoint: EthEndpoint<'a, 'e>,
handler: H,
}
pub struct Sender<'a, 'e, H> {
endpoint: EthEndpoint<'a, 'e>,
handler: H,
}
struct EthEndpoint<'a, 'e> {
inner: &'a mut Endpoint<'e>,
}
impl<'a> Endpoint<'a> {
pub fn new(addr: ethernet::Address) -> Self {
Endpoint {
addr,
data: PhantomData,
}
}
pub fn recv<H>(&mut self, handler: H) -> Receiver<'_, 'a, H> {
Receiver { endpoint: self.eth(), 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.eth(), handler, }
}
pub fn send_with<H>(&mut self, handler: H) -> Sender<'_, 'a, FnHandler<H>> {
self.send(FnHandler(handler))
}
fn eth(&mut self) -> EthEndpoint<'_, 'a> {
EthEndpoint {
inner: self,
}
}
fn accepts(&self, dst_addr: ethernet::Address) -> bool {
self.addr == dst_addr || dst_addr.is_broadcast()
}
}
impl packet::Endpoint for EthEndpoint<'_, '_> {
fn src_addr(&mut self) -> ethernet::Address {
self.inner.addr
}
}
impl<H, P, T> nic::Recv<H, P> for Receiver<'_, '_, T>
where
H: nic::Handle,
P: Payload,
T: Recv<P>,
{
fn receive(&mut self, packet: nic::Packet<H, P>) {
let frame = match ethernet::Frame::new_checked(packet.payload) {
Ok(frame) => frame,
Err(_) => return,
};
let repr = frame.repr();
if !self.endpoint.inner.accepts(repr.dst_addr) {
return
}
let control = Controller {
nic_handle: packet.handle,
endpoint: &mut self.endpoint,
};
let packet = packet::In { control, frame };
self.handler.receive(packet)
}
}
impl<H, P, T> nic::Send<H, P> for Sender<'_, '_, T>
where
H: nic::Handle,
P: Payload + PayloadMut,
T: Send<P>,
{
fn send(&mut self, nic::Packet { handle, payload }: nic::Packet<H, P>) {
let control = Controller {
nic_handle: handle,
endpoint: &mut self.endpoint,
};
let packet = packet::Raw { control, payload };
self.handler.send(packet)
}
}
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)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::managed::Slice;
use crate::nic::{external::External, Device};
use crate::layer::eth::Init;
const MAC_ADDR_1: ethernet::Address = ethernet::Address([0, 1, 2, 3, 4, 5]);
static PAYLOAD_BYTES: [u8; 50] =
[0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff];
fn simple_send<P: Payload + PayloadMut>(mut frame: packet::Raw<P>) {
let src_addr = frame.control.src_addr();
let init = Init {
src_addr,
dst_addr: MAC_ADDR_1,
ethertype: ethernet::EtherType::Unknown(0xBEEF),
payload: PAYLOAD_BYTES.len(),
};
let mut prepared = frame.prepare(init)
.expect("Preparing frame mustn't fail in controlled environment");
prepared
.payload_mut_slice()
.copy_from_slice(&PAYLOAD_BYTES[..]);
prepared
.send()
.expect("Sending is possible");
}
fn simple_recv<P: Payload>(frame: packet::In<P>) {
assert_eq!(frame.frame.payload().as_slice(), &PAYLOAD_BYTES[..]);
}
#[test]
fn simple() {
let mut endpoint = Endpoint::new(MAC_ADDR_1);
let mut nic = External::new_send(Slice::One(vec![0; 1024]));
let sent = nic.tx(
1,
endpoint
.send_with(simple_send));
assert_eq!(sent, Ok(1));
nic.set_one_past_receive(1);
let recv = nic.rx(
1,
endpoint
.recv_with(simple_recv));
assert_eq!(recv, Ok(1));
}
}