Implement the extended CONNECT protocol from RFC 8441 (#565)
This commit is contained in:
		| @@ -47,6 +47,16 @@ macro_rules! assert_settings { | ||||
|     }}; | ||||
| } | ||||
|  | ||||
| #[macro_export] | ||||
| macro_rules! assert_go_away { | ||||
|     ($frame:expr) => {{ | ||||
|         match $frame { | ||||
|             h2::frame::Frame::GoAway(v) => v, | ||||
|             f => panic!("expected GO_AWAY; actual={:?}", f), | ||||
|         } | ||||
|     }}; | ||||
| } | ||||
|  | ||||
| #[macro_export] | ||||
| macro_rules! poll_err { | ||||
|     ($transport:expr) => {{ | ||||
| @@ -80,6 +90,7 @@ macro_rules! assert_default_settings { | ||||
|  | ||||
| use h2::frame::Frame; | ||||
|  | ||||
| #[track_caller] | ||||
| pub fn assert_frame_eq<T: Into<Frame>, U: Into<Frame>>(t: T, u: U) { | ||||
|     let actual: Frame = t.into(); | ||||
|     let expected: Frame = u.into(); | ||||
|   | ||||
| @@ -4,7 +4,10 @@ use std::fmt; | ||||
| use bytes::Bytes; | ||||
| use http::{self, HeaderMap, StatusCode}; | ||||
|  | ||||
| use h2::frame::{self, Frame, StreamId}; | ||||
| use h2::{ | ||||
|     ext::Protocol, | ||||
|     frame::{self, Frame, StreamId}, | ||||
| }; | ||||
|  | ||||
| pub const SETTINGS: &'static [u8] = &[0, 0, 0, 4, 0, 0, 0, 0, 0]; | ||||
| pub const SETTINGS_ACK: &'static [u8] = &[0, 0, 0, 4, 1, 0, 0, 0, 0]; | ||||
| @@ -109,7 +112,9 @@ impl Mock<frame::Headers> { | ||||
|         let method = method.try_into().unwrap(); | ||||
|         let uri = uri.try_into().unwrap(); | ||||
|         let (id, _, fields) = self.into_parts(); | ||||
|         let frame = frame::Headers::new(id, frame::Pseudo::request(method, uri), fields); | ||||
|         let extensions = Default::default(); | ||||
|         let pseudo = frame::Pseudo::request(method, uri, extensions); | ||||
|         let frame = frame::Headers::new(id, pseudo, fields); | ||||
|         Mock(frame) | ||||
|     } | ||||
|  | ||||
| @@ -179,6 +184,15 @@ impl Mock<frame::Headers> { | ||||
|         Mock(frame::Headers::new(id, pseudo, fields)) | ||||
|     } | ||||
|  | ||||
|     pub fn protocol(self, value: &str) -> Self { | ||||
|         let (id, mut pseudo, fields) = self.into_parts(); | ||||
|         let value = Protocol::from(value); | ||||
|  | ||||
|         pseudo.set_protocol(value); | ||||
|  | ||||
|         Mock(frame::Headers::new(id, pseudo, fields)) | ||||
|     } | ||||
|  | ||||
|     pub fn eos(mut self) -> Self { | ||||
|         self.0.set_end_stream(); | ||||
|         self | ||||
| @@ -230,8 +244,9 @@ impl Mock<frame::PushPromise> { | ||||
|         let method = method.try_into().unwrap(); | ||||
|         let uri = uri.try_into().unwrap(); | ||||
|         let (id, promised, _, fields) = self.into_parts(); | ||||
|         let frame = | ||||
|             frame::PushPromise::new(id, promised, frame::Pseudo::request(method, uri), fields); | ||||
|         let extensions = Default::default(); | ||||
|         let pseudo = frame::Pseudo::request(method, uri, extensions); | ||||
|         let frame = frame::PushPromise::new(id, promised, pseudo, fields); | ||||
|         Mock(frame) | ||||
|     } | ||||
|  | ||||
| @@ -352,6 +367,11 @@ impl Mock<frame::Settings> { | ||||
|         self.0.set_enable_push(false); | ||||
|         self | ||||
|     } | ||||
|  | ||||
|     pub fn enable_connect_protocol(mut self, val: u32) -> Self { | ||||
|         self.0.set_enable_connect_protocol(Some(val)); | ||||
|         self | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl From<Mock<frame::Settings>> for frame::Settings { | ||||
|   | ||||
| @@ -221,22 +221,15 @@ impl Handle { | ||||
|         let settings = settings.into(); | ||||
|         self.send(settings.into()).await.unwrap(); | ||||
|  | ||||
|         let frame = self.next().await; | ||||
|         let settings = match frame { | ||||
|             Some(frame) => match frame.unwrap() { | ||||
|                 Frame::Settings(settings) => { | ||||
|                     // Send the ACK | ||||
|                     let ack = frame::Settings::ack(); | ||||
|         let frame = self.next().await.expect("unexpected EOF").unwrap(); | ||||
|         let settings = assert_settings!(frame); | ||||
|  | ||||
|                     // TODO: Don't unwrap? | ||||
|                     self.send(ack.into()).await.unwrap(); | ||||
|         // Send the ACK | ||||
|         let ack = frame::Settings::ack(); | ||||
|  | ||||
|         // TODO: Don't unwrap? | ||||
|         self.send(ack.into()).await.unwrap(); | ||||
|  | ||||
|                     settings | ||||
|                 } | ||||
|                 frame => panic!("unexpected frame; frame={:?}", frame), | ||||
|             }, | ||||
|             None => panic!("unexpected EOF"), | ||||
|         }; | ||||
|         let frame = self.next().await; | ||||
|         let f = assert_settings!(frame.unwrap().unwrap()); | ||||
|  | ||||
|   | ||||
| @@ -2,6 +2,7 @@ | ||||
| pub use h2; | ||||
|  | ||||
| pub use h2::client; | ||||
| pub use h2::ext::Protocol; | ||||
| pub use h2::frame::StreamId; | ||||
| pub use h2::server; | ||||
| pub use h2::*; | ||||
| @@ -20,8 +21,8 @@ pub use super::{Codec, SendFrame}; | ||||
|  | ||||
| // Re-export macros | ||||
| pub use super::{ | ||||
|     assert_closed, assert_data, assert_default_settings, assert_headers, assert_ping, poll_err, | ||||
|     poll_frame, raw_codec, | ||||
|     assert_closed, assert_data, assert_default_settings, assert_go_away, assert_headers, | ||||
|     assert_ping, assert_settings, poll_err, poll_frame, raw_codec, | ||||
| }; | ||||
|  | ||||
| pub use super::assert::assert_frame_eq; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user