QUICにおけるヘッダ圧縮の提案仕様 QPACK(旧QCRAM) その2 (draft-04)

20180313追記
QCRAMと呼ばれていた仕様は、QPACKに改称されました。
github.com


HTTP over QUICでは、HTTP/2のフレームを利用するが、HTTPヘッダ圧縮にHTTP/2のHPACKをそのまま使用するのはHoLBの問題が知られている。

HPACKでは、ヘッダが送った順番通りに届く事を想定しており、送信側と受信側が完全に同じ状態を保てる。しかし、QUICではメッセージの届く順番は入れ替わる可能性があり、動的テーブルの参照する際にまだそのインデックスが挿入されていないというケースが生じうる。QUICでは、届いたメッセージから処理できるはずが、ここで待ち状態になってしまう。

そこでQUICでのHTTPヘッダ圧縮は新しい仕組みを導入することが検討されており、幾つか提案されているなかの一つが「Header Compression for HTTP over QUIC」であり、QCRAMと呼ばれている。

そのQCRAMが Call for Adoption となっている、またGo実装でもあるminhqでもQCRAMが試験的に実装されている。IETF101に向けて、事前に仕様を読んでおく。

今回は、前回のdraft-02からのアップデートのみ触れる。詳しくは前回を参照のこと。
asnokaze.hatenablog.com

draft-04

Call for Adoption となっている、現在のQCRAMはdraft-04であり、draft-02から幾つかの変更点がある。

主な変更点である、下記について書く

  • HEADER_ACK
  • BLOCKING flag
  • ヘッダブロックプレフィックス
HEADER_ACK フレーム

新しく HEADER_ACKフレームが定義される。これは、デコーダ側がヘッダブロックを処理した際にControl Streamでエンコーダ側へ通知される。このHEADER_ACKフレームをエンコーダ側が受信することで、送ったヘッダがどこまで処理されてるか判別することが出来るようになる。

f:id:ASnoKaze:20180212221216p:plain

  • Stream ID: ヘッダブロックを処理したストリームID(可変長)

trailersなどで複数回ヘッダブロックを処理する可能性があるが、おそらくその都度送信される。

BLOCKING フラグ

HEADERSフレームとPUSH_PROMISEフレームにBLOCKING フラグが追加されます。

前述のHEADER_ACKによってエンコーダ側は送信したヘッダブロックがどこまで処理されているかを知ることが出来ます。そこで、ヘッダブロックを送信する際に、そのデコーダ側がヘッダブロックを処理するのにブロックされうるのかが分かります。

このフラグが0の場合は、デコーダ側はすぐにそのヘッダブロックを処理できます。1の場合は、依存するヘッダブロックが処理されるまで待つ可能性があります。

ヘッダブロックプレフィックス

以前の記事で説明したとおり、QCRAMではヘッダブロックにプレフィックスが追加されます。このプレフィックスもdraft-02から変更されています。

このヘッダブロックプレフィックスは、BLOCKING フラグによって変わります。
BLOCKINGフラグが0の場合が左、BLOCKINGフラグが1の場合は右です。


f:id:ASnoKaze:20180212231947p:plain

  • Base Index: 現在のヘッダブロックを初果する前の、追加されたエントリの合計
  • Depends: Base Indexの位置よりどれくらい前のインデックスに依存するか。Base Index - Dependsが依存する最大のインデックス値になります。

HPACKではエントリを挿入するたびにインデックス値がずれていきましたが、Base Indexから場所を計算することで順番通りでない挿入でも正しい場所にエントリを挿入できます。

Dependsがあることで、ブロックの処理を開始する前に必要なインデックス値を確認できるようになっています。