Files
h2/src/proto/framed_read.rs
Oliver Gould 40b57cb7fa touchup
2017-07-24 16:57:44 +00:00

169 lines
4.7 KiB
Rust

use {hpack, ConnectionError};
use frame::{self, Frame, Kind};
use frame::DEFAULT_SETTINGS_HEADER_TABLE_SIZE;
use proto::{ApplySettings, ReadySink};
use futures::*;
use bytes::Bytes;
use tokio_io::AsyncRead;
use tokio_io::codec::length_delimited;
use std::io::{self, Cursor};
#[derive(Debug)]
pub struct FramedRead<T> {
inner: length_delimited::FramedRead<T>,
// hpack decoder state
hpack: hpack::Decoder,
partial: Option<Partial>,
}
/// Partially loaded headers frame
#[derive(Debug)]
enum Partial {
Headers(frame::Headers),
// PushPromise(frame::PushPromise),
}
impl<T> FramedRead<T> {
pub fn new(inner: length_delimited::FramedRead<T>) -> FramedRead<T> {
FramedRead {
inner: inner,
hpack: hpack::Decoder::new(DEFAULT_SETTINGS_HEADER_TABLE_SIZE),
partial: None,
}
}
fn decode_frame(&mut self, mut bytes: Bytes) -> Result<Option<Frame>, ConnectionError> {
trace!("decoding frame from {}B", bytes.len());
// Parse the head
let head = frame::Head::parse(&bytes);
if self.partial.is_some() && head.kind() != Kind::Continuation {
unimplemented!();
}
let kind = head.kind();
debug!("decoded; kind={:?}", kind);
let frame = match kind {
Kind::Settings => {
frame::Settings::load(head, &bytes[frame::HEADER_LEN..])?.into()
}
Kind::Ping => {
frame::Ping::load(head, &bytes[frame::HEADER_LEN..])?.into()
}
Kind::WindowUpdate => {
frame::WindowUpdate::load(head, &bytes[frame::HEADER_LEN..])?.into()
}
Kind::Data => {
let _ = bytes.split_to(frame::HEADER_LEN);
frame::Data::load(head, bytes)?.into()
}
Kind::Headers => {
let mut buf = Cursor::new(bytes);
buf.set_position(frame::HEADER_LEN as u64);
// TODO: Change to drain: carllerche/bytes#130
let frame = try!(frame::Headers::load(head, &mut buf, &mut self.hpack));
if !frame.is_end_headers() {
// Wait for continuation frames
self.partial = Some(Partial::Headers(frame));
return Ok(None);
}
frame.into()
}
Kind::Reset => {
frame::Reset::load(head, &bytes[frame::HEADER_LEN..])?.into()
}
// TODO
Kind::GoAway => {
let _todo = try!(frame::GoAway::load(&bytes[frame::HEADER_LEN..]));
unimplemented!();
}
Kind::PushPromise |
Kind::Priority |
Kind::Continuation |
Kind::Unknown => {
unimplemented!()
}
};
debug!("decoded; frame={:?}", frame);
Ok(Some(frame))
}
}
impl<T: ApplySettings> ApplySettings for FramedRead<T> {
fn apply_local_settings(&mut self, set: &frame::SettingSet) -> Result<(), ConnectionError> {
self.inner.get_mut().apply_local_settings(set)
}
fn apply_remote_settings(&mut self, set: &frame::SettingSet) -> Result<(), ConnectionError> {
self.inner.get_mut().apply_remote_settings(set)
}
}
impl<T> Stream for FramedRead<T>
where T: AsyncRead,
{
type Item = Frame;
type Error = ConnectionError;
fn poll(&mut self) -> Poll<Option<Frame>, ConnectionError> {
loop {
trace!("poll");
let bytes = match try_ready!(self.inner.poll()) {
Some(bytes) => bytes.freeze(),
None => return Ok(Async::Ready(None)),
};
trace!("poll; bytes={}B", bytes.len());
if let Some(frame) = try!(self.decode_frame(bytes)) {
debug!("poll; frame={:?}", frame);
return Ok(Async::Ready(Some(frame)));
}
}
}
}
impl<T: Sink> Sink for FramedRead<T> {
type SinkItem = T::SinkItem;
type SinkError = T::SinkError;
fn start_send(&mut self, item: T::SinkItem) -> StartSend<T::SinkItem, T::SinkError> {
self.inner.get_mut().start_send(item)
}
fn poll_complete(&mut self) -> Poll<(), T::SinkError> {
self.inner.get_mut().poll_complete()
}
}
impl<T: ReadySink> ReadySink for FramedRead<T> {
fn poll_ready(&mut self) -> Poll<(), Self::SinkError> {
self.inner.get_mut().poll_ready()
}
}
impl<T: io::Write> io::Write for FramedRead<T> {
fn write(&mut self, src: &[u8]) -> io::Result<usize> {
self.inner.get_mut().write(src)
}
fn flush(&mut self) -> io::Result<()> {
self.inner.get_mut().flush()
}
}