@@ -20,12 +20,58 @@ use crate::{
20
20
Dir , Side , StreamId , TransportError , VarInt , MAX_STREAM_COUNT ,
21
21
} ;
22
22
23
+ /// Wrapper around `Recv` that facilitates reusing `Recv` instances
24
+ #[ derive( Debug ) ]
25
+ pub ( super ) enum StreamRecv {
26
+ /// A `Recv` that is ready to be opened
27
+ Free ( Box < Recv > ) ,
28
+ /// A `Recv` that has been opened
29
+ Open ( Box < Recv > ) ,
30
+ }
31
+
32
+ impl StreamRecv {
33
+ /// Returns a reference to the inner `Recv` if the stream is open
34
+ pub ( super ) fn as_open_recv ( & self ) -> Option < & Recv > {
35
+ match self {
36
+ Self :: Open ( r) => Some ( r) ,
37
+ _ => None ,
38
+ }
39
+ }
40
+
41
+ // Returns a mutable reference to the inner `Recv` if the stream is open
42
+ pub ( super ) fn as_open_recv_mut ( & mut self ) -> Option < & mut Recv > {
43
+ match self {
44
+ Self :: Open ( r) => Some ( r) ,
45
+ _ => None ,
46
+ }
47
+ }
48
+
49
+ // Returns the inner `Recv`
50
+ pub ( super ) fn into_inner ( self ) -> Box < Recv > {
51
+ match self {
52
+ Self :: Free ( r) | Self :: Open ( r) => r,
53
+ }
54
+ }
55
+
56
+ // Reinitialize the stream so the inner `Recv` can be reused
57
+ pub ( super ) fn free ( self , initial_max_data : u64 ) -> Self {
58
+ match self {
59
+ Self :: Free ( _) => unreachable ! ( "Self::Free on reinit()" ) ,
60
+ Self :: Open ( mut recv) => {
61
+ recv. reinit ( initial_max_data) ;
62
+ Self :: Free ( recv)
63
+ }
64
+ }
65
+ }
66
+ }
67
+
23
68
#[ allow( unreachable_pub) ] // fuzzing only
24
69
pub struct StreamsState {
25
70
pub ( super ) side : Side ,
26
71
// Set of streams that are currently open, or could be immediately opened by the peer
27
72
pub ( super ) send : FxHashMap < StreamId , Option < Box < Send > > > ,
28
- pub ( super ) recv : FxHashMap < StreamId , Option < Box < Recv > > > ,
73
+ pub ( super ) recv : FxHashMap < StreamId , Option < StreamRecv > > ,
74
+ pub ( super ) free_recv : Vec < StreamRecv > ,
29
75
pub ( super ) next : [ u64 ; 2 ] ,
30
76
/// Maximum number of locally-initiated streams that may be opened over the lifetime of the
31
77
/// connection so far, per direction
@@ -105,6 +151,7 @@ impl StreamsState {
105
151
side,
106
152
send : FxHashMap :: default ( ) ,
107
153
recv : FxHashMap :: default ( ) ,
154
+ free_recv : Vec :: new ( ) ,
108
155
next : [ 0 , 0 ] ,
109
156
max : [ 0 , 0 ] ,
110
157
max_remote : [ max_remote_bi. into ( ) , max_remote_uni. into ( ) ] ,
@@ -240,8 +287,8 @@ impl StreamsState {
240
287
241
288
// Stopped streams become closed instantly on FIN, so check whether we need to clean up
242
289
if closed {
243
- self . recv . remove ( & id) ;
244
- self . stream_freed ( id, StreamHalf :: Recv ) ;
290
+ let rs = self . recv . remove ( & id) . flatten ( ) . unwrap ( ) ;
291
+ self . stream_recv_freed ( id, rs ) ;
245
292
}
246
293
247
294
// We don't buffer data on stopped streams, so issue flow control credit immediately
@@ -293,8 +340,8 @@ impl StreamsState {
293
340
let end = rs. end ;
294
341
if stopped {
295
342
// Stopped streams should be disposed immediately on reset
296
- self . recv . remove ( & id) ;
297
- self . stream_freed ( id, StreamHalf :: Recv ) ;
343
+ let rs = self . recv . remove ( & id) . flatten ( ) . unwrap ( ) ;
344
+ self . stream_recv_freed ( id, rs ) ;
298
345
}
299
346
self . on_stream_frame ( !stopped, id) ;
300
347
@@ -358,6 +405,7 @@ impl StreamsState {
358
405
self . recv
359
406
. get ( & id)
360
407
. and_then ( |s| s. as_ref ( ) )
408
+ . and_then ( |s| s. as_open_recv ( ) )
361
409
. map_or ( false , |s| s. can_send_flow_control ( ) )
362
410
}
363
411
@@ -442,7 +490,12 @@ impl StreamsState {
442
490
None => break ,
443
491
} ;
444
492
pending. max_stream_data . remove ( & id) ;
445
- let rs = match self . recv . get_mut ( & id) . and_then ( |s| s. as_mut ( ) ) {
493
+ let rs = match self
494
+ . recv
495
+ . get_mut ( & id)
496
+ . and_then ( |s| s. as_mut ( ) )
497
+ . and_then ( |s| s. as_open_recv_mut ( ) )
498
+ {
446
499
Some ( x) => x,
447
500
None => continue ,
448
501
} ;
@@ -831,7 +884,8 @@ impl StreamsState {
831
884
}
832
885
// bidirectional OR (unidirectional AND remote)
833
886
if bi || remote {
834
- assert ! ( self . recv. insert( id, None ) . is_none( ) ) ;
887
+ let recv = self . free_recv . pop ( ) ;
888
+ assert ! ( self . recv. insert( id, recv) . is_none( ) ) ;
835
889
}
836
890
}
837
891
@@ -883,6 +937,11 @@ impl StreamsState {
883
937
}
884
938
}
885
939
940
+ pub ( super ) fn stream_recv_freed ( & mut self , id : StreamId , recv : StreamRecv ) {
941
+ self . free_recv . push ( recv. free ( self . stream_receive_window ) ) ;
942
+ self . stream_freed ( id, StreamHalf :: Recv ) ;
943
+ }
944
+
886
945
pub ( super ) fn max_send_data ( & self , id : StreamId ) -> VarInt {
887
946
let remote = self . side != id. initiator ( ) ;
888
947
match id. dir ( ) {
@@ -905,8 +964,16 @@ pub(super) fn get_or_insert_send(
905
964
#[ inline]
906
965
pub ( super ) fn get_or_insert_recv (
907
966
initial_max_data : u64 ,
908
- ) -> impl Fn ( & mut Option < Box < Recv > > ) -> & mut Box < Recv > {
909
- move |opt| opt. get_or_insert_with ( || Recv :: new ( initial_max_data) )
967
+ ) -> impl FnMut ( & mut Option < StreamRecv > ) -> & mut Recv {
968
+ move |opt| {
969
+ * opt = opt. take ( ) . map ( |s| match s {
970
+ StreamRecv :: Free ( recv) => StreamRecv :: Open ( recv) ,
971
+ s => s,
972
+ } ) ;
973
+ opt. get_or_insert_with ( || StreamRecv :: Open ( Recv :: new ( initial_max_data) ) )
974
+ . as_open_recv_mut ( )
975
+ . unwrap ( )
976
+ }
910
977
}
911
978
912
979
#[ cfg( test) ]
0 commit comments