1 /*
2 * ngtcp2
3 *
4 * Copyright (c) 2017 ngtcp2 contributors
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25 #include "ngtcp2_pkt.h"
26
27 #include <assert.h>
28 #include <string.h>
29
30 #include "ngtcp2_conv.h"
31 #include "ngtcp2_str.h"
32 #include "ngtcp2_macro.h"
33 #include "ngtcp2_cid.h"
34 #include "ngtcp2_mem.h"
35 #include "ngtcp2_vec.h"
36
ngtcp2_pkt_chain_new(ngtcp2_pkt_chain ** ppc,const ngtcp2_path * path,const ngtcp2_pkt_info * pi,const uint8_t * pkt,size_t pktlen,size_t dgramlen,ngtcp2_tstamp ts,const ngtcp2_mem * mem)37 int ngtcp2_pkt_chain_new(ngtcp2_pkt_chain **ppc, const ngtcp2_path *path,
38 const ngtcp2_pkt_info *pi, const uint8_t *pkt,
39 size_t pktlen, size_t dgramlen, ngtcp2_tstamp ts,
40 const ngtcp2_mem *mem) {
41 *ppc = ngtcp2_mem_malloc(mem, sizeof(ngtcp2_pkt_chain) + pktlen);
42 if (*ppc == NULL) {
43 return NGTCP2_ERR_NOMEM;
44 }
45
46 ngtcp2_path_storage_init2(&(*ppc)->path, path);
47 (*ppc)->pi = *pi;
48 (*ppc)->next = NULL;
49 (*ppc)->pkt = (uint8_t *)(*ppc) + sizeof(ngtcp2_pkt_chain);
50 (*ppc)->pktlen = pktlen;
51 (*ppc)->dgramlen = dgramlen;
52 (*ppc)->ts = ts;
53
54 memcpy((*ppc)->pkt, pkt, pktlen);
55
56 return 0;
57 }
58
ngtcp2_pkt_chain_del(ngtcp2_pkt_chain * pc,const ngtcp2_mem * mem)59 void ngtcp2_pkt_chain_del(ngtcp2_pkt_chain *pc, const ngtcp2_mem *mem) {
60 ngtcp2_mem_free(mem, pc);
61 }
62
ngtcp2_pkt_decode_version_cid(ngtcp2_version_cid * dest,const uint8_t * data,size_t datalen,size_t short_dcidlen)63 int ngtcp2_pkt_decode_version_cid(ngtcp2_version_cid *dest, const uint8_t *data,
64 size_t datalen, size_t short_dcidlen) {
65 size_t len;
66 uint32_t version;
67 size_t dcidlen, scidlen;
68 int supported_version;
69
70 assert(datalen);
71
72 if (data[0] & NGTCP2_HEADER_FORM_BIT) {
73 /* 1 byte (Header Form, Fixed Bit, Long Packet Type, Type-Specific bits)
74 * 4 bytes Version
75 * 1 byte DCID Length
76 * 1 byte SCID Length
77 */
78 len = 1 + 4 + 1 + 1;
79 if (datalen < len) {
80 return NGTCP2_ERR_INVALID_ARGUMENT;
81 }
82
83 dcidlen = data[5];
84 len += dcidlen;
85 if (datalen < len) {
86 return NGTCP2_ERR_INVALID_ARGUMENT;
87 }
88 scidlen = data[5 + 1 + dcidlen];
89 len += scidlen;
90 if (datalen < len) {
91 return NGTCP2_ERR_INVALID_ARGUMENT;
92 }
93
94 version = ngtcp2_get_uint32(&data[1]);
95
96 supported_version = ngtcp2_is_supported_version(version);
97
98 if (supported_version &&
99 (dcidlen > NGTCP2_MAX_CIDLEN || scidlen > NGTCP2_MAX_CIDLEN)) {
100 return NGTCP2_ERR_INVALID_ARGUMENT;
101 }
102
103 if (version && !supported_version &&
104 datalen < NGTCP2_MAX_UDP_PAYLOAD_SIZE) {
105 return NGTCP2_ERR_INVALID_ARGUMENT;
106 }
107
108 dest->version = version;
109 dest->dcid = &data[6];
110 dest->dcidlen = dcidlen;
111 dest->scid = &data[6 + dcidlen + 1];
112 dest->scidlen = scidlen;
113
114 if (!version) {
115 /* VN */
116 return 0;
117 }
118
119 if (!supported_version) {
120 return NGTCP2_ERR_VERSION_NEGOTIATION;
121 }
122 return 0;
123 }
124
125 assert(short_dcidlen <= NGTCP2_MAX_CIDLEN);
126
127 len = 1 + short_dcidlen;
128 if (datalen < len) {
129 return NGTCP2_ERR_INVALID_ARGUMENT;
130 }
131
132 dest->version = 0;
133 dest->dcid = &data[1];
134 dest->dcidlen = short_dcidlen;
135 dest->scid = NULL;
136 dest->scidlen = 0;
137
138 return 0;
139 }
140
ngtcp2_pkt_hd_init(ngtcp2_pkt_hd * hd,uint8_t flags,uint8_t type,const ngtcp2_cid * dcid,const ngtcp2_cid * scid,int64_t pkt_num,size_t pkt_numlen,uint32_t version,size_t len)141 void ngtcp2_pkt_hd_init(ngtcp2_pkt_hd *hd, uint8_t flags, uint8_t type,
142 const ngtcp2_cid *dcid, const ngtcp2_cid *scid,
143 int64_t pkt_num, size_t pkt_numlen, uint32_t version,
144 size_t len) {
145 hd->flags = flags;
146 hd->type = type;
147 if (dcid) {
148 hd->dcid = *dcid;
149 } else {
150 ngtcp2_cid_zero(&hd->dcid);
151 }
152 if (scid) {
153 hd->scid = *scid;
154 } else {
155 ngtcp2_cid_zero(&hd->scid);
156 }
157 hd->pkt_num = pkt_num;
158 hd->token.base = NULL;
159 hd->token.len = 0;
160 hd->pkt_numlen = pkt_numlen;
161 hd->version = version;
162 hd->len = len;
163 }
164
has_mask(uint8_t b,uint8_t mask)165 static int has_mask(uint8_t b, uint8_t mask) { return (b & mask) == mask; }
166
ngtcp2_pkt_decode_hd_long(ngtcp2_pkt_hd * dest,const uint8_t * pkt,size_t pktlen)167 ngtcp2_ssize ngtcp2_pkt_decode_hd_long(ngtcp2_pkt_hd *dest, const uint8_t *pkt,
168 size_t pktlen) {
169 uint8_t type;
170 uint32_t version;
171 size_t dcil, scil;
172 const uint8_t *p;
173 size_t len = 0;
174 size_t n;
175 size_t ntokenlen = 0;
176 const uint8_t *token = NULL;
177 size_t tokenlen = 0;
178 uint64_t vi;
179 uint8_t flags = NGTCP2_PKT_FLAG_LONG_FORM;
180
181 if (pktlen < 5) {
182 return NGTCP2_ERR_INVALID_ARGUMENT;
183 }
184
185 if (!(pkt[0] & NGTCP2_HEADER_FORM_BIT)) {
186 return NGTCP2_ERR_INVALID_ARGUMENT;
187 }
188
189 version = ngtcp2_get_uint32(&pkt[1]);
190
191 if (version == 0) {
192 type = NGTCP2_PKT_VERSION_NEGOTIATION;
193 /* Version Negotiation is not a long header packet. */
194 flags = NGTCP2_PKT_FLAG_NONE;
195 /* This must be Version Negotiation packet which lacks packet
196 number and payload length fields. */
197 len = 5 + 2;
198 } else {
199 if (!(pkt[0] & NGTCP2_FIXED_BIT_MASK)) {
200 flags |= NGTCP2_PKT_FLAG_FIXED_BIT_CLEAR;
201 }
202
203 type = ngtcp2_pkt_get_type_long(version, pkt[0]);
204 switch (type) {
205 case 0:
206 return NGTCP2_ERR_INVALID_ARGUMENT;
207 case NGTCP2_PKT_INITIAL:
208 len = 1 /* Token Length */ + NGTCP2_MIN_LONG_HEADERLEN -
209 1; /* Cut packet number field */
210 break;
211 case NGTCP2_PKT_RETRY:
212 /* Retry packet does not have packet number and length fields */
213 len = 5 + 2;
214 break;
215 case NGTCP2_PKT_HANDSHAKE:
216 case NGTCP2_PKT_0RTT:
217 len = NGTCP2_MIN_LONG_HEADERLEN - 1; /* Cut packet number field */
218 break;
219 default:
220 /* Unreachable */
221 assert(0);
222 }
223 }
224
225 if (pktlen < len) {
226 return NGTCP2_ERR_INVALID_ARGUMENT;
227 }
228
229 p = &pkt[5];
230 dcil = *p;
231 if (dcil > NGTCP2_MAX_CIDLEN) {
232 /* QUIC v1 implementation never expect to receive CID length more
233 than NGTCP2_MAX_CIDLEN. */
234 return NGTCP2_ERR_INVALID_ARGUMENT;
235 }
236 len += dcil;
237
238 if (pktlen < len) {
239 return NGTCP2_ERR_INVALID_ARGUMENT;
240 }
241
242 p += 1 + dcil;
243 scil = *p;
244 if (scil > NGTCP2_MAX_CIDLEN) {
245 return NGTCP2_ERR_INVALID_ARGUMENT;
246 }
247 len += scil;
248
249 if (pktlen < len) {
250 return NGTCP2_ERR_INVALID_ARGUMENT;
251 }
252
253 p += 1 + scil;
254
255 if (type == NGTCP2_PKT_INITIAL) {
256 /* Token Length */
257 ntokenlen = ngtcp2_get_varint_len(p);
258 len += ntokenlen - 1;
259
260 if (pktlen < len) {
261 return NGTCP2_ERR_INVALID_ARGUMENT;
262 }
263
264 vi = ngtcp2_get_varint(&ntokenlen, p);
265 if (pktlen - len < vi) {
266 return NGTCP2_ERR_INVALID_ARGUMENT;
267 }
268 tokenlen = (size_t)vi;
269 len += tokenlen;
270
271 p += ntokenlen;
272
273 if (tokenlen) {
274 token = p;
275 }
276
277 p += tokenlen;
278 }
279
280 switch (type) {
281 case NGTCP2_PKT_RETRY:
282 break;
283 default:
284 if (!(flags & NGTCP2_PKT_FLAG_LONG_FORM)) {
285 assert(type == NGTCP2_PKT_VERSION_NEGOTIATION);
286 /* Version Negotiation is not a long header packet. */
287 break;
288 }
289
290 /* Length */
291 n = ngtcp2_get_varint_len(p);
292 len += n - 1;
293
294 if (pktlen < len) {
295 return NGTCP2_ERR_INVALID_ARGUMENT;
296 }
297 }
298
299 dest->flags = flags;
300 dest->type = type;
301 dest->version = version;
302 dest->pkt_num = 0;
303 dest->pkt_numlen = 0;
304
305 p = &pkt[6];
306 ngtcp2_cid_init(&dest->dcid, p, dcil);
307 p += dcil + 1;
308 ngtcp2_cid_init(&dest->scid, p, scil);
309 p += scil;
310
311 dest->token.base = (uint8_t *)token;
312 dest->token.len = tokenlen;
313 p += ntokenlen + tokenlen;
314
315 switch (type) {
316 case NGTCP2_PKT_RETRY:
317 dest->len = 0;
318 break;
319 default:
320 if (!(flags & NGTCP2_PKT_FLAG_LONG_FORM)) {
321 assert(type == NGTCP2_PKT_VERSION_NEGOTIATION);
322 /* Version Negotiation is not a long header packet. */
323 dest->len = 0;
324 break;
325 }
326
327 vi = ngtcp2_get_varint(&n, p);
328 if (vi > SIZE_MAX) {
329 return NGTCP2_ERR_INVALID_ARGUMENT;
330 }
331 dest->len = (size_t)vi;
332 p += n;
333 }
334
335 assert((size_t)(p - pkt) == len);
336
337 return (ngtcp2_ssize)len;
338 }
339
ngtcp2_pkt_decode_hd_short(ngtcp2_pkt_hd * dest,const uint8_t * pkt,size_t pktlen,size_t dcidlen)340 ngtcp2_ssize ngtcp2_pkt_decode_hd_short(ngtcp2_pkt_hd *dest, const uint8_t *pkt,
341 size_t pktlen, size_t dcidlen) {
342 size_t len = 1 + dcidlen;
343 const uint8_t *p = pkt;
344 uint8_t flags = NGTCP2_PKT_FLAG_NONE;
345
346 assert(dcidlen <= NGTCP2_MAX_CIDLEN);
347
348 if (pktlen < len) {
349 return NGTCP2_ERR_INVALID_ARGUMENT;
350 }
351
352 if (pkt[0] & NGTCP2_HEADER_FORM_BIT) {
353 return NGTCP2_ERR_INVALID_ARGUMENT;
354 }
355
356 if (!(pkt[0] & NGTCP2_FIXED_BIT_MASK)) {
357 flags |= NGTCP2_PKT_FLAG_FIXED_BIT_CLEAR;
358 }
359
360 p = &pkt[1];
361
362 dest->type = NGTCP2_PKT_1RTT;
363
364 ngtcp2_cid_init(&dest->dcid, p, dcidlen);
365 p += dcidlen;
366
367 /* Set 0 to SCID so that we don't accidentally reference it and gets
368 garbage. */
369 ngtcp2_cid_zero(&dest->scid);
370
371 dest->flags = flags;
372 dest->version = 0;
373 dest->len = 0;
374 dest->pkt_num = 0;
375 dest->pkt_numlen = 0;
376 dest->token.base = NULL;
377 dest->token.len = 0;
378
379 assert((size_t)(p - pkt) == len);
380
381 return (ngtcp2_ssize)len;
382 }
383
ngtcp2_pkt_encode_hd_long(uint8_t * out,size_t outlen,const ngtcp2_pkt_hd * hd)384 ngtcp2_ssize ngtcp2_pkt_encode_hd_long(uint8_t *out, size_t outlen,
385 const ngtcp2_pkt_hd *hd) {
386 uint8_t *p;
387 size_t len = NGTCP2_MIN_LONG_HEADERLEN + hd->dcid.datalen + hd->scid.datalen -
388 2; /* NGTCP2_MIN_LONG_HEADERLEN includes 1 byte for
389 len and 1 byte for packet number. */
390
391 if (hd->type != NGTCP2_PKT_RETRY) {
392 len += NGTCP2_PKT_LENGTHLEN /* Length */ + hd->pkt_numlen;
393 }
394
395 if (hd->type == NGTCP2_PKT_INITIAL) {
396 len += ngtcp2_put_varint_len(hd->token.len) + hd->token.len;
397 }
398
399 if (outlen < len) {
400 return NGTCP2_ERR_NOBUF;
401 }
402
403 p = out;
404
405 *p = (uint8_t)(NGTCP2_HEADER_FORM_BIT |
406 (ngtcp2_pkt_versioned_type(hd->version, hd->type) << 4) |
407 (uint8_t)(hd->pkt_numlen - 1));
408 if (!(hd->flags & NGTCP2_PKT_FLAG_FIXED_BIT_CLEAR)) {
409 *p |= NGTCP2_FIXED_BIT_MASK;
410 }
411
412 ++p;
413
414 p = ngtcp2_put_uint32be(p, hd->version);
415 *p++ = (uint8_t)hd->dcid.datalen;
416 if (hd->dcid.datalen) {
417 p = ngtcp2_cpymem(p, hd->dcid.data, hd->dcid.datalen);
418 }
419 *p++ = (uint8_t)hd->scid.datalen;
420 if (hd->scid.datalen) {
421 p = ngtcp2_cpymem(p, hd->scid.data, hd->scid.datalen);
422 }
423
424 if (hd->type == NGTCP2_PKT_INITIAL) {
425 p = ngtcp2_put_varint(p, hd->token.len);
426 if (hd->token.len) {
427 p = ngtcp2_cpymem(p, hd->token.base, hd->token.len);
428 }
429 }
430
431 if (hd->type != NGTCP2_PKT_RETRY) {
432 p = ngtcp2_put_varint30(p, (uint32_t)hd->len);
433 p = ngtcp2_put_pkt_num(p, hd->pkt_num, hd->pkt_numlen);
434 }
435
436 assert((size_t)(p - out) == len);
437
438 return (ngtcp2_ssize)len;
439 }
440
ngtcp2_pkt_encode_hd_short(uint8_t * out,size_t outlen,const ngtcp2_pkt_hd * hd)441 ngtcp2_ssize ngtcp2_pkt_encode_hd_short(uint8_t *out, size_t outlen,
442 const ngtcp2_pkt_hd *hd) {
443 uint8_t *p;
444 size_t len = 1 + hd->dcid.datalen + hd->pkt_numlen;
445
446 if (outlen < len) {
447 return NGTCP2_ERR_NOBUF;
448 }
449
450 p = out;
451
452 *p = (uint8_t)(hd->pkt_numlen - 1);
453 if (!(hd->flags & NGTCP2_PKT_FLAG_FIXED_BIT_CLEAR)) {
454 *p |= NGTCP2_FIXED_BIT_MASK;
455 }
456 if (hd->flags & NGTCP2_PKT_FLAG_KEY_PHASE) {
457 *p |= NGTCP2_SHORT_KEY_PHASE_BIT;
458 }
459
460 ++p;
461
462 if (hd->dcid.datalen) {
463 p = ngtcp2_cpymem(p, hd->dcid.data, hd->dcid.datalen);
464 }
465
466 p = ngtcp2_put_pkt_num(p, hd->pkt_num, hd->pkt_numlen);
467
468 assert((size_t)(p - out) == len);
469
470 return (ngtcp2_ssize)len;
471 }
472
ngtcp2_pkt_decode_frame(ngtcp2_frame * dest,const uint8_t * payload,size_t payloadlen)473 ngtcp2_ssize ngtcp2_pkt_decode_frame(ngtcp2_frame *dest, const uint8_t *payload,
474 size_t payloadlen) {
475 uint8_t type;
476
477 if (payloadlen == 0) {
478 return 0;
479 }
480
481 type = payload[0];
482
483 switch (type) {
484 case NGTCP2_FRAME_PADDING:
485 return (ngtcp2_ssize)ngtcp2_pkt_decode_padding_frame(&dest->padding,
486 payload, payloadlen);
487 case NGTCP2_FRAME_RESET_STREAM:
488 return ngtcp2_pkt_decode_reset_stream_frame(&dest->reset_stream, payload,
489 payloadlen);
490 case NGTCP2_FRAME_CONNECTION_CLOSE:
491 case NGTCP2_FRAME_CONNECTION_CLOSE_APP:
492 return ngtcp2_pkt_decode_connection_close_frame(&dest->connection_close,
493 payload, payloadlen);
494 case NGTCP2_FRAME_MAX_DATA:
495 return ngtcp2_pkt_decode_max_data_frame(&dest->max_data, payload,
496 payloadlen);
497 case NGTCP2_FRAME_MAX_STREAM_DATA:
498 return ngtcp2_pkt_decode_max_stream_data_frame(&dest->max_stream_data,
499 payload, payloadlen);
500 case NGTCP2_FRAME_MAX_STREAMS_BIDI:
501 case NGTCP2_FRAME_MAX_STREAMS_UNI:
502 return ngtcp2_pkt_decode_max_streams_frame(&dest->max_streams, payload,
503 payloadlen);
504 case NGTCP2_FRAME_PING:
505 return ngtcp2_pkt_decode_ping_frame(&dest->ping, payload, payloadlen);
506 case NGTCP2_FRAME_DATA_BLOCKED:
507 return ngtcp2_pkt_decode_data_blocked_frame(&dest->data_blocked, payload,
508 payloadlen);
509 case NGTCP2_FRAME_STREAM_DATA_BLOCKED:
510 return ngtcp2_pkt_decode_stream_data_blocked_frame(
511 &dest->stream_data_blocked, payload, payloadlen);
512 case NGTCP2_FRAME_STREAMS_BLOCKED_BIDI:
513 case NGTCP2_FRAME_STREAMS_BLOCKED_UNI:
514 return ngtcp2_pkt_decode_streams_blocked_frame(&dest->streams_blocked,
515 payload, payloadlen);
516 case NGTCP2_FRAME_NEW_CONNECTION_ID:
517 return ngtcp2_pkt_decode_new_connection_id_frame(&dest->new_connection_id,
518 payload, payloadlen);
519 case NGTCP2_FRAME_STOP_SENDING:
520 return ngtcp2_pkt_decode_stop_sending_frame(&dest->stop_sending, payload,
521 payloadlen);
522 case NGTCP2_FRAME_ACK:
523 case NGTCP2_FRAME_ACK_ECN:
524 return ngtcp2_pkt_decode_ack_frame(&dest->ack, payload, payloadlen);
525 case NGTCP2_FRAME_PATH_CHALLENGE:
526 return ngtcp2_pkt_decode_path_challenge_frame(&dest->path_challenge,
527 payload, payloadlen);
528 case NGTCP2_FRAME_PATH_RESPONSE:
529 return ngtcp2_pkt_decode_path_response_frame(&dest->path_response, payload,
530 payloadlen);
531 case NGTCP2_FRAME_CRYPTO:
532 return ngtcp2_pkt_decode_crypto_frame(&dest->crypto, payload, payloadlen);
533 case NGTCP2_FRAME_NEW_TOKEN:
534 return ngtcp2_pkt_decode_new_token_frame(&dest->new_token, payload,
535 payloadlen);
536 case NGTCP2_FRAME_RETIRE_CONNECTION_ID:
537 return ngtcp2_pkt_decode_retire_connection_id_frame(
538 &dest->retire_connection_id, payload, payloadlen);
539 case NGTCP2_FRAME_HANDSHAKE_DONE:
540 return ngtcp2_pkt_decode_handshake_done_frame(&dest->handshake_done,
541 payload, payloadlen);
542 case NGTCP2_FRAME_DATAGRAM:
543 case NGTCP2_FRAME_DATAGRAM_LEN:
544 return ngtcp2_pkt_decode_datagram_frame(&dest->datagram, payload,
545 payloadlen);
546 default:
547 if (has_mask(type, NGTCP2_FRAME_STREAM)) {
548 return ngtcp2_pkt_decode_stream_frame(&dest->stream, payload, payloadlen);
549 }
550 return NGTCP2_ERR_FRAME_ENCODING;
551 }
552 }
553
ngtcp2_pkt_decode_stream_frame(ngtcp2_stream * dest,const uint8_t * payload,size_t payloadlen)554 ngtcp2_ssize ngtcp2_pkt_decode_stream_frame(ngtcp2_stream *dest,
555 const uint8_t *payload,
556 size_t payloadlen) {
557 uint8_t type;
558 size_t len = 1 + 1;
559 const uint8_t *p;
560 size_t datalen;
561 size_t ndatalen = 0;
562 size_t n;
563 uint64_t vi;
564
565 if (payloadlen < len) {
566 return NGTCP2_ERR_FRAME_ENCODING;
567 }
568
569 type = payload[0];
570
571 p = payload + 1;
572
573 n = ngtcp2_get_varint_len(p);
574 len += n - 1;
575
576 if (payloadlen < len) {
577 return NGTCP2_ERR_FRAME_ENCODING;
578 }
579
580 p += n;
581
582 if (type & NGTCP2_STREAM_OFF_BIT) {
583 ++len;
584 if (payloadlen < len) {
585 return NGTCP2_ERR_FRAME_ENCODING;
586 }
587
588 n = ngtcp2_get_varint_len(p);
589 len += n - 1;
590
591 if (payloadlen < len) {
592 return NGTCP2_ERR_FRAME_ENCODING;
593 }
594
595 p += n;
596 }
597
598 if (type & NGTCP2_STREAM_LEN_BIT) {
599 ++len;
600 if (payloadlen < len) {
601 return NGTCP2_ERR_FRAME_ENCODING;
602 }
603
604 ndatalen = ngtcp2_get_varint_len(p);
605 len += ndatalen - 1;
606
607 if (payloadlen < len) {
608 return NGTCP2_ERR_FRAME_ENCODING;
609 }
610
611 vi = ngtcp2_get_varint(&ndatalen, p);
612 if (payloadlen - len < vi) {
613 return NGTCP2_ERR_FRAME_ENCODING;
614 }
615 datalen = (size_t)vi;
616 len += datalen;
617 } else {
618 len = payloadlen;
619 }
620
621 p = payload + 1;
622
623 dest->type = NGTCP2_FRAME_STREAM;
624 dest->flags = (uint8_t)(type & ~NGTCP2_FRAME_STREAM);
625 dest->fin = (type & NGTCP2_STREAM_FIN_BIT) != 0;
626 dest->stream_id = (int64_t)ngtcp2_get_varint(&n, p);
627 p += n;
628
629 if (type & NGTCP2_STREAM_OFF_BIT) {
630 dest->offset = ngtcp2_get_varint(&n, p);
631 p += n;
632 } else {
633 dest->offset = 0;
634 }
635
636 if (type & NGTCP2_STREAM_LEN_BIT) {
637 p += ndatalen;
638 } else {
639 datalen = payloadlen - (size_t)(p - payload);
640 }
641
642 if (datalen) {
643 dest->data[0].len = datalen;
644 dest->data[0].base = (uint8_t *)p;
645 dest->datacnt = 1;
646 p += datalen;
647 } else {
648 dest->datacnt = 0;
649 }
650
651 assert((size_t)(p - payload) == len);
652
653 return (ngtcp2_ssize)len;
654 }
655
ngtcp2_pkt_decode_ack_frame(ngtcp2_ack * dest,const uint8_t * payload,size_t payloadlen)656 ngtcp2_ssize ngtcp2_pkt_decode_ack_frame(ngtcp2_ack *dest,
657 const uint8_t *payload,
658 size_t payloadlen) {
659 size_t num_blks, max_num_blks;
660 size_t nnum_blks;
661 size_t len = 1 + 1 + 1 + 1 + 1;
662 const uint8_t *p;
663 size_t i, j;
664 ngtcp2_ack_blk *blk;
665 size_t n;
666 uint8_t type;
667 uint64_t vi;
668
669 if (payloadlen < len) {
670 return NGTCP2_ERR_FRAME_ENCODING;
671 }
672
673 type = payload[0];
674
675 p = payload + 1;
676
677 /* Largest Acknowledged */
678 n = ngtcp2_get_varint_len(p);
679 len += n - 1;
680
681 if (payloadlen < len) {
682 return NGTCP2_ERR_FRAME_ENCODING;
683 }
684
685 p += n;
686
687 /* ACK Delay */
688 n = ngtcp2_get_varint_len(p);
689 len += n - 1;
690
691 if (payloadlen < len) {
692 return NGTCP2_ERR_FRAME_ENCODING;
693 }
694
695 p += n;
696
697 /* ACK Block Count */
698 nnum_blks = ngtcp2_get_varint_len(p);
699 len += nnum_blks - 1;
700
701 if (payloadlen < len) {
702 return NGTCP2_ERR_FRAME_ENCODING;
703 }
704
705 vi = ngtcp2_get_varint(&nnum_blks, p);
706 if (vi > SIZE_MAX / (1 + 1) || payloadlen - len < vi * (1 + 1)) {
707 return NGTCP2_ERR_FRAME_ENCODING;
708 }
709
710 num_blks = (size_t)vi;
711 len += num_blks * (1 + 1);
712
713 p += nnum_blks;
714
715 /* First ACK Block */
716 n = ngtcp2_get_varint_len(p);
717 len += n - 1;
718
719 if (payloadlen < len) {
720 return NGTCP2_ERR_FRAME_ENCODING;
721 }
722
723 p += n;
724
725 for (i = 0; i < num_blks; ++i) {
726 /* Gap, and Additional ACK Block */
727 for (j = 0; j < 2; ++j) {
728 n = ngtcp2_get_varint_len(p);
729 len += n - 1;
730
731 if (payloadlen < len) {
732 return NGTCP2_ERR_FRAME_ENCODING;
733 }
734
735 p += n;
736 }
737 }
738
739 if (type == NGTCP2_FRAME_ACK_ECN) {
740 len += 3;
741 if (payloadlen < len) {
742 return NGTCP2_ERR_FRAME_ENCODING;
743 }
744
745 for (i = 0; i < 3; ++i) {
746 n = ngtcp2_get_varint_len(p);
747 len += n - 1;
748
749 if (payloadlen < len) {
750 return NGTCP2_ERR_FRAME_ENCODING;
751 }
752
753 p += n;
754 }
755 }
756
757 /* TODO We might not decode all blocks. It could be very large. */
758 max_num_blks = ngtcp2_min(NGTCP2_MAX_ACK_BLKS, num_blks);
759
760 p = payload + 1;
761
762 dest->type = type;
763 dest->largest_ack = (int64_t)ngtcp2_get_varint(&n, p);
764 p += n;
765 dest->ack_delay = ngtcp2_get_varint(&n, p);
766 /* This value will be assigned in the upper layer. */
767 dest->ack_delay_unscaled = 0;
768 p += n;
769 dest->num_blks = max_num_blks;
770 p += nnum_blks;
771 dest->first_ack_blklen = ngtcp2_get_varint(&n, p);
772 p += n;
773
774 for (i = 0; i < max_num_blks; ++i) {
775 blk = &dest->blks[i];
776 blk->gap = ngtcp2_get_varint(&n, p);
777 p += n;
778 blk->blklen = ngtcp2_get_varint(&n, p);
779 p += n;
780 }
781 for (i = max_num_blks; i < num_blks; ++i) {
782 p += ngtcp2_get_varint_len(p);
783 p += ngtcp2_get_varint_len(p);
784 }
785
786 if (type == NGTCP2_FRAME_ACK_ECN) {
787 dest->ecn.ect0 = ngtcp2_get_varint(&n, p);
788 p += n;
789
790 dest->ecn.ect1 = ngtcp2_get_varint(&n, p);
791 p += n;
792
793 dest->ecn.ce = ngtcp2_get_varint(&n, p);
794 p += n;
795 }
796
797 assert((size_t)(p - payload) == len);
798
799 return (ngtcp2_ssize)len;
800 }
801
ngtcp2_pkt_decode_padding_frame(ngtcp2_padding * dest,const uint8_t * payload,size_t payloadlen)802 size_t ngtcp2_pkt_decode_padding_frame(ngtcp2_padding *dest,
803 const uint8_t *payload,
804 size_t payloadlen) {
805 const uint8_t *p, *ep;
806
807 assert(payloadlen > 0);
808
809 p = payload + 1;
810 ep = payload + payloadlen;
811
812 for (; p != ep && *p == NGTCP2_FRAME_PADDING; ++p)
813 ;
814
815 dest->type = NGTCP2_FRAME_PADDING;
816 dest->len = (size_t)(p - payload);
817
818 return dest->len;
819 }
820
ngtcp2_pkt_decode_reset_stream_frame(ngtcp2_reset_stream * dest,const uint8_t * payload,size_t payloadlen)821 ngtcp2_ssize ngtcp2_pkt_decode_reset_stream_frame(ngtcp2_reset_stream *dest,
822 const uint8_t *payload,
823 size_t payloadlen) {
824 size_t len = 1 + 1 + 1 + 1;
825 const uint8_t *p;
826 size_t n;
827
828 if (payloadlen < len) {
829 return NGTCP2_ERR_FRAME_ENCODING;
830 }
831
832 p = payload + 1;
833
834 n = ngtcp2_get_varint_len(p);
835 len += n - 1;
836 if (payloadlen < len) {
837 return NGTCP2_ERR_FRAME_ENCODING;
838 }
839 p += n;
840 n = ngtcp2_get_varint_len(p);
841 len += n - 1;
842 if (payloadlen < len) {
843 return NGTCP2_ERR_FRAME_ENCODING;
844 }
845 p += n;
846 n = ngtcp2_get_varint_len(p);
847 len += n - 1;
848 if (payloadlen < len) {
849 return NGTCP2_ERR_FRAME_ENCODING;
850 }
851
852 p = payload + 1;
853
854 dest->type = NGTCP2_FRAME_RESET_STREAM;
855 dest->stream_id = (int64_t)ngtcp2_get_varint(&n, p);
856 p += n;
857 dest->app_error_code = ngtcp2_get_varint(&n, p);
858 p += n;
859 dest->final_size = ngtcp2_get_varint(&n, p);
860 p += n;
861
862 assert((size_t)(p - payload) == len);
863
864 return (ngtcp2_ssize)len;
865 }
866
ngtcp2_pkt_decode_connection_close_frame(ngtcp2_connection_close * dest,const uint8_t * payload,size_t payloadlen)867 ngtcp2_ssize ngtcp2_pkt_decode_connection_close_frame(
868 ngtcp2_connection_close *dest, const uint8_t *payload, size_t payloadlen) {
869 size_t len = 1 + 1 + 1;
870 const uint8_t *p;
871 size_t reasonlen;
872 size_t nreasonlen;
873 size_t n;
874 uint8_t type;
875 uint64_t vi;
876
877 if (payloadlen < len) {
878 return NGTCP2_ERR_FRAME_ENCODING;
879 }
880
881 type = payload[0];
882
883 p = payload + 1;
884
885 n = ngtcp2_get_varint_len(p);
886 len += n - 1;
887 if (payloadlen < len) {
888 return NGTCP2_ERR_FRAME_ENCODING;
889 }
890
891 p += n;
892
893 if (type == NGTCP2_FRAME_CONNECTION_CLOSE) {
894 ++len;
895
896 n = ngtcp2_get_varint_len(p);
897 len += n - 1;
898 if (payloadlen < len) {
899 return NGTCP2_ERR_FRAME_ENCODING;
900 }
901
902 p += n;
903 }
904
905 nreasonlen = ngtcp2_get_varint_len(p);
906 len += nreasonlen - 1;
907 if (payloadlen < len) {
908 return NGTCP2_ERR_FRAME_ENCODING;
909 }
910
911 vi = ngtcp2_get_varint(&nreasonlen, p);
912 if (payloadlen - len < vi) {
913 return NGTCP2_ERR_FRAME_ENCODING;
914 }
915 reasonlen = (size_t)vi;
916 len += reasonlen;
917
918 p = payload + 1;
919
920 dest->type = type;
921 dest->error_code = ngtcp2_get_varint(&n, p);
922 p += n;
923 if (type == NGTCP2_FRAME_CONNECTION_CLOSE) {
924 dest->frame_type = ngtcp2_get_varint(&n, p);
925 p += n;
926 } else {
927 dest->frame_type = 0;
928 }
929 dest->reasonlen = reasonlen;
930 p += nreasonlen;
931 if (reasonlen == 0) {
932 dest->reason = NULL;
933 } else {
934 dest->reason = (uint8_t *)p;
935 p += reasonlen;
936 }
937
938 assert((size_t)(p - payload) == len);
939
940 return (ngtcp2_ssize)len;
941 }
942
ngtcp2_pkt_decode_max_data_frame(ngtcp2_max_data * dest,const uint8_t * payload,size_t payloadlen)943 ngtcp2_ssize ngtcp2_pkt_decode_max_data_frame(ngtcp2_max_data *dest,
944 const uint8_t *payload,
945 size_t payloadlen) {
946 size_t len = 1 + 1;
947 const uint8_t *p;
948 size_t n;
949
950 if (payloadlen < len) {
951 return NGTCP2_ERR_FRAME_ENCODING;
952 }
953
954 p = payload + 1;
955
956 n = ngtcp2_get_varint_len(p);
957 len += n - 1;
958
959 if (payloadlen < len) {
960 return NGTCP2_ERR_FRAME_ENCODING;
961 }
962
963 dest->type = NGTCP2_FRAME_MAX_DATA;
964 dest->max_data = ngtcp2_get_varint(&n, p);
965 p += n;
966
967 assert((size_t)(p - payload) == len);
968
969 return (ngtcp2_ssize)len;
970 }
971
ngtcp2_pkt_decode_max_stream_data_frame(ngtcp2_max_stream_data * dest,const uint8_t * payload,size_t payloadlen)972 ngtcp2_ssize ngtcp2_pkt_decode_max_stream_data_frame(
973 ngtcp2_max_stream_data *dest, const uint8_t *payload, size_t payloadlen) {
974 size_t len = 1 + 1 + 1;
975 const uint8_t *p;
976 size_t n;
977
978 if (payloadlen < len) {
979 return NGTCP2_ERR_FRAME_ENCODING;
980 }
981
982 p = payload + 1;
983
984 n = ngtcp2_get_varint_len(p);
985 len += n - 1;
986
987 if (payloadlen < len) {
988 return NGTCP2_ERR_FRAME_ENCODING;
989 }
990
991 p += n;
992
993 n = ngtcp2_get_varint_len(p);
994 len += n - 1;
995
996 if (payloadlen < len) {
997 return NGTCP2_ERR_FRAME_ENCODING;
998 }
999
1000 p = payload + 1;
1001
1002 dest->type = NGTCP2_FRAME_MAX_STREAM_DATA;
1003 dest->stream_id = (int64_t)ngtcp2_get_varint(&n, p);
1004 p += n;
1005 dest->max_stream_data = ngtcp2_get_varint(&n, p);
1006 p += n;
1007
1008 assert((size_t)(p - payload) == len);
1009
1010 return (ngtcp2_ssize)len;
1011 }
1012
ngtcp2_pkt_decode_max_streams_frame(ngtcp2_max_streams * dest,const uint8_t * payload,size_t payloadlen)1013 ngtcp2_ssize ngtcp2_pkt_decode_max_streams_frame(ngtcp2_max_streams *dest,
1014 const uint8_t *payload,
1015 size_t payloadlen) {
1016 size_t len = 1 + 1;
1017 const uint8_t *p;
1018 size_t n;
1019
1020 if (payloadlen < len) {
1021 return NGTCP2_ERR_FRAME_ENCODING;
1022 }
1023
1024 p = payload + 1;
1025
1026 n = ngtcp2_get_varint_len(p);
1027 len += n - 1;
1028
1029 if (payloadlen < len) {
1030 return NGTCP2_ERR_FRAME_ENCODING;
1031 }
1032
1033 dest->type = payload[0];
1034 dest->max_streams = ngtcp2_get_varint(&n, p);
1035 p += n;
1036
1037 assert((size_t)(p - payload) == len);
1038
1039 return (ngtcp2_ssize)len;
1040 }
1041
ngtcp2_pkt_decode_ping_frame(ngtcp2_ping * dest,const uint8_t * payload,size_t payloadlen)1042 ngtcp2_ssize ngtcp2_pkt_decode_ping_frame(ngtcp2_ping *dest,
1043 const uint8_t *payload,
1044 size_t payloadlen) {
1045 (void)payload;
1046 (void)payloadlen;
1047
1048 dest->type = NGTCP2_FRAME_PING;
1049 return 1;
1050 }
1051
ngtcp2_pkt_decode_data_blocked_frame(ngtcp2_data_blocked * dest,const uint8_t * payload,size_t payloadlen)1052 ngtcp2_ssize ngtcp2_pkt_decode_data_blocked_frame(ngtcp2_data_blocked *dest,
1053 const uint8_t *payload,
1054 size_t payloadlen) {
1055 size_t len = 1 + 1;
1056 const uint8_t *p;
1057 size_t n;
1058
1059 if (payloadlen < len) {
1060 return NGTCP2_ERR_FRAME_ENCODING;
1061 }
1062
1063 p = payload + 1;
1064
1065 n = ngtcp2_get_varint_len(p);
1066 len += n - 1;
1067
1068 if (payloadlen < len) {
1069 return NGTCP2_ERR_FRAME_ENCODING;
1070 }
1071
1072 dest->type = NGTCP2_FRAME_DATA_BLOCKED;
1073 dest->offset = ngtcp2_get_varint(&n, p);
1074 p += n;
1075
1076 assert((size_t)(p - payload) == len);
1077
1078 return (ngtcp2_ssize)len;
1079 }
1080
1081 ngtcp2_ssize
ngtcp2_pkt_decode_stream_data_blocked_frame(ngtcp2_stream_data_blocked * dest,const uint8_t * payload,size_t payloadlen)1082 ngtcp2_pkt_decode_stream_data_blocked_frame(ngtcp2_stream_data_blocked *dest,
1083 const uint8_t *payload,
1084 size_t payloadlen) {
1085 size_t len = 1 + 1 + 1;
1086 const uint8_t *p;
1087 size_t n;
1088
1089 if (payloadlen < len) {
1090 return NGTCP2_ERR_FRAME_ENCODING;
1091 }
1092
1093 p = payload + 1;
1094
1095 n = ngtcp2_get_varint_len(p);
1096 len += n - 1;
1097
1098 if (payloadlen < len) {
1099 return NGTCP2_ERR_FRAME_ENCODING;
1100 }
1101
1102 p += n;
1103
1104 n = ngtcp2_get_varint_len(p);
1105 len += n - 1;
1106
1107 if (payloadlen < len) {
1108 return NGTCP2_ERR_FRAME_ENCODING;
1109 }
1110
1111 p = payload + 1;
1112
1113 dest->type = NGTCP2_FRAME_STREAM_DATA_BLOCKED;
1114 dest->stream_id = (int64_t)ngtcp2_get_varint(&n, p);
1115 p += n;
1116 dest->offset = ngtcp2_get_varint(&n, p);
1117 p += n;
1118
1119 assert((size_t)(p - payload) == len);
1120
1121 return (ngtcp2_ssize)len;
1122 }
1123
ngtcp2_pkt_decode_streams_blocked_frame(ngtcp2_streams_blocked * dest,const uint8_t * payload,size_t payloadlen)1124 ngtcp2_ssize ngtcp2_pkt_decode_streams_blocked_frame(
1125 ngtcp2_streams_blocked *dest, const uint8_t *payload, size_t payloadlen) {
1126 size_t len = 1 + 1;
1127 const uint8_t *p;
1128 size_t n;
1129
1130 if (payloadlen < len) {
1131 return NGTCP2_ERR_FRAME_ENCODING;
1132 }
1133
1134 p = payload + 1;
1135
1136 n = ngtcp2_get_varint_len(p);
1137 len += n - 1;
1138
1139 if (payloadlen < len) {
1140 return NGTCP2_ERR_FRAME_ENCODING;
1141 }
1142
1143 dest->type = payload[0];
1144 dest->max_streams = ngtcp2_get_varint(&n, p);
1145 p += n;
1146
1147 assert((size_t)(p - payload) == len);
1148
1149 return (ngtcp2_ssize)len;
1150 }
1151
ngtcp2_pkt_decode_new_connection_id_frame(ngtcp2_new_connection_id * dest,const uint8_t * payload,size_t payloadlen)1152 ngtcp2_ssize ngtcp2_pkt_decode_new_connection_id_frame(
1153 ngtcp2_new_connection_id *dest, const uint8_t *payload, size_t payloadlen) {
1154 size_t len = 1 + 1 + 1 + 1 + 16;
1155 const uint8_t *p;
1156 size_t n;
1157 size_t cil;
1158
1159 if (payloadlen < len) {
1160 return NGTCP2_ERR_FRAME_ENCODING;
1161 }
1162
1163 p = payload + 1;
1164
1165 n = ngtcp2_get_varint_len(p);
1166 len += n - 1;
1167 if (payloadlen < len) {
1168 return NGTCP2_ERR_FRAME_ENCODING;
1169 }
1170
1171 p += n;
1172
1173 n = ngtcp2_get_varint_len(p);
1174 len += n - 1;
1175 if (payloadlen < len) {
1176 return NGTCP2_ERR_FRAME_ENCODING;
1177 }
1178
1179 p += n;
1180
1181 cil = *p;
1182 if (cil < NGTCP2_MIN_CIDLEN || cil > NGTCP2_MAX_CIDLEN) {
1183 return NGTCP2_ERR_FRAME_ENCODING;
1184 }
1185
1186 len += cil;
1187 if (payloadlen < len) {
1188 return NGTCP2_ERR_FRAME_ENCODING;
1189 }
1190
1191 p = payload + 1;
1192
1193 dest->type = NGTCP2_FRAME_NEW_CONNECTION_ID;
1194 dest->seq = ngtcp2_get_varint(&n, p);
1195 p += n;
1196 dest->retire_prior_to = ngtcp2_get_varint(&n, p);
1197 p += n + 1;
1198 ngtcp2_cid_init(&dest->cid, p, cil);
1199 p += cil;
1200 memcpy(dest->stateless_reset_token, p, NGTCP2_STATELESS_RESET_TOKENLEN);
1201 p += NGTCP2_STATELESS_RESET_TOKENLEN;
1202
1203 assert((size_t)(p - payload) == len);
1204
1205 return (ngtcp2_ssize)len;
1206 }
1207
ngtcp2_pkt_decode_stop_sending_frame(ngtcp2_stop_sending * dest,const uint8_t * payload,size_t payloadlen)1208 ngtcp2_ssize ngtcp2_pkt_decode_stop_sending_frame(ngtcp2_stop_sending *dest,
1209 const uint8_t *payload,
1210 size_t payloadlen) {
1211 size_t len = 1 + 1 + 1;
1212 const uint8_t *p;
1213 size_t n;
1214
1215 if (payloadlen < len) {
1216 return NGTCP2_ERR_FRAME_ENCODING;
1217 }
1218
1219 p = payload + 1;
1220
1221 n = ngtcp2_get_varint_len(p);
1222 len += n - 1;
1223
1224 if (payloadlen < len) {
1225 return NGTCP2_ERR_FRAME_ENCODING;
1226 }
1227 p += n;
1228 n = ngtcp2_get_varint_len(p);
1229 len += n - 1;
1230
1231 if (payloadlen < len) {
1232 return NGTCP2_ERR_FRAME_ENCODING;
1233 }
1234
1235 p = payload + 1;
1236
1237 dest->type = NGTCP2_FRAME_STOP_SENDING;
1238 dest->stream_id = (int64_t)ngtcp2_get_varint(&n, p);
1239 p += n;
1240 dest->app_error_code = ngtcp2_get_varint(&n, p);
1241 p += n;
1242
1243 assert((size_t)(p - payload) == len);
1244
1245 return (ngtcp2_ssize)len;
1246 }
1247
ngtcp2_pkt_decode_path_challenge_frame(ngtcp2_path_challenge * dest,const uint8_t * payload,size_t payloadlen)1248 ngtcp2_ssize ngtcp2_pkt_decode_path_challenge_frame(ngtcp2_path_challenge *dest,
1249 const uint8_t *payload,
1250 size_t payloadlen) {
1251 size_t len = 1 + 8;
1252 const uint8_t *p;
1253
1254 if (payloadlen < len) {
1255 return NGTCP2_ERR_FRAME_ENCODING;
1256 }
1257
1258 p = payload + 1;
1259
1260 dest->type = NGTCP2_FRAME_PATH_CHALLENGE;
1261 ngtcp2_cpymem(dest->data, p, sizeof(dest->data));
1262 p += sizeof(dest->data);
1263
1264 assert((size_t)(p - payload) == len);
1265
1266 return (ngtcp2_ssize)len;
1267 }
1268
ngtcp2_pkt_decode_path_response_frame(ngtcp2_path_response * dest,const uint8_t * payload,size_t payloadlen)1269 ngtcp2_ssize ngtcp2_pkt_decode_path_response_frame(ngtcp2_path_response *dest,
1270 const uint8_t *payload,
1271 size_t payloadlen) {
1272 size_t len = 1 + 8;
1273 const uint8_t *p;
1274
1275 if (payloadlen < len) {
1276 return NGTCP2_ERR_FRAME_ENCODING;
1277 }
1278
1279 p = payload + 1;
1280
1281 dest->type = NGTCP2_FRAME_PATH_RESPONSE;
1282 ngtcp2_cpymem(dest->data, p, sizeof(dest->data));
1283 p += sizeof(dest->data);
1284
1285 assert((size_t)(p - payload) == len);
1286
1287 return (ngtcp2_ssize)len;
1288 }
1289
ngtcp2_pkt_decode_crypto_frame(ngtcp2_crypto * dest,const uint8_t * payload,size_t payloadlen)1290 ngtcp2_ssize ngtcp2_pkt_decode_crypto_frame(ngtcp2_crypto *dest,
1291 const uint8_t *payload,
1292 size_t payloadlen) {
1293 size_t len = 1 + 1 + 1;
1294 const uint8_t *p;
1295 size_t datalen;
1296 size_t ndatalen;
1297 size_t n;
1298 uint64_t vi;
1299
1300 if (payloadlen < len) {
1301 return NGTCP2_ERR_FRAME_ENCODING;
1302 }
1303
1304 p = payload + 1;
1305
1306 n = ngtcp2_get_varint_len(p);
1307 len += n - 1;
1308
1309 if (payloadlen < len) {
1310 return NGTCP2_ERR_FRAME_ENCODING;
1311 }
1312
1313 p += n;
1314
1315 ndatalen = ngtcp2_get_varint_len(p);
1316 len += ndatalen - 1;
1317
1318 if (payloadlen < len) {
1319 return NGTCP2_ERR_FRAME_ENCODING;
1320 }
1321
1322 vi = ngtcp2_get_varint(&ndatalen, p);
1323 if (payloadlen - len < vi) {
1324 return NGTCP2_ERR_FRAME_ENCODING;
1325 }
1326
1327 datalen = (size_t)vi;
1328 len += datalen;
1329
1330 p = payload + 1;
1331
1332 dest->type = NGTCP2_FRAME_CRYPTO;
1333 dest->offset = ngtcp2_get_varint(&n, p);
1334 p += n;
1335 dest->data[0].len = datalen;
1336 p += ndatalen;
1337 if (dest->data[0].len) {
1338 dest->data[0].base = (uint8_t *)p;
1339 p += dest->data[0].len;
1340 dest->datacnt = 1;
1341 } else {
1342 dest->data[0].base = NULL;
1343 dest->datacnt = 0;
1344 }
1345
1346 assert((size_t)(p - payload) == len);
1347
1348 return (ngtcp2_ssize)len;
1349 }
1350
ngtcp2_pkt_decode_new_token_frame(ngtcp2_new_token * dest,const uint8_t * payload,size_t payloadlen)1351 ngtcp2_ssize ngtcp2_pkt_decode_new_token_frame(ngtcp2_new_token *dest,
1352 const uint8_t *payload,
1353 size_t payloadlen) {
1354 size_t len = 1 + 1;
1355 const uint8_t *p;
1356 size_t n;
1357 size_t datalen;
1358 uint64_t vi;
1359
1360 if (payloadlen < len) {
1361 return NGTCP2_ERR_FRAME_ENCODING;
1362 }
1363
1364 p = payload + 1;
1365
1366 n = ngtcp2_get_varint_len(p);
1367 len += n - 1;
1368
1369 if (payloadlen < len) {
1370 return NGTCP2_ERR_FRAME_ENCODING;
1371 }
1372
1373 vi = ngtcp2_get_varint(&n, p);
1374 if (payloadlen - len < vi) {
1375 return NGTCP2_ERR_FRAME_ENCODING;
1376 }
1377 datalen = (size_t)vi;
1378 len += datalen;
1379
1380 dest->type = NGTCP2_FRAME_NEW_TOKEN;
1381 dest->token.len = datalen;
1382 p += n;
1383 dest->token.base = (uint8_t *)p;
1384 p += dest->token.len;
1385
1386 assert((size_t)(p - payload) == len);
1387
1388 return (ngtcp2_ssize)len;
1389 }
1390
1391 ngtcp2_ssize
ngtcp2_pkt_decode_retire_connection_id_frame(ngtcp2_retire_connection_id * dest,const uint8_t * payload,size_t payloadlen)1392 ngtcp2_pkt_decode_retire_connection_id_frame(ngtcp2_retire_connection_id *dest,
1393 const uint8_t *payload,
1394 size_t payloadlen) {
1395 size_t len = 1 + 1;
1396 const uint8_t *p;
1397 size_t n;
1398
1399 if (payloadlen < len) {
1400 return NGTCP2_ERR_FRAME_ENCODING;
1401 }
1402
1403 p = payload + 1;
1404
1405 n = ngtcp2_get_varint_len(p);
1406 len += n - 1;
1407
1408 if (payloadlen < len) {
1409 return NGTCP2_ERR_FRAME_ENCODING;
1410 }
1411
1412 dest->type = NGTCP2_FRAME_RETIRE_CONNECTION_ID;
1413 dest->seq = ngtcp2_get_varint(&n, p);
1414 p += n;
1415
1416 assert((size_t)(p - payload) == len);
1417
1418 return (ngtcp2_ssize)len;
1419 }
1420
ngtcp2_pkt_decode_handshake_done_frame(ngtcp2_handshake_done * dest,const uint8_t * payload,size_t payloadlen)1421 ngtcp2_ssize ngtcp2_pkt_decode_handshake_done_frame(ngtcp2_handshake_done *dest,
1422 const uint8_t *payload,
1423 size_t payloadlen) {
1424 (void)payload;
1425 (void)payloadlen;
1426
1427 dest->type = NGTCP2_FRAME_HANDSHAKE_DONE;
1428 return 1;
1429 }
1430
ngtcp2_pkt_decode_datagram_frame(ngtcp2_datagram * dest,const uint8_t * payload,size_t payloadlen)1431 ngtcp2_ssize ngtcp2_pkt_decode_datagram_frame(ngtcp2_datagram *dest,
1432 const uint8_t *payload,
1433 size_t payloadlen) {
1434 size_t len = 1;
1435 const uint8_t *p;
1436 uint8_t type;
1437 size_t datalen;
1438 size_t n;
1439 uint64_t vi;
1440
1441 if (payloadlen < len) {
1442 return NGTCP2_ERR_FRAME_ENCODING;
1443 }
1444
1445 type = payload[0];
1446
1447 p = payload + 1;
1448
1449 switch (type) {
1450 case NGTCP2_FRAME_DATAGRAM:
1451 datalen = payloadlen - 1;
1452 len = payloadlen;
1453 break;
1454 case NGTCP2_FRAME_DATAGRAM_LEN:
1455 ++len;
1456 if (payloadlen < len) {
1457 return NGTCP2_ERR_FRAME_ENCODING;
1458 }
1459
1460 n = ngtcp2_get_varint_len(p);
1461 len += n - 1;
1462
1463 if (payloadlen < len) {
1464 return NGTCP2_ERR_FRAME_ENCODING;
1465 }
1466
1467 vi = ngtcp2_get_varint(&n, p);
1468 if (payloadlen - len < vi) {
1469 return NGTCP2_ERR_FRAME_ENCODING;
1470 }
1471
1472 datalen = (size_t)vi;
1473 len += datalen;
1474 break;
1475 default:
1476 assert(0);
1477 abort();
1478 }
1479
1480 dest->type = type;
1481
1482 if (datalen == 0) {
1483 dest->datacnt = 0;
1484 dest->data = NULL;
1485
1486 if (type == NGTCP2_FRAME_DATAGRAM_LEN) {
1487 p += n;
1488 }
1489 } else {
1490 dest->datacnt = 1;
1491 dest->data = dest->rdata;
1492 dest->rdata[0].len = datalen;
1493
1494 if (type == NGTCP2_FRAME_DATAGRAM_LEN) {
1495 p += n;
1496 }
1497
1498 dest->rdata[0].base = (uint8_t *)p;
1499 p += datalen;
1500 }
1501
1502 assert((size_t)(p - payload) == len);
1503
1504 return (ngtcp2_ssize)len;
1505 }
1506
ngtcp2_pkt_encode_frame(uint8_t * out,size_t outlen,ngtcp2_frame * fr)1507 ngtcp2_ssize ngtcp2_pkt_encode_frame(uint8_t *out, size_t outlen,
1508 ngtcp2_frame *fr) {
1509 switch (fr->type) {
1510 case NGTCP2_FRAME_STREAM:
1511 return ngtcp2_pkt_encode_stream_frame(out, outlen, &fr->stream);
1512 case NGTCP2_FRAME_ACK:
1513 case NGTCP2_FRAME_ACK_ECN:
1514 return ngtcp2_pkt_encode_ack_frame(out, outlen, &fr->ack);
1515 case NGTCP2_FRAME_PADDING:
1516 return ngtcp2_pkt_encode_padding_frame(out, outlen, &fr->padding);
1517 case NGTCP2_FRAME_RESET_STREAM:
1518 return ngtcp2_pkt_encode_reset_stream_frame(out, outlen, &fr->reset_stream);
1519 case NGTCP2_FRAME_CONNECTION_CLOSE:
1520 case NGTCP2_FRAME_CONNECTION_CLOSE_APP:
1521 return ngtcp2_pkt_encode_connection_close_frame(out, outlen,
1522 &fr->connection_close);
1523 case NGTCP2_FRAME_MAX_DATA:
1524 return ngtcp2_pkt_encode_max_data_frame(out, outlen, &fr->max_data);
1525 case NGTCP2_FRAME_MAX_STREAM_DATA:
1526 return ngtcp2_pkt_encode_max_stream_data_frame(out, outlen,
1527 &fr->max_stream_data);
1528 case NGTCP2_FRAME_MAX_STREAMS_BIDI:
1529 case NGTCP2_FRAME_MAX_STREAMS_UNI:
1530 return ngtcp2_pkt_encode_max_streams_frame(out, outlen, &fr->max_streams);
1531 case NGTCP2_FRAME_PING:
1532 return ngtcp2_pkt_encode_ping_frame(out, outlen, &fr->ping);
1533 case NGTCP2_FRAME_DATA_BLOCKED:
1534 return ngtcp2_pkt_encode_data_blocked_frame(out, outlen, &fr->data_blocked);
1535 case NGTCP2_FRAME_STREAM_DATA_BLOCKED:
1536 return ngtcp2_pkt_encode_stream_data_blocked_frame(
1537 out, outlen, &fr->stream_data_blocked);
1538 case NGTCP2_FRAME_STREAMS_BLOCKED_BIDI:
1539 case NGTCP2_FRAME_STREAMS_BLOCKED_UNI:
1540 return ngtcp2_pkt_encode_streams_blocked_frame(out, outlen,
1541 &fr->streams_blocked);
1542 case NGTCP2_FRAME_NEW_CONNECTION_ID:
1543 return ngtcp2_pkt_encode_new_connection_id_frame(out, outlen,
1544 &fr->new_connection_id);
1545 case NGTCP2_FRAME_STOP_SENDING:
1546 return ngtcp2_pkt_encode_stop_sending_frame(out, outlen, &fr->stop_sending);
1547 case NGTCP2_FRAME_PATH_CHALLENGE:
1548 return ngtcp2_pkt_encode_path_challenge_frame(out, outlen,
1549 &fr->path_challenge);
1550 case NGTCP2_FRAME_PATH_RESPONSE:
1551 return ngtcp2_pkt_encode_path_response_frame(out, outlen,
1552 &fr->path_response);
1553 case NGTCP2_FRAME_CRYPTO:
1554 return ngtcp2_pkt_encode_crypto_frame(out, outlen, &fr->crypto);
1555 case NGTCP2_FRAME_NEW_TOKEN:
1556 return ngtcp2_pkt_encode_new_token_frame(out, outlen, &fr->new_token);
1557 case NGTCP2_FRAME_RETIRE_CONNECTION_ID:
1558 return ngtcp2_pkt_encode_retire_connection_id_frame(
1559 out, outlen, &fr->retire_connection_id);
1560 case NGTCP2_FRAME_HANDSHAKE_DONE:
1561 return ngtcp2_pkt_encode_handshake_done_frame(out, outlen,
1562 &fr->handshake_done);
1563 case NGTCP2_FRAME_DATAGRAM:
1564 case NGTCP2_FRAME_DATAGRAM_LEN:
1565 return ngtcp2_pkt_encode_datagram_frame(out, outlen, &fr->datagram);
1566 default:
1567 return NGTCP2_ERR_INVALID_ARGUMENT;
1568 }
1569 }
1570
ngtcp2_pkt_encode_stream_frame(uint8_t * out,size_t outlen,ngtcp2_stream * fr)1571 ngtcp2_ssize ngtcp2_pkt_encode_stream_frame(uint8_t *out, size_t outlen,
1572 ngtcp2_stream *fr) {
1573 size_t len = 1;
1574 uint8_t flags = NGTCP2_STREAM_LEN_BIT;
1575 uint8_t *p;
1576 size_t i;
1577 size_t datalen = 0;
1578
1579 if (fr->fin) {
1580 flags |= NGTCP2_STREAM_FIN_BIT;
1581 }
1582
1583 if (fr->offset) {
1584 flags |= NGTCP2_STREAM_OFF_BIT;
1585 len += ngtcp2_put_varint_len(fr->offset);
1586 }
1587
1588 len += ngtcp2_put_varint_len((uint64_t)fr->stream_id);
1589
1590 for (i = 0; i < fr->datacnt; ++i) {
1591 datalen += fr->data[i].len;
1592 }
1593
1594 len += ngtcp2_put_varint_len(datalen);
1595 len += datalen;
1596
1597 if (outlen < len) {
1598 return NGTCP2_ERR_NOBUF;
1599 }
1600
1601 p = out;
1602
1603 *p++ = flags | NGTCP2_FRAME_STREAM;
1604
1605 fr->flags = flags;
1606
1607 p = ngtcp2_put_varint(p, (uint64_t)fr->stream_id);
1608
1609 if (fr->offset) {
1610 p = ngtcp2_put_varint(p, fr->offset);
1611 }
1612
1613 p = ngtcp2_put_varint(p, datalen);
1614
1615 for (i = 0; i < fr->datacnt; ++i) {
1616 assert(fr->data[i].len);
1617 assert(fr->data[i].base);
1618 p = ngtcp2_cpymem(p, fr->data[i].base, fr->data[i].len);
1619 }
1620
1621 assert((size_t)(p - out) == len);
1622
1623 return (ngtcp2_ssize)len;
1624 }
1625
ngtcp2_pkt_encode_ack_frame(uint8_t * out,size_t outlen,ngtcp2_ack * fr)1626 ngtcp2_ssize ngtcp2_pkt_encode_ack_frame(uint8_t *out, size_t outlen,
1627 ngtcp2_ack *fr) {
1628 size_t len = 1 + ngtcp2_put_varint_len((uint64_t)fr->largest_ack) +
1629 ngtcp2_put_varint_len(fr->ack_delay) +
1630 ngtcp2_put_varint_len(fr->num_blks) +
1631 ngtcp2_put_varint_len(fr->first_ack_blklen);
1632 uint8_t *p;
1633 size_t i;
1634 const ngtcp2_ack_blk *blk;
1635
1636 for (i = 0; i < fr->num_blks; ++i) {
1637 blk = &fr->blks[i];
1638 len += ngtcp2_put_varint_len(blk->gap);
1639 len += ngtcp2_put_varint_len(blk->blklen);
1640 }
1641
1642 if (fr->type == NGTCP2_FRAME_ACK_ECN) {
1643 len += ngtcp2_put_varint_len(fr->ecn.ect0) +
1644 ngtcp2_put_varint_len(fr->ecn.ect1) +
1645 ngtcp2_put_varint_len(fr->ecn.ce);
1646 }
1647
1648 if (outlen < len) {
1649 return NGTCP2_ERR_NOBUF;
1650 }
1651
1652 p = out;
1653
1654 *p++ = fr->type;
1655 p = ngtcp2_put_varint(p, (uint64_t)fr->largest_ack);
1656 p = ngtcp2_put_varint(p, fr->ack_delay);
1657 p = ngtcp2_put_varint(p, fr->num_blks);
1658 p = ngtcp2_put_varint(p, fr->first_ack_blklen);
1659
1660 for (i = 0; i < fr->num_blks; ++i) {
1661 blk = &fr->blks[i];
1662 p = ngtcp2_put_varint(p, blk->gap);
1663 p = ngtcp2_put_varint(p, blk->blklen);
1664 }
1665
1666 if (fr->type == NGTCP2_FRAME_ACK_ECN) {
1667 p = ngtcp2_put_varint(p, fr->ecn.ect0);
1668 p = ngtcp2_put_varint(p, fr->ecn.ect1);
1669 p = ngtcp2_put_varint(p, fr->ecn.ce);
1670 }
1671
1672 assert((size_t)(p - out) == len);
1673
1674 return (ngtcp2_ssize)len;
1675 }
1676
ngtcp2_pkt_encode_padding_frame(uint8_t * out,size_t outlen,const ngtcp2_padding * fr)1677 ngtcp2_ssize ngtcp2_pkt_encode_padding_frame(uint8_t *out, size_t outlen,
1678 const ngtcp2_padding *fr) {
1679 if (outlen < fr->len) {
1680 return NGTCP2_ERR_NOBUF;
1681 }
1682
1683 memset(out, 0, fr->len);
1684
1685 return (ngtcp2_ssize)fr->len;
1686 }
1687
1688 ngtcp2_ssize
ngtcp2_pkt_encode_reset_stream_frame(uint8_t * out,size_t outlen,const ngtcp2_reset_stream * fr)1689 ngtcp2_pkt_encode_reset_stream_frame(uint8_t *out, size_t outlen,
1690 const ngtcp2_reset_stream *fr) {
1691 size_t len = 1 + ngtcp2_put_varint_len((uint64_t)fr->stream_id) +
1692 ngtcp2_put_varint_len(fr->app_error_code) +
1693 ngtcp2_put_varint_len(fr->final_size);
1694 uint8_t *p;
1695
1696 if (outlen < len) {
1697 return NGTCP2_ERR_NOBUF;
1698 }
1699
1700 p = out;
1701
1702 *p++ = NGTCP2_FRAME_RESET_STREAM;
1703 p = ngtcp2_put_varint(p, (uint64_t)fr->stream_id);
1704 p = ngtcp2_put_varint(p, fr->app_error_code);
1705 p = ngtcp2_put_varint(p, fr->final_size);
1706
1707 assert((size_t)(p - out) == len);
1708
1709 return (ngtcp2_ssize)len;
1710 }
1711
1712 ngtcp2_ssize
ngtcp2_pkt_encode_connection_close_frame(uint8_t * out,size_t outlen,const ngtcp2_connection_close * fr)1713 ngtcp2_pkt_encode_connection_close_frame(uint8_t *out, size_t outlen,
1714 const ngtcp2_connection_close *fr) {
1715 size_t len = 1 + ngtcp2_put_varint_len(fr->error_code) +
1716 (fr->type == NGTCP2_FRAME_CONNECTION_CLOSE
1717 ? ngtcp2_put_varint_len(fr->frame_type)
1718 : 0) +
1719 ngtcp2_put_varint_len(fr->reasonlen) + fr->reasonlen;
1720 uint8_t *p;
1721
1722 if (outlen < len) {
1723 return NGTCP2_ERR_NOBUF;
1724 }
1725
1726 p = out;
1727
1728 *p++ = fr->type;
1729 p = ngtcp2_put_varint(p, fr->error_code);
1730 if (fr->type == NGTCP2_FRAME_CONNECTION_CLOSE) {
1731 p = ngtcp2_put_varint(p, fr->frame_type);
1732 }
1733 p = ngtcp2_put_varint(p, fr->reasonlen);
1734 if (fr->reasonlen) {
1735 p = ngtcp2_cpymem(p, fr->reason, fr->reasonlen);
1736 }
1737
1738 assert((size_t)(p - out) == len);
1739
1740 return (ngtcp2_ssize)len;
1741 }
1742
ngtcp2_pkt_encode_max_data_frame(uint8_t * out,size_t outlen,const ngtcp2_max_data * fr)1743 ngtcp2_ssize ngtcp2_pkt_encode_max_data_frame(uint8_t *out, size_t outlen,
1744 const ngtcp2_max_data *fr) {
1745 size_t len = 1 + ngtcp2_put_varint_len(fr->max_data);
1746 uint8_t *p;
1747
1748 if (outlen < len) {
1749 return NGTCP2_ERR_NOBUF;
1750 }
1751
1752 p = out;
1753
1754 *p++ = NGTCP2_FRAME_MAX_DATA;
1755 p = ngtcp2_put_varint(p, fr->max_data);
1756
1757 assert((size_t)(p - out) == len);
1758
1759 return (ngtcp2_ssize)len;
1760 }
1761
1762 ngtcp2_ssize
ngtcp2_pkt_encode_max_stream_data_frame(uint8_t * out,size_t outlen,const ngtcp2_max_stream_data * fr)1763 ngtcp2_pkt_encode_max_stream_data_frame(uint8_t *out, size_t outlen,
1764 const ngtcp2_max_stream_data *fr) {
1765 size_t len = 1 + ngtcp2_put_varint_len((uint64_t)fr->stream_id) +
1766 ngtcp2_put_varint_len(fr->max_stream_data);
1767 uint8_t *p;
1768
1769 if (outlen < len) {
1770 return NGTCP2_ERR_NOBUF;
1771 }
1772
1773 p = out;
1774
1775 *p++ = NGTCP2_FRAME_MAX_STREAM_DATA;
1776 p = ngtcp2_put_varint(p, (uint64_t)fr->stream_id);
1777 p = ngtcp2_put_varint(p, fr->max_stream_data);
1778
1779 assert((size_t)(p - out) == len);
1780
1781 return (ngtcp2_ssize)len;
1782 }
1783
ngtcp2_pkt_encode_max_streams_frame(uint8_t * out,size_t outlen,const ngtcp2_max_streams * fr)1784 ngtcp2_ssize ngtcp2_pkt_encode_max_streams_frame(uint8_t *out, size_t outlen,
1785 const ngtcp2_max_streams *fr) {
1786 size_t len = 1 + ngtcp2_put_varint_len(fr->max_streams);
1787 uint8_t *p;
1788
1789 if (outlen < len) {
1790 return NGTCP2_ERR_NOBUF;
1791 }
1792
1793 p = out;
1794
1795 *p++ = fr->type;
1796 p = ngtcp2_put_varint(p, fr->max_streams);
1797
1798 assert((size_t)(p - out) == len);
1799
1800 return (ngtcp2_ssize)len;
1801 }
1802
ngtcp2_pkt_encode_ping_frame(uint8_t * out,size_t outlen,const ngtcp2_ping * fr)1803 ngtcp2_ssize ngtcp2_pkt_encode_ping_frame(uint8_t *out, size_t outlen,
1804 const ngtcp2_ping *fr) {
1805 (void)fr;
1806
1807 if (outlen < 1) {
1808 return NGTCP2_ERR_NOBUF;
1809 }
1810
1811 *out++ = NGTCP2_FRAME_PING;
1812
1813 return 1;
1814 }
1815
1816 ngtcp2_ssize
ngtcp2_pkt_encode_data_blocked_frame(uint8_t * out,size_t outlen,const ngtcp2_data_blocked * fr)1817 ngtcp2_pkt_encode_data_blocked_frame(uint8_t *out, size_t outlen,
1818 const ngtcp2_data_blocked *fr) {
1819 size_t len = 1 + ngtcp2_put_varint_len(fr->offset);
1820 uint8_t *p;
1821
1822 if (outlen < len) {
1823 return NGTCP2_ERR_NOBUF;
1824 }
1825
1826 p = out;
1827
1828 *p++ = NGTCP2_FRAME_DATA_BLOCKED;
1829 p = ngtcp2_put_varint(p, fr->offset);
1830
1831 assert((size_t)(p - out) == len);
1832
1833 return (ngtcp2_ssize)len;
1834 }
1835
ngtcp2_pkt_encode_stream_data_blocked_frame(uint8_t * out,size_t outlen,const ngtcp2_stream_data_blocked * fr)1836 ngtcp2_ssize ngtcp2_pkt_encode_stream_data_blocked_frame(
1837 uint8_t *out, size_t outlen, const ngtcp2_stream_data_blocked *fr) {
1838 size_t len = 1 + ngtcp2_put_varint_len((uint64_t)fr->stream_id) +
1839 ngtcp2_put_varint_len(fr->offset);
1840 uint8_t *p;
1841
1842 if (outlen < len) {
1843 return NGTCP2_ERR_NOBUF;
1844 }
1845
1846 p = out;
1847
1848 *p++ = NGTCP2_FRAME_STREAM_DATA_BLOCKED;
1849 p = ngtcp2_put_varint(p, (uint64_t)fr->stream_id);
1850 p = ngtcp2_put_varint(p, fr->offset);
1851
1852 assert((size_t)(p - out) == len);
1853
1854 return (ngtcp2_ssize)len;
1855 }
1856
1857 ngtcp2_ssize
ngtcp2_pkt_encode_streams_blocked_frame(uint8_t * out,size_t outlen,const ngtcp2_streams_blocked * fr)1858 ngtcp2_pkt_encode_streams_blocked_frame(uint8_t *out, size_t outlen,
1859 const ngtcp2_streams_blocked *fr) {
1860 size_t len = 1 + ngtcp2_put_varint_len(fr->max_streams);
1861 uint8_t *p;
1862
1863 if (outlen < len) {
1864 return NGTCP2_ERR_NOBUF;
1865 }
1866
1867 p = out;
1868
1869 *p++ = fr->type;
1870 p = ngtcp2_put_varint(p, fr->max_streams);
1871
1872 assert((size_t)(p - out) == len);
1873
1874 return (ngtcp2_ssize)len;
1875 }
1876
1877 ngtcp2_ssize
ngtcp2_pkt_encode_new_connection_id_frame(uint8_t * out,size_t outlen,const ngtcp2_new_connection_id * fr)1878 ngtcp2_pkt_encode_new_connection_id_frame(uint8_t *out, size_t outlen,
1879 const ngtcp2_new_connection_id *fr) {
1880 size_t len = 1 + ngtcp2_put_varint_len(fr->seq) +
1881 ngtcp2_put_varint_len(fr->retire_prior_to) + 1 +
1882 fr->cid.datalen + NGTCP2_STATELESS_RESET_TOKENLEN;
1883 uint8_t *p;
1884
1885 if (outlen < len) {
1886 return NGTCP2_ERR_NOBUF;
1887 }
1888
1889 p = out;
1890
1891 *p++ = NGTCP2_FRAME_NEW_CONNECTION_ID;
1892 p = ngtcp2_put_varint(p, fr->seq);
1893 p = ngtcp2_put_varint(p, fr->retire_prior_to);
1894 *p++ = (uint8_t)fr->cid.datalen;
1895 p = ngtcp2_cpymem(p, fr->cid.data, fr->cid.datalen);
1896 p = ngtcp2_cpymem(p, fr->stateless_reset_token,
1897 NGTCP2_STATELESS_RESET_TOKENLEN);
1898
1899 assert((size_t)(p - out) == len);
1900
1901 return (ngtcp2_ssize)len;
1902 }
1903
1904 ngtcp2_ssize
ngtcp2_pkt_encode_stop_sending_frame(uint8_t * out,size_t outlen,const ngtcp2_stop_sending * fr)1905 ngtcp2_pkt_encode_stop_sending_frame(uint8_t *out, size_t outlen,
1906 const ngtcp2_stop_sending *fr) {
1907 size_t len = 1 + ngtcp2_put_varint_len((uint64_t)fr->stream_id) +
1908 ngtcp2_put_varint_len(fr->app_error_code);
1909 uint8_t *p;
1910
1911 if (outlen < len) {
1912 return NGTCP2_ERR_NOBUF;
1913 }
1914
1915 p = out;
1916
1917 *p++ = NGTCP2_FRAME_STOP_SENDING;
1918 p = ngtcp2_put_varint(p, (uint64_t)fr->stream_id);
1919 p = ngtcp2_put_varint(p, fr->app_error_code);
1920
1921 assert((size_t)(p - out) == len);
1922
1923 return (ngtcp2_ssize)len;
1924 }
1925
1926 ngtcp2_ssize
ngtcp2_pkt_encode_path_challenge_frame(uint8_t * out,size_t outlen,const ngtcp2_path_challenge * fr)1927 ngtcp2_pkt_encode_path_challenge_frame(uint8_t *out, size_t outlen,
1928 const ngtcp2_path_challenge *fr) {
1929 size_t len = 1 + 8;
1930 uint8_t *p;
1931
1932 if (outlen < len) {
1933 return NGTCP2_ERR_NOBUF;
1934 }
1935
1936 p = out;
1937
1938 *p++ = NGTCP2_FRAME_PATH_CHALLENGE;
1939 p = ngtcp2_cpymem(p, fr->data, sizeof(fr->data));
1940
1941 assert((size_t)(p - out) == len);
1942
1943 return (ngtcp2_ssize)len;
1944 }
1945
1946 ngtcp2_ssize
ngtcp2_pkt_encode_path_response_frame(uint8_t * out,size_t outlen,const ngtcp2_path_response * fr)1947 ngtcp2_pkt_encode_path_response_frame(uint8_t *out, size_t outlen,
1948 const ngtcp2_path_response *fr) {
1949 size_t len = 1 + 8;
1950 uint8_t *p;
1951
1952 if (outlen < len) {
1953 return NGTCP2_ERR_NOBUF;
1954 }
1955
1956 p = out;
1957
1958 *p++ = NGTCP2_FRAME_PATH_RESPONSE;
1959 p = ngtcp2_cpymem(p, fr->data, sizeof(fr->data));
1960
1961 assert((size_t)(p - out) == len);
1962
1963 return (ngtcp2_ssize)len;
1964 }
1965
ngtcp2_pkt_encode_crypto_frame(uint8_t * out,size_t outlen,const ngtcp2_crypto * fr)1966 ngtcp2_ssize ngtcp2_pkt_encode_crypto_frame(uint8_t *out, size_t outlen,
1967 const ngtcp2_crypto *fr) {
1968 size_t len = 1;
1969 uint8_t *p;
1970 size_t i;
1971 size_t datalen = 0;
1972
1973 len += ngtcp2_put_varint_len(fr->offset);
1974
1975 for (i = 0; i < fr->datacnt; ++i) {
1976 datalen += fr->data[i].len;
1977 }
1978
1979 len += ngtcp2_put_varint_len(datalen);
1980 len += datalen;
1981
1982 if (outlen < len) {
1983 return NGTCP2_ERR_NOBUF;
1984 }
1985
1986 p = out;
1987
1988 *p++ = NGTCP2_FRAME_CRYPTO;
1989
1990 p = ngtcp2_put_varint(p, fr->offset);
1991 p = ngtcp2_put_varint(p, datalen);
1992
1993 for (i = 0; i < fr->datacnt; ++i) {
1994 assert(fr->data[i].base);
1995 p = ngtcp2_cpymem(p, fr->data[i].base, fr->data[i].len);
1996 }
1997
1998 assert((size_t)(p - out) == len);
1999
2000 return (ngtcp2_ssize)len;
2001 }
2002
ngtcp2_pkt_encode_new_token_frame(uint8_t * out,size_t outlen,const ngtcp2_new_token * fr)2003 ngtcp2_ssize ngtcp2_pkt_encode_new_token_frame(uint8_t *out, size_t outlen,
2004 const ngtcp2_new_token *fr) {
2005 size_t len = 1 + ngtcp2_put_varint_len(fr->token.len) + fr->token.len;
2006 uint8_t *p;
2007
2008 assert(fr->token.len);
2009
2010 if (outlen < len) {
2011 return NGTCP2_ERR_NOBUF;
2012 }
2013
2014 p = out;
2015
2016 *p++ = NGTCP2_FRAME_NEW_TOKEN;
2017
2018 p = ngtcp2_put_varint(p, fr->token.len);
2019 p = ngtcp2_cpymem(p, fr->token.base, fr->token.len);
2020
2021 assert((size_t)(p - out) == len);
2022
2023 return (ngtcp2_ssize)len;
2024 }
2025
ngtcp2_pkt_encode_retire_connection_id_frame(uint8_t * out,size_t outlen,const ngtcp2_retire_connection_id * fr)2026 ngtcp2_ssize ngtcp2_pkt_encode_retire_connection_id_frame(
2027 uint8_t *out, size_t outlen, const ngtcp2_retire_connection_id *fr) {
2028 size_t len = 1 + ngtcp2_put_varint_len(fr->seq);
2029 uint8_t *p;
2030
2031 if (outlen < len) {
2032 return NGTCP2_ERR_NOBUF;
2033 }
2034
2035 p = out;
2036
2037 *p++ = NGTCP2_FRAME_RETIRE_CONNECTION_ID;
2038
2039 p = ngtcp2_put_varint(p, fr->seq);
2040
2041 assert((size_t)(p - out) == len);
2042
2043 return (ngtcp2_ssize)len;
2044 }
2045
2046 ngtcp2_ssize
ngtcp2_pkt_encode_handshake_done_frame(uint8_t * out,size_t outlen,const ngtcp2_handshake_done * fr)2047 ngtcp2_pkt_encode_handshake_done_frame(uint8_t *out, size_t outlen,
2048 const ngtcp2_handshake_done *fr) {
2049 (void)fr;
2050
2051 if (outlen < 1) {
2052 return NGTCP2_ERR_NOBUF;
2053 }
2054
2055 *out++ = NGTCP2_FRAME_HANDSHAKE_DONE;
2056
2057 return 1;
2058 }
2059
ngtcp2_pkt_encode_datagram_frame(uint8_t * out,size_t outlen,const ngtcp2_datagram * fr)2060 ngtcp2_ssize ngtcp2_pkt_encode_datagram_frame(uint8_t *out, size_t outlen,
2061 const ngtcp2_datagram *fr) {
2062 uint64_t datalen = ngtcp2_vec_len(fr->data, fr->datacnt);
2063 uint64_t len =
2064 1 +
2065 (fr->type == NGTCP2_FRAME_DATAGRAM ? 0 : ngtcp2_put_varint_len(datalen)) +
2066 datalen;
2067 uint8_t *p;
2068 size_t i;
2069
2070 assert(fr->type == NGTCP2_FRAME_DATAGRAM ||
2071 fr->type == NGTCP2_FRAME_DATAGRAM_LEN);
2072
2073 if (outlen < len) {
2074 return NGTCP2_ERR_NOBUF;
2075 }
2076
2077 p = out;
2078
2079 *p++ = fr->type;
2080 if (fr->type == NGTCP2_FRAME_DATAGRAM_LEN) {
2081 p = ngtcp2_put_varint(p, datalen);
2082 }
2083
2084 for (i = 0; i < fr->datacnt; ++i) {
2085 assert(fr->data[i].len);
2086 assert(fr->data[i].base);
2087 p = ngtcp2_cpymem(p, fr->data[i].base, fr->data[i].len);
2088 }
2089
2090 assert((size_t)(p - out) == len);
2091
2092 return (ngtcp2_ssize)len;
2093 }
2094
ngtcp2_pkt_write_version_negotiation(uint8_t * dest,size_t destlen,uint8_t unused_random,const uint8_t * dcid,size_t dcidlen,const uint8_t * scid,size_t scidlen,const uint32_t * sv,size_t nsv)2095 ngtcp2_ssize ngtcp2_pkt_write_version_negotiation(
2096 uint8_t *dest, size_t destlen, uint8_t unused_random, const uint8_t *dcid,
2097 size_t dcidlen, const uint8_t *scid, size_t scidlen, const uint32_t *sv,
2098 size_t nsv) {
2099 size_t len = 1 + 4 + 1 + dcidlen + 1 + scidlen + nsv * 4;
2100 uint8_t *p;
2101 size_t i;
2102
2103 assert(dcidlen < 256);
2104 assert(scidlen < 256);
2105
2106 if (destlen < len) {
2107 return NGTCP2_ERR_NOBUF;
2108 }
2109
2110 p = dest;
2111
2112 *p++ = 0x80 | unused_random;
2113 p = ngtcp2_put_uint32be(p, 0);
2114 *p++ = (uint8_t)dcidlen;
2115 if (dcidlen) {
2116 p = ngtcp2_cpymem(p, dcid, dcidlen);
2117 }
2118 *p++ = (uint8_t)scidlen;
2119 if (scidlen) {
2120 p = ngtcp2_cpymem(p, scid, scidlen);
2121 }
2122
2123 for (i = 0; i < nsv; ++i) {
2124 p = ngtcp2_put_uint32be(p, sv[i]);
2125 }
2126
2127 assert((size_t)(p - dest) == len);
2128
2129 return (ngtcp2_ssize)len;
2130 }
2131
ngtcp2_pkt_decode_version_negotiation(uint32_t * dest,const uint8_t * payload,size_t payloadlen)2132 size_t ngtcp2_pkt_decode_version_negotiation(uint32_t *dest,
2133 const uint8_t *payload,
2134 size_t payloadlen) {
2135 const uint8_t *end = payload + payloadlen;
2136
2137 assert((payloadlen % sizeof(uint32_t)) == 0);
2138
2139 for (; payload != end; payload += sizeof(uint32_t)) {
2140 *dest++ = ngtcp2_get_uint32(payload);
2141 }
2142
2143 return payloadlen / sizeof(uint32_t);
2144 }
2145
ngtcp2_pkt_decode_stateless_reset(ngtcp2_pkt_stateless_reset * sr,const uint8_t * payload,size_t payloadlen)2146 int ngtcp2_pkt_decode_stateless_reset(ngtcp2_pkt_stateless_reset *sr,
2147 const uint8_t *payload,
2148 size_t payloadlen) {
2149 const uint8_t *p = payload;
2150
2151 if (payloadlen <
2152 NGTCP2_MIN_STATELESS_RESET_RANDLEN + NGTCP2_STATELESS_RESET_TOKENLEN) {
2153 return NGTCP2_ERR_INVALID_ARGUMENT;
2154 }
2155
2156 sr->rand = p;
2157 sr->randlen = payloadlen - NGTCP2_STATELESS_RESET_TOKENLEN;
2158 p += sr->randlen;
2159 memcpy(sr->stateless_reset_token, p, NGTCP2_STATELESS_RESET_TOKENLEN);
2160
2161 return 0;
2162 }
2163
ngtcp2_pkt_decode_retry(ngtcp2_pkt_retry * dest,const uint8_t * payload,size_t payloadlen)2164 int ngtcp2_pkt_decode_retry(ngtcp2_pkt_retry *dest, const uint8_t *payload,
2165 size_t payloadlen) {
2166 size_t len = /* token */ 1 + NGTCP2_RETRY_TAGLEN;
2167
2168 if (payloadlen < len) {
2169 return NGTCP2_ERR_INVALID_ARGUMENT;
2170 }
2171
2172 dest->token.base = (uint8_t *)payload;
2173 dest->token.len = (size_t)(payloadlen - NGTCP2_RETRY_TAGLEN);
2174 ngtcp2_cpymem(dest->tag, payload + dest->token.len, NGTCP2_RETRY_TAGLEN);
2175
2176 return 0;
2177 }
2178
ngtcp2_pkt_adjust_pkt_num(int64_t max_pkt_num,int64_t pkt_num,size_t n)2179 int64_t ngtcp2_pkt_adjust_pkt_num(int64_t max_pkt_num, int64_t pkt_num,
2180 size_t n) {
2181 int64_t expected = max_pkt_num + 1;
2182 int64_t win = (int64_t)1 << n;
2183 int64_t hwin = win / 2;
2184 int64_t mask = win - 1;
2185 int64_t cand = (expected & ~mask) | pkt_num;
2186
2187 if (cand <= expected - hwin) {
2188 assert(cand <= (int64_t)NGTCP2_MAX_VARINT - win);
2189 return cand + win;
2190 }
2191 if (cand > expected + hwin && cand >= win) {
2192 return cand - win;
2193 }
2194 return cand;
2195 }
2196
ngtcp2_pkt_validate_ack(ngtcp2_ack * fr)2197 int ngtcp2_pkt_validate_ack(ngtcp2_ack *fr) {
2198 int64_t largest_ack = fr->largest_ack;
2199 size_t i;
2200
2201 if (largest_ack < (int64_t)fr->first_ack_blklen) {
2202 return NGTCP2_ERR_ACK_FRAME;
2203 }
2204
2205 largest_ack -= (int64_t)fr->first_ack_blklen;
2206
2207 for (i = 0; i < fr->num_blks; ++i) {
2208 if (largest_ack < (int64_t)fr->blks[i].gap + 2) {
2209 return NGTCP2_ERR_ACK_FRAME;
2210 }
2211
2212 largest_ack -= (int64_t)fr->blks[i].gap + 2;
2213
2214 if (largest_ack < (int64_t)fr->blks[i].blklen) {
2215 return NGTCP2_ERR_ACK_FRAME;
2216 }
2217
2218 largest_ack -= (int64_t)fr->blks[i].blklen;
2219 }
2220
2221 return 0;
2222 }
2223
2224 ngtcp2_ssize
ngtcp2_pkt_write_stateless_reset(uint8_t * dest,size_t destlen,const uint8_t * stateless_reset_token,const uint8_t * rand,size_t randlen)2225 ngtcp2_pkt_write_stateless_reset(uint8_t *dest, size_t destlen,
2226 const uint8_t *stateless_reset_token,
2227 const uint8_t *rand, size_t randlen) {
2228 uint8_t *p;
2229
2230 if (destlen <
2231 NGTCP2_MIN_STATELESS_RESET_RANDLEN + NGTCP2_STATELESS_RESET_TOKENLEN) {
2232 return NGTCP2_ERR_NOBUF;
2233 }
2234
2235 if (randlen < NGTCP2_MIN_STATELESS_RESET_RANDLEN) {
2236 return NGTCP2_ERR_INVALID_ARGUMENT;
2237 }
2238
2239 p = dest;
2240
2241 randlen = ngtcp2_min(destlen - NGTCP2_STATELESS_RESET_TOKENLEN, randlen);
2242
2243 p = ngtcp2_cpymem(p, rand, randlen);
2244 p = ngtcp2_cpymem(p, stateless_reset_token, NGTCP2_STATELESS_RESET_TOKENLEN);
2245 *dest = (uint8_t)((*dest & 0x7fu) | 0x40u);
2246
2247 return p - dest;
2248 }
2249
ngtcp2_pkt_write_retry(uint8_t * dest,size_t destlen,uint32_t version,const ngtcp2_cid * dcid,const ngtcp2_cid * scid,const ngtcp2_cid * odcid,const uint8_t * token,size_t tokenlen,ngtcp2_encrypt encrypt,const ngtcp2_crypto_aead * aead,const ngtcp2_crypto_aead_ctx * aead_ctx)2250 ngtcp2_ssize ngtcp2_pkt_write_retry(
2251 uint8_t *dest, size_t destlen, uint32_t version, const ngtcp2_cid *dcid,
2252 const ngtcp2_cid *scid, const ngtcp2_cid *odcid, const uint8_t *token,
2253 size_t tokenlen, ngtcp2_encrypt encrypt, const ngtcp2_crypto_aead *aead,
2254 const ngtcp2_crypto_aead_ctx *aead_ctx) {
2255 ngtcp2_pkt_hd hd;
2256 uint8_t pseudo_retry[1500];
2257 ngtcp2_ssize pseudo_retrylen;
2258 uint8_t tag[NGTCP2_RETRY_TAGLEN];
2259 int rv;
2260 uint8_t *p;
2261 size_t offset;
2262 const uint8_t *nonce;
2263 size_t noncelen;
2264
2265 assert(tokenlen > 0);
2266 assert(!ngtcp2_cid_eq(scid, odcid));
2267
2268 /* Retry packet is sent at most once per one connection attempt. In
2269 the first connection attempt, client has to send random DCID
2270 which is at least NGTCP2_MIN_INITIAL_DCIDLEN bytes long. */
2271 if (odcid->datalen < NGTCP2_MIN_INITIAL_DCIDLEN) {
2272 return NGTCP2_ERR_INVALID_ARGUMENT;
2273 }
2274
2275 ngtcp2_pkt_hd_init(&hd, NGTCP2_PKT_FLAG_LONG_FORM, NGTCP2_PKT_RETRY, dcid,
2276 scid, /* pkt_num = */ 0, /* pkt_numlen = */ 1, version,
2277 /* len = */ 0);
2278
2279 pseudo_retrylen =
2280 ngtcp2_pkt_encode_pseudo_retry(pseudo_retry, sizeof(pseudo_retry), &hd,
2281 /* unused = */ 0, odcid, token, tokenlen);
2282 if (pseudo_retrylen < 0) {
2283 return pseudo_retrylen;
2284 }
2285
2286 switch (version) {
2287 case NGTCP2_PROTO_VER_V1:
2288 nonce = (const uint8_t *)NGTCP2_RETRY_NONCE_V1;
2289 noncelen = sizeof(NGTCP2_RETRY_NONCE_V1) - 1;
2290 break;
2291 case NGTCP2_PROTO_VER_V2_DRAFT:
2292 nonce = (const uint8_t *)NGTCP2_RETRY_NONCE_V2_DRAFT;
2293 noncelen = sizeof(NGTCP2_RETRY_NONCE_V2_DRAFT) - 1;
2294 break;
2295 default:
2296 nonce = (const uint8_t *)NGTCP2_RETRY_NONCE_DRAFT;
2297 noncelen = sizeof(NGTCP2_RETRY_NONCE_DRAFT) - 1;
2298 }
2299
2300 /* OpenSSL does not like NULL plaintext. */
2301 rv = encrypt(tag, aead, aead_ctx, (const uint8_t *)"", 0, nonce, noncelen,
2302 pseudo_retry, (size_t)pseudo_retrylen);
2303 if (rv != 0) {
2304 return rv;
2305 }
2306
2307 offset = 1 + odcid->datalen;
2308 if (destlen < (size_t)pseudo_retrylen + sizeof(tag) - offset) {
2309 return NGTCP2_ERR_NOBUF;
2310 }
2311
2312 p = ngtcp2_cpymem(dest, pseudo_retry + offset,
2313 (size_t)pseudo_retrylen - offset);
2314 p = ngtcp2_cpymem(p, tag, sizeof(tag));
2315
2316 return p - dest;
2317 }
2318
ngtcp2_pkt_encode_pseudo_retry(uint8_t * dest,size_t destlen,const ngtcp2_pkt_hd * hd,uint8_t unused,const ngtcp2_cid * odcid,const uint8_t * token,size_t tokenlen)2319 ngtcp2_ssize ngtcp2_pkt_encode_pseudo_retry(
2320 uint8_t *dest, size_t destlen, const ngtcp2_pkt_hd *hd, uint8_t unused,
2321 const ngtcp2_cid *odcid, const uint8_t *token, size_t tokenlen) {
2322 uint8_t *p = dest;
2323 ngtcp2_ssize nwrite;
2324
2325 if (destlen < 1 + odcid->datalen) {
2326 return NGTCP2_ERR_NOBUF;
2327 }
2328
2329 *p++ = (uint8_t)odcid->datalen;
2330 p = ngtcp2_cpymem(p, odcid->data, odcid->datalen);
2331 destlen -= (size_t)(p - dest);
2332
2333 nwrite = ngtcp2_pkt_encode_hd_long(p, destlen, hd);
2334 if (nwrite < 0) {
2335 return nwrite;
2336 }
2337
2338 if (destlen < (size_t)nwrite + tokenlen) {
2339 return NGTCP2_ERR_NOBUF;
2340 }
2341
2342 *p &= 0xf0;
2343 *p |= unused;
2344
2345 p += nwrite;
2346
2347 p = ngtcp2_cpymem(p, token, tokenlen);
2348
2349 return p - dest;
2350 }
2351
ngtcp2_pkt_verify_retry_tag(uint32_t version,const ngtcp2_pkt_retry * retry,const uint8_t * pkt,size_t pktlen,ngtcp2_encrypt encrypt,const ngtcp2_crypto_aead * aead,const ngtcp2_crypto_aead_ctx * aead_ctx)2352 int ngtcp2_pkt_verify_retry_tag(uint32_t version, const ngtcp2_pkt_retry *retry,
2353 const uint8_t *pkt, size_t pktlen,
2354 ngtcp2_encrypt encrypt,
2355 const ngtcp2_crypto_aead *aead,
2356 const ngtcp2_crypto_aead_ctx *aead_ctx) {
2357 uint8_t pseudo_retry[1500];
2358 size_t pseudo_retrylen;
2359 uint8_t *p = pseudo_retry;
2360 int rv;
2361 uint8_t tag[NGTCP2_RETRY_TAGLEN];
2362 const uint8_t *nonce;
2363 size_t noncelen;
2364
2365 assert(pktlen >= sizeof(retry->tag));
2366
2367 if (sizeof(pseudo_retry) <
2368 1 + retry->odcid.datalen + pktlen - sizeof(retry->tag)) {
2369 return NGTCP2_ERR_PROTO;
2370 }
2371
2372 *p++ = (uint8_t)retry->odcid.datalen;
2373 p = ngtcp2_cpymem(p, retry->odcid.data, retry->odcid.datalen);
2374 p = ngtcp2_cpymem(p, pkt, pktlen - sizeof(retry->tag));
2375
2376 pseudo_retrylen = (size_t)(p - pseudo_retry);
2377
2378 switch (version) {
2379 case NGTCP2_PROTO_VER_V1:
2380 nonce = (const uint8_t *)NGTCP2_RETRY_NONCE_V1;
2381 noncelen = sizeof(NGTCP2_RETRY_NONCE_V1) - 1;
2382 break;
2383 case NGTCP2_PROTO_VER_V2_DRAFT:
2384 nonce = (const uint8_t *)NGTCP2_RETRY_NONCE_V2_DRAFT;
2385 noncelen = sizeof(NGTCP2_RETRY_NONCE_V2_DRAFT) - 1;
2386 break;
2387 default:
2388 nonce = (const uint8_t *)NGTCP2_RETRY_NONCE_DRAFT;
2389 noncelen = sizeof(NGTCP2_RETRY_NONCE_DRAFT) - 1;
2390 }
2391
2392 /* OpenSSL does not like NULL plaintext. */
2393 rv = encrypt(tag, aead, aead_ctx, (const uint8_t *)"", 0, nonce, noncelen,
2394 pseudo_retry, pseudo_retrylen);
2395 if (rv != 0) {
2396 return rv;
2397 }
2398
2399 if (0 != memcmp(retry->tag, tag, sizeof(retry->tag))) {
2400 return NGTCP2_ERR_PROTO;
2401 }
2402
2403 return 0;
2404 }
2405
ngtcp2_pkt_stream_max_datalen(int64_t stream_id,uint64_t offset,uint64_t len,size_t left)2406 size_t ngtcp2_pkt_stream_max_datalen(int64_t stream_id, uint64_t offset,
2407 uint64_t len, size_t left) {
2408 size_t n = 1 /* type */ + ngtcp2_put_varint_len((uint64_t)stream_id) +
2409 (offset ? ngtcp2_put_varint_len(offset) : 0);
2410
2411 if (left <= n) {
2412 return (size_t)-1;
2413 }
2414
2415 left -= n;
2416
2417 if (left > 8 + 1073741823 && len > 1073741823) {
2418 #if SIZE_MAX > UINT32_MAX
2419 len = ngtcp2_min(len, 4611686018427387903lu);
2420 #endif /* SIZE_MAX > UINT32_MAX */
2421 return (size_t)ngtcp2_min(len, (uint64_t)(left - 8));
2422 }
2423
2424 if (left > 4 + 16383 && len > 16383) {
2425 len = ngtcp2_min(len, 1073741823);
2426 return (size_t)ngtcp2_min(len, (uint64_t)(left - 4));
2427 }
2428
2429 if (left > 2 + 63 && len > 63) {
2430 len = ngtcp2_min(len, 16383);
2431 return (size_t)ngtcp2_min(len, (uint64_t)(left - 2));
2432 }
2433
2434 len = ngtcp2_min(len, 63);
2435 return (size_t)ngtcp2_min(len, (uint64_t)(left - 1));
2436 }
2437
ngtcp2_pkt_crypto_max_datalen(uint64_t offset,size_t len,size_t left)2438 size_t ngtcp2_pkt_crypto_max_datalen(uint64_t offset, size_t len, size_t left) {
2439 size_t n = 1 /* type */ + ngtcp2_put_varint_len(offset);
2440
2441 /* CRYPTO frame must contain nonzero length data. Return -1 if
2442 there is no space to write crypto data. */
2443 if (left <= n + 1) {
2444 return (size_t)-1;
2445 }
2446
2447 left -= n;
2448
2449 if (left > 8 + 1073741823 && len > 1073741823) {
2450 #if SIZE_MAX > UINT32_MAX
2451 len = ngtcp2_min(len, 4611686018427387903lu);
2452 #endif /* SIZE_MAX > UINT32_MAX */
2453 return ngtcp2_min(len, left - 8);
2454 }
2455
2456 if (left > 4 + 16383 && len > 16383) {
2457 len = ngtcp2_min(len, 1073741823);
2458 return ngtcp2_min(len, left - 4);
2459 }
2460
2461 if (left > 2 + 63 && len > 63) {
2462 len = ngtcp2_min(len, 16383);
2463 return ngtcp2_min(len, left - 2);
2464 }
2465
2466 len = ngtcp2_min(len, 63);
2467 return ngtcp2_min(len, left - 1);
2468 }
2469
ngtcp2_pkt_datagram_framelen(size_t len)2470 size_t ngtcp2_pkt_datagram_framelen(size_t len) {
2471 return 1 /* type */ + ngtcp2_put_varint_len(len) + len;
2472 }
2473
ngtcp2_is_supported_version(uint32_t version)2474 int ngtcp2_is_supported_version(uint32_t version) {
2475 switch (version) {
2476 case NGTCP2_PROTO_VER_V1:
2477 case NGTCP2_PROTO_VER_V2_DRAFT:
2478 return 1;
2479 default:
2480 return NGTCP2_PROTO_VER_DRAFT_MIN <= version &&
2481 version <= NGTCP2_PROTO_VER_DRAFT_MAX;
2482 }
2483 }
2484
ngtcp2_is_reserved_version(uint32_t version)2485 int ngtcp2_is_reserved_version(uint32_t version) {
2486 return (version & NGTCP2_RESERVED_VERSION_MASK) ==
2487 NGTCP2_RESERVED_VERSION_MASK;
2488 }
2489
ngtcp2_pkt_get_type_long(uint32_t version,uint8_t c)2490 uint8_t ngtcp2_pkt_get_type_long(uint32_t version, uint8_t c) {
2491 uint8_t pkt_type = (uint8_t)((c & NGTCP2_LONG_TYPE_MASK) >> 4);
2492
2493 switch (version) {
2494 case NGTCP2_PROTO_VER_V2_DRAFT:
2495 switch (pkt_type) {
2496 case NGTCP2_PKT_TYPE_INITIAL_V2_DRAFT:
2497 return NGTCP2_PKT_INITIAL;
2498 case NGTCP2_PKT_TYPE_0RTT_V2_DRAFT:
2499 return NGTCP2_PKT_0RTT;
2500 case NGTCP2_PKT_TYPE_HANDSHAKE_V2_DRAFT:
2501 return NGTCP2_PKT_HANDSHAKE;
2502 case NGTCP2_PKT_TYPE_RETRY_V2_DRAFT:
2503 return NGTCP2_PKT_RETRY;
2504 default:
2505 return 0;
2506 }
2507 default:
2508 if (!ngtcp2_is_supported_version(version)) {
2509 return 0;
2510 }
2511
2512 /* QUIC v1 and draft versions share the same numeric packet
2513 types. */
2514 switch (pkt_type) {
2515 case NGTCP2_PKT_TYPE_INITIAL_V1:
2516 return NGTCP2_PKT_INITIAL;
2517 case NGTCP2_PKT_TYPE_0RTT_V1:
2518 return NGTCP2_PKT_0RTT;
2519 case NGTCP2_PKT_TYPE_HANDSHAKE_V1:
2520 return NGTCP2_PKT_HANDSHAKE;
2521 case NGTCP2_PKT_TYPE_RETRY_V1:
2522 return NGTCP2_PKT_RETRY;
2523 default:
2524 return 0;
2525 }
2526 }
2527 }
2528
ngtcp2_pkt_versioned_type(uint32_t version,uint32_t pkt_type)2529 uint8_t ngtcp2_pkt_versioned_type(uint32_t version, uint32_t pkt_type) {
2530 switch (version) {
2531 case NGTCP2_PROTO_VER_V2_DRAFT:
2532 switch (pkt_type) {
2533 case NGTCP2_PKT_INITIAL:
2534 return NGTCP2_PKT_TYPE_INITIAL_V2_DRAFT;
2535 case NGTCP2_PKT_0RTT:
2536 return NGTCP2_PKT_TYPE_0RTT_V2_DRAFT;
2537 case NGTCP2_PKT_HANDSHAKE:
2538 return NGTCP2_PKT_TYPE_HANDSHAKE_V2_DRAFT;
2539 case NGTCP2_PKT_RETRY:
2540 return NGTCP2_PKT_TYPE_RETRY_V2_DRAFT;
2541 default:
2542 assert(0);
2543 abort();
2544 }
2545 default:
2546 /* Assume that unsupported versions share the numeric long packet
2547 types with QUIC v1 in order to send a packet to elicit Version
2548 Negotiation packet. */
2549
2550 /* QUIC v1 and draft versions share the same numeric packet
2551 types. */
2552 switch (pkt_type) {
2553 case NGTCP2_PKT_INITIAL:
2554 return NGTCP2_PKT_TYPE_INITIAL_V1;
2555 case NGTCP2_PKT_0RTT:
2556 return NGTCP2_PKT_TYPE_0RTT_V1;
2557 case NGTCP2_PKT_HANDSHAKE:
2558 return NGTCP2_PKT_TYPE_HANDSHAKE_V1;
2559 case NGTCP2_PKT_RETRY:
2560 return NGTCP2_PKT_TYPE_RETRY_V1;
2561 default:
2562 assert(0);
2563 abort();
2564 }
2565 }
2566 }
2567
ngtcp2_pkt_verify_reserved_bits(uint8_t c)2568 int ngtcp2_pkt_verify_reserved_bits(uint8_t c) {
2569 if (c & NGTCP2_HEADER_FORM_BIT) {
2570 return (c & NGTCP2_LONG_RESERVED_BIT_MASK) == 0 ? 0 : NGTCP2_ERR_PROTO;
2571 }
2572 return (c & NGTCP2_SHORT_RESERVED_BIT_MASK) == 0 ? 0 : NGTCP2_ERR_PROTO;
2573 }
2574