From 47ed87f85548e329bbfa76dfc8749ac0f21e55ca Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Mon, 13 Jul 2020 12:38:08 +0300 Subject: HTTP/3: renamed ngx_http_v3.c to ngx_http_v3_encode.c. The file contains only encoding functions. --- src/http/v3/ngx_http_v3_encode.c | 227 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 src/http/v3/ngx_http_v3_encode.c (limited to 'src/http/v3/ngx_http_v3_encode.c') diff --git a/src/http/v3/ngx_http_v3_encode.c b/src/http/v3/ngx_http_v3_encode.c new file mode 100644 index 000000000..a80310faf --- /dev/null +++ b/src/http/v3/ngx_http_v3_encode.c @@ -0,0 +1,227 @@ + +/* + * Copyright (C) Roman Arutyunyan + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +uintptr_t +ngx_http_v3_encode_varlen_int(u_char *p, uint64_t value) +{ + if (value <= 63) { + if (p == NULL) { + return 1; + } + + *p++ = value; + return (uintptr_t) p; + } + + if (value <= 16383) { + if (p == NULL) { + return 2; + } + + *p++ = 0x40 | (value >> 8); + *p++ = value; + return (uintptr_t) p; + } + + if (value <= 1073741823) { + if (p == NULL) { + return 4; + } + + *p++ = 0x80 | (value >> 24); + *p++ = (value >> 16); + *p++ = (value >> 8); + *p++ = value; + return (uintptr_t) p; + } + + if (p == NULL) { + return 8; + } + + *p++ = 0xc0 | (value >> 56); + *p++ = (value >> 48); + *p++ = (value >> 40); + *p++ = (value >> 32); + *p++ = (value >> 24); + *p++ = (value >> 16); + *p++ = (value >> 8); + *p++ = value; + return (uintptr_t) p; +} + + +uintptr_t +ngx_http_v3_encode_prefix_int(u_char *p, uint64_t value, ngx_uint_t prefix) +{ + ngx_uint_t thresh, n; + + thresh = (1 << prefix) - 1; + + if (value < thresh) { + if (p == NULL) { + return 1; + } + + *p++ |= value; + return (uintptr_t) p; + } + + value -= thresh; + + if (p == NULL) { + for (n = 2; value >= 128; n++) { + value >>= 7; + } + + return n; + } + + *p++ |= thresh; + + while (value >= 128) { + *p++ = 0x80 | value; + value >>= 7; + } + + *p++ = value; + + return (uintptr_t) p; +} + + +uintptr_t +ngx_http_v3_encode_header_block_prefix(u_char *p, ngx_uint_t insert_count, + ngx_uint_t sign, ngx_uint_t delta_base) +{ + if (p == NULL) { + return ngx_http_v3_encode_prefix_int(NULL, insert_count, 8) + + ngx_http_v3_encode_prefix_int(NULL, delta_base, 7); + } + + *p = 0; + p = (u_char *) ngx_http_v3_encode_prefix_int(p, insert_count, 8); + + *p = sign ? 0x80 : 0; + p = (u_char *) ngx_http_v3_encode_prefix_int(p, delta_base, 7); + + return (uintptr_t) p; +} + + +uintptr_t +ngx_http_v3_encode_header_ri(u_char *p, ngx_uint_t dynamic, ngx_uint_t index) +{ + /* Indexed Header Field */ + + if (p == NULL) { + return ngx_http_v3_encode_prefix_int(NULL, index, 6); + } + + *p = dynamic ? 0x80 : 0xc0; + + return ngx_http_v3_encode_prefix_int(p, index, 6); +} + + +uintptr_t +ngx_http_v3_encode_header_lri(u_char *p, ngx_uint_t dynamic, ngx_uint_t index, + u_char *data, size_t len) +{ + /* Literal Header Field With Name Reference */ + + if (p == NULL) { + return ngx_http_v3_encode_prefix_int(NULL, index, 4) + + ngx_http_v3_encode_prefix_int(NULL, len, 7) + + len; + } + + *p = dynamic ? 0x60 : 0x70; + p = (u_char *) ngx_http_v3_encode_prefix_int(p, index, 4); + + *p = 0; + p = (u_char *) ngx_http_v3_encode_prefix_int(p, len, 7); + + if (data) { + p = ngx_cpymem(p, data, len); + } + + return (uintptr_t) p; +} + + +uintptr_t +ngx_http_v3_encode_header_l(u_char *p, ngx_str_t *name, ngx_str_t *value) +{ + /* Literal Header Field Without Name Reference */ + + if (p == NULL) { + return ngx_http_v3_encode_prefix_int(NULL, name->len, 3) + + name->len + + ngx_http_v3_encode_prefix_int(NULL, value->len, 7) + + value->len; + } + + *p = 0x30; + p = (u_char *) ngx_http_v3_encode_prefix_int(p, name->len, 3); + + ngx_strlow(p, name->data, name->len); + p += name->len; + + *p = 0; + p = (u_char *) ngx_http_v3_encode_prefix_int(p, value->len, 7); + + p = ngx_cpymem(p, value->data, value->len); + + return (uintptr_t) p; +} + + +uintptr_t +ngx_http_v3_encode_header_pbi(u_char *p, ngx_uint_t index) +{ + /* Indexed Header Field With Post-Base Index */ + + if (p == NULL) { + return ngx_http_v3_encode_prefix_int(NULL, index, 4); + } + + *p = 0x10; + + return ngx_http_v3_encode_prefix_int(p, index, 4); +} + + +uintptr_t +ngx_http_v3_encode_header_lpbi(u_char *p, ngx_uint_t index, u_char *data, + size_t len) +{ + /* Literal Header Field With Post-Base Name Reference */ + + if (p == NULL) { + return ngx_http_v3_encode_prefix_int(NULL, index, 3) + + ngx_http_v3_encode_prefix_int(NULL, len, 7) + + len; + } + + *p = 0x08; + p = (u_char *) ngx_http_v3_encode_prefix_int(p, index, 3); + + *p = 0; + p = (u_char *) ngx_http_v3_encode_prefix_int(p, len, 7); + + if (data) { + p = ngx_cpymem(p, data, len); + } + + return (uintptr_t) p; +} -- cgit From e443b1244f60448805a873bf488a9d9f89bf7488 Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Mon, 31 Aug 2020 18:42:26 +0300 Subject: HTTP/3: do not set the never-indexed literal bit by default. The "Literal Header Field Never Indexed" header field representation is not used in HTTP/2, and it makes little sense to make a distinction in HTTP/3. --- src/http/v3/ngx_http_v3_encode.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/http/v3/ngx_http_v3_encode.c') diff --git a/src/http/v3/ngx_http_v3_encode.c b/src/http/v3/ngx_http_v3_encode.c index a80310faf..b7bc3dd7c 100644 --- a/src/http/v3/ngx_http_v3_encode.c +++ b/src/http/v3/ngx_http_v3_encode.c @@ -145,7 +145,7 @@ ngx_http_v3_encode_header_lri(u_char *p, ngx_uint_t dynamic, ngx_uint_t index, + len; } - *p = dynamic ? 0x60 : 0x70; + *p = dynamic ? 0x40 : 0x50; p = (u_char *) ngx_http_v3_encode_prefix_int(p, index, 4); *p = 0; @@ -171,7 +171,7 @@ ngx_http_v3_encode_header_l(u_char *p, ngx_str_t *name, ngx_str_t *value) + value->len; } - *p = 0x30; + *p = 0x20; p = (u_char *) ngx_http_v3_encode_prefix_int(p, name->len, 3); ngx_strlow(p, name->data, name->len); @@ -213,7 +213,7 @@ ngx_http_v3_encode_header_lpbi(u_char *p, ngx_uint_t index, u_char *data, + len; } - *p = 0x08; + *p = 0; p = (u_char *) ngx_http_v3_encode_prefix_int(p, index, 3); *p = 0; -- cgit From a85084fea109c019d1ad7466ed063afa7961acba Mon Sep 17 00:00:00 2001 From: Sergey Kandaurov Date: Thu, 1 Jul 2021 15:37:53 +0300 Subject: HTTP/3: quic-qpack term updates. Renamed header -> field per quic-qpack naming convention, in particular: - Header Field -> Field Line - Header Block -> (Encoded) Field Section - Without Name Reference -> With Literal Name - Header Acknowledgement -> Section Acknowledgment --- src/http/v3/ngx_http_v3_encode.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'src/http/v3/ngx_http_v3_encode.c') diff --git a/src/http/v3/ngx_http_v3_encode.c b/src/http/v3/ngx_http_v3_encode.c index b7bc3dd7c..2740ccffa 100644 --- a/src/http/v3/ngx_http_v3_encode.c +++ b/src/http/v3/ngx_http_v3_encode.c @@ -100,7 +100,7 @@ ngx_http_v3_encode_prefix_int(u_char *p, uint64_t value, ngx_uint_t prefix) uintptr_t -ngx_http_v3_encode_header_block_prefix(u_char *p, ngx_uint_t insert_count, +ngx_http_v3_encode_field_section_prefix(u_char *p, ngx_uint_t insert_count, ngx_uint_t sign, ngx_uint_t delta_base) { if (p == NULL) { @@ -119,9 +119,9 @@ ngx_http_v3_encode_header_block_prefix(u_char *p, ngx_uint_t insert_count, uintptr_t -ngx_http_v3_encode_header_ri(u_char *p, ngx_uint_t dynamic, ngx_uint_t index) +ngx_http_v3_encode_field_ri(u_char *p, ngx_uint_t dynamic, ngx_uint_t index) { - /* Indexed Header Field */ + /* Indexed Field Line */ if (p == NULL) { return ngx_http_v3_encode_prefix_int(NULL, index, 6); @@ -134,10 +134,10 @@ ngx_http_v3_encode_header_ri(u_char *p, ngx_uint_t dynamic, ngx_uint_t index) uintptr_t -ngx_http_v3_encode_header_lri(u_char *p, ngx_uint_t dynamic, ngx_uint_t index, +ngx_http_v3_encode_field_lri(u_char *p, ngx_uint_t dynamic, ngx_uint_t index, u_char *data, size_t len) { - /* Literal Header Field With Name Reference */ + /* Literal Field Line With Name Reference */ if (p == NULL) { return ngx_http_v3_encode_prefix_int(NULL, index, 4) @@ -160,9 +160,9 @@ ngx_http_v3_encode_header_lri(u_char *p, ngx_uint_t dynamic, ngx_uint_t index, uintptr_t -ngx_http_v3_encode_header_l(u_char *p, ngx_str_t *name, ngx_str_t *value) +ngx_http_v3_encode_field_l(u_char *p, ngx_str_t *name, ngx_str_t *value) { - /* Literal Header Field Without Name Reference */ + /* Literal Field Line With Literal Name */ if (p == NULL) { return ngx_http_v3_encode_prefix_int(NULL, name->len, 3) @@ -187,9 +187,9 @@ ngx_http_v3_encode_header_l(u_char *p, ngx_str_t *name, ngx_str_t *value) uintptr_t -ngx_http_v3_encode_header_pbi(u_char *p, ngx_uint_t index) +ngx_http_v3_encode_field_pbi(u_char *p, ngx_uint_t index) { - /* Indexed Header Field With Post-Base Index */ + /* Indexed Field Line With Post-Base Index */ if (p == NULL) { return ngx_http_v3_encode_prefix_int(NULL, index, 4); @@ -202,10 +202,10 @@ ngx_http_v3_encode_header_pbi(u_char *p, ngx_uint_t index) uintptr_t -ngx_http_v3_encode_header_lpbi(u_char *p, ngx_uint_t index, u_char *data, +ngx_http_v3_encode_field_lpbi(u_char *p, ngx_uint_t index, u_char *data, size_t len) { - /* Literal Header Field With Post-Base Name Reference */ + /* Literal Field Line With Post-Base Name Reference */ if (p == NULL) { return ngx_http_v3_encode_prefix_int(NULL, index, 3) -- cgit From 0ac1f6fd47b59bd59abb4c8465e622e60f666ee0 Mon Sep 17 00:00:00 2001 From: Sergey Kandaurov Date: Mon, 13 Sep 2021 16:25:08 +0300 Subject: HTTP/3: implemented QPACK Huffman encoding for response fields. --- src/http/v3/ngx_http_v3_encode.c | 87 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 82 insertions(+), 5 deletions(-) (limited to 'src/http/v3/ngx_http_v3_encode.c') diff --git a/src/http/v3/ngx_http_v3_encode.c b/src/http/v3/ngx_http_v3_encode.c index 2740ccffa..a62f5d30f 100644 --- a/src/http/v3/ngx_http_v3_encode.c +++ b/src/http/v3/ngx_http_v3_encode.c @@ -137,6 +137,9 @@ uintptr_t ngx_http_v3_encode_field_lri(u_char *p, ngx_uint_t dynamic, ngx_uint_t index, u_char *data, size_t len) { + size_t hlen; + u_char *p1, *p2; + /* Literal Field Line With Name Reference */ if (p == NULL) { @@ -148,11 +151,28 @@ ngx_http_v3_encode_field_lri(u_char *p, ngx_uint_t dynamic, ngx_uint_t index, *p = dynamic ? 0x40 : 0x50; p = (u_char *) ngx_http_v3_encode_prefix_int(p, index, 4); + p1 = p; *p = 0; p = (u_char *) ngx_http_v3_encode_prefix_int(p, len, 7); if (data) { - p = ngx_cpymem(p, data, len); + p2 = p; + hlen = ngx_http_v2_huff_encode(data, len, p, 0); + + if (hlen) { + p = p1; + *p = 0x80; + p = (u_char *) ngx_http_v3_encode_prefix_int(p, hlen, 7); + + if (p != p2) { + ngx_memmove(p, p2, hlen); + } + + p += hlen; + + } else { + p = ngx_cpymem(p, data, len); + } } return (uintptr_t) p; @@ -162,6 +182,9 @@ ngx_http_v3_encode_field_lri(u_char *p, ngx_uint_t dynamic, ngx_uint_t index, uintptr_t ngx_http_v3_encode_field_l(u_char *p, ngx_str_t *name, ngx_str_t *value) { + size_t hlen; + u_char *p1, *p2; + /* Literal Field Line With Literal Name */ if (p == NULL) { @@ -171,16 +194,50 @@ ngx_http_v3_encode_field_l(u_char *p, ngx_str_t *name, ngx_str_t *value) + value->len; } + p1 = p; *p = 0x20; p = (u_char *) ngx_http_v3_encode_prefix_int(p, name->len, 3); - ngx_strlow(p, name->data, name->len); - p += name->len; + p2 = p; + hlen = ngx_http_v2_huff_encode(name->data, name->len, p, 1); + + if (hlen) { + p = p1; + *p = 0x28; + p = (u_char *) ngx_http_v3_encode_prefix_int(p, hlen, 3); + + if (p != p2) { + ngx_memmove(p, p2, hlen); + } + + p += hlen; + + } else { + ngx_strlow(p, name->data, name->len); + p += name->len; + } + p1 = p; *p = 0; p = (u_char *) ngx_http_v3_encode_prefix_int(p, value->len, 7); - p = ngx_cpymem(p, value->data, value->len); + p2 = p; + hlen = ngx_http_v2_huff_encode(value->data, value->len, p, 0); + + if (hlen) { + p = p1; + *p = 0x80; + p = (u_char *) ngx_http_v3_encode_prefix_int(p, hlen, 7); + + if (p != p2) { + ngx_memmove(p, p2, hlen); + } + + p += hlen; + + } else { + p = ngx_cpymem(p, value->data, value->len); + } return (uintptr_t) p; } @@ -205,6 +262,9 @@ uintptr_t ngx_http_v3_encode_field_lpbi(u_char *p, ngx_uint_t index, u_char *data, size_t len) { + size_t hlen; + u_char *p1, *p2; + /* Literal Field Line With Post-Base Name Reference */ if (p == NULL) { @@ -216,11 +276,28 @@ ngx_http_v3_encode_field_lpbi(u_char *p, ngx_uint_t index, u_char *data, *p = 0; p = (u_char *) ngx_http_v3_encode_prefix_int(p, index, 3); + p1 = p; *p = 0; p = (u_char *) ngx_http_v3_encode_prefix_int(p, len, 7); if (data) { - p = ngx_cpymem(p, data, len); + p2 = p; + hlen = ngx_http_v2_huff_encode(data, len, p, 0); + + if (hlen) { + p = p1; + *p = 0x80; + p = (u_char *) ngx_http_v3_encode_prefix_int(p, hlen, 7); + + if (p != p2) { + ngx_memmove(p, p2, hlen); + } + + p += hlen; + + } else { + p = ngx_cpymem(p, data, len); + } } return (uintptr_t) p; -- cgit