diff options
author | Glenn Strauss <gstrauss@gluelogic.com> | 2023-04-08 21:01:31 -0400 |
---|---|---|
committer | Glenn Strauss <gstrauss@gluelogic.com> | 2023-04-24 21:17:29 -0400 |
commit | 723176fa3f4e499554dc9c98563dd4eb1a8a9150 (patch) | |
tree | 6be5af17e086fa1f949220284c65ddc29330c1a1 /src/h2.c | |
parent | fdb7ffed88b9dfe09a51e7fb58e5ddfe938c1ec9 (diff) | |
download | lighttpd-git-723176fa3f4e499554dc9c98563dd4eb1a8a9150.tar.gz |
[core] connection_check_upgrade() h2_upgrade_h2c()
separate generic HTTP handling of Upgrade request header
from handling of Upgrade: h2c
Diffstat (limited to 'src/h2.c')
-rw-r--r-- | src/h2.c | 99 |
1 files changed, 35 insertions, 64 deletions
@@ -1929,7 +1929,7 @@ h2_read_client_connection_preface (struct connection * const con, chunkqueue * c void -h2_init_con (request_st * const restrict h2r, connection * const restrict con, const buffer * const restrict http2_settings) +h2_init_con (request_st * const restrict h2r, connection * const restrict con) { h2con * const h2c = con->h2 = ck_calloc(1, sizeof(h2con)); con->read_idle_ts = log_monotonic_secs; @@ -1951,9 +1951,6 @@ h2_init_con (request_st * const restrict h2r, connection * const restrict con, c lshpack_enc_init(&h2c->encoder); lshpack_enc_use_hist(&h2c->encoder, 1); - if (http2_settings) /*(if Upgrade: h2c)*/ - h2_parse_frame_settings(con, (uint8_t *)BUF_PTR_LEN(http2_settings)); - static const uint8_t h2settings[] = { /*(big-endian numbers)*/ /* SETTINGS */ 0x00, 0x00, 0x1e /* frame length */ /* 5 * (6 bytes per setting) */ @@ -2897,7 +2894,7 @@ h2_retire_con (request_st * const h2r, connection * const con) static void -h2_con_upgrade_h2c (request_st * const h2r, const buffer * const http2_settings) +h2_con_upgrade_h2c (request_st * const h2r, connection * const con) { /* HTTP/1.1 101 Switching Protocols * Connection: Upgrade @@ -2919,8 +2916,7 @@ h2_con_upgrade_h2c (request_st * const h2r, const buffer * const http2_settings) h2r->http_status = 0; #endif - connection * const con = h2r->con; - h2_init_con(h2r, con, http2_settings); + h2_init_con(h2r, con); if (con->h2->sent_goaway) return; con->h2->h2_cid = 1; /* stream id 1 is assigned to h2c upgrade */ @@ -2932,7 +2928,7 @@ h2_con_upgrade_h2c (request_st * const h2r, const buffer * const http2_settings) request_st * const r = h2_init_stream(h2r, con); /*(undo double-count; already incremented in CON_STATE_REQUEST_START)*/ --con->request_count; - r->state = CON_STATE_REQUEST_END; + r->state = CON_STATE_WRITE; /* require 0 == r->reqbody_length */ r->http_status = 0; r->http_method = h2r->http_method; r->h2state = H2_STATE_HALF_CLOSED_REMOTE; @@ -3000,62 +2996,37 @@ h2_con_upgrade_h2c (request_st * const h2r, const buffer * const http2_settings) } -int -h2_check_con_upgrade_h2c (request_st * const r) +__attribute_cold__ +__attribute_nonnull__() +static void +h2_upgrade_h2c (request_st * const r, connection * const con) { - /* RFC7540 3.2 Starting HTTP/2 for "http" URIs */ - - buffer *http_connection, *http2_settings; - buffer *upgrade = http_header_request_get(r, HTTP_HEADER_UPGRADE, - CONST_STR_LEN("Upgrade")); - if (NULL == upgrade) return 0; - http_connection = http_header_request_get(r, HTTP_HEADER_CONNECTION, - CONST_STR_LEN("Connection")); - if (NULL == http_connection) { - http_header_request_unset(r, HTTP_HEADER_UPGRADE, - CONST_STR_LEN("Upgrade")); - return 0; - } - if (r->http_version != HTTP_VERSION_1_1) { - http_header_request_unset(r, HTTP_HEADER_UPGRADE, - CONST_STR_LEN("Upgrade")); - http_header_remove_token(http_connection, CONST_STR_LEN("Upgrade")); - return 0; + /* Upgrade: h2c + * RFC7540 3.2 Starting HTTP/2 for "http" URIs */ + + buffer * const http2_settings = + http_header_request_get(r, HTTP_HEADER_HTTP2_SETTINGS, + CONST_STR_LEN("HTTP2-Settings")); + + /* ignore Upgrade: h2c if request body present since we do not + * (currently) handle request body before transition to h2c */ + /* RFC7540 3.2 Requests that contain a payload body MUST be sent + * in their entirety before the client can send HTTP/2 frames. */ + + if (NULL != http2_settings + && 0 == r->reqbody_length + && r->conf.h2proto > 1/*(must be enabled with server.h2c feature)*/ + && !con->is_ssl_sock) { /*(disallow h2c over TLS socket)*/ + + r->http_version = HTTP_VERSION_2; + h2_con_upgrade_h2c(r, con); + + buffer * const b = r->tmp_buf; + buffer_clear(b); + if (buffer_append_base64_decode(b, BUF_PTR_LEN(http2_settings), + BASE64_URL)) + h2_parse_frame_settings(con, (uint8_t *)BUF_PTR_LEN(b)); + else + h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR); } - - if (!http_header_str_contains_token(BUF_PTR_LEN(upgrade), - CONST_STR_LEN("h2c"))) - return 0; - - http2_settings = http_header_request_get(r, HTTP_HEADER_HTTP2_SETTINGS, - CONST_STR_LEN("HTTP2-Settings")); - if (NULL != http2_settings) { - if (0 == r->reqbody_length) { - buffer * const b = r->tmp_buf; - buffer_clear(b); - if (r->conf.h2proto > 1/*(must be enabled with server.h2c feature)*/ - && !r->con->is_ssl_sock /*(disallow h2c over TLS socket)*/ - && - http_header_str_contains_token(BUF_PTR_LEN(http_connection), - CONST_STR_LEN("HTTP2-Settings")) - && buffer_append_base64_decode(b, BUF_PTR_LEN(http2_settings), - BASE64_URL)) { - h2_con_upgrade_h2c(r, b); - r->http_version = HTTP_VERSION_2; - } /* else ignore if invalid base64 */ - } - else { - /* ignore Upgrade: h2c if request body present since we do not - * (currently) handle request body before transition to h2c */ - /* RFC7540 3.2 Requests that contain a payload body MUST be sent - * in their entirety before the client can send HTTP/2 frames. */ - } - http_header_request_unset(r, HTTP_HEADER_HTTP2_SETTINGS, - CONST_STR_LEN("HTTP2-Settings")); - http_header_remove_token(http_connection, CONST_STR_LEN("HTTP2-Settings")); - } /* else ignore Upgrade: h2c; HTTP2-Settings required for Upgrade: h2c */ - http_header_request_unset(r, HTTP_HEADER_UPGRADE, - CONST_STR_LEN("Upgrade")); - http_header_remove_token(http_connection, CONST_STR_LEN("Upgrade")); - return (r->http_version == HTTP_VERSION_2); } |