summaryrefslogtreecommitdiffstats
path: root/dev/qpack/decode.c
diff options
context:
space:
mode:
Diffstat (limited to 'dev/qpack/decode.c')
-rw-r--r--dev/qpack/decode.c171
1 files changed, 171 insertions, 0 deletions
diff --git a/dev/qpack/decode.c b/dev/qpack/decode.c
new file mode 100644
index 0000000..b2d233a
--- /dev/null
+++ b/dev/qpack/decode.c
@@ -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;
+}