Start hooking up data receiving
This commit is contained in:
@@ -23,12 +23,21 @@ 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.
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Stream<B: IntoBuf> {
|
pub struct Stream<B: IntoBuf> {
|
||||||
inner: proto::StreamRef<Peer, B::Buf>,
|
inner: proto::StreamRef<Peer, B::Buf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Body<B: IntoBuf> {
|
||||||
|
inner: proto::StreamRef<Peer, B::Buf>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Chunk<B: IntoBuf> {
|
||||||
|
inner: proto::Chunk<Peer, B::Buf>,
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> Client<T, Bytes>
|
impl<T> Client<T, Bytes>
|
||||||
where T: AsyncRead + AsyncWrite + 'static,
|
where T: AsyncRead + AsyncWrite + 'static,
|
||||||
{
|
{
|
||||||
@@ -90,19 +99,6 @@ impl<T, B> Client<T, B>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, B> Future for Client<T, B>
|
|
||||||
// TODO: Get rid of 'static
|
|
||||||
where T: AsyncRead + AsyncWrite + 'static,
|
|
||||||
B: IntoBuf + 'static,
|
|
||||||
{
|
|
||||||
type Item = ();
|
|
||||||
type Error = ConnectionError;
|
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<(), ConnectionError> {
|
|
||||||
self.connection.poll()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, B> fmt::Debug for Client<T, B>
|
impl<T, B> fmt::Debug for Client<T, B>
|
||||||
where T: fmt::Debug,
|
where T: fmt::Debug,
|
||||||
B: fmt::Debug + IntoBuf,
|
B: fmt::Debug + IntoBuf,
|
||||||
@@ -140,8 +136,11 @@ impl<T, B> fmt::Debug for Handshake<T, B>
|
|||||||
|
|
||||||
impl<B: IntoBuf> Stream<B> {
|
impl<B: IntoBuf> Stream<B> {
|
||||||
/// Receive the HTTP/2.0 response, if it is ready.
|
/// Receive the HTTP/2.0 response, if it is ready.
|
||||||
pub fn poll_response(&mut self) -> Poll<Response<()>, ConnectionError> {
|
pub fn poll_response(&mut self) -> Poll<Response<Body<B>>, ConnectionError> {
|
||||||
self.inner.poll_response()
|
let (parts, _) = try_ready!(self.inner.poll_response()).into_parts();
|
||||||
|
let body = Body { inner: self.inner.clone() };
|
||||||
|
|
||||||
|
Ok(Response::from_parts(parts, body).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send data
|
/// Send data
|
||||||
@@ -160,7 +159,7 @@ impl<B: IntoBuf> Stream<B> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<B: IntoBuf> Future for Stream<B> {
|
impl<B: IntoBuf> Future for Stream<B> {
|
||||||
type Item = Response<()>;
|
type Item = Response<Body<B>>;
|
||||||
type Error = ConnectionError;
|
type Error = ConnectionError;
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||||
|
|||||||
@@ -67,6 +67,15 @@ pub enum Frame<T = Bytes> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Frame<T> {
|
impl<T> Frame<T> {
|
||||||
|
/// Returns true if the frame is a DATA frame.
|
||||||
|
pub fn is_data(&self) -> bool {
|
||||||
|
use self::Frame::*;
|
||||||
|
|
||||||
|
match *self {
|
||||||
|
Data(..) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> fmt::Debug for Frame<T> {
|
impl<T> fmt::Debug for Frame<T> {
|
||||||
|
|||||||
@@ -127,19 +127,8 @@ impl<T, P, B> Connection<T, P, B>
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
Some(Data(frame)) => {
|
Some(Data(frame)) => {
|
||||||
unimplemented!();
|
|
||||||
/*
|
|
||||||
trace!("recv DATA; frame={:?}", frame);
|
trace!("recv DATA; frame={:?}", frame);
|
||||||
try!(self.streams.recv_data(&frame));
|
try!(self.streams.recv_data(frame));
|
||||||
|
|
||||||
let frame = Frame::Data {
|
|
||||||
id: frame.stream_id(),
|
|
||||||
end_of_stream: frame.is_end_stream(),
|
|
||||||
data: frame.into_payload(),
|
|
||||||
};
|
|
||||||
|
|
||||||
return Ok(Some(frame).into());
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
Some(Reset(frame)) => {
|
Some(Reset(frame)) => {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ mod settings;
|
|||||||
mod streams;
|
mod streams;
|
||||||
|
|
||||||
pub use self::connection::Connection;
|
pub use self::connection::Connection;
|
||||||
pub use self::streams::{Streams, StreamRef};
|
pub use self::streams::{Streams, StreamRef, Chunk};
|
||||||
|
|
||||||
use self::framed_read::FramedRead;
|
use self::framed_read::FramedRead;
|
||||||
use self::framed_write::FramedWrite;
|
use self::framed_write::FramedWrite;
|
||||||
|
|||||||
@@ -88,4 +88,53 @@ impl<B> Deque<B> {
|
|||||||
None => None,
|
None => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn take_while<F>(&mut self, buf: &mut Buffer<B>, mut f: F) -> Self
|
||||||
|
where F: FnMut(&Frame<B>) -> bool
|
||||||
|
{
|
||||||
|
match self.indices {
|
||||||
|
Some(mut idxs) => {
|
||||||
|
if !f(&buf.slab[idxs.head].frame) {
|
||||||
|
return Deque::new();
|
||||||
|
}
|
||||||
|
|
||||||
|
let head = idxs.head;
|
||||||
|
let mut tail = idxs.head;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let next = match buf.slab[tail].next {
|
||||||
|
Some(next) => next,
|
||||||
|
None => {
|
||||||
|
self.indices = None;
|
||||||
|
return Deque {
|
||||||
|
indices: Some(idxs),
|
||||||
|
_p: PhantomData,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if !f(&buf.slab[next].frame) {
|
||||||
|
// Split the linked list
|
||||||
|
buf.slab[tail].next = None;
|
||||||
|
|
||||||
|
self.indices = Some(Indices {
|
||||||
|
head: next,
|
||||||
|
tail: idxs.tail,
|
||||||
|
});
|
||||||
|
|
||||||
|
return Deque {
|
||||||
|
indices: Some(Indices {
|
||||||
|
head: head,
|
||||||
|
tail: tail,
|
||||||
|
}),
|
||||||
|
_p: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tail = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => Deque::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ mod store;
|
|||||||
mod stream;
|
mod stream;
|
||||||
mod streams;
|
mod streams;
|
||||||
|
|
||||||
pub use self::streams::{Streams, StreamRef};
|
pub use self::streams::{Streams, StreamRef, Chunk};
|
||||||
|
|
||||||
use self::buffer::Buffer;
|
use self::buffer::Buffer;
|
||||||
use self::flow_control::FlowControl;
|
use self::flow_control::FlowControl;
|
||||||
|
|||||||
@@ -32,6 +32,12 @@ pub(super) struct Recv<P, B> {
|
|||||||
_p: PhantomData<(P, B)>,
|
_p: PhantomData<(P, B)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub(super) struct Chunk {
|
||||||
|
/// Data frames pending receival
|
||||||
|
pub pending_recv: buffer::Deque<Bytes>,
|
||||||
|
}
|
||||||
|
|
||||||
impl<P, B> Recv<P, B>
|
impl<P, B> Recv<P, B>
|
||||||
where P: Peer,
|
where P: Peer,
|
||||||
B: Buf,
|
B: Buf,
|
||||||
@@ -98,7 +104,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 Stream<B>)
|
||||||
-> Result<(), ConnectionError>
|
-> Result<(), ConnectionError>
|
||||||
{
|
{
|
||||||
@@ -130,6 +136,10 @@ impl<P, B> Recv<P, B>
|
|||||||
try!(stream.state.recv_close());
|
try!(stream.state.recv_close());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Push the frame onto the recv buffer
|
||||||
|
stream.pending_recv.push_back(&mut self.buffer, frame.into());
|
||||||
|
stream.notify_recv();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,6 +228,33 @@ impl<P, B> Recv<P, B>
|
|||||||
Ok(().into())
|
Ok(().into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn poll_chunk(&mut self, stream: &mut Stream<B>)
|
||||||
|
-> Poll<Option<Chunk>, ConnectionError>
|
||||||
|
{
|
||||||
|
let frames = stream.pending_recv
|
||||||
|
.take_while(&mut self.buffer, |frame| frame.is_data());
|
||||||
|
|
||||||
|
if frames.is_empty() {
|
||||||
|
stream.recv_task = Some(task::current());
|
||||||
|
Ok(Async::NotReady)
|
||||||
|
} else {
|
||||||
|
Ok(Some(Chunk {
|
||||||
|
pending_recv: frames,
|
||||||
|
}).into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pop_bytes(&mut self, chunk: &mut Chunk) -> Option<Bytes> {
|
||||||
|
match chunk.pending_recv.pop_front(&mut self.buffer) {
|
||||||
|
Some(Frame::Data(frame)) => {
|
||||||
|
Some(frame.into_payload())
|
||||||
|
}
|
||||||
|
None => None,
|
||||||
|
_ => panic!("unexpected frame type"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Send stream level window update
|
/// Send stream level window update
|
||||||
pub fn send_stream_window_update<T>(&mut self,
|
pub fn send_stream_window_update<T>(&mut self,
|
||||||
streams: &mut Store<B>,
|
streams: &mut Store<B>,
|
||||||
|
|||||||
@@ -18,6 +18,15 @@ pub struct StreamRef<P, B> {
|
|||||||
key: store::Key,
|
key: store::Key,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Chunk<P, B>
|
||||||
|
where P: Peer,
|
||||||
|
B: Buf,
|
||||||
|
{
|
||||||
|
inner: Arc<Mutex<Inner<P, B>>>,
|
||||||
|
recv: recv::Chunk,
|
||||||
|
}
|
||||||
|
|
||||||
/// 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.
|
||||||
///
|
///
|
||||||
@@ -103,7 +112,7 @@ impl<P, B> Streams<P, B>
|
|||||||
Ok(ret)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn recv_data(&mut self, frame: &frame::Data)
|
pub fn recv_data(&mut self, frame: frame::Data)
|
||||||
-> Result<(), ConnectionError>
|
-> Result<(), ConnectionError>
|
||||||
{
|
{
|
||||||
let id = frame.stream_id();
|
let id = frame.stream_id();
|
||||||
@@ -305,6 +314,34 @@ impl<B> Streams<client::Peer, B>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ===== impl StreamRef =====
|
||||||
|
|
||||||
|
impl<P, B> StreamRef<P, B>
|
||||||
|
where P: Peer,
|
||||||
|
B: Buf,
|
||||||
|
{
|
||||||
|
pub fn poll_data(&mut self) -> Poll<Option<Chunk<P, B>>, ConnectionError> {
|
||||||
|
let recv = {
|
||||||
|
let mut me = self.inner.lock().unwrap();
|
||||||
|
let me = &mut *me;
|
||||||
|
|
||||||
|
let mut stream = me.store.resolve(self.key);
|
||||||
|
|
||||||
|
try_ready!(me.actions.recv.poll_chunk(&mut stream))
|
||||||
|
};
|
||||||
|
|
||||||
|
// Convert to a chunk
|
||||||
|
let chunk = recv.map(|recv| {
|
||||||
|
Chunk {
|
||||||
|
inner: self.inner.clone(),
|
||||||
|
recv: recv,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(chunk.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<B> StreamRef<client::Peer, B>
|
impl<B> StreamRef<client::Peer, B>
|
||||||
where B: Buf,
|
where B: Buf,
|
||||||
{
|
{
|
||||||
@@ -318,6 +355,34 @@ impl<B> StreamRef<client::Peer, B>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
impl<P, B> Clone for StreamRef<P, B> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
StreamRef {
|
||||||
|
inner: self.inner.clone(),
|
||||||
|
key: self.key.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== impl Chunk =====
|
||||||
|
|
||||||
|
impl<P, B> Drop for Chunk<P, B>
|
||||||
|
where P: Peer,
|
||||||
|
B: Buf,
|
||||||
|
{
|
||||||
|
fn drop(&mut self) {
|
||||||
|
let mut me = self.inner.lock().unwrap();
|
||||||
|
let me = &mut *me;
|
||||||
|
|
||||||
|
while let Some(_) = me.actions.recv.pop_bytes(&mut self.recv) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== impl Actions =====
|
||||||
|
|
||||||
impl<P, B> Actions<P, B>
|
impl<P, B> Actions<P, B>
|
||||||
where P: Peer,
|
where P: Peer,
|
||||||
B: Buf,
|
B: Buf,
|
||||||
|
|||||||
Reference in New Issue
Block a user