Skip to content

Commit

Permalink
[!] fix bugs and building error on ubuntu and macOS, add initial rtt (#…
Browse files Browse the repository at this point in the history
…407)

[-] deprecate XQC_NO_PID_PACKET_PROCESS;
[=] optimize connection transport parameters;
[!] fix CC frame packet error;
[+] add initial_rtt;
[!] fix loss, retransmission, and spurious loss counting;
[!] optimize 0-RTT sending;
[!] add protection for zero-length header value;
[=] reduce http3 body read notify;
[!] retransmit PING frame sent by app layer;
[!] fix building boringssl on ubuntu and macOS;
  • Loading branch information
Kulsk authored Mar 19, 2024
1 parent f3cab88 commit 3607442
Show file tree
Hide file tree
Showing 41 changed files with 478 additions and 334 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,7 @@ if(PLATFORM MATCHES "mac")
${SSL_LIB_PATH}
"-Wl"
-lpthread
-lstdc++
)
else()
target_link_libraries(
Expand Down
27 changes: 14 additions & 13 deletions demo/demo_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ typedef struct xqc_demo_cli_quic_config_s {

size_t max_pkt_sz;

char co_str[XQC_CO_STR_MAX_LEN];

} xqc_demo_cli_quic_config_t;


Expand Down Expand Up @@ -1265,9 +1267,9 @@ xqc_demo_cli_h3_request_close_notify(xqc_h3_request_t *h3_request, void *user_da
xqc_request_stats_t stats;
stats = xqc_h3_request_get_stats(h3_request);
printf("send_body_size:%zu, recv_body_size:%zu, send_header_size:%zu, recv_header_size:%zu, "
"recv_fin:%d, err:%d, rate_limit:%"PRIu64", mp_state:%d, avail_send_weight:%.3lf, avail_recv_weight:%.3lf\n",
"recv_fin:%d, err:%d, rate_limit:%"PRIu64", mp_state:%d, early_data:%d, avail_send_weight:%.3lf, avail_recv_weight:%.3lf\n",
stats.send_body_size, stats.recv_body_size, stats.send_header_size, stats.recv_header_size,
user_stream->recv_fin, stats.stream_err, stats.rate_limit, stats.mp_state,
user_stream->recv_fin, stats.stream_err, stats.rate_limit, stats.mp_state, stats.early_data_state,
stats.mp_default_path_send_weight, stats.mp_default_path_recv_weight);

printf("\033[33m[H3-req] send_bytes:%zu, recv_bytes:%zu, path_info:%s\n\033[0m",
Expand Down Expand Up @@ -1337,19 +1339,11 @@ xqc_demo_cli_socket_read_handler(xqc_demo_cli_user_conn_t *user_conn, int fd)
recv_sum += recv_size;
uint64_t recv_time = xqc_now();
user_path->last_sock_op_time = recv_time;
#ifdef XQC_NO_PID_PACKET_PROCESS
if (xqc_engine_packet_process(user_conn->ctx->engine, packet_buf, recv_size,
(struct sockaddr *)(&user_path->local_addr),
user_path->local_addrlen, (struct sockaddr *)(&addr),
addr_len, (xqc_msec_t)recv_time,
user_conn) != XQC_OK)
#else
if (xqc_engine_packet_process(user_conn->ctx->engine, packet_buf, recv_size,
(struct sockaddr *)(&user_path->local_addr),
user_path->local_addrlen, (struct sockaddr *)(&addr),
addr_len, user_path->path_id, (xqc_msec_t)recv_time,
user_conn) != XQC_OK)
#endif
{
return;
}
Expand Down Expand Up @@ -1630,7 +1624,7 @@ xqc_demo_cli_init_conneciton_settings(xqc_conn_settings_t* settings,
settings->pacing_on = args->net_cfg.pacing;
settings->cong_ctrl_callback = cong_ctrl;
settings->cc_params.customize_on = 1,
settings->cc_params.init_cwnd = 32,
settings->cc_params.init_cwnd = 96,
settings->so_sndbuf = 1024*1024;
settings->proto_version = XQC_VERSION_V1;
settings->spurious_loss_detect_on = 1;
Expand All @@ -1651,6 +1645,7 @@ xqc_demo_cli_init_conneciton_settings(xqc_conn_settings_t* settings,
settings->enable_stream_rate_limit = 1;
settings->recv_rate_bytes_per_sec = 0;
}
strncpy(settings->conn_option_str, args->quic_cfg.co_str, XQC_CO_STR_MAX_LEN);
}

/* set client args to default values */
Expand Down Expand Up @@ -1797,14 +1792,15 @@ xqc_demo_cli_usage(int argc, char *argv[])
" -e NAT rebinding on path 0\n"
" -E NAT rebinding on path 1\n"
" -F MTU size (default: 1200)\n"
" -G Google connection options (e.g. CBBR,TBBR)\n"
, prog);
}

void
xqc_demo_cli_parse_args(int argc, char *argv[], xqc_demo_cli_client_args_t *args)
{
int ch = 0;
while ((ch = getopt(argc, argv, "a:p:c:Ct:S:0m:A:D:l:L:k:K:U:u:dMoi:w:Ps:bZ:NQT:R:V:B:I:n:eEF:")) != -1) {
while ((ch = getopt(argc, argv, "a:p:c:Ct:S:0m:A:D:l:L:k:K:U:u:dMoi:w:Ps:bZ:NQT:R:V:B:I:n:eEF:G:")) != -1) {
switch (ch) {
/* server ip */
case 'a':
Expand Down Expand Up @@ -2043,6 +2039,11 @@ xqc_demo_cli_parse_args(int argc, char *argv[], xqc_demo_cli_client_args_t *args
printf("MTU size: %s\n", optarg);
args->quic_cfg.max_pkt_sz = atoi(optarg);
break;

case 'G':
printf("Google connection options: %s\n", optarg);
strncpy(args->quic_cfg.co_str, optarg, XQC_CO_STR_MAX_LEN);
break;

default:
printf("other option :%c\n", ch);
Expand Down Expand Up @@ -2266,7 +2267,7 @@ xqc_demo_cli_h3_conn_close_notify(xqc_h3_conn_t *h3_conn, const xqc_cid_t *cid,
xqc_demo_cli_user_conn_t *user_conn = (xqc_demo_cli_user_conn_t *)user_data;
xqc_conn_stats_t stats = xqc_conn_get_stats(user_conn->ctx->engine, cid);
printf("send_count:%u, lost_count:%u, tlp_count:%u, recv_count:%u, srtt:%"PRIu64" "
"early_data_flag:%d, conn_err:%d, ack_info:%s conn_info:%s\n", stats.send_count, stats.lost_count,
"early_data_flag:%d, conn_err:%d, ack_info:%s, conn_info:%s\n", stats.send_count, stats.lost_count,
stats.tlp_count, stats.recv_count, stats.srtt, stats.early_data_flag, stats.conn_err,
stats.ack_info, stats.conn_info);

Expand Down
7 changes: 0 additions & 7 deletions demo/demo_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -1052,17 +1052,10 @@ xqc_demo_svr_socket_read_handler(xqc_demo_svr_ctx_t *ctx, int fd)
recv_sum += recv_size;

uint64_t recv_time = xqc_now();
#ifdef XQC_NO_PID_PACKET_PROCESS
xqc_int_t ret = xqc_engine_packet_process(ctx->engine, packet_buf, recv_size,
(struct sockaddr *)(&ctx->local_addr), ctx->local_addrlen,
(struct sockaddr *)(&peer_addr), peer_addrlen,
(xqc_usec_t)recv_time, ctx);
#else
xqc_int_t ret = xqc_engine_packet_process(ctx->engine, packet_buf, recv_size,
(struct sockaddr *)(&ctx->local_addr), ctx->local_addrlen,
(struct sockaddr *)(&peer_addr), peer_addrlen, XQC_UNKNOWN_PATH_ID,
(xqc_usec_t)recv_time, ctx);
#endif
if (ret != XQC_OK) {
printf("server_read_handler: packet process err, ret: %d\n", ret);
return;
Expand Down
8 changes: 8 additions & 0 deletions include/xquic/xqc_http3.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,14 @@ typedef struct xqc_request_stats_s {

uint64_t rate_limit;

/**
* @brief 0RTT state
* 0: no 0RTT
* 1: 0RTT accept
* 2: 0RTT reject
*/
uint8_t early_data_state;

char stream_info[XQC_STREAM_INFO_LEN];
} xqc_request_stats_t;

Expand Down
43 changes: 28 additions & 15 deletions include/xquic/xquic.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ typedef enum xqc_proto_version_s {

#define XQC_DGRAM_RETX_ASKED_BY_APP 1

#define XQC_CO_MAX_NUM 16
#define XQC_CO_STR_MAX_LEN (5 * XQC_CO_MAX_NUM)


/**
* @brief get timestamp callback function. this might be useful on different platforms
Expand Down Expand Up @@ -1263,6 +1266,19 @@ typedef struct xqc_conn_settings_s {
uint8_t protect_pool_mem;
#endif

char conn_option_str[XQC_CO_STR_MAX_LEN];

/**
* @brief intial_rtt (us). Default: 0 (use the internal default value -- 250000)
*
*/
xqc_usec_t initial_rtt;
/**
* @brief initial pto duration (us). Default: 0 (use the internal default value -- 3xinitial_rtt)
*
*/
xqc_usec_t initial_pto_duration;

} xqc_conn_settings_t;


Expand Down Expand Up @@ -1335,6 +1351,11 @@ typedef struct xqc_conn_stats_s {
char alpn[XQC_MAX_ALPN_BUF_LEN];
} xqc_conn_stats_t;

typedef struct xqc_conn_qos_stats_s {
xqc_usec_t srtt; /* smoothed SRTT at present: initial value = 250000 */
xqc_usec_t min_rtt; /* minimum RTT until now: initial value = 0xFFFFFFFF */
uint64_t inflight_bytes; /* initial value = 0 */
} xqc_conn_qos_stats_t;

/*************************************************************
* engine layer APIs
Expand Down Expand Up @@ -1400,29 +1421,14 @@ xqc_int_t xqc_engine_unregister_alpn(xqc_engine_t *engine, const char *alpn, siz
* Pass received UDP packet payload into xquic engine.
* @param recv_time UDP packet received time in microsecond
* @param user_data connection user_data, server is NULL
* @param path_id XQC_UNKNOWN_PATH_ID = unknown path (only use cid to identify the path)
*/

#ifdef XQC_NO_PID_PACKET_PROCESS

XQC_EXPORT_PUBLIC_API
xqc_int_t xqc_engine_packet_process(xqc_engine_t *engine,
const unsigned char *packet_in_buf, size_t packet_in_size,
const struct sockaddr *local_addr, socklen_t local_addrlen,
const struct sockaddr *peer_addr, socklen_t peer_addrlen,
xqc_usec_t recv_time, void *user_data);

#else

XQC_EXPORT_PUBLIC_API
xqc_int_t xqc_engine_packet_process(xqc_engine_t *engine,
const unsigned char *packet_in_buf, size_t packet_in_size,
const struct sockaddr *local_addr, socklen_t local_addrlen,
const struct sockaddr *peer_addr, socklen_t peer_addrlen,
uint64_t path_id, xqc_usec_t recv_time, void *user_data);

#endif


/**
* @brief Process all connections, application implements MUST call this function in timer callback
Expand Down Expand Up @@ -1817,6 +1823,13 @@ void xqc_conn_continue_send_by_conn(xqc_connection_t *conn);
XQC_EXPORT_PUBLIC_API
xqc_conn_stats_t xqc_conn_get_stats(xqc_engine_t *engine, const xqc_cid_t *cid);


/**
* User can get xqc_conn_qos_stats_t by cid
*/
XQC_EXPORT_PUBLIC_API
xqc_conn_qos_stats_t xqc_conn_get_qos_stats(xqc_engine_t *engine, const xqc_cid_t *cid);

/**
* create new path for client
* @param cid scid for connection
Expand Down
58 changes: 58 additions & 0 deletions include/xquic/xquic_typedef.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ typedef struct xqc_path_ctx_s xqc_path_ctx_t;
typedef struct xqc_timer_manager_s xqc_timer_manager_t;
typedef struct xqc_h3_ext_bytestream_s xqc_h3_ext_bytestream_t;
typedef struct xqc_ping_record_s xqc_ping_record_t;
typedef struct xqc_conn_qos_stats_s xqc_conn_qos_stats_t;

typedef uint64_t xqc_msec_t; /* store millisecond values */
typedef uint64_t xqc_usec_t; /* store microsecond values */
Expand Down Expand Up @@ -221,4 +222,61 @@ typedef struct xqc_stream_settings_s {
uint64_t recv_rate_bytes_per_sec;
} xqc_stream_settings_t;

#define XQC_CO_TAG(a, b, c, d) (uint32_t)((a << 24) + (b << 16) + (c << 8) + d)

typedef enum xqc_conn_option_e {
XQC_CO_TBBR = XQC_CO_TAG('T', 'B', 'B', 'R'), // Reduced Buffer Bloat TCP
XQC_CO_1RTT = XQC_CO_TAG('1', 'R', 'T', 'T'), // STARTUP in BBR for 1 RTT
XQC_CO_2RTT = XQC_CO_TAG('2', 'R', 'T', 'T'), // STARTUP in BBR for 2 RTTs
XQC_CO_BBR4 = XQC_CO_TAG('B', 'B', 'R', '4'), // 20 RTT ack aggregation
XQC_CO_BBR5 = XQC_CO_TAG('B', 'B', 'R', '5'), // 40 RTT ack aggregation
XQC_CO_IW03 = XQC_CO_TAG('I', 'W', '0', '3'), // Force ICWND to 3
XQC_CO_IW10 = XQC_CO_TAG('I', 'W', '1', '0'), // Force ICWND to 10
XQC_CO_IW20 = XQC_CO_TAG('I', 'W', '2', '0'), // Force ICWND to 20
XQC_CO_IW50 = XQC_CO_TAG('I', 'W', '5', '0'), // Force ICWND to 50
XQC_CO_B2ON = XQC_CO_TAG('B', '2', 'O', 'N'), // Enable BBRv2
XQC_CO_COPA = XQC_CO_TAG('C', 'O', 'P', 'A'), // Enable COPA
XQC_CO_C2ON = XQC_CO_TAG('C', '2', 'O', 'N'), // Enable CopaV2
XQC_CO_QBIC = XQC_CO_TAG('Q', 'B', 'I', 'C'), // TCP Cubic
XQC_CO_RENO = XQC_CO_TAG('R', 'E', 'N', 'O'), // Enable reno
XQC_CO_SPRI = XQC_CO_TAG('S', 'P', 'R', 'I'), // enable stream priority by streamid
XQC_CO_9218 = XQC_CO_TAG('9', '2', '1', '8'), // enable stream priority by rfc9218
XQC_CO_D218 = XQC_CO_TAG('D', '2', '1', '8'), // disable rfc9218
XQC_CO_DRST = XQC_CO_TAG('D', 'R', 'S', 'T'), // disable cease sending stream
XQC_CO_CBBR = XQC_CO_TAG('C', 'B', 'B', 'R'), // A global option to enable all the following options (Customized BBR)
XQC_CO_BNLS = XQC_CO_TAG('B', 'N', 'L', 'S'), // Force BBR not to respond on losses during STARTUP
XQC_CO_BACG = XQC_CO_TAG('B', 'A', 'C', 'G'), // Use Adaptive CWND_GAIN in BBR
XQC_CO_CG03 = XQC_CO_TAG('C', 'G', '0', '3'), // Use 3 for CWND_GAIN in BBR
XQC_CO_CG05 = XQC_CO_TAG('C', 'G', '0', '5'), // Use 5 for CWND_GAIN in BBR
XQC_CO_CG10 = XQC_CO_TAG('C', 'G', '1', '0'), // Use 10 for CWND_GAIN in BBR
XQC_CO_CG20 = XQC_CO_TAG('C', 'G', '2', '0'), // Use 20 for CWND_GAIN in BBR
XQC_CO_PG11 = XQC_CO_TAG('P', 'G', '1', '1'), // Use 1.1 for PACING_GAIN in BBR PROBE_UP
XQC_CO_PG15 = XQC_CO_TAG('P', 'G', '1', '5'), // Use 1.5 for PACING_GAIN in BBR PROBE_UP
XQC_CO_BNLR = XQC_CO_TAG('B', 'N', 'L', 'R'), // Disable BBR's loss recovery state
XQC_CO_MW10 = XQC_CO_TAG('M', 'W', '1', '0'), // Set min CWND to 10
XQC_CO_MW20 = XQC_CO_TAG('M', 'W', '2', '0'), // Set min CWND to 20
XQC_CO_MW32 = XQC_CO_TAG('M', 'W', '3', '2'), // Set min CWND to 32
XQC_CO_MW50 = XQC_CO_TAG('M', 'W', '5', '0'), // Set min CWND to 50
XQC_CO_WL20 = XQC_CO_TAG('W', 'L', '2', '0'), // Set BW window length to 20 (RTTs)
XQC_CO_WL30 = XQC_CO_TAG('W', 'L', '3', '0'), // Set BW window length to 30 (RTTs)
XQC_CO_WL40 = XQC_CO_TAG('W', 'L', '4', '0'), // Set BW window length to 40 (RTTs)
XQC_CO_WL50 = XQC_CO_TAG('W', 'L', '5', '0'), // Set BW window length to 50 (RTTs)
XQC_CO_PR02 = XQC_CO_TAG('P', 'R', '0', '2'), // Set the target CWND in ProbeRTT to 0.2xBDP
XQC_CO_PR03 = XQC_CO_TAG('P', 'R', '0', '3'), // Set the target CWND in ProbeRTT to 0.3xBDP
XQC_CO_PR04 = XQC_CO_TAG('P', 'R', '0', '4'), // Set the target CWND in ProbeRTT to 0.4xBDP
XQC_CO_PR05 = XQC_CO_TAG('P', 'R', '0', '5'), // Set the target CWND in ProbeRTT to 0.5xBDP
XQC_CO_PR06 = XQC_CO_TAG('P', 'R', '0', '6'), // Set the target CWND in ProbeRTT to 0.6xBDP
XQC_CO_PR07 = XQC_CO_TAG('P', 'R', '0', '7'), // Set the target CWND in ProbeRTT to 0.7xBDP
XQC_CO_ENWC = XQC_CO_TAG('E', 'N', 'W', 'C'), // Enable CWND compensation according to jitter
XQC_CO_JW10 = XQC_CO_TAG('J', 'W', '1', '0'), // Set the window length of max jitter filter to 10xRTT (default)
XQC_CO_JW20 = XQC_CO_TAG('J', 'W', '2', '0'), // Set the window length of max jitter filter to 20xRTT
XQC_CO_JW30 = XQC_CO_TAG('J', 'W', '3', '0'), // Set the window length of max jitter filter to 30xRTT
XQC_CO_JW40 = XQC_CO_TAG('J', 'W', '4', '0'), // Set the window length of max jitter filter to 40xRTT
XQC_CO_JW50 = XQC_CO_TAG('J', 'W', '5', '0'), // Set the window length of max jitter filter to 50xRTT
XQC_CO_SL03 = XQC_CO_TAG('S', 'L', '0', '3'), // Set the STARTUP loss rate threshold to 0.03
XQC_CO_SL04 = XQC_CO_TAG('S', 'L', '0', '4'), // Set the STARTUP loss rate threshold to 0.04
XQC_CO_SL05 = XQC_CO_TAG('S', 'L', '0', '5'), // Set the STARTUP loss rate threshold to 0.05
XQC_CO_SL10 = XQC_CO_TAG('S', 'L', '1', '0'), // Set the STARTUP loss rate threshold to 0.05
} xqc_conn_option_t;

#endif /*_XQUIC_TYPEDEF_H_INCLUDED_*/
26 changes: 19 additions & 7 deletions scripts/case_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,22 @@ fi
grep_err_log


clear_log
echo -e "empty header value ...\c"
${CLIENT_BIN} -x 47 -1 -n 10 >> stdlog
result=`grep -E "test_result_speed:.*request_cnt: 10." stdlog`
errlog=`grep_err_log`
if [ -n "$result" ] && [ -z "$errlog" ]; then
echo ">>>>>>>> pass:1"
case_print_result "empty_header_value" "pass"
else
echo ">>>>>>>> pass:0"
case_print_result "empty_header_value" "fail"
exit 1
fi
grep_err_log


clear_log
rm -f test_session
echo -e "NULL stream callback ...\c"
Expand Down Expand Up @@ -819,7 +835,7 @@ grep_err_log|grep -v xqc_h3_stream_send_headers

clear_log
echo -e "send 1K data ...\c"
result=`${CLIENT_BIN} -s 1024 -l d -t 1 -E|grep ">>>>>>>> pass"`
result=`${CLIENT_BIN} -s 1024 -l d -t 1 -E --conn_options CBBR|grep ">>>>>>>> pass"`
errlog=`grep_err_log`
echo "$result"
if [ -z "$errlog" ] && [ "$result" == ">>>>>>>> pass:1" ]; then
Expand Down Expand Up @@ -4126,13 +4142,11 @@ rm -rf tp_localhost test_session xqc_token
clear_log
echo -e "freeze path0 ...\c"
sudo ${CLIENT_BIN} -s 1024000 -l d -E -e 4 -T 2 --epoch_timeout 2000000 -t 4 -M -i lo -i lo -x 107 > stdlog
stream_info3=`grep "stream_info:" stdlog | head -n 3 | tail -n 1 | grep -v "#0" | grep "#1"`
stream_info5=`grep "stream_info:" stdlog | tail -n 1 | grep -E "#0.*#1"`
clog_res1=`grep -E "path:0.*app_path_status:2->3" clog`
clog_res2=`grep -E "path:0.*app_path_status:3->1" clog`
slog_res1=`grep -E "path:0.*app_path_status:2->3" slog`
slog_res2=`grep -E "path:0.*app_path_status:3->1" slog`
if [ -n "$stream_info3" ] && [ -n "$stream_info5" ] && [ -n "$clog_res1" ] && [ -n "$clog_res2" ] && [ -n "$slog_res1" ] && [ -n "$slog_res2" ] ; then
if [ -n "$clog_res1" ] && [ -n "$clog_res2" ] && [ -n "$slog_res1" ] && [ -n "$slog_res2" ] ; then
echo ">>>>>>>> pass:1"
case_print_result "freeze_path0" "pass"
else
Expand All @@ -4144,13 +4158,11 @@ rm -rf tp_localhost test_session xqc_token
clear_log
echo -e "freeze path1 ...\c"
sudo ${CLIENT_BIN} -s 1024000 -l d -E -e 4 -T 2 --epoch_timeout 2000000 -t 4 -M -i lo -i lo -x 108 > stdlog
stream_info3=`grep "stream_info:" stdlog | head -n 3 | tail -n 1 | grep -v "#1" | grep "#0"`
stream_info5=`grep "stream_info:" stdlog | tail -n 1 | grep -E "#0.*#1"`
clog_res1=`grep -E "path:1.*app_path_status:2->3" clog`
clog_res2=`grep -E "path:1.*app_path_status:3->1" clog`
slog_res1=`grep -E "path:1.*app_path_status:2->3" slog`
slog_res2=`grep -E "path:1.*app_path_status:3->1" slog`
if [ -n "$stream_info3" ] && [ -n "$stream_info5" ] && [ -n "$clog_res1" ] && [ -n "$clog_res2" ] && [ -n "$slog_res1" ] && [ -n "$slog_res2" ] ; then
if [ -n "$clog_res1" ] && [ -n "$clog_res2" ] && [ -n "$slog_res1" ] && [ -n "$slog_res2" ] ; then
echo ">>>>>>>> pass:1"
case_print_result "freeze_path1" "pass"
else
Expand Down
2 changes: 1 addition & 1 deletion src/common/utils/ringmem/xqc_ring_mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ xqc_ring_mem_undo(xqc_ring_mem_t *rmem, xqc_ring_mem_idx_t idx, size_t len)
int
xqc_ring_mem_cmp(xqc_ring_mem_t *rmem, xqc_ring_mem_idx_t idx, uint8_t *data, size_t len)
{
if (idx < rmem->sidx || idx + len > rmem->eidx) {
if (idx < rmem->sidx || idx + len > rmem->eidx || len == 0) {
return -XQC_EPARAM;
}

Expand Down
12 changes: 12 additions & 0 deletions src/common/xqc_algorithm.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,16 @@ xqc_uint32_list_find(const uint32_t *list, size_t count, uint32_t target)
return -1;
}

static inline uint64_t
xqc_uint64_bounded_subtract(uint64_t a, uint64_t b)
{
return a > b ? a - b : 0;
}

static inline uint32_t
xqc_uint32_bounded_subtract(uint32_t a, uint32_t b)
{
return a > b ? a - b : 0;
}

#endif /* XQC_ALGORITHM_H_INCLUDED */
11 changes: 11 additions & 0 deletions src/common/xqc_str.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,5 +95,16 @@ xqc_memeq(const void *s1, const void *s2, size_t n)
return n == 0 || memcmp(s1, s2, n) == 0;
}

inline static xqc_bool_t
xqc_char_is_letter_or_number(char c)
{
if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')
|| (c >= '0' && c <= '9'))
{
return XQC_TRUE;
}
return XQC_FALSE;
}


#endif /*_XQC_STR_H_INCLUDED_*/
Loading

0 comments on commit 3607442

Please sign in to comment.