Skip to content

Long header round trip

Every QUIC long header starts with the same invariant fields: type, version and two connection IDs. This page encodes an Initial header and decodes it again.

Code

main.c
#define WIRED_MAIN
#include "wired.h"
int wired_main(int argc, char** argv) {
(void)argc;
(void)argv;
/* An Initial, version 1, with the connection IDs of RFC 9001 Appendix A. */
wired_header in = {.long_type = WIRED_LP_INITIAL, .version = 1};
in.dcid_len = 8;
in.scid_len = 8;
memcpy(in.dcid, "\x83\x94\xc8\xf0\x3e\x51\x57\x08", 8);
memcpy(in.scid, "\xf0\x67\xa5\x50\x2a\x42\x62\xb5", 8);
u8 wire[64];
usz n = wired_header_build_long(wire, sizeof wire, &in);
wired_header out = {0};
if (n == 0 || wired_header_parse(wire, n, &out) != n) return 1;
static const char* types[] = {"Initial", "0-RTT", "Handshake", "Retry"};
wired_dprintf(2, "built %llu bytes: ", (u64)n);
wired_dump_hex(2, wired_span_of(wire, n));
wired_dprintf(
2, "\nform=%s type=%s version=0x%08x\ndcid=",
out.form == WIRED_FORM_LONG ? "long" : "short", types[out.long_type],
out.version);
wired_dump_hex(2, wired_span_of(out.dcid, out.dcid_len));
wired_dprintf(2, "\nscid=");
wired_dump_hex(2, wired_span_of(out.scid, out.scid_len));
wired_dprintf(2, "\n");
return 0;
}

Output

Terminal window
$ ./quic-header
built 23 bytes: c000000001088394c8f03e51570808f067a5502a4262b5
form=long type=Initial version=0x00000001
dcid=8394c8f03e515708
scid=f067a5502a4262b5
  • wired_header holds the fields; long_type takes WIRED_LP_INITIAL, WIRED_LP_0RTT, WIRED_LP_HANDSHAKE or WIRED_LP_RETRY.
  • wired_header_build_long(buf, cap, &h) writes byte 0, the version and the length-prefixed DCID and SCID, and returns the byte count (0 if it does not fit).
  • wired_header_parse(buf, n, &h) reads them back and returns the bytes consumed (0 on truncated or malformed input).
  • wired_dprintf formats numbers and strings (%llu, %08x, %s) to stderr; wired_dump_hex writes a byte span as hex, which printf has no conversion for.