RTCQuicTransport Coming to an Origin Trial Near You (Chrome 73) | Web | Google Developers
今回は翻訳ではなく、気になる点の抜粋です。
TL;DR
- WebRTCにQUICがくるよ
- まずは`RTCQuicTransport`がChromeに実装されます
- M73からOriginTrialできます
WebRTCにQUICがくる
- まずは`RTCQuicTransport`というクラスから
- ICEは変わらず、`RTCIceTransport`というクラスに
- QUICなので順序も再送も保証!
- ゲームやメディアや様々な用途に使えるよ
なんで
- こういう低レイヤーが充実すると、もっといろんなことができる
- それがWebRTC Next Versionだよ
なぜQUIC
- リアルタイム性のため
- UDPの上に位置する
- `RTCDataChannel`的に見えるかも
- 似てるけど違う
- それSCTPじゃなくてQUICでできるよ
- `RTCPeerConnection`とも隔離されてるし
どうやって使うの
- 3つの構成要素がカギ
- `RTCIceTransport`
- `RTCQuicTransport`
- `RTCQuicStream`
RTCIceTransport
- ICEです
- `RTCQuicTransport`のコンストラクタに渡される
RTCQuicTransport
- QUICのコネクション
- なので接続状況のstatsとかもとれる
RTCQuicStream
- Read/Write
- 1つの`RTCQuicTransport`に複数もてる
- なんかWriteすると`onquicstream`イベントがリモートで発火する
- 軽量でコネクションを越えてmultiprexされる
コードのイメージ
コネクションの確立
ただコピペしてもしゃーないので、コメントをいれてみた。
とあるクライアント。
const iceTransport = new RTCIceTransport(); // ICEは別クラスになってて渡せる const quicTransport = new RTCQuicTransport(iceTransport); // いわゆるオファー // シグナリングを規定しないのは変わらず signalingChannel.send({ // SDPの代わり iceParams: iceTransport.getLocalParameters(), quicKey: quicTransport.getKey(), }); // TrickleICEっぽい iceTransport.onicecandidate = e => { if (e.candidate) { signalingChannel.send({candidate: e.candidate} ); } } // いわゆるアンサー待ち signalingChannel.onMessage = async ({iceParams, candidate}) => { // これがアンサー if (iceParams) { iceTransport.start(iceParams); quicTransport.connect(); } // ICE candidateだけ else if (candidate) { iceTransport.addRemoteCandidate(candidate); } };
とあるサーバー。
ほとんど一緒。
const iceTransport = new RTCIceTransport(); const quicTransport = new RTCQuicTransport(iceTransport); signalingChannel.send({ iceParams: iceTransport.getLocalParameters(), }); iceTransport.onicecandidate = e => { if (e.candidate) { signalingChannel.send({candidate: e.candidate}); } } signalingChannel.onMessage = async ({iceParams, quicKey, candidate}) => { if (iceParams && quicKey) { iceTransport.start(iceParams); quicTransport.listen(quicKey); } else if (candidate) { iceTransport.addRemoteCandidate(candidate); } };
実行順序やら細かいところには目をつぶるとして、だいたいこんな感じらしい。
`RTCPeerConnection`的な層がないとこんな感じよねー。
データを送る
`RTCQuicStream`にあるAPIはこんな感じらしい。
RTCQuicStreamReadResult readInto(Uint8Array data); void write(RTCQuicStreamWriteParameters data); Promise<void> waitForWriteBufferedAmountBelow(unsigned long amount); Promise<void> waitForReadable(unsigned long amount);
肝心の`stream`はこのように。
quicTransport.addEventListener('quicstream', stream => { // ... });
受け取った`stream`の使い方はこちらから。
Read
let readAllData = false; while (!readAllData) { await readStream.waitForReadable(readStream.maxReadBufferedAmount / 2); const readBuffer = new Uint8Array(stream.maxReadBufferedAmount); const { amount, finished } = readStream.readInto(readBuffer); // Do something with the data. } // Close the stream. Writing a finish back to the remote side also will close // the stream. readStream.reset();
Write
while (haveDataToWrite()) { await waitForWriteBufferedAmountBelow(writeStream.maxWriteBufferedAmount / 2); const nextChunkSize = writeStream.maxWriteBufferedAmount - writeStream.writeBufferedAmount; writeStream.write({ data: getNextChunk(nextChunkSize) }) } // All waitForReadable promises are resolved when the finish arrives to the read // buffer on the remote side. Writing it after we are done here ensures that // all chunks of data are read out on the remote side. writeStream.write({ finish: true });
という感じで、どことなくWHATWG Streamを思わせる・・・。
バッファリング
unordered/unreliable
- QUICだとデフォルトでできない
- なので意図的にストリームを分けるとかしてやって
いつから使えるの
- ChromeのM73からOriginTrial
- M75まで
その他
セキュリティ
- QUICのhandshakeで使うキーはJSから見えます
- シグナリングするときは気をつけて
- PSK
というわけで
まだ全然一般ユーザーには関係ないけど、WebRTC業界としては大きな動きがありそうという。
実装される風のAPIたちも、本家のSpecと微妙に違うようにも見えるし、まだまだ変わる可能性に満ち溢れてるけど・・。
初OriginTrialしてみようかしら。