Mercurial > hg > nginx-quic
annotate src/http/v3/ngx_http_v3_streams.c @ 7870:e169cce912c7 quic
Avoid retransmitting of packets with discarded keys.
Sections 4.10.1 and 4.10.2 of quic transport describe discarding of initial
and handshake keys. Since the keys are discarded, we no longer need
to retransmit packets and corresponding queues should be emptied.
This patch removes previously added workaround that did not require
acknowledgement for initial packets, resulting in avoiding retransmission,
which is wrong because a packet could be lost and we have to retransmit it.
author | Vladimir Homutov <vl@nginx.com> |
---|---|
date | Mon, 18 May 2020 13:54:53 +0300 |
parents | 44cac24aaa44 |
children | c101438c69a4 |
rev | line source |
---|---|
7681 | 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 | |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
13 typedef ngx_int_t (*ngx_http_v3_handler_pt)(ngx_connection_t *c, void *data, |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
14 u_char ch); |
7681 | 15 |
16 | |
17 typedef struct { | |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
18 ngx_http_v3_handler_pt handler; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
19 void *data; |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
20 ngx_int_t index; |
7681 | 21 } ngx_http_v3_uni_stream_t; |
22 | |
23 | |
24 static void ngx_http_v3_close_uni_stream(ngx_connection_t *c); | |
25 static void ngx_http_v3_read_uni_stream_type(ngx_event_t *rev); | |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
26 static void ngx_http_v3_uni_read_handler(ngx_event_t *rev); |
7747
618a65de08b3
When closing a QUIC connection, wait for all streams to finish.
Roman Arutyunyan <arut@nginx.com>
parents:
7694
diff
changeset
|
27 static void ngx_http_v3_dummy_write_handler(ngx_event_t *wev); |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
28 static ngx_connection_t *ngx_http_v3_get_uni_stream(ngx_connection_t *c, |
7681 | 29 ngx_uint_t type); |
30 | |
31 | |
32 void | |
33 ngx_http_v3_handle_client_uni_stream(ngx_connection_t *c) | |
34 { | |
35 ngx_http_v3_uni_stream_t *us; | |
36 | |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
37 ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_CONTROL); |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
38 ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_ENCODER); |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
39 ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_DECODER); |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
40 |
7681 | 41 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
42 "http3 new uni stream id:0x%uxL", c->qs->id); |
7681 | 43 |
44 us = ngx_pcalloc(c->pool, sizeof(ngx_http_v3_uni_stream_t)); | |
45 if (us == NULL) { | |
46 ngx_http_v3_close_uni_stream(c); | |
47 return; | |
48 } | |
49 | |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
50 us->index = -1; |
7681 | 51 |
52 c->data = us; | |
53 | |
54 c->read->handler = ngx_http_v3_read_uni_stream_type; | |
7747
618a65de08b3
When closing a QUIC connection, wait for all streams to finish.
Roman Arutyunyan <arut@nginx.com>
parents:
7694
diff
changeset
|
55 c->write->handler = ngx_http_v3_dummy_write_handler; |
618a65de08b3
When closing a QUIC connection, wait for all streams to finish.
Roman Arutyunyan <arut@nginx.com>
parents:
7694
diff
changeset
|
56 |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
57 ngx_http_v3_read_uni_stream_type(c->read); |
7681 | 58 } |
59 | |
60 | |
61 static void | |
62 ngx_http_v3_close_uni_stream(ngx_connection_t *c) | |
63 { | |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
64 ngx_pool_t *pool; |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
65 ngx_http_v3_connection_t *h3c; |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
66 ngx_http_v3_uni_stream_t *us; |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
67 |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
68 us = c->data; |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
69 h3c = c->qs->parent->data; |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
70 |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
71 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 close stream"); |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
72 |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
73 if (us->index >= 0) { |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
74 h3c->known_streams[us->index] = NULL; |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
75 } |
7681 | 76 |
77 c->destroyed = 1; | |
78 | |
79 pool = c->pool; | |
80 | |
81 ngx_close_connection(c); | |
82 | |
83 ngx_destroy_pool(pool); | |
84 } | |
85 | |
86 | |
87 static void | |
88 ngx_http_v3_read_uni_stream_type(ngx_event_t *rev) | |
89 { | |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
90 u_char ch; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
91 ssize_t n; |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
92 ngx_int_t index; |
7681 | 93 ngx_connection_t *c; |
94 ngx_http_v3_connection_t *h3c; | |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
95 ngx_http_v3_uni_stream_t *us; |
7681 | 96 |
97 c = rev->data; | |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
98 us = c->data; |
7681 | 99 h3c = c->qs->parent->data; |
100 | |
101 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 read stream type"); | |
102 | |
103 while (rev->ready) { | |
104 | |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
105 n = c->recv(c, &ch, 1); |
7681 | 106 |
107 if (n == NGX_ERROR) { | |
108 goto failed; | |
109 } | |
110 | |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
111 if (n == NGX_AGAIN || n != 1) { |
7681 | 112 break; |
113 } | |
114 | |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
115 switch (ch) { |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
116 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
117 case NGX_HTTP_V3_STREAM_ENCODER: |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
118 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
119 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
120 "http3 encoder stream"); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
121 |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
122 index = NGX_HTTP_V3_STREAM_CLIENT_ENCODER; |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
123 us->handler = ngx_http_v3_parse_encoder; |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
124 n = sizeof(ngx_http_v3_parse_encoder_t); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
125 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
126 break; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
127 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
128 case NGX_HTTP_V3_STREAM_DECODER: |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
129 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
130 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
131 "http3 decoder stream"); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
132 |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
133 index = NGX_HTTP_V3_STREAM_CLIENT_DECODER; |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
134 us->handler = ngx_http_v3_parse_decoder; |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
135 n = sizeof(ngx_http_v3_parse_decoder_t); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
136 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
137 break; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
138 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
139 case NGX_HTTP_V3_STREAM_CONTROL: |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
140 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
141 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
142 "http3 control stream"); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
143 |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
144 index = NGX_HTTP_V3_STREAM_CLIENT_CONTROL; |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
145 us->handler = ngx_http_v3_parse_control; |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
146 n = sizeof(ngx_http_v3_parse_control_t); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
147 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
148 break; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
149 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
150 default: |
7681 | 151 |
152 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
153 "http3 stream 0x%02xi", (ngx_int_t) ch); |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
154 index = -1; |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
155 n = 0; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
156 } |
7681 | 157 |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
158 if (index >= 0) { |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
159 if (h3c->known_streams[index]) { |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
160 ngx_log_error(NGX_LOG_INFO, c->log, 0, "stream exists"); |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
161 goto failed; |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
162 } |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
163 |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
164 us->index = index; |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
165 h3c->known_streams[index] = c; |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
166 } |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
167 |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
168 if (n) { |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
169 us->data = ngx_pcalloc(c->pool, n); |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
170 if (us->data == NULL) { |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
171 goto failed; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
172 } |
7681 | 173 } |
174 | |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
175 rev->handler = ngx_http_v3_uni_read_handler; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
176 ngx_http_v3_uni_read_handler(rev); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
177 return; |
7681 | 178 } |
179 | |
180 if (ngx_handle_read_event(rev, 0) != NGX_OK) { | |
181 goto failed; | |
182 } | |
183 | |
184 return; | |
185 | |
186 failed: | |
187 | |
188 ngx_http_v3_close_uni_stream(c); | |
189 } | |
190 | |
191 | |
192 static void | |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
193 ngx_http_v3_uni_read_handler(ngx_event_t *rev) |
7681 | 194 { |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
195 u_char buf[128]; |
7681 | 196 ssize_t n; |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
197 ngx_int_t rc, i; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
198 ngx_connection_t *c; |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
199 ngx_http_v3_uni_stream_t *us; |
7681 | 200 |
201 c = rev->data; | |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
202 us = c->data; |
7681 | 203 |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
204 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 read handler"); |
7681 | 205 |
206 while (rev->ready) { | |
207 | |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
208 n = c->recv(c, buf, sizeof(buf)); |
7681 | 209 |
210 if (n == NGX_ERROR || n == 0) { | |
211 goto failed; | |
212 } | |
213 | |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
214 if (n == NGX_AGAIN) { |
7681 | 215 break; |
216 } | |
217 | |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
218 if (us->handler == NULL) { |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
219 continue; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
220 } |
7681 | 221 |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
222 for (i = 0; i < n; i++) { |
7681 | 223 |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
224 rc = us->handler(c, us->data, buf[i]); |
7681 | 225 |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
226 if (rc == NGX_ERROR) { |
7681 | 227 goto failed; |
228 } | |
229 | |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
230 if (rc == NGX_DONE) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
231 goto done; |
7681 | 232 } |
233 | |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
234 /* rc == NGX_AGAIN */ |
7681 | 235 } |
236 } | |
237 | |
238 if (ngx_handle_read_event(rev, 0) != NGX_OK) { | |
239 goto failed; | |
240 } | |
241 | |
242 return; | |
243 | |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
244 done: |
7681 | 245 |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7681
diff
changeset
|
246 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 read done"); |
7681 | 247 |
248 failed: | |
249 | |
250 ngx_http_v3_close_uni_stream(c); | |
251 } | |
252 | |
253 | |
7747
618a65de08b3
When closing a QUIC connection, wait for all streams to finish.
Roman Arutyunyan <arut@nginx.com>
parents:
7694
diff
changeset
|
254 static void |
618a65de08b3
When closing a QUIC connection, wait for all streams to finish.
Roman Arutyunyan <arut@nginx.com>
parents:
7694
diff
changeset
|
255 ngx_http_v3_dummy_write_handler(ngx_event_t *wev) |
618a65de08b3
When closing a QUIC connection, wait for all streams to finish.
Roman Arutyunyan <arut@nginx.com>
parents:
7694
diff
changeset
|
256 { |
618a65de08b3
When closing a QUIC connection, wait for all streams to finish.
Roman Arutyunyan <arut@nginx.com>
parents:
7694
diff
changeset
|
257 ngx_connection_t *c; |
618a65de08b3
When closing a QUIC connection, wait for all streams to finish.
Roman Arutyunyan <arut@nginx.com>
parents:
7694
diff
changeset
|
258 |
618a65de08b3
When closing a QUIC connection, wait for all streams to finish.
Roman Arutyunyan <arut@nginx.com>
parents:
7694
diff
changeset
|
259 c = wev->data; |
618a65de08b3
When closing a QUIC connection, wait for all streams to finish.
Roman Arutyunyan <arut@nginx.com>
parents:
7694
diff
changeset
|
260 |
618a65de08b3
When closing a QUIC connection, wait for all streams to finish.
Roman Arutyunyan <arut@nginx.com>
parents:
7694
diff
changeset
|
261 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 dummy write handler"); |
618a65de08b3
When closing a QUIC connection, wait for all streams to finish.
Roman Arutyunyan <arut@nginx.com>
parents:
7694
diff
changeset
|
262 |
618a65de08b3
When closing a QUIC connection, wait for all streams to finish.
Roman Arutyunyan <arut@nginx.com>
parents:
7694
diff
changeset
|
263 if (ngx_handle_write_event(wev, 0) != NGX_OK) { |
618a65de08b3
When closing a QUIC connection, wait for all streams to finish.
Roman Arutyunyan <arut@nginx.com>
parents:
7694
diff
changeset
|
264 ngx_http_v3_close_uni_stream(c); |
618a65de08b3
When closing a QUIC connection, wait for all streams to finish.
Roman Arutyunyan <arut@nginx.com>
parents:
7694
diff
changeset
|
265 } |
618a65de08b3
When closing a QUIC connection, wait for all streams to finish.
Roman Arutyunyan <arut@nginx.com>
parents:
7694
diff
changeset
|
266 } |
618a65de08b3
When closing a QUIC connection, wait for all streams to finish.
Roman Arutyunyan <arut@nginx.com>
parents:
7694
diff
changeset
|
267 |
618a65de08b3
When closing a QUIC connection, wait for all streams to finish.
Roman Arutyunyan <arut@nginx.com>
parents:
7694
diff
changeset
|
268 |
7681 | 269 /* XXX async & buffered stream writes */ |
270 | |
271 static ngx_connection_t * | |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
272 ngx_http_v3_get_uni_stream(ngx_connection_t *c, ngx_uint_t type) |
7681 | 273 { |
274 u_char buf[NGX_HTTP_V3_VARLEN_INT_LEN]; | |
275 size_t n; | |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
276 ngx_int_t index; |
7681 | 277 ngx_connection_t *sc; |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
278 ngx_http_v3_connection_t *h3c; |
7681 | 279 ngx_http_v3_uni_stream_t *us; |
280 | |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
281 switch (type) { |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
282 case NGX_HTTP_V3_STREAM_ENCODER: |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
283 index = NGX_HTTP_V3_STREAM_SERVER_ENCODER; |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
284 break; |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
285 case NGX_HTTP_V3_STREAM_DECODER: |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
286 index = NGX_HTTP_V3_STREAM_SERVER_DECODER; |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
287 break; |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
288 case NGX_HTTP_V3_STREAM_CONTROL: |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
289 index = NGX_HTTP_V3_STREAM_SERVER_CONTROL; |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
290 break; |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
291 default: |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
292 index = -1; |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
293 } |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
294 |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
295 h3c = c->qs->parent->data; |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
296 |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
297 if (index >= 0) { |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
298 if (h3c->known_streams[index]) { |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
299 return h3c->known_streams[index]; |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
300 } |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
301 } |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
302 |
7694
ac41c53e446d
Fixed HTTP/3 server stream creation.
Roman Arutyunyan <arut@nginx.com>
parents:
7692
diff
changeset
|
303 sc = ngx_quic_create_uni_stream(c); |
7681 | 304 if (sc == NULL) { |
305 return NULL; | |
306 } | |
307 | |
308 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
309 "http3 create uni stream, type:%ui", type); | |
310 | |
311 us = ngx_pcalloc(sc->pool, sizeof(ngx_http_v3_uni_stream_t)); | |
312 if (us == NULL) { | |
313 goto failed; | |
314 } | |
315 | |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
316 us->index = index; |
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
317 |
7681 | 318 sc->data = us; |
319 | |
7747
618a65de08b3
When closing a QUIC connection, wait for all streams to finish.
Roman Arutyunyan <arut@nginx.com>
parents:
7694
diff
changeset
|
320 sc->read->handler = ngx_http_v3_uni_read_handler; |
618a65de08b3
When closing a QUIC connection, wait for all streams to finish.
Roman Arutyunyan <arut@nginx.com>
parents:
7694
diff
changeset
|
321 sc->write->handler = ngx_http_v3_dummy_write_handler; |
618a65de08b3
When closing a QUIC connection, wait for all streams to finish.
Roman Arutyunyan <arut@nginx.com>
parents:
7694
diff
changeset
|
322 |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
323 h3c->known_streams[index] = sc; |
7681 | 324 |
325 n = (u_char *) ngx_http_v3_encode_varlen_int(buf, type) - buf; | |
326 | |
327 if (sc->send(sc, buf, n) != (ssize_t) n) { | |
328 goto failed; | |
329 } | |
330 | |
331 return sc; | |
332 | |
333 failed: | |
334 | |
335 ngx_http_v3_close_uni_stream(sc); | |
336 | |
337 return NULL; | |
338 } | |
339 | |
340 | |
341 ngx_int_t | |
342 ngx_http_v3_client_ref_insert(ngx_connection_t *c, ngx_uint_t dynamic, | |
343 ngx_uint_t index, ngx_str_t *value) | |
344 { | |
345 u_char *p, buf[NGX_HTTP_V3_PREFIX_INT_LEN * 2]; | |
346 size_t n; | |
347 ngx_connection_t *ec; | |
348 | |
349 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
350 "http3 client ref insert, %s[%ui] \"%V\"", | |
351 dynamic ? "dynamic" : "static", index, value); | |
352 | |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
353 ec = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_ENCODER); |
7681 | 354 if (ec == NULL) { |
355 return NGX_ERROR; | |
356 } | |
357 | |
358 p = buf; | |
359 | |
360 *p = (dynamic ? 0x80 : 0xc0); | |
361 p = (u_char *) ngx_http_v3_encode_prefix_int(p, index, 6); | |
362 | |
363 /* XXX option for huffman? */ | |
364 *p = 0; | |
365 p = (u_char *) ngx_http_v3_encode_prefix_int(p, value->len, 7); | |
366 | |
367 n = p - buf; | |
368 | |
369 if (ec->send(ec, buf, n) != (ssize_t) n) { | |
370 goto failed; | |
371 } | |
372 | |
373 if (ec->send(ec, value->data, value->len) != (ssize_t) value->len) { | |
374 goto failed; | |
375 } | |
376 | |
377 return NGX_OK; | |
378 | |
379 failed: | |
380 | |
381 ngx_http_v3_close_uni_stream(ec); | |
382 | |
383 return NGX_ERROR; | |
384 } | |
385 | |
386 | |
387 ngx_int_t | |
388 ngx_http_v3_client_insert(ngx_connection_t *c, ngx_str_t *name, | |
389 ngx_str_t *value) | |
390 { | |
391 u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN]; | |
392 size_t n; | |
393 ngx_connection_t *ec; | |
394 | |
395 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
396 "http3 client insert \"%V\":\"%V\"", name, value); | |
397 | |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
398 ec = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_ENCODER); |
7681 | 399 if (ec == NULL) { |
400 return NGX_ERROR; | |
401 } | |
402 | |
403 /* XXX option for huffman? */ | |
404 buf[0] = 0x40; | |
405 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, name->len, 5) - buf; | |
406 | |
407 if (ec->send(ec, buf, n) != (ssize_t) n) { | |
408 goto failed; | |
409 } | |
410 | |
411 if (ec->send(ec, name->data, name->len) != (ssize_t) name->len) { | |
412 goto failed; | |
413 } | |
414 | |
415 /* XXX option for huffman? */ | |
416 buf[0] = 0; | |
417 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, value->len, 7) - buf; | |
418 | |
419 if (ec->send(ec, buf, n) != (ssize_t) n) { | |
420 goto failed; | |
421 } | |
422 | |
423 if (ec->send(ec, value->data, value->len) != (ssize_t) value->len) { | |
424 goto failed; | |
425 } | |
426 | |
427 return NGX_OK; | |
428 | |
429 failed: | |
430 | |
431 ngx_http_v3_close_uni_stream(ec); | |
432 | |
433 return NGX_ERROR; | |
434 } | |
435 | |
436 | |
437 ngx_int_t | |
438 ngx_http_v3_client_set_capacity(ngx_connection_t *c, ngx_uint_t capacity) | |
439 { | |
440 u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN]; | |
441 size_t n; | |
442 ngx_connection_t *ec; | |
443 | |
444 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
445 "http3 client set capacity %ui", capacity); | |
446 | |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
447 ec = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_ENCODER); |
7681 | 448 if (ec == NULL) { |
449 return NGX_ERROR; | |
450 } | |
451 | |
452 buf[0] = 0x20; | |
453 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, capacity, 5) - buf; | |
454 | |
455 if (ec->send(ec, buf, n) != (ssize_t) n) { | |
456 ngx_http_v3_close_uni_stream(ec); | |
457 return NGX_ERROR; | |
458 } | |
459 | |
460 return NGX_OK; | |
461 } | |
462 | |
463 | |
464 ngx_int_t | |
465 ngx_http_v3_client_duplicate(ngx_connection_t *c, ngx_uint_t index) | |
466 { | |
467 u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN]; | |
468 size_t n; | |
469 ngx_connection_t *ec; | |
470 | |
471 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
472 "http3 client duplicate %ui", index); | |
473 | |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
474 ec = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_ENCODER); |
7681 | 475 if (ec == NULL) { |
476 return NGX_ERROR; | |
477 } | |
478 | |
479 buf[0] = 0; | |
480 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, index, 5) - buf; | |
481 | |
482 if (ec->send(ec, buf, n) != (ssize_t) n) { | |
483 ngx_http_v3_close_uni_stream(ec); | |
484 return NGX_ERROR; | |
485 } | |
486 | |
487 return NGX_OK; | |
488 } | |
489 | |
490 | |
491 ngx_int_t | |
492 ngx_http_v3_client_ack_header(ngx_connection_t *c, ngx_uint_t stream_id) | |
493 { | |
494 u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN]; | |
495 size_t n; | |
496 ngx_connection_t *dc; | |
497 | |
498 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
499 "http3 client ack header %ui", stream_id); | |
500 | |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
501 dc = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_DECODER); |
7681 | 502 if (dc == NULL) { |
503 return NGX_ERROR; | |
504 } | |
505 | |
506 buf[0] = 0x80; | |
507 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, stream_id, 7) - buf; | |
508 | |
509 if (dc->send(dc, buf, n) != (ssize_t) n) { | |
510 ngx_http_v3_close_uni_stream(dc); | |
511 return NGX_ERROR; | |
512 } | |
513 | |
514 return NGX_OK; | |
515 } | |
516 | |
517 | |
518 ngx_int_t | |
519 ngx_http_v3_client_cancel_stream(ngx_connection_t *c, ngx_uint_t stream_id) | |
520 { | |
521 u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN]; | |
522 size_t n; | |
523 ngx_connection_t *dc; | |
524 | |
525 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
526 "http3 client cancel stream %ui", stream_id); | |
527 | |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
528 dc = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_DECODER); |
7681 | 529 if (dc == NULL) { |
530 return NGX_ERROR; | |
531 } | |
532 | |
533 buf[0] = 0x40; | |
534 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, stream_id, 6) - buf; | |
535 | |
536 if (dc->send(dc, buf, n) != (ssize_t) n) { | |
537 ngx_http_v3_close_uni_stream(dc); | |
538 return NGX_ERROR; | |
539 } | |
540 | |
541 return NGX_OK; | |
542 } | |
543 | |
544 | |
545 ngx_int_t | |
546 ngx_http_v3_client_inc_insert_count(ngx_connection_t *c, ngx_uint_t inc) | |
547 { | |
548 u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN]; | |
549 size_t n; | |
550 ngx_connection_t *dc; | |
551 | |
552 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
553 "http3 client increment insert count %ui", inc); | |
554 | |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
555 dc = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_DECODER); |
7681 | 556 if (dc == NULL) { |
557 return NGX_ERROR; | |
558 } | |
559 | |
560 buf[0] = 0; | |
561 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, inc, 6) - buf; | |
562 | |
563 if (dc->send(dc, buf, n) != (ssize_t) n) { | |
564 ngx_http_v3_close_uni_stream(dc); | |
565 return NGX_ERROR; | |
566 } | |
567 | |
568 return NGX_OK; | |
569 } |