aboutsummaryrefslogtreecommitdiff
path: root/src/http/v3/ngx_http_v3_encode.c
diff options
context:
space:
mode:
authorSergey Kandaurov <pluknet@nginx.com>2021-09-13 16:25:08 +0300
committerSergey Kandaurov <pluknet@nginx.com>2021-09-13 16:25:08 +0300
commit0ac1f6fd47b59bd59abb4c8465e622e60f666ee0 (patch)
tree897955449060c040bc21967d531aee51ef01e1f1 /src/http/v3/ngx_http_v3_encode.c
parent590996466ca568dbc7de5d40b7062dc254d211c2 (diff)
downloadnginx-0ac1f6fd47b59bd59abb4c8465e622e60f666ee0.tar.gz
nginx-0ac1f6fd47b59bd59abb4c8465e622e60f666ee0.zip
HTTP/3: implemented QPACK Huffman encoding for response fields.
Diffstat (limited to 'src/http/v3/ngx_http_v3_encode.c')
-rw-r--r--src/http/v3/ngx_http_v3_encode.c87
1 files changed, 82 insertions, 5 deletions
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;