comparison src/http/v2/ngx_http_v2.c @ 7923:4775c1d27378

HTTP/2: fixed timers left after request body reading. Following rb->filter_need_buffering changes, request body reading is only finished after the filter chain is called and rb->last_saved is set. As such, with r->request_body_no_buffering, timer on fc->read is no longer removed when the last part of the body is received, potentially resulting in incorrect behaviour. The fix is to call ngx_http_v2_process_request_body() from the ngx_http_v2_read_unbuffered_request_body() function instead of directly calling ngx_http_v2_filter_request_body(), so the timer is properly removed.
author Maxim Dounin <mdounin@mdounin.ru>
date Mon, 06 Sep 2021 14:54:48 +0300
parents e9f402bfe37e
children d9e009b39596
comparison
equal deleted inserted replaced
7922:e9f402bfe37e 7923:4775c1d27378
4261 4261
4262 if (size == 0 && last) { 4262 if (size == 0 && last) {
4263 rb->rest = 0; 4263 rb->rest = 0;
4264 } 4264 }
4265 4265
4266 if (r->request_body_no_buffering) { 4266 if (r->request_body_no_buffering && !flush) {
4267 break; 4267 break;
4268 } 4268 }
4269 4269
4270 /* pass buffer to request body filter chain */ 4270 /* pass buffer to request body filter chain */
4271 4271
4294 if (size == 0) { 4294 if (size == 0) {
4295 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); 4295 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
4296 ngx_add_timer(fc->read, clcf->client_body_timeout); 4296 ngx_add_timer(fc->read, clcf->client_body_timeout);
4297 4297
4298 if (r->request_body_no_buffering) { 4298 if (r->request_body_no_buffering) {
4299 ngx_post_event(fc->read, &ngx_posted_events); 4299 if (!flush) {
4300 ngx_post_event(fc->read, &ngx_posted_events);
4301 }
4302
4300 return NGX_AGAIN; 4303 return NGX_AGAIN;
4301 } 4304 }
4302 4305
4303 return NGX_AGAIN; 4306 return NGX_AGAIN;
4304 } 4307 }
4307 if (fc->read->timer_set) { 4310 if (fc->read->timer_set) {
4308 ngx_del_timer(fc->read); 4311 ngx_del_timer(fc->read);
4309 } 4312 }
4310 4313
4311 if (r->request_body_no_buffering) { 4314 if (r->request_body_no_buffering) {
4312 ngx_post_event(fc->read, &ngx_posted_events); 4315 if (!flush) {
4316 ngx_post_event(fc->read, &ngx_posted_events);
4317 }
4318
4313 return NGX_OK; 4319 return NGX_OK;
4314 } 4320 }
4315 4321
4316 if (r->headers_in.chunked) { 4322 if (r->headers_in.chunked) {
4317 r->headers_in.content_length_n = rb->received; 4323 r->headers_in.content_length_n = rb->received;
4525 ngx_buf_t *buf; 4531 ngx_buf_t *buf;
4526 ngx_int_t rc; 4532 ngx_int_t rc;
4527 ngx_connection_t *fc; 4533 ngx_connection_t *fc;
4528 ngx_http_v2_stream_t *stream; 4534 ngx_http_v2_stream_t *stream;
4529 ngx_http_v2_connection_t *h2c; 4535 ngx_http_v2_connection_t *h2c;
4530 ngx_http_core_loc_conf_t *clcf;
4531 4536
4532 stream = r->stream; 4537 stream = r->stream;
4533 fc = r->connection; 4538 fc = r->connection;
4534 4539
4535 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0, 4540 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0,
4549 if (fc->error) { 4554 if (fc->error) {
4550 stream->skip_data = 1; 4555 stream->skip_data = 1;
4551 return NGX_HTTP_BAD_REQUEST; 4556 return NGX_HTTP_BAD_REQUEST;
4552 } 4557 }
4553 4558
4554 rc = ngx_http_v2_filter_request_body(r); 4559 rc = ngx_http_v2_process_request_body(r, NULL, 0, r->stream->in_closed, 1);
4555 4560
4556 if (rc != NGX_OK) { 4561 if (rc != NGX_OK && rc != NGX_AGAIN) {
4557 stream->skip_data = 1; 4562 stream->skip_data = 1;
4558 return rc; 4563 return rc;
4559 } 4564 }
4560 4565
4561 if (r->request_body->rest == 0 && r->request_body->last_saved) { 4566 if (rc == NGX_OK) {
4562 return NGX_OK; 4567 return NGX_OK;
4563 } 4568 }
4564 4569
4565 if (r->request_body->rest == 0) { 4570 if (r->request_body->rest == 0) {
4566 return NGX_AGAIN; 4571 return NGX_AGAIN;
4602 } 4607 }
4603 4608
4604 if (ngx_http_v2_send_output_queue(h2c) == NGX_ERROR) { 4609 if (ngx_http_v2_send_output_queue(h2c) == NGX_ERROR) {
4605 stream->skip_data = 1; 4610 stream->skip_data = 1;
4606 return NGX_HTTP_INTERNAL_SERVER_ERROR; 4611 return NGX_HTTP_INTERNAL_SERVER_ERROR;
4607 }
4608
4609 if (stream->recv_window == 0) {
4610 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
4611 ngx_add_timer(fc->read, clcf->client_body_timeout);
4612 } 4612 }
4613 4613
4614 stream->recv_window = window; 4614 stream->recv_window = window;
4615 4615
4616 return NGX_AGAIN; 4616 return NGX_AGAIN;