aboutsummaryrefslogtreecommitdiff
path: root/src/http/v3/ngx_http_v3_encode.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/http/v3/ngx_http_v3_encode.c')
-rw-r--r--src/http/v3/ngx_http_v3_encode.c304
1 files changed, 304 insertions, 0 deletions
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..fb089c413
--- /dev/null
+++ b/src/http/v3/ngx_http_v3_encode.c
@@ -0,0 +1,304 @@
+
+/*
+ * Copyright (C) Roman Arutyunyan
+ * Copyright (C) Nginx, Inc.
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+
+
+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_field_section_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_field_ri(u_char *p, ngx_uint_t dynamic, ngx_uint_t index)
+{
+ /* Indexed Field Line */
+
+ 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_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) {
+ return ngx_http_v3_encode_prefix_int(NULL, index, 4)
+ + ngx_http_v3_encode_prefix_int(NULL, len, 7)
+ + len;
+ }
+
+ *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) {
+ p2 = p;
+ hlen = ngx_http_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;
+}
+
+
+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) {
+ 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;
+ }
+
+ p1 = p;
+ *p = 0x20;
+ p = (u_char *) ngx_http_v3_encode_prefix_int(p, name->len, 3);
+
+ p2 = p;
+ hlen = ngx_http_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);
+
+ p2 = p;
+ hlen = ngx_http_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;
+}
+
+
+uintptr_t
+ngx_http_v3_encode_field_pbi(u_char *p, ngx_uint_t index)
+{
+ /* Indexed Field Line 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_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) {
+ return ngx_http_v3_encode_prefix_int(NULL, index, 3)
+ + ngx_http_v3_encode_prefix_int(NULL, len, 7)
+ + len;
+ }
+
+ *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) {
+ p2 = p;
+ hlen = ngx_http_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;
+}