web-socket-jsのFlash接続について
web-socket-jsとは
WebSocketに対応していないブラウザに対してFlashを利用して擬似的に
WebSocket接続を行うもの。
socket.ioなどのライブラリはWebSocketに対応していないとFlashやLong Cometに置き換えるがweb-socket-jsは一貫してWebSocketを貫き通す。
ソースコードもGithubにあがっているのでとても使いやすい。
対応ブラウザもGithub上のREADMEに書いてある。
Flash接続について
web-socket-jsを利用する場合十分に考慮しないといけないのがFlashのSocket接続だと思う。
ソケットポリシーファイルのやり取りが必要になりFlashの仕様として、以下の手順を踏むことになっている。(リンク先引用)
- まず843番ポート(ソケットマスターポリシーファイル)にアクセス。繋がらない or 3秒以内に返事がない場合は、次へ。
- Security.loadPolicyFile("xmlsocket://...");で指定されたポートがあれば、そこにアクセス。繋がらない or しばらく(20秒ぐらい?)返事がない場合は、次へ。URLがxmlsocket://...の場合のみ有効なので注意。Security.loadPolicyFile("http://...");で指定されたファイルはSocket、XMLSocketによる通信では無視される。
- Socketの接続先と同じポートにアクセス。適切なソケットポリシーファイルが受信できなければ、SecurityError
843ポートに接続する
一番最初にここを見に行くのでここでソケットマスターポリシーファイルを返せるなら一番これがいい。でも、大体社内では閉じられていたりするので厳しかったりもする。
ちなみに閉じた状態で試してみると3回SYN飛ばして諦めてた。
Security.loadPolicyFileで接続する
ここは設定次第で接続しにいくみたいだけどよくわからなかった。
web-socket-jsではWebSocket.loadFlashPolicyFileを事前に設定すると呼ばれないようだ。
(loadFlashPolicyFileの設定先はFlashが読みにいくそれとは違うみたい)
Socketの接続先と同じポートにアクセス
最後にここにたどり着く。
web-socket-jsの作者が開発されているwebsocket-rubyでは以下のように対応されている。以下引用。
def create_web_socket(socket) ch = socket.getc() if ch == ?< # This is Flash socket policy file request, not an actual Web Socket connection. send_flash_socket_policy_file(socket) return nil else socket.ungetc(ch) if ch return WebSocket.new(socket, :server => self) end end # Handles Flash socket policy file request sent when web-socket-js is used: # http://github.com/gimite/web-socket-js/tree/master def send_flash_socket_policy_file(socket) socket.puts('<?xml version="1.0"?>') socket.puts('<!DOCTYPE cross-domain-policy SYSTEM ' + '"http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">') socket.puts('<cross-domain-policy>') for domain in @accepted_domains next if domain == "file://" socket.puts("<allow-access-from domain=\"#{domain}\" to-ports=\"#{@port}\"/>") end socket.puts('</cross-domain-policy>') socket.close() end
Socketから取得したデータに対して"<"で始まっていればポリシーマスターファイルを返している。
実際Flashからリクエストが来た時の中身はこんな感じ。
<policy-file-request/>\x00
URLのパスとか全く考慮されてないので柔軟には扱えないかなと思う。