メインコンテンツまでスキップ

2. 圧縮プロセスの概要 (Compression Process Overview)

HPACK と同様に、QPACK はフィールド行をインデックスに関連付けるために 2 つのテーブルを使用します。静的テーブル(セクション 3.1 を参照)は事前定義されており、共通のフィールド行(一部は値あり、一部は値なし)が含まれています。動的テーブル(セクション 3.2 を参照)は動的に構築され、エンコードされたフィールドセクション内の繰り返しフィールドの効率的なエンコーディングを可能にします。

QPACK は、フィールドセクションのエンコーディングまたはデコーディングをブロックすることなく、動的テーブルの状態を変更および追跡するための単方向ストリームを定義します。エンコーダストリームは、エンコーダからデコーダへのテーブル変更を運び、デコーダストリームは、デコーダからエンコーダへのテーブル変更の確認応答とテーブル使用を運びます。

QPACK は、必要な動的テーブル状態が利用可能になる前にデコーダがブロック解除できるようにする、エンコードされたフィールドセクションのモデリング命令を提供します。これは、ストリームが多重化される際に順序外配信により発生する可能性があります。

2.1 エンコーダ (Encoder)

エンコーダは、フィールドセクションを静的テーブルまたは動的テーブルのエントリと照合することにより、一連の表現に変換します。フィールド行名を超える参照情報は、一致する名前と値を持つフィールド行のエントリを参照することによって([RFC7541] のセクション 3.2.3 を参照)、または一致する名前と異なる値を持つフィールド行のエントリを参照することによって([RFC7541] のセクション 3.2.4 を参照)エンコードできます。

エンコーダは、Post-Base リテラルインデックス(セクション 4.5.5 を参照)を使用して静的フィールド行を参照してはなりません(MUST NOT)。デコーダは、静的テーブルを参照するインデックスを持つ Post-Base 命令の受信を QPACK_DECOMPRESSION_FAILED タイプのストリームエラーとして扱わなければなりません(MUST)。

2.1.1 動的テーブル挿入の制限 (Limits on Dynamic Table Insertions)

エンコーダは、デコーダからのシグナル(セクション 4.4.1 を参照)を使用して、動的テーブル内のエントリの最大数を制限します。エンコーダは、動的テーブルがその最大容量を超える原因となる場合、動的テーブルにエントリを挿入(または既存のエントリを複製)してはなりません(MUST NOT)。将来の挿入のために動的テーブルのスペースを保持するために、エンコーダは最大容量より低い容量を設定することで重複エントリを削除することを選択できます(セクション 3.2.3 を参照)。

エンコーダは、デコーダが通知した最大容量より大きい値に動的テーブルの容量を設定してはなりません(MUST NOT)。HTTP/3 では、この最大値はデコーダから受信した SETTINGS_QPACK_MAX_TABLE_CAPACITY パラメータ(セクション 5 を参照)の値です。エンコーダは、デコーダがその後より大きなパラメータを送信した場合でも、動的テーブルの容量をこの最大値より大きい値に設定してはなりません(MUST NOT)。

エンコードされた各フィールドセクションについて、動的テーブルに最も最近挿入されたエントリがまだ削除可能でない場合、エンコーダは必要挿入カウント(セクション 4.5.1 を参照)と挿入カウント増分命令(セクション 4.4.3 を参照)を挿入しなければなりません(MUST)。デコーダは、その動的テーブルの現在の状態を、フィールドセクションをデコードするために必要な動的テーブルの状態と比較します。十分でない場合、デコーダは同期が達成されるまでセクションの処理をブロックできます(セクション 2.2 を参照)。

2.1.2 ブロックされたストリーム (Blocked Streams)

動的テーブルを参照する表現の場合、デコーダがフィールドセクションの処理をブロックする可能性がある場合、エンコーダはブロックされたストリームの数がデコーダによって許可された最大値を超えないことを確認しなければなりません(MUST)。ストリームは、参照される最大の動的テーブルエントリがまだ受信されていない場合、ブロックされていると見なされます。表現は任意の順序でエントリを参照でき、エンコーダは一般に相対インデックスを使用することに注意してください(セクション 3.2.5 を参照)。したがって、フィールドセクションが古いエントリを参照している場合でも、ブロックされている可能性があります。

エンコーダは、ストリームのブロックを回避する場合、動的テーブルを参照しない表現を使用することを選択できます(MAY)。

エンコーダがブロックされると予想されるストリーム上のフィールドセクションをエンコードする場合、エンコーダは必要挿入カウントが達成されるか、まもなく達成されるように Base 値(セクション 4.5.1 を参照)を選択します。必要挿入カウントが現在動的テーブルに存在するエントリの数を超える場合、デコーダによって不足しているエントリが動的テーブルに挿入されるまで、フィールドセクションはブロックされます(セクション 4.4.3 を参照)。

エンコーダ実装は、静的テーブルを参照する表現のみを使用するか、リテラルを使用することを決定できます。このようなエンコーダは、動的テーブル処理でストリームをブロックする必要がなく、ブロックされたストリームの最大数を超えるリスクもありません。圧縮効率を犠牲にして、この実装はブロックされたストリームの数を追跡する必要もありません。

動的テーブルにエントリを挿入する選択と、エンコードされたフィールドセクションでそれらへの参照は独立した決定であることに注意してください。エンコーダは、「Insert With Name Reference」命令(セクション 4.3.2 を参照)を使用して動的テーブルにエントリを挿入し、そのエントリを参照しないことができます。

2.1.3 フロー制御デッドロックの回避 (Avoiding Flow-Control Deadlocks)

