HTTP DatagramsとCapsuleプロトコルについて

HTTP Datagrams and the Capsule Protocol」という提案仕様が出されている。長く議論されている仕様ではあるが、動きがあったので眺めておく

背景

トランスポートプロトコルであるQUICでは、パケットロスがあったとしてもアプリケーションプロトコルのデータは再送してピアに届けられます。

「RFC9221 An Unreliable Datagram Extension to QUIC」という仕様で定義される、QUIC DATAGRAMフレーム拡張では、信頼性のないアプリケーションデータの送受信が可能になります。DATAGRAMフレームのデータはパケットロスで失われても再送する必要はありません。

DATAGRAMフレームは受信したものから処理することができます、アプリケーションの要件によりデータの再送が必要な場合はアプリケーションレイヤで再送信を行うこともできます。

f:id:ASnoKaze:20220331001525p:plain

WebTransportやMASQUE(CONNECT-UDP)といった仕様では、このQUIC DATAGRAM拡張をHTTPで利用します。ただし、普通のQUIC DATAGRAMフレームはストリーム上で送信されません。HTTPでDATAGRAMを送受信するには、HTTPメッセージと関連付ける必要があります。それを定義するのが「HTTP Datagrams and the Capsule Protocol」です。

もともとHTTP/3を前提にしていましたが、途中にProxyが居るケースなどを想定しHTTP/1.1やHTTP/2も想定したCapsuleプロトコルとともに標準化が進められています。

なお、WebTransportやMASQUE(CONNECT-UDP)については過去に書いた記事を御覧ください

(HTTP DatagramはWebTransportなどで利用されます。通常のHTTPリクエスト・レスポンスで使う想定は今のところありません)

HTTP DatagramsとCapsuleプロトコル

HTTP/3, HTTP/2, HTTP/1の場合でそれぞれ、データの送り方が違います。

  • HTTP/3では、QUIC DATAGRAMフレームを利用します
  • HTTP/2では、拡張CONNECTでトンネルを確立し、CAPSULEプロトコルを使ってデータを送信します。(信頼性のない通信はできません)
  • HTTP/1では、HTTP Upgradeの手順でトンネルを確立し、CAPSULEプロトコルを使ってデータを送信します。(信頼性のない通信はできません)

常にHTTP/3(QUIC)が使えるとは限りません、QUICがブロックされている環境では、HTTP/2やHTTP/1.1でDatagramメッセージを送れる必要があります。このときCAPSULEプロトコルという仕組みでは、TCPなHTTPでDatagramメッセージをやりとりできるようになります。

HTTP/3

HTTP/3では、QUIC DATAGRAMフレームに以下のデータを格納します
f:id:ASnoKaze:20220331002111p:plain

  • Quarter Stream IDは、このDatagramが関連付けられれたHTTPリクエストのストリームIDが格納されます (クライアントが開始したストリームが前提なので4で割った数値で十分)
  • HTTP Datagram Payloadは、アプリケーションのデータです

ご覧の通り、以前まであった、一つのストリームに複数のDatagaram フローを関連付ける仕組みはなくなりました (CONNECT-UDPといったより上位のプロトコルで定義してたりします)。

なおこの拡張を利用するには、H3_DATAGRAM SETTINGSパラメータが有効になっている必要があります。

HTTP/1.1とHTTP/2におけるコネクションの確率

DatagramメッセージをTCPなHTTPプロトコルで送信できるようにします。

HTTP/1.1の場合は Upgradeの手順をもって通信を一旦確立します。その後、そのコネクション上でデータをやり取りします
```
GET https://proxy.example.org/.well-known/masque/udp/192.0.2.42/443/ HTTP/1.1
Host: proxy.example.org
Connection: upgrade
Upgrade: connect-udp
```

HTTP/2の場合は拡張CONNECTの手順をもって通信を一旦確立します。その後、そのコネクション上でデータをやり取りします。
```
HEADERS
:method = CONNECT
:protocol = connect-udp
:scheme = https
:path = /.well-known/masque/udp/192.0.2.42/443/
:authority = proxy.example.org
```

やりとりするデータはCAPSULEプロトコルに則ります

CAPSULEプロトコル

CAPSULEプロトコルでは確立された通信路で、次の形式でメッセージを送受信します。ここに、Datagramデータが入ることになります。
f:id:ASnoKaze:20220331003315p:plain

(なお、CAPSULEプロトコルはType, Length, Valueの形式をしており、独自のTypeを定義し任意のメッセージをカプセル化できます)

おまけ、あるいは動向

HTTP Datagrams and the Capsule Protocol」ではあくまでHTTP DatagramsとCapsuleプロトコルを定義しているだけで、上位のプロトコルがどのように使うかは定義されていません。

WebTransportやCONNECT-UDPの仕様を見るとよりイメージが湧くかと思います。

先日行われたIETF113では、WebTransport over HTTP/2でCAPSULEプロトコルを利用するのか議論がありましたが結論はでてません。まだまだ動きがありそうです。