There are a bunch of solutions for making a bridge to use the flash sockets (flash.net.Socket) in javascript, notably socketBridge and jssockets. But I didn’t like the way they made you write your client code: because you can’t pass javascript function references through the ExternalInterface you usually pass your callbacks as strings representing the name of an global object. IMHO, that just sucks so I’ve made my own mix named HaxeSocketBridge.
You can write the client code like this:
var s = new FlashSocket({
on_data: function(data) {
document.getElementById('datapanel').value = data;
},
on_io_error: function(msg) {
alert("IO ERROR: "+msg);
},
on_security_error: function(msg) {
alert("SECURITY ERROR: "+msg);
},
on_close: function(msg) {
alert("Connection closed.");
},
on_connect: function() {
s.write("GET / HTTP/1.0\r\n\r\n");
}
});
s.connect('example.com', 80);
Here’s the whole example.
How does it work? You can execute arbitrary javascript code though the external interface, so why not execute some boilerplate code and setup a global FlashSocket class that handles all the nasty actionscript-javascript communication. I’ve seen this arguably good idea in the SWFHttpRequest bridge. If you do something like this be careful with those damn commas/semicolons or else you’re in i-dont-know-why-it-breaks hell :)
Here’s how the guts look like (note that the language is haxe):
ExternalInterface.addCallback("connect", connect);
ExternalInterface.addCallback("close", close);
ExternalInterface.addCallback("write", write);
ExternalInterface.addCallback("CAN_I_HAS_SOCKET", CAN_I_HAS_SOCKET);
ExternalInterface.call([
"(function(){",
"if (window.FlashSocket) return;",
"var Class = function(properties){",
"var klass = function(event_handlers){ ",
"for (var p in event_handlers) {",
"if (event_handlers.hasOwnProperty(p)) {",
"this[p] = event_handlers[p];",
"}",
"}",
"return this.init.apply(this);",
"};",
"klass.prototype = properties;",
"klass.constructor = arguments.callee;",
"return klass;",
"};",
"window.FlashSocket = new Class({",
"init: function(){",
"this._instance = ''+window.FlashSocket._instances.length;",
"window.FlashSocket._instances.push(this);",
"},",
"close: function(){ ",
"window.FlashSocket._instances[this._instance] = null;",
"window.FlashSocket._bridge.close(this._instance );",
"},",
"write: function(data){ ",
"window.FlashSocket._bridge.write(this._instance, data);",
"},",
"connect: function(host, port) {",
"window.FlashSocket._bridge.connect(this._instance, host, port);",
"}",
"});",
"window.FlashSocket._instances = [];",
"var f = function(tag){",
"var elems = document.getElementsByTagName(tag);",
"for (var i=0; i<elems.length; i++) if (elems[i].CAN_I_HAS_SOCKET) return elems[i];",
"};",
"window.FlashSocket._bridge = f('embed') || f('object');",
"})" ].join('') );
if (flash.Lib.current.loaderInfo.parameters.onloadcallback != null)
ExternalInterface.call(flash.Lib.current.loaderInfo.parameters.onloadcallback);
The trick is that we can setup a global javascript class-like object from the flash clip.
You can grab the code here. Also, if you test from a local disc you might want to adjust your flash security settings. To compile the .hx file run “haxe compile.hxml“.
Now, the only thing I miss is some buffering/readline logic.
22 Comments
This is a much nicer javascript interface to the SWF, glad to see someone else getting involved on this problem too.
Can’t see how you’d get multiple concurrent connections with this SWF though, as there is only ever one instance of window.FlashSocket._bridge. I know that’s an edge case though.
Good work and a nice pattern to remember in future.
Oh, my bad, scrap that last comment. I see there is support for multiple connections in the haxe source.
Hm ya there seems to be multi-connection support, but how can I use it? I thought I could do it by initiating another FlashSocket Object. But it’s not working. my first object is getting killed or better the connection gets resetted.
Thanks,
Chris
Can you post sample code proving the problem ?
nice every is compiled but i got a security alert
and i don’t see what i have to set in the security settings from adobe
thank you for your nice example
@jean-michel, If you are testing locally you need to add a path for a trusted location in the security manager. Otherwise you usually need to have a proper policy file serving daemon running on port 843 on the servers you are making socket connections to.
sorry to disturb you again ionel and thank you for your former answer .
but i have seen the place in adobe page to give the path for a trusted location
i have given the place where socket_bridge.swf is , but no change i have still the
same behaviour security error #2048
in fact i think i don’t understand at all what means a trusted location ???
i have read a lot of thing but …
i give you the location on my PC http://jmg78.hd.free.fr/sock.htm
Trusted locations work only for local files, eg: your url is like “file:///c:/bla/bla.html”
If you are loading the page from a http webserver you need to have a additional service there listening on 843 and sending a string like this on each connection:
assuming you want to accept connections on jmg78.hd.free.fr from any domain on port 80.
thanks again
you are going to think i am stupid :)
for the moment i want to test on “localhost” but of course i use a browser to call my htm file
i have try to put both files sock.htm and socket_bridge.swf on the trusted files list and even the whole directory
no change
in the second case if i use a service listening on 843
you say i have to send a string like this : but i dont see any string
PS i am under linux
Drats! wordpress removed it (was some xml markup). Here is it: http://code.google.com/p/ionel-whatever-code/wiki/FlashSocket
Hello and thanks much, good job, everything works fine, but i’ve caught some strange behaviour.
I open localhost/test.html, flash successfuly gets policy file (i have a daemon on 843 port), socket connects to localhost:80, gets and prints content, server closes connection, i get all expected debug alerts. But then, after about 15 seconds, there’s a 2048 security error. o_O
It looks like client tries to connect one more time to some different place (where?..) and fails to get policy file or whatever, with timeout. I’ve looked through the code, recompiled, tried >1024 port, no effect..
win xp sp3, differect browsers
Thanks
Do you have a traceback for that last error?
eer, no, how can i get it? ) i’m totally new to flash and haxe
i put at the beginning of SocketBridge::connect this:
ExternalInterface.call( “(function(){alert(‘called ::connect’);})”);
but it alerts only once when it’s expected
How does your policy file look like ?
Are you sure you serving the policy file right ? (that means send the xml, close the connection -or- prepend a null char and flash will close the connection. see: http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7c60.html )
Might want to try fetching the policy file yourself (eg, FlashSocket.loadPolicyFile(“xmlsocket://localhost:843″); )
Still doesn’t explain why you still get the response and the security error though …
My policy file – http://pastebin.ca/1420519 , but also i tried different params
>Are you sure you serving the policy file right ?
Yes, i’m sure.. At first time i used example python server from http://www.adobe.com/devnet/flashplayer/articles/socket_policy_files.html but then i wrote my own on erlang and experimented a lot. Also i installed debug flash player and set up logging, it produces little more info but still clueless..
I also wrote another server to test client with, instead of simply connecting to the same apache that serves page-with-client. Some results:
While connected, there is no error, and it raises after about 15 sec after server closes socket (notable that “close” event is raised by flash as expected). If flash closes socket, error doesnt rise. It seems that sometimes error doesnt rise at all.. To sum up, for disconnection i can send “command” to client that it should close the socket. Bad solution, but it works for the present..
I’ll experiment more and post if get any results..
hi, this really helpme out, but Ionel, please tell me what kinf of licence is this under? can i use it in my comercial site?
other thing, i dont want people to see so direct my ip and port adress i know theres no point on hiding it because the one who wants to know it knows it esaly… but we are not all geeks….:-) soo can i modify the code to hide it?
Yeah use it however you want. I will add a MIT license text in the source code so there won\’t be any confusion.
thx…any ideia to improve security and encryption…?
Hello
I have a problem getting your example to work. I am not familiar with haxe or flash, but it seems like the ExternalInterface’s methods are not working. I reduced the main function to the following lines of code
trace(ExternalInterface.available);
if (flash.Lib.current.loaderInfo.parameters.onloadcallback != null)
{
trace(“callback function: “+flash.Lib.current.loaderInfo.parameters.onloadcallback);
ExternalInterface.call(“document.title = ‘Hello World’”);
}
trace(“Hello World”);
and everything before ExtrenalInterface.call is being outputed, but “Hello World” is not unless ExternalInterface.call is commented. The same issue occurs when trying to use ExternalInterface.addCallback. Can you please point me what I am missing/doing wrong?
Thanks in advance
The callback must be a function name that is available on the global javascript scope (window).
See http://ionel-whatever-code.googlecode.com/svn/trunk/HaxeSocketBridge/test.html for an example.
Thank you for your answer but I don’t think that is the problem. I got the exact code from here http://ionel-whatever-code.googlecode.com/svn/trunk/HaxeSocketBridge/ and it was not working. I tried to simplify it in order to get at the bottom of the problem and the following is still not working:
trace(ExternalInterface.available);
if (flash.Lib.current.loaderInfo.parameters.onloadcallback != null)
{
trace(“callback function: “+flash.Lib.current.loaderInfo.parameters.onloadcallback);
ExternalInterface.call(“test”);
}
trace(“Hello World”);
In the html page the test function is defined as follows:
function test() {
alert(“on load callback”);
}
Could this issue be related with the flash player version?
Thanks
Are you sure the function is defined when the flash clip tries to call it? Can you post example code reproducing the problem?
One Trackback
[...] Update: 5 May 2009 This post has generated a (relatively) large amount of interest so I feel I should point out the ionel is also hosting his improved version of the socketBridge. It has a nicer OO interface and might solve some issues with the javascript callbacks and setTimeouts. Might be worth a peek for all those interested: http://ionelmc.wordpress.com/2008/11/29/flash-socket-bridge-with-haxe/ [...]