エンコーダストリームへの書き込みでは、エンコーダは書き込む前にデコーダストリームでデータが到着するのを待つべきではありません。実装がこれを行う場合、デッドロックの可能性があります。デコーダはエンコーダに比例フロー制御クレジットを付与するため、エンコーダが過度に書き込む場合、デコーダはエンコーダストリームからいくつかのデータを読み取ることができるまでブロックする可能性があります。ただし、エンコーダがデコーダストリームで他のものをエンコーダストリームに書き込む前にデコーダが確認応答を送信するのを待つ場合、デッドロックが発生する可能性があります:デコーダはフロー制御クレジットのロック解除を待っているためブロックされているため確認応答を送信できず、エンコーダはデコーダからの確認応答を待っているためフロー制御クレジットをロック解除するものを書き込みません。

QUIC のフロー制御の詳細については、[QUIC-TRANSPORT] のセクション 4 を参照してください。

2.1.4 既知受信カウント (Known Received Count)

エンコーダがデコーダが持っていると考える動的テーブルを識別するために、エンコードされたフィールドセクション(セクション 4.5.1 を参照)には必要挿入カウントが含まれています。必要挿入カウントは、エンコードされたフィールドセクションで動的テーブルを参照するために使用される最大の絶対インデックスを示し、整数としてエンコードされます。必要挿入カウントと、確認応答されてから削除されたテーブルエントリの数を使用して、エンコーダストリームとデコーダストリームの命令は相対インデックスまたは Post-Base インデックスを使用してテーブルエントリを識別できます(セクション 3.2.5 およびセクション 3.2.6 を参照)。

デコーダは、エンコードされたフィールドセクションの処理を完了した後、セクション確認応答(セクション 4.4.1 を参照)を送信します。この確認応答は、ラウンドトリップ遅延後にエンコーダによって受信されます。確認応答された最大必要挿入カウントは、セクション確認応答が受信された最高の絶対インデックスに 1 を加えたものです。このインデックスは、デコーダの「既知受信カウント」または「Known Received Count」とも呼ばれます。

2.2 デコーダ (Decoder)

HPACK と同様に、デコーダは一連の表現を処理し、それらをフィールド行のリストに追加します。リテラルである表現は、静的に提供された名前と値を持つフィールド行を追加します。インデックス付きである表現は、静的テーブルまたは動的テーブルのエントリから名前と値を取得してフィールド行を追加します。

デコーダは、エンコーダストリームでエンコーダ命令を受信します。エンコーダ命令が動的テーブルに新しいエントリを挿入すると、デコーダは独自の動的テーブルに対応するエントリを作成します(セクション 4.3.1 を参照)。このエントリは、エンコードされたフィールドセクションによって参照できるようになります。

2.2.1 ブロックされたストリーム (Blocked Streams)

エンコードされたフィールドセクションを処理する際、デコーダはまだ受信されていない動的テーブルエントリへの参照に遭遇する可能性があります。この場合、デコーダはフィールドセクションのデコードを一時停止し、関連するストリームをブロックします。デコーダは、必要なすべての動的テーブルエントリが受信され、動的テーブルに挿入されると、ストリームのブロックを解除します。

デコーダは、エンコードされたフィールド行で参照されているすべての動的テーブルエントリを受信する前にストリームのブロックを解除してはなりません(MUST NOT)。

順序外配信とエンコーダストリームがブロックされるリスクを考慮すると、デコーダ実装は、エンコーダストリームとデコーダストリームを含むすべてのストリーム間で公平な読み取り戦略を採用する必要があります。ブロッキングのためにストリームを処理できない場合、デコーダは、ブロックされたストリームをより迅速にブロック解除するために、エンコーダストリームを含む他の利用可能なストリームから読み取りを続行する必要があります。

2.2.2 状態同期 (State Synchronization)

デコーダは、デコードされたフィールドセクションによって参照されるすべての新しいテーブルエントリについてエンコーダに通知しなければなりません(MUST)。これにより、エンコーダは、デコーダの状態がサポートできるテーブルへの参照を認識できます。この情報がないと、エンコーダはデコーダによって既に削除されたエントリを参照し、デコードエラーが発生する可能性があります(セクション 3.2.4 を参照)。

デコーダは、エンコードされたフィールドセクションの処理を完了した後、セクション確認応答を送信します(セクション 4.4.1 を参照)。この確認応答は、以前に受信されたフィールドセクションによって参照されたすべての動的テーブルエントリが受信されたことをエンコーダに通知します。

セクション確認応答を送信する際、デコーダはフィールドセクションで参照された挿入されたエントリを示すエンコーディングの Base 値(セクション 4.5.1 を参照)を選択します。デコーダは、デコードされたフィールド行を HTTP/3 アプリケーションに返す前に、デコーダストリーム(セクション 4.2 を参照)でこの確認応答を送信しなければなりません(MUST)。

以前にデコードされたエンコードされたフィールドセクションが既に同じエントリを参照している場合、動的テーブルへの一部の参照は追加のセクション確認応答を生成しない可能性があります。エンコーダは、デコーダがそれを使用しなくなった場合でも、動的テーブルから削除する前に、参照された最新のテーブルエントリがセクション確認応答によって確認されたことを確認しなければなりません(MUST)。

デコーダは、エンコーダの既知の状態を変更しない場合(つまり、すべての参照が既に確認されている場合)、セクション確認応答を送信しないことを選択することもできます。

ストリームがリセットまたは放棄された場合、デコーダはセクション確認応答の代わりにストリームキャンセル命令(セクション 4.4.2 を参照)を送信します。これにより、関連するフィールドセクションが無視されたことがエンコーダに通知され、エンコーダがそのストリームの状態の追跡を停止できるようになります。