mod crc;
mod frame_reader;
mod frame_writer;
use core::ops::Range;
use self::frame_reader::FrameReader;
use self::frame_writer::FrameWriter;
use crate::ppp::PPP;
use crate::wire::{Packet, ProtocolType};
use crate::{Config, Status};
pub use self::frame_writer::BufferFullError;
pub enum PPPoSAction {
None,
Received(Range<usize>),
Transmit(usize),
}
pub struct PPPoS<'a> {
frame_reader: FrameReader,
ppp: PPP<'a>,
}
impl<'a> PPPoS<'a> {
pub fn new(config: Config<'a>) -> Self {
Self {
frame_reader: FrameReader::new(),
ppp: PPP::new(config),
}
}
pub fn status(&self) -> Status {
self.ppp.status()
}
pub fn open(&mut self) -> Result<(), crate::InvalidStateError> {
self.ppp.open()
}
pub fn poll(&mut self, tx_buf: &mut [u8], rx_buf: &mut [u8]) -> PPPoSAction {
let mut w = FrameWriter::new(tx_buf);
let mut tx = |pkt: Packet<'_>| {
let mut buf = [0; 128];
let len = pkt.buffer_len();
assert!(len <= buf.len());
pkt.emit(&mut buf[..len]);
w.start().unwrap();
w.append(&mut buf[..len]).unwrap();
w.finish().unwrap();
};
if let Some(range) = self.frame_reader.receive() {
let pkt = &mut rx_buf[range.clone()];
let proto = u16::from_be_bytes(pkt[0..2].try_into().unwrap());
match proto.into() {
ProtocolType::IPv4 => return PPPoSAction::Received((range.start + 2)..range.end),
_ => self.ppp.received(pkt, &mut tx),
}
}
self.ppp.poll(tx);
let r = w.len();
if r == 0 {
PPPoSAction::None
} else {
PPPoSAction::Transmit(r)
}
}
pub fn send(&mut self, pkt: &[u8], tx_buf: &mut [u8]) -> Result<usize, BufferFullError> {
let mut w = FrameWriter::new_with_asyncmap(tx_buf, self.ppp.lcp.proto().asyncmap_remote);
let proto: u16 = ProtocolType::IPv4.into();
w.start()?;
w.append(&proto.to_be_bytes())?;
w.append(pkt)?;
w.finish()?;
Ok(w.len())
}
pub fn consume(&mut self, data: &[u8], rx_buf: &mut [u8]) -> usize {
self.frame_reader.consume(rx_buf, data)
}
}