aboutsummaryrefslogtreecommitdiff
path: root/src/http/v3/ngx_http_v3_request.c
diff options
context:
space:
mode:
authorRoman Arutyunyan <arut@nginx.com>2020-03-18 20:22:16 +0300
committerRoman Arutyunyan <arut@nginx.com>2020-03-18 20:22:16 +0300
commite63accd7bd222aebd7cf4f90aeb8cca617d01b94 (patch)
treed07764273e242b4c74d335182911d17ddadccfe3 /src/http/v3/ngx_http_v3_request.c
parent5aa8e519c9fecc00b3a74781716ceb66609c5661 (diff)
downloadnginx-e63accd7bd222aebd7cf4f90aeb8cca617d01b94.tar.gz
nginx-e63accd7bd222aebd7cf4f90aeb8cca617d01b94.zip
HTTP/3 $request_line variable.
Diffstat (limited to 'src/http/v3/ngx_http_v3_request.c')
-rw-r--r--src/http/v3/ngx_http_v3_request.c573
1 files changed, 35 insertions, 538 deletions
diff --git a/src/http/v3/ngx_http_v3_request.c b/src/http/v3/ngx_http_v3_request.c
index a9adcf8c2..75488db1d 100644
--- a/src/http/v3/ngx_http_v3_request.c
+++ b/src/http/v3/ngx_http_v3_request.c
@@ -40,6 +40,8 @@ struct {
ngx_int_t
ngx_http_v3_parse_header(ngx_http_request_t *r, ngx_buf_t *b)
{
+ size_t n;
+ u_char *p;
ngx_int_t rc;
ngx_str_t *name, *value;
ngx_connection_t *c;
@@ -97,23 +99,45 @@ ngx_http_v3_parse_header(ngx_http_request_t *r, ngx_buf_t *b)
name = &st->header_rep.header.name;
value = &st->header_rep.header.value;
- if (r->state == sw_start
- && ngx_http_v3_process_pseudo_header(r, name, value) != NGX_OK)
- {
- if (rc == NGX_DONE) {
- r->state = sw_last;
- } else {
+ if (r->state == sw_start) {
+
+ if (ngx_http_v3_process_pseudo_header(r, name, value) == NGX_OK) {
+ if (rc == NGX_OK) {
+ continue;
+ }
+
+ r->state = sw_done;
+
+ } else if (rc == NGX_OK) {
r->state = sw_prev;
+
+ } else {
+ r->state = sw_last;
+ }
+
+ n = (r->method_end - r->method_start) + 1
+ + (r->uri_end - r->uri_start) + 1
+ + sizeof("HTTP/3") - 1;
+
+ p = ngx_pnalloc(c->pool, n);
+ if (p == NULL) {
+ goto failed;
}
+ r->request_start = p;
+
+ p = ngx_cpymem(p, r->method_start, r->method_end - r->method_start);
+ *p++ = ' ';
+ p = ngx_cpymem(p, r->uri_start, r->uri_end - r->uri_start);
+ *p++ = ' ';
+ p = ngx_cpymem(p, "HTTP/3", sizeof("HTTP/3") - 1);
+
+ r->request_end = p;
+
} else if (rc == NGX_DONE) {
r->state = sw_done;
}
- if (r->state == sw_start) {
- continue;
- }
-
r->header_name_start = name->data;
r->header_name_end = name->data + name->len;
r->header_start = value->data;
@@ -139,533 +163,6 @@ done:
return NGX_HTTP_PARSE_HEADER_DONE;
}
-#if 0
-ngx_int_t
-ngx_http_v3_parse_header(ngx_http_request_t *r, ngx_buf_t *b, ngx_uint_t pseudo)
-{
- u_char *p, ch;
- ngx_str_t name, value;
- ngx_int_t rc;
- ngx_uint_t length, index, insert_count, sign, base, delta_base,
- huffman, dynamic, offset;
- ngx_connection_t *c;
- ngx_http_v3_header_t *h;
- enum {
- sw_start = 0,
- sw_length,
- sw_length_1,
- sw_length_2,
- sw_length_3,
- sw_header_block,
- sw_req_insert_count,
- sw_delta_base,
- sw_read_delta_base,
- sw_header,
- sw_old_header,
- sw_header_ri,
- sw_header_pbi,
- sw_header_lri,
- sw_header_lpbi,
- sw_header_l_name_len,
- sw_header_l_name,
- sw_header_value_len,
- sw_header_read_value_len,
- sw_header_value
- } state;
-
- c = r->connection;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
- "http3 parse header, pseudo:%ui", pseudo);
-
- if (r->state == sw_old_header) {
- r->state = sw_header;
- return NGX_OK;
- }
-
- length = r->h3_length;
- index = r->h3_index;
- insert_count = r->h3_insert_count;
- sign = r->h3_sign;
- delta_base = r->h3_delta_base;
- huffman = r->h3_huffman;
- dynamic = r->h3_dynamic;
- offset = r->h3_offset;
-
- name.data = r->header_name_start;
- name.len = r->header_name_end - r->header_name_start;
- value.data = r->header_start;
- value.len = r->header_end - r->header_start;
-
- if (r->state == sw_start) {
- length = 1;
- }
-
-again:
-
- state = r->state;
-
- if (state == sw_header && length == 0) {
- r->state = sw_start;
- return NGX_HTTP_PARSE_HEADER_DONE;
- }
-
- for (p = b->pos; p < b->last; p++) {
-
- if (state >= sw_header_block && length-- == 0) {
- goto failed;
- }
-
- ch = *p;
-
- switch (state) {
-
- case sw_start:
-
- if (ch != NGX_HTTP_V3_FRAME_HEADERS) {
- goto failed;
- }
-
- r->request_start = p;
- state = sw_length;
- break;
-
- case sw_length:
-
- length = ch;
- if (length & 0xc0) {
- state = sw_length_1;
- break;
- }
-
- state = sw_header_block;
- break;
-
- case sw_length_1:
-
- length = (length << 8) + ch;
- if ((length & 0xc000) != 0x4000) {
- state = sw_length_2;
- break;
- }
-
- length &= 0x3fff;
- state = sw_header_block;
- break;
-
- case sw_length_2:
-
- length = (length << 8) + ch;
- if ((length & 0xc00000) != 0x800000) {
- state = sw_length_3;
- break;
- }
-
- length &= 0x3fffff;
- state = sw_header_block;
- break;
-
- case sw_length_3:
-
- length = (length << 8) + ch;
- length &= 0x3fffffff;
- state = sw_header_block;
- break;
-
- case sw_header_block:
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
- "http3 header block length:%ui", length);
-
- if (ch != 0xff) {
- insert_count = ch;
- state = sw_delta_base;
- break;
- }
-
- insert_count = 0;
- state = sw_req_insert_count;
- break;
-
- case sw_req_insert_count:
-
- insert_count = (insert_count << 7) + (ch & 0x7f);
- if (ch & 0x80) {
- break;
- }
-
- insert_count += 0xff;
- state = sw_delta_base;
- break;
-
- case sw_delta_base:
-
- sign = (ch & 0x80) ? 1 : 0;
- delta_base = ch & 0x7f;
-
- if (delta_base != 0x7f) {
- ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
- "http3 header block "
- "insert_count:%ui, sign:%ui, delta_base:%ui",
- insert_count, sign, delta_base);
- goto done;
- }
-
- delta_base = 0;
- state = sw_read_delta_base;
- break;
-
- case sw_read_delta_base:
-
- delta_base = (delta_base << 7) + (ch & 0x7f);
- if (ch & 0x80) {
- break;
- }
-
- delta_base += 0x7f;
-
- ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
- "http3 header block "
- "insert_count:%ui, sign:%ui, delta_base:%ui",
- insert_count, sign, delta_base);
- goto done;
-
- case sw_header:
-
- index = 0;
- huffman = 0;
- ngx_str_null(&name);
- ngx_str_null(&value);
-
- if (ch & 0x80) {
- /* Indexed Header Field */
-
- dynamic = (ch & 0x40) ? 0 : 1;
- index = ch & 0x3f;
-
- if (index != 0x3f) {
- goto done;
- }
-
- index = 0;
- state = sw_header_ri;
- break;
- }
-
- if (ch & 0x40) {
- /* Literal Header Field With Name Reference */
-
- dynamic = (ch & 0x10) ? 0 : 1;
- index = ch & 0x0f;
-
- if (index != 0x0f) {
- state = sw_header_value_len;
- break;
- }
-
- index = 0;
- state = sw_header_lri;
- break;
- }
-
- if (ch & 0x20) {
- /* Literal Header Field Without Name Reference */
-
- huffman = (ch & 0x08) ? 1 : 0;
- name.len = ch & 0x07;
-
- if (name.len == 0) {
- goto failed;
- }
-
- if (name.len != 0x07) {
- offset = 0;
- state = sw_header_l_name;
- break;
- }
-
- name.len = 0;
- state = sw_header_l_name_len;
- break;
- }
-
- if (ch & 10) {
- /* Indexed Header Field With Post-Base Index */
-
- dynamic = 2;
- index = ch & 0x0f;
-
- if (index != 0x0f) {
- goto done;
- }
-
- index = 0;
- state = sw_header_pbi;
- break;
- }
-
- /* Literal Header Field With Post-Base Name Reference */
-
- dynamic = 2;
- index = ch & 0x07;
-
- if (index != 0x07) {
- state = sw_header_value_len;
- break;
- }
-
- index = 0;
- state = sw_header_lpbi;
- break;
-
- case sw_header_ri:
-
- index = (index << 7) + (ch & 0x7f);
- if (ch & 0x80) {
- break;
- }
-
- index += 0x3f;
- goto done;
-
- case sw_header_pbi:
-
- index = (index << 7) + (ch & 0x7f);
- if (ch & 0x80) {
- break;
- }
-
- index += 0x0f;
- goto done;
-
- case sw_header_lri:
-
- index = (index << 7) + (ch & 0x7f);
- if (ch & 0x80) {
- break;
- }
-
- index += 0x0f;
- state = sw_header_value_len;
- break;
-
- case sw_header_lpbi:
-
- index = (index << 7) + (ch & 0x7f);
- if (ch & 0x80) {
- break;
- }
-
- index += 0x07;
- state = sw_header_value_len;
- break;
-
-
- case sw_header_l_name_len:
-
- name.len = (name.len << 7) + (ch & 0x7f);
- if (ch & 0x80) {
- break;
- }
-
- name.len += 0x07;
- offset = 0;
- state = sw_header_l_name;
- break;
-
- case sw_header_l_name:
- if (offset++ == 0) {
- name.data = p;
- }
-
- if (offset != name.len) {
- break;
- }
-
- if (huffman) {
- if (ngx_http_v3_decode_huffman(c, &name) != NGX_OK) {
- goto failed;
- }
- }
-
- state = sw_header_value_len;
- break;
-
- case sw_header_value_len:
-
- huffman = (ch & 0x80) ? 1 : 0;
- value.len = ch & 0x7f;
-
- if (value.len == 0) {
- value.data = p;
- goto done;
- }
-
- if (value.len != 0x7f) {
- offset = 0;
- state = sw_header_value;
- break;
- }
-
- value.len = 0;
- state = sw_header_read_value_len;
- break;
-
- case sw_header_read_value_len:
-
- value.len = (value.len << 7) + (ch & 0x7f);
- if (ch & 0x80) {
- break;
- }
-
- value.len += 0x7f;
- offset = 0;
- state = sw_header_value;
- break;
-
- case sw_header_value:
-
- if (offset++ == 0) {
- value.data = p;
- }
-
- if (offset != value.len) {
- break;
- }
-
- if (huffman) {
- if (ngx_http_v3_decode_huffman(c, &value) != NGX_OK) {
- goto failed;
- }
- }
-
- goto done;
-
- case sw_old_header:
-
- break;
- }
- }
-
- b->pos = p;
- r->state = state;
- r->h3_length = length;
- r->h3_index = index;
- r->h3_insert_count = insert_count;
- r->h3_sign = sign;
- r->h3_delta_base = delta_base;
- r->h3_huffman = huffman;
- r->h3_dynamic = dynamic;
- r->h3_offset = offset;
-
- /* XXX fix large reallocations */
- r->header_name_start = name.data;
- r->header_name_end = name.data + name.len;
- r->header_start = value.data;
- r->header_end = value.data + value.len;
-
- /* XXX r->lowcase_index = i; */
-
- return NGX_AGAIN;
-
-done:
-
- b->pos = p + 1;
- r->state = sw_header;
- r->h3_length = length;
- r->h3_insert_count = insert_count;
- r->h3_sign = sign;
- r->h3_delta_base = delta_base;
-
- if (state < sw_header) {
- if (ngx_http_v3_check_insert_count(c, insert_count) != NGX_OK) {
- return NGX_DONE;
- }
-
- goto again;
- }
-
- if (sign == 0) {
- base = insert_count + delta_base;
- } else {
- base = insert_count - delta_base - 1;
- }
-
- ngx_log_debug5(NGX_LOG_DEBUG_HTTP, c->log, 0,
- "http3 header %s[%ui], base:%ui, \"%V\":\"%V\"",
- dynamic ? "dynamic" : "static", index, base, &name, &value);
-
- if (name.data == NULL) {
-
- if (dynamic == 2) {
- index = base - index - 1;
- } else if (dynamic == 1) {
- index += base;
- }
-
- h = ngx_http_v3_lookup_table(c, dynamic, index);
- if (h == NULL) {
- goto failed;
- }
-
- name = h->name;
-
- if (value.data == NULL) {
- value = h->value;
- }
- }
-
- /* XXX ugly reallocation for the trailing '\0' */
-
- p = ngx_pnalloc(c->pool, name.len + value.len + 2);
- if (p == NULL) {
- return NGX_ERROR;
- }
-
- ngx_memcpy(p, name.data, name.len);
- name.data = p;
- ngx_memcpy(p + name.len + 1, value.data, value.len);
- value.data = p + name.len + 1;
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
- "http3 header \"%V\":\"%V\"", &name, &value);
-
- if (pseudo) {
- rc = ngx_http_v3_process_pseudo_header(r, &name, &value);
-
- if (rc == NGX_ERROR) {
- goto failed;
- }
-
- if (rc == NGX_OK) {
- r->request_end = p + 1;
- goto again;
- }
-
- /* rc == NGX_DONE */
-
- r->state = sw_old_header;
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
- "http3 header left:%ui", length);
-
- r->header_name_start = name.data;
- r->header_name_end = name.data + name.len;
- r->header_start = value.data;
- r->header_end = value.data + value.len;
- r->header_hash = ngx_hash_key(name.data, name.len); /* XXX */
-
- /* XXX r->lowcase_index = i; */
-
- return NGX_OK;
-
-failed:
-
- return NGX_HTTP_PARSE_INVALID_REQUEST;
-}
-#endif
-
static ngx_int_t
ngx_http_v3_process_pseudo_header(ngx_http_request_t *r, ngx_str_t *name,
@@ -675,7 +172,7 @@ ngx_http_v3_process_pseudo_header(ngx_http_request_t *r, ngx_str_t *name,
ngx_connection_t *c;
if (name->len == 0 || name->data[0] != ':') {
- return NGX_DECLINED;
+ return NGX_DONE;
}
c = r->connection;