use std::collections::{HashMap, VecDeque};
use nom::Offset;
use crate::{
protocol::h2::{parser, serializer, stream},
Ready,
};
#[derive(Clone, Debug, PartialEq)]
pub struct OutputFrame {
header: parser::FrameHeader,
payload: Option<Vec<u8>>,
}
#[derive(Clone, Debug, PartialEq)]
pub enum FrameResult {
Close,
Continue,
ConnectBackend(u32),
}
#[derive(Clone, Debug, PartialEq)]
pub enum St {
Init,
ClientPrefaceReceived,
ServerPrefaceSent,
}
#[derive(Clone, Debug, PartialEq)]
pub struct State {
pub output: VecDeque<OutputFrame>,
pub state: St,
pub interest: Ready,
pub max_frame_size: u32,
pub streams: HashMap<u32, stream::Stream>,
}
impl State {
pub fn new() -> State {
State {
output: VecDeque::new(),
state: St::Init,
interest: Ready::READABLE | Ready::HUP | Ready::ERROR,
max_frame_size: 16384,
streams: HashMap::new(),
}
}
pub fn parse<'a>(&mut self, mut input: &'a [u8]) -> (usize, Result<parser::Frame<'a>, ()>) {
let mut consumed = 0usize;
if self.state == St::Init {
match parser::preface(input) {
Err(e) => {
error!("parser::preface error: {:?}", e);
return (0, Err(()));
}
Ok((i, _)) => {
consumed += input.offset(i);
self.state = St::ClientPrefaceReceived;
input = i;
}
}
}
match parser::frame(input, self.max_frame_size) {
Err(e) => {
error!("parser::frame error: {:?}", e);
return (consumed, Err(()));
}
Ok((i, frame)) => {
consumed += input.offset(i);
(consumed, Ok(frame))
}
}
}
pub fn handle(&mut self, frame: &parser::Frame) -> FrameResult {
let stream_id = frame.stream_id();
if stream_id != 0 {
return self.stream_handle(stream_id, frame);
}
match self.state {
St::Init => FrameResult::Continue,
St::ClientPrefaceReceived => {
match frame {
parser::Frame::Settings(s) => {
let server_settings = OutputFrame {
header: parser::FrameHeader {
payload_len: 0,
frame_type: parser::FrameType::Settings,
flags: 1,
stream_id: 0,
},
payload: None,
};
self.output.push_back(server_settings);
self.state = St::ServerPrefaceSent;
self.interest.insert(Ready::WRITABLE);
FrameResult::Continue
}
f => {
unimplemented!("invalid frame: {:?}, should send back an error", f);
}
}
}
St::ServerPrefaceSent => match frame {
frame => {
panic!("unknown frame for now: {:?}", frame);
}
},
}
}
pub fn parse_and_handle<'a>(&mut self, mut input: &'a [u8]) -> (usize, FrameResult) {
let (sz, res) = self.parse(input);
match res {
Err(e) => {
error!("error parsing frame: {:?}", e);
(sz, FrameResult::Close)
}
Ok(frame) => {
info!("parsed frame: {:?}", frame);
(sz, self.handle(&frame))
}
}
}
pub fn gen(&mut self, mut output: &mut [u8]) -> Result<usize, ()> {
if let Some(frame) = self.output.pop_front() {
match serializer::gen_frame_header((output, 0), &frame.header) {
Err(e) => {
panic!("error serializing: {:?}", e);
}
Ok((sl, index)) => Ok(index),
}
} else {
self.interest.remove(Ready::WRITABLE);
Ok(0)
}
}
pub fn stream_handle(&mut self, stream_id: u32, frame: &parser::Frame) -> FrameResult {
assert!(stream_id != 0);
self.streams
.entry(stream_id)
.or_insert(stream::Stream::new(stream_id))
.handle(frame)
}
}