@@ -690,6 +690,16 @@ fd_quic_svc_schedule1( fd_quic_conn_t * conn ) {
690
690
fd_quic_svc_schedule ( fd_quic_get_state (conn -> quic )-> svc_timers , conn );
691
691
}
692
692
693
+ /* Validation Helper */
694
+ static inline void
695
+ svc_cnt_eq_active_conn ( fd_quic_svc_timers_t * timers , fd_quic_t * quic ) {
696
+ ulong const event_cnt = fd_quic_svc_cnt_events ( timers );
697
+ ulong const conn_cnt = quic -> metrics .conn_active_cnt ;
698
+ if ( FD_UNLIKELY ( event_cnt != conn_cnt ) ) {
699
+ FD_LOG_CRIT (( "only %lu out of %lu connections are in timer" , event_cnt , conn_cnt ));
700
+ }
701
+ }
702
+
693
703
/* validates the free conn list doesn't cycle, point nowhere, leak, or point to live conn */
694
704
static void
695
705
fd_quic_conn_free_validate ( fd_quic_t * quic ) {
@@ -2252,6 +2262,8 @@ fd_quic_process_quic_packet_v1( fd_quic_t * quic,
2252
2262
break ;
2253
2263
}
2254
2264
2265
+ fd_quic_svc_schedule ( state -> svc_timers , conn );
2266
+
2255
2267
if ( FD_UNLIKELY ( rc == FD_QUIC_PARSE_FAIL ) ) {
2256
2268
FD_DEBUG ( FD_LOG_DEBUG (( "Rejected packet (type=%d)" , long_packet_type )); )
2257
2269
return FD_QUIC_PARSE_FAIL ;
@@ -2268,6 +2280,9 @@ fd_quic_process_quic_packet_v1( fd_quic_t * quic,
2268
2280
ulong dst_conn_id = fd_ulong_load_8 ( cur_ptr + 1 );
2269
2281
conn = fd_quic_conn_query ( state -> conn_map , dst_conn_id );
2270
2282
rc = fd_quic_handle_v1_one_rtt ( quic , conn , pkt , cur_ptr , cur_sz );
2283
+
2284
+ fd_quic_svc_schedule ( state -> svc_timers , conn );
2285
+
2271
2286
if ( FD_UNLIKELY ( rc == FD_QUIC_PARSE_FAIL ) ) {
2272
2287
return FD_QUIC_PARSE_FAIL ;
2273
2288
}
@@ -2283,6 +2298,7 @@ fd_quic_process_quic_packet_v1( fd_quic_t * quic,
2283
2298
int ack_type = fd_quic_lazy_ack_pkt ( quic , conn , pkt );
2284
2299
quic -> metrics .ack_tx [ ack_type ]++ ;
2285
2300
2301
+ /* fd_quic_lazy_ack_pkt may have prepped schedule */
2286
2302
fd_quic_svc_schedule ( state -> svc_timers , conn );
2287
2303
2288
2304
if ( pkt -> rtt_ack_time ) {
@@ -2462,6 +2478,7 @@ fd_quic_process_packet_impl( fd_quic_t * quic,
2462
2478
}
2463
2479
2464
2480
rc = fd_quic_process_quic_packet_v1 ( quic , & pkt , cur_ptr , cur_sz );
2481
+ svc_cnt_eq_active_conn ( state -> svc_timers , quic );
2465
2482
2466
2483
/* 0UL means no progress, so fail */
2467
2484
if ( FD_UNLIKELY ( ( rc == FD_QUIC_PARSE_FAIL ) |
@@ -2491,6 +2508,7 @@ fd_quic_process_packet_impl( fd_quic_t * quic,
2491
2508
/* short header packet
2492
2509
only one_rtt packets currently have short headers */
2493
2510
fd_quic_process_quic_packet_v1 ( quic , & pkt , cur_ptr , cur_sz );
2511
+ svc_cnt_eq_active_conn ( state -> svc_timers , quic );
2494
2512
}
2495
2513
2496
2514
void
@@ -2875,7 +2893,7 @@ fd_quic_svc_poll( fd_quic_t * quic,
2875
2893
max_idle_timeout value advertised by both endpoints." */
2876
2894
FD_DEBUG ( FD_LOG_WARNING (("%s conn %p conn_idx: %u closing due to idle timeout (%g ms)" ,
2877
2895
conn -> server ?"SERVER" :"CLIENT" ,
2878
- (void * )conn , conn -> conn_idx , (double )fd_quic_ticks_to_us (conn -> idle_timeout_ticks ) / 1e3 )); )
2896
+ (void * )conn , conn -> conn_idx , (double )fd_quic_ticks_to_us ( quic , conn -> idle_timeout_ticks ) / 1e3 )); )
2879
2897
2880
2898
fd_quic_set_conn_state ( conn , FD_QUIC_CONN_STATE_DEAD );
2881
2899
quic -> metrics .conn_timeout_cnt ++ ;
@@ -2909,7 +2927,7 @@ fd_quic_svc_poll( fd_quic_t * quic,
2909
2927
break ;
2910
2928
default :
2911
2929
/* prep idle timeout or keep alive at idle timeout/2 */
2912
- fd_quic_svc_prep_schedule ( conn , state -> now + (conn -> idle_timeout_ticks >>(quic -> config .keep_alive )) );
2930
+ fd_quic_svc_prep_schedule ( conn , conn -> last_activity + (conn -> idle_timeout_ticks >>(quic -> config .keep_alive )) );
2913
2931
fd_quic_svc_schedule ( state -> svc_timers , conn );
2914
2932
break ;
2915
2933
}
@@ -2927,6 +2945,7 @@ fd_quic_service( fd_quic_t * quic ) {
2927
2945
long now_ticks = fd_tickcount ();
2928
2946
2929
2947
fd_quic_svc_timers_t * timers = state -> svc_timers ;
2948
+ svc_cnt_eq_active_conn ( timers , quic );
2930
2949
fd_quic_svc_event_t next = fd_quic_svc_timers_next ( timers , now , 1 /* pop */ );
2931
2950
if ( FD_UNLIKELY ( next .conn == NULL ) ) {
2932
2951
return 0 ;
@@ -3513,6 +3532,8 @@ fd_quic_gen_frames( fd_quic_conn_t * conn,
3513
3532
}
3514
3533
}
3515
3534
3535
+ fd_quic_svc_prep_schedule ( conn , pkt_meta_tmpl -> expiry );
3536
+
3516
3537
return payload_ptr ;
3517
3538
}
3518
3539
@@ -3576,7 +3597,8 @@ fd_quic_conn_tx( fd_quic_t * quic,
3576
3597
ulong now = fd_quic_get_state ( quic )-> now ;
3577
3598
3578
3599
/* initialize expiry and tx_time */
3579
- fd_quic_pkt_meta_t pkt_meta_tmpl [1 ] = {{.expiry = now + 500000000UL , .tx_time = now }};
3600
+ ulong const retx_timeout = fd_quic_us_to_ticks ( quic , 500000UL ); /* 500 ms */
3601
+ fd_quic_pkt_meta_t pkt_meta_tmpl [1 ] = {{.expiry = now + retx_timeout , .tx_time = now }};
3580
3602
// pkt_meta_tmpl->expiry = fd_quic_calc_expiry( conn, now );
3581
3603
//ulong margin = (ulong)(conn->rtt->smoothed_rtt) + (ulong)(3 * conn->rtt->var_rtt);
3582
3604
//if( margin < pkt_meta->expiry ) {
@@ -3855,7 +3877,6 @@ fd_quic_conn_tx( fd_quic_t * quic,
3855
3877
void
3856
3878
fd_quic_conn_service ( fd_quic_t * quic , fd_quic_conn_t * conn , ulong now ) {
3857
3879
(void )now ;
3858
- conn -> svc_meta .next_timeout = ULONG_MAX ;
3859
3880
3860
3881
/* Send new rtt measurement probe? */
3861
3882
if ( FD_UNLIKELY (now > conn -> last_ack + (ulong )conn -> rtt_period_ticks ) ) {
@@ -3947,6 +3968,7 @@ fd_quic_conn_service( fd_quic_t * quic, fd_quic_conn_t * conn, ulong now ) {
3947
3968
case FD_QUIC_CONN_STATE_INVALID :
3948
3969
/* fall thru */
3949
3970
default :
3971
+ FD_LOG_CRIT (( "invalid conn state %u" , conn -> state ));
3950
3972
return ;
3951
3973
}
3952
3974
@@ -3972,12 +3994,6 @@ fd_quic_conn_free( fd_quic_t * quic,
3972
3994
3973
3995
fd_quic_state_t * state = fd_quic_get_state ( quic );
3974
3996
3975
- /* no need to remove this connection from the events queue
3976
- free is called from two places:
3977
- fini - service will never be called again. All events are destroyed
3978
- service - removes event before calling free. Event only allowed to be
3979
- enqueued once */
3980
-
3981
3997
/* remove all stream ids from map, and free stream */
3982
3998
3983
3999
/* remove used streams */
@@ -4034,12 +4050,12 @@ fd_quic_conn_free( fd_quic_t * quic,
4034
4050
}
4035
4051
conn -> tls_hs = NULL ;
4036
4052
4053
+ /* remove from service queue */
4037
4054
fd_quic_svc_cancel ( state -> svc_timers , conn );
4038
4055
4039
4056
/* put connection back in free list */
4040
4057
conn -> free_conn_next = state -> free_conn_list ;
4041
4058
state -> free_conn_list = conn -> conn_idx ;
4042
- fd_quic_set_conn_state ( conn , FD_QUIC_CONN_STATE_INVALID );
4043
4059
4044
4060
quic -> metrics .conn_active_cnt -- ;
4045
4061
@@ -4066,7 +4082,6 @@ fd_quic_connect( fd_quic_t * quic,
4066
4082
}
4067
4083
}
4068
4084
4069
-
4070
4085
fd_rng_t * rng = state -> _rng ;
4071
4086
4072
4087
/* create conn ids for us and them
0 commit comments