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