[PATCH 1 of 2] HTTP/3: use parent QUIC connection as argument when possible

Roman Arutyunyan arut at nginx.com
Thu Nov 18 09:52:14 UTC 2021


# HG changeset patch
# User Roman Arutyunyan <arut at nginx.com>
# Date 1637160358 -10800
#      Wed Nov 17 17:45:58 2021 +0300
# Branch quic
# Node ID b844c77ff22218a4863d1d926bcaaa0b043c8af5
# Parent  41caf541011045612975b7bb8423a18fd424df77
HTTP/3: use parent QUIC connection as argument when possible.

Functions in ngx_http_v3.c, ngx_http_v3_streams.c and ngx_http_v3_tables.c
now receive parent QUIC connection as the first argument instead of QUIC stream
connection.  It makes sense since they are not related to a QUIC stream and
operate connection-wise.

Also, ngx_quic_open_stream() now receives parent QUIC connection instead of
QUIC stream connection for the same reason.

Also, ngx_http_v3_finalize_connection() and ngx_http_v3_shutdown_connection()
macros are eliminated.  Instead, ngx_quic_finalize_connection() and
ngx_quic_shutdown_connection() are called directly with the parent QUIC
connection.

diff --git a/src/event/quic/ngx_event_quic_streams.c b/src/event/quic/ngx_event_quic_streams.c
--- a/src/event/quic/ngx_event_quic_streams.c
+++ b/src/event/quic/ngx_event_quic_streams.c
@@ -37,11 +37,10 @@ ngx_connection_t *
 ngx_quic_open_stream(ngx_connection_t *c, ngx_uint_t bidi)
 {
     uint64_t                id;
-    ngx_quic_stream_t      *qs, *nqs;
+    ngx_quic_stream_t      *qs;
     ngx_quic_connection_t  *qc;
 
-    qs = c->quic;
-    qc = ngx_quic_get_connection(qs->parent);
+    qc = ngx_quic_get_connection(c);
 
     if (bidi) {
         if (qc->streams.server_streams_bidi
@@ -87,12 +86,12 @@ ngx_quic_open_stream(ngx_connection_t *c
         qc->streams.server_streams_uni++;
     }
 
-    nqs = ngx_quic_create_stream(qs->parent, id);
-    if (nqs == NULL) {
+    qs = ngx_quic_create_stream(c, id);
+    if (qs == NULL) {
         return NULL;
     }
 
-    return nqs->connection;
+    return qs->connection;
 }
 
 
diff --git a/src/http/modules/ngx_http_quic_module.h b/src/http/modules/ngx_http_quic_module.h
--- a/src/http/modules/ngx_http_quic_module.h
+++ b/src/http/modules/ngx_http_quic_module.h
@@ -19,7 +19,8 @@
 
 
 #define ngx_http_quic_get_connection(c)                                       \
-    ((ngx_http_connection_t *) (c)->quic->parent->data)
+    ((ngx_http_connection_t *) ((c)->quic ? (c)->quic->parent->data           \
+                                          : (c)->data))
 
 
 ngx_int_t ngx_http_quic_init(ngx_connection_t *c);
diff --git a/src/http/v3/ngx_http_v3.c b/src/http/v3/ngx_http_v3.c
--- a/src/http/v3/ngx_http_v3.c
+++ b/src/http/v3/ngx_http_v3.c
@@ -17,13 +17,11 @@ static void ngx_http_v3_cleanup_session(
 ngx_int_t
 ngx_http_v3_init_session(ngx_connection_t *c)
 {
-    ngx_connection_t       *pc;
     ngx_pool_cleanup_t     *cln;
     ngx_http_connection_t  *hc;
     ngx_http_v3_session_t  *h3c;
 
-    pc = c->quic->parent;
-    hc = pc->data;
+    hc = c->data;
 
     if (hc->v3_session) {
         return NGX_OK;
@@ -31,7 +29,7 @@ ngx_http_v3_init_session(ngx_connection_
 
     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 init session");
 
-    h3c = ngx_pcalloc(pc->pool, sizeof(ngx_http_v3_session_t));
+    h3c = ngx_pcalloc(c->pool, sizeof(ngx_http_v3_session_t));
     if (h3c == NULL) {
         goto failed;
     }
@@ -42,12 +40,12 @@ ngx_http_v3_init_session(ngx_connection_
     ngx_queue_init(&h3c->blocked);
     ngx_queue_init(&h3c->pushing);
 
-    h3c->keepalive.log = pc->log;
-    h3c->keepalive.data = pc;
+    h3c->keepalive.log = c->log;
+    h3c->keepalive.data = c;
     h3c->keepalive.handler = ngx_http_v3_keepalive_handler;
     h3c->keepalive.cancelable = 1;
 
-    cln = ngx_pool_cleanup_add(pc->pool, 0);
+    cln = ngx_pool_cleanup_add(c->pool, 0);
     if (cln == NULL) {
         goto failed;
     }
@@ -63,8 +61,8 @@ failed:
 
     ngx_log_error(NGX_LOG_ERR, c->log, 0, "failed to create http3 session");
 
-    ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_INTERNAL_ERROR,
-                                    "failed to create http3 session");
+    ngx_quic_finalize_connection(c, NGX_HTTP_V3_ERR_INTERNAL_ERROR,
+                                 "failed to create http3 session");
     return NGX_ERROR;
 }
 
@@ -106,8 +104,8 @@ ngx_http_v3_check_flood(ngx_connection_t
     if (h3c->total_bytes / 8 > h3c->payload_bytes + 1048576) {
         ngx_log_error(NGX_LOG_INFO, c->log, 0, "http3 flood detected");
 
-        ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_NO_ERROR,
-                                        "HTTP/3 flood detected");
+        ngx_quic_finalize_connection(c, NGX_HTTP_V3_ERR_NO_ERROR,
+                                     "HTTP/3 flood detected");
         return NGX_ERROR;
     }
 
diff --git a/src/http/v3/ngx_http_v3.h b/src/http/v3/ngx_http_v3.h
--- a/src/http/v3/ngx_http_v3.h
+++ b/src/http/v3/ngx_http_v3.h
@@ -84,12 +84,6 @@
     ngx_http_get_module_srv_conf(ngx_http_quic_get_connection(c)->conf_ctx,     \
                                  module)
 
-#define ngx_http_v3_finalize_connection(c, code, reason)                      \
-    ngx_quic_finalize_connection(c->quic->parent, code, reason)
-
-#define ngx_http_v3_shutdown_connection(c, code, reason)                      \
-    ngx_quic_shutdown_connection(c->quic->parent, code, reason)
-
 #define ngx_http_v3_connection(c)                                             \
     ((c)->quic ? ngx_http_quic_get_connection(c)->addr_conf->http3 : 0)
 
diff --git a/src/http/v3/ngx_http_v3_filter_module.c b/src/http/v3/ngx_http_v3_filter_module.c
--- a/src/http/v3/ngx_http_v3_filter_module.c
+++ b/src/http/v3/ngx_http_v3_filter_module.c
@@ -907,7 +907,7 @@ ngx_http_v3_create_push_request(ngx_http
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
                    "http3 create push request id:%uL", push_id);
 
-    c = ngx_http_v3_create_push_stream(pc, push_id);
+    c = ngx_http_v3_create_push_stream(pc->quic->parent, push_id);
     if (c == NULL) {
         return NGX_ABORT;
     }
diff --git a/src/http/v3/ngx_http_v3_parse.c b/src/http/v3/ngx_http_v3_parse.c
--- a/src/http/v3/ngx_http_v3_parse.c
+++ b/src/http/v3/ngx_http_v3_parse.c
@@ -353,7 +353,8 @@ ngx_http_v3_parse_headers(ngx_connection
 
         case sw_verify:
 
-            rc = ngx_http_v3_check_insert_count(c, st->prefix.insert_count);
+            rc = ngx_http_v3_check_insert_count(c->quic->parent,
+                                                st->prefix.insert_count);
             if (rc != NGX_OK) {
                 return rc;
             }
@@ -392,7 +393,9 @@ done:
     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse headers done");
 
     if (st->prefix.insert_count > 0) {
-        if (ngx_http_v3_send_ack_section(c, c->quic->id) != NGX_OK) {
+        if (ngx_http_v3_send_ack_section(c->quic->parent, c->quic->id)
+            != NGX_OK)
+        {
             return NGX_ERROR;
         }
     }
@@ -466,7 +469,7 @@ ngx_http_v3_parse_field_section_prefix(n
 
 done:
 
-    rc = ngx_http_v3_decode_insert_count(c, &st->insert_count);
+    rc = ngx_http_v3_decode_insert_count(c->quic->parent, &st->insert_count);
     if (rc != NGX_OK) {
         return rc;
     }
@@ -1102,14 +1105,16 @@ ngx_http_v3_parse_lookup(ngx_connection_
     u_char  *p;
 
     if (!dynamic) {
-        if (ngx_http_v3_lookup_static(c, index, name, value) != NGX_OK) {
+        if (ngx_http_v3_lookup_static(c->quic->parent, index, name, value)
+            != NGX_OK)
+        {
             return NGX_HTTP_V3_ERR_DECOMPRESSION_FAILED;
         }
 
         return NGX_OK;
     }
 
-    if (ngx_http_v3_lookup(c, index, name, value) != NGX_OK) {
+    if (ngx_http_v3_lookup(c->quic->parent, index, name, value) != NGX_OK) {
         return NGX_HTTP_V3_ERR_DECOMPRESSION_FAILED;
     }
 
@@ -1264,7 +1269,7 @@ ngx_http_v3_parse_control(ngx_connection
                 return rc;
             }
 
-            rc = ngx_http_v3_cancel_push(c, st->vlint.value);
+            rc = ngx_http_v3_cancel_push(c->quic->parent, st->vlint.value);
             if (rc != NGX_OK) {
                 return rc;
             }
@@ -1310,7 +1315,7 @@ ngx_http_v3_parse_control(ngx_connection
                 return rc;
             }
 
-            rc = ngx_http_v3_set_max_push_id(c, st->vlint.value);
+            rc = ngx_http_v3_set_max_push_id(c->quic->parent, st->vlint.value);
             if (rc != NGX_OK) {
                 return rc;
             }
@@ -1334,7 +1339,7 @@ ngx_http_v3_parse_control(ngx_connection
                 return rc;
             }
 
-            rc = ngx_http_v3_goaway(c, st->vlint.value);
+            rc = ngx_http_v3_goaway(c->quic->parent, st->vlint.value);
             if (rc != NGX_OK) {
                 return rc;
             }
@@ -1398,7 +1403,9 @@ ngx_http_v3_parse_settings(ngx_connectio
                 return rc;
             }
 
-            if (ngx_http_v3_set_param(c, st->id, st->vlint.value) != NGX_OK) {
+            if (ngx_http_v3_set_param(c->quic->parent, st->id, st->vlint.value)
+                != NGX_OK)
+            {
                 return NGX_HTTP_V3_ERR_SETTINGS_ERROR;
             }
 
@@ -1493,7 +1500,7 @@ ngx_http_v3_parse_encoder(ngx_connection
                 return rc;
             }
 
-            rc = ngx_http_v3_set_capacity(c, st->pint.value);
+            rc = ngx_http_v3_set_capacity(c->quic->parent, st->pint.value);
             if (rc != NGX_OK) {
                 return rc;
             }
@@ -1508,7 +1515,7 @@ ngx_http_v3_parse_encoder(ngx_connection
                 return rc;
             }
 
-            rc = ngx_http_v3_duplicate(c, st->pint.value);
+            rc = ngx_http_v3_duplicate(c->quic->parent, st->pint.value);
             if (rc != NGX_OK) {
                 return rc;
             }
@@ -1613,7 +1620,8 @@ done:
                    st->dynamic ? "dynamic" : "static",
                    st->index, &st->value);
 
-    rc = ngx_http_v3_ref_insert(c, st->dynamic, st->index, &st->value);
+    rc = ngx_http_v3_ref_insert(c->quic->parent, st->dynamic, st->index,
+                                &st->value);
     if (rc != NGX_OK) {
         return rc;
     }
@@ -1731,7 +1739,7 @@ done:
                    "http3 parse field iln done \"%V\":\"%V\"",
                    &st->name, &st->value);
 
-    rc = ngx_http_v3_insert(c, &st->name, &st->value);
+    rc = ngx_http_v3_insert(c->quic->parent, &st->name, &st->value);
     if (rc != NGX_OK) {
         return rc;
     }
@@ -1793,7 +1801,7 @@ ngx_http_v3_parse_decoder(ngx_connection
                 return rc;
             }
 
-            rc = ngx_http_v3_ack_section(c, st->pint.value);
+            rc = ngx_http_v3_ack_section(c->quic->parent, st->pint.value);
             if (rc != NGX_OK) {
                 return rc;
             }
@@ -1808,7 +1816,7 @@ ngx_http_v3_parse_decoder(ngx_connection
                 return rc;
             }
 
-            rc = ngx_http_v3_cancel_stream(c, st->pint.value);
+            rc = ngx_http_v3_cancel_stream(c->quic->parent, st->pint.value);
             if (rc != NGX_OK) {
                 return rc;
             }
@@ -1823,7 +1831,7 @@ ngx_http_v3_parse_decoder(ngx_connection
                 return rc;
             }
 
-            rc = ngx_http_v3_inc_insert_count(c, st->pint.value);
+            rc = ngx_http_v3_inc_insert_count(c->quic->parent, st->pint.value);
             if (rc != NGX_OK) {
                 return rc;
             }
diff --git a/src/http/v3/ngx_http_v3_request.c b/src/http/v3/ngx_http_v3_request.c
--- a/src/http/v3/ngx_http_v3_request.c
+++ b/src/http/v3/ngx_http_v3_request.c
@@ -61,7 +61,7 @@ ngx_http_v3_init(ngx_connection_t *c)
     ngx_http_core_loc_conf_t  *clcf;
     ngx_http_core_srv_conf_t  *cscf;
 
-    if (ngx_http_v3_init_session(c) != NGX_OK) {
+    if (ngx_http_v3_init_session(c->quic->parent) != NGX_OK) {
         ngx_http_close_connection(c);
         return;
     }
@@ -84,8 +84,9 @@ ngx_http_v3_init(ngx_connection_t *c)
     n = c->quic->id >> 2;
 
     if (n >= clcf->keepalive_requests * 2) {
-        ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_EXCESSIVE_LOAD,
-                                        "too many requests per connection");
+        ngx_quic_finalize_connection(c->quic->parent,
+                                     NGX_HTTP_V3_ERR_EXCESSIVE_LOAD,
+                                     "too many requests per connection");
         ngx_http_close_connection(c);
         return;
     }
@@ -104,13 +105,13 @@ ngx_http_v3_init(ngx_connection_t *c)
     {
         h3c->goaway = 1;
 
-        if (ngx_http_v3_send_goaway(c, (n + 1) << 2) != NGX_OK) {
+        if (ngx_http_v3_send_goaway(c->quic->parent, (n + 1) << 2) != NGX_OK) {
             ngx_http_close_connection(c);
             return;
         }
 
-        ngx_http_v3_shutdown_connection(c, NGX_HTTP_V3_ERR_NO_ERROR,
-                                        "reached maximum number of requests");
+        ngx_quic_shutdown_connection(c->quic->parent, NGX_HTTP_V3_ERR_NO_ERROR,
+                                     "reached maximum number of requests");
     }
 
     rev = c->read;
@@ -284,7 +285,7 @@ ngx_http_v3_reset_connection(ngx_connect
     h3scf = ngx_http_v3_get_module_srv_conf(c, ngx_http_v3_module);
 
     if (h3scf->max_table_capacity > 0 && !c->read->eof) {
-        (void) ngx_http_v3_send_cancel_stream(c, c->quic->id);
+        (void) ngx_http_v3_send_cancel_stream(c->quic->parent, c->quic->id);
     }
 
     if (c->timedout) {
@@ -416,7 +417,7 @@ ngx_http_v3_process_request(ngx_event_t 
         r->request_length += b->pos - p;
         h3c->total_bytes += b->pos - p;
 
-        if (ngx_http_v3_check_flood(c) != NGX_OK) {
+        if (ngx_http_v3_check_flood(c->quic->parent) != NGX_OK) {
             ngx_http_close_request(r, NGX_HTTP_CLOSE);
             break;
         }
@@ -1266,7 +1267,9 @@ ngx_http_v3_request_body_filter(ngx_http
                 r->request_length += cl->buf->pos - p;
                 h3c->total_bytes += cl->buf->pos - p;
 
-                if (ngx_http_v3_check_flood(r->connection) != NGX_OK) {
+                if (ngx_http_v3_check_flood(r->connection->quic->parent)
+                    != NGX_OK)
+                {
                     return NGX_HTTP_CLOSE;
                 }
 
diff --git a/src/http/v3/ngx_http_v3_streams.c b/src/http/v3/ngx_http_v3_streams.c
--- a/src/http/v3/ngx_http_v3_streams.c
+++ b/src/http/v3/ngx_http_v3_streams.c
@@ -46,9 +46,9 @@ ngx_http_v3_init_uni_stream(ngx_connecti
     n = c->quic->id >> 2;
 
     if (n >= h3scf->max_uni_streams) {
-        ngx_http_v3_finalize_connection(c,
-                                      NGX_HTTP_V3_ERR_STREAM_CREATION_ERROR,
-                                      "reached maximum number of uni streams");
+        ngx_quic_finalize_connection(c->quic->parent,
+                                     NGX_HTTP_V3_ERR_STREAM_CREATION_ERROR,
+                                     "reached maximum number of uni streams");
         c->data = NULL;
         ngx_http_v3_close_uni_stream(c);
         return;
@@ -58,9 +58,9 @@ ngx_http_v3_init_uni_stream(ngx_connecti
 
     us = ngx_pcalloc(c->pool, sizeof(ngx_http_v3_uni_stream_t));
     if (us == NULL) {
-        ngx_http_v3_finalize_connection(c,
-                                        NGX_HTTP_V3_ERR_INTERNAL_ERROR,
-                                        "memory allocation error");
+        ngx_quic_finalize_connection(c->quic->parent,
+                                     NGX_HTTP_V3_ERR_INTERNAL_ERROR,
+                                     "memory allocation error");
         c->data = NULL;
         ngx_http_v3_close_uni_stream(c);
         return;
@@ -216,7 +216,7 @@ ngx_http_v3_uni_read_handler(ngx_event_t
         h3c = ngx_http_v3_get_session(c);
         h3c->total_bytes += n;
 
-        if (ngx_http_v3_check_flood(c) != NGX_OK) {
+        if (ngx_http_v3_check_flood(c->quic->parent) != NGX_OK) {
             ngx_http_v3_close_uni_stream(c);
             return;
         }
@@ -249,7 +249,7 @@ ngx_http_v3_uni_read_handler(ngx_event_t
 
 failed:
 
-    ngx_http_v3_finalize_connection(c, rc, "stream error");
+    ngx_quic_finalize_connection(c->quic->parent, rc, "stream error");
     ngx_http_v3_close_uni_stream(c);
 }
 
@@ -264,8 +264,8 @@ ngx_http_v3_dummy_write_handler(ngx_even
     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 dummy write handler");
 
     if (ngx_handle_write_event(wev, 0) != NGX_OK) {
-        ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_INTERNAL_ERROR,
-                                        NULL);
+        ngx_quic_finalize_connection(c->quic->parent,
+                                     NGX_HTTP_V3_ERR_INTERNAL_ERROR, NULL);
         ngx_http_v3_close_uni_stream(c);
     }
 }
@@ -325,8 +325,8 @@ failed:
 
     ngx_log_error(NGX_LOG_ERR, c->log, 0, "failed to create push stream");
 
-    ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_STREAM_CREATION_ERROR,
-                                    "failed to create push stream");
+    ngx_quic_finalize_connection(c, NGX_HTTP_V3_ERR_STREAM_CREATION_ERROR,
+                                 "failed to create push stream");
     if (sc) {
         ngx_http_v3_close_uni_stream(sc);
     }
@@ -418,8 +418,8 @@ failed:
 
     ngx_log_error(NGX_LOG_ERR, c->log, 0, "failed to create server stream");
 
-    ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_STREAM_CREATION_ERROR,
-                                    "failed to create server stream");
+    ngx_quic_finalize_connection(c, NGX_HTTP_V3_ERR_STREAM_CREATION_ERROR,
+                                 "failed to create server stream");
     if (sc) {
         ngx_http_v3_close_uni_stream(sc);
     }
@@ -476,8 +476,8 @@ failed:
 
     ngx_log_error(NGX_LOG_ERR, c->log, 0, "failed to send settings");
 
-    ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_EXCESSIVE_LOAD,
-                                    "failed to send settings");
+    ngx_quic_finalize_connection(c, NGX_HTTP_V3_ERR_EXCESSIVE_LOAD,
+                                 "failed to send settings");
     ngx_http_v3_close_uni_stream(cc);
 
     return NGX_ERROR;
@@ -518,8 +518,8 @@ failed:
 
     ngx_log_error(NGX_LOG_ERR, c->log, 0, "failed to send goaway");
 
-    ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_EXCESSIVE_LOAD,
-                                    "failed to send goaway");
+    ngx_quic_finalize_connection(c, NGX_HTTP_V3_ERR_EXCESSIVE_LOAD,
+                                 "failed to send goaway");
     ngx_http_v3_close_uni_stream(cc);
 
     return NGX_ERROR;
@@ -559,8 +559,8 @@ failed:
     ngx_log_error(NGX_LOG_ERR, c->log, 0,
                   "failed to send section acknowledgement");
 
-    ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_EXCESSIVE_LOAD,
-                                    "failed to send section acknowledgement");
+    ngx_quic_finalize_connection(c, NGX_HTTP_V3_ERR_EXCESSIVE_LOAD,
+                                 "failed to send section acknowledgement");
     ngx_http_v3_close_uni_stream(dc);
 
     return NGX_ERROR;
@@ -599,8 +599,8 @@ failed:
 
     ngx_log_error(NGX_LOG_ERR, c->log, 0, "failed to send stream cancellation");
 
-    ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_EXCESSIVE_LOAD,
-                                    "failed to send stream cancellation");
+    ngx_quic_finalize_connection(c, NGX_HTTP_V3_ERR_EXCESSIVE_LOAD,
+                                 "failed to send stream cancellation");
     ngx_http_v3_close_uni_stream(dc);
 
     return NGX_ERROR;
@@ -640,8 +640,8 @@ failed:
     ngx_log_error(NGX_LOG_ERR, c->log, 0,
                   "failed to send insert count increment");
 
-    ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_EXCESSIVE_LOAD,
-                                    "failed to send insert count increment");
+    ngx_quic_finalize_connection(c, NGX_HTTP_V3_ERR_EXCESSIVE_LOAD,
+                                 "failed to send insert count increment");
     ngx_http_v3_close_uni_stream(dc);
 
     return NGX_ERROR;
diff --git a/src/http/v3/ngx_http_v3_tables.c b/src/http/v3/ngx_http_v3_tables.c
--- a/src/http/v3/ngx_http_v3_tables.c
+++ b/src/http/v3/ngx_http_v3_tables.c
@@ -590,9 +590,9 @@ ngx_http_v3_check_insert_count(ngx_conne
             ngx_log_error(NGX_LOG_INFO, c->log, 0,
                           "client exceeded http3_max_blocked_streams limit");
 
-            ngx_http_v3_finalize_connection(c,
-                                          NGX_HTTP_V3_ERR_DECOMPRESSION_FAILED,
-                                          "too many blocked streams");
+            ngx_quic_finalize_connection(c,
+                                         NGX_HTTP_V3_ERR_DECOMPRESSION_FAILED,
+                                         "too many blocked streams");
             return NGX_HTTP_V3_ERR_DECOMPRESSION_FAILED;
         }
 


More information about the nginx-devel mailing list