Add Graceful Shutdown support

If graceful shutdown is initiated, a GOAWAY of the max stream ID - 1 is
sent, followed by a PING frame, to measure RTT. When the PING is ACKed,
the connection sends a new GOAWAY with the proper last processed stream
ID. From there, once all active streams have completely, the connection
will finally close.
This commit is contained in:
Sean McArthur
2018-03-29 11:54:45 -07:00
parent 01d81b46c2
commit 1c5d4ded50
11 changed files with 483 additions and 92 deletions

View File

@@ -127,6 +127,11 @@ where
let mut me = self.inner.lock().unwrap();
let me = &mut *me;
if id > me.actions.recv.max_stream_id() {
trace!("id ({:?}) > max_stream_id ({:?}), ignoring HEADERS", id, me.actions.recv.max_stream_id());
return Ok(());
}
let key = match me.store.find_entry(id) {
Entry::Occupied(e) => e.key(),
Entry::Vacant(e) => match me.actions.recv.open(id, &mut me.counts)? {
@@ -209,6 +214,11 @@ where
let stream = match me.store.find_mut(&id) {
Some(stream) => stream,
None => {
if id > me.actions.recv.max_stream_id() {
trace!("id ({:?}) > max_stream_id ({:?}), ignoring DATA", id, me.actions.recv.max_stream_id());
return Ok(());
}
trace!("recv_data; stream not found: {:?}", id);
return Err(RecvError::Connection(Reason::PROTOCOL_ERROR));
},
@@ -243,6 +253,11 @@ where
return Err(RecvError::Connection(Reason::PROTOCOL_ERROR));
}
if id > me.actions.recv.max_stream_id() {
trace!("id ({:?}) > max_stream_id ({:?}), ignoring RST_STREAM", id, me.actions.recv.max_stream_id());
return Ok(());
}
let stream = match me.store.find_mut(&id) {
Some(stream) => stream,
None => {
@@ -295,7 +310,7 @@ where
last_processed_id
}
pub fn recv_goaway(&mut self, frame: &frame::GoAway) {
pub fn recv_go_away(&mut self, frame: &frame::GoAway) {
let mut me = self.inner.lock().unwrap();
let me = &mut *me;
@@ -307,6 +322,8 @@ where
let last_stream_id = frame.last_stream_id();
let err = frame.reason().into();
actions.recv.go_away(last_stream_id);
me.store
.for_each(|stream| if stream.id > last_stream_id {
counts.transition(stream, |_, stream| {
@@ -631,6 +648,13 @@ where
actions.recv.enqueue_reset_expiration(stream, counts)
})
}
pub fn send_go_away(&mut self, last_processed_id: StreamId) {
let mut me = self.inner.lock().unwrap();
let me = &mut *me;
let actions = &mut me.actions;
actions.recv.go_away(last_processed_id);
}
}
impl<B> Streams<B, client::Peer>