refactor(lib): convert usage of tokio_core::io to tokio_io
This commit updates to the most recent versions (released today) of the various Tokio libraries in use. Namely the `tokio_core::io` module has now been deprecated in favor of an external `tokio-io` crate. This commit pulls in that crate and uses the `AsyncRead + AsyncWrite` abstraction instead of `Io` from tokio-core. BREAKING CHANGE: Any external types that were using that had implemented `Io` will need to implement `AsyncRead + AsyncWrite` from tokio_io.
This commit is contained in:
committed by
Sean McArthur
parent
34509ef51a
commit
8554904dc9
@@ -22,17 +22,17 @@ include = [
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
base64 = "0.4"
|
base64 = "0.4"
|
||||||
bytes = "0.4"
|
bytes = "0.4"
|
||||||
futures = "0.1.7"
|
futures = "0.1.11"
|
||||||
futures-cpupool = "0.1"
|
futures-cpupool = "0.1"
|
||||||
httparse = "1.0"
|
httparse = "1.0"
|
||||||
language-tags = "0.2"
|
language-tags = "0.2"
|
||||||
log = "0.3"
|
log = "0.3"
|
||||||
mime = "0.2"
|
mime = "0.2"
|
||||||
relay = "0.1"
|
|
||||||
time = "0.1"
|
time = "0.1"
|
||||||
tokio-core = "0.1"
|
tokio-core = "0.1.6"
|
||||||
tokio-proto = "0.1"
|
tokio-proto = "0.1"
|
||||||
tokio-service = "0.1"
|
tokio-service = "0.1"
|
||||||
|
tokio-io = "0.1"
|
||||||
unicase = "1.0"
|
unicase = "1.0"
|
||||||
url = "1.0"
|
url = "1.0"
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use std::io;
|
|||||||
//use std::net::SocketAddr;
|
//use std::net::SocketAddr;
|
||||||
|
|
||||||
use futures::{Future, Poll, Async};
|
use futures::{Future, Poll, Async};
|
||||||
use tokio::io::Io;
|
use tokio_io::{AsyncRead, AsyncWrite};
|
||||||
use tokio::reactor::Handle;
|
use tokio::reactor::Handle;
|
||||||
use tokio::net::{TcpStream, TcpStreamNew};
|
use tokio::net::{TcpStream, TcpStreamNew};
|
||||||
use tokio_service::Service;
|
use tokio_service::Service;
|
||||||
@@ -18,7 +18,7 @@ use super::dns;
|
|||||||
/// `Request=Url` and `Response: Io` instead.
|
/// `Request=Url` and `Response: Io` instead.
|
||||||
pub trait Connect: Service<Request=Url, Error=io::Error> + 'static {
|
pub trait Connect: Service<Request=Url, Error=io::Error> + 'static {
|
||||||
/// The connected Io Stream.
|
/// The connected Io Stream.
|
||||||
type Output: Io + 'static;
|
type Output: AsyncRead + AsyncWrite + 'static;
|
||||||
/// A Future that will resolve to the connected Stream.
|
/// A Future that will resolve to the connected Stream.
|
||||||
type Future: Future<Item=Self::Output, Error=io::Error> + 'static;
|
type Future: Future<Item=Self::Output, Error=io::Error> + 'static;
|
||||||
/// Connect to a remote address.
|
/// Connect to a remote address.
|
||||||
@@ -27,7 +27,7 @@ pub trait Connect: Service<Request=Url, Error=io::Error> + 'static {
|
|||||||
|
|
||||||
impl<T> Connect for T
|
impl<T> Connect for T
|
||||||
where T: Service<Request=Url, Error=io::Error> + 'static,
|
where T: Service<Request=Url, Error=io::Error> + 'static,
|
||||||
T::Response: Io,
|
T::Response: AsyncRead + AsyncWrite,
|
||||||
T::Future: Future<Error=io::Error>,
|
T::Future: Future<Error=io::Error>,
|
||||||
{
|
{
|
||||||
type Output = T::Response;
|
type Output = T::Response;
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ use std::rc::Rc;
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use futures::{Poll, Async, Future, Stream};
|
use futures::{Poll, Async, Future, Stream};
|
||||||
use relay;
|
use futures::unsync::oneshot;
|
||||||
use tokio::io::Io;
|
use tokio_io::{AsyncRead, AsyncWrite};
|
||||||
use tokio::reactor::Handle;
|
use tokio::reactor::Handle;
|
||||||
use tokio_proto::BindClient;
|
use tokio_proto::BindClient;
|
||||||
use tokio_proto::streaming::Message;
|
use tokio_proto::streaming::Message;
|
||||||
@@ -149,12 +149,12 @@ where C: Connect,
|
|||||||
let pool_key = Rc::new(url[..::url::Position::BeforePath].to_owned());
|
let pool_key = Rc::new(url[..::url::Position::BeforePath].to_owned());
|
||||||
self.connector.connect(url)
|
self.connector.connect(url)
|
||||||
.map(move |io| {
|
.map(move |io| {
|
||||||
let (tx, rx) = relay::channel();
|
let (tx, rx) = oneshot::channel();
|
||||||
let client = HttpClient {
|
let client = HttpClient {
|
||||||
client_rx: RefCell::new(Some(rx)),
|
client_rx: RefCell::new(Some(rx)),
|
||||||
}.bind_client(&handle, io);
|
}.bind_client(&handle, io);
|
||||||
let pooled = pool.pooled(pool_key, client);
|
let pooled = pool.pooled(pool_key, client);
|
||||||
tx.complete(pooled.clone());
|
drop(tx.send(pooled.clone()));
|
||||||
pooled
|
pooled
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
@@ -207,11 +207,11 @@ impl<C, B> fmt::Debug for Client<C, B> {
|
|||||||
type TokioClient<B> = ClientProxy<Message<http::RequestHead, B>, Message<http::ResponseHead, TokioBody>, ::Error>;
|
type TokioClient<B> = ClientProxy<Message<http::RequestHead, B>, Message<http::ResponseHead, TokioBody>, ::Error>;
|
||||||
|
|
||||||
struct HttpClient<B> {
|
struct HttpClient<B> {
|
||||||
client_rx: RefCell<Option<relay::Receiver<Pooled<TokioClient<B>>>>>,
|
client_rx: RefCell<Option<oneshot::Receiver<Pooled<TokioClient<B>>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, B> ClientProto<T> for HttpClient<B>
|
impl<T, B> ClientProto<T> for HttpClient<B>
|
||||||
where T: Io + 'static,
|
where T: AsyncRead + AsyncWrite + 'static,
|
||||||
B: Stream<Error=::Error> + 'static,
|
B: Stream<Error=::Error> + 'static,
|
||||||
B::Item: AsRef<[u8]>,
|
B::Item: AsRef<[u8]>,
|
||||||
{
|
{
|
||||||
@@ -232,12 +232,12 @@ where T: Io + 'static,
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct BindingClient<T, B> {
|
struct BindingClient<T, B> {
|
||||||
rx: relay::Receiver<Pooled<TokioClient<B>>>,
|
rx: oneshot::Receiver<Pooled<TokioClient<B>>>,
|
||||||
io: Option<T>,
|
io: Option<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, B> Future for BindingClient<T, B>
|
impl<T, B> Future for BindingClient<T, B>
|
||||||
where T: Io + 'static,
|
where T: AsyncRead + AsyncWrite + 'static,
|
||||||
B: Stream<Error=::Error>,
|
B: Stream<Error=::Error>,
|
||||||
B::Item: AsRef<[u8]>,
|
B::Item: AsRef<[u8]>,
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use std::rc::Rc;
|
|||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use futures::{Future, Async, Poll};
|
use futures::{Future, Async, Poll};
|
||||||
use relay;
|
use futures::unsync::oneshot;
|
||||||
|
|
||||||
use http::{KeepAlive, KA};
|
use http::{KeepAlive, KA};
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ pub struct Pool<T> {
|
|||||||
struct PoolInner<T> {
|
struct PoolInner<T> {
|
||||||
enabled: bool,
|
enabled: bool,
|
||||||
idle: HashMap<Rc<String>, Vec<Entry<T>>>,
|
idle: HashMap<Rc<String>, Vec<Entry<T>>>,
|
||||||
parked: HashMap<Rc<String>, VecDeque<relay::Sender<Entry<T>>>>,
|
parked: HashMap<Rc<String>, VecDeque<oneshot::Sender<Entry<T>>>>,
|
||||||
timeout: Option<Duration>,
|
timeout: Option<Duration>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,31 +44,33 @@ impl<T: Clone> Pool<T> {
|
|||||||
|
|
||||||
fn put(&mut self, key: Rc<String>, entry: Entry<T>) {
|
fn put(&mut self, key: Rc<String>, entry: Entry<T>) {
|
||||||
trace!("Pool::put {:?}", key);
|
trace!("Pool::put {:?}", key);
|
||||||
|
let mut inner = self.inner.borrow_mut();
|
||||||
|
//let inner = &mut *inner;
|
||||||
let mut remove_parked = false;
|
let mut remove_parked = false;
|
||||||
let tx = self.inner.borrow_mut().parked.get_mut(&key).and_then(|parked| {
|
let mut entry = Some(entry);
|
||||||
let mut ret = None;
|
if let Some(parked) = inner.parked.get_mut(&key) {
|
||||||
while let Some(tx) = parked.pop_front() {
|
while let Some(tx) = parked.pop_front() {
|
||||||
if !tx.is_canceled() {
|
match tx.send(entry.take().unwrap()) {
|
||||||
ret = Some(tx);
|
Ok(()) => break,
|
||||||
break;
|
Err(e) => {
|
||||||
|
trace!("Pool::put removing canceled parked {:?}", key);
|
||||||
|
entry = Some(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
trace!("Pool::put removing canceled parked {:?}", key);
|
|
||||||
}
|
}
|
||||||
remove_parked = parked.is_empty();
|
remove_parked = parked.is_empty();
|
||||||
ret
|
}
|
||||||
});
|
|
||||||
if remove_parked {
|
if remove_parked {
|
||||||
self.inner.borrow_mut().parked.remove(&key);
|
inner.parked.remove(&key);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(tx) = tx {
|
match entry {
|
||||||
trace!("Pool::put found parked {:?}", key);
|
Some(entry) => {
|
||||||
tx.complete(entry);
|
inner.idle.entry(key)
|
||||||
} else {
|
.or_insert(Vec::new())
|
||||||
self.inner.borrow_mut()
|
.push(entry);
|
||||||
.idle.entry(key)
|
}
|
||||||
.or_insert(Vec::new())
|
None => trace!("Pool::put found parked {:?}", key),
|
||||||
.push(entry);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +102,7 @@ impl<T: Clone> Pool<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn park(&mut self, key: Rc<String>, tx: relay::Sender<Entry<T>>) {
|
fn park(&mut self, key: Rc<String>, tx: oneshot::Sender<Entry<T>>) {
|
||||||
trace!("Pool::park {:?}", key);
|
trace!("Pool::park {:?}", key);
|
||||||
self.inner.borrow_mut()
|
self.inner.borrow_mut()
|
||||||
.parked.entry(key)
|
.parked.entry(key)
|
||||||
@@ -191,7 +193,7 @@ struct Entry<T> {
|
|||||||
pub struct Checkout<T> {
|
pub struct Checkout<T> {
|
||||||
key: Rc<String>,
|
key: Rc<String>,
|
||||||
pool: Pool<T>,
|
pool: Pool<T>,
|
||||||
parked: Option<relay::Receiver<Entry<T>>>,
|
parked: Option<oneshot::Receiver<Entry<T>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Clone> Future for Checkout<T> {
|
impl<T: Clone> Future for Checkout<T> {
|
||||||
@@ -247,7 +249,7 @@ impl<T: Clone> Future for Checkout<T> {
|
|||||||
Some(entry) => Ok(Async::Ready(self.pool.reuse(self.key.clone(), entry))),
|
Some(entry) => Ok(Async::Ready(self.pool.reuse(self.key.clone(), entry))),
|
||||||
None => {
|
None => {
|
||||||
if self.parked.is_none() {
|
if self.parked.is_none() {
|
||||||
let (tx, mut rx) = relay::channel();
|
let (tx, mut rx) = oneshot::channel();
|
||||||
let _ = rx.poll(); // park this task
|
let _ = rx.poll(); // park this task
|
||||||
self.pool.park(self.key.clone(), tx);
|
self.pool.park(self.key.clone(), tx);
|
||||||
self.parked = Some(rx);
|
self.parked = Some(rx);
|
||||||
@@ -279,6 +281,7 @@ mod tests {
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use futures::{Async, Future};
|
use futures::{Async, Future};
|
||||||
|
use futures::future;
|
||||||
use http::KeepAlive;
|
use http::KeepAlive;
|
||||||
use super::Pool;
|
use super::Pool;
|
||||||
|
|
||||||
@@ -297,7 +300,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_pool_checkout_returns_none_if_expired() {
|
fn test_pool_checkout_returns_none_if_expired() {
|
||||||
::futures::lazy(|| {
|
future::lazy(|| {
|
||||||
let pool = Pool::new(true, Some(Duration::from_secs(1)));
|
let pool = Pool::new(true, Some(Duration::from_secs(1)));
|
||||||
let key = Rc::new("foo".to_string());
|
let key = Rc::new("foo".to_string());
|
||||||
let mut pooled = pool.pooled(key.clone(), 41);
|
let mut pooled = pool.pooled(key.clone(), 41);
|
||||||
@@ -339,7 +342,7 @@ mod tests {
|
|||||||
let pooled1 = pool.pooled(key.clone(), 41);
|
let pooled1 = pool.pooled(key.clone(), 41);
|
||||||
|
|
||||||
let mut pooled = pooled1.clone();
|
let mut pooled = pooled1.clone();
|
||||||
let checkout = pool.checkout(&key).join(::futures::lazy(move || {
|
let checkout = pool.checkout(&key).join(future::lazy(move || {
|
||||||
// the checkout future will park first,
|
// the checkout future will park first,
|
||||||
// and then this lazy future will be polled, which will insert
|
// and then this lazy future will be polled, which will insert
|
||||||
// the pooled back into the pool
|
// the pooled back into the pool
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use std::time::Instant;
|
|||||||
|
|
||||||
use futures::{Poll, Async, AsyncSink, Stream, Sink, StartSend};
|
use futures::{Poll, Async, AsyncSink, Stream, Sink, StartSend};
|
||||||
use futures::task::Task;
|
use futures::task::Task;
|
||||||
use tokio::io::Io;
|
use tokio_io::{AsyncRead, AsyncWrite};
|
||||||
use tokio_proto::streaming::pipeline::{Frame, Transport};
|
use tokio_proto::streaming::pipeline::{Frame, Transport};
|
||||||
|
|
||||||
use header::{ContentLength, TransferEncoding};
|
use header::{ContentLength, TransferEncoding};
|
||||||
@@ -16,7 +16,7 @@ use version::HttpVersion;
|
|||||||
|
|
||||||
|
|
||||||
/// This handles a connection, which will have been established over an
|
/// This handles a connection, which will have been established over an
|
||||||
/// `Io` (like a socket), and will likely include multiple
|
/// `AsyncRead + AsyncWrite` (like a socket), and will likely include multiple
|
||||||
/// `Transaction`s over HTTP.
|
/// `Transaction`s over HTTP.
|
||||||
///
|
///
|
||||||
/// The connection will determine when a message begins and ends as well as
|
/// The connection will determine when a message begins and ends as well as
|
||||||
@@ -29,7 +29,7 @@ pub struct Conn<I, B, T, K = KA> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<I, B, T, K> Conn<I, B, T, K>
|
impl<I, B, T, K> Conn<I, B, T, K>
|
||||||
where I: Io,
|
where I: AsyncRead + AsyncWrite,
|
||||||
B: AsRef<[u8]>,
|
B: AsRef<[u8]>,
|
||||||
T: Http1Transaction,
|
T: Http1Transaction,
|
||||||
K: KeepAlive
|
K: KeepAlive
|
||||||
@@ -155,7 +155,7 @@ where I: Io,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn maybe_park_read(&mut self) {
|
fn maybe_park_read(&mut self) {
|
||||||
if self.io.poll_read().is_ready() {
|
if !self.io.is_read_blocked() {
|
||||||
// the Io object is ready to read, which means it will never alert
|
// 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
|
// 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
|
// finished reading, so we need to park the task to be able to
|
||||||
@@ -350,7 +350,7 @@ where I: Io,
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<I, B, T, K> Stream for Conn<I, B, T, K>
|
impl<I, B, T, K> Stream for Conn<I, B, T, K>
|
||||||
where I: Io,
|
where I: AsyncRead + AsyncWrite,
|
||||||
B: AsRef<[u8]>,
|
B: AsRef<[u8]>,
|
||||||
T: Http1Transaction,
|
T: Http1Transaction,
|
||||||
K: KeepAlive,
|
K: KeepAlive,
|
||||||
@@ -385,7 +385,7 @@ where I: Io,
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<I, B, T, K> Sink for Conn<I, B, T, K>
|
impl<I, B, T, K> Sink for Conn<I, B, T, K>
|
||||||
where I: Io,
|
where I: AsyncRead + AsyncWrite,
|
||||||
B: AsRef<[u8]>,
|
B: AsRef<[u8]>,
|
||||||
T: Http1Transaction,
|
T: Http1Transaction,
|
||||||
K: KeepAlive,
|
K: KeepAlive,
|
||||||
@@ -450,10 +450,15 @@ where I: Io,
|
|||||||
trace!("Conn::flush = {:?}", ret);
|
trace!("Conn::flush = {:?}", ret);
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn close(&mut self) -> Poll<(), Self::SinkError> {
|
||||||
|
try_ready!(self.poll_complete());
|
||||||
|
self.io.io_mut().shutdown()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I, B, T, K> Transport for Conn<I, B, T, K>
|
impl<I, B, T, K> Transport for Conn<I, B, T, K>
|
||||||
where I: Io + 'static,
|
where I: AsyncRead + AsyncWrite + 'static,
|
||||||
B: AsRef<[u8]> + 'static,
|
B: AsRef<[u8]> + 'static,
|
||||||
T: Http1Transaction + 'static,
|
T: Http1Transaction + 'static,
|
||||||
K: KeepAlive + 'static,
|
K: KeepAlive + 'static,
|
||||||
@@ -665,6 +670,7 @@ impl<'a, T: fmt::Debug + 'a, B: AsRef<[u8]> + 'a> fmt::Debug for DebugFrame<'a,
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use futures::{Async, Future, Stream, Sink};
|
use futures::{Async, Future, Stream, Sink};
|
||||||
|
use futures::future;
|
||||||
use tokio_proto::streaming::pipeline::Frame;
|
use tokio_proto::streaming::pipeline::Frame;
|
||||||
|
|
||||||
use http::{self, MessageHead, ServerTransaction};
|
use http::{self, MessageHead, ServerTransaction};
|
||||||
@@ -705,7 +711,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_conn_parse_partial() {
|
fn test_conn_parse_partial() {
|
||||||
let _: Result<(), ()> = ::futures::lazy(|| {
|
let _: Result<(), ()> = future::lazy(|| {
|
||||||
let good_message = b"GET / HTTP/1.1\r\nHost: foo.bar\r\n\r\n".to_vec();
|
let good_message = b"GET / HTTP/1.1\r\nHost: foo.bar\r\n\r\n".to_vec();
|
||||||
let io = AsyncIo::new_buf(good_message, 10);
|
let io = AsyncIo::new_buf(good_message, 10);
|
||||||
let mut conn = Conn::<_, http::Chunk, ServerTransaction>::new(io, Default::default());
|
let mut conn = Conn::<_, http::Chunk, ServerTransaction>::new(io, Default::default());
|
||||||
@@ -772,7 +778,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_conn_body_write_length() {
|
fn test_conn_body_write_length() {
|
||||||
let _: Result<(), ()> = ::futures::lazy(|| {
|
let _: Result<(), ()> = future::lazy(|| {
|
||||||
let io = AsyncIo::new_buf(vec![], 0);
|
let io = AsyncIo::new_buf(vec![], 0);
|
||||||
let mut conn = Conn::<_, http::Chunk, ServerTransaction>::new(io, Default::default());
|
let mut conn = Conn::<_, http::Chunk, ServerTransaction>::new(io, Default::default());
|
||||||
let max = ::http::io::MAX_BUFFER_SIZE + 4096;
|
let max = ::http::io::MAX_BUFFER_SIZE + 4096;
|
||||||
@@ -800,7 +806,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_conn_body_write_chunked() {
|
fn test_conn_body_write_chunked() {
|
||||||
let _: Result<(), ()> = ::futures::lazy(|| {
|
let _: Result<(), ()> = future::lazy(|| {
|
||||||
let io = AsyncIo::new_buf(vec![], 4096);
|
let io = AsyncIo::new_buf(vec![], 4096);
|
||||||
let mut conn = Conn::<_, http::Chunk, ServerTransaction>::new(io, Default::default());
|
let mut conn = Conn::<_, http::Chunk, ServerTransaction>::new(io, Default::default());
|
||||||
conn.state.writing = Writing::Body(Encoder::chunked(), None);
|
conn.state.writing = Writing::Body(Encoder::chunked(), None);
|
||||||
@@ -813,7 +819,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_conn_body_flush() {
|
fn test_conn_body_flush() {
|
||||||
let _: Result<(), ()> = ::futures::lazy(|| {
|
let _: Result<(), ()> = future::lazy(|| {
|
||||||
let io = AsyncIo::new_buf(vec![], 1024 * 1024 * 5);
|
let io = AsyncIo::new_buf(vec![], 1024 * 1024 * 5);
|
||||||
let mut conn = Conn::<_, http::Chunk, ServerTransaction>::new(io, Default::default());
|
let mut conn = Conn::<_, http::Chunk, ServerTransaction>::new(io, Default::default());
|
||||||
conn.state.writing = Writing::Body(Encoder::length(1024 * 1024), None);
|
conn.state.writing = Writing::Body(Encoder::length(1024 * 1024), None);
|
||||||
@@ -829,7 +835,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_conn_parking() {
|
fn test_conn_parking() {
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use futures::task::Unpark;
|
use futures::executor::Unpark;
|
||||||
|
|
||||||
struct Car {
|
struct Car {
|
||||||
permit: bool,
|
permit: bool,
|
||||||
@@ -847,7 +853,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// test that once writing is done, unparks
|
// test that once writing is done, unparks
|
||||||
let f = ::futures::lazy(|| {
|
let f = future::lazy(|| {
|
||||||
let io = AsyncIo::new_buf(vec![], 4096);
|
let io = AsyncIo::new_buf(vec![], 4096);
|
||||||
let mut conn = Conn::<_, http::Chunk, ServerTransaction>::new(io, Default::default());
|
let mut conn = Conn::<_, http::Chunk, ServerTransaction>::new(io, Default::default());
|
||||||
conn.state.reading = Reading::KeepAlive;
|
conn.state.reading = Reading::KeepAlive;
|
||||||
@@ -861,7 +867,7 @@ mod tests {
|
|||||||
|
|
||||||
|
|
||||||
// test that flushing when not waiting on read doesn't unpark
|
// test that flushing when not waiting on read doesn't unpark
|
||||||
let f = ::futures::lazy(|| {
|
let f = future::lazy(|| {
|
||||||
let io = AsyncIo::new_buf(vec![], 4096);
|
let io = AsyncIo::new_buf(vec![], 4096);
|
||||||
let mut conn = Conn::<_, http::Chunk, ServerTransaction>::new(io, Default::default());
|
let mut conn = Conn::<_, http::Chunk, ServerTransaction>::new(io, Default::default());
|
||||||
conn.state.writing = Writing::KeepAlive;
|
conn.state.writing = Writing::KeepAlive;
|
||||||
@@ -872,7 +878,7 @@ mod tests {
|
|||||||
|
|
||||||
|
|
||||||
// test that flushing and writing isn't done doesn't unpark
|
// test that flushing and writing isn't done doesn't unpark
|
||||||
let f = ::futures::lazy(|| {
|
let f = future::lazy(|| {
|
||||||
let io = AsyncIo::new_buf(vec![], 4096);
|
let io = AsyncIo::new_buf(vec![], 4096);
|
||||||
let mut conn = Conn::<_, http::Chunk, ServerTransaction>::new(io, Default::default());
|
let mut conn = Conn::<_, http::Chunk, ServerTransaction>::new(io, Default::default());
|
||||||
conn.state.reading = Reading::KeepAlive;
|
conn.state.reading = Reading::KeepAlive;
|
||||||
|
|||||||
@@ -295,7 +295,7 @@ mod tests {
|
|||||||
let (a, b) = self.split_at(n);
|
let (a, b) = self.split_at(n);
|
||||||
let mut buf = BytesMut::from(a);
|
let mut buf = BytesMut::from(a);
|
||||||
*self = b;
|
*self = b;
|
||||||
Ok(buf.drain_to(n).freeze())
|
Ok(buf.split_to(n).freeze())
|
||||||
} else {
|
} else {
|
||||||
Ok(Bytes::new())
|
Ok(Bytes::new())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ impl Http1Transaction for ServerTransaction {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut headers = Headers::with_capacity(headers_len);
|
let mut headers = Headers::with_capacity(headers_len);
|
||||||
let slice = buf.drain_to(len).freeze();
|
let slice = buf.split_to(len).freeze();
|
||||||
let path = slice.slice(path.0, path.1);
|
let path = slice.slice(path.0, path.1);
|
||||||
// path was found to be utf8 by httparse
|
// path was found to be utf8 by httparse
|
||||||
let path = unsafe { ByteStr::from_utf8_unchecked(path) };
|
let path = unsafe { ByteStr::from_utf8_unchecked(path) };
|
||||||
@@ -171,7 +171,7 @@ impl Http1Transaction for ClientTransaction {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut headers = Headers::with_capacity(headers_len);
|
let mut headers = Headers::with_capacity(headers_len);
|
||||||
let slice = buf.drain_to(len).freeze();
|
let slice = buf.split_to(len).freeze();
|
||||||
headers.extend(HeadersAsBytesIter {
|
headers.extend(HeadersAsBytesIter {
|
||||||
headers: headers_indices[..headers_len].iter(),
|
headers: headers_indices[..headers_len].iter(),
|
||||||
slice: slice,
|
slice: slice,
|
||||||
|
|||||||
@@ -3,8 +3,7 @@ use std::fmt;
|
|||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
use futures::Async;
|
use tokio_io::{AsyncRead, AsyncWrite};
|
||||||
use tokio::io::Io;
|
|
||||||
|
|
||||||
use http::{Http1Transaction, h1, MessageHead, ParseResult, DebugTruncate};
|
use http::{Http1Transaction, h1, MessageHead, ParseResult, DebugTruncate};
|
||||||
use bytes::{BytesMut, Bytes};
|
use bytes::{BytesMut, Bytes};
|
||||||
@@ -14,6 +13,7 @@ pub const MAX_BUFFER_SIZE: usize = 8192 + 4096 * 100;
|
|||||||
|
|
||||||
pub struct Buffered<T> {
|
pub struct Buffered<T> {
|
||||||
io: T,
|
io: T,
|
||||||
|
read_blocked: bool,
|
||||||
read_buf: BytesMut,
|
read_buf: BytesMut,
|
||||||
write_buf: WriteBuf,
|
write_buf: WriteBuf,
|
||||||
}
|
}
|
||||||
@@ -27,12 +27,13 @@ impl<T> fmt::Debug for Buffered<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Io> Buffered<T> {
|
impl<T: AsyncRead + AsyncWrite> Buffered<T> {
|
||||||
pub fn new(io: T) -> Buffered<T> {
|
pub fn new(io: T) -> Buffered<T> {
|
||||||
Buffered {
|
Buffered {
|
||||||
io: io,
|
io: io,
|
||||||
read_buf: BytesMut::with_capacity(0),
|
read_buf: BytesMut::with_capacity(0),
|
||||||
write_buf: WriteBuf::new(),
|
write_buf: WriteBuf::new(),
|
||||||
|
read_blocked: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,14 +50,10 @@ impl<T: Io> Buffered<T> {
|
|||||||
_ => break,
|
_ => break,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.read_buf.drain_to(i);
|
self.read_buf.split_to(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn poll_read(&mut self) -> Async<()> {
|
|
||||||
self.io.poll_read()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse<S: Http1Transaction>(&mut self) -> ::Result<Option<MessageHead<S::Incoming>>> {
|
pub fn parse<S: Http1Transaction>(&mut self) -> ::Result<Option<MessageHead<S::Incoming>>> {
|
||||||
self.reserve_read_buf();
|
self.reserve_read_buf();
|
||||||
match self.read_from_io() {
|
match self.read_from_io() {
|
||||||
@@ -88,8 +85,17 @@ impl<T: Io> Buffered<T> {
|
|||||||
|
|
||||||
fn read_from_io(&mut self) -> io::Result<usize> {
|
fn read_from_io(&mut self) -> io::Result<usize> {
|
||||||
use bytes::BufMut;
|
use bytes::BufMut;
|
||||||
|
self.read_blocked = false;
|
||||||
unsafe {
|
unsafe {
|
||||||
let n = try!(self.io.read(self.read_buf.bytes_mut()));
|
let n = match self.io.read(self.read_buf.bytes_mut()) {
|
||||||
|
Ok(n) => n,
|
||||||
|
Err(e) => {
|
||||||
|
if e.kind() == io::ErrorKind::WouldBlock {
|
||||||
|
self.read_blocked = true;
|
||||||
|
}
|
||||||
|
return Err(e)
|
||||||
|
}
|
||||||
|
};
|
||||||
self.read_buf.advance_mut(n);
|
self.read_buf.advance_mut(n);
|
||||||
Ok(n)
|
Ok(n)
|
||||||
}
|
}
|
||||||
@@ -112,10 +118,13 @@ impl<T: Io> Buffered<T> {
|
|||||||
self.write_buf.buffer(buf.as_ref())
|
self.write_buf.buffer(buf.as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
pub fn io_mut(&mut self) -> &mut T {
|
pub fn io_mut(&mut self) -> &mut T {
|
||||||
&mut self.io
|
&mut self.io
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_read_blocked(&self) -> bool {
|
||||||
|
self.read_blocked
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Write> Write for Buffered<T> {
|
impl<T: Write> Write for Buffered<T> {
|
||||||
@@ -146,17 +155,17 @@ pub trait MemRead {
|
|||||||
fn read_mem(&mut self, len: usize) -> io::Result<Bytes>;
|
fn read_mem(&mut self, len: usize) -> io::Result<Bytes>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Io> MemRead for Buffered<T> {
|
impl<T: AsyncRead + AsyncWrite> MemRead for Buffered<T> {
|
||||||
fn read_mem(&mut self, len: usize) -> io::Result<Bytes> {
|
fn read_mem(&mut self, len: usize) -> io::Result<Bytes> {
|
||||||
trace!("Buffered.read_mem read_buf={}, wanted={}", self.read_buf.len(), len);
|
trace!("Buffered.read_mem read_buf={}, wanted={}", self.read_buf.len(), len);
|
||||||
if !self.read_buf.is_empty() {
|
if !self.read_buf.is_empty() {
|
||||||
let n = ::std::cmp::min(len, self.read_buf.len());
|
let n = ::std::cmp::min(len, self.read_buf.len());
|
||||||
trace!("Buffered.read_mem read_buf is not empty, slicing {}", n);
|
trace!("Buffered.read_mem read_buf is not empty, slicing {}", n);
|
||||||
Ok(self.read_buf.drain_to(n).freeze())
|
Ok(self.read_buf.split_to(n).freeze())
|
||||||
} else {
|
} else {
|
||||||
self.reserve_read_buf();
|
self.reserve_read_buf();
|
||||||
let n = try!(self.read_from_io());
|
let n = try!(self.read_from_io());
|
||||||
Ok(self.read_buf.drain_to(::std::cmp::min(len, n)).freeze())
|
Ok(self.read_buf.split_to(::std::cmp::min(len, n)).freeze())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,10 +21,10 @@ extern crate httparse;
|
|||||||
#[cfg_attr(test, macro_use)] extern crate language_tags;
|
#[cfg_attr(test, macro_use)] extern crate language_tags;
|
||||||
#[macro_use] extern crate log;
|
#[macro_use] extern crate log;
|
||||||
#[macro_use] pub extern crate mime;
|
#[macro_use] pub extern crate mime;
|
||||||
extern crate relay;
|
|
||||||
extern crate base64;
|
extern crate base64;
|
||||||
extern crate time;
|
extern crate time;
|
||||||
#[macro_use] extern crate tokio_core as tokio;
|
#[macro_use] extern crate tokio_core as tokio;
|
||||||
|
extern crate tokio_io;
|
||||||
extern crate tokio_proto;
|
extern crate tokio_proto;
|
||||||
extern crate tokio_service;
|
extern crate tokio_service;
|
||||||
extern crate unicase;
|
extern crate unicase;
|
||||||
|
|||||||
23
src/mock.rs
23
src/mock.rs
@@ -1,8 +1,8 @@
|
|||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::io::{self, Read, Write};
|
use std::io::{self, Read, Write};
|
||||||
|
|
||||||
use futures::Async;
|
use futures::Poll;
|
||||||
use tokio::io::Io;
|
use tokio_io::{AsyncRead, AsyncWrite};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Buf {
|
pub struct Buf {
|
||||||
@@ -123,21 +123,12 @@ impl<T: Write> Write for AsyncIo<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Read + Write> Io for AsyncIo<T> {
|
impl<T: Read + Write> AsyncRead for AsyncIo<T> {
|
||||||
fn poll_read(&mut self) -> Async<()> {
|
}
|
||||||
if self.bytes_until_block == 0 {
|
|
||||||
Async::NotReady
|
|
||||||
} else {
|
|
||||||
Async::Ready(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn poll_write(&mut self) -> Async<()> {
|
impl<T: Read + Write> AsyncWrite for AsyncIo<T> {
|
||||||
if self.bytes_until_block == 0 {
|
fn shutdown(&mut self) -> Poll<(), io::Error> {
|
||||||
Async::NotReady
|
Ok(().into())
|
||||||
} else {
|
|
||||||
Async::Ready(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,9 +13,10 @@ use std::time::Duration;
|
|||||||
|
|
||||||
use futures::future;
|
use futures::future;
|
||||||
use futures::task::{self, Task};
|
use futures::task::{self, Task};
|
||||||
use futures::{Future, Map, Stream, Poll, Async, Sink, StartSend, AsyncSink};
|
use futures::{Future, Stream, Poll, Async, Sink, StartSend, AsyncSink};
|
||||||
|
use futures::future::Map;
|
||||||
|
|
||||||
use tokio::io::Io;
|
use tokio_io::{AsyncRead, AsyncWrite};
|
||||||
use tokio::reactor::{Core, Handle, Timeout};
|
use tokio::reactor::{Core, Handle, Timeout};
|
||||||
use tokio::net::TcpListener;
|
use tokio::net::TcpListener;
|
||||||
use tokio_proto::BindServer;
|
use tokio_proto::BindServer;
|
||||||
@@ -124,7 +125,7 @@ impl<B: AsRef<[u8]> + 'static> Http<B> {
|
|||||||
service: S)
|
service: S)
|
||||||
where S: Service<Request = Request, Response = Response<Bd>, Error = ::Error> + 'static,
|
where S: Service<Request = Request, Response = Response<Bd>, Error = ::Error> + 'static,
|
||||||
Bd: Stream<Item=B, Error=::Error> + 'static,
|
Bd: Stream<Item=B, Error=::Error> + 'static,
|
||||||
I: Io + 'static,
|
I: AsyncRead + AsyncWrite + 'static,
|
||||||
{
|
{
|
||||||
self.bind_server(handle, io, HttpService {
|
self.bind_server(handle, io, HttpService {
|
||||||
inner: service,
|
inner: service,
|
||||||
@@ -165,8 +166,8 @@ pub struct __ProtoBindTransport<T, B> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T, B> ServerProto<T> for Http<B>
|
impl<T, B> ServerProto<T> for Http<B>
|
||||||
where T: Io + 'static,
|
where T: AsyncRead + AsyncWrite + 'static,
|
||||||
B: AsRef<[u8]> + 'static,
|
B: AsRef<[u8]> + 'static,
|
||||||
{
|
{
|
||||||
type Request = __ProtoRequest;
|
type Request = __ProtoRequest;
|
||||||
type RequestBody = http::Chunk;
|
type RequestBody = http::Chunk;
|
||||||
@@ -189,8 +190,8 @@ where T: Io + 'static,
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T, B> Sink for __ProtoTransport<T, B>
|
impl<T, B> Sink for __ProtoTransport<T, B>
|
||||||
where T: Io + 'static,
|
where T: AsyncRead + AsyncWrite + 'static,
|
||||||
B: AsRef<[u8]>,
|
B: AsRef<[u8]> + 'static,
|
||||||
{
|
{
|
||||||
type SinkItem = Frame<__ProtoResponse, B, ::Error>;
|
type SinkItem = Frame<__ProtoResponse, B, ::Error>;
|
||||||
type SinkError = io::Error;
|
type SinkError = io::Error;
|
||||||
@@ -224,9 +225,16 @@ where T: Io + 'static,
|
|||||||
fn poll_complete(&mut self) -> Poll<(), io::Error> {
|
fn poll_complete(&mut self) -> Poll<(), io::Error> {
|
||||||
self.0.poll_complete()
|
self.0.poll_complete()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn close(&mut self) -> Poll<(), io::Error> {
|
||||||
|
self.0.close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Io + 'static, B: AsRef<[u8]>> Stream for __ProtoTransport<T, B> {
|
impl<T, B> Stream for __ProtoTransport<T, B>
|
||||||
|
where T: AsyncRead + AsyncWrite + 'static,
|
||||||
|
B: AsRef<[u8]> + 'static,
|
||||||
|
{
|
||||||
type Item = Frame<__ProtoRequest, http::Chunk, ::Error>;
|
type Item = Frame<__ProtoRequest, http::Chunk, ::Error>;
|
||||||
type Error = io::Error;
|
type Error = io::Error;
|
||||||
|
|
||||||
@@ -246,7 +254,10 @@ impl<T: Io + 'static, B: AsRef<[u8]>> Stream for __ProtoTransport<T, B> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Io + 'static, B: AsRef<[u8]> + 'static> Transport for __ProtoTransport<T, B> {
|
impl<T, B> Transport for __ProtoTransport<T, B>
|
||||||
|
where T: AsyncRead + AsyncWrite + 'static,
|
||||||
|
B: AsRef<[u8]> + 'static,
|
||||||
|
{
|
||||||
fn tick(&mut self) {
|
fn tick(&mut self) {
|
||||||
self.0.tick()
|
self.0.tick()
|
||||||
}
|
}
|
||||||
@@ -256,7 +267,9 @@ impl<T: Io + 'static, B: AsRef<[u8]> + 'static> Transport for __ProtoTransport<T
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Io + 'static, B> Future for __ProtoBindTransport<T, B> {
|
impl<T, B> Future for __ProtoBindTransport<T, B>
|
||||||
|
where T: AsyncRead + AsyncWrite + 'static,
|
||||||
|
{
|
||||||
type Item = __ProtoTransport<T, B>;
|
type Item = __ProtoTransport<T, B>;
|
||||||
type Error = io::Error;
|
type Error = io::Error;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user