A lot of structural work
This commit is contained in:
@@ -6,7 +6,7 @@ mod store;
|
||||
mod stream;
|
||||
mod streams;
|
||||
|
||||
pub use self::streams::Streams;
|
||||
pub use self::streams::{Streams, Stream};
|
||||
|
||||
use self::flow_control::FlowControl;
|
||||
use self::recv::Recv;
|
||||
@@ -19,6 +19,8 @@ use proto::*;
|
||||
use error::Reason::*;
|
||||
use error::User::*;
|
||||
|
||||
use http::{Request, Response};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Config {
|
||||
/// Maximum number of remote initiated streams
|
||||
|
||||
@@ -17,6 +17,9 @@ pub struct Send<P> {
|
||||
/// 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,
|
||||
|
||||
@@ -37,9 +40,16 @@ pub struct Send<P> {
|
||||
|
||||
impl<P: Peer> Send<P> {
|
||||
pub fn new(config: &Config) -> Self {
|
||||
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,
|
||||
flow_control: FlowControl::new(config.init_local_window_sz),
|
||||
pending_window_updates: VecDeque::new(),
|
||||
@@ -51,8 +61,8 @@ impl<P: Peer> Send<P> {
|
||||
/// Update state reflecting a new, locally opened stream
|
||||
///
|
||||
/// Returns the stream state if successful. `None` if refused
|
||||
pub fn open(&mut self, id: StreamId) -> Result<State, ConnectionError> {
|
||||
try!(self.ensure_can_open(id));
|
||||
pub fn open(&mut self) -> Result<(StreamId, State), ConnectionError> {
|
||||
try!(self.ensure_can_open());
|
||||
|
||||
if let Some(max) = self.max_streams {
|
||||
if max <= self.num_streams {
|
||||
@@ -60,10 +70,13 @@ impl<P: Peer> Send<P> {
|
||||
}
|
||||
}
|
||||
|
||||
let ret = (self.next_stream_id, State::default());
|
||||
|
||||
// Increment the number of locally initiated streams
|
||||
self.num_streams += 1;
|
||||
self.next_stream_id.increment();
|
||||
|
||||
Ok(State::default())
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
pub fn send_headers(&mut self, state: &mut State, eos: bool)
|
||||
@@ -191,15 +204,13 @@ impl<P: Peer> Send<P> {
|
||||
}
|
||||
|
||||
/// Returns true if the local actor can initiate a stream with the given ID.
|
||||
fn ensure_can_open(&self, id: StreamId) -> Result<(), ConnectionError> {
|
||||
fn ensure_can_open(&self) -> Result<(), ConnectionError> {
|
||||
if P::is_server() {
|
||||
// Servers cannot open streams. PushPromise must first be reserved.
|
||||
return Err(UnexpectedFrameType.into());
|
||||
}
|
||||
|
||||
if !id.is_client_initiated() {
|
||||
return Err(InvalidStreamId.into());
|
||||
}
|
||||
// TODO: Handle StreamId overflow
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -42,6 +42,11 @@ impl Store {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, id: StreamId, val: State) {
|
||||
let handle = self.slab.insert(val);
|
||||
assert!(self.ids.insert(id, handle).is_none());
|
||||
}
|
||||
|
||||
pub fn entry(&mut self, id: StreamId) -> Entry {
|
||||
use self::hash_map::Entry::*;
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use client;
|
||||
use proto::*;
|
||||
use super::*;
|
||||
|
||||
@@ -10,6 +11,12 @@ pub struct Streams<P> {
|
||||
inner: Arc<Mutex<Inner<P>>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Stream<P> {
|
||||
inner: Arc<Mutex<Inner<P>>>,
|
||||
id: StreamId,
|
||||
}
|
||||
|
||||
/// Fields needed to manage state related to managing the set of streams. This
|
||||
/// is mostly split out to make ownership happy.
|
||||
///
|
||||
@@ -139,28 +146,22 @@ impl<P: Peer> Streams<P> {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
pub fn send_headers(&mut self, frame: &frame::Headers)
|
||||
pub fn send_headers(&mut self, headers: frame::Headers)
|
||||
-> Result<(), ConnectionError>
|
||||
{
|
||||
unimplemented!();
|
||||
/*
|
||||
let id = frame.stream_id();
|
||||
let mut me = self.inner.lock().unwrap();
|
||||
let me = &mut *me;
|
||||
|
||||
trace!("send_headers; id={:?}", id);
|
||||
// let (id, state) = me.actions.send.open());
|
||||
|
||||
|
||||
let state = match me.store.entry(id) {
|
||||
Entry::Occupied(e) => e.into_mut(),
|
||||
Entry::Vacant(e) => {
|
||||
// Trailers cannot open a stream. Trailers are header frames
|
||||
// that do not contain pseudo headers. Requests MUST contain a
|
||||
// method and responses MUST contain a status. If they do not,t
|
||||
// hey are considered to be malformed.
|
||||
if frame.is_trailers() {
|
||||
// TODO: Should this be a different error?
|
||||
return Err(UnexpectedFrameType.into());
|
||||
}
|
||||
|
||||
let state = try!(me.actions.send.open(id));
|
||||
let (id, state) = try!(me.actions.send.open());
|
||||
e.insert(state)
|
||||
}
|
||||
};
|
||||
@@ -176,6 +177,7 @@ impl<P: Peer> Streams<P> {
|
||||
}
|
||||
|
||||
Ok(())
|
||||
*/
|
||||
}
|
||||
|
||||
pub fn send_data<B: Buf>(&mut self, frame: &frame::Data<B>)
|
||||
@@ -250,6 +252,40 @@ impl<P: Peer> Streams<P> {
|
||||
}
|
||||
}
|
||||
|
||||
impl Streams<client::Peer> {
|
||||
pub fn send_request(&mut self, request: Request<()>, end_of_stream: bool)
|
||||
-> Result<Stream<client::Peer>, ConnectionError>
|
||||
{
|
||||
let id = {
|
||||
let mut me = self.inner.lock().unwrap();
|
||||
let me = &mut *me;
|
||||
|
||||
// Initialize a new stream. This fails if the connection is at capacity.
|
||||
let (id, mut state) = me.actions.send.open()?;
|
||||
|
||||
// Convert the message
|
||||
let headers = client::Peer::convert_send_message(
|
||||
id, request, end_of_stream);
|
||||
|
||||
me.actions.send.send_headers(&mut state, end_of_stream)?;
|
||||
|
||||
// Given that the stream has been initialized, it should not be in the
|
||||
// closed state.
|
||||
debug_assert!(!state.is_closed());
|
||||
|
||||
// Store the state
|
||||
me.store.insert(id, state);
|
||||
|
||||
id
|
||||
};
|
||||
|
||||
Ok(Stream {
|
||||
inner: self.inner.clone(),
|
||||
id: id,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Peer> Actions<P> {
|
||||
fn dec_num_streams(&mut self, id: StreamId) {
|
||||
if self.is_local_init(id) {
|
||||
|
||||
Reference in New Issue
Block a user