6. ストリームマッピングと使用 (Stream Mapping and Usage)
QUICストリームは、信頼性の高い順序付きバイト配信を提供しますが、他のストリーム上のバイトに関する配信順序については保証しません。QUICバージョン1では、HTTPフレームを含むストリームデータはQUIC STREAMフレームによって運ばれますが、このフレーミングはHTTPフレーミング層には見えません。トランスポート層は受信したストリームデータをバッファリングして順序付けし、アプリケーションに信頼性の高いバイトストリームを公開します。QUICはストリーム内での順序外配信を許可しますが、HTTP/3はこの機能を使用しません。
QUICストリームは、開始者から受信者へのみデータを運ぶ単方向、または両方向にデータを運ぶ双方向のいずれかになります。ストリームはクライアントまたはサーバーのいずれかによって開始できます。QUICストリームの詳細については、[QUIC-TRANSPORT]のセクション2を参照してください。
HTTPフィールドとデータがQUICを介して送信される場合、QUIC層はストリーム管理のほとんどを処理します。QUICを使用する場合、HTTPは個別の多重化を行う必要はありません。QUICストリームを介して送信されるデータは、常に特定のHTTPトランザクションまたはHTTP/3接続コンテキスト全体にマップされます。
6.1. 双方向ストリーム (Bidirectional Streams)
すべてのクライアントが開始した双方向ストリームは、HTTPリクエストとレスポンスに使用されます。双方向ストリームにより、レスポンスをリクエストと容易に関連付けることができます。これらのストリームはリクエストストリーム (Request Streams) と呼ばれます。
これは、クライアントの最初のリクエストがQUICストリーム0で発生し、後続のリクエストがストリーム4、8などで発生することを意味します。これらのストリームを開くことを許可するために、HTTP/3サーバーは、許可されるストリーム数と初期ストリームフロー制御ウィンドウの非ゼロ最小値を設定すべきです (SHOULD)。並列性を不必要に制限しないように、同時に少なくとも100のリクエストストリームを許可すべきです (SHOULD)。
HTTP/3はサーバーが開始した双方向ストリームを使用しませんが、拡張機能がこれらのストリームの用途を定義する可能性があります。クライアントは、そのような拡張機能がネゴシエートされていない限り、サーバーが開始した双方向ストリームの受信をH3_STREAM_CREATION_ERRORタイプの接続エラー (Connection Error) として扱わなければなりません (MUST)。
6.2. 単方向ストリーム (Unidirectional Streams)
いずれかの方向の単方向ストリームは、さまざまな目的に使用されます。目的はストリームタイプ (Stream Type) によって示され、ストリームの開始時に可変長整数として送信されます。この整数に続くデータのフォーマットと構造は、ストリームタイプによって決定されます。
Unidirectional Stream Header {
Stream Type (i),
}
図1:単方向ストリームヘッダー
このドキュメントでは2つのストリームタイプが定義されています:コントロールストリーム (Control Streams)(セクション6.2.1)とプッシュストリーム (Push Streams)(セクション6.2.2)。[QPACK]は2つの追加のストリームタイプを定義しています。他のストリームタイプは、HTTP/3の拡張機能によって定義できます。詳細については、セクション9を参照してください。一部のストリームタイプは予約されています(セクション6.2.3)。
HTTP/3接続のライフタイムの初期段階におけるパフォーマンスは、単方向ストリームでのデータの作成と交換に敏感です。これらのストリームの数やフロー制御ウィンドウを過度に制限するエンドポイントは、リモートピアが早期に制限に達してブロックされる可能性を高めます。特に、実装は、リモートピアが使用を許可されている単方向ストリームの一部で予約ストリーム動作(セクション6.2.3)を行使したい場合があることを考慮すべきです。
各エンドポイントは、HTTPコントロールストリーム用に少なくとも1つの単方向ストリームを作成する必要があります。QPACKには2つの追加の単方向ストリームが必要であり、他の拡張機能にはさらにストリームが必要な場合があります。したがって、クライアントとサーバーの両方が送信するトランスポートパラメータは、ピアが少なくとも3つの単方向ストリームを作成できるようにしなければなりません (MUST)。これらのトランスポートパラメータは、各単方向ストリームに少なくとも1,024バイトのフロー制御クレジットを提供すべきです (SHOULD)。
エンドポイントのピアが重要な単方向ストリームを作成する前にすべての初期クレジットを消費した場合、エンドポイントはより多くの単方向ストリームを作成するために追加のクレジットを付与する必要はありません。エンドポイントは、HTTPコントロールストリームと、必須の拡張機能(QPACKエンコーダーおよびデコーダーストリームなど)に必要な単方向ストリームを最初に作成し、その後、ピアによって許可されている追加のストリームを作成すべきです (SHOULD)。
ストリームヘッダーが受信者によってサポートされていないストリームタイプを示す場合、セマンティクスが不明であるため、ストリームの残りを消費できません。未知のストリームタイプの受信者は、ストリームの読み取りを中止するか、さらなる処理なしで受信データを破棄しなければなりません (MUST)。読み取りが中止された場合、受信者はH3_STREAM_CREATION_ERRORエラーコードまたは予約エラーコード(セクション8.1)を使用すべきです (SHOULD)。受信者は、未知のストリームタイプをいかなる種類の接続エラーとも見なしてはなりません (MUST NOT)。
特定のストリームタイプは接続状態に影響を与える可能性があるため、受信者は、ストリームタイプを読み取る前に受信単方向ストリームからのデータを破棄すべきではありません (SHOULD NOT)。
実装は、ピアがそれらをサポートするかどうかを知る前にストリームタイプを送信してもかまいません (MAY)。ただし、QPACKや他の拡張機能を含む既存のプロトコルコンポーネントの状態またはセマンティクスを変更する可能性のあるストリームタイプは、ピアがそれらをサポートすることが分かるまで送信してはなりません (MUST NOT)。
別段の規定がない限り、送信者は単方向ストリームを閉じるかリセットできます。受信者は、単方向ストリームヘッダーの受信前に単方向ストリームが閉じられたりリセットされたりすることを許容しなければなりません (MUST)。
6.2.1. コントロールストリーム (Control Streams)
コントロールストリームは、ストリームタイプ0x00によって示されます。このストリーム上のデータは、セクション7.2で定義されているHTTP/3フレームで構成されます。
各側は、接続の開始時に単一のコントロールストリームを開始し、このストリームの最初のフレームとしてSETTINGSフレームを送信しなければなりません (MUST)。コントロールストリームの最初のフレームが他のフレームタイプである場合、これはH3_MISSING_SETTINGSタイプの接続エラーとして扱わなければなりません (MUST)。ピアごとに1つのコントロールストリームのみが許可されます。コントロールストリームであると主張する2番目のストリームを受信することは、H3_STREAM_CREATION_ERRORタイプの接続エラーとして扱わなければなりません (MUST)。送信者はコントロールストリームを閉じてはならず (MUST NOT)、受信者は送信者にコントロールストリームを閉じるよう要求してはなりません (MUST NOT)。いずれかのコントロールストリームが任意の時点で閉じられた場合、これはH3_CLOSED_CRITICAL_STREAMタイプの接続エラーとして扱わなければなりません (MUST)。接続エラーはセクション8で説明されています。
コントロールストリームの内容は他のストリームの動作を管理するために使用されるため、エンドポイントは、ピアのコントロールストリームがブロックされないようにするために十分なフロー制御クレジットを提供すべきです (SHOULD)。
単一の双方向ストリームではなく、一対の単方向ストリームが使用されます。これにより、いずれかのピアが可能になり次第データを送信できます。QUIC接続で0-RTTが利用可能かどうかに応じて、クライアントまたはサーバーのいずれかが最初にストリームデータを送信できる場合があります。
6.2.2. プッシュストリーム (Push Streams)
サーバープッシュ (Server Push) は、HTTP/2で導入されたオプション機能で、リクエストが行われる前にサーバーがレスポンスを開始できるようにします。詳細については、セクション4.6を参照してください。
プッシュストリームは、ストリームタイプ0x01によって示され、その後に、可変長整数としてエンコードされた、それが履行する約束のプッシュID (Push ID) が続きます。このストリーム上の残りのデータは、セクション7.2で定義されているHTTP/3フレームで構成され、セクション4.1で定義されているように、0個以上の暫定HTTPレスポンスに続いて単一の最終HTTPレスポンスによって約束されたサーバープッシュを履行します。サーバープッシュとプッシュIDはセクション4.6で説明されています。
サーバーのみがプッシュできます。サーバーがクライアントが開始したプッシュストリームを受信した場合、これはH3_STREAM_CREATION_ERRORタイプの接続エラーとして扱わなければなりません (MUST)。
Push Stream Header {
Stream Type (i) = 0x01,
Push ID (i),
}
図2:プッシュストリームヘッダー
クライアントは、プッシュストリームヘッダーを読み取る前にプッシュストリームの読み取りを中止すべきではありません (SHOULD NOT)。これにより、どのプッシュIDがすでに消費されたかについて、クライアントとサーバーの間で意見の相違が生じる可能性があるためです。
各プッシュIDは、プッシュストリームヘッダーで一度だけ使用されなければなりません (MUST)。クライアントが、プッシュストリームヘッダーに別のプッシュストリームヘッダーで使用されたプッシュIDが含まれていることを検出した場合、クライアントはこれをH3_ID_ERRORタイプの接続エラーとして扱わなければなりません (MUST)。
6.2.3. 予約ストリームタイプ (Reserved Stream Types)
形式が0x1f * N + 0x21(Nは非負整数値)のストリームタイプは、未知のタイプを無視する要件を行使するために予約されています。これらのストリームにはセマンティクスがなく、アプリケーション層のパディングが必要な場合に送信できます。現在データが転送されていない接続でも送信してもかまいません (MAY)。エンドポイントは、受信時にこれらのストリームが何らかの意味を持つと見なしてはなりません (MUST NOT)。
ペイロードとストリームの長さは、送信実装が選択する任意の方法で選択されます。予約ストリームタイプを送信する場合、実装はストリームをクリーンに終了するかリセットしてもかまいません (MAY)。ストリームをリセットする場合、H3_NO_ERRORエラーコードまたは予約エラーコード(セクション8.1)を使用すべきです (SHOULD)。