diff --git a/src/client.rs b/src/client.rs index b819e94..c1c733e 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1,3 +1,4 @@ +//! HTTP2 client side. use {SendStream, RecvStream, ReleaseCapacity}; use codec::{Codec, RecvError}; use frame::{Headers, Pseudo, Reason, Settings, StreamId}; @@ -14,6 +15,7 @@ use std::io; use std::marker::PhantomData; /// In progress H2 connection binding +#[must_use = "futures do nothing unless polled"] pub struct Handshake { builder: Builder, inner: MapErr, fn(io::Error) -> ::Error>, @@ -26,11 +28,17 @@ pub struct Client { pending: Option, } +/// A future to drive the H2 protocol on a connection. +/// +/// This must be placed in an executor to ensure proper connection management. +#[must_use = "futures do nothing unless polled"] pub struct Connection { inner: proto::Connection, } +/// A future of an HTTP response. #[derive(Debug)] +#[must_use = "futures do nothing unless polled"] pub struct ResponseFuture { inner: proto::OpaqueStreamRef, } diff --git a/src/frame/reason.rs b/src/frame/reason.rs index 6271026..4584bb0 100644 --- a/src/frame/reason.rs +++ b/src/frame/reason.rs @@ -1,25 +1,56 @@ use std::fmt; +/// HTTP2 Error codes +/// +/// See [Error Codes in the spec][spec]. +/// +/// [spec}: http://httpwg.org/specs/rfc7540.html#ErrorCodes #[derive(PartialEq, Eq, Clone, Copy)] pub struct Reason(u32); impl Reason { + /// The associated condition is not a result of an error. + /// + /// For example, a GOAWAY might include this code to indicate graceful + /// shutdown of a connection. pub const NO_ERROR: Reason = Reason(0); + /// The endpoint detected an unspecific protocol error. + /// + /// This error is for use when a more specific error code is not available. pub const PROTOCOL_ERROR: Reason = Reason(1); + /// The endpoint encountered an unexpected internal error. pub const INTERNAL_ERROR: Reason = Reason(2); + /// The endpoint detected that its peer violated the flow-control protocol. pub const FLOW_CONTROL_ERROR: Reason = Reason(3); + /// The endpoint sent a SETTINGS frame but did not receive a response in + /// a timely manner. pub const SETTINGS_TIMEOUT: Reason = Reason(4); + /// The endpoint received a frame after a stream was half-closed. pub const STREAM_CLOSED: Reason = Reason(5); + /// The endpoint received a frame with an invalid size. pub const FRAME_SIZE_ERROR: Reason = Reason(6); + /// The endpoint refused the stream prior to performing any application + /// processing. pub const REFUSED_STREAM: Reason = Reason(7); + /// Used by the endpoint to indicate that the stream is no longer needed. pub const CANCEL: Reason = Reason(8); + /// The endpoint is unable to maintain the header compression context for + /// the connection. pub const COMPRESSION_ERROR: Reason = Reason(9); + /// The connection established in response to a CONNECT request was reset + /// or abnormally closed. pub const CONNECT_ERROR: Reason = Reason(10); + /// The endpoint detected that its peer is exhibiting a behavior that might + /// be generating excessive load. pub const ENHANCE_YOUR_CALM: Reason = Reason(11); + /// The underlying transport has properties that do not meet minimum + /// security requirements. pub const INADEQUATE_SECURITY: Reason = Reason(12); - pub const HTTP11_REQUIRED: Reason = Reason(13); + /// The endpoint requires that HTTP/1.1 be used instead of HTTP/2. + pub const HTTP_1_1_REQUIRED: Reason = Reason(13); + /// Get a string description of the error code. pub fn description(&self) -> &str { match self.0 { 0 => "not a result of an error", diff --git a/src/lib.rs b/src/lib.rs index 3629b5b..941a810 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,6 @@ -#![deny(warnings, missing_debug_implementations)] +#![deny(warnings, missing_debug_implementations, missing_docs)] + +//! HTTP2 #[macro_use] extern crate futures; @@ -24,6 +26,7 @@ extern crate string; extern crate ordermap; mod error; +#[cfg_attr(feature = "unstable", allow(missing_docs))] mod codec; mod hpack; mod proto; @@ -32,6 +35,7 @@ mod proto; mod frame; #[cfg(feature = "unstable")] +#[allow(missing_docs)] pub mod frame; pub mod client; diff --git a/src/server.rs b/src/server.rs index bab5bcb..dab7d71 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1,3 +1,5 @@ +//! HTTP2 server side. + use {SendStream, RecvStream, ReleaseCapacity}; use codec::{Codec, RecvError}; use frame::{self, Reason, Settings, StreamId}; @@ -10,6 +12,7 @@ use tokio_io::{AsyncRead, AsyncWrite}; use std::{convert, fmt, mem}; /// In progress H2 connection binding +#[must_use = "futures do nothing unless polled"] pub struct Handshake { /// SETTINGS frame that will be sent once the connection is established. settings: Settings, @@ -18,6 +21,7 @@ pub struct Handshake { } /// Marker type indicating a client peer +#[must_use = "streams do nothing unless polled"] pub struct Server { connection: Connection, } @@ -31,7 +35,7 @@ pub struct Builder { /// Respond to a request /// /// -/// Instances of `Respond` are used to send a respond or reserve push promises. +/// Instances of `Respond` are used to send a response or reserve push promises. #[derive(Debug)] pub struct Respond { inner: proto::StreamRef, diff --git a/src/share.rs b/src/share.rs index d60f4bc..b86e254 100644 --- a/src/share.rs +++ b/src/share.rs @@ -1,3 +1,4 @@ +use codec::UserError; use frame::Reason; use proto::{self, WindowSize}; @@ -7,15 +8,19 @@ use http::{HeaderMap}; use std::fmt; +/// Send frames to a remote. #[derive(Debug)] pub struct SendStream { inner: proto::StreamRef, } +/// Receive frames from a remote. +#[must_use = "streams do nothing unless polled"] pub struct RecvStream { inner: ReleaseCapacity, } +/// A handle to release window capacity to a remote stream. #[derive(Debug)] pub struct ReleaseCapacity { inner: proto::OpaqueStreamRef, @@ -85,6 +90,9 @@ impl RecvStream { self.inner.inner.is_end_stream() } + /// Get a mutable reference to this streams `ReleaseCapacity`. + /// + /// It can be used immediately, or cloned to be used later. pub fn release_capacity(&mut self) -> &mut ReleaseCapacity { &mut self.inner } @@ -121,7 +129,11 @@ impl ReleaseCapacity { ReleaseCapacity { inner } } + /// Release window capacity back to remote stream. pub fn release_capacity(&mut self, sz: usize) -> Result<(), ::Error> { + if sz > proto::MAX_WINDOW_SIZE as usize { + return Err(UserError::ReleaseCapacityTooBig.into()); + } self.inner .release_capacity(sz as proto::WindowSize) .map_err(Into::into)