Mercurial > hg > nginx
annotate src/http/v3/ngx_http_v3_streams.c @ 8281:618a65de08b3 quic
When closing a QUIC connection, wait for all streams to finish.
Additionally, streams are now removed from the tree in cleanup handler.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Tue, 24 Mar 2020 18:05:45 +0300 |
parents | ac41c53e446d |
children | dadbc66e9fca |
rev | line source |
---|---|
8215 | 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 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
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:
8215
diff
changeset
|
14 u_char ch); |
8215 | 15 |
16 | |
17 typedef struct { | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
18 uint32_t signature; /* QSTR */ |
8215 | 19 |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
20 ngx_http_v3_handler_pt handler; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
21 void *data; |
8215 | 22 |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
23 ngx_uint_t type; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
24 ngx_uint_t client; /* unsigned client:1; */ |
8215 | 25 } ngx_http_v3_uni_stream_t; |
26 | |
27 | |
28 static void ngx_http_v3_close_uni_stream(ngx_connection_t *c); | |
29 static void ngx_http_v3_uni_stream_cleanup(void *data); | |
30 static void ngx_http_v3_read_uni_stream_type(ngx_event_t *rev); | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
31 static void ngx_http_v3_uni_read_handler(ngx_event_t *rev); |
8281
618a65de08b3
When closing a QUIC connection, wait for all streams to finish.
Roman Arutyunyan <arut@nginx.com>
parents:
8228
diff
changeset
|
32 static void ngx_http_v3_dummy_write_handler(ngx_event_t *wev); |
8215 | 33 static ngx_connection_t *ngx_http_v3_create_uni_stream(ngx_connection_t *c, |
34 ngx_uint_t type); | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
35 static ngx_connection_t *ngx_http_v3_get_control(ngx_connection_t *c); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
36 static ngx_connection_t *ngx_http_v3_get_encoder(ngx_connection_t *c); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
37 static ngx_connection_t *ngx_http_v3_get_decoder(ngx_connection_t *c); |
8215 | 38 |
39 | |
40 void | |
41 ngx_http_v3_handle_client_uni_stream(ngx_connection_t *c) | |
42 { | |
43 ngx_pool_cleanup_t *cln; | |
44 ngx_http_v3_uni_stream_t *us; | |
45 | |
46 c->log->connection = c->number; | |
47 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
48 /* XXX */ |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
49 (void) ngx_http_v3_get_control(c); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
50 (void) ngx_http_v3_get_encoder(c); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
51 (void) ngx_http_v3_get_decoder(c); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
52 |
8215 | 53 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
54 "http3 new uni stream id:0x%uxL", c->qs->id); |
8215 | 55 |
56 us = ngx_pcalloc(c->pool, sizeof(ngx_http_v3_uni_stream_t)); | |
57 if (us == NULL) { | |
58 ngx_http_v3_close_uni_stream(c); | |
59 return; | |
60 } | |
61 | |
62 us->signature = NGX_HTTP_V3_STREAM; | |
63 us->client = 1; | |
64 us->type = (ngx_uint_t) -1; | |
65 | |
66 c->data = us; | |
67 | |
68 cln = ngx_pool_cleanup_add(c->pool, 0); | |
69 if (cln == NULL) { | |
70 ngx_http_v3_close_uni_stream(c); | |
71 return; | |
72 } | |
73 | |
74 cln->handler = ngx_http_v3_uni_stream_cleanup; | |
75 cln->data = c; | |
76 | |
77 c->read->handler = ngx_http_v3_read_uni_stream_type; | |
8281
618a65de08b3
When closing a QUIC connection, wait for all streams to finish.
Roman Arutyunyan <arut@nginx.com>
parents:
8228
diff
changeset
|
78 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:
8228
diff
changeset
|
79 |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
80 ngx_http_v3_read_uni_stream_type(c->read); |
8215 | 81 } |
82 | |
83 | |
84 static void | |
85 ngx_http_v3_close_uni_stream(ngx_connection_t *c) | |
86 { | |
87 ngx_pool_t *pool; | |
88 | |
89 c->destroyed = 1; | |
90 | |
91 pool = c->pool; | |
92 | |
93 ngx_close_connection(c); | |
94 | |
95 ngx_destroy_pool(pool); | |
96 } | |
97 | |
98 | |
99 static void | |
100 ngx_http_v3_uni_stream_cleanup(void *data) | |
101 { | |
102 ngx_connection_t *c = data; | |
103 | |
104 ngx_http_v3_connection_t *h3c; | |
105 ngx_http_v3_uni_stream_t *us; | |
106 | |
107 us = c->data; | |
108 h3c = c->qs->parent->data; | |
109 | |
110 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 close stream"); | |
111 | |
112 switch (us->type) { | |
113 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
114 case NGX_HTTP_V3_STREAM_ENCODER: |
8215 | 115 |
116 if (us->client) { | |
117 h3c->client_encoder = NULL; | |
118 } else { | |
119 h3c->server_encoder = NULL; | |
120 } | |
121 | |
122 break; | |
123 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
124 case NGX_HTTP_V3_STREAM_DECODER: |
8215 | 125 |
126 if (us->client) { | |
127 h3c->client_decoder = NULL; | |
128 } else { | |
129 h3c->server_decoder = NULL; | |
130 } | |
131 | |
132 break; | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
133 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
134 case NGX_HTTP_V3_STREAM_CONTROL: |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
135 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
136 if (us->client) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
137 h3c->client_control = NULL; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
138 } else { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
139 h3c->server_control = NULL; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
140 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
141 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
142 break; |
8215 | 143 } |
144 } | |
145 | |
146 | |
147 static void | |
148 ngx_http_v3_read_uni_stream_type(ngx_event_t *rev) | |
149 { | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
150 u_char ch; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
151 ssize_t n; |
8215 | 152 ngx_connection_t *c; |
153 ngx_http_v3_connection_t *h3c; | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
154 ngx_http_v3_uni_stream_t *st; |
8215 | 155 |
156 c = rev->data; | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
157 st = c->data; |
8215 | 158 h3c = c->qs->parent->data; |
159 | |
160 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 read stream type"); | |
161 | |
162 while (rev->ready) { | |
163 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
164 n = c->recv(c, &ch, 1); |
8215 | 165 |
166 if (n == NGX_ERROR) { | |
167 goto failed; | |
168 } | |
169 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
170 if (n == NGX_AGAIN || n != 1) { |
8215 | 171 break; |
172 } | |
173 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
174 st->type = ch; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
175 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
176 switch (st->type) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
177 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
178 case NGX_HTTP_V3_STREAM_ENCODER: |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
179 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
180 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
181 "http3 encoder stream"); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
182 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
183 if (h3c->client_encoder) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
184 goto failed; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
185 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
186 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
187 h3c->client_encoder = c; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
188 st->handler = ngx_http_v3_parse_encoder; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
189 n = sizeof(ngx_http_v3_parse_encoder_t); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
190 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
191 break; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
192 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
193 case NGX_HTTP_V3_STREAM_DECODER: |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
194 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
195 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
196 "http3 decoder stream"); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
197 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
198 if (h3c->client_decoder) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
199 goto failed; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
200 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
201 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
202 h3c->client_decoder = c; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
203 st->handler = ngx_http_v3_parse_decoder; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
204 n = sizeof(ngx_http_v3_parse_decoder_t); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
205 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
206 break; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
207 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
208 case NGX_HTTP_V3_STREAM_CONTROL: |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
209 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
210 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
211 "http3 control stream"); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
212 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
213 if (h3c->client_control) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
214 goto failed; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
215 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
216 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
217 h3c->client_control = c; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
218 st->handler = ngx_http_v3_parse_control; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
219 n = sizeof(ngx_http_v3_parse_control_t); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
220 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
221 break; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
222 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
223 default: |
8215 | 224 |
225 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
226 "http3 stream 0x%02xi", st->type); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
227 n = 0; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
228 } |
8215 | 229 |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
230 if (n) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
231 st->data = ngx_pcalloc(c->pool, n); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
232 if (st->data == NULL) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
233 goto failed; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
234 } |
8215 | 235 } |
236 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
237 rev->handler = ngx_http_v3_uni_read_handler; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
238 ngx_http_v3_uni_read_handler(rev); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
239 return; |
8215 | 240 } |
241 | |
242 if (ngx_handle_read_event(rev, 0) != NGX_OK) { | |
243 goto failed; | |
244 } | |
245 | |
246 return; | |
247 | |
248 failed: | |
249 | |
250 ngx_http_v3_close_uni_stream(c); | |
251 } | |
252 | |
253 | |
254 static void | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
255 ngx_http_v3_uni_read_handler(ngx_event_t *rev) |
8215 | 256 { |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
257 u_char buf[128]; |
8215 | 258 ssize_t n; |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
259 ngx_int_t rc, i; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
260 ngx_connection_t *c; |
8215 | 261 ngx_http_v3_uni_stream_t *st; |
262 | |
263 c = rev->data; | |
264 st = c->data; | |
265 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
266 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 read handler"); |
8215 | 267 |
268 while (rev->ready) { | |
269 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
270 n = c->recv(c, buf, sizeof(buf)); |
8215 | 271 |
272 if (n == NGX_ERROR || n == 0) { | |
273 goto failed; | |
274 } | |
275 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
276 if (n == NGX_AGAIN) { |
8215 | 277 break; |
278 } | |
279 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
280 if (st->handler == NULL) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
281 continue; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
282 } |
8215 | 283 |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
284 for (i = 0; i < n; i++) { |
8215 | 285 |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
286 rc = st->handler(c, st->data, buf[i]); |
8215 | 287 |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
288 if (rc == NGX_ERROR) { |
8215 | 289 goto failed; |
290 } | |
291 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
292 if (rc == NGX_DONE) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
293 goto done; |
8215 | 294 } |
295 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
296 /* rc == NGX_AGAIN */ |
8215 | 297 } |
298 } | |
299 | |
300 if (ngx_handle_read_event(rev, 0) != NGX_OK) { | |
301 goto failed; | |
302 } | |
303 | |
304 return; | |
305 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
306 done: |
8215 | 307 |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
308 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 read done"); |
8215 | 309 |
310 failed: | |
311 | |
312 ngx_http_v3_close_uni_stream(c); | |
313 } | |
314 | |
315 | |
8281
618a65de08b3
When closing a QUIC connection, wait for all streams to finish.
Roman Arutyunyan <arut@nginx.com>
parents:
8228
diff
changeset
|
316 static void |
618a65de08b3
When closing a QUIC connection, wait for all streams to finish.
Roman Arutyunyan <arut@nginx.com>
parents:
8228
diff
changeset
|
317 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:
8228
diff
changeset
|
318 { |
618a65de08b3
When closing a QUIC connection, wait for all streams to finish.
Roman Arutyunyan <arut@nginx.com>
parents:
8228
diff
changeset
|
319 ngx_connection_t *c; |
618a65de08b3
When closing a QUIC connection, wait for all streams to finish.
Roman Arutyunyan <arut@nginx.com>
parents:
8228
diff
changeset
|
320 |
618a65de08b3
When closing a QUIC connection, wait for all streams to finish.
Roman Arutyunyan <arut@nginx.com>
parents:
8228
diff
changeset
|
321 c = wev->data; |
618a65de08b3
When closing a QUIC connection, wait for all streams to finish.
Roman Arutyunyan <arut@nginx.com>
parents:
8228
diff
changeset
|
322 |
618a65de08b3
When closing a QUIC connection, wait for all streams to finish.
Roman Arutyunyan <arut@nginx.com>
parents:
8228
diff
changeset
|
323 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:
8228
diff
changeset
|
324 |
618a65de08b3
When closing a QUIC connection, wait for all streams to finish.
Roman Arutyunyan <arut@nginx.com>
parents:
8228
diff
changeset
|
325 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:
8228
diff
changeset
|
326 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:
8228
diff
changeset
|
327 } |
618a65de08b3
When closing a QUIC connection, wait for all streams to finish.
Roman Arutyunyan <arut@nginx.com>
parents:
8228
diff
changeset
|
328 } |
618a65de08b3
When closing a QUIC connection, wait for all streams to finish.
Roman Arutyunyan <arut@nginx.com>
parents:
8228
diff
changeset
|
329 |
618a65de08b3
When closing a QUIC connection, wait for all streams to finish.
Roman Arutyunyan <arut@nginx.com>
parents:
8228
diff
changeset
|
330 |
8215 | 331 /* XXX async & buffered stream writes */ |
332 | |
333 static ngx_connection_t * | |
334 ngx_http_v3_create_uni_stream(ngx_connection_t *c, ngx_uint_t type) | |
335 { | |
336 u_char buf[NGX_HTTP_V3_VARLEN_INT_LEN]; | |
337 size_t n; | |
338 ngx_connection_t *sc; | |
339 ngx_pool_cleanup_t *cln; | |
340 ngx_http_v3_uni_stream_t *us; | |
341 | |
8228
ac41c53e446d
Fixed HTTP/3 server stream creation.
Roman Arutyunyan <arut@nginx.com>
parents:
8226
diff
changeset
|
342 sc = ngx_quic_create_uni_stream(c); |
8215 | 343 if (sc == NULL) { |
344 return NULL; | |
345 } | |
346 | |
347 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
348 "http3 create uni stream, type:%ui", type); | |
349 | |
350 us = ngx_pcalloc(sc->pool, sizeof(ngx_http_v3_uni_stream_t)); | |
351 if (us == NULL) { | |
352 goto failed; | |
353 } | |
354 | |
355 us->signature = NGX_HTTP_V3_STREAM; | |
356 us->type = type; | |
357 sc->data = us; | |
358 | |
8281
618a65de08b3
When closing a QUIC connection, wait for all streams to finish.
Roman Arutyunyan <arut@nginx.com>
parents:
8228
diff
changeset
|
359 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:
8228
diff
changeset
|
360 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:
8228
diff
changeset
|
361 |
8215 | 362 cln = ngx_pool_cleanup_add(sc->pool, 0); |
363 if (cln == NULL) { | |
364 goto failed; | |
365 } | |
366 | |
367 cln->handler = ngx_http_v3_uni_stream_cleanup; | |
368 cln->data = sc; | |
369 | |
370 n = (u_char *) ngx_http_v3_encode_varlen_int(buf, type) - buf; | |
371 | |
372 if (sc->send(sc, buf, n) != (ssize_t) n) { | |
373 goto failed; | |
374 } | |
375 | |
376 return sc; | |
377 | |
378 failed: | |
379 | |
380 ngx_http_v3_close_uni_stream(sc); | |
381 | |
382 return NULL; | |
383 } | |
384 | |
385 | |
386 static ngx_connection_t * | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
387 ngx_http_v3_get_control(ngx_connection_t *c) |
8215 | 388 { |
389 ngx_http_v3_connection_t *h3c; | |
390 | |
391 h3c = c->qs->parent->data; | |
392 | |
8228
ac41c53e446d
Fixed HTTP/3 server stream creation.
Roman Arutyunyan <arut@nginx.com>
parents:
8226
diff
changeset
|
393 if (h3c->server_control == NULL) { |
ac41c53e446d
Fixed HTTP/3 server stream creation.
Roman Arutyunyan <arut@nginx.com>
parents:
8226
diff
changeset
|
394 h3c->server_control = ngx_http_v3_create_uni_stream(c, |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
395 NGX_HTTP_V3_STREAM_CONTROL); |
8215 | 396 } |
397 | |
398 return h3c->server_encoder; | |
399 } | |
400 | |
401 | |
402 static ngx_connection_t * | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
403 ngx_http_v3_get_encoder(ngx_connection_t *c) |
8215 | 404 { |
405 ngx_http_v3_connection_t *h3c; | |
406 | |
407 h3c = c->qs->parent->data; | |
408 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
409 if (h3c->server_encoder == NULL) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
410 h3c->server_encoder = ngx_http_v3_create_uni_stream(c, |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
411 NGX_HTTP_V3_STREAM_ENCODER); |
8215 | 412 } |
413 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
414 return h3c->server_encoder; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
415 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
416 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
417 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
418 static ngx_connection_t * |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
419 ngx_http_v3_get_decoder(ngx_connection_t *c) |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
420 { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
421 ngx_http_v3_connection_t *h3c; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
422 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
423 h3c = c->qs->parent->data; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
424 |
8228
ac41c53e446d
Fixed HTTP/3 server stream creation.
Roman Arutyunyan <arut@nginx.com>
parents:
8226
diff
changeset
|
425 if (h3c->server_decoder == NULL) { |
ac41c53e446d
Fixed HTTP/3 server stream creation.
Roman Arutyunyan <arut@nginx.com>
parents:
8226
diff
changeset
|
426 h3c->server_decoder = ngx_http_v3_create_uni_stream(c, |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
427 NGX_HTTP_V3_STREAM_DECODER); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
428 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
429 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
430 return h3c->server_encoder; |
8215 | 431 } |
432 | |
433 | |
434 ngx_int_t | |
435 ngx_http_v3_client_ref_insert(ngx_connection_t *c, ngx_uint_t dynamic, | |
436 ngx_uint_t index, ngx_str_t *value) | |
437 { | |
438 u_char *p, buf[NGX_HTTP_V3_PREFIX_INT_LEN * 2]; | |
439 size_t n; | |
440 ngx_connection_t *ec; | |
441 | |
442 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
443 "http3 client ref insert, %s[%ui] \"%V\"", | |
444 dynamic ? "dynamic" : "static", index, value); | |
445 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
446 ec = ngx_http_v3_get_encoder(c); |
8215 | 447 if (ec == NULL) { |
448 return NGX_ERROR; | |
449 } | |
450 | |
451 p = buf; | |
452 | |
453 *p = (dynamic ? 0x80 : 0xc0); | |
454 p = (u_char *) ngx_http_v3_encode_prefix_int(p, index, 6); | |
455 | |
456 /* XXX option for huffman? */ | |
457 *p = 0; | |
458 p = (u_char *) ngx_http_v3_encode_prefix_int(p, value->len, 7); | |
459 | |
460 n = p - buf; | |
461 | |
462 if (ec->send(ec, buf, n) != (ssize_t) n) { | |
463 goto failed; | |
464 } | |
465 | |
466 if (ec->send(ec, value->data, value->len) != (ssize_t) value->len) { | |
467 goto failed; | |
468 } | |
469 | |
470 return NGX_OK; | |
471 | |
472 failed: | |
473 | |
474 ngx_http_v3_close_uni_stream(ec); | |
475 | |
476 return NGX_ERROR; | |
477 } | |
478 | |
479 | |
480 ngx_int_t | |
481 ngx_http_v3_client_insert(ngx_connection_t *c, ngx_str_t *name, | |
482 ngx_str_t *value) | |
483 { | |
484 u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN]; | |
485 size_t n; | |
486 ngx_connection_t *ec; | |
487 | |
488 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
489 "http3 client insert \"%V\":\"%V\"", name, value); | |
490 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
491 ec = ngx_http_v3_get_encoder(c); |
8215 | 492 if (ec == NULL) { |
493 return NGX_ERROR; | |
494 } | |
495 | |
496 /* XXX option for huffman? */ | |
497 buf[0] = 0x40; | |
498 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, name->len, 5) - buf; | |
499 | |
500 if (ec->send(ec, buf, n) != (ssize_t) n) { | |
501 goto failed; | |
502 } | |
503 | |
504 if (ec->send(ec, name->data, name->len) != (ssize_t) name->len) { | |
505 goto failed; | |
506 } | |
507 | |
508 /* XXX option for huffman? */ | |
509 buf[0] = 0; | |
510 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, value->len, 7) - buf; | |
511 | |
512 if (ec->send(ec, buf, n) != (ssize_t) n) { | |
513 goto failed; | |
514 } | |
515 | |
516 if (ec->send(ec, value->data, value->len) != (ssize_t) value->len) { | |
517 goto failed; | |
518 } | |
519 | |
520 return NGX_OK; | |
521 | |
522 failed: | |
523 | |
524 ngx_http_v3_close_uni_stream(ec); | |
525 | |
526 return NGX_ERROR; | |
527 } | |
528 | |
529 | |
530 ngx_int_t | |
531 ngx_http_v3_client_set_capacity(ngx_connection_t *c, ngx_uint_t capacity) | |
532 { | |
533 u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN]; | |
534 size_t n; | |
535 ngx_connection_t *ec; | |
536 | |
537 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
538 "http3 client set capacity %ui", capacity); | |
539 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
540 ec = ngx_http_v3_get_encoder(c); |
8215 | 541 if (ec == NULL) { |
542 return NGX_ERROR; | |
543 } | |
544 | |
545 buf[0] = 0x20; | |
546 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, capacity, 5) - buf; | |
547 | |
548 if (ec->send(ec, buf, n) != (ssize_t) n) { | |
549 ngx_http_v3_close_uni_stream(ec); | |
550 return NGX_ERROR; | |
551 } | |
552 | |
553 return NGX_OK; | |
554 } | |
555 | |
556 | |
557 ngx_int_t | |
558 ngx_http_v3_client_duplicate(ngx_connection_t *c, ngx_uint_t index) | |
559 { | |
560 u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN]; | |
561 size_t n; | |
562 ngx_connection_t *ec; | |
563 | |
564 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
565 "http3 client duplicate %ui", index); | |
566 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
567 ec = ngx_http_v3_get_encoder(c); |
8215 | 568 if (ec == NULL) { |
569 return NGX_ERROR; | |
570 } | |
571 | |
572 buf[0] = 0; | |
573 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, index, 5) - buf; | |
574 | |
575 if (ec->send(ec, buf, n) != (ssize_t) n) { | |
576 ngx_http_v3_close_uni_stream(ec); | |
577 return NGX_ERROR; | |
578 } | |
579 | |
580 return NGX_OK; | |
581 } | |
582 | |
583 | |
584 ngx_int_t | |
585 ngx_http_v3_client_ack_header(ngx_connection_t *c, ngx_uint_t stream_id) | |
586 { | |
587 u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN]; | |
588 size_t n; | |
589 ngx_connection_t *dc; | |
590 | |
591 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
592 "http3 client ack header %ui", stream_id); | |
593 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
594 dc = ngx_http_v3_get_decoder(c); |
8215 | 595 if (dc == NULL) { |
596 return NGX_ERROR; | |
597 } | |
598 | |
599 buf[0] = 0x80; | |
600 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, stream_id, 7) - buf; | |
601 | |
602 if (dc->send(dc, buf, n) != (ssize_t) n) { | |
603 ngx_http_v3_close_uni_stream(dc); | |
604 return NGX_ERROR; | |
605 } | |
606 | |
607 return NGX_OK; | |
608 } | |
609 | |
610 | |
611 ngx_int_t | |
612 ngx_http_v3_client_cancel_stream(ngx_connection_t *c, ngx_uint_t stream_id) | |
613 { | |
614 u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN]; | |
615 size_t n; | |
616 ngx_connection_t *dc; | |
617 | |
618 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
619 "http3 client cancel stream %ui", stream_id); | |
620 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
621 dc = ngx_http_v3_get_decoder(c); |
8215 | 622 if (dc == NULL) { |
623 return NGX_ERROR; | |
624 } | |
625 | |
626 buf[0] = 0x40; | |
627 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, stream_id, 6) - buf; | |
628 | |
629 if (dc->send(dc, buf, n) != (ssize_t) n) { | |
630 ngx_http_v3_close_uni_stream(dc); | |
631 return NGX_ERROR; | |
632 } | |
633 | |
634 return NGX_OK; | |
635 } | |
636 | |
637 | |
638 ngx_int_t | |
639 ngx_http_v3_client_inc_insert_count(ngx_connection_t *c, ngx_uint_t inc) | |
640 { | |
641 u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN]; | |
642 size_t n; | |
643 ngx_connection_t *dc; | |
644 | |
645 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
646 "http3 client increment insert count %ui", inc); | |
647 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
648 dc = ngx_http_v3_get_decoder(c); |
8215 | 649 if (dc == NULL) { |
650 return NGX_ERROR; | |
651 } | |
652 | |
653 buf[0] = 0; | |
654 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, inc, 6) - buf; | |
655 | |
656 if (dc->send(dc, buf, n) != (ssize_t) n) { | |
657 ngx_http_v3_close_uni_stream(dc); | |
658 return NGX_ERROR; | |
659 } | |
660 | |
661 return NGX_OK; | |
662 } |