@@ -68,6 +68,9 @@ typedef enum xqc_proto_version_s {
6868#define XQC_MAX_SEND_MSG_ONCE 32
6969
7070
71+ #define XQC_INITIAL_PATH_ID 0
72+
73+
7174/**
7275 * @brief get timestamp callback function. this might be useful on different platforms
7376 * @return timestamp in microsecond
@@ -287,6 +290,18 @@ typedef int (*xqc_cert_verify_pt)(const unsigned char *certs[], const size_t cer
287290typedef void (* xqc_conn_peer_addr_changed_nofity_pt )(xqc_connection_t * conn , void * conn_user_data );
288291
289292
293+ /**
294+ * @brief server peer addr changed notify
295+ *
296+ * this function will be trigger after receive peer's changed addr.
297+ *
298+ * @param conn connection handler
299+ * @param path_id id of path
300+ * @param conn_user_data connection level user_data
301+ */
302+ typedef void (* xqc_path_peer_addr_changed_nofity_pt )(xqc_connection_t * conn , uint64_t path_id , void * conn_user_data );
303+
304+
290305/**
291306 * @brief return value of xqc_socket_write_pt and xqc_send_mmsg_pt callback function
292307 */
@@ -359,15 +374,19 @@ typedef void (*xqc_conn_ready_to_create_path_notify_pt)(const xqc_cid_t *scid,
359374/**
360375 * @brief multi-path create callback function
361376 *
377+ * @param conn connection handler
362378 * @param scid source connection id of endpoint
363379 * @param path_id id of path
364380 * @param conn_user_data user_data of connection
365381 */
366- typedef void (* xqc_path_created_notify_pt )(const xqc_cid_t * scid , uint64_t path_id ,
367- void * conn_user_data );
382+ typedef int (* xqc_path_created_notify_pt )(xqc_connection_t * conn ,
383+ const xqc_cid_t * scid , uint64_t path_id , void * conn_user_data );
368384
369385/**
370- * @brief multi-path remove path callback function. will be triggered when path is destroyed
386+ * @brief multi-path remove path callback function.
387+ *
388+ * this callback function will be triggered when path is closing
389+ * and then the application-layer can release related resource.
371390 *
372391 * @param scid source connection id of endpoint
373392 * @param path_id id of path
@@ -391,8 +410,10 @@ typedef void (*xqc_path_removed_notify_pt)(const xqc_cid_t *scid, uint64_t path_
391410 * XQC_SOCKET_EAGAIN for EAGAIN, we should call xqc_conn_continue_send when socket is ready to write
392411 * Warning: server's user_data is what passed in xqc_engine_packet_process when send a reset packet
393412 */
394- typedef ssize_t (* xqc_mp_socket_write_pt )(uint64_t path_id , const unsigned char * buf , size_t size ,
395- const struct sockaddr * peer_addr , socklen_t peer_addrlen , void * conn_user_data );
413+ typedef ssize_t (* xqc_socket_write_ex_pt )(uint64_t path_id ,
414+ const unsigned char * buf , size_t size ,
415+ const struct sockaddr * peer_addr , socklen_t peer_addrlen ,
416+ void * conn_user_data );
396417
397418/**
398419 * @brief multi-path write socket callback function with sendmmsg
@@ -409,8 +430,9 @@ typedef ssize_t (*xqc_mp_socket_write_pt)(uint64_t path_id, const unsigned char
409430 * XQC_SOCKET_EAGAIN for EAGAIN, we should call xqc_conn_continue_send when socket is ready to write
410431 * Warning: server's user_data is what passed in xqc_engine_packet_process when send a reset packet
411432 */
412- typedef ssize_t (* xqc_mp_send_mmsg_pt )(uint64_t path_id , const struct iovec * msg_iov ,
413- unsigned int vlen , const struct sockaddr * peer_addr , socklen_t peer_addrlen ,
433+ typedef ssize_t (* xqc_send_mmsg_ex_pt )(uint64_t path_id ,
434+ const struct iovec * msg_iov , unsigned int vlen ,
435+ const struct sockaddr * peer_addr , socklen_t peer_addrlen ,
414436 void * conn_user_data );
415437
416438
@@ -479,6 +501,16 @@ typedef struct xqc_transport_callbacks_s {
479501 */
480502 xqc_send_mmsg_pt write_mmsg ;
481503
504+ /**
505+ * write socket callback, ALTERNATIVE with write_mmsg
506+ */
507+ xqc_socket_write_ex_pt write_socket_ex ;
508+
509+ /**
510+ * write socket with send_mmsg callback, ALTERNATIVE with write_socket
511+ */
512+ xqc_send_mmsg_ex_pt write_mmsg_ex ;
513+
482514 /**
483515 * QUIC connection cid update callback, REQUIRED for both server and client
484516 */
@@ -529,6 +561,11 @@ typedef struct xqc_transport_callbacks_s {
529561 */
530562 xqc_conn_peer_addr_changed_nofity_pt conn_peer_addr_changed_notify ;
531563
564+ /**
565+ * QUIC path peer addr changed callback, REQUIRED for server.
566+ */
567+ xqc_path_peer_addr_changed_nofity_pt path_peer_addr_changed_notify ;
568+
532569} xqc_transport_callbacks_t ;
533570
534571
@@ -680,6 +717,19 @@ XQC_EXPORT_PUBLIC_API XQC_EXTERN const xqc_cong_ctrl_callback_t xqc_bbr2_cb;
680717#endif
681718XQC_EXPORT_PUBLIC_API XQC_EXTERN const xqc_cong_ctrl_callback_t xqc_bbr_cb ;
682719XQC_EXPORT_PUBLIC_API XQC_EXTERN const xqc_cong_ctrl_callback_t xqc_cubic_cb ;
720+ typedef struct xqc_scheduler_callback_s {
721+
722+ size_t (* xqc_scheduler_size )(void );
723+
724+ void (* xqc_scheduler_init )(void * scheduler , xqc_log_t * log );
725+
726+ xqc_path_ctx_t * (* xqc_scheduler_get_path )(void * scheduler ,
727+ xqc_connection_t * conn , xqc_packet_out_t * packet_out ,
728+ int check_cwnd , int reinject );
729+
730+ } xqc_scheduler_callback_t ;
731+
732+ XQC_EXPORT_PUBLIC_API XQC_EXTERN const xqc_scheduler_callback_t xqc_minrtt_scheduler_cb ;
683733
684734
685735/**
@@ -845,6 +895,27 @@ typedef struct xqc_conn_settings_s {
845895 uint32_t anti_amplification_limit ; /* limit of anti-amplification, default 3 */
846896 uint64_t keyupdate_pkt_threshold ; /* packet limit of a single 1-rtt key, 0 for unlimited */
847897 size_t max_pkt_out_size ;
898+
899+ /*
900+ * multipath option:
901+ * 0: don't support multipath
902+ * 1: only support one PN space for multipath
903+ * 2: only support multiple PN spaces for multipath
904+ * 3: support both one PN space and multiple PN space
905+ * !Attention: don't use xqc_bbr_cb or xqc_bbr2_cb
906+ */
907+ uint64_t enable_multipath ;
908+ /*
909+ * reinjection option:
910+ * 0: default
911+ * 1: try to reinject unacked packets if paths still have cwnd.
912+ * the current reinjection mode is very aggressive, please use with caution.
913+ */
914+ int mp_enable_reinjection ;
915+
916+ /* scheduler callback, default: xqc_minrtt_scheduler_cb */
917+ xqc_scheduler_callback_t scheduler_callback ;
918+
848919} xqc_conn_settings_t ;
849920
850921
@@ -854,6 +925,20 @@ typedef enum {
854925 XQC_0RTT_REJECT , /* 0-RTT was rejected */
855926} xqc_0rtt_flag_t ;
856927
928+
929+ #define XQC_MAX_PATHS_COUNT 8
930+ #define XQC_CONN_INFO_LEN 400
931+
932+ typedef struct xqc_path_metrics_s {
933+ uint64_t path_id ;
934+
935+ uint64_t path_pkt_recv_count ;
936+ uint64_t path_pkt_send_count ;
937+ uint64_t path_send_bytes ;
938+ uint64_t path_reinject_bytes ;
939+ } xqc_path_metrics_t ;
940+
941+
857942typedef struct xqc_conn_stats_s {
858943 uint32_t send_count ;
859944 uint32_t lost_count ;
@@ -865,6 +950,11 @@ typedef struct xqc_conn_stats_s {
865950 int spurious_loss_detect_on ;
866951 int conn_err ;
867952 char ack_info [50 ];
953+
954+ int enable_multipath ;
955+ int mp_state ;
956+ xqc_path_metrics_t paths_info [XQC_MAX_PATHS_COUNT ];
957+ char conn_info [XQC_CONN_INFO_LEN ];
868958} xqc_conn_stats_t ;
869959
870960
@@ -1220,9 +1310,47 @@ xqc_int_t xqc_conn_continue_send(xqc_engine_t *engine, const xqc_cid_t *cid);
12201310XQC_EXPORT_PUBLIC_API
12211311xqc_conn_stats_t xqc_conn_get_stats (xqc_engine_t * engine , const xqc_cid_t * cid );
12221312
1313+ /**
1314+ * create new path for client
1315+ * @param cid scid for connection
1316+ * @param new_path_id if new path is created successfully, return new_path_id in this param
1317+ * @return XQC_OK (0) when success, <0 for error
1318+ */
1319+ XQC_EXPORT_PUBLIC_API
1320+ xqc_int_t xqc_conn_create_path (xqc_engine_t * engine ,
1321+ const xqc_cid_t * cid , uint64_t * new_path_id );
1322+
1323+
1324+ /**
1325+ * Close a path
1326+ * @param cid scid for connection
1327+ * @param close_path_id path identifier for the closing path
1328+ * @return XQC_OK (0) when success, <0 for error
1329+ */
1330+ XQC_EXPORT_PUBLIC_API
1331+ xqc_int_t xqc_conn_close_path (xqc_engine_t * engine , const xqc_cid_t * cid , uint64_t closed_path_id );
1332+
12231333XQC_EXPORT_PUBLIC_API
12241334xqc_conn_type_t xqc_conn_get_type (xqc_connection_t * conn );
12251335
1336+ /**
1337+ * Server should get peer addr when path_create_notify callbacks
1338+ * @param peer_addr_len is a return value
1339+ * @return XQC_OK for success, others for failure
1340+ */
1341+ XQC_EXPORT_PUBLIC_API
1342+ xqc_int_t xqc_path_get_peer_addr (xqc_connection_t * conn , uint64_t path_id ,
1343+ struct sockaddr * addr , socklen_t addr_cap , socklen_t * peer_addr_len );
1344+
1345+ /**
1346+ * Server should get local addr when path_create_notify callbacks
1347+ * @param local_addr_len is a return value
1348+ * @return XQC_OK for success, others for failure
1349+ */
1350+ XQC_EXPORT_PUBLIC_API
1351+ xqc_int_t xqc_path_get_local_addr (xqc_connection_t * conn , uint64_t path_id ,
1352+ struct sockaddr * addr , socklen_t addr_cap , socklen_t * local_addr_len );
1353+
12261354/**
12271355 * @brief load balance cid encryption.
12281356 * According to Draft : https://datatracker.ietf.org/doc/html/draft-ietf-quic-load-balancers-13#section-4.3.2
0 commit comments