What?(何が)
RTCQuicTransport は、QUIC プロトコルを使用してリモートピアと任意のデータを交換できる、新しいウェブ プラットフォーム API です。ピアツーピアのユースケースを想定しているため、スタンドアロンの RTCIceTransport API と一緒に使用され、ICE を介してピアツーピア接続を確立します。データが確実かつ順番に転送される(順序指定のない配信や信頼性の低い配信について詳しくは、以下のセクションをご覧ください)。汎用の双方向データ転送であるため、ゲーム、ファイル転送、メディア転送、メッセージングなどに使用できます。
どうしてですか?
強力なローレベル データ転送 API を使用すると、アプリケーション(リアルタイム通信など)がウェブ上で新しい処理を実行できます。たとえば、API に基づいて独自のソリューションを作成し、ピアツーピア接続で可能なことの限界を押し広げることができます(たとえば、カスタム ビットレート割り当てノブのロック解除)。将来的には、エンコードされたメディアのさらなるサポートにより、低レベルの制御を備えた独自の動画通信アプリを構築することも可能になります。WebRTC の NV の取り組みは、下位レベルの API に移行することであり、これを早期にテストすることは非常に重要です。
QUIC を選ぶ理由
QUIC プロトコルは、リアルタイムの通信に適しています。これは UDP 上に構築され、暗号化と輻輳制御が組み込まれており、ヘッド オブ ライン ブロッキングなしで多重化されています。RTCQuicTransport
は RTCDataChannel
API とよく似た機能を備えていますが、トランスポート プロトコルとして SCTP ではなく QUIC を使用します。RTCQuicTransport
はスタンドアロン API であるため、リアルタイムのメディア スタックを含む RTCPeerConnection
API のオーバーヘッドはありません。
方法
汎用 API の概要
API には、RTCIceTransport
、RTCQuicTransport
、RTCQuicStream
という 3 つの主要な抽象化があります。
RTCIceTransport
ICE は、インターネット経由でピアツーピア接続を確立するプロトコルで、現在 WebRTC で使用されています。このオブジェクトは、ICE 接続を確立するためのスタンドアロン API を提供します。これは QUIC 接続のパケット転送として使用され、RTCQuicTransport
がそのコンストラクタで受け取ります。
RTCQuicTransport
QUIC 接続を表します。これは、QUIC 接続を確立し、QUIC ストリームを作成するために使用されます。また、QUIC 接続レベルの関連統計情報も公開されます。
RTCQuicStream
リモート側との間でデータの読み取りと書き込みを行うために使用されます。ストリームは、データを確実かつ順番に転送します。同じ RTCQuicTransport
から複数のストリームを作成できます。データがストリームに書き込まれると、リモート トランスポートで「onquicstream」イベントが発生します。ストリームにより、同じ QUIC 接続上の異なるデータを区別できます。一般的な例として、別々のストリームに別々のファイルを送信したり、異なるストリームに小さなデータチャンクを送信したり、別々のストリームに異なる種類のメディアを送信したりすることが考えられます。RTCQuicStream
は軽量で、QUIC 接続で多重化され、他の RTCQuicStream
へのヘッド オブ ライン ブロッキングは発生しません。
接続の設定
ピアツーピアの QUIC 接続を設定する例を次に示します。RTCPeerConnection
と同様に、RTCQuicTransport
API は、セキュリティ パラメータを含む接続のパラメータについて、ネゴシエートするためにセキュア シグナリング チャネルを使用する必要があります。RTCIceTransport
は、ICE パラメータ(ufrag と password)と RTCIceCandidate
をネゴシエートします。
クライアントの視点:
const iceTransport = new RTCIceTransport();
const quicTransport = new RTCQuicTransport(iceTransport);
// Signal parameters, key and candidates.
signalingChannel.send({
iceParams: iceTransport.getLocalParameters(),
quicKey: quicTransport.getKey(),
});
iceTransport.onicecandidate = e => {
if (e.candidate) {
signalingChannel.send({candidate: e.candidate});
}
};
// When remote parameters are signaled, start connection.
signalingChannel.onMessage = async ({iceParams, candidate}) => {
if (iceParams) {
iceTransport.start(iceParams);
quicTransport.connect();
} else if (candidate) {
iceTransport.addRemoteCandidate(candidate);
}
};
サーバーの視点:
const iceTransport = new RTCIceTransport();
const quicTransport = new RTCQuicTransport(iceTransport);
// Signal parameters, key and candidates.
signalingChannel.send({
iceParams: iceTransport.getLocalParameters(),
});
iceTransport.onicecandidate = e => {
if (e.candidate) {
signalingChannel.send({candidate: e.candidate});
}
};
// When remote parameters are signaled, start connection.
signalingChannel.onMessage = async ({iceParams, quicKey, candidate}) => {
if (iceParams && quicKey) {
iceTransport.start(iceParams);
quicTransport.listen(quicKey);
} else if (candidate) {
iceTransport.addRemoteCandidate(candidate);
}
};
データ移行
データ転送を行うには、RTCQuicStream API を使用して読み取りと書き込みを行います。
RTCQuicStreamReadResult readInto(Uint8Array data);
void write(RTCQuicStreamWriteParameters data);
Promise<void> waitForWriteBufferedAmountBelow(unsigned long amount);
Promise<void> waitForReadable(unsigned long amount);
バッファリング
JavaScript がビジー状態のときに、waitFor*
メソッドによって返される Promise によってデータをバッファリングできます。バック プレッシャーは、受信側で読み取りバッファがいっぱいになると、送信側に適用されます。送信側には、バック プレッシャーが適用されたときにいっぱいになる書き込みバッファがあるため、書き込み側にも waitForWriteBufferedAmountBelow
メソッドがあり、バッファが書き込みを行うのを待機できます。データの書き込みと読み取りの詳細については、該当のデベロッパー向けドキュメントをご覧ください。
順序なし/信頼性が低い配信
RTCQuicStream
はデータの確実な順序付けのみをサポートしますが、信頼できない/順序のない配信は他の方法で実現できます。順序なし配信の場合、ストリーム間でデータが並べ替えられないため、小さなデータチャンクを個別のストリームで送信できます。信頼性の低い配信の場合、finish を true に設定して小さなデータチャンクを送信し、タイムアウト後にストリームで reset()
を呼び出します。タイムアウトは、データをドロップする前に必要な再送回数に依存する必要があります。
時期
オリジン トライアルは Chrome 73 バージョンで開始され、M75 バージョンまで利用できます。この日を過ぎると、オリジン トライアルは終了します。Google は、フィードバックと関心に基づいて適切な変更を加え、API をリリースするか、この API の新しいオリジン トライアルを継続するか、API の提供を中止します。
場所:
iOS 以外のすべてのプラットフォームの Chrome ブラウザ。
他には?
フィードバック
オリジン トライアルの主な目的の一つは、デベロッパーからフィードバックを得ることです。関心のあるトピックは次のとおりです。
- この API で実現できること
- この API は、他のデータ転送 API(
WebSocket
や WebRTC のRTCDataChannel
)をどのように改善していますか?また、改善すべき点を教えてください。 - パフォーマンス
- API エルゴノミクス
オリジン トライアルに登録する
- 送信元のトークンをリクエストします。
- トークンをページに追加します。このトークンを元のページに追加する方法は 2 つあります。
- 任意のページの head 部に
origin-trial
<meta>
タグを追加します。たとえば、<meta http-equiv="origin-trial" content="TOKEN_GOES_HERE">
のようになります。 - サーバーを設定できる場合は、
Origin-Trial
HTTP ヘッダーを使用してページでトークンを指定することもできます。結果のレスポンス ヘッダーは、Origin-Trial: TOKEN_GOES_HERE
のようになります。
- 任意のページの head 部に
ウェブ仕様
ドラフトの仕様は、次のようなオリジン トライアルの API より先立っています。
- WHATWG ストリームにより密接に連動する単方向ストリーム
- 再送信の無効化
- (近日提供予定)データグラム
Google は、完全な仕様とそれ以外(WHATWG ストリームのサポートを含む)の実装に関心がありますが、まずフィードバックをお寄せください。
セキュリティ
QUIC handshake でのセキュリティは、事前共有鍵を使用して暗号化された P2P QUIC 接続を確立することを通じて適用されます。この鍵は、機密性と完全性が保証された安全な帯域外チャネルでシグナリングする必要があります。キーは JavaScript に公開されます。
アクティブな攻撃
証明書のフィンガープリントのシグナリングに完全性のみを必要とする DTLS-SRTP とは異なり、事前共有キーのシグナリングには完全性と機密性が必要です。PSK が(シグナリング チャネルのサーバーなどによって)侵害されると、アクティブな攻撃者が QUIC handshake に対して中間者攻撃を仕掛ける可能性があります。
現在のステータス
ステップ | ステータス |
---|---|
1. 説明を作成 | 完了 |
**2a. RTCQuicTransport 仕様 ** | **進行中** |
**2b. RTCIceTransport の仕様 ** | **進行中** |
**3. フィードバックを収集して設計を繰り返す** | **進行中** |
4. オリジン トライアル | Chrome 73 で開始 |
5. 開始 | 未対応 |
関連リンク
- その他のドキュメント
- 公開の説明
- バグの追跡
- オリジン トライアル トークンをリクエストする
- オリジン トライアル トークンの使用方法
- RTCQuicTransport の問題に関するディスカッション
- RTCIceTransport の問題に関するディスカッション