Here is a more simple patch. And the temp buffer has also been freed.

Please make your comments. Thanks.


diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 89cfe77a..d97952bc 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -17,6 +17,10 @@ static ssize_t 
ngx_http_read_request_header(ngx_http_request_t *r);
 static ngx_int_t ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
     ngx_uint_t request_line);
 
+#if (NGX_HTTP_V2)
+static void ngx_http_wait_v2_preface_handler(ngx_event_t *rev);
+#endif
+
 static ngx_int_t ngx_http_process_header_line(ngx_http_request_t *r,
     ngx_table_elt_t *h, ngx_uint_t offset);
 static ngx_int_t ngx_http_process_unique_header_line(ngx_http_request_t *r,
@@ -321,7 +325,7 @@ ngx_http_init_connection(ngx_connection_t *c)
 
 #if (NGX_HTTP_V2)
     if (hc->addr_conf->http2) {
-        rev->handler = ngx_http_v2_init;
+        rev->handler = ngx_http_wait_v2_preface_handler;
     }
 #endif
 
@@ -377,6 +381,110 @@ ngx_http_init_connection(ngx_connection_t *c)
 }
 
 
+#if (NGX_HTTP_V2)
+static void
+ngx_http_wait_v2_preface_handler(ngx_event_t *rev)
+{
+    size_t                     size;
+    ssize_t                    n;
+    ngx_buf_t                 *b;
+    ngx_connection_t          *c;
+    static const u_char        preface[] = "PRI";
+
+    c = rev->data;
+    size = sizeof(preface) - 1;
+
+    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
+            "http wait h2 preface handler");
+
+    if (rev->timedout) {
+        ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
+        ngx_http_close_connection(c);
+        return;
+    }
+
+    if (c->close) {
+        ngx_http_close_connection(c);
+        return;
+    }
+
+    b = c->buffer;
+
+    if (b == NULL) {
+        b = ngx_create_temp_buf(c->pool, size);
+        if (b == NULL) {
+            ngx_http_close_connection(c);
+            return;
+        }
+
+        c->buffer = b;
+
+    } else if (b->start == NULL) {
+
+        b->start = ngx_palloc(c->pool, size);
+        if (b->start == NULL) {
+            ngx_http_close_connection(c);
+            return;
+        }
+
+        b->pos = b->start;
+        b->last = b->start;
+        b->end = b->last + size;
+    }
+
+    n = c->recv(c, b->last, size);
+
+    if (n == NGX_AGAIN) {
+
+        if (!rev->timer_set) {
+            ngx_add_timer(rev, c->listening->post_accept_timeout);
+            ngx_reusable_connection(c, 1);
+        }
+
+        if (ngx_handle_read_event(rev, 0) != NGX_OK) {
+            ngx_http_close_connection(c);
+            return;
+        }
+
+        /*
+         * We are trying to not hold c->buffer's memory for an idle connection.
+         */
+
+        if (ngx_pfree(c->pool, b->start) == NGX_OK) {
+            b->start = NULL;
+        }
+
+        return;
+    }
+
+    if (n == NGX_ERROR) {
+        ngx_http_close_connection(c);
+        return;
+    }
+
+    if (n == 0) {
+        ngx_log_error(NGX_LOG_INFO, c->log, 0,
+                      "client closed connection");
+        ngx_http_close_connection(c);
+        return;
+    }
+
+    b->last += n;
+
+    if (b->last == b->end) {
+        /* b will be freed in ngx_http_v2_init/ngx_http_wait_request_handler */
+
+        if (ngx_strncmp(b->start, preface, size) == 0) {
+            ngx_http_v2_init(rev);
+        } else {
+            rev->handler = ngx_http_wait_request_handler;
+            ngx_http_wait_request_handler(rev);
+        }
+    }
+}
+#endif
+
+
 static void
 ngx_http_wait_request_handler(ngx_event_t *rev)
 {
@@ -430,6 +538,22 @@ ngx_http_wait_request_handler(ngx_event_t *rev)
         b->pos = b->start;
         b->last = b->start;
         b->end = b->last + size;
+    } else {
+
+        p = ngx_palloc(c->pool, size);
+        if (p == NULL) {
+            ngx_http_close_connection(c);
+            return;
+        }
+
+        n = b->last - b->start;
+        ngx_memcpy(p, b->start, n);
+        ngx_pfree(c->pool, b->start);
+
+        b->start = p;
+        b->pos = b->start;
+        b->last = b->start + n;
+        b->end = b->last + size;
     }
 
     n = c->recv(c, b->last, size);
diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c
index d9df0f90..e36bf382 100644
--- a/src/http/v2/ngx_http_v2.c
+++ b/src/http/v2/ngx_http_v2.c
@@ -231,6 +231,8 @@ static ngx_http_v2_parse_header_t  
ngx_http_v2_parse_headers[] = {
 void
 ngx_http_v2_init(ngx_event_t *rev)
 {
+    size_t                     size;
+    ngx_buf_t                 *b;
     ngx_connection_t          *c;
     ngx_pool_cleanup_t        *cln;
     ngx_http_connection_t     *hc;
@@ -262,6 +264,23 @@ ngx_http_v2_init(ngx_event_t *rev)
         return;
     }
 
+    b = c->buffer;
+
+    if (b != NULL) {
+        size = b->last - b->start;
+
+        if (size > h2mcf->recv_buffer_size) {
+            size = h2mcf->recv_buffer_size;
+        }
+
+        ngx_memcpy(h2mcf->recv_buffer, b->start, size);
+        h2c->state.buffer_used = size;
+
+        ngx_pfree(c->pool, b->start);
+        ngx_pfree(c->pool, b);
+        c->buffer = NULL;
+    }
+
     h2c->connection = c;
     h2c->http_connection = hc;
 
@@ -381,13 +400,15 @@ ngx_http_v2_read_handler(ngx_event_t *rev)
     h2mcf = ngx_http_get_module_main_conf(h2c->http_connection->conf_ctx,
                                           ngx_http_v2_module);
 
-    available = h2mcf->recv_buffer_size - 2 * NGX_HTTP_V2_STATE_BUFFER_SIZE;
+    available = h2mcf->recv_buffer_size - h2c->state.buffer_used - 2 * 
NGX_HTTP_V2_STATE_BUFFER_SIZE;
 
     do {
         p = h2mcf->recv_buffer;
 
-        ngx_memcpy(p, h2c->state.buffer, NGX_HTTP_V2_STATE_BUFFER_SIZE);
         end = p + h2c->state.buffer_used;
+        if (h2c->state.buffer_used == 0) {
+            ngx_memcpy(p, h2c->state.buffer, NGX_HTTP_V2_STATE_BUFFER_SIZE);
+        }
 
         n = c->recv(c, end, available);
 


> On Mar 6, 2018, at 10:19, Haitao Lv <i...@lvht.net> wrote:
> 
> Hello, here is another patch(more sample) according Maxim Dounin advice.
> 
> Please offer your comment. Thanks.
> 
> diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
> index 89cfe77a..71bc7b59 100644
> --- a/src/http/ngx_http_request.c
> +++ b/src/http/ngx_http_request.c
> @@ -17,6 +17,10 @@ static ssize_t 
> ngx_http_read_request_header(ngx_http_request_t *r);
> static ngx_int_t ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
>     ngx_uint_t request_line);
> 
> +#if (NGX_HTTP_V2)
> +static void ngx_http_wait_v2_preface_handler(ngx_event_t *rev);
> +#endif
> +
> static ngx_int_t ngx_http_process_header_line(ngx_http_request_t *r,
>     ngx_table_elt_t *h, ngx_uint_t offset);
> static ngx_int_t ngx_http_process_unique_header_line(ngx_http_request_t *r,
> @@ -321,7 +325,7 @@ ngx_http_init_connection(ngx_connection_t *c)
> 
> #if (NGX_HTTP_V2)
>     if (hc->addr_conf->http2) {
> -        rev->handler = ngx_http_v2_init;
> +        rev->handler = ngx_http_wait_v2_preface_handler;
>     }
> #endif
> 
> @@ -377,6 +381,108 @@ ngx_http_init_connection(ngx_connection_t *c)
> }
> 
> 
> +#if (NGX_HTTP_V2)
> +static void
> +ngx_http_wait_v2_preface_handler(ngx_event_t *rev)
> +{
> +    size_t                     size;
> +    ssize_t                    n;
> +    ngx_buf_t                 *b;
> +    ngx_connection_t          *c;
> +
> +    c = rev->data;
> +
> +    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
> +            "http wait h2 preface handler");
> +
> +    if (rev->timedout) {
> +        ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed 
> out");
> +        ngx_http_close_connection(c);
> +        return;
> +    }
> +
> +    if (c->close) {
> +        ngx_http_close_connection(c);
> +        return;
> +    }
> +
> +    size = 5 /* strlen("PRI *") */;
> +
> +    b = c->buffer;
> +
> +    if (b == NULL) {
> +        b = ngx_create_temp_buf(c->pool, size);
> +        if (b == NULL) {
> +            ngx_http_close_connection(c);
> +            return;
> +        }
> +
> +        c->buffer = b;
> +
> +    } else if (b->start == NULL) {
> +
> +        b->start = ngx_palloc(c->pool, size);
> +        if (b->start == NULL) {
> +            ngx_http_close_connection(c);
> +            return;
> +        }
> +
> +        b->pos = b->start;
> +        b->last = b->start;
> +        b->end = b->last + size;
> +    }
> +
> +    n = c->recv(c, b->last, size);
> +
> +    if (n == NGX_AGAIN) {
> +
> +        if (!rev->timer_set) {
> +            ngx_add_timer(rev, c->listening->post_accept_timeout);
> +            ngx_reusable_connection(c, 1);
> +        }
> +
> +        if (ngx_handle_read_event(rev, 0) != NGX_OK) {
> +            ngx_http_close_connection(c);
> +            return;
> +        }
> +
> +        /*
> +         * We are trying to not hold c->buffer's memory for an idle 
> connection.
> +         */
> +
> +        if (ngx_pfree(c->pool, b->start) == NGX_OK) {
> +            b->start = NULL;
> +        }
> +
> +        return;
> +    }
> +
> +    if (n == NGX_ERROR) {
> +        ngx_http_close_connection(c);
> +        return;
> +    }
> +
> +    if (n == 0) {
> +        ngx_log_error(NGX_LOG_INFO, c->log, 0,
> +                      "client closed connection");
> +        ngx_http_close_connection(c);
> +        return;
> +    }
> +
> +    b->last += n;
> +
> +    if (b->last == b->end) {
> +        if (ngx_strncmp(b->start, "PRI *", 5) == 0) {
> +            ngx_http_v2_init_with_buf(rev, b);
> +        } else {
> +            rev->handler = ngx_http_wait_request_handler;
> +            ngx_http_wait_request_handler(rev);
> +        }
> +    }
> +}
> +#endif
> +
> +
> static void
> ngx_http_wait_request_handler(ngx_event_t *rev)
> {
> @@ -430,6 +536,21 @@ ngx_http_wait_request_handler(ngx_event_t *rev)
>         b->pos = b->start;
>         b->last = b->start;
>         b->end = b->last + size;
> +    } else {
> +
> +        p = ngx_palloc(c->pool, size);
> +        if (p == NULL) {
> +            ngx_http_close_connection(c);
> +            return;
> +        }
> +
> +        n = b->last - b->start;
> +        ngx_memcpy(p, b->start, n);
> +
> +        b->start = p;
> +        b->pos = b->start;
> +        b->last = b->start + n;
> +        b->end = b->last + size;
>     }
> 
>     n = c->recv(c, b->last, size);
> diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c
> index d9df0f90..a990c96f 100644
> --- a/src/http/v2/ngx_http_v2.c
> +++ b/src/http/v2/ngx_http_v2.c
> @@ -231,6 +231,14 @@ static ngx_http_v2_parse_header_t  
> ngx_http_v2_parse_headers[] = {
> void
> ngx_http_v2_init(ngx_event_t *rev)
> {
> +    ngx_http_v2_init_with_buf(rev, NULL);
> +}
> +
> +
> +void
> +ngx_http_v2_init_with_buf(ngx_event_t *rev, ngx_buf_t *buf)
> +{
> +    size_t                     size;
>     ngx_connection_t          *c;
>     ngx_pool_cleanup_t        *cln;
>     ngx_http_connection_t     *hc;
> @@ -262,6 +270,17 @@ ngx_http_v2_init(ngx_event_t *rev)
>         return;
>     }
> 
> +    if (buf != NULL) {
> +        size = buf->last - buf->start;
> +
> +        if (size > h2mcf->recv_buffer_size) {
> +            size = h2mcf->recv_buffer_size;
> +        }
> +
> +        ngx_memcpy(h2mcf->recv_buffer, buf->start, size);
> +        h2c->state.buffer_used = size;
> +    }
> +
>     h2c->connection = c;
>     h2c->http_connection = hc;
> 
> @@ -381,13 +400,16 @@ ngx_http_v2_read_handler(ngx_event_t *rev)
>     h2mcf = ngx_http_get_module_main_conf(h2c->http_connection->conf_ctx,
>                                           ngx_http_v2_module);
> 
> -    available = h2mcf->recv_buffer_size - 2 * NGX_HTTP_V2_STATE_BUFFER_SIZE;
> +    available = h2mcf->recv_buffer_size - h2c->state.buffer_used - 2 * 
> NGX_HTTP_V2_STATE_BUFFER_SIZE;
> 
>     do {
>         p = h2mcf->recv_buffer;
> 
> -        ngx_memcpy(p, h2c->state.buffer, NGX_HTTP_V2_STATE_BUFFER_SIZE);
>         end = p + h2c->state.buffer_used;
> +        if (h2c->state.buffer_used == 0) {
> +            ngx_memcpy(p, h2c->state.buffer, NGX_HTTP_V2_STATE_BUFFER_SIZE);
> +        }
> +
> 
>         n = c->recv(c, end, available);
> 
> diff --git a/src/http/v2/ngx_http_v2.h b/src/http/v2/ngx_http_v2.h
> index d89e8fef..7b223b29 100644
> --- a/src/http/v2/ngx_http_v2.h
> +++ b/src/http/v2/ngx_http_v2.h
> @@ -279,6 +279,7 @@ ngx_http_v2_queue_ordered_frame(ngx_http_v2_connection_t 
> *h2c,
> 
> 
> void ngx_http_v2_init(ngx_event_t *rev);
> +void ngx_http_v2_init_with_buf(ngx_event_t *rev, ngx_buf_t *buf);
> 
> ngx_int_t ngx_http_v2_read_request_body(ngx_http_request_t *r);
> ngx_int_t ngx_http_v2_read_unbuffered_request_body(ngx_http_request_t *r);
> 
> 
> _______________________________________________
> nginx-devel mailing list
> nginx-devel@nginx.org
> http://mailman.nginx.org/mailman/listinfo/nginx-devel



_______________________________________________
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel

Reply via email to