Mercurial > hg > nginx-quic
comparison src/event/quic/ngx_event_quic_transport.c @ 8266:046c951e393a quic
QUIC: moved all quic sources into src/event/quic.
author | Vladimir Homutov <vl@nginx.com> |
---|---|
date | Fri, 25 Dec 2020 14:01:28 +0300 |
parents | src/event/ngx_event_quic_transport.c@5247461c17e1 |
children | 7df607cb2d11 |
comparison
equal
deleted
inserted
replaced
8265:13c537def699 | 8266:046c951e393a |
---|---|
1 | |
2 /* | |
3 * Copyright (C) Nginx, Inc. | |
4 */ | |
5 | |
6 | |
7 #include <ngx_config.h> | |
8 #include <ngx_core.h> | |
9 #include <ngx_event.h> | |
10 #include <ngx_event_quic_transport.h> | |
11 | |
12 | |
13 #define NGX_QUIC_LONG_DCID_LEN_OFFSET 5 | |
14 #define NGX_QUIC_LONG_DCID_OFFSET 6 | |
15 #define NGX_QUIC_SHORT_DCID_OFFSET 1 | |
16 | |
17 | |
18 #if (NGX_HAVE_NONALIGNED) | |
19 | |
20 #define ngx_quic_parse_uint16(p) ntohs(*(uint16_t *) (p)) | |
21 #define ngx_quic_parse_uint32(p) ntohl(*(uint32_t *) (p)) | |
22 | |
23 #define ngx_quic_write_uint16 ngx_quic_write_uint16_aligned | |
24 #define ngx_quic_write_uint32 ngx_quic_write_uint32_aligned | |
25 | |
26 #else | |
27 | |
28 #define ngx_quic_parse_uint16(p) ((p)[0] << 8 | (p)[1]) | |
29 #define ngx_quic_parse_uint32(p) \ | |
30 ((uint32_t) (p)[0] << 24 | (p)[1] << 16 | (p)[2] << 8 | (p)[3]) | |
31 | |
32 #define ngx_quic_write_uint16(p, s) \ | |
33 ((p)[0] = (u_char) ((s) >> 8), \ | |
34 (p)[1] = (u_char) (s), \ | |
35 (p) + sizeof(uint16_t)) | |
36 | |
37 #define ngx_quic_write_uint32(p, s) \ | |
38 ((p)[0] = (u_char) ((s) >> 24), \ | |
39 (p)[1] = (u_char) ((s) >> 16), \ | |
40 (p)[2] = (u_char) ((s) >> 8), \ | |
41 (p)[3] = (u_char) (s), \ | |
42 (p) + sizeof(uint32_t)) | |
43 | |
44 #endif | |
45 | |
46 #define ngx_quic_write_uint24(p, s) \ | |
47 ((p)[0] = (u_char) ((s) >> 16), \ | |
48 (p)[1] = (u_char) ((s) >> 8), \ | |
49 (p)[2] = (u_char) (s), \ | |
50 (p) + 3) | |
51 | |
52 #define ngx_quic_write_uint16_aligned(p, s) \ | |
53 (*(uint16_t *) (p) = htons((uint16_t) (s)), (p) + sizeof(uint16_t)) | |
54 | |
55 #define ngx_quic_write_uint32_aligned(p, s) \ | |
56 (*(uint32_t *) (p) = htonl((uint32_t) (s)), (p) + sizeof(uint32_t)) | |
57 | |
58 #define NGX_QUIC_VERSION(c) (0xff000000 + (c)) | |
59 | |
60 | |
61 static u_char *ngx_quic_parse_int(u_char *pos, u_char *end, uint64_t *out); | |
62 static ngx_uint_t ngx_quic_varint_len(uint64_t value); | |
63 static void ngx_quic_build_int(u_char **pos, uint64_t value); | |
64 | |
65 static u_char *ngx_quic_read_uint8(u_char *pos, u_char *end, uint8_t *value); | |
66 static u_char *ngx_quic_read_uint32(u_char *pos, u_char *end, uint32_t *value); | |
67 static u_char *ngx_quic_read_bytes(u_char *pos, u_char *end, size_t len, | |
68 u_char **out); | |
69 static u_char *ngx_quic_copy_bytes(u_char *pos, u_char *end, size_t len, | |
70 u_char *dst); | |
71 | |
72 static ngx_int_t ngx_quic_parse_short_header(ngx_quic_header_t *pkt, | |
73 size_t dcid_len); | |
74 static ngx_int_t ngx_quic_parse_long_header(ngx_quic_header_t *pkt); | |
75 static ngx_int_t ngx_quic_supported_version(uint32_t version); | |
76 static ngx_int_t ngx_quic_parse_long_header_v1(ngx_quic_header_t *pkt); | |
77 | |
78 static size_t ngx_quic_create_long_header(ngx_quic_header_t *pkt, u_char *out, | |
79 size_t pkt_len, u_char **pnp); | |
80 static size_t ngx_quic_create_short_header(ngx_quic_header_t *pkt, u_char *out, | |
81 size_t pkt_len, u_char **pnp); | |
82 | |
83 static ngx_int_t ngx_quic_frame_allowed(ngx_quic_header_t *pkt, | |
84 ngx_uint_t frame_type); | |
85 static size_t ngx_quic_create_ack(u_char *p, ngx_quic_ack_frame_t *ack, | |
86 ngx_chain_t *ranges); | |
87 static size_t ngx_quic_create_stop_sending(u_char *p, | |
88 ngx_quic_stop_sending_frame_t *ss); | |
89 static size_t ngx_quic_create_crypto(u_char *p, | |
90 ngx_quic_crypto_frame_t *crypto, ngx_chain_t *data); | |
91 static size_t ngx_quic_create_hs_done(u_char *p); | |
92 static size_t ngx_quic_create_new_token(u_char *p, | |
93 ngx_quic_new_token_frame_t *token); | |
94 static size_t ngx_quic_create_stream(u_char *p, ngx_quic_stream_frame_t *sf, | |
95 ngx_chain_t *data); | |
96 static size_t ngx_quic_create_max_streams(u_char *p, | |
97 ngx_quic_max_streams_frame_t *ms); | |
98 static size_t ngx_quic_create_max_stream_data(u_char *p, | |
99 ngx_quic_max_stream_data_frame_t *ms); | |
100 static size_t ngx_quic_create_max_data(u_char *p, | |
101 ngx_quic_max_data_frame_t *md); | |
102 static size_t ngx_quic_create_path_response(u_char *p, | |
103 ngx_quic_path_challenge_frame_t *pc); | |
104 static size_t ngx_quic_create_new_connection_id(u_char *p, | |
105 ngx_quic_new_conn_id_frame_t *rcid); | |
106 static size_t ngx_quic_create_retire_connection_id(u_char *p, | |
107 ngx_quic_retire_cid_frame_t *rcid); | |
108 static size_t ngx_quic_create_close(u_char *p, ngx_quic_close_frame_t *cl); | |
109 | |
110 static ngx_int_t ngx_quic_parse_transport_param(u_char *p, u_char *end, | |
111 uint16_t id, ngx_quic_tp_t *dst); | |
112 | |
113 | |
114 uint32_t ngx_quic_versions[] = { | |
115 #if (NGX_QUIC_DRAFT_VERSION >= 29) | |
116 /* pretend we support all versions in range draft-29..v1 */ | |
117 NGX_QUIC_VERSION(29), | |
118 NGX_QUIC_VERSION(30), | |
119 NGX_QUIC_VERSION(31), | |
120 NGX_QUIC_VERSION(32), | |
121 /* QUICv1 */ | |
122 0x00000001 | |
123 #else | |
124 NGX_QUIC_VERSION(NGX_QUIC_DRAFT_VERSION) | |
125 #endif | |
126 }; | |
127 | |
128 #define NGX_QUIC_NVERSIONS \ | |
129 (sizeof(ngx_quic_versions) / sizeof(ngx_quic_versions[0])) | |
130 | |
131 | |
132 /* literal errors indexed by corresponding value */ | |
133 static char *ngx_quic_errors[] = { | |
134 "NO_ERROR", | |
135 "INTERNAL_ERROR", | |
136 "CONNECTION_REFUSED", | |
137 "FLOW_CONTROL_ERROR", | |
138 "STREAM_LIMIT_ERROR", | |
139 "STREAM_STATE_ERROR", | |
140 "FINAL_SIZE_ERROR", | |
141 "FRAME_ENCODING_ERROR", | |
142 "TRANSPORT_PARAMETER_ERROR", | |
143 "CONNECTION_ID_LIMIT_ERROR", | |
144 "PROTOCOL_VIOLATION", | |
145 "INVALID_TOKEN", | |
146 "APPLICATION_ERROR", | |
147 "CRYPTO_BUFFER_EXCEEDED", | |
148 "KEY_UPDATE_ERROR", | |
149 }; | |
150 | |
151 | |
152 static ngx_inline u_char * | |
153 ngx_quic_parse_int(u_char *pos, u_char *end, uint64_t *out) | |
154 { | |
155 u_char *p; | |
156 uint64_t value; | |
157 ngx_uint_t len; | |
158 | |
159 if (pos >= end) { | |
160 return NULL; | |
161 } | |
162 | |
163 p = pos; | |
164 len = 1 << (*p >> 6); | |
165 | |
166 value = *p++ & 0x3f; | |
167 | |
168 if ((size_t)(end - p) < (len - 1)) { | |
169 return NULL; | |
170 } | |
171 | |
172 while (--len) { | |
173 value = (value << 8) + *p++; | |
174 } | |
175 | |
176 *out = value; | |
177 | |
178 return p; | |
179 } | |
180 | |
181 | |
182 static ngx_inline u_char * | |
183 ngx_quic_read_uint8(u_char *pos, u_char *end, uint8_t *value) | |
184 { | |
185 if ((size_t)(end - pos) < 1) { | |
186 return NULL; | |
187 } | |
188 | |
189 *value = *pos; | |
190 | |
191 return pos + 1; | |
192 } | |
193 | |
194 | |
195 static ngx_inline u_char * | |
196 ngx_quic_read_uint32(u_char *pos, u_char *end, uint32_t *value) | |
197 { | |
198 if ((size_t)(end - pos) < sizeof(uint32_t)) { | |
199 return NULL; | |
200 } | |
201 | |
202 *value = ngx_quic_parse_uint32(pos); | |
203 | |
204 return pos + sizeof(uint32_t); | |
205 } | |
206 | |
207 | |
208 static ngx_inline u_char * | |
209 ngx_quic_read_bytes(u_char *pos, u_char *end, size_t len, u_char **out) | |
210 { | |
211 if ((size_t)(end - pos) < len) { | |
212 return NULL; | |
213 } | |
214 | |
215 *out = pos; | |
216 | |
217 return pos + len; | |
218 } | |
219 | |
220 | |
221 static u_char * | |
222 ngx_quic_copy_bytes(u_char *pos, u_char *end, size_t len, u_char *dst) | |
223 { | |
224 if ((size_t)(end - pos) < len) { | |
225 return NULL; | |
226 } | |
227 | |
228 ngx_memcpy(dst, pos, len); | |
229 | |
230 return pos + len; | |
231 } | |
232 | |
233 | |
234 static ngx_uint_t | |
235 ngx_quic_varint_len(uint64_t value) | |
236 { | |
237 ngx_uint_t bits; | |
238 | |
239 bits = 0; | |
240 while (value >> ((8 << bits) - 2)) { | |
241 bits++; | |
242 } | |
243 | |
244 return 1 << bits; | |
245 } | |
246 | |
247 | |
248 static void | |
249 ngx_quic_build_int(u_char **pos, uint64_t value) | |
250 { | |
251 u_char *p; | |
252 ngx_uint_t bits, len; | |
253 | |
254 p = *pos; | |
255 bits = 0; | |
256 | |
257 while (value >> ((8 << bits) - 2)) { | |
258 bits++; | |
259 } | |
260 | |
261 len = (1 << bits); | |
262 | |
263 while (len--) { | |
264 *p++ = value >> (len * 8); | |
265 } | |
266 | |
267 **pos |= bits << 6; | |
268 *pos = p; | |
269 } | |
270 | |
271 | |
272 u_char * | |
273 ngx_quic_error_text(uint64_t error_code) | |
274 { | |
275 if (error_code >= NGX_QUIC_ERR_CRYPTO_ERROR) { | |
276 return (u_char *) "handshake error"; | |
277 } | |
278 | |
279 if (error_code >= NGX_QUIC_ERR_LAST) { | |
280 return (u_char *) "unknown error"; | |
281 } | |
282 | |
283 return (u_char *) ngx_quic_errors[error_code]; | |
284 } | |
285 | |
286 | |
287 ngx_int_t | |
288 ngx_quic_parse_packet(ngx_quic_header_t *pkt) | |
289 { | |
290 if (!ngx_quic_long_pkt(pkt->flags)) { | |
291 pkt->level = ssl_encryption_application; | |
292 | |
293 if (ngx_quic_parse_short_header(pkt, NGX_QUIC_SERVER_CID_LEN) != NGX_OK) | |
294 { | |
295 return NGX_DECLINED; | |
296 } | |
297 | |
298 return NGX_OK; | |
299 } | |
300 | |
301 if (ngx_quic_parse_long_header(pkt) != NGX_OK) { | |
302 return NGX_DECLINED; | |
303 } | |
304 | |
305 if (!ngx_quic_supported_version(pkt->version)) { | |
306 return NGX_ABORT; | |
307 } | |
308 | |
309 if (ngx_quic_parse_long_header_v1(pkt) != NGX_OK) { | |
310 return NGX_DECLINED; | |
311 } | |
312 | |
313 return NGX_OK; | |
314 } | |
315 | |
316 | |
317 static ngx_int_t | |
318 ngx_quic_parse_short_header(ngx_quic_header_t *pkt, size_t dcid_len) | |
319 { | |
320 u_char *p, *end; | |
321 | |
322 p = pkt->raw->pos; | |
323 end = pkt->data + pkt->len; | |
324 | |
325 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, pkt->log, 0, | |
326 "quic packet rx short flags:%xd", pkt->flags); | |
327 | |
328 if (!(pkt->flags & NGX_QUIC_PKT_FIXED_BIT)) { | |
329 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, "quic fixed bit is not set"); | |
330 return NGX_ERROR; | |
331 } | |
332 | |
333 pkt->dcid.len = dcid_len; | |
334 | |
335 p = ngx_quic_read_bytes(p, end, dcid_len, &pkt->dcid.data); | |
336 if (p == NULL) { | |
337 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, | |
338 "quic packet is too small to read dcid"); | |
339 return NGX_ERROR; | |
340 } | |
341 | |
342 pkt->raw->pos = p; | |
343 | |
344 return NGX_OK; | |
345 } | |
346 | |
347 | |
348 static ngx_int_t | |
349 ngx_quic_parse_long_header(ngx_quic_header_t *pkt) | |
350 { | |
351 u_char *p, *end; | |
352 uint8_t idlen; | |
353 | |
354 p = pkt->raw->pos; | |
355 end = pkt->data + pkt->len; | |
356 | |
357 p = ngx_quic_read_uint32(p, end, &pkt->version); | |
358 if (p == NULL) { | |
359 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, | |
360 "quic packet is too small to read version"); | |
361 return NGX_ERROR; | |
362 } | |
363 | |
364 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, pkt->log, 0, | |
365 "quic packet rx long flags:%xd version:%xD", | |
366 pkt->flags, pkt->version); | |
367 | |
368 if (!(pkt->flags & NGX_QUIC_PKT_FIXED_BIT)) { | |
369 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, "quic fixed bit is not set"); | |
370 return NGX_ERROR; | |
371 } | |
372 | |
373 p = ngx_quic_read_uint8(p, end, &idlen); | |
374 if (p == NULL) { | |
375 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, | |
376 "quic packet is too small to read dcid len"); | |
377 return NGX_ERROR; | |
378 } | |
379 | |
380 if (idlen > NGX_QUIC_CID_LEN_MAX) { | |
381 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, | |
382 "quic packet dcid is too long"); | |
383 return NGX_ERROR; | |
384 } | |
385 | |
386 pkt->dcid.len = idlen; | |
387 | |
388 p = ngx_quic_read_bytes(p, end, idlen, &pkt->dcid.data); | |
389 if (p == NULL) { | |
390 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, | |
391 "quic packet is too small to read dcid"); | |
392 return NGX_ERROR; | |
393 } | |
394 | |
395 p = ngx_quic_read_uint8(p, end, &idlen); | |
396 if (p == NULL) { | |
397 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, | |
398 "quic packet is too small to read scid len"); | |
399 return NGX_ERROR; | |
400 } | |
401 | |
402 if (idlen > NGX_QUIC_CID_LEN_MAX) { | |
403 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, | |
404 "quic packet scid is too long"); | |
405 return NGX_ERROR; | |
406 } | |
407 | |
408 pkt->scid.len = idlen; | |
409 | |
410 p = ngx_quic_read_bytes(p, end, idlen, &pkt->scid.data); | |
411 if (p == NULL) { | |
412 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, | |
413 "quic packet is too small to read scid"); | |
414 return NGX_ERROR; | |
415 } | |
416 | |
417 pkt->raw->pos = p; | |
418 | |
419 return NGX_OK; | |
420 } | |
421 | |
422 | |
423 static ngx_int_t | |
424 ngx_quic_supported_version(uint32_t version) | |
425 { | |
426 ngx_uint_t i; | |
427 | |
428 for (i = 0; i < NGX_QUIC_NVERSIONS; i++) { | |
429 if (ngx_quic_versions[i] == version) { | |
430 return 1; | |
431 } | |
432 } | |
433 | |
434 return 0; | |
435 } | |
436 | |
437 | |
438 static ngx_int_t | |
439 ngx_quic_parse_long_header_v1(ngx_quic_header_t *pkt) | |
440 { | |
441 u_char *p, *end; | |
442 uint64_t varint; | |
443 | |
444 p = pkt->raw->pos; | |
445 end = pkt->raw->last; | |
446 | |
447 pkt->log->action = "parsing quic long header"; | |
448 | |
449 if (ngx_quic_pkt_in(pkt->flags)) { | |
450 | |
451 if (pkt->len < NGX_QUIC_MIN_INITIAL_SIZE) { | |
452 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, | |
453 "quic UDP datagram is too small for initial packet"); | |
454 return NGX_DECLINED; | |
455 } | |
456 | |
457 p = ngx_quic_parse_int(p, end, &varint); | |
458 if (p == NULL) { | |
459 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, | |
460 "quic failed to parse token length"); | |
461 return NGX_ERROR; | |
462 } | |
463 | |
464 pkt->token.len = varint; | |
465 | |
466 p = ngx_quic_read_bytes(p, end, pkt->token.len, &pkt->token.data); | |
467 if (p == NULL) { | |
468 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, | |
469 "quic packet too small to read token data"); | |
470 return NGX_ERROR; | |
471 } | |
472 | |
473 pkt->level = ssl_encryption_initial; | |
474 | |
475 } else if (ngx_quic_pkt_zrtt(pkt->flags)) { | |
476 pkt->level = ssl_encryption_early_data; | |
477 | |
478 } else if (ngx_quic_pkt_hs(pkt->flags)) { | |
479 pkt->level = ssl_encryption_handshake; | |
480 | |
481 } else { | |
482 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, | |
483 "quic bad packet type"); | |
484 return NGX_DECLINED; | |
485 } | |
486 | |
487 p = ngx_quic_parse_int(p, end, &varint); | |
488 if (p == NULL) { | |
489 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, "quic bad packet length"); | |
490 return NGX_ERROR; | |
491 } | |
492 | |
493 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, pkt->log, 0, | |
494 "quic packet rx %s len:%uL", | |
495 ngx_quic_level_name(pkt->level), varint); | |
496 | |
497 if (varint > (uint64_t) ((pkt->data + pkt->len) - p)) { | |
498 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, "quic truncated %s packet", | |
499 ngx_quic_level_name(pkt->level)); | |
500 return NGX_ERROR; | |
501 } | |
502 | |
503 pkt->raw->pos = p; | |
504 pkt->len = p + varint - pkt->data; | |
505 | |
506 return NGX_OK; | |
507 } | |
508 | |
509 | |
510 ngx_int_t | |
511 ngx_quic_get_packet_dcid(ngx_log_t *log, u_char *data, size_t n, | |
512 ngx_str_t *dcid) | |
513 { | |
514 size_t len, offset; | |
515 | |
516 if (n == 0) { | |
517 goto failed; | |
518 } | |
519 | |
520 if (ngx_quic_long_pkt(*data)) { | |
521 if (n < NGX_QUIC_LONG_DCID_LEN_OFFSET + 1) { | |
522 goto failed; | |
523 } | |
524 | |
525 len = data[NGX_QUIC_LONG_DCID_LEN_OFFSET]; | |
526 offset = NGX_QUIC_LONG_DCID_OFFSET; | |
527 | |
528 } else { | |
529 len = NGX_QUIC_SERVER_CID_LEN; | |
530 offset = NGX_QUIC_SHORT_DCID_OFFSET; | |
531 } | |
532 | |
533 if (n < len + offset) { | |
534 goto failed; | |
535 } | |
536 | |
537 dcid->len = len; | |
538 dcid->data = &data[offset]; | |
539 | |
540 return NGX_OK; | |
541 | |
542 failed: | |
543 | |
544 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, log, 0, "quic malformed packet"); | |
545 | |
546 return NGX_ERROR; | |
547 } | |
548 | |
549 | |
550 size_t | |
551 ngx_quic_create_version_negotiation(ngx_quic_header_t *pkt, u_char *out) | |
552 { | |
553 u_char *p, *start; | |
554 ngx_uint_t i; | |
555 | |
556 p = start = out; | |
557 | |
558 *p++ = pkt->flags; | |
559 | |
560 /* | |
561 * The Version field of a Version Negotiation packet | |
562 * MUST be set to 0x00000000 | |
563 */ | |
564 p = ngx_quic_write_uint32(p, 0); | |
565 | |
566 *p++ = pkt->dcid.len; | |
567 p = ngx_cpymem(p, pkt->dcid.data, pkt->dcid.len); | |
568 | |
569 *p++ = pkt->scid.len; | |
570 p = ngx_cpymem(p, pkt->scid.data, pkt->scid.len); | |
571 | |
572 for (i = 0; i < NGX_QUIC_NVERSIONS; i++) { | |
573 p = ngx_quic_write_uint32(p, ngx_quic_versions[i]); | |
574 } | |
575 | |
576 return p - start; | |
577 } | |
578 | |
579 | |
580 size_t | |
581 ngx_quic_create_header(ngx_quic_header_t *pkt, u_char *out, size_t pkt_len, | |
582 u_char **pnp) | |
583 { | |
584 return ngx_quic_short_pkt(pkt->flags) | |
585 ? ngx_quic_create_short_header(pkt, out, pkt_len, pnp) | |
586 : ngx_quic_create_long_header(pkt, out, pkt_len, pnp); | |
587 } | |
588 | |
589 | |
590 static size_t | |
591 ngx_quic_create_long_header(ngx_quic_header_t *pkt, u_char *out, | |
592 size_t pkt_len, u_char **pnp) | |
593 { | |
594 u_char *p, *start; | |
595 | |
596 if (out == NULL) { | |
597 return 5 + 2 + pkt->dcid.len + pkt->scid.len | |
598 + ngx_quic_varint_len(pkt_len + pkt->num_len) + pkt->num_len | |
599 + (pkt->level == ssl_encryption_initial ? 1 : 0); | |
600 } | |
601 | |
602 p = start = out; | |
603 | |
604 *p++ = pkt->flags; | |
605 | |
606 p = ngx_quic_write_uint32(p, pkt->version); | |
607 | |
608 *p++ = pkt->dcid.len; | |
609 p = ngx_cpymem(p, pkt->dcid.data, pkt->dcid.len); | |
610 | |
611 *p++ = pkt->scid.len; | |
612 p = ngx_cpymem(p, pkt->scid.data, pkt->scid.len); | |
613 | |
614 if (pkt->level == ssl_encryption_initial) { | |
615 ngx_quic_build_int(&p, 0); | |
616 } | |
617 | |
618 ngx_quic_build_int(&p, pkt_len + pkt->num_len); | |
619 | |
620 *pnp = p; | |
621 | |
622 switch (pkt->num_len) { | |
623 case 1: | |
624 *p++ = pkt->trunc; | |
625 break; | |
626 case 2: | |
627 p = ngx_quic_write_uint16(p, pkt->trunc); | |
628 break; | |
629 case 3: | |
630 p = ngx_quic_write_uint24(p, pkt->trunc); | |
631 break; | |
632 case 4: | |
633 p = ngx_quic_write_uint32(p, pkt->trunc); | |
634 break; | |
635 } | |
636 | |
637 return p - start; | |
638 } | |
639 | |
640 | |
641 static size_t | |
642 ngx_quic_create_short_header(ngx_quic_header_t *pkt, u_char *out, | |
643 size_t pkt_len, u_char **pnp) | |
644 { | |
645 u_char *p, *start; | |
646 | |
647 if (out == NULL) { | |
648 return 1 + pkt->dcid.len + pkt->num_len; | |
649 } | |
650 | |
651 p = start = out; | |
652 | |
653 *p++ = pkt->flags; | |
654 | |
655 p = ngx_cpymem(p, pkt->dcid.data, pkt->dcid.len); | |
656 | |
657 *pnp = p; | |
658 | |
659 switch (pkt->num_len) { | |
660 case 1: | |
661 *p++ = pkt->trunc; | |
662 break; | |
663 case 2: | |
664 p = ngx_quic_write_uint16(p, pkt->trunc); | |
665 break; | |
666 case 3: | |
667 p = ngx_quic_write_uint24(p, pkt->trunc); | |
668 break; | |
669 case 4: | |
670 p = ngx_quic_write_uint32(p, pkt->trunc); | |
671 break; | |
672 } | |
673 | |
674 return p - start; | |
675 } | |
676 | |
677 | |
678 size_t | |
679 ngx_quic_create_retry_itag(ngx_quic_header_t *pkt, u_char *out, | |
680 u_char **start) | |
681 { | |
682 u_char *p; | |
683 | |
684 p = out; | |
685 | |
686 *p++ = pkt->odcid.len; | |
687 p = ngx_cpymem(p, pkt->odcid.data, pkt->odcid.len); | |
688 | |
689 *start = p; | |
690 | |
691 *p++ = 0xff; | |
692 | |
693 p = ngx_quic_write_uint32(p, pkt->version); | |
694 | |
695 *p++ = pkt->dcid.len; | |
696 p = ngx_cpymem(p, pkt->dcid.data, pkt->dcid.len); | |
697 | |
698 *p++ = pkt->scid.len; | |
699 p = ngx_cpymem(p, pkt->scid.data, pkt->scid.len); | |
700 | |
701 p = ngx_cpymem(p, pkt->token.data, pkt->token.len); | |
702 | |
703 return p - out; | |
704 } | |
705 | |
706 | |
707 #define ngx_quic_stream_bit_off(val) (((val) & 0x04) ? 1 : 0) | |
708 #define ngx_quic_stream_bit_len(val) (((val) & 0x02) ? 1 : 0) | |
709 #define ngx_quic_stream_bit_fin(val) (((val) & 0x01) ? 1 : 0) | |
710 | |
711 ssize_t | |
712 ngx_quic_parse_frame(ngx_quic_header_t *pkt, u_char *start, u_char *end, | |
713 ngx_quic_frame_t *f) | |
714 { | |
715 u_char *p; | |
716 uint64_t varint; | |
717 ngx_buf_t *b; | |
718 ngx_uint_t i; | |
719 | |
720 b = f->data->buf; | |
721 | |
722 p = start; | |
723 | |
724 p = ngx_quic_parse_int(p, end, &varint); | |
725 if (p == NULL) { | |
726 pkt->error = NGX_QUIC_ERR_FRAME_ENCODING_ERROR; | |
727 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, | |
728 "quic failed to obtain quic frame type"); | |
729 return NGX_ERROR; | |
730 } | |
731 | |
732 f->type = varint; | |
733 | |
734 if (ngx_quic_frame_allowed(pkt, f->type) != NGX_OK) { | |
735 pkt->error = NGX_QUIC_ERR_PROTOCOL_VIOLATION; | |
736 return NGX_ERROR; | |
737 } | |
738 | |
739 switch (f->type) { | |
740 | |
741 case NGX_QUIC_FT_CRYPTO: | |
742 | |
743 p = ngx_quic_parse_int(p, end, &f->u.crypto.offset); | |
744 if (p == NULL) { | |
745 goto error; | |
746 } | |
747 | |
748 p = ngx_quic_parse_int(p, end, &f->u.crypto.length); | |
749 if (p == NULL) { | |
750 goto error; | |
751 } | |
752 | |
753 p = ngx_quic_read_bytes(p, end, f->u.crypto.length, &b->pos); | |
754 if (p == NULL) { | |
755 goto error; | |
756 } | |
757 | |
758 b->last = p; | |
759 | |
760 break; | |
761 | |
762 case NGX_QUIC_FT_PADDING: | |
763 | |
764 while (p < end && *p == NGX_QUIC_FT_PADDING) { | |
765 p++; | |
766 } | |
767 | |
768 break; | |
769 | |
770 case NGX_QUIC_FT_ACK: | |
771 case NGX_QUIC_FT_ACK_ECN: | |
772 | |
773 if (!((p = ngx_quic_parse_int(p, end, &f->u.ack.largest)) | |
774 && (p = ngx_quic_parse_int(p, end, &f->u.ack.delay)) | |
775 && (p = ngx_quic_parse_int(p, end, &f->u.ack.range_count)) | |
776 && (p = ngx_quic_parse_int(p, end, &f->u.ack.first_range)))) | |
777 { | |
778 goto error; | |
779 } | |
780 | |
781 b->pos = p; | |
782 | |
783 /* process all ranges to get bounds, values are ignored */ | |
784 for (i = 0; i < f->u.ack.range_count; i++) { | |
785 | |
786 p = ngx_quic_parse_int(p, end, &varint); | |
787 if (p) { | |
788 p = ngx_quic_parse_int(p, end, &varint); | |
789 } | |
790 | |
791 if (p == NULL) { | |
792 goto error; | |
793 } | |
794 } | |
795 | |
796 b->last = p; | |
797 | |
798 f->u.ack.ranges_length = b->last - b->pos; | |
799 | |
800 if (f->type == NGX_QUIC_FT_ACK_ECN) { | |
801 | |
802 if (!((p = ngx_quic_parse_int(p, end, &f->u.ack.ect0)) | |
803 && (p = ngx_quic_parse_int(p, end, &f->u.ack.ect1)) | |
804 && (p = ngx_quic_parse_int(p, end, &f->u.ack.ce)))) | |
805 { | |
806 goto error; | |
807 } | |
808 | |
809 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, pkt->log, 0, | |
810 "quic ACK ECN counters ect0:%uL ect1:%uL ce:%uL", | |
811 f->u.ack.ect0, f->u.ack.ect1, f->u.ack.ce); | |
812 } | |
813 | |
814 break; | |
815 | |
816 case NGX_QUIC_FT_PING: | |
817 break; | |
818 | |
819 case NGX_QUIC_FT_NEW_CONNECTION_ID: | |
820 | |
821 p = ngx_quic_parse_int(p, end, &f->u.ncid.seqnum); | |
822 if (p == NULL) { | |
823 goto error; | |
824 } | |
825 | |
826 p = ngx_quic_parse_int(p, end, &f->u.ncid.retire); | |
827 if (p == NULL) { | |
828 goto error; | |
829 } | |
830 | |
831 if (f->u.ncid.retire > f->u.ncid.seqnum) { | |
832 goto error; | |
833 } | |
834 | |
835 p = ngx_quic_read_uint8(p, end, &f->u.ncid.len); | |
836 if (p == NULL) { | |
837 goto error; | |
838 } | |
839 | |
840 if (f->u.ncid.len < 1 || f->u.ncid.len > NGX_QUIC_CID_LEN_MAX) { | |
841 goto error; | |
842 } | |
843 | |
844 p = ngx_quic_copy_bytes(p, end, f->u.ncid.len, f->u.ncid.cid); | |
845 if (p == NULL) { | |
846 goto error; | |
847 } | |
848 | |
849 p = ngx_quic_copy_bytes(p, end, NGX_QUIC_SR_TOKEN_LEN, f->u.ncid.srt); | |
850 if (p == NULL) { | |
851 goto error; | |
852 } | |
853 | |
854 break; | |
855 | |
856 case NGX_QUIC_FT_RETIRE_CONNECTION_ID: | |
857 | |
858 p = ngx_quic_parse_int(p, end, &f->u.retire_cid.sequence_number); | |
859 if (p == NULL) { | |
860 goto error; | |
861 } | |
862 | |
863 break; | |
864 | |
865 case NGX_QUIC_FT_CONNECTION_CLOSE: | |
866 case NGX_QUIC_FT_CONNECTION_CLOSE_APP: | |
867 | |
868 p = ngx_quic_parse_int(p, end, &f->u.close.error_code); | |
869 if (p == NULL) { | |
870 goto error; | |
871 } | |
872 | |
873 if (f->type == NGX_QUIC_FT_CONNECTION_CLOSE) { | |
874 p = ngx_quic_parse_int(p, end, &f->u.close.frame_type); | |
875 if (p == NULL) { | |
876 goto error; | |
877 } | |
878 } | |
879 | |
880 p = ngx_quic_parse_int(p, end, &varint); | |
881 if (p == NULL) { | |
882 goto error; | |
883 } | |
884 | |
885 f->u.close.reason.len = varint; | |
886 | |
887 p = ngx_quic_read_bytes(p, end, f->u.close.reason.len, | |
888 &f->u.close.reason.data); | |
889 if (p == NULL) { | |
890 goto error; | |
891 } | |
892 | |
893 break; | |
894 | |
895 case NGX_QUIC_FT_STREAM0: | |
896 case NGX_QUIC_FT_STREAM1: | |
897 case NGX_QUIC_FT_STREAM2: | |
898 case NGX_QUIC_FT_STREAM3: | |
899 case NGX_QUIC_FT_STREAM4: | |
900 case NGX_QUIC_FT_STREAM5: | |
901 case NGX_QUIC_FT_STREAM6: | |
902 case NGX_QUIC_FT_STREAM7: | |
903 | |
904 f->u.stream.type = f->type; | |
905 | |
906 f->u.stream.off = ngx_quic_stream_bit_off(f->type); | |
907 f->u.stream.len = ngx_quic_stream_bit_len(f->type); | |
908 f->u.stream.fin = ngx_quic_stream_bit_fin(f->type); | |
909 | |
910 p = ngx_quic_parse_int(p, end, &f->u.stream.stream_id); | |
911 if (p == NULL) { | |
912 goto error; | |
913 } | |
914 | |
915 if (f->type & 0x04) { | |
916 p = ngx_quic_parse_int(p, end, &f->u.stream.offset); | |
917 if (p == NULL) { | |
918 goto error; | |
919 } | |
920 | |
921 } else { | |
922 f->u.stream.offset = 0; | |
923 } | |
924 | |
925 if (f->type & 0x02) { | |
926 p = ngx_quic_parse_int(p, end, &f->u.stream.length); | |
927 if (p == NULL) { | |
928 goto error; | |
929 } | |
930 | |
931 } else { | |
932 f->u.stream.length = end - p; /* up to packet end */ | |
933 } | |
934 | |
935 p = ngx_quic_read_bytes(p, end, f->u.stream.length, &b->pos); | |
936 if (p == NULL) { | |
937 goto error; | |
938 } | |
939 | |
940 b->last = p; | |
941 break; | |
942 | |
943 case NGX_QUIC_FT_MAX_DATA: | |
944 | |
945 p = ngx_quic_parse_int(p, end, &f->u.max_data.max_data); | |
946 if (p == NULL) { | |
947 goto error; | |
948 } | |
949 | |
950 break; | |
951 | |
952 case NGX_QUIC_FT_RESET_STREAM: | |
953 | |
954 if (!((p = ngx_quic_parse_int(p, end, &f->u.reset_stream.id)) | |
955 && (p = ngx_quic_parse_int(p, end, &f->u.reset_stream.error_code)) | |
956 && (p = ngx_quic_parse_int(p, end, | |
957 &f->u.reset_stream.final_size)))) | |
958 { | |
959 goto error; | |
960 } | |
961 | |
962 break; | |
963 | |
964 case NGX_QUIC_FT_STOP_SENDING: | |
965 | |
966 p = ngx_quic_parse_int(p, end, &f->u.stop_sending.id); | |
967 if (p == NULL) { | |
968 goto error; | |
969 } | |
970 | |
971 p = ngx_quic_parse_int(p, end, &f->u.stop_sending.error_code); | |
972 if (p == NULL) { | |
973 goto error; | |
974 } | |
975 | |
976 break; | |
977 | |
978 case NGX_QUIC_FT_STREAMS_BLOCKED: | |
979 case NGX_QUIC_FT_STREAMS_BLOCKED2: | |
980 | |
981 p = ngx_quic_parse_int(p, end, &f->u.streams_blocked.limit); | |
982 if (p == NULL) { | |
983 goto error; | |
984 } | |
985 | |
986 f->u.streams_blocked.bidi = | |
987 (f->type == NGX_QUIC_FT_STREAMS_BLOCKED) ? 1 : 0; | |
988 break; | |
989 | |
990 case NGX_QUIC_FT_MAX_STREAMS: | |
991 case NGX_QUIC_FT_MAX_STREAMS2: | |
992 | |
993 p = ngx_quic_parse_int(p, end, &f->u.max_streams.limit); | |
994 if (p == NULL) { | |
995 goto error; | |
996 } | |
997 | |
998 f->u.max_streams.bidi = (f->type == NGX_QUIC_FT_MAX_STREAMS) ? 1 : 0; | |
999 | |
1000 break; | |
1001 | |
1002 case NGX_QUIC_FT_MAX_STREAM_DATA: | |
1003 | |
1004 p = ngx_quic_parse_int(p, end, &f->u.max_stream_data.id); | |
1005 if (p == NULL) { | |
1006 goto error; | |
1007 } | |
1008 | |
1009 p = ngx_quic_parse_int(p, end, &f->u.max_stream_data.limit); | |
1010 if (p == NULL) { | |
1011 goto error; | |
1012 } | |
1013 | |
1014 break; | |
1015 | |
1016 case NGX_QUIC_FT_DATA_BLOCKED: | |
1017 | |
1018 p = ngx_quic_parse_int(p, end, &f->u.data_blocked.limit); | |
1019 if (p == NULL) { | |
1020 goto error; | |
1021 } | |
1022 | |
1023 break; | |
1024 | |
1025 case NGX_QUIC_FT_STREAM_DATA_BLOCKED: | |
1026 | |
1027 p = ngx_quic_parse_int(p, end, &f->u.stream_data_blocked.id); | |
1028 if (p == NULL) { | |
1029 goto error; | |
1030 } | |
1031 | |
1032 p = ngx_quic_parse_int(p, end, &f->u.stream_data_blocked.limit); | |
1033 if (p == NULL) { | |
1034 goto error; | |
1035 } | |
1036 | |
1037 break; | |
1038 | |
1039 case NGX_QUIC_FT_PATH_CHALLENGE: | |
1040 | |
1041 p = ngx_quic_copy_bytes(p, end, 8, f->u.path_challenge.data); | |
1042 if (p == NULL) { | |
1043 goto error; | |
1044 } | |
1045 | |
1046 break; | |
1047 | |
1048 case NGX_QUIC_FT_PATH_RESPONSE: | |
1049 | |
1050 p = ngx_quic_copy_bytes(p, end, 8, f->u.path_response.data); | |
1051 if (p == NULL) { | |
1052 goto error; | |
1053 } | |
1054 | |
1055 break; | |
1056 | |
1057 default: | |
1058 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, | |
1059 "quic unknown frame type 0x%xi", f->type); | |
1060 return NGX_ERROR; | |
1061 } | |
1062 | |
1063 f->level = pkt->level; | |
1064 | |
1065 return p - start; | |
1066 | |
1067 error: | |
1068 | |
1069 pkt->error = NGX_QUIC_ERR_FRAME_ENCODING_ERROR; | |
1070 | |
1071 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, | |
1072 "quic failed to parse frame type:0x%xi", f->type); | |
1073 | |
1074 return NGX_ERROR; | |
1075 } | |
1076 | |
1077 | |
1078 static ngx_int_t | |
1079 ngx_quic_frame_allowed(ngx_quic_header_t *pkt, ngx_uint_t frame_type) | |
1080 { | |
1081 uint8_t ptype; | |
1082 | |
1083 /* frame permissions per packet: 4 bits: IH01: 12.4, Table 3 */ | |
1084 static uint8_t ngx_quic_frame_masks[] = { | |
1085 /* PADDING */ 0xF, | |
1086 /* PING */ 0xF, | |
1087 /* ACK */ 0xD, | |
1088 /* ACK_ECN */ 0xD, | |
1089 /* RESET_STREAM */ 0x3, | |
1090 /* STOP_SENDING */ 0x3, | |
1091 /* CRYPTO */ 0xD, | |
1092 /* NEW_TOKEN */ 0x0, /* only sent by server */ | |
1093 /* STREAM0 */ 0x3, | |
1094 /* STREAM1 */ 0x3, | |
1095 /* STREAM2 */ 0x3, | |
1096 /* STREAM3 */ 0x3, | |
1097 /* STREAM4 */ 0x3, | |
1098 /* STREAM5 */ 0x3, | |
1099 /* STREAM6 */ 0x3, | |
1100 /* STREAM7 */ 0x3, | |
1101 /* MAX_DATA */ 0x3, | |
1102 /* MAX_STREAM_DATA */ 0x3, | |
1103 /* MAX_STREAMS */ 0x3, | |
1104 /* MAX_STREAMS2 */ 0x3, | |
1105 /* DATA_BLOCKED */ 0x3, | |
1106 /* STREAM_DATA_BLOCKED */ 0x3, | |
1107 /* STREAMS_BLOCKED */ 0x3, | |
1108 /* STREAMS_BLOCKED2 */ 0x3, | |
1109 /* NEW_CONNECTION_ID */ 0x3, | |
1110 /* RETIRE_CONNECTION_ID */ 0x3, | |
1111 /* PATH_CHALLENGE */ 0x3, | |
1112 /* PATH_RESPONSE */ 0x3, | |
1113 #if (NGX_QUIC_DRAFT_VERSION >= 28) | |
1114 /* CONNECTION_CLOSE */ 0xF, | |
1115 /* CONNECTION_CLOSE2 */ 0x3, | |
1116 #else | |
1117 /* CONNECTION_CLOSE */ 0xD, | |
1118 /* CONNECTION_CLOSE2 */ 0x1, | |
1119 #endif | |
1120 /* HANDSHAKE_DONE */ 0x0, /* only sent by server */ | |
1121 }; | |
1122 | |
1123 if (ngx_quic_long_pkt(pkt->flags)) { | |
1124 | |
1125 if (ngx_quic_pkt_in(pkt->flags)) { | |
1126 ptype = 8; /* initial */ | |
1127 | |
1128 } else if (ngx_quic_pkt_hs(pkt->flags)) { | |
1129 ptype = 4; /* handshake */ | |
1130 | |
1131 } else { | |
1132 ptype = 2; /* zero-rtt */ | |
1133 } | |
1134 | |
1135 } else { | |
1136 ptype = 1; /* application data */ | |
1137 } | |
1138 | |
1139 if (ptype & ngx_quic_frame_masks[frame_type]) { | |
1140 return NGX_OK; | |
1141 } | |
1142 | |
1143 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, | |
1144 "quic frame type 0x%xi is not " | |
1145 "allowed in packet with flags 0x%xd", | |
1146 frame_type, pkt->flags); | |
1147 | |
1148 return NGX_DECLINED; | |
1149 } | |
1150 | |
1151 | |
1152 ssize_t | |
1153 ngx_quic_parse_ack_range(ngx_log_t *log, u_char *start, u_char *end, | |
1154 uint64_t *gap, uint64_t *range) | |
1155 { | |
1156 u_char *p; | |
1157 | |
1158 p = start; | |
1159 | |
1160 p = ngx_quic_parse_int(p, end, gap); | |
1161 if (p == NULL) { | |
1162 ngx_log_error(NGX_LOG_INFO, log, 0, | |
1163 "quic failed to parse ack frame gap"); | |
1164 return NGX_ERROR; | |
1165 } | |
1166 | |
1167 p = ngx_quic_parse_int(p, end, range); | |
1168 if (p == NULL) { | |
1169 ngx_log_error(NGX_LOG_INFO, log, 0, | |
1170 "quic failed to parse ack frame range"); | |
1171 return NGX_ERROR; | |
1172 } | |
1173 | |
1174 return p - start; | |
1175 } | |
1176 | |
1177 | |
1178 size_t | |
1179 ngx_quic_create_ack_range(u_char *p, uint64_t gap, uint64_t range) | |
1180 { | |
1181 size_t len; | |
1182 u_char *start; | |
1183 | |
1184 if (p == NULL) { | |
1185 len = ngx_quic_varint_len(gap); | |
1186 len += ngx_quic_varint_len(range); | |
1187 return len; | |
1188 } | |
1189 | |
1190 start = p; | |
1191 | |
1192 ngx_quic_build_int(&p, gap); | |
1193 ngx_quic_build_int(&p, range); | |
1194 | |
1195 return p - start; | |
1196 } | |
1197 | |
1198 | |
1199 ssize_t | |
1200 ngx_quic_create_frame(u_char *p, ngx_quic_frame_t *f) | |
1201 { | |
1202 /* | |
1203 * QUIC-recovery, section 2: | |
1204 * | |
1205 * Ack-eliciting Frames: All frames other than ACK, PADDING, and | |
1206 * CONNECTION_CLOSE are considered ack-eliciting. | |
1207 */ | |
1208 f->need_ack = 1; | |
1209 | |
1210 switch (f->type) { | |
1211 case NGX_QUIC_FT_ACK: | |
1212 f->need_ack = 0; | |
1213 return ngx_quic_create_ack(p, &f->u.ack, f->data); | |
1214 | |
1215 case NGX_QUIC_FT_STOP_SENDING: | |
1216 return ngx_quic_create_stop_sending(p, &f->u.stop_sending); | |
1217 | |
1218 case NGX_QUIC_FT_CRYPTO: | |
1219 return ngx_quic_create_crypto(p, &f->u.crypto, f->data); | |
1220 | |
1221 case NGX_QUIC_FT_HANDSHAKE_DONE: | |
1222 return ngx_quic_create_hs_done(p); | |
1223 | |
1224 case NGX_QUIC_FT_NEW_TOKEN: | |
1225 return ngx_quic_create_new_token(p, &f->u.token); | |
1226 | |
1227 case NGX_QUIC_FT_STREAM0: | |
1228 case NGX_QUIC_FT_STREAM1: | |
1229 case NGX_QUIC_FT_STREAM2: | |
1230 case NGX_QUIC_FT_STREAM3: | |
1231 case NGX_QUIC_FT_STREAM4: | |
1232 case NGX_QUIC_FT_STREAM5: | |
1233 case NGX_QUIC_FT_STREAM6: | |
1234 case NGX_QUIC_FT_STREAM7: | |
1235 return ngx_quic_create_stream(p, &f->u.stream, f->data); | |
1236 | |
1237 case NGX_QUIC_FT_CONNECTION_CLOSE: | |
1238 case NGX_QUIC_FT_CONNECTION_CLOSE_APP: | |
1239 f->need_ack = 0; | |
1240 return ngx_quic_create_close(p, &f->u.close); | |
1241 | |
1242 case NGX_QUIC_FT_MAX_STREAMS: | |
1243 return ngx_quic_create_max_streams(p, &f->u.max_streams); | |
1244 | |
1245 case NGX_QUIC_FT_MAX_STREAM_DATA: | |
1246 return ngx_quic_create_max_stream_data(p, &f->u.max_stream_data); | |
1247 | |
1248 case NGX_QUIC_FT_MAX_DATA: | |
1249 return ngx_quic_create_max_data(p, &f->u.max_data); | |
1250 | |
1251 case NGX_QUIC_FT_PATH_RESPONSE: | |
1252 return ngx_quic_create_path_response(p, &f->u.path_response); | |
1253 | |
1254 case NGX_QUIC_FT_NEW_CONNECTION_ID: | |
1255 return ngx_quic_create_new_connection_id(p, &f->u.ncid); | |
1256 | |
1257 case NGX_QUIC_FT_RETIRE_CONNECTION_ID: | |
1258 return ngx_quic_create_retire_connection_id(p, &f->u.retire_cid); | |
1259 | |
1260 default: | |
1261 /* BUG: unsupported frame type generated */ | |
1262 return NGX_ERROR; | |
1263 } | |
1264 } | |
1265 | |
1266 | |
1267 static size_t | |
1268 ngx_quic_create_ack(u_char *p, ngx_quic_ack_frame_t *ack, ngx_chain_t *ranges) | |
1269 { | |
1270 size_t len; | |
1271 u_char *start; | |
1272 ngx_buf_t *b; | |
1273 | |
1274 if (p == NULL) { | |
1275 len = ngx_quic_varint_len(NGX_QUIC_FT_ACK); | |
1276 len += ngx_quic_varint_len(ack->largest); | |
1277 len += ngx_quic_varint_len(ack->delay); | |
1278 len += ngx_quic_varint_len(ack->range_count); | |
1279 len += ngx_quic_varint_len(ack->first_range); | |
1280 len += ack->ranges_length; | |
1281 | |
1282 return len; | |
1283 } | |
1284 | |
1285 start = p; | |
1286 | |
1287 ngx_quic_build_int(&p, NGX_QUIC_FT_ACK); | |
1288 ngx_quic_build_int(&p, ack->largest); | |
1289 ngx_quic_build_int(&p, ack->delay); | |
1290 ngx_quic_build_int(&p, ack->range_count); | |
1291 ngx_quic_build_int(&p, ack->first_range); | |
1292 | |
1293 while (ranges) { | |
1294 b = ranges->buf; | |
1295 p = ngx_cpymem(p, b->pos, b->last - b->pos); | |
1296 ranges = ranges->next; | |
1297 } | |
1298 | |
1299 return p - start; | |
1300 } | |
1301 | |
1302 | |
1303 static size_t | |
1304 ngx_quic_create_stop_sending(u_char *p, ngx_quic_stop_sending_frame_t *ss) | |
1305 { | |
1306 size_t len; | |
1307 u_char *start; | |
1308 | |
1309 if (p == NULL) { | |
1310 len = ngx_quic_varint_len(NGX_QUIC_FT_STOP_SENDING); | |
1311 len += ngx_quic_varint_len(ss->id); | |
1312 len += ngx_quic_varint_len(ss->error_code); | |
1313 return len; | |
1314 } | |
1315 | |
1316 start = p; | |
1317 | |
1318 ngx_quic_build_int(&p, NGX_QUIC_FT_STOP_SENDING); | |
1319 ngx_quic_build_int(&p, ss->id); | |
1320 ngx_quic_build_int(&p, ss->error_code); | |
1321 | |
1322 return p - start; | |
1323 } | |
1324 | |
1325 | |
1326 static size_t | |
1327 ngx_quic_create_crypto(u_char *p, ngx_quic_crypto_frame_t *crypto, | |
1328 ngx_chain_t *data) | |
1329 { | |
1330 size_t len; | |
1331 u_char *start; | |
1332 ngx_buf_t *b; | |
1333 | |
1334 if (p == NULL) { | |
1335 len = ngx_quic_varint_len(NGX_QUIC_FT_CRYPTO); | |
1336 len += ngx_quic_varint_len(crypto->offset); | |
1337 len += ngx_quic_varint_len(crypto->length); | |
1338 len += crypto->length; | |
1339 | |
1340 return len; | |
1341 } | |
1342 | |
1343 start = p; | |
1344 | |
1345 ngx_quic_build_int(&p, NGX_QUIC_FT_CRYPTO); | |
1346 ngx_quic_build_int(&p, crypto->offset); | |
1347 ngx_quic_build_int(&p, crypto->length); | |
1348 | |
1349 while (data) { | |
1350 b = data->buf; | |
1351 p = ngx_cpymem(p, b->pos, b->last - b->pos); | |
1352 data = data->next; | |
1353 } | |
1354 | |
1355 return p - start; | |
1356 } | |
1357 | |
1358 | |
1359 static size_t | |
1360 ngx_quic_create_hs_done(u_char *p) | |
1361 { | |
1362 u_char *start; | |
1363 | |
1364 if (p == NULL) { | |
1365 return ngx_quic_varint_len(NGX_QUIC_FT_HANDSHAKE_DONE); | |
1366 } | |
1367 | |
1368 start = p; | |
1369 | |
1370 ngx_quic_build_int(&p, NGX_QUIC_FT_HANDSHAKE_DONE); | |
1371 | |
1372 return p - start; | |
1373 } | |
1374 | |
1375 | |
1376 static size_t | |
1377 ngx_quic_create_new_token(u_char *p, ngx_quic_new_token_frame_t *token) | |
1378 { | |
1379 size_t len; | |
1380 u_char *start; | |
1381 | |
1382 if (p == NULL) { | |
1383 len = ngx_quic_varint_len(NGX_QUIC_FT_NEW_TOKEN); | |
1384 len += ngx_quic_varint_len(token->length); | |
1385 len += token->length; | |
1386 | |
1387 return len; | |
1388 } | |
1389 | |
1390 start = p; | |
1391 | |
1392 ngx_quic_build_int(&p, NGX_QUIC_FT_NEW_TOKEN); | |
1393 ngx_quic_build_int(&p, token->length); | |
1394 p = ngx_cpymem(p, token->data, token->length); | |
1395 | |
1396 return p - start; | |
1397 } | |
1398 | |
1399 | |
1400 static size_t | |
1401 ngx_quic_create_stream(u_char *p, ngx_quic_stream_frame_t *sf, | |
1402 ngx_chain_t *data) | |
1403 { | |
1404 size_t len; | |
1405 u_char *start; | |
1406 ngx_buf_t *b; | |
1407 | |
1408 if (p == NULL) { | |
1409 len = ngx_quic_varint_len(sf->type); | |
1410 | |
1411 if (sf->off) { | |
1412 len += ngx_quic_varint_len(sf->offset); | |
1413 } | |
1414 | |
1415 len += ngx_quic_varint_len(sf->stream_id); | |
1416 | |
1417 /* length is always present in generated frames */ | |
1418 len += ngx_quic_varint_len(sf->length); | |
1419 | |
1420 len += sf->length; | |
1421 | |
1422 return len; | |
1423 } | |
1424 | |
1425 start = p; | |
1426 | |
1427 ngx_quic_build_int(&p, sf->type); | |
1428 ngx_quic_build_int(&p, sf->stream_id); | |
1429 | |
1430 if (sf->off) { | |
1431 ngx_quic_build_int(&p, sf->offset); | |
1432 } | |
1433 | |
1434 /* length is always present in generated frames */ | |
1435 ngx_quic_build_int(&p, sf->length); | |
1436 | |
1437 while (data) { | |
1438 b = data->buf; | |
1439 p = ngx_cpymem(p, b->pos, b->last - b->pos); | |
1440 data = data->next; | |
1441 } | |
1442 | |
1443 return p - start; | |
1444 } | |
1445 | |
1446 | |
1447 static size_t | |
1448 ngx_quic_create_max_streams(u_char *p, ngx_quic_max_streams_frame_t *ms) | |
1449 { | |
1450 size_t len; | |
1451 u_char *start; | |
1452 ngx_uint_t type; | |
1453 | |
1454 type = ms->bidi ? NGX_QUIC_FT_MAX_STREAMS : NGX_QUIC_FT_MAX_STREAMS2; | |
1455 | |
1456 if (p == NULL) { | |
1457 len = ngx_quic_varint_len(type); | |
1458 len += ngx_quic_varint_len(ms->limit); | |
1459 return len; | |
1460 } | |
1461 | |
1462 start = p; | |
1463 | |
1464 ngx_quic_build_int(&p, type); | |
1465 ngx_quic_build_int(&p, ms->limit); | |
1466 | |
1467 return p - start; | |
1468 } | |
1469 | |
1470 | |
1471 static ngx_int_t | |
1472 ngx_quic_parse_transport_param(u_char *p, u_char *end, uint16_t id, | |
1473 ngx_quic_tp_t *dst) | |
1474 { | |
1475 uint64_t varint; | |
1476 ngx_str_t str; | |
1477 | |
1478 varint = 0; | |
1479 ngx_str_null(&str); | |
1480 | |
1481 switch (id) { | |
1482 | |
1483 case NGX_QUIC_TP_DISABLE_ACTIVE_MIGRATION: | |
1484 /* zero-length option */ | |
1485 if (end - p != 0) { | |
1486 return NGX_ERROR; | |
1487 } | |
1488 dst->disable_active_migration = 1; | |
1489 return NGX_OK; | |
1490 | |
1491 case NGX_QUIC_TP_MAX_IDLE_TIMEOUT: | |
1492 case NGX_QUIC_TP_MAX_UDP_PAYLOAD_SIZE: | |
1493 case NGX_QUIC_TP_INITIAL_MAX_DATA: | |
1494 case NGX_QUIC_TP_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL: | |
1495 case NGX_QUIC_TP_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE: | |
1496 case NGX_QUIC_TP_INITIAL_MAX_STREAM_DATA_UNI: | |
1497 case NGX_QUIC_TP_INITIAL_MAX_STREAMS_BIDI: | |
1498 case NGX_QUIC_TP_INITIAL_MAX_STREAMS_UNI: | |
1499 case NGX_QUIC_TP_ACK_DELAY_EXPONENT: | |
1500 case NGX_QUIC_TP_MAX_ACK_DELAY: | |
1501 case NGX_QUIC_TP_ACTIVE_CONNECTION_ID_LIMIT: | |
1502 | |
1503 p = ngx_quic_parse_int(p, end, &varint); | |
1504 if (p == NULL) { | |
1505 return NGX_ERROR; | |
1506 } | |
1507 break; | |
1508 | |
1509 case NGX_QUIC_TP_INITIAL_SCID: | |
1510 | |
1511 str.len = end - p; | |
1512 str.data = p; | |
1513 break; | |
1514 | |
1515 default: | |
1516 return NGX_DECLINED; | |
1517 } | |
1518 | |
1519 switch (id) { | |
1520 | |
1521 case NGX_QUIC_TP_MAX_IDLE_TIMEOUT: | |
1522 dst->max_idle_timeout = varint; | |
1523 break; | |
1524 | |
1525 case NGX_QUIC_TP_MAX_UDP_PAYLOAD_SIZE: | |
1526 dst->max_udp_payload_size = varint; | |
1527 break; | |
1528 | |
1529 case NGX_QUIC_TP_INITIAL_MAX_DATA: | |
1530 dst->initial_max_data = varint; | |
1531 break; | |
1532 | |
1533 case NGX_QUIC_TP_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL: | |
1534 dst->initial_max_stream_data_bidi_local = varint; | |
1535 break; | |
1536 | |
1537 case NGX_QUIC_TP_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE: | |
1538 dst->initial_max_stream_data_bidi_remote = varint; | |
1539 break; | |
1540 | |
1541 case NGX_QUIC_TP_INITIAL_MAX_STREAM_DATA_UNI: | |
1542 dst->initial_max_stream_data_uni = varint; | |
1543 break; | |
1544 | |
1545 case NGX_QUIC_TP_INITIAL_MAX_STREAMS_BIDI: | |
1546 dst->initial_max_streams_bidi = varint; | |
1547 break; | |
1548 | |
1549 case NGX_QUIC_TP_INITIAL_MAX_STREAMS_UNI: | |
1550 dst->initial_max_streams_uni = varint; | |
1551 break; | |
1552 | |
1553 case NGX_QUIC_TP_ACK_DELAY_EXPONENT: | |
1554 dst->ack_delay_exponent = varint; | |
1555 break; | |
1556 | |
1557 case NGX_QUIC_TP_MAX_ACK_DELAY: | |
1558 dst->max_ack_delay = varint; | |
1559 break; | |
1560 | |
1561 case NGX_QUIC_TP_ACTIVE_CONNECTION_ID_LIMIT: | |
1562 dst->active_connection_id_limit = varint; | |
1563 break; | |
1564 | |
1565 case NGX_QUIC_TP_INITIAL_SCID: | |
1566 dst->initial_scid = str; | |
1567 break; | |
1568 | |
1569 default: | |
1570 return NGX_ERROR; | |
1571 } | |
1572 | |
1573 return NGX_OK; | |
1574 } | |
1575 | |
1576 | |
1577 ngx_int_t | |
1578 ngx_quic_parse_transport_params(u_char *p, u_char *end, ngx_quic_tp_t *tp, | |
1579 ngx_log_t *log) | |
1580 { | |
1581 uint64_t id, len; | |
1582 ngx_int_t rc; | |
1583 | |
1584 while (p < end) { | |
1585 p = ngx_quic_parse_int(p, end, &id); | |
1586 if (p == NULL) { | |
1587 ngx_log_error(NGX_LOG_INFO, log, 0, | |
1588 "quic failed to parse transport param id"); | |
1589 return NGX_ERROR; | |
1590 } | |
1591 | |
1592 switch (id) { | |
1593 case NGX_QUIC_TP_ORIGINAL_DCID: | |
1594 case NGX_QUIC_TP_PREFERRED_ADDRESS: | |
1595 case NGX_QUIC_TP_RETRY_SCID: | |
1596 case NGX_QUIC_TP_SR_TOKEN: | |
1597 ngx_log_error(NGX_LOG_INFO, log, 0, | |
1598 "quic client sent forbidden transport param" | |
1599 " id:0x%xL", id); | |
1600 return NGX_ERROR; | |
1601 } | |
1602 | |
1603 p = ngx_quic_parse_int(p, end, &len); | |
1604 if (p == NULL) { | |
1605 ngx_log_error(NGX_LOG_INFO, log, 0, | |
1606 "quic failed to parse" | |
1607 " transport param id:0x%xL length", id); | |
1608 return NGX_ERROR; | |
1609 } | |
1610 | |
1611 rc = ngx_quic_parse_transport_param(p, p + len, id, tp); | |
1612 | |
1613 if (rc == NGX_ERROR) { | |
1614 ngx_log_error(NGX_LOG_INFO, log, 0, | |
1615 "quic failed to parse" | |
1616 " transport param id:0x%xL data", id); | |
1617 return NGX_ERROR; | |
1618 } | |
1619 | |
1620 if (rc == NGX_DECLINED) { | |
1621 ngx_log_error(NGX_LOG_INFO, log, 0, | |
1622 "quic unknown transport param id:0x%xL, skipped", id); | |
1623 } | |
1624 | |
1625 p += len; | |
1626 } | |
1627 | |
1628 if (p != end) { | |
1629 ngx_log_error(NGX_LOG_INFO, log, 0, | |
1630 "quic trailing garbage in" | |
1631 " transport parameters: bytes:%ui", | |
1632 end - p); | |
1633 return NGX_ERROR; | |
1634 } | |
1635 | |
1636 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, log, 0, | |
1637 "quic transport parameters parsed ok"); | |
1638 | |
1639 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0, | |
1640 "quic tp disable active migration: %ui", | |
1641 tp->disable_active_migration); | |
1642 | |
1643 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0, "quic tp idle_timeout:%ui", | |
1644 tp->max_idle_timeout); | |
1645 | |
1646 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0, | |
1647 "quic tp max_udp_payload_size:%ui", | |
1648 tp->max_udp_payload_size); | |
1649 | |
1650 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0, "quic tp max_data:%ui", | |
1651 tp->initial_max_data); | |
1652 | |
1653 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0, | |
1654 "quic tp max_stream_data_bidi_local:%ui", | |
1655 tp->initial_max_stream_data_bidi_local); | |
1656 | |
1657 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0, | |
1658 "quic tp max_stream_data_bidi_remote:%ui", | |
1659 tp->initial_max_stream_data_bidi_remote); | |
1660 | |
1661 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0, | |
1662 "quic tp max_stream_data_uni:%ui", | |
1663 tp->initial_max_stream_data_uni); | |
1664 | |
1665 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0, | |
1666 "quic tp initial_max_streams_bidi:%ui", | |
1667 tp->initial_max_streams_bidi); | |
1668 | |
1669 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0, | |
1670 "quic tp initial_max_streams_uni:%ui", | |
1671 tp->initial_max_streams_uni); | |
1672 | |
1673 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0, | |
1674 "quic tp ack_delay_exponent:%ui", | |
1675 tp->ack_delay_exponent); | |
1676 | |
1677 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0, "quic tp max_ack_delay:%ui", | |
1678 tp->max_ack_delay); | |
1679 | |
1680 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0, | |
1681 "quic tp active_connection_id_limit:%ui", | |
1682 tp->active_connection_id_limit); | |
1683 | |
1684 #if (NGX_QUIC_DRAFT_VERSION >= 28) | |
1685 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0, | |
1686 "quic tp initial source_connection_id len:%uz %xV", | |
1687 tp->initial_scid.len, &tp->initial_scid); | |
1688 #endif | |
1689 | |
1690 return NGX_OK; | |
1691 } | |
1692 | |
1693 | |
1694 static size_t | |
1695 ngx_quic_create_max_stream_data(u_char *p, ngx_quic_max_stream_data_frame_t *ms) | |
1696 { | |
1697 size_t len; | |
1698 u_char *start; | |
1699 | |
1700 if (p == NULL) { | |
1701 len = ngx_quic_varint_len(NGX_QUIC_FT_MAX_STREAM_DATA); | |
1702 len += ngx_quic_varint_len(ms->id); | |
1703 len += ngx_quic_varint_len(ms->limit); | |
1704 return len; | |
1705 } | |
1706 | |
1707 start = p; | |
1708 | |
1709 ngx_quic_build_int(&p, NGX_QUIC_FT_MAX_STREAM_DATA); | |
1710 ngx_quic_build_int(&p, ms->id); | |
1711 ngx_quic_build_int(&p, ms->limit); | |
1712 | |
1713 return p - start; | |
1714 } | |
1715 | |
1716 | |
1717 static size_t | |
1718 ngx_quic_create_max_data(u_char *p, ngx_quic_max_data_frame_t *md) | |
1719 { | |
1720 size_t len; | |
1721 u_char *start; | |
1722 | |
1723 if (p == NULL) { | |
1724 len = ngx_quic_varint_len(NGX_QUIC_FT_MAX_DATA); | |
1725 len += ngx_quic_varint_len(md->max_data); | |
1726 return len; | |
1727 } | |
1728 | |
1729 start = p; | |
1730 | |
1731 ngx_quic_build_int(&p, NGX_QUIC_FT_MAX_DATA); | |
1732 ngx_quic_build_int(&p, md->max_data); | |
1733 | |
1734 return p - start; | |
1735 } | |
1736 | |
1737 | |
1738 static size_t | |
1739 ngx_quic_create_path_response(u_char *p, ngx_quic_path_challenge_frame_t *pc) | |
1740 { | |
1741 size_t len; | |
1742 u_char *start; | |
1743 | |
1744 if (p == NULL) { | |
1745 len = ngx_quic_varint_len(NGX_QUIC_FT_PATH_RESPONSE); | |
1746 len += sizeof(pc->data); | |
1747 return len; | |
1748 } | |
1749 | |
1750 start = p; | |
1751 | |
1752 ngx_quic_build_int(&p, NGX_QUIC_FT_PATH_RESPONSE); | |
1753 p = ngx_cpymem(p, &pc->data, sizeof(pc->data)); | |
1754 | |
1755 return p - start; | |
1756 } | |
1757 | |
1758 | |
1759 static size_t | |
1760 ngx_quic_create_new_connection_id(u_char *p, ngx_quic_new_conn_id_frame_t *ncid) | |
1761 { | |
1762 size_t len; | |
1763 u_char *start; | |
1764 | |
1765 if (p == NULL) { | |
1766 len = ngx_quic_varint_len(NGX_QUIC_FT_NEW_CONNECTION_ID); | |
1767 len += ngx_quic_varint_len(ncid->seqnum); | |
1768 len += ngx_quic_varint_len(ncid->retire); | |
1769 len++; | |
1770 len += ncid->len; | |
1771 len += NGX_QUIC_SR_TOKEN_LEN; | |
1772 return len; | |
1773 } | |
1774 | |
1775 start = p; | |
1776 | |
1777 ngx_quic_build_int(&p, NGX_QUIC_FT_NEW_CONNECTION_ID); | |
1778 ngx_quic_build_int(&p, ncid->seqnum); | |
1779 ngx_quic_build_int(&p, ncid->retire); | |
1780 *p++ = ncid->len; | |
1781 p = ngx_cpymem(p, ncid->cid, ncid->len); | |
1782 p = ngx_cpymem(p, ncid->srt, NGX_QUIC_SR_TOKEN_LEN); | |
1783 | |
1784 return p - start; | |
1785 } | |
1786 | |
1787 | |
1788 static size_t | |
1789 ngx_quic_create_retire_connection_id(u_char *p, | |
1790 ngx_quic_retire_cid_frame_t *rcid) | |
1791 { | |
1792 size_t len; | |
1793 u_char *start; | |
1794 | |
1795 if (p == NULL) { | |
1796 len = ngx_quic_varint_len(NGX_QUIC_FT_RETIRE_CONNECTION_ID); | |
1797 len += ngx_quic_varint_len(rcid->sequence_number); | |
1798 return len; | |
1799 } | |
1800 | |
1801 start = p; | |
1802 | |
1803 ngx_quic_build_int(&p, NGX_QUIC_FT_RETIRE_CONNECTION_ID); | |
1804 ngx_quic_build_int(&p, rcid->sequence_number); | |
1805 | |
1806 return p - start; | |
1807 } | |
1808 | |
1809 | |
1810 ssize_t | |
1811 ngx_quic_create_transport_params(u_char *pos, u_char *end, ngx_quic_tp_t *tp, | |
1812 size_t *clen) | |
1813 { | |
1814 u_char *p; | |
1815 size_t len; | |
1816 | |
1817 #define ngx_quic_tp_len(id, value) \ | |
1818 ngx_quic_varint_len(id) \ | |
1819 + ngx_quic_varint_len(value) \ | |
1820 + ngx_quic_varint_len(ngx_quic_varint_len(value)) | |
1821 | |
1822 #define ngx_quic_tp_vint(id, value) \ | |
1823 do { \ | |
1824 ngx_quic_build_int(&p, id); \ | |
1825 ngx_quic_build_int(&p, ngx_quic_varint_len(value)); \ | |
1826 ngx_quic_build_int(&p, value); \ | |
1827 } while (0) | |
1828 | |
1829 #define ngx_quic_tp_strlen(id, value) \ | |
1830 ngx_quic_varint_len(id) \ | |
1831 + ngx_quic_varint_len(value.len) \ | |
1832 + value.len | |
1833 | |
1834 #define ngx_quic_tp_str(id, value) \ | |
1835 do { \ | |
1836 ngx_quic_build_int(&p, id); \ | |
1837 ngx_quic_build_int(&p, value.len); \ | |
1838 p = ngx_cpymem(p, value.data, value.len); \ | |
1839 } while (0) | |
1840 | |
1841 p = pos; | |
1842 | |
1843 len = ngx_quic_tp_len(NGX_QUIC_TP_INITIAL_MAX_DATA, tp->initial_max_data); | |
1844 | |
1845 len += ngx_quic_tp_len(NGX_QUIC_TP_INITIAL_MAX_STREAMS_UNI, | |
1846 tp->initial_max_streams_uni); | |
1847 | |
1848 len += ngx_quic_tp_len(NGX_QUIC_TP_INITIAL_MAX_STREAMS_BIDI, | |
1849 tp->initial_max_streams_bidi); | |
1850 | |
1851 len += ngx_quic_tp_len(NGX_QUIC_TP_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL, | |
1852 tp->initial_max_stream_data_bidi_local); | |
1853 | |
1854 len += ngx_quic_tp_len(NGX_QUIC_TP_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE, | |
1855 tp->initial_max_stream_data_bidi_remote); | |
1856 | |
1857 len += ngx_quic_tp_len(NGX_QUIC_TP_INITIAL_MAX_STREAM_DATA_UNI, | |
1858 tp->initial_max_stream_data_uni); | |
1859 | |
1860 len += ngx_quic_tp_len(NGX_QUIC_TP_MAX_IDLE_TIMEOUT, | |
1861 tp->max_idle_timeout); | |
1862 | |
1863 if (clen) { | |
1864 *clen = len; | |
1865 } | |
1866 | |
1867 if (tp->disable_active_migration) { | |
1868 len += ngx_quic_varint_len(NGX_QUIC_TP_DISABLE_ACTIVE_MIGRATION); | |
1869 len += ngx_quic_varint_len(0); | |
1870 } | |
1871 | |
1872 len += ngx_quic_tp_len(NGX_QUIC_TP_ACTIVE_CONNECTION_ID_LIMIT, | |
1873 tp->active_connection_id_limit); | |
1874 | |
1875 #if (NGX_QUIC_DRAFT_VERSION >= 28) | |
1876 len += ngx_quic_tp_strlen(NGX_QUIC_TP_ORIGINAL_DCID, tp->original_dcid); | |
1877 len += ngx_quic_tp_strlen(NGX_QUIC_TP_INITIAL_SCID, tp->initial_scid); | |
1878 | |
1879 if (tp->retry_scid.len) { | |
1880 len += ngx_quic_tp_strlen(NGX_QUIC_TP_RETRY_SCID, tp->retry_scid); | |
1881 } | |
1882 #else | |
1883 if (tp->original_dcid.len) { | |
1884 len += ngx_quic_tp_strlen(NGX_QUIC_TP_ORIGINAL_DCID, tp->original_dcid); | |
1885 } | |
1886 #endif | |
1887 | |
1888 len += ngx_quic_varint_len(NGX_QUIC_TP_SR_TOKEN); | |
1889 len += ngx_quic_varint_len(NGX_QUIC_SR_TOKEN_LEN); | |
1890 len += NGX_QUIC_SR_TOKEN_LEN; | |
1891 | |
1892 if (pos == NULL) { | |
1893 return len; | |
1894 } | |
1895 | |
1896 ngx_quic_tp_vint(NGX_QUIC_TP_INITIAL_MAX_DATA, | |
1897 tp->initial_max_data); | |
1898 | |
1899 ngx_quic_tp_vint(NGX_QUIC_TP_INITIAL_MAX_STREAMS_UNI, | |
1900 tp->initial_max_streams_uni); | |
1901 | |
1902 ngx_quic_tp_vint(NGX_QUIC_TP_INITIAL_MAX_STREAMS_BIDI, | |
1903 tp->initial_max_streams_bidi); | |
1904 | |
1905 ngx_quic_tp_vint(NGX_QUIC_TP_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL, | |
1906 tp->initial_max_stream_data_bidi_local); | |
1907 | |
1908 ngx_quic_tp_vint(NGX_QUIC_TP_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE, | |
1909 tp->initial_max_stream_data_bidi_remote); | |
1910 | |
1911 ngx_quic_tp_vint(NGX_QUIC_TP_INITIAL_MAX_STREAM_DATA_UNI, | |
1912 tp->initial_max_stream_data_uni); | |
1913 | |
1914 ngx_quic_tp_vint(NGX_QUIC_TP_MAX_IDLE_TIMEOUT, | |
1915 tp->max_idle_timeout); | |
1916 | |
1917 if (tp->disable_active_migration) { | |
1918 ngx_quic_build_int(&p, NGX_QUIC_TP_DISABLE_ACTIVE_MIGRATION); | |
1919 ngx_quic_build_int(&p, 0); | |
1920 } | |
1921 | |
1922 ngx_quic_tp_vint(NGX_QUIC_TP_ACTIVE_CONNECTION_ID_LIMIT, | |
1923 tp->active_connection_id_limit); | |
1924 | |
1925 #if (NGX_QUIC_DRAFT_VERSION >= 28) | |
1926 ngx_quic_tp_str(NGX_QUIC_TP_ORIGINAL_DCID, tp->original_dcid); | |
1927 ngx_quic_tp_str(NGX_QUIC_TP_INITIAL_SCID, tp->initial_scid); | |
1928 | |
1929 if (tp->retry_scid.len) { | |
1930 ngx_quic_tp_str(NGX_QUIC_TP_RETRY_SCID, tp->retry_scid); | |
1931 } | |
1932 #else | |
1933 if (tp->original_dcid.len) { | |
1934 ngx_quic_tp_str(NGX_QUIC_TP_ORIGINAL_DCID, tp->original_dcid); | |
1935 } | |
1936 #endif | |
1937 | |
1938 ngx_quic_build_int(&p, NGX_QUIC_TP_SR_TOKEN); | |
1939 ngx_quic_build_int(&p, NGX_QUIC_SR_TOKEN_LEN); | |
1940 p = ngx_cpymem(p, tp->sr_token, NGX_QUIC_SR_TOKEN_LEN); | |
1941 | |
1942 return p - pos; | |
1943 } | |
1944 | |
1945 | |
1946 static size_t | |
1947 ngx_quic_create_close(u_char *p, ngx_quic_close_frame_t *cl) | |
1948 { | |
1949 size_t len; | |
1950 u_char *start; | |
1951 ngx_uint_t type; | |
1952 | |
1953 type = cl->app ? NGX_QUIC_FT_CONNECTION_CLOSE_APP | |
1954 : NGX_QUIC_FT_CONNECTION_CLOSE; | |
1955 | |
1956 if (p == NULL) { | |
1957 len = ngx_quic_varint_len(type); | |
1958 len += ngx_quic_varint_len(cl->error_code); | |
1959 | |
1960 if (!cl->app) { | |
1961 len += ngx_quic_varint_len(cl->frame_type); | |
1962 } | |
1963 | |
1964 len += ngx_quic_varint_len(cl->reason.len); | |
1965 len += cl->reason.len; | |
1966 | |
1967 return len; | |
1968 } | |
1969 | |
1970 start = p; | |
1971 | |
1972 ngx_quic_build_int(&p, type); | |
1973 ngx_quic_build_int(&p, cl->error_code); | |
1974 | |
1975 if (!cl->app) { | |
1976 ngx_quic_build_int(&p, cl->frame_type); | |
1977 } | |
1978 | |
1979 ngx_quic_build_int(&p, cl->reason.len); | |
1980 p = ngx_cpymem(p, cl->reason.data, cl->reason.len); | |
1981 | |
1982 return p - start; | |
1983 } |