ロングヘッダーの往復
ロングヘッダーは、QUIC が接続を確立するまでのパケットに使うヘッダー形式です。 どのロングヘッダーも、同じ不変のフィールド(タイプ、バージョン、2 つのコネクション ID)から始まります。 このページでは Initial(接続の最初に送るパケット種別)のヘッダーをエンコードし、それをデコードし直します。
コード
#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;}実行結果
$ ./quic-headerbuilt 23 bytes: c000000001088394c8f03e51570808f067a5502a4262b5form=long type=Initial version=0x00000001dcid=8394c8f03e515708scid=f067a5502a4262b5wired_headerはヘッダーのフィールドを保持します。long_typeにはWIRED_LP_INITIAL、WIRED_LP_0RTT、WIRED_LP_HANDSHAKE、WIRED_LP_RETRYのいずれかを入れます。wired_header_build_long(buf, cap, &h)は先頭バイト、バージョン、長さ付きの DCID と SCID(宛先と送信元のコネクション ID)を書き込み、書いたバイト数を返します。 バッファーに収まらないときは 0 を返します。wired_header_parse(buf, n, &h)はそれらを読み戻し、消費したバイト数を返します。 入力が途中で切れているか不正なときは 0 を返します。wired_dprintfは数値と文字列 (%llu,%08x,%s) を stderr に書き出します。 バイト列を 16 進で出す変換指定は printf に無いので、wired_dump_hexを使います。