33mod tests;
44
55/// Client-side session manager implementation.
6+ use std:: future:: Future ;
67use std:: mem:: take;
8+ use std:: pin:: Pin ;
79use std:: sync:: Arc ;
810use std:: sync:: atomic:: { AtomicU32 , Ordering } ;
911
@@ -12,7 +14,7 @@ use log::{debug, warn};
1214use crate :: bytes:: { ByteBuffer , ByteBufferMut , DynamicByteBuffer } ;
1315use crate :: cache:: SharedValue ;
1416use crate :: crypto:: ClientCryptoTool ;
15- use crate :: flow:: FlowManager ;
17+ use crate :: flow:: { FlowControllerError , FlowManager } ;
1618use crate :: session:: client_health:: ClientHealthProvider ;
1719use crate :: session:: common:: SessionManager ;
1820use crate :: session:: error:: SessionControllerError ;
@@ -22,6 +24,8 @@ use crate::tailor::{ClientConnectionHandler, IdentityType, PacketFlags, Tailor};
2224use crate :: utils:: random:: { SupportRng , get_rng} ;
2325use crate :: utils:: sync:: { AsyncExecutor , Mutex , create_watch} ;
2426
27+ type RecvFut = Pin < Box < dyn Future < Output = Result < DynamicByteBuffer , FlowControllerError > > + Send > > ;
28+
2529struct ClientSessionManagerInternalSend < T : IdentityType + Clone > {
2630 cipher : SharedValue < ClientCryptoTool < T > > ,
2731}
@@ -31,16 +35,18 @@ struct ClientSessionManagerInternalReceive<T: IdentityType + Clone> {
3135}
3236
3337/// Client-side session manager that encrypts data and manages health checking.
34- pub struct ClientSessionManager < T : IdentityType + Clone + ' static , AE : AsyncExecutor + ' static , FM : FlowManager + Send + Sync + ' static , CC : ClientConnectionHandler + ' static > {
38+ pub struct ClientSessionManager < T : IdentityType + Clone + ' static , AE : AsyncExecutor + ' static , FM : FlowManager + Clone + Send + Sync + ' static , CC : ClientConnectionHandler + ' static > {
3539 health_provider : ClientHealthProvider < T , AE , Self , CC > ,
3640 send_internal : Mutex < ClientSessionManagerInternalSend < T > > ,
3741 receive_internal : Mutex < ClientSessionManagerInternalReceive < T > > ,
3842 incremental_counter : AtomicU32 ,
3943 flows : Vec < FM > ,
4044 settings : Arc < Settings < AE > > ,
45+ /// Persistent per-flow receive futures and their flow indices, reused across `receive_packet` calls.
46+ recv_state : Mutex < Option < ( Vec < RecvFut > , Vec < usize > ) > > ,
4147}
4248
43- impl < T : IdentityType + Clone , AE : AsyncExecutor , FM : FlowManager + Send + Sync , CC : ClientConnectionHandler + ' static > ClientSessionManager < T , AE , FM , CC > {
49+ impl < T : IdentityType + Clone , AE : AsyncExecutor , FM : FlowManager + Clone + Send + Sync , CC : ClientConnectionHandler + ' static > ClientSessionManager < T , AE , FM , CC > {
4450 /// Create a new client session manager without starting the handshake.
4551 /// Call `start()` after the background receive loop is running.
4652 pub fn new ( cipher : SharedValue < ClientCryptoTool < T > > , flows : Vec < FM > , settings : Arc < Settings < AE > > , initial_data_generator : CC ) -> Result < Arc < Self > , SessionControllerError > {
@@ -65,6 +71,7 @@ impl<T: IdentityType + Clone, AE: AsyncExecutor, FM: FlowManager + Send + Sync,
6571 incremental_counter : AtomicU32 :: new ( 0 ) ,
6672 flows,
6773 settings,
74+ recv_state : Mutex :: new ( None ) ,
6875 }
6976 } ) ;
7077
@@ -91,7 +98,7 @@ impl<T: IdentityType + Clone, AE: AsyncExecutor, FM: FlowManager + Send + Sync,
9198 }
9299}
93100
94- impl < T : IdentityType + Clone , AE : AsyncExecutor , FM : FlowManager + Send + Sync , CC : ClientConnectionHandler + ' static > SessionManager for ClientSessionManager < T , AE , FM , CC > {
101+ impl < T : IdentityType + Clone , AE : AsyncExecutor , FM : FlowManager + Clone + Send + Sync + ' static , CC : ClientConnectionHandler + ' static > SessionManager for ClientSessionManager < T , AE , FM , CC > {
95102 async fn send_packet ( & self , packet : DynamicByteBuffer , generated : bool ) -> Result < ( ) , SessionControllerError > {
96103 let full_packet = if generated {
97104 packet
@@ -130,15 +137,34 @@ impl<T: IdentityType + Clone, AE: AsyncExecutor, FM: FlowManager + Send + Sync,
130137 let recv_buf = self . settings . pool ( ) . allocate_for_recv ( ) ;
131138 self . flows [ 0 ] . receive_packet ( recv_buf) . await . map_err ( SessionControllerError :: FlowError ) ?
132139 } else {
133- let futs: Vec < _ > = self
134- . flows
135- . iter ( )
136- . map ( |flow| {
137- let buf = self . settings . pool ( ) . allocate_for_recv ( ) ;
138- Box :: pin ( flow. receive_packet ( buf) )
140+ // Take the persistent future state (releasing the lock before awaiting).
141+ let ( futs, mut flow_indices) = {
142+ let mut guard = self . recv_state . lock ( ) . await ;
143+ guard. take ( ) . unwrap_or_else ( || {
144+ let mut futs: Vec < RecvFut > = Vec :: with_capacity ( self . flows . len ( ) ) ;
145+ let mut indices: Vec < usize > = Vec :: with_capacity ( self . flows . len ( ) ) ;
146+ for ( i, flow) in self . flows . iter ( ) . enumerate ( ) {
147+ let f = flow. clone ( ) ;
148+ let buf = self . settings . pool ( ) . allocate_for_recv ( ) ;
149+ futs. push ( Box :: pin ( async move { f. receive_packet ( buf) . await } ) ) ;
150+ indices. push ( i) ;
151+ }
152+ ( futs, indices)
139153 } )
140- . collect ( ) ;
141- futures:: future:: select_all ( futs) . await . 0 . map_err ( SessionControllerError :: FlowError ) ?
154+ } ;
155+
156+ let ( result, completed_pos, mut remaining_futs) = futures:: future:: select_all ( futs) . await ;
157+ let completed_flow_idx = flow_indices. remove ( completed_pos) ;
158+
159+ // Replenish a new future for the flow that just completed.
160+ let f = self . flows [ completed_flow_idx] . clone ( ) ;
161+ let buf = self . settings . pool ( ) . allocate_for_recv ( ) ;
162+ remaining_futs. push ( Box :: pin ( async move { f. receive_packet ( buf) . await } ) ) ;
163+ flow_indices. push ( completed_flow_idx) ;
164+
165+ * self . recv_state . lock ( ) . await = Some ( ( remaining_futs, flow_indices) ) ;
166+
167+ result. map_err ( SessionControllerError :: FlowError ) ?
142168 } ;
143169
144170 // The flow manager returns: encrypted_payload || plaintext_tailor (full TAILOR_LENGTH + T::length() bytes).
@@ -171,7 +197,7 @@ impl<T: IdentityType + Clone, AE: AsyncExecutor, FM: FlowManager + Send + Sync,
171197 }
172198}
173199
174- impl < T : IdentityType + Clone , AE : AsyncExecutor , FM : FlowManager + Send + Sync , CC : ClientConnectionHandler + ' static > Drop for ClientSessionManager < T , AE , FM , CC > {
200+ impl < T : IdentityType + Clone , AE : AsyncExecutor , FM : FlowManager + Clone + Send + Sync + ' static , CC : ClientConnectionHandler + ' static > Drop for ClientSessionManager < T , AE , FM , CC > {
175201 fn drop ( & mut self ) {
176202 drop ( take ( & mut self . flows ) ) ;
177203 }
0 commit comments