Handle the remote returning a protocol error
This commit is contained in:
@@ -92,6 +92,16 @@ impl<T, P, B> Connection<T, P, B>
|
||||
|
||||
/// Advances the internal state of the connection.
|
||||
pub fn poll(&mut self) -> Poll<(), ConnectionError> {
|
||||
match self.poll2() {
|
||||
Err(e) => {
|
||||
self.streams.recv_err(&e);
|
||||
Err(e)
|
||||
}
|
||||
ret => ret,
|
||||
}
|
||||
}
|
||||
|
||||
fn poll2(&mut self) -> Poll<(), ConnectionError> {
|
||||
use frame::Frame::*;
|
||||
|
||||
loop {
|
||||
@@ -178,9 +188,6 @@ impl<T, P, B> Connection<T, P, B>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Flush the write buffer
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -143,6 +143,14 @@ impl<P, B> Recv<P, B>
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn recv_err(&mut self, err: &ConnectionError, stream: &mut Stream<B>) {
|
||||
// Receive an error
|
||||
stream.state.recv_err(err);
|
||||
|
||||
// If a receiver is waiting, notify it
|
||||
stream.notify_recv();
|
||||
}
|
||||
|
||||
pub fn dec_num_streams(&mut self) {
|
||||
self.num_streams -= 1;
|
||||
}
|
||||
@@ -308,6 +316,8 @@ impl<B> Recv<client::Peer, B>
|
||||
}
|
||||
Some(frame) => unimplemented!(),
|
||||
None => {
|
||||
stream.state.ensure_recv_open()?;
|
||||
|
||||
stream.recv_task = Some(task::current());
|
||||
Ok(Async::NotReady)
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ enum Inner {
|
||||
HalfClosedLocal(Peer), // TODO: explicitly name this value
|
||||
HalfClosedRemote(Peer),
|
||||
// When reset, a reason is provided
|
||||
Closed(Option<Reason>),
|
||||
Closed(Option<Cause>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
@@ -76,6 +76,12 @@ enum Peer {
|
||||
Streaming(FlowControl),
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
enum Cause {
|
||||
Proto(Reason),
|
||||
Io,
|
||||
}
|
||||
|
||||
impl State {
|
||||
/// Opens the send-half of a stream if it is not already open.
|
||||
pub fn send_open(&mut self, sz: WindowSize, eos: bool) -> Result<(), ConnectionError> {
|
||||
@@ -178,6 +184,19 @@ impl State {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn recv_err(&mut self, err: &ConnectionError) {
|
||||
match self.inner {
|
||||
Closed(..) => {}
|
||||
_ => {
|
||||
self.inner = Closed(match *err {
|
||||
ConnectionError::Proto(reason) => Some(Cause::Proto(reason)),
|
||||
ConnectionError::Io(..) => Some(Cause::Io),
|
||||
_ => panic!("cannot terminate stream with user error"),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Indicates that the local side will not send more data to the local.
|
||||
pub fn send_close(&mut self) -> Result<(), ConnectionError> {
|
||||
match self.inner {
|
||||
@@ -225,6 +244,21 @@ impl State {
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ensure_recv_open(&self) -> Result<(), ConnectionError> {
|
||||
use std::io;
|
||||
|
||||
// TODO: Is this correct?
|
||||
match self.inner {
|
||||
Closed(Some(Cause::Proto(reason))) => {
|
||||
Err(ConnectionError::Proto(reason))
|
||||
}
|
||||
Closed(Some(Cause::Io)) => {
|
||||
Err(ConnectionError::Io(io::ErrorKind::BrokenPipe.into()))
|
||||
}
|
||||
_ => Ok(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for State {
|
||||
|
||||
@@ -90,6 +90,14 @@ impl<B> Store<B> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn for_each<F>(&mut self, mut f: F)
|
||||
where F: FnMut(&mut Stream<B>)
|
||||
{
|
||||
for &id in self.ids.values() {
|
||||
f(&mut self.slab[id])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ===== impl Ptr =====
|
||||
@@ -142,7 +150,7 @@ impl<'a, B> OccupiedEntry<'a, B> {
|
||||
}
|
||||
|
||||
// ===== impl VacantEntry =====
|
||||
//
|
||||
|
||||
impl<'a, B> VacantEntry<'a, B> {
|
||||
pub fn insert(self, value: Stream<B>) -> Key {
|
||||
// Insert the value in the slab
|
||||
|
||||
@@ -141,6 +141,14 @@ impl<P, B> Streams<P, B>
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
pub fn recv_err(&mut self, err: &ConnectionError) {
|
||||
let mut me = self.inner.lock().unwrap();
|
||||
let me = &mut *me;
|
||||
|
||||
let actions = &mut me.actions;
|
||||
me.store.for_each(|stream| actions.recv.recv_err(err, stream));
|
||||
}
|
||||
|
||||
pub fn recv_window_update(&mut self, frame: frame::WindowUpdate)
|
||||
-> Result<(), ConnectionError> {
|
||||
let id = frame.stream_id();
|
||||
|
||||
Reference in New Issue
Block a user