Mercurial > hg > nginx-quic
annotate src/http/v3/ngx_http_v3_streams.c @ 7916:c206233d9c29 quic
Fixed transport parameters on a new connection with a valid token.
Previously, the retry transport parameter was sent regardless.
author | Sergey Kandaurov <pluknet@nginx.com> |
---|---|
date | Mon, 01 Jun 2020 19:16:44 +0300 |
parents | c101438c69a4 |
children | c9538aef3211 |
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 |
7880
c101438c69a4
HTTP/3: prevent array access by negative index for unknown streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7839
diff
changeset
|
323 if (index >= 0) { |
c101438c69a4
HTTP/3: prevent array access by negative index for unknown streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7839
diff
changeset
|
324 h3c->known_streams[index] = sc; |
c101438c69a4
HTTP/3: prevent array access by negative index for unknown streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7839
diff
changeset
|
325 } |
7681 | 326 |
327 n = (u_char *) ngx_http_v3_encode_varlen_int(buf, type) - buf; | |
328 | |
329 if (sc->send(sc, buf, n) != (ssize_t) n) { | |
330 goto failed; | |
331 } | |
332 | |
333 return sc; | |
334 | |
335 failed: | |
336 | |
337 ngx_http_v3_close_uni_stream(sc); | |
338 | |
339 return NULL; | |
340 } | |
341 | |
342 | |
343 ngx_int_t | |
344 ngx_http_v3_client_ref_insert(ngx_connection_t *c, ngx_uint_t dynamic, | |
345 ngx_uint_t index, ngx_str_t *value) | |
346 { | |
347 u_char *p, buf[NGX_HTTP_V3_PREFIX_INT_LEN * 2]; | |
348 size_t n; | |
349 ngx_connection_t *ec; | |
350 | |
351 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
352 "http3 client ref insert, %s[%ui] \"%V\"", | |
353 dynamic ? "dynamic" : "static", index, value); | |
354 | |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
355 ec = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_ENCODER); |
7681 | 356 if (ec == NULL) { |
357 return NGX_ERROR; | |
358 } | |
359 | |
360 p = buf; | |
361 | |
362 *p = (dynamic ? 0x80 : 0xc0); | |
363 p = (u_char *) ngx_http_v3_encode_prefix_int(p, index, 6); | |
364 | |
365 /* XXX option for huffman? */ | |
366 *p = 0; | |
367 p = (u_char *) ngx_http_v3_encode_prefix_int(p, value->len, 7); | |
368 | |
369 n = p - buf; | |
370 | |
371 if (ec->send(ec, buf, n) != (ssize_t) n) { | |
372 goto failed; | |
373 } | |
374 | |
375 if (ec->send(ec, value->data, value->len) != (ssize_t) value->len) { | |
376 goto failed; | |
377 } | |
378 | |
379 return NGX_OK; | |
380 | |
381 failed: | |
382 | |
383 ngx_http_v3_close_uni_stream(ec); | |
384 | |
385 return NGX_ERROR; | |
386 } | |
387 | |
388 | |
389 ngx_int_t | |
390 ngx_http_v3_client_insert(ngx_connection_t *c, ngx_str_t *name, | |
391 ngx_str_t *value) | |
392 { | |
393 u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN]; | |
394 size_t n; | |
395 ngx_connection_t *ec; | |
396 | |
397 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
398 "http3 client insert \"%V\":\"%V\"", name, value); | |
399 | |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
400 ec = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_ENCODER); |
7681 | 401 if (ec == NULL) { |
402 return NGX_ERROR; | |
403 } | |
404 | |
405 /* XXX option for huffman? */ | |
406 buf[0] = 0x40; | |
407 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, name->len, 5) - buf; | |
408 | |
409 if (ec->send(ec, buf, n) != (ssize_t) n) { | |
410 goto failed; | |
411 } | |
412 | |
413 if (ec->send(ec, name->data, name->len) != (ssize_t) name->len) { | |
414 goto failed; | |
415 } | |
416 | |
417 /* XXX option for huffman? */ | |
418 buf[0] = 0; | |
419 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, value->len, 7) - buf; | |
420 | |
421 if (ec->send(ec, buf, n) != (ssize_t) n) { | |
422 goto failed; | |
423 } | |
424 | |
425 if (ec->send(ec, value->data, value->len) != (ssize_t) value->len) { | |
426 goto failed; | |
427 } | |
428 | |
429 return NGX_OK; | |
430 | |
431 failed: | |
432 | |
433 ngx_http_v3_close_uni_stream(ec); | |
434 | |
435 return NGX_ERROR; | |
436 } | |
437 | |
438 | |
439 ngx_int_t | |
440 ngx_http_v3_client_set_capacity(ngx_connection_t *c, ngx_uint_t capacity) | |
441 { | |
442 u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN]; | |
443 size_t n; | |
444 ngx_connection_t *ec; | |
445 | |
446 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
447 "http3 client set capacity %ui", capacity); | |
448 | |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
449 ec = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_ENCODER); |
7681 | 450 if (ec == NULL) { |
451 return NGX_ERROR; | |
452 } | |
453 | |
454 buf[0] = 0x20; | |
455 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, capacity, 5) - buf; | |
456 | |
457 if (ec->send(ec, buf, n) != (ssize_t) n) { | |
458 ngx_http_v3_close_uni_stream(ec); | |
459 return NGX_ERROR; | |
460 } | |
461 | |
462 return NGX_OK; | |
463 } | |
464 | |
465 | |
466 ngx_int_t | |
467 ngx_http_v3_client_duplicate(ngx_connection_t *c, ngx_uint_t index) | |
468 { | |
469 u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN]; | |
470 size_t n; | |
471 ngx_connection_t *ec; | |
472 | |
473 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
474 "http3 client duplicate %ui", index); | |
475 | |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
476 ec = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_ENCODER); |
7681 | 477 if (ec == NULL) { |
478 return NGX_ERROR; | |
479 } | |
480 | |
481 buf[0] = 0; | |
482 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, index, 5) - buf; | |
483 | |
484 if (ec->send(ec, buf, n) != (ssize_t) n) { | |
485 ngx_http_v3_close_uni_stream(ec); | |
486 return NGX_ERROR; | |
487 } | |
488 | |
489 return NGX_OK; | |
490 } | |
491 | |
492 | |
493 ngx_int_t | |
494 ngx_http_v3_client_ack_header(ngx_connection_t *c, ngx_uint_t stream_id) | |
495 { | |
496 u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN]; | |
497 size_t n; | |
498 ngx_connection_t *dc; | |
499 | |
500 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
501 "http3 client ack header %ui", stream_id); | |
502 | |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
503 dc = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_DECODER); |
7681 | 504 if (dc == NULL) { |
505 return NGX_ERROR; | |
506 } | |
507 | |
508 buf[0] = 0x80; | |
509 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, stream_id, 7) - buf; | |
510 | |
511 if (dc->send(dc, buf, n) != (ssize_t) n) { | |
512 ngx_http_v3_close_uni_stream(dc); | |
513 return NGX_ERROR; | |
514 } | |
515 | |
516 return NGX_OK; | |
517 } | |
518 | |
519 | |
520 ngx_int_t | |
521 ngx_http_v3_client_cancel_stream(ngx_connection_t *c, ngx_uint_t stream_id) | |
522 { | |
523 u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN]; | |
524 size_t n; | |
525 ngx_connection_t *dc; | |
526 | |
527 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
528 "http3 client cancel stream %ui", stream_id); | |
529 | |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
530 dc = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_DECODER); |
7681 | 531 if (dc == NULL) { |
532 return NGX_ERROR; | |
533 } | |
534 | |
535 buf[0] = 0x40; | |
536 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, stream_id, 6) - buf; | |
537 | |
538 if (dc->send(dc, buf, n) != (ssize_t) n) { | |
539 ngx_http_v3_close_uni_stream(dc); | |
540 return NGX_ERROR; | |
541 } | |
542 | |
543 return NGX_OK; | |
544 } | |
545 | |
546 | |
547 ngx_int_t | |
548 ngx_http_v3_client_inc_insert_count(ngx_connection_t *c, ngx_uint_t inc) | |
549 { | |
550 u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN]; | |
551 size_t n; | |
552 ngx_connection_t *dc; | |
553 | |
554 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
555 "http3 client increment insert count %ui", inc); | |
556 | |
7749
dadbc66e9fca
Simplifed handling HTTP/3 streams.
Roman Arutyunyan <arut@nginx.com>
parents:
7747
diff
changeset
|
557 dc = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_DECODER); |
7681 | 558 if (dc == NULL) { |
559 return NGX_ERROR; | |
560 } | |
561 | |
562 buf[0] = 0; | |
563 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, inc, 6) - buf; | |
564 | |
565 if (dc->send(dc, buf, n) != (ssize_t) n) { | |
566 ngx_http_v3_close_uni_stream(dc); | |
567 return NGX_ERROR; | |
568 } | |
569 | |
570 return NGX_OK; | |
571 } |