src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_str.h
src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_strm.c
src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_strm.h
+src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_unreachable.c
+src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_unreachable.h
src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_vec.c
src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_vec.h
src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_version.c
# QUIC support
AC_ARG_ENABLE([quic],
- AS_HELP_STRING([--enable-quic=auto|yes|no], [Support DoQ (needs libngtcp2 >= 0.8.0, gnutls >= 3.7.2) [default=auto]]),
+ AS_HELP_STRING([--enable-quic=auto|yes|no], [Support DoQ (needs libngtcp2 >= 0.10.0, gnutls >= 3.7.2) [default=auto]]),
[], [enable_quic=auto])
AS_CASE([$enable_quic],
- [auto], [PKG_CHECK_MODULES([libngtcp2], [libngtcp2 >= 0.8.0 libngtcp2_crypto_gnutls], [enable_quic=yes], [enable_quic=no])],
- [yes], [PKG_CHECK_MODULES([libngtcp2], [libngtcp2 >= 0.8.0 libngtcp2_crypto_gnutls], [enable_quic=yes],
+ [auto], [PKG_CHECK_MODULES([libngtcp2], [libngtcp2 >= 0.10.0 libngtcp2_crypto_gnutls], [enable_quic=yes], [enable_quic=no])],
+ [yes], [PKG_CHECK_MODULES([libngtcp2], [libngtcp2 >= 0.10.0 libngtcp2_crypto_gnutls], [enable_quic=yes],
AS_IF([test "$gnutls_quic" = "yes"],
[enable_quic=embedded
embedded_libngtcp2_CFLAGS="-I\$(top_srcdir)/src/contrib/libngtcp2 -I\$(top_srcdir)/src/contrib/libngtcp2/ngtcp2/lib"
DNS-over-QUIC (DoQ) support in :doc:`knotd<man_knotd>`, :doc:`kxdpgun<man_kxdpgun>`,
and :doc:`kdig<man_kdig>`:
-* libngtcp2 >= 0.8.0 (or embedded one via `--enable-quic`)
+* libngtcp2 >= 0.10.0 (or embedded one via `--enable-quic`)
* gnutls >= 3.7.2
* :ref:`Mode XDP` (for knotd and kxdpgun)
contrib/libngtcp2/ngtcp2/lib/ngtcp2_str.h \
contrib/libngtcp2/ngtcp2/lib/ngtcp2_strm.c \
contrib/libngtcp2/ngtcp2/lib/ngtcp2_strm.h \
+ contrib/libngtcp2/ngtcp2/lib/ngtcp2_unreachable.c \
+ contrib/libngtcp2/ngtcp2/lib/ngtcp2_unreachable.h \
contrib/libngtcp2/ngtcp2/lib/ngtcp2_vec.c \
contrib/libngtcp2/ngtcp2/lib/ngtcp2_vec.h \
contrib/libngtcp2/ngtcp2/lib/ngtcp2_version.c \
#include <string.h>
#include <assert.h>
+#include "ngtcp2_unreachable.h"
+
ngtcp2_addr *ngtcp2_addr_init(ngtcp2_addr *dest, const ngtcp2_sockaddr *addr,
ngtcp2_socklen addrlen) {
dest->addrlen = addrlen;
memcmp(&ai->sin6_addr, &bi->sin6_addr, sizeof(ai->sin6_addr)) == 0;
}
default:
- assert(0);
- abort();
+ ngtcp2_unreachable();
}
}
return flags;
}
default:
- assert(0);
- abort();
+ ngtcp2_unreachable();
}
}
static const double pacing_gain_cycle[] = {1.25, 0.75, 1, 1, 1, 1, 1, 1};
-#define NGTCP2_BBR_GAIN_CYCLELEN \
- (sizeof(pacing_gain_cycle) / sizeof(pacing_gain_cycle[0]))
+#define NGTCP2_BBR_GAIN_CYCLELEN ngtcp2_arraylen(pacing_gain_cycle)
#define NGTCP2_BBR_HIGH_GAIN 2.89
#define NGTCP2_BBR_PROBE_RTT_DURATION (200 * NGTCP2_MILLISECONDS)
cc->packet_conservation = 0;
bbr_save_cwnd(cc, cstat);
- cstat->cwnd = 2 * cstat->max_udp_payload_size;
+ cstat->cwnd = 2 * cstat->max_tx_udp_payload_size;
}
void ngtcp2_cc_bbr_cc_on_ack_recv(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat,
if (cc->congestion_recovery_start_ts != UINT64_MAX) {
cc->in_loss_recovery = 1;
bbr_save_cwnd(cc, cstat);
- cstat->cwnd = cstat->bytes_in_flight +
- ngtcp2_max(ack->bytes_delivered, cstat->max_udp_payload_size);
+ cstat->cwnd =
+ cstat->bytes_in_flight +
+ ngtcp2_max(ack->bytes_delivered, cstat->max_tx_udp_payload_size);
cstat->congestion_recovery_start_ts = cc->congestion_recovery_start_ts;
cc->congestion_recovery_start_ts = UINT64_MAX;
(void)cc;
if (cstat->pacing_rate < 1.2 * 1024 * 1024 / 8 / NGTCP2_SECONDS) {
- cstat->send_quantum = cstat->max_udp_payload_size;
+ cstat->send_quantum = cstat->max_tx_udp_payload_size;
} else if (cstat->pacing_rate < 24.0 * 1024 * 1024 / 8 / NGTCP2_SECONDS) {
- cstat->send_quantum = cstat->max_udp_payload_size * 2;
+ cstat->send_quantum = cstat->max_tx_udp_payload_size * 2;
} else {
send_quantum =
(uint64_t)(cstat->pacing_rate * (double)(cstat->min_rtt == UINT64_MAX
}
cstat->send_quantum =
- ngtcp2_max(cstat->send_quantum, cstat->max_udp_payload_size * 10);
+ ngtcp2_max(cstat->send_quantum, cstat->max_tx_udp_payload_size * 10);
}
static uint64_t bbr_inflight(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat,
if (ack->bytes_lost > 0) {
if (cstat->cwnd > ack->bytes_lost) {
cstat->cwnd -= ack->bytes_lost;
- cstat->cwnd = ngtcp2_max(cstat->cwnd, 2 * cstat->max_udp_payload_size);
+ cstat->cwnd = ngtcp2_max(cstat->cwnd, 2 * cstat->max_tx_udp_payload_size);
} else {
- cstat->cwnd = cstat->max_udp_payload_size;
+ cstat->cwnd = 2 * cstat->max_tx_udp_payload_size;
}
}
ngtcp2_conn_stat *cstat) {
if (cc->state == NGTCP2_BBR_STATE_PROBE_RTT) {
cstat->cwnd =
- ngtcp2_min(cstat->cwnd, min_pipe_cwnd(cstat->max_udp_payload_size));
+ ngtcp2_min(cstat->cwnd, min_pipe_cwnd(cstat->max_tx_udp_payload_size));
}
}
}
cstat->cwnd =
- ngtcp2_max(cstat->cwnd, min_pipe_cwnd(cstat->max_udp_payload_size));
+ ngtcp2_max(cstat->cwnd, min_pipe_cwnd(cstat->max_tx_udp_payload_size));
}
bbr_modulate_cwnd_for_probe_rtt(cc, cstat);
cc->congestion_recovery_next_round_delivered = 0;
cc->in_loss_recovery = 0;
- cstat->send_quantum = cstat->max_udp_payload_size * 10;
+ cstat->send_quantum = cstat->max_tx_udp_payload_size * 10;
ngtcp2_window_filter_init(&cc->btl_bw_filter, NGTCP2_BBR_BTL_BW_FILTERLEN);
cc->rst->app_limited = app_limited ? app_limited : 1;
if (cc->probe_rtt_done_stamp == UINT64_MAX &&
- cstat->bytes_in_flight <= min_pipe_cwnd(cstat->max_udp_payload_size)) {
+ cstat->bytes_in_flight <= min_pipe_cwnd(cstat->max_tx_udp_payload_size)) {
cc->probe_rtt_done_stamp = ts + NGTCP2_BBR_PROBE_RTT_DURATION;
cc->probe_rtt_round_done = 0;
cc->next_round_delivered = cc->rst->delivered;
bbr_init_pacing_rate(bbr, cstat);
bbr_enter_startup(bbr);
- cstat->send_quantum = cstat->max_udp_payload_size * 10;
+ cstat->send_quantum = cstat->max_tx_udp_payload_size * 10;
/* Missing in documentation */
bbr->loss_round_start = 0;
return UINT64_MAX;
}
- headroom = ngtcp2_max(cstat->max_udp_payload_size,
+ headroom = ngtcp2_max(cstat->max_tx_udp_payload_size,
bbr->inflight_hi * NGTCP2_BBR_HEADROOM_NUMER /
NGTCP2_BBR_HEADROOM_DENOM);
- mpcwnd = min_pipe_cwnd(cstat->max_udp_payload_size);
+ mpcwnd = min_pipe_cwnd(cstat->max_tx_udp_payload_size);
if (bbr->inflight_hi > headroom) {
return ngtcp2_max(bbr->inflight_hi - headroom, mpcwnd);
static void bbr_raise_inflight_hi_slope(ngtcp2_bbr2_cc *bbr,
ngtcp2_conn_stat *cstat) {
- uint64_t growth_this_round = cstat->max_udp_payload_size
+ uint64_t growth_this_round = cstat->max_tx_udp_payload_size
<< bbr->bw_probe_up_rounds;
bbr->bw_probe_up_rounds = ngtcp2_min(bbr->bw_probe_up_rounds + 1, 30);
bbr->probe_up_cnt = ngtcp2_max(cstat->cwnd / growth_this_round, 1) *
- cstat->max_udp_payload_size;
+ cstat->max_tx_udp_payload_size;
}
static void bbr_probe_inflight_hi_upward(ngtcp2_bbr2_cc *bbr,
if (bbr->bw_probe_up_acks >= bbr->probe_up_cnt) {
delta = bbr->bw_probe_up_acks / bbr->probe_up_cnt;
bbr->bw_probe_up_acks -= delta * bbr->probe_up_cnt;
- bbr->inflight_hi += delta * cstat->max_udp_payload_size;
+ bbr->inflight_hi += delta * cstat->max_tx_udp_payload_size;
}
if (bbr->round_start) {
static int bbr_is_reno_coexistence_probe_time(ngtcp2_bbr2_cc *bbr,
ngtcp2_conn_stat *cstat) {
uint64_t reno_rounds =
- bbr_target_inflight(bbr, cstat) / cstat->max_udp_payload_size;
+ bbr_target_inflight(bbr, cstat) / cstat->max_tx_udp_payload_size;
return bbr->rounds_since_bw_probe >= ngtcp2_min(reno_rounds, 63);
}
if (app_limited) {
bbr->rst->app_limited = app_limited;
} else {
- bbr->rst->app_limited = cstat->max_udp_payload_size;
+ bbr->rst->app_limited = cstat->max_tx_udp_payload_size;
}
}
bbr_update_offload_budget(bbr, cstat);
inflight = ngtcp2_max(inflight, bbr->offload_budget);
- inflight = ngtcp2_max(inflight, min_pipe_cwnd(cstat->max_udp_payload_size));
+ inflight =
+ ngtcp2_max(inflight, min_pipe_cwnd(cstat->max_tx_udp_payload_size));
if (bbr->state == NGTCP2_BBR2_STATE_PROBE_BW_UP) {
- inflight += 2 * cstat->max_udp_payload_size;
+ inflight += 2 * cstat->max_tx_udp_payload_size;
}
return inflight;
if (ack->bytes_lost > 0) {
if (cstat->cwnd > ack->bytes_lost) {
cstat->cwnd -= ack->bytes_lost;
- cstat->cwnd = ngtcp2_max(cstat->cwnd, 2 * cstat->max_udp_payload_size);
+ cstat->cwnd = ngtcp2_max(cstat->cwnd, 2 * cstat->max_tx_udp_payload_size);
} else {
- cstat->cwnd = cstat->max_udp_payload_size;
+ cstat->cwnd = 2 * cstat->max_tx_udp_payload_size;
}
}
ngtcp2_conn_stat *cstat) {
uint64_t probe_rtt_cwnd =
bbr_bdp_multiple(bbr, bbr->bw, NGTCP2_BBR_PROBE_RTT_CWND_GAIN);
- uint64_t mpcwnd = min_pipe_cwnd(cstat->max_udp_payload_size);
+ uint64_t mpcwnd = min_pipe_cwnd(cstat->max_tx_udp_payload_size);
return ngtcp2_max(probe_rtt_cwnd, mpcwnd);
}
cstat->cwnd += ack->bytes_delivered;
}
- mpcwnd = min_pipe_cwnd(cstat->max_udp_payload_size);
+ mpcwnd = min_pipe_cwnd(cstat->max_tx_udp_payload_size);
cstat->cwnd = ngtcp2_max(cstat->cwnd, mpcwnd);
}
static void bbr_bound_cwnd_for_model(ngtcp2_bbr2_cc *bbr,
ngtcp2_conn_stat *cstat) {
uint64_t cap = UINT64_MAX;
- uint64_t mpcwnd = min_pipe_cwnd(cstat->max_udp_payload_size);
+ uint64_t mpcwnd = min_pipe_cwnd(cstat->max_tx_udp_payload_size);
if (bbr_is_in_probe_bw_state(bbr) &&
bbr->state != NGTCP2_BBR2_STATE_PROBE_BW_CRUISE) {
cstat->send_quantum = ngtcp2_min(send_quantum, 64 * 1024);
cstat->send_quantum =
- ngtcp2_max(cstat->send_quantum, cstat->max_udp_payload_size * 10);
+ ngtcp2_max(cstat->send_quantum, cstat->max_tx_udp_payload_size * 10);
}
static int in_congestion_recovery(const ngtcp2_conn_stat *cstat,
if (bbr->congestion_recovery_start_ts != UINT64_MAX) {
bbr->in_loss_recovery = 1;
bbr_save_cwnd(bbr, cstat);
- cstat->cwnd = cstat->bytes_in_flight +
- ngtcp2_max(ack->bytes_delivered, cstat->max_udp_payload_size);
+ cstat->cwnd =
+ cstat->bytes_in_flight +
+ ngtcp2_max(ack->bytes_delivered, cstat->max_tx_udp_payload_size);
cstat->congestion_recovery_start_ts = bbr->congestion_recovery_start_ts;
bbr->congestion_recovery_start_ts = UINT64_MAX;
bbr->packet_conservation = 0;
bbr_save_cwnd(bbr, cstat);
- cstat->cwnd = cstat->bytes_in_flight + cstat->max_udp_payload_size;
+ cstat->cwnd = cstat->bytes_in_flight + cstat->max_tx_udp_payload_size;
cstat->cwnd =
- ngtcp2_max(cstat->cwnd, min_pipe_cwnd(cstat->max_udp_payload_size));
+ ngtcp2_max(cstat->cwnd, min_pipe_cwnd(cstat->max_tx_udp_payload_size));
}
static void bbr2_cc_on_ack_recv(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat,
return;
}
- m = cstat->max_udp_payload_size * pkt->pktlen + cc->pending_add;
+ m = cstat->max_tx_udp_payload_size * pkt->pktlen + cc->pending_add;
cc->pending_add = m % cstat->cwnd;
cstat->cwnd += m / cstat->cwnd;
cstat->congestion_recovery_start_ts = ts;
cstat->cwnd >>= NGTCP2_LOSS_REDUCTION_FACTOR_BITS;
- min_cwnd = 2 * cstat->max_udp_payload_size;
+ min_cwnd = 2 * cstat->max_tx_udp_payload_size;
cstat->cwnd = ngtcp2_max(cstat->cwnd, min_cwnd);
cstat->ssthresh = cstat->cwnd;
(void)ccx;
(void)ts;
- cstat->cwnd = 2 * cstat->max_udp_payload_size;
+ cstat->cwnd = 2 * cstat->max_tx_udp_payload_size;
cstat->congestion_recovery_start_ts = UINT64_MAX;
}
if (cstat->min_rtt != UINT64_MAX && cc->max_delivery_rate_sec) {
target_cwnd = cc->max_delivery_rate_sec * cstat->min_rtt / NGTCP2_SECONDS;
- initcwnd = ngtcp2_cc_compute_initcwnd(cstat->max_udp_payload_size);
+ initcwnd = ngtcp2_cc_compute_initcwnd(cstat->max_tx_udp_payload_size);
cc->target_cwnd = ngtcp2_max(initcwnd, target_cwnd) * 289 / 100;
ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV,
if (cc->last_round_min_rtt != UINT64_MAX &&
cc->current_round_min_rtt != UINT64_MAX &&
- cstat->cwnd >= NGTCP2_HS_MIN_SSTHRESH * cstat->max_udp_payload_size &&
+ cstat->cwnd >=
+ NGTCP2_HS_MIN_SSTHRESH * cstat->max_tx_udp_payload_size &&
cc->rtt_sample_count >= NGTCP2_HS_N_RTT_SAMPLE) {
eta = cc->last_round_min_rtt / 8;
cc->epoch_start = ts;
if (cstat->cwnd < cc->w_last_max) {
cc->k = ngtcp2_cbrt((cc->w_last_max - cstat->cwnd) * 10 / 4 /
- cstat->max_udp_payload_size);
+ cstat->max_tx_udp_payload_size);
cc->origin_point = cc->w_last_max;
} else {
cc->k = 0;
time_delta = kx - tx;
}
- delta = cstat->max_udp_payload_size *
+ delta = cstat->max_tx_udp_payload_size *
((((time_delta * time_delta) >> 10) * time_delta) >> 10) * 4 / 10;
delta >>= 10;
}
if (target > cstat->cwnd) {
- m = cc->pending_add + cstat->max_udp_payload_size * (target - cstat->cwnd);
+ m = cc->pending_add +
+ cstat->max_tx_udp_payload_size * (target - cstat->cwnd);
add = m / cstat->cwnd;
cc->pending_add = m % cstat->cwnd;
} else {
- m = cc->pending_add + cstat->max_udp_payload_size;
+ m = cc->pending_add + cstat->max_tx_udp_payload_size;
add = m / (100 * cstat->cwnd);
cc->pending_add = m % (100 * cstat->cwnd);
}
- m = cc->pending_w_add + cstat->max_udp_payload_size * pkt->pktlen;
+ m = cc->pending_w_add + cstat->max_tx_udp_payload_size * pkt->pktlen;
cc->w_tcp += m / cstat->cwnd;
cc->pending_w_add = m % cstat->cwnd;
if (cc->w_tcp > cstat->cwnd) {
- tcp_add =
- cstat->max_udp_payload_size * (cc->w_tcp - cstat->cwnd) / cstat->cwnd;
+ tcp_add = cstat->max_tx_udp_payload_size * (cc->w_tcp - cstat->cwnd) /
+ cstat->cwnd;
if (tcp_add > add) {
add = tcp_add;
}
cc->w_last_max = cstat->cwnd;
}
- min_cwnd = 2 * cstat->max_udp_payload_size;
+ min_cwnd = 2 * cstat->max_tx_udp_payload_size;
cstat->ssthresh = cstat->cwnd * 7 / 10;
cstat->ssthresh = ngtcp2_max(cstat->ssthresh, min_cwnd);
cstat->cwnd = cstat->ssthresh;
(void)ccx;
(void)ts;
- cstat->cwnd = 2 * cstat->max_udp_payload_size;
+ cstat->cwnd = 2 * cstat->max_tx_udp_payload_size;
cstat->congestion_recovery_start_ts = UINT64_MAX;
}
if (cstat->min_rtt != UINT64_MAX && cc->max_delivery_rate_sec) {
target_cwnd = cc->max_delivery_rate_sec * cstat->min_rtt / NGTCP2_SECONDS;
- initcwnd = ngtcp2_cc_compute_initcwnd(cstat->max_udp_payload_size);
+ initcwnd = ngtcp2_cc_compute_initcwnd(cstat->max_tx_udp_payload_size);
cc->target_cwnd = ngtcp2_max(initcwnd, target_cwnd) * 289 / 100;
ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV,
#include "ngtcp2_addr.h"
#include "ngtcp2_path.h"
#include "ngtcp2_rcvry.h"
+#include "ngtcp2_unreachable.h"
/* NGTCP2_FLOW_WINDOW_RTT_FACTOR is the factor of RTT when flow
control window auto-tuning is triggered. */
cstat->pto_count = 0;
cstat->loss_detection_timer = UINT64_MAX;
cstat->cwnd =
- ngtcp2_cc_compute_initcwnd(conn->local.settings.max_udp_payload_size);
+ ngtcp2_cc_compute_initcwnd(conn->local.settings.max_tx_udp_payload_size);
cstat->ssthresh = UINT64_MAX;
cstat->congestion_recovery_start_ts = UINT64_MAX;
cstat->bytes_in_flight = 0;
case NGTCP2_ECN_STATE_FAILED:
break;
default:
- assert(0);
+ ngtcp2_unreachable();
}
}
assert(settings->max_window <= NGTCP2_MAX_VARINT);
assert(settings->max_stream_window <= NGTCP2_MAX_VARINT);
- assert(settings->max_udp_payload_size);
- assert(settings->max_udp_payload_size <= NGTCP2_HARD_MAX_UDP_PAYLOAD_SIZE);
+ assert(settings->max_tx_udp_payload_size);
+ assert(settings->max_tx_udp_payload_size <= NGTCP2_HARD_MAX_UDP_PAYLOAD_SIZE);
assert(params->active_connection_id_limit <= NGTCP2_MAX_DCID_POOL_SIZE);
assert(params->initial_max_data <= NGTCP2_MAX_VARINT);
assert(params->initial_max_stream_data_bidi_local <= NGTCP2_MAX_VARINT);
conn_reset_conn_stat(*pconn, &(*pconn)->cstat);
(*pconn)->cstat.initial_rtt = settings->initial_rtt;
- (*pconn)->cstat.max_udp_payload_size =
- (*pconn)->local.settings.max_udp_payload_size;
+ (*pconn)->cstat.max_tx_udp_payload_size =
+ (*pconn)->local.settings.max_tx_udp_payload_size;
ngtcp2_rst_init(&(*pconn)->rst);
}
break;
default:
- assert(0);
+ ngtcp2_unreachable();
}
rv = pktns_new(&(*pconn)->in_pktns, NGTCP2_PKTNS_ID_INITIAL, &(*pconn)->rst,
*/
static uint64_t conn_get_cwnd(ngtcp2_conn *conn) {
return conn->pv && (conn->pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE)
- ? ngtcp2_cc_compute_initcwnd(conn->cstat.max_udp_payload_size)
+ ? ngtcp2_cc_compute_initcwnd(conn->cstat.max_tx_udp_payload_size)
: conn->cstat.cwnd;
}
cc.hp_ctx = pktns->crypto.tx.hp_ctx;
break;
default:
- assert(0);
- abort();
+ ngtcp2_unreachable();
}
cc.aead = pktns->crypto.ctx.aead;
rv = conn_ppe_write_frame_hd_log(conn, &ppe, &hd_logged, &hd, &nfrc->fr);
if (rv != 0) {
- assert(0);
+ ngtcp2_unreachable();
}
*pfrc = nfrc;
ack_delay_exponent = conn->local.transport_params.ack_delay_exponent;
break;
default:
- assert(0);
- abort();
+ ngtcp2_unreachable();
}
if (!pktns->crypto.tx.ckm) {
ngtcp2_ssize res = 0, nwrite = 0;
/* In the most cases, client sends ACK in conn_write_handshake_pkt.
- This function is only called when it is CWND limited. It is not
- required for client to send ACK for server Initial. This is
- because once it gets server Initial, it gets Handshake tx key and
- discards Initial key. The only good reason to send ACK is give
- server RTT measurement early. */
+ This function is only called when it is CWND limited or pacing
+ limited. It is not required for client to send ACK for server
+ Initial. This is because once it gets server Initial, it gets
+ Handshake tx key and discards Initial key. The only good reason
+ to send ACK is give server RTT measurement early. */
if (conn->server && conn->in_pktns) {
nwrite =
conn_write_ack_pkt(conn, pi, dest, destlen, NGTCP2_PKT_INITIAL, ts);
break;
default:
/* Unreachable */
- assert(0);
+ ngtcp2_unreachable();
}
cc->encrypt = conn->callbacks.encrypt;
break;
case NGTCP2_FRAME_STREAM:
- assert(0);
- break;
+ ngtcp2_unreachable();
case NGTCP2_FRAME_MAX_STREAMS_BIDI:
if ((*pfrc)->fr.max_streams.max_streams <
conn->remote.bidi.max_streams) {
}
break;
case NGTCP2_FRAME_CRYPTO:
- assert(0);
- break;
+ ngtcp2_unreachable();
}
rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &(*pfrc)->fr);
rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &nfrc->fr);
if (rv != 0) {
- assert(0);
+ ngtcp2_unreachable();
}
*pfrc = nfrc;
rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &nfrc->fr);
if (rv != 0) {
- assert(0);
+ ngtcp2_unreachable();
}
*pfrc = nfrc;
rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &nfrc->fr);
if (rv != 0) {
- assert(0);
+ ngtcp2_unreachable();
}
*pfrc = nfrc;
calls ngtcp2_conn_writev_datagram again. */
break;
default:
- assert(0);
+ ngtcp2_unreachable();
}
}
break;
default:
/* We don't support 0-RTT packet in this function. */
- assert(0);
- abort();
+ ngtcp2_unreachable();
}
cc.aead = pktns->crypto.ctx.aead;
conn_update_keep_alive_last_ts(conn, ts);
}
- conn->tx.pacing.pktlen += (size_t)nwrite;
+ if (!padded) {
+ switch (fr->type) {
+ case NGTCP2_FRAME_ACK:
+ case NGTCP2_FRAME_ACK_ECN:
+ break;
+ default:
+ conn->tx.pacing.pktlen += (size_t)nwrite;
+ }
+ } else {
+ conn->tx.pacing.pktlen += (size_t)nwrite;
+ }
ngtcp2_qlog_metrics_updated(&conn->qlog, &conn->cstat);
assert(conn->remote.transport_params->max_udp_payload_size >=
NGTCP2_MAX_UDP_PAYLOAD_SIZE);
- hard_max_udp_payload_size =
- (size_t)ngtcp2_min(conn->remote.transport_params->max_udp_payload_size,
- (uint64_t)conn->local.settings.max_udp_payload_size);
+ hard_max_udp_payload_size = (size_t)ngtcp2_min(
+ conn->remote.transport_params->max_udp_payload_size,
+ (uint64_t)conn->local.settings.max_tx_udp_payload_size);
rv = ngtcp2_pmtud_new(&conn->pmtud, conn->dcid.current.max_udp_payload_size,
hard_max_udp_payload_size,
}
payloadlen =
- ngtcp2_min(payloadlen, conn->local.settings.max_udp_payload_size);
+ ngtcp2_min(payloadlen, conn->local.settings.max_tx_udp_payload_size);
- if (conn->local.settings.no_udp_payload_size_shaping) {
+ if (conn->local.settings.no_tx_udp_payload_size_shaping) {
return payloadlen;
}
case 4:
return 32;
default:
- assert(0);
- abort();
+ ngtcp2_unreachable();
}
}
}
break;
default:
- assert(0);
+ ngtcp2_unreachable();
}
if (payloadlen == 0) {
break;
default:
/* Unreachable */
- assert(0);
+ ngtcp2_unreachable();
}
} else {
rv = conn_verify_dcid(conn, &new_cid_used, &hd);
}
break;
default:
- assert(0);
- abort();
+ ngtcp2_unreachable();
}
return conn_recv_cpkt(conn, path, pi, pkt, pktlen, ts);
assert(vneg_other_versions_includes(conn->vneg.other_versions,
conn->vneg.other_versionslen,
conn->negotiated_version));
- } else if (conn->client_chosen_version != conn->negotiated_version ||
- conn->client_chosen_version !=
- conn->local.settings.original_version) {
+ } else if (conn->client_chosen_version != conn->negotiated_version) {
return NGTCP2_ERR_VERSION_NEGOTIATION_FAILURE;
}
/* When client reacted upon Version Negotiation */
if (conn->local.settings.original_version != conn->client_chosen_version) {
- assert(params->version_info_present);
+ if (!params->version_info_present) {
+ assert(conn->client_chosen_version == conn->negotiated_version);
+
+ /* QUIC v1 (and the supported draft versions) are treated
+ specially. If version_info is missing, no further validation
+ is necessary.
+ https://datatracker.ietf.org/doc/html/draft-ietf-quic-version-negotiation-10#section-8
+ */
+ if (conn->client_chosen_version == NGTCP2_PROTO_VER_V1 ||
+ (NGTCP2_PROTO_VER_DRAFT_MIN <= conn->client_chosen_version &&
+ conn->client_chosen_version <= NGTCP2_PROTO_VER_DRAFT_MAX)) {
+ return 0;
+ }
+
+ return NGTCP2_ERR_VERSION_NEGOTIATION_FAILURE;
+ }
/* Server choose original version after Version Negotiation.
Draft does not say this particular case, but this smells like
if (vmsg == NULL && cstat->bytes_in_flight < cstat->cwnd &&
conn->tx.strmq_nretrans == 0) {
- if (conn->local.settings.no_udp_payload_size_shaping) {
- undersized = (size_t)nwrite < conn->local.settings.max_udp_payload_size;
+ if (conn->local.settings.no_tx_udp_payload_size_shaping) {
+ undersized =
+ (size_t)nwrite < conn->local.settings.max_tx_udp_payload_size;
} else {
undersized = (size_t)nwrite < conn->dcid.current.max_udp_payload_size;
}
conn->rst.app_limited = conn->rst.delivered + cstat->bytes_in_flight;
if (conn->rst.app_limited == 0) {
- conn->rst.app_limited = cstat->max_udp_payload_size;
+ conn->rst.app_limited = cstat->max_tx_udp_payload_size;
}
}
}
pi->ecn = NGTCP2_ECN_NOT_ECT;
}
- if (!conn_pacing_pkt_tx_allowed(conn, ts)) {
- return 0;
- }
-
switch (conn->state) {
case NGTCP2_CS_CLIENT_INITIAL:
case NGTCP2_CS_CLIENT_WAIT_HANDSHAKE:
case NGTCP2_CS_CLIENT_TLS_HANDSHAKE_FAILED:
+ if (!conn_pacing_pkt_tx_allowed(conn, ts)) {
+ assert(!ppe_pending);
+
+ return conn_write_handshake_ack_pkts(conn, pi, dest, origlen, ts);
+ }
+
nwrite = conn_client_write_handshake(conn, pi, dest, destlen, vmsg, ts);
/* We might be unable to write a packet because of depletion of
congestion window budget, perhaps due to packet loss that
case NGTCP2_CS_SERVER_INITIAL:
case NGTCP2_CS_SERVER_WAIT_HANDSHAKE:
case NGTCP2_CS_SERVER_TLS_HANDSHAKE_FAILED:
+ if (!conn_pacing_pkt_tx_allowed(conn, ts)) {
+ assert(!ppe_pending);
+
+ if (!(conn->dcid.current.flags & NGTCP2_DCID_FLAG_PATH_VALIDATED)) {
+ server_tx_left = conn_server_tx_left(conn, &conn->dcid.current);
+ if (server_tx_left == 0) {
+ return 0;
+ }
+
+ origlen = (size_t)ngtcp2_min((uint64_t)origlen, server_tx_left);
+ }
+
+ return conn_write_handshake_ack_pkts(conn, pi, dest, origlen, ts);
+ }
+
if (!ppe_pending) {
if (!(conn->dcid.current.flags & NGTCP2_DCID_FLAG_PATH_VALIDATED)) {
server_tx_left = conn_server_tx_left(conn, &conn->dcid.current);
NGTCP2_DATAGRAM_OVERHEAD;
break;
default:
- assert(0);
+ ngtcp2_unreachable();
}
if (conn->in_pktns && write_datalen > 0) {
}
break;
case NGTCP2_CS_POST_HANDSHAKE:
+ if (!conn_pacing_pkt_tx_allowed(conn, ts)) {
+ assert(!ppe_pending);
+
+ if (conn->server &&
+ !(conn->dcid.current.flags & NGTCP2_DCID_FLAG_PATH_VALIDATED)) {
+ server_tx_left = conn_server_tx_left(conn, &conn->dcid.current);
+ if (server_tx_left == 0) {
+ return 0;
+ }
+
+ origlen = (size_t)ngtcp2_min((uint64_t)origlen, server_tx_left);
+ }
+
+ return conn_write_ack_pkt(conn, pi, dest, origlen, NGTCP2_PKT_1RTT, ts);
+ }
+
break;
case NGTCP2_CS_CLOSING:
return NGTCP2_ERR_CLOSING;
}
}
-void ngtcp2_conn_early_data_rejected(ngtcp2_conn *conn) {
+int ngtcp2_conn_early_data_rejected(ngtcp2_conn *conn) {
if (conn->flags & NGTCP2_CONN_FLAG_EARLY_DATA_REJECTED) {
- return;
+ return 0;
}
conn->flags |= NGTCP2_CONN_FLAG_EARLY_DATA_REJECTED;
conn_discard_early_data_state(conn);
+
+ if (conn->callbacks.early_data_rejected) {
+ return conn->callbacks.early_data_rejected(conn, conn->user_data);
+ }
+
+ return 0;
+}
+
+int ngtcp2_conn_get_early_data_rejected(ngtcp2_conn *conn) {
+ return (conn->flags & NGTCP2_CONN_FLAG_EARLY_DATA_REJECTED) != 0;
}
int ngtcp2_conn_update_rtt(ngtcp2_conn *conn, ngtcp2_duration rtt,
ngtcp2_pktns *pktns = conn->in_pktns;
size_t i;
- for (i = 0; i < sizeof(ns) / sizeof(ns[0]); ++i) {
+ for (i = 0; i < ngtcp2_arraylen(ns); ++i) {
if (ns[i] == NULL || loss_time[i] >= earliest_loss_time) {
continue;
}
return &conn->dcid.current.ps.path;
}
-size_t ngtcp2_conn_get_max_udp_payload_size(ngtcp2_conn *conn) {
- return conn->local.settings.max_udp_payload_size;
+size_t ngtcp2_conn_get_max_tx_udp_payload_size(ngtcp2_conn *conn) {
+ return conn->local.settings.max_tx_udp_payload_size;
}
-size_t ngtcp2_conn_get_path_max_udp_payload_size(ngtcp2_conn *conn) {
- if (conn->local.settings.no_udp_payload_size_shaping) {
- return ngtcp2_conn_get_max_udp_payload_size(conn);
+size_t ngtcp2_conn_get_path_max_tx_udp_payload_size(ngtcp2_conn *conn) {
+ if (conn->local.settings.no_tx_udp_payload_size_shaping) {
+ return ngtcp2_conn_get_max_tx_udp_payload_size(conn);
}
return conn->dcid.current.max_udp_payload_size;
}
void ngtcp2_conn_update_pkt_tx_time(ngtcp2_conn *conn, ngtcp2_tstamp ts) {
+ double pacing_rate;
+ ngtcp2_duration interval;
+
if (conn->tx.pacing.pktlen == 0) {
return;
}
if (conn->cstat.pacing_rate > 0) {
- conn->tx.pacing.next_ts =
- ts + (ngtcp2_duration)((double)conn->tx.pacing.pktlen /
- conn->cstat.pacing_rate);
+ pacing_rate = conn->cstat.pacing_rate;
} else {
- double pacing_rate =
- (double)conn->cstat.cwnd / (double)(conn->cstat.min_rtt != UINT64_MAX
- ? conn->cstat.min_rtt
- : NGTCP2_MILLISECONDS);
- conn->tx.pacing.next_ts =
- ts + (ngtcp2_duration)((double)conn->tx.pacing.pktlen / pacing_rate);
+ /* 1.25 is the under-utilization avoidance factor described in
+ https://datatracker.ietf.org/doc/html/rfc9002#section-7.7 */
+ pacing_rate =
+ (double)conn->cstat.cwnd / (double)conn->cstat.smoothed_rtt * 1.25;
}
+ interval = (ngtcp2_duration)((double)conn->tx.pacing.pktlen / pacing_rate);
+
+ conn->tx.pacing.next_ts = ts + interval;
conn->tx.pacing.pktlen = 0;
}
size_t i;
if (conn->dcid.retire_unacked.len >=
- sizeof(conn->dcid.retire_unacked.seqs) /
- sizeof(conn->dcid.retire_unacked.seqs[0])) {
+ ngtcp2_arraylen(conn->dcid.retire_unacked.seqs)) {
return NGTCP2_ERR_CONNECTION_ID_LIMIT;
}
/* Make sure that we do not have a duplicate */
for (i = 0; i < conn->dcid.retire_unacked.len; ++i) {
if (conn->dcid.retire_unacked.seqs[i] == seq) {
- assert(0);
+ ngtcp2_unreachable();
}
}
settings->cc_algo = NGTCP2_CC_ALGO_CUBIC;
settings->initial_rtt = NGTCP2_DEFAULT_INITIAL_RTT;
settings->ack_thresh = 2;
- settings->max_udp_payload_size = 1500 - 48;
+ settings->max_tx_udp_payload_size = 1500 - 48;
settings->handshake_timeout = NGTCP2_DEFAULT_HANDSHAKE_TIMEOUT;
}
#include "ngtcp2_str.h"
#include "ngtcp2_pkt.h"
#include "ngtcp2_net.h"
+#include "ngtcp2_unreachable.h"
uint64_t ngtcp2_get_uint64(const uint8_t *p) {
uint64_t n;
n.b[0] &= 0x3f;
return ngtcp2_ntohl64(n.n64);
default:
- assert(0);
+ ngtcp2_unreachable();
}
return 0;
case 4:
return (int64_t)ngtcp2_get_uint32(p);
default:
- assert(0);
- abort();
+ ngtcp2_unreachable();
}
}
ngtcp2_put_uint32be(p, (uint32_t)pkt_num);
return p + 4;
default:
- assert(0);
- abort();
+ ngtcp2_unreachable();
}
}
#include "ngtcp2_vec.h"
#include "ngtcp2_macro.h"
#include "ngtcp2_conv.h"
+#include "ngtcp2_unreachable.h"
void ngtcp2_log_init(ngtcp2_log *log, const ngtcp2_cid *scid,
ngtcp2_printf log_printf, ngtcp2_tstamp ts,
log_fr_datagram(log, hd, &fr->datagram, dir);
break;
default:
- assert(0);
+ ngtcp2_unreachable();
}
}
*(PD) = (T); \
} while (0)
+/*
+ * ngtcp2_arraylen returns the number of elements in array |A|.
+ */
+#define ngtcp2_arraylen(A) (sizeof(A) / sizeof(A[0]))
+
#endif /* NGTCP2_MACRO_H */
#include "ngtcp2_cid.h"
#include "ngtcp2_mem.h"
#include "ngtcp2_vec.h"
+#include "ngtcp2_unreachable.h"
int ngtcp2_pkt_chain_new(ngtcp2_pkt_chain **ppc, const ngtcp2_path *path,
const ngtcp2_pkt_info *pi, const uint8_t *pkt,
break;
default:
/* Unreachable */
- assert(0);
+ ngtcp2_unreachable();
}
}
len += datalen;
break;
default:
- assert(0);
- abort();
+ ngtcp2_unreachable();
}
dest->type = type;
case NGTCP2_PKT_RETRY:
return NGTCP2_PKT_TYPE_RETRY_V2_DRAFT;
default:
- assert(0);
- abort();
+ ngtcp2_unreachable();
}
default:
/* Assume that unsupported versions share the numeric long packet
case NGTCP2_PKT_RETRY:
return NGTCP2_PKT_TYPE_RETRY_V1;
default:
- assert(0);
- abort();
+ ngtcp2_unreachable();
}
}
}
1492 - 48, /* PPPoE */
};
-static size_t mtu_probeslen = sizeof(mtu_probes) / sizeof(mtu_probes[0]);
+#define NGTCP2_MTU_PROBESLEN ngtcp2_arraylen(mtu_probes)
int ngtcp2_pmtud_new(ngtcp2_pmtud **ppmtud, size_t max_udp_payload_size,
size_t hard_max_udp_payload_size, int64_t tx_pkt_num,
pmtud->hard_max_udp_payload_size = hard_max_udp_payload_size;
pmtud->min_fail_udp_payload_size = SIZE_MAX;
- for (; pmtud->mtu_idx < mtu_probeslen; ++pmtud->mtu_idx) {
+ for (; pmtud->mtu_idx < NGTCP2_MTU_PROBESLEN; ++pmtud->mtu_idx) {
if (mtu_probes[pmtud->mtu_idx] > pmtud->hard_max_udp_payload_size) {
continue;
}
}
size_t ngtcp2_pmtud_probelen(ngtcp2_pmtud *pmtud) {
- assert(pmtud->mtu_idx < mtu_probeslen);
+ assert(pmtud->mtu_idx < NGTCP2_MTU_PROBESLEN);
return mtu_probes[pmtud->mtu_idx];
}
}
static void pmtud_next_probe(ngtcp2_pmtud *pmtud) {
- assert(pmtud->mtu_idx < mtu_probeslen);
+ assert(pmtud->mtu_idx < NGTCP2_MTU_PROBESLEN);
++pmtud->mtu_idx;
pmtud->num_pkts_sent = 0;
pmtud->expiry = UINT64_MAX;
- for (; pmtud->mtu_idx < mtu_probeslen; ++pmtud->mtu_idx) {
+ for (; pmtud->mtu_idx < NGTCP2_MTU_PROBESLEN; ++pmtud->mtu_idx) {
if (mtu_probes[pmtud->mtu_idx] <= pmtud->max_udp_payload_size ||
mtu_probes[pmtud->mtu_idx] > pmtud->hard_max_udp_payload_size) {
continue;
pmtud->max_udp_payload_size =
ngtcp2_max(pmtud->max_udp_payload_size, payloadlen);
- assert(pmtud->mtu_idx < mtu_probeslen);
+ assert(pmtud->mtu_idx < NGTCP2_MTU_PROBESLEN);
if (mtu_probes[pmtud->mtu_idx] > pmtud->max_udp_payload_size) {
return;
}
int ngtcp2_pmtud_finished(ngtcp2_pmtud *pmtud) {
- return pmtud->mtu_idx >= mtu_probeslen;
+ return pmtud->mtu_idx >= NGTCP2_MTU_PROBESLEN;
}
#include "ngtcp2_vec.h"
#include "ngtcp2_conv.h"
#include "ngtcp2_net.h"
+#include "ngtcp2_unreachable.h"
void ngtcp2_qlog_init(ngtcp2_qlog *qlog, ngtcp2_qlog_write write,
ngtcp2_tstamp ts, void *user_data) {
p = write_datagram_frame(p, &fr->datagram);
break;
default:
- assert(0);
+ ngtcp2_unreachable();
}
*p++ = ',';
#include "ngtcp2_cc.h"
#include "ngtcp2_rcvry.h"
#include "ngtcp2_rst.h"
+#include "ngtcp2_unreachable.h"
int ngtcp2_frame_chain_new(ngtcp2_frame_chain **pfrc, const ngtcp2_mem *mem) {
*pfrc = ngtcp2_mem_malloc(mem, sizeof(ngtcp2_frame_chain));
pktns = &conn->pktns;
break;
default:
- assert(0);
+ ngtcp2_unreachable();
}
conn_ack_crypto_data(conn, pktns, datalen);
ngtcp2_cc *cc = rtb->cc;
int rv;
uint64_t pkt_thres =
- rtb->cc_bytes_in_flight / cstat->max_udp_payload_size / 2;
+ rtb->cc_bytes_in_flight / cstat->max_tx_udp_payload_size / 2;
size_t ecn_pkt_lost = 0;
ngtcp2_tstamp start_ts;
ngtcp2_duration pto = ngtcp2_conn_compute_pto(conn, pktns);
--- /dev/null
+/*
+ * ngtcp2
+ *
+ * Copyright (c) 2022 ngtcp2 contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "ngtcp2_unreachable.h"
+
+#include <stdio.h>
+#include <errno.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#include <stdlib.h>
+#ifdef WIN32
+# include <io.h>
+#endif /* WIN32 */
+
+void ngtcp2_unreachable_fail(const char *file, int line, const char *func) {
+ char *buf;
+ size_t buflen;
+ int rv;
+
+#define NGTCP2_UNREACHABLE_TEMPLATE "%s:%d %s: Unreachable.\n"
+
+ rv = snprintf(NULL, 0, NGTCP2_UNREACHABLE_TEMPLATE, file, line, func);
+ if (rv < 0) {
+ abort();
+ }
+
+ /* here we explicitly use system malloc */
+ buflen = (size_t)rv + 1;
+ buf = malloc(buflen);
+ if (buf == NULL) {
+ abort();
+ }
+
+ rv = snprintf(buf, buflen, NGTCP2_UNREACHABLE_TEMPLATE, file, line, func);
+ if (rv < 0) {
+ abort();
+ }
+
+#ifndef WIN32
+ while (write(STDERR_FILENO, buf, (size_t)rv) == -1 && errno == EINTR)
+ ;
+#else /* WIN32 */
+ _write(_fileno(stderr), buf, (unsigned int)rv);
+#endif /* WIN32 */
+
+ free(buf);
+
+ abort();
+}
--- /dev/null
+/*
+ * ngtcp2
+ *
+ * Copyright (c) 2022 ngtcp2 contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef NGTCP2_UNREACHABLE_H
+#define NGTCP2_UNREACHABLE_H
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <ngtcp2/ngtcp2.h>
+
+#define ngtcp2_unreachable() \
+ ngtcp2_unreachable_fail(__FILE__, __LINE__, __func__)
+
+#ifdef _MSC_VER
+__declspec(noreturn)
+#endif /* _MSC_VER */
+ void ngtcp2_unreachable_fail(const char *file, int line, const char *func)
+#ifndef _MSC_VER
+ __attribute__((noreturn))
+#endif /* !_MSC_VER */
+ ;
+
+#endif /* NGTCP2_UNREACHABLE_H */
uint8_t stateless_reset_token[NGTCP2_STATELESS_RESET_TOKENLEN];
/**
* :member:`grease_quic_bit` is nonzero if sender supports "Greasing
- * the QUIC Bit" extension. See
- * https://datatracker.ietf.org/doc/html/draft-ietf-quic-bit-grease.
- * Note that the local endpoint always enables greasing QUIC bit
- * regardless of this field value.
+ * the QUIC Bit" extension. See :rfc:`9287`. Note that the local
+ * endpoint always enables greasing QUIC bit regardless of this
+ * field value.
*/
uint8_t grease_quic_bit;
/**
*/
uint64_t bytes_in_flight;
/**
- * :member:`max_udp_payload_size` is the maximum size of UDP
+ * :member:`max_tx_udp_payload_size` is the maximum size of UDP
* datagram payload that this endpoint transmits. It is used by
* congestion controller to compute congestion window.
*/
- size_t max_udp_payload_size;
+ size_t max_tx_udp_payload_size;
/**
* :member:`delivery_rate_sec` is the current sending rate measured
* in byte per second.
*/
ngtcp2_printf log_printf;
/**
- * :member:`max_udp_payload_size` is the maximum size of UDP
+ * :member:`max_tx_udp_payload_size` is the maximum size of UDP
* datagram payload that this endpoint transmits. It is used by
* congestion controller to compute congestion window.
*/
- size_t max_udp_payload_size;
+ size_t max_tx_udp_payload_size;
/**
* :member:`token` is a token from Retry packet or NEW_TOKEN frame.
*
*/
size_t ack_thresh;
/**
- * :member:`no_udp_payload_size_shaping`, if set to nonzero,
+ * :member:`no_tx_udp_payload_size_shaping`, if set to nonzero,
* instructs the library not to limit the UDP payload size to
* :macro:`NGTCP2_MAX_UDP_PAYLOAD_SIZE` (which can be extended by
* Path MTU Discovery) and instead use the mininum size among the
- * given buffer size, :member:`max_udp_payload_size`, and the
+ * given buffer size, :member:`max_tx_udp_payload_size`, and the
* received max_udp_payload QUIC transport parameter.
*/
- int no_udp_payload_size_shaping;
+ int no_tx_udp_payload_size_shaping;
/**
* :member:`handshake_timeout` is the period of time before giving
* up QUIC connection establishment. If QUIC handshake is not
typedef int (*ngtcp2_recv_key)(ngtcp2_conn *conn, ngtcp2_crypto_level level,
void *user_data);
+/**
+ * @functypedef
+ *
+ * :type:`ngtcp2_early_data_rejected` is invoked when early data was
+ * rejected by server, or client decided not to attempt early data.
+ *
+ * The callback function must return 0 if it succeeds. Returning
+ * :macro:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library call return
+ * immediately.
+ */
+typedef int (*ngtcp2_early_data_rejected)(ngtcp2_conn *conn, void *user_data);
+
#define NGTCP2_CALLBACKS_VERSION_V1 1
#define NGTCP2_CALLBACKS_VERSION NGTCP2_CALLBACKS_VERSION_V1
* :enum:`ngtcp2_crypto_level.NGTCP2_CRYPTO_LEVEL_INITIAL`.
*/
ngtcp2_recv_key recv_tx_key;
+ /**
+ * :member:`ngtcp2_early_data_rejected` is a callback function which
+ * is invoked when an attempt to send early data by client was
+ * rejected by server, or client decided not to attempt early data.
+ * This callback function is only used by client.
+ */
+ ngtcp2_early_data_rejected early_data_rejected;
} ngtcp2_callbacks;
/**
* handshake as well.
*
* |destlen| should be at least
- * :member:`ngtcp2_settings.max_udp_payload_size`.
+ * :member:`ngtcp2_settings.max_tx_udp_payload_size`.
*
* Specifying -1 to |stream_id| means no new stream data to send.
*
* as well.
*
* |destlen| should be at least
- * :member:`ngtcp2_settings.max_udp_payload_size`.
+ * :member:`ngtcp2_settings.max_tx_udp_payload_size`.
*
* For |path| and |pi| parameters, refer to
* `ngtcp2_conn_writev_stream`.
* @function
*
* `ngtcp2_conn_early_data_rejected` tells |conn| that early data was
- * rejected by a server. |conn| discards the following connection
- * states:
+ * rejected by a server, or client decided not to attempt early data
+ * for some reason. |conn| discards the following connection states:
*
* - Any opended streams.
* - Stream identifier allocations.
*
* Application which wishes to retransmit early data, it has to open
* streams and send stream data again.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :macro:`NGTCP2_ERR_CALLBACK_FAILURE`
+ * User callback failed
*/
-NGTCP2_EXTERN void ngtcp2_conn_early_data_rejected(ngtcp2_conn *conn);
+NGTCP2_EXTERN int ngtcp2_conn_early_data_rejected(ngtcp2_conn *conn);
+
+/**
+ * @function
+ *
+ * `ngtcp2_conn_get_early_data_rejected` returns nonzero if
+ * `ngtcp2_conn_early_data_rejected` has been called.
+ */
+NGTCP2_EXTERN int ngtcp2_conn_get_early_data_rejected(ngtcp2_conn *conn);
/**
* @function
/**
* @function
*
- * `ngtcp2_conn_get_max_udp_payload_size` returns the maximum UDP
+ * `ngtcp2_conn_get_max_tx_udp_payload_size` returns the maximum UDP
* payload size that this local endpoint would send. This is the
- * value of :member:`ngtcp2_settings.max_udp_payload_size` that is
+ * value of :member:`ngtcp2_settings.max_tx_udp_payload_size` that is
* passed to `ngtcp2_conn_client_new` or `ngtcp2_conn_server_new`.
*/
-NGTCP2_EXTERN size_t ngtcp2_conn_get_max_udp_payload_size(ngtcp2_conn *conn);
+NGTCP2_EXTERN size_t ngtcp2_conn_get_max_tx_udp_payload_size(ngtcp2_conn *conn);
/**
* @function
*
- * `ngtcp2_conn_get_path_max_udp_payload_size` returns the maximum UDP
- * payload size for the current path. If
- * :member:`ngtcp2_settings.no_udp_payload_size_shaping` is set to
+ * `ngtcp2_conn_get_path_max_tx_udp_payload_size` returns the maximum
+ * UDP payload size for the current path. If
+ * :member:`ngtcp2_settings.no_tx_udp_payload_size_shaping` is set to
* nonzero, this function is equivalent to
- * `ngtcp2_conn_get_max_udp_payload_size`. Otherwise, it returns the
- * maximum UDP payload size that is probed for the current path.
+ * `ngtcp2_conn_get_max_tx_udp_payload_size`. Otherwise, it returns
+ * the maximum UDP payload size that is probed for the current path.
*/
NGTCP2_EXTERN size_t
-ngtcp2_conn_get_path_max_udp_payload_size(ngtcp2_conn *conn);
+ngtcp2_conn_get_path_max_tx_udp_payload_size(ngtcp2_conn *conn);
/**
* @function
* * :type:`initial_rtt <ngtcp2_settings.initial_rtt>` =
* :macro:`NGTCP2_DEFAULT_INITIAL_RTT`
* * :type:`ack_thresh <ngtcp2_settings.ack_thresh>` = 2
- * * :type:`max_udp_payload_size
- * <ngtcp2_settings.max_udp_payload_size>` = 1452
+ * * :type:`max_tx_udp_payload_size
+ * <ngtcp2_settings.max_tx_udp_payload_size>` = 1452
* * :type:`handshake_timeout <ngtcp2_settings.handshake_timeout>` =
* :macro:`NGTCP2_DEFAULT_HANDSHAKE_TIMEOUT`.
*/
*
* Version number of the ngtcp2 library release.
*/
-#define NGTCP2_VERSION "0.9.0"
+#define NGTCP2_VERSION "0.10.0"
/**
* @macro
* number, 8 bits for minor and 8 bits for patch. Version 1.2.3
* becomes 0x010203.
*/
-#define NGTCP2_VERSION_NUM 0x000900
+#define NGTCP2_VERSION_NUM 0x000a00
#endif /* VERSION_H */