comparison src/http/v3/ngx_http_v3_streams.c @ 8460:72f9ff4e0a88 quic

HTTP/3: close QUIC connection with HTTP/QPACK errors when needed. Previously errors led only to closing streams. To simplify closing QUIC connection from a QUIC stream context, new macro ngx_http_v3_finalize_connection() is introduced. It calls ngx_quic_finalize_connection() for the parent connection.
author Roman Arutyunyan <arut@nginx.com>
date Thu, 02 Jul 2020 16:47:51 +0300
parents c9538aef3211
children 0d2b2664b41c
comparison
equal deleted inserted replaced
8459:1ed698947172 8460:72f9ff4e0a88
37 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, 37 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
38 "http3 new uni stream id:0x%uxL", c->qs->id); 38 "http3 new uni stream id:0x%uxL", c->qs->id);
39 39
40 us = ngx_pcalloc(c->pool, sizeof(ngx_http_v3_uni_stream_t)); 40 us = ngx_pcalloc(c->pool, sizeof(ngx_http_v3_uni_stream_t));
41 if (us == NULL) { 41 if (us == NULL) {
42 ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_INTERNAL_ERROR,
43 NULL);
42 ngx_http_v3_close_uni_stream(c); 44 ngx_http_v3_close_uni_stream(c);
43 return; 45 return;
44 } 46 }
45 47
46 us->index = -1; 48 us->index = -1;
83 static void 85 static void
84 ngx_http_v3_read_uni_stream_type(ngx_event_t *rev) 86 ngx_http_v3_read_uni_stream_type(ngx_event_t *rev)
85 { 87 {
86 u_char ch; 88 u_char ch;
87 ssize_t n; 89 ssize_t n;
88 ngx_int_t index; 90 ngx_int_t index, rc;
89 ngx_connection_t *c; 91 ngx_connection_t *c;
90 ngx_http_v3_connection_t *h3c; 92 ngx_http_v3_connection_t *h3c;
91 ngx_http_v3_uni_stream_t *us; 93 ngx_http_v3_uni_stream_t *us;
92 94
93 c = rev->data; 95 c = rev->data;
98 100
99 while (rev->ready) { 101 while (rev->ready) {
100 102
101 n = c->recv(c, &ch, 1); 103 n = c->recv(c, &ch, 1);
102 104
103 if (n == NGX_ERROR) { 105 if (n == NGX_AGAIN) {
106 break;
107 }
108
109 if (n == 0) {
110 rc = NGX_HTTP_V3_ERR_GENERAL_PROTOCOL_ERROR;
104 goto failed; 111 goto failed;
105 } 112 }
106 113
107 if (n == NGX_AGAIN || n != 1) { 114 if (n != 1) {
108 break; 115 rc = NGX_HTTP_V3_ERR_INTERNAL_ERROR;
116 goto failed;
109 } 117 }
110 118
111 switch (ch) { 119 switch (ch) {
112 120
113 case NGX_HTTP_V3_STREAM_ENCODER: 121 case NGX_HTTP_V3_STREAM_ENCODER:
152 } 160 }
153 161
154 if (index >= 0) { 162 if (index >= 0) {
155 if (h3c->known_streams[index]) { 163 if (h3c->known_streams[index]) {
156 ngx_log_error(NGX_LOG_INFO, c->log, 0, "stream exists"); 164 ngx_log_error(NGX_LOG_INFO, c->log, 0, "stream exists");
165 rc = NGX_HTTP_V3_ERR_STREAM_CREATION_ERROR;
157 goto failed; 166 goto failed;
158 } 167 }
159 168
160 us->index = index; 169 us->index = index;
161 h3c->known_streams[index] = c; 170 h3c->known_streams[index] = c;
162 } 171 }
163 172
164 if (n) { 173 if (n) {
165 us->data = ngx_pcalloc(c->pool, n); 174 us->data = ngx_pcalloc(c->pool, n);
166 if (us->data == NULL) { 175 if (us->data == NULL) {
176 rc = NGX_HTTP_V3_ERR_INTERNAL_ERROR;
167 goto failed; 177 goto failed;
168 } 178 }
169 } 179 }
170 180
171 rev->handler = ngx_http_v3_uni_read_handler; 181 rev->handler = ngx_http_v3_uni_read_handler;
172 ngx_http_v3_uni_read_handler(rev); 182 ngx_http_v3_uni_read_handler(rev);
173 return; 183 return;
174 } 184 }
175 185
176 if (ngx_handle_read_event(rev, 0) != NGX_OK) { 186 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
187 rc = NGX_HTTP_V3_ERR_INTERNAL_ERROR;
177 goto failed; 188 goto failed;
178 } 189 }
179 190
180 return; 191 return;
181 192
182 failed: 193 failed:
183 194
195 ngx_http_v3_finalize_connection(c, rc, "could not read stream type");
184 ngx_http_v3_close_uni_stream(c); 196 ngx_http_v3_close_uni_stream(c);
185 } 197 }
186 198
187 199
188 static void 200 static void
201 213
202 while (rev->ready) { 214 while (rev->ready) {
203 215
204 n = c->recv(c, buf, sizeof(buf)); 216 n = c->recv(c, buf, sizeof(buf));
205 217
206 if (n == NGX_ERROR || n == 0) { 218 if (n == NGX_ERROR) {
219 rc = NGX_HTTP_V3_ERR_INTERNAL_ERROR;
207 goto failed; 220 goto failed;
221 }
222
223 if (n == 0) {
224 if (us->index >= 0) {
225 rc = NGX_HTTP_V3_ERR_CLOSED_CRITICAL_STREAM;
226 goto failed;
227 }
228
229 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 read eof");
230 ngx_http_v3_close_uni_stream(c);
231 return;
208 } 232 }
209 233
210 if (n == NGX_AGAIN) { 234 if (n == NGX_AGAIN) {
211 break; 235 break;
212 } 236 }
217 241
218 for (i = 0; i < n; i++) { 242 for (i = 0; i < n; i++) {
219 243
220 rc = us->handler(c, us->data, buf[i]); 244 rc = us->handler(c, us->data, buf[i]);
221 245
222 if (rc == NGX_ERROR) { 246 if (rc == NGX_DONE) {
247 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
248 "http3 read done");
249 ngx_http_v3_close_uni_stream(c);
250 return;
251 }
252
253 if (rc > 0) {
223 goto failed; 254 goto failed;
224 } 255 }
225 256
226 if (rc == NGX_DONE) { 257 if (rc != NGX_AGAIN) {
227 goto done; 258 rc = NGX_HTTP_V3_ERR_GENERAL_PROTOCOL_ERROR;
259 goto failed;
228 } 260 }
229
230 /* rc == NGX_AGAIN */
231 } 261 }
232 } 262 }
233 263
234 if (ngx_handle_read_event(rev, 0) != NGX_OK) { 264 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
265 rc = NGX_HTTP_V3_ERR_INTERNAL_ERROR;
235 goto failed; 266 goto failed;
236 } 267 }
237 268
238 return; 269 return;
239 270
240 done:
241
242 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 read done");
243
244 failed: 271 failed:
245 272
273 ngx_http_v3_finalize_connection(c, rc, "stream error");
246 ngx_http_v3_close_uni_stream(c); 274 ngx_http_v3_close_uni_stream(c);
247 } 275 }
248 276
249 277
250 static void 278 static void
255 c = wev->data; 283 c = wev->data;
256 284
257 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 dummy write handler"); 285 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 dummy write handler");
258 286
259 if (ngx_handle_write_event(wev, 0) != NGX_OK) { 287 if (ngx_handle_write_event(wev, 0) != NGX_OK) {
288 ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_INTERNAL_ERROR,
289 NULL);
260 ngx_http_v3_close_uni_stream(c); 290 ngx_http_v3_close_uni_stream(c);
261 } 291 }
262 } 292 }
263 293
264 294