読者です 読者をやめる 読者になる 読者になる

Block Rockin’ Codes

back with another one of those block rockin' codes

Blog を引っ越しました

blog web

新しい技術などを自分で色々試せるように、自分のドメインの、自分で作ったブログに移行しました。

ここの記事も、いくつかはアップデートがてら移行していく予定です。

あたらしいブログは以下です。

よろしくお願いします。

2015 年をふりかえる

Intro

個人的には HTTP2 と ORTC/WebRTC と Service Worker 周りさわって、 JS と Go を書いてる一年だった。

Extensible Web - Progressive Web APP

Extensible Web で始まった話が、様々な API の設計に適用された。 結果手に入った Service Worker を始めとする Low Level API を組み合わせて、もう一度モバイルと Web の関係を見直す Progressive Web App まで進み、 Web の形が見直された年だった。

Extensible Web の夜明けと開発者が得た可能性の話 - Block Rockin’ Codes

HTTPS

また、 HTTPS の重要性の認識が、啓蒙からデプロイまで降りたという印象。そして、待望だった Let's Encrypt がついに始まった。 ブラウザの APIHTTPS only も増えているので、まだしばらく続きそう。

Let's Encrypt を支える ACME プロトコル - Block Rockin’ Codes

HTTP2

5 月についに RFC7540 が出て、策定というフェーズでは一段落した。 そこからは #http2study も、「どう使うか」というフェーズに移って、デプロイに向けた知見を整えて行くフェーズかなと思っている。 HTTP2 は未だに、その本質が正しく理解されてない部分もあるかなと思うので、これは引き続き来年もやっていきたい。

HTTP2 の RFC7540 が公開されました - Block Rockin’ Codes

ORTC/WebRTC

割ととめまぐるしい一年だった。 特に SVC Simulcast 周りの理解が WebRTC 側にも進んで、WebRTC NV へはそこが取り込まれる方向で話がまとまった。 WebRTC をまじめにやると、JS でのフロントの実装は全体のほんの一部で、それ以外にもかなり広範囲な分野の知識と技術が必要になる。 今年後半から来年に書けてはむしろそっちの方をやっていく予定。

ORTC が切り開く SVC サイマルキャストと WebRTC NV - Block Rockin’ Codes

mozaic.fm

今年は 8 エピソードを公開した。 出て頂いた皆さん、本当にありがとうございました。

セキュキャン

フレームワークを正しく使ってれば、基本的な脆弱性対策は完了する」というレベルまで落とし込まないと、 一般の開発には降りてこないし、そこまでいって初めて成熟と言えると思う。という話をさせてもらった。

Security - フレームワークに見る Web セキュリティ対策 - Qiita

YPAC Asia 2015

HTTP2 に関して何が起こっていて、これからどうなるのか、という話をさせてもらった。 ベストトーク 2 位に選ばれた。

HTTP2 時代の Web - web over http2

次世代 Web カンファレンス

Web についてひたすら議論をしたい。そのためだけにやった。 出演者とスタッフの方の協力によって、よい議論の場ができたと思う。 みなさんありがとうございました。

次世代 Web カンファレンスを開催しました #nextwebconf - Block Rockin’ Codes

TPAC & IETF

札幌-横浜で2週間、なかなかハードスケジュールだったけど、 参加できたので良い機会だった。

HTTP2/QUIC meetup

TPAC と IETF の間に、日本に来てる人達を呼んでミートアップをやった。 mnot, EKR, martin etc, と思いがけず、もの凄い充実したミートアップになった。

http2/quic meetup - connpass

Outro

前半は色々仕込んで、後半がイベントづくし。 年末は NY に行ったり、引越したりとちょっと詰め込みすぎた。 良くも、悪くも、色々あったけど、まあまずまずの一年だったと思う。 来年はまた新しいことをやってみようかと思ってる。

今年も色々な方にお世話になり、色々と経験し成長できたと思います。 来年もよろしくお願いいたします。

Jxck

HTTP/2 Push を Service Worker + Cache Aware Server Push で効率化したい話

http2 server push h2o casper dispenser.js

intro

このエントリは、 http2 advent calendar の 1 日目です。

http2study の分かってる人にとっては、「casper の JS 版を作ってる」だけで伝わるかもしれませんが、そうでない場合非常に話すべきことがたくさん有る気がするので、順を追って説明します。

今回理解すべき内容は以下

  • http2 push の問題点
  • cache aware server push
  • bloom filter と golomb coded set
  • cache fingerprinting
  • dispenser.js

(最初は casper.js と言ってたけど、よく考えると被ってるのがあるので dispenser.js に変えました)

そして結論からいうと、まだまだ想定していた挙動まではいけませんでした。。

http2 push の問題点

http2 で push することで、リソースをブラウザにキャッシュしてキャッシュヒットさせる、というユースケースについてはもう散々語られたと思うので、それは前提とします。

問題は、例えば index.html へのリクエストで script.js を push する設定をした場合に、サーバは毎回 script.js を push しては無駄なわけです。 もしすでに push 済みであれば、 push しないで index.html に対するレスポンスを返し、 script.js を速やかにリクエストさせてキャッシュヒットさせたい。

問題はつまりこういうことです。

ブラウザが何をキャッシュとして持っているか、サーバが知る方法が無い

ブラウザのキャッシュを取得できると、閲覧履歴などがわかってしまい問題となる可能性もあるため、基本的にこういうことをする API はありません。

cache aware server push

そこで kazuho さんは、 push 済みのリソースの情報を Cookie に付与しておくことで、次のリクエストで 「index.html が欲しいけど scirpt.js はもうキャッシュに有るから push しないでいいよ」という情報をクライアントから取得するという方法を考えました。

これが Cache Aware Server Push という方式です。

では、実際 cookie には何の情報を入れればいいでしょうか?

例えば、 script.js を Push したら Cookie にも "script.js" って書けばいいかもしれません。 しかし、それだとキャッシュされた script.js よりも、サーバが持っている script.js が新しく更新された場合に、「新しくなったから更新」ということができません。

それは、ファイルのバージョンを示すのに使われる Etag の値を一緒に載せればわかるでしょう。

/assets/scripts/script.js:zidr965q3jalsfda4

でもこれでは、ファイルパスや Etag が長くて、さらにファイルが何個もあったら、すぐに膨らんでしまいます。 Cookie は他にも多くの情報を入れるために使われるので、サブリソースが多くなりがちな昨今ではちょっと辛いです。

そこで、この情報をうまく圧縮する必要があります。

false positive

ファイルパスと Etag があれば十分ではありますが、本当に全部入れる必要はあるでしょうか? そもそも、ブラウザのキャッシュなんていつ消えるかわかりません。 Cookie がそれと完全に同期するのがそもそも無理です。

したがって 100% は無理なので、そこを狙う必要は無く、もし当てが外れても以下の二通りになります。

  • 「キャッシュされてると思って Push しなかったら、されてなかった」=> ブラウザが普通に GET するだけ
  • 「キャッシュされてないと思って Push したら、されてた」 => キャッシュが上書きされるだけ

つまり Push は読みが外れても動かなくなるものではありません。

