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
						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,32 +44,34 @@ 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); |                         trace!("Pool::put removing canceled parked {:?}", key); | ||||||
|  |                         entry = Some(e); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|             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 { |  | ||||||
|             self.inner.borrow_mut() |  | ||||||
|                 .idle.entry(key) |  | ||||||
|                      .or_insert(Vec::new()) |                      .or_insert(Vec::new()) | ||||||
|                      .push(entry); |                      .push(entry); | ||||||
|             } |             } | ||||||
|  |             None => trace!("Pool::put found parked {:?}", key), | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     pub fn pooled(&self, key: Rc<String>, value: T) -> Pooled<T> { |     pub fn pooled(&self, key: Rc<String>, value: T) -> Pooled<T> { | ||||||
| @@ -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; | ||||||
|   | |||||||
							
								
								
									
										21
									
								
								src/mock.rs
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								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,7 +166,7 @@ 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; | ||||||
| @@ -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