Updated as per review comments
This commit is contained in:
committed by
Sean McArthur
parent
0a4bd393ec
commit
ad7ffa795f
@@ -41,9 +41,9 @@ members = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
futures-preview = "0.3.0-alpha.18"
|
futures-preview = "0.3.0-alpha.17"
|
||||||
tokio-io = { git = "https://github.com/tokio-rs/tokio" }
|
tokio-io = "0.2.0-alpha.1"
|
||||||
tokio-codec = { git = "https://github.com/tokio-rs/tokio" }
|
tokio-codec = "0.2.0-alpha.1"
|
||||||
bytes = "0.4.7"
|
bytes = "0.4.7"
|
||||||
http = "0.1.8"
|
http = "0.1.8"
|
||||||
log = "0.4.1"
|
log = "0.4.1"
|
||||||
@@ -65,7 +65,7 @@ serde = "1.0.0"
|
|||||||
serde_json = "1.0.0"
|
serde_json = "1.0.0"
|
||||||
|
|
||||||
# Akamai example
|
# Akamai example
|
||||||
tokio = { git = "https://github.com/tokio-rs/tokio" }
|
tokio = "0.2.0-alpha.1"
|
||||||
env_logger = { version = "0.5.3", default-features = false }
|
env_logger = { version = "0.5.3", default-features = false }
|
||||||
rustls = "0.12"
|
rustls = "0.12"
|
||||||
tokio-rustls = "0.5.0"
|
tokio-rustls = "0.5.0"
|
||||||
|
|||||||
@@ -1,48 +1,14 @@
|
|||||||
#![feature(async_await)]
|
#![feature(async_await)]
|
||||||
|
|
||||||
use futures::{ready, Stream};
|
use futures::future::poll_fn;
|
||||||
|
use futures::StreamExt;
|
||||||
use h2::client;
|
use h2::client;
|
||||||
use h2::RecvStream;
|
|
||||||
use http::{HeaderMap, Request};
|
use http::{HeaderMap, Request};
|
||||||
use std::future::Future;
|
|
||||||
use std::pin::Pin;
|
|
||||||
use std::task::{Context, Poll};
|
|
||||||
|
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
use tokio::net::TcpStream;
|
use tokio::net::TcpStream;
|
||||||
|
|
||||||
struct Process {
|
|
||||||
body: RecvStream,
|
|
||||||
trailers: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Future for Process {
|
|
||||||
type Output = Result<(), h2::Error>;
|
|
||||||
|
|
||||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
|
||||||
loop {
|
|
||||||
if self.trailers {
|
|
||||||
let trailers = ready!(self.body.poll_trailers(cx));
|
|
||||||
|
|
||||||
println!("GOT TRAILERS: {:?}", trailers);
|
|
||||||
|
|
||||||
return Poll::Ready(Ok(()));
|
|
||||||
} else {
|
|
||||||
match ready!(Pin::new(&mut self.body).poll_next(cx)) {
|
|
||||||
Some(Ok(chunk)) => {
|
|
||||||
println!("GOT CHUNK = {:?}", chunk);
|
|
||||||
}
|
|
||||||
Some(Err(e)) => return Poll::Ready(Err(e)),
|
|
||||||
None => {
|
|
||||||
self.trailers = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
pub async fn main() -> Result<(), Box<dyn Error>> {
|
pub async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
let _ = env_logger::try_init();
|
let _ = env_logger::try_init();
|
||||||
@@ -76,12 +42,15 @@ pub async fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
println!("GOT RESPONSE: {:?}", response);
|
println!("GOT RESPONSE: {:?}", response);
|
||||||
|
|
||||||
// Get the body
|
// Get the body
|
||||||
let (_, body) = response.into_parts();
|
let (_, mut body) = response.into_parts();
|
||||||
|
|
||||||
Process {
|
while let Some(chunk) = body.next().await {
|
||||||
body,
|
println!("GOT CHUNK = {:?}", chunk?);
|
||||||
trailers: false,
|
|
||||||
}
|
}
|
||||||
.await?;
|
|
||||||
|
if let Some(trailers) = poll_fn(|cx| body.poll_trailers(cx)).await {
|
||||||
|
println!("GOT TRAILERS: {:?}", trailers?);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -280,6 +280,14 @@ impl<T: AsyncRead + Unpin, B: Unpin> AsyncRead for FramedWrite<T, B> {
|
|||||||
) -> Poll<io::Result<usize>> {
|
) -> Poll<io::Result<usize>> {
|
||||||
Pin::new(&mut self.inner).poll_read(cx, buf)
|
Pin::new(&mut self.inner).poll_read(cx, buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn poll_read_buf<Buf: BufMut>(
|
||||||
|
mut self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
buf: &mut Buf,
|
||||||
|
) -> Poll<io::Result<usize>> {
|
||||||
|
Pin::new(&mut self.inner).poll_read_buf(cx, buf)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "unstable")]
|
#[cfg(feature = "unstable")]
|
||||||
|
|||||||
@@ -289,8 +289,8 @@ where
|
|||||||
// The order here matters:
|
// The order here matters:
|
||||||
// - poll_go_away may buffer a graceful shutdown GOAWAY frame
|
// - poll_go_away may buffer a graceful shutdown GOAWAY frame
|
||||||
// - If it has, we've also added a PING to be sent in poll_ready
|
// - If it has, we've also added a PING to be sent in poll_ready
|
||||||
match ready!(self.poll_go_away(cx)) {
|
match ready!(self.poll_go_away(cx)?) {
|
||||||
Some(Ok(reason)) => {
|
Some(reason) => {
|
||||||
if self.go_away.should_close_now() {
|
if self.go_away.should_close_now() {
|
||||||
if self.go_away.is_user_initiated() {
|
if self.go_away.is_user_initiated() {
|
||||||
// A user initiated abrupt shutdown shouldn't return
|
// A user initiated abrupt shutdown shouldn't return
|
||||||
@@ -307,33 +307,32 @@ where
|
|||||||
"graceful GOAWAY should be NO_ERROR"
|
"graceful GOAWAY should be NO_ERROR"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Some(Err(e)) => return Poll::Ready(Err(e.into())),
|
|
||||||
None => (),
|
None => (),
|
||||||
}
|
}
|
||||||
ready!(self.poll_ready(cx))?;
|
ready!(self.poll_ready(cx))?;
|
||||||
|
|
||||||
match ready!(Pin::new(&mut self.codec).poll_next(cx)) {
|
match ready!(Pin::new(&mut self.codec).poll_next(cx)?) {
|
||||||
Some(Ok(Headers(frame))) => {
|
Some(Headers(frame)) => {
|
||||||
log::trace!("recv HEADERS; frame={:?}", frame);
|
log::trace!("recv HEADERS; frame={:?}", frame);
|
||||||
self.streams.recv_headers(frame)?;
|
self.streams.recv_headers(frame)?;
|
||||||
}
|
}
|
||||||
Some(Ok(Data(frame))) => {
|
Some(Data(frame)) => {
|
||||||
log::trace!("recv DATA; frame={:?}", frame);
|
log::trace!("recv DATA; frame={:?}", frame);
|
||||||
self.streams.recv_data(frame)?;
|
self.streams.recv_data(frame)?;
|
||||||
}
|
}
|
||||||
Some(Ok(Reset(frame))) => {
|
Some(Reset(frame)) => {
|
||||||
log::trace!("recv RST_STREAM; frame={:?}", frame);
|
log::trace!("recv RST_STREAM; frame={:?}", frame);
|
||||||
self.streams.recv_reset(frame)?;
|
self.streams.recv_reset(frame)?;
|
||||||
}
|
}
|
||||||
Some(Ok(PushPromise(frame))) => {
|
Some(PushPromise(frame)) => {
|
||||||
log::trace!("recv PUSH_PROMISE; frame={:?}", frame);
|
log::trace!("recv PUSH_PROMISE; frame={:?}", frame);
|
||||||
self.streams.recv_push_promise(frame)?;
|
self.streams.recv_push_promise(frame)?;
|
||||||
}
|
}
|
||||||
Some(Ok(Settings(frame))) => {
|
Some(Settings(frame)) => {
|
||||||
log::trace!("recv SETTINGS; frame={:?}", frame);
|
log::trace!("recv SETTINGS; frame={:?}", frame);
|
||||||
self.settings.recv_settings(frame);
|
self.settings.recv_settings(frame);
|
||||||
}
|
}
|
||||||
Some(Ok(GoAway(frame))) => {
|
Some(GoAway(frame)) => {
|
||||||
log::trace!("recv GOAWAY; frame={:?}", frame);
|
log::trace!("recv GOAWAY; frame={:?}", frame);
|
||||||
// This should prevent starting new streams,
|
// This should prevent starting new streams,
|
||||||
// but should allow continuing to process current streams
|
// but should allow continuing to process current streams
|
||||||
@@ -342,7 +341,7 @@ where
|
|||||||
self.streams.recv_go_away(&frame)?;
|
self.streams.recv_go_away(&frame)?;
|
||||||
self.error = Some(frame.reason());
|
self.error = Some(frame.reason());
|
||||||
}
|
}
|
||||||
Some(Ok(Ping(frame))) => {
|
Some(Ping(frame)) => {
|
||||||
log::trace!("recv PING; frame={:?}", frame);
|
log::trace!("recv PING; frame={:?}", frame);
|
||||||
let status = self.ping_pong.recv_ping(frame);
|
let status = self.ping_pong.recv_ping(frame);
|
||||||
if status.is_shutdown() {
|
if status.is_shutdown() {
|
||||||
@@ -355,15 +354,14 @@ where
|
|||||||
self.go_away(last_processed_id, Reason::NO_ERROR);
|
self.go_away(last_processed_id, Reason::NO_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(Ok(WindowUpdate(frame))) => {
|
Some(WindowUpdate(frame)) => {
|
||||||
log::trace!("recv WINDOW_UPDATE; frame={:?}", frame);
|
log::trace!("recv WINDOW_UPDATE; frame={:?}", frame);
|
||||||
self.streams.recv_window_update(frame)?;
|
self.streams.recv_window_update(frame)?;
|
||||||
}
|
}
|
||||||
Some(Ok(Priority(frame))) => {
|
Some(Priority(frame)) => {
|
||||||
log::trace!("recv PRIORITY; frame={:?}", frame);
|
log::trace!("recv PRIORITY; frame={:?}", frame);
|
||||||
// TODO: handle
|
// TODO: handle
|
||||||
}
|
}
|
||||||
Some(Err(e)) => return Poll::Ready(Err(e)),
|
|
||||||
None => {
|
None => {
|
||||||
log::trace!("codec closed");
|
log::trace!("codec closed");
|
||||||
self.streams.recv_eof(false).ok().expect("mutex poisoned");
|
self.streams.recv_eof(false).ok().expect("mutex poisoned");
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ edition = "2018"
|
|||||||
h2 = { path = "../.." }
|
h2 = { path = "../.." }
|
||||||
|
|
||||||
env_logger = { version = "0.5.3", default-features = false }
|
env_logger = { version = "0.5.3", default-features = false }
|
||||||
futures-preview = "0.3.0-alpha.18"
|
futures-preview = "0.3.0-alpha.17"
|
||||||
honggfuzz = "0.5"
|
honggfuzz = "0.5"
|
||||||
http = "0.1.3"
|
http = "0.1.3"
|
||||||
tokio = { git = "https://github.com/tokio-rs/tokio" }
|
tokio = "0.2.0-alpha.1"
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ h2 = { path = "../..", features = ["unstable"] }
|
|||||||
|
|
||||||
bytes = "0.4.7"
|
bytes = "0.4.7"
|
||||||
env_logger = "0.5.9"
|
env_logger = "0.5.9"
|
||||||
futures-preview = "0.3.0-alpha.18"
|
futures-preview = "0.3.0-alpha.17"
|
||||||
http = "0.1.5"
|
http = "0.1.5"
|
||||||
string = "0.2"
|
string = "0.2"
|
||||||
tokio = { git = "https://github.com/tokio-rs/tokio" }
|
tokio = "0.2.0-alpha.1"
|
||||||
|
|||||||
@@ -7,16 +7,15 @@ pub mod assert;
|
|||||||
pub mod raw;
|
pub mod raw;
|
||||||
|
|
||||||
pub mod frames;
|
pub mod frames;
|
||||||
pub mod prelude;
|
|
||||||
pub mod mock;
|
pub mod mock;
|
||||||
pub mod mock_io;
|
pub mod mock_io;
|
||||||
pub mod notify;
|
pub mod prelude;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
|
||||||
mod client_ext;
|
mod client_ext;
|
||||||
mod future_ext;
|
mod future_ext;
|
||||||
|
|
||||||
pub use crate::client_ext::{SendRequestExt};
|
pub use crate::client_ext::SendRequestExt;
|
||||||
pub use crate::future_ext::TestFuture;
|
pub use crate::future_ext::TestFuture;
|
||||||
|
|
||||||
pub type WindowSize = usize;
|
pub type WindowSize = usize;
|
||||||
|
|||||||
@@ -1,53 +0,0 @@
|
|||||||
use std::sync::Arc;
|
|
||||||
use std::sync::atomic::AtomicBool;
|
|
||||||
use std::sync::atomic::Ordering::SeqCst;
|
|
||||||
|
|
||||||
pub struct MockNotify {
|
|
||||||
inner: Arc<Inner>,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Inner {
|
|
||||||
notified: AtomicBool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MockNotify {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
MockNotify {
|
|
||||||
inner: Arc::new(Inner {
|
|
||||||
notified: AtomicBool::new(false),
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with<F: FnOnce() -> R, R>(&self, _f: F) -> R {
|
|
||||||
unimplemented!();
|
|
||||||
// use futures::future::poll_fn;
|
|
||||||
|
|
||||||
// self.clear();
|
|
||||||
|
|
||||||
// let mut f = Some(f);
|
|
||||||
|
|
||||||
// let res = tokio::spawn(poll_fn(move |cx| {
|
|
||||||
// Poll::Ready(f.take().unwrap()())
|
|
||||||
// })).poll_future_notify(&self.inner, 0);
|
|
||||||
|
|
||||||
// match res {
|
|
||||||
// Poll::Ready(v) => v,
|
|
||||||
// _ => unreachable!(),
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn clear(&self) {
|
|
||||||
self.inner.notified.store(false, SeqCst);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_notified(&self) -> bool {
|
|
||||||
self.inner.notified.load(SeqCst)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// impl Notify for Inner {
|
|
||||||
// fn notify(&self, _: usize) {
|
|
||||||
// self.notified.store(true, SeqCst);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
@@ -12,9 +12,6 @@ pub use super::mock::{self, idle_ms};
|
|||||||
// Re-export frames helpers
|
// Re-export frames helpers
|
||||||
pub use super::frames;
|
pub use super::frames;
|
||||||
|
|
||||||
// Re-export mock notify
|
|
||||||
pub use super::notify::MockNotify;
|
|
||||||
|
|
||||||
// Re-export utility mod
|
// Re-export utility mod
|
||||||
pub use super::util;
|
pub use super::util;
|
||||||
|
|
||||||
|
|||||||
@@ -10,5 +10,5 @@ edition = "2018"
|
|||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
h2-support = { path = "../h2-support" }
|
h2-support = { path = "../h2-support" }
|
||||||
log = "0.4.1"
|
log = "0.4.1"
|
||||||
futures-preview = "0.3.0-alpha.18"
|
futures-preview = "0.3.0-alpha.17"
|
||||||
tokio = { git = "https://github.com/tokio-rs/tokio" }
|
tokio = "0.2.0-alpha.1"
|
||||||
|
|||||||
Reference in New Issue
Block a user