@@ -1468,6 +1468,39 @@ rops_handle_POLLIN_quic(struct lws_context_per_thread *pt, struct lws *wsi,
14681468 nwsi -> quic .qn -> probing_sa46 = migration_sa46 ;
14691469 nwsi -> quic .qn -> probing_sa46_valid = 1 ;
14701470
1471+ /*
1472+ * Queue PATH_CHALLENGE immediately, tagged to
1473+ * the new 4-tuple via has_dest. Do NOT commit
1474+ * udp->sa46 yet — keep ordinary traffic (incl.
1475+ * Handshake ACKs) flowing to the OLD path until
1476+ * PATH_RESPONSE validates the new one. This
1477+ * ensures the first server datagram to the new
1478+ * client port carries PATH_CHALLENGE (RFC 9000
1479+ * §8.2 / QIR connectionmigration requirement).
1480+ */
1481+ if (!nwsi -> quic .qn -> path_challenge_pending ) {
1482+ struct lws_quic_tx_frame * f_pc =
1483+ lws_zalloc (sizeof (* f_pc ) + 8 ,
1484+ "quic path_chall" );
1485+ if (f_pc ) {
1486+ f_pc -> type = LWS_QUIC_FT_PATH_CHALLENGE ;
1487+ f_pc -> len = 8 ;
1488+ f_pc -> data = (uint8_t * )& f_pc [1 ];
1489+ if (lws_get_random (wsi -> a .context ,
1490+ f_pc -> data , 8 ) != 8 ) {
1491+ lws_free (f_pc );
1492+ return LWS_HPI_RET_HANDLED ;
1493+ }
1494+ memcpy (nwsi -> quic .qn -> path_challenge ,
1495+ f_pc -> data , 8 );
1496+ nwsi -> quic .qn -> path_challenge_pending = 1 ;
1497+ f_pc -> has_dest = 1 ;
1498+ f_pc -> dest_sa46 = migration_sa46 ;
1499+ lws_dll2_add_head (& f_pc -> list ,
1500+ & nwsi -> quic .qn -> pending_tx [LWS_QUIC_LEVEL_APP ]);
1501+ }
1502+ }
1503+
14711504 } else {
14721505#if (_LWS_ENABLED_LOGS & LLL_NOTICE )
14731506 lwsl_notice ("QUIC Client: Server address changed from %s:%u to %s:%u, re-connecting socket\n" ,
@@ -1504,9 +1537,15 @@ rops_handle_POLLIN_quic(struct lws_context_per_thread *pt, struct lws *wsi,
15041537 nwsi -> quic .qn -> bytes_sent = 0 ;
15051538 }
15061539
1507- /* Initiate Path Validation (Generate PATH_CHALLENGE) if none pending */
1508- if (!nwsi -> quic .qn -> path_challenge_pending ) {
1509- struct lws_quic_tx_frame * f_pc = lws_zalloc (sizeof (* f_pc ) + 8 , "quic path_chall" );
1540+ /*
1541+ * Client path: queue PATH_CHALLENGE for the
1542+ * server-address-change case (server already did
1543+ * its own above).
1544+ */
1545+ if (!nwsi -> quic .qn -> is_server &&
1546+ !nwsi -> quic .qn -> path_challenge_pending ) {
1547+ struct lws_quic_tx_frame * f_pc =
1548+ lws_zalloc (sizeof (* f_pc ) + 8 , "quic path_chall" );
15101549 if (f_pc ) {
15111550 f_pc -> type = LWS_QUIC_FT_PATH_CHALLENGE ;
15121551 f_pc -> len = 8 ;
@@ -1517,16 +1556,11 @@ rops_handle_POLLIN_quic(struct lws_context_per_thread *pt, struct lws *wsi,
15171556 }
15181557 memcpy (nwsi -> quic .qn -> path_challenge , f_pc -> data , 8 );
15191558 nwsi -> quic .qn -> path_challenge_pending = 1 ;
1520-
1521- if (nwsi -> quic .qn -> is_server ) {
1522- f_pc -> has_dest = 1 ;
1523- f_pc -> dest_sa46 = migration_sa46 ;
1524- }
1525-
1526- lws_dll2_add_head (& f_pc -> list , & nwsi -> quic .qn -> pending_tx [LWS_QUIC_LEVEL_APP ]);
1527- lws_callback_on_writable (nwsi );
1559+ lws_dll2_add_head (& f_pc -> list ,
1560+ & nwsi -> quic .qn -> pending_tx [LWS_QUIC_LEVEL_APP ]);
15281561 }
15291562 }
1563+ lws_callback_on_writable (nwsi );
15301564 }
15311565 }
15321566
0 commit comments