Mercurial > hg > nginx
comparison src/event/quic/ngx_event_quic_frames.c @ 8749:660c4a2f95f3 quic
QUIC: separate files for frames related processing.
author | Vladimir Homutov <vl@nginx.com> |
---|---|
date | Tue, 13 Apr 2021 14:38:46 +0300 |
parents | |
children | 46161c610919 |
comparison
equal
deleted
inserted
replaced
8748:e0cb1e58ca13 | 8749:660c4a2f95f3 |
---|---|
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_connection.h> | |
11 | |
12 | |
13 #define NGX_QUIC_BUFFER_SIZE 4096 | |
14 | |
15 | |
16 static void ngx_quic_free_bufs(ngx_connection_t *c, ngx_chain_t *in); | |
17 static ngx_chain_t *ngx_quic_split_bufs(ngx_connection_t *c, ngx_chain_t *in, | |
18 size_t len); | |
19 | |
20 static ngx_int_t ngx_quic_buffer_frame(ngx_connection_t *c, | |
21 ngx_quic_frames_stream_t *stream, ngx_quic_frame_t *f); | |
22 static ngx_int_t ngx_quic_adjust_frame_offset(ngx_connection_t *c, | |
23 ngx_quic_frame_t *f, uint64_t offset_in); | |
24 | |
25 | |
26 ngx_quic_frame_t * | |
27 ngx_quic_alloc_frame(ngx_connection_t *c) | |
28 { | |
29 ngx_queue_t *q; | |
30 ngx_quic_frame_t *frame; | |
31 ngx_quic_connection_t *qc; | |
32 | |
33 qc = ngx_quic_get_connection(c); | |
34 | |
35 if (!ngx_queue_empty(&qc->free_frames)) { | |
36 | |
37 q = ngx_queue_head(&qc->free_frames); | |
38 frame = ngx_queue_data(q, ngx_quic_frame_t, queue); | |
39 | |
40 ngx_queue_remove(&frame->queue); | |
41 | |
42 #ifdef NGX_QUIC_DEBUG_ALLOC | |
43 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
44 "quic reuse frame n:%ui", qc->nframes); | |
45 #endif | |
46 | |
47 } else { | |
48 frame = ngx_pcalloc(c->pool, sizeof(ngx_quic_frame_t)); | |
49 if (frame == NULL) { | |
50 return NULL; | |
51 } | |
52 | |
53 #ifdef NGX_QUIC_DEBUG_ALLOC | |
54 ++qc->nframes; | |
55 | |
56 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
57 "quic alloc frame n:%ui", qc->nframes); | |
58 #endif | |
59 } | |
60 | |
61 ngx_memzero(frame, sizeof(ngx_quic_frame_t)); | |
62 | |
63 return frame; | |
64 } | |
65 | |
66 | |
67 void | |
68 ngx_quic_free_frame(ngx_connection_t *c, ngx_quic_frame_t *frame) | |
69 { | |
70 ngx_quic_connection_t *qc; | |
71 | |
72 qc = ngx_quic_get_connection(c); | |
73 | |
74 if (frame->data) { | |
75 ngx_quic_free_bufs(c, frame->data); | |
76 } | |
77 | |
78 ngx_queue_insert_head(&qc->free_frames, &frame->queue); | |
79 | |
80 #ifdef NGX_QUIC_DEBUG_ALLOC | |
81 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
82 "quic free frame n:%ui", qc->nframes); | |
83 #endif | |
84 } | |
85 | |
86 | |
87 static void | |
88 ngx_quic_free_bufs(ngx_connection_t *c, ngx_chain_t *in) | |
89 { | |
90 ngx_buf_t *b, *shadow; | |
91 ngx_chain_t *cl; | |
92 ngx_quic_connection_t *qc; | |
93 | |
94 qc = ngx_quic_get_connection(c); | |
95 | |
96 while (in) { | |
97 #ifdef NGX_QUIC_DEBUG_ALLOC | |
98 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
99 "quic free buffer n:%ui", qc->nbufs); | |
100 #endif | |
101 | |
102 cl = in; | |
103 in = in->next; | |
104 b = cl->buf; | |
105 | |
106 if (b->shadow) { | |
107 if (!b->last_shadow) { | |
108 b->recycled = 1; | |
109 ngx_free_chain(c->pool, cl); | |
110 continue; | |
111 } | |
112 | |
113 do { | |
114 shadow = b->shadow; | |
115 b->shadow = qc->free_shadow_bufs; | |
116 qc->free_shadow_bufs = b; | |
117 b = shadow; | |
118 } while (b->recycled); | |
119 | |
120 if (b->shadow) { | |
121 b->last_shadow = 1; | |
122 ngx_free_chain(c->pool, cl); | |
123 continue; | |
124 } | |
125 | |
126 cl->buf = b; | |
127 } | |
128 | |
129 cl->next = qc->free_bufs; | |
130 qc->free_bufs = cl; | |
131 } | |
132 } | |
133 | |
134 | |
135 void | |
136 ngx_quic_free_frames(ngx_connection_t *c, ngx_queue_t *frames) | |
137 { | |
138 ngx_queue_t *q; | |
139 ngx_quic_frame_t *f; | |
140 | |
141 do { | |
142 q = ngx_queue_head(frames); | |
143 | |
144 if (q == ngx_queue_sentinel(frames)) { | |
145 break; | |
146 } | |
147 | |
148 ngx_queue_remove(q); | |
149 | |
150 f = ngx_queue_data(q, ngx_quic_frame_t, queue); | |
151 | |
152 ngx_quic_free_frame(c, f); | |
153 } while (1); | |
154 } | |
155 | |
156 | |
157 void | |
158 ngx_quic_queue_frame(ngx_quic_connection_t *qc, ngx_quic_frame_t *frame) | |
159 { | |
160 ngx_quic_send_ctx_t *ctx; | |
161 | |
162 ctx = ngx_quic_get_send_ctx(qc, frame->level); | |
163 | |
164 ngx_queue_insert_tail(&ctx->frames, &frame->queue); | |
165 | |
166 frame->len = ngx_quic_create_frame(NULL, frame); | |
167 /* always succeeds */ | |
168 | |
169 if (qc->closing) { | |
170 return; | |
171 } | |
172 | |
173 ngx_post_event(&qc->push, &ngx_posted_events); | |
174 } | |
175 | |
176 | |
177 ngx_int_t | |
178 ngx_quic_split_frame(ngx_connection_t *c, ngx_quic_frame_t *f, size_t len) | |
179 { | |
180 size_t shrink; | |
181 ngx_quic_frame_t *nf; | |
182 ngx_quic_ordered_frame_t *of, *onf; | |
183 | |
184 switch (f->type) { | |
185 case NGX_QUIC_FT_CRYPTO: | |
186 case NGX_QUIC_FT_STREAM0: | |
187 case NGX_QUIC_FT_STREAM1: | |
188 case NGX_QUIC_FT_STREAM2: | |
189 case NGX_QUIC_FT_STREAM3: | |
190 case NGX_QUIC_FT_STREAM4: | |
191 case NGX_QUIC_FT_STREAM5: | |
192 case NGX_QUIC_FT_STREAM6: | |
193 case NGX_QUIC_FT_STREAM7: | |
194 break; | |
195 | |
196 default: | |
197 return NGX_DECLINED; | |
198 } | |
199 | |
200 if ((size_t) f->len <= len) { | |
201 return NGX_OK; | |
202 } | |
203 | |
204 shrink = f->len - len; | |
205 | |
206 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
207 "quic split frame now:%uz need:%uz shrink:%uz", | |
208 f->len, len, shrink); | |
209 | |
210 of = &f->u.ord; | |
211 | |
212 if (of->length <= shrink) { | |
213 return NGX_DECLINED; | |
214 } | |
215 | |
216 of->length -= shrink; | |
217 f->len = ngx_quic_create_frame(NULL, f); | |
218 | |
219 if ((size_t) f->len > len) { | |
220 ngx_log_error(NGX_LOG_ERR, c->log, 0, "could not split QUIC frame"); | |
221 return NGX_ERROR; | |
222 } | |
223 | |
224 nf = ngx_quic_alloc_frame(c); | |
225 if (nf == NULL) { | |
226 return NGX_ERROR; | |
227 } | |
228 | |
229 *nf = *f; | |
230 onf = &nf->u.ord; | |
231 onf->offset += of->length; | |
232 onf->length = shrink; | |
233 nf->len = ngx_quic_create_frame(NULL, nf); | |
234 | |
235 nf->data = ngx_quic_split_bufs(c, f->data, of->length); | |
236 if (nf->data == NGX_CHAIN_ERROR) { | |
237 return NGX_ERROR; | |
238 } | |
239 | |
240 ngx_queue_insert_after(&f->queue, &nf->queue); | |
241 | |
242 return NGX_OK; | |
243 } | |
244 | |
245 | |
246 static ngx_chain_t * | |
247 ngx_quic_split_bufs(ngx_connection_t *c, ngx_chain_t *in, size_t len) | |
248 { | |
249 size_t n; | |
250 ngx_buf_t *b; | |
251 ngx_chain_t *out; | |
252 ngx_quic_connection_t *qc; | |
253 | |
254 qc = ngx_quic_get_connection(c); | |
255 | |
256 while (in) { | |
257 n = ngx_buf_size(in->buf); | |
258 | |
259 if (n == len) { | |
260 out = in->next; | |
261 in->next = NULL; | |
262 return out; | |
263 } | |
264 | |
265 if (n > len) { | |
266 break; | |
267 } | |
268 | |
269 len -= n; | |
270 in = in->next; | |
271 } | |
272 | |
273 if (in == NULL) { | |
274 return NULL; | |
275 } | |
276 | |
277 /* split in->buf by creating shadow bufs which reference it */ | |
278 | |
279 if (in->buf->shadow == NULL) { | |
280 if (qc->free_shadow_bufs) { | |
281 b = qc->free_shadow_bufs; | |
282 qc->free_shadow_bufs = b->shadow; | |
283 | |
284 } else { | |
285 b = ngx_alloc_buf(c->pool); | |
286 if (b == NULL) { | |
287 return NGX_CHAIN_ERROR; | |
288 } | |
289 } | |
290 | |
291 *b = *in->buf; | |
292 b->shadow = in->buf; | |
293 b->last_shadow = 1; | |
294 in->buf = b; | |
295 } | |
296 | |
297 out = ngx_alloc_chain_link(c->pool); | |
298 if (out == NULL) { | |
299 return NGX_CHAIN_ERROR; | |
300 } | |
301 | |
302 if (qc->free_shadow_bufs) { | |
303 b = qc->free_shadow_bufs; | |
304 qc->free_shadow_bufs = b->shadow; | |
305 | |
306 } else { | |
307 b = ngx_alloc_buf(c->pool); | |
308 if (b == NULL) { | |
309 ngx_free_chain(c->pool, out); | |
310 return NGX_CHAIN_ERROR; | |
311 } | |
312 } | |
313 | |
314 out->buf = b; | |
315 out->next = in->next; | |
316 in->next = NULL; | |
317 | |
318 *b = *in->buf; | |
319 b->last_shadow = 0; | |
320 b->pos = b->pos + len; | |
321 | |
322 in->buf->shadow = b; | |
323 in->buf->last = in->buf->pos + len; | |
324 | |
325 return out; | |
326 } | |
327 | |
328 | |
329 ngx_chain_t * | |
330 ngx_quic_alloc_buf(ngx_connection_t *c) | |
331 { | |
332 ngx_buf_t *b; | |
333 ngx_chain_t *cl; | |
334 ngx_quic_connection_t *qc; | |
335 | |
336 qc = ngx_quic_get_connection(c); | |
337 | |
338 if (qc->free_bufs) { | |
339 cl = qc->free_bufs; | |
340 qc->free_bufs = cl->next; | |
341 | |
342 b = cl->buf; | |
343 b->pos = b->start; | |
344 b->last = b->start; | |
345 | |
346 #ifdef NGX_QUIC_DEBUG_ALLOC | |
347 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
348 "quic reuse buffer n:%ui", qc->nbufs); | |
349 #endif | |
350 | |
351 return cl; | |
352 } | |
353 | |
354 cl = ngx_alloc_chain_link(c->pool); | |
355 if (cl == NULL) { | |
356 return NULL; | |
357 } | |
358 | |
359 b = ngx_create_temp_buf(c->pool, NGX_QUIC_BUFFER_SIZE); | |
360 if (b == NULL) { | |
361 return NULL; | |
362 } | |
363 | |
364 b->tag = (ngx_buf_tag_t) &ngx_quic_alloc_buf; | |
365 | |
366 cl->buf = b; | |
367 | |
368 #ifdef NGX_QUIC_DEBUG_ALLOC | |
369 ++qc->nbufs; | |
370 | |
371 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
372 "quic alloc buffer n:%ui", qc->nbufs); | |
373 #endif | |
374 | |
375 return cl; | |
376 } | |
377 | |
378 | |
379 ngx_chain_t * | |
380 ngx_quic_copy_buf(ngx_connection_t *c, u_char *data, size_t len) | |
381 { | |
382 size_t n; | |
383 ngx_buf_t *b; | |
384 ngx_chain_t *cl, *out, **ll; | |
385 | |
386 out = NULL; | |
387 ll = &out; | |
388 | |
389 while (len) { | |
390 cl = ngx_quic_alloc_buf(c); | |
391 if (cl == NULL) { | |
392 return NGX_CHAIN_ERROR; | |
393 } | |
394 | |
395 b = cl->buf; | |
396 n = ngx_min((size_t) (b->end - b->last), len); | |
397 | |
398 b->last = ngx_cpymem(b->last, data, n); | |
399 | |
400 data += n; | |
401 len -= n; | |
402 | |
403 *ll = cl; | |
404 ll = &cl->next; | |
405 } | |
406 | |
407 *ll = NULL; | |
408 | |
409 return out; | |
410 } | |
411 | |
412 | |
413 ngx_chain_t * | |
414 ngx_quic_copy_chain(ngx_connection_t *c, ngx_chain_t *in, size_t limit) | |
415 { | |
416 size_t n; | |
417 ngx_buf_t *b; | |
418 ngx_chain_t *cl, *out, **ll; | |
419 | |
420 out = NULL; | |
421 ll = &out; | |
422 | |
423 while (in) { | |
424 if (!ngx_buf_in_memory(in->buf) || ngx_buf_size(in->buf) == 0) { | |
425 in = in->next; | |
426 continue; | |
427 } | |
428 | |
429 cl = ngx_quic_alloc_buf(c); | |
430 if (cl == NULL) { | |
431 return NGX_CHAIN_ERROR; | |
432 } | |
433 | |
434 *ll = cl; | |
435 ll = &cl->next; | |
436 | |
437 b = cl->buf; | |
438 | |
439 while (in && b->last != b->end) { | |
440 | |
441 n = ngx_min(in->buf->last - in->buf->pos, b->end - b->last); | |
442 | |
443 if (limit > 0 && n > limit) { | |
444 n = limit; | |
445 } | |
446 | |
447 b->last = ngx_cpymem(b->last, in->buf->pos, n); | |
448 | |
449 in->buf->pos += n; | |
450 if (in->buf->pos == in->buf->last) { | |
451 in = in->next; | |
452 } | |
453 | |
454 if (limit > 0) { | |
455 if (limit == n) { | |
456 goto done; | |
457 } | |
458 | |
459 limit -= n; | |
460 } | |
461 } | |
462 } | |
463 | |
464 done: | |
465 | |
466 *ll = NULL; | |
467 | |
468 return out; | |
469 } | |
470 | |
471 | |
472 ngx_int_t ngx_quic_crypto_input(ngx_connection_t *c, | |
473 ngx_quic_frame_t *frame, void *data); | |
474 | |
475 | |
476 ngx_int_t | |
477 ngx_quic_handle_ordered_frame(ngx_connection_t *c, ngx_quic_frames_stream_t *fs, | |
478 ngx_quic_frame_t *frame, ngx_quic_frame_handler_pt handler, void *data) | |
479 { | |
480 size_t full_len; | |
481 ngx_int_t rc; | |
482 ngx_queue_t *q; | |
483 ngx_quic_ordered_frame_t *f; | |
484 | |
485 f = &frame->u.ord; | |
486 | |
487 if (f->offset > fs->received) { | |
488 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
489 "quic out-of-order frame: expecting:%uL got:%uL", | |
490 fs->received, f->offset); | |
491 | |
492 return ngx_quic_buffer_frame(c, fs, frame); | |
493 } | |
494 | |
495 if (f->offset < fs->received) { | |
496 | |
497 if (ngx_quic_adjust_frame_offset(c, frame, fs->received) | |
498 == NGX_DONE) | |
499 { | |
500 /* old/duplicate data range */ | |
501 return handler == ngx_quic_crypto_input ? NGX_DECLINED : NGX_OK; | |
502 } | |
503 | |
504 /* intersecting data range, frame modified */ | |
505 } | |
506 | |
507 /* f->offset == fs->received */ | |
508 | |
509 rc = handler(c, frame, data); | |
510 if (rc == NGX_ERROR) { | |
511 return NGX_ERROR; | |
512 | |
513 } else if (rc == NGX_DONE) { | |
514 /* handler destroyed stream, queue no longer exists */ | |
515 return NGX_OK; | |
516 } | |
517 | |
518 /* rc == NGX_OK */ | |
519 | |
520 fs->received += f->length; | |
521 | |
522 /* now check the queue if we can continue with buffered frames */ | |
523 | |
524 do { | |
525 q = ngx_queue_head(&fs->frames); | |
526 if (q == ngx_queue_sentinel(&fs->frames)) { | |
527 break; | |
528 } | |
529 | |
530 frame = ngx_queue_data(q, ngx_quic_frame_t, queue); | |
531 f = &frame->u.ord; | |
532 | |
533 if (f->offset > fs->received) { | |
534 /* gap found, nothing more to do */ | |
535 break; | |
536 } | |
537 | |
538 full_len = f->length; | |
539 | |
540 if (f->offset < fs->received) { | |
541 | |
542 if (ngx_quic_adjust_frame_offset(c, frame, fs->received) | |
543 == NGX_DONE) | |
544 { | |
545 /* old/duplicate data range */ | |
546 ngx_queue_remove(q); | |
547 fs->total -= f->length; | |
548 | |
549 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
550 "quic skipped buffered frame, total:%ui", | |
551 fs->total); | |
552 ngx_quic_free_frame(c, frame); | |
553 continue; | |
554 } | |
555 | |
556 /* frame was adjusted, proceed to input */ | |
557 } | |
558 | |
559 /* f->offset == fs->received */ | |
560 | |
561 rc = handler(c, frame, data); | |
562 | |
563 if (rc == NGX_ERROR) { | |
564 return NGX_ERROR; | |
565 | |
566 } else if (rc == NGX_DONE) { | |
567 /* handler destroyed stream, queue no longer exists */ | |
568 return NGX_OK; | |
569 } | |
570 | |
571 fs->received += f->length; | |
572 fs->total -= full_len; | |
573 | |
574 ngx_queue_remove(q); | |
575 | |
576 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
577 "quic consumed buffered frame, total:%ui", fs->total); | |
578 | |
579 ngx_quic_free_frame(c, frame); | |
580 | |
581 } while (1); | |
582 | |
583 return NGX_OK; | |
584 } | |
585 | |
586 | |
587 static ngx_int_t | |
588 ngx_quic_adjust_frame_offset(ngx_connection_t *c, ngx_quic_frame_t *frame, | |
589 uint64_t offset_in) | |
590 { | |
591 size_t tail, n; | |
592 ngx_buf_t *b; | |
593 ngx_chain_t *cl; | |
594 ngx_quic_ordered_frame_t *f; | |
595 | |
596 f = &frame->u.ord; | |
597 | |
598 tail = offset_in - f->offset; | |
599 | |
600 if (tail >= f->length) { | |
601 /* range preceeding already received data or duplicate, ignore */ | |
602 | |
603 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
604 "quic old or duplicate data in ordered frame, ignored"); | |
605 return NGX_DONE; | |
606 } | |
607 | |
608 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
609 "quic adjusted ordered frame data start to expected offset"); | |
610 | |
611 /* intersecting range: adjust data size */ | |
612 | |
613 f->offset += tail; | |
614 f->length -= tail; | |
615 | |
616 for (cl = frame->data; cl; cl = cl->next) { | |
617 b = cl->buf; | |
618 n = ngx_buf_size(b); | |
619 | |
620 if (n >= tail) { | |
621 b->pos += tail; | |
622 break; | |
623 } | |
624 | |
625 cl->buf->pos = cl->buf->last; | |
626 tail -= n; | |
627 } | |
628 | |
629 return NGX_OK; | |
630 } | |
631 | |
632 | |
633 static ngx_int_t | |
634 ngx_quic_buffer_frame(ngx_connection_t *c, ngx_quic_frames_stream_t *fs, | |
635 ngx_quic_frame_t *frame) | |
636 { | |
637 ngx_queue_t *q; | |
638 ngx_quic_frame_t *dst, *item; | |
639 ngx_quic_ordered_frame_t *f, *df; | |
640 | |
641 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
642 "quic ngx_quic_buffer_frame"); | |
643 | |
644 f = &frame->u.ord; | |
645 | |
646 /* frame start offset is in the future, buffer it */ | |
647 | |
648 dst = ngx_quic_alloc_frame(c); | |
649 if (dst == NULL) { | |
650 return NGX_ERROR; | |
651 } | |
652 | |
653 ngx_memcpy(dst, frame, sizeof(ngx_quic_frame_t)); | |
654 | |
655 dst->data = ngx_quic_copy_chain(c, frame->data, 0); | |
656 if (dst->data == NGX_CHAIN_ERROR) { | |
657 return NGX_ERROR; | |
658 } | |
659 | |
660 df = &dst->u.ord; | |
661 | |
662 fs->total += f->length; | |
663 | |
664 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
665 "quic ordered frame with unexpected offset:" | |
666 " buffered total:%ui", fs->total); | |
667 | |
668 if (ngx_queue_empty(&fs->frames)) { | |
669 ngx_queue_insert_after(&fs->frames, &dst->queue); | |
670 return NGX_OK; | |
671 } | |
672 | |
673 for (q = ngx_queue_last(&fs->frames); | |
674 q != ngx_queue_sentinel(&fs->frames); | |
675 q = ngx_queue_prev(q)) | |
676 { | |
677 item = ngx_queue_data(q, ngx_quic_frame_t, queue); | |
678 f = &item->u.ord; | |
679 | |
680 if (f->offset < df->offset) { | |
681 ngx_queue_insert_after(q, &dst->queue); | |
682 return NGX_OK; | |
683 } | |
684 } | |
685 | |
686 ngx_queue_insert_after(&fs->frames, &dst->queue); | |
687 | |
688 return NGX_OK; | |
689 } | |
690 | |
691 | |
692 #if (NGX_DEBUG) | |
693 | |
694 void | |
695 ngx_quic_log_frame(ngx_log_t *log, ngx_quic_frame_t *f, ngx_uint_t tx) | |
696 { | |
697 u_char *p, *last, *pos, *end; | |
698 ssize_t n; | |
699 uint64_t gap, range, largest, smallest; | |
700 ngx_uint_t i; | |
701 u_char buf[NGX_MAX_ERROR_STR]; | |
702 | |
703 p = buf; | |
704 last = buf + sizeof(buf); | |
705 | |
706 switch (f->type) { | |
707 | |
708 case NGX_QUIC_FT_CRYPTO: | |
709 p = ngx_slprintf(p, last, "CRYPTO len:%uL off:%uL", | |
710 f->u.crypto.length, f->u.crypto.offset); | |
711 break; | |
712 | |
713 case NGX_QUIC_FT_PADDING: | |
714 p = ngx_slprintf(p, last, "PADDING"); | |
715 break; | |
716 | |
717 case NGX_QUIC_FT_ACK: | |
718 case NGX_QUIC_FT_ACK_ECN: | |
719 | |
720 p = ngx_slprintf(p, last, "ACK n:%ui delay:%uL ", | |
721 f->u.ack.range_count, f->u.ack.delay); | |
722 | |
723 if (f->data) { | |
724 pos = f->data->buf->pos; | |
725 end = f->data->buf->last; | |
726 | |
727 } else { | |
728 pos = NULL; | |
729 end = NULL; | |
730 } | |
731 | |
732 largest = f->u.ack.largest; | |
733 smallest = f->u.ack.largest - f->u.ack.first_range; | |
734 | |
735 if (largest == smallest) { | |
736 p = ngx_slprintf(p, last, "%uL", largest); | |
737 | |
738 } else { | |
739 p = ngx_slprintf(p, last, "%uL-%uL", largest, smallest); | |
740 } | |
741 | |
742 for (i = 0; i < f->u.ack.range_count; i++) { | |
743 n = ngx_quic_parse_ack_range(log, pos, end, &gap, &range); | |
744 if (n == NGX_ERROR) { | |
745 break; | |
746 } | |
747 | |
748 pos += n; | |
749 | |
750 largest = smallest - gap - 2; | |
751 smallest = largest - range; | |
752 | |
753 if (largest == smallest) { | |
754 p = ngx_slprintf(p, last, " %uL", largest); | |
755 | |
756 } else { | |
757 p = ngx_slprintf(p, last, " %uL-%uL", largest, smallest); | |
758 } | |
759 } | |
760 | |
761 if (f->type == NGX_QUIC_FT_ACK_ECN) { | |
762 p = ngx_slprintf(p, last, " ECN counters ect0:%uL ect1:%uL ce:%uL", | |
763 f->u.ack.ect0, f->u.ack.ect1, f->u.ack.ce); | |
764 } | |
765 break; | |
766 | |
767 case NGX_QUIC_FT_PING: | |
768 p = ngx_slprintf(p, last, "PING"); | |
769 break; | |
770 | |
771 case NGX_QUIC_FT_NEW_CONNECTION_ID: | |
772 p = ngx_slprintf(p, last, | |
773 "NEW_CONNECTION_ID seq:%uL retire:%uL len:%ud", | |
774 f->u.ncid.seqnum, f->u.ncid.retire, f->u.ncid.len); | |
775 break; | |
776 | |
777 case NGX_QUIC_FT_RETIRE_CONNECTION_ID: | |
778 p = ngx_slprintf(p, last, "RETIRE_CONNECTION_ID seqnum:%uL", | |
779 f->u.retire_cid.sequence_number); | |
780 break; | |
781 | |
782 case NGX_QUIC_FT_CONNECTION_CLOSE: | |
783 case NGX_QUIC_FT_CONNECTION_CLOSE_APP: | |
784 p = ngx_slprintf(p, last, "CONNECTION_CLOSE%s err:%ui", | |
785 f->type == NGX_QUIC_FT_CONNECTION_CLOSE ? "" : "_APP", | |
786 f->u.close.error_code); | |
787 | |
788 if (f->u.close.reason.len) { | |
789 p = ngx_slprintf(p, last, " %V", &f->u.close.reason); | |
790 } | |
791 | |
792 if (f->type == NGX_QUIC_FT_CONNECTION_CLOSE) { | |
793 p = ngx_slprintf(p, last, " ft:%ui", f->u.close.frame_type); | |
794 } | |
795 | |
796 break; | |
797 | |
798 case NGX_QUIC_FT_STREAM0: | |
799 case NGX_QUIC_FT_STREAM1: | |
800 case NGX_QUIC_FT_STREAM2: | |
801 case NGX_QUIC_FT_STREAM3: | |
802 case NGX_QUIC_FT_STREAM4: | |
803 case NGX_QUIC_FT_STREAM5: | |
804 case NGX_QUIC_FT_STREAM6: | |
805 case NGX_QUIC_FT_STREAM7: | |
806 | |
807 p = ngx_slprintf(p, last, "STREAM id:0x%xL", f->u.stream.stream_id); | |
808 | |
809 if (f->u.stream.off) { | |
810 p = ngx_slprintf(p, last, " off:%uL", f->u.stream.offset); | |
811 } | |
812 | |
813 if (f->u.stream.len) { | |
814 p = ngx_slprintf(p, last, " len:%uL", f->u.stream.length); | |
815 } | |
816 | |
817 if (f->u.stream.fin) { | |
818 p = ngx_slprintf(p, last, " fin:1"); | |
819 } | |
820 | |
821 #ifdef NGX_QUIC_DEBUG_FRAMES | |
822 { | |
823 ngx_chain_t *cl; | |
824 | |
825 p = ngx_slprintf(p, last, " data:"); | |
826 | |
827 for (cl = f->data; cl; cl = cl->next) { | |
828 p = ngx_slprintf(p, last, "%*xs", | |
829 cl->buf->last - cl->buf->pos, cl->buf->pos); | |
830 } | |
831 } | |
832 #endif | |
833 | |
834 break; | |
835 | |
836 case NGX_QUIC_FT_MAX_DATA: | |
837 p = ngx_slprintf(p, last, "MAX_DATA max_data:%uL on recv", | |
838 f->u.max_data.max_data); | |
839 break; | |
840 | |
841 case NGX_QUIC_FT_RESET_STREAM: | |
842 p = ngx_slprintf(p, last, "RESET_STREAM" | |
843 " id:0x%xL error_code:0x%xL final_size:0x%xL", | |
844 f->u.reset_stream.id, f->u.reset_stream.error_code, | |
845 f->u.reset_stream.final_size); | |
846 break; | |
847 | |
848 case NGX_QUIC_FT_STOP_SENDING: | |
849 p = ngx_slprintf(p, last, "STOP_SENDING id:0x%xL err:0x%xL", | |
850 f->u.stop_sending.id, f->u.stop_sending.error_code); | |
851 break; | |
852 | |
853 case NGX_QUIC_FT_STREAMS_BLOCKED: | |
854 case NGX_QUIC_FT_STREAMS_BLOCKED2: | |
855 p = ngx_slprintf(p, last, "STREAMS_BLOCKED limit:%uL bidi:%ui", | |
856 f->u.streams_blocked.limit, f->u.streams_blocked.bidi); | |
857 break; | |
858 | |
859 case NGX_QUIC_FT_MAX_STREAMS: | |
860 case NGX_QUIC_FT_MAX_STREAMS2: | |
861 p = ngx_slprintf(p, last, "MAX_STREAMS limit:%uL bidi:%ui", | |
862 f->u.max_streams.limit, f->u.max_streams.bidi); | |
863 break; | |
864 | |
865 case NGX_QUIC_FT_MAX_STREAM_DATA: | |
866 p = ngx_slprintf(p, last, "MAX_STREAM_DATA id:0x%xL limit:%uL", | |
867 f->u.max_stream_data.id, f->u.max_stream_data.limit); | |
868 break; | |
869 | |
870 | |
871 case NGX_QUIC_FT_DATA_BLOCKED: | |
872 p = ngx_slprintf(p, last, "DATA_BLOCKED limit:%uL", | |
873 f->u.data_blocked.limit); | |
874 break; | |
875 | |
876 case NGX_QUIC_FT_STREAM_DATA_BLOCKED: | |
877 p = ngx_slprintf(p, last, "STREAM_DATA_BLOCKED id:0x%xL limit:%uL", | |
878 f->u.stream_data_blocked.id, | |
879 f->u.stream_data_blocked.limit); | |
880 break; | |
881 | |
882 case NGX_QUIC_FT_PATH_CHALLENGE: | |
883 p = ngx_slprintf(p, last, "PATH_CHALLENGE data:0x%*xs", | |
884 sizeof(f->u.path_challenge.data), | |
885 f->u.path_challenge.data); | |
886 break; | |
887 | |
888 case NGX_QUIC_FT_PATH_RESPONSE: | |
889 p = ngx_slprintf(p, last, "PATH_RESPONSE data:0x%*xs", | |
890 sizeof(f->u.path_challenge.data), | |
891 f->u.path_challenge.data); | |
892 break; | |
893 | |
894 case NGX_QUIC_FT_NEW_TOKEN: | |
895 p = ngx_slprintf(p, last, "NEW_TOKEN"); | |
896 break; | |
897 | |
898 case NGX_QUIC_FT_HANDSHAKE_DONE: | |
899 p = ngx_slprintf(p, last, "HANDSHAKE DONE"); | |
900 break; | |
901 | |
902 default: | |
903 p = ngx_slprintf(p, last, "unknown type 0x%xi", f->type); | |
904 break; | |
905 } | |
906 | |
907 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, log, 0, "quic frame %s %s %*s", | |
908 tx ? "tx" : "rx", ngx_quic_level_name(f->level), | |
909 p - buf, buf); | |
910 } | |
911 | |
912 #endif |