ハンドシェイクと可観測性のつまみ
接続が運ぶ内容そのものは変えず、接続がそこへ至る過程と、あわせて記録される情報だけを変える 4 つのサーバーオプションです。 セッションチケットによる再開、RFC 9000 8.1.2 の Retry、 輻輳制御(ネットワークの混み具合に合わせて送信量を調整する仕組み)のアルゴリズム、 そして qlog / NSS key log の出力です。
コード
#define WIRED_MAIN#include "wired.h"
static int on_request( void* ctx, const wired_h3reqdrive_req* req, u64 offset, wired_obuf* body_out, const char** content_type, int* more, u64* total_size) { (void)ctx; (void)req; (void)offset; (void)more; (void)total_size; wired_log_str("request /\n"); *content_type = "text/plain"; wired_obuf_printf(body_out, "ok"); return 1;}
int wired_main(int argc, char** argv) { /* The same fixed demo identity as the HTTP/3 hello page. */ static wired_srvboot_demo_keys keys; wired_srvboot_id id; wired_srvboot_demo(&id, &keys, 0x50, "guide-h3"); /* Non-0 enables session-ticket resumption/0-RTT (RFC 8446 4.6.1): the * SDK's per-process ticket seed; the sealing side and this id derive the * same rotating ticket keys from it. */ id.ticket_key = wired_srvloop_ticket_key();
wired_srvrun_opt opt = {0}; opt.incoming_cpu = -1; /* RFC 9000 8.1.2: answer every Initial with a stateless Retry first, * only accepting one that carries a valid Retry token. */ opt.force_retry = 1;
wired_srvrun_obs obs = { "demo.qlog", /* RFC 9002-shaped packet_sent/packet_received events */ "demo.keylog", /* SSLKEYLOGFILE, decrypts a capture in Wireshark */ 0, 0, 1, /* CC_ALGO_CUBIC (see transport/recovery/congestion/cc/cc.h); * 0 = NewReno, 2 = BBR */ };
u16 port = (u16)wired_cliargs_int(argc, argv, "--port", 4433); wired_srvrun_handler h = {.cb = on_request}; return wired_server_run_opt(port, &id, h, obs, &opt) ? 0 : 1;}実行結果
$ ./ops-handshake-knobs --port 4433request /conn closed by peer (CONNECTION_CLOSE)$ probe h3get 127.0.0.1:4433 /GET / status=200 content-type=text/plain body="ok"id.ticket_key = wired_srvloop_ticket_key()は、セッションチケットによる再開 (RFC 8446 4.6.1。往復を待たずにデータを送り始める 0-RTT の前提条件)を有効にします。 チケットキーは SDK がプロセスごとに持つシードから導出し、2 時間ごとに切り替えます。 新しいチケットは現在のキーで封印し、提示されたチケットは現在か 1 つ前のキーで復号します。 それより古いチケットは無視され、クライアントは通常のハンドシェイクを行います。opt.force_retry = 1を設定すると、有効な Retry トークンを持たない Initial (接続開始時の最初のパケット)には、 まずステートレスな Retry が返るようになります(RFC 9000 8.1.2)。 quic-interop-runner の retry テストケースにおけるサーバー側の動作です。 実際のクライアントはこれを自動で処理するので、往復が 1 回増えるだけで、ハンドシェイクは普通に完了します。obs.cc_algoは、新しい接続の輻輳制御アルゴリズムを選びます (CC_ALGO_NEWRENOが 0、CC_ALGO_CUBICが 1、CC_ALGO_BBRが 2。transport/recovery/congestion/cc/cc.hを参照)。 ビルド側で上書きしない限り、0は Cubic(srvrun.c のWIRED_CC_ALGO_DEFAULT)を意味します。 実行時に NewReno を明示的に指定しても値は同じ0で、 「未指定」と区別できないためです。 デフォルトを NewReno にしたいビルドは、代わりに-DWIRED_CC_ALGO_DEFAULT=0を上書きします。obs.qlog_pathとobs.keylog_pathは、qlog(RFC 9002 の形式に沿ったpacket_sent/packet_receivedイベント)と、 Wireshark などのツールがキャプチャの復号に使う NSS key log(SSLKEYLOGFILE形式)を書き出します。 どちらもデフォルトは 0(無効)です。