/* * 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 #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); }