]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: qpack: implement standalone decoder tool
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Tue, 14 Jun 2022 14:35:41 +0000 (16:35 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 15 Jun 2022 13:42:10 +0000 (15:42 +0200)
Implement a standalone binary to be able to easily a hex-string QPACK
stream. The binary must be compiled via the Makefile. Hex-strings are
specified on stdin.

.gitignore
Makefile
dev/qpack/decode.c [new file with mode: 0644]

index d588b0751e2026bbcfa006dedaad190cf0e0806f..a2776883ee04e5967945d725385ca8fc8f09b7c4 100644 (file)
@@ -49,6 +49,7 @@ dev/poll/poll
 dev/tcploop/tcploop
 dev/hpack/decode
 dev/hpack/gen-rht
+dev/qpack/decode
 /src/dlmalloc.c
 /tests/test_hashes
 doc/lua-api/_build
index c852d9d6fbe78f760a7941b0e3532e7970cfca68..b248acccfa45dfbc0766f4da406261b155ed15b8 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1018,6 +1018,9 @@ dev/hpack/%: dev/hpack/%.o
 dev/poll/poll:
        $(Q)$(MAKE) -C dev/poll poll CC='$(cmd_CC)' OPTIMIZE='$(COPTS)'
 
+dev/qpack/decode: dev/qpack/decode.o
+       $(cmd_LD) $(LDFLAGS) -o $@ $^ $(LDOPTS)
+
 dev/tcploop/tcploop:
        $(Q)$(MAKE) -C dev/tcploop tcploop CC='$(cmd_CC)' OPTIMIZE='$(COPTS)'
 
@@ -1088,6 +1091,7 @@ clean:
        $(Q)rm -f dev/*/*.[oas]
        $(Q)rm -f dev/flags/flags dev/poll/poll dev/tcploop/tcploop
        $(Q)rm -f dev/hpack/decode dev/hpack/gen-enc dev/hpack/gen-rht
+       $(Q)rm -f dev/qpack/decode
 
 tags:
        $(Q)find src include \( -name '*.c' -o -name '*.h' \) -print0 | \
diff --git a/dev/qpack/decode.c b/dev/qpack/decode.c
new file mode 100644 (file)
index 0000000..b2d233a
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * QPACK stream decoder. Decode a series of hex codes on stdin using one line
+ * per H3 HEADERS frame. Silently skip spaces, tabs, CR, '-' and ','.
+ *
+ * Compilation via Makefile
+ *
+ * Example run:
+ *   echo 0000d1d7508b089d5c0b8170dc101a699fc15f5085ed6989397f | ./dev/qpack/decode
+ */
+
+#include <ctype.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define MAX_RQ_SIZE 65536
+#define MAX_HDR_NUM 1000
+
+#define QPACK_STANDALONE
+
+#define USE_OPENSSL
+#define USE_QUIC
+
+#include <haproxy/buf-t.h>
+#include <haproxy/http-hdr-t.h>
+#include <haproxy/qpack-dec.h>
+#include <haproxy/qpack-tbl.h>
+
+char line[MAX_RQ_SIZE * 3 + 3];
+uint8_t bin[MAX_RQ_SIZE];
+
+char tmp_buf[MAX_RQ_SIZE];
+struct buffer buf   = { .area = tmp_buf,   .data = 0, .size = sizeof(tmp_buf)   };
+
+#define DEBUG_QPACK
+#include "../src/hpack-huff.c"
+#include "../src/qpack-dec.c"
+#include "../src/qpack-tbl.c"
+
+/* define to compile with BUG_ON/ABORT_NOW statements */
+void ha_backtrace_to_stderr(void)
+{
+}
+
+/* taken from dev/hpack/decode.c */
+int hex2bin(const char *hex, uint8_t *bin, int size)
+{
+       int a, b, c;
+       uint8_t code;
+       int len = 0;
+
+       a = b = -1;
+
+       for (; *hex; hex++) {
+               c = *hex;
+               if (c == ' ' || c == '\t' || c == '\r' ||
+                   c == '-' || c == ',')
+                       continue;
+
+               if (c == '\n' || c == '#')
+                       break;
+
+               if (c >= '0' && c <= '9')
+                       c -= '0';
+               else if (c >= 'a' && c <= 'f')
+                       c -= 'a' - 10;
+               else if (c >= 'A' && c <= 'F')
+                       c -= 'A' - 10;
+               else
+                       return -1;
+
+               if (a == -1)
+                       a = c;
+               else
+                       b = c;
+
+               if (b == -1)
+                       continue;
+
+               code = (a << 4) | b;
+               a = b = -1;
+               if (len >= size)
+                       return -2;
+
+               bin[len] = code;
+               len++;
+       }
+       if (a >= 0 || b >= 0)
+               return -3;
+       return len;
+}
+
+/* taken from src/tools.c */
+void debug_hexdump(FILE *out, const char *pfx, const char *buf,
+                   unsigned int baseaddr, int len)
+{
+       unsigned int i;
+       int b, j;
+
+       for (i = 0; i < (len + (baseaddr & 15)); i += 16) {
+               b = i - (baseaddr & 15);
+               fprintf(out, "%s%08x: ", pfx ? pfx : "", i + (baseaddr & ~15));
+               for (j = 0; j < 8; j++) {
+                       if (b + j >= 0 && b + j < len)
+                               fprintf(out, "%02x ", (unsigned char)buf[b + j]);
+                       else
+                               fprintf(out, "   ");
+               }
+
+               if (b + j >= 0 && b + j < len)
+                       fputc('-', out);
+               else
+                       fputc(' ', out);
+
+               for (j = 8; j < 16; j++) {
+                       if (b + j >= 0 && b + j < len)
+                               fprintf(out, " %02x", (unsigned char)buf[b + j]);
+                       else
+                               fprintf(out, "   ");
+               }
+
+               fprintf(out, "   ");
+               for (j = 0; j < 16; j++) {
+                       if (b + j >= 0 && b + j < len) {
+                               if (isprint((unsigned char)buf[b + j]))
+                                       fputc((unsigned char)buf[b + j], out);
+                               else
+                                       fputc('.', out);
+                       }
+                       else
+                               fputc(' ', out);
+               }
+               fputc('\n', out);
+       }
+}
+
+int main(int argc, char **argv)
+{
+       struct http_hdr hdrs[MAX_HDR_NUM];
+       int len, outlen, hdr_idx;
+
+       do {
+               if (!fgets(line, sizeof(line), stdin))
+                       break;
+
+               if ((len = hex2bin(line, bin, MAX_RQ_SIZE)) < 0)
+                       break;
+
+               outlen = qpack_decode_fs(bin, len, &buf, hdrs,
+                                        sizeof(hdrs) / sizeof(hdrs[0]));
+               if (outlen < 0) {
+                       fprintf(stderr, "QPACK decoding failed: %d\n", outlen);
+                       continue;
+               }
+
+               hdr_idx = 0;
+               fprintf(stderr, "<<< Found %d headers:\n", outlen);
+               while (1) {
+                       if (isteq(hdrs[hdr_idx].n, ist("")))
+                               break;
+
+                       fprintf(stderr, "%.*s: %.*s\n",
+                               (int)hdrs[hdr_idx].n.len, hdrs[hdr_idx].n.ptr,
+                               (int)hdrs[hdr_idx].v.len, hdrs[hdr_idx].v.ptr);
+
+                       ++hdr_idx;
+               }
+       } while (1);
+
+       return EXIT_SUCCESS;
+}