Mercurial > hg > nginx-quic
comparison src/http/v3/ngx_http_v3_uni.c @ 8714:18d23ed15eef quic
HTTP/3: renamed files.
ngx_http_v3_tables.h and ngx_http_v3_tables.c are renamed to
ngx_http_v3_table.h and ngx_http_v3_table.c to better match HTTP/2 code.
ngx_http_v3_streams.h and ngx_http_v3_streams.c are renamed to
ngx_http_v3_uni.h and ngx_http_v3_uni.c to better match their content.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Tue, 07 Dec 2021 13:01:28 +0300 |
parents | src/http/v3/ngx_http_v3_streams.c@d6ef13c5fd8e |
children | 3436b441239b |
comparison
equal
deleted
inserted
replaced
8713:d6ef13c5fd8e | 8714:18d23ed15eef |
---|---|
1 | |
2 /* | |
3 * Copyright (C) Roman Arutyunyan | |
4 * Copyright (C) Nginx, Inc. | |
5 */ | |
6 | |
7 | |
8 #include <ngx_config.h> | |
9 #include <ngx_core.h> | |
10 #include <ngx_http.h> | |
11 | |
12 | |
13 typedef struct { | |
14 ngx_http_v3_parse_uni_t parse; | |
15 ngx_int_t index; | |
16 } ngx_http_v3_uni_stream_t; | |
17 | |
18 | |
19 typedef struct { | |
20 ngx_queue_t queue; | |
21 uint64_t id; | |
22 ngx_connection_t *connection; | |
23 ngx_uint_t *npushing; | |
24 } ngx_http_v3_push_t; | |
25 | |
26 | |
27 static void ngx_http_v3_close_uni_stream(ngx_connection_t *c); | |
28 static void ngx_http_v3_uni_read_handler(ngx_event_t *rev); | |
29 static void ngx_http_v3_dummy_write_handler(ngx_event_t *wev); | |
30 static void ngx_http_v3_push_cleanup(void *data); | |
31 static ngx_connection_t *ngx_http_v3_get_uni_stream(ngx_connection_t *c, | |
32 ngx_uint_t type); | |
33 | |
34 | |
35 void | |
36 ngx_http_v3_init_uni_stream(ngx_connection_t *c) | |
37 { | |
38 uint64_t n; | |
39 ngx_http_v3_uni_stream_t *us; | |
40 | |
41 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 init uni stream"); | |
42 | |
43 n = c->quic->id >> 2; | |
44 | |
45 if (n >= NGX_HTTP_V3_MAX_UNI_STREAMS) { | |
46 ngx_http_v3_finalize_connection(c, | |
47 NGX_HTTP_V3_ERR_STREAM_CREATION_ERROR, | |
48 "reached maximum number of uni streams"); | |
49 c->data = NULL; | |
50 ngx_http_v3_close_uni_stream(c); | |
51 return; | |
52 } | |
53 | |
54 c->quic->cancelable = 1; | |
55 | |
56 us = ngx_pcalloc(c->pool, sizeof(ngx_http_v3_uni_stream_t)); | |
57 if (us == NULL) { | |
58 ngx_http_v3_finalize_connection(c, | |
59 NGX_HTTP_V3_ERR_INTERNAL_ERROR, | |
60 "memory allocation error"); | |
61 c->data = NULL; | |
62 ngx_http_v3_close_uni_stream(c); | |
63 return; | |
64 } | |
65 | |
66 us->index = -1; | |
67 | |
68 c->data = us; | |
69 | |
70 c->read->handler = ngx_http_v3_uni_read_handler; | |
71 c->write->handler = ngx_http_v3_dummy_write_handler; | |
72 | |
73 ngx_http_v3_uni_read_handler(c->read); | |
74 } | |
75 | |
76 | |
77 static void | |
78 ngx_http_v3_close_uni_stream(ngx_connection_t *c) | |
79 { | |
80 ngx_pool_t *pool; | |
81 ngx_http_v3_session_t *h3c; | |
82 ngx_http_v3_uni_stream_t *us; | |
83 | |
84 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 close stream"); | |
85 | |
86 us = c->data; | |
87 | |
88 if (us && us->index >= 0) { | |
89 h3c = ngx_http_v3_get_session(c); | |
90 h3c->known_streams[us->index] = NULL; | |
91 } | |
92 | |
93 c->destroyed = 1; | |
94 | |
95 pool = c->pool; | |
96 | |
97 ngx_close_connection(c); | |
98 | |
99 ngx_destroy_pool(pool); | |
100 } | |
101 | |
102 | |
103 ngx_int_t | |
104 ngx_http_v3_register_uni_stream(ngx_connection_t *c, uint64_t type) | |
105 { | |
106 ngx_int_t index; | |
107 ngx_http_v3_session_t *h3c; | |
108 ngx_http_v3_uni_stream_t *us; | |
109 | |
110 h3c = ngx_http_v3_get_session(c); | |
111 | |
112 switch (type) { | |
113 | |
114 case NGX_HTTP_V3_STREAM_ENCODER: | |
115 | |
116 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
117 "http3 encoder stream"); | |
118 index = NGX_HTTP_V3_STREAM_CLIENT_ENCODER; | |
119 break; | |
120 | |
121 case NGX_HTTP_V3_STREAM_DECODER: | |
122 | |
123 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
124 "http3 decoder stream"); | |
125 index = NGX_HTTP_V3_STREAM_CLIENT_DECODER; | |
126 break; | |
127 | |
128 case NGX_HTTP_V3_STREAM_CONTROL: | |
129 | |
130 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
131 "http3 control stream"); | |
132 index = NGX_HTTP_V3_STREAM_CLIENT_CONTROL; | |
133 | |
134 break; | |
135 | |
136 default: | |
137 | |
138 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
139 "http3 stream 0x%02xL", type); | |
140 | |
141 if (h3c->known_streams[NGX_HTTP_V3_STREAM_CLIENT_ENCODER] == NULL | |
142 || h3c->known_streams[NGX_HTTP_V3_STREAM_CLIENT_DECODER] == NULL | |
143 || h3c->known_streams[NGX_HTTP_V3_STREAM_CLIENT_CONTROL] == NULL) | |
144 { | |
145 ngx_log_error(NGX_LOG_INFO, c->log, 0, "missing mandatory stream"); | |
146 return NGX_HTTP_V3_ERR_STREAM_CREATION_ERROR; | |
147 } | |
148 | |
149 index = -1; | |
150 } | |
151 | |
152 if (index >= 0) { | |
153 if (h3c->known_streams[index]) { | |
154 ngx_log_error(NGX_LOG_INFO, c->log, 0, "stream exists"); | |
155 return NGX_HTTP_V3_ERR_STREAM_CREATION_ERROR; | |
156 } | |
157 | |
158 h3c->known_streams[index] = c; | |
159 | |
160 us = c->data; | |
161 us->index = index; | |
162 } | |
163 | |
164 return NGX_OK; | |
165 } | |
166 | |
167 | |
168 static void | |
169 ngx_http_v3_uni_read_handler(ngx_event_t *rev) | |
170 { | |
171 u_char buf[128]; | |
172 ssize_t n; | |
173 ngx_buf_t b; | |
174 ngx_int_t rc; | |
175 ngx_connection_t *c; | |
176 ngx_http_v3_session_t *h3c; | |
177 ngx_http_v3_uni_stream_t *us; | |
178 | |
179 c = rev->data; | |
180 us = c->data; | |
181 | |
182 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 read handler"); | |
183 | |
184 ngx_memzero(&b, sizeof(ngx_buf_t)); | |
185 | |
186 while (rev->ready) { | |
187 | |
188 n = c->recv(c, buf, sizeof(buf)); | |
189 | |
190 if (n == NGX_ERROR) { | |
191 rc = NGX_HTTP_V3_ERR_INTERNAL_ERROR; | |
192 goto failed; | |
193 } | |
194 | |
195 if (n == 0) { | |
196 if (us->index >= 0) { | |
197 rc = NGX_HTTP_V3_ERR_CLOSED_CRITICAL_STREAM; | |
198 goto failed; | |
199 } | |
200 | |
201 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 read eof"); | |
202 ngx_http_v3_close_uni_stream(c); | |
203 return; | |
204 } | |
205 | |
206 if (n == NGX_AGAIN) { | |
207 break; | |
208 } | |
209 | |
210 b.pos = buf; | |
211 b.last = buf + n; | |
212 | |
213 h3c = ngx_http_v3_get_session(c); | |
214 h3c->total_bytes += n; | |
215 | |
216 if (ngx_http_v3_check_flood(c) != NGX_OK) { | |
217 ngx_http_v3_close_uni_stream(c); | |
218 return; | |
219 } | |
220 | |
221 rc = ngx_http_v3_parse_uni(c, &us->parse, &b); | |
222 | |
223 if (rc == NGX_DONE) { | |
224 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
225 "http3 read done"); | |
226 ngx_http_v3_close_uni_stream(c); | |
227 return; | |
228 } | |
229 | |
230 if (rc > 0) { | |
231 goto failed; | |
232 } | |
233 | |
234 if (rc != NGX_AGAIN) { | |
235 rc = NGX_HTTP_V3_ERR_GENERAL_PROTOCOL_ERROR; | |
236 goto failed; | |
237 } | |
238 } | |
239 | |
240 if (ngx_handle_read_event(rev, 0) != NGX_OK) { | |
241 rc = NGX_HTTP_V3_ERR_INTERNAL_ERROR; | |
242 goto failed; | |
243 } | |
244 | |
245 return; | |
246 | |
247 failed: | |
248 | |
249 ngx_http_v3_finalize_connection(c, rc, "stream error"); | |
250 ngx_http_v3_close_uni_stream(c); | |
251 } | |
252 | |
253 | |
254 static void | |
255 ngx_http_v3_dummy_write_handler(ngx_event_t *wev) | |
256 { | |
257 ngx_connection_t *c; | |
258 | |
259 c = wev->data; | |
260 | |
261 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 dummy write handler"); | |
262 | |
263 if (ngx_handle_write_event(wev, 0) != NGX_OK) { | |
264 ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_INTERNAL_ERROR, | |
265 NULL); | |
266 ngx_http_v3_close_uni_stream(c); | |
267 } | |
268 } | |
269 | |
270 | |
271 /* XXX async & buffered stream writes */ | |
272 | |
273 ngx_connection_t * | |
274 ngx_http_v3_create_push_stream(ngx_connection_t *c, uint64_t push_id) | |
275 { | |
276 u_char *p, buf[NGX_HTTP_V3_VARLEN_INT_LEN * 2]; | |
277 size_t n; | |
278 ngx_connection_t *sc; | |
279 ngx_pool_cleanup_t *cln; | |
280 ngx_http_v3_push_t *push; | |
281 ngx_http_v3_session_t *h3c; | |
282 | |
283 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
284 "http3 create push stream id:%uL", push_id); | |
285 | |
286 sc = ngx_quic_open_stream(c, 0); | |
287 if (sc == NULL) { | |
288 goto failed; | |
289 } | |
290 | |
291 p = buf; | |
292 p = (u_char *) ngx_http_v3_encode_varlen_int(p, NGX_HTTP_V3_STREAM_PUSH); | |
293 p = (u_char *) ngx_http_v3_encode_varlen_int(p, push_id); | |
294 n = p - buf; | |
295 | |
296 h3c = ngx_http_v3_get_session(c); | |
297 h3c->total_bytes += n; | |
298 | |
299 if (sc->send(sc, buf, n) != (ssize_t) n) { | |
300 goto failed; | |
301 } | |
302 | |
303 cln = ngx_pool_cleanup_add(sc->pool, sizeof(ngx_http_v3_push_t)); | |
304 if (cln == NULL) { | |
305 goto failed; | |
306 } | |
307 | |
308 h3c->npushing++; | |
309 | |
310 cln->handler = ngx_http_v3_push_cleanup; | |
311 | |
312 push = cln->data; | |
313 push->id = push_id; | |
314 push->connection = sc; | |
315 push->npushing = &h3c->npushing; | |
316 | |
317 ngx_queue_insert_tail(&h3c->pushing, &push->queue); | |
318 | |
319 return sc; | |
320 | |
321 failed: | |
322 | |
323 ngx_log_error(NGX_LOG_ERR, c->log, 0, "failed to create push stream"); | |
324 | |
325 ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_STREAM_CREATION_ERROR, | |
326 "failed to create push stream"); | |
327 if (sc) { | |
328 ngx_http_v3_close_uni_stream(sc); | |
329 } | |
330 | |
331 return NULL; | |
332 } | |
333 | |
334 | |
335 static void | |
336 ngx_http_v3_push_cleanup(void *data) | |
337 { | |
338 ngx_http_v3_push_t *push = data; | |
339 | |
340 ngx_queue_remove(&push->queue); | |
341 (*push->npushing)--; | |
342 } | |
343 | |
344 | |
345 static ngx_connection_t * | |
346 ngx_http_v3_get_uni_stream(ngx_connection_t *c, ngx_uint_t type) | |
347 { | |
348 u_char buf[NGX_HTTP_V3_VARLEN_INT_LEN]; | |
349 size_t n; | |
350 ngx_int_t index; | |
351 ngx_connection_t *sc; | |
352 ngx_http_v3_session_t *h3c; | |
353 ngx_http_v3_uni_stream_t *us; | |
354 | |
355 switch (type) { | |
356 case NGX_HTTP_V3_STREAM_ENCODER: | |
357 index = NGX_HTTP_V3_STREAM_SERVER_ENCODER; | |
358 break; | |
359 case NGX_HTTP_V3_STREAM_DECODER: | |
360 index = NGX_HTTP_V3_STREAM_SERVER_DECODER; | |
361 break; | |
362 case NGX_HTTP_V3_STREAM_CONTROL: | |
363 index = NGX_HTTP_V3_STREAM_SERVER_CONTROL; | |
364 break; | |
365 default: | |
366 index = -1; | |
367 } | |
368 | |
369 h3c = ngx_http_v3_get_session(c); | |
370 | |
371 if (index >= 0) { | |
372 if (h3c->known_streams[index]) { | |
373 return h3c->known_streams[index]; | |
374 } | |
375 } | |
376 | |
377 sc = ngx_quic_open_stream(c, 0); | |
378 if (sc == NULL) { | |
379 goto failed; | |
380 } | |
381 | |
382 sc->quic->cancelable = 1; | |
383 | |
384 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
385 "http3 create uni stream, type:%ui", type); | |
386 | |
387 us = ngx_pcalloc(sc->pool, sizeof(ngx_http_v3_uni_stream_t)); | |
388 if (us == NULL) { | |
389 goto failed; | |
390 } | |
391 | |
392 us->index = index; | |
393 | |
394 sc->data = us; | |
395 | |
396 sc->read->handler = ngx_http_v3_uni_read_handler; | |
397 sc->write->handler = ngx_http_v3_dummy_write_handler; | |
398 | |
399 if (index >= 0) { | |
400 h3c->known_streams[index] = sc; | |
401 } | |
402 | |
403 n = (u_char *) ngx_http_v3_encode_varlen_int(buf, type) - buf; | |
404 | |
405 h3c = ngx_http_v3_get_session(c); | |
406 h3c->total_bytes += n; | |
407 | |
408 if (sc->send(sc, buf, n) != (ssize_t) n) { | |
409 goto failed; | |
410 } | |
411 | |
412 return sc; | |
413 | |
414 failed: | |
415 | |
416 ngx_log_error(NGX_LOG_ERR, c->log, 0, "failed to create server stream"); | |
417 | |
418 ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_STREAM_CREATION_ERROR, | |
419 "failed to create server stream"); | |
420 if (sc) { | |
421 ngx_http_v3_close_uni_stream(sc); | |
422 } | |
423 | |
424 return NULL; | |
425 } | |
426 | |
427 | |
428 ngx_int_t | |
429 ngx_http_v3_send_settings(ngx_connection_t *c) | |
430 { | |
431 u_char *p, buf[NGX_HTTP_V3_VARLEN_INT_LEN * 6]; | |
432 size_t n; | |
433 ngx_connection_t *cc; | |
434 ngx_http_v3_session_t *h3c; | |
435 ngx_http_v3_srv_conf_t *h3scf; | |
436 | |
437 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 send settings"); | |
438 | |
439 cc = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_CONTROL); | |
440 if (cc == NULL) { | |
441 return NGX_ERROR; | |
442 } | |
443 | |
444 h3scf = ngx_http_v3_get_module_srv_conf(c, ngx_http_v3_module); | |
445 | |
446 n = ngx_http_v3_encode_varlen_int(NULL, | |
447 NGX_HTTP_V3_PARAM_MAX_TABLE_CAPACITY); | |
448 n += ngx_http_v3_encode_varlen_int(NULL, h3scf->max_table_capacity); | |
449 n += ngx_http_v3_encode_varlen_int(NULL, NGX_HTTP_V3_PARAM_BLOCKED_STREAMS); | |
450 n += ngx_http_v3_encode_varlen_int(NULL, h3scf->max_blocked_streams); | |
451 | |
452 p = (u_char *) ngx_http_v3_encode_varlen_int(buf, | |
453 NGX_HTTP_V3_FRAME_SETTINGS); | |
454 p = (u_char *) ngx_http_v3_encode_varlen_int(p, n); | |
455 p = (u_char *) ngx_http_v3_encode_varlen_int(p, | |
456 NGX_HTTP_V3_PARAM_MAX_TABLE_CAPACITY); | |
457 p = (u_char *) ngx_http_v3_encode_varlen_int(p, h3scf->max_table_capacity); | |
458 p = (u_char *) ngx_http_v3_encode_varlen_int(p, | |
459 NGX_HTTP_V3_PARAM_BLOCKED_STREAMS); | |
460 p = (u_char *) ngx_http_v3_encode_varlen_int(p, h3scf->max_blocked_streams); | |
461 n = p - buf; | |
462 | |
463 h3c = ngx_http_v3_get_session(c); | |
464 h3c->total_bytes += n; | |
465 | |
466 if (cc->send(cc, buf, n) != (ssize_t) n) { | |
467 goto failed; | |
468 } | |
469 | |
470 return NGX_OK; | |
471 | |
472 failed: | |
473 | |
474 ngx_log_error(NGX_LOG_ERR, c->log, 0, "failed to send settings"); | |
475 | |
476 ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_EXCESSIVE_LOAD, | |
477 "failed to send settings"); | |
478 ngx_http_v3_close_uni_stream(cc); | |
479 | |
480 return NGX_ERROR; | |
481 } | |
482 | |
483 | |
484 ngx_int_t | |
485 ngx_http_v3_send_goaway(ngx_connection_t *c, uint64_t id) | |
486 { | |
487 u_char *p, buf[NGX_HTTP_V3_VARLEN_INT_LEN * 3]; | |
488 size_t n; | |
489 ngx_connection_t *cc; | |
490 ngx_http_v3_session_t *h3c; | |
491 | |
492 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 send goaway %uL", id); | |
493 | |
494 cc = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_CONTROL); | |
495 if (cc == NULL) { | |
496 return NGX_ERROR; | |
497 } | |
498 | |
499 n = ngx_http_v3_encode_varlen_int(NULL, id); | |
500 p = (u_char *) ngx_http_v3_encode_varlen_int(buf, NGX_HTTP_V3_FRAME_GOAWAY); | |
501 p = (u_char *) ngx_http_v3_encode_varlen_int(p, n); | |
502 p = (u_char *) ngx_http_v3_encode_varlen_int(p, id); | |
503 n = p - buf; | |
504 | |
505 h3c = ngx_http_v3_get_session(c); | |
506 h3c->total_bytes += n; | |
507 | |
508 if (cc->send(cc, buf, n) != (ssize_t) n) { | |
509 goto failed; | |
510 } | |
511 | |
512 return NGX_OK; | |
513 | |
514 failed: | |
515 | |
516 ngx_log_error(NGX_LOG_ERR, c->log, 0, "failed to send goaway"); | |
517 | |
518 ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_EXCESSIVE_LOAD, | |
519 "failed to send goaway"); | |
520 ngx_http_v3_close_uni_stream(cc); | |
521 | |
522 return NGX_ERROR; | |
523 } | |
524 | |
525 | |
526 ngx_int_t | |
527 ngx_http_v3_send_ack_section(ngx_connection_t *c, ngx_uint_t stream_id) | |
528 { | |
529 u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN]; | |
530 size_t n; | |
531 ngx_connection_t *dc; | |
532 ngx_http_v3_session_t *h3c; | |
533 | |
534 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
535 "http3 send section acknowledgement %ui", stream_id); | |
536 | |
537 dc = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_DECODER); | |
538 if (dc == NULL) { | |
539 return NGX_ERROR; | |
540 } | |
541 | |
542 buf[0] = 0x80; | |
543 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, stream_id, 7) - buf; | |
544 | |
545 h3c = ngx_http_v3_get_session(c); | |
546 h3c->total_bytes += n; | |
547 | |
548 if (dc->send(dc, buf, n) != (ssize_t) n) { | |
549 goto failed; | |
550 } | |
551 | |
552 return NGX_OK; | |
553 | |
554 failed: | |
555 | |
556 ngx_log_error(NGX_LOG_ERR, c->log, 0, | |
557 "failed to send section acknowledgement"); | |
558 | |
559 ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_EXCESSIVE_LOAD, | |
560 "failed to send section acknowledgement"); | |
561 ngx_http_v3_close_uni_stream(dc); | |
562 | |
563 return NGX_ERROR; | |
564 } | |
565 | |
566 | |
567 ngx_int_t | |
568 ngx_http_v3_send_cancel_stream(ngx_connection_t *c, ngx_uint_t stream_id) | |
569 { | |
570 u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN]; | |
571 size_t n; | |
572 ngx_connection_t *dc; | |
573 ngx_http_v3_session_t *h3c; | |
574 | |
575 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
576 "http3 send stream cancellation %ui", stream_id); | |
577 | |
578 dc = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_DECODER); | |
579 if (dc == NULL) { | |
580 return NGX_ERROR; | |
581 } | |
582 | |
583 buf[0] = 0x40; | |
584 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, stream_id, 6) - buf; | |
585 | |
586 h3c = ngx_http_v3_get_session(c); | |
587 h3c->total_bytes += n; | |
588 | |
589 if (dc->send(dc, buf, n) != (ssize_t) n) { | |
590 goto failed; | |
591 } | |
592 | |
593 return NGX_OK; | |
594 | |
595 failed: | |
596 | |
597 ngx_log_error(NGX_LOG_ERR, c->log, 0, "failed to send stream cancellation"); | |
598 | |
599 ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_EXCESSIVE_LOAD, | |
600 "failed to send stream cancellation"); | |
601 ngx_http_v3_close_uni_stream(dc); | |
602 | |
603 return NGX_ERROR; | |
604 } | |
605 | |
606 | |
607 ngx_int_t | |
608 ngx_http_v3_send_inc_insert_count(ngx_connection_t *c, ngx_uint_t inc) | |
609 { | |
610 u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN]; | |
611 size_t n; | |
612 ngx_connection_t *dc; | |
613 ngx_http_v3_session_t *h3c; | |
614 | |
615 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
616 "http3 send insert count increment %ui", inc); | |
617 | |
618 dc = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_DECODER); | |
619 if (dc == NULL) { | |
620 return NGX_ERROR; | |
621 } | |
622 | |
623 buf[0] = 0; | |
624 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, inc, 6) - buf; | |
625 | |
626 h3c = ngx_http_v3_get_session(c); | |
627 h3c->total_bytes += n; | |
628 | |
629 if (dc->send(dc, buf, n) != (ssize_t) n) { | |
630 goto failed; | |
631 } | |
632 | |
633 return NGX_OK; | |
634 | |
635 failed: | |
636 | |
637 ngx_log_error(NGX_LOG_ERR, c->log, 0, | |
638 "failed to send insert count increment"); | |
639 | |
640 ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_EXCESSIVE_LOAD, | |
641 "failed to send insert count increment"); | |
642 ngx_http_v3_close_uni_stream(dc); | |
643 | |
644 return NGX_ERROR; | |
645 } | |
646 | |
647 | |
648 ngx_int_t | |
649 ngx_http_v3_set_max_push_id(ngx_connection_t *c, uint64_t max_push_id) | |
650 { | |
651 ngx_http_v3_session_t *h3c; | |
652 | |
653 h3c = ngx_http_v3_get_session(c); | |
654 | |
655 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
656 "http3 MAX_PUSH_ID:%uL", max_push_id); | |
657 | |
658 if (h3c->max_push_id != (uint64_t) -1 && max_push_id < h3c->max_push_id) { | |
659 return NGX_HTTP_V3_ERR_ID_ERROR; | |
660 } | |
661 | |
662 h3c->max_push_id = max_push_id; | |
663 | |
664 return NGX_OK; | |
665 } | |
666 | |
667 | |
668 ngx_int_t | |
669 ngx_http_v3_goaway(ngx_connection_t *c, uint64_t push_id) | |
670 { | |
671 ngx_http_v3_session_t *h3c; | |
672 | |
673 h3c = ngx_http_v3_get_session(c); | |
674 | |
675 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 GOAWAY:%uL", push_id); | |
676 | |
677 h3c->goaway_push_id = push_id; | |
678 | |
679 return NGX_OK; | |
680 } | |
681 | |
682 | |
683 ngx_int_t | |
684 ngx_http_v3_cancel_push(ngx_connection_t *c, uint64_t push_id) | |
685 { | |
686 ngx_queue_t *q; | |
687 ngx_http_request_t *r; | |
688 ngx_http_v3_push_t *push; | |
689 ngx_http_v3_session_t *h3c; | |
690 | |
691 h3c = ngx_http_v3_get_session(c); | |
692 | |
693 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
694 "http3 CANCEL_PUSH:%uL", push_id); | |
695 | |
696 if (push_id >= h3c->next_push_id) { | |
697 return NGX_HTTP_V3_ERR_ID_ERROR; | |
698 } | |
699 | |
700 for (q = ngx_queue_head(&h3c->pushing); | |
701 q != ngx_queue_sentinel(&h3c->pushing); | |
702 q = ngx_queue_next(&h3c->pushing)) | |
703 { | |
704 push = (ngx_http_v3_push_t *) q; | |
705 | |
706 if (push->id != push_id) { | |
707 continue; | |
708 } | |
709 | |
710 r = push->connection->data; | |
711 | |
712 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
713 "http3 cancel push"); | |
714 | |
715 ngx_http_finalize_request(r, NGX_HTTP_CLOSE); | |
716 | |
717 break; | |
718 } | |
719 | |
720 return NGX_OK; | |
721 } | |
722 | |
723 | |
724 ngx_int_t | |
725 ngx_http_v3_cancel_stream(ngx_connection_t *c, ngx_uint_t stream_id) | |
726 { | |
727 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
728 "http3 cancel stream %ui", stream_id); | |
729 | |
730 /* we do not use dynamic tables */ | |
731 | |
732 return NGX_OK; | |
733 } |