Verethragnaのブラウザ接続について。
Verethragnaのブラウザ接続を開発中なんですがなんとなく見えてきたのでこの辺で記事をば。
大長編です。
まず、従来のVerethragnaはWindows版のクライアントのみでした。Brynhildrの時はiOS版のKeroRemoteとかQtBrynhildrとかありましたのでクライアントはマルチプラットフォームと言えた感じです。
Verethragnaもかなり前からマルチプラットフォームのクライアントの計画はありまして、ブラウザ版を作ることで対応は可能だと考えブラウザ版の計画は始まったわけです。
が、しかし。
Brynhildrの時はパブリックモードという形で通常の接続方式ではなく暗号化も簡易的な接続方式を作りました。Appleも暗号化の通信に関しては厳しかったのでこーゆー簡易的な感じになったのですが、基本的にTCPでの接続でした。
ただ、Verethragnaでやろーとしてたブラウザ版はTCPではなくその上位レイヤーのHTTPということになります。つまりはブラウザの通信仕様に合わせる感じです。まあ、ブラウザ上で動かす必要があったので最低でもHTMLでJavaScriptは必要になるかなー、程度で考えておりました。
この安易な考えは間もなく叩きつけられます。TCPというかソケットサーバーでHTTPを対応することはそれほど難しくありません。ただここに暗号化(SSL)やリアルタイム通信などが加わってくると話はまるで別物です。手前のソケットサーバーに実装となるとますます大変です。OpenSSLやLibwebsocketsなどを追加していけばいけないこともないのですがメンテナンス性も含めてあまり将来的に変更があるだろうライブラリをリンクさせたくないなとゆー思いがありました。まあVP8やCELTやBlowfishやFastLZは今後も変化はたぶんないでしょうから安心してリンクしてるんですけど。
さて、そんな感じで既に心が砕けそうになってましたが、考え方を変えました。下位モデルと上位モデルを作ることにしました。下位モデルは従来のTCPからのHTTPのみを通信できるモデル、上位モデルはHTTPSやWebSocketなども対応できるモデル、という風にすることにしました。上位モデルはWindowsのカーネルモードドライバーである「HTTP.sys」を利用すればいけそうなことは見えてましたので。まあこのHTTP.sysはこれはこれでサンプルも少ないですしなかなか苦労することになるのですがそれはまた別のお話で・・・。
そんなこんなでまずは下位モデルとゆーことで、開発することになりました。すぐに暗礁に乗り上げますが。
まず、映像で利用する予定だったVP8。これをiOSで描画することができません。正確にはiOSのブラウザのWebKitではVP8を再生できません。WindowsとかAndroidはいけます。まあVP8はGoogleですんで。
さすがにここでH.264系に舵を切ると負けかなと思ってましたのと何よりライセンスが微妙です。例えば、WindowsのDXVAでH.264のエンコードは実装できました。ただ、H.264というかMPEG系の映像圧縮のアルゴリズムをエンコードで利用すると特許利用料(パテント)が発生するのですが、それをMicrosoftが支払っているかというとどうやらそうではないんです。まあOSですし当たり前と言えば当たり前なんですけど法的なとこは個々に対応をってことになってます、OSの規約をみると。
https://www.microsoft.com/en-us/Useterms/OEM/Windows/11/Useterms_OEM_Windows_11_Japanese.htm
大丈夫ですか?御社でご利用のそのH.264での圧縮は。
てことでめんどーなH.264は避けるとして、となるとやっぱりVP8なんですけど、WebAssemblyを利用すればiOSのブラウザでもVP8でデコードできることは確認してました。ならばWebAssemblyと思いましたけど、WebAssemblyはTCPが使えないのでWebSocketを利用する必要がありました。ここでWebSocketかー、ってなりました。将来的にWebAssemblyでもTCPはいけるようになるみたいなんですけど今じゃないと。
そもそもWebKitとゆーかiOSで何とかならんのかと思ってたんですけど、Appleの仕様でiOSのChromeでもWebKitを使うことになってるんで何ともなりなさげ。でも最近ですと欧州でiOSでWebKitに限定しちゃダメってことでChromeのネイティブエンジンがiOSに載るってニュースになりましたよね。これは良い流れ。
https://gigazine.net/news/20240126-ios-17-4-webkit-alternative-browser-engines/
でもまだVP8は動かない。今じゃないと。
てことでそれまで待てないので手っ取り早く考えたのが、JPEGとPNGでハイブリッドにして描画する形式。HTMLのIMGタグの中身を高速に書き換えてやればいけるんじゃないかと。でも実際にはNGでPNGを利用するのは差分で描画するのことが必要でよーわ透過で描画できないIMGタグはNG。透過ができないと画面に動きがなくても常時JPEGででかめの通信量が発生してしまうので面白くない。てことで何とか透過はできないものかと探していたらありましたCanvas。
CanvasはHTML5の時に出てきてまあ今はHTML5とは呼ばないんですけど使える描画コントロール。透過もいけるになりより書き換えが不要でよーわMotionJPEGみたいにストリーミングで流せる。これは良い。ただ、JPEGは画質が良くなくて何とかしたかった。PNGは可逆だけどデータ量がでかいし。
そこで登場したのがWebP。JPEGの代わりにこれでいこうかと。Libwebp で色々試してみたけど良い感じ。で、調べていくとこのWebPってVP8のよーわキーフレーム(Iフレーム)なんです。てことはですよ、Verethragnaで利用しているVP8のライブラリからもWebP形式を生成できるのではと思って色々とやってみてたらできました。これは最高すぎる。てことでCanvasには動きがあればWebP、動きがなければPNGとゆー仕様になりました。
さらに開発を進めるとまた難関が。映像と音声はFetchを使ってサーバーからのストリームにしたのですが、マウスとキーボードの入力はサーバーへのストリームにしないといけない。Fetch Upload Streamingを使わねばならん。だがしかしまたもiOSでは非対応。またか。てことで連続でGETを投げるしかない。で、やってみたんですけどどーやらFetchよりもXMLHttpRequest (Ajax)の方が高速。これは良い。迷いもなくXMLHttpRequestに。
ちなみに、これは最近なんですけどサーバー側のソケットでacceptを使ってたんですけどAcceptEXの方がすげーよってMicosoftのサイトに書いてあったのでそーすることにしました。ApacheのサイトにはBSDのacceptよりもすげーって書いてあったので間違いないですよね。
https://httpd.apache.org/docs/2.2/ja/mod/mpm_winnt.html
これ、接続を受ける際にちょっと仕組みが異なっていてTCPでもHTTPでも使い勝手が良かったのでVerethragnaの次回バージョンアップで実装されてしまいます。
てことで入力系はサーバー側の修正もあり連続GET(のちに連続POSTに変更)のパターンです。いずれFetch Upload Streamingが対応すればこっちを使いたいんですけど今じゃないと。
あと音声なんですけど圧縮ができません。たぶんMP3とかAACとか使えばできるんですけどサーバー側も対応しなきゃなんで、これは下位モデルですし、とりあえずPCMでモノラルにしました。だいぶ心が負けてきております、この時点で。
あとCanvasの仕様でさっきのPNGの差分描画の時に縮小されているとちゃんと差分で描画できません。だー、こんにゃろー。ちゃんとしてくれー。ゴミがどーしても残ってしまうので一定間隔でWebPによる画面更新を余儀なくされております。
あと暗号化はできないので排他的論理和でハッシュ化程度です。必要であればVPNなどの回線の方で暗号化してくださいお願いします・・・。
そんなこんなで下位モデルはこんな感じで後半はグダグダで開発されましたが、まあでもちゃんと動くよーに頑張ってはおりますのでー。JavaScriptとゆーかHTMLファイルでのスクリプトはユーザー側でも作れるよーにしたいと思ってますので、Brynhildrのパブリックモードのよーに自由にクライアントを作ることができればと考えております。自分が作ったのはあくまでもサンプル・・・サンプルなんですよ、ドーン!的な。いやホントだいぶしんどいです、JavaScript。
で、上位モデルのHTTP.sysはSSL(HTTPS)もいけるわWebSocketもいけるわ、であればWebAssemblyもいけるわ、でもちろんVP8もCELTも入力系のストリーミング化もできるし何でもござれなんですよね。いやまだ全然コアの部分しかできてないんですけど。まあ希望しかないですよね、下位モデルはずいぶん大変でしたもので特に。
その頃にはiOSでもVP8がネイティブで対応できてるかもしれないですし、WebAssemblyでTCPがいけるかもしれないですしとか状況は変わってるかもしれないんですけどねーー。
あと、1つHTTPで非暗号化で良いところは、プロキシへの対応ですかね。恐らくWebSocketもSSLと同じくプロキシの対応が難しいと思うんですよね。WebSocketも厳密にはHTTPではないのでSSLと同じ中身は分からんのでポート開けたるからそこへどうぞってことになると思うので。大丈夫ですかね、そーゆー面でのセキュリティ。その辺、下位モデルのHTTPであればFetchとかであれば逆にちゃんと中身も確認できると思いますので安心かなと。空港の保安検査場的な。
そもそも最近は何でもかんでも暗号化暗号化で中身が分からんので安心かもしれないですけど、もし情報が漏洩しても中身が分からんから漏洩してても分からんとかゆーこともありホントにそれはそれで大丈夫なのk
はい、話が逸れ始めましたし長文になりましたしこの辺で。
てことでVerethragnaのブラウザ接続は開発順調?ですんでもう少々お待ちください!