Bunch of work
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
use frame::{util, Head, Error, StreamId};
|
||||
use bytes::Bytes;
|
||||
use frame::{util, Head, Error, StreamId, Kind};
|
||||
use bytes::{BufMut, Bytes};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Data {
|
||||
stream_id: StreamId,
|
||||
data: Bytes,
|
||||
@@ -33,6 +34,23 @@ impl Data {
|
||||
pad_len: pad_len,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.data.len()
|
||||
}
|
||||
|
||||
pub fn encode<T: BufMut>(&self, dst: &mut T) {
|
||||
self.head().encode(self.len(), dst);
|
||||
dst.put(&self.data);
|
||||
}
|
||||
|
||||
pub fn head(&self) -> Head {
|
||||
Head::new(Kind::Data, self.flags.into(), self.stream_id)
|
||||
}
|
||||
|
||||
pub fn into_payload(self) -> Bytes {
|
||||
self.data
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -57,3 +75,9 @@ impl DataFlag {
|
||||
self.0 & PADDED == PADDED
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DataFlag> for u8 {
|
||||
fn from(src: DataFlag) -> u8 {
|
||||
src.0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ impl Head {
|
||||
super::HEADER_LEN
|
||||
}
|
||||
|
||||
pub fn encode<T: BufMut>(&self, payload_len: usize, dst: &mut T) -> Result<(), Error> {
|
||||
pub fn encode<T: BufMut>(&self, payload_len: usize, dst: &mut T) {
|
||||
debug_assert_eq!(self.encode_len(), dst.remaining_mut());
|
||||
debug_assert!(self.stream_id & STREAM_ID_MASK == 0);
|
||||
|
||||
@@ -73,7 +73,6 @@ impl Head {
|
||||
dst.put_u8(self.kind as u8);
|
||||
dst.put_u8(self.flag);
|
||||
dst.put_u32::<BigEndian>(self.stream_id);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,43 +1,79 @@
|
||||
use super::StreamId;
|
||||
use util::byte_str::ByteStr;
|
||||
|
||||
use http::{Method, StatusCode};
|
||||
use http::header::{self, HeaderMap, HeaderValue};
|
||||
|
||||
/// Header frame
|
||||
///
|
||||
/// This could be either a request or a response.
|
||||
#[derive(Debug)]
|
||||
pub struct Headers {
|
||||
/// The ID of the stream with which this frame is associated.
|
||||
stream_id: StreamId,
|
||||
|
||||
/// The stream dependency information, if any.
|
||||
stream_dep: Option<StreamDependency>,
|
||||
|
||||
/// The decoded headers
|
||||
headers: HeaderMap,
|
||||
headers: HeaderMap<HeaderValue>,
|
||||
|
||||
/// Pseudo headers, these are broken out as they must be sent as part of the
|
||||
/// headers frame.
|
||||
pseudo: Pseudo,
|
||||
flags: HeaderFlag,
|
||||
|
||||
/// The associated flags
|
||||
flags: HeadersFlag,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Default)]
|
||||
pub struct HeadersFlag(u8);
|
||||
|
||||
pub struct PushPromise;
|
||||
#[derive(Debug)]
|
||||
pub struct PushPromise {
|
||||
/// The ID of the stream with which this frame is associated.
|
||||
stream_id: StreamId,
|
||||
|
||||
/// The ID of the stream being reserved by this PushPromise.
|
||||
promised_id: StreamId,
|
||||
|
||||
/// The associated flags
|
||||
flags: HeadersFlag,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct StreamDependency {
|
||||
/// The ID of the stream dependency target
|
||||
stream_id: StreamId,
|
||||
|
||||
/// The weight for the stream. The value exposed (and set) here is always in
|
||||
/// the range [0, 255], instead of [1, 256] (as defined in section 5.3.2.)
|
||||
/// so that the value fits into a `u8`.
|
||||
weight: u8,
|
||||
|
||||
/// True if the stream dependency is exclusive.
|
||||
is_exclusive: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Pseudo {
|
||||
// Request
|
||||
method: Option<()>,
|
||||
scheme: Option<()>,
|
||||
authority: Option<()>,
|
||||
path: Option<()>,
|
||||
method: Option<Method>,
|
||||
scheme: Option<ByteStr>,
|
||||
authority: Option<ByteStr>,
|
||||
path: Option<ByteStr>,
|
||||
|
||||
// Response
|
||||
status: Option<()>,
|
||||
status: Option<StatusCode>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Iter {
|
||||
/// Pseudo headers
|
||||
pseudo: Option<Pseudo>,
|
||||
|
||||
/// Headers
|
||||
headers: header::IntoIter<HeaderValue>,
|
||||
}
|
||||
|
||||
const END_STREAM: u8 = 0x1;
|
||||
@@ -52,7 +88,7 @@ const ALL: u8 = END_STREAM
|
||||
// ===== impl HeadersFlag =====
|
||||
|
||||
impl HeadersFlag {
|
||||
pub empty() -> HeadersFlag {
|
||||
pub fn empty() -> HeadersFlag {
|
||||
HeadersFlag(0)
|
||||
}
|
||||
|
||||
|
||||
@@ -26,31 +26,29 @@ macro_rules! unpack_octets_4 {
|
||||
|
||||
mod data;
|
||||
mod head;
|
||||
mod headers;
|
||||
mod settings;
|
||||
mod unknown;
|
||||
mod util;
|
||||
|
||||
pub use self::data::Data;
|
||||
pub use self::head::{Head, Kind, StreamId};
|
||||
pub use self::headers::{Headers, PushPromise};
|
||||
pub use self::settings::{Settings, SettingSet};
|
||||
pub use self::unknown::Unknown;
|
||||
|
||||
// Re-export some constants
|
||||
pub use self::settings::{
|
||||
DEFAULT_SETTINGS_HEADER_TABLE_SIZE,
|
||||
DEFAULT_MAX_FRAME_SIZE,
|
||||
};
|
||||
|
||||
pub const HEADER_LEN: usize = 9;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[derive(Debug /*, Clone, PartialEq */)]
|
||||
pub enum Frame {
|
||||
/*
|
||||
Data(DataFrame<'a>),
|
||||
HeadersFrame(HeadersFrame<'a>),
|
||||
RstStreamFrame(RstStreamFrame),
|
||||
SettingsFrame(SettingsFrame),
|
||||
PingFrame(PingFrame),
|
||||
GoawayFrame(GoawayFrame<'a>),
|
||||
WindowUpdateFrame(WindowUpdateFrame),
|
||||
UnknownFrame(RawFrame<'a>),
|
||||
*/
|
||||
Data(Data),
|
||||
Headers(Headers),
|
||||
PushPromise(PushPromise),
|
||||
Settings(Settings),
|
||||
Unknown(Unknown),
|
||||
}
|
||||
|
||||
/// Errors that can occur during parsing an HTTP/2 frame.
|
||||
@@ -99,40 +97,6 @@ pub enum Error {
|
||||
// ===== impl Frame ======
|
||||
|
||||
impl Frame {
|
||||
pub fn load(mut frame: Bytes) -> Result<Frame, Error> {
|
||||
let head = Head::parse(&frame);
|
||||
|
||||
// Extract the payload from the frame
|
||||
let _ = frame.drain_to(HEADER_LEN);
|
||||
|
||||
match head.kind() {
|
||||
Kind::Unknown => {
|
||||
let unknown = Unknown::new(head, frame);
|
||||
Ok(Frame::Unknown(unknown))
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn encode_len(&self) -> usize {
|
||||
use self::Frame::*;
|
||||
|
||||
match *self {
|
||||
Settings(ref frame) => frame.encode_len(),
|
||||
Unknown(ref frame) => frame.encode_len(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn encode(&self, dst: &mut BytesMut) -> Result<(), Error> {
|
||||
use self::Frame::*;
|
||||
|
||||
debug_assert!(dst.remaining_mut() >= self.encode_len());
|
||||
|
||||
match *self {
|
||||
Settings(ref frame) => frame.encode(dst),
|
||||
Unknown(ref frame) => frame.encode(dst),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ===== impl Error =====
|
||||
|
||||
@@ -37,6 +37,9 @@ pub struct SettingsFlag(u8);
|
||||
const ACK: u8 = 0x1;
|
||||
const ALL: u8 = ACK;
|
||||
|
||||
pub const DEFAULT_SETTINGS_HEADER_TABLE_SIZE: usize = 4_096;
|
||||
pub const DEFAULT_MAX_FRAME_SIZE: usize = 16_384;
|
||||
|
||||
// ===== impl Settings =====
|
||||
|
||||
impl Settings {
|
||||
@@ -111,27 +114,21 @@ impl Settings {
|
||||
Ok(settings)
|
||||
}
|
||||
|
||||
pub fn encode_len(&self) -> usize {
|
||||
super::HEADER_LEN + self.payload_len()
|
||||
}
|
||||
|
||||
fn payload_len(&self) -> usize {
|
||||
let mut len = 0;
|
||||
self.for_each(|_| len += 6);
|
||||
len
|
||||
}
|
||||
|
||||
pub fn encode(&self, dst: &mut BytesMut) -> Result<(), Error> {
|
||||
pub fn encode(&self, dst: &mut BytesMut) {
|
||||
// Create & encode an appropriate frame head
|
||||
let head = Head::new(Kind::Settings, self.flag.into(), 0);
|
||||
let payload_len = self.payload_len();
|
||||
|
||||
try!(head.encode(payload_len, dst));
|
||||
head.encode(payload_len, dst);
|
||||
|
||||
// Encode the settings
|
||||
self.for_each(|setting| setting.encode(dst));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn for_each<F: FnMut(Setting)>(&self, mut f: F) {
|
||||
|
||||
Reference in New Issue
Block a user