Merge branch 'nginx' (nginx-1.21.3).

Change-Id: I6187c1805b0cba41ca9aa0abfe66b21b793a3772
Signed-off-by: Piotr Sikora <piotrsikora@google.com>
diff --git a/.hgtags b/.hgtags
index e9aa48d..34b2f18 100644
--- a/.hgtags
+++ b/.hgtags
@@ -463,3 +463,4 @@
 df34dcc9ac072ffd0945e5a1f3eb7987e8275375 release-1.21.0
 a68ac0677f8553b1f84d357bc9da114731ab5f47 release-1.21.1
 bfbc52374adcbf2f9060afd62de940f6fab3bba5 release-1.21.2
+2217a9c1d0b86026f22700b3c089545db1964f55 release-1.21.3
diff --git a/BUILD b/BUILD
index 8ca4e1c..807986d 100644
--- a/BUILD
+++ b/BUILD
@@ -1538,5 +1538,5 @@
     preinst = "@nginx_pkgoss//:debian_preinst",
     prerm = "@nginx_pkgoss//:debian_prerm",
     section = "httpd",
-    version = "1.21.2",
+    version = "1.21.3",
 )
diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl
index 7d3f324..dacedbc 100644
--- a/bazel/repositories.bzl
+++ b/bazel/repositories.bzl
@@ -34,9 +34,9 @@
     new_git_repository(
         name = "nginx_pkgoss",
         build_file = "@nginx//bazel/external:nginx_pkgoss.BUILD",
-        commit = "39dacf6a68cc1af4b1110f3bc46ade6026e4a387",  # nginx-1.21.2
+        commit = "48ec648c7fd9157a68f209b60e7abb25350d1ce5",  # nginx-1.21.3
         remote = "https://nginx.googlesource.com/nginx-pkgoss",
-        shallow_since = "1630424319 +0300",
+        shallow_since = "1631031305 +0300",
     )
 
     http_archive(
diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml
index fb64a47..65772d0 100644
--- a/docs/xml/nginx/changes.xml
+++ b/docs/xml/nginx/changes.xml
@@ -5,6 +5,33 @@
 <change_log title="nginx">
 
 
+<changes ver="1.21.3" date="2021-09-07">
+
+<change type="change">
+<para lang="ru">
+оптимизация чтения тела запроса
+при использовании HTTP/2.
+</para>
+<para lang="en">
+optimization of client request body reading
+when using HTTP/2.
+</para>
+</change>
+
+<change type="bugfix">
+<para lang="ru">
+во внутреннем API для обработки тела запроса
+при использовании HTTP/2 и буферизации обрабатываемых данных.
+</para>
+<para lang="en">
+in request body filters internal API
+when using HTTP/2 and buffering of the data being processed.
+</para>
+</change>
+
+</changes>
+
+
 <changes ver="1.21.2" date="2021-08-31">
 
 <change type="change">
diff --git a/src/core/nginx.h b/src/core/nginx.h
index 70b1b87..f60ced9 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -13,8 +13,8 @@
 #define NGINX_NAME         "nginx"
 #endif
 
-#define nginx_version      1021002
-#define NGINX_VERSION      "1.21.2"
+#define nginx_version      1021003
+#define NGINX_VERSION      "1.21.3"
 #define NGINX_VER          NGINX_NAME "/" NGINX_VERSION
 
 #ifdef NGX_BUILD
diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c
index aa4a725..26f529f 100644
--- a/src/http/v2/ngx_http_v2.c
+++ b/src/http/v2/ngx_http_v2.c
@@ -1093,7 +1093,7 @@
 ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos,
     u_char *end)
 {
-    size_t                   size, window;
+    size_t                   size;
     ngx_buf_t               *buf;
     ngx_int_t                rc;
     ngx_connection_t        *fc;
@@ -1149,32 +1149,6 @@
             ngx_http_finalize_request(r, rc);
         }
 
