summaryrefslogtreecommitdiffstats
path: root/tests/ngtcp2_pkt_test.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ngtcp2_pkt_test.c')
-rw-r--r--tests/ngtcp2_pkt_test.c1644
1 files changed, 1644 insertions, 0 deletions
diff --git a/tests/ngtcp2_pkt_test.c b/tests/ngtcp2_pkt_test.c
new file mode 100644
index 0000000..f225610
--- /dev/null
+++ b/tests/ngtcp2_pkt_test.c
@@ -0,0 +1,1644 @@
+/*
+ * ngtcp2
+ *
+ * Copyright (c) 2017 ngtcp2 contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "ngtcp2_pkt_test.h"
+
+#include <CUnit/CUnit.h>
+
+#include "ngtcp2_pkt.h"
+#include "ngtcp2_test_helper.h"
+#include "ngtcp2_conv.h"
+#include "ngtcp2_cid.h"
+#include "ngtcp2_str.h"
+#include "ngtcp2_vec.h"
+
+static int null_retry_encrypt(uint8_t *dest, const ngtcp2_crypto_aead *aead,
+ const ngtcp2_crypto_aead_ctx *aead_ctx,
+ const uint8_t *plaintext, size_t plaintextlen,
+ const uint8_t *nonce, size_t noncelen,
+ const uint8_t *aad, size_t aadlen) {
+ (void)dest;
+ (void)aead;
+ (void)aead_ctx;
+ (void)plaintext;
+ (void)plaintextlen;
+ (void)nonce;
+ (void)noncelen;
+ (void)aad;
+ (void)aadlen;
+
+ if (plaintextlen && plaintext != dest) {
+ memcpy(dest, plaintext, plaintextlen);
+ }
+ memset(dest + plaintextlen, 0, NGTCP2_RETRY_TAGLEN);
+
+ return 0;
+}
+
+void test_ngtcp2_pkt_decode_version_cid(void) {
+ uint8_t buf[NGTCP2_MAX_UDP_PAYLOAD_SIZE];
+ ngtcp2_version_cid vc;
+ int rv;
+ uint8_t *p;
+
+ /* Supported QUIC version */
+ p = buf;
+ *p++ = NGTCP2_HEADER_FORM_BIT;
+ p = ngtcp2_put_uint32be(p, NGTCP2_PROTO_VER_V1);
+ *p++ = NGTCP2_MAX_CIDLEN;
+ p = ngtcp2_setmem(p, 0xf1, NGTCP2_MAX_CIDLEN);
+ *p++ = NGTCP2_MAX_CIDLEN - 1;
+ p = ngtcp2_setmem(p, 0xf2, NGTCP2_MAX_CIDLEN - 1);
+
+ rv = ngtcp2_pkt_decode_version_cid(&vc, buf, (size_t)(p - buf), 0);
+
+ CU_ASSERT(0 == rv);
+ CU_ASSERT(NGTCP2_PROTO_VER_V1 == vc.version);
+ CU_ASSERT(NGTCP2_MAX_CIDLEN == vc.dcidlen);
+ CU_ASSERT(&buf[6] == vc.dcid);
+ CU_ASSERT(NGTCP2_MAX_CIDLEN - 1 == vc.scidlen);
+ CU_ASSERT(&buf[6 + NGTCP2_MAX_CIDLEN + 1] == vc.scid);
+
+ /* Unsupported QUIC version */
+ memset(buf, 0, sizeof(buf));
+ p = buf;
+ *p++ = NGTCP2_HEADER_FORM_BIT;
+ p = ngtcp2_put_uint32be(p, 0xffffff00);
+ *p++ = NGTCP2_MAX_CIDLEN;
+ p = ngtcp2_setmem(p, 0xf1, NGTCP2_MAX_CIDLEN);
+ *p++ = NGTCP2_MAX_CIDLEN - 1;
+ ngtcp2_setmem(p, 0xf2, NGTCP2_MAX_CIDLEN - 1);
+
+ rv = ngtcp2_pkt_decode_version_cid(&vc, buf, sizeof(buf), 0);
+
+ CU_ASSERT(NGTCP2_ERR_VERSION_NEGOTIATION == rv);
+ CU_ASSERT(0xffffff00 == vc.version);
+ CU_ASSERT(NGTCP2_MAX_CIDLEN == vc.dcidlen);
+ CU_ASSERT(&buf[6] == vc.dcid);
+ CU_ASSERT(NGTCP2_MAX_CIDLEN - 1 == vc.scidlen);
+ CU_ASSERT(&buf[6 + NGTCP2_MAX_CIDLEN + 1] == vc.scid);
+
+ /* Unsupported QUIC version with UDP payload size < 1200 */
+ p = buf;
+ *p++ = NGTCP2_HEADER_FORM_BIT;
+ p = ngtcp2_put_uint32be(p, 0xffffff00);
+ *p++ = NGTCP2_MAX_CIDLEN;
+ p = ngtcp2_setmem(p, 0xf1, NGTCP2_MAX_CIDLEN);
+ *p++ = NGTCP2_MAX_CIDLEN - 1;
+ p = ngtcp2_setmem(p, 0xf2, NGTCP2_MAX_CIDLEN - 1);
+
+ rv = ngtcp2_pkt_decode_version_cid(&vc, buf, (size_t)(p - buf), 0);
+
+ CU_ASSERT(NGTCP2_ERR_INVALID_ARGUMENT == rv);
+
+ /* Supported QUIC version with long CID */
+ p = buf;
+ *p++ = NGTCP2_HEADER_FORM_BIT;
+ p = ngtcp2_put_uint32be(p, NGTCP2_PROTO_VER_V1);
+ *p++ = NGTCP2_MAX_CIDLEN + 1;
+ p = ngtcp2_setmem(p, 0xf1, NGTCP2_MAX_CIDLEN + 1);
+ *p++ = NGTCP2_MAX_CIDLEN;
+ p = ngtcp2_setmem(p, 0xf2, NGTCP2_MAX_CIDLEN);
+
+ rv = ngtcp2_pkt_decode_version_cid(&vc, buf, (size_t)(p - buf), 0);
+
+ CU_ASSERT(NGTCP2_ERR_INVALID_ARGUMENT == rv);
+
+ /* Unsupported QUIC version with long CID */
+ memset(buf, 0, sizeof(buf));
+ p = buf;
+ *p++ = NGTCP2_HEADER_FORM_BIT;
+ p = ngtcp2_put_uint32be(p, 0xffffff00);
+ *p++ = NGTCP2_MAX_CIDLEN + 1;
+ p = ngtcp2_setmem(p, 0xf1, NGTCP2_MAX_CIDLEN + 1);
+ *p++ = NGTCP2_MAX_CIDLEN;
+ ngtcp2_setmem(p, 0xf2, NGTCP2_MAX_CIDLEN);
+
+ rv = ngtcp2_pkt_decode_version_cid(&vc, buf, sizeof(buf), 0);
+
+ CU_ASSERT(NGTCP2_ERR_VERSION_NEGOTIATION == rv);
+ CU_ASSERT(0xffffff00 == vc.version);
+ CU_ASSERT(NGTCP2_MAX_CIDLEN + 1 == vc.dcidlen);
+ CU_ASSERT(&buf[6] == vc.dcid);
+ CU_ASSERT(NGTCP2_MAX_CIDLEN == vc.scidlen);
+ CU_ASSERT(&buf[6 + NGTCP2_MAX_CIDLEN + 1 + 1] == vc.scid);
+
+ /* VN */
+ p = buf;
+ *p++ = NGTCP2_HEADER_FORM_BIT;
+ p = ngtcp2_put_uint32be(p, 0);
+ *p++ = NGTCP2_MAX_CIDLEN;
+ p = ngtcp2_setmem(p, 0xf1, NGTCP2_MAX_CIDLEN);
+ *p++ = NGTCP2_MAX_CIDLEN - 1;
+ p = ngtcp2_setmem(p, 0xf2, NGTCP2_MAX_CIDLEN - 1);
+
+ rv = ngtcp2_pkt_decode_version_cid(&vc, buf, (size_t)(p - buf), 0);
+
+ CU_ASSERT(0 == rv);
+ CU_ASSERT(0 == vc.version);
+ CU_ASSERT(NGTCP2_MAX_CIDLEN == vc.dcidlen);
+ CU_ASSERT(&buf[6] == vc.dcid);
+ CU_ASSERT(NGTCP2_MAX_CIDLEN - 1 == vc.scidlen);
+ CU_ASSERT(&buf[6 + NGTCP2_MAX_CIDLEN + 1] == vc.scid);
+
+ /* VN with long CID */
+ p = buf;
+ *p++ = NGTCP2_HEADER_FORM_BIT;
+ p = ngtcp2_put_uint32be(p, 0);
+ *p++ = NGTCP2_MAX_CIDLEN + 1;
+ p = ngtcp2_setmem(p, 0xf1, NGTCP2_MAX_CIDLEN + 1);
+ *p++ = NGTCP2_MAX_CIDLEN;
+ p = ngtcp2_setmem(p, 0xf2, NGTCP2_MAX_CIDLEN);
+
+ rv = ngtcp2_pkt_decode_version_cid(&vc, buf, (size_t)(p - buf), 0);
+
+ CU_ASSERT(0 == rv);
+ CU_ASSERT(0 == vc.version);
+ CU_ASSERT(NGTCP2_MAX_CIDLEN + 1 == vc.dcidlen);
+ CU_ASSERT(&buf[6] == vc.dcid);
+ CU_ASSERT(NGTCP2_MAX_CIDLEN == vc.scidlen);
+ CU_ASSERT(&buf[6 + NGTCP2_MAX_CIDLEN + 1 + 1] == vc.scid);
+
+ /* Malformed Long packet */
+ p = buf;
+ *p++ = NGTCP2_HEADER_FORM_BIT;
+ p = ngtcp2_put_uint32be(p, NGTCP2_PROTO_VER_V1);
+ *p++ = NGTCP2_MAX_CIDLEN;
+ p = ngtcp2_setmem(p, 0xf1, NGTCP2_MAX_CIDLEN);
+ *p++ = NGTCP2_MAX_CIDLEN - 1;
+ p = ngtcp2_setmem(p, 0xf2, NGTCP2_MAX_CIDLEN - 1);
+ --p;
+
+ rv = ngtcp2_pkt_decode_version_cid(&vc, buf, (size_t)(p - buf), 0);
+
+ CU_ASSERT(NGTCP2_ERR_INVALID_ARGUMENT == rv);
+
+ /* Short packet */
+ p = buf;
+ *p++ = 0;
+ p = ngtcp2_setmem(p, 0xf1, NGTCP2_MAX_CIDLEN);
+
+ rv = ngtcp2_pkt_decode_version_cid(&vc, buf, (size_t)(p - buf),
+ NGTCP2_MAX_CIDLEN);
+
+ CU_ASSERT(0 == rv);
+ CU_ASSERT(0 == vc.version);
+ CU_ASSERT(&buf[1] == vc.dcid);
+ CU_ASSERT(NGTCP2_MAX_CIDLEN == vc.dcidlen);
+ CU_ASSERT(NULL == vc.scid);
+ CU_ASSERT(0 == vc.scidlen);
+
+ /* Malformed Short packet */
+ p = buf;
+ *p++ = 0;
+ p = ngtcp2_setmem(p, 0xf1, NGTCP2_MAX_CIDLEN);
+ --p;
+
+ rv = ngtcp2_pkt_decode_version_cid(&vc, buf, (size_t)(p - buf),
+ NGTCP2_MAX_CIDLEN);
+
+ CU_ASSERT(NGTCP2_ERR_INVALID_ARGUMENT == rv);
+}
+
+void test_ngtcp2_pkt_decode_hd_long(void) {
+ ngtcp2_pkt_hd hd, nhd;
+ uint8_t buf[256];
+ ngtcp2_ssize rv;
+ ngtcp2_cid dcid, scid;
+ size_t len;
+
+ dcid_init(&dcid);
+ scid_init(&scid);
+
+ /* Handshake */
+ ngtcp2_pkt_hd_init(&hd, NGTCP2_PKT_FLAG_LONG_FORM, NGTCP2_PKT_HANDSHAKE,
+ &dcid, &scid, 0xe1e2e3e4u, 4, NGTCP2_PROTO_VER_V1, 16383);
+
+ rv = ngtcp2_pkt_encode_hd_long(buf, sizeof(buf), &hd);
+
+ len = 1 + 4 + 1 + dcid.datalen + 1 + scid.datalen + NGTCP2_PKT_LENGTHLEN + 4;
+
+ CU_ASSERT((ngtcp2_ssize)len == rv);
+ CU_ASSERT(buf[0] & NGTCP2_FIXED_BIT_MASK);
+
+ rv = pkt_decode_hd_long(&nhd, buf, len);
+
+ CU_ASSERT((ngtcp2_ssize)len == rv);
+ CU_ASSERT(hd.type == nhd.type);
+ CU_ASSERT(hd.flags == nhd.flags);
+ CU_ASSERT(ngtcp2_cid_eq(&hd.dcid, &nhd.dcid));
+ CU_ASSERT(ngtcp2_cid_eq(&hd.scid, &nhd.scid));
+ CU_ASSERT(0xe1e2e3e4u == nhd.pkt_num);
+ CU_ASSERT(hd.version == nhd.version);
+ CU_ASSERT(hd.len == nhd.len);
+
+ /* Handshake without Fixed Bit set */
+ ngtcp2_pkt_hd_init(
+ &hd, NGTCP2_PKT_FLAG_LONG_FORM | NGTCP2_PKT_FLAG_FIXED_BIT_CLEAR,
+ NGTCP2_PKT_HANDSHAKE, &dcid, &scid, 0xe1e2e3e4u, 4, NGTCP2_PROTO_VER_V1,
+ 16383);
+
+ rv = ngtcp2_pkt_encode_hd_long(buf, sizeof(buf), &hd);
+
+ len = 1 + 4 + 1 + dcid.datalen + 1 + scid.datalen + NGTCP2_PKT_LENGTHLEN + 4;
+
+ CU_ASSERT((ngtcp2_ssize)len == rv);
+ CU_ASSERT((buf[0] & NGTCP2_FIXED_BIT_MASK) == 0);
+
+ rv = pkt_decode_hd_long(&nhd, buf, len);
+
+ CU_ASSERT((ngtcp2_ssize)len == rv);
+ CU_ASSERT(hd.type == nhd.type);
+ CU_ASSERT(hd.flags == nhd.flags);
+ CU_ASSERT(ngtcp2_cid_eq(&hd.dcid, &nhd.dcid));
+ CU_ASSERT(ngtcp2_cid_eq(&hd.scid, &nhd.scid));
+ CU_ASSERT(0xe1e2e3e4u == nhd.pkt_num);
+ CU_ASSERT(hd.version == nhd.version);
+ CU_ASSERT(hd.len == nhd.len);
+
+ /* VN */
+ /* Set random packet type */
+ ngtcp2_pkt_hd_init(&hd, NGTCP2_PKT_FLAG_LONG_FORM, NGTCP2_PKT_HANDSHAKE,
+ &dcid, &scid, 0, 4, NGTCP2_PROTO_VER_V1, 0);
+
+ rv = ngtcp2_pkt_encode_hd_long(buf, sizeof(buf), &hd);
+ /* Set version field to 0 */
+ memset(&buf[1], 0, 4);
+
+ len = 1 + 4 + 1 + dcid.datalen + 1 + scid.datalen;
+
+ CU_ASSERT((ngtcp2_ssize)len == rv - NGTCP2_PKT_LENGTHLEN - 4 /* pkt_num */);
+
+ rv = pkt_decode_hd_long(&nhd, buf, len);
+
+ CU_ASSERT((ngtcp2_ssize)len == rv);
+ CU_ASSERT(NGTCP2_PKT_VERSION_NEGOTIATION == nhd.type);
+ CU_ASSERT((hd.flags & ~NGTCP2_PKT_FLAG_LONG_FORM) == nhd.flags);
+ CU_ASSERT(ngtcp2_cid_eq(&hd.dcid, &nhd.dcid));
+ CU_ASSERT(ngtcp2_cid_eq(&hd.scid, &nhd.scid));
+ CU_ASSERT(hd.pkt_num == nhd.pkt_num);
+ CU_ASSERT(0 == nhd.version);
+ CU_ASSERT(hd.len == nhd.len);
+}
+
+void test_ngtcp2_pkt_decode_hd_short(void) {
+ ngtcp2_pkt_hd hd, nhd;
+ uint8_t buf[256];
+ ngtcp2_ssize rv;
+ size_t expectedlen;
+ ngtcp2_cid dcid, zcid;
+
+ dcid_init(&dcid);
+ ngtcp2_cid_zero(&zcid);
+
+ /* 4 bytes packet number */
+ ngtcp2_pkt_hd_init(&hd, NGTCP2_PKT_FLAG_NONE, NGTCP2_PKT_1RTT, &dcid, NULL,
+ 0xe1e2e3e4u, 4, 0xd1d2d3d4u, 0);
+
+ expectedlen = 1 + dcid.datalen + 4;
+
+ rv = ngtcp2_pkt_encode_hd_short(buf, sizeof(buf), &hd);
+
+ CU_ASSERT((ngtcp2_ssize)expectedlen == rv);
+ CU_ASSERT(buf[0] & NGTCP2_FIXED_BIT_MASK);
+
+ rv = pkt_decode_hd_short(&nhd, buf, expectedlen, dcid.datalen);
+
+ CU_ASSERT((ngtcp2_ssize)expectedlen == rv);
+ CU_ASSERT(hd.flags == nhd.flags);
+ CU_ASSERT(NGTCP2_PKT_1RTT == nhd.type);
+ CU_ASSERT(ngtcp2_cid_eq(&dcid, &nhd.dcid));
+ CU_ASSERT(ngtcp2_cid_empty(&nhd.scid));
+ CU_ASSERT(0xe1e2e3e4u == nhd.pkt_num);
+ CU_ASSERT(hd.pkt_numlen == nhd.pkt_numlen);
+ CU_ASSERT(0 == nhd.version);
+ CU_ASSERT(0 == nhd.len);
+
+ /* 4 bytes packet number without Fixed Bit set */
+ ngtcp2_pkt_hd_init(
+ &hd, NGTCP2_PKT_FLAG_NONE | NGTCP2_PKT_FLAG_FIXED_BIT_CLEAR,
+ NGTCP2_PKT_1RTT, &dcid, NULL, 0xe1e2e3e4u, 4, 0xd1d2d3d4u, 0);
+
+ expectedlen = 1 + dcid.datalen + 4;
+
+ rv = ngtcp2_pkt_encode_hd_short(buf, sizeof(buf), &hd);
+
+ CU_ASSERT((ngtcp2_ssize)expectedlen == rv);
+ CU_ASSERT((buf[0] & NGTCP2_FIXED_BIT_MASK) == 0);
+
+ rv = pkt_decode_hd_short(&nhd, buf, expectedlen, dcid.datalen);
+
+ CU_ASSERT((ngtcp2_ssize)expectedlen == rv);
+ CU_ASSERT(hd.flags == nhd.flags);
+ CU_ASSERT(NGTCP2_PKT_1RTT == nhd.type);
+ CU_ASSERT(ngtcp2_cid_eq(&dcid, &nhd.dcid));
+ CU_ASSERT(ngtcp2_cid_empty(&nhd.scid));
+ CU_ASSERT(0xe1e2e3e4u == nhd.pkt_num);
+ CU_ASSERT(hd.pkt_numlen == nhd.pkt_numlen);
+ CU_ASSERT(0 == nhd.version);
+ CU_ASSERT(0 == nhd.len);
+
+ /* 2 bytes packet number */
+ ngtcp2_pkt_hd_init(&hd, NGTCP2_PKT_FLAG_NONE, NGTCP2_PKT_1RTT, &dcid, NULL,
+ 0xe1e2e3e4u, 2, 0xd1d2d3d4u, 0);
+
+ expectedlen = 1 + dcid.datalen + 2;
+
+ rv = ngtcp2_pkt_encode_hd_short(buf, sizeof(buf), &hd);
+
+ CU_ASSERT((ngtcp2_ssize)expectedlen == rv);
+
+ rv = pkt_decode_hd_short(&nhd, buf, expectedlen, dcid.datalen);
+
+ CU_ASSERT((ngtcp2_ssize)expectedlen == rv);
+ CU_ASSERT(hd.flags == nhd.flags);
+ CU_ASSERT(NGTCP2_PKT_1RTT == nhd.type);
+ CU_ASSERT(ngtcp2_cid_eq(&dcid, &nhd.dcid));
+ CU_ASSERT(ngtcp2_cid_empty(&nhd.scid));
+ CU_ASSERT(0xe3e4u == nhd.pkt_num);
+ CU_ASSERT(hd.pkt_numlen == nhd.pkt_numlen);
+ CU_ASSERT(0 == nhd.version);
+ CU_ASSERT(0 == nhd.len);
+
+ /* 1 byte packet number */
+ ngtcp2_pkt_hd_init(&hd, NGTCP2_PKT_FLAG_NONE, NGTCP2_PKT_1RTT, &dcid, NULL,
+ 0xe1e2e3e4u, 1, 0xd1d2d3d4u, 0);
+
+ expectedlen = 1 + dcid.datalen + 1;
+
+ rv = ngtcp2_pkt_encode_hd_short(buf, sizeof(buf), &hd);
+
+ CU_ASSERT((ngtcp2_ssize)expectedlen == rv);
+
+ rv = pkt_decode_hd_short(&nhd, buf, expectedlen, dcid.datalen);
+
+ CU_ASSERT((ngtcp2_ssize)expectedlen == rv);
+ CU_ASSERT(hd.flags == nhd.flags);
+ CU_ASSERT(NGTCP2_PKT_1RTT == nhd.type);
+ CU_ASSERT(ngtcp2_cid_eq(&dcid, &nhd.dcid));
+ CU_ASSERT(ngtcp2_cid_empty(&nhd.scid));
+ CU_ASSERT(0xe4 == nhd.pkt_num);
+ CU_ASSERT(hd.pkt_numlen == nhd.pkt_numlen);
+ CU_ASSERT(0 == nhd.version);
+ CU_ASSERT(0 == nhd.len);
+
+ /* With Key Phase */
+ ngtcp2_pkt_hd_init(&hd, NGTCP2_PKT_FLAG_KEY_PHASE, NGTCP2_PKT_1RTT, &dcid,
+ NULL, 0xe1e2e3e4u, 4, 0xd1d2d3d4u, 0);
+
+ expectedlen = 1 + dcid.datalen + 4;
+
+ rv = ngtcp2_pkt_encode_hd_short(buf, sizeof(buf), &hd);
+
+ CU_ASSERT((ngtcp2_ssize)expectedlen == rv);
+
+ rv = pkt_decode_hd_short(&nhd, buf, expectedlen, dcid.datalen);
+
+ CU_ASSERT((ngtcp2_ssize)expectedlen == rv);
+ /* key phase bit is protected by header protection and
+ ngtcp2_pkt_decode_hd_short does not decode it. */
+ CU_ASSERT(NGTCP2_PKT_FLAG_NONE == nhd.flags);
+ CU_ASSERT(NGTCP2_PKT_1RTT == nhd.type);
+ CU_ASSERT(ngtcp2_cid_eq(&dcid, &nhd.dcid));
+ CU_ASSERT(ngtcp2_cid_empty(&nhd.scid));
+ CU_ASSERT(0xe1e2e3e4u == nhd.pkt_num);
+ CU_ASSERT(hd.pkt_numlen == nhd.pkt_numlen);
+ CU_ASSERT(0 == nhd.version);
+ CU_ASSERT(0 == nhd.len);
+
+ /* With empty DCID */
+ ngtcp2_pkt_hd_init(&hd, NGTCP2_PKT_FLAG_NONE, NGTCP2_PKT_1RTT, NULL, NULL,
+ 0xe1e2e3e4u, 4, 0xd1d2d3d4u, 0);
+
+ expectedlen = 1 + 4;
+
+ rv = ngtcp2_pkt_encode_hd_short(buf, sizeof(buf), &hd);
+
+ CU_ASSERT((ngtcp2_ssize)expectedlen == rv);
+
+ rv = pkt_decode_hd_short(&nhd, buf, expectedlen, 0);
+
+ CU_ASSERT((ngtcp2_ssize)expectedlen == rv);
+ CU_ASSERT(hd.flags == nhd.flags);
+ CU_ASSERT(NGTCP2_PKT_1RTT == nhd.type);
+ CU_ASSERT(ngtcp2_cid_empty(&nhd.dcid));
+ CU_ASSERT(ngtcp2_cid_empty(&nhd.scid));
+ CU_ASSERT(0xe1e2e3e4u == nhd.pkt_num);
+ CU_ASSERT(hd.pkt_numlen == nhd.pkt_numlen);
+ CU_ASSERT(0 == nhd.version);
+ CU_ASSERT(0 == nhd.len);
+}
+
+void test_ngtcp2_pkt_decode_stream_frame(void) {
+ uint8_t buf[256];
+ size_t buflen;
+ ngtcp2_frame fr;
+ ngtcp2_ssize rv;
+ size_t expectedlen;
+
+ /* 32 bits Stream ID + 62 bits Offset + Data Length */
+ buflen = ngtcp2_t_encode_stream_frame(buf, NGTCP2_STREAM_LEN_BIT, 0xf1f2f3f4u,
+ 0x31f2f3f4f5f6f7f8llu, 0x14);
+
+ expectedlen = 1 + 8 + 8 + 1 + 20;
+
+ CU_ASSERT(expectedlen == buflen);
+
+ rv = ngtcp2_pkt_decode_stream_frame(&fr.stream, buf, buflen);
+
+ CU_ASSERT((ngtcp2_ssize)expectedlen == rv);
+ CU_ASSERT(0 == fr.stream.fin);
+ CU_ASSERT(0xf1f2f3f4u == fr.stream.stream_id);
+ CU_ASSERT(0x31f2f3f4f5f6f7f8llu == fr.stream.offset);
+ CU_ASSERT(1 == fr.stream.datacnt);
+ CU_ASSERT(0x14 == fr.stream.data[0].len);
+
+ /* Cutting 1 bytes from the tail must cause invalid argument
+ error */
+ rv = ngtcp2_pkt_decode_stream_frame(&fr.stream, buf, buflen - 1);
+
+ CU_ASSERT(NGTCP2_ERR_FRAME_ENCODING == rv);
+
+ memset(&fr, 0, sizeof(fr));
+
+ /* 6 bits Stream ID + no Offset + Data Length */
+ buflen = ngtcp2_t_encode_stream_frame(buf, NGTCP2_STREAM_LEN_BIT, 0x31, 0x00,
+ 0x14);
+
+ expectedlen = 1 + 1 + 0 + 1 + 20;
+
+ CU_ASSERT(expectedlen == buflen);
+
+ rv = ngtcp2_pkt_decode_stream_frame(&fr.stream, buf, buflen);
+
+ CU_ASSERT((ngtcp2_ssize)expectedlen == rv);
+ CU_ASSERT(0 == fr.stream.fin);
+ CU_ASSERT(0x31 == fr.stream.stream_id);
+ CU_ASSERT(0x00 == fr.stream.offset);
+ CU_ASSERT(1 == fr.stream.datacnt);
+ CU_ASSERT(0x14 == fr.stream.data[0].len);
+
+ /* Cutting 1 bytes from the tail must cause invalid argument
+ error */
+ rv = ngtcp2_pkt_decode_stream_frame(&fr.stream, buf, buflen - 1);
+
+ CU_ASSERT(NGTCP2_ERR_FRAME_ENCODING == rv);
+
+ memset(&fr, 0, sizeof(fr));
+
+ /* Fin bit set + no Data Length */
+ buflen = ngtcp2_t_encode_stream_frame(buf, NGTCP2_STREAM_FIN_BIT, 0x31f2f3f4u,
+ 0x00, 0x14);
+
+ expectedlen = 1 + 4 + 20;
+
+ CU_ASSERT(expectedlen == buflen);
+
+ rv = ngtcp2_pkt_decode_stream_frame(&fr.stream, buf, buflen);
+
+ CU_ASSERT((ngtcp2_ssize)expectedlen == rv);
+ CU_ASSERT(1 == fr.stream.fin);
+ CU_ASSERT(0x31f2f3f4u == fr.stream.stream_id);
+ CU_ASSERT(0x00 == fr.stream.offset);
+ CU_ASSERT(1 == fr.stream.datacnt);
+ CU_ASSERT(0x14 == fr.stream.data[0].len);
+
+ memset(&fr, 0, sizeof(fr));
+}
+
+void test_ngtcp2_pkt_decode_ack_frame(void) {
+ uint8_t buf[256];
+ size_t buflen;
+ ngtcp2_frame fr;
+ ngtcp2_ssize rv;
+ size_t expectedlen;
+
+ /* 62 bits Largest Acknowledged */
+ buflen = ngtcp2_t_encode_ack_frame(buf, 0x31f2f3f4f5f6f7f8llu,
+ 0x31e2e3e4e5e6e7e8llu, 99,
+ 0x31d2d3d4d5d6d7d8llu);
+
+ expectedlen = 1 + 8 + 1 + 1 + 8 + 2 + 8;
+
+ CU_ASSERT(expectedlen == buflen);
+
+ rv = ngtcp2_pkt_decode_ack_frame(&fr.ack, buf, buflen);
+
+ CU_ASSERT((ngtcp2_ssize)expectedlen == rv);
+ CU_ASSERT(0x31f2f3f4f5f6f7f8llu == fr.ack.largest_ack);
+ CU_ASSERT(1 == fr.ack.rangecnt);
+ CU_ASSERT(0x31e2e3e4e5e6e7e8llu == fr.ack.first_ack_range);
+ CU_ASSERT(99 == fr.ack.ranges[0].gap);
+ CU_ASSERT(0x31d2d3d4d5d6d7d8llu == fr.ack.ranges[0].len);
+}
+
+void test_ngtcp2_pkt_decode_padding_frame(void) {
+ uint8_t buf[256];
+ ngtcp2_frame fr;
+ ngtcp2_ssize rv;
+ size_t paddinglen = 31;
+
+ memset(buf, 0, paddinglen);
+ buf[paddinglen] = NGTCP2_FRAME_STREAM;
+
+ rv = ngtcp2_pkt_decode_padding_frame(&fr.padding, buf, paddinglen + 1);
+
+ CU_ASSERT((ngtcp2_ssize)paddinglen == rv);
+ CU_ASSERT((size_t)31 == fr.padding.len);
+}
+
+void test_ngtcp2_pkt_encode_stream_frame(void) {
+ const uint8_t data[] = "0123456789abcdef0";
+ uint8_t buf[256];
+ ngtcp2_frame fr, nfr;
+ ngtcp2_ssize rv;
+ size_t framelen;
+ size_t i;
+
+ /* 32 bits Stream ID + 62 bits Offset + Data Length */
+ fr.type = NGTCP2_FRAME_STREAM;
+ fr.stream.fin = 0;
+ fr.stream.stream_id = 0xf1f2f3f4u;
+ fr.stream.offset = 0x31f2f3f4f5f6f7f8llu;
+ fr.stream.datacnt = 1;
+ fr.stream.data[0].len = strsize(data);
+ fr.stream.data[0].base = (uint8_t *)data;
+
+ framelen = 1 + 8 + 8 + 1 + 17;
+
+ rv = ngtcp2_pkt_encode_stream_frame(buf, sizeof(buf), &fr.stream);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+
+ rv = ngtcp2_pkt_decode_stream_frame(&nfr.stream, buf, framelen);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+ CU_ASSERT(fr.type == nfr.type);
+ CU_ASSERT((NGTCP2_STREAM_OFF_BIT | NGTCP2_STREAM_LEN_BIT) ==
+ nfr.stream.flags);
+ CU_ASSERT(fr.stream.fin == nfr.stream.fin);
+ CU_ASSERT(fr.stream.stream_id == nfr.stream.stream_id);
+ CU_ASSERT(fr.stream.offset == nfr.stream.offset);
+ CU_ASSERT(1 == nfr.stream.datacnt);
+ CU_ASSERT(fr.stream.data[0].len == nfr.stream.data[0].len);
+ CU_ASSERT(0 == memcmp(fr.stream.data[0].base, nfr.stream.data[0].base,
+ fr.stream.data[0].len));
+
+ memset(&nfr, 0, sizeof(nfr));
+
+ /* 6 bits Stream ID + No Offset + Data Length */
+ fr.type = NGTCP2_FRAME_STREAM;
+ fr.stream.fin = 0;
+ fr.stream.stream_id = 0x31;
+ fr.stream.offset = 0;
+ fr.stream.datacnt = 1;
+ fr.stream.data[0].len = strsize(data);
+ fr.stream.data[0].base = (uint8_t *)data;
+
+ framelen = 1 + 1 + 1 + 17;
+
+ rv = ngtcp2_pkt_encode_stream_frame(buf, sizeof(buf), &fr.stream);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+
+ rv = ngtcp2_pkt_decode_stream_frame(&nfr.stream, buf, framelen);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+ CU_ASSERT(fr.type == nfr.type);
+ CU_ASSERT(NGTCP2_STREAM_LEN_BIT == nfr.stream.flags);
+ CU_ASSERT(fr.stream.fin == nfr.stream.fin);
+ CU_ASSERT(fr.stream.stream_id == nfr.stream.stream_id);
+ CU_ASSERT(fr.stream.offset == nfr.stream.offset);
+ CU_ASSERT(1 == nfr.stream.datacnt);
+ CU_ASSERT(fr.stream.data[0].len == nfr.stream.data[0].len);
+ CU_ASSERT(0 == memcmp(fr.stream.data[0].base, nfr.stream.data[0].base,
+ fr.stream.data[0].len));
+
+ memset(&nfr, 0, sizeof(nfr));
+
+ /* Fin + 32 bits Stream ID + 62 bits Offset + Data Length */
+ fr.type = NGTCP2_FRAME_STREAM;
+ fr.stream.fin = 1;
+ fr.stream.stream_id = 0xf1f2f3f4u;
+ fr.stream.offset = 0x31f2f3f4f5f6f7f8llu;
+ fr.stream.datacnt = 1;
+ fr.stream.data[0].len = strsize(data);
+ fr.stream.data[0].base = (uint8_t *)data;
+
+ framelen = 1 + 8 + 8 + 1 + 17;
+
+ rv = ngtcp2_pkt_encode_stream_frame(buf, sizeof(buf), &fr.stream);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+
+ rv = ngtcp2_pkt_decode_stream_frame(&nfr.stream, buf, framelen);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+ CU_ASSERT(fr.type == nfr.type);
+ CU_ASSERT((NGTCP2_STREAM_FIN_BIT | NGTCP2_STREAM_OFF_BIT |
+ NGTCP2_STREAM_LEN_BIT) == nfr.stream.flags);
+ CU_ASSERT(fr.stream.fin == nfr.stream.fin);
+ CU_ASSERT(fr.stream.stream_id == nfr.stream.stream_id);
+ CU_ASSERT(fr.stream.offset == nfr.stream.offset);
+ CU_ASSERT(1 == nfr.stream.datacnt);
+ CU_ASSERT(fr.stream.data[0].len == nfr.stream.data[0].len);
+ CU_ASSERT(0 == memcmp(fr.stream.data[0].base, nfr.stream.data[0].base,
+ fr.stream.data[0].len));
+
+ /* Make sure that we check the length properly. */
+ for (i = 1; i < framelen; ++i) {
+ rv = ngtcp2_pkt_decode_stream_frame(&nfr.stream, buf, i);
+
+ CU_ASSERT(NGTCP2_ERR_FRAME_ENCODING == rv);
+ }
+
+ memset(&nfr, 0, sizeof(nfr));
+
+ /* NOBUF: Fin + 32 bits Stream ID + 62 bits Offset + Data Length */
+ fr.type = NGTCP2_FRAME_STREAM;
+ fr.stream.fin = 1;
+ fr.stream.stream_id = 0xf1f2f3f4u;
+ fr.stream.offset = 0x31f2f3f4f5f6f7f8llu;
+ fr.stream.datacnt = 1;
+ fr.stream.data[0].len = strsize(data);
+ fr.stream.data[0].base = (uint8_t *)data;
+
+ framelen = 1 + 8 + 8 + 1 + 17;
+
+ rv = ngtcp2_pkt_encode_stream_frame(buf, framelen - 1, &fr.stream);
+
+ CU_ASSERT(NGTCP2_ERR_NOBUF == rv);
+}
+
+void test_ngtcp2_pkt_encode_ack_frame(void) {
+ uint8_t buf[256];
+ ngtcp2_max_frame mfr, nmfr;
+ ngtcp2_frame *fr = &mfr.fr, *nfr = &nmfr.fr;
+ ngtcp2_ssize rv;
+ size_t framelen;
+ size_t i;
+ ngtcp2_ack_range *ranges;
+
+ /* 0 Num Blocks */
+ fr->type = NGTCP2_FRAME_ACK;
+ fr->ack.largest_ack = 0xf1f2f3f4llu;
+ fr->ack.first_ack_range = 0;
+ fr->ack.ack_delay = 0;
+ fr->ack.rangecnt = 0;
+
+ framelen = 1 + 8 + 1 + 1 + 1;
+
+ rv = ngtcp2_pkt_encode_ack_frame(buf, sizeof(buf), &fr->ack);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+
+ rv = ngtcp2_pkt_decode_ack_frame(&nfr->ack, buf, framelen);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+ CU_ASSERT(fr->type == nfr->type);
+ CU_ASSERT(fr->ack.largest_ack == nfr->ack.largest_ack);
+ CU_ASSERT(fr->ack.ack_delay == nfr->ack.ack_delay);
+ CU_ASSERT(fr->ack.rangecnt == nfr->ack.rangecnt);
+
+ memset(&nmfr, 0, sizeof(nmfr));
+
+ /* 2 Num Blocks */
+ fr->type = NGTCP2_FRAME_ACK;
+ fr->ack.largest_ack = 0xf1f2f3f4llu;
+ fr->ack.first_ack_range = 0xe1e2e3e4llu;
+ fr->ack.ack_delay = 0xf1f2;
+ fr->ack.rangecnt = 2;
+ ranges = fr->ack.ranges;
+ ranges[0].gap = 255;
+ ranges[0].len = 0xd1d2d3d4llu;
+ ranges[1].gap = 1;
+ ranges[1].len = 0xd1d2d3d4llu;
+
+ framelen = 1 + 8 + 4 + 1 + 8 + (2 + 8) + (1 + 8);
+
+ rv = ngtcp2_pkt_encode_ack_frame(buf, sizeof(buf), &fr->ack);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+
+ rv = ngtcp2_pkt_decode_ack_frame(&nfr->ack, buf, framelen);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+ CU_ASSERT(fr->type == nfr->type);
+ CU_ASSERT(fr->ack.largest_ack == nfr->ack.largest_ack);
+ CU_ASSERT(fr->ack.ack_delay == nfr->ack.ack_delay);
+ CU_ASSERT(fr->ack.rangecnt == nfr->ack.rangecnt);
+
+ for (i = 0; i < fr->ack.rangecnt; ++i) {
+ CU_ASSERT(fr->ack.ranges[i].gap == nfr->ack.ranges[i].gap);
+ CU_ASSERT(fr->ack.ranges[i].len == nfr->ack.ranges[i].len);
+ }
+
+ memset(&nmfr, 0, sizeof(nmfr));
+}
+
+void test_ngtcp2_pkt_encode_ack_ecn_frame(void) {
+ uint8_t buf[256];
+ ngtcp2_max_frame mfr, nmfr;
+ ngtcp2_frame *fr = &mfr.fr, *nfr = &nmfr.fr;
+ ngtcp2_ssize rv;
+ size_t framelen;
+ size_t i;
+ ngtcp2_ack_range *ranges;
+
+ /* 0 Num Blocks */
+ fr->type = NGTCP2_FRAME_ACK_ECN;
+ fr->ack.largest_ack = 0xf1f2f3f4llu;
+ fr->ack.first_ack_range = 0;
+ fr->ack.ack_delay = 0;
+ fr->ack.rangecnt = 0;
+ fr->ack.ecn.ect0 = 64;
+ fr->ack.ecn.ect1 = 16384;
+ fr->ack.ecn.ce = 1073741824;
+
+ framelen = 1 + 8 + 1 + 1 + 1 + 2 + 4 + 8;
+
+ rv = ngtcp2_pkt_encode_ack_frame(buf, sizeof(buf), &fr->ack);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+
+ rv = ngtcp2_pkt_decode_ack_frame(&nfr->ack, buf, framelen);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+ CU_ASSERT(fr->type == nfr->type);
+ CU_ASSERT(fr->ack.largest_ack == nfr->ack.largest_ack);
+ CU_ASSERT(fr->ack.ack_delay == nfr->ack.ack_delay);
+ CU_ASSERT(fr->ack.rangecnt == nfr->ack.rangecnt);
+ CU_ASSERT(fr->ack.ecn.ect0 == nfr->ack.ecn.ect0);
+ CU_ASSERT(fr->ack.ecn.ect1 == nfr->ack.ecn.ect1);
+ CU_ASSERT(fr->ack.ecn.ce == nfr->ack.ecn.ce);
+
+ memset(&nmfr, 0, sizeof(nmfr));
+
+ /* 2 Num Blocks */
+ fr->type = NGTCP2_FRAME_ACK_ECN;
+ fr->ack.largest_ack = 0xf1f2f3f4llu;
+ fr->ack.first_ack_range = 0xe1e2e3e4llu;
+ fr->ack.ack_delay = 0xf1f2;
+ fr->ack.rangecnt = 2;
+ ranges = fr->ack.ranges;
+ ranges[0].gap = 255;
+ ranges[0].len = 0xd1d2d3d4llu;
+ ranges[1].gap = 1;
+ ranges[1].len = 0xd1d2d3d4llu;
+ fr->ack.ecn.ect0 = 0;
+ fr->ack.ecn.ect1 = 64;
+ fr->ack.ecn.ce = 16384;
+
+ framelen = 1 + 8 + 4 + 1 + 8 + (2 + 8) + (1 + 8) + 1 + 2 + 4;
+
+ rv = ngtcp2_pkt_encode_ack_frame(buf, sizeof(buf), &fr->ack);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+
+ rv = ngtcp2_pkt_decode_ack_frame(&nfr->ack, buf, framelen);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+ CU_ASSERT(fr->type == nfr->type);
+ CU_ASSERT(fr->ack.largest_ack == nfr->ack.largest_ack);
+ CU_ASSERT(fr->ack.ack_delay == nfr->ack.ack_delay);
+ CU_ASSERT(fr->ack.rangecnt == nfr->ack.rangecnt);
+
+ for (i = 0; i < fr->ack.rangecnt; ++i) {
+ CU_ASSERT(fr->ack.ranges[i].gap == nfr->ack.ranges[i].gap);
+ CU_ASSERT(fr->ack.ranges[i].len == nfr->ack.ranges[i].len);
+ }
+
+ CU_ASSERT(fr->ack.ecn.ect0 == nfr->ack.ecn.ect0);
+ CU_ASSERT(fr->ack.ecn.ect1 == nfr->ack.ecn.ect1);
+ CU_ASSERT(fr->ack.ecn.ce == nfr->ack.ecn.ce);
+
+ memset(&nmfr, 0, sizeof(nmfr));
+}
+
+void test_ngtcp2_pkt_encode_reset_stream_frame(void) {
+ uint8_t buf[32];
+ ngtcp2_reset_stream fr, nfr;
+ ngtcp2_ssize rv;
+ size_t framelen = 1 + 4 + 4 + 8;
+
+ fr.type = NGTCP2_FRAME_RESET_STREAM;
+ fr.stream_id = 1000000007;
+ fr.app_error_code = 0xe1e2;
+ fr.final_size = 0x31f2f3f4f5f6f7f8llu;
+
+ rv = ngtcp2_pkt_encode_reset_stream_frame(buf, sizeof(buf), &fr);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+
+ rv = ngtcp2_pkt_decode_reset_stream_frame(&nfr, buf, framelen);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+ CU_ASSERT(fr.type == nfr.type);
+ CU_ASSERT(fr.stream_id == nfr.stream_id);
+ CU_ASSERT(fr.app_error_code == nfr.app_error_code);
+ CU_ASSERT(fr.final_size == nfr.final_size);
+}
+
+void test_ngtcp2_pkt_encode_connection_close_frame(void) {
+ uint8_t buf[2048];
+ ngtcp2_frame fr, nfr;
+ ngtcp2_ssize rv;
+ size_t framelen;
+ uint8_t reason[1024];
+
+ memset(reason, 0xfa, sizeof(reason));
+
+ /* no Reason Phrase */
+ fr.type = NGTCP2_FRAME_CONNECTION_CLOSE;
+ fr.connection_close.error_code = 0xf1f2u;
+ fr.connection_close.frame_type = 255;
+ fr.connection_close.reasonlen = 0;
+ fr.connection_close.reason = NULL;
+
+ framelen = 1 + 4 + 2 + 1;
+
+ rv = ngtcp2_pkt_encode_connection_close_frame(buf, sizeof(buf),
+ &fr.connection_close);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+
+ rv = ngtcp2_pkt_decode_connection_close_frame(&nfr.connection_close, buf,
+ framelen);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+ CU_ASSERT(fr.type == nfr.type);
+ CU_ASSERT(fr.connection_close.error_code == nfr.connection_close.error_code);
+ CU_ASSERT(fr.connection_close.reasonlen == nfr.connection_close.reasonlen);
+ CU_ASSERT(fr.connection_close.reason == nfr.connection_close.reason);
+
+ memset(&nfr, 0, sizeof(nfr));
+
+ /* 1024 bytes Reason Phrase */
+ fr.type = NGTCP2_FRAME_CONNECTION_CLOSE;
+ fr.connection_close.error_code = 0xf3f4u;
+ fr.connection_close.frame_type = 0;
+ fr.connection_close.reasonlen = sizeof(reason);
+ fr.connection_close.reason = reason;
+
+ framelen = 1 + 4 + 1 + 2 + sizeof(reason);
+
+ rv = ngtcp2_pkt_encode_connection_close_frame(buf, sizeof(buf),
+ &fr.connection_close);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+
+ rv = ngtcp2_pkt_decode_connection_close_frame(&nfr.connection_close, buf,
+ framelen);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+ CU_ASSERT(fr.type == nfr.type);
+ CU_ASSERT(fr.connection_close.error_code == nfr.connection_close.error_code);
+ CU_ASSERT(fr.connection_close.reasonlen == nfr.connection_close.reasonlen);
+ CU_ASSERT(0 == memcmp(reason, nfr.connection_close.reason, sizeof(reason)));
+
+ memset(&nfr, 0, sizeof(nfr));
+}
+
+void test_ngtcp2_pkt_encode_connection_close_app_frame(void) {
+ uint8_t buf[2048];
+ ngtcp2_frame fr, nfr;
+ ngtcp2_ssize rv;
+ size_t framelen;
+ uint8_t reason[1024];
+
+ memset(reason, 0xfa, sizeof(reason));
+
+ /* no Reason Phrase */
+ fr.type = NGTCP2_FRAME_CONNECTION_CLOSE_APP;
+ fr.connection_close.error_code = 0xf1f2u;
+ fr.connection_close.frame_type = 0xff; /* This must be ignored. */
+ fr.connection_close.reasonlen = 0;
+ fr.connection_close.reason = NULL;
+
+ framelen = 1 + 4 + 1;
+
+ rv = ngtcp2_pkt_encode_connection_close_frame(buf, sizeof(buf),
+ &fr.connection_close);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+
+ rv = ngtcp2_pkt_decode_connection_close_frame(&nfr.connection_close, buf,
+ framelen);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+ CU_ASSERT(fr.type == nfr.type);
+ CU_ASSERT(fr.connection_close.error_code == nfr.connection_close.error_code);
+ CU_ASSERT(0 == nfr.connection_close.frame_type);
+ CU_ASSERT(fr.connection_close.reasonlen == nfr.connection_close.reasonlen);
+ CU_ASSERT(fr.connection_close.reason == nfr.connection_close.reason);
+
+ memset(&nfr, 0, sizeof(nfr));
+}
+
+void test_ngtcp2_pkt_encode_max_data_frame(void) {
+ uint8_t buf[16];
+ ngtcp2_max_data fr, nfr;
+ ngtcp2_ssize rv;
+ size_t framelen = 1 + 8;
+
+ fr.type = NGTCP2_FRAME_MAX_DATA;
+ fr.max_data = 0x31f2f3f4f5f6f7f8llu;
+
+ rv = ngtcp2_pkt_encode_max_data_frame(buf, sizeof(buf), &fr);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+
+ rv = ngtcp2_pkt_decode_max_data_frame(&nfr, buf, framelen);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+ CU_ASSERT(fr.type == nfr.type);
+ CU_ASSERT(fr.max_data == nfr.max_data);
+}
+
+void test_ngtcp2_pkt_encode_max_stream_data_frame(void) {
+ uint8_t buf[17];
+ ngtcp2_max_stream_data fr, nfr;
+ ngtcp2_ssize rv;
+ size_t framelen = 1 + 8 + 8;
+
+ fr.type = NGTCP2_FRAME_MAX_STREAM_DATA;
+ fr.stream_id = 0xf1f2f3f4u;
+ fr.max_stream_data = 0x35f6f7f8f9fafbfcllu;
+
+ rv = ngtcp2_pkt_encode_max_stream_data_frame(buf, sizeof(buf), &fr);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+
+ rv = ngtcp2_pkt_decode_max_stream_data_frame(&nfr, buf, framelen);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+ CU_ASSERT(fr.type == nfr.type);
+ CU_ASSERT(fr.stream_id == nfr.stream_id);
+ CU_ASSERT(fr.max_stream_data == nfr.max_stream_data);
+}
+
+void test_ngtcp2_pkt_encode_max_streams_frame(void) {
+ uint8_t buf[16];
+ ngtcp2_max_streams fr, nfr;
+ ngtcp2_ssize rv;
+ size_t framelen = 1 + 8;
+
+ fr.type = NGTCP2_FRAME_MAX_STREAMS_BIDI;
+ fr.max_streams = 0xf1f2f3f4u;
+
+ rv = ngtcp2_pkt_encode_max_streams_frame(buf, sizeof(buf), &fr);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+
+ rv = ngtcp2_pkt_decode_max_streams_frame(&nfr, buf, framelen);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+ CU_ASSERT(fr.type == nfr.type);
+ CU_ASSERT(fr.max_streams == nfr.max_streams);
+}
+
+void test_ngtcp2_pkt_encode_ping_frame(void) {
+ uint8_t buf[3];
+ ngtcp2_ping fr, nfr;
+ ngtcp2_ssize rv;
+ size_t framelen;
+
+ fr.type = NGTCP2_FRAME_PING;
+
+ framelen = 1;
+
+ rv = ngtcp2_pkt_encode_ping_frame(buf, sizeof(buf), &fr);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+
+ rv = ngtcp2_pkt_decode_ping_frame(&nfr, buf, framelen);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+ CU_ASSERT(fr.type == nfr.type);
+}
+
+void test_ngtcp2_pkt_encode_data_blocked_frame(void) {
+ uint8_t buf[9];
+ ngtcp2_data_blocked fr, nfr;
+ ngtcp2_ssize rv;
+ size_t framelen = 1 + 8;
+
+ fr.type = NGTCP2_FRAME_DATA_BLOCKED;
+ fr.offset = 0x31f2f3f4f5f6f7f8llu;
+
+ rv = ngtcp2_pkt_encode_data_blocked_frame(buf, sizeof(buf), &fr);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+
+ rv = ngtcp2_pkt_decode_data_blocked_frame(&nfr, buf, framelen);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+ CU_ASSERT(fr.type == nfr.type);
+ CU_ASSERT(fr.offset == nfr.offset);
+}
+
+void test_ngtcp2_pkt_encode_stream_data_blocked_frame(void) {
+ uint8_t buf[17];
+ ngtcp2_stream_data_blocked fr, nfr;
+ ngtcp2_ssize rv;
+ size_t framelen = 1 + 8 + 8;
+
+ fr.type = NGTCP2_FRAME_STREAM_DATA_BLOCKED;
+ fr.stream_id = 0xf1f2f3f4u;
+ fr.offset = 0x35f6f7f8f9fafbfcllu;
+
+ rv = ngtcp2_pkt_encode_stream_data_blocked_frame(buf, sizeof(buf), &fr);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+
+ rv = ngtcp2_pkt_decode_stream_data_blocked_frame(&nfr, buf, framelen);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+ CU_ASSERT(fr.type == nfr.type);
+ CU_ASSERT(fr.stream_id == nfr.stream_id);
+ CU_ASSERT(fr.offset == nfr.offset);
+}
+
+void test_ngtcp2_pkt_encode_streams_blocked_frame(void) {
+ uint8_t buf[9];
+ ngtcp2_streams_blocked fr, nfr;
+ ngtcp2_ssize rv;
+ size_t framelen = 1 + 8;
+
+ fr.type = NGTCP2_FRAME_STREAMS_BLOCKED_BIDI;
+ fr.max_streams = 0xf1f2f3f4u;
+
+ rv = ngtcp2_pkt_encode_streams_blocked_frame(buf, sizeof(buf), &fr);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+
+ rv = ngtcp2_pkt_decode_streams_blocked_frame(&nfr, buf, framelen);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+ CU_ASSERT(fr.type == nfr.type);
+ CU_ASSERT(fr.max_streams == nfr.max_streams);
+}
+
+void test_ngtcp2_pkt_encode_new_connection_id_frame(void) {
+ uint8_t buf[256];
+ ngtcp2_new_connection_id fr, nfr;
+ ngtcp2_ssize rv;
+ size_t framelen = 1 + 4 + 2 + 1 + 18 + NGTCP2_STATELESS_RESET_TOKENLEN;
+
+ fr.type = NGTCP2_FRAME_NEW_CONNECTION_ID;
+ fr.seq = 1000000009;
+ fr.retire_prior_to = 255;
+ scid_init(&fr.cid);
+ memset(fr.stateless_reset_token, 0xe1, sizeof(fr.stateless_reset_token));
+
+ rv = ngtcp2_pkt_encode_new_connection_id_frame(buf, sizeof(buf), &fr);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+
+ rv = ngtcp2_pkt_decode_new_connection_id_frame(&nfr, buf, framelen);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+ CU_ASSERT(fr.type == nfr.type);
+ CU_ASSERT(fr.seq == nfr.seq);
+ CU_ASSERT(ngtcp2_cid_eq(&fr.cid, &nfr.cid));
+ CU_ASSERT(0 == memcmp(fr.stateless_reset_token, nfr.stateless_reset_token,
+ sizeof(fr.stateless_reset_token)));
+}
+
+void test_ngtcp2_pkt_encode_stop_sending_frame(void) {
+ uint8_t buf[16];
+ ngtcp2_stop_sending fr, nfr;
+ ngtcp2_ssize rv;
+ size_t framelen = 1 + 8 + 4;
+
+ fr.type = NGTCP2_FRAME_STOP_SENDING;
+ fr.stream_id = 0xf1f2f3f4u;
+ fr.app_error_code = 0xe1e2u;
+
+ rv = ngtcp2_pkt_encode_stop_sending_frame(buf, sizeof(buf), &fr);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+
+ rv = ngtcp2_pkt_decode_stop_sending_frame(&nfr, buf, framelen);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+ CU_ASSERT(fr.type == nfr.type);
+ CU_ASSERT(fr.stream_id == nfr.stream_id);
+ CU_ASSERT(fr.app_error_code == nfr.app_error_code);
+}
+
+void test_ngtcp2_pkt_encode_path_challenge_frame(void) {
+ uint8_t buf[9];
+ ngtcp2_path_challenge fr, nfr;
+ ngtcp2_ssize rv;
+ size_t framelen = 1 + 8;
+ size_t i;
+
+ fr.type = NGTCP2_FRAME_PATH_CHALLENGE;
+ for (i = 0; i < sizeof(fr.data); ++i) {
+ fr.data[i] = (uint8_t)(i + 1);
+ }
+
+ rv = ngtcp2_pkt_encode_path_challenge_frame(buf, sizeof(buf), &fr);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+
+ rv = ngtcp2_pkt_decode_path_challenge_frame(&nfr, buf, framelen);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+ CU_ASSERT(fr.type == nfr.type);
+ CU_ASSERT(0 == memcmp(fr.data, nfr.data, sizeof(fr.data)));
+}
+
+void test_ngtcp2_pkt_encode_path_response_frame(void) {
+ uint8_t buf[9];
+ ngtcp2_path_response fr, nfr;
+ ngtcp2_ssize rv;
+ size_t framelen = 1 + 8;
+ size_t i;
+
+ fr.type = NGTCP2_FRAME_PATH_RESPONSE;
+ for (i = 0; i < sizeof(fr.data); ++i) {
+ fr.data[i] = (uint8_t)(i + 1);
+ }
+
+ rv = ngtcp2_pkt_encode_path_response_frame(buf, sizeof(buf), &fr);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+
+ rv = ngtcp2_pkt_decode_path_response_frame(&nfr, buf, framelen);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+ CU_ASSERT(fr.type == nfr.type);
+ CU_ASSERT(0 == memcmp(fr.data, nfr.data, sizeof(fr.data)));
+}
+
+void test_ngtcp2_pkt_encode_crypto_frame(void) {
+ const uint8_t data[] = "0123456789abcdef1";
+ uint8_t buf[256];
+ ngtcp2_frame fr, nfr;
+ ngtcp2_ssize rv;
+ size_t framelen;
+
+ fr.type = NGTCP2_FRAME_CRYPTO;
+ fr.crypto.offset = 0x31f2f3f4f5f6f7f8llu;
+ fr.crypto.datacnt = 1;
+ fr.crypto.data[0].len = strsize(data);
+ fr.crypto.data[0].base = (uint8_t *)data;
+
+ framelen = 1 + 8 + 1 + 17;
+
+ rv = ngtcp2_pkt_encode_crypto_frame(buf, sizeof(buf), &fr.crypto);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+
+ rv = ngtcp2_pkt_decode_crypto_frame(&nfr.crypto, buf, framelen);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+ CU_ASSERT(fr.type == nfr.type);
+ CU_ASSERT(fr.crypto.offset == nfr.crypto.offset);
+ CU_ASSERT(fr.crypto.datacnt == nfr.crypto.datacnt);
+ CU_ASSERT(fr.crypto.data[0].len == nfr.crypto.data[0].len);
+ CU_ASSERT(0 == memcmp(fr.crypto.data[0].base, nfr.crypto.data[0].base,
+ fr.crypto.data[0].len));
+}
+
+void test_ngtcp2_pkt_encode_new_token_frame(void) {
+ const uint8_t token[] = "0123456789abcdef2";
+ uint8_t buf[256];
+ ngtcp2_frame fr, nfr;
+ ngtcp2_ssize rv;
+ size_t framelen;
+
+ fr.type = NGTCP2_FRAME_NEW_TOKEN;
+ ngtcp2_vec_init(&fr.new_token.token, token, strsize(token));
+
+ framelen = 1 + 1 + strsize(token);
+
+ rv = ngtcp2_pkt_encode_new_token_frame(buf, sizeof(buf), &fr.new_token);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+
+ rv = ngtcp2_pkt_decode_new_token_frame(&nfr.new_token, buf, framelen);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+ CU_ASSERT(fr.type == nfr.type);
+ CU_ASSERT(fr.new_token.token.len == nfr.new_token.token.len);
+ CU_ASSERT(0 == memcmp(fr.new_token.token.base, nfr.new_token.token.base,
+ fr.new_token.token.len));
+}
+
+void test_ngtcp2_pkt_encode_retire_connection_id_frame(void) {
+ uint8_t buf[256];
+ ngtcp2_frame fr, nfr;
+ ngtcp2_ssize rv;
+ size_t framelen;
+
+ fr.type = NGTCP2_FRAME_RETIRE_CONNECTION_ID;
+ fr.retire_connection_id.seq = 1000000007;
+
+ framelen = 1 + ngtcp2_put_uvarintlen(fr.retire_connection_id.seq);
+
+ rv = ngtcp2_pkt_encode_retire_connection_id_frame(buf, sizeof(buf),
+ &fr.retire_connection_id);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+
+ rv = ngtcp2_pkt_decode_retire_connection_id_frame(&nfr.retire_connection_id,
+ buf, framelen);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+ CU_ASSERT(fr.type == nfr.type);
+ CU_ASSERT(fr.retire_connection_id.seq == nfr.retire_connection_id.seq);
+}
+
+void test_ngtcp2_pkt_encode_handshake_done_frame(void) {
+ uint8_t buf[16];
+ ngtcp2_handshake_done fr, nfr;
+ ngtcp2_ssize rv;
+ size_t framelen = 1;
+
+ fr.type = NGTCP2_FRAME_HANDSHAKE_DONE;
+
+ rv = ngtcp2_pkt_encode_handshake_done_frame(buf, sizeof(buf), &fr);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+
+ rv = ngtcp2_pkt_decode_handshake_done_frame(&nfr, buf, framelen);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+ CU_ASSERT(fr.type == nfr.type);
+}
+
+void test_ngtcp2_pkt_encode_datagram_frame(void) {
+ const uint8_t data[] = "0123456789abcdef3";
+ uint8_t buf[256];
+ ngtcp2_frame fr, nfr;
+ ngtcp2_ssize rv;
+ size_t framelen;
+
+ fr.type = NGTCP2_FRAME_DATAGRAM_LEN;
+ fr.datagram.datacnt = 1;
+ fr.datagram.data = fr.datagram.rdata;
+ fr.datagram.rdata[0].len = strsize(data);
+ fr.datagram.rdata[0].base = (uint8_t *)data;
+
+ framelen = 1 + 1 + 17;
+
+ rv = ngtcp2_pkt_encode_datagram_frame(buf, sizeof(buf), &fr.datagram);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+
+ rv = ngtcp2_pkt_decode_datagram_frame(&nfr.datagram, buf, framelen);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+ CU_ASSERT(fr.type == nfr.type);
+ CU_ASSERT(fr.datagram.datacnt == nfr.datagram.datacnt);
+ CU_ASSERT(fr.datagram.data->len == nfr.datagram.data->len);
+ CU_ASSERT(0 == memcmp(fr.datagram.data->base, nfr.datagram.data->base,
+ fr.datagram.data->len));
+
+ memset(&nfr, 0, sizeof(nfr));
+
+ /* Without length field */
+ fr.type = NGTCP2_FRAME_DATAGRAM;
+ fr.datagram.datacnt = 1;
+ fr.datagram.data = fr.datagram.rdata;
+ fr.datagram.rdata[0].len = strsize(data);
+ fr.datagram.rdata[0].base = (uint8_t *)data;
+
+ framelen = 1 + 17;
+
+ rv = ngtcp2_pkt_encode_datagram_frame(buf, sizeof(buf), &fr.datagram);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+
+ rv = ngtcp2_pkt_decode_datagram_frame(&nfr.datagram, buf, framelen);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+ CU_ASSERT(fr.type == nfr.type);
+ CU_ASSERT(fr.datagram.datacnt == nfr.datagram.datacnt);
+ CU_ASSERT(fr.datagram.data->len == nfr.datagram.data->len);
+ CU_ASSERT(0 == memcmp(fr.datagram.data->base, nfr.datagram.data->base,
+ fr.datagram.data->len));
+
+ memset(&nfr, 0, sizeof(nfr));
+
+ /* Zero length data with length field */
+ fr.type = NGTCP2_FRAME_DATAGRAM_LEN;
+ fr.datagram.datacnt = 0;
+ fr.datagram.data = NULL;
+
+ framelen = 1 + 1;
+
+ rv = ngtcp2_pkt_encode_datagram_frame(buf, sizeof(buf), &fr.datagram);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+
+ rv = ngtcp2_pkt_decode_datagram_frame(&nfr.datagram, buf, framelen);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+ CU_ASSERT(fr.type == nfr.type);
+ CU_ASSERT(fr.datagram.datacnt == nfr.datagram.datacnt);
+ CU_ASSERT(NULL == nfr.datagram.data);
+
+ /* Zero length data without length field */
+ fr.type = NGTCP2_FRAME_DATAGRAM;
+ fr.datagram.datacnt = 0;
+ fr.datagram.data = NULL;
+
+ framelen = 1;
+
+ rv = ngtcp2_pkt_encode_datagram_frame(buf, sizeof(buf), &fr.datagram);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+
+ rv = ngtcp2_pkt_decode_datagram_frame(&nfr.datagram, buf, framelen);
+
+ CU_ASSERT((ngtcp2_ssize)framelen == rv);
+ CU_ASSERT(fr.type == nfr.type);
+ CU_ASSERT(fr.datagram.datacnt == nfr.datagram.datacnt);
+ CU_ASSERT(NULL == nfr.datagram.data);
+}
+
+void test_ngtcp2_pkt_adjust_pkt_num(void) {
+ CU_ASSERT(0xaa831f94llu ==
+ ngtcp2_pkt_adjust_pkt_num(0xaa82f30ellu, 0x1f94, 16));
+
+ CU_ASSERT(0xff == ngtcp2_pkt_adjust_pkt_num(0x0100, 0xff, 8));
+ CU_ASSERT(0x01ff == ngtcp2_pkt_adjust_pkt_num(0x01ff, 0xff, 8));
+ CU_ASSERT(0x0fff == ngtcp2_pkt_adjust_pkt_num(0x1000, 0xff, 8));
+ CU_ASSERT(0x80 == ngtcp2_pkt_adjust_pkt_num(0x00, 0x80, 8));
+ CU_ASSERT(0x3fffffffffffffabllu ==
+ ngtcp2_pkt_adjust_pkt_num(NGTCP2_MAX_PKT_NUM, 0xab, 8));
+ CU_ASSERT(0x4000000000000000llu ==
+ ngtcp2_pkt_adjust_pkt_num(NGTCP2_MAX_PKT_NUM, 0x00, 8));
+ CU_ASSERT(250 == ngtcp2_pkt_adjust_pkt_num(255, 250, 8));
+ CU_ASSERT(8 == ngtcp2_pkt_adjust_pkt_num(50, 8, 8));
+ CU_ASSERT(0 == ngtcp2_pkt_adjust_pkt_num(-1, 0, 8));
+}
+
+void test_ngtcp2_pkt_validate_ack(void) {
+ int rv;
+ ngtcp2_ack fr;
+
+ /* too long first_ack_range */
+ fr.largest_ack = 1;
+ fr.first_ack_range = 2;
+ fr.rangecnt = 0;
+
+ rv = ngtcp2_pkt_validate_ack(&fr);
+
+ CU_ASSERT(NGTCP2_ERR_ACK_FRAME == rv);
+
+ /* gap is too large */
+ fr.largest_ack = 250;
+ fr.first_ack_range = 1;
+ fr.rangecnt = 1;
+ fr.ranges[0].gap = 248;
+ fr.ranges[0].len = 0;
+
+ rv = ngtcp2_pkt_validate_ack(&fr);
+
+ CU_ASSERT(NGTCP2_ERR_ACK_FRAME == rv);
+
+ /* too large range len */
+ fr.largest_ack = 250;
+ fr.first_ack_range = 0;
+ fr.rangecnt = 1;
+ fr.ranges[0].gap = 248;
+ fr.ranges[0].len = 1;
+
+ rv = ngtcp2_pkt_validate_ack(&fr);
+
+ CU_ASSERT(NGTCP2_ERR_ACK_FRAME == rv);
+}
+
+void test_ngtcp2_pkt_write_stateless_reset(void) {
+ uint8_t buf[256];
+ ngtcp2_ssize spktlen;
+ uint8_t token[NGTCP2_STATELESS_RESET_TOKENLEN];
+ uint8_t rand[256];
+ size_t i;
+ uint8_t *p;
+ size_t randlen;
+
+ memset(rand, 0, sizeof(rand));
+ for (i = 0; i < NGTCP2_STATELESS_RESET_TOKENLEN; ++i) {
+ token[i] = (uint8_t)(i + 1);
+ }
+
+ spktlen = ngtcp2_pkt_write_stateless_reset(buf, sizeof(buf), token, rand,
+ sizeof(rand));
+
+ p = buf;
+
+ CU_ASSERT(256 == spktlen);
+ CU_ASSERT(0 == (*p & NGTCP2_HEADER_FORM_BIT));
+ CU_ASSERT((*p & NGTCP2_FIXED_BIT_MASK));
+
+ ++p;
+
+ randlen = (size_t)(spktlen - (p - buf) - NGTCP2_STATELESS_RESET_TOKENLEN);
+
+ CU_ASSERT(0 == memcmp(rand, p, randlen));
+
+ p += randlen;
+
+ CU_ASSERT(0 == memcmp(token, p, NGTCP2_STATELESS_RESET_TOKENLEN));
+
+ p += NGTCP2_STATELESS_RESET_TOKENLEN;
+
+ CU_ASSERT(spktlen == p - buf);
+
+ /* Not enough buffer */
+ spktlen = ngtcp2_pkt_write_stateless_reset(
+ buf,
+ NGTCP2_MIN_STATELESS_RESET_RANDLEN - 1 + NGTCP2_STATELESS_RESET_TOKENLEN,
+ token, rand, sizeof(rand));
+
+ CU_ASSERT(NGTCP2_ERR_NOBUF == spktlen);
+}
+
+void test_ngtcp2_pkt_write_retry(void) {
+ uint8_t buf[256];
+ ngtcp2_ssize spktlen;
+ ngtcp2_cid scid, dcid, odcid;
+ ngtcp2_pkt_hd nhd;
+ uint8_t token[32];
+ size_t i;
+ ngtcp2_pkt_retry retry;
+ ngtcp2_ssize nread;
+ int rv;
+ ngtcp2_crypto_aead aead = {0};
+ ngtcp2_crypto_aead_ctx aead_ctx = {0};
+ uint8_t tag[NGTCP2_RETRY_TAGLEN] = {0};
+
+ scid_init(&scid);
+ dcid_init(&dcid);
+ rcid_init(&odcid);
+
+ for (i = 0; i < sizeof(token); ++i) {
+ token[i] = (uint8_t)i;
+ }
+
+ spktlen = ngtcp2_pkt_write_retry(buf, sizeof(buf), NGTCP2_PROTO_VER_V1, &dcid,
+ &scid, &odcid, token, sizeof(token),
+ null_retry_encrypt, &aead, &aead_ctx);
+
+ CU_ASSERT(spktlen > 0);
+
+ memset(&nhd, 0, sizeof(nhd));
+
+ nread = ngtcp2_pkt_decode_hd_long(&nhd, buf, (size_t)spktlen);
+
+ CU_ASSERT(nread > 0);
+ CU_ASSERT(NGTCP2_PKT_RETRY == nhd.type);
+ CU_ASSERT(NGTCP2_PROTO_VER_V1 == nhd.version);
+ CU_ASSERT(ngtcp2_cid_eq(&dcid, &nhd.dcid));
+ CU_ASSERT(ngtcp2_cid_eq(&scid, &nhd.scid));
+
+ rv = ngtcp2_pkt_decode_retry(&retry, buf + nread, (size_t)(spktlen - nread));
+
+ CU_ASSERT(0 == rv);
+ CU_ASSERT(sizeof(token) == retry.token.len);
+ CU_ASSERT(0 == memcmp(token, retry.token.base, sizeof(token)));
+ CU_ASSERT(0 == memcmp(tag, retry.tag, sizeof(tag)));
+}
+
+void test_ngtcp2_pkt_write_version_negotiation(void) {
+ uint8_t buf[256];
+ ngtcp2_ssize spktlen;
+ const uint32_t sv[] = {0xf1f2f3f4, 0x1f2f3f4f};
+ const uint8_t *p;
+ size_t i;
+ ngtcp2_cid dcid, scid;
+ uint32_t v;
+
+ dcid_init(&dcid);
+ scid_init(&scid);
+
+ spktlen = ngtcp2_pkt_write_version_negotiation(
+ buf, sizeof(buf), 133, dcid.data, dcid.datalen, scid.data, scid.datalen,
+ sv, ngtcp2_arraylen(sv));
+
+ CU_ASSERT((ngtcp2_ssize)(1 + 4 + 1 + dcid.datalen + 1 + scid.datalen +
+ ngtcp2_arraylen(sv) * 4) == spktlen);
+
+ p = buf;
+
+ CU_ASSERT((0x80 | 133) == buf[0]);
+
+ ++p;
+
+ p = ngtcp2_get_uint32(&v, p);
+
+ CU_ASSERT(0 == v);
+
+ CU_ASSERT(dcid.datalen == *p);
+
+ ++p;
+
+ CU_ASSERT(0 == memcmp(dcid.data, p, dcid.datalen));
+
+ p += dcid.datalen;
+
+ CU_ASSERT(scid.datalen == *p);
+
+ ++p;
+
+ CU_ASSERT(0 == memcmp(scid.data, p, scid.datalen));
+
+ p += scid.datalen;
+
+ for (i = 0; i < ngtcp2_arraylen(sv); ++i) {
+ p = ngtcp2_get_uint32(&v, p);
+
+ CU_ASSERT(sv[i] == v);
+ }
+}
+
+void test_ngtcp2_pkt_stream_max_datalen(void) {
+ size_t len;
+
+ len = ngtcp2_pkt_stream_max_datalen(63, 0, 0, 2);
+
+ CU_ASSERT((size_t)-1 == len);
+
+ len = ngtcp2_pkt_stream_max_datalen(63, 0, 0, 3);
+
+ CU_ASSERT(0 == len);
+
+ len = ngtcp2_pkt_stream_max_datalen(63, 0, 1, 3);
+
+ CU_ASSERT(0 == len);
+
+ len = ngtcp2_pkt_stream_max_datalen(63, 0, 1, 4);
+
+ CU_ASSERT(1 == len);
+
+ len = ngtcp2_pkt_stream_max_datalen(63, 1, 1, 4);
+
+ CU_ASSERT(0 == len);
+
+ len = ngtcp2_pkt_stream_max_datalen(63, 0, 63, 66);
+
+ CU_ASSERT(63 == len);
+
+ len = ngtcp2_pkt_stream_max_datalen(63, 0, 63, 65);
+
+ CU_ASSERT(62 == len);
+
+ len = ngtcp2_pkt_stream_max_datalen(63, 0, 1396, 1400);
+
+ CU_ASSERT(1396 == len);
+
+ len = ngtcp2_pkt_stream_max_datalen(63, 0, 1396, 1399);
+
+ CU_ASSERT(1395 == len);
+
+ len = ngtcp2_pkt_stream_max_datalen(63, 0, 1396, 9);
+
+ CU_ASSERT(6 == len);
+
+ len = ngtcp2_pkt_stream_max_datalen(63, 0, 16385, 16391);
+
+ CU_ASSERT(16385 == len);
+
+ len = ngtcp2_pkt_stream_max_datalen(63, 0, 16385, 16390);
+
+ CU_ASSERT(16384 == len);
+
+ len = ngtcp2_pkt_stream_max_datalen(63, 0, 1073741824, 1073741834);
+
+ CU_ASSERT(1073741824 == len);
+
+ len = ngtcp2_pkt_stream_max_datalen(63, 0, 1073741824, 1073741833);
+
+ CU_ASSERT(1073741823 == len);
+
+ len = ngtcp2_pkt_stream_max_datalen(63, 0, 16383, 16387);
+
+ CU_ASSERT(16383 == len);
+}