]> git.ipfire.org Git - thirdparty/knot-dns.git/commitdiff
libngtcp2: update embedded library to v1.18.0
authorDaniel Salzman <daniel.salzman@nic.cz>
Sun, 23 Nov 2025 15:59:21 +0000 (16:59 +0100)
committerDaniel Salzman <daniel.salzman@nic.cz>
Sun, 23 Nov 2025 15:59:21 +0000 (16:59 +0100)
33 files changed:
src/contrib/libngtcp2/ngtcp2/crypto/shared.c
src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_acktr.c
src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_addr.c
src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_bbr.c
src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_buf.c
src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_cc.c
src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_cc.h
src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_cid.c
src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conn.c
src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conn.h
src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_crypto.c
src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ksl.c
src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ksl.h
src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_log.c
src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_log.h
src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_map.c
src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_map.h
src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_path.c
src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_path.h
src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pcg.c
src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pkt.c
src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_qlog.c
src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rob.c
src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rst.c
src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rtb.c
src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_settings.h
src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_str.c
src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_str.h
src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_strm.c
src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_vec.c
src/contrib/libngtcp2/ngtcp2/ngtcp2.h
src/contrib/libngtcp2/ngtcp2/ngtcp2_crypto.h
src/contrib/libngtcp2/ngtcp2/version.h