-        if (rc == NGX_AGAIN && !stream->no_flow_control) {
-            buf = r->request_body->buf;
-            window = buf->end - buf->last;
-
-            window -= h2c->state.length - size;
-
-            if (window < stream->recv_window) {
-                ngx_log_error(NGX_LOG_ALERT, h2c->connection->log, 0,
-                              "http2 negative window update");
-                return ngx_http_v2_connection_error(h2c,
-                                                    NGX_HTTP_V2_INTERNAL_ERROR);
-            }
-
-            if (window > stream->recv_window) {
-                if (ngx_http_v2_send_window_update(h2c, stream->node->id,
-                                                   window - stream->recv_window)
-                    == NGX_ERROR)
-                {
-                    return ngx_http_v2_connection_error(h2c,
-                                                    NGX_HTTP_V2_INTERNAL_ERROR);
-                }
-
-                stream->recv_window = window;
-            }
-        }
-
         ngx_http_run_posted_requests(fc);
 
     } else if (size) {
@@ -4257,8 +4231,8 @@
 
                 /* update chains */
 
-                ngx_log_error(NGX_LOG_DEBUG, fc->log, 0,
-                              "http2 body update chains");
+                ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0,
+                               "http2 body update chains");
 
                 rc = ngx_http_v2_filter_request_body(r);
 
@@ -4298,22 +4272,6 @@
                 rb->rest = 0;
             }
 
-            if (r->request_body_no_buffering) {
-                break;
-            }
-
-            /* pass buffer to request body filter chain */
-
-            rc = ngx_http_v2_filter_request_body(r);
-
-            if (rc != NGX_OK) {
-                return rc;
-            }
-
-            if (rb->rest == 0) {
-                break;
-            }
-
             if (size == 0) {
                 break;
             }
@@ -4322,6 +4280,14 @@
         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0,
                        "http2 request body rest %O", rb->rest);
 
+        if (flush) {
+            rc = ngx_http_v2_filter_request_body(r);
+
+            if (rc != NGX_OK) {
+                return rc;
+            }
+        }
+
         if (rb->rest == 0 && rb->last_saved) {
             break;
         }
@@ -4330,9 +4296,8 @@
             clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
             ngx_add_timer(fc->read, clcf->client_body_timeout);
 
-            if (r->request_body_no_buffering) {
+            if (!flush) {
                 ngx_post_event(fc->read, &ngx_posted_events);
-                return NGX_AGAIN;
             }
 
             return NGX_AGAIN;
@@ -4344,7 +4309,10 @@
     }
 
     if (r->request_body_no_buffering) {
-        ngx_post_event(fc->read, &ngx_posted_events);
+        if (!flush) {
+            ngx_post_event(fc->read, &ngx_posted_events);
+        }
+
         return NGX_OK;
     }
 
@@ -4498,14 +4466,26 @@
         return;
     }
 
+    if (r->stream->no_flow_control) {
+        return;
+    }
+
     if (r->request_body->rest == 0) {
         return;
     }
 
+    if (r->request_body->busy != NULL) {
+        return;
+    }
+
     stream = r->stream;
     h2c = stream->connection;
 
     buf = r->request_body->buf;
+
+    buf->pos = buf->start;
+    buf->last = buf->start;
+
     window = buf->end - buf->start;
 
     if (h2c->state.stream == stream) {
@@ -4554,7 +4534,6 @@
     ngx_connection_t          *fc;
     ngx_http_v2_stream_t      *stream;
     ngx_http_v2_connection_t  *h2c;
-    ngx_http_core_loc_conf_t  *clcf;
 
     stream = r->stream;
     fc = r->connection;
@@ -4578,14 +4557,14 @@
         return NGX_HTTP_BAD_REQUEST;
     }
 
-    rc = ngx_http_v2_filter_request_body(r);
+    rc = ngx_http_v2_process_request_body(r, NULL, 0, r->stream->in_closed, 1);
 
-    if (rc != NGX_OK) {
+    if (rc != NGX_OK && rc != NGX_AGAIN) {
         stream->skip_data = 1;
         return rc;
     }
 
-    if (r->request_body->rest == 0 && r->request_body->last_saved) {
+    if (rc == NGX_OK) {
         return NGX_OK;
     }
 
@@ -4633,11 +4612,6 @@
         return NGX_HTTP_INTERNAL_SERVER_ERROR;
     }
 
-    if (stream->recv_window == 0) {
-        clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-        ngx_add_timer(fc->read, clcf->client_body_timeout);
-    }
-
     stream->recv_window = window;
 
     return NGX_AGAIN;