use std::net::SocketAddr;
use serde::{Deserialize, Serialize};
use unix_time::Instant as UnixInstant;
use crate::{Bytes, ConversionError, PluginVal};
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord)]
#[repr(C)]
pub enum FrameSendKind {
OncePerPacket,
ManyPerPacket,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord)]
#[repr(C)]
pub enum FrameSendOrder {
First,
AfterACK,
BeforeStream,
End,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
#[repr(C)]
pub struct FrameRegistration {
ty: u64,
send_order: FrameSendOrder,
send_kind: FrameSendKind,
ack_eliciting: bool,
count_in_flight: bool,
}
impl FrameRegistration {
pub fn new(
ty: u64,
send_order: FrameSendOrder,
send_kind: FrameSendKind,
ack_eliciting: bool,
count_in_flight: bool,
) -> Self {
Self {
ty,
send_order,
send_kind,
ack_eliciting,
count_in_flight,
}
}
pub fn get_type(&self) -> u64 {
self.ty
}
pub fn send_order(&self) -> FrameSendOrder {
self.send_order
}
pub fn ack_eliciting(&self) -> bool {
self.ack_eliciting
}
pub fn count_for_in_flight(&self) -> bool {
self.count_in_flight
}
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
#[repr(C)]
pub enum Registration {
TransportParameter(u64),
Frame(FrameRegistration),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize)]
pub enum PacketType {
Initial,
Retry,
Handshake,
ZeroRTT,
VersionNegotiation,
Short,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd)]
#[repr(usize)]
pub enum KPacketNumberSpace {
Initial = 0,
Handshake = 1,
ApplicationData = 2,
}
pub type PacketNumber = u64;
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
#[repr(C)]
pub enum RecoveryField {
LatestRtt,
SmoothedRtt,
Rttvar,
MinRtt,
FirstRttSample,
MaxAckDelay,
LossDetectionTimer,
PtoCount(KPacketNumberSpace),
TimeOfLastAckElicitingPacket(KPacketNumberSpace),
LargestAckedPacket(KPacketNumberSpace),
LossTime(KPacketNumberSpace),
SentPackets(KPacketNumberSpace, PacketNumber),
MaxDatagramSize,
EcnCeCounters(KPacketNumberSpace),
BytesInFlight,
CongestionWindow,
CongestionRecoveryStartTime,
Ssthresh,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
#[repr(C)]
pub enum RangeSetField {
Length,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
#[repr(C)]
pub enum PacketNumberSpaceField {
ReceivedPacketNeedAck,
AckEllicited,
NextPacketNumber,
HasSendKeys,
ShouldSend,
LargestRxPacketNumber,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
#[repr(C)]
pub enum Host {
Local,
Remote,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
#[repr(C)]
pub enum Direction {
Source,
Destination,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
#[repr(C)]
pub enum TransportParameterField {
AckDelayExponent,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
#[repr(C)]
pub enum IDList {
Length,
MinID,
MaxID,
Elem(u64),
All,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
#[repr(C)]
pub struct Address {
pub addr: SocketAddr,
pub local: bool,
pub verified: bool,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
#[repr(C)]
pub enum ConnectionField {
IsServer,
InternalID,
Version,
MaxTxData,
ConnectionID(Direction, IDList),
PacketNumberSpace(KPacketNumberSpace, PacketNumberSpaceField),
TransportParameter(Host, TransportParameterField),
Token,
ConnectionError,
HandshakeWriteLevel,
IsEstablished,
IsInEarlyData,
IsBlocked,
HasFlushableStreams,
HasBlockedStreams,
MaxSendUdpPayloadLength,
MaxSendBytes,
Address(Host, IDList),
RxData,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
#[repr(C)]
pub enum SentPacketField {
PacketNumber,
AckEliciting,
InFlight,
SentBytes,
TimeSent,
SourceAddress,
DestinationAddress,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
#[repr(C)]
pub enum RcvPacketField {
SourceAddress,
DestinationAddress,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd)]
#[repr(C)]
pub struct HeaderExt {
pub packet_number: Option<u64>,
pub packet_number_len: Option<u8>,
pub token: Option<Bytes>,
pub key_phase: Option<bool>,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd)]
#[repr(C)]
pub struct Header {
pub first: u8,
pub version: Option<u32>,
pub destination_cid: Bytes,
pub source_cid: Option<Bytes>,
pub supported_versions: Option<Bytes>,
pub ext: Option<HeaderExt>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[repr(C)]
pub struct SentPacket {
pub header: Header,
pub source_address: SocketAddr,
pub destination_address: SocketAddr,
pub packet_number: u64,
pub packet_number_len: u8,
pub ack_elliciting: bool,
pub in_flight: bool,
pub sent_bytes: usize,
pub time_sent: UnixInstant,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
#[repr(C)]
pub struct AckRange {
pub gap: u64,
pub ack_range_length: u64,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd)]
#[repr(C)]
pub struct EcnCount {
pub ect0_count: u64,
pub ect1_count: u64,
pub ectce_count: u64,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[repr(C)]
pub struct ConnectionId {
pub sequence_number: u64,
pub connection_id: Vec<u8>,
pub stateless_reset_token: Option<Vec<u8>>,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd)]
#[non_exhaustive]
#[repr(C)]
pub enum Frame {
Padding(PaddingFrame),
Ping(PingFrame),
ACK(ACKFrame),
ResetStream(ResetStreamFrame),
StopSending(StopSendingFrame),
Crypto(CryptoFrame),
NewToken(NewTokenFrame),
Stream(StreamFrame),
MaxData(MaxDataFrame),
MaxStreamData(MaxStreamDataFrame),
MaxStreams(MaxStreamsFrame),
DataBlocked(DataBlockedFrame),
StreamDataBlocked(StreamDataBlockedFrame),
StreamsBlocked(StreamsBlockedFrame),
NewConnectionId(NewConnectionIdFrame),
RetireConnectionId(RetireConnectionIdFrame),
PathChallenge(PathChallengeFrame),
PathResponse(PathResponseFrame),
ConnectionClose(ConnectionCloseFrame),
HandshakeDone(HandshakeDoneFrame),
Extension(ExtensionFrame),
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd)]
#[repr(C)]
pub struct PaddingFrame {
pub length: u64,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd)]
#[repr(C)]
pub struct PingFrame;
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd)]
#[repr(C)]
pub struct ACKFrame {
pub largest_acknowledged: u64,
pub ack_delay: u64,
pub ack_range_count: u64,
pub first_ack_range: u64,
pub ack_ranges: Bytes,
pub ecn_counts: Option<EcnCount>,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd)]
#[repr(C)]
pub struct ResetStreamFrame {
pub stream_id: u64,
pub application_protocol_error_code: u64,
pub final_size: u64,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd)]
#[repr(C)]
pub struct StopSendingFrame {
pub stream_id: u64,
pub application_protocol_error_code: u64,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd)]
#[repr(C)]
pub struct CryptoFrame {
pub offset: u64,
pub length: u64,
pub crypto_data: Bytes,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd)]
#[repr(C)]
pub struct NewTokenFrame {
pub token_length: u64,
pub token: Bytes,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd)]
#[repr(C)]
pub struct StreamFrame {
pub stream_id: u64,
pub offset: Option<u64>,
pub length: Option<u64>,
pub fin: bool,
pub stream_data: Bytes,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd)]
#[repr(C)]
pub struct MaxDataFrame {
pub maximum_data: u64,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd)]
#[repr(C)]
pub struct MaxStreamDataFrame {
pub stream_id: u64,
pub maximum_stream_data: u64,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd)]
#[repr(C)]
pub struct MaxStreamsFrame {
pub unidirectional: bool,
pub maximum_streams: u64,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd)]
#[repr(C)]
pub struct DataBlockedFrame {
pub maximum_data: u64,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd)]
#[repr(C)]
pub struct StreamDataBlockedFrame {
pub stream_id: u64,
pub maximum_stream_data: u64,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd)]
#[repr(C)]
pub struct StreamsBlockedFrame {
pub unidirectional: bool,
pub maximum_streams: u64,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd)]
#[repr(C)]
pub struct NewConnectionIdFrame {
pub sequence_number: u64,
pub retire_prior_to: u64,
pub length: u8,
pub connection_id: Bytes,
pub stateless_reset_token: Bytes,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd)]
#[repr(C)]
pub struct RetireConnectionIdFrame {
pub sequence_number: u64,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd)]
#[repr(C)]
pub struct PathChallengeFrame {
pub data: u64,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd)]
#[repr(C)]
pub struct PathResponseFrame {
pub data: u64,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd)]
#[repr(C)]
pub struct ConnectionCloseFrame {
pub error_code: u64,
pub frame_type: Option<u64>,
pub reason_phrase_length: u64,
pub reason_phrase: Bytes,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd)]
#[repr(C)]
pub struct HandshakeDoneFrame;
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd)]
#[repr(C)]
pub struct ExtensionFrame {
pub frame_type: u64,
pub tag: u64,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd)]
#[repr(C)]
pub struct RcvInfo {
pub from: SocketAddr,
pub to: SocketAddr,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd)]
#[repr(C)]
pub enum QVal {
Header(Header),
Frame(Frame),
RcvInfo(RcvInfo),
PacketNumberSpace(KPacketNumberSpace),
PacketType(PacketType),
}
macro_rules! impl_from_try_from_qval {
($e:ident, $v:ident, $t:ty, $err:ident, $verr:ident) => {
impl From<$t> for $e {
fn from(v: $t) -> Self {
$e::QUIC(QVal::$v(v))
}
}
impl TryFrom<$e> for $t {
type Error = $err;
fn try_from(v: $e) -> Result<Self, Self::Error> {
match v {
$e::QUIC(QVal::$v(v)) => Ok(v),
_ => Err($err::$verr),
}
}
}
};
}
impl_from_try_from_qval!(PluginVal, Header, Header, ConversionError, InvalidQVal);
impl_from_try_from_qval!(PluginVal, Frame, Frame, ConversionError, InvalidQVal);
impl_from_try_from_qval!(PluginVal, RcvInfo, RcvInfo, ConversionError, InvalidQVal);
impl_from_try_from_qval!(
PluginVal,
PacketNumberSpace,
KPacketNumberSpace,
ConversionError,
InvalidQVal
);
impl_from_try_from_qval!(
PluginVal,
PacketType,
PacketType,
ConversionError,
InvalidQVal
);