index 98cd4de7e8097db7cfd9f6bec4bfde1552685e4f..062efb45e950cc4eb9ad3d48d37bf1f2f957f82d 100644 (file)
@@ -461,7 +461,9 @@ int ngtcp2_crypto_derive_and_install_tx_key(ngtcp2_conn *conn, uint8_t *key,
 
     if (ngtcp2_conn_is_server(conn) &&
         crypto_set_local_transport_params(conn, tls) != 0) {
-      goto fail;
+      /* Just return -1 because aead_ctx and hp_ctx are now owned by
+         conn. */
+      return -1;
     }
 
     break;
@@ -1305,13 +1307,22 @@ static size_t crypto_generate_regular_token_aad(uint8_t *dest,
   return addrlen;
 }
 
+/* NGTCP2_CRYPTO_MAX_REGULAR_TOKEN_DATALEN is the maximum length of
+   opaque data embedded in a regular token. */
+#define NGTCP2_CRYPTO_MAX_REGULAR_TOKEN_DATALEN 256
+
+/* NGTCP2_CRYPTO_MAX_REGULAR_TOKEN_PLAINTEXTLEN is the maximum length
+   of plaintext included in a regular token. */
+#define NGTCP2_CRYPTO_MAX_REGULAR_TOKEN_PLAINTEXTLEN                           \
+  (sizeof(ngtcp2_tstamp) + NGTCP2_CRYPTO_MAX_REGULAR_TOKEN_DATALEN)
+
 static const uint8_t regular_token_info_prefix[] = "regular_token";
 
-ngtcp2_ssize ngtcp2_crypto_generate_regular_token(
+static ngtcp2_ssize crypto_generate_regular_token(
   uint8_t *token, const uint8_t *secret, size_t secretlen,
   const ngtcp2_sockaddr *remote_addr, ngtcp2_socklen remote_addrlen,
-  ngtcp2_tstamp ts) {
-  uint8_t plaintext[sizeof(ngtcp2_tstamp)];
+  const void *data, size_t datalen, ngtcp2_tstamp ts) {
+  uint8_t plaintext[NGTCP2_CRYPTO_MAX_REGULAR_TOKEN_PLAINTEXTLEN];
   uint8_t rand_data[NGTCP2_CRYPTO_TOKEN_RAND_DATALEN];
   uint8_t key[16];
   uint8_t iv[12];
@@ -1328,9 +1339,18 @@ ngtcp2_ssize ngtcp2_crypto_generate_regular_token(
   int rv;
   (void)remote_addrlen;
 
+  if (datalen > NGTCP2_CRYPTO_MAX_REGULAR_TOKEN_DATALEN) {
+    return -1;
+  }
+
   memcpy(p, &ts_be, sizeof(ts_be));
   p += sizeof(ts_be);
 
+  if (datalen) {
+    memcpy(p, data, datalen);
+    p += datalen;
+  }
+
   plaintextlen = (size_t)(p - plaintext);
 
   if (ngtcp2_crypto_random(rand_data, sizeof(rand_data)) != 0) {
@@ -1378,13 +1398,11 @@ ngtcp2_ssize ngtcp2_crypto_generate_regular_token(
   return p - token;
 }
 
-int ngtcp2_crypto_verify_regular_token(const uint8_t *token, size_t tokenlen,
-                                       const uint8_t *secret, size_t secretlen,
-                                       const ngtcp2_sockaddr *remote_addr,
-                                       ngtcp2_socklen remote_addrlen,
-                                       ngtcp2_duration timeout,
-                                       ngtcp2_tstamp ts) {
-  uint8_t plaintext[sizeof(ngtcp2_tstamp)];
+static ngtcp2_ssize crypto_verify_regular_token(
+  void *data, size_t max_datalen, const uint8_t *token, size_t tokenlen,
+  const uint8_t *secret, size_t secretlen, const ngtcp2_sockaddr *remote_addr,
+  ngtcp2_socklen remote_addrlen, ngtcp2_duration timeout, ngtcp2_tstamp ts) {
+  uint8_t plaintext[NGTCP2_CRYPTO_MAX_REGULAR_TOKEN_PLAINTEXTLEN];
   uint8_t key[16];
   uint8_t iv[12];
   size_t keylen;
@@ -1397,13 +1415,14 @@ int ngtcp2_crypto_verify_regular_token(const uint8_t *token, size_t tokenlen,
   const uint8_t *rand_data;
   const uint8_t *ciphertext;
   size_t ciphertextlen;
+  size_t datalen;
   int rv;
   ngtcp2_tstamp gen_ts;
   (void)remote_addrlen;
 
-  if (tokenlen != NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN ||
+  if (tokenlen < NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN ||
       token[0] != NGTCP2_CRYPTO_TOKEN_MAGIC_REGULAR) {
-    return -1;
+    return NGTCP2_CRYPTO_ERR_UNREADABLE_TOKEN;
   }
 
   rand_data = token + tokenlen - NGTCP2_CRYPTO_TOKEN_RAND_DATALEN;
@@ -1413,6 +1432,10 @@ int ngtcp2_crypto_verify_regular_token(const uint8_t *token, size_t tokenlen,
   ngtcp2_crypto_aead_aes_128_gcm(&aead);
   ngtcp2_crypto_md_sha256(&md);
 
+  if (ciphertextlen > sizeof(plaintext) + aead.max_overhead) {
+    return NGTCP2_CRYPTO_ERR_UNREADABLE_TOKEN;
+  }
+
   keylen = ngtcp2_crypto_aead_keylen(&aead);
   ivlen = ngtcp2_crypto_aead_noncelen(&aead);
 
@@ -1423,13 +1446,13 @@ int ngtcp2_crypto_verify_regular_token(const uint8_t *token, size_t tokenlen,
                               rand_data, NGTCP2_CRYPTO_TOKEN_RAND_DATALEN,
                               regular_token_info_prefix,
                               sizeof(regular_token_info_prefix) - 1) != 0) {
-    return -1;
+    return NGTCP2_CRYPTO_ERR_INTERNAL;
   }
 
   aadlen = crypto_generate_regular_token_aad(aad, remote_addr);
 
   if (ngtcp2_crypto_aead_ctx_decrypt_init(&aead_ctx, &aead, key, ivlen) != 0) {
-    return -1;
+    return NGTCP2_CRYPTO_ERR_INTERNAL;
   }
 
   rv = ngtcp2_crypto_decrypt(plaintext, &aead, &aead_ctx, ciphertext,
@@ -1438,19 +1461,74 @@ int ngtcp2_crypto_verify_regular_token(const uint8_t *token, size_t tokenlen,
   ngtcp2_crypto_aead_ctx_free(&aead_ctx);
 
   if (rv != 0) {
-    return -1;
+    return NGTCP2_CRYPTO_ERR_UNREADABLE_TOKEN;
   }
 
   memcpy(&gen_ts, plaintext, sizeof(gen_ts));
 
   gen_ts = ngtcp2_ntohl64(gen_ts);
   if (gen_ts + timeout <= ts) {
+    return NGTCP2_CRYPTO_ERR_VERIFY_TOKEN;
+  }
+
+  if (max_datalen == 0) {
+    return 0;
+  }
+
+  datalen = ciphertextlen - aead.max_overhead - sizeof(gen_ts);
+  if (datalen > max_datalen) {
+    return 0;
+  }
+
+  memcpy(data, plaintext + sizeof(gen_ts), datalen);
+
+  return (ngtcp2_ssize)datalen;
+}
+
+ngtcp2_ssize ngtcp2_crypto_generate_regular_token(
+  uint8_t *token, const uint8_t *secret, size_t secretlen,
+  const ngtcp2_sockaddr *remote_addr, ngtcp2_socklen remote_addrlen,
+  ngtcp2_tstamp ts) {
+  return crypto_generate_regular_token(token, secret, secretlen, remote_addr,
+                                       remote_addrlen, NULL, 0, ts);
+}
+
+int ngtcp2_crypto_verify_regular_token(const uint8_t *token, size_t tokenlen,
+                                       const uint8_t *secret, size_t secretlen,
+                                       const ngtcp2_sockaddr *remote_addr,
+                                       ngtcp2_socklen remote_addrlen,
+                                       ngtcp2_duration timeout,
+                                       ngtcp2_tstamp ts) {
+  ngtcp2_ssize datalen =
+    crypto_verify_regular_token(NULL, 0, token, tokenlen, secret, secretlen,
+                                remote_addr, remote_addrlen, timeout, ts);
+
+  if (datalen < 0) {
     return -1;
   }
 
+  assert(0 == datalen);
+
   return 0;
 }
 
+ngtcp2_ssize ngtcp2_crypto_generate_regular_token2(
+  uint8_t *token, const uint8_t *secret, size_t secretlen,
+  const ngtcp2_sockaddr *remote_addr, ngtcp2_socklen remote_addrlen,
+  const void *data, size_t datalen, ngtcp2_tstamp ts) {
+  return crypto_generate_regular_token(token, secret, secretlen, remote_addr,
+                                       remote_addrlen, data, datalen, ts);
+}
+
+ngtcp2_ssize ngtcp2_crypto_verify_regular_token2(
+  void *data, size_t max_datalen, const uint8_t *token, size_t tokenlen,
+  const uint8_t *secret, size_t secretlen, const ngtcp2_sockaddr *remote_addr,
+  ngtcp2_socklen remote_addrlen, ngtcp2_duration timeout, ngtcp2_tstamp ts) {
+  return crypto_verify_regular_token(data, max_datalen, token, tokenlen, secret,
+                                     secretlen, remote_addr, remote_addrlen,
+                                     timeout, ts);
+}
+
 ngtcp2_ssize ngtcp2_crypto_write_connection_close(
   uint8_t *dest, size_t destlen, uint32_t version, const ngtcp2_cid *dcid,
   const ngtcp2_cid *scid, uint64_t error_code, const uint8_t *reason,
index 59bc621ef46b283f1b64b7d21530cfbb6ccc4cc0..0781f082e7b845a2037d4eb24f94f9a9d5ccba5d 100644 (file)
@@ -34,9 +34,11 @@ ngtcp2_objalloc_def(acktr_entry, ngtcp2_acktr_entry, oplent)
 
 static void acktr_entry_init(ngtcp2_acktr_entry *ent, int64_t pkt_num,
                              ngtcp2_tstamp tstamp) {
-  ent->pkt_num = pkt_num;
-  ent->len = 1;
-  ent->tstamp = tstamp;
+  *ent = (ngtcp2_acktr_entry){
+    .pkt_num = pkt_num,
+    .len = 1,
+    .tstamp = tstamp,
+  };
 }
 
 int ngtcp2_acktr_entry_objalloc_new(ngtcp2_acktr_entry **ent, int64_t pkt_num,
@@ -219,8 +221,10 @@ ngtcp2_acktr_ack_entry *ngtcp2_acktr_add_ack(ngtcp2_acktr *acktr,
                                              int64_t largest_ack) {
   ngtcp2_acktr_ack_entry *ent = ngtcp2_ringbuf_push_front(&acktr->acks.rb);
 
-  ent->largest_ack = largest_ack;
-  ent->pkt_num = pkt_num;
+  *ent = (ngtcp2_acktr_ack_entry){
+    .largest_ack = largest_ack,
+    .pkt_num = pkt_num,
+  };
 
   return ent;
 }
index a028a8a8f4045fd7529265fb51019a09104a1378..58694e3836e42ec6785e22d9604c082af52f114f 100644 (file)
 
 ngtcp2_addr *ngtcp2_addr_init(ngtcp2_addr *dest, const ngtcp2_sockaddr *addr,
                               ngtcp2_socklen addrlen) {
-  dest->addrlen = addrlen;
-  dest->addr = (ngtcp2_sockaddr *)addr;
+  *dest = (ngtcp2_addr){
+    .addr = (ngtcp2_sockaddr *)addr,
+    .addrlen = addrlen,
+  };
+
   return dest;
 }
 
index 62e6b2f125aafe9939f64b44b61cd8eab7d39a75..babf35bfdb68aa4cffeda254a9a8a7ebc6d3d66d 100644 (file)
@@ -1097,13 +1097,8 @@ static void bbr_check_probe_rtt_done(ngtcp2_cc_bbr *bbr,
 
 static void bbr_mark_connection_app_limited(ngtcp2_cc_bbr *bbr,
                                             ngtcp2_conn_stat *cstat) {
-  uint64_t app_limited = bbr->rst->delivered + cstat->bytes_in_flight;
-
-  if (app_limited) {
-    bbr->rst->app_limited = app_limited;
-  } else {
-    bbr->rst->app_limited = cstat->max_tx_udp_payload_size;
-  }
+  bbr->rst->app_limited =
+    ngtcp2_max_uint64(bbr->rst->delivered + cstat->bytes_in_flight, 1);
 }
 
 static void bbr_exit_probe_rtt(ngtcp2_cc_bbr *bbr, ngtcp2_tstamp ts) {
index bf4273f816a8103987b724e4c8368863e9eb527a..083a766281b2990dc88068fc4650c211d5f72626 100644 (file)
 #include "ngtcp2_mem.h"
 
 void ngtcp2_buf_init(ngtcp2_buf *buf, uint8_t *begin, size_t len) {
-  buf->begin = buf->pos = buf->last = begin;
-  buf->end = begin + len;
+  *buf = (ngtcp2_buf){
+    .begin = begin,
+    .end = begin + len,
+    .pos = begin,
+    .last = begin,
+  };
 }
 
 void ngtcp2_buf_reset(ngtcp2_buf *buf) { buf->pos = buf->last = buf->begin; }
index f8e420ed7d8ea6b28387bdadb41159e08f8e634d..73dfde6904b93d7b001aa679da47d0fb44c3c8b7 100644 (file)
@@ -261,7 +261,6 @@ uint64_t ngtcp2_cbrt(uint64_t n) {
   y <<= 1;
   b = 3 * y * (y + 1) + 1;
   if (n >= b) {
-    n -= b;
     y++;
   }
 
index 010a1c3541d51b55c585349804848dc7086f3168..a19e90b1d0db47dce15b5013919a027a747e56e9 100644 (file)
@@ -184,20 +184,12 @@ typedef void (*ngtcp2_cc_on_ack_recv)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
  * @functypedef
  *
  * :type:`ngtcp2_cc_on_pkt_sent` is a callback function which is
- * called when an ack-eliciting packet is sent.
+ * called when an ack-eliciting packet is sent.  The lost,
+ * tx_in_flight, and is_app_limited fields in |pkt| are set to 0.
  */
 typedef void (*ngtcp2_cc_on_pkt_sent)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
                                       const ngtcp2_cc_pkt *pkt);
 
-/**
- * @functypedef
- *
- * :type:`ngtcp2_cc_new_rtt_sample` is a callback function which is
- * called when new RTT sample is obtained.
- */
-typedef void (*ngtcp2_cc_new_rtt_sample)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
-                                         ngtcp2_tstamp ts);
-
 /**
  * @functypedef
  *
@@ -207,28 +199,6 @@ typedef void (*ngtcp2_cc_new_rtt_sample)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
 typedef void (*ngtcp2_cc_reset)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
                                 ngtcp2_tstamp ts);
 
-/**
- * @enum
- *
- * :type:`ngtcp2_cc_event_type` defines congestion control events.
- */
-typedef enum ngtcp2_cc_event_type {
-  /**
-   * :enum:`NGTCP2_CC_EVENT_TX_START` occurs when ack-eliciting packet
-   * is sent and no other ack-eliciting packet is present.
-   */
-  NGTCP2_CC_EVENT_TYPE_TX_START
-} ngtcp2_cc_event_type;
-
-/**
- * @functypedef
- *
- * :type:`ngtcp2_cc_event` is a callback function which is called when
- * a specific event happens.
- */
-typedef void (*ngtcp2_cc_event)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
-                                ngtcp2_cc_event_type event, ngtcp2_tstamp ts);
-
 /**
  * @struct
  *
@@ -275,21 +245,11 @@ typedef struct ngtcp2_cc {
    * ack-eliciting packet is sent.
    */
   ngtcp2_cc_on_pkt_sent on_pkt_sent;
-  /**
-   * :member:`new_rtt_sample` is a callback function which is called
-   * when new RTT sample is obtained.
-   */
-  ngtcp2_cc_new_rtt_sample new_rtt_sample;
   /**
    * :member:`reset` is a callback function which is called when
    * congestion control state must be reset.
    */
   ngtcp2_cc_reset reset;
-  /**
-   * :member:`event` is a callback function which is called when a
-   * specific event happens.
-   */
-  ngtcp2_cc_event event;
 } ngtcp2_cc;
 
 /*
index acbee78aaf435fd5b14bb8a95d6e962989f9ab84..42a4827664912fdb546928e75bb7aa86f1d50042 100644 (file)
@@ -58,11 +58,13 @@ int ngtcp2_cid_less(const ngtcp2_cid *lhs, const ngtcp2_cid *rhs) {
 int ngtcp2_cid_empty(const ngtcp2_cid *cid) { return cid->datalen == 0; }
 
 void ngtcp2_scid_init(ngtcp2_scid *scid, uint64_t seq, const ngtcp2_cid *cid) {
-  scid->pe.index = NGTCP2_PQ_BAD_INDEX;
-  scid->seq = seq;
-  scid->cid = *cid;
-  scid->retired_ts = UINT64_MAX;
-  scid->flags = NGTCP2_SCID_FLAG_NONE;
+  *scid = (ngtcp2_scid){
+    .pe.index = NGTCP2_PQ_BAD_INDEX,
+    .seq = seq,
+    .cid = *cid,
+    .retired_ts = UINT64_MAX,
+    .flags = NGTCP2_SCID_FLAG_NONE,
+  };
 }
 
 void ngtcp2_scid_copy(ngtcp2_scid *dest, const ngtcp2_scid *src) {
index b1a9840c6e1d20fb425347ed6f41fda779298022..827cacd5357e4c7db9f96b59e973da11687f0d68 100644 (file)
@@ -697,8 +697,10 @@ static int conn_call_recv_tx_key(ngtcp2_conn *conn,
   return 0;
 }
 
-// pktns_init initializes |pktns|.  It assumes that the object pointed
-// by |pktns| is zero-cleared.
+/*
+ * pktns_init initializes |pktns|.  It assumes that the object pointed
+ * by |pktns| is zero-cleared.
+ */
 static void pktns_init(ngtcp2_pktns *pktns, ngtcp2_pktns_id pktns_id,
                        ngtcp2_rst *rst, ngtcp2_cc *cc, int64_t initial_pkt_num,
                        ngtcp2_log *log, ngtcp2_qlog *qlog,
@@ -1525,6 +1527,8 @@ fail_seqgap_push:
 fail_token:
   ngtcp2_mem_free(mem, *pconn);
 
+  *pconn = NULL;
+
   return rv;
 }
 
@@ -1552,6 +1556,8 @@ int ngtcp2_conn_client_new_versioned(
   rv = ngtcp2_conn_commit_local_transport_params(*pconn);
   if (rv != 0) {
     ngtcp2_conn_del(*pconn);
+    *pconn = NULL;
+
     return rv;
   }
 
@@ -1809,8 +1815,18 @@ static int conn_ppe_write_frame(ngtcp2_conn *conn, ngtcp2_ppe *ppe,
 static int conn_on_pkt_sent(ngtcp2_conn *conn, ngtcp2_pktns *pktns,
                             ngtcp2_rtb_entry *ent) {
   ngtcp2_rtb *rtb = &pktns->rtb;
+  ngtcp2_cc_pkt cc_pkt;
   int rv;
 
+  if ((ent->flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) &&
+      conn->cc.on_pkt_sent) {
+    conn->cc.on_pkt_sent(
+      &conn->cc, &conn->cstat,
+      ngtcp2_cc_pkt_init(&cc_pkt, ent->hd.pkt_num, ent->pktlen, pktns->id,
+                         ent->ts, /* lost = */ 0,
+                         /* tx_in_flight = */ 0, /* is_app_limited = */ 0));
+  }
+
   /* This function implements OnPacketSent, but it handles only
      non-ACK-only packet. */
   rv = ngtcp2_rtb_add(rtb, ent, &conn->cstat);
@@ -2015,6 +2031,12 @@ static int conn_should_pad_pkt(ngtcp2_conn *conn, uint8_t type, size_t left,
       return 1;
     }
 
+    /* We might send Handshake packet even if exceeding CWND.  In that
+       case, we do not write non-probe 1RTT packet. */
+    if (conn_cwnd_is_zero(conn) && conn->pktns.rtb.probe_pkt_left == 0) {
+      return 1;
+    }
+
     min_payloadlen = NGTCP2_MIN_COALESCED_PAYLOADLEN;
   }
 
@@ -2194,12 +2216,15 @@ static int conn_cut_crypto_frame(ngtcp2_conn *conn, ngtcp2_frame_chain **pfrc,
   }
 
   /* ngtcp2_frame_chain for the removed data */
-  removed_frc->fr.stream.type = NGTCP2_FRAME_CRYPTO;
-  removed_frc->fr.stream.offset = (*pfrc)->fr.stream.offset + offset;
-  removed_frc->fr.stream.datacnt = 1;
-  removed_frc->fr.stream.data[0] = (ngtcp2_vec){
-    .base = data->base + offset,
-    .len = removed_data->len,
+  removed_frc->fr.stream = (ngtcp2_stream){
+    .type = NGTCP2_FRAME_CRYPTO,
+    .offset = (*pfrc)->fr.stream.offset + offset,
+    .datacnt = 1,
+    .data[0] =
+      {
+        .base = data->base + offset,
+        .len = removed_data->len,
+      },
   };
 
   rv = ngtcp2_strm_streamfrq_push(crypto_strm, removed_frc);
@@ -2249,12 +2274,15 @@ static int conn_cut_crypto_frame(ngtcp2_conn *conn, ngtcp2_frame_chain **pfrc,
     return rv;
   }
 
-  left_frc->fr.stream.type = NGTCP2_FRAME_CRYPTO;
-  left_frc->fr.stream.offset = (*pfrc)->fr.stream.offset;
-  left_frc->fr.stream.datacnt = 1;
-  left_frc->fr.stream.data[0] = (ngtcp2_vec){
-    .base = data[0].base,
-    .len = offset,
+  left_frc->fr.stream = (ngtcp2_stream){
+    .type = NGTCP2_FRAME_CRYPTO,
+    .offset = (*pfrc)->fr.stream.offset,
+    .datacnt = 1,
+    .data[0] =
+      {
+        .base = data[0].base,
+        .len = offset,
+      },
   };
   left_frc->next = right_frc;
 
@@ -3078,21 +3106,16 @@ static ngtcp2_ssize conn_write_handshake_pkts(ngtcp2_conn *conn,
       dest += nwrite;
       destlen -= (size_t)nwrite;
 
-      /* If initial packet size is at least
-         NGTCP2_MAX_UDP_PAYLOAD_SIZE, no extra padding is needed in a
-         subsequent packet. */
-      if (nwrite < NGTCP2_MAX_UDP_PAYLOAD_SIZE) {
-        if (conn->server) {
-          it = ngtcp2_rtb_head(&conn->in_pktns->rtb);
-          if (!ngtcp2_ksl_it_end(&it)) {
-            rtbent = ngtcp2_ksl_it_get(&it);
-            if (rtbent->flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) {
-              wflags |= NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING;
-            }
+      if (conn->server) {
+        it = ngtcp2_rtb_head(&conn->in_pktns->rtb);
+        if (!ngtcp2_ksl_it_end(&it)) {
+          rtbent = ngtcp2_ksl_it_get(&it);
+          if (rtbent->flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) {
+            wflags |= NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING;
           }
-        } else {
-          wflags |= NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING;
         }
+      } else {
+        wflags |= NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING;
       }
     }
   }
@@ -3457,7 +3480,6 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi,
   size_t min_pktlen = conn_min_pktlen(conn);
   int min_padded = 0;
   int padded = 0;
-  ngtcp2_cc_pkt cc_pkt;
   uint64_t crypto_offset;
   uint64_t stream_offset;
   ngtcp2_ssize num_reclaimed;
@@ -3573,8 +3595,10 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi,
 
       conn->tx.last_max_data_ts = ts;
 
-      nfrc->fr.type = NGTCP2_FRAME_MAX_DATA;
-      nfrc->fr.max_data.max_data = conn->rx.unsent_max_offset + delta;
+      nfrc->fr.max_data = (ngtcp2_max_data){
+        .type = NGTCP2_FRAME_MAX_DATA,
+        .max_data = conn->rx.unsent_max_offset + delta,
+      };
       nfrc->next = pktns->tx.frq;
       pktns->tx.frq = nfrc;
 
@@ -3817,11 +3841,12 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi,
             return rv;
           }
 
-          nfrc->fr.type = NGTCP2_FRAME_RESET_STREAM;
-          nfrc->fr.reset_stream.stream_id = strm->stream_id;
-          nfrc->fr.reset_stream.app_error_code =
-            strm->tx.reset_stream_app_error_code;
-          nfrc->fr.reset_stream.final_size = strm->tx.offset;
+          nfrc->fr.reset_stream = (ngtcp2_reset_stream){
+            .type = NGTCP2_FRAME_RESET_STREAM,
+            .stream_id = strm->stream_id,
+            .app_error_code = strm->tx.reset_stream_app_error_code,
+            .final_size = strm->tx.offset,
+          };
           *pfrc = nfrc;
 
           strm->flags &= ~NGTCP2_STRM_FLAG_SEND_RESET_STREAM;
@@ -3860,10 +3885,11 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi,
               return rv;
             }
 
-            nfrc->fr.type = NGTCP2_FRAME_STOP_SENDING;
-            nfrc->fr.stop_sending.stream_id = strm->stream_id;
-            nfrc->fr.stop_sending.app_error_code =
-              strm->tx.stop_sending_app_error_code;
+            nfrc->fr.stop_sending = (ngtcp2_stop_sending){
+              .type = NGTCP2_FRAME_STOP_SENDING,
+              .stream_id = strm->stream_id,
+              .app_error_code = strm->tx.stop_sending_app_error_code,
+            };
             *pfrc = nfrc;
 
             strm->flags &= ~NGTCP2_STRM_FLAG_SEND_STOP_SENDING;
@@ -3891,9 +3917,11 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi,
             return rv;
           }
 
-          nfrc->fr.type = NGTCP2_FRAME_STREAM_DATA_BLOCKED;
-          nfrc->fr.stream_data_blocked.stream_id = strm->stream_id;
-          nfrc->fr.stream_data_blocked.offset = strm->tx.max_offset;
+          nfrc->fr.stream_data_blocked = (ngtcp2_stream_data_blocked){
+            .type = NGTCP2_FRAME_STREAM_DATA_BLOCKED,
+            .stream_id = strm->stream_id,
+            .offset = strm->tx.max_offset,
+          };
           *pfrc = nfrc;
 
           strm->tx.last_blocked_offset = strm->tx.max_offset;
@@ -3945,10 +3973,11 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi,
 
           strm->tx.last_max_stream_data_ts = ts;
 
-          nfrc->fr.type = NGTCP2_FRAME_MAX_STREAM_DATA;
-          nfrc->fr.max_stream_data.stream_id = strm->stream_id;
-          nfrc->fr.max_stream_data.max_stream_data =
-            strm->rx.unsent_max_offset + delta;
+          nfrc->fr.max_stream_data = (ngtcp2_max_stream_data){
+            .type = NGTCP2_FRAME_MAX_STREAM_DATA,
+            .stream_id = strm->stream_id,
+            .max_stream_data = strm->rx.unsent_max_offset + delta,
+          };
           *pfrc = nfrc;
 
           strm->rx.max_offset = strm->rx.unsent_max_offset =
@@ -4044,8 +4073,10 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi,
         assert(ngtcp2_err_is_fatal(rv));
         return rv;
       }
-      nfrc->fr.type = NGTCP2_FRAME_MAX_STREAMS_BIDI;
-      nfrc->fr.max_streams.max_streams = conn->remote.bidi.unsent_max_streams;
+      nfrc->fr.max_streams = (ngtcp2_max_streams){
+        .type = NGTCP2_FRAME_MAX_STREAMS_BIDI,
+        .max_streams = conn->remote.bidi.unsent_max_streams,
+      };
       *pfrc = nfrc;
 
       conn->remote.bidi.max_streams = conn->remote.bidi.unsent_max_streams;
@@ -4076,8 +4107,10 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi,
         assert(ngtcp2_err_is_fatal(rv));
         return rv;
       }
-      nfrc->fr.type = NGTCP2_FRAME_MAX_STREAMS_UNI;
-      nfrc->fr.max_streams.max_streams = conn->remote.uni.unsent_max_streams;
+      nfrc->fr.max_streams = (ngtcp2_max_streams){
+        .type = NGTCP2_FRAME_MAX_STREAMS_UNI,
+        .max_streams = conn->remote.uni.unsent_max_streams,
+      };
       *pfrc = nfrc;
 
       conn->remote.uni.max_streams = conn->remote.uni.unsent_max_streams;
@@ -4198,8 +4231,10 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi,
         return rv;
       }
 
-      nfrc->fr.type = NGTCP2_FRAME_DATA_BLOCKED;
-      nfrc->fr.data_blocked.offset = conn->tx.offset;
+      nfrc->fr.data_blocked = (ngtcp2_data_blocked){
+        .type = NGTCP2_FRAME_DATA_BLOCKED,
+        .offset = conn->tx.offset,
+      };
 
       rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &nfrc->fr);
       if (rv != 0) {
@@ -4230,9 +4265,11 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi,
         return rv;
       }
 
-      nfrc->fr.type = NGTCP2_FRAME_STREAM_DATA_BLOCKED;
-      nfrc->fr.stream_data_blocked.stream_id = strm->stream_id;
-      nfrc->fr.stream_data_blocked.offset = strm->tx.max_offset;
+      nfrc->fr.stream_data_blocked = (ngtcp2_stream_data_blocked){
+        .type = NGTCP2_FRAME_STREAM_DATA_BLOCKED,
+        .stream_id = strm->stream_id,
+        .offset = strm->tx.max_offset,
+      };
 
       rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &nfrc->fr);
       if (rv != 0) {
@@ -4390,7 +4427,6 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi,
           rtb_entry_flags |= NGTCP2_RTB_ENTRY_FLAG_PTO_ELICITING;
         }
         pktns->tx.non_ack_pkt_start_ts = UINT64_MAX;
-        pkt_empty = 0;
       }
     } else if (pktns->tx.non_ack_pkt_start_ts == UINT64_MAX) {
       pktns->tx.non_ack_pkt_start_ts = ts;
@@ -4452,12 +4488,6 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi,
       *pfrc = NULL;
     }
 
-    if ((rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) &&
-        pktns->rtb.num_ack_eliciting == 0 && conn->cc.event) {
-      conn->cc.event(&conn->cc, &conn->cstat, NGTCP2_CC_EVENT_TYPE_TX_START,
-                     ts);
-    }
-
     rv = conn_on_pkt_sent(conn, pktns, ent);
     if (rv != 0) {
       assert(ngtcp2_err_is_fatal(rv));
@@ -4466,18 +4496,9 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi,
       return rv;
     }
 
-    if (rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) {
-      if (conn->cc.on_pkt_sent) {
-        conn->cc.on_pkt_sent(
-          &conn->cc, &conn->cstat,
-          ngtcp2_cc_pkt_init(&cc_pkt, hd->pkt_num, (size_t)nwrite,
-                             NGTCP2_PKTNS_ID_APPLICATION, ts, ent->rst.lost,
-                             ent->rst.tx_in_flight, ent->rst.is_app_limited));
-      }
-
-      if (conn->flags & NGTCP2_CONN_FLAG_RESTART_IDLE_TIMER_ON_WRITE) {
-        conn_restart_timer_on_write(conn, ts);
-      }
+    if ((rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) &&
+        (conn->flags & NGTCP2_CONN_FLAG_RESTART_IDLE_TIMER_ON_WRITE)) {
+      conn_restart_timer_on_write(conn, ts);
     }
   } else if (pi && conn->tx.ecn.state == NGTCP2_ECN_STATE_CAPABLE) {
     conn_handle_tx_ecn(conn, pi, NULL, pktns, hd, ts);
@@ -4652,6 +4673,13 @@ ngtcp2_ssize ngtcp2_conn_write_single_frame_pkt(
       padded = 0;
     }
 
+    break;
+  case NGTCP2_FRAME_CONNECTION_CLOSE:
+  case NGTCP2_FRAME_CONNECTION_CLOSE_APP:
+    /* Clear padded so that we never store the terminal packet in
+       ngtcp2_rtb. */
+    padded = 0;
+
     break;
   }
 
@@ -4778,8 +4806,10 @@ static int conn_enqueue_retire_connection_id(ngtcp2_conn *conn, uint64_t seq) {
     return rv;
   }
 
-  nfrc->fr.type = NGTCP2_FRAME_RETIRE_CONNECTION_ID;
-  nfrc->fr.retire_connection_id.seq = seq;
+  nfrc->fr.retire_connection_id = (ngtcp2_retire_connection_id){
+    .type = NGTCP2_FRAME_RETIRE_CONNECTION_ID,
+    .seq = seq,
+  };
   nfrc->next = pktns->tx.frq;
   pktns->tx.frq = nfrc;
 
@@ -5415,7 +5445,7 @@ static int conn_on_retry(ngtcp2_conn *conn, const ngtcp2_pkt_hd *hd,
   ngtcp2_pktns *in_pktns = conn->in_pktns;
   ngtcp2_rtb *rtb = &conn->pktns.rtb;
   ngtcp2_rtb *in_rtb;
-  uint8_t cidbuf[sizeof(retry.odcid.data) * 2 + 1];
+  char cidbuf[sizeof(retry.odcid.data) * 2 + 1];
   uint8_t *token;
 
   if (!in_pktns || (conn->flags & NGTCP2_CONN_FLAG_RECV_RETRY)) {
@@ -5440,9 +5470,9 @@ static int conn_on_retry(ngtcp2_conn *conn, const ngtcp2_pkt_hd *hd,
     return rv;
   }
 
-  ngtcp2_log_infof(&conn->log, NGTCP2_LOG_EVENT_PKT, "odcid=0x%s",
-                   (const char *)ngtcp2_encode_hex(cidbuf, retry.odcid.data,
-                                                   retry.odcid.datalen));
+  ngtcp2_log_infof(
+    &conn->log, NGTCP2_LOG_EVENT_PKT, "odcid=0x%s",
+    ngtcp2_encode_hex_cstr(cidbuf, retry.odcid.data, retry.odcid.datalen));
 
   if (retry.tokenlen == 0) {
     return NGTCP2_ERR_PROTO;
@@ -8742,7 +8772,6 @@ static int conn_recv_non_probing_pkt_on_new_path(ngtcp2_conn *conn,
   ngtcp2_pv *pv = NULL;
   int rv;
   ngtcp2_duration pto;
-  int require_new_cid;
   int local_addr_eq;
   int pref_addr_migration;
   uint32_t remote_addr_cmp;
@@ -8800,9 +8829,6 @@ static int conn_recv_non_probing_pkt_on_new_path(ngtcp2_conn *conn,
    * continue to use the current connection ID with the new remote
    * address while still sending from the same local address.
    */
-  require_new_cid = conn->dcid.current.cid.datalen &&
-                    ((new_cid_used && remote_addr_cmp) || !local_addr_eq);
-
   ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON,
                   "non-probing packet was received from new remote address");
 
@@ -8810,8 +8836,6 @@ static int conn_recv_non_probing_pkt_on_new_path(ngtcp2_conn *conn,
     ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON,
                     "Found DCID which has already been bound to the new path");
 
-    require_new_cid = 0;
-
     if (dcid.cid.datalen) {
       rv = conn_call_activate_dcid(conn, &dcid);
       if (rv != 0) {
@@ -8819,7 +8843,9 @@ static int conn_recv_non_probing_pkt_on_new_path(ngtcp2_conn *conn,
       }
     }
   } else {
-    if (require_new_cid) {
+    if (conn->dcid.current.cid.datalen &&
+        ((new_cid_used && remote_addr_cmp) || !local_addr_eq)) {
+      /* New DCID is required. */
       if (ngtcp2_dcidtr_unused_empty(&conn->dcid.dtr)) {
         return NGTCP2_ERR_CONN_ID_BLOCKED;
       }
@@ -10592,8 +10618,6 @@ static ngtcp2_ssize conn_write_handshake(ngtcp2_conn *conn, ngtcp2_pkt_info *pi,
       }
 
       res += nwrite;
-      dest += nwrite;
-      destlen -= (size_t)nwrite;
     }
 
     if (res == 0) {
@@ -10603,8 +10627,6 @@ static ngtcp2_ssize conn_write_handshake(ngtcp2_conn *conn, ngtcp2_pkt_info *pi,
       }
 
       res += nwrite;
-      dest += nwrite;
-      origlen -= (size_t)nwrite;
     }
 
     return res;
@@ -10840,6 +10862,9 @@ int ngtcp2_conn_install_initial_key(
   rv = ngtcp2_crypto_km_new(&pktns->crypto.tx.ckm, NULL, 0, NULL, tx_iv, ivlen,
                             conn->mem);
   if (rv != 0) {
+    ngtcp2_crypto_km_del(pktns->crypto.rx.ckm, conn->mem);
+    pktns->crypto.rx.ckm = NULL;
+
     return rv;
   }
 
@@ -10890,6 +10915,9 @@ int ngtcp2_conn_install_vneg_initial_key(
   rv = ngtcp2_crypto_km_new(&conn->vneg.tx.ckm, NULL, 0, NULL, tx_iv, ivlen,
                             conn->mem);
   if (rv != 0) {
+    ngtcp2_crypto_km_del(conn->vneg.rx.ckm, conn->mem);
+    conn->vneg.rx.ckm = NULL;
+
     return rv;
   }
 
@@ -10958,21 +10986,27 @@ int ngtcp2_conn_install_tx_handshake_key(
   if (conn->server) {
     rv = ngtcp2_conn_commit_local_transport_params(conn);
     if (rv != 0) {
-      return rv;
+      goto fail;
     }
   }
 
   rv = conn_call_recv_tx_key(conn, NGTCP2_ENCRYPTION_LEVEL_HANDSHAKE);
   if (rv != 0) {
-    ngtcp2_crypto_km_del(pktns->crypto.tx.ckm, conn->mem);
-    pktns->crypto.tx.ckm = NULL;
-
-    memset(&pktns->crypto.tx.hp_ctx, 0, sizeof(pktns->crypto.tx.hp_ctx));
-
-    return rv;
+    goto fail;
   }
 
   return 0;
+
+fail:
+  /* If this function fails, aead_ctx and hp_ctx are still owned by
+     the caller.  Delete the install key to remove the any reference
+     to them. */
+  ngtcp2_crypto_km_del(pktns->crypto.tx.ckm, conn->mem);
+  pktns->crypto.tx.ckm = NULL;
+
+  memset(&pktns->crypto.tx.hp_ctx, 0, sizeof(pktns->crypto.tx.hp_ctx));
+
+  return rv;
 }
 
 int ngtcp2_conn_install_0rtt_key(ngtcp2_conn *conn,
@@ -11924,11 +11958,8 @@ conn_write_vmsg_wrapper(ngtcp2_conn *conn, ngtcp2_path *path,
                 packet is produced, if it is set, we are sure that we
                 are not app-limited. */
              !(conn->flags & NGTCP2_CONN_FLAG_AGGREGATE_PKTS)) {
-    conn->rst.app_limited = conn->rst.delivered + cstat->bytes_in_flight;
-
-    if (conn->rst.app_limited == 0) {
-      conn->rst.app_limited = cstat->max_tx_udp_payload_size;
-    }
+    conn->rst.app_limited =
+      ngtcp2_max_uint64(conn->rst.delivered + cstat->bytes_in_flight, 1);
   }
 
   return nwrite;
@@ -12111,27 +12142,29 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path,
       conn_client_write_handshake(conn, pi, dest, destlen, wflags, vmsg, ts);
     /* We might be unable to write a packet because of depletion of
        congestion window budget, perhaps due to packet loss that
-       shrinks the window drastically. */
-    if (nwrite <= 0) {
+       shrinks the window drastically.  Then continue if we are in
+       post-handshake.  There, we might be able to write packets
+       exceeding CWND to avoid deadlock. */
+    if (nwrite < 0) {
       return nwrite;
     }
     if (conn->state != NGTCP2_CS_POST_HANDSHAKE) {
       return nwrite;
     }
 
-    assert(nwrite);
-    assert(dest[0] & NGTCP2_HEADER_FORM_BIT);
-    assert(conn->negotiated_version);
+    if (nwrite) {
+      assert(dest[0] & NGTCP2_HEADER_FORM_BIT);
+      assert(conn->negotiated_version);
 
-    if (nwrite < NGTCP2_MAX_UDP_PAYLOAD_SIZE &&
-        ngtcp2_pkt_get_type_long(conn->negotiated_version, dest[0]) ==
+      if (ngtcp2_pkt_get_type_long(conn->negotiated_version, dest[0]) ==
           NGTCP2_PKT_INITIAL) {
-      wflags |= NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING;
-    }
+        wflags |= NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING;
+      }
 
-    res = nwrite;
-    dest += nwrite;
-    destlen -= (size_t)nwrite;
+      res = nwrite;
+      dest += nwrite;
+      destlen -= (size_t)nwrite;
+    }
     /* Break here so that we can coalesces 1RTT packet. */
     break;
   case NGTCP2_CS_SERVER_INITIAL:
@@ -12186,7 +12219,7 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path,
       dest += nwrite;
       destlen -= (size_t)nwrite;
 
-      if (res < NGTCP2_MAX_UDP_PAYLOAD_SIZE && conn->in_pktns && nwrite > 0) {
+      if (conn->in_pktns && nwrite > 0) {
         it = ngtcp2_rtb_head(&conn->in_pktns->rtb);
         if (!ngtcp2_ksl_it_end(&it)) {
           rtbent = ngtcp2_ksl_it_get(&it);
@@ -12333,9 +12366,22 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path,
         return nwrite;
       }
       if (nwrite > 0) {
+        /* This makes 1RTT packet padded.  If 1RTT packet is not going
+           to be sent, packet is already padded. */
+        if (ngtcp2_pkt_get_type_long(conn->negotiated_version, dest[0]) ==
+            NGTCP2_PKT_INITIAL) {
+          wflags |= NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING;
+        }
+
         res = nwrite;
         dest += nwrite;
         destlen -= (size_t)nwrite;
+
+        /* We only exceed CWND to avoid deadlock.  Do no write 1RTT
+           packet if CWND is depleted. */
+        if (conn_cwnd_is_zero(conn) && conn->pktns.rtb.probe_pkt_left == 0) {
+          goto fin;
+        }
       } else if (destlen == 0) {
         res = conn_write_handshake_ack_pkts(conn, pi, dest, origlen, ts);
         if (res) {
@@ -12402,11 +12448,12 @@ conn_write_connection_close(ngtcp2_conn *conn, ngtcp2_pkt_info *pi,
   ngtcp2_frame fr;
   uint8_t flags = NGTCP2_WRITE_PKT_FLAG_NONE;
 
-  fr.type = NGTCP2_FRAME_CONNECTION_CLOSE;
-  fr.connection_close.error_code = error_code;
-  fr.connection_close.frame_type = 0;
-  fr.connection_close.reasonlen = reasonlen;
-  fr.connection_close.reason = (uint8_t *)reason;
+  fr.connection_close = (ngtcp2_connection_close){
+    .type = NGTCP2_FRAME_CONNECTION_CLOSE,
+    .error_code = error_code,
+    .reasonlen = reasonlen,
+    .reason = (uint8_t *)reason,
+  };
 
   if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED) &&
       pkt_type != NGTCP2_PKT_INITIAL) {
@@ -12581,11 +12628,12 @@ ngtcp2_ssize ngtcp2_conn_write_application_close_pkt(
 
   assert(conn->pktns.crypto.tx.ckm);
 
-  fr.type = NGTCP2_FRAME_CONNECTION_CLOSE_APP;
-  fr.connection_close.error_code = app_error_code;
-  fr.connection_close.frame_type = 0;
-  fr.connection_close.reasonlen = reasonlen;
-  fr.connection_close.reason = (uint8_t *)reason;
+  fr.connection_close = (ngtcp2_connection_close){
+    .type = NGTCP2_FRAME_CONNECTION_CLOSE_APP,
+    .error_code = app_error_code,
+    .reasonlen = reasonlen,
+    .reason = (uint8_t *)reason,
+  };
 
   nwrite = ngtcp2_conn_write_single_frame_pkt(
     conn, pi, dest, destlen, NGTCP2_PKT_1RTT, NGTCP2_WRITE_PKT_FLAG_NONE,
@@ -12609,11 +12657,12 @@ ngtcp2_ssize ngtcp2_conn_write_application_close_pkt(
 static void ccerr_init(ngtcp2_ccerr *ccerr, ngtcp2_ccerr_type type,
                        uint64_t error_code, const uint8_t *reason,
                        size_t reasonlen) {
-  ccerr->type = type;
-  ccerr->error_code = error_code;
-  ccerr->frame_type = 0;
-  ccerr->reason = (uint8_t *)reason;
-  ccerr->reasonlen = reasonlen;
+  *ccerr = (ngtcp2_ccerr){
+    .type = type,
+    .error_code = error_code,
+    .reason = (uint8_t *)reason,
+    .reasonlen = reasonlen,
+  };
 }
 
 void ngtcp2_ccerr_default(ngtcp2_ccerr *ccerr) {
@@ -13029,8 +13078,8 @@ int ngtcp2_conn_get_tls_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_duration ack_delay, ngtcp2_tstamp ts) {
+void ngtcp2_conn_update_rtt(ngtcp2_conn *conn, ngtcp2_duration rtt,
+                            ngtcp2_duration ack_delay, ngtcp2_tstamp ts) {
   ngtcp2_conn_stat *cstat = &conn->cstat;
 
   assert(rtt > 0);
@@ -13057,7 +13106,7 @@ int ngtcp2_conn_update_rtt(ngtcp2_conn *conn, ngtcp2_duration rtt,
         " min_rtt=%" PRIu64 " ack_delay=%" PRIu64,
         rtt / NGTCP2_MILLISECONDS, cstat->min_rtt / NGTCP2_MILLISECONDS,
         ack_delay / NGTCP2_MILLISECONDS);
-      return NGTCP2_ERR_INVALID_ARGUMENT;
+      return;
     }
 
     cstat->latest_rtt = rtt;
@@ -13082,8 +13131,6 @@ int ngtcp2_conn_update_rtt(ngtcp2_conn *conn, ngtcp2_duration rtt,
     cstat->min_rtt / NGTCP2_MILLISECONDS,
     cstat->smoothed_rtt / NGTCP2_MILLISECONDS,
     cstat->rttvar / NGTCP2_MILLISECONDS, ack_delay / NGTCP2_MILLISECONDS);
-
-  return 0;
 }
 
 void ngtcp2_conn_get_conn_info_versioned(ngtcp2_conn *conn,
@@ -13314,7 +13361,6 @@ int ngtcp2_conn_submit_crypto_data(ngtcp2_conn *conn,
                                    const uint8_t *data, const size_t datalen) {
   ngtcp2_pktns *pktns;
   ngtcp2_frame_chain *frc;
-  ngtcp2_stream *fr;
   int rv;
 
   if (datalen == 0) {
@@ -13347,16 +13393,16 @@ int ngtcp2_conn_submit_crypto_data(ngtcp2_conn *conn,
     return rv;
   }
 
-  fr = &frc->fr.stream;
-
-  fr->type = NGTCP2_FRAME_CRYPTO;
-  fr->flags = 0;
-  fr->fin = 0;
-  fr->stream_id = 0;
-  fr->offset = pktns->crypto.tx.offset;
-  fr->datacnt = 1;
-  fr->data[0].len = datalen;
-  fr->data[0].base = (uint8_t *)data;
+  frc->fr.stream = (ngtcp2_stream){
+    .type = NGTCP2_FRAME_CRYPTO,
+    .offset = pktns->crypto.tx.offset,
+    .datacnt = 1,
+    .data[0] =
+      {
+        .base = (uint8_t *)data,
+        .len = datalen,
+      },
+  };
 
   rv = ngtcp2_strm_streamfrq_push(&pktns->crypto.strm, frc);
   if (rv != 0) {
index 30a44e726644cf5152234699460da451439e06f5..8cda85edbf25c297c38f8cb8492d4d71caff532a 100644 (file)
@@ -768,15 +768,9 @@ int ngtcp2_conn_close_stream_if_shut_rdwr(ngtcp2_conn *conn, ngtcp2_strm *strm);
  * ack_delay included in ACK frame.  |ack_delay| is actually tainted
  * (sent by peer), so don't assume that |ack_delay| is always smaller
  * than, or equals to |rtt|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_INVALID_ARGUMENT
- *     RTT sample is ignored.
  */
-int ngtcp2_conn_update_rtt(ngtcp2_conn *conn, ngtcp2_duration rtt,
-                           ngtcp2_duration ack_delay, ngtcp2_tstamp ts);
+void ngtcp2_conn_update_rtt(ngtcp2_conn *conn, ngtcp2_duration rtt,
+                            ngtcp2_duration ack_delay, ngtcp2_tstamp ts);
 
 void ngtcp2_conn_set_loss_detection_timer(ngtcp2_conn *conn, ngtcp2_tstamp ts);
 
index 1f74e8c58397b1cf15e8e88520f73aa6706b2f9a..078568fde3b09e0b9fd59ac13a6bd620f78e45b4 100644 (file)
@@ -65,15 +65,21 @@ int ngtcp2_crypto_km_nocopy_new(ngtcp2_crypto_km **pckm, size_t secretlen,
   }
 
   p = (uint8_t *)(*pckm) + sizeof(ngtcp2_crypto_km);
-  (*pckm)->secret.base = p;
-  (*pckm)->secret.len = secretlen;
-  p += secretlen;
-  (*pckm)->iv.base = p;
-  (*pckm)->iv.len = ivlen;
-  (*pckm)->aead_ctx.native_handle = NULL;
-  (*pckm)->pkt_num = -1;
-  (*pckm)->use_count = 0;
-  (*pckm)->flags = NGTCP2_CRYPTO_KM_FLAG_NONE;
+
+  **pckm = (ngtcp2_crypto_km){
+    .secret =
+      {
+        .base = p,
+        .len = secretlen,
+      },
+    .iv =
+      {
+        .base = p + secretlen,
+        .len = ivlen,
+      },
+    .pkt_num = -1,
+    .flags = NGTCP2_CRYPTO_KM_FLAG_NONE,
+  };
 
   return 0;
 }
index 22c131a1ac677c58477a449fcb93cd23b4763128..25e803efbbb29b3a4a6869bc44eacb0660db8825 100644 (file)
@@ -37,33 +37,31 @@ static ngtcp2_ksl_blk null_blk;
 
 ngtcp2_objalloc_def(ksl_blk, ngtcp2_ksl_blk, oplent)
 
-static size_t ksl_nodelen(size_t keylen) {
-  assert(keylen >= sizeof(uint64_t));
-
-  return (sizeof(ngtcp2_ksl_node) + keylen - sizeof(uint64_t) + 0x7u) &
-         ~(uintptr_t)0x7u;
-}
-
-static size_t ksl_blklen(size_t nodelen) {
-  return sizeof(ngtcp2_ksl_blk) + nodelen * NGTCP2_KSL_MAX_NBLK -
+static size_t ksl_blklen(size_t aligned_keylen) {
+  return sizeof(ngtcp2_ksl_blk) + NGTCP2_KSL_MAX_NBLK * aligned_keylen -
          sizeof(uint64_t);
 }
 
 /*
- * ksl_node_set_key sets |key| to |node|.
+ * ksl_set_nth_key sets |key| to |n|th node under |blk|.
  */
-static void ksl_node_set_key(ngtcp2_ksl *ksl, ngtcp2_ksl_node *node,
-                             const void *key) {
-  memcpy(node->key, key, ksl->keylen);
+static void ksl_set_nth_key(const ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk,
+                            size_t n, const ngtcp2_ksl_key *key) {
+  memcpy(blk->keys + n * ksl->aligned_keylen, key, ksl->keylen);
 }
 
 void ngtcp2_ksl_init(ngtcp2_ksl *ksl, ngtcp2_ksl_compar compar,
                      ngtcp2_ksl_search search, size_t keylen,
                      const ngtcp2_mem *mem) {
-  size_t nodelen = ksl_nodelen(keylen);
+  size_t aligned_keylen;
+
+  assert(keylen >= sizeof(uint64_t));
+
+  aligned_keylen = (keylen + 0x7u) & ~0x7u;
 
   ngtcp2_objalloc_init(&ksl->blkalloc,
-                       (ksl_blklen(nodelen) + 0xfu) & ~(uintptr_t)0xfu, mem);
+                       (ksl_blklen(aligned_keylen) + 0xfu) & ~(uintptr_t)0xfu,
+                       mem);
 
   ksl->head = NULL;
   ksl->front = ksl->back = NULL;
@@ -71,12 +69,12 @@ void ngtcp2_ksl_init(ngtcp2_ksl *ksl, ngtcp2_ksl_compar compar,
   ksl->search = search;
   ksl->n = 0;
   ksl->keylen = keylen;
-  ksl->nodelen = nodelen;
+  ksl->aligned_keylen = aligned_keylen;
 }
 
 static ngtcp2_ksl_blk *ksl_blk_objalloc_new(ngtcp2_ksl *ksl) {
   return ngtcp2_objalloc_ksl_blk_len_get(&ksl->blkalloc,
-                                         ksl_blklen(ksl->nodelen));
+                                         ksl_blklen(ksl->aligned_keylen));
 }
 
 static void ksl_blk_objalloc_del(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk) {
@@ -109,7 +107,7 @@ static void ksl_free_blk(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk) {
 
   if (!blk->leaf) {
     for (i = 0; i < blk->n; ++i) {
-      ksl_free_blk(ksl, ngtcp2_ksl_nth_node(ksl, blk, i)->blk);
+      ksl_free_blk(ksl, blk->nodes[i].blk);
     }
   }
 
@@ -160,8 +158,10 @@ static ngtcp2_ksl_blk *ksl_split_blk(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk) {
   rblk->n = blk->n / 2;
   blk->n -= rblk->n;
 
-  memcpy(rblk->nodes, blk->nodes + ksl->nodelen * blk->n,
-         ksl->nodelen * rblk->n);
+  memcpy(rblk->nodes, blk->nodes + blk->n, rblk->n * sizeof(ngtcp2_ksl_node));
+
+  memcpy(rblk->keys, blk->keys + blk->n * ksl->aligned_keylen,
+         rblk->n * ksl->aligned_keylen);
 
   assert(blk->n >= NGTCP2_KSL_MIN_NBLK);
   assert(rblk->n >= NGTCP2_KSL_MIN_NBLK);
@@ -181,25 +181,25 @@ static ngtcp2_ksl_blk *ksl_split_blk(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk) {
  *     Out of memory.
  */
 static int ksl_split_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) {
-  ngtcp2_ksl_node *node;
-  ngtcp2_ksl_blk *lblk = ngtcp2_ksl_nth_node(ksl, blk, i)->blk, *rblk;
+  ngtcp2_ksl_blk *lblk = blk->nodes[i].blk, *rblk;
 
   rblk = ksl_split_blk(ksl, lblk);
   if (rblk == NULL) {
     return NGTCP2_ERR_NOMEM;
   }
 
-  memmove(blk->nodes + (i + 2) * ksl->nodelen,
-          blk->nodes + (i + 1) * ksl->nodelen,
-          ksl->nodelen * (blk->n - (i + 1)));
+  memmove(blk->nodes + (i + 2), blk->nodes + (i + 1),
+          (blk->n - (i + 1)) * sizeof(ngtcp2_ksl_node));
 
-  node = ngtcp2_ksl_nth_node(ksl, blk, i + 1);
-  node->blk = rblk;
+  memmove(blk->keys + (i + 2) * ksl->aligned_keylen,
+          blk->keys + (i + 1) * ksl->aligned_keylen,
+          (blk->n - (i + 1)) * ksl->aligned_keylen);
+
+  blk->nodes[i + 1].blk = rblk;
   ++blk->n;
-  ksl_node_set_key(ksl, node, ngtcp2_ksl_nth_node(ksl, rblk, rblk->n - 1)->key);
+  ksl_set_nth_key(ksl, blk, i + 1, ngtcp2_ksl_nth_key(ksl, rblk, rblk->n - 1));
 
-  node = ngtcp2_ksl_nth_node(ksl, blk, i);
-  ksl_node_set_key(ksl, node, ngtcp2_ksl_nth_node(ksl, lblk, lblk->n - 1)->key);
+  ksl_set_nth_key(ksl, blk, i, ngtcp2_ksl_nth_key(ksl, lblk, lblk->n - 1));
 
   return 0;
 }
@@ -216,7 +216,6 @@ static int ksl_split_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) {
  */
 static int ksl_split_head(ngtcp2_ksl *ksl) {
   ngtcp2_ksl_blk *rblk = NULL, *lblk, *nhead = NULL;
-  ngtcp2_ksl_node *node;
 
   rblk = ksl_split_blk(ksl, ksl->head);
   if (rblk == NULL) {
@@ -236,13 +235,11 @@ static int ksl_split_head(ngtcp2_ksl *ksl) {
   nhead->n = 2;
   nhead->leaf = 0;
 
-  node = ngtcp2_ksl_nth_node(ksl, nhead, 0);
-  ksl_node_set_key(ksl, node, ngtcp2_ksl_nth_node(ksl, lblk, lblk->n - 1)->key);
-  node->blk = lblk;
+  ksl_set_nth_key(ksl, nhead, 0, ngtcp2_ksl_nth_key(ksl, lblk, lblk->n - 1));
+  nhead->nodes[0].blk = lblk;
 
-  node = ngtcp2_ksl_nth_node(ksl, nhead, 1);
-  ksl_node_set_key(ksl, node, ngtcp2_ksl_nth_node(ksl, rblk, rblk->n - 1)->key);
-  node->blk = rblk;
+  ksl_set_nth_key(ksl, nhead, 1, ngtcp2_ksl_nth_key(ksl, rblk, rblk->n - 1));
+  nhead->nodes[1].blk = rblk;
 
   ksl->head = nhead;
 
@@ -257,16 +254,17 @@ static int ksl_split_head(ngtcp2_ksl *ksl) {
  */
 static void ksl_insert_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i,
                             const ngtcp2_ksl_key *key, void *data) {
-  ngtcp2_ksl_node *node;
-
   assert(blk->n < NGTCP2_KSL_MAX_NBLK);
 
-  memmove(blk->nodes + (i + 1) * ksl->nodelen, blk->nodes + i * ksl->nodelen,
-          ksl->nodelen * (blk->n - i));
+  memmove(blk->nodes + (i + 1), blk->nodes + i,
+          (blk->n - i) * sizeof(ngtcp2_ksl_node));
+
+  memmove(blk->keys + (i + 1) * ksl->aligned_keylen,
+          blk->keys + i * ksl->aligned_keylen,
+          (blk->n - i) * ksl->aligned_keylen);
 
-  node = ngtcp2_ksl_nth_node(ksl, blk, i);
-  ksl_node_set_key(ksl, node, key);
-  node->data = data;
+  ksl_set_nth_key(ksl, blk, i, key);
+  blk->nodes[i].data = data;
 
   ++blk->n;
 }
@@ -298,8 +296,7 @@ int ngtcp2_ksl_insert(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it,
     i = ksl->search(ksl, blk, key);
 
     if (blk->leaf) {
-      if (i < blk->n &&
-          !ksl->compar(key, ngtcp2_ksl_nth_node(ksl, blk, i)->key)) {
+      if (i < blk->n && !ksl->compar(key, ngtcp2_ksl_nth_key(ksl, blk, i))) {
         if (it) {
           *it = ngtcp2_ksl_end(ksl);
         }
@@ -320,17 +317,17 @@ int ngtcp2_ksl_insert(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it,
     if (i == blk->n) {
       /* This insertion extends the largest key in this subtree. */
       for (; !blk->leaf;) {
-        node = ngtcp2_ksl_nth_node(ksl, blk, blk->n - 1);
+        node = &blk->nodes[blk->n - 1];
         if (node->blk->n == NGTCP2_KSL_MAX_NBLK) {
           rv = ksl_split_node(ksl, blk, blk->n - 1);
           if (rv != 0) {
             return rv;
           }
 
-          node = ngtcp2_ksl_nth_node(ksl, blk, blk->n - 1);
+          node = &blk->nodes[blk->n - 1];
         }
 
-        ksl_node_set_key(ksl, node, key);
+        ksl_set_nth_key(ksl, blk, blk->n - 1, key);
         blk = node->blk;
       }
 
@@ -344,7 +341,7 @@ int ngtcp2_ksl_insert(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it,
       return 0;
     }
 
-    node = ngtcp2_ksl_nth_node(ksl, blk, i);
+    node = &blk->nodes[i];
 
     if (node->blk->n == NGTCP2_KSL_MAX_NBLK) {
       rv = ksl_split_node(ksl, blk, i);
@@ -352,11 +349,11 @@ int ngtcp2_ksl_insert(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it,
         return rv;
       }
 
-      if (ksl->compar((ngtcp2_ksl_key *)node->key, key)) {
-        node = ngtcp2_ksl_nth_node(ksl, blk, i + 1);
+      if (ksl->compar(ngtcp2_ksl_nth_key(ksl, blk, i), key)) {
+        node = &blk->nodes[i + 1];
 
-        if (ksl->compar((ngtcp2_ksl_key *)node->key, key)) {
-          ksl_node_set_key(ksl, node, key);
+        if (ksl->compar(ngtcp2_ksl_nth_key(ksl, blk, i + 1), key)) {
+          ksl_set_nth_key(ksl, blk, i + 1, key);
         }
       }
     }
@@ -370,8 +367,12 @@ int ngtcp2_ksl_insert(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it,
  * |i|.
  */
 static void ksl_remove_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) {
-  memmove(blk->nodes + i * ksl->nodelen, blk->nodes + (i + 1) * ksl->nodelen,
-          ksl->nodelen * (blk->n - (i + 1)));
+  memmove(blk->nodes + i, blk->nodes + (i + 1),
+          (blk->n - (i + 1)) * sizeof(ngtcp2_ksl_node));
+
+  memmove(blk->keys + i * ksl->aligned_keylen,
+          blk->keys + (i + 1) * ksl->aligned_keylen,
+          (blk->n - (i + 1)) * ksl->aligned_keylen);
 
   --blk->n;
 }
@@ -393,15 +394,17 @@ static ngtcp2_ksl_blk *ksl_merge_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk,
 
   assert(i + 1 < blk->n);
 
-  lnode = ngtcp2_ksl_nth_node(ksl, blk, i);
+  lnode = &blk->nodes[i];
 
   lblk = lnode->blk;
-  rblk = ngtcp2_ksl_nth_node(ksl, blk, i + 1)->blk;
+  rblk = blk->nodes[i + 1].blk;
 
   assert(lblk->n + rblk->n < NGTCP2_KSL_MAX_NBLK);
 
-  memcpy(lblk->nodes + ksl->nodelen * lblk->n, rblk->nodes,
-         ksl->nodelen * rblk->n);
+  memcpy(lblk->nodes + lblk->n, rblk->nodes, rblk->n * sizeof(ngtcp2_ksl_node));
+
+  memcpy(lblk->keys + lblk->n * ksl->aligned_keylen, rblk->keys,
+         rblk->n * ksl->aligned_keylen);
 
   lblk->n += rblk->n;
   lblk->next = rblk->next;
@@ -419,8 +422,7 @@ static ngtcp2_ksl_blk *ksl_merge_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk,
     ksl->head = lblk;
   } else {
     ksl_remove_node(ksl, blk, i + 1);
-    ksl_node_set_key(ksl, lnode,
-                     ngtcp2_ksl_nth_node(ksl, lblk, lblk->n - 1)->key);
+    ksl_set_nth_key(ksl, blk, i, ngtcp2_ksl_nth_key(ksl, lblk, lblk->n - 1));
   }
 
   return lblk;
@@ -438,8 +440,8 @@ static void ksl_shift_left(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) {
 
   assert(i > 0);
 
-  lnode = ngtcp2_ksl_nth_node(ksl, blk, i - 1);
-  rnode = ngtcp2_ksl_nth_node(ksl, blk, i);
+  lnode = &blk->nodes[i - 1];
+  rnode = &blk->nodes[i];
 
   lblk = lnode->blk;
   rblk = rnode->blk;
@@ -453,15 +455,20 @@ static void ksl_shift_left(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) {
   assert(lblk->n <= NGTCP2_KSL_MAX_NBLK - n);
   assert(rblk->n >= NGTCP2_KSL_MIN_NBLK + n);
 
-  memcpy(lblk->nodes + ksl->nodelen * lblk->n, rblk->nodes, ksl->nodelen * n);
+  memcpy(lblk->nodes + lblk->n, rblk->nodes, n * sizeof(ngtcp2_ksl_node));
+
+  memcpy(lblk->keys + lblk->n * ksl->aligned_keylen, rblk->keys,
+         n * ksl->aligned_keylen);
 
   lblk->n += (uint32_t)n;
   rblk->n -= (uint32_t)n;
 
-  ksl_node_set_key(ksl, lnode,
-                   ngtcp2_ksl_nth_node(ksl, lblk, lblk->n - 1)->key);
+  ksl_set_nth_key(ksl, blk, i - 1, ngtcp2_ksl_nth_key(ksl, lblk, lblk->n - 1));
+
+  memmove(rblk->nodes, rblk->nodes + n, rblk->n * sizeof(ngtcp2_ksl_node));
 
-  memmove(rblk->nodes, rblk->nodes + ksl->nodelen * n, ksl->nodelen * rblk->n);
+  memmove(rblk->keys, rblk->keys + n * ksl->aligned_keylen,
+          rblk->n * ksl->aligned_keylen);
 }
 
 /*
@@ -476,8 +483,8 @@ static void ksl_shift_right(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) {
 
   assert(i < blk->n - 1);
 
-  lnode = ngtcp2_ksl_nth_node(ksl, blk, i);
-  rnode = ngtcp2_ksl_nth_node(ksl, blk, i + 1);
+  lnode = &blk->nodes[i];
+  rnode = &blk->nodes[i + 1];
 
   lblk = lnode->blk;
   rblk = rnode->blk;
@@ -491,15 +498,20 @@ static void ksl_shift_right(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) {
   assert(lblk->n >= NGTCP2_KSL_MIN_NBLK + n);
   assert(rblk->n <= NGTCP2_KSL_MAX_NBLK - n);
 
-  memmove(rblk->nodes + ksl->nodelen * n, rblk->nodes, ksl->nodelen * rblk->n);
+  memmove(rblk->nodes + n, rblk->nodes, rblk->n * sizeof(ngtcp2_ksl_node));
+
+  memmove(rblk->keys + n * ksl->aligned_keylen, rblk->keys,
+          rblk->n * ksl->aligned_keylen);
 
   rblk->n += (uint32_t)n;
   lblk->n -= (uint32_t)n;
 
-  memcpy(rblk->nodes, lblk->nodes + ksl->nodelen * lblk->n, ksl->nodelen * n);
+  memcpy(rblk->nodes, lblk->nodes + lblk->n, n * sizeof(ngtcp2_ksl_node));
 
-  ksl_node_set_key(ksl, lnode,
-                   ngtcp2_ksl_nth_node(ksl, lblk, lblk->n - 1)->key);
+  memcpy(rblk->keys, lblk->keys + lblk->n * ksl->aligned_keylen,
+         n * ksl->aligned_keylen);
+
+  ksl_set_nth_key(ksl, blk, i, ngtcp2_ksl_nth_key(ksl, lblk, lblk->n - 1));
 }
 
 /*
@@ -548,8 +560,8 @@ int ngtcp2_ksl_remove(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it,
   }
 
   if (!blk->leaf && blk->n == 2 &&
-      ngtcp2_ksl_nth_node(ksl, blk, 0)->blk->n == NGTCP2_KSL_MIN_NBLK &&
-      ngtcp2_ksl_nth_node(ksl, blk, 1)->blk->n == NGTCP2_KSL_MIN_NBLK) {
+      blk->nodes[0].blk->n == NGTCP2_KSL_MIN_NBLK &&
+      blk->nodes[1].blk->n == NGTCP2_KSL_MIN_NBLK) {
     blk = ksl_merge_node(ksl, blk, 0);
   }
 
@@ -565,7 +577,7 @@ int ngtcp2_ksl_remove(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it,
     }
 
     if (blk->leaf) {
-      if (ksl->compar(key, ngtcp2_ksl_nth_node(ksl, blk, i)->key)) {
+      if (ksl->compar(key, ngtcp2_ksl_nth_key(ksl, blk, i))) {
         if (it) {
           *it = ngtcp2_ksl_end(ksl);
         }
@@ -587,7 +599,7 @@ int ngtcp2_ksl_remove(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it,
       return 0;
     }
 
-    node = ngtcp2_ksl_nth_node(ksl, blk, i);
+    node = &blk->nodes[i];
 
     if (node->blk->n > NGTCP2_KSL_MIN_NBLK) {
       blk = node->blk;
@@ -596,16 +608,14 @@ int ngtcp2_ksl_remove(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it,
 
     assert(node->blk->n == NGTCP2_KSL_MIN_NBLK);
 
-    if (i + 1 < blk->n &&
-        ngtcp2_ksl_nth_node(ksl, blk, i + 1)->blk->n > NGTCP2_KSL_MIN_NBLK) {
+    if (i + 1 < blk->n && blk->nodes[i + 1].blk->n > NGTCP2_KSL_MIN_NBLK) {
       ksl_shift_left(ksl, blk, i + 1);
       blk = node->blk;
 
       continue;
     }
 
-    if (i > 0 &&
-        ngtcp2_ksl_nth_node(ksl, blk, i - 1)->blk->n > NGTCP2_KSL_MIN_NBLK) {
+    if (i > 0 && blk->nodes[i - 1].blk->n > NGTCP2_KSL_MIN_NBLK) {
       ksl_shift_right(ksl, blk, i - 1);
       blk = node->blk;
 
@@ -657,7 +667,7 @@ ngtcp2_ksl_it ngtcp2_ksl_lower_bound_search(const ngtcp2_ksl *ksl,
     if (i == blk->n) {
       /* This happens if descendant has smaller key.  Fast forward to
          find last node in this subtree. */
-      for (; !blk->leaf; blk = ngtcp2_ksl_nth_node(ksl, blk, blk->n - 1)->blk)
+      for (; !blk->leaf; blk = blk->nodes[blk->n - 1].blk)
         ;
 
       if (blk->next) {
@@ -672,7 +682,7 @@ ngtcp2_ksl_it ngtcp2_ksl_lower_bound_search(const ngtcp2_ksl *ksl,
       return it;
     }
 
-    blk = ngtcp2_ksl_nth_node(ksl, blk, i)->blk;
+    blk = blk->nodes[i].blk;
   }
 }
 
@@ -680,6 +690,7 @@ void ngtcp2_ksl_update_key(ngtcp2_ksl *ksl, const ngtcp2_ksl_key *old_key,
                            const ngtcp2_ksl_key *new_key) {
   ngtcp2_ksl_blk *blk = ksl->head;
   ngtcp2_ksl_node *node;
+  const ngtcp2_ksl_key *node_key;
   size_t i;
 
   assert(ksl->head);
@@ -688,18 +699,19 @@ void ngtcp2_ksl_update_key(ngtcp2_ksl *ksl, const ngtcp2_ksl_key *old_key,
     i = ksl->search(ksl, blk, old_key);
 
     assert(i < blk->n);
-    node = ngtcp2_ksl_nth_node(ksl, blk, i);
+    node = &blk->nodes[i];
+    node_key = ngtcp2_ksl_nth_key(ksl, blk, i);
 
     if (blk->leaf) {
-      assert(key_equal(ksl->compar, (ngtcp2_ksl_key *)node->key, old_key));
-      ksl_node_set_key(ksl, node, new_key);
+      assert(key_equal(ksl->compar, node_key, old_key));
+      ksl_set_nth_key(ksl, blk, i, new_key);
 
       return;
     }
 
-    if (key_equal(ksl->compar, (ngtcp2_ksl_key *)node->key, old_key) ||
-        ksl->compar((ngtcp2_ksl_key *)node->key, new_key)) {
-      ksl_node_set_key(ksl, node, new_key);
+    if (key_equal(ksl->compar, node_key, old_key) ||
+        ksl->compar(node_key, new_key)) {
+      ksl_set_nth_key(ksl, blk, i, new_key);
     }
 
     blk = node->blk;
@@ -727,14 +739,12 @@ void ngtcp2_ksl_clear(ngtcp2_ksl *ksl) {
 static void ksl_print(const ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk,
                       size_t level) {
   size_t i;
-  ngtcp2_ksl_node *node;
 
   fprintf(stderr, "LV=%zu n=%u\n", level, blk->n);
 
   if (blk->leaf) {
     for (i = 0; i < blk->n; ++i) {
-      node = ngtcp2_ksl_nth_node(ksl, blk, i);
-      fprintf(stderr, " %" PRId64, *(int64_t *)(void *)node->key);
+      fprintf(stderr, " %" PRId64, *(int64_t *)ngtcp2_ksl_nth_key(ksl, blk, i));
     }
 
     fprintf(stderr, "\n");
@@ -743,7 +753,7 @@ static void ksl_print(const ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk,
   }
 
   for (i = 0; i < blk->n; ++i) {
-    ksl_print(ksl, ngtcp2_ksl_nth_node(ksl, blk, i)->blk, level + 1);
+    ksl_print(ksl, blk->nodes[i].blk, level + 1);
   }
 }
 
index d5c3f61d2acc7bc690db530d4c151198a5cd6e6f..32f754c459694eab97e35019ca39cd961238166a 100644 (file)
@@ -55,22 +55,13 @@ typedef struct ngtcp2_ksl_blk ngtcp2_ksl_blk;
 /*
  * ngtcp2_ksl_node is a node which contains either ngtcp2_ksl_blk or
  * opaque data.  If a node is an internal node, it contains
- * ngtcp2_ksl_blk.  Otherwise, it has data.  The key is stored at the
- * location starting at key.
+ * ngtcp2_ksl_blk.  Otherwise, it has data.
  */
 struct ngtcp2_ksl_node {
   union {
     ngtcp2_ksl_blk *blk;
     void *data;
   };
-  union {
-    uint64_t align;
-    /* key is a buffer to include key associated to this node.
-       Because the length of key is unknown until ngtcp2_ksl_init is
-       called, the actual buffer will be allocated after this
-       field. */
-    uint8_t key[1];
-  };
 };
 
 /*
@@ -88,14 +79,14 @@ struct ngtcp2_ksl_blk {
       uint32_t n;
       /* leaf is nonzero if this block contains leaf nodes. */
       uint32_t leaf;
+      ngtcp2_ksl_node nodes[NGTCP2_KSL_MAX_NBLK];
       union {
         uint64_t align;
-        /* nodes is a buffer to contain NGTCP2_KSL_MAX_NBLK
-           ngtcp2_ksl_node objects.  Because ngtcp2_ksl_node object is
-           allocated along with the additional variable length key
-           storage, the size of buffer is unknown until ngtcp2_ksl_init is
-           called. */
-        uint8_t nodes[1];
+        /* keys is a buffer to include NGTCP2_KSL_MAX_NBLK keys.
+           Because the length of key is unknown until ngtcp2_ksl_init
+           is called, the actual buffer will be allocated after this
+           field. */
+        uint8_t keys[1];
       };
     };
 
@@ -131,11 +122,10 @@ typedef size_t (*ngtcp2_ksl_search)(const ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk,
   static size_t ksl_##NAME##_search(                                           \
     const ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, const ngtcp2_ksl_key *key) {   \
     size_t i;                                                                  \
-    ngtcp2_ksl_node *node;                                                     \
+    uint8_t *node_key;                                                         \
                                                                                \
-    for (i = 0, node = (ngtcp2_ksl_node *)(void *)blk->nodes;                  \
-         i < blk->n && COMPAR((ngtcp2_ksl_key *)node->key, key); ++i,          \
-        node = (ngtcp2_ksl_node *)(void *)((uint8_t *)node + ksl->nodelen))    \
+    for (i = 0, node_key = blk->keys; i < blk->n && COMPAR(node_key, key);     \
+         ++i, node_key += ksl->aligned_keylen)                                 \
       ;                                                                        \
                                                                                \
     return i;                                                                  \
@@ -169,9 +159,7 @@ struct ngtcp2_ksl {
   size_t n;
   /* keylen is the size of key */
   size_t keylen;
-  /* nodelen is the actual size of ngtcp2_ksl_node including key
-     storage. */
-  size_t nodelen;
+  size_t aligned_keylen;
 };
 
 /*
@@ -290,12 +278,11 @@ size_t ngtcp2_ksl_len(const ngtcp2_ksl *ksl);
 void ngtcp2_ksl_clear(ngtcp2_ksl *ksl);
 
 /*
- * ngtcp2_ksl_nth_node returns the |n|th node under |blk|.
+ * ngtcp2_ksl_nth_key returns the |n|th key under |blk|.
  */
-static inline ngtcp2_ksl_node *ngtcp2_ksl_nth_node(const ngtcp2_ksl *ksl,
-                                                   const ngtcp2_ksl_blk *blk,
-                                                   size_t n) {
-  return (ngtcp2_ksl_node *)(void *)(blk->nodes + ksl->nodelen * n);
+static inline const ngtcp2_ksl_key *
+ngtcp2_ksl_nth_key(const ngtcp2_ksl *ksl, const ngtcp2_ksl_blk *blk, size_t n) {
+  return blk->keys + n * ksl->aligned_keylen;
 }
 
 #ifndef WIN32
@@ -319,7 +306,7 @@ void ngtcp2_ksl_it_init(ngtcp2_ksl_it *it, const ngtcp2_ksl *ksl,
  * ngtcp2_ksl_it_end(it) returns nonzero.
  */
 static inline void *ngtcp2_ksl_it_get(const ngtcp2_ksl_it *it) {
-  return ngtcp2_ksl_nth_node(it->ksl, it->blk, it->i)->data;
+  return it->blk->nodes[it->i].data;
 }
 
 /*
@@ -361,8 +348,8 @@ int ngtcp2_ksl_it_begin(const ngtcp2_ksl_it *it);
  * It is undefined to call this function when ngtcp2_ksl_it_end(it)
  * returns nonzero.
  */
-static inline ngtcp2_ksl_key *ngtcp2_ksl_it_key(const ngtcp2_ksl_it *it) {
-  return (ngtcp2_ksl_key *)ngtcp2_ksl_nth_node(it->ksl, it->blk, it->i)->key;
+static inline const ngtcp2_ksl_key *ngtcp2_ksl_it_key(const ngtcp2_ksl_it *it) {
+  return ngtcp2_ksl_nth_key(it->ksl, it->blk, it->i);
 }
 
 /*
index 5c31f44a734334a45323797470b4cca7445dc4e3..d11e24455a23dfd3f2cf4687dc22cd7712ecd4fc 100644 (file)
@@ -42,7 +42,7 @@ void ngtcp2_log_init(ngtcp2_log *log, const ngtcp2_cid *scid,
                      ngtcp2_printf log_printf, ngtcp2_tstamp ts,
                      void *user_data) {
   if (scid) {
-    ngtcp2_encode_hex(log->scid, scid->data, scid->datalen);
+    ngtcp2_encode_hex_cstr(log->scid, scid->data, scid->datalen);
   } else {
     log->scid[0] = '\0';
   }
@@ -267,7 +267,7 @@ static void log_fr_connection_close(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
     fr->type == NGTCP2_FRAME_CONNECTION_CLOSE ? strerrorcode(fr->error_code)
                                               : strapperrorcode(fr->error_code),
     fr->error_code, fr->frame_type, fr->reasonlen,
-    ngtcp2_encode_printable_ascii(reason, fr->reason, reasonlen));
+    ngtcp2_encode_printable_ascii_cstr(reason, fr->reason, reasonlen));
 }
 
 static void log_fr_max_data(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
@@ -335,8 +335,8 @@ static void log_fr_streams_blocked(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
 static void log_fr_new_connection_id(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
                                      const ngtcp2_new_connection_id *fr,
                                      const char *dir) {
-  uint8_t buf[sizeof(fr->stateless_reset_token) * 2 + 1];
-  uint8_t cid[sizeof(fr->cid.data) * 2 + 1];
+  char buf[sizeof(fr->stateless_reset_token) * 2 + 1];
+  char cid[sizeof(fr->cid.data) * 2 + 1];
 
   ngtcp2_log_infof_raw(
     log, NGTCP2_LOG_EVENT_FRM,
@@ -344,10 +344,10 @@ static void log_fr_new_connection_id(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
                    " cid=0x%s retire_prior_to=%" PRIu64
                    " stateless_reset_token=0x%s",
     NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type, fr->seq,
-    (const char *)ngtcp2_encode_hex(cid, fr->cid.data, fr->cid.datalen),
+    ngtcp2_encode_hex_cstr(cid, fr->cid.data, fr->cid.datalen),
     fr->retire_prior_to,
-    (const char *)ngtcp2_encode_hex(buf, fr->stateless_reset_token,
-                                    sizeof(fr->stateless_reset_token)));
+    ngtcp2_encode_hex_cstr(buf, fr->stateless_reset_token,
+                           sizeof(fr->stateless_reset_token)));
 }
 
 static void log_fr_stop_sending(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
@@ -364,25 +364,25 @@ static void log_fr_stop_sending(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
 static void log_fr_path_challenge(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
                                   const ngtcp2_path_challenge *fr,
                                   const char *dir) {
-  uint8_t buf[sizeof(fr->data) * 2 + 1];
+  char buf[sizeof(fr->data) * 2 + 1];
 
-  ngtcp2_log_infof_raw(
-    log, NGTCP2_LOG_EVENT_FRM,
-    NGTCP2_LOG_PKT " PATH_CHALLENGE(0x%02" PRIx64 ") data=0x%s",
-    NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type,
-    (const char *)ngtcp2_encode_hex(buf, fr->data, sizeof(fr->data)));
+  ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_FRM,
+                       NGTCP2_LOG_PKT " PATH_CHALLENGE(0x%02" PRIx64
+                                      ") data=0x%s",
+                       NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type,
+                       ngtcp2_encode_hex_cstr(buf, fr->data, sizeof(fr->data)));
 }
 
 static void log_fr_path_response(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
                                  const ngtcp2_path_response *fr,
                                  const char *dir) {
-  uint8_t buf[sizeof(fr->data) * 2 + 1];
+  char buf[sizeof(fr->data) * 2 + 1];
 
-  ngtcp2_log_infof_raw(
-    log, NGTCP2_LOG_EVENT_FRM,
-    NGTCP2_LOG_PKT " PATH_RESPONSE(0x%02" PRIx64 ") data=0x%s",
-    NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type,
-    (const char *)ngtcp2_encode_hex(buf, fr->data, sizeof(fr->data)));
+  ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_FRM,
+                       NGTCP2_LOG_PKT " PATH_RESPONSE(0x%02" PRIx64
+                                      ") data=0x%s",
+                       NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type,
+                       ngtcp2_encode_hex_cstr(buf, fr->data, sizeof(fr->data)));
 }
 
 static void log_fr_crypto(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
@@ -398,21 +398,21 @@ static void log_fr_new_token(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
                              const ngtcp2_new_token *fr, const char *dir) {
   /* Show at most first 64 bytes of token.  If token is longer than 64
      bytes, log first 64 bytes and then append "*" */
-  uint8_t buf[128 + 1 + 1];
-  uint8_t *p;
+  char buf[128 + 1 + 1];
+  char *p;
 
   if (fr->tokenlen > 64) {
-    p = ngtcp2_encode_hex(buf, fr->token, 64);
+    p = ngtcp2_encode_hex_cstr(buf, fr->token, 64);
     p[128] = '*';
     p[129] = '\0';
   } else {
-    p = ngtcp2_encode_hex(buf, fr->token, fr->tokenlen);
+    p = ngtcp2_encode_hex_cstr(buf, fr->token, fr->tokenlen);
   }
 
   ngtcp2_log_infof_raw(
     log, NGTCP2_LOG_EVENT_FRM,
     NGTCP2_LOG_PKT " NEW_TOKEN(0x%02" PRIx64 ") token=0x%s len=%zu",
-    NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type, (const char *)p, fr->tokenlen);
+    NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type, p, fr->tokenlen);
 }
 
 static void log_fr_retire_connection_id(ngtcp2_log *log,
@@ -550,7 +550,7 @@ void ngtcp2_log_rx_vn(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
 }
 
 void ngtcp2_log_rx_sr(ngtcp2_log *log, const ngtcp2_pkt_stateless_reset *sr) {
-  uint8_t buf[sizeof(sr->stateless_reset_token) * 2 + 1];
+  char buf[sizeof(sr->stateless_reset_token) * 2 + 1];
   ngtcp2_pkt_hd shd;
   ngtcp2_pkt_hd *hd = &shd;
 
@@ -565,16 +565,16 @@ void ngtcp2_log_rx_sr(ngtcp2_log *log, const ngtcp2_pkt_stateless_reset *sr) {
   ngtcp2_log_infof_raw(
     log, NGTCP2_LOG_EVENT_PKT, NGTCP2_LOG_PKT " token=0x%s randlen=%zu",
     NGTCP2_LOG_PKT_HD_FIELDS("rx"),
-    (const char *)ngtcp2_encode_hex(buf, sr->stateless_reset_token,
-                                    sizeof(sr->stateless_reset_token)),
+    ngtcp2_encode_hex_cstr(buf, sr->stateless_reset_token,
+                           sizeof(sr->stateless_reset_token)),
     sr->randlen);
 }
 
 void ngtcp2_log_remote_tp(ngtcp2_log *log,
                           const ngtcp2_transport_params *params) {
-  uint8_t token[NGTCP2_STATELESS_RESET_TOKENLEN * 2 + 1];
-  uint8_t addr[16 * 2 + 7 + 1];
-  uint8_t cid[NGTCP2_MAX_CIDLEN * 2 + 1];
+  char token[NGTCP2_STATELESS_RESET_TOKENLEN * 2 + 1];
+  char addr[16 * 2 + 7 + 1];
+  char cid[NGTCP2_MAX_CIDLEN * 2 + 1];
   size_t i;
   const ngtcp2_sockaddr_in *sa_in;
   const ngtcp2_sockaddr_in6 *sa_in6;
@@ -588,18 +588,18 @@ void ngtcp2_log_remote_tp(ngtcp2_log *log,
   if (params->stateless_reset_token_present) {
     ngtcp2_log_infof_raw(
       log, NGTCP2_LOG_EVENT_CRY, NGTCP2_LOG_TP " stateless_reset_token=0x%s",
-      (const char *)ngtcp2_encode_hex(token, params->stateless_reset_token,
-                                      sizeof(params->stateless_reset_token)));
+      ngtcp2_encode_hex_cstr(token, params->stateless_reset_token,
+                             sizeof(params->stateless_reset_token)));
   }
 
   if (params->preferred_addr_present) {
     if (params->preferred_addr.ipv4_present) {
       sa_in = &params->preferred_addr.ipv4;
 
-      ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_CRY,
-                           NGTCP2_LOG_TP " preferred_address.ipv4_addr=%s",
-                           (const char *)ngtcp2_encode_ipv4(
-                             addr, (const uint8_t *)&sa_in->sin_addr));
+      ngtcp2_log_infof_raw(
+        log, NGTCP2_LOG_EVENT_CRY,
+        NGTCP2_LOG_TP " preferred_address.ipv4_addr=%s",
+        ngtcp2_encode_ipv4_cstr(addr, (const uint8_t *)&sa_in->sin_addr));
       ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_CRY,
                            NGTCP2_LOG_TP " preferred_address.ipv4_port=%u",
                            ngtcp2_ntohs(sa_in->sin_port));
@@ -608,10 +608,10 @@ void ngtcp2_log_remote_tp(ngtcp2_log *log,
     if (params->preferred_addr.ipv6_present) {
       sa_in6 = &params->preferred_addr.ipv6;
 
-      ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_CRY,
-                           NGTCP2_LOG_TP " preferred_address.ipv6_addr=%s",
-                           (const char *)ngtcp2_encode_ipv6(
-                             addr, (const uint8_t *)&sa_in6->sin6_addr));
+      ngtcp2_log_infof_raw(
+        log, NGTCP2_LOG_EVENT_CRY,
+        NGTCP2_LOG_TP " preferred_address.ipv6_addr=%s",
+        ngtcp2_encode_ipv6_cstr(addr, (const uint8_t *)&sa_in6->sin6_addr));
       ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_CRY,
                            NGTCP2_LOG_TP " preferred_address.ipv6_port=%u",
                            ngtcp2_ntohs(sa_in6->sin6_port));
@@ -619,38 +619,36 @@ void ngtcp2_log_remote_tp(ngtcp2_log *log,
 
     ngtcp2_log_infof_raw(
       log, NGTCP2_LOG_EVENT_CRY, NGTCP2_LOG_TP " preferred_address.cid=0x%s",
-      (const char *)ngtcp2_encode_hex(cid, params->preferred_addr.cid.data,
-                                      params->preferred_addr.cid.datalen));
+      ngtcp2_encode_hex_cstr(cid, params->preferred_addr.cid.data,
+                             params->preferred_addr.cid.datalen));
     ngtcp2_log_infof_raw(
       log, NGTCP2_LOG_EVENT_CRY,
       NGTCP2_LOG_TP " preferred_address.stateless_reset_token=0x%s",
-      (const char *)ngtcp2_encode_hex(
+      ngtcp2_encode_hex_cstr(
         token, params->preferred_addr.stateless_reset_token,
         sizeof(params->preferred_addr.stateless_reset_token)));
   }
 
   if (params->original_dcid_present) {
-    ngtcp2_log_infof_raw(
-      log, NGTCP2_LOG_EVENT_CRY,
-      NGTCP2_LOG_TP " original_destination_connection_id=0x%s",
-      (const char *)ngtcp2_encode_hex(cid, params->original_dcid.data,
-                                      params->original_dcid.datalen));
+    ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_CRY,
+                         NGTCP2_LOG_TP
+                         " original_destination_connection_id=0x%s",
+                         ngtcp2_encode_hex_cstr(cid, params->original_dcid.data,
+                                                params->original_dcid.datalen));
   }
 
   if (params->retry_scid_present) {
-    ngtcp2_log_infof_raw(
-      log, NGTCP2_LOG_EVENT_CRY,
-      NGTCP2_LOG_TP " retry_source_connection_id=0x%s",
-      (const char *)ngtcp2_encode_hex(cid, params->retry_scid.data,
-                                      params->retry_scid.datalen));
+    ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_CRY,
+                         NGTCP2_LOG_TP " retry_source_connection_id=0x%s",
+                         ngtcp2_encode_hex_cstr(cid, params->retry_scid.data,
+                                                params->retry_scid.datalen));
   }
 
   if (params->initial_scid_present) {
-    ngtcp2_log_infof_raw(
-      log, NGTCP2_LOG_EVENT_CRY,
-      NGTCP2_LOG_TP " initial_source_connection_id=0x%s",
-      (const char *)ngtcp2_encode_hex(cid, params->initial_scid.data,
-                                      params->initial_scid.datalen));
+    ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_CRY,
+                         NGTCP2_LOG_TP " initial_source_connection_id=0x%s",
+                         ngtcp2_encode_hex_cstr(cid, params->initial_scid.data,
+                                                params->initial_scid.datalen));
   }
 
   ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_CRY,
@@ -732,8 +730,8 @@ void ngtcp2_log_pkt_lost(ngtcp2_log *log, int64_t pkt_num, uint8_t type,
 
 static void log_pkt_hd(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
                        const char *dir) {
-  uint8_t dcid[sizeof(hd->dcid.data) * 2 + 1];
-  uint8_t scid[sizeof(hd->scid.data) * 2 + 1];
+  char dcid[sizeof(hd->dcid.data) * 2 + 1];
+  char scid[sizeof(hd->scid.data) * 2 + 1];
 
   if (!log->log_printf || !(log->events & NGTCP2_LOG_EVENT_PKT)) {
     return;
@@ -743,15 +741,15 @@ static void log_pkt_hd(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
     ngtcp2_log_infof(
       log, NGTCP2_LOG_EVENT_PKT, "%s pkn=%" PRId64 " dcid=0x%s type=%s k=%d",
       dir, hd->pkt_num,
-      (const char *)ngtcp2_encode_hex(dcid, hd->dcid.data, hd->dcid.datalen),
+      ngtcp2_encode_hex_cstr(dcid, hd->dcid.data, hd->dcid.datalen),
       strpkttype(hd), (hd->flags & NGTCP2_PKT_FLAG_KEY_PHASE) != 0);
   } else {
     ngtcp2_log_infof(
       log, NGTCP2_LOG_EVENT_PKT,
       "%s pkn=%" PRId64 " dcid=0x%s scid=0x%s version=0x%08x type=%s len=%zu",
       dir, hd->pkt_num,
-      (const char *)ngtcp2_encode_hex(dcid, hd->dcid.data, hd->dcid.datalen),
-      (const char *)ngtcp2_encode_hex(scid, hd->scid.data, hd->scid.datalen),
+      ngtcp2_encode_hex_cstr(dcid, hd->dcid.data, hd->dcid.datalen),
+      ngtcp2_encode_hex_cstr(scid, hd->scid.data, hd->scid.datalen),
       hd->version, strpkttype(hd), hd->len);
   }
 }
index 707cd3089e53cca8bda480ee16817f98d939fbb9..fabd5908e0d492d15ad414dc8eb64e1114a26b11 100644 (file)
@@ -49,7 +49,7 @@ typedef struct ngtcp2_log {
      log_pritnf. */
   void *user_data;
   /* scid is SCID encoded as NULL-terminated hex string. */
-  uint8_t scid[NGTCP2_MAX_CIDLEN * 2 + 1];
+  char scid[NGTCP2_MAX_CIDLEN * 2 + 1];
 } ngtcp2_log;
 
 /**
index 246c779f2908ca701efb54246d003b8761ef4493..6b332f6b58dbd800a252ea3dc0d5eec2e39101a4 100644 (file)
 #define NGTCP2_INITIAL_HASHBITS 4
 
 void ngtcp2_map_init(ngtcp2_map *map, uint64_t seed, const ngtcp2_mem *mem) {
-  map->mem = mem;
-  map->hashbits = 0;
-  map->table = NULL;
-  map->seed = seed;
-  map->size = 0;
+  *map = (ngtcp2_map){
+    .mem = mem,
+    .seed = seed,
+  };
 }
 
 void ngtcp2_map_free(ngtcp2_map *map) {
@@ -46,30 +45,27 @@ void ngtcp2_map_free(ngtcp2_map *map) {
     return;
   }
 
-  ngtcp2_mem_free(map->mem, map->table);
+  ngtcp2_mem_free(map->mem, map->keys);
 }
 
 int ngtcp2_map_each(const ngtcp2_map *map, int (*func)(void *data, void *ptr),
                     void *ptr) {
   int rv;
   size_t i;
-  ngtcp2_map_bucket *bkt;
   size_t tablelen;
 
   if (map->size == 0) {
     return 0;
   }
 
-  tablelen = 1u << map->hashbits;
+  tablelen = (size_t)1 << map->hashbits;
 
   for (i = 0; i < tablelen; ++i) {
-    bkt = &map->table[i];
-
-    if (bkt->data == NULL) {
+    if (map->psl[i] == 0) {
       continue;
     }
 
-    rv = func(bkt->data, ptr);
+    rv = func(map->data[i], ptr);
     if (rv != 0) {
       return rv;
     }
@@ -78,176 +74,228 @@ int ngtcp2_map_each(const ngtcp2_map *map, int (*func)(void *data, void *ptr),
   return 0;
 }
 
-static size_t map_hash(const ngtcp2_map *map, ngtcp2_map_key_type key) {
-  /* hasher from
-     https://github.com/rust-lang/rustc-hash/blob/dc5c33f1283de2da64d8d7a06401d91aded03ad4/src/lib.rs
-     We do not perform finalization here because we use top bits
-     anyway. */
-  key += map->seed;
-  key *= 0xf1357aea2e62a9c5ull;
-  return (size_t)((key * 11400714819323198485llu) >> (64 - map->hashbits));
-}
-
-static void map_bucket_swap(ngtcp2_map_bucket *a, ngtcp2_map_bucket *b) {
-  ngtcp2_map_bucket c = *a;
+/* Hasher from
+   https://github.com/rust-lang/rustc-hash/blob/dc5c33f1283de2da64d8d7a06401d91aded03ad4/src/lib.rs
+   to maximize the output's sensitivity to all input bits. */
+#define NGTCP2_MAP_HASHER 0xf1357aea2e62a9c5ull
+/* 64-bit Fibonacci hashing constant, Golden Ratio constant, to get
+   the high bits with the good distribution. */
+#define NGTCP2_MAP_FIBO 0x9e3779b97f4a7c15ull
 
-  *a = *b;
-  *b = c;
+static size_t map_index(const ngtcp2_map *map, ngtcp2_map_key_type key) {
+  key += map->seed;
+  key *= NGTCP2_MAP_HASHER;
+  return (size_t)((key * NGTCP2_MAP_FIBO) >> (64 - map->hashbits));
 }
 
 #ifndef WIN32
 void ngtcp2_map_print_distance(const ngtcp2_map *map) {
   size_t i;
   size_t idx;
-  ngtcp2_map_bucket *bkt;
   size_t tablelen;
 
   if (map->size == 0) {
     return;
   }
 
-  tablelen = 1u << map->hashbits;
+  tablelen = (size_t)1 << map->hashbits;
 
   for (i = 0; i < tablelen; ++i) {
-    bkt = &map->table[i];
-
-    if (bkt->data == NULL) {
+    if (map->psl[i] == 0) {
       fprintf(stderr, "@%zu <EMPTY>\n", i);
       continue;
     }
 
-    idx = map_hash(map, bkt->key);
-    fprintf(stderr, "@%zu hash=%zu key=%" PRIu64 " base=%zu distance=%u\n", i,
-            map_hash(map, bkt->key), bkt->key, idx, bkt->psl);
+    idx = map_index(map, map->keys[i]);
+    fprintf(stderr, "@%zu key=%" PRIu64 " base=%zu distance=%u\n", i,
+            map->keys[i], idx, map->psl[i] - 1);
   }
 }
 #endif /* !defined(WIN32) */
 
-static int map_insert(ngtcp2_map *map, ngtcp2_map_key_type key, void *data) {
-  size_t idx = map_hash(map, key);
-  ngtcp2_map_bucket b = {
-    .key = key,
-    .data = data,
-  };
-  ngtcp2_map_bucket *bkt;
-  size_t mask = (1u << map->hashbits) - 1;
+static void map_set_entry(ngtcp2_map *map, size_t idx, ngtcp2_map_key_type key,
+                          void *data, size_t psl) {
+  map->keys[idx] = key;
+  map->data[idx] = data;
+  map->psl[idx] = (uint8_t)psl;
+}
+
+#define NGTCP2_SWAP(TYPE, A, B)                                                \
+  do {                                                                         \
+    TYPE t = (TYPE) * (A);                                                     \
+                                                                               \
+    *(A) = *(B);                                                               \
+    *(B) = t;                                                                  \
+  } while (0)
+
+/*
+ * map_insert inserts |key| and |data| to |map|, and returns the index
+ * where the pair is stored if it succeeds.  Otherwise, it returns one
+ * of the following negative error codes:
+ *
+ * NGTCP2_ERR_INVALID_ARGUMENT
+ *     The another data associated to |key| is already present.
+ */
+static ngtcp2_ssize map_insert(ngtcp2_map *map, ngtcp2_map_key_type key,
+                               void *data) {
+  size_t idx = map_index(map, key);
+  size_t mask = ((size_t)1 << map->hashbits) - 1;
+  size_t psl = 1;
+  size_t kpsl;
 
   for (;;) {
-    bkt = &map->table[idx];
+    kpsl = map->psl[idx];
 
-    if (bkt->data == NULL) {
-      *bkt = b;
+    if (kpsl == 0) {
+      map_set_entry(map, idx, key, data, psl);
       ++map->size;
-      return 0;
+
+      return (ngtcp2_ssize)idx;
     }
 
-    if (b.psl > bkt->psl) {
-      map_bucket_swap(bkt, &b);
-    } else if (bkt->key == key) {
-      /* TODO This check is just a waste after first swap or if this
-         function is called from map_resize.  That said, there is no
-         difference with or without this conditional in performance
-         wise. */
+    if (psl > kpsl) {
+      NGTCP2_SWAP(ngtcp2_map_key_type, &key, &map->keys[idx]);
+      NGTCP2_SWAP(void *, &data, &map->data[idx]);
+      NGTCP2_SWAP(uint8_t, &psl, &map->psl[idx]);
+    } else if (map->keys[idx] == key) {
+      /* This check ensures that no duplicate keys are inserted.  But
+         it is just a waste after first swap or if this function is
+         called from map_resize.  That said, there is no difference
+         with or without this conditional in performance wise. */
       return NGTCP2_ERR_INVALID_ARGUMENT;
     }
 
-    ++b.psl;
+    ++psl;
     idx = (idx + 1) & mask;
   }
 }
 
+/* NGTCP2_MAP_MAX_HASHBITS is the maximum number of bits used for hash
+   table.  The theoretical limit of the maximum number of keys that
+   can be stored is 1 << NGTCP2_MAP_MAX_HASHBITS. */
+#define NGTCP2_MAP_MAX_HASHBITS (sizeof(size_t) * 8 - 1)
+
 static int map_resize(ngtcp2_map *map, size_t new_hashbits) {
   size_t i;
-  ngtcp2_map_bucket *bkt;
   size_t tablelen;
-  int rv;
+  ngtcp2_ssize idx;
   ngtcp2_map new_map = {
-    .table = ngtcp2_mem_calloc(map->mem, 1u << new_hashbits,
-                               sizeof(ngtcp2_map_bucket)),
     .mem = map->mem,
     .seed = map->seed,
     .hashbits = new_hashbits,
   };
-  (void)rv;
+  void *buf;
+  (void)idx;
 
-  if (new_map.table == NULL) {
+  if (new_hashbits > NGTCP2_MAP_MAX_HASHBITS) {
     return NGTCP2_ERR_NOMEM;
   }
 
+  tablelen = (size_t)1 << new_hashbits;
+
+  buf = ngtcp2_mem_calloc(map->mem, tablelen,
+                          sizeof(ngtcp2_map_key_type) + sizeof(void *) +
+                            sizeof(uint8_t));
+  if (buf == NULL) {
+    return NGTCP2_ERR_NOMEM;
+  }
+
+  new_map.keys = buf;
+  new_map.data =
+    (void *)((uint8_t *)new_map.keys + tablelen * sizeof(ngtcp2_map_key_type));
+  new_map.psl = (uint8_t *)new_map.data + tablelen * sizeof(void *);
+
   if (map->size) {
-    tablelen = 1u << map->hashbits;
+    tablelen = (size_t)1 << map->hashbits;
 
     for (i = 0; i < tablelen; ++i) {
-      bkt = &map->table[i];
-      if (bkt->data == NULL) {
+      if (map->psl[i] == 0) {
         continue;
       }
 
-      rv = map_insert(&new_map, bkt->key, bkt->data);
+      idx = map_insert(&new_map, map->keys[i], map->data[i]);
 
-      assert(0 == rv);
+      /* map_insert must not fail because all keys are unique during
+         resize. */
+      assert(idx >= 0);
     }
   }
 
-  ngtcp2_mem_free(map->mem, map->table);
-  map->table = new_map.table;
+  ngtcp2_mem_free(map->mem, map->keys);
+  map->keys = new_map.keys;
+  map->data = new_map.data;
+  map->psl = new_map.psl;
   map->hashbits = new_hashbits;
 
   return 0;
 }
 
+/* NGTCP2_MAX_PSL_RESIZE_THRESH is the maximum psl threshold.  If
+   reached, resize the table. */
+#define NGTCP2_MAX_PSL_RESIZE_THRESH 128
+
 int ngtcp2_map_insert(ngtcp2_map *map, ngtcp2_map_key_type key, void *data) {
   int rv;
+  size_t tablelen;
+  ngtcp2_ssize idx;
 
   assert(data);
 
-  /* Load factor is 7/8 */
-  /* Under the very initial condition, that is map->size == 0 and
-     map->hashbits == 0, 8 > 7 still holds nicely. */
-  if ((map->size + 1) * 8 > (1u << map->hashbits) * 7) {
-    if (map->hashbits) {
-      rv = map_resize(map, map->hashbits + 1);
-      if (rv != 0) {
-        return rv;
-      }
-    } else {
-      rv = map_resize(map, NGTCP2_INITIAL_HASHBITS);
-      if (rv != 0) {
-        return rv;
-      }
+  /* tablelen is incorrect if map->hashbits == 0 which leads to
+     tablelen = 1, but it is only used to check the load factor, and
+     it works in this special case. */
+  tablelen = (size_t)1 << map->hashbits;
+
+  /* Load factor is 7 / 8.  Because tablelen is power of 2, (tablelen
+     - (tablelen >> 3)) computes tablelen * 7 / 8. */
+  if (map->size + 1 >= (tablelen - (tablelen >> 3))) {
+    rv = map_resize(map, map->hashbits ? map->hashbits + 1
+                                       : NGTCP2_INITIAL_HASHBITS);
+    if (rv != 0) {
+      return rv;
     }
+
+    idx = map_insert(map, key, data);
+    if (idx < 0) {
+      return (int)idx;
+    }
+
+    return 0;
   }
 
-  rv = map_insert(map, key, data);
-  if (rv != 0) {
-    return rv;
+  idx = map_insert(map, key, data);
+  if (idx < 0) {
+    return (int)idx;
   }
 
-  return 0;
+  /* Resize if psl reaches really large value which is almost
+     improbable, but just in case. */
+  if (map->psl[idx] - 1 < NGTCP2_MAX_PSL_RESIZE_THRESH) {
+    return 0;
+  }
+
+  return map_resize(map, map->hashbits + 1);
 }
 
 void *ngtcp2_map_find(const ngtcp2_map *map, ngtcp2_map_key_type key) {
   size_t idx;
-  ngtcp2_map_bucket *bkt;
-  size_t psl = 0;
+  size_t psl = 1;
   size_t mask;
 
   if (map->size == 0) {
     return NULL;
   }
 
-  idx = map_hash(map, key);
-  mask = (1u << map->hashbits) - 1;
+  idx = map_index(map, key);
+  mask = ((size_t)1 << map->hashbits) - 1;
 
   for (;;) {
-    bkt = &map->table[idx];
-
-    if (bkt->data == NULL || psl > bkt->psl) {
+    if (psl > map->psl[idx]) {
       return NULL;
     }
 
-    if (bkt->key == key) {
-      return bkt->data;
+    if (map->keys[idx] == key) {
+      return map->data[idx];
     }
 
     ++psl;
@@ -257,38 +305,36 @@ void *ngtcp2_map_find(const ngtcp2_map *map, ngtcp2_map_key_type key) {
 
 int ngtcp2_map_remove(ngtcp2_map *map, ngtcp2_map_key_type key) {
   size_t idx;
-  ngtcp2_map_bucket *b, *bkt;
-  size_t psl = 0;
+  size_t dest;
+  size_t psl = 1, kpsl;
   size_t mask;
 
   if (map->size == 0) {
     return NGTCP2_ERR_INVALID_ARGUMENT;
   }
 
-  idx = map_hash(map, key);
-  mask = (1u << map->hashbits) - 1;
+  idx = map_index(map, key);
+  mask = ((size_t)1 << map->hashbits) - 1;
 
   for (;;) {
-    bkt = &map->table[idx];
-
-    if (bkt->data == NULL || psl > bkt->psl) {
+    if (psl > map->psl[idx]) {
       return NGTCP2_ERR_INVALID_ARGUMENT;
     }
 
-    if (bkt->key == key) {
-      b = bkt;
+    if (map->keys[idx] == key) {
+      dest = idx;
       idx = (idx + 1) & mask;
 
       for (;;) {
-        bkt = &map->table[idx];
-        if (bkt->data == NULL || bkt->psl == 0) {
-          b->data = NULL;
+        kpsl = map->psl[idx];
+        if (kpsl <= 1) {
+          map->psl[dest] = 0;
           break;
         }
 
-        --bkt->psl;
-        *b = *bkt;
-        b = bkt;
+        map_set_entry(map, dest, map->keys[idx], map->data[idx], kpsl - 1);
+
+        dest = idx;
 
         idx = (idx + 1) & mask;
       }
@@ -308,7 +354,7 @@ void ngtcp2_map_clear(ngtcp2_map *map) {
     return;
   }
 
-  memset(map->table, 0, sizeof(*map->table) * (1u << map->hashbits));
+  memset(map->psl, 0, sizeof(*map->psl) * ((size_t)1 << map->hashbits));
   map->size = 0;
 }
 
index 0c1a76552aa4c4edee287cd85f7d51c635ffe564..1afe3167e65b850a2e36617a0b222ae261b3059e 100644 (file)
 
 typedef uint64_t ngtcp2_map_key_type;
 
-typedef struct ngtcp2_map_bucket {
-  uint32_t psl;
-  ngtcp2_map_key_type key;
-  void *data;
-} ngtcp2_map_bucket;
-
 typedef struct ngtcp2_map {
-  ngtcp2_map_bucket *table;
+  ngtcp2_map_key_type *keys;
+  void **data;
+  /* psl is the Probe Sequence Length.  0 has special meaning that the
+     element is not stored at i-th position if psl[i] == 0.  Because
+     of this, the actual psl value is psl[i] - 1 if psl[i] > 0. */
+  uint8_t *psl;
   const ngtcp2_mem *mem;
   uint64_t seed;
   size_t size;
index 832387300335377beded278d7e67e55077e223e2..c9636a8db9a90f32c5696ae4dea9905364dcbdb1 100644 (file)
 
 #include "ngtcp2_addr.h"
 
-void ngtcp2_path_init(ngtcp2_path *path, const ngtcp2_addr *local,
-                      const ngtcp2_addr *remote) {
-  path->local = *local;
-  path->remote = *remote;
-}
-
 void ngtcp2_path_copy(ngtcp2_path *dest, const ngtcp2_path *src) {
   ngtcp2_addr_copy(&dest->local, &src->local);
   ngtcp2_addr_copy(&dest->remote, &src->remote);
index a708378db32fbbd45b86637d6627bfbc10f8306a..9d4205cee2279fbe7d51e15f4c56d3a50d500784 100644 (file)
 
 #include <ngtcp2/ngtcp2.h>
 
-/*
- * ngtcp2_path_init initializes |path| with the given addresses.  Note
- * that the buffer pointed by local->addr and remote->addr are not
- * copied.  Their pointer values are assigned instead.
- */
-void ngtcp2_path_init(ngtcp2_path *path, const ngtcp2_addr *local,
-                      const ngtcp2_addr *remote);
-
 /*
  * ngtcp2_path_storage_init2 initializes |ps| using |path| as initial
  * data.
index 9d0eb57e0db9404a3fa7851f441b03f298591376..c8490467e436149b3df898573a2f79ee4b7e430d 100644 (file)
@@ -66,7 +66,7 @@ void ngtcp2_pcg32_init(ngtcp2_pcg32 *pcg, uint64_t seed) {
 }
 
 static uint32_t pcg_rotr_32(uint32_t value, unsigned int rot) {
-  return (value >> rot) | (value << ((-rot) & 31));
+  return (value >> rot) | (value << ((32 - rot) & 31));
 }
 
 static uint32_t pcg_output_xsh_rr_64_32(uint64_t state) {
index d63dc932e1bfb45005d335674fec94a85262a1d4..db9ecf8313d6823518d997837c5ae9857ad2f6e4 100644 (file)
@@ -918,7 +918,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_connection_close_frame(
     return NGTCP2_ERR_FRAME_ENCODING;
   }
 
-  p = ngtcp2_get_uvarint(&vi, p);
+  ngtcp2_get_uvarint(&vi, p);
   if (payloadlen - len < vi) {
     return NGTCP2_ERR_FRAME_ENCODING;
   }
@@ -1053,6 +1053,8 @@ ngtcp2_ssize ngtcp2_pkt_decode_ping_frame(ngtcp2_ping *dest,
   (void)payload;
   (void)payloadlen;
 
+  assert(payloadlen > 0);
+
   dest->type = NGTCP2_FRAME_PING;
   return 1;
 }
@@ -1321,7 +1323,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_crypto_frame(ngtcp2_stream *dest,
     return NGTCP2_ERR_FRAME_ENCODING;
   }
 
-  p = ngtcp2_get_uvarint(&vi, p);
+  ngtcp2_get_uvarint(&vi, p);
   if (payloadlen - len < vi) {
     return NGTCP2_ERR_FRAME_ENCODING;
   }
@@ -1428,6 +1430,8 @@ ngtcp2_ssize ngtcp2_pkt_decode_handshake_done_frame(ngtcp2_handshake_done *dest,
   (void)payload;
   (void)payloadlen;
 
+  assert(payloadlen > 0);
+
   dest->type = NGTCP2_FRAME_HANDSHAKE_DONE;
   return 1;
 }
@@ -1442,9 +1446,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_datagram_frame(ngtcp2_datagram *dest,
   size_t n;
   uint64_t vi;
 
-  if (payloadlen < len) {
-    return NGTCP2_ERR_FRAME_ENCODING;
-  }
+  assert(payloadlen > 0);
 
   type = payload[0];
 
index 19667e17dba3ac898829174cfc4969afe19c1c46..b8a94b7c9564d3859e18fd8bc7d2e6aa4e1daa05 100644 (file)
@@ -55,15 +55,9 @@ static uint8_t *write_string_impl(uint8_t *p, const uint8_t *data,
 #define write_string(DEST, S)                                                  \
   write_string_impl((DEST), (const uint8_t *)(S), sizeof(S) - 1)
 
-#define NGTCP2_LOWER_XDIGITS "0123456789abcdef"
-
 static uint8_t *write_hex(uint8_t *p, const uint8_t *data, size_t datalen) {
-  const uint8_t *b = data, *end = data + datalen;
   *p++ = '"';
-  for (; b != end; ++b) {
-    *p++ = (uint8_t)NGTCP2_LOWER_XDIGITS[*b >> 4];
-    *p++ = (uint8_t)NGTCP2_LOWER_XDIGITS[*b & 0xf];
-  }
+  p = ngtcp2_encode_hex(p, data, datalen);
   *p++ = '"';
   return p;
 }
@@ -72,31 +66,12 @@ static uint8_t *write_cid(uint8_t *p, const ngtcp2_cid *cid) {
   return write_hex(p, cid->data, cid->datalen);
 }
 
-static uint8_t *write_number(uint8_t *p, uint64_t n) {
-  size_t nlen = 0;
-  uint64_t t;
-  uint8_t *res;
-
-  if (n == 0) {
-    *p++ = '0';
-    return p;
-  }
-  for (t = n; t; t /= 10, ++nlen)
-    ;
-  p += nlen;
-  res = p;
-  for (; n; n /= 10) {
-    *--p = (uint8_t)((n % 10) + '0');
-  }
-  return res;
-}
-
 static uint8_t *write_tstamp(uint8_t *p, ngtcp2_tstamp ts) {
-  return write_number(p, ts / NGTCP2_MILLISECONDS);
+  return ngtcp2_encode_uint(p, ts / NGTCP2_MILLISECONDS);
 }
 
 static uint8_t *write_duration(uint8_t *p, ngtcp2_duration duration) {
-  return write_number(p, duration / NGTCP2_MILLISECONDS);
+  return ngtcp2_encode_uint(p, duration / NGTCP2_MILLISECONDS);
 }
 
 static uint8_t *write_bool(uint8_t *p, int b) {
@@ -132,7 +107,7 @@ static uint8_t *write_pair_number_impl(uint8_t *p, const uint8_t *name,
                                        size_t namelen, uint64_t value) {
   p = write_string_impl(p, name, namelen);
   *p++ = ':';
-  return write_number(p, value);
+  return ngtcp2_encode_uint(p, value);
 }
 
 #define write_pair_number(DEST, NAME, VALUE)                                   \
@@ -338,10 +313,10 @@ static uint8_t *write_ack_frame(uint8_t *p, const ngtcp2_ack *fr) {
   min_ack = fr->largest_ack - (int64_t)fr->first_ack_range;
 
   *p++ = '[';
-  p = write_number(p, (uint64_t)min_ack);
+  p = ngtcp2_encode_uint(p, (uint64_t)min_ack);
   if (largest_ack != min_ack) {
     *p++ = ',';
-    p = write_number(p, (uint64_t)largest_ack);
+    p = ngtcp2_encode_uint(p, (uint64_t)largest_ack);
   }
   *p++ = ']';
 
@@ -351,10 +326,10 @@ static uint8_t *write_ack_frame(uint8_t *p, const ngtcp2_ack *fr) {
     min_ack = largest_ack - (int64_t)range->len;
     *p++ = ',';
     *p++ = '[';
-    p = write_number(p, (uint64_t)min_ack);
+    p = ngtcp2_encode_uint(p, (uint64_t)min_ack);
     if (largest_ack != min_ack) {
       *p++ = ',';
-      p = write_number(p, (uint64_t)largest_ack);
+      p = ngtcp2_encode_uint(p, (uint64_t)largest_ack);
     }
     *p++ = ']';
   }
@@ -736,7 +711,7 @@ static void qlog_pkt_write_end(ngtcp2_qlog *qlog, const ngtcp2_pkt_hd *hd,
   p = write_verbatim(p, "],\"header\":");
   p = write_pkt_hd(p, hd);
   p = write_verbatim(p, ",\"raw\":{\"length\":");
-  p = write_number(p, pktlen);
+  p = ngtcp2_encode_uint(p, pktlen);
   p = write_verbatim(p, "}}}\n");
 
   qlog->buf.last = p;
index ef1938ea6326ca59b2d7ab3ff4091731950358e0..20eae1d88191339541eaf51ca76b0a64442dc038 100644 (file)
@@ -36,8 +36,13 @@ int ngtcp2_rob_gap_new(ngtcp2_rob_gap **pg, uint64_t begin, uint64_t end,
     return NGTCP2_ERR_NOMEM;
   }
 
-  (*pg)->range.begin = begin;
-  (*pg)->range.end = end;
+  **pg = (ngtcp2_rob_gap){
+    .range =
+      {
+        .begin = begin,
+        .end = end,
+      },
+  };
 
   return 0;
 }
@@ -53,9 +58,14 @@ int ngtcp2_rob_data_new(ngtcp2_rob_data **pd, uint64_t offset, size_t chunk,
     return NGTCP2_ERR_NOMEM;
   }
 
-  (*pd)->range.begin = offset;
-  (*pd)->range.end = offset + chunk;
-  (*pd)->begin = (uint8_t *)(*pd) + sizeof(ngtcp2_rob_data);
+  **pd = (ngtcp2_rob_data){
+    .range =
+      {
+        .begin = offset,
+        .end = offset + chunk,
+      },
+    .begin = (uint8_t *)(*pd) + sizeof(ngtcp2_rob_data),
+  };
 
   return 0;
 }
@@ -254,9 +264,11 @@ void ngtcp2_rob_remove_prefix(ngtcp2_rob *rob, uint64_t offset) {
     }
 
     if (offset < g->range.end) {
-      ngtcp2_range r = {offset, g->range.end};
-
-      ngtcp2_ksl_update_key(&rob->gapksl, &g->range, &r);
+      ngtcp2_ksl_update_key(&rob->gapksl, &g->range,
+                            &(ngtcp2_range){
+                              .begin = offset,
+                              .end = g->range.end,
+                            });
       g->range.begin = offset;
 
       break;
index 77247108ec469ff7e1cadc5a4c3027fec5d0d3a7..89b395cd954b0d8015cf995abb5df64f9b766846 100644 (file)
 #include "ngtcp2_conn_stat.h"
 
 void ngtcp2_rs_init(ngtcp2_rs *rs) {
-  rs->interval = UINT64_MAX;
-  rs->delivered = 0;
-  rs->prior_delivered = 0;
-  rs->prior_ts = UINT64_MAX;
-  rs->tx_in_flight = 0;
-  rs->lost = 0;
-  rs->send_elapsed = 0;
-  rs->ack_elapsed = 0;
-  rs->last_end_seq = -1;
-  rs->is_app_limited = 0;
+  *rs = (ngtcp2_rs){
+    .interval = UINT64_MAX,
+    .prior_ts = UINT64_MAX,
+    .last_end_seq = -1,
+  };
 }
 
 void ngtcp2_rst_init(ngtcp2_rst *rst) {
index 5908fcc5c5c39e268c6bf254eafe443ac85e92f7..ae68d93e9597a29773775f956763100f711ef78b 100644 (file)
@@ -531,9 +531,10 @@ static void rtb_remove(ngtcp2_rtb *rtb, ngtcp2_ksl_it *it,
   int rv;
   (void)rv;
 
+  rtb_on_remove(rtb, ent, cstat);
+
   rv = ngtcp2_ksl_remove_hint(&rtb->ents, it, it, &ent->hd.pkt_num);
   assert(0 == rv);
-  rtb_on_remove(rtb, ent, cstat);
 
   assert(ent->next == NULL);
 
@@ -895,11 +896,7 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr,
     cc_ack.rtt = ngtcp2_max_uint64(pkt_ts - cc_ack.largest_pkt_sent_ts,
                                    NGTCP2_NANOSECONDS);
 
-    rv = ngtcp2_conn_update_rtt(conn, cc_ack.rtt, fr->ack_delay_unscaled, ts);
-    if (rv == 0 && cc->new_rtt_sample &&
-        rtb->largest_acked_tx_pkt_num >= rtb->cc_pkt_num) {
-      cc->new_rtt_sample(cc, cstat, ts);
-    }
+    ngtcp2_conn_update_rtt(conn, cc_ack.rtt, fr->ack_delay_unscaled, ts);
   }
 
   if (conn) {
@@ -1193,12 +1190,12 @@ static int rtb_detect_lost_pkt(ngtcp2_rtb *rtb, ngtcp2_cc_ack *cc_ack,
 int ngtcp2_rtb_detect_lost_pkt(ngtcp2_rtb *rtb, ngtcp2_conn *conn,
                                ngtcp2_pktns *pktns, ngtcp2_conn_stat *cstat,
                                ngtcp2_tstamp ts) {
-  ngtcp2_cc_ack cc_ack = {
-    .largest_pkt_sent_ts = UINT64_MAX,
-    .rtt = UINT64_MAX,
-  };
-
-  return rtb_detect_lost_pkt(rtb, &cc_ack, conn, pktns, cstat, ts);
+  return rtb_detect_lost_pkt(rtb,
+                             &(ngtcp2_cc_ack){
+                               .largest_pkt_sent_ts = UINT64_MAX,
+                               .rtt = UINT64_MAX,
+                             },
+                             conn, pktns, cstat, ts);
 }
 
 void ngtcp2_rtb_remove_excessive_lost_pkt(ngtcp2_rtb *rtb, size_t n) {
@@ -1251,8 +1248,9 @@ void ngtcp2_rtb_remove_expired_lost_pkt(ngtcp2_rtb *rtb,
     ngtcp2_ksl_it_prev(&it);
     ent = ngtcp2_ksl_it_get(&it);
 
-    if (!(ent->flags & NGTCP2_RTB_ENTRY_FLAG_LOST_RETRANSMITTED) ||
-        ts - ent->lost_ts < timeout) {
+    assert(ent->flags & NGTCP2_RTB_ENTRY_FLAG_LOST_RETRANSMITTED);
+
+    if (ts - ent->lost_ts < timeout) {
       return;
     }
 
@@ -1412,12 +1410,19 @@ int ngtcp2_rtb_reclaim_on_retry(ngtcp2_rtb *rtb, ngtcp2_conn *conn,
       ngtcp2_log_infof(rtb->log, NGTCP2_LOG_EVENT_LDC,
                        "pkn=%" PRId64 " has already been reclaimed on PTO",
                        ent->hd.pkt_num);
+
+      ngtcp2_rtb_entry_objalloc_del(ent, rtb->rtb_entry_objalloc,
+                                    rtb->frc_objalloc, rtb->mem);
+
       continue;
     }
 
     if (!(ent->flags & NGTCP2_RTB_ENTRY_FLAG_RETRANSMITTABLE) &&
         (!(ent->flags & NGTCP2_RTB_ENTRY_FLAG_DATAGRAM) ||
          !conn->callbacks.lost_datagram)) {
+      ngtcp2_rtb_entry_objalloc_del(ent, rtb->rtb_entry_objalloc,
+                                    rtb->frc_objalloc, rtb->mem);
+
       continue;
     }
 
index caa0fb58c58b137ea025867d5d2f68a9707c0ac9..28b91d8d36ff72e0c547da20a626712f24bd6d46 100644 (file)
 
 /* NGTCP2_DEFAULT_GLITCH_RATELIM_BURST is the maximum number of tokens
    in glitch rate limiter.  It is also the initial value. */
-#define NGTCP2_DEFAULT_GLITCH_RATELIM_BURST 1000
+#define NGTCP2_DEFAULT_GLITCH_RATELIM_BURST 4000
 /* NGTCP2_DEFAULT_GLITCH_RATELIM_RATE is the rate of tokens generated
    per second for glitch rate limiter. */
-#define NGTCP2_DEFAULT_GLITCH_RATELIM_RATE 33
+#define NGTCP2_DEFAULT_GLITCH_RATELIM_RATE 132
 
 /*
  * ngtcp2_settings_convert_to_latest converts |src| of version
index a61636d188fae5c0506b2e43cd8ba5d2a02c2c21..01f270604351af6bfd8b041f30488b0c226f3b74 100644 (file)
@@ -54,13 +54,19 @@ uint8_t *ngtcp2_encode_hex(uint8_t *dest, const uint8_t *data, size_t len) {
     *p++ = (uint8_t)LOWER_XDIGITS[data[i] & 0xf];
   }
 
+  return p;
+}
+
+char *ngtcp2_encode_hex_cstr(char *dest, const uint8_t *data, size_t len) {
+  uint8_t *p = ngtcp2_encode_hex((uint8_t *)dest, data, len);
+
   *p = '\0';
 
   return dest;
 }
 
-char *ngtcp2_encode_printable_ascii(char *dest, const uint8_t *data,
-                                    size_t len) {
+char *ngtcp2_encode_printable_ascii_cstr(char *dest, const uint8_t *data,
+                                         size_t len) {
   size_t i;
   char *p = dest;
   uint8_t c;
@@ -79,40 +85,15 @@ char *ngtcp2_encode_printable_ascii(char *dest, const uint8_t *data,
   return dest;
 }
 
-/*
- * write_uint writes |n| to the buffer pointed by |p| in decimal
- * representation.  It returns |p| plus the number of bytes written.
- * The function assumes that the buffer has enough capacity to contain
- * a string.
- */
-static uint8_t *write_uint(uint8_t *p, uint64_t n) {
-  size_t nlen = 0;
-  uint64_t t;
-  uint8_t *res;
-
-  if (n == 0) {
-    *p++ = '0';
-    return p;
-  }
-  for (t = n; t; t /= 10, ++nlen)
-    ;
-  p += nlen;
-  res = p;
-  for (; n; n /= 10) {
-    *--p = (uint8_t)((n % 10) + '0');
-  }
-  return res;
-}
-
-uint8_t *ngtcp2_encode_ipv4(uint8_t *dest, const uint8_t *addr) {
+char *ngtcp2_encode_ipv4_cstr(char *dest, const uint8_t *addr) {
   size_t i;
-  uint8_t *p = dest;
+  char *p = dest;
 
-  p = write_uint(p, addr[0]);
+  p = (char *)ngtcp2_encode_uint((uint8_t *)p, addr[0]);
 
   for (i = 1; i < 4; ++i) {
     *p++ = '.';
-    p = write_uint(p, addr[i]);
+    p = (char *)ngtcp2_encode_uint((uint8_t *)p, addr[i]);
   }
 
   *p = '\0';
@@ -125,9 +106,9 @@ uint8_t *ngtcp2_encode_ipv4(uint8_t *dest, const uint8_t *addr) {
  * length |len| to |dest| in hex string.  Any leading zeros are
  * suppressed.  It returns |dest| plus the number of bytes written.
  */
-static uint8_t *write_hex_zsup(uint8_t *dest, const uint8_t *data, size_t len) {
+static char *write_hex_zsup(char *dest, const uint8_t *data, size_t len) {
   size_t i;
-  uint8_t *p = dest;
+  char *p = dest;
   uint8_t d;
 
   for (i = 0; i < len; ++i) {
@@ -139,7 +120,7 @@ static uint8_t *write_hex_zsup(uint8_t *dest, const uint8_t *data, size_t len) {
     d &= 0xf;
 
     if (d) {
-      *p++ = (uint8_t)LOWER_XDIGITS[d];
+      *p++ = LOWER_XDIGITS[d];
       ++i;
       break;
     }
@@ -152,19 +133,19 @@ static uint8_t *write_hex_zsup(uint8_t *dest, const uint8_t *data, size_t len) {
 
   for (; i < len; ++i) {
     d = data[i];
-    *p++ = (uint8_t)LOWER_XDIGITS[d >> 4];
-    *p++ = (uint8_t)LOWER_XDIGITS[d & 0xf];
+    *p++ = LOWER_XDIGITS[d >> 4];
+    *p++ = LOWER_XDIGITS[d & 0xf];
   }
 
   return p;
 }
 
-uint8_t *ngtcp2_encode_ipv6(uint8_t *dest, const uint8_t *addr) {
+char *ngtcp2_encode_ipv6_cstr(char *dest, const uint8_t *addr) {
   uint16_t blks[8];
   size_t i;
   size_t zlen, zoff;
   size_t max_zlen = 0, max_zoff = 8;
-  uint8_t *p = dest;
+  char *p = dest;
 
   for (i = 0; i < 16; i += sizeof(uint16_t)) {
     /* Copy in network byte order. */
@@ -231,3 +212,124 @@ int ngtcp2_cmemeq(const uint8_t *a, const uint8_t *b, size_t n) {
 
   return rv == 0;
 }
+
+/* countl_zero counts the number of leading zeros in |x|.  It is
+   undefined if |x| is 0. */
+static int countl_zero(uint64_t x) {
+#ifdef __GNUC__
+  return __builtin_clzll(x);
+#else  /* !defined(__GNUC__) */
+  /* This is the same implementation of Go's LeadingZeros64 in
+     math/bits package. */
+  static const uint8_t len8tab[] = {
+    0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
+    5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
+    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+    7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+  };
+  int n = 0;
+
+  if (x >= 1ull << 32) {
+    x >>= 32;
+    n += 32;
+  }
+
+  if (x >= 1 << 16) {
+    x >>= 16;
+    n += 16;
+  }
+
+  if (x >= 1 << 8) {
+    x >>= 8;
+    n += 8;
+  }
+
+  return 64 - (n + len8tab[x]);
+#endif /* !defined(__GNUC__) */
+}
+
+/*
+ * count_digit returns the minimum number of digits to represent |x|
+ * in base 10.
+ *
+ * credit:
+ * https://lemire.me/blog/2025/01/07/counting-the-digits-of-64-bit-integers/
+ */
+static size_t count_digit(uint64_t x) {
+  static const uint64_t count_digit_tbl[] = {
+    9ull,
+    99ull,
+    999ull,
+    9999ull,
+    99999ull,
+    999999ull,
+    9999999ull,
+    99999999ull,
+    999999999ull,
+    9999999999ull,
+    99999999999ull,
+    999999999999ull,
+    9999999999999ull,
+    99999999999999ull,
+    999999999999999ull,
+    9999999999999999ull,
+    99999999999999999ull,
+    999999999999999999ull,
+    9999999999999999999ull,
+  };
+  size_t y = (size_t)(19 * (63 - countl_zero(x | 1)) >> 6);
+
+  y += x > count_digit_tbl[y];
+
+  return y + 1;
+}
+
+uint8_t *ngtcp2_encode_uint(uint8_t *dest, uint64_t n) {
+  static const uint8_t uint_digits[] =
+    "00010203040506070809101112131415161718192021222324252627282930313233343536"
+    "37383940414243444546474849505152535455565758596061626364656667686970717273"
+    "7475767778798081828384858687888990919293949596979899";
+  uint8_t *p;
+  const uint8_t *tp;
+
+  if (n < 10) {
+    *dest++ = (uint8_t)('0' + n);
+    return dest;
+  }
+
+  if (n < 100) {
+    tp = &uint_digits[n * 2];
+    *dest++ = *tp++;
+    *dest++ = *tp;
+    return dest;
+  }
+
+  dest += count_digit(n);
+  p = dest;
+
+  for (; n >= 100; n /= 100) {
+    p -= 2;
+    tp = &uint_digits[(n % 100) * 2];
+    p[0] = *tp++;
+    p[1] = *tp;
+  }
+
+  if (n < 10) {
+    *--p = (uint8_t)('0' + n);
+    return dest;
+  }
+
+  p -= 2;
+  tp = &uint_digits[n * 2];
+  p[0] = *tp++;
+  p[1] = *tp;
+
+  return dest;
+}
index f970c153e805a89435686af0d13fa57114aa5074..051053d75b7c042f0fd2c765c4ba87c0e6f95397 100644 (file)
@@ -46,24 +46,31 @@ uint8_t *ngtcp2_setmem(uint8_t *dest, uint8_t b, size_t n);
 const void *ngtcp2_get_bytes(void *dest, const void *src, size_t n);
 
 /*
- * ngtcp2_encode_hex encodes |data| of length |len| in hex string.  It
- * writes additional NULL bytes at the end of the buffer.  The buffer
- * pointed by |dest| must have at least |len| * 2 + 1 bytes space.
- * This function returns |dest|.
+ * ngtcp2_encode_hex encodes |data| of length |len| in hex string.
+ * The buffer pointed by |dest| must have at least |len| * 2 bytes
+ * space.  This function returns |dest| + |len| * 2.
  */
 uint8_t *ngtcp2_encode_hex(uint8_t *dest, const uint8_t *data, size_t len);
 
 /*
- * ngtcp2_encode_ipv4 encodes binary form IPv4 address stored in
+ * ngtcp2_encode_hex_cstr encodes |data| of length |len| in hex
+ * string.  It writes additional NULL bytes at the end of the buffer.
+ * The buffer pointed by |dest| must have at least |len| * 2 + 1 bytes
+ * space.  This function returns |dest|.
+ */
+char *ngtcp2_encode_hex_cstr(char *dest, const uint8_t *data, size_t len);
+
+/*
+ * ngtcp2_encode_ipv4_cstr encodes binary form IPv4 address stored in
  * |addr| to human readable text form in the buffer pointed by |dest|.
  * The capacity of buffer must have enough length to store a text form
  * plus a terminating NULL byte.  The resulting text form ends with
  * NULL byte.  The function returns |dest|.
  */
-uint8_t *ngtcp2_encode_ipv4(uint8_t *dest, const uint8_t *addr);
+char *ngtcp2_encode_ipv4_cstr(char *dest, const uint8_t *addr);
 
 /*
- * ngtcp2_encode_ipv6 encodes binary form IPv6 address stored in
+ * ngtcp2_encode_ipv6_cstr encodes binary form IPv6 address stored in
  * |addr| to human readable text form in the buffer pointed by |dest|.
  * The capacity of buffer must have enough length to store a text form
  * plus a terminating NULL byte.  The resulting text form ends with
@@ -72,7 +79,7 @@ uint8_t *ngtcp2_encode_ipv4(uint8_t *dest, const uint8_t *addr);
  * https://tools.ietf.org/html/rfc5952#section-4.  The function
  * returns |dest|.
  */
-uint8_t *ngtcp2_encode_ipv6(uint8_t *dest, const uint8_t *addr);
+char *ngtcp2_encode_ipv6_cstr(char *dest, const uint8_t *addr);
 
 /*
  * ngtcp2_encode_printable_ascii encodes |data| of length |len| in
@@ -81,8 +88,8 @@ uint8_t *ngtcp2_encode_ipv6(uint8_t *dest, const uint8_t *addr);
  * writes additional NULL bytes at the end of the buffer.  |dest| must
  * have at least |len| + 1 bytes.  This function returns |dest|.
  */
-char *ngtcp2_encode_printable_ascii(char *dest, const uint8_t *data,
-                                    size_t len);
+char *ngtcp2_encode_printable_ascii_cstr(char *dest, const uint8_t *data,
+                                         size_t len);
 
 /*
  * ngtcp2_cmemeq returns nonzero if the first |n| bytes of the buffers
@@ -91,4 +98,12 @@ char *ngtcp2_encode_printable_ascii(char *dest, const uint8_t *data,
  */
 int ngtcp2_cmemeq(const uint8_t *a, const uint8_t *b, size_t n);
 
+/*
+ * ngtcp2_encode_uint encodes |n| as a decimal integer to the buffer
+ * pointed by |dest|.  This function assumes that the buffer contains
+ * the sufficient capacity to write the number.  This function returns
+ * the pointer to the buffer past the last byte written.
+ */
+uint8_t *ngtcp2_encode_uint(uint8_t *dest, uint64_t n);
+
 #endif /* !defined(NGTCP2_STR_H) */
index faa417713224d5e59fe1246e6a3cebe6d81b2df2..26871aa0a229bd8ff058bc4f79811efa1d7ad465 100644 (file)
@@ -36,30 +36,27 @@ void ngtcp2_strm_init(ngtcp2_strm *strm, int64_t stream_id, uint32_t flags,
                       uint64_t max_rx_offset, uint64_t max_tx_offset,
                       void *stream_user_data, ngtcp2_objalloc *frc_objalloc,
                       const ngtcp2_mem *mem) {
-  strm->pe.index = NGTCP2_PQ_BAD_INDEX;
-  strm->cycle = 0;
-  strm->frc_objalloc = frc_objalloc;
-  strm->tx.acked_offset = NULL;
-  strm->tx.cont_acked_offset = 0;
-  strm->tx.streamfrq = NULL;
-  strm->tx.offset = 0;
-  strm->tx.max_offset = max_tx_offset;
-  strm->tx.last_blocked_offset = UINT64_MAX;
-  strm->tx.last_max_stream_data_ts = UINT64_MAX;
-  strm->tx.loss_count = 0;
-  strm->tx.last_lost_pkt_num = -1;
-  strm->tx.stop_sending_app_error_code = 0;
-  strm->tx.reset_stream_app_error_code = 0;
-  strm->rx.rob = NULL;
-  strm->rx.cont_offset = 0;
-  strm->rx.last_offset = 0;
-  strm->rx.max_offset = strm->rx.unsent_max_offset = strm->rx.window =
-    max_rx_offset;
-  strm->mem = mem;
-  strm->stream_id = stream_id;
-  strm->stream_user_data = stream_user_data;
-  strm->flags = flags;
-  strm->app_error_code = 0;
+  *strm = (ngtcp2_strm){
+    .pe.index = NGTCP2_PQ_BAD_INDEX,
+    .frc_objalloc = frc_objalloc,
+    .tx =
+      {
+        .max_offset = max_tx_offset,
+        .last_blocked_offset = UINT64_MAX,
+        .last_max_stream_data_ts = UINT64_MAX,
+        .last_lost_pkt_num = -1,
+      },
+    .rx =
+      {
+        .max_offset = max_rx_offset,
+        .unsent_max_offset = max_rx_offset,
+        .window = max_rx_offset,
+      },
+    .mem = mem,
+    .stream_id = stream_id,
+    .stream_user_data = stream_user_data,
+    .flags = flags,
+  };
 }
 
 void ngtcp2_strm_free(ngtcp2_strm *strm) {
@@ -120,7 +117,7 @@ uint64_t ngtcp2_strm_rx_offset(const ngtcp2_strm *strm) {
 /* strm_rob_heavily_fragmented returns nonzero if the number of gaps
    in |rob| exceeds the limit. */
 static int strm_rob_heavily_fragmented(const ngtcp2_rob *rob) {
-  return ngtcp2_ksl_len(&rob->gapksl) >= 1000;
+  return ngtcp2_ksl_len(&rob->gapksl) >= 4000;
 }
 
 ngtcp2_ssize ngtcp2_strm_recv_reordering(ngtcp2_strm *strm, const uint8_t *data,
@@ -694,12 +691,11 @@ int ngtcp2_strm_is_all_tx_data_fin_acked(const ngtcp2_strm *strm) {
 
 ngtcp2_range ngtcp2_strm_get_unacked_range_after(const ngtcp2_strm *strm,
                                                  uint64_t offset) {
-  ngtcp2_range gap;
-
   if (strm->tx.acked_offset == NULL) {
-    gap.begin = strm->tx.cont_acked_offset;
-    gap.end = UINT64_MAX;
-    return gap;
+    return (ngtcp2_range){
+      .begin = strm->tx.cont_acked_offset,
+      .end = UINT64_MAX,
+    };
   }
 
   return ngtcp2_gaptr_get_first_gap_after(strm->tx.acked_offset, offset);
@@ -754,7 +750,7 @@ int ngtcp2_strm_ack_data(ngtcp2_strm *strm, uint64_t offset, uint64_t len) {
     return rv;
   }
 
-  if (ngtcp2_ksl_len(&strm->tx.acked_offset->gap) >= 1000) {
+  if (ngtcp2_ksl_len(&strm->tx.acked_offset->gap) >= 4000) {
     return NGTCP2_ERR_INTERNAL;
   }
 
index ada027b9095f4ed78ae12cd14ec11c000a6ce5a5..537599f6c1fe482c4071770e6dfe36834f36c9ec 100644 (file)
 #include "ngtcp2_str.h"
 
 ngtcp2_vec *ngtcp2_vec_init(ngtcp2_vec *vec, const uint8_t *base, size_t len) {
-  vec->base = (uint8_t *)base;
-  vec->len = len;
+  *vec = (ngtcp2_vec){
+    .base = (uint8_t *)base,
+    .len = len,
+  };
+
   return vec;
 }
 
@@ -158,8 +161,10 @@ size_t ngtcp2_vec_merge(ngtcp2_vec *dst, size_t *pdstcnt, ngtcp2_vec *src,
       } else if (*pdstcnt == maxcnt) {
         break;
       } else {
-        dst[*pdstcnt].len = left;
-        dst[*pdstcnt].base = b->base;
+        dst[*pdstcnt] = (ngtcp2_vec){
+          .base = b->base,
+          .len = left,
+        };
         ++*pdstcnt;
       }
 
@@ -199,8 +204,10 @@ size_t ngtcp2_vec_copy_at_most(ngtcp2_vec *dst, size_t dstcnt,
     }
 
     if (src[i].len > left) {
-      dst[j].base = src[i].base;
-      dst[j].len = left;
+      dst[j] = (ngtcp2_vec){
+        .base = src[i].base,
+        .len = left,
+      };
 
       return j + 1;
     }
index 5634c9c751e0522da8e9b22a66b12d3c302b411d..a89e9d8184d51388b750877bbd99e9bc677a9aff 100644 (file)
@@ -5579,7 +5579,9 @@ NGTCP2_EXTERN void ngtcp2_ccerr_set_application_error(ngtcp2_ccerr *ccerr,
  * |destlen| could be shorten by some factors (e.g., server side
  * amplification limit).  This function returns
  * :macro:`NGTCP2_ERR_NOBUF` if the resulting buffer is too small even
- * if the given buffer has enough space.
+ * if the given buffer has enough space.  This can happen if sending a
+ * packet would exceed a transmission limit (e.g., for amplification
+ * attack protection).
  *
  * This function must not be called from inside the callback
  * functions.
@@ -5594,7 +5596,8 @@ NGTCP2_EXTERN void ngtcp2_ccerr_set_application_error(ngtcp2_ccerr *ccerr,
  * :macro:`NGTCP2_ERR_NOMEM`
  *     Out of memory
  * :macro:`NGTCP2_ERR_NOBUF`
- *     Buffer is too small
+ *     Buffer is too small or packet would exceed the transmission
+ *     limit (e.g., for amplification attack protection).
  * :macro:`NGTCP2_ERR_INVALID_STATE`
  *     The current state does not allow sending CONNECTION_CLOSE
  *     frame.
@@ -5916,9 +5919,9 @@ NGTCP2_EXTERN void ngtcp2_path_storage_zero(ngtcp2_path_storage *ps);
  * * :member:`handshake_timeout <ngtcp2_settings.handshake_timeout>` =
  *   ``UINT64_MAX``
  * * :member:`glitch_ratelim_burst
- *   <ngtcp2_settings.glitch_ratelim_burst>` = 1000
+ *   <ngtcp2_settings.glitch_ratelim_burst>` = 4000
  * * :member:`glitch_ratelim_rate
- *   <ngtcp2_settings.glitch_ratelim_rate>` = 33
+ *   <ngtcp2_settings.glitch_ratelim_rate>` = 132
  */
 NGTCP2_EXTERN void ngtcp2_settings_default_versioned(int settings_version,
                                                      ngtcp2_settings *settings);
index 003ec6b4c3f23ce07823734ecb1c1379c8dcae4a..c2099d24950ac269219126622894596074f7bfe9 100644 (file)
@@ -627,7 +627,10 @@ NGTCP2_EXTERN int ngtcp2_crypto_generate_stateless_reset_token(
  * @macro
  *
  * :macro:`NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN` is the maximum length
- *  of a token generated by `ngtcp2_crypto_generate_regular_token`.
+ * of a token generated by `ngtcp2_crypto_generate_regular_token`.
+ * `ngtcp2_crypto_generate_regular_token2` generates a token of length
+ * at most :macro:`NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN` bytes + the
+ * length of the provided opaque data.
  */
 #define NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN                                     \
   (/* magic = */ 1 + sizeof(ngtcp2_tstamp) + /* aead tag = */ 16 +             \
@@ -787,6 +790,77 @@ NGTCP2_EXTERN int ngtcp2_crypto_verify_regular_token(
   size_t secretlen, const ngtcp2_sockaddr *remote_addr,
   ngtcp2_socklen remote_addrlen, ngtcp2_duration timeout, ngtcp2_tstamp ts);
 
+/**
+ * @function
+ *
+ * `ngtcp2_crypto_generate_regular_token2` generates a token in the
+ * buffer pointed by |token| that is sent with NEW_TOKEN frame.  The
+ * buffer pointed by |token| must have at least
+ * :macro:`NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN` + |datalen| bytes long.
+ * The successfully generated token starts with
+ * :macro:`NGTCP2_CRYPTO_TOKEN_MAGIC_REGULAR`.  |secret| of length
+ * |secretlen| is a keying material to generate keys to encrypt the
+ * token.  |remote_addr| of length |remote_addrlen| is an address of
+ * client.  |ts| is the timestamp when the token is generated.  |data|
+ * of length |datalen| is an opaque data embedded in the token.
+ * |datalen| must be less than or equal to 256.
+ *
+ * Calling this function with |datalen| = 0 is equivalent to calling
+ * `ngtcp2_crypto_generate_regular_token`.
+ *
+ * To get the opaque data after successful verification, use
+ * `ngtcp2_crypto_verify_regular_token2`.
+ * `ngtcp2_crypto_verify_regular_token` can verify the token with
+ * |datalen| > 0, but it discards the opaque data.
+ *
+ * This function returns the length of generated token if it succeeds,
+ * or -1.
+ */
+NGTCP2_EXTERN ngtcp2_ssize ngtcp2_crypto_generate_regular_token2(
+  uint8_t *token, const uint8_t *secret, size_t secretlen,
+  const ngtcp2_sockaddr *remote_addr, ngtcp2_socklen remote_addrlen,
+  const void *data, size_t datalen, ngtcp2_tstamp ts);
+
+/**
+ * @function
+ *
+ * `ngtcp2_crypto_verify_regular_token2` verifies a regular token
+ * stored in the buffer pointed by |token| of length |tokenlen|.
+ * |secret| of length |secretlen| is a keying material to generate
+ * keys to decrypt the token.  |remote_addr| of length
+ * |remote_addrlen| is an address of client.  |timeout| is the period
+ * during which the token is valid.  |ts| is the current timestamp.
+ * |data| is the pointer to the buffer of length at least
+ * |max_datalen| bytes.  If the token is verified successfully, the
+ * opaque data embedded in the token is copied to the buffer pointed
+ * by |data|.
+ *
+ * If |tokenlen| is less than
+ * :macro:`NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN`, this function returns
+ * :macro:`NGTCP2_CRYPTO_ERR_UNREADABLE_TOKEN`.
+ *
+ * If the length of opaque data is larger than |max_datalen|, the
+ * verification still succeeds, but nothing is written to the buffer
+ * pointed by |data|, and this function returns 0.  In other words,
+ * the opaque data is discarded.
+ *
+ * This function returns the number of the opaque data written to the
+ * buffer pointed by |data| if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :macro:`NGTCP2_CRYPTO_ERR_UNREADABLE_TOKEN`
+ *     A token is badly formatted; or verifying the integrity
+ *     protection failed.
+ * :macro:`NGTCP2_CRYPTO_ERR_VERIFY_TOKEN`
+ *     A token validity has expired.
+ * :macro:`NGTCP2_CRYPTO_ERR_INTERNAL`
+ *     Internal error occurred.
+ */
+NGTCP2_EXTERN ngtcp2_ssize ngtcp2_crypto_verify_regular_token2(
+  void *data, size_t max_datalen, const uint8_t *token, size_t tokenlen,
+  const uint8_t *secret, size_t secretlen, const ngtcp2_sockaddr *remote_addr,
+  ngtcp2_socklen remote_addrlen, ngtcp2_duration timeout, ngtcp2_tstamp ts);
+
 /**
  * @function
  *
index 3ff1ebac9705ca103b2aa037e36363eeed59780d..3e60b39d5d2c99f85f3c1f583d003976965070d4 100644 (file)
@@ -36,7 +36,7 @@
  *
  * Version number of the ngtcp2 library release.
  */
-#define NGTCP2_VERSION "1.17.0"
+#define NGTCP2_VERSION "1.18.0"
 
 /**
  * @macro
@@ -46,6 +46,6 @@
  * number, 8 bits for minor and 8 bits for patch. Version 1.2.3
  * becomes 0x010203.
  */
-#define NGTCP2_VERSION_NUM 0x011100
+#define NGTCP2_VERSION_NUM 0x011200
 
 #endif /* !defined(NGTCP2_VERSION_H) */