@@ -4306,19 +4306,44 @@ impl Connection {
43064306 . get_mut ( & path_id)
43074307 . expect ( "payload is processed only after the path becomes known" ) ;
43084308
4309- use paths:: OnPathResponseReceived :: * ;
4310- match path. data . on_path_response_received ( now, response. 0 , remote) {
4311- OnPath { was_open } => {
4312- use PathTimer :: * ;
4313- let qlog = self . qlog . with_time ( now) ;
4314-
4315- self . timers
4316- . stop ( Timer :: PerPath ( path_id, PathValidation ) , qlog. clone ( ) ) ;
4317- self . timers
4318- . stop ( Timer :: PerPath ( path_id, PathOpen ) , qlog. clone ( ) ) ;
4319- if !was_open {
4320- self . events
4321- . push_back ( Event :: Path ( PathEvent :: Opened { id : path_id } ) ) ;
4309+ match path. data . challenges_sent . get ( & response. 0 ) {
4310+ // Response to an on-path PathChallenge
4311+ Some ( info) if info. remote == remote && path. data . remote == remote => {
4312+ let sent_instant = info. sent_instant ;
4313+ // TODO(@divma): reset timers using the remaining off-path challenges
4314+ self . timers . stop (
4315+ Timer :: PerPath ( path_id, PathTimer :: PathValidation ) ,
4316+ self . qlog . with_time ( now) ,
4317+ ) ;
4318+ self . timers . stop (
4319+ Timer :: PerPath ( path_id, PathTimer :: PathChallengeLost ) ,
4320+ self . qlog . with_time ( now) ,
4321+ ) ;
4322+ if !path. data . validated {
4323+ trace ! ( "new path validated" ) ;
4324+ }
4325+ self . timers . stop (
4326+ Timer :: PerPath ( path_id, PathTimer :: PathOpen ) ,
4327+ self . qlog . with_time ( now) ,
4328+ ) ;
4329+ // Clear any other on-path sent challenge.
4330+ path. data
4331+ . challenges_sent
4332+ . retain ( |_token, info| info. remote != remote) ;
4333+ path. data . send_new_challenge = false ;
4334+ path. data . validated = true ;
4335+
4336+ // This RTT can only be used for the initial RTT, not as a normal
4337+ // sample: https://www.rfc-editor.org/rfc/rfc9002#section-6.2.2-2.
4338+ let rtt = now. saturating_duration_since ( sent_instant) ;
4339+ path. data . rtt . reset_initial_rtt ( rtt) ;
4340+
4341+ self . events
4342+ . push_back ( Event :: Path ( PathEvent :: Opened { id : path_id } ) ) ;
4343+ // mark the path as open from the application perspective now that Opened
4344+ // event has been queued
4345+ if !std:: mem:: replace ( & mut path. data . open , true ) {
4346+ trace ! ( "path opened" ) ;
43224347 if let Some ( observed) = path. data . last_observed_addr_report . as_ref ( )
43234348 {
43244349 self . events . push_back ( Event :: Path ( PathEvent :: ObservedAddr {
@@ -4331,44 +4356,20 @@ impl Connection {
43314356 prev. challenges_sent . clear ( ) ;
43324357 prev. send_new_challenge = false ;
43334358 }
4334-
4335- match path. data . earliest_expiring_challenge ( ) {
4336- Some ( new_expire_time) => {
4337- let expires = new_expire_time
4338- + self . ack_frequency . max_ack_delay_for_pto ( ) ;
4339- self . timers . set (
4340- Timer :: PerPath ( path_id, PathChallengeLost ) ,
4341- expires,
4342- qlog,
4343- )
4344- }
4345- None => self
4346- . timers
4347- . stop ( Timer :: PerPath ( path_id, PathChallengeLost ) , qlog) ,
4348- }
43494359 }
4350- OffPath => {
4360+ // Response to an off-path PathChallenge
4361+ Some ( info) if info. remote == remote => {
43514362 debug ! ( "Response to off-path PathChallenge!" ) ;
4352- match path. data . earliest_expiring_challenge ( ) {
4353- Some ( new_expire_time) => {
4354- let expires = new_expire_time
4355- + self . ack_frequency . max_ack_delay_for_pto ( ) ;
4356- self . timers . set (
4357- Timer :: PerPath ( path_id, PathTimer :: PathChallengeLost ) ,
4358- expires,
4359- self . qlog . with_time ( now) ,
4360- )
4361- }
4362- None => self . timers . stop (
4363- Timer :: PerPath ( path_id, PathTimer :: PathChallengeLost ) ,
4364- self . qlog . with_time ( now) ,
4365- ) ,
4366- }
4363+ path. data
4364+ . challenges_sent
4365+ . retain ( |_token, info| info. remote != remote) ;
43674366 }
4368- Unknown => debug ! ( %response , "ignoring invalid PATH_RESPONSE" ) ,
4369- Invalid { expected } => {
4370- debug ! ( %response, from=%remote, % expected, "ignoring invalid PATH_RESPONSE" )
4367+ // Response to a PathChallenge we recognize, but from an invalid remote
4368+ Some ( info ) => {
4369+ debug ! ( %response, from=%remote, expected=%info . remote , "ignoring invalid PATH_RESPONSE" )
43714370 }
4371+ // Response to an unknown PathChallenge
4372+ None => debug ! ( %response, "ignoring invalid PATH_RESPONSE" ) ,
43724373 }
43734374 }
43744375 Frame :: MaxData ( bytes) => {
0 commit comments