use std::{fmt::Debug, ops};
use bytes::{BufMut, BytesMut, buf::UninitSlice};
use derive_more::{Deref, DerefMut};
use enum_dispatch::enum_dispatch;
use getset::CopyGetters;
use header::{LongHeader, io::WriteHeader};
use crate::{
cid::ConnectionId,
frame::{ContainSpec, FrameFeature, FrameType, Spec},
packet::keys::DirectionalKeys,
};
pub mod error;
pub mod signal;
#[doc(hidden)]
pub use signal::{KeyPhaseBit, SpinBit};
pub mod r#type;
#[doc(hidden)]
pub use r#type::{
GetPacketNumberLength, LONG_RESERVED_MASK, LongSpecificBits, SHORT_RESERVED_MASK,
ShortSpecificBits, Type,
};
pub mod header;
#[doc(hidden)]
pub use header::{
EncodeHeader, GetDcid, GetScid, GetType, HandshakeHeader, Header, InitialHeader,
LongHeaderBuilder, OneRttHeader, RetryHeader, VersionNegotiationHeader, ZeroRttHeader, long,
};
pub mod io;
pub use io::{
AssemblePacket, Package, PacketInfo, PacketSpace, PacketWriter, ProductHeader, RecordFrame,
};
pub mod number;
#[doc(hidden)]
pub use number::{InvalidPacketNumber, PacketNumber, WritePacketNumber, take_pn_len};
pub mod decrypt;
pub mod encrypt;
pub mod keys;
#[derive(Debug, Clone)]
#[enum_dispatch(GetDcid, GetType)]
pub enum DataHeader {
Long(long::DataHeader),
Short(OneRttHeader),
}
#[derive(Debug, Clone, Deref, DerefMut)]
pub struct DataPacket {
#[deref]
#[deref_mut]
pub header: DataHeader,
pub bytes: BytesMut,
pub offset: usize,
}
impl GetType for DataPacket {
fn get_type(&self) -> Type {
self.header.get_type()
}
}
#[derive(Default, Debug, Clone, Copy, PartialEq)]
pub enum PacketContent {
#[default]
NonAckEliciting,
JustPing,
EffectivePayload,
}
impl PacketContent {
pub fn is_ack_eliciting(self) -> bool {
self != Self::NonAckEliciting
}
}
impl From<FrameType> for PacketContent {
fn from(frame_type: FrameType) -> Self {
match frame_type {
FrameType::Ping => Self::JustPing,
fty if !fty.specs().contain(Spec::NonAckEliciting) => Self::EffectivePayload,
_ => Self::NonAckEliciting,
}
}
}
impl ops::AddAssign<FrameType> for PacketContent {
fn add_assign(&mut self, rhs: FrameType) {
match rhs {
FrameType::Ping if *self == PacketContent::NonAckEliciting => *self = Self::JustPing,
fty if !fty.specs().contain(Spec::NonAckEliciting) => *self = Self::EffectivePayload,
_ => (),
}
}
}
impl ops::AddAssign for PacketContent {
fn add_assign(&mut self, rhs: Self) {
match rhs {
PacketContent::EffectivePayload => *self = PacketContent::EffectivePayload,
PacketContent::JustPing if *self == PacketContent::NonAckEliciting => {
*self = PacketContent::JustPing
}
_ => {}
}
}
}
#[derive(Debug, Clone)]
pub enum Packet {
VN(VersionNegotiationHeader),
Retry(RetryHeader),
Data(DataPacket),
}
#[derive(Debug)]
pub struct PacketReader {
raw_bytes: BytesMut,
dcid_len: usize,
}
impl PacketReader {
pub fn new(raw_bytes: BytesMut, dcid_len: usize) -> Self {
Self {
raw_bytes,
dcid_len,
}
}
}
impl Iterator for PacketReader {
type Item = Result<Packet, error::Error>;
fn next(&mut self) -> Option<Self::Item> {
if self.raw_bytes.is_empty() {
return None;
}
match io::be_packet(&mut self.raw_bytes, self.dcid_len) {
Ok(packet) => Some(Ok(packet)),
Err(error) => {
tracing::debug!(target: "dquic", ?error, "dropped unparsed packet");
self.raw_bytes.clear(); Some(Err(error))
}
}
}
}