Mercurial > hg > nginx-quic
comparison src/event/quic/ngx_event_quic_streams.c @ 8727: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
8726:0692355a3519 | 8727: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 |