From ac2959e956d29adc69eee7e44410242dbe521734 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Fri, 23 Jun 2017 15:51:00 -0700 Subject: [PATCH] Get settings handshake working + other junk --- src/client.rs | 2 +- src/frame/settings.rs | 42 +++++++++++++++++++++++++----------------- src/lib.rs | 1 + src/proto/settings.rs | 18 +++++++++++++++++- 4 files changed, 44 insertions(+), 19 deletions(-) diff --git a/src/client.rs b/src/client.rs index 5531e87..d0f8d85 100644 --- a/src/client.rs +++ b/src/client.rs @@ -83,7 +83,7 @@ impl Peer for Client { // TODO: Factor in trailers if !body { - frame.set_end_stream(); + // frame.set_end_stream(); } else { unimplemented!(); } diff --git a/src/frame/settings.rs b/src/frame/settings.rs index 99bdeb7..c6507f3 100644 --- a/src/frame/settings.rs +++ b/src/frame/settings.rs @@ -3,7 +3,7 @@ use bytes::{Bytes, BytesMut, BufMut, BigEndian}; #[derive(Debug, Clone, Default, Eq, PartialEq)] pub struct Settings { - flag: SettingsFlag, + flags: SettingsFlags, // Fields values: SettingSet, } @@ -32,7 +32,7 @@ pub enum Setting { } #[derive(Debug, Copy, Clone, Eq, PartialEq, Default)] -pub struct SettingsFlag(u8); +pub struct SettingsFlags(u8); const ACK: u8 = 0x1; const ALL: u8 = ACK; @@ -45,18 +45,26 @@ pub const DEFAULT_MAX_FRAME_SIZE: usize = 16_384; impl Settings { pub fn ack() -> Settings { Settings { - flag: SettingsFlag::ack(), + flags: SettingsFlags::ack(), .. Settings::default() } } pub fn new(values: SettingSet) -> Settings { Settings { - flag: SettingsFlag::empty(), + flags: SettingsFlags::empty(), values: values, } } + pub fn is_ack(&self) -> bool { + self.flags.is_ack() + } + + pub fn into_set(self) -> SettingSet { + self.values + } + pub fn load(head: Head, payload: &[u8]) -> Result { use self::Setting::*; @@ -67,7 +75,7 @@ impl Settings { } // Load the flag - let flag = SettingsFlag::load(head.flag()); + let flag = SettingsFlags::load(head.flag()); if flag.is_ack() { // Ensure that the payload is empty @@ -86,7 +94,7 @@ impl Settings { } let mut settings = Settings::default(); - debug_assert!(!settings.flag.is_ack()); + debug_assert!(!settings.flags.is_ack()); for raw in payload.chunks(6) { match Setting::load(raw) { @@ -123,7 +131,7 @@ impl Settings { pub fn encode(&self, dst: &mut BytesMut) { // Create & encode an appropriate frame head - let head = Head::new(Kind::Settings, self.flag.into(), 0); + let head = Head::new(Kind::Settings, self.flags.into(), 0); let payload_len = self.payload_len(); head.encode(payload_len, dst); @@ -221,19 +229,19 @@ impl Setting { } } -// ===== impl SettingsFlag ===== +// ===== impl SettingsFlags ===== -impl SettingsFlag { - pub fn empty() -> SettingsFlag { - SettingsFlag(0) +impl SettingsFlags { + pub fn empty() -> SettingsFlags { + SettingsFlags(0) } - pub fn load(bits: u8) -> SettingsFlag { - SettingsFlag(bits & ALL) + pub fn load(bits: u8) -> SettingsFlags { + SettingsFlags(bits & ALL) } - pub fn ack() -> SettingsFlag { - SettingsFlag(ACK) + pub fn ack() -> SettingsFlags { + SettingsFlags(ACK) } pub fn is_ack(&self) -> bool { @@ -241,8 +249,8 @@ impl SettingsFlag { } } -impl From for u8 { - fn from(src: SettingsFlag) -> u8 { +impl From for u8 { + fn from(src: SettingsFlags) -> u8 { src.0 } } diff --git a/src/lib.rs b/src/lib.rs index 086da68..5f29153 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -36,6 +36,7 @@ pub use frame::{StreamId}; pub use proto::Connection; /// An H2 connection frame +#[derive(Debug)] pub enum Frame { Message { id: StreamId, diff --git a/src/proto/settings.rs b/src/proto/settings.rs index fb1e8f3..4ef687c 100644 --- a/src/proto/settings.rs +++ b/src/proto/settings.rs @@ -78,7 +78,23 @@ impl Stream for Settings type Error = ConnectionError; fn poll(&mut self) -> Poll, ConnectionError> { - self.inner.poll() + loop { + match try_ready!(self.inner.poll()) { + Some(Frame::Settings(v)) => { + if v.is_ack() { + debug!("received remote settings ack"); + // TODO: Handle acks + } else { + // Received new settings, queue an ACK + self.remaining_acks += 1; + + // Save off the settings + self.remote = v.into_set(); + } + } + v => return Ok(Async::Ready(v)), + } + } } }