From 343f8d9c6f20ed8762168bb5fbaa8a9138b32b3f Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> Date: Fri, 17 Aug 2018 21:04:22 +0900 Subject: [PATCH] NEW_TOKEN frame --- lib/includes/ngtcp2/ngtcp2.h | 10 +++++- lib/ngtcp2_pkt.c | 67 ++++++++++++++++++++++++++++++++++++ lib/ngtcp2_pkt.h | 28 +++++++++++++++ tests/main.c | 2 ++ tests/ngtcp2_pkt_test.c | 26 ++++++++++++++ tests/ngtcp2_pkt_test.h | 1 + 6 files changed, 133 insertions(+), 1 deletion(-) diff --git a/lib/includes/ngtcp2/ngtcp2.h b/lib/includes/ngtcp2/ngtcp2.h index d45fd043..45d0280b 100644 --- a/lib/includes/ngtcp2/ngtcp2.h +++ b/lib/includes/ngtcp2/ngtcp2.h @@ -258,7 +258,8 @@ typedef enum { NGTCP2_FRAME_PATH_CHALLENGE = 0x0e, NGTCP2_FRAME_PATH_RESPONSE = 0x0f, NGTCP2_FRAME_STREAM = 0x10, - NGTCP2_FRAME_CRYPTO = 0x18 + NGTCP2_FRAME_CRYPTO = 0x18, + NGTCP2_FRAME_NEW_TOKEN = 0x19 } ngtcp2_frame_type; typedef enum { @@ -492,6 +493,12 @@ typedef struct { ngtcp2_vec data[1]; } ngtcp2_crypto; +typedef struct { + uint8_t type; + size_t tokenlen; + const uint8_t *token; +} ngtcp2_new_token; + typedef union { uint8_t type; ngtcp2_stream stream; @@ -512,6 +519,7 @@ typedef union { ngtcp2_path_challenge path_challenge; ngtcp2_path_response path_response; ngtcp2_crypto crypto; + ngtcp2_new_token new_token; } ngtcp2_frame; typedef enum { diff --git a/lib/ngtcp2_pkt.c b/lib/ngtcp2_pkt.c index 6ed9459e..57b26615 100644 --- a/lib/ngtcp2_pkt.c +++ b/lib/ngtcp2_pkt.c @@ -368,6 +368,9 @@ ssize_t ngtcp2_pkt_decode_frame(ngtcp2_frame *dest, const uint8_t *payload, payloadlen); case NGTCP2_FRAME_CRYPTO: return ngtcp2_pkt_decode_crypto_frame(&dest->crypto, payload, payloadlen); + case NGTCP2_FRAME_NEW_TOKEN: + return ngtcp2_pkt_decode_new_token_frame(&dest->new_token, payload, + payloadlen); default: if (has_mask(type, NGTCP2_FRAME_STREAM)) { return ngtcp2_pkt_decode_stream_frame(&dest->stream, payload, payloadlen); @@ -1138,6 +1141,45 @@ ssize_t ngtcp2_pkt_decode_crypto_frame(ngtcp2_crypto *dest, return (ssize_t)len; } +ssize_t ngtcp2_pkt_decode_new_token_frame(ngtcp2_new_token *dest, + const uint8_t *payload, + size_t payloadlen) { + size_t len = 1 + 1; + const uint8_t *p; + size_t n; + size_t datalen; + + if (payloadlen < len) { + return NGTCP2_ERR_FRAME_ENCODING; + } + + p = payload + 1; + + n = ngtcp2_get_varint_len(p); + len += n - 1; + + if (payloadlen < len) { + return NGTCP2_ERR_FRAME_ENCODING; + } + + datalen = ngtcp2_get_varint(&n, p); + len += datalen; + + if (payloadlen < len) { + return NGTCP2_ERR_FRAME_ENCODING; + } + + dest->type = NGTCP2_FRAME_NEW_TOKEN; + dest->tokenlen = datalen; + p += n; + dest->token = p; + p += dest->tokenlen; + + assert((size_t)(p - payload) == len); + + return (ssize_t)len; +} + ssize_t ngtcp2_pkt_encode_frame(uint8_t *out, size_t outlen, ngtcp2_frame *fr) { switch (fr->type) { case NGTCP2_FRAME_STREAM: @@ -1185,6 +1227,8 @@ ssize_t ngtcp2_pkt_encode_frame(uint8_t *out, size_t outlen, ngtcp2_frame *fr) { &fr->path_response); case NGTCP2_FRAME_CRYPTO: return ngtcp2_pkt_encode_crypto_frame(out, outlen, &fr->crypto); + case NGTCP2_FRAME_NEW_TOKEN: + return ngtcp2_pkt_encode_new_token_frame(out, outlen, &fr->new_token); default: return NGTCP2_ERR_INVALID_ARGUMENT; } @@ -1613,6 +1657,29 @@ ssize_t ngtcp2_pkt_encode_crypto_frame(uint8_t *out, size_t outlen, return (ssize_t)len; } +ssize_t ngtcp2_pkt_encode_new_token_frame(uint8_t *out, size_t outlen, + const ngtcp2_new_token *fr) { + size_t len = 1 + ngtcp2_put_varint_len(fr->tokenlen) + fr->tokenlen; + uint8_t *p; + + if (outlen < len) { + return NGTCP2_ERR_NOBUF; + } + + p = out; + + *p++ = NGTCP2_FRAME_NEW_TOKEN; + + p = ngtcp2_put_varint(p, fr->tokenlen); + if (fr->tokenlen) { + p = ngtcp2_cpymem(p, fr->token, fr->tokenlen); + } + + assert((size_t)(p - out) == len); + + return (ssize_t)len; +} + ssize_t ngtcp2_pkt_write_version_negotiation(uint8_t *dest, size_t destlen, uint8_t unused_random, const ngtcp2_cid *dcid, diff --git a/lib/ngtcp2_pkt.h b/lib/ngtcp2_pkt.h index e3a31f3e..6c2878c5 100644 --- a/lib/ngtcp2_pkt.h +++ b/lib/ngtcp2_pkt.h @@ -414,6 +414,21 @@ ssize_t ngtcp2_pkt_decode_crypto_frame(ngtcp2_crypto *dest, const uint8_t *payload, size_t payloadlen); +/* + * ngtcp2_pkt_decode_new_token_frame decodes NEW_TOKEN frame from + * |payload| of length |payloadlen|. The result is stored in the + * object pointed by |dest|. NEW_TOKEN frame must start at + * payload[0]. This function finishes when it decodes one NEW_TOKEN + * frame, and returns the exact number of bytes read to decode a frame + * if it succeeds, or one of the following negative error codes: + * + * NGTCP2_ERR_FRAME_ENCODING + * Payload is too short to include NEW_TOKEN frame. + */ +ssize_t ngtcp2_pkt_decode_new_token_frame(ngtcp2_new_token *dest, + const uint8_t *payload, + size_t payloadlen); + /* * ngtcp2_pkt_encode_stream_frame encodes STREAM frame |fr| into the * buffer pointed by |out| of length |outlen|. @@ -661,6 +676,19 @@ ssize_t ngtcp2_pkt_encode_path_response_frame(uint8_t *out, size_t outlen, ssize_t ngtcp2_pkt_encode_crypto_frame(uint8_t *out, size_t outlen, const ngtcp2_crypto *fr); +/* + * ngtcp2_pkt_encode_new_token_frame encodes NEW_TOKEN frame |fr| into + * the buffer pointed by |out| of length |outlen|. + * + * This function returns the number of bytes written if it succeeds, + * or one of the following negative error codes: + * + * NGTCP2_ERR_NOBUF + * Buffer does not have enough capacity to write a frame. + */ +ssize_t ngtcp2_pkt_encode_new_token_frame(uint8_t *out, size_t outlen, + const ngtcp2_new_token *fr); + /* * ngtcp2_pkt_adjust_pkt_num find the full 64 bits packet number for * |pkt_num|, which is expected to be least significant |n| bits. The diff --git a/tests/main.c b/tests/main.c index cc9414d0..aef737a0 100644 --- a/tests/main.c +++ b/tests/main.c @@ -108,6 +108,8 @@ int main() { test_ngtcp2_pkt_encode_path_response_frame) || !CU_add_test(pSuite, "pkt_encode_crypto_frame", test_ngtcp2_pkt_encode_crypto_frame) || + !CU_add_test(pSuite, "pkt_encode_new_token_frame", + test_ngtcp2_pkt_encode_new_token_frame) || !CU_add_test(pSuite, "pkt_adjust_pkt_num", test_ngtcp2_pkt_adjust_pkt_num) || !CU_add_test(pSuite, "pkt_validate_ack", test_ngtcp2_pkt_validate_ack) || diff --git a/tests/ngtcp2_pkt_test.c b/tests/ngtcp2_pkt_test.c index a4255564..0d7fb219 100644 --- a/tests/ngtcp2_pkt_test.c +++ b/tests/ngtcp2_pkt_test.c @@ -913,6 +913,32 @@ void test_ngtcp2_pkt_encode_crypto_frame(void) { 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; + ssize_t rv; + size_t framelen; + + fr.type = NGTCP2_FRAME_NEW_TOKEN; + fr.new_token.tokenlen = strsize(token); + fr.new_token.token = token; + + framelen = 1 + 1 + strsize(token); + + rv = ngtcp2_pkt_encode_new_token_frame(buf, sizeof(buf), &fr.new_token); + + CU_ASSERT((ssize_t)framelen == rv); + + rv = ngtcp2_pkt_decode_new_token_frame(&nfr.new_token, buf, framelen); + + CU_ASSERT((ssize_t)framelen == rv); + CU_ASSERT(fr.type == nfr.type); + CU_ASSERT(fr.new_token.tokenlen == nfr.new_token.tokenlen); + CU_ASSERT(0 == memcmp(fr.new_token.token, nfr.new_token.token, + fr.new_token.tokenlen)); +} + void test_ngtcp2_pkt_adjust_pkt_num(void) { CU_ASSERT(0xaa831f94llu == ngtcp2_pkt_adjust_pkt_num(0xaa82f30ellu, 0x1f94, 16)); diff --git a/tests/ngtcp2_pkt_test.h b/tests/ngtcp2_pkt_test.h index 5267a0f5..9ca8bbf0 100644 --- a/tests/ngtcp2_pkt_test.h +++ b/tests/ngtcp2_pkt_test.h @@ -51,6 +51,7 @@ void test_ngtcp2_pkt_encode_stop_sending_frame(void); void test_ngtcp2_pkt_encode_path_challenge_frame(void); void test_ngtcp2_pkt_encode_path_response_frame(void); void test_ngtcp2_pkt_encode_crypto_frame(void); +void test_ngtcp2_pkt_encode_new_token_frame(void); void test_ngtcp2_pkt_adjust_pkt_num(void); void test_ngtcp2_pkt_validate_ack(void); void test_ngtcp2_pkt_write_stateless_reset(void); -- GitLab