use std::collections::HashMap;
use derive_builder::Builder;
use serde::{Deserialize, Serialize};
use super::{PacketHeader, PacketNumberSpace, QuicFrame};
#[serde_with::skip_serializing_none]
#[derive(Builder, Debug, Clone, Serialize, Deserialize, PartialEq)]
#[builder(setter(into, strip_option), build_fn(private, name = "fallible_build"))]
pub struct RecoveryParametersSet {
#[builder(default)]
reordering_threshold: Option<u16>,
#[builder(default)]
time_threshold: Option<f32>,
timer_granularity: u16,
#[builder(default)]
initial_rtt: Option<f32>,
#[builder(default)]
max_datagram_size: Option<u32>,
#[builder(default)]
initial_congestion_window: Option<u64>,
#[builder(default)]
minimum_congestion_window: Option<u64>,
loss_reduction_factor: Option<f32>,
#[builder(default)]
persistent_congestion_threshold: Option<u16>,
#[builder(default)]
#[serde(flatten)]
#[serde(skip_serializing_if = "HashMap::is_empty")]
custom_fields: HashMap<String, serde_json::Value>,
}
#[serde_with::skip_serializing_none]
#[derive(Builder, Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
#[builder(
default,
setter(into, strip_option),
build_fn(private, name = "fallible_build")
)]
pub struct RecoveryMetricsUpdated {
smoothed_rtt: Option<f32>,
min_rtt: Option<f32>,
latest_rtt: Option<f32>,
rtt_variance: Option<f32>,
pto_count: Option<u16>,
congestion_window: Option<u64>,
bytes_in_flight: Option<u64>,
ssthresh: Option<u64>,
packets_in_flight: Option<u64>,
pacing_rate: Option<u64>,
#[serde(flatten)]
#[serde(skip_serializing_if = "HashMap::is_empty")]
custom_fields: HashMap<String, serde_json::Value>,
}
#[serde_with::skip_serializing_none]
#[derive(Builder, Debug, Clone, Serialize, Deserialize, PartialEq)]
#[builder(setter(into, strip_option), build_fn(private, name = "fallible_build"))]
pub struct CongestionStateUpdated {
#[builder(default)]
old: Option<String>,
new: String,
#[builder(default)]
trigger: Option<String>,
}
#[serde_with::skip_serializing_none]
#[derive(Builder, Debug, Clone, Serialize, Deserialize, PartialEq)]
#[builder(setter(into, strip_option), build_fn(private, name = "fallible_build"))]
pub struct LossTimerUpdated {
#[builder(default)]
timer_type: Option<TimerType>,
#[builder(default)]
packet_number_space: Option<PacketNumberSpace>,
event_type: EventType,
#[builder(default)]
delta: Option<f32>,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum TimerType {
Ack,
Pto,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum EventType {
Set,
Expired,
Cancelled,
}
#[serde_with::skip_serializing_none]
#[derive(Builder, Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
#[builder(
default,
setter(into, strip_option),
build_fn(private, name = "fallible_build")
)]
pub struct PacketLost {
header: Option<PacketHeader>,
frames: Option<Vec<QuicFrame>>,
is_mtu_probe_packet: bool,
trigger: Option<PacketLostTrigger>,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum PacketLostTrigger {
ReorderingThreshold,
TimeThreshold,
PtoExpired,
}
#[derive(Builder, Debug, Clone, Serialize, Deserialize, PartialEq)]
#[builder(setter(into), build_fn(private, name = "fallible_build"))]
pub struct MarkedForRetransmit {
frames: Vec<QuicFrame>,
}
#[serde_with::skip_serializing_none]
#[derive(Builder, Debug, Clone, Serialize, Deserialize, PartialEq)]
#[builder(setter(into, strip_option), build_fn(private, name = "fallible_build"))]
pub struct ECNStateUpdated {
#[builder(default)]
old: Option<ECNState>,
new: ECNState,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum ECNState {
Testing,
Unknown,
Failed,
Capable,
}
crate::gen_builder_method! {
RecoveryParametersSetBuilder => RecoveryParametersSet;
RecoveryMetricsUpdatedBuilder => RecoveryMetricsUpdated;
CongestionStateUpdatedBuilder => CongestionStateUpdated;
LossTimerUpdatedBuilder => LossTimerUpdated;
PacketLostBuilder => PacketLost;
MarkedForRetransmitBuilder => MarkedForRetransmit;
ECNStateUpdatedBuilder => ECNStateUpdated;
}
mod rollback {
use super::*;
use crate::{build, legacy::quic as legacy};
impl From<RecoveryParametersSet> for legacy::RecoveryParametersSet {
fn from(value: RecoveryParametersSet) -> Self {
build!(legacy::RecoveryParametersSet {
?reordering_threshold: value.reordering_threshold,
?time_threshold: value.time_threshold,
timer_granularity: value.timer_granularity,
?initial_rtt: value.initial_rtt,
?max_datagram_size: value.max_datagram_size,
?initial_congestion_window: value.initial_congestion_window,
?minimum_congestion_window: value.minimum_congestion_window.map(|v| v as u32),
?loss_reduction_factor: value.loss_reduction_factor,
?persistent_congestion_threshold: value.persistent_congestion_threshold,
custom_fields: value.custom_fields,
})
}
}
impl From<RecoveryMetricsUpdated> for legacy::RecoveryMetricsUpdated {
fn from(value: RecoveryMetricsUpdated) -> Self {
build!(legacy::RecoveryMetricsUpdated {
?smoothed_rtt: value.smoothed_rtt,
?min_rtt: value.min_rtt,
?latest_rtt: value.latest_rtt,
?rtt_variance: value.rtt_variance,
?pto_count: value.pto_count,
?congestion_window: value.congestion_window,
?bytes_in_flight: value.bytes_in_flight,
?ssthresh: value.ssthresh,
?packets_in_flight: value.packets_in_flight,
?pacing_rate: value.pacing_rate,
custom_fields: value.custom_fields,
})
}
}
impl From<CongestionStateUpdated> for legacy::RecoveryCongestionStateUpdated {
fn from(value: CongestionStateUpdated) -> Self {
build!(legacy::RecoveryCongestionStateUpdated {
?old: value.old,
new: value.new,
?trigger: match value.trigger {
Some(s) if s == "persistent_congestion" => Some(legacy::RecoveryCongestionStateUpdatedTrigger::PersistentCongestion),
Some(s) if s == "ecn" => Some(legacy::RecoveryCongestionStateUpdatedTrigger::Ecn),
_ => None,
},
})
}
}
impl From<TimerType> for legacy::LossTimerType {
#[inline]
fn from(value: TimerType) -> Self {
match value {
TimerType::Ack => legacy::LossTimerType::Ack,
TimerType::Pto => legacy::LossTimerType::Pto,
}
}
}
impl From<EventType> for legacy::LossTimerEventType {
#[inline]
fn from(value: EventType) -> Self {
match value {
EventType::Set => legacy::LossTimerEventType::Set,
EventType::Expired => legacy::LossTimerEventType::Expired,
EventType::Cancelled => legacy::LossTimerEventType::Cancelled,
}
}
}
impl From<LossTimerUpdated> for legacy::RecoveryLossTimerUpdated {
fn from(value: LossTimerUpdated) -> Self {
build!(legacy::RecoveryLossTimerUpdated {
?timer_type: value.timer_type,
?packet_number_space: value.packet_number_space,
event_type: value.event_type,
?delta: value.delta,
})
}
}
impl From<PacketLostTrigger> for legacy::RecoveryPacketLostTrigger {
#[inline]
fn from(value: PacketLostTrigger) -> Self {
match value {
PacketLostTrigger::ReorderingThreshold => {
legacy::RecoveryPacketLostTrigger::ReorderingThreshold
}
PacketLostTrigger::TimeThreshold => {
legacy::RecoveryPacketLostTrigger::TimeThreshold
}
PacketLostTrigger::PtoExpired => legacy::RecoveryPacketLostTrigger::PtoExpired,
}
}
}
impl From<PacketLost> for legacy::RecoveryPacketLost {
fn from(value: PacketLost) -> Self {
build!(legacy::RecoveryPacketLost {
?header: value.header,
?frames: value.frames.map(|v| v.into_iter().map(Into::into).collect::<Vec<_>>()),
?trigger: value.trigger,
})
}
}
impl From<MarkedForRetransmit> for legacy::RecoveryMarkedForRetransmit {
fn from(value: MarkedForRetransmit) -> Self {
build!(legacy::RecoveryMarkedForRetransmit {
frames: value.frames.into_iter().map(Into::into).collect::<Vec<_>>(),
})
}
}
}