comparison src/http/v3/ngx_http_v3_streams.c @ 7681:38c0898b6df7 quic

HTTP/3.
author Roman Arutyunyan <arut@nginx.com>
date Fri, 13 Mar 2020 19:36:33 +0300
parents
children 268f4389130d
comparison
equal deleted inserted replaced
7680:6fd2cce50fe2 7681:38c0898b6df7
1
2 /*
3 * Copyright (C) Roman Arutyunyan
4 * Copyright (C) Nginx, Inc.
5 */
6
7
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_http.h>
11
12
13 #define NGX_HTTP_V3_CONTROL_STREAM 0x00
14 #define NGX_HTTP_V3_PUSH_STREAM 0x01
15 #define NGX_HTTP_V3_ENCODER_STREAM 0x02
16 #define NGX_HTTP_V3_DECODER_STREAM 0x03
17
18
19 typedef struct {
20 uint32_t signature; /* QSTR */
21 u_char buf[4];
22
23 ngx_uint_t len;
24 ngx_uint_t type;
25 ngx_uint_t state;
26 ngx_uint_t index;
27 ngx_uint_t offset;
28
29 ngx_str_t name;
30 ngx_str_t value;
31
32 unsigned client:1;
33 unsigned dynamic:1;
34 unsigned huffman:1;
35 } ngx_http_v3_uni_stream_t;
36
37
38 static void ngx_http_v3_close_uni_stream(ngx_connection_t *c);
39 static void ngx_http_v3_uni_stream_cleanup(void *data);
40 static void ngx_http_v3_read_uni_stream_type(ngx_event_t *rev);
41 static void ngx_http_v3_dummy_stream_handler(ngx_event_t *rev);
42 static void ngx_http_v3_client_encoder_handler(ngx_event_t *rev);
43 static void ngx_http_v3_client_decoder_handler(ngx_event_t *rev);
44
45 static ngx_connection_t *ngx_http_v3_create_uni_stream(ngx_connection_t *c,
46 ngx_uint_t type);
47 static ngx_connection_t *ngx_http_v3_get_server_encoder(ngx_connection_t *c);
48 static ngx_connection_t *ngx_http_v3_get_server_decoder(ngx_connection_t *c);
49
50
51 void
52 ngx_http_v3_handle_client_uni_stream(ngx_connection_t *c)
53 {
54 ngx_pool_cleanup_t *cln;
55 ngx_http_v3_uni_stream_t *us;
56
57 c->log->connection = c->number;
58
59 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
60 "http3 new uni stream id:0x%uXL", c->qs->id);
61
62 us = ngx_pcalloc(c->pool, sizeof(ngx_http_v3_uni_stream_t));
63 if (us == NULL) {
64 ngx_http_v3_close_uni_stream(c);
65 return;
66 }
67
68 us->signature = NGX_HTTP_V3_STREAM;
69 us->client = 1;
70 us->type = (ngx_uint_t) -1;
71
72 c->data = us;
73
74 cln = ngx_pool_cleanup_add(c->pool, 0);
75 if (cln == NULL) {
76 ngx_http_v3_close_uni_stream(c);
77 return;
78 }
79
80 cln->handler = ngx_http_v3_uni_stream_cleanup;
81 cln->data = c;
82
83 c->read->handler = ngx_http_v3_read_uni_stream_type;
84 c->read->handler(c->read);
85 }
86
87
88 static void
89 ngx_http_v3_close_uni_stream(ngx_connection_t *c)
90 {
91 ngx_pool_t *pool;
92
93 c->destroyed = 1;
94
95 pool = c->pool;
96
97 ngx_close_connection(c);
98
99 ngx_destroy_pool(pool);
100 }
101
102
103 static void
104 ngx_http_v3_uni_stream_cleanup(void *data)
105 {
106 ngx_connection_t *c = data;
107
108 ngx_http_v3_connection_t *h3c;
109 ngx_http_v3_uni_stream_t *us;
110
111 us = c->data;
112 h3c = c->qs->parent->data;
113
114 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 close stream");
115
116 switch (us->type) {
117
118 case NGX_HTTP_V3_ENCODER_STREAM:
119
120 if (us->client) {
121 h3c->client_encoder = NULL;
122 } else {
123 h3c->server_encoder = NULL;
124 }
125
126 break;
127
128 case NGX_HTTP_V3_DECODER_STREAM:
129
130 if (us->client) {
131 h3c->client_decoder = NULL;
132 } else {
133 h3c->server_decoder = NULL;
134 }
135
136 break;
137 }
138 }
139
140
141 static void
142 ngx_http_v3_read_uni_stream_type(ngx_event_t *rev)
143 {
144 u_char *p;
145 ssize_t n, len;
146 ngx_connection_t *c;
147 ngx_http_v3_connection_t *h3c;
148 ngx_http_v3_uni_stream_t *us;
149
150 c = rev->data;
151 us = c->data;
152 h3c = c->qs->parent->data;
153
154 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 read stream type");
155
156 while (rev->ready) {
157
158 p = &us->buf[us->len];
159
160 if (us->len == 0) {
161 len = 1;
162 } else {
163 len = (us->buf[0] >> 6) + 1 - us->len;
164 }
165
166 n = c->recv(c, p, len);
167
168 if (n == NGX_ERROR) {
169 goto failed;
170 }
171
172 if (n == NGX_AGAIN) {
173 break;
174 }
175
176 us->len += n;
177
178 if (n != len) {
179 break;
180 }
181
182 if ((us->buf[0] >> 6) + 1 == us->len) {
183 us->type = ngx_http_v3_decode_varlen_int(us->buf);
184
185 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
186 "http3 stream type:%ui", us->type);
187
188 switch (us->type) {
189
190 case NGX_HTTP_V3_ENCODER_STREAM:
191 if (h3c->client_encoder) {
192 goto failed;
193 }
194
195 h3c->client_encoder = c;
196 rev->handler = ngx_http_v3_client_encoder_handler;
197 break;
198
199 case NGX_HTTP_V3_DECODER_STREAM:
200 if (h3c->client_decoder) {
201 goto failed;
202 }
203
204 h3c->client_decoder = c;
205 rev->handler = ngx_http_v3_client_decoder_handler;
206 break;
207
208 case NGX_HTTP_V3_CONTROL_STREAM:
209 case NGX_HTTP_V3_PUSH_STREAM:
210
211 /* ignore these */
212
213 default:
214 rev->handler = ngx_http_v3_dummy_stream_handler;
215 }
216
217 rev->handler(rev);
218 return;
219 }
220 }
221
222 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
223 goto failed;
224 }
225
226 return;
227
228 failed:
229
230 ngx_http_v3_close_uni_stream(c);
231 }
232
233
234 static void
235 ngx_http_v3_dummy_stream_handler(ngx_event_t *rev)
236 {
237 u_char buf[128];
238 ngx_connection_t *c;
239
240 /* read out and ignore */
241
242 c = rev->data;
243
244 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 dummy stream reader");
245
246 while (rev->ready) {
247 if (c->recv(c, buf, sizeof(buf)) == NGX_ERROR) {
248 goto failed;
249 }
250 }
251
252 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
253 goto failed;
254 }
255
256 return;
257
258 failed:
259
260 ngx_http_v3_close_uni_stream(c);
261 }
262
263
264 static void
265 ngx_http_v3_client_encoder_handler(ngx_event_t *rev)
266 {
267 u_char v;
268 ssize_t n;
269 ngx_str_t name, value;
270 ngx_uint_t dynamic, huffman, index, offset;
271 ngx_connection_t *c, *pc;
272 ngx_http_v3_uni_stream_t *st;
273 enum {
274 sw_start = 0,
275 sw_inr_name_index,
276 sw_inr_value_length,
277 sw_inr_read_value_length,
278 sw_inr_value,
279 sw_iwnr_name_length,
280 sw_iwnr_name,
281 sw_iwnr_value_length,
282 sw_iwnr_read_value_length,
283 sw_iwnr_value,
284 sw_capacity,
285 sw_duplicate
286 } state;
287
288 c = rev->data;
289 st = c->data;
290 pc = c->qs->parent;
291
292 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 client encoder");
293
294 state = st->state;
295 dynamic = st->dynamic;
296 huffman = st->huffman;
297 index = st->index;
298 offset = st->offset;
299 name = st->name;
300 value = st->value;
301
302 while (rev->ready) {
303
304 /* XXX limit checks */
305 /* XXX buffer input */
306
307 n = c->recv(c, &v, 1);
308
309 if (n == NGX_ERROR || n == 0) {
310 goto failed;
311 }
312
313 if (n != 1) {
314 break;
315 }
316
317 /* XXX v -> ch */
318
319 switch (state) {
320
321 case sw_start:
322
323 if (v & 0x80) {
324 /* Insert With Name Reference */
325
326 dynamic = (v & 0x40) ? 0 : 1;
327 index = v & 0x3f;
328
329 if (index != 0x3f) {
330 state = sw_inr_value_length;
331 break;
332 }
333
334 index = 0;
335 state = sw_inr_name_index;
336 break;
337 }
338
339 if (v & 0x40) {
340 /* Insert Without Name Reference */
341
342 huffman = (v & 0x20) ? 1 : 0;
343 name.len = v & 0x1f;
344
345 if (name.len != 0x1f) {
346 offset = 0;
347 state = sw_iwnr_name;
348 break;
349 }
350
351 name.len = 0;
352 state = sw_iwnr_name_length;
353 break;
354 }
355
356 if (v & 0x20) {
357 /* Set Dynamic Table Capacity */
358
359 index = v & 0x1f;
360
361 if (index != 0x1f) {
362 if (ngx_http_v3_set_capacity(c, index) != NGX_OK) {
363 goto failed;
364 }
365
366 break;
367 }
368
369 index = 0;
370 state = sw_capacity;
371 break;
372 }
373
374 /* Duplicate */
375
376 index = v & 0x1f;
377
378 if (index != 0x1f) {
379 if (ngx_http_v3_duplicate(c, index) != NGX_OK) {
380 goto failed;
381 }
382
383 break;
384 }
385
386 index = 0;
387 state = sw_duplicate;
388 break;
389
390 case sw_inr_name_index:
391
392 index = (index << 7) + (v & 0x7f);
393 if (v & 0x80) {
394 break;
395 }
396
397 index += 0x3f;
398 state = sw_inr_value_length;
399 break;
400
401 case sw_inr_value_length:
402
403 huffman = (v & 0x80) ? 1 : 0;
404 value.len = v & 0x7f;
405
406 if (value.len == 0) {
407 value.data = NULL;
408
409 if (ngx_http_v3_ref_insert(c, dynamic, index, &value) != NGX_OK)
410 {
411 goto failed;
412 }
413
414 state = sw_start;
415 break;
416 }
417
418 if (value.len != 0x7f) {
419 value.data = ngx_pnalloc(pc->pool, value.len);
420 if (value.data == NULL) {
421 goto failed;
422 }
423
424 state = sw_inr_value;
425 offset = 0;
426 break;
427 }
428
429 value.len = 0;
430 state = sw_inr_read_value_length;
431 break;
432
433 case sw_inr_read_value_length:
434
435 value.len = (value.len << 7) + (v & 0x7f);
436 if (v & 0x80) {
437 break;
438 }
439
440 value.len += 0x7f;
441
442 value.data = ngx_pnalloc(pc->pool, value.len);
443 if (value.data == NULL) {
444 goto failed;
445 }
446
447 state = sw_inr_value;
448 offset = 0;
449 break;
450
451 case sw_inr_value:
452
453 value.data[offset++] = v;
454 if (offset != value.len) {
455 break;
456 }
457
458 if (huffman) {
459 if (ngx_http_v3_decode_huffman(pc, &value) != NGX_OK) {
460 goto failed;
461 }
462 }
463
464 if (ngx_http_v3_ref_insert(c, dynamic, index, &value) != NGX_OK) {
465 goto failed;
466 }
467
468 state = sw_start;
469 break;
470
471 case sw_iwnr_name_length:
472
473 name.len = (name.len << 7) + (v & 0x7f);
474 if (v & 0x80) {
475 break;
476 }
477
478 name.len += 0x1f;
479
480 name.data = ngx_pnalloc(pc->pool, name.len);
481 if (name.data == NULL) {
482 goto failed;
483 }
484
485 offset = 0;
486 state = sw_iwnr_name;
487 break;
488
489 case sw_iwnr_name:
490
491 name.data[offset++] = v;
492 if (offset != name.len) {
493 break;
494 }
495
496 if (huffman) {
497 if (ngx_http_v3_decode_huffman(pc, &name) != NGX_OK) {
498 goto failed;
499 }
500 }
501
502 state = sw_iwnr_value_length;
503 break;
504
505 case sw_iwnr_value_length:
506
507 huffman = (v & 0x80) ? 1 : 0;
508 value.len = v & 0x7f;
509
510 if (value.len == 0) {
511 value.data = NULL;
512
513 if (ngx_http_v3_insert(c, &name, &value) != NGX_OK) {
514 goto failed;
515 }
516
517 state = sw_start;
518 break;
519 }
520
521 if (value.len != 0x7f) {
522 value.data = ngx_pnalloc(pc->pool, value.len);
523 if (value.data == NULL) {
524 goto failed;
525 }
526
527 offset = 0;
528 state = sw_iwnr_value;
529 break;
530 }
531
532 state = sw_iwnr_read_value_length;
533 break;
534
535 case sw_iwnr_read_value_length:
536
537 value.len = (value.len << 7) + (v & 0x7f);
538 if (v & 0x80) {
539 break;
540 }
541
542 value.data = ngx_pnalloc(pc->pool, value.len);
543 if (value.data == NULL) {
544 goto failed;
545 }
546
547 offset = 0;
548 state = sw_iwnr_value;
549 break;
550
551 case sw_iwnr_value:
552
553 value.data[offset++] = v;
554 if (offset != value.len) {
555 break;
556 }
557
558 if (huffman) {
559 if (ngx_http_v3_decode_huffman(pc, &value) != NGX_OK) {
560 goto failed;
561 }
562 }
563
564 if (ngx_http_v3_insert(c, &name, &value) != NGX_OK) {
565 goto failed;
566 }
567
568 state = sw_start;
569 break;
570
571
572 case sw_capacity:
573
574 index = (index << 7) + (v & 0x7f);
575 if (v & 0x80) {
576 break;
577 }
578
579 index += 0x1f;
580
581 if (ngx_http_v3_set_capacity(c, index) != NGX_OK) {
582 goto failed;
583 }
584
585 state = sw_start;
586 break;
587
588 case sw_duplicate:
589
590 index = (index << 7) + (v & 0x7f);
591 if (v & 0x80) {
592 break;
593 }
594
595 index += 0x1f;
596
597 if (ngx_http_v3_duplicate(c, index) != NGX_OK) {
598 goto failed;
599 }
600
601 state = sw_start;
602 break;
603 }
604 }
605
606 st->state = state;
607 st->dynamic = dynamic;
608 st->huffman = huffman;
609 st->index = index;
610 st->offset = offset;
611 st->name = name;
612 st->value = value;
613
614 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
615 goto failed;
616 }
617
618 return;
619
620 failed:
621
622 ngx_http_v3_close_uni_stream(c);
623 }
624
625
626 static void
627 ngx_http_v3_client_decoder_handler(ngx_event_t *rev)
628 {
629 u_char v;
630 ssize_t n;
631 ngx_uint_t index;
632 ngx_connection_t *c;
633 ngx_http_v3_uni_stream_t *st;
634 enum {
635 sw_start = 0,
636 sw_ack_header,
637 sw_cancel_stream,
638 sw_inc_insert_count
639 } state;
640
641 c = rev->data;
642 st = c->data;
643
644 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 client decoder");
645
646 state = st->state;
647 index = st->index;
648
649 while (rev->ready) {
650
651 /* XXX limit checks */
652 /* XXX buffer input */
653
654 n = c->recv(c, &v, 1);
655
656 if (n == NGX_ERROR || n == 0) {
657 goto failed;
658 }
659
660 if (n != 1) {
661 break;
662 }
663
664 switch (state) {
665
666 case sw_start:
667
668 if (v & 0x80) {
669 /* Header Acknowledgement */
670
671 index = v & 0x7f;
672
673 if (index != 0x7f) {
674 if (ngx_http_v3_ack_header(c, index) != NGX_OK) {
675 goto failed;
676 }
677
678 break;
679 }
680
681 index = 0;
682 state = sw_ack_header;
683 break;
684 }
685
686 if (v & 0x40) {
687 /* Stream Cancellation */
688
689 index = v & 0x3f;
690
691 if (index != 0x3f) {
692 if (ngx_http_v3_cancel_stream(c, index) != NGX_OK) {
693 goto failed;
694 }
695
696 break;
697 }
698
699 index = 0;
700 state = sw_cancel_stream;
701 break;
702 }
703
704 /* Insert Count Increment */
705
706 index = v & 0x3f;
707
708 if (index != 0x3f) {
709 if (ngx_http_v3_inc_insert_count(c, index) != NGX_OK) {
710 goto failed;
711 }
712
713 break;
714 }
715
716 index = 0;
717 state = sw_inc_insert_count;
718 break;
719
720 case sw_ack_header:
721
722 index = (index << 7) + (v & 0x7f);
723 if (v & 0x80) {
724 break;
725 }
726
727 index += 0x7f;
728
729 if (ngx_http_v3_ack_header(c, index) != NGX_OK) {
730 goto failed;
731 }
732
733 state = sw_start;
734 break;
735
736 case sw_cancel_stream:
737
738 index = (index << 7) + (v & 0x7f);
739 if (v & 0x80) {
740 break;
741 }
742
743 index += 0x3f;
744
745 if (ngx_http_v3_cancel_stream(c, index) != NGX_OK) {
746 goto failed;
747 }
748
749 state = sw_start;
750 break;
751
752 case sw_inc_insert_count:
753
754 index = (index << 7) + (v & 0x7f);
755 if (v & 0x80) {
756 break;
757 }
758
759 index += 0x3f;
760
761 if (ngx_http_v3_inc_insert_count(c, index) != NGX_OK) {
762 goto failed;
763 }
764
765 state = sw_start;
766 break;
767 }
768 }
769
770 st->state = state;
771 st->index = index;
772
773 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
774 goto failed;
775 }
776
777 return;
778
779 failed:
780
781 ngx_http_v3_close_uni_stream(c);
782 }
783
784
785 /* XXX async & buffered stream writes */
786
787 static ngx_connection_t *
788 ngx_http_v3_create_uni_stream(ngx_connection_t *c, ngx_uint_t type)
789 {
790 u_char buf[NGX_HTTP_V3_VARLEN_INT_LEN];
791 size_t n;
792 ngx_connection_t *sc;
793 ngx_pool_cleanup_t *cln;
794 ngx_http_v3_uni_stream_t *us;
795
796 sc = ngx_quic_create_uni_stream(c->qs->parent);
797 if (sc == NULL) {
798 return NULL;
799 }
800
801 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
802 "http3 create uni stream, type:%ui", type);
803
804 us = ngx_pcalloc(sc->pool, sizeof(ngx_http_v3_uni_stream_t));
805 if (us == NULL) {
806 goto failed;
807 }
808
809 us->signature = NGX_HTTP_V3_STREAM;
810 us->type = type;
811 sc->data = us;
812
813 cln = ngx_pool_cleanup_add(sc->pool, 0);
814 if (cln == NULL) {
815 goto failed;
816 }
817
818 cln->handler = ngx_http_v3_uni_stream_cleanup;
819 cln->data = sc;
820
821 n = (u_char *) ngx_http_v3_encode_varlen_int(buf, type) - buf;
822
823 if (sc->send(sc, buf, n) != (ssize_t) n) {
824 goto failed;
825 }
826
827 return sc;
828
829 failed:
830
831 ngx_http_v3_close_uni_stream(sc);
832
833 return NULL;
834 }
835
836
837 static ngx_connection_t *
838 ngx_http_v3_get_server_encoder(ngx_connection_t *c)
839 {
840 ngx_http_v3_connection_t *h3c;
841
842 h3c = c->qs->parent->data;
843
844 if (h3c->server_encoder == NULL) {
845 h3c->server_encoder = ngx_http_v3_create_uni_stream(c,
846 NGX_HTTP_V3_ENCODER_STREAM);
847 }
848
849 return h3c->server_encoder;
850 }
851
852
853 static ngx_connection_t *
854 ngx_http_v3_get_server_decoder(ngx_connection_t *c)
855 {
856 ngx_http_v3_connection_t *h3c;
857
858 h3c = c->qs->parent->data;
859
860 if (h3c->server_decoder == NULL) {
861 h3c->server_decoder = ngx_http_v3_create_uni_stream(c,
862 NGX_HTTP_V3_DECODER_STREAM);
863 }
864
865 return h3c->server_decoder;
866 }
867
868
869 ngx_int_t
870 ngx_http_v3_client_ref_insert(ngx_connection_t *c, ngx_uint_t dynamic,
871 ngx_uint_t index, ngx_str_t *value)
872 {
873 u_char *p, buf[NGX_HTTP_V3_PREFIX_INT_LEN * 2];
874 size_t n;
875 ngx_connection_t *ec;
876
877 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
878 "http3 client ref insert, %s[%ui] \"%V\"",
879 dynamic ? "dynamic" : "static", index, value);
880
881 ec = ngx_http_v3_get_server_encoder(c);
882 if (ec == NULL) {
883 return NGX_ERROR;
884 }
885
886 p = buf;
887
888 *p = (dynamic ? 0x80 : 0xc0);
889 p = (u_char *) ngx_http_v3_encode_prefix_int(p, index, 6);
890
891 /* XXX option for huffman? */
892 *p = 0;
893 p = (u_char *) ngx_http_v3_encode_prefix_int(p, value->len, 7);
894
895 n = p - buf;
896
897 if (ec->send(ec, buf, n) != (ssize_t) n) {
898 goto failed;
899 }
900
901 if (ec->send(ec, value->data, value->len) != (ssize_t) value->len) {
902 goto failed;
903 }
904
905 return NGX_OK;
906
907 failed:
908
909 ngx_http_v3_close_uni_stream(ec);
910
911 return NGX_ERROR;
912 }
913
914
915 ngx_int_t
916 ngx_http_v3_client_insert(ngx_connection_t *c, ngx_str_t *name,
917 ngx_str_t *value)
918 {
919 u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN];
920 size_t n;
921 ngx_connection_t *ec;
922
923 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
924 "http3 client insert \"%V\":\"%V\"", name, value);
925
926 ec = ngx_http_v3_get_server_encoder(c);
927 if (ec == NULL) {
928 return NGX_ERROR;
929 }
930
931 /* XXX option for huffman? */
932 buf[0] = 0x40;
933 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, name->len, 5) - buf;
934
935 if (ec->send(ec, buf, n) != (ssize_t) n) {
936 goto failed;
937 }
938
939 if (ec->send(ec, name->data, name->len) != (ssize_t) name->len) {
940 goto failed;
941 }
942
943 /* XXX option for huffman? */
944 buf[0] = 0;
945 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, value->len, 7) - buf;
946
947 if (ec->send(ec, buf, n) != (ssize_t) n) {
948 goto failed;
949 }
950
951 if (ec->send(ec, value->data, value->len) != (ssize_t) value->len) {
952 goto failed;
953 }
954
955 return NGX_OK;
956
957 failed:
958
959 ngx_http_v3_close_uni_stream(ec);
960
961 return NGX_ERROR;
962 }
963
964
965 ngx_int_t
966 ngx_http_v3_client_set_capacity(ngx_connection_t *c, ngx_uint_t capacity)
967 {
968 u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN];
969 size_t n;
970 ngx_connection_t *ec;
971
972 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
973 "http3 client set capacity %ui", capacity);
974
975 ec = ngx_http_v3_get_server_encoder(c);
976 if (ec == NULL) {
977 return NGX_ERROR;
978 }
979
980 buf[0] = 0x20;
981 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, capacity, 5) - buf;
982
983 if (ec->send(ec, buf, n) != (ssize_t) n) {
984 ngx_http_v3_close_uni_stream(ec);
985 return NGX_ERROR;
986 }
987
988 return NGX_OK;
989 }
990
991
992 ngx_int_t
993 ngx_http_v3_client_duplicate(ngx_connection_t *c, ngx_uint_t index)
994 {
995 u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN];
996 size_t n;
997 ngx_connection_t *ec;
998
999 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
1000 "http3 client duplicate %ui", index);
1001
1002 ec = ngx_http_v3_get_server_encoder(c);
1003 if (ec == NULL) {
1004 return NGX_ERROR;
1005 }
1006
1007 buf[0] = 0;
1008 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, index, 5) - buf;
1009
1010 if (ec->send(ec, buf, n) != (ssize_t) n) {
1011 ngx_http_v3_close_uni_stream(ec);
1012 return NGX_ERROR;
1013 }
1014
1015 return NGX_OK;
1016 }
1017
1018
1019 ngx_int_t
1020 ngx_http_v3_client_ack_header(ngx_connection_t *c, ngx_uint_t stream_id)
1021 {
1022 u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN];
1023 size_t n;
1024 ngx_connection_t *dc;
1025
1026 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
1027 "http3 client ack header %ui", stream_id);
1028
1029 dc = ngx_http_v3_get_server_decoder(c);
1030 if (dc == NULL) {
1031 return NGX_ERROR;
1032 }
1033
1034 buf[0] = 0x80;
1035 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, stream_id, 7) - buf;
1036
1037 if (dc->send(dc, buf, n) != (ssize_t) n) {
1038 ngx_http_v3_close_uni_stream(dc);
1039 return NGX_ERROR;
1040 }
1041
1042 return NGX_OK;
1043 }
1044
1045
1046 ngx_int_t
1047 ngx_http_v3_client_cancel_stream(ngx_connection_t *c, ngx_uint_t stream_id)
1048 {
1049 u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN];
1050 size_t n;
1051 ngx_connection_t *dc;
1052
1053 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
1054 "http3 client cancel stream %ui", stream_id);
1055
1056 dc = ngx_http_v3_get_server_decoder(c);
1057 if (dc == NULL) {
1058 return NGX_ERROR;
1059 }
1060
1061 buf[0] = 0x40;
1062 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, stream_id, 6) - buf;
1063
1064 if (dc->send(dc, buf, n) != (ssize_t) n) {
1065 ngx_http_v3_close_uni_stream(dc);
1066 return NGX_ERROR;
1067 }
1068
1069 return NGX_OK;
1070 }
1071
1072
1073 ngx_int_t
1074 ngx_http_v3_client_inc_insert_count(ngx_connection_t *c, ngx_uint_t inc)
1075 {
1076 u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN];
1077 size_t n;
1078 ngx_connection_t *dc;
1079
1080 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
1081 "http3 client increment insert count %ui", inc);
1082
1083 dc = ngx_http_v3_get_server_decoder(c);
1084 if (dc == NULL) {
1085 return NGX_ERROR;
1086 }
1087
1088 buf[0] = 0;
1089 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, inc, 6) - buf;
1090
1091 if (dc->send(dc, buf, n) != (ssize_t) n) {
1092 ngx_http_v3_close_uni_stream(dc);
1093 return NGX_ERROR;
1094 }
1095
1096 return NGX_OK;
1097 }