しかし、かといって毎回 Push しまくってはせっかくのキャッシュで 0 RTT hit させられるのに無駄です。 狙いは、「なるべく無駄な Push を減らす」ことです、すると本質的に必要な情報は以下になります。

「今から Push しようとしているファイルは、すでにキャッシュに 有りそうかどうか? (あるとはいってない)」

100% でなくてもよい(あると思ったら無かった=false positive が許される)、となると実は情報を圧縮する方法がいくつかあります。 その代表例が確率的データ構造である bloom fileter です。

bloom filter

bloom filter については こちら 説明あたりがわかりやすいと思います。

簡単に言えば、その構造体の中に特定のデータが含まれているかどうかを検査を、元のデータセットより小さいサイズで実現できます。

具体的には k 個のハッシュ関数を用意し、要素をそのハッシュにかけます。 そこ結果を、求めるデータサイズ m ビットで丸めると、 0~m の範囲の値が一要素につき k 個得られます。 ゼロクリアした m bit の値に対し、それぞれの値の場所(3 なら 3bit 目)を 1 にします。 全ての要素でこれを繰り返せば完成です。

ある要素がそこに入ってるかを検証するには、同じくハッシュを通してビットが立ってるかを調べます。

この場合、全部のビットが立ってなければ確実に無いことがわかります。 しかし、全部のビットが立っていても、それが他の要素の計算による可能性があるわけです。 これが "False Positive" = 「Positive(ある) と思ったら False(嘘) だった」です。

Bloom Filter は

  • 素数(ファイルの数) = n
  • ハッシュ関数の数(要素ごとに立つビットの数) = k
  • 結果のビット数 = m

とすると

誤検出の確率 = (1 - e*p(-float(k * n) / m)) ** k
m = -n*ln(p) / (ln(2)^2)
k = m/n * ln(2)

の関係がわかっています。 HTTP のペイロードに載せることを考えれば、計算量よりもデータサイズが小さいことが望ましいため、許容できる誤検出を元に、これを最適化することができます。

ただし、計算量を追加することで、より論理的な限界までこれを圧縮するというのが Golomb Coded Set(GCS) です。

Golomb Coded Set(GCS)

Golomb-coded set は、ほぼ ここ に書かれた通りなのでそれを元に紹介。

まずターゲットが以下の値(N=26)だとします。

['alpha', 'bravo', 'charlie', 'delta', 'echo', 'foxtrot',
 'golf', 'hotel', 'india', 'juliet', 'kilo', 'lima', 'mike',
 'november', 'oscar', 'papa', 'quebec', 'romeo', 'sierra',
 'tango', 'uniform', 'victor', 'whiskey', 'xray', 'yankee',
 'zulu']

これを P=64 (誤検出が64回に1回) になるようにします。

ハッシュ関数は、セキュリティ面で言われる危殆化が関係ないため、 MD5SHA1 などで構いません。 求めた値が [0, N*P) = [0, 1664) に収まるように mod で丸め込むと、

[('alpha', 1017), ('bravo', 591), ('charlie', 1207)...]

このハッシュ部分だけをソートして

[151, 192, 208, ..., 1630]

このとき、ハッシュの質が良ければ、結果は [0, 1664) に一様分布するはずです。

そして、それぞれの値の間の距離をとると以下になります。

[151, 41, 16, 61, ...]

26 個の値を 26*64 の間に分布させたので、距離の平均は 64 になるはずです。 つまり、この距離の配列の中には、 多くの 64 近い値 と、少しの 64 と遠い値 があるはずです。 (実際、 64 との差の絶対値をプロットするとわかる)

Golomb Coded Set は、この性質を利用して、配列を圧縮します。

まず、この配列の各値を 64 で割ると、多くの商は 0, 1, 2 あたりになります。(最悪 25 だがそれはハッシュ関数を見直した方が良い)

で、その商を Unary Encoding(商の数だけ 0 の前に 1 をつける) します。 具体的には、こうです。

商   Unary encoding
 0   0
 1   10
 2   110
 3   1110
 4   11110
 5   111110
 6   1111110

これに余り(0~63) をそのまま 6bit バイナリとして加えると、

距離  商  余   Golomb encoding
151    2  23      110 010111
 41    0  41        0 101001
 16    0  16        0 010000
 61    0  61        0 111101
192    3   0     1110 000000
 51    0  51        0 110011
.
.

結果の長さは、

  • 0~63 は 0+6bit で 7bit
  • 64~127 は 10+6bit で 8bit
  • 128~191 は 110+6bit で 9bit

なので、 64 に近い値が多いという前提であれば、これで多くの値が小さくエンコードできることがわかります。

結果を全部つなげると完成です。

11001011 10101001 00100000 11110111 10000000 0110011...

元に戻すには 0 がくるまで 1 を並べ、その後固定長(ここでは 6bit) とって逆算すれば、順番にハッシュが取得できます。

これが基本的なアイデア

cache aware server push と casper cookie

で、 kazuho さんはこれを使って push 済みのファイル(Path+Etag)情報を圧縮し、 Cookie につけてクライアントに送る。クライアントから来る Cookie の情報から Push するかしないかを判断するという方法を、 h2o に実装しました。

その Cookie を casper cookie と言います。

現在 h2o のデモページ ではその Cookie が付与されています。

で、 kazuho さんがこの方法を 10月の #http2study httpbis ガチ勢の前でデモした結果大好評となり、「これは Cookie より別途ヘッダがあった方がいい」「ドラフト書け」みたいな話になって kazuho さんが書いたドラフトが以下です。

Cache fingerprinting for HTTP

cache fingerprinting

Cache Fingerprinting では、以下の二つのヘッダが定義されています。

  • Cache-Fingerprint-Key
  • Cache-FIngerprint

Cache-Fingerprint-Key

この値が、各ファイルごとのハッシュ値になります。 casper cookie の頃は、 Path+Etag の sha1 hash でしたが、 この値を別のロジックで出すことで最適化できる可能性もあるため、 仕様上この値の導出は明記されていません。実装依存です。

値が uint32 (0~232) までとだけ定義されています。

Cache-Fingerprint Header Field

クライアントはキャッシュしたレスポンスの fingerprint key を集め、 Golombset でエンコードした結果を Cache-Fingerprint ヘッダで送ることで、サーバにキャッシュしているファイルを伝えることができます。

リクエストヘッダなので、通常はブラウザが実装することが想定されます。

(注意: このブログを書いてる最中に、フレームが良いということになって、ドラフトは http2 に拡張フレームを定義しています)

dispenser.js

やっと本題です。

ブラウザが実装するまでは、このヘッダは使えないので、 h2o は Cookie にも fingerprint を吐いていますが、 Cookie はブラウザキャッシュとは同期させられません。

そこで、 Service Worker がブラウザキャッシュの代わりに Cache API でキャッシュを管理し Fingerprint を計算、リクエストを Proxy しヘッダに追加して行けば、より正確にキャッシュの管理ができ、無駄な Push を減らせるということで作ったのが dispenser.js です。

動作

基本の流れはこうです。

  • 最初のリクエストでサーバは全てのサブリソースを Push する
  • Service Worker を登録する
  • 次のリクエストは SW で interapt する
  • SW は fetch を発行し、それがブラウザキャッシュヒットする
  • 取得したレスポンスを Cache API で保存し、返す
  • それ以降のリクエストは、 Cache に無いものだけ、キャッシュしたレスポンスのヘッダから fingerprint を計算してヘッダに足す

これにより、 SW で発行した fetch がブラウザキャッシュにヒットしたときに Cache API に移され、ブラウザキャッシュを JS で管理している状態に近づけます。 また、サーバにキャッシュの情報を正確に伝えることで、無駄な Push を減らすことができます。

実装

ここです。(あとで色々整理します。。)

https://github.com/Jxck/dispenser.js

知見

ということで作って検証していたのですが、色々と課題が出てしまいました。。

SW 内の fetch はブラウザキャッシュヒットしない

これ、すると思ってたのですが、現状していません。これでは Push したリソースを fetch でキャッシュヒットさせて SW 内の Cache に引き込むことができません。大前提が。。

今後 Push API が http2 push を受けられるようになったりすればまた少し変わりますが、もしかしたらフロントの fetch でキャッシュヒットさせて SW に送り込むとかしないといけないかもしれません。

それもまだ未検証です。

Chrome Canary だと onfetch でフックした Request を引数に new Request すると怒られる

Stable ではできているのですが、 Canary だと怒られます。つまりそのうち使えなくなる可能性が。 ブラウザからのリクエストを雑に複製するのは簡単なのですが、このスクリプトが casper 対応サーバで無条件にホストして良いレベルの汎用スクリプトにするためには、複製した Request はオリジナルと限りなく近い必要があります。

そもそもなんで動かなくなったのか?(仕様変更か実装の話か) などもう少し調べる必要があります。

https://localhost 開発問題

http2 なので開発も https でやっています。オレオレ証明書https://localhost を許可するわけですが、この場合 invalid cert なので、 SW の register がエラーになります。

現状これを回避する方法は、全ての証明書エラーを無視するという、ちょっとデンジャラスな起動オプションを使う必要があります。 有効にした場合、開発中に同じブラウザでググるみたいなのが総じて危険になるため、本当はより正しいやり方があるのですが、その正しいやり方の方が Chrome のバグで動きません。

デンジャラスな方が広まると良く無いのでここには書きません。

バグは issue を上げてあるので、直ったら追記したり呟いたりします。

Chrome ではリロードとナビゲートでキャッシュの扱いが違う

@kinu さんに教えてもらったのですが

  • リロード(CTL+R) では、ブラウザキャッシュは無視して必ずサーバにリクエスト
  • ナビゲート(CTL+L Enter) は、ブラウザキャッシュがあればキャッシュヒット

なので、この開発中は CTL+R で更新してたので、非常にハマりました。

https://twitter.com/kinu/status/669432544178380806

Push されたことを確実に知る方法

cache hit すると DevTools の NetWork タブで from cache みたいな感じで出ますが、より正確に知るためには chrome://net-internal で http2 のセッションを見るしか無いようです。

例えば index.html が 1.css, 2.css を含み、 CSS は PUSH している場合以下のようになります(抜粋) 1.css, 2.css は PUSH_PROMISE で送られていて、二つに対する SEND_HEADERS が書かれてなければ、キャッシュヒットしています。

t=1386045 [st=    0]    HTTP2_SESSION_SEND_HEADERS
                        --> fin = true
                        --> :authority: 127.0.0.1:3000
                            :method: GET
                            :path: /main.html
                            :scheme: https
                        --> priority = 0
                        --> stream_id = 1
                        --> unidirectional = false
t=1386045 [st=    0]    HTTP2_SESSION_RECV_PUSH_PROMISE
                        --> :authority: 127.0.0.1:3000
                            :method: GET
                            :path: /1.css
                            :scheme: https
                        --> id = 1
                        --> promised_stream_id = 2
t=1386045 [st=    0]    HTTP2_SESSION_RECV_HEADERS
                        --> fin = false
                        --> :status: 200
                            accept-ranges: bytes
                            cache-fingerprint-key: 7351
                            content-length: 23
                            content-type: text/css
                            etag: "5643ea29-17"
                            last-modified: Thu, 12 Nov 2015 01:23:53 GMT
                            server: h2o/1.6.0-beta1
                            x-http2-push: pushed
                        --> stream_id = 2
t=1386045 [st=    0]    HTTP2_SESSION_RECV_PUSH_PROMISE
                        --> :authority: 127.0.0.1:3000
                            :method: GET
                            :path: /2.css
                            :scheme: https
                        --> id = 1
                        --> promised_stream_id = 4
t=1386045 [st=    0]    HTTP2_SESSION_RECV_HEADERS
                        --> fin = false
                        --> :status: 200
                            accept-ranges: bytes
                            cache-fingerprint-key: 4710
                            content-length: 27
                            content-type: text/css
                            etag: "5654b166-1b"
                            last-modified: Tue, 24 Nov 2015 18:50:14 GMT
                            server: h2o/1.6.0-beta1
                            x-http2-push: pushed
                        --> stream_id = 4
t=1386046 [st=    1]    HTTP2_SESSION_RECV_HEADERS
                        --> fin = false
                        --> :status: 200
                            accept-ranges: bytes
                            content-length: 7774
                            content-type: text/html
                            etag: "565e3110-1e5e"
                            last-modified: Tue, 01 Dec 2015 23:45:20 GMT
                            link: </1.css>; rel=preload</2.css>; rel=preload
                            server: h2o/1.6.0-beta1
                            set-cookie: [64 bytes were stripped]
                        --> stream_id = 1
t=1396049 [st=10004]    HTTP2_SESSION_GOAWAY
                        --> active_streams = 1
                        --> last_accepted_stream_id = 1
                        --> status = 0
                        --> unclaimed_streams = 1

これを見やすくするツールが一応あるようです。

https://github.com/rmurphey/chrome-http2-log-parser

Chrome には表示を追加する issue があるようです。

https://code.google.com/p/chromium/issues/detail?id=464501

まとめ

本当は「作りました!」で効果測定の結果などを書きたかったですが、そこまで行けませんでした。

HTTP2 Push も Service Worker もまだまだ研究の余地が一杯あるなということで、地道に頑張ります。

Jxck

Let's Encrypt を支える ACME プロトコル

tls let's encrypt acme

Intro

先日 #http2studymozilla の Richard Barnes が Let's Encrypt について話してくれました。

資料: Let's Encrypt Overview

この資料の翻訳 はしたのですが、いらなくなってしまったので供養もかねてこのプロジェクトのモチベーションと、 Web でおこっている HTTPS 推進のたどる道について、資料を補足しつつ紹介します。

結論から言うと Let's Encrypt はもちろん ACME プロトコル についても是非知っておくと良いと思います。

HTTPS の問題

すでにこのブログでも紹介しているように、 Web における HTTPS の重要性は増し、それの普及を後押しする活動が各所で進められています。

HTTPS 化する Web をどう考えるか

よく言われる盗聴防止を始め、暗号化を行うことで防げる問題は多くあります。ブラウザの API には HTTPS で無いと使えないものも出てき始めています。 それらを担保するために、 HTTPS 化が有効なわけですが、現時点での進捗は以下だそうです。

究極には 全てのトラフィックHTTPS になる状況が望ましいとすると、進捗はまだまだと言えます。

HTTPS 普及上の問題

実際には多くの問題がありますが、一番分かりやすいのは「証明書」の問題でしょう。

  • 証明書は有料
  • 発行機関ごとに申請方法が違う
  • 発行プロセスが基本手動
  • 追加でサーバの設定
  • etc

料金の問題は、特に個人のホビー用途での側面が強いでしょう。 しかし、ビジネスの場面でも、申請フローが自動化できない(しにくい)ことによって、今日のデプロイプロセスに混ぜにくいという問題があります。

つまり、 無料 かつ 自動 で発行できると、かなり状況は改善できる可能性があるというのが、 Let's Encrypt のモチベーションになります。

Let's Encrypt の発行する証明書

CA が発行する証明書にはいくつかの種類があります。

  • DV(Domain Validation): ドメインの所有を確認して発行
  • OV(Organization Validation): 組織の実在の確認をして発行
  • EV(Extended Validation): より厳密な実在確認をして発行

OV, EV は申請が複雑ですが、 DV は「申請者がそのドメインを持っているかどうか」を確認するだけなので、信頼性は劣りますが発行が短期間で済みます。

Let's Encrypt が発行できるのは、この DV 証明書だけです。

また、単体の証明書は例えば mail.example.comwww.example.com は別のものが必用ですが、 *.example.com 全体を一つでカバーできるワイルドカード証明書というものがあります。 しかし、 Let's Encrypt はワイルドカード証明書は発行できません。無料であるため、サブドメイン毎にガンガン発行することになるようです。

Let's Encrypt のクロスルート証明書

Let's Encrypt は CA であるため、クライアントから信頼されていなければなりません。 これは通常、 Let's Encrypt 自体の CA 証明書が OS やブラウザなどにビルトインされている必用があります。(無い場合は、 HTTPS が成立しない)

現在 Let's Encrypt 自体の CA 証明書はまだ OS などには入っていません。 しかし、 IdenTrust という多くの環境で信用されている別の CA とチェーンを結ぶようになりました。 これにより Let's Encrypt の証明書は「クロスルート証明書」となり、 IdenTrust を信用する環境で信用されるようになりました。

要するに、大抵の環境で Let's Encrypt の証明書はすぐに使えるようになるわけです。

不安な場合は、対象とするクライアントで以下の URL を開けば、きちんど動作するか確認できます。

https://helloworld.letsencrypt.org/

DV 証明書発行の自動化

DV 証明書に発行に必用なのは以下の確認です。

example.com の証明書が欲しいと要求してきた人が 本当に example.com の所有者かの確認

この方法はいくつか考えられますが、基本的には「そのドメインを持っている人にしかできない操作をさせて、それを確認する」という発想になります。

Let's Encrypt が求めるのは以下のような操作です。

  • example.com のサーバで TLS を有効にする
  • DNS_acme-challenge.example.com に対して Let's Encrypt が指定した値を返す TXT レコードを設定する
  • HTTP で http://example.com/.well-known/acme-challenge/ に対して Let's Encrypt が指定したテキストを返す設定をする

ドメイン所有者はこれを行い、 Let's Encrypt が設定の正しさを外から確認することで、ドメインの所有者を確認し、証明書を発行します。 Let's Encrypt への依頼は API 経由でできるため、そこで受け取ったトークンを用いて、これらのプロセスさえ自動化できれば、完全自動で証明書が発行できるわけです。

ACME プロトコル

実は、前述のような証明書発行のプロトコルは標準化されています。

それが ACME プロトコル です。

仕様はまだ策定中ではありますが、 Let's Encrypt はこの ACME を(仕様策定にフィードバックしながら)実装しています。

ACME プロトコルは前述したクライアント(発行依頼側)だけではなく、サーバ(発行側)についてもカバーしています。 このプロトコル自体が、今後の HTTPS の普及に重要なものだと考えています。

ACME 対応サーバ

Let's Encrypt は、証明書の発行を自動化する Python 製の CLI ツールを公開しています。

https://github.com/letsencrypt/letsencrypt

これはつまり、 ACME クライアントツールということになります。 これを用いて CLI ベースで証明書の発行を行うことができます。

しかし、 ACME および Let's Encrypt の目指す自動化はもう少し先にあります。

例えば発行した証明書は、最終的には Nginx や Apache などの設定ファイルに記述して有効化する必用があります。 そこで、「Nginx や Apache などのサーバ自体が ACME プロトコルを話し、勝手に証明書を取得して、勝手に設定する」というところまやると、証明書の知識が少ない初心者にも、 HTTPS を有効化する敷居を下げることができるというモチベーションです。

すでに Nginx と Apache の Plugin があるようです。

個人的には、設定ファイルが勝手に書き変わることには多少懐疑的ですが、プロトコル自体があるなら、サーバが直接話さないにしてもデプロイプロセスに取り込むことはできると思います。

今後 ACME 対応のエコシステムが揃えば、より選択肢が増え、知見が溜まって行くと思います。

ACME 対応 CA

ACME は Let's Encrypt だけのものではありません、 Let's Encrypt 以外の CA も ACME に対応することで、自動化の恩恵を受けることができます。

言い換えれば Let's Encrypt 自体も ACME 対応サービスの一つです。そしてこれも OSS ベースで公開されています。

https://github.com/letsencrypt/boulder/

今後より重要度が増して行く HTTPS において、こうした標準的な発行手段が(例え DV のみでも)普及することは、デプロイのオーバーヘッドを減らして行く意味でも価値があるのではないでしょうか?

まとめ

  • ACME という、証明書発行プロトコルが現在策定中
  • Let's Encrypt は ACME のサービス実装の一つ
  • ACME を話せるクライアントがあれば、自動化が可能

Let's Encrypt は 無料 だという部分がフィーチャーされてて、それはもちろん凄いんだけど、裏ではこんな動きもありますよという話でした。

ちなみにこのステッカーが、そのうち沢山貰える予定なので、欲しい人は声かけてください。

f:id:Jxck:20151107161258j:plain

次世代 Web カンファレンスを開催しました #nextwebconf

nextwebconf web

intro

次世代 Web カンファレンスを開催しました。

next web conf logo

実施概要

概ね開催概要の通りです。

jxck.hatenablog.com

やったこと

やったことはシンプルです。

テーマ毎に、今 Web がどうなっていてこれからどうなっていくのか をひたすら議論するセッションのみのカンファレンス

やらなかったこと

以下はこのカンファレンスではやりませんでした。

  • スポンサー募集
  • Tシャツ/ステッカー/チラシ作成
  • 公式サイト作成/ドメイン取得
  • 公式懇親会
  • LT大会/ドラ
  • 基調講演
  • メディア連携/対応
  • 何かの宣伝
  • お金を扱うこと全て

セッション

  • テーマ毎に 60 or 80 分のセッションを行う
  • 3 トラック並行で実施
  • セッションオーナー(まとめ役) + 2~3 人の登壇者で実施
  • スライドやデモ・台本などは用意しない
  • プロジェクタは固定スライドを表示
  • 資料が無いので、資料公開はない。代わりにセッション自体の配信、録画を公開。
  • 登壇者の発言は、所属する組織とは関係なく、個人の発言である」を全体共通とする。

登壇者にお願いした事

全ての登壇者に以下をお願いしました。

  • 何かを宣伝する目的で出ないでください
  • 登壇者の発言は、所属する組織・団体とは関係なく、個人の発言である」を前提としてください
  • (初心者など)聞き手のレベルを意識せず、話したいレベルで話してください
  • 録画を公開させてください(声だけも可)
  • 資料やデモなどの準備はいりません
  • 細かく打ち合わせしすぎると、当日話す事がなくなり失敗するので、打ち合わせしすぎないでください
  • ひたすら日頃思っている事を議論してください
  • 登壇者にスタッフも兼ねてもらいます
  • 出演費・移動費など、お金は一切出ません
  • 実施形態に納得できない場合は出演を断ってください

録画

405(#nextwebconf405)


次世代Webカンファレンス 405 #nextwebconf - YouTube

406(#nextwebconf406)


ライブ配信|次世代Webカンファレンス 406 #nextwebconf - YouTube

407(#nextwebconf407)


次世代Webカンファレンス 407 #nextwebconf - YouTube

outro

登壇者・スタッフのみなさん、最後までおつきあい頂き本当にありがとうございました!


議論というものにフォーカスを絞ってやってみました、決して簡単とは言わないが、こういうのもありなんじゃないかと思う。

次回とかは考えてない。またあるかもしれないし、二度とないかもしれない。

Jxck

ORTC が切り開く SVC サイマルキャストと WebRTC NV

intro

「ORTC って WebRTC がちょっと便利になるくらいなんでしょ?」くらいに思っている人が結構いるようだったので、現時点で予想される ORTC のもつ可能性 と、現状の WebRTC の問題点、そして WebRTC がこれからどうなっていきそうかについて、自分の理解している範囲で書いてみます。

ORTC については、ほとんど実装が無く(と書いてる間に Edge に入っちゃったんですが)まだドラフトやそこにある Example、 ML での議論などの公開情報を元に書いてるだけなので、間違っているものや、将来変わるところも有ると思います。よって内容は一切保証しません。 また、何か自分の理解がおかしいところなど有った場合は、コメントなどで指摘頂けると幸いです。

低レベル API 化へ

WebRTC は少なからず「ブラウザで P2P テレビ会議」をするというユースケースを中心として策定されました。 HTML5 の流れを組む API 群は、最初に「ユースケース」を大事にしていたのと同様に、WebRTC 1.0 もちょっとまじめに触ると「ユースケースを外れた途端の使いにくさ」が少なからずありました。

例えば、シグナリングで使用する情報が SDP 文字列であるために、変更したい場合は文字列処理が必要であったり、通信相手ごとに映像のクオリティを分けることができないなどの問題が指摘されています。 また、 WebRTC スタックは複数プロトコルの合わせ技でできているにも関わらず、高レベルな API でラップされているため、それら個々のプロトコルレベルで細かい制御ができないという問題も有ります。

最近では、こうした API は「低レベル API セット」の上で再構築という流れになるのは、このブログでも何度か言及した通りです。

それが MS 主導で提案された ORTC でした。今までの WebRTC API に輪をかけて色々と濃い感じになってます。

しかし ORTC は CG(community group) のものであり、 W3C が管理する API ではありません。したがって、これがこのまま W3C で勧告されることは基本的にはあり得ません。 W3C では、この ORTC の知見を WebRTC にどう取り込んで行くのか、そして WebRTC 1.0 の次のバージョンである、 WebRTC NV(next version) の方向性について議論が進んでいます。

今回は、特に話題となっている以下の2つを中心に、これから WebRTC に何が起こって行くのかを見てみたいと思います。

  • MultiStream
  • SVC Simulcast

MultiStream

相手と複数のストリーム(MediaStream)、例えば二つのカメラの映像をやり取りしたい場合、単純に二本の PeerConnection を張るという方法があります。 しかし、一本の PeerConnection の上に二本のストリームを多重化できればリソースを節約できます。

f:id:Jxck:20150923010536p:plain

実際に WebRTC 1.0 の API は、この MultiStream に対応した形で定義されています。 具体的には addStream()onnegotiationneeded イベントです。

addStream()

その名の通り、 PeerConnection に対してストリームを追加するメソッドです。 しかし、ただこのメソッドを呼んで終わりとはいきません。

シグナリングを実施して、 Peer に対してストリームの追加を通知する必要があります。 これは、 onnegotiationneeded の発火によって補足することができるため、そのコールバックで再度 SDP を取得し直してシグナリングしなおします。

peerConnection.onnegotiationneeded = () => {
  // ここでシグナリング
};

// 既存コネクションにストリームを追加
peerConnection.addStream(stream);

すると相手側で onaddstream が発火し、そこで追加のストリームを取得できるわけです。

peerConnection.onaddstream = (stream) => {
  // video タグに表示など
}

このフローを使うと、ストリームが追加されてない状態から順次ストリームを追加して行くこともできます。

Web にあるサンプルコードでは、あらかじめ addStream() を終えてから最初のシグナリングを行うことで onnegotiationneeded は無視されている場合もありますが、本来はこのイベントが「シグナリングを実行すべきタイミング」です。 ストリームの追加を途中で扱うためにはこのフローを行うことになります。

そして、そこで必ずハマるのは ChromeFirefox 間で、このフローがうまくいかないことがあるということです。

SDP plan B と unified plan

onnegtiationneeded のタイミングで createOffer() し直して取得する SDP には、複数ストリームの存在を示すラインが追加されます(m-line)。

しかし、この SDP の記述方式には現在 Chrome が採用している "plang B" というフォーマットと、 Firefox が採用している "Unified Plan" というフォーマットの二種類があります。

残念なことに、この二つのフォーマットには互換性が無いため、 multistream を Ch <-> FF 間で行おうとすると失敗する場合があります。

回避方法として、出力結果である文字列の SDP を書き換える方法があります。これを行うライブラリもすでに提供されています。

https://github.com/jitsi/sdp-interop

しかし、本質的な解決は plan の統一です。これは今後 Unified Plan での統一が決まっているため、基本的には Chrome の実装待ちとなるでしょう。

Track レベルの多重化

さて、 multi stream はストリーム(MediaStream)レベルの多重化な訳ですが、より細かく制御したい場合は、これだと粒度が大きすぎる場合があります。具体的には、ストリームは複数のトラック(MediaStreamTrack)からできているため、そのトラックレベルで制御をしたい場合です。

例えば getUserMedia(){ audio: true, video: true } を指定するおなじみのアレで取得されるストリームは Audio トラックと Video トラックが両方入ったストリームです。そしてストリームには addTrack() でより多くのトラックを追加できます。

PeerConnection は、このトラックレベルでのネットワーク上の扱いをそこまで細かく指定することができませんでした。

この問題は後述する、 ORTC で RTPSender/Receiver が追加されることで解決します。

SVC サイマルキャスト

多拠点で会議をして受信側が複数人いた場合、それぞれのネットワーク状況や受信している端末は同じとは限りません。

例えば送信者が送った動画が高画質・高フレームレートだったとしても、受信者が弱い Wi-Fi 上の画面の小さいモバイル端末だった場合は、あまり嬉しくありません。むしろ解像度とフレームレートを下げたものを送ってくれた方が快適な場合があります。

本来であれば、受信者の持つ表示能力やおかれている帯域状況に応じて、適切なクオリティの動画を配信したい。つまり、一つの動画を複数のクオリティで配信する。これがサイマルキャスト(Simulcast)です。

Wikipedia でサイマルキャスト(サイマル放送)を調べると全然違う意味で載っているように、一言でサイマルキャスと言ってもコンテキストによって意味が変わります。ここで言っているのは、テレビ会議などで使われるサイマルキャストです。

では、どのように自分に合ったクオリティの動画を要求するのでしょうか?

従来の AVC(Advanced Video Coding) であれば、一旦サーバで配信者の動画を受け取り、それを個々の受信者に合わせたパラメータに変えて、再エンコードをするという方法があります。

f:id:Jxck:20150923010628p:plain

しかし、これは再エンコードにかなりのリソースが必要な上、受信者によって必要なパラメータの組み合わせも非常に多くなってしまいます。遅延の問題も無視できません。

そこで注目されるのが SVC(Scalable Video Coding) という仕様です。

SVC(Scalable Video Coding)

SVC の基本的なアイデアは、動画を複数のレイヤに分けてエンコードすることです。

まず、元となる映像をベースとなる低解像度・低フレームレート・低ビットレートなパラメータでエンコードします。これを基本レイヤーと呼び、全員に配ります。

加えて、基本レイヤとの差分となる拡張レイヤをエンコードします。これはいわゆる diff のようなものだと考えるとわかりやすいでしょう。

サーバは、受け取った SVC の映像のレイヤを把握し、クライアントに配信する際に対象の表示能力や帯域状況に応じて、必要なレイヤだけを流してやります。

例えば受信者が低帯域にある画面の小さいモバイルだった場合は、基本レイヤ(解像度/フレームレート/ビットレート)のみを受けとります。

一方で、受信者が十分な帯域のある大画面のテレビ会議システムだった場合、基本レイヤに加えて二つの拡張レイヤを受けとり、デコード時にマージすることで高クオリティ(解像度/フレームレート/ビットレート)の映像が手に入るわけです。

もちろん、その中間のスペックの受信者は、基本レイヤに加えて一つ目の拡張レイヤだけを加えることで、中クオリティの映像を手に入れることができます。

f:id:Jxck:20150923010647p:plain

基本レイヤは、最低限会議は成り立つというレベルのものであり、クオリティが低い変わりにデータも小さくなっています。代わりにエラー訂正などについては他のレイヤよりも重視します。

拡張レイヤが壊れたり落ちたりしても基本レイヤがあれば最低限の映像は見えるため、そうした場合は基本レイヤにフォールバックしてリアルタイム性を確保します。

これは見方を変えると、単一レイヤに全てまとまっていた AVC ではロスによって画面がこわれていたものが、 SVC ではデータの少ない基本レイヤのリカバリにだけ気を使って入れば、ネットワークが不安定になっても、低クオリティへのフォールバックによって会議を続けることができるなどのメリットもあります。

また、映像を犠牲にしてオーディオに優先度を振ることで、会議を快適にすることができます。

なによりサーバ側で再エンコードが必要だった AVC と違い、エンコードを配信元クライアントが一回だけ行えばよく、サーバのリソースも節約できるため、効率のよいテレビ会議を構築するためには非常に有望な技術なのです。

SVCエンコードパラメータ

SVCエンコード時に注目するパラメータは大きく三つあります。

  • フレームレート(Temporal)
  • 解像度(Spatial)
  • 画質(Quarity)

フレームレート(Temporal)

フレームレートは一秒間に表示する画の数です。拡張レイヤを加えるとフレームが増え、動きが滑らかになります。

f:id:Jxck:20150923010659p:plain

解像度(Spatial)

解像度は単位面積あたりの画素数です。拡張レイヤを加えると大きな画面でもはっきり映ります。

f:id:Jxck:20150923010712p:plain

画質(Quality)

SNR と言われる場合もあるようです。いわゆる画の鮮明さです。

f:id:Jxck:20150923010725p:plain

ORTC の Low Level API セット

ORTC というと必ずと言っていいほど出てくる図があります。

ORTC

この図だけ見ても分かりにくいかもしれませんが、ざっくり言うと各ブロックがオブジェクトで、横の矢印が依存関係、縦がイベントとなっています。ここに出てないオブジェクトもまだあります。

ここまでの話を踏まえつつ少し細かく見てみます。

基本

これまでの WebRTC は RTCPeerConnection というオブジェクトが諸々よしなにやってくれるのという感じでした。ORTC では、その時ブラウザが内部で行っていた個々の操作をオブジェクトにしているイメージです。

たとえば DataChannel が欲しければ、これまでは peerconnection.createDataChannel() だったのですが、ORTC では こうなります。

let iceGatherer = new RTCIceGatherer(iceGatherOptions);
let iceTransport = new RTCIceTransport(iceGatherer);
let dtlsTransport = new RTCDtlsTransport(iceTransport);
let sctpTransport = new RTCSctpTransport(dtlsTransport);

let dataChannel = new RTCDataChannel(sctpTransport);

コードが増えてるだけに思えるかもしれませんが、実は WebRTC のスタックを理解できていると、レイヤリングされているプロトコルがオブジェクトとして抽象化されているだけだと言うことが良くわかるかと思います。

次に Video のトラックを一つだけ交換してみます。 DTLS までは作ったとして、そこから Sender/Receiver の生成は以下のような感じになります。

// DTLS Transport と MediaStreamTrack から Sender を生成
let rtpSender = new RTCRtpSender(mediaStreamTrack, dtlsTransport);

// DTLS Transport から Receiver を生成
let rtpReceiver = new RTCRtpReceiver(dtlsTransport);

// Capabilities を取得
let sendCapas = RTCRtpSender.getCapabilities('video');
let recvCapas = RTCRtpReceiver.getCapabilities('video');

// シグナリングで受信
signaller.on('capability', (remote) => {
  // Capability を変換
  let sendParameters = cap2param(sendCaps, remote.sendCapas);
  let recvParameters = cap2param(recvCaps, remote.recvCapas);

  // パラメータの設定
  rtpSender.send(sendParameters);
  rtpReceiver.receive(recvParameters);

  // これで sender/receiver がメディアを扱える
});

// シグナリングで送る
signaller.send("capability", {
  sendCapas,
  recvCapas,
});

この RTPSender/Receiver の存在も、初期の WebRTC では意識されていませんでした。 この API が今後どうなるかは後述するとして、レイヤが低いという意味はなんとなく感じて頂けたかと思います。

ここでは取得した capability を送信していますが、ここには WebRTC 1.0 で文字列化されていた SDP の情報の一部が含まれています。

dictionary RTCRtpCapabilities {
 sequence<RTCRtpCodecCapability> codecs;
 sequence<RTCRtpHeaderExtension> headerExtensions;
 sequence<DOMString>             fecMechanisms;
};

ここに track から取得した情報などを付加すると、 SDP 文字列を生成することができます。 SDP という文字列として表現されたものを、本来保有してるものをオブジェクトとして取得し、そこから情報を取得する低レベルな API が定義されたため、こうしたことが可能になった訳です。

実際にこれらのコードから SDP を生成する例が adapter.js のブランチに入ってたので、参考にしてみてください。

https://github.com/fippo/adapter/blob/41952910b199816de5a7323f866809560aa5088d/adapter.js#L1283

もちろん、面倒であればこれをラップしたライブラリを作れば良いでしょうし、それは従来の PeerConnection と同等になるでしょう。

MultiTrack(MultiStream) 対応

ORTC では、 track 単位で RTPSender/Receiver を作り、トランスポートに紐づけることができます。 そして、その RTPSender/Receiver 単位で capability を取得してシグナリングを行います。 トランスポートに複数の track を紐づけることが可能なため、その track を適宜 stream にまとめれば multistream 相当になります。

要するに先の例で、 track に合わせて Sender/Receive を増やしていけば良いという意味です。

// track を DTLS transport に紐づけて Sender/Receiver を作成
let audioSender = new RTCRtpSender(audioTrack, dtlsTransport);
let videoSender = new RTCRtpSender(videoTrack, dtlsTransport);
let audioReceiver = new RTCRtpReceiver(transport);
let videoReceiver = new RTCRtpReceiver(transport);

// capability を取得
let recvAudioCaps = RTCRtpReceiver.getCapabilities('audio');
let recvVideoCaps = RTCRtpReceiver.getCapabilities('video');
let sendAudioCaps = RTCRtpSender.getCapabilities('audio');
let sendVideoCaps = RTCRtpSender.getCapabilities('video');

// いわゆる createOffer でやっていたこと
signaller.send('capability', {
  recvAudioCaps,
  recvVideoCaps,
  sendAudioCaps,
  sendVideoCaps,
});

SVC Simulcast

ORTC では、ブラウザに SVC 対応のコーデックを載せ、そのレイヤパラメータを JS から細かく指定できるようにする方向で API の議論が進んでいます。

具体的には以下のような形で指定します。

// 2-layer spatial simulcast combined with 2-layer temporal scalability
// Solid arrows represent temporal prediction.
// 矢印がテンポラルな予測を表す
//
// I0:  base-layer I-frame
// P0:  base-layer P-frames
// EI0: enhanced resolution base-layer I-frame
// EP0: P-frames within the enhanced resolution base layer.
// P1:  first temporal enhancement layer,
// EP1: temporal enhancement to the enhanced resolution simulcast base-layer.
//
//          +----+                +----+
//          |EP1 |                |EP1 |
//          |    |                |    |
//          ++---+                ++---+
//           ^ +----+              ^ +----+
//           | |P1  |              | |P1  |
//           | |    |              | |    |
//           | ++---+              | ++---+
// +----+    |  ^        +----+    |  ^        +----+
// |EI0 +----+  |        |EP0 +----+  |        |EP0 |
// |    +--------------->+    +--------------->+    |
// +----+       |        +----+       |        +----+
//              |                     |
// +----+       |        +----+       |        +----+
// |I0  +-------+        |P0  +-------+        |P0  |
// |    +--------------->+    +--------------->+    |
// +----+                +----+                +----+
//
var encodings = [
  {
    // 低解像度ベースレイヤ(1/2 フレームレート 1/2 解像度)
    encodingId: "0",
    resolutionScale: 2.0,
    framerateScale: 2.0
  },
  {
    // 拡張解像度ベースレイヤ(1/2 フレームレート 1/1 解像度)
    encodingId: "E0",
    resolutionScale: 1.0,
    framerateScale: 2.0
  },
  {
    // 低解像度ベースへの拡張レイヤ (1/1 レート, 1/2 解像度)
    encodingId: "1",
    dependencyEncodingIds: ["0"],
    resolutionScale: 2.0,
    framerateScale: 1.0
  },
  {
    // 拡張解像度ベースへの拡張レイヤ (1/1 レート, 1/1 解像度)
    encodingId: "E1",
    dependencyEncodingIds: ["E0"],
    resolutionScale: 1.0,
    framerateScale: 1.0
  }
];

ざっくり言えば、個々のレイヤのパラメータと、そのレイヤの依存関係の指定になっています。 一般の開発者にはなかなか敷居が高いかもしれません、逆にコーデックやネットワークの状態の把握にノウハウがあると、その知見をここのパラメータに反映することができます。

ブラウザの場合は、コーデックがブラウザに載っているものだけに限定されているため、弄れる余地が少なかったわけですが、ORTC ではそうしたレベルにも干渉できるくらい低レベルな API が来る可能性があります。

ORTC の今と WebRTC の今後

ORTC と Edge

ORTC のドキュメントは正直言って Example がちょっと分かりにくすぎる(というか JS レベル、プログラミングレベルで間違ってる)ので PR しまくってる訳ですが、エディタがよくわからないフローで更新しているようで何とも言えません。。 (しかし、各 API や挙動の定義は割とキチンと書けているので、単にエディタがプログラミング苦手なだけだかなと思います。)

しかし、そんなドラフトでも実装は進んでおり、ついに先日 MS Edge に API の一部が実装されたと発表されました。 moder.ie のバーチャルマシンにはまだ更新されてないので、 Win10 を持って無い筆者はまだ試せていませんが、もし持っていたら是非試してみてください。

http://blogs.windows.com/msedgedev/2015/09/18/ortc-api-is-now-available-in-microsoft-edge/

ちなみに H.264/SVC についても、 H.264/UC として AVC/SVC 両方を包括した仕様として実装するそうなので、 ORTC レベルの APISVC を使わなければ AVC として使えるようになるのではないかと見ています。

WebRTC 1.0 の RC に向けて

今年は TPAC と IETF がどちらも日本で連続して開催されます。 TPAC は年に一度しかなく、そこで重要な問題にのみ時間を裂き、その結果を IETF にも持っていけるようにするため、 事前ミーティングとして WebRTC についての F2F(face to face meeting) が先日シアトルで開催されました。

minutes は以下です。

https://lists.w3.org/Archives/Public/public-webrtc/2015Sep/0075.html

また、そのすぐ後に kranky geek というカンファレンスで WebRTC がテーマになり、主要なエンジニアが発表をしています。 ORTC や Simulcast についての発表もありましたが、今回のエントリに関わる発表としては Google チームの発表が参考になります。

http://www.slideshare.net/webrtclive/kranky-geek-google-team

この辺の話を総合すると、今後の流れとして抑えておくべき点として以下が上げられると思います。

  • WebRTC 1.0 を 2015 年末に RC(勧告候補) として公開したい。
  • その後 ORTC の成果を汲んで WebRTC NV (next version) として次の仕様に取り組みたい。
  • ただし サイマルキャスト などについては WebRTC 1.0 にも入れたい。

WebRTC 1.0 を本当に年内に RC まで持って行くためには、かなり急いで準備(特にブラウザの実装)をすすめ、 TPAC/IETF である程度実現してから、残りの策定作業をする必要があります。 そんなスケジュール感でも、サイマルキャスト周りを 1.0 に入れてしまいたいというくらい、これらの API への要望が強く対応が急務になっていると見ることができそうです。

まとめ

ORTC はかなり複雑な API に見えますが、そもそも WebRTC でやろうとしていることが複雑なので、本気でやるとしたらこのくらいフックポイントがあっても良いだろうと思います。 全ての開発者がまんべんなく使いこなす必要は無いため、他の低レベル API (WebComponents 系、 ServiceWorker 系 etc) と同様、フレームワークなどが成熟することで、開発者が必要に応じて選ぶかたちになっていくでしょう。

そこでさらにサイマルキャストのような、さらに複雑なものが入ってくるのは、今 WebRTC に求められている重要な機能だということだと感じるし、じっさい標準化の場面でも非常に話題になっています。

前述の通り TPAC/IETF を経て、 WebRTC 1.0 が RC に向かうとすれば、今年の年末は WebRTC に取って一つの重要な転換期になるでしょう。 Edge に続いて、 Chrome/Firefox などの実装も進むことが予想されます。 そして、新たに策定が始まるかもしれない WebRTC NV は、当初 WebRTC 2.0 と呼ばれていたものに繋がって行くのではないかと思います。 すると、 ORTC 並みの低レベル API が揃い、それらを適切に使いこなせれば WebRTC を使ったサービスの品質向上につながるでしょう。

そして個人的には「想定と全く違う使い方」例えば、 ORTC で降りて来た低レベル API の一部を使い、これまで前提となっていた「テレビ会議」というユースケースに縛られない、全く予想外な使い方による何かが出てくると、面白いのではないかと思います。

低レベルで非常に複雑だけどスタックが分かっていると割と自然で、さらにもっと広い範囲でサイマルキャストもカバーし、ユースケースと外れた使い方もでき可能性があるかもしれない、そういう可能性が ORTC にはあるなぁという話でした。

総合格闘技を戦い抜くために

片手間じゃない WebRTC をちゃんとやろうとすると

  • RTP でのリアルタイムネットワークプロトコル
  • DTLS での暗号通信
  • ICE での Hole Punching
  • H.264-5/VP8-9 周りのコーデック
  • SVC でのサイマルキャスト
  • イベント/Promise を扱う片手間じゃない JS
  • IETF/TPAC 両方の標準化追従
  • クロスブラウザAPI の補完
  • TURN/STUN/MCU/SFU などのインフラ構築力

くらいの知識が平気で必要になります。

この総合格闘技を一人で戦い抜くのもいいけれど、正直それができる人を俺は知りません。

自分は Web はエコシステムで作るものだと思うので、全部一人で抱えるよりは、得意な人が得意な分野を開拓して、補いながら作り上げていく方が全体としては成長するんじゃないかと思います。 そのサイクルが回らないと WebRTC 自体が、己の自重で沈んでしまうでしょう。

こんなエントリでも、そのサイクルを回す一助となればと思います。

参考

2015 夏 (#seccamp -> #summersonic -> #yapcasia)

seccamp summersonic yapcasia

Intro

色々あって正直疲れたけど、濃く熱い夏になった。

セキュキャン

セキュリティの専門家ではないけど、開発者からの視点で話して欲しいという事で講義の一部を担当させていただいた。

資料はこちら。 主旨としては、 Web における脆弱性の知見が集積される場所として、フレームワークがあるということに着目し、その代表例である Rails を例に、具体的にどんな対応がされているかを解説したもの。

f:id:Jxck:20150831203718p:plain フレームワークに見る Web セキュリティ対策

なんだけど、この資料は一切使わず、アドリブで全然別の話をした。(全然でも無いか)

自分の発表は 4 日目だったんだけど、1 日目から参加させてもらって、受講者や他の講師と話をしているうちに、「あー俺がここで彼らに話すべき事ってもっと別にあるなぁ」と気づいたので、そこにいた若くて超優秀な受講者の人達に 本当に話したいこと を話させてもらった。

この資料は、まあ書いてある以上でも以下でも無いので。

IPA という機関が関わってることも有り、コミュニティベースのイベントとは違う雰囲気だったけど、お盆ど真ん中でこれだけの若い芽を育てる努力には頭が下がります。講師、参加者、運営のみなさんお疲れさまでした。

Summer Sonic 2015

今回はほぼ Chemical Bros を見に行ったようなものだった。 Don't Think の収録があった Fuji Rock 2011 に行かなかったことを心から悔いていたので、今回は外せなかった。

途中 Sonic Stage でちょっと休んだけど、基本的には Marine Stage にいた。

Echo Smith -> Cody Simpson -> MADEON -> Ariana Grande -> The Chemical Brothers

資料はこちら。

# chemial brothers set list

1.Hey Boy Hey Girl
2.EML Ritual
3.Do It Again
4.Go
5.Swoon
6.Star Guitar
7.Sometimes I Feel So Deserted
8.Chemical Beats
9.Acid Children
10.Setting Sun / Out of Control
11.It Doesn’t Matter
12.Saturate
13.Elektrobank
14.I’ll See You There
15.Believe
16.The Sunshine Underground
17.Escape Velocity
18.Don’t Think
19.Under the Influence
20.Galvanize
21.Music: Response
22.Block Rockin Beats

http://dailysetlist.net/archives/6463

おわかり頂けただろうか?ちなみに最後の曲は、このブログのタイトルの元ネタである。

本当に大盤振る舞いだった。ちょっとツナギが荒かったけど、とにかく楽しめた。 次の日は腕が上がらなかった。暑かったけど、雨が降らなかったのが非常に良かった。

MADEON もやっぱり良かった。という意味では二日目の ZEDD も見たかったけど、一日目でかなり満足して、二日目は 全体としてそこまで惹かれなかったうえに、帰りが混む時間は本当に大変なので昼頃まで寝てからそのまま帰った。

Ed も早く帰って来て欲しいなぁ。

YAPC::Asia 2015

「HTTP2 時代の Web」というタイトルで発表されていただいた。 YAPC は去年初めて参加して、二回目にして登壇となったけど、最後に思い切ってプロポーサル出しておいて良かった。

資料はこちら。

映像も公開された。


HTTP2 時代の Web / Jxck - YouTube

世間では「HTTP2 なんて Google しか使わない」とか「HTTP2 使えば速くなる」とか、 HTTP2 のほんの一面だけを取り出して、大きな述語というか、シンプルな解釈に押し込もうとする人が結構いるように感じている。

そこまで単純じゃないという話と、 HTTP2 の仕様自体の絶対評価だけで話すより、もう少し広く考えた上で 「自分は HTTP2 を本当に使うべきなのか?」を考える上で参考になりそうな話を選んで組んだ。

RFC も出た事だし、「HTTP2 は何か」という部分をひたすら話しても良かったんだけど、 話飽きたところもあるし、そのフェーズもそろそろ終わったかなと思ったので。

ベストトークで 2 位に選ばれ、商品として Apple Watch を頂きました!!

残念ながら自分は時計を(発表とか TOEIC 以外)基本しないので、開封はここまで。あとでおいしく頂きます。

マキさん、そして YAPC の運営に携わった多くのみなさん、本当にお疲れさまでした。

まとめ

セキュキャンは普通なら年齢的に絶対参加できないところ参加できたし、サマソニは悔いの無い参加ができたし、YAPC は終わってしまう前に登壇の機会を得て賞ももらえたし。

色々充実した夏になりました。本当にありがとうございました。

Jxck