Wire in PushPromise
This commit is contained in:
@@ -320,6 +320,14 @@ impl PushPromise {
|
|||||||
flags: flags,
|
flags: flags,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn stream_id(&self) -> StreamId {
|
||||||
|
self.stream_id
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn promised_id(&self) -> StreamId {
|
||||||
|
self.promised_id
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> From<PushPromise> for Frame<T> {
|
impl<T> From<PushPromise> for Frame<T> {
|
||||||
|
|||||||
@@ -155,11 +155,8 @@ impl<T, P, B> Connection<T, P, B>
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
Some(PushPromise(frame)) => {
|
Some(PushPromise(frame)) => {
|
||||||
// TODO: implement
|
|
||||||
/*
|
|
||||||
trace!("recv PUSH_PROMISE; frame={:?}", frame);
|
trace!("recv PUSH_PROMISE; frame={:?}", frame);
|
||||||
try!(self.streams.recv_push_promise(frame));
|
self.streams.recv_push_promise(frame)?;
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
Some(Settings(frame)) => {
|
Some(Settings(frame)) => {
|
||||||
trace!("recv SETTINGS; frame={:?}", frame);
|
trace!("recv SETTINGS; frame={:?}", frame);
|
||||||
|
|||||||
@@ -2,24 +2,18 @@ use super::*;
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(super) struct Prioritize<B> {
|
pub(super) struct Prioritize<B> {
|
||||||
pending_send: Option<Indices>,
|
pending_send: store::List<B>,
|
||||||
|
|
||||||
/// Holds frames that are waiting to be written to the socket
|
/// Holds frames that are waiting to be written to the socket
|
||||||
buffer: Buffer<B>,
|
buffer: Buffer<B>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
struct Indices {
|
|
||||||
head: store::Key,
|
|
||||||
tail: store::Key,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<B> Prioritize<B>
|
impl<B> Prioritize<B>
|
||||||
where B: Buf,
|
where B: Buf,
|
||||||
{
|
{
|
||||||
pub fn new() -> Prioritize<B> {
|
pub fn new() -> Prioritize<B> {
|
||||||
Prioritize {
|
Prioritize {
|
||||||
pending_send: None,
|
pending_send: store::List::new(),
|
||||||
buffer: Buffer::new(),
|
buffer: Buffer::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -32,7 +26,7 @@ impl<B> Prioritize<B>
|
|||||||
stream.pending_send.push_back(&mut self.buffer, frame);
|
stream.pending_send.push_back(&mut self.buffer, frame);
|
||||||
|
|
||||||
if stream.is_pending_send {
|
if stream.is_pending_send {
|
||||||
debug_assert!(self.pending_send.is_some());
|
debug_assert!(!self.pending_send.is_empty());
|
||||||
|
|
||||||
// Already queued to have frame processed.
|
// Already queued to have frame processed.
|
||||||
return;
|
return;
|
||||||
@@ -84,44 +78,20 @@ impl<B> Prioritize<B>
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn push_sender(&mut self, stream: &mut store::Ptr<B>) {
|
fn push_sender(&mut self, stream: &mut store::Ptr<B>) {
|
||||||
// The next pointer shouldn't be set
|
debug_assert!(!stream.is_pending_send);
|
||||||
debug_assert!(stream.next_pending_send.is_none());
|
|
||||||
|
|
||||||
// Queue the stream
|
self.pending_send.push(stream);
|
||||||
match self.pending_send {
|
|
||||||
Some(ref mut idxs) => {
|
|
||||||
// Update the current tail node to point to `stream`
|
|
||||||
stream.resolve(idxs.tail).next_pending_send = Some(stream.key());
|
|
||||||
|
|
||||||
// Update the tail pointer
|
|
||||||
idxs.tail = stream.key();
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
self.pending_send = Some(Indices {
|
|
||||||
head: stream.key(),
|
|
||||||
tail: stream.key(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stream.is_pending_send = true;
|
stream.is_pending_send = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pop_sender<'a>(&mut self, store: &'a mut Store<B>) -> Option<store::Ptr<'a, B>> {
|
fn pop_sender<'a>(&mut self, store: &'a mut Store<B>) -> Option<store::Ptr<'a, B>> {
|
||||||
if let Some(mut idxs) = self.pending_send {
|
match self.pending_send.pop(store) {
|
||||||
let mut stream = store.resolve(idxs.head);
|
Some(mut stream) => {
|
||||||
|
stream.is_pending_send = false;
|
||||||
if idxs.head == idxs.tail {
|
Some(stream)
|
||||||
assert!(stream.next_pending_send.is_none());
|
}
|
||||||
self.pending_send = None;
|
None => None,
|
||||||
} else {
|
|
||||||
idxs.head = stream.next_pending_send.take().unwrap();
|
|
||||||
self.pending_send = Some(idxs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Some(stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ pub(super) struct Recv<P, B> {
|
|||||||
/// Connection level flow control governing received data
|
/// Connection level flow control governing received data
|
||||||
flow_control: FlowControl,
|
flow_control: FlowControl,
|
||||||
|
|
||||||
|
/// Streams that have pending window updates
|
||||||
|
/// TODO: don't use a VecDeque
|
||||||
pending_window_updates: VecDeque<StreamId>,
|
pending_window_updates: VecDeque<StreamId>,
|
||||||
|
|
||||||
/// Holds frames that are waiting to be read
|
/// Holds frames that are waiting to be read
|
||||||
@@ -38,6 +40,12 @@ pub(super) struct Chunk {
|
|||||||
pub pending_recv: buffer::Deque<Bytes>,
|
pub pending_recv: buffer::Deque<Bytes>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
struct Indices {
|
||||||
|
head: store::Key,
|
||||||
|
tail: store::Key,
|
||||||
|
}
|
||||||
|
|
||||||
impl<P, B> Recv<P, B>
|
impl<P, B> Recv<P, B>
|
||||||
where P: Peer,
|
where P: Peer,
|
||||||
B: Buf,
|
B: Buf,
|
||||||
@@ -63,15 +71,10 @@ impl<P, B> Recv<P, B>
|
|||||||
|
|
||||||
try!(self.ensure_can_open(id));
|
try!(self.ensure_can_open(id));
|
||||||
|
|
||||||
if let Some(max) = self.max_streams {
|
if !self.can_inc_num_streams() {
|
||||||
if max <= self.num_streams {
|
|
||||||
self.refused = Some(id);
|
self.refused = Some(id);
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Increment the number of remote initiated streams
|
|
||||||
self.num_streams += 1;
|
|
||||||
|
|
||||||
Ok(Some(Stream::new(id)))
|
Ok(Some(Stream::new(id)))
|
||||||
}
|
}
|
||||||
@@ -82,7 +85,16 @@ impl<P, B> Recv<P, B>
|
|||||||
stream: &mut store::Ptr<B>)
|
stream: &mut store::Ptr<B>)
|
||||||
-> Result<Option<frame::Headers>, ConnectionError>
|
-> Result<Option<frame::Headers>, ConnectionError>
|
||||||
{
|
{
|
||||||
stream.state.recv_open(self.init_window_sz, frame.is_end_stream())?;
|
let is_initial = stream.state.recv_open(self.init_window_sz, frame.is_end_stream())?;
|
||||||
|
|
||||||
|
if is_initial {
|
||||||
|
if !self.can_inc_num_streams() {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increment the number of concurrent streams
|
||||||
|
self.inc_num_streams();
|
||||||
|
}
|
||||||
|
|
||||||
// Only servers can receive a headers frame that initiates the stream.
|
// Only servers can receive a headers frame that initiates the stream.
|
||||||
// This is verified in `Streams` before calling this function.
|
// This is verified in `Streams` before calling this function.
|
||||||
@@ -105,7 +117,7 @@ impl<P, B> Recv<P, B>
|
|||||||
|
|
||||||
pub fn recv_data(&mut self,
|
pub fn recv_data(&mut self,
|
||||||
frame: frame::Data,
|
frame: frame::Data,
|
||||||
stream: &mut Stream<B>)
|
stream: &mut store::Ptr<B>)
|
||||||
-> Result<(), ConnectionError>
|
-> Result<(), ConnectionError>
|
||||||
{
|
{
|
||||||
let sz = frame.payload().len();
|
let sz = frame.payload().len();
|
||||||
@@ -143,6 +155,48 @@ impl<P, B> Recv<P, B>
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn recv_push_promise(&mut self, frame: frame::PushPromise, stream: &mut store::Ptr<B>)
|
||||||
|
-> Result<(), ConnectionError>
|
||||||
|
{
|
||||||
|
// First, make sure that the values are legit
|
||||||
|
self.ensure_can_reserve(frame.promised_id())?;
|
||||||
|
|
||||||
|
// Make sure that the stream state is valid
|
||||||
|
stream.state.ensure_recv_open()?;
|
||||||
|
|
||||||
|
// TODO: Streams in the reserved states do not count towards the concurrency
|
||||||
|
// limit. However, it seems like there should be a cap otherwise this
|
||||||
|
// could grow in memory indefinitely.
|
||||||
|
|
||||||
|
/*
|
||||||
|
if !self.inc_num_streams() {
|
||||||
|
self.refused = Some(frame.promised_id());
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TODO: All earlier stream IDs should be implicitly closed.
|
||||||
|
|
||||||
|
// Now, create a new entry for the stream
|
||||||
|
let mut new_stream = Stream::new(frame.promised_id());
|
||||||
|
new_stream.state.reserve_remote();
|
||||||
|
|
||||||
|
let mut ppp = stream.pending_push_promises.take();
|
||||||
|
|
||||||
|
{
|
||||||
|
// Store the stream
|
||||||
|
let mut new_stream = stream.store()
|
||||||
|
.insert(frame.promised_id(), new_stream);
|
||||||
|
|
||||||
|
ppp.push(&mut new_stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.pending_push_promises = ppp;
|
||||||
|
stream.notify_recv();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn recv_err(&mut self, err: &ConnectionError, stream: &mut Stream<B>) {
|
pub fn recv_err(&mut self, err: &ConnectionError, stream: &mut Stream<B>) {
|
||||||
// Receive an error
|
// Receive an error
|
||||||
stream.state.recv_err(err);
|
stream.state.recv_err(err);
|
||||||
@@ -151,6 +205,26 @@ impl<P, B> Recv<P, B>
|
|||||||
stream.notify_recv();
|
stream.notify_recv();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if the current stream concurrency can be incremetned
|
||||||
|
fn can_inc_num_streams(&self) -> bool {
|
||||||
|
if let Some(max) = self.max_streams {
|
||||||
|
max > self.num_streams
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Increments the number of concurrenty streams. Panics on failure as this
|
||||||
|
/// should have been validated before hand.
|
||||||
|
fn inc_num_streams(&mut self) {
|
||||||
|
if !self.can_inc_num_streams() {
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increment the number of remote initiated streams
|
||||||
|
self.num_streams += 1;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn dec_num_streams(&mut self) {
|
pub fn dec_num_streams(&mut self) {
|
||||||
self.num_streams -= 1;
|
self.num_streams -= 1;
|
||||||
}
|
}
|
||||||
@@ -171,6 +245,21 @@ impl<P, B> Recv<P, B>
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if the remote peer can reserve a stream with the given ID.
|
||||||
|
fn ensure_can_reserve(&self, promised_id: StreamId) -> Result<(), ConnectionError> {
|
||||||
|
// TODO: Are there other rules?
|
||||||
|
if P::is_server() {
|
||||||
|
// The remote is a client and cannot reserve
|
||||||
|
return Err(ProtocolError.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
if !promised_id.is_server_initiated() {
|
||||||
|
return Err(ProtocolError.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Send any pending refusals.
|
/// Send any pending refusals.
|
||||||
pub fn send_pending_refusal<T>(&mut self, dst: &mut Codec<T, B>)
|
pub fn send_pending_refusal<T>(&mut self, dst: &mut Codec<T, B>)
|
||||||
-> Poll<(), ConnectionError>
|
-> Poll<(), ConnectionError>
|
||||||
@@ -206,7 +295,7 @@ impl<P, B> Recv<P, B>
|
|||||||
pub fn expand_stream_window(&mut self,
|
pub fn expand_stream_window(&mut self,
|
||||||
id: StreamId,
|
id: StreamId,
|
||||||
sz: WindowSize,
|
sz: WindowSize,
|
||||||
stream: &mut Stream<B>)
|
stream: &mut store::Ptr<B>)
|
||||||
-> Result<(), ConnectionError>
|
-> Result<(), ConnectionError>
|
||||||
{
|
{
|
||||||
// TODO: handle overflow
|
// TODO: handle overflow
|
||||||
@@ -276,7 +365,7 @@ impl<P, B> Recv<P, B>
|
|||||||
{
|
{
|
||||||
while let Some(id) = self.pending_window_updates.pop_front() {
|
while let Some(id) = self.pending_window_updates.pop_front() {
|
||||||
let flow = streams.find_mut(&id)
|
let flow = streams.find_mut(&id)
|
||||||
.and_then(|stream| stream.recv_flow_control());
|
.and_then(|stream| stream.into_mut().recv_flow_control());
|
||||||
|
|
||||||
|
|
||||||
if let Some(flow) = flow {
|
if let Some(flow) = flow {
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ impl<P, B> Send<P, B>
|
|||||||
let update = self.pending_window_updates.pop_front()
|
let update = self.pending_window_updates.pop_front()
|
||||||
.and_then(|id| {
|
.and_then(|id| {
|
||||||
streams.find_mut(&id)
|
streams.find_mut(&id)
|
||||||
.and_then(|stream| stream.send_flow_control())
|
.and_then(|stream| stream.into_mut().send_flow_control())
|
||||||
.and_then(|flow| flow.apply_window_update())
|
.and_then(|flow| flow.apply_window_update())
|
||||||
.map(|incr| WindowUpdate::new(id, incr))
|
.map(|incr| WindowUpdate::new(id, incr))
|
||||||
});
|
});
|
||||||
@@ -209,7 +209,7 @@ impl<P, B> Send<P, B>
|
|||||||
|
|
||||||
pub fn recv_stream_window_update(&mut self,
|
pub fn recv_stream_window_update(&mut self,
|
||||||
frame: frame::WindowUpdate,
|
frame: frame::WindowUpdate,
|
||||||
stream: &mut Stream<B>)
|
stream: &mut store::Ptr<B>)
|
||||||
-> Result<(), ConnectionError>
|
-> Result<(), ConnectionError>
|
||||||
{
|
{
|
||||||
if let Some(flow) = stream.send_flow_control() {
|
if let Some(flow) = stream.send_flow_control() {
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ enum Inner {
|
|||||||
Idle,
|
Idle,
|
||||||
// TODO: these states shouldn't count against concurrency limits:
|
// TODO: these states shouldn't count against concurrency limits:
|
||||||
//ReservedLocal,
|
//ReservedLocal,
|
||||||
//ReservedRemote,
|
ReservedRemote,
|
||||||
Open {
|
Open {
|
||||||
local: Peer,
|
local: Peer,
|
||||||
remote: Peer,
|
remote: Peer,
|
||||||
@@ -126,11 +126,16 @@ impl State {
|
|||||||
|
|
||||||
/// Open the receive have of the stream, this action is taken when a HEADERS
|
/// Open the receive have of the stream, this action is taken when a HEADERS
|
||||||
/// frame is received.
|
/// frame is received.
|
||||||
pub fn recv_open(&mut self, sz: WindowSize, eos: bool) -> Result<(), ConnectionError> {
|
///
|
||||||
|
/// Returns true if this transitions the state to Open
|
||||||
|
pub fn recv_open(&mut self, sz: WindowSize, eos: bool) -> Result<bool, ConnectionError> {
|
||||||
let remote = Peer::streaming(sz);
|
let remote = Peer::streaming(sz);
|
||||||
|
let mut initial = false;
|
||||||
|
|
||||||
self.inner = match self.inner {
|
self.inner = match self.inner {
|
||||||
Idle => {
|
Idle => {
|
||||||
|
initial = true;
|
||||||
|
|
||||||
if eos {
|
if eos {
|
||||||
HalfClosedRemote(AwaitingHeaders)
|
HalfClosedRemote(AwaitingHeaders)
|
||||||
} else {
|
} else {
|
||||||
@@ -140,6 +145,18 @@ impl State {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ReservedRemote => {
|
||||||
|
initial = true;
|
||||||
|
|
||||||
|
if eos {
|
||||||
|
Closed(None)
|
||||||
|
} else {
|
||||||
|
Open {
|
||||||
|
local: AwaitingHeaders,
|
||||||
|
remote,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Open { local, remote: AwaitingHeaders } => {
|
Open { local, remote: AwaitingHeaders } => {
|
||||||
if eos {
|
if eos {
|
||||||
HalfClosedRemote(local)
|
HalfClosedRemote(local)
|
||||||
@@ -163,7 +180,18 @@ impl State {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return Ok(());
|
return Ok(initial);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Transition from Idle -> ReservedRemote
|
||||||
|
pub fn reserve_remote(&mut self) -> Result<(), ConnectionError> {
|
||||||
|
match self.inner {
|
||||||
|
Idle => {
|
||||||
|
self.inner = ReservedRemote;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
_ => Err(ProtocolError.into()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Indicates that the remote side will not send more data to the local.
|
/// Indicates that the remote side will not send more data to the local.
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use slab;
|
|||||||
|
|
||||||
use std::ops;
|
use std::ops;
|
||||||
use std::collections::{HashMap, hash_map};
|
use std::collections::{HashMap, hash_map};
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
/// Storage for streams
|
/// Storage for streams
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -22,6 +23,19 @@ pub(super) struct Ptr<'a, B: 'a> {
|
|||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub(super) struct Key(usize);
|
pub(super) struct Key(usize);
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub(super) struct List<B> {
|
||||||
|
indices: Option<store::Indices>,
|
||||||
|
_p: PhantomData<B>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A linked list
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
struct Indices {
|
||||||
|
pub head: Key,
|
||||||
|
pub tail: Key,
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) enum Entry<'a, B: 'a> {
|
pub(super) enum Entry<'a, B: 'a> {
|
||||||
Occupied(OccupiedEntry<'a, B>),
|
Occupied(OccupiedEntry<'a, B>),
|
||||||
Vacant(VacantEntry<'a, B>),
|
Vacant(VacantEntry<'a, B>),
|
||||||
@@ -54,9 +68,12 @@ impl<B> Store<B> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_mut(&mut self, id: &StreamId) -> Option<&mut Stream<B>> {
|
pub fn find_mut(&mut self, id: &StreamId) -> Option<Ptr<B>> {
|
||||||
if let Some(handle) = self.ids.get(id) {
|
if let Some(&key) = self.ids.get(id) {
|
||||||
Some(&mut self.slab[*handle])
|
Some(Ptr {
|
||||||
|
key: Key(key),
|
||||||
|
store: self,
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@@ -100,6 +117,68 @@ impl<B> Store<B> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ===== impl List =====
|
||||||
|
|
||||||
|
impl<B> List<B> {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
List {
|
||||||
|
indices: None,
|
||||||
|
_p: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_empty(&self) -> bool {
|
||||||
|
self.indices.is_none()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn take(&mut self) -> Self {
|
||||||
|
List {
|
||||||
|
indices: self.indices.take(),
|
||||||
|
_p: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push(&mut self, stream: &mut store::Ptr<B>) {
|
||||||
|
// The next pointer shouldn't be set
|
||||||
|
debug_assert!(stream.next.is_none());
|
||||||
|
|
||||||
|
// Queue the stream
|
||||||
|
match self.indices {
|
||||||
|
Some(ref mut idxs) => {
|
||||||
|
// Update the current tail node to point to `stream`
|
||||||
|
stream.resolve(idxs.tail).next = Some(stream.key());
|
||||||
|
|
||||||
|
// Update the tail pointer
|
||||||
|
idxs.tail = stream.key();
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
self.indices = Some(store::Indices {
|
||||||
|
head: stream.key(),
|
||||||
|
tail: stream.key(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pop<'a>(&mut self, store: &'a mut Store<B>) -> Option<store::Ptr<'a, B>> {
|
||||||
|
if let Some(mut idxs) = self.indices {
|
||||||
|
let mut stream = store.resolve(idxs.head);
|
||||||
|
|
||||||
|
if idxs.head == idxs.tail {
|
||||||
|
assert!(stream.next.is_none());
|
||||||
|
self.indices = None;
|
||||||
|
} else {
|
||||||
|
idxs.head = stream.next.take().unwrap();
|
||||||
|
self.indices = Some(idxs);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Some(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ===== impl Ptr =====
|
// ===== impl Ptr =====
|
||||||
|
|
||||||
impl<'a, B: 'a> Ptr<'a, B> {
|
impl<'a, B: 'a> Ptr<'a, B> {
|
||||||
@@ -107,12 +186,20 @@ impl<'a, B: 'a> Ptr<'a, B> {
|
|||||||
self.key
|
self.key
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn store(&mut self) -> &mut Store<B> {
|
||||||
|
&mut self.store
|
||||||
|
}
|
||||||
|
|
||||||
pub fn resolve(&mut self, key: Key) -> Ptr<B> {
|
pub fn resolve(&mut self, key: Key) -> Ptr<B> {
|
||||||
Ptr {
|
Ptr {
|
||||||
key: key,
|
key: key,
|
||||||
store: self.store,
|
store: self.store,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn into_mut(self) -> &'a mut Stream<B> {
|
||||||
|
&mut self.store.slab[self.key.0]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, B: 'a> ops::Deref for Ptr<'a, B> {
|
impl<'a, B: 'a> ops::Deref for Ptr<'a, B> {
|
||||||
|
|||||||
@@ -17,8 +17,14 @@ pub(super) struct Stream<B> {
|
|||||||
/// Frames pending for this stream being sent to the socket
|
/// Frames pending for this stream being sent to the socket
|
||||||
pub pending_send: buffer::Deque<B>,
|
pub pending_send: buffer::Deque<B>,
|
||||||
|
|
||||||
/// Next stream pending send
|
/// Next node in the `Stream` linked list.
|
||||||
pub next_pending_send: Option<store::Key>,
|
///
|
||||||
|
/// This field is used in different linked lists depending on the stream
|
||||||
|
/// state.
|
||||||
|
pub next: Option<store::Key>,
|
||||||
|
|
||||||
|
/// The stream's pending push promises
|
||||||
|
pub pending_push_promises: store::List<B>,
|
||||||
|
|
||||||
/// True if the stream is currently pending send
|
/// True if the stream is currently pending send
|
||||||
pub is_pending_send: bool,
|
pub is_pending_send: bool,
|
||||||
@@ -32,7 +38,8 @@ impl<B> Stream<B> {
|
|||||||
pending_recv: buffer::Deque::new(),
|
pending_recv: buffer::Deque::new(),
|
||||||
recv_task: None,
|
recv_task: None,
|
||||||
pending_send: buffer::Deque::new(),
|
pending_send: buffer::Deque::new(),
|
||||||
next_pending_send: None,
|
next: None,
|
||||||
|
pending_push_promises: store::List::new(),
|
||||||
is_pending_send: false,
|
is_pending_send: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,14 +119,14 @@ impl<P, B> Streams<P, B>
|
|||||||
let mut me = self.inner.lock().unwrap();
|
let mut me = self.inner.lock().unwrap();
|
||||||
let me = &mut *me;
|
let me = &mut *me;
|
||||||
|
|
||||||
let stream = match me.store.find_mut(&id) {
|
let mut stream = match me.store.find_mut(&id) {
|
||||||
Some(stream) => stream,
|
Some(stream) => stream,
|
||||||
None => return Err(ProtocolError.into()),
|
None => return Err(ProtocolError.into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Ensure there's enough capacity on the connection before acting on the
|
// Ensure there's enough capacity on the connection before acting on the
|
||||||
// stream.
|
// stream.
|
||||||
try!(me.actions.recv.recv_data(frame, stream));
|
try!(me.actions.recv.recv_data(frame, &mut stream));
|
||||||
|
|
||||||
if stream.state.is_closed() {
|
if stream.state.is_closed() {
|
||||||
me.actions.dec_num_streams(id);
|
me.actions.dec_num_streams(id);
|
||||||
@@ -160,18 +160,28 @@ impl<P, B> Streams<P, B>
|
|||||||
} else {
|
} else {
|
||||||
// The remote may send window updates for streams that the local now
|
// The remote may send window updates for streams that the local now
|
||||||
// considers closed. It's ok...
|
// considers closed. It's ok...
|
||||||
if let Some(state) = me.store.find_mut(&id) {
|
if let Some(mut stream) = me.store.find_mut(&id) {
|
||||||
try!(me.actions.send.recv_stream_window_update(frame, state));
|
try!(me.actions.send.recv_stream_window_update(frame, &mut stream));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn recv_push_promise(&mut self, _frame: frame::PushPromise)
|
pub fn recv_push_promise(&mut self, frame: frame::PushPromise)
|
||||||
-> Result<(), ConnectionError>
|
-> Result<(), ConnectionError>
|
||||||
{
|
{
|
||||||
unimplemented!();
|
let mut me = self.inner.lock().unwrap();
|
||||||
|
let me = &mut *me;
|
||||||
|
|
||||||
|
let id = frame.stream_id();
|
||||||
|
|
||||||
|
let mut stream = match me.store.find_mut(&id) {
|
||||||
|
Some(stream) => stream,
|
||||||
|
None => return Err(ProtocolError.into()),
|
||||||
|
};
|
||||||
|
|
||||||
|
me.actions.recv.recv_push_promise(frame, &mut stream)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_headers(&mut self, headers: frame::Headers)
|
pub fn send_headers(&mut self, headers: frame::Headers)
|
||||||
@@ -208,31 +218,6 @@ impl<P, B> Streams<P, B>
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
pub fn send_data(&mut self, frame: &frame::Data<B>)
|
|
||||||
-> Result<(), ConnectionError>
|
|
||||||
{
|
|
||||||
let id = frame.stream_id();
|
|
||||||
let mut me = self.inner.lock().unwrap();
|
|
||||||
let me = &mut *me;
|
|
||||||
|
|
||||||
let stream = match me.store.find_mut(&id) {
|
|
||||||
Some(stream) => stream,
|
|
||||||
None => return Err(UnexpectedFrameType.into()),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Ensure there's enough capacity on the connection before acting on the
|
|
||||||
// stream.
|
|
||||||
try!(me.actions.send.send_data(frame, stream));
|
|
||||||
|
|
||||||
if stream.state.is_closed() {
|
|
||||||
me.actions.dec_num_streams(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
pub fn poll_window_update(&mut self)
|
pub fn poll_window_update(&mut self)
|
||||||
-> Poll<WindowUpdate, ConnectionError>
|
-> Poll<WindowUpdate, ConnectionError>
|
||||||
{
|
{
|
||||||
@@ -250,8 +235,8 @@ impl<P, B> Streams<P, B>
|
|||||||
if id.is_zero() {
|
if id.is_zero() {
|
||||||
try!(me.actions.recv.expand_connection_window(sz));
|
try!(me.actions.recv.expand_connection_window(sz));
|
||||||
} else {
|
} else {
|
||||||
if let Some(state) = me.store.find_mut(&id) {
|
if let Some(mut stream) = me.store.find_mut(&id) {
|
||||||
try!(me.actions.recv.expand_stream_window(id, sz, state));
|
try!(me.actions.recv.expand_stream_window(id, sz, &mut stream));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user