@@ -543,6 +543,10 @@ pub struct Socket<'a> {
543
543
rx_waker : WakerRegistration ,
544
544
#[ cfg( feature = "async" ) ]
545
545
tx_waker : WakerRegistration ,
546
+
547
+ /// If this is set, we will not send a SYN|ACK until this is unset.
548
+ #[ cfg( feature = "socket-tcp-pause-synack" ) ]
549
+ synack_paused : bool ,
546
550
}
547
551
548
552
const DEFAULT_MSS : usize = 536 ;
@@ -606,6 +610,9 @@ impl<'a> Socket<'a> {
606
610
rx_waker : WakerRegistration :: new ( ) ,
607
611
#[ cfg( feature = "async" ) ]
608
612
tx_waker : WakerRegistration :: new ( ) ,
613
+
614
+ #[ cfg( feature = "socket-tcp-pause-synack" ) ]
615
+ synack_paused : false ,
609
616
}
610
617
}
611
618
@@ -724,6 +731,16 @@ impl<'a> Socket<'a> {
724
731
self . nagle
725
732
}
726
733
734
+ /// Pause sending of SYN|ACK packets.
735
+ ///
736
+ /// When this flag is set, the socket will get stuck in `SynReceived` state without sending
737
+ /// any SYN|ACK packets back, until this flag is unset. This is useful for certain niche TCP
738
+ /// proxy usecases.
739
+ #[ cfg( feature = "socket-tcp-pause-synack" ) ]
740
+ pub fn pause_synack ( & mut self , pause : bool ) {
741
+ self . synack_paused = pause;
742
+ }
743
+
727
744
/// Return the current window field value, including scaling according to RFC 1323.
728
745
///
729
746
/// Used in internal calculations as well as packet generation.
@@ -2372,6 +2389,11 @@ impl<'a> Socket<'a> {
2372
2389
. on_retransmit ( cx. now ( ) ) ;
2373
2390
}
2374
2391
2392
+ #[ cfg( feature = "socket-tcp-pause-synack" ) ]
2393
+ if matches ! ( self . state, State :: SynReceived ) && self . synack_paused {
2394
+ return Ok ( ( ) ) ;
2395
+ }
2396
+
2375
2397
// Decide whether we're sending a packet.
2376
2398
if self . seq_to_transmit ( cx) {
2377
2399
// If we have data to transmit and it fits into partner's window, do it.
@@ -3332,6 +3354,37 @@ mod test {
3332
3354
sanity ! ( s, socket_established( ) ) ;
3333
3355
}
3334
3356
3357
+ #[ cfg( feature = "socket-tcp-pause-synack" ) ]
3358
+ #[ test]
3359
+ fn test_syn_paused_ack ( ) {
3360
+ let mut s = socket_syn_received ( ) ;
3361
+
3362
+ s. pause_synack ( true ) ;
3363
+ recv_nothing ! ( s) ;
3364
+ assert_eq ! ( s. state, State :: SynReceived ) ;
3365
+
3366
+ s. pause_synack ( false ) ;
3367
+ recv ! (
3368
+ s,
3369
+ [ TcpRepr {
3370
+ control: TcpControl :: Syn ,
3371
+ seq_number: LOCAL_SEQ ,
3372
+ ack_number: Some ( REMOTE_SEQ + 1 ) ,
3373
+ max_seg_size: Some ( BASE_MSS ) ,
3374
+ ..RECV_TEMPL
3375
+ } ]
3376
+ ) ;
3377
+ send ! (
3378
+ s,
3379
+ TcpRepr {
3380
+ seq_number: REMOTE_SEQ + 1 ,
3381
+ ack_number: Some ( LOCAL_SEQ + 1 ) ,
3382
+ ..SEND_TEMPL
3383
+ }
3384
+ ) ;
3385
+ assert_eq ! ( s. state, State :: Established ) ;
3386
+ }
3387
+
3335
3388
#[ test]
3336
3389
fn test_syn_received_ack_too_low ( ) {
3337
3390
let mut s = socket_syn_received ( ) ;
0 commit comments