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