comparison src/http/v2/ngx_http_v2.c @ 7922:e9f402bfe37e

HTTP/2: fixed window updates when buffering in filters. In the body read handler, the window was incorrectly calculated based on the full buffer size instead of the amount of free space in the buffer. If the request body is buffered by a filter, and the buffer is not empty after the read event is generated by the filter to resume request body processing, this could result in "http2 negative window update" alerts. Further, in the body ready handler and in ngx_http_v2_state_read_data() the buffer wasn't cleared when the data were already written to disk, so the client might stuck without window updates.
author Maxim Dounin <mdounin@mdounin.ru>
date Mon, 06 Sep 2021 14:54:47 +0300
parents 2245324a507a
children 4775c1d27378
comparison
equal deleted inserted replaced
7921:2245324a507a 7922:e9f402bfe37e
1146 if (rc != NGX_OK && rc != NGX_AGAIN) { 1146 if (rc != NGX_OK && rc != NGX_AGAIN) {
1147 stream->skip_data = 1; 1147 stream->skip_data = 1;
1148 ngx_http_finalize_request(r, rc); 1148 ngx_http_finalize_request(r, rc);
1149 } 1149 }
1150 1150
1151 if (rc == NGX_AGAIN && !stream->no_flow_control) { 1151 if (rc == NGX_AGAIN
1152 && !stream->no_flow_control
1153 && !r->request_body_no_buffering)
1154 {
1152 buf = r->request_body->buf; 1155 buf = r->request_body->buf;
1156
1157 if (r->request_body->busy == NULL) {
1158 buf->pos = buf->start;
1159 buf->last = buf->start;
1160 }
1161
1153 window = buf->end - buf->last; 1162 window = buf->end - buf->last;
1154
1155 window -= h2c->state.length - size; 1163 window -= h2c->state.length - size;
1156 1164
1157 if (window < stream->recv_window) { 1165 if (window < stream->recv_window) {
1158 ngx_log_error(NGX_LOG_ALERT, h2c->connection->log, 0, 1166 ngx_log_error(NGX_LOG_ALERT, h2c->connection->log, 0,
1159 "http2 negative window update"); 1167 "http2 negative window update");
4457 4465
4458 if (r->request_body->rest == 0) { 4466 if (r->request_body->rest == 0) {
4459 return; 4467 return;
4460 } 4468 }
4461 4469
4470 if (r->request_body->busy != NULL) {
4471 return;
4472 }
4473
4462 stream = r->stream; 4474 stream = r->stream;
4463 h2c = stream->connection; 4475 h2c = stream->connection;
4464 4476
4465 buf = r->request_body->buf; 4477 buf = r->request_body->buf;
4478
4479 buf->pos = buf->start;
4480 buf->last = buf->start;
4481
4466 window = buf->end - buf->start; 4482 window = buf->end - buf->start;
4467 4483
4468 if (h2c->state.stream == stream) { 4484 if (h2c->state.stream == stream) {
4469 window -= h2c->state.length; 4485 window -= h2c->state.length;
4470 } 4486 }