Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[!] fix bugs and building error on ubuntu and macOS, add initial rtt #407

Merged
merged 8 commits into from
Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading