diff src/http/v3/ngx_http_v3_request.c @ 9081:c851a2ed5ce8 quic

HTTP/3: "quic" parameter of "listen" directive. Now "listen" directve has a new "quic" parameter which enables QUIC protocol for the address. Further, to enable HTTP/3, a new directive "http3" is introduced. The hq-interop protocol is enabled by "http3_hq" as before. Now application protocol is chosen by ALPN. Previously used "http3" parameter of "listen" is deprecated.
author Roman Arutyunyan <arut@nginx.com>
date Mon, 27 Feb 2023 14:00:56 +0400
parents 6bb884dc7291
children 69bae2437d74
line wrap: on
line diff
--- a/src/http/v3/ngx_http_v3_request.c
+++ b/src/http/v3/ngx_http_v3_request.c
@@ -110,7 +110,10 @@ ngx_http_v3_init_stream(ngx_connection_t
 ngx_int_t
 ngx_http_v3_init(ngx_connection_t *c)
 {
+    unsigned int               len;
+    const unsigned char       *data;
     ngx_http_v3_session_t     *h3c;
+    ngx_http_v3_srv_conf_t    *h3scf;
     ngx_http_core_loc_conf_t  *clcf;
 
     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 init");
@@ -119,11 +122,23 @@ ngx_http_v3_init(ngx_connection_t *c)
     clcf = ngx_http_v3_get_module_loc_conf(c, ngx_http_core_module);
     ngx_add_timer(&h3c->keepalive, clcf->keepalive_timeout);
 
-#if (NGX_HTTP_V3_HQ)
-    if (h3c->hq) {
-        return NGX_OK;
+    h3scf = ngx_http_v3_get_module_srv_conf(c, ngx_http_v3_module);
+
+    if (h3scf->enable_hq) {
+        if (!h3scf->enable) {
+            h3c->hq = 1;
+            return NGX_OK;
+        }
+
+        SSL_get0_alpn_selected(c->ssl->connection, &data, &len);
+
+        if (len == sizeof(NGX_HTTP_V3_HQ_PROTO) - 1
+            && ngx_strncmp(data, NGX_HTTP_V3_HQ_PROTO, len) == 0)
+        {
+            h3c->hq = 1;
+            return NGX_OK;
+        }
     }
-#endif
 
     return ngx_http_v3_send_settings(c);
 }
@@ -147,10 +162,7 @@ ngx_http_v3_shutdown(ngx_connection_t *c
     if (!h3c->goaway) {
         h3c->goaway = 1;
 
-#if (NGX_HTTP_V3_HQ)
-        if (!h3c->hq)
-#endif
-        {
+        if (!h3c->hq) {
             (void) ngx_http_v3_send_goaway(c, h3c->next_request_id);
         }
 
@@ -205,10 +217,7 @@ ngx_http_v3_init_request_stream(ngx_conn
     {
         h3c->goaway = 1;
 
-#if (NGX_HTTP_V3_HQ)
-        if (!h3c->hq)
-#endif
-        {
+        if (!h3c->hq) {
             if (ngx_http_v3_send_goaway(c, h3c->next_request_id) != NGX_OK) {
                 ngx_http_close_connection(c);
                 return;
@@ -236,10 +245,7 @@ ngx_http_v3_init_request_stream(ngx_conn
 
     rev = c->read;
 
-#if (NGX_HTTP_V3_HQ)
-    if (!h3c->hq)
-#endif
-    {
+    if (!h3c->hq) {
         rev->handler = ngx_http_v3_wait_request_handler;
         c->write->handler = ngx_http_empty_handler;
     }
@@ -398,14 +404,14 @@ ngx_http_v3_wait_request_handler(ngx_eve
 void
 ngx_http_v3_reset_stream(ngx_connection_t *c)
 {
+    ngx_http_v3_session_t   *h3c;
     ngx_http_v3_srv_conf_t  *h3scf;
 
     h3scf = ngx_http_v3_get_module_srv_conf(c, ngx_http_v3_module);
 
-    if (h3scf->max_table_capacity > 0 && !c->read->eof
-#if (NGX_HTTP_V3_HQ)
-        && !h3scf->hq
-#endif
+    h3c = ngx_http_v3_get_session(c);
+
+    if (h3scf->max_table_capacity > 0 && !c->read->eof && !h3c->hq
         && (c->quic->id & NGX_QUIC_STREAM_UNIDIRECTIONAL) == 0)
     {
         (void) ngx_http_v3_send_cancel_stream(c, c->quic->id);
@@ -993,9 +999,11 @@ failed:
 static ngx_int_t
 ngx_http_v3_process_request_header(ngx_http_request_t *r)
 {
-    ssize_t            n;
-    ngx_buf_t         *b;
-    ngx_connection_t  *c;
+    ssize_t                  n;
+    ngx_buf_t               *b;
+    ngx_connection_t        *c;
+    ngx_http_v3_session_t   *h3c;
+    ngx_http_v3_srv_conf_t  *h3scf;
 
     c = r->connection;
 
@@ -1003,6 +1011,19 @@ ngx_http_v3_process_request_header(ngx_h
         return NGX_ERROR;
     }
 
+    h3c = ngx_http_v3_get_session(c);
+    h3scf = ngx_http_get_module_srv_conf(r, ngx_http_v3_module);
+
+    if (!r->http_connection->addr_conf->http3) {
+        if ((h3c->hq && !h3scf->enable_hq) || (!h3c->hq && !h3scf->enable)) {
+            ngx_log_error(NGX_LOG_INFO, c->log, 0,
+                          "client attempted to request the server name "
+                          "for which the negotiated protocol is disabled");
+            ngx_http_finalize_request(r, NGX_HTTP_MISDIRECTED_REQUEST);
+            return NGX_ERROR;
+        }
+    }
+
     if (ngx_http_v3_construct_cookie_header(r) != NGX_OK) {
         return NGX_ERROR;
     }