File tree Expand file tree Collapse file tree 6 files changed +70
-3
lines changed Expand file tree Collapse file tree 6 files changed +70
-3
lines changed Original file line number Diff line number Diff line change @@ -63,6 +63,9 @@ pub enum UserError {
6363
6464 /// Tries to update local SETTINGS while ACK has not been received.
6565 SendSettingsWhilePending ,
66+
67+ /// Tries to send push promise to peer who has disabled server push
68+ PeerDisabledServerPush ,
6669}
6770
6871// ===== impl RecvError =====
@@ -136,6 +139,7 @@ impl fmt::Display for UserError {
136139 PollResetAfterSendResponse => "poll_reset after send_response is illegal" ,
137140 SendPingWhilePending => "send_ping before received previous pong" ,
138141 SendSettingsWhilePending => "sending SETTINGS before received previous ACK" ,
142+ PeerDisabledServerPush => "sending PUSH_PROMISE to peer who disabled server push" ,
139143 } )
140144 }
141145}
Original file line number Diff line number Diff line change @@ -99,8 +99,8 @@ impl Settings {
9999 self . max_header_list_size = size;
100100 }
101101
102- pub fn is_push_enabled ( & self ) -> bool {
103- self . enable_push . unwrap_or ( 1 ) != 0
102+ pub fn is_push_enabled ( & self ) -> Option < bool > {
103+ self . enable_push . map ( |val| val != 0 )
104104 }
105105
106106 pub fn set_enable_push ( & mut self , enable : bool ) {
Original file line number Diff line number Diff line change 8686 . unwrap_or ( DEFAULT_INITIAL_WINDOW_SIZE ) ,
8787 initial_max_send_streams : config. initial_max_send_streams ,
8888 local_next_stream_id : config. next_stream_id ,
89- local_push_enabled : config. settings . is_push_enabled ( ) ,
89+ local_push_enabled : config. settings . is_push_enabled ( ) . unwrap_or ( true ) ,
9090 local_reset_duration : config. reset_stream_duration ,
9191 local_reset_max : config. reset_stream_max ,
9292 remote_init_window_sz : DEFAULT_INITIAL_WINDOW_SIZE ,
Original file line number Diff line number Diff line change @@ -32,6 +32,8 @@ pub(super) struct Send {
3232
3333 /// Prioritization layer
3434 prioritize : Prioritize ,
35+
36+ is_push_enabled : bool ,
3537}
3638
3739/// A value to detect which public API has called `poll_reset`.
@@ -49,6 +51,7 @@ impl Send {
4951 max_stream_id : StreamId :: MAX ,
5052 next_stream_id : Ok ( config. local_next_stream_id ) ,
5153 prioritize : Prioritize :: new ( config) ,
54+ is_push_enabled : true ,
5255 }
5356 }
5457
@@ -95,6 +98,10 @@ impl Send {
9598 stream : & mut store:: Ptr ,
9699 task : & mut Option < Waker > ,
97100 ) -> Result < ( ) , UserError > {
101+ if !self . is_push_enabled {
102+ return Err ( UserError :: PeerDisabledServerPush ) ;
103+ }
104+
98105 tracing:: trace!(
99106 "send_push_promise; frame={:?}; init_window={:?}" ,
100107 frame,
@@ -496,6 +503,10 @@ impl Send {
496503 }
497504 }
498505
506+ if let Some ( val) = settings. is_push_enabled ( ) {
507+ self . is_push_enabled = val
508+ }
509+
499510 Ok ( ( ) )
500511 }
501512
Original file line number Diff line number Diff line change @@ -339,6 +339,11 @@ impl Mock<frame::Settings> {
339339 self . 0 . set_max_header_list_size ( Some ( val) ) ;
340340 self
341341 }
342+
343+ pub fn disable_push ( mut self ) -> Self {
344+ self . 0 . set_enable_push ( false ) ;
345+ self
346+ }
342347}
343348
344349impl From < Mock < frame:: Settings > > for frame:: Settings {
Original file line number Diff line number Diff line change @@ -220,6 +220,53 @@ async fn push_request() {
220220 join ( client, srv) . await ;
221221}
222222
223+ #[ tokio:: test]
224+ async fn push_request_disabled ( ) {
225+ h2_support:: trace_init!( ) ;
226+ let ( io, mut client) = mock:: new ( ) ;
227+
228+ let client = async move {
229+ client
230+ . assert_server_handshake_with_settings ( frames:: settings ( ) . disable_push ( ) )
231+ . await ;
232+ client
233+ . send_frame (
234+ frames:: headers ( 1 )
235+ . request ( "GET" , "https://example.com/" )
236+ . eos ( ) ,
237+ )
238+ . await ;
239+ client
240+ . recv_frame ( frames:: headers ( 1 ) . response ( 200 ) . eos ( ) )
241+ . await ;
242+ } ;
243+
244+ let srv = async move {
245+ let mut srv = server:: handshake ( io) . await . expect ( "handshake" ) ;
246+ let ( req, mut stream) = srv. next ( ) . await . unwrap ( ) . unwrap ( ) ;
247+
248+ assert_eq ! ( req. method( ) , & http:: Method :: GET ) ;
249+
250+ // attempt to push - expect failure
251+ let req = http:: Request :: builder ( )
252+ . method ( "GET" )
253+ . uri ( "https://http2.akamai.com/style.css" )
254+ . body ( ( ) )
255+ . unwrap ( ) ;
256+ stream
257+ . push_request ( req)
258+ . expect_err ( "push_request should error" ) ;
259+
260+ // send normal response
261+ let rsp = http:: Response :: builder ( ) . status ( 200 ) . body ( ( ) ) . unwrap ( ) ;
262+ stream. send_response ( rsp, true ) . unwrap ( ) ;
263+
264+ assert ! ( srv. next( ) . await . is_none( ) ) ;
265+ } ;
266+
267+ join ( client, srv) . await ;
268+ }
269+
223270#[ tokio:: test]
224271async fn push_request_against_concurrency ( ) {
225272 h2_support:: trace_init!( ) ;
You can’t perform that action at this time.
0 commit comments