comparison src/event/quic/ngx_event_quic_streams.c @ 8938:23880e4ad3e2 quic

QUIC: write and full stream shutdown support. Full stream shutdown is now called from stream cleanup handler instead of explicitly sending frames.
author Roman Arutyunyan <arut@nginx.com>
date Mon, 13 Dec 2021 14:49:42 +0300
parents 0692355a3519
children 56dec0d4e5b1
comparison
equal deleted inserted replaced
8937:0692355a3519 8938:23880e4ad3e2
11 11
12 12
13 #define NGX_QUIC_STREAM_GONE (void *) -1 13 #define NGX_QUIC_STREAM_GONE (void *) -1
14 14
15 15
16 static ngx_int_t ngx_quic_shutdown_stream_send(ngx_connection_t *c);
17 static ngx_int_t ngx_quic_shutdown_stream_recv(ngx_connection_t *c);
16 static ngx_quic_stream_t *ngx_quic_get_stream(ngx_connection_t *c, uint64_t id); 18 static ngx_quic_stream_t *ngx_quic_get_stream(ngx_connection_t *c, uint64_t id);
17 static ngx_int_t ngx_quic_reject_stream(ngx_connection_t *c, uint64_t id); 19 static ngx_int_t ngx_quic_reject_stream(ngx_connection_t *c, uint64_t id);
18 static void ngx_quic_init_stream_handler(ngx_event_t *ev); 20 static void ngx_quic_init_stream_handler(ngx_event_t *ev);
19 static void ngx_quic_init_streams_handler(ngx_connection_t *c); 21 static void ngx_quic_init_streams_handler(ngx_connection_t *c);
20 static ngx_quic_stream_t *ngx_quic_create_stream(ngx_connection_t *c, 22 static ngx_quic_stream_t *ngx_quic_create_stream(ngx_connection_t *c,
255 257
256 258
257 ngx_int_t 259 ngx_int_t
258 ngx_quic_shutdown_stream(ngx_connection_t *c, int how) 260 ngx_quic_shutdown_stream(ngx_connection_t *c, int how)
259 { 261 {
262 ngx_quic_stream_t *qs;
263
264 qs = c->quic;
265
266 if (how == NGX_RDWR_SHUTDOWN || how == NGX_WRITE_SHUTDOWN) {
267 if ((qs->id & NGX_QUIC_STREAM_SERVER_INITIATED)
268 || (qs->id & NGX_QUIC_STREAM_UNIDIRECTIONAL) == 0)
269 {
270 if (ngx_quic_shutdown_stream_send(c) != NGX_OK) {
271 return NGX_ERROR;
272 }
273 }
274 }
275
276 if (how == NGX_RDWR_SHUTDOWN || how == NGX_READ_SHUTDOWN) {
277 if ((qs->id & NGX_QUIC_STREAM_SERVER_INITIATED) == 0
278 || (qs->id & NGX_QUIC_STREAM_UNIDIRECTIONAL) == 0)
279 {
280 if (ngx_quic_shutdown_stream_recv(c) != NGX_OK) {
281 return NGX_ERROR;
282 }
283 }
284 }
285
286 return NGX_OK;
287 }
288
289
290 static ngx_int_t
291 ngx_quic_shutdown_stream_send(ngx_connection_t *c)
292 {
260 ngx_event_t *wev; 293 ngx_event_t *wev;
261 ngx_connection_t *pc; 294 ngx_connection_t *pc;
262 ngx_quic_frame_t *frame; 295 ngx_quic_frame_t *frame;
263 ngx_quic_stream_t *qs; 296 ngx_quic_stream_t *qs;
264 ngx_quic_connection_t *qc; 297 ngx_quic_connection_t *qc;
265 298
266 if (how != NGX_WRITE_SHUTDOWN) {
267 return NGX_OK;
268 }
269
270 wev = c->write; 299 wev = c->write;
271 300
272 if (wev->error) { 301 if (wev->error) {
273 return NGX_OK; 302 return NGX_OK;
274 } 303 }
281 if (frame == NULL) { 310 if (frame == NULL) {
282 return NGX_ERROR; 311 return NGX_ERROR;
283 } 312 }
284 313
285 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, 314 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
286 "quic stream id:0x%xL shutdown", qs->id); 315 "quic stream id:0x%xL send shutdown", qs->id);
287 316
288 frame->level = ssl_encryption_application; 317 frame->level = ssl_encryption_application;
289 frame->type = NGX_QUIC_FT_STREAM; 318 frame->type = NGX_QUIC_FT_STREAM;
290 frame->u.stream.off = 1; 319 frame->u.stream.off = 1;
291 frame->u.stream.len = 1; 320 frame->u.stream.len = 1;
295 frame->u.stream.offset = c->sent; 324 frame->u.stream.offset = c->sent;
296 frame->u.stream.length = 0; 325 frame->u.stream.length = 0;
297 326
298 ngx_quic_queue_frame(qc, frame); 327 ngx_quic_queue_frame(qc, frame);
299 328
300 wev->ready = 1;
301 wev->error = 1; 329 wev->error = 1;
330
331 return NGX_OK;
332 }
333
334
335 static ngx_int_t
336 ngx_quic_shutdown_stream_recv(ngx_connection_t *c)
337 {
338 ngx_event_t *rev;
339 ngx_connection_t *pc;
340 ngx_quic_frame_t *frame;
341 ngx_quic_stream_t *qs;
342 ngx_quic_connection_t *qc;
343
344 rev = c->read;
345
346 if (rev->pending_eof || rev->error) {
347 return NGX_OK;
348 }
349
350 qs = c->quic;
351 pc = qs->parent;
352 qc = ngx_quic_get_connection(pc);
353
354 if (qc->conf->stream_close_code == 0) {
355 return NGX_OK;
356 }
357
358 frame = ngx_quic_alloc_frame(pc);
359 if (frame == NULL) {
360 return NGX_ERROR;
361 }
362
363 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
364 "quic stream id:0x%xL recv shutdown", qs->id);
365
366 frame->level = ssl_encryption_application;
367 frame->type = NGX_QUIC_FT_STOP_SENDING;
368 frame->u.stop_sending.id = qs->id;
369 frame->u.stop_sending.error_code = qc->conf->stream_close_code;
370
371 ngx_quic_queue_frame(qc, frame);
372
373 rev->error = 1;
302 374
303 return NGX_OK; 375 return NGX_OK;
304 } 376 }
305 377
306 378
914 986
915 if (qc->error) { 987 if (qc->error) {
916 goto done; 988 goto done;
917 } 989 }
918 990
919 c->read->pending_eof = 1; 991 (void) ngx_quic_shutdown_stream(c, NGX_RDWR_SHUTDOWN);
920 992
921 (void) ngx_quic_update_flow(c, qs->recv_last); 993 (void) ngx_quic_update_flow(c, qs->recv_last);
922
923 if ((qs->id & NGX_QUIC_STREAM_SERVER_INITIATED) == 0
924 || (qs->id & NGX_QUIC_STREAM_UNIDIRECTIONAL) == 0)
925 {
926 if (!c->read->pending_eof && !c->read->error
927 && qc->conf->stream_close_code)
928 {
929 frame = ngx_quic_alloc_frame(pc);
930 if (frame == NULL) {
931 goto done;
932 }
933
934 frame->level = ssl_encryption_application;
935 frame->type = NGX_QUIC_FT_STOP_SENDING;
936 frame->u.stop_sending.id = qs->id;
937 frame->u.stop_sending.error_code = qc->conf->stream_close_code;
938
939 ngx_quic_queue_frame(qc, frame);
940 }
941 }
942 994
943 if ((qs->id & NGX_QUIC_STREAM_SERVER_INITIATED) == 0) { 995 if ((qs->id & NGX_QUIC_STREAM_SERVER_INITIATED) == 0) {
944 frame = ngx_quic_alloc_frame(pc); 996 frame = ngx_quic_alloc_frame(pc);
945 if (frame == NULL) { 997 if (frame == NULL) {
946 goto done; 998 goto done;
957 frame->u.max_streams.limit = ++qc->streams.client_max_streams_bidi; 1009 frame->u.max_streams.limit = ++qc->streams.client_max_streams_bidi;
958 frame->u.max_streams.bidi = 1; 1010 frame->u.max_streams.bidi = 1;
959 } 1011 }
960 1012
961 ngx_quic_queue_frame(qc, frame); 1013 ngx_quic_queue_frame(qc, frame);
962 1014 }
963 if (qs->id & NGX_QUIC_STREAM_UNIDIRECTIONAL) {
964 /* do not send fin for client unidirectional streams */
965 goto done;
966 }
967 }
968
969 if (c->write->error) {
970 goto done;
971 }
972
973 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
974 "quic stream id:0x%xL send fin", qs->id);
975
976 frame = ngx_quic_alloc_frame(pc);
977 if (frame == NULL) {
978 goto done;
979 }
980
981 frame->level = ssl_encryption_application;
982 frame->type = NGX_QUIC_FT_STREAM;
983 frame->u.stream.off = 1;
984 frame->u.stream.len = 1;
985 frame->u.stream.fin = 1;
986
987 frame->u.stream.stream_id = qs->id;
988 frame->u.stream.offset = c->sent;
989 frame->u.stream.length = 0;
990
991 ngx_quic_queue_frame(qc, frame);
992 1015
993 done: 1016 done:
994 1017
995 (void) ngx_quic_output(pc); 1018 (void) ngx_quic_output(pc);
996 1019