Ref count stream state and release when final (#73)

Previously, stream state was never released so that long-lived connections
leaked memory.

Now, stream states are reference-counted and freed from the stream slab
when complete.  Locally reset streams are retained so that received frames
may be ignored.
This commit is contained in:
Carl Lerche
2017-09-10 16:01:19 -07:00
committed by Oliver Gould
parent daa54b9512
commit 5c0efcf8c4
15 changed files with 542 additions and 190 deletions

View File

@@ -1,4 +1,3 @@
use client;
use frame::{self, Reason};
use codec::{RecvError, UserError};
use codec::UserError::*;
@@ -14,21 +13,12 @@ use std::io;
pub(super) struct Send<B, P>
where P: Peer,
{
/// Maximum number of locally initiated streams
max_streams: Option<usize>,
/// Current number of locally initiated streams
num_streams: usize,
/// Stream identifier to use for next initialized stream.
next_stream_id: StreamId,
/// Initial window size of locally initiated streams
init_window_sz: WindowSize,
/// Task awaiting notification to open a new stream.
blocked_open: Option<task::Task>,
/// Prioritization layer
prioritize: Prioritize<B, P>,
}
@@ -42,11 +32,8 @@ where B: Buf,
let next_stream_id = if P::is_server() { 2 } else { 1 };
Send {
max_streams: config.max_local_initiated,
num_streams: 0,
next_stream_id: next_stream_id.into(),
init_window_sz: config.init_local_window_sz,
blocked_open: None,
prioritize: Prioritize::new(config),
}
}
@@ -59,22 +46,20 @@ where B: Buf,
/// Update state reflecting a new, locally opened stream
///
/// Returns the stream state if successful. `None` if refused
pub fn open(&mut self)
pub fn open(&mut self, counts: &mut Counts<P>)
-> Result<StreamId, UserError>
{
try!(self.ensure_can_open());
if let Some(max) = self.max_streams {
if max <= self.num_streams {
return Err(Rejected.into());
}
if !counts.can_inc_num_send_streams() {
return Err(Rejected.into());
}
let ret = self.next_stream_id;
self.next_stream_id.increment();
// Increment the number of locally initiated streams
self.num_streams += 1;
self.next_stream_id.increment();
counts.inc_num_send_streams();
Ok(ret)
}
@@ -167,11 +152,12 @@ where B: Buf,
pub fn poll_complete<T>(&mut self,
store: &mut Store<B, P>,
counts: &mut Counts<P>,
dst: &mut Codec<T, Prioritized<B>>)
-> Poll<(), io::Error>
where T: AsyncWrite,
{
self.prioritize.poll_complete(store, dst)
self.prioritize.poll_complete(store, counts, dst)
}
/// Request capacity to send data
@@ -237,10 +223,6 @@ where B: Buf,
task: &mut Option<Task>)
-> Result<(), RecvError>
{
if let Some(val) = settings.max_concurrent_streams() {
self.max_streams = Some(val as usize);
}
// Applies an update to the remote endpoint's initial window size.
//
// Per RFC 7540 §6.9.2:
@@ -304,16 +286,6 @@ where B: Buf,
Ok(())
}
pub fn dec_num_streams(&mut self) {
self.num_streams -= 1;
if self.num_streams < self.max_streams.unwrap_or(::std::usize::MAX) {
if let Some(task) = self.blocked_open.take() {
task.notify();
}
}
}
/// Returns true if the local actor can initiate a stream with the given ID.
fn ensure_can_open(&self) -> Result<(), UserError> {
if P::is_server() {
@@ -326,18 +298,3 @@ where B: Buf,
Ok(())
}
}
impl<B> Send<B, client::Peer>
where B: Buf,
{
pub fn poll_open_ready(&mut self) -> Async<()> {
if let Some(max) = self.max_streams {
if max <= self.num_streams {
self.blocked_open = Some(task::current());
return Async::NotReady;
}
}
return Async::Ready(());
}
}