2011年5月27日金曜日

RtmpClientの使い方その4 scheme1のValidation通してみる。

Red5の内部についている。RTMPClientをつかって別のRed5のサーバーにクライアントとして接続させると動作的に不正なクライアントと判定されます。
これはscheme1のValidationが有効になるようにRTMPClientがHandshakeしないためです。
Red5のサーバー動作側がscheme1でValidationの確認してるんだから、Red5チームがメンテしわすれたんでしょうね。

さて、この問題をなんとかしてみます。
ちなみに、現状のバージョンのRed5では別にValidation通さなくてもなんの問題もありません。判定だけしてそのまま処理続行してますから。ただの自己満足の色合いが強いです。

ソースコードの全体図はgithubにあげたred5_phpのリポジトリを確認してください。
ここのcom.ttProject.TestClassを実行するとlocalhostの1935ポートのRtmpサーバーのliveアプリケーションに接続しにいくようにしてあります。

まずは変更点の解説
■RtmpClientEx.javaの中
1:コンストラクタ上でioHandlerの初期化を実行
2:startConnectorのメソッドをRTMPClientよりオーバーライド
元ネタのRTMPClientではioHandlerをRTMPMinaIoHandlerとして初期化しています。
このHandlerの内部でつかっているOutboundHandshakeというクラスの中身を必要に応じて変更したいので、Handlerに細工する→Sessionに独自handshakeクラスを注入するという手を使います。
2の方のstartConnectorのメソッドのオーバーライドはioHandlerがprivateではなくprotectedだったら必要なかったのですが、まぁしかたないです。

■RTMPMinaIoHandlerEx
1:sessionCreatedをオーバーライド
このイベントの時に、オリジナルのRTMPMinaIoHandlerの処理を実施したあとに、sessionの設定属性を独自のものに書き換え。
テスト等でオリジナルのRTMPClientのHandshakeを実行したい場合は設定しているOutboundHandshakeExの部分をコメントアウトすれば大丈夫です。

■OutboundHandshakeEx
1:generateClientRequest1をオーバーライド
2:addBytesメソッド
3:calculateOffsetメソッド
2と3は内部で使う補助メソッドです。OutboundHandshakeの中でも定義されているんですが、privateになっているため、コピーしました。
問題は1の部分

大本のOutboundHandshakeクラスの中では次のようにHandshakeが進行します。
はじめにcreateHandshakeBytesメソッドで、timestamp(4バイト) + プレーヤーバージョン指定(4バイト*1) + 1528バイトのランダムバイトをひな形として作成します。
続いてgenerateClientRequest1メソッドで、送信バイトデータとして、Encrypted識別子(0x03)と先ほどつくったひな形をHandshakeのエントリーとして送信しています。(*2)

*1:ここでいうプレーヤーのバージョンは、adobeのFlashプレーヤーのバージョン確認ででるバージョンとは別のデータになります。内部管理用のバージョン番号が別にあるのでしょう。
*2:adobeのサイトのrtmpの仕様書によるとHandshakeの冒頭でc0 c1 c2 s0 s1 s2とクライアントが3回、サーバーが3回データを送信するように設計されていると記述されています。このc0c1に相当するデータが一度に送信されています。(ってか分けてる必要あんのこれ?)

OutboundHandshakeExではひな形はcreateHandshakeBytesでつくってもらってからgenerateClientRequest1上で次のようなことを行っています。
まず、ひな形をローカル変数に保持。
続いて772から4バイトがvalidation用のキーの埋め込み場所を指定するデータとなるため、その4バイトを取得する。
776から728バイトのデータがどうなっているかをキーにSHA256で暗号化するのでその計算を実行。
できたキーを先ほど計算した埋め込み場所に上書き。
でHandshakeのひな形できあがりとなります。

では最後に、conf/logback.xmlでorg.red5.server.net.rtmpをDEBUGにした状態でRed5 1.0.0 RC2 Rev 4222に接続させてみます。
まずは、エラーにRTMPClientでつないだ場合

[DEBUG] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandshake - Player encryption byte: 3
[DEBUG] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandshake - Detecting flash player version 9,0,124,2
[DEBUG] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandshake - Player version byte: 9
[DEBUG] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandshake - Scheme: 0 client digest offset: 342
[DEBUG] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandshake - Temp: 1f52f06ea4da019863e8d35badd242cb29be6224613996df3bf3becd2da28676
[DEBUG] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandshake - Scheme: 1 client digest offset: 1284
[DEBUG] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandshake - Temp: 32ba98dd706a7c8ecb089ea49c44c31aafe2bbcc5ad0b44e489bbf13e1d0761b
[ERROR] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandshake - Unable to validate client
[INFO] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandshake - Invalid RTMP connection data detected, you may experience errors
[DEBUG] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandshake - Using new style handshake
ちゃんと無効なクライアントと判定されてしまいました。Scheme 0もScheme 1も認証がとおっていません。

続いて修正版で接続した場合
[DEBUG] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandshake - Player encryption byte: 3
[DEBUG] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandshake - Detecting flash player version 9,0,124,2
[DEBUG] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandshake - Player version byte: 9
[DEBUG] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandshake - Scheme: 0 client digest offset: 691
[DEBUG] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandshake - Temp: 4f19642c794f70f130ac7b159cda40f71a754abbcea4fa40d8bc328923bf0504
[DEBUG] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandshake - Scheme: 1 client digest offset: 1217
[DEBUG] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandshake - Temp: 55671918c7a41de1e20d29b1f9b11e3c70951ce34e13f5c4b32b51054bbef963
[DEBUG] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandshake - Selected scheme: 1
[DEBUG] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandshake - Valid RTMP client detected
[DEBUG] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandshake - Using new style handshake
きちんとScheme1を検出して有効と判定してくれました。
まぁやってることは同じですけどw

最後にFlashPlayerでつないだ場合
[DEBUG] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandshake - Player encryption byte: 3
[DEBUG] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandshake - Detecting flash player version 128,0,7,2
[DEBUG] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandshake - Player version byte: 128
[DEBUG] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandshake - Scheme: 0 client digest offset: 374
[DEBUG] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandshake - Temp: e038bc995719caece95d042eb4e71a1ffbfb140d4a6ac3aa52e296c742d3082b
[DEBUG] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandshake - Scheme: 1 client digest offset: 1310
[DEBUG] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandshake - Temp: 8753c820eb1225042a7c13ce15bc5f99af692caa07986d0125b9567eec7f4bc4
[DEBUG] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandshake - Selected scheme: 1
[DEBUG] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandshake - Valid RTMP client detected
[DEBUG] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandshake - Using new style handshake

これで似た感じの動作になってきました。

0 件のコメント:

コメントを投稿