1
1
use std:: { cell:: Cell , cell:: RefCell , fmt, mem, rc:: Rc } ;
2
- use std:: { collections:: VecDeque , time:: Instant } ;
2
+ use std:: { collections:: VecDeque , time:: Duration , time :: Instant } ;
3
3
4
4
use ntex_bytes:: { ByteString , Bytes } ;
5
5
use ntex_http:: { HeaderMap , Method } ;
6
6
use ntex_io:: IoRef ;
7
7
use ntex_util:: time:: { self , now, sleep} ;
8
- use ntex_util:: { channel:: pool, future:: Either , spawn, HashMap , HashSet } ;
8
+ use ntex_util:: { channel:: pool, future:: Either , spawn, HashMap } ;
9
9
10
10
use crate :: config:: { Config , ConfigInner } ;
11
11
use crate :: error:: { ConnectionError , OperationError , StreamError , StreamErrorInner } ;
@@ -22,7 +22,6 @@ bitflags::bitflags! {
22
22
#[ derive( Copy , Clone , Debug , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
23
23
pub ( crate ) struct ConnectionFlags : u8 {
24
24
const SETTINGS_PROCESSED = 0b0000_0001 ;
25
- const DELAY_DROP_TASK_STARTED = 0b0000_0010 ;
26
25
const DISCONNECT_WHEN_READY = 0b0000_1000 ;
27
26
const SECURE = 0b0001_0000 ;
28
27
const STREAM_REFUSED = 0b0010_0000 ;
@@ -55,8 +54,7 @@ struct ConnectionState {
55
54
// Max frame size
56
55
remote_frame_size : Cell < u32 > ,
57
56
// Locally reset streams
58
- local_reset_queue : RefCell < VecDeque < ( StreamId , Instant ) > > ,
59
- local_reset_ids : RefCell < HashSet < StreamId > > ,
57
+ local_pending_reset : Pending ,
60
58
// protocol level error
61
59
error : Cell < Option < OperationError > > ,
62
60
// connection state flags
@@ -112,8 +110,7 @@ impl Connection {
112
110
next_stream_id : Cell :: new ( StreamId :: new ( 1 ) ) ,
113
111
local_config : config,
114
112
local_max_concurrent_streams : Cell :: new ( None ) ,
115
- local_reset_ids : RefCell :: new ( HashSet :: default ( ) ) ,
116
- local_reset_queue : RefCell :: new ( VecDeque :: new ( ) ) ,
113
+ local_pending_reset : Default :: default ( ) ,
117
114
remote_window_sz : Cell :: new ( frame:: DEFAULT_INITIAL_WINDOW_SIZE ) ,
118
115
error : Cell :: new ( None ) ,
119
116
flags : Cell :: new ( if secure {
@@ -410,20 +407,8 @@ impl Connection {
410
407
return ;
411
408
}
412
409
413
- let mut ids = self . 0 . local_reset_ids . borrow_mut ( ) ;
414
- let mut queue = self . 0 . local_reset_queue . borrow_mut ( ) ;
415
-
416
- // check queue size
417
- if queue. len ( ) >= self . 0 . local_config . 0 . reset_max . get ( ) {
418
- if let Some ( ( id, _) ) = queue. pop_front ( ) {
419
- ids. remove ( & id) ;
420
- }
421
- }
422
- ids. insert ( id) ;
423
- queue. push_back ( ( id, now ( ) + self . 0 . local_config . 0 . reset_duration . get ( ) ) ) ;
424
- if !flags. contains ( ConnectionFlags :: DELAY_DROP_TASK_STARTED ) {
425
- let _ = spawn ( delay_drop_task ( self . clone ( ) ) ) ;
426
- }
410
+ // Add ids to pending queue
411
+ self . 0 . local_pending_reset . add ( id) ;
427
412
}
428
413
429
414
pub ( crate ) fn recv_half ( & self ) -> RecvHalfConnection {
@@ -482,7 +467,8 @@ impl RecvHalfConnection {
482
467
Ok ( item) => Ok ( item. map ( move |msg| ( stream, msg) ) ) ,
483
468
Err ( kind) => Err ( Either :: Right ( StreamErrorInner :: new ( stream, kind) ) ) ,
484
469
}
485
- } else if self . 0 . local_reset_ids . borrow ( ) . contains ( & id) {
470
+ } else if !self . 0 . local_config . is_server ( ) && self . 0 . local_pending_reset . is_pending ( id) {
471
+ // if client and no stream, then it was closed
486
472
self . encode ( frame:: Reset :: new ( id, frame:: Reason :: STREAM_CLOSED ) ) ;
487
473
Ok ( None )
488
474
} else if id < self . 0 . next_stream_id . get ( ) {
@@ -562,7 +548,7 @@ impl RecvHalfConnection {
562
548
Ok ( item) => Ok ( item. map ( move |msg| ( stream, msg) ) ) ,
563
549
Err ( kind) => Err ( Either :: Right ( StreamErrorInner :: new ( stream, kind) ) ) ,
564
550
}
565
- } else if self . 0 . local_reset_ids . borrow ( ) . contains ( & frm. stream_id ( ) ) {
551
+ } else if self . 0 . local_pending_reset . is_pending ( frm. stream_id ( ) ) {
566
552
self . encode ( frame:: Reset :: new (
567
553
frm. stream_id ( ) ,
568
554
frame:: Reason :: STREAM_CLOSED ,
@@ -701,7 +687,7 @@ impl RecvHalfConnection {
701
687
stream
702
688
. recv_window_update ( frm)
703
689
. map_err ( |kind| Either :: Right ( StreamErrorInner :: new ( stream, kind) ) )
704
- } else if self . 0 . local_reset_ids . borrow ( ) . contains ( & frm. stream_id ( ) ) {
690
+ } else if self . 0 . local_pending_reset . is_pending ( frm. stream_id ( ) ) {
705
691
Ok ( ( ) )
706
692
} else {
707
693
log:: trace!( "Unknown WINDOW_UPDATE {:?}" , frm) ;
@@ -738,7 +724,7 @@ impl RecvHalfConnection {
738
724
stream,
739
725
StreamError :: Reset ( frm. reason ( ) ) ,
740
726
) ) )
741
- } else if self . 0 . local_reset_ids . borrow ( ) . contains ( & frm. stream_id ( ) ) {
727
+ } else if self . 0 . local_pending_reset . is_pending ( frm. stream_id ( ) ) {
742
728
self . update_rst_count ( )
743
729
} else {
744
730
self . update_rst_count ( ) ?;
@@ -851,42 +837,6 @@ impl fmt::Debug for Connection {
851
837
}
852
838
}
853
839
854
- async fn delay_drop_task ( state : Connection ) {
855
- state. set_flags ( ConnectionFlags :: DELAY_DROP_TASK_STARTED ) ;
856
-
857
- loop {
858
- let next = if let Some ( item) = state. 0 . local_reset_queue . borrow ( ) . front ( ) {
859
- item. 1 - now ( )
860
- } else {
861
- break ;
862
- } ;
863
- sleep ( next) . await ;
864
-
865
- if state. is_closed ( ) {
866
- return ;
867
- }
868
-
869
- let now = now ( ) ;
870
- let mut ids = state. 0 . local_reset_ids . borrow_mut ( ) ;
871
- let mut queue = state. 0 . local_reset_queue . borrow_mut ( ) ;
872
- loop {
873
- if let Some ( item) = queue. front ( ) {
874
- if item. 1 <= now {
875
- log:: trace!( "{}: dropping {:?} after delay" , state. tag( ) , item. 0 ) ;
876
- ids. remove ( & item. 0 ) ;
877
- queue. pop_front ( ) ;
878
- } else {
879
- break ;
880
- }
881
- } else {
882
- state. unset_flags ( ConnectionFlags :: DELAY_DROP_TASK_STARTED ) ;
883
- return ;
884
- }
885
- }
886
- }
887
- state. unset_flags ( ConnectionFlags :: DELAY_DROP_TASK_STARTED ) ;
888
- }
889
-
890
840
async fn ping ( st : Connection , timeout : time:: Seconds , io : IoRef ) {
891
841
log:: debug!( "start http client ping/pong task" ) ;
892
842
@@ -917,3 +867,54 @@ async fn ping(st: Connection, timeout: time::Seconds, io: IoRef) {
917
867
st. 0 . pings_count . set ( st. 0 . pings_count . get ( ) + 1 ) ;
918
868
}
919
869
}
870
+
871
+ const BLOCKS : usize = 6 ;
872
+ const BLOCK_SIZE : Duration = Duration :: from_secs ( 30 ) ;
873
+ const LAST_BLOCK : usize = 5 ;
874
+
875
+ #[ derive( Default ) ]
876
+ struct Pending {
877
+ times : RefCell < [ Option < ( StreamId , Instant ) > ; BLOCKS ] > ,
878
+ }
879
+
880
+ impl Pending {
881
+ fn add ( & self , id : StreamId ) {
882
+ let cur = now ( ) ;
883
+ let mut times = self . times . borrow_mut ( ) ;
884
+
885
+ if let Some ( item) = & times[ 0 ] {
886
+ // check if we need to insert new block
887
+ if item. 1 < ( cur - BLOCK_SIZE ) {
888
+ // shift blocks
889
+ let mut i = LAST_BLOCK - 1 ;
890
+ loop {
891
+ times[ i + 1 ] = times[ i] ;
892
+ if i == 0 {
893
+ break ;
894
+ }
895
+ i -= 1 ;
896
+ }
897
+ // insert new item
898
+ times[ 0 ] = Some ( ( id, cur) ) ;
899
+ }
900
+ } else {
901
+ // insert new item
902
+ times[ 0 ] = Some ( ( id, cur) ) ;
903
+ }
904
+ }
905
+
906
+ fn is_pending ( & self , id : StreamId ) -> bool {
907
+ let times = self . times . borrow ( ) ;
908
+ let mut idx = LAST_BLOCK ;
909
+ loop {
910
+ if let Some ( item) = & times[ idx] {
911
+ return id >= item. 0 ;
912
+ } else if idx == 0 {
913
+ break ;
914
+ } else {
915
+ idx -= 1 ;
916
+ }
917
+ }
918
+ false
919
+ }
920
+ }
0 commit comments