2022/03/31 最新動向も踏まえ、記事を新しく書き直しました
HTTP DatagramsとCapsuleプロトコルについて - ASnoKaze blog
QUICで再送を必要としないアプリケーションデータを送信するのに、DATAGRAMフレームが利用できます。このDATAGRAMフレームで送ったアプリケーションデータは、パケットの順番が入れ替わったり、パケットロスが起こってもQUICレイヤでの回復は行われません。
HTTP/3を応用したプロトコルであるWebTransportやMASQUEプロトコルでにおいて、このQUIC DATAGRAMフレームを利用するための議論が行われています。
今回は、HTTP/3でQUIC DATAGRAMフレームを使うための仕様を読んでいこうかと思います
www.ietf.org
なお、WebTransportやMASQUEについては過去に書いた記事を御覧ください
Using QUIC Datagrams with HTTP/3
HTTP/3で、QUICのDATAGRAMフレームを使うにあたって、どのHTTPリクエストに紐づくDATAGRAMフレームなのか関連付ける必要があります。
もともとは、ストリームIDで該当のリクエストストリームと紐付ける方法が考えられていました。しかし、ストリームIDはhop-by-hopの値ですので、end-to-endでHTTPリクエストと紐付けられる仕組みに変更されました。こうすることでproxyといった中間装置がいてもend-to-endでDATAGRAMをHTTPリクエストと関連付けることができます。
「Using QUIC Datagrams with HTTP/3」のdraft-01では、Context IDを新しく導入し、HTTPリクエストとDATAGRAMフレームを関連付けます。DATAGRAMフレームを使う前に、HTTP/3のCAPSULEフレームで、リクエストストリーム上で明示的にその関連付けを行います。
なお、Context IDは62bit空間をもち、クライアントから払い出す場合は偶数を、サーバから払い出す場合は奇数となります。
HTTP/3 CAPSULEフレーム
CAPSULEフレームは、HTTP/3レイヤの拡張フレームです。HTTPリクエストを送信したリクエストストリーム上で送信されます。
CAPSULEフレームには、3つのタイプが定義されています。
- REGISTER_DATAGRAM_CONTEXT: HTTPリクエストとDATAGRAMフレームを関連付けるのに使用するContext IDを通知します。
- CLOSE_DATAGRAM_CONTEXT: REGISTER_DATAGRAM_CONTEXTをキャンセルします
- DATAGRAM: QUIC DATAGRAMフレームが使えない場合に、カプセル化してDatagram Payloadを送信します
なお、片方向からREGISTER_DATAGRAM_CONTEXTを送れば、双方向にDATAGRAMフレームが送信できます。
HTTP/3でDATAGRAMフレームを使うときのフォーマット
HTTP/3でQUIC DATAGRAMフレームを使う場合は下記のフォーマットとなります。
関連付けるストリームは、クライアントが開始した双方向ストリームであるリクエストストリームなので、4で割ってQuarter Stream IDとして記載します。Context IDはCAPSULEフレームで登録したIDを指定します。
なお、REGISTER_DATAGRAM_CONTEXTで登録されていないContext IDを受信したエンドポイントは、バッファしておいたREGISTER_DATAGRAM_CONTEXTが届くのを待つか、単純に破棄します。
例
仕様には、MASQUEとWebTrasnportの通信例が紹介されています。例えばWebTransportは次のとおりです。
リクエストストリーム上でREGISTER_DATAGRAM_CONTEXTタイプのCAPSULEフレームを送りContext IDを登録してます。そのご双方向にDATAGAMフレームが送れるようになります。
HTTP/2やHTTP/1.1の場合
HTTP/2やHTTP/1.1でもDatagram Payloadを送れるようにすることを検討しているようです。QUICの接続に失敗するケースで、MASQUEやWebTrasnport個々別にフォールバック先を定義する必要がなくなります。
具体的な方法は今後議論されていくでしょう。