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

60 lines
1.7 KiB
Rust

use ConnectionError;
use error::Reason;
use frame::{self, Frame};
use proto::*;
use proto::ready::ReadySink;
/// Tracks END_STREAM frames received from the remote peer.
#[derive(Debug)]
pub struct StreamRecvClose<T> {
inner: T,
}
impl<T, U> StreamRecvClose<T>
where T: Stream<Item = Frame, Error = ConnectionError>,
T: Sink<SinkItem = Frame<U>, SinkError = ConnectionError>,
T: ControlStreams,
{
pub fn new(inner: T) -> StreamRecvClose<T> {
StreamRecvClose { inner }
}
}
/// Tracks END_STREAM frames received from the remote peer.
impl<T> Stream for StreamRecvClose<T>
where T: Stream<Item = Frame, Error = ConnectionError>,
T: ControlStreams,
{
type Item = T::Item;
type Error = T::Error;
fn poll(&mut self) -> Poll<Option<T::Item>, T::Error> {
let frame = match try_ready!(self.inner.poll()) {
None => return Ok(Async::Ready(None)),
Some(f) => f,
};
let id = frame.stream_id();
if !id.is_zero() {
if frame.is_end_stream() {
trace!("poll: id={:?} eos", id);
if let &Frame::Reset(ref rst) = &frame {
self.inner.reset_stream(id, rst.reason());
} else {
debug_assert!(self.inner.is_active(id));
self.inner.close_recv_half(id)?;
}
}
}
Ok(Async::Ready(Some(frame)))
}
}
proxy_apply_settings!(StreamRecvClose);
proxy_control_flow!(StreamRecvClose);
proxy_control_streams!(StreamRecvClose);
proxy_control_ping!(StreamRecvClose);
proxy_sink!(StreamRecvClose);
proxy_ready_sink!(StreamRecvClose);