@@ -89,7 +89,7 @@ static const char * const xqc_conn_flag_to_str[XQC_CONN_FLAG_SHIFT_NUM] = {
8989 [XQC_CONN_FLAG_0RTT_OK_SHIFT ] = "0RTT_OK" ,
9090 [XQC_CONN_FLAG_0RTT_REJ_SHIFT ] = "0RTT_REJECT" ,
9191 [XQC_CONN_FLAG_UPPER_CONN_EXIST_SHIFT ] = "UPPER_CONN_EXIST" ,
92- [XQC_CONN_FLAG_SVR_INIT_RECVD_SHIFT ] = "INIT_RECVD" ,
92+ [XQC_CONN_FLAG_INIT_RECVD_SHIFT ] = "INIT_RECVD" ,
9393 [XQC_CONN_FLAG_NEED_RUN_SHIFT ] = "NEED_RUN" ,
9494 [XQC_CONN_FLAG_PING_SHIFT ] = "PING" ,
9595 [XQC_CONN_FLAG_HSK_ACKED_SHIFT ] = "HSK_ACKED" ,
@@ -102,7 +102,7 @@ static const char * const xqc_conn_flag_to_str[XQC_CONN_FLAG_SHIFT_NUM] = {
102102 [XQC_CONN_FLAG_ADDR_VALIDATED_SHIFT ] = "ADDR_VALIDATED" ,
103103 [XQC_CONN_FLAG_NEW_CID_RECEIVED_SHIFT ] = "NEW_CID_RECEIVED" ,
104104 [XQC_CONN_FLAG_LINGER_CLOSING_SHIFT ] = "LINGER_CLOSING" ,
105- [XQC_CONN_FLAG_RECV_RETRY_SHIFT ] = "RETRY_RCVD " ,
105+ [XQC_CONN_FLAG_RETRY_RECVD_SHIFT ] = "RETRY_RECVD " ,
106106 [XQC_CONN_FLAG_TLS_HSK_COMPLETED_SHIFT ] = "TLS_HSK_CMPTD"
107107};
108108
@@ -330,7 +330,6 @@ xqc_conn_create(xqc_engine_t *engine, xqc_cid_t *dcid, xqc_cid_t *scid,
330330 xqc_init_list_head (& xc -> initial_crypto_data_list );
331331 xqc_init_list_head (& xc -> hsk_crypto_data_list );
332332 xqc_init_list_head (& xc -> application_crypto_data_list );
333- xqc_init_list_head (& xc -> retry_crypto_data_buffer );
334333 for (xqc_encrypt_level_t encrypt_level = XQC_ENC_LEV_INIT ; encrypt_level < XQC_ENC_LEV_MAX ; encrypt_level ++ ) {
335334 xqc_init_list_head (& xc -> undecrypt_packet_in [encrypt_level ]);
336335 }
@@ -1600,7 +1599,7 @@ xqc_conn_immediate_close(xqc_connection_t *conn)
16001599 return XQC_OK ;
16011600 }
16021601
1603- if (!(conn -> conn_flag & XQC_CONN_FLAG_SVR_INIT_RECVD )
1602+ if (!(conn -> conn_flag & XQC_CONN_FLAG_INIT_RECVD )
16041603 && conn -> conn_type == XQC_CONN_TYPE_SERVER )
16051604 {
16061605 conn -> conn_state = XQC_CONN_STATE_CLOSED ;
@@ -2857,36 +2856,141 @@ xqc_conn_has_hsk_keys(xqc_connection_t *c)
28572856 && xqc_tls_is_key_ready (c -> tls , XQC_ENC_LEV_HSK , XQC_KEY_TYPE_RX_READ );
28582857}
28592858
2860- xqc_int_t
2861- xqc_conn_on_recv_retry (xqc_connection_t * conn )
2859+
2860+ static xqc_bool_t
2861+ xqc_need_reassemble_packet (xqc_packet_out_t * packet_out )
28622862{
2863- /* only client will receive retry packet, and can't receive */
2864- if ((conn -> conn_type != XQC_CONN_TYPE_CLIENT )
2865- || (conn -> conn_flag & XQC_CONN_FLAG_RECV_RETRY ))
2863+ if (packet_out -> po_pkt .pkt_type == XQC_PTYPE_INIT
2864+ && packet_out -> po_frame_types & XQC_FRAME_BIT_CRYPTO )
28662865 {
2867- xqc_log (conn -> log , XQC_LOG_ERROR ,
2868- "|server recv retry or client recv retry two or more times|" );
2869- XQC_CONN_ERR (conn , TRA_PROTOCOL_VIOLATION );
2870- return - XQC_EPROTO ;
2866+ return XQC_TRUE ;
2867+
2868+ } else if (packet_out -> po_pkt .pkt_type == XQC_PTYPE_0RTT ) {
2869+ return XQC_TRUE ;
2870+ }
2871+
2872+ return XQC_FALSE ;
2873+ }
2874+
2875+ static xqc_int_t
2876+ xqc_conn_reassemble_packet (xqc_connection_t * conn , xqc_packet_out_t * ori_po )
2877+ {
2878+ xqc_packet_out_t * new_po = xqc_write_new_packet (conn , ori_po -> po_pkt .pkt_type );
2879+ if (new_po == NULL ) {
2880+ xqc_log (conn -> log , XQC_LOG_ERROR , "|xqc_write_new_packet error|" );
2881+ return - XQC_EWRITE_PKT ;
2882+ }
2883+
2884+ /* copy frame without padding */
2885+ unsigned int ori_payload_len = 0 ;
2886+ if (xqc_need_padding (conn , ori_po ) && ori_po -> po_padding != NULL ) {
2887+ ori_payload_len = ori_po -> po_padding - ori_po -> po_payload ;
2888+
2889+ } else {
2890+ ori_payload_len = ori_po -> po_used_size - (ori_po -> po_payload - ori_po -> po_buf );
2891+ }
2892+
2893+ new_po -> po_payload = new_po -> po_buf + new_po -> po_used_size ;
2894+ memcpy (new_po -> po_payload , ori_po -> po_payload , ori_payload_len );
2895+ new_po -> po_used_size += ori_payload_len ;
2896+
2897+ /* copy packet_out info */
2898+ new_po -> po_frame_types = ori_po -> po_frame_types ;
2899+ for (int i = 0 ; i < XQC_MAX_STREAM_FRAME_IN_PO ; i ++ ) {
2900+ new_po -> po_stream_frames [i ] = ori_po -> po_stream_frames [i ];
2901+ }
2902+
2903+ /* set RESEND flag */
2904+ new_po -> po_flag |= XQC_POF_RESEND ;
2905+
2906+ if (new_po -> po_frame_types & XQC_FRAME_BIT_CRYPTO ) {
2907+ xqc_send_ctl_move_to_high_pri (& new_po -> po_list , conn -> conn_send_ctl );
2908+ }
2909+
2910+ xqc_log (conn -> log , XQC_LOG_DEBUG ,
2911+ "|pkt_num:%ui|ptype:%d|frames:%s|" ,
2912+ new_po -> po_pkt .pkt_num , new_po -> po_pkt .pkt_type ,
2913+ xqc_frame_type_2_str (new_po -> po_frame_types ));
2914+
2915+ return XQC_OK ;
2916+ }
2917+
2918+ static xqc_int_t
2919+ xqc_conn_resend_packets (xqc_connection_t * conn )
2920+ {
2921+ /*
2922+ * Generate new header and reassemble packet for Initial and 0-RTT packets
2923+ * that need to be resent, and drop all old packets with the original header.
2924+ *
2925+ * TODO: Refactoring packet generation: generate packet header before sent.
2926+ * Then we don't have to reassemble the packets.
2927+ */
2928+
2929+ xqc_int_t ret ;
2930+ xqc_send_ctl_t * ctl = conn -> conn_send_ctl ;
2931+
2932+ xqc_list_head_t * pos , * next ;
2933+ xqc_packet_out_t * packet_out ;
2934+
2935+ xqc_list_for_each_safe (pos , next , & ctl -> ctl_send_packets ) {
2936+ packet_out = xqc_list_entry (pos , xqc_packet_out_t , po_list );
2937+
2938+ if (packet_out -> po_flag & XQC_POF_RESEND ) {
2939+ continue ;
2940+ }
2941+
2942+ /* reassemble new packet with updated header and insert to send queue */
2943+ if (xqc_need_reassemble_packet (packet_out )) {
2944+ ret = xqc_conn_reassemble_packet (conn , packet_out );
2945+ if (ret != XQC_OK ) {
2946+ xqc_log (conn -> log , XQC_LOG_ERROR , "|xqc_conn_reassemble_packet error|ret:%d|" , ret );
2947+ return ret ;
2948+ }
2949+ }
2950+
2951+ /* drop old packet */
2952+ xqc_send_ctl_remove_send (pos );
2953+ xqc_send_ctl_insert_free (pos , & ctl -> ctl_free_packets , ctl );
28712954 }
28722955
2873- /* reset connection state */
2874- conn -> conn_state = XQC_CONN_STATE_CLIENT_INIT ;
2875- conn -> conn_flag |= XQC_CONN_FLAG_RECV_RETRY ;
2956+ return XQC_OK ;
2957+ }
2958+
2959+ xqc_int_t
2960+ xqc_conn_on_recv_retry (xqc_connection_t * conn , xqc_cid_t * retry_scid )
2961+ {
2962+ xqc_int_t ret ;
2963+
2964+ conn -> conn_flag |= XQC_CONN_FLAG_RETRY_RECVD ;
2965+
2966+ /* change the DCID it uses for sending packets in response to Retry packet. */
2967+ xqc_cid_copy (& conn -> dcid_set .current_dcid , retry_scid );
28762968
28772969 /* reset initial keys */
2878- xqc_int_t ret = xqc_tls_reset_initial (conn -> tls , conn -> version , & conn -> original_dcid );
2970+ ret = xqc_tls_reset_initial (conn -> tls , conn -> version , retry_scid );
28792971 if (ret != XQC_OK ) {
2972+ xqc_log (conn -> log , XQC_LOG_ERROR ,
2973+ "|xqc_tls_reset_initial error|retry_scid:%s|ret:%d|" ,
2974+ xqc_scid_str (retry_scid ), ret );
28802975 return ret ;
28812976 }
28822977
2883- /* Copy ClientHello to buffer list */
2884- xqc_list_head_t * head = & conn -> initial_crypto_data_list ;
2885- xqc_list_head_t * pos , * next ;
2978+ /*
2979+ * clients that receive a Retry packet reset congestion control and loss
2980+ * recovery state, including resetting any pending timers.
2981+ */
2982+ xqc_send_ctl_reset (conn -> conn_send_ctl );
28862983
2887- xqc_list_for_each_safe (pos , next , head ) {
2888- xqc_list_del (pos );
2889- xqc_list_add_tail (pos , & conn -> retry_crypto_data_buffer );
2984+ /*
2985+ * client responds to a Retry packet with an Initial packet that includes
2986+ * the provided Retry token to continue connection establishment.
2987+ * client SHOULD attempt to resend data in 0-RTT packets after it sends a
2988+ * new Initial packet.
2989+ */
2990+ ret = xqc_conn_resend_packets (conn );
2991+ if (ret != XQC_OK ) {
2992+ xqc_log (conn -> log , XQC_LOG_ERROR , "|xqc_conn_resend_packets error|ret:%d|" , ret );
2993+ return ret ;
28902994 }
28912995
28922996 return XQC_OK ;
@@ -3027,6 +3131,18 @@ xqc_conn_check_transport_params(xqc_connection_t *conn, const xqc_transport_para
30273131 }
30283132 }
30293133
3134+ if (conn -> conn_type == XQC_CONN_TYPE_CLIENT ) {
3135+ /* check retry_source_connection_id parameter if recv retry packet */
3136+ if (conn -> conn_flag & XQC_CONN_FLAG_RETRY_RECVD ) {
3137+ if (!params -> retry_source_connection_id_present ) {
3138+ return - XQC_TLS_TRANSPORT_PARAM ;
3139+ }
3140+
3141+ } else if (params -> retry_source_connection_id_present ) {
3142+ return - XQC_TLS_TRANSPORT_PARAM ;
3143+ }
3144+ }
3145+
30303146 return XQC_OK ;
30313147}
30323148
@@ -3277,7 +3393,6 @@ xqc_conn_tls_handshake_completed_cb(void *user_data)
32773393
32783394 conn -> conn_flag |= XQC_CONN_FLAG_TLS_HSK_COMPLETED ;
32793395 conn -> handshake_complete_time = xqc_monotonic_timestamp ();
3280- xqc_free_crypto_buffer_list (& conn -> retry_crypto_data_buffer );
32813396}
32823397
32833398const xqc_tls_callbacks_t xqc_conn_tls_cbs = {
0 commit comments