use std::collections::HashMap;
use std::time::Duration;
use quiche;
use quiche::h3::frame::Frame;
use quiche::h3::Header;
use quiche::ConnectionError;
use serde::Deserialize;
use serde::Serialize;
use serde_with::serde_as;
use crate::encode_header_block;
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Action {
SendFrame {
stream_id: u64,
fin_stream: bool,
frame: Frame,
},
SendHeadersFrame {
stream_id: u64,
fin_stream: bool,
headers: Vec<Header>,
frame: Frame,
},
StreamBytes {
stream_id: u64,
fin_stream: bool,
bytes: Vec<u8>,
},
OpenUniStream {
stream_id: u64,
fin_stream: bool,
stream_type: u64,
},
ResetStream {
stream_id: u64,
error_code: u64,
},
StopSending {
stream_id: u64,
error_code: u64,
},
ConnectionClose {
error: ConnectionError,
},
FlushPackets,
Wait {
wait_type: WaitType,
},
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(untagged)]
#[serde_as]
pub enum WaitType {
#[serde_as(as = "DurationMilliSeconds<f64>")]
WaitDuration(Duration),
StreamEvent(StreamEvent),
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename = "snake_case")]
pub struct StreamEvent {
pub stream_id: u64,
#[serde(rename = "type")]
pub event_type: StreamEventType,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum StreamEventType {
Headers,
Data,
Finished,
}
#[derive(Debug, Default)]
pub(crate) struct WaitingFor(HashMap<u64, Vec<StreamEvent>>);
impl WaitingFor {
pub(crate) fn is_empty(&self) -> bool {
self.0.values().all(|v| v.is_empty())
}
pub(crate) fn add_wait(&mut self, stream_event: &StreamEvent) {
self.0
.entry(stream_event.stream_id)
.or_default()
.push(*stream_event);
}
pub(crate) fn remove_wait(&mut self, stream_event: StreamEvent) {
if let Some(waits) = self.0.get_mut(&stream_event.stream_id) {
let old_len = waits.len();
waits.retain(|wait| wait != &stream_event);
let new_len = waits.len();
if old_len != new_len {
log::info!("No longer waiting for {:?}", stream_event);
}
}
}
pub(crate) fn clear_waits_on_stream(&mut self, stream_id: u64) {
if let Some(waits) = self.0.get_mut(&stream_id) {
if !waits.is_empty() {
log::info!("Clearing all waits for stream {}", stream_id);
waits.clear();
}
}
}
}
pub fn send_headers_frame(
stream_id: u64, fin_stream: bool, headers: Vec<Header>,
) -> Action {
let header_block = encode_header_block(&headers).unwrap();
Action::SendHeadersFrame {
stream_id,
fin_stream,
headers,
frame: Frame::Headers { header_block },
}
}