refactor(lib): convert to futures 0.2.0-beta (#1470)

This commit is contained in:
Sam Rijs
2018-03-30 07:32:44 +11:00
committed by Sean McArthur
parent 5db85316a1
commit a12f7beed9
34 changed files with 1366 additions and 1347 deletions

View File

@@ -3,8 +3,9 @@ use std::borrow::Cow;
use std::fmt;
use bytes::Bytes;
use futures::{Async, Future, Poll, Stream};
use futures::sync::{mpsc, oneshot};
use futures::{Async, Future, Poll, Stream, StreamExt};
use futures::task;
use futures::channel::{mpsc, oneshot};
use http::HeaderMap;
use super::Chunk;
@@ -24,14 +25,14 @@ pub trait Entity {
///
/// Similar to `Stream::poll_next`, this yields `Some(Data)` until
/// the body ends, when it yields `None`.
fn poll_data(&mut self) -> Poll<Option<Self::Data>, Self::Error>;
fn poll_data(&mut self, cx: &mut task::Context) -> Poll<Option<Self::Data>, Self::Error>;
/// Poll for an optional **single** `HeaderMap` of trailers.
///
/// This should **only** be called after `poll_data` has ended.
///
/// Note: Trailers aren't currently used for HTTP/1, only for HTTP/2.
fn poll_trailers(&mut self) -> Poll<Option<HeaderMap>, Self::Error> {
fn poll_trailers(&mut self, _cx: &mut task::Context) -> Poll<Option<HeaderMap>, Self::Error> {
Ok(Async::Ready(None))
}
@@ -67,12 +68,12 @@ impl<E: Entity> Entity for Box<E> {
type Data = E::Data;
type Error = E::Error;
fn poll_data(&mut self) -> Poll<Option<Self::Data>, Self::Error> {
(**self).poll_data()
fn poll_data(&mut self, cx: &mut task::Context) -> Poll<Option<Self::Data>, Self::Error> {
(**self).poll_data(cx)
}
fn poll_trailers(&mut self) -> Poll<Option<HeaderMap>, Self::Error> {
(**self).poll_trailers()
fn poll_trailers(&mut self, cx: &mut task::Context) -> Poll<Option<HeaderMap>, Self::Error> {
(**self).poll_trailers(cx)
}
fn is_end_stream(&self) -> bool {
@@ -96,10 +97,10 @@ impl<E: Entity> Stream for EntityStream<E> {
type Item = E::Data;
type Error = E::Error;
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
fn poll_next(&mut self, cx: &mut task::Context) -> Poll<Option<Self::Item>, Self::Error> {
loop {
if self.is_data_eof {
return self.entity.poll_trailers()
return self.entity.poll_trailers(cx)
.map(|async| {
async.map(|_opt| {
// drop the trailers and return that Stream is done
@@ -108,7 +109,7 @@ impl<E: Entity> Stream for EntityStream<E> {
});
}
let opt = try_ready!(self.entity.poll_data());
let opt = try_ready!(self.entity.poll_data(cx));
if let Some(data) = opt {
return Ok(Async::Ready(Some(data)));
} else {
@@ -211,14 +212,14 @@ impl Body {
/// ```
/// # extern crate futures;
/// # extern crate hyper;
/// # use futures::{Future, Stream};
/// # use futures::{FutureExt, StreamExt};
/// # use hyper::{Body, Request};
/// # fn request_concat(some_req: Request<Body>) {
/// let req: Request<Body> = some_req;
/// let body = req.into_body();
///
/// let stream = body.into_stream();
/// stream.concat2()
/// stream.concat()
/// .map(|buf| {
/// println!("body length: {}", buf.len());
/// });
@@ -267,15 +268,15 @@ impl Entity for Body {
type Data = Chunk;
type Error = ::Error;
fn poll_data(&mut self) -> Poll<Option<Self::Data>, Self::Error> {
fn poll_data(&mut self, cx: &mut task::Context) -> Poll<Option<Self::Data>, Self::Error> {
match self.kind {
Kind::Chan { ref mut rx, .. } => match rx.poll().expect("mpsc cannot error") {
Kind::Chan { ref mut rx, .. } => match rx.poll_next(cx).expect("mpsc cannot error") {
Async::Ready(Some(Ok(chunk))) => Ok(Async::Ready(Some(chunk))),
Async::Ready(Some(Err(err))) => Err(err),
Async::Ready(None) => Ok(Async::Ready(None)),
Async::NotReady => Ok(Async::NotReady),
Async::Pending => Ok(Async::Pending),
},
Kind::Wrapped(ref mut s) => s.poll(),
Kind::Wrapped(ref mut s) => s.poll_next(cx),
Kind::Once(ref mut val) => Ok(Async::Ready(val.take())),
Kind::Empty => Ok(Async::Ready(None)),
}
@@ -310,13 +311,13 @@ impl fmt::Debug for Body {
impl Sender {
/// Check to see if this `Sender` can send more data.
pub fn poll_ready(&mut self) -> Poll<(), ()> {
match self.close_rx.poll() {
pub fn poll_ready(&mut self, cx: &mut task::Context) -> Poll<(), ()> {
match self.close_rx.poll(cx) {
Ok(Async::Ready(())) | Err(_) => return Err(()),
Ok(Async::NotReady) => (),
Ok(Async::Pending) => (),
}
self.tx.poll_ready().map_err(|_| ())
self.tx.poll_ready(cx).map_err(|_| ())
}
/// Sends data on this channel.
@@ -413,13 +414,11 @@ fn _assert_send_sync() {
#[test]
fn test_body_stream_concat() {
use futures::{Stream, Future};
use futures::{StreamExt};
let body = Body::from("hello world");
let total = body.into_stream()
.concat2()
.wait()
let total = ::futures::executor::block_on(body.into_stream().concat())
.unwrap();
assert_eq!(total.as_ref(), b"hello world");

View File

@@ -3,10 +3,10 @@ use std::io::{self};
use std::marker::PhantomData;
use bytes::Bytes;
use futures::{Async, AsyncSink, Poll, StartSend};
use futures::task::Task;
use futures::{Async, Poll};
use futures::task;
use futures::io::{AsyncRead, AsyncWrite};
use http::{Method, Version};
use tokio_io::{AsyncRead, AsyncWrite};
use proto::{BodyLength, Chunk, Decode, Http1Transaction, MessageHead};
use super::io::{Cursor, Buffered};
@@ -113,14 +113,14 @@ where I: AsyncRead + AsyncWrite,
T::should_error_on_parse_eof() && !self.state.is_idle()
}
pub fn read_head(&mut self) -> Poll<Option<(MessageHead<T::Incoming>, bool)>, ::Error> {
pub fn read_head(&mut self, cx: &mut task::Context) -> Poll<Option<(MessageHead<T::Incoming>, bool)>, ::Error> {
debug_assert!(self.can_read_head());
trace!("Conn::read_head");
loop {
let (version, head) = match self.io.parse::<T>() {
let (version, head) = match self.io.parse::<T>(cx) {
Ok(Async::Ready(head)) => (head.version, head),
Ok(Async::NotReady) => return Ok(Async::NotReady),
Ok(Async::Pending) => return Ok(Async::Pending),
Err(e) => {
// If we are currently waiting on a message, then an empty
// message should be reported as an error. If not, it is just
@@ -132,7 +132,7 @@ where I: AsyncRead + AsyncWrite,
return if was_mid_parse || must_error {
debug!("parse error ({}) with {} bytes", e, self.io.read_buf().len());
self.on_parse_error(e)
.map(|()| Async::NotReady)
.map(|()| Async::Pending)
} else {
debug!("read eof");
Ok(Async::Ready(None))
@@ -169,7 +169,7 @@ where I: AsyncRead + AsyncWrite,
debug!("decoder error = {:?}", e);
self.state.close_read();
return self.on_parse_error(e)
.map(|()| Async::NotReady);
.map(|()| Async::Pending);
}
};
@@ -193,20 +193,20 @@ where I: AsyncRead + AsyncWrite,
self.state.reading = reading;
}
if !body {
self.try_keep_alive();
self.try_keep_alive(cx);
}
return Ok(Async::Ready(Some((head, body))));
}
}
pub fn read_body(&mut self) -> Poll<Option<Chunk>, io::Error> {
pub fn read_body(&mut self, cx: &mut task::Context) -> Poll<Option<Chunk>, io::Error> {
debug_assert!(self.can_read_body());
trace!("Conn::read_body");
let (reading, ret) = match self.state.reading {
Reading::Body(ref mut decoder) => {
match decoder.decode(&mut self.io) {
match decoder.decode(&mut self.io, cx) {
Ok(Async::Ready(slice)) => {
let (reading, chunk) = if !slice.is_empty() {
return Ok(Async::Ready(Some(Chunk::from(slice))));
@@ -222,7 +222,7 @@ where I: AsyncRead + AsyncWrite,
};
(reading, Ok(Async::Ready(chunk)))
},
Ok(Async::NotReady) => return Ok(Async::NotReady),
Ok(Async::Pending) => return Ok(Async::Pending),
Err(e) => {
trace!("decode stream error: {}", e);
(Reading::Closed, Err(e))
@@ -233,19 +233,19 @@ where I: AsyncRead + AsyncWrite,
};
self.state.reading = reading;
self.try_keep_alive();
self.try_keep_alive(cx);
ret
}
pub fn read_keep_alive(&mut self) -> Result<(), ::Error> {
pub fn read_keep_alive(&mut self, cx: &mut task::Context) -> Result<(), ::Error> {
debug_assert!(!self.can_read_head() && !self.can_read_body());
trace!("read_keep_alive; is_mid_message={}", self.is_mid_message());
if self.is_mid_message() {
self.maybe_park_read();
self.maybe_park_read(cx);
} else {
self.require_empty_read()?;
self.require_empty_read(cx)?;
}
Ok(())
}
@@ -257,18 +257,19 @@ where I: AsyncRead + AsyncWrite,
}
}
fn maybe_park_read(&mut self) {
fn maybe_park_read(&mut self, cx: &mut task::Context) {
if !self.io.is_read_blocked() {
// the Io object is ready to read, which means it will never alert
// us that it is ready until we drain it. However, we're currently
// finished reading, so we need to park the task to be able to
// wake back up later when more reading should happen.
let current_waker = cx.waker();
let park = self.state.read_task.as_ref()
.map(|t| !t.will_notify_current())
.map(|t| !t.will_wake(current_waker))
.unwrap_or(true);
if park {
trace!("parking current task");
self.state.read_task = Some(::futures::task::current());
self.state.read_task = Some(current_waker.clone());
}
}
}
@@ -277,14 +278,14 @@ where I: AsyncRead + AsyncWrite,
//
// This should only be called for Clients wanting to enter the idle
// state.
fn require_empty_read(&mut self) -> io::Result<()> {
fn require_empty_read(&mut self, cx: &mut task::Context) -> io::Result<()> {
assert!(!self.can_read_head() && !self.can_read_body());
if !self.io.read_buf().is_empty() {
debug!("received an unexpected {} bytes", self.io.read_buf().len());
Err(io::Error::new(io::ErrorKind::InvalidData, "unexpected bytes after message ended"))
} else {
match self.try_io_read()? {
match self.try_io_read(cx)? {
Async::Ready(0) => {
// case handled in try_io_read
Ok(())
@@ -298,15 +299,15 @@ where I: AsyncRead + AsyncWrite,
};
Err(io::Error::new(io::ErrorKind::InvalidData, desc))
},
Async::NotReady => {
Async::Pending => {
Ok(())
},
}
}
}
fn try_io_read(&mut self) -> Poll<usize, io::Error> {
match self.io.read_from_io() {
fn try_io_read(&mut self, cx: &mut task::Context) -> Poll<usize, io::Error> {
match self.io.read_from_io(cx) {
Ok(Async::Ready(0)) => {
trace!("try_io_read; found EOF on connection: {:?}", self.state);
let must_error = self.should_error_on_eof();
@@ -328,8 +329,8 @@ where I: AsyncRead + AsyncWrite,
Ok(Async::Ready(n)) => {
Ok(Async::Ready(n))
},
Ok(Async::NotReady) => {
Ok(Async::NotReady)
Ok(Async::Pending) => {
Ok(Async::Pending)
},
Err(e) => {
self.state.close();
@@ -339,8 +340,8 @@ where I: AsyncRead + AsyncWrite,
}
fn maybe_notify(&mut self) {
// its possible that we returned NotReady from poll() without having
fn maybe_notify(&mut self, cx: &mut task::Context) {
// its possible that we returned Pending from poll() without having
// exhausted the underlying Io. We would have done this when we
// determined we couldn't keep reading until we knew how writing
// would finish.
@@ -366,9 +367,9 @@ where I: AsyncRead + AsyncWrite,
if !self.io.is_read_blocked() {
if wants_read && self.io.read_buf().is_empty() {
match self.io.read_from_io() {
match self.io.read_from_io(cx) {
Ok(Async::Ready(_)) => (),
Ok(Async::NotReady) => {
Ok(Async::Pending) => {
trace!("maybe_notify; read_from_io blocked");
return
},
@@ -380,16 +381,16 @@ where I: AsyncRead + AsyncWrite,
}
if let Some(ref task) = self.state.read_task {
trace!("maybe_notify; notifying task");
task.notify();
task.wake();
} else {
trace!("maybe_notify; no task to notify");
}
}
}
fn try_keep_alive(&mut self) {
fn try_keep_alive(&mut self, cx: &mut task::Context) {
self.state.try_keep_alive();
self.maybe_notify();
self.maybe_notify(cx);
}
pub fn can_write_head(&self) -> bool {
@@ -475,17 +476,15 @@ where I: AsyncRead + AsyncWrite,
}
}
pub fn write_body(&mut self, chunk: Option<B>) -> StartSend<Option<B>, io::Error> {
pub fn write_body(&mut self, _cx: &mut task::Context, chunk: Option<B>) -> Poll<(), io::Error> {
debug_assert!(self.can_write_body());
if !self.can_buffer_body() {
if let Async::NotReady = self.flush()? {
// if chunk is Some(&[]), aka empty, whatever, just skip it
if chunk.as_ref().map(|c| c.as_ref().is_empty()).unwrap_or(false) {
return Ok(AsyncSink::Ready);
} else {
return Ok(AsyncSink::NotReady(chunk));
}
// if chunk is Some(&[]), aka empty, whatever, just skip it
if chunk.as_ref().map(|c| c.as_ref().is_empty()).unwrap_or(true) {
return Ok(Async::Ready(()));
} else {
return Err(io::Error::new(io::ErrorKind::Other, "tried to write chunk when body can't buffer"));
}
}
@@ -493,7 +492,7 @@ where I: AsyncRead + AsyncWrite,
Writing::Body(ref mut encoder) => {
if let Some(chunk) = chunk {
if chunk.as_ref().is_empty() {
return Ok(AsyncSink::Ready);
return Ok(Async::Ready(()));
}
let encoded = encoder.encode(Cursor::new(chunk));
@@ -506,7 +505,7 @@ where I: AsyncRead + AsyncWrite,
Writing::KeepAlive
}
} else {
return Ok(AsyncSink::Ready);
return Ok(Async::Ready(()));
}
} else {
// end of stream, that means we should try to eof
@@ -529,7 +528,7 @@ where I: AsyncRead + AsyncWrite,
};
self.state.writing = state;
Ok(AsyncSink::Ready)
Ok(Async::Ready(()))
}
// When we get a parse error, depending on what side we are, we might be able
@@ -553,16 +552,16 @@ where I: AsyncRead + AsyncWrite,
Err(err)
}
pub fn flush(&mut self) -> Poll<(), io::Error> {
try_ready!(self.io.flush());
self.try_keep_alive();
pub fn flush(&mut self, cx: &mut task::Context) -> Poll<(), io::Error> {
try_ready!(self.io.flush(cx));
self.try_keep_alive(cx);
trace!("flushed {:?}", self.state);
Ok(Async::Ready(()))
}
pub fn shutdown(&mut self) -> Poll<(), io::Error> {
match self.io.io_mut().shutdown() {
Ok(Async::NotReady) => Ok(Async::NotReady),
pub fn shutdown(&mut self, cx: &mut task::Context) -> Poll<(), io::Error> {
match self.io.io_mut().poll_close(cx) {
Ok(Async::Pending) => Ok(Async::Pending),
Ok(Async::Ready(())) => {
trace!("shut down IO");
Ok(Async::Ready(()))
@@ -612,7 +611,7 @@ struct State {
error: Option<::Error>,
keep_alive: KA,
method: Option<Method>,
read_task: Option<Task>,
read_task: Option<task::Waker>,
reading: Reading,
writing: Writing,
version: Version,
@@ -964,7 +963,7 @@ mod tests {
}
match conn.poll() {
Ok(Async::NotReady) => (),
Ok(Async::Pending) => (),
other => panic!("unexpected frame: {:?}", other)
}
Ok(())

View File

@@ -4,6 +4,7 @@ use std::usize;
use std::io;
use futures::{Async, Poll};
use futures::task;
use bytes::Bytes;
use super::io::MemRead;
@@ -84,7 +85,7 @@ impl Decoder {
}
}
pub fn decode<R: MemRead>(&mut self, body: &mut R) -> Poll<Bytes, io::Error> {
pub fn decode<R: MemRead>(&mut self, body: &mut R, cx: &mut task::Context) -> Poll<Bytes, io::Error> {
trace!("decode; state={:?}", self.kind);
match self.kind {
Length(ref mut remaining) => {
@@ -92,7 +93,7 @@ impl Decoder {
Ok(Async::Ready(Bytes::new()))
} else {
let to_read = *remaining as usize;
let buf = try_ready!(body.read_mem(to_read));
let buf = try_ready!(body.read_mem(cx, to_read));
let num = buf.as_ref().len() as u64;
if num > *remaining {
*remaining = 0;
@@ -108,7 +109,7 @@ impl Decoder {
loop {
let mut buf = None;
// advances the chunked state
*state = try_ready!(state.step(body, size, &mut buf));
*state = try_ready!(state.step(body, cx, size, &mut buf));
if *state == ChunkedState::End {
trace!("end of chunked");
return Ok(Async::Ready(Bytes::new()));
@@ -125,7 +126,7 @@ impl Decoder {
// 8192 chosen because its about 2 packets, there probably
// won't be that much available, so don't have MemReaders
// allocate buffers to big
let slice = try_ready!(body.read_mem(8192));
let slice = try_ready!(body.read_mem(cx, 8192));
*is_eof = slice.is_empty();
Ok(Async::Ready(slice))
}
@@ -152,8 +153,8 @@ impl fmt::Display for Decoder {
}
macro_rules! byte (
($rdr:ident) => ({
let buf = try_ready!($rdr.read_mem(1));
($rdr:ident, $cx:ident) => ({
let buf = try_ready!($rdr.read_mem($cx, 1));
if !buf.is_empty() {
buf[0]
} else {
@@ -166,27 +167,28 @@ macro_rules! byte (
impl ChunkedState {
fn step<R: MemRead>(&self,
body: &mut R,
cx: &mut task::Context,
size: &mut u64,
buf: &mut Option<Bytes>)
-> Poll<ChunkedState, io::Error> {
use self::ChunkedState::*;
match *self {
Size => ChunkedState::read_size(body, size),
SizeLws => ChunkedState::read_size_lws(body),
Extension => ChunkedState::read_extension(body),
SizeLf => ChunkedState::read_size_lf(body, *size),
Body => ChunkedState::read_body(body, size, buf),
BodyCr => ChunkedState::read_body_cr(body),
BodyLf => ChunkedState::read_body_lf(body),
EndCr => ChunkedState::read_end_cr(body),
EndLf => ChunkedState::read_end_lf(body),
Size => ChunkedState::read_size(body, cx, size),
SizeLws => ChunkedState::read_size_lws(body, cx),
Extension => ChunkedState::read_extension(body, cx),
SizeLf => ChunkedState::read_size_lf(body, cx, *size),
Body => ChunkedState::read_body(body, cx, size, buf),
BodyCr => ChunkedState::read_body_cr(body, cx),
BodyLf => ChunkedState::read_body_lf(body, cx),
EndCr => ChunkedState::read_end_cr(body, cx),
EndLf => ChunkedState::read_end_lf(body, cx),
End => Ok(Async::Ready(ChunkedState::End)),
}
}
fn read_size<R: MemRead>(rdr: &mut R, size: &mut u64) -> Poll<ChunkedState, io::Error> {
fn read_size<R: MemRead>(rdr: &mut R, cx: &mut task::Context, size: &mut u64) -> Poll<ChunkedState, io::Error> {
trace!("Read chunk hex size");
let radix = 16;
match byte!(rdr) {
match byte!(rdr, cx) {
b @ b'0'...b'9' => {
*size *= radix;
*size += (b - b'0') as u64;
@@ -209,9 +211,9 @@ impl ChunkedState {
}
Ok(Async::Ready(ChunkedState::Size))
}
fn read_size_lws<R: MemRead>(rdr: &mut R) -> Poll<ChunkedState, io::Error> {
fn read_size_lws<R: MemRead>(rdr: &mut R, cx: &mut task::Context) -> Poll<ChunkedState, io::Error> {
trace!("read_size_lws");
match byte!(rdr) {
match byte!(rdr, cx) {
// LWS can follow the chunk size, but no more digits can come
b'\t' | b' ' => Ok(Async::Ready(ChunkedState::SizeLws)),
b';' => Ok(Async::Ready(ChunkedState::Extension)),
@@ -222,16 +224,16 @@ impl ChunkedState {
}
}
}
fn read_extension<R: MemRead>(rdr: &mut R) -> Poll<ChunkedState, io::Error> {
fn read_extension<R: MemRead>(rdr: &mut R, cx: &mut task::Context) -> Poll<ChunkedState, io::Error> {
trace!("read_extension");
match byte!(rdr) {
match byte!(rdr, cx) {
b'\r' => Ok(Async::Ready(ChunkedState::SizeLf)),
_ => Ok(Async::Ready(ChunkedState::Extension)), // no supported extensions
}
}
fn read_size_lf<R: MemRead>(rdr: &mut R, size: u64) -> Poll<ChunkedState, io::Error> {
fn read_size_lf<R: MemRead>(rdr: &mut R, cx: &mut task::Context, size: u64) -> Poll<ChunkedState, io::Error> {
trace!("Chunk size is {:?}", size);
match byte!(rdr) {
match byte!(rdr, cx) {
b'\n' => {
if size == 0 {
Ok(Async::Ready(ChunkedState::EndCr))
@@ -244,7 +246,7 @@ impl ChunkedState {
}
}
fn read_body<R: MemRead>(rdr: &mut R,
fn read_body<R: MemRead>(rdr: &mut R, cx: &mut task::Context,
rem: &mut u64,
buf: &mut Option<Bytes>)
-> Poll<ChunkedState, io::Error> {
@@ -257,7 +259,7 @@ impl ChunkedState {
};
let to_read = rem_cap;
let slice = try_ready!(rdr.read_mem(to_read));
let slice = try_ready!(rdr.read_mem(cx, to_read));
let count = slice.len();
if count == 0 {
@@ -273,27 +275,27 @@ impl ChunkedState {
Ok(Async::Ready(ChunkedState::BodyCr))
}
}
fn read_body_cr<R: MemRead>(rdr: &mut R) -> Poll<ChunkedState, io::Error> {
match byte!(rdr) {
fn read_body_cr<R: MemRead>(rdr: &mut R, cx: &mut task::Context) -> Poll<ChunkedState, io::Error> {
match byte!(rdr, cx) {
b'\r' => Ok(Async::Ready(ChunkedState::BodyLf)),
_ => Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid chunk body CR")),
}
}
fn read_body_lf<R: MemRead>(rdr: &mut R) -> Poll<ChunkedState, io::Error> {
match byte!(rdr) {
fn read_body_lf<R: MemRead>(rdr: &mut R, cx: &mut task::Context) -> Poll<ChunkedState, io::Error> {
match byte!(rdr, cx) {
b'\n' => Ok(Async::Ready(ChunkedState::Size)),
_ => Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid chunk body LF")),
}
}
fn read_end_cr<R: MemRead>(rdr: &mut R) -> Poll<ChunkedState, io::Error> {
match byte!(rdr) {
fn read_end_cr<R: MemRead>(rdr: &mut R, cx: &mut task::Context) -> Poll<ChunkedState, io::Error> {
match byte!(rdr, cx) {
b'\r' => Ok(Async::Ready(ChunkedState::EndLf)),
_ => Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid chunk end CR")),
}
}
fn read_end_lf<R: MemRead>(rdr: &mut R) -> Poll<ChunkedState, io::Error> {
match byte!(rdr) {
fn read_end_lf<R: MemRead>(rdr: &mut R, cx: &mut task::Context) -> Poll<ChunkedState, io::Error> {
match byte!(rdr, cx) {
b'\n' => Ok(Async::Ready(ChunkedState::End)),
_ => Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid chunk end LF")),
}
@@ -323,11 +325,14 @@ mod tests {
use super::ChunkedState;
use super::super::io::MemRead;
use futures::{Async, Poll};
use futures::task;
use futures::future::lazy;
use futures::executor::block_on;
use bytes::{BytesMut, Bytes};
use mock::AsyncIo;
impl<'a> MemRead for &'a [u8] {
fn read_mem(&mut self, len: usize) -> Poll<Bytes, io::Error> {
fn read_mem(&mut self, _cx: &mut task::Context, len: usize) -> Poll<Bytes, io::Error> {
let n = ::std::cmp::min(len, self.len());
if n > 0 {
let (a, b) = self.split_at(n);
@@ -347,7 +352,7 @@ mod tests {
fn unwrap(self) -> Bytes {
match self {
Async::Ready(bytes) => bytes,
Async::NotReady => panic!(),
Async::Pending => panic!(),
}
}
}
@@ -355,7 +360,7 @@ mod tests {
fn unwrap(self) -> ChunkedState {
match self {
Async::Ready(state) => state,
Async::NotReady => panic!(),
Async::Pending => panic!(),
}
}
}
@@ -364,12 +369,12 @@ mod tests {
fn test_read_chunk_size() {
use std::io::ErrorKind::{UnexpectedEof, InvalidInput};
fn read(s: &str) -> u64 {
fn read(cx: &mut task::Context, s: &str) -> u64 {
let mut state = ChunkedState::Size;
let rdr = &mut s.as_bytes();
let mut size = 0;
loop {
let result = state.step(rdr, &mut size, &mut None);
let result = state.step(rdr, cx, &mut size, &mut None);
let desc = format!("read_size failed for {:?}", s);
state = result.expect(desc.as_str()).unwrap();
if state == ChunkedState::Body || state == ChunkedState::EndCr {
@@ -379,12 +384,12 @@ mod tests {
size
}
fn read_err(s: &str, expected_err: io::ErrorKind) {
fn read_err(cx: &mut task::Context, s: &str, expected_err: io::ErrorKind) {
let mut state = ChunkedState::Size;
let rdr = &mut s.as_bytes();
let mut size = 0;
loop {
let result = state.step(rdr, &mut size, &mut None);
let result = state.step(rdr, cx, &mut size, &mut None);
state = match result {
Ok(s) => s.unwrap(),
Err(e) => {
@@ -399,90 +404,111 @@ mod tests {
}
}
assert_eq!(1, read("1\r\n"));
assert_eq!(1, read("01\r\n"));
assert_eq!(0, read("0\r\n"));
assert_eq!(0, read("00\r\n"));
assert_eq!(10, read("A\r\n"));
assert_eq!(10, read("a\r\n"));
assert_eq!(255, read("Ff\r\n"));
assert_eq!(255, read("Ff \r\n"));
// Missing LF or CRLF
read_err("F\rF", InvalidInput);
read_err("F", UnexpectedEof);
// Invalid hex digit
read_err("X\r\n", InvalidInput);
read_err("1X\r\n", InvalidInput);
read_err("-\r\n", InvalidInput);
read_err("-1\r\n", InvalidInput);
// Acceptable (if not fully valid) extensions do not influence the size
assert_eq!(1, read("1;extension\r\n"));
assert_eq!(10, read("a;ext name=value\r\n"));
assert_eq!(1, read("1;extension;extension2\r\n"));
assert_eq!(1, read("1;;; ;\r\n"));
assert_eq!(2, read("2; extension...\r\n"));
assert_eq!(3, read("3 ; extension=123\r\n"));
assert_eq!(3, read("3 ;\r\n"));
assert_eq!(3, read("3 ; \r\n"));
// Invalid extensions cause an error
read_err("1 invalid extension\r\n", InvalidInput);
read_err("1 A\r\n", InvalidInput);
read_err("1;no CRLF", UnexpectedEof);
block_on(lazy(|cx| {
assert_eq!(1, read(cx, "1\r\n"));
assert_eq!(1, read(cx, "01\r\n"));
assert_eq!(0, read(cx, "0\r\n"));
assert_eq!(0, read(cx, "00\r\n"));
assert_eq!(10, read(cx, "A\r\n"));
assert_eq!(10, read(cx, "a\r\n"));
assert_eq!(255, read(cx, "Ff\r\n"));
assert_eq!(255, read(cx, "Ff \r\n"));
// Missing LF or CRLF
read_err(cx, "F\rF", InvalidInput);
read_err(cx, "F", UnexpectedEof);
// Invalid hex digit
read_err(cx, "X\r\n", InvalidInput);
read_err(cx, "1X\r\n", InvalidInput);
read_err(cx, "-\r\n", InvalidInput);
read_err(cx, "-1\r\n", InvalidInput);
// Acceptable (if not fully valid) extensions do not influence the size
assert_eq!(1, read(cx, "1;extension\r\n"));
assert_eq!(10, read(cx, "a;ext name=value\r\n"));
assert_eq!(1, read(cx, "1;extension;extension2\r\n"));
assert_eq!(1, read(cx, "1;;; ;\r\n"));
assert_eq!(2, read(cx, "2; extension...\r\n"));
assert_eq!(3, read(cx, "3 ; extension=123\r\n"));
assert_eq!(3, read(cx, "3 ;\r\n"));
assert_eq!(3, read(cx, "3 ; \r\n"));
// Invalid extensions cause an error
read_err(cx, "1 invalid extension\r\n", InvalidInput);
read_err(cx, "1 A\r\n", InvalidInput);
read_err(cx, "1;no CRLF", UnexpectedEof);
Ok::<_, ()>(())
})).unwrap()
}
#[test]
fn test_read_sized_early_eof() {
let mut bytes = &b"foo bar"[..];
let mut decoder = Decoder::length(10);
assert_eq!(decoder.decode(&mut bytes).unwrap().unwrap().len(), 7);
let e = decoder.decode(&mut bytes).unwrap_err();
assert_eq!(e.kind(), io::ErrorKind::UnexpectedEof);
block_on(lazy(|cx| {
let mut bytes = &b"foo bar"[..];
let mut decoder = Decoder::length(10);
assert_eq!(decoder.decode(&mut bytes, cx).unwrap().unwrap().len(), 7);
let e = decoder.decode(&mut bytes, cx).unwrap_err();
assert_eq!(e.kind(), io::ErrorKind::UnexpectedEof);
Ok::<_, ()>(())
})).unwrap()
}
#[test]
fn test_read_chunked_early_eof() {
let mut bytes = &b"\
9\r\n\
foo bar\
"[..];
let mut decoder = Decoder::chunked();
assert_eq!(decoder.decode(&mut bytes).unwrap().unwrap().len(), 7);
let e = decoder.decode(&mut bytes).unwrap_err();
assert_eq!(e.kind(), io::ErrorKind::UnexpectedEof);
block_on(lazy(|cx| {
let mut bytes = &b"\
9\r\n\
foo bar\
"[..];
let mut decoder = Decoder::chunked();
assert_eq!(decoder.decode(&mut bytes, cx).unwrap().unwrap().len(), 7);
let e = decoder.decode(&mut bytes, cx).unwrap_err();
assert_eq!(e.kind(), io::ErrorKind::UnexpectedEof);
Ok::<_, ()>(())
})).unwrap()
}
#[test]
fn test_read_chunked_single_read() {
let mut mock_buf = &b"10\r\n1234567890abcdef\r\n0\r\n"[..];
let buf = Decoder::chunked().decode(&mut mock_buf).expect("decode").unwrap();
assert_eq!(16, buf.len());
let result = String::from_utf8(buf.as_ref().to_vec()).expect("decode String");
assert_eq!("1234567890abcdef", &result);
block_on(lazy(|cx| {
let mut mock_buf = &b"10\r\n1234567890abcdef\r\n0\r\n"[..];
let buf = Decoder::chunked().decode(&mut mock_buf, cx).expect("decode").unwrap();
assert_eq!(16, buf.len());
let result = String::from_utf8(buf.as_ref().to_vec()).expect("decode String");
assert_eq!("1234567890abcdef", &result);
Ok::<_, ()>(())
})).unwrap()
}
#[test]
fn test_read_chunked_after_eof() {
let mut mock_buf = &b"10\r\n1234567890abcdef\r\n0\r\n\r\n"[..];
let mut decoder = Decoder::chunked();
block_on(lazy(|cx| {
let mut mock_buf = &b"10\r\n1234567890abcdef\r\n0\r\n\r\n"[..];
let mut decoder = Decoder::chunked();
// normal read
let buf = decoder.decode(&mut mock_buf).expect("decode").unwrap();
assert_eq!(16, buf.len());
let result = String::from_utf8(buf.as_ref().to_vec()).expect("decode String");
assert_eq!("1234567890abcdef", &result);
// normal read
let buf = decoder.decode(&mut mock_buf, cx).expect("decode").unwrap();
assert_eq!(16, buf.len());
let result = String::from_utf8(buf.as_ref().to_vec()).expect("decode String");
assert_eq!("1234567890abcdef", &result);
// eof read
let buf = decoder.decode(&mut mock_buf).expect("decode").unwrap();
assert_eq!(0, buf.len());
// eof read
let buf = decoder.decode(&mut mock_buf, cx).expect("decode").unwrap();
assert_eq!(0, buf.len());
// ensure read after eof also returns eof
let buf = decoder.decode(&mut mock_buf).expect("decode").unwrap();
assert_eq!(0, buf.len());
// ensure read after eof also returns eof
let buf = decoder.decode(&mut mock_buf, cx).expect("decode").unwrap();
assert_eq!(0, buf.len());
Ok::<_, ()>(())
})).unwrap()
}
// perform an async read using a custom buffer size and causing a blocking
// read at the specified byte
fn read_async(mut decoder: Decoder,
cx: &mut task::Context,
content: &[u8],
block_at: usize)
-> String {
@@ -490,14 +516,14 @@ mod tests {
let mut ins = AsyncIo::new(content, block_at);
let mut outs = Vec::new();
loop {
match decoder.decode(&mut ins).expect("unexpected decode error: {}") {
match decoder.decode(&mut ins, cx).expect("unexpected decode error: {}") {
Async::Ready(buf) => {
if buf.is_empty() {
break; // eof
}
outs.write(buf.as_ref()).expect("write buffer");
},
Async::NotReady => {
Async::Pending => {
ins.block_in(content_len); // we only block once
}
};
@@ -508,11 +534,14 @@ mod tests {
// iterate over the different ways that this async read could go.
// tests blocking a read at each byte along the content - The shotgun approach
fn all_async_cases(content: &str, expected: &str, decoder: Decoder) {
let content_len = content.len();
for block_at in 0..content_len {
let actual = read_async(decoder.clone(), content.as_bytes(), block_at);
assert_eq!(expected, &actual) //, "Failed async. Blocking at {}", block_at);
}
block_on(lazy(|cx| {
let content_len = content.len();
for block_at in 0..content_len {
let actual = read_async(decoder.clone(), cx, content.as_bytes(), block_at);
assert_eq!(expected, &actual) //, "Failed async. Blocking at {}", block_at);
}
Ok::<_, ()>(())
})).unwrap()
}
#[test]

View File

@@ -2,13 +2,15 @@ use std::io;
use bytes::Bytes;
use futures::{Async, Future, Poll, Stream};
use futures::task;
use futures::io::{AsyncRead, AsyncWrite};
use http::{Request, Response, StatusCode};
use tokio_io::{AsyncRead, AsyncWrite};
use tokio_service::Service;
use proto::body::Entity;
use proto::{Body, BodyLength, Conn, Http1Transaction, MessageHead, RequestHead, RequestLine, ResponseHead};
use ::service::Service;
pub struct Dispatcher<D, Bs, I, B, T> {
conn: Conn<I, B, T>,
dispatch: D,
@@ -21,9 +23,9 @@ pub trait Dispatch {
type PollItem;
type PollBody;
type RecvItem;
fn poll_msg(&mut self) -> Poll<Option<(Self::PollItem, Option<Self::PollBody>)>, ::Error>;
fn recv_msg(&mut self, msg: ::Result<(Self::RecvItem, Body)>) -> ::Result<()>;
fn poll_ready(&mut self) -> Poll<(), ()>;
fn poll_msg(&mut self, cx: &mut task::Context) -> Poll<Option<(Self::PollItem, Option<Self::PollBody>)>, ::Error>;
fn recv_msg(&mut self, cx: &mut task::Context, msg: ::Result<(Self::RecvItem, Body)>) -> ::Result<()>;
fn poll_ready(&mut self, cx: &mut task::Context) -> Poll<(), ()>;
fn should_poll(&self) -> bool;
}
@@ -69,57 +71,57 @@ where
/// The "Future" poll function. Runs this dispatcher until the
/// connection is shutdown, or an error occurs.
pub fn poll_until_shutdown(&mut self) -> Poll<(), ::Error> {
self.poll_catch(true)
pub fn poll_until_shutdown(&mut self, cx: &mut task::Context) -> Poll<(), ::Error> {
self.poll_catch(cx, true)
}
/// Run this dispatcher until HTTP says this connection is done,
/// but don't call `AsyncWrite::shutdown` on the underlying IO.
///
/// This is useful for HTTP upgrades.
pub fn poll_without_shutdown(&mut self) -> Poll<(), ::Error> {
self.poll_catch(false)
pub fn poll_without_shutdown(&mut self, cx: &mut task::Context) -> Poll<(), ::Error> {
self.poll_catch(cx, false)
}
fn poll_catch(&mut self, should_shutdown: bool) -> Poll<(), ::Error> {
self.poll_inner(should_shutdown).or_else(|e| {
fn poll_catch(&mut self, cx: &mut task::Context, should_shutdown: bool) -> Poll<(), ::Error> {
self.poll_inner(cx, should_shutdown).or_else(|e| {
// An error means we're shutting down either way.
// We just try to give the error to the user,
// and close the connection with an Ok. If we
// cannot give it to the user, then return the Err.
self.dispatch.recv_msg(Err(e)).map(Async::Ready)
self.dispatch.recv_msg(cx, Err(e)).map(Async::Ready)
})
}
fn poll_inner(&mut self, should_shutdown: bool) -> Poll<(), ::Error> {
self.poll_read()?;
self.poll_write()?;
self.poll_flush()?;
fn poll_inner(&mut self, cx: &mut task::Context, should_shutdown: bool) -> Poll<(), ::Error> {
self.poll_read(cx)?;
self.poll_write(cx)?;
self.poll_flush(cx)?;
if self.is_done() {
if should_shutdown {
try_ready!(self.conn.shutdown());
try_ready!(self.conn.shutdown(cx));
}
self.conn.take_error()?;
Ok(Async::Ready(()))
} else {
Ok(Async::NotReady)
Ok(Async::Pending)
}
}
fn poll_read(&mut self) -> Poll<(), ::Error> {
fn poll_read(&mut self, cx: &mut task::Context) -> Poll<(), ::Error> {
loop {
if self.is_closing {
return Ok(Async::Ready(()));
} else if self.conn.can_read_head() {
try_ready!(self.poll_read_head());
try_ready!(self.poll_read_head(cx));
} else if let Some(mut body) = self.body_tx.take() {
if self.conn.can_read_body() {
match body.poll_ready() {
match body.poll_ready(cx) {
Ok(Async::Ready(())) => (),
Ok(Async::NotReady) => {
Ok(Async::Pending) => {
self.body_tx = Some(body);
return Ok(Async::NotReady);
return Ok(Async::Pending);
},
Err(_canceled) => {
// user doesn't care about the body
@@ -129,7 +131,7 @@ where
return Ok(Async::Ready(()));
}
}
match self.conn.read_body() {
match self.conn.read_body(cx) {
Ok(Async::Ready(Some(chunk))) => {
match body.send_data(chunk) {
Ok(()) => {
@@ -147,9 +149,9 @@ where
Ok(Async::Ready(None)) => {
// just drop, the body will close automatically
},
Ok(Async::NotReady) => {
Ok(Async::Pending) => {
self.body_tx = Some(body);
return Ok(Async::NotReady);
return Ok(Async::Pending);
}
Err(e) => {
body.send_error(::Error::Io(e));
@@ -159,16 +161,16 @@ where
// just drop, the body will close automatically
}
} else {
return self.conn.read_keep_alive().map(Async::Ready);
return self.conn.read_keep_alive(cx).map(Async::Ready);
}
}
}
fn poll_read_head(&mut self) -> Poll<(), ::Error> {
fn poll_read_head(&mut self, cx: &mut task::Context) -> Poll<(), ::Error> {
// can dispatch receive, or does it still care about, an incoming message?
match self.dispatch.poll_ready() {
match self.dispatch.poll_ready(cx) {
Ok(Async::Ready(())) => (),
Ok(Async::NotReady) => unreachable!("dispatch not ready when conn is"),
Ok(Async::Pending) => unreachable!("dispatch not ready when conn is"),
Err(()) => {
trace!("dispatch no longer receiving messages");
self.close();
@@ -176,27 +178,27 @@ where
}
}
// dispatch is ready for a message, try to read one
match self.conn.read_head() {
match self.conn.read_head(cx) {
Ok(Async::Ready(Some((head, has_body)))) => {
let body = if has_body {
let (mut tx, rx) = Body::channel();
let _ = tx.poll_ready(); // register this task if rx is dropped
let _ = tx.poll_ready(cx); // register this task if rx is dropped
self.body_tx = Some(tx);
rx
} else {
Body::empty()
};
self.dispatch.recv_msg(Ok((head, body)))?;
self.dispatch.recv_msg(cx, Ok((head, body)))?;
Ok(Async::Ready(()))
},
Ok(Async::Ready(None)) => {
// read eof, conn will start to shutdown automatically
Ok(Async::Ready(()))
}
Ok(Async::NotReady) => Ok(Async::NotReady),
Ok(Async::Pending) => Ok(Async::Pending),
Err(err) => {
debug!("read_head error: {}", err);
self.dispatch.recv_msg(Err(err))?;
self.dispatch.recv_msg(cx, Err(err))?;
// if here, the dispatcher gave the user the error
// somewhere else. we still need to shutdown, but
// not as a second error.
@@ -205,12 +207,12 @@ where
}
}
fn poll_write(&mut self) -> Poll<(), ::Error> {
fn poll_write(&mut self, cx: &mut task::Context) -> Poll<(), ::Error> {
loop {
if self.is_closing {
return Ok(Async::Ready(()));
} else if self.body_rx.is_none() && self.conn.can_write_head() && self.dispatch.should_poll() {
if let Some((head, body)) = try_ready!(self.dispatch.poll_msg()) {
if let Some((head, body)) = try_ready!(self.dispatch.poll_msg(cx)) {
let body_type = body.as_ref().map(|body| {
body.content_length()
.map(BodyLength::Known)
@@ -223,27 +225,27 @@ where
return Ok(Async::Ready(()));
}
} else if !self.conn.can_buffer_body() {
try_ready!(self.poll_flush());
try_ready!(self.poll_flush(cx));
} else if let Some(mut body) = self.body_rx.take() {
let chunk = match body.poll_data()? {
let chunk = match body.poll_data(cx)? {
Async::Ready(Some(chunk)) => {
self.body_rx = Some(body);
chunk
},
Async::Ready(None) => {
if self.conn.can_write_body() {
self.conn.write_body(None)?;
self.conn.write_body(cx, None)?;
}
continue;
},
Async::NotReady => {
Async::Pending => {
self.body_rx = Some(body);
return Ok(Async::NotReady);
return Ok(Async::Pending);
}
};
if self.conn.can_write_body() {
assert!(self.conn.write_body(Some(chunk))?.is_ready());
self.conn.write_body(cx, Some(chunk))?;
// This allows when chunk is `None`, or `Some([])`.
} else if chunk.as_ref().len() == 0 {
// ok
@@ -251,13 +253,13 @@ where
warn!("unexpected chunk when body cannot write");
}
} else {
return Ok(Async::NotReady);
return Ok(Async::Pending);
}
}
}
fn poll_flush(&mut self) -> Poll<(), ::Error> {
self.conn.flush().map_err(|err| {
fn poll_flush(&mut self, cx: &mut task::Context) -> Poll<(), ::Error> {
self.conn.flush(cx).map_err(|err| {
debug!("error writing: {}", err);
err.into()
})
@@ -300,8 +302,8 @@ where
type Error = ::Error;
#[inline]
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
self.poll_until_shutdown()
fn poll(&mut self, cx: &mut task::Context) -> Poll<Self::Item, Self::Error> {
self.poll_until_shutdown(cx)
}
}
@@ -325,13 +327,13 @@ where
type PollBody = Bs;
type RecvItem = RequestHead;
fn poll_msg(&mut self) -> Poll<Option<(Self::PollItem, Option<Self::PollBody>)>, ::Error> {
fn poll_msg(&mut self, cx: &mut task::Context) -> Poll<Option<(Self::PollItem, Option<Self::PollBody>)>, ::Error> {
if let Some(mut fut) = self.in_flight.take() {
let resp = match fut.poll()? {
let resp = match fut.poll(cx)? {
Async::Ready(res) => res,
Async::NotReady => {
Async::Pending => {
self.in_flight = Some(fut);
return Ok(Async::NotReady);
return Ok(Async::Pending);
}
};
let (parts, body) = resp.into_parts();
@@ -351,7 +353,7 @@ where
}
}
fn recv_msg(&mut self, msg: ::Result<(Self::RecvItem, Body)>) -> ::Result<()> {
fn recv_msg(&mut self, _cx: &mut task::Context, msg: ::Result<(Self::RecvItem, Body)>) -> ::Result<()> {
let (msg, body) = msg?;
let mut req = Request::new(body);
*req.method_mut() = msg.subject.0;
@@ -362,9 +364,9 @@ where
Ok(())
}
fn poll_ready(&mut self) -> Poll<(), ()> {
fn poll_ready(&mut self, _cx: &mut task::Context) -> Poll<(), ()> {
if self.in_flight.is_some() {
Ok(Async::NotReady)
Ok(Async::Pending)
} else {
Ok(Async::Ready(()))
}
@@ -395,16 +397,16 @@ where
type PollBody = B;
type RecvItem = ResponseHead;
fn poll_msg(&mut self) -> Poll<Option<(Self::PollItem, Option<Self::PollBody>)>, ::Error> {
match self.rx.poll() {
fn poll_msg(&mut self, cx: &mut task::Context) -> Poll<Option<(Self::PollItem, Option<Self::PollBody>)>, ::Error> {
match self.rx.poll_next(cx) {
Ok(Async::Ready(Some((req, mut cb)))) => {
// check that future hasn't been canceled already
match cb.poll_cancel().expect("poll_cancel cannot error") {
match cb.poll_cancel(cx).expect("poll_cancel cannot error") {
Async::Ready(()) => {
trace!("request canceled");
Ok(Async::Ready(None))
},
Async::NotReady => {
Async::Pending => {
let (parts, body) = req.into_parts();
let head = RequestHead {
version: parts.version,
@@ -427,12 +429,12 @@ where
// user has dropped sender handle
Ok(Async::Ready(None))
},
Ok(Async::NotReady) => return Ok(Async::NotReady),
Ok(Async::Pending) => return Ok(Async::Pending),
Err(_) => unreachable!("receiver cannot error"),
}
}
fn recv_msg(&mut self, msg: ::Result<(Self::RecvItem, Body)>) -> ::Result<()> {
fn recv_msg(&mut self, cx: &mut task::Context, msg: ::Result<(Self::RecvItem, Body)>) -> ::Result<()> {
match msg {
Ok((msg, body)) => {
if let Some(cb) = self.callback.take() {
@@ -450,7 +452,7 @@ where
if let Some(cb) = self.callback.take() {
let _ = cb.send(Err((err, None)));
Ok(())
} else if let Ok(Async::Ready(Some((req, cb)))) = self.rx.poll() {
} else if let Ok(Async::Ready(Some((req, cb)))) = self.rx.poll_next(cx) {
trace!("canceling queued request with connection error: {}", err);
// in this case, the message was never even started, so it's safe to tell
// the user that the request was completely canceled
@@ -463,14 +465,14 @@ where
}
}
fn poll_ready(&mut self) -> Poll<(), ()> {
fn poll_ready(&mut self, cx: &mut task::Context) -> Poll<(), ()> {
match self.callback {
Some(ref mut cb) => match cb.poll_cancel() {
Some(ref mut cb) => match cb.poll_cancel(cx) {
Ok(Async::Ready(())) => {
trace!("callback receiver has dropped");
Err(())
},
Ok(Async::NotReady) => Ok(Async::Ready(())),
Ok(Async::Pending) => Ok(Async::Ready(())),
Err(_) => unreachable!("oneshot poll_cancel cannot error"),
},
None => Err(()),
@@ -487,31 +489,32 @@ mod tests {
extern crate pretty_env_logger;
use super::*;
use futures::executor::block_on;
use futures::future::lazy;
use mock::AsyncIo;
use proto::ClientTransaction;
#[test]
fn client_read_bytes_before_writing_request() {
let _ = pretty_env_logger::try_init();
::futures::lazy(|| {
block_on(lazy(|cx| {
let io = AsyncIo::new_buf(b"HTTP/1.1 200 OK\r\n\r\n".to_vec(), 100);
let (mut tx, rx) = ::client::dispatch::channel();
let conn = Conn::<_, ::Chunk, ClientTransaction>::new(io);
let mut dispatcher = Dispatcher::new(Client::new(rx), conn);
let res_rx = tx.try_send(::Request::new(::Body::empty())).unwrap();
let mut res_rx = tx.try_send(::Request::new(::Body::empty())).unwrap();
let a1 = dispatcher.poll().expect("error should be sent on channel");
let a1 = dispatcher.poll(cx).expect("error should be sent on channel");
assert!(a1.is_ready(), "dispatcher should be closed");
let err = res_rx.wait()
.expect("callback poll")
.expect_err("callback response");
let result = res_rx.poll(cx)
.expect("callback poll");
match err {
(::Error::Cancel(_), Some(_)) => (),
other => panic!("expected Canceled, got {:?}", other),
match result {
Async::Ready(Err((::Error::Cancel(_), Some(_)))) => (),
other => panic!("expected Err(Canceled), got {:?}", other),
}
Ok::<(), ()>(())
}).wait().unwrap();
Ok::<_, ()>(())
})).unwrap();
}
}

View File

@@ -1,12 +1,12 @@
use std::cell::Cell;
use std::collections::VecDeque;
use std::fmt;
use std::io;
use bytes::{Buf, BufMut, Bytes, BytesMut};
use futures::{Async, Poll};
use futures::task;
use futures::io::{AsyncRead, AsyncWrite};
use iovec::IoVec;
use tokio_io::{AsyncRead, AsyncWrite};
use proto::{Http1Transaction, MessageHead};
@@ -108,7 +108,7 @@ where
}
}
pub fn parse<S: Http1Transaction>(&mut self) -> Poll<MessageHead<S::Incoming>, ::Error> {
pub fn parse<S: Http1Transaction>(&mut self, cx: &mut task::Context) -> Poll<MessageHead<S::Incoming>, ::Error> {
loop {
match try!(S::parse(&mut self.read_buf)) {
Some((head, len)) => {
@@ -122,7 +122,7 @@ where
}
},
}
match try_ready!(self.read_from_io()) {
match try_ready!(self.read_from_io(cx)) {
0 => {
trace!("parse eof");
return Err(::Error::Incomplete);
@@ -132,21 +132,21 @@ where
}
}
pub fn read_from_io(&mut self) -> Poll<usize, io::Error> {
pub fn read_from_io(&mut self, cx: &mut task::Context) -> Poll<usize, io::Error> {
use bytes::BufMut;
self.read_blocked = false;
if self.read_buf.remaining_mut() < INIT_BUFFER_SIZE {
self.read_buf.reserve(INIT_BUFFER_SIZE);
}
self.io.read_buf(&mut self.read_buf).map(|ok| {
read_buf(&mut self.io, cx, &mut self.read_buf).map(|ok| {
match ok {
Async::Ready(n) => {
debug!("read {} bytes", n);
Async::Ready(n)
},
Async::NotReady => {
Async::Pending => {
self.read_blocked = true;
Async::NotReady
Async::Pending
}
}
})
@@ -164,14 +164,14 @@ where
self.read_blocked
}
pub fn flush(&mut self) -> Poll<(), io::Error> {
pub fn flush(&mut self, cx: &mut task::Context) -> Poll<(), io::Error> {
if self.flush_pipeline && !self.read_buf.is_empty() {
//Ok(())
} else if self.write_buf.remaining() == 0 {
try_nb!(self.io.flush());
try_ready!(self.io.poll_flush(cx));
} else {
loop {
let n = try_ready!(self.io.write_buf(&mut self.write_buf.auto()));
let n = try_ready!(self.write_buf.poll_flush_into(&mut self.io, cx));
debug!("flushed {} bytes", n);
if self.write_buf.remaining() == 0 {
break;
@@ -180,14 +180,33 @@ where
return Err(io::ErrorKind::WriteZero.into())
}
}
try_nb!(self.io.flush())
try_ready!(self.io.poll_flush(cx))
}
Ok(Async::Ready(()))
}
}
fn read_buf<I: AsyncRead, B: BufMut>(io: &mut I, cx: &mut task::Context, buf: &mut B) -> Poll<usize, io::Error> {
if !buf.has_remaining_mut() {
return Ok(Async::Ready(0));
}
unsafe {
let n = {
let b = buf.bytes_mut();
io.initializer().initialize(b);
try_ready!(io.poll_read(cx, b))
};
buf.advance_mut(n);
Ok(Async::Ready(n))
}
}
pub trait MemRead {
fn read_mem(&mut self, len: usize) -> Poll<Bytes, io::Error>;
fn read_mem(&mut self, cx: &mut task::Context, len: usize) -> Poll<Bytes, io::Error>;
}
impl<T, B> MemRead for Buffered<T, B>
@@ -195,12 +214,12 @@ where
T: AsyncRead + AsyncWrite,
B: Buf,
{
fn read_mem(&mut self, len: usize) -> Poll<Bytes, io::Error> {
fn read_mem(&mut self, cx: &mut task::Context, len: usize) -> Poll<Bytes, io::Error> {
if !self.read_buf.is_empty() {
let n = ::std::cmp::min(len, self.read_buf.len());
Ok(Async::Ready(self.read_buf.split_to(n).freeze()))
} else {
let n = try_ready!(self.read_from_io());
let n = try_ready!(self.read_from_io(cx));
Ok(Async::Ready(self.read_buf.split_to(::std::cmp::min(len, n)).freeze()))
}
}
@@ -294,11 +313,6 @@ where
self.strategy = strategy;
}
#[inline]
fn auto(&mut self) -> WriteBufAuto<B> {
WriteBufAuto::new(self)
}
fn buffer(&mut self, buf: B) {
match self.strategy {
Strategy::Flatten => {
@@ -343,6 +357,48 @@ where
unreachable!("head_buf just pushed on back");
}
}
fn poll_flush_into<I: AsyncWrite>(&mut self, io: &mut I, cx: &mut task::Context) -> Poll<usize, io::Error> {
if !self.has_remaining() {
return Ok(Async::Ready(0));
}
let (num_bufs_avail, num_bytes_written, len_first_buf) = {
static PLACEHOLDER: &[u8] = &[0];
let mut bufs = [From::from(PLACEHOLDER); 64];
let num_bufs_avail = self.bytes_vec(&mut bufs[..]);
let num_bytes_written = try_ready!(io.poll_vectored_write(cx, &bufs[..num_bufs_avail]));
(num_bufs_avail, num_bytes_written, bufs[0].len())
};
self.advance(num_bytes_written);
if let Strategy::Auto = self.strategy {
if num_bufs_avail > 1 {
// If there's more than one IoVec available, attempt to
// determine the best buffering strategy based on whether
// the underlying AsyncWrite object supports vectored I/O.
if num_bytes_written == len_first_buf {
// If only the first of many IoVec was written, we can assume
// with some certainty that vectored I/O _is not_ supported.
//
// Switch to a flattening strategy for buffering data.
trace!("detected no usage of vectored write, flattening");
let mut vec = Vec::new();
vec.put(&mut self.buf);
self.buf.bufs.push_back(VecOrBuf::Vec(Cursor::new(vec)));
self.strategy = Strategy::Flatten;
} else if num_bytes_written > len_first_buf {
// If more than the first IoVec was written, we can assume
// with some certainty that vectored I/O _is_ supported.
//
// Switch to a queuing strategy for buffering data.
self.strategy = Strategy::Queue;
}
}
}
Ok(Async::Ready(num_bytes_written))
}
}
impl<B: Buf> fmt::Debug for WriteBuf<B> {
@@ -376,65 +432,6 @@ impl<B: Buf> Buf for WriteBuf<B> {
}
}
/// Detects when wrapped `WriteBuf` is used for vectored IO, and
/// adjusts the `WriteBuf` strategy if not.
struct WriteBufAuto<'a, B: Buf + 'a> {
bytes_called: Cell<bool>,
bytes_vec_called: Cell<bool>,
inner: &'a mut WriteBuf<B>,
}
impl<'a, B: Buf> WriteBufAuto<'a, B> {
fn new(inner: &'a mut WriteBuf<B>) -> WriteBufAuto<'a, B> {
WriteBufAuto {
bytes_called: Cell::new(false),
bytes_vec_called: Cell::new(false),
inner: inner,
}
}
}
impl<'a, B: Buf> Buf for WriteBufAuto<'a, B> {
#[inline]
fn remaining(&self) -> usize {
self.inner.remaining()
}
#[inline]
fn bytes(&self) -> &[u8] {
self.bytes_called.set(true);
self.inner.bytes()
}
#[inline]
fn advance(&mut self, cnt: usize) {
self.inner.advance(cnt)
}
#[inline]
fn bytes_vec<'t>(&'t self, dst: &mut [&'t IoVec]) -> usize {
self.bytes_vec_called.set(true);
self.inner.bytes_vec(dst)
}
}
impl<'a, B: Buf + 'a> Drop for WriteBufAuto<'a, B> {
fn drop(&mut self) {
if let Strategy::Auto = self.inner.strategy {
if self.bytes_vec_called.get() {
self.inner.strategy = Strategy::Queue;
} else if self.bytes_called.get() {
trace!("detected no usage of vectored write, flattening");
self.inner.strategy = Strategy::Flatten;
let mut vec = Vec::new();
vec.put(&mut self.inner.buf);
self.inner.buf.bufs.push_back(VecOrBuf::Vec(Cursor::new(vec)));
}
}
}
}
#[derive(Debug)]
enum Strategy {
Auto,
@@ -568,51 +565,68 @@ impl<T: Buf> Buf for BufDeque<T> {
mod tests {
use super::*;
use std::io::Read;
use futures::task;
use futures::future;
use futures::executor::block_on;
use futures::io::AsyncRead;
use mock::AsyncIo;
#[cfg(test)]
impl<T: Read> MemRead for ::mock::AsyncIo<T> {
fn read_mem(&mut self, len: usize) -> Poll<Bytes, io::Error> {
fn read_mem(&mut self, cx: &mut task::Context, len: usize) -> Poll<Bytes, io::Error> {
let mut v = vec![0; len];
let n = try_nb!(self.read(v.as_mut_slice()));
let n = try_ready!(self.poll_read(cx, v.as_mut_slice()));
Ok(Async::Ready(BytesMut::from(&v[..n]).freeze()))
}
}
#[test]
fn iobuf_write_empty_slice() {
let mut mock = AsyncIo::new_buf(vec![], 256);
mock.error(io::Error::new(io::ErrorKind::Other, "logic error"));
block_on(future::lazy(|cx| {
let mut mock = AsyncIo::new_buf(vec![], 256);
mock.error(io::Error::new(io::ErrorKind::Other, "logic error"));
let mut io_buf = Buffered::<_, Cursor<Vec<u8>>>::new(mock);
let mut io_buf = Buffered::<_, Cursor<Vec<u8>>>::new(mock);
// underlying io will return the logic error upon write,
// so we are testing that the io_buf does not trigger a write
// when there is nothing to flush
io_buf.flush().expect("should short-circuit flush");
// underlying io will return the logic error upon write,
// so we are testing that the io_buf does not trigger a write
// when there is nothing to flush
io_buf.flush(cx).expect("should short-circuit flush");
Ok::<_, ()>(())
})).unwrap()
}
#[test]
fn parse_reads_until_blocked() {
// missing last line ending
let raw = "HTTP/1.1 200 OK\r\n";
block_on(future::lazy(|cx| {
// missing last line ending
let raw = "HTTP/1.1 200 OK\r\n";
let mock = AsyncIo::new_buf(raw, raw.len());
let mut buffered = Buffered::<_, Cursor<Vec<u8>>>::new(mock);
assert_eq!(buffered.parse::<::proto::ClientTransaction>().unwrap(), Async::NotReady);
assert!(buffered.io.blocked());
let mock = AsyncIo::new_buf(raw, raw.len());
let mut buffered = Buffered::<_, Cursor<Vec<u8>>>::new(mock);
assert_eq!(buffered.parse::<::proto::ClientTransaction>(cx).unwrap(), Async::Pending);
assert!(buffered.io.blocked());
Ok::<_, ()>(())
})).unwrap()
}
#[test]
fn write_buf_skips_empty_bufs() {
let mut mock = AsyncIo::new_buf(vec![], 1024);
mock.max_read_vecs(0); // disable vectored IO
let mut buffered = Buffered::<_, Cursor<Vec<u8>>>::new(mock);
block_on(future::lazy(|cx| {
let mut mock = AsyncIo::new_buf(vec![], 1024);
mock.max_read_vecs(0); // disable vectored IO
let mut buffered = Buffered::<_, Cursor<Vec<u8>>>::new(mock);
buffered.buffer(Cursor::new(Vec::new()));
buffered.buffer(Cursor::new(b"hello".to_vec()));
buffered.flush().unwrap();
assert_eq!(buffered.io, b"hello");
buffered.buffer(Cursor::new(Vec::new()));
buffered.buffer(Cursor::new(b"hello".to_vec()));
buffered.flush(cx).unwrap();
assert_eq!(buffered.io, b"hello");
Ok::<_, ()>(())
})).unwrap()
}
#[test]
@@ -620,17 +634,22 @@ mod tests {
extern crate pretty_env_logger;
let _ = pretty_env_logger::try_init();
let mock = AsyncIo::new_buf(vec![], 1024);
let mut buffered = Buffered::<_, Cursor<Vec<u8>>>::new(mock);
block_on(future::lazy(|cx| {
let mock = AsyncIo::new_buf(vec![], 1024);
let mut buffered = Buffered::<_, Cursor<Vec<u8>>>::new(mock);
buffered.write_buf_mut().extend(b"hello ");
buffered.buffer(Cursor::new(b"world, ".to_vec()));
buffered.write_buf_mut().extend(b"it's ");
buffered.buffer(Cursor::new(b"hyper!".to_vec()));
buffered.flush().unwrap();
buffered.write_buf_mut().extend(b"hello ");
buffered.buffer(Cursor::new(b"world, ".to_vec()));
buffered.write_buf_mut().extend(b"it's ");
buffered.buffer(Cursor::new(b"hyper!".to_vec()));
assert_eq!(buffered.io.num_writes(), 0);
buffered.flush(cx).unwrap();
assert_eq!(buffered.io, b"hello world, it's hyper!");
assert_eq!(buffered.io.num_writes(), 1);
assert_eq!(buffered.io, b"hello world, it's hyper!");
assert_eq!(buffered.io.num_writes(), 1);
Ok::<_, ()>(())
})).unwrap()
}
#[test]
@@ -638,27 +657,31 @@ mod tests {
extern crate pretty_env_logger;
let _ = pretty_env_logger::try_init();
let mock = AsyncIo::new_buf(vec![], 1024);
let mut buffered = Buffered::<_, Cursor<Vec<u8>>>::new(mock);
block_on(future::lazy(|cx| {
let mock = AsyncIo::new_buf(vec![], 1024);
let mut buffered = Buffered::<_, Cursor<Vec<u8>>>::new(mock);
buffered.write_buf_mut().extend(b"hello ");
assert_eq!(buffered.write_buf.buf.bufs.len(), 1);
buffered.write_buf_mut().extend(b"world, ");
assert_eq!(buffered.write_buf.buf.bufs.len(), 1);
buffered.write_buf_mut().extend(b"hello ");
assert_eq!(buffered.write_buf.buf.bufs.len(), 1);
buffered.write_buf_mut().extend(b"world, ");
assert_eq!(buffered.write_buf.buf.bufs.len(), 1);
// after flushing, reclaim the Vec
buffered.flush().unwrap();
assert_eq!(buffered.write_buf.remaining(), 0);
assert_eq!(buffered.write_buf.buf.bufs.len(), 1);
// after flushing, reclaim the Vec
buffered.flush(cx).unwrap();
assert_eq!(buffered.write_buf.remaining(), 0);
assert_eq!(buffered.write_buf.buf.bufs.len(), 1);
// add a user buf in the way
buffered.buffer(Cursor::new(b"it's ".to_vec()));
// and then add more hyper bytes
buffered.write_buf_mut().extend(b"hyper!");
buffered.flush().unwrap();
assert_eq!(buffered.write_buf.buf.bufs.len(), 1);
// add a user buf in the way
buffered.buffer(Cursor::new(b"it's ".to_vec()));
// and then add more hyper bytes
buffered.write_buf_mut().extend(b"hyper!");
buffered.flush(cx).unwrap();
assert_eq!(buffered.write_buf.buf.bufs.len(), 1);
assert_eq!(buffered.io, b"hello world, it's hyper!");
assert_eq!(buffered.io, b"hello world, it's hyper!");
Ok::<_, ()>(())
})).unwrap()
}
#[test]
@@ -666,21 +689,25 @@ mod tests {
extern crate pretty_env_logger;
let _ = pretty_env_logger::try_init();
let mock = AsyncIo::new_buf(vec![], 1024);
let mut buffered = Buffered::<_, Cursor<Vec<u8>>>::new(mock);
buffered.write_buf.set_strategy(Strategy::Flatten);
block_on(future::lazy(|cx| {
let mock = AsyncIo::new_buf(vec![], 1024);
let mut buffered = Buffered::<_, Cursor<Vec<u8>>>::new(mock);
buffered.write_buf.set_strategy(Strategy::Flatten);
buffered.write_buf_mut().extend(b"hello ");
buffered.buffer(Cursor::new(b"world, ".to_vec()));
buffered.write_buf_mut().extend(b"it's ");
buffered.buffer(Cursor::new(b"hyper!".to_vec()));
assert_eq!(buffered.write_buf.buf.bufs.len(), 1);
buffered.write_buf_mut().extend(b"hello ");
buffered.buffer(Cursor::new(b"world, ".to_vec()));
buffered.write_buf_mut().extend(b"it's ");
buffered.buffer(Cursor::new(b"hyper!".to_vec()));
assert_eq!(buffered.write_buf.buf.bufs.len(), 1);
buffered.flush().unwrap();
buffered.flush(cx).unwrap();
assert_eq!(buffered.io, b"hello world, it's hyper!");
assert_eq!(buffered.io.num_writes(), 1);
assert_eq!(buffered.write_buf.buf.bufs.len(), 1);
assert_eq!(buffered.io, b"hello world, it's hyper!");
assert_eq!(buffered.io.num_writes(), 1);
assert_eq!(buffered.write_buf.buf.bufs.len(), 1);
Ok::<_, ()>(())
})).unwrap()
}
#[test]
@@ -688,22 +715,26 @@ mod tests {
extern crate pretty_env_logger;
let _ = pretty_env_logger::try_init();
let mut mock = AsyncIo::new_buf(vec![], 1024);
mock.max_read_vecs(0); // disable vectored IO
let mut buffered = Buffered::<_, Cursor<Vec<u8>>>::new(mock);
block_on(future::lazy(|cx| {
let mut mock = AsyncIo::new_buf(vec![], 1024);
mock.max_read_vecs(0); // disable vectored IO
let mut buffered = Buffered::<_, Cursor<Vec<u8>>>::new(mock);
// we have 4 buffers, but hope to detect that vectored IO isn't
// being used, and switch to flattening automatically,
// resulting in only 2 writes
buffered.write_buf_mut().extend(b"hello ");
buffered.buffer(Cursor::new(b"world, ".to_vec()));
buffered.write_buf_mut().extend(b"it's hyper!");
//buffered.buffer(Cursor::new(b"hyper!".to_vec()));
buffered.flush().unwrap();
// we have 4 buffers, but hope to detect that vectored IO isn't
// being used, and switch to flattening automatically,
// resulting in only 2 writes
buffered.write_buf_mut().extend(b"hello ");
buffered.buffer(Cursor::new(b"world, ".to_vec()));
buffered.write_buf_mut().extend(b"it's hyper!");
//buffered.buffer(Cursor::new(b"hyper!".to_vec()));
buffered.flush(cx).unwrap();
assert_eq!(buffered.io, b"hello world, it's hyper!");
assert_eq!(buffered.io.num_writes(), 2);
assert_eq!(buffered.write_buf.buf.bufs.len(), 1);
assert_eq!(buffered.io, b"hello world, it's hyper!");
assert_eq!(buffered.io.num_writes(), 2);
assert_eq!(buffered.write_buf.buf.bufs.len(), 1);
Ok::<_, ()>(())
})).unwrap()
}
#[test]
@@ -711,20 +742,24 @@ mod tests {
extern crate pretty_env_logger;
let _ = pretty_env_logger::try_init();
let mut mock = AsyncIo::new_buf(vec![], 1024);
mock.max_read_vecs(0); // disable vectored IO
let mut buffered = Buffered::<_, Cursor<Vec<u8>>>::new(mock);
buffered.write_buf.set_strategy(Strategy::Queue);
block_on(future::lazy(move |cx| {
let mut mock = AsyncIo::new_buf(vec![], 1024);
mock.max_read_vecs(0); // disable vectored IO
let mut buffered = Buffered::<_, Cursor<Vec<u8>>>::new(mock);
buffered.write_buf.set_strategy(Strategy::Queue);
// we have 4 buffers, and vec IO disabled, but explicitly said
// don't try to auto detect (via setting strategy above)
buffered.write_buf_mut().extend(b"hello ");
buffered.buffer(Cursor::new(b"world, ".to_vec()));
buffered.write_buf_mut().extend(b"it's ");
buffered.buffer(Cursor::new(b"hyper!".to_vec()));
buffered.flush().unwrap();
// we have 4 buffers, and vec IO disabled, but explicitly said
// don't try to auto detect (via setting strategy above)
buffered.write_buf_mut().extend(b"hello ");
buffered.buffer(Cursor::new(b"world, ".to_vec()));
buffered.write_buf_mut().extend(b"it's ");
buffered.buffer(Cursor::new(b"hyper!".to_vec()));
buffered.flush(cx).unwrap();
assert_eq!(buffered.io, b"hello world, it's hyper!");
assert_eq!(buffered.io.num_writes(), 4);
assert_eq!(buffered.io, b"hello world, it's hyper!");
assert_eq!(buffered.io.num_writes(), 4);
Ok::<_, ()>(())
})).unwrap()
}
}