@@ -1523,7 +1523,7 @@ impl Connection {
15231523 Duration :: from_micros ( ack. delay << self . peer_params . ack_delay_exponent . 0 ) ,
15241524 )
15251525 } ;
1526- let rtt = instant_saturating_sub ( now, self . spaces [ space] . largest_acked_packet_sent ) ;
1526+ let rtt = now. saturating_duration_since ( self . spaces [ space] . largest_acked_packet_sent ) ;
15271527 self . path . rtt . update ( ack_delay, rtt) ;
15281528 if self . path . first_packet_after_rtt_sample . is_none ( ) {
15291529 self . path . first_packet_after_rtt_sample =
@@ -1712,8 +1712,6 @@ impl Connection {
17121712 let rtt = self . path . rtt . conservative ( ) ;
17131713 let loss_delay = cmp:: max ( rtt. mul_f32 ( self . config . time_threshold ) , TIMER_GRANULARITY ) ;
17141714
1715- // Packets sent before this time are deemed lost.
1716- let lost_send_time = now. checked_sub ( loss_delay) . unwrap ( ) ;
17171715 let largest_acked_packet = self . spaces [ pn_space] . largest_acked_packet . unwrap ( ) ;
17181716 let packet_threshold = self . config . packet_threshold as u64 ;
17191717 let mut size_of_lost_packets = 0u64 ;
@@ -1737,8 +1735,11 @@ impl Connection {
17371735 persistent_congestion_start = None ;
17381736 }
17391737
1740- if info. time_sent <= lost_send_time || largest_acked_packet >= packet + packet_threshold
1741- {
1738+ // Packets sent before now - loss_delay are deemed lost.
1739+ // However, we avoid this subtraction as it can panic and there's no
1740+ // saturating equivalent of this substraction operation with a Duration.
1741+ let packet_too_old = now. saturating_duration_since ( info. time_sent ) >= loss_delay;
1742+ if packet_too_old || largest_acked_packet >= packet + packet_threshold {
17421743 if Some ( packet) == in_flight_mtu_probe {
17431744 // Lost MTU probes are not included in `lost_packets`, because they should not
17441745 // trigger a congestion control response
@@ -1791,6 +1792,17 @@ impl Connection {
17911792 lost_packets, size_of_lost_packets
17921793 ) ;
17931794
1795+ // Packets sent before this time are deemed lost.
1796+ // We avoid computing this value above, since it's possible for this to panic
1797+ // if the `loss_delay` value internally stores a bigger `Duration` than the
1798+ // `Duration` that's stored inside the `Instant`, because some platforms may
1799+ // implement the `Instant` with a counter relative to system or even process
1800+ // startup (Wasm is one such case).
1801+ // If we're at this point, then it must be possible to have instants that are
1802+ // longer ago than `loss_delay` (see the `packet_too_old` computation
1803+ // above).
1804+ let lost_send_time = now. checked_sub ( loss_delay) . unwrap ( ) ;
1805+
17941806 for & packet in & lost_packets {
17951807 let info = self . spaces [ pn_space] . take ( packet) . unwrap ( ) ; // safe: lost_packets is populated just above
17961808 self . config . qlog_sink . emit_packet_lost (
@@ -4056,10 +4068,6 @@ pub enum Event {
40564068 DatagramsUnblocked ,
40574069}
40584070
4059- fn instant_saturating_sub ( x : Instant , y : Instant ) -> Duration {
4060- if x > y { x - y } else { Duration :: ZERO }
4061- }
4062-
40634071fn get_max_ack_delay ( params : & TransportParameters ) -> Duration {
40644072 Duration :: from_micros ( params. max_ack_delay . 0 * 1000 )
40654073}
0 commit comments