A lot of structural work
This commit is contained in:
112
src/client.rs
112
src/client.rs
@@ -16,13 +16,19 @@ pub struct Handshake<T, B: IntoBuf = Bytes> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Peer;
|
pub(crate) struct Peer;
|
||||||
|
|
||||||
/// Marker type indicating a client peer
|
/// Marker type indicating a client peer
|
||||||
pub struct Client<T, B: IntoBuf> {
|
pub struct Client<T, B: IntoBuf> {
|
||||||
connection: Connection<T, Peer, B>,
|
connection: Connection<T, Peer, B>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Client half of an active HTTP/2.0 stream.
|
||||||
|
pub struct Stream<B: IntoBuf> {
|
||||||
|
inner: proto::Stream<Peer>,
|
||||||
|
_p: ::std::marker::PhantomData<B>,
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> Client<T, Bytes>
|
impl<T> Client<T, Bytes>
|
||||||
where T: AsyncRead + AsyncWrite + 'static,
|
where T: AsyncRead + AsyncWrite + 'static,
|
||||||
{
|
{
|
||||||
@@ -67,11 +73,82 @@ impl<T, B> Client<T, B>
|
|||||||
Handshake { inner: Box::new(handshake) }
|
Handshake { inner: Box::new(handshake) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn request(&mut self) {
|
/// Returns `Ready` when the connection can initialize a new HTTP 2.0
|
||||||
|
/// stream.
|
||||||
|
pub fn poll_ready(&mut self) -> Poll<(), ConnectionError> {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Send a request on a new HTTP 2.0 stream
|
||||||
|
pub fn request(&mut self, request: Request<()>, end_of_stream: bool)
|
||||||
|
-> Result<Stream<B>, ConnectionError>
|
||||||
|
{
|
||||||
|
self.connection.send_request(request, end_of_stream)
|
||||||
|
.map(|stream| Stream {
|
||||||
|
inner: stream,
|
||||||
|
_p: ::std::marker::PhantomData,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, B> fmt::Debug for Client<T, B>
|
||||||
|
where T: fmt::Debug,
|
||||||
|
B: fmt::Debug + IntoBuf,
|
||||||
|
B::Buf: fmt::Debug + IntoBuf,
|
||||||
|
{
|
||||||
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
fmt.debug_struct("Client")
|
||||||
|
.field("connection", &self.connection)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== impl Handshake =====
|
||||||
|
|
||||||
|
impl<T, B: IntoBuf> Future for Handshake<T, B> {
|
||||||
|
type Item = Client<T, B>;
|
||||||
|
type Error = ConnectionError;
|
||||||
|
|
||||||
|
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||||
|
self.inner.poll()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, B> fmt::Debug for Handshake<T, B>
|
||||||
|
where T: fmt::Debug,
|
||||||
|
B: fmt::Debug + IntoBuf,
|
||||||
|
B::Buf: fmt::Debug + IntoBuf,
|
||||||
|
{
|
||||||
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(fmt, "client::Handshake")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== impl Stream =====
|
||||||
|
|
||||||
|
impl<B: IntoBuf> Stream<B> {
|
||||||
|
/// Receive the HTTP/2.0 response, if it is ready.
|
||||||
|
pub fn poll_response(&mut self) -> Poll<(), ConnectionError> {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Send data
|
||||||
|
pub fn send_data(&mut self, data: B, end_of_stream: bool)
|
||||||
|
-> Result<(), ConnectionError>
|
||||||
|
{
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Send trailers
|
||||||
|
pub fn send_trailers(&mut self, trailers: ())
|
||||||
|
-> Result<(), ConnectionError>
|
||||||
|
{
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ===== impl Peer =====
|
||||||
|
|
||||||
impl proto::Peer for Peer {
|
impl proto::Peer for Peer {
|
||||||
type Send = Request<()>;
|
type Send = Request<()>;
|
||||||
type Poll = Response<()>;
|
type Poll = Response<()>;
|
||||||
@@ -109,34 +186,3 @@ impl proto::Peer for Peer {
|
|||||||
.map_err(|_| ProtocolError.into())
|
.map_err(|_| ProtocolError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, B: IntoBuf> Future for Handshake<T, B> {
|
|
||||||
type Item = Client<T, B>;
|
|
||||||
type Error = ConnectionError;
|
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
|
||||||
self.inner.poll()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, B> fmt::Debug for Handshake<T, B>
|
|
||||||
where T: fmt::Debug,
|
|
||||||
B: fmt::Debug + IntoBuf,
|
|
||||||
B::Buf: fmt::Debug + IntoBuf,
|
|
||||||
{
|
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
write!(fmt, "client::Handshake")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, B> fmt::Debug for Client<T, B>
|
|
||||||
where T: fmt::Debug,
|
|
||||||
B: fmt::Debug + IntoBuf,
|
|
||||||
B::Buf: fmt::Debug + IntoBuf,
|
|
||||||
{
|
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
fmt.debug_struct("Client")
|
|
||||||
.field("connection", &self.connection)
|
|
||||||
.finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -39,6 +39,10 @@ impl StreamId {
|
|||||||
pub fn is_zero(&self) -> bool {
|
pub fn is_zero(&self) -> bool {
|
||||||
self.0 == 0
|
self.0 == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn increment(&mut self) {
|
||||||
|
self.0 += 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<u32> for StreamId {
|
impl From<u32> for StreamId {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// #![allow(warnings)]
|
#![allow(warnings)]
|
||||||
#![deny(missing_debug_implementations)]
|
// #![deny(missing_debug_implementations)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate futures;
|
extern crate futures;
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
use {ConnectionError, Frame};
|
use {client, ConnectionError, Frame};
|
||||||
use HeaderMap;
|
use HeaderMap;
|
||||||
use frame::{self, StreamId};
|
use frame::{self, StreamId};
|
||||||
|
|
||||||
use proto::*;
|
use proto::*;
|
||||||
|
|
||||||
use http::{request, response};
|
use http::{Request, Response};
|
||||||
use bytes::{Bytes, IntoBuf};
|
use bytes::{Bytes, IntoBuf};
|
||||||
use tokio_io::{AsyncRead, AsyncWrite};
|
use tokio_io::{AsyncRead, AsyncWrite};
|
||||||
|
|
||||||
@@ -80,6 +80,7 @@ impl<T, P, B> Connection<T, P, B>
|
|||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `Ready` when the connection is ready to receive a frame.
|
||||||
pub fn poll_ready(&mut self) -> Poll<(), ConnectionError> {
|
pub fn poll_ready(&mut self) -> Poll<(), ConnectionError> {
|
||||||
try_ready!(self.poll_send_ready());
|
try_ready!(self.poll_send_ready());
|
||||||
|
|
||||||
@@ -89,6 +90,7 @@ impl<T, P, B> Connection<T, P, B>
|
|||||||
Ok(().into())
|
Ok(().into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
pub fn send_data(self,
|
pub fn send_data(self,
|
||||||
id: StreamId,
|
id: StreamId,
|
||||||
data: B,
|
data: B,
|
||||||
@@ -112,10 +114,7 @@ impl<T, P, B> Connection<T, P, B>
|
|||||||
headers,
|
headers,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
pub fn start_ping(&mut self, _body: PingPayload) -> StartSend<PingPayload, ConnectionError> {
|
|
||||||
unimplemented!();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===== Private =====
|
// ===== Private =====
|
||||||
|
|
||||||
@@ -227,6 +226,13 @@ impl<T, P, B> Connection<T, P, B>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn poll_complete(&mut self) -> Poll<(), ConnectionError> {
|
||||||
|
try_ready!(self.poll_send_ready());
|
||||||
|
try_ready!(self.codec.poll_complete());
|
||||||
|
|
||||||
|
Ok(().into())
|
||||||
|
}
|
||||||
|
|
||||||
fn convert_poll_message(frame: frame::Headers) -> Result<Frame<P::Poll>, ConnectionError> {
|
fn convert_poll_message(frame: frame::Headers) -> Result<Frame<P::Poll>, ConnectionError> {
|
||||||
if frame.is_trailers() {
|
if frame.is_trailers() {
|
||||||
Ok(Frame::Trailers {
|
Ok(Frame::Trailers {
|
||||||
@@ -243,6 +249,18 @@ impl<T, P, B> Connection<T, P, B>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T, B> Connection<T, client::Peer, B>
|
||||||
|
where T: AsyncRead + AsyncWrite,
|
||||||
|
B: IntoBuf,
|
||||||
|
{
|
||||||
|
/// Initialize a new HTTP/2.0 stream and send the message.
|
||||||
|
pub fn send_request(&mut self, request: Request<()>, end_of_stream: bool)
|
||||||
|
-> Result<Stream<client::Peer>, ConnectionError>
|
||||||
|
{
|
||||||
|
self.streams.send_request(request, end_of_stream)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
impl<T, B> Connection<T, Client, B>
|
impl<T, B> Connection<T, Client, B>
|
||||||
where T: AsyncRead + AsyncWrite,
|
where T: AsyncRead + AsyncWrite,
|
||||||
@@ -292,20 +310,7 @@ impl<T, B> Connection<T, Server, B>
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
impl<T, P, B> Stream for Connection<T, P, B>
|
/*
|
||||||
where T: AsyncRead + AsyncWrite,
|
|
||||||
P: Peer,
|
|
||||||
B: IntoBuf,
|
|
||||||
{
|
|
||||||
type Item = Frame<P::Poll>;
|
|
||||||
type Error = ConnectionError;
|
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<Option<Self::Item>, ConnectionError> {
|
|
||||||
// TODO: intercept errors and flag the connection
|
|
||||||
self.recv_frame()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, P, B> Sink for Connection<T, P, B>
|
impl<T, P, B> Sink for Connection<T, P, B>
|
||||||
where T: AsyncRead + AsyncWrite,
|
where T: AsyncRead + AsyncWrite,
|
||||||
P: Peer,
|
P: Peer,
|
||||||
@@ -379,11 +384,5 @@ impl<T, P, B> Sink for Connection<T, P, B>
|
|||||||
// Return success
|
// Return success
|
||||||
Ok(AsyncSink::Ready)
|
Ok(AsyncSink::Ready)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll_complete(&mut self) -> Poll<(), ConnectionError> {
|
|
||||||
try_ready!(self.poll_send_ready());
|
|
||||||
try_ready!(self.codec.poll_complete());
|
|
||||||
|
|
||||||
Ok(().into())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ impl<T: ApplySettings> ApplySettings for FramedRead<T> {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
impl<T> Stream for FramedRead<T>
|
impl<T> futures::Stream for FramedRead<T>
|
||||||
where T: AsyncRead,
|
where T: AsyncRead,
|
||||||
{
|
{
|
||||||
type Item = Frame;
|
type Item = Frame;
|
||||||
|
|||||||
@@ -6,18 +6,18 @@ mod settings;
|
|||||||
mod streams;
|
mod streams;
|
||||||
|
|
||||||
pub use self::connection::Connection;
|
pub use self::connection::Connection;
|
||||||
|
pub use self::streams::{Streams, Stream};
|
||||||
|
|
||||||
use self::framed_read::FramedRead;
|
use self::framed_read::FramedRead;
|
||||||
use self::framed_write::FramedWrite;
|
use self::framed_write::FramedWrite;
|
||||||
use self::ping_pong::PingPong;
|
use self::ping_pong::PingPong;
|
||||||
use self::settings::Settings;
|
use self::settings::Settings;
|
||||||
use self::streams::Streams;
|
|
||||||
|
|
||||||
use {StreamId, ConnectionError};
|
use {StreamId, ConnectionError};
|
||||||
use error::Reason;
|
use error::Reason;
|
||||||
use frame::{self, Frame};
|
use frame::{self, Frame};
|
||||||
|
|
||||||
use futures::*;
|
use futures::{self, task, Poll, Async, AsyncSink, Sink, Stream as Stream2};
|
||||||
use bytes::{Buf, IntoBuf};
|
use bytes::{Buf, IntoBuf};
|
||||||
use tokio_io::{AsyncRead, AsyncWrite};
|
use tokio_io::{AsyncRead, AsyncWrite};
|
||||||
use tokio_io::codec::length_delimited;
|
use tokio_io::codec::length_delimited;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ mod store;
|
|||||||
mod stream;
|
mod stream;
|
||||||
mod streams;
|
mod streams;
|
||||||
|
|
||||||
pub use self::streams::Streams;
|
pub use self::streams::{Streams, Stream};
|
||||||
|
|
||||||
use self::flow_control::FlowControl;
|
use self::flow_control::FlowControl;
|
||||||
use self::recv::Recv;
|
use self::recv::Recv;
|
||||||
@@ -19,6 +19,8 @@ use proto::*;
|
|||||||
use error::Reason::*;
|
use error::Reason::*;
|
||||||
use error::User::*;
|
use error::User::*;
|
||||||
|
|
||||||
|
use http::{Request, Response};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
/// Maximum number of remote initiated streams
|
/// Maximum number of remote initiated streams
|
||||||
|
|||||||
@@ -17,6 +17,9 @@ pub struct Send<P> {
|
|||||||
/// Current number of locally initiated streams
|
/// Current number of locally initiated streams
|
||||||
num_streams: usize,
|
num_streams: usize,
|
||||||
|
|
||||||
|
/// Stream identifier to use for next initialized stream.
|
||||||
|
next_stream_id: StreamId,
|
||||||
|
|
||||||
/// Initial window size of locally initiated streams
|
/// Initial window size of locally initiated streams
|
||||||
init_window_sz: WindowSize,
|
init_window_sz: WindowSize,
|
||||||
|
|
||||||
@@ -37,9 +40,16 @@ pub struct Send<P> {
|
|||||||
|
|
||||||
impl<P: Peer> Send<P> {
|
impl<P: Peer> Send<P> {
|
||||||
pub fn new(config: &Config) -> Self {
|
pub fn new(config: &Config) -> Self {
|
||||||
|
let next_stream_id = if P::is_server() {
|
||||||
|
2
|
||||||
|
} else {
|
||||||
|
1
|
||||||
|
};
|
||||||
|
|
||||||
Send {
|
Send {
|
||||||
max_streams: config.max_local_initiated,
|
max_streams: config.max_local_initiated,
|
||||||
num_streams: 0,
|
num_streams: 0,
|
||||||
|
next_stream_id: next_stream_id.into(),
|
||||||
init_window_sz: config.init_local_window_sz,
|
init_window_sz: config.init_local_window_sz,
|
||||||
flow_control: FlowControl::new(config.init_local_window_sz),
|
flow_control: FlowControl::new(config.init_local_window_sz),
|
||||||
pending_window_updates: VecDeque::new(),
|
pending_window_updates: VecDeque::new(),
|
||||||
@@ -51,8 +61,8 @@ impl<P: Peer> Send<P> {
|
|||||||
/// Update state reflecting a new, locally opened stream
|
/// Update state reflecting a new, locally opened stream
|
||||||
///
|
///
|
||||||
/// Returns the stream state if successful. `None` if refused
|
/// Returns the stream state if successful. `None` if refused
|
||||||
pub fn open(&mut self, id: StreamId) -> Result<State, ConnectionError> {
|
pub fn open(&mut self) -> Result<(StreamId, State), ConnectionError> {
|
||||||
try!(self.ensure_can_open(id));
|
try!(self.ensure_can_open());
|
||||||
|
|
||||||
if let Some(max) = self.max_streams {
|
if let Some(max) = self.max_streams {
|
||||||
if max <= self.num_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
|
// Increment the number of locally initiated streams
|
||||||
self.num_streams += 1;
|
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)
|
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.
|
/// 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() {
|
if P::is_server() {
|
||||||
// Servers cannot open streams. PushPromise must first be reserved.
|
// Servers cannot open streams. PushPromise must first be reserved.
|
||||||
return Err(UnexpectedFrameType.into());
|
return Err(UnexpectedFrameType.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
if !id.is_client_initiated() {
|
// TODO: Handle StreamId overflow
|
||||||
return Err(InvalidStreamId.into());
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
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 {
|
pub fn entry(&mut self, id: StreamId) -> Entry {
|
||||||
use self::hash_map::Entry::*;
|
use self::hash_map::Entry::*;
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use client;
|
||||||
use proto::*;
|
use proto::*;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
@@ -10,6 +11,12 @@ pub struct Streams<P> {
|
|||||||
inner: Arc<Mutex<Inner<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
|
/// Fields needed to manage state related to managing the set of streams. This
|
||||||
/// is mostly split out to make ownership happy.
|
/// is mostly split out to make ownership happy.
|
||||||
///
|
///
|
||||||
@@ -139,28 +146,22 @@ impl<P: Peer> Streams<P> {
|
|||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_headers(&mut self, frame: &frame::Headers)
|
pub fn send_headers(&mut self, headers: frame::Headers)
|
||||||
-> Result<(), ConnectionError>
|
-> Result<(), ConnectionError>
|
||||||
{
|
{
|
||||||
|
unimplemented!();
|
||||||
|
/*
|
||||||
let id = frame.stream_id();
|
let id = frame.stream_id();
|
||||||
let mut me = self.inner.lock().unwrap();
|
let mut me = self.inner.lock().unwrap();
|
||||||
let me = &mut *me;
|
let me = &mut *me;
|
||||||
|
|
||||||
trace!("send_headers; id={:?}", id);
|
// let (id, state) = me.actions.send.open());
|
||||||
|
|
||||||
|
|
||||||
let state = match me.store.entry(id) {
|
let state = match me.store.entry(id) {
|
||||||
Entry::Occupied(e) => e.into_mut(),
|
Entry::Occupied(e) => e.into_mut(),
|
||||||
Entry::Vacant(e) => {
|
Entry::Vacant(e) => {
|
||||||
// Trailers cannot open a stream. Trailers are header frames
|
let (id, state) = try!(me.actions.send.open());
|
||||||
// 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));
|
|
||||||
e.insert(state)
|
e.insert(state)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -176,6 +177,7 @@ impl<P: Peer> Streams<P> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_data<B: Buf>(&mut self, frame: &frame::Data<B>)
|
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> {
|
impl<P: Peer> Actions<P> {
|
||||||
fn dec_num_streams(&mut self, id: StreamId) {
|
fn dec_num_streams(&mut self, id: StreamId) {
|
||||||
if self.is_local_init(id) {
|
if self.is_local_init(id) {
|
||||||
|
|||||||
@@ -117,6 +117,11 @@ fn recv_invalid_server_stream_id() {
|
|||||||
assert_proto_err!(err, ProtocolError);
|
assert_proto_err!(err, ProtocolError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn sending_request_on_closed_soket() {
|
||||||
|
}
|
||||||
|
|
||||||
const SETTINGS: &'static [u8] = &[0, 0, 0, 4, 0, 0, 0, 0, 0];
|
const SETTINGS: &'static [u8] = &[0, 0, 0, 4, 0, 0, 0, 0, 0];
|
||||||
const SETTINGS_ACK: &'static [u8] = &[0, 0, 0, 4, 1, 0, 0, 0, 0];
|
const SETTINGS_ACK: &'static [u8] = &[0, 0, 0, 4, 1, 0, 0, 0, 0];
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user