gimite / web-socket-js

HTML5 Web Socket implementation powered by Flash

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

The current implementation favors port 843 for socket policy files

jvshahid opened this issue · comments

According to this article http://www.adobe.com/devnet/flashplayer/articles/fplayer9_security.html#_Configuring_Socket_Policy:

...that you need to provide more explicit guidance to Flash Player from ActionScript by calling loadPolicyFile to indicate the location of a socket policy file. When you call loadPolicyFile rather than allowing Flash Player to check locations by default, Flash Player will wait as long as necessary for a response from a socket policy file server, rather than timing out after 3 seconds. This may help your application's reliability in marginal network conditions. It can thus be helpful to call loadPolicyFile even for a default socket policy file location—simply to request that Flash Player wait patiently for the socket policy file server to respond.

It looks like asking flash to load the policy file from port 843 (WebSocketMain.as:53) will make it favor that port over the destination port. This will cause a problem if port 843 is blocked by a firewall. I noticed that flash will try port 843 three time and it waits the first time for 3 sec then it waits for 6 sec for the second and third retries (On Windows it's 3, 6 and 12 seconds resp.) That's about 15-21 seconds between the time the user loads the page and a connection being established.

I'm proposing to remove that line (WebSocketMain.as:53) since flash will try port 843 anyway. Without that line, it'll try port 843 only once with a timeout of 3 seconds. This is more acceptable than the 15 seconds delay in my opinion.

Thanks,

Yeah it makes some sense. But I also have some reason to prefer the current way:

  • If we don't call loadPolicyFile() and socket policy file is provided only on port 843 (not on the connection port), connection fails if the server or network is slow and client cannot receive socket policy file in 3 sec.
  • If port 843 is not blocked, providing socket policy file on port 843 is the most efficient way, because anyway Flash Player tries port 843 first.

So the preference depends on how often port 843 is blocked. I don't have clear idea. I believe it's somewhat common to block everything and allow only connection to HTTP proxy, but in that case, anyway Flash socket is not available.

One option is to provide API to set policy file URL in JavaScript.

Yes, I was thinking about setting the policy file url through a method call in the API. That will make the library very flexible. Regarding port 843 I believe it's blocked in most corporate networks, at least this is the case for inbound traffic to my company's network. This is actually why I started investigating the reasons behind having higher load time in Firefox and IE than in Chrome.

Now you can load policy file from other port by e.g.

WebSocket.loadFlashPolicyFile("xmlsocket://example.com:80");

What if you WANT it to fail in 3 seconds when 843 is blocked? I guess now I know this is why things are taking forever to time out I can just comment out the line that's doing the explicit loadPolicyFile, but it'd be nice if I could force it to fail-fast without a hack.

Commits 0d8d903d8b3a2e0ce99a and 6640d9d806972ea1720a provide a way to override the default port. Take a look at the commit messages.

I have, but it doesn't address NOT setting the loadPolicyFile at all so that flash "fails fast" when 843 is blocked. I don't want to change the default port, I want to not set a port at all and fail fast if the port is blocked.

I commented out the call to loadPolicyFile for the default port, and it worked. I'm just going to do that in a local change.

Did you try this?:

WebSocket.loadFlashPolicyFile("xmlsocket://example.com:80");

(You should replace the port number with your Web Socket port)

I guess not calling Security.loadPolicyFile() is equivalent to above, because it loads policy file from the port you are connecting to by default. Note that in both cases it first tries port 843 and gives up in 3 seconds.

@Vagabond, I don't understand what you're trying to do here. If you're not changing the default port then I'm assuming you're policy file will be on port 843 (correct me if I'm wrong). If so why do you care about failing fast, the flash websocket implementation won't work anyway.

"When you call loadPolicyFile rather than allowing Flash Player to check locations by default, Flash Player will wait as long as necessary for a response from a socket policy file server, rather than timing out after 3 seconds."

Doesn't this mean that NOT calling loadPolicyFile at all will change the timeout behavior or am I reading it wrong?

That's partially correct, flash won't wait as necessary. As it's pointed out in the issue, it will timeout after 15-21 sec depending on the flash version and the OS. My question was, what difference does it make in your app. In my case the policy file is served on the destination port so making flash timeout after 15 seconds wasn't acceptable. I'd like to hear your answer, just present your case.

I run the policy server on the default port. The policy server runs on an appliance device which may or may not be firewalled, I have no way to tell or mandate whether is it or not.

I have a websocket server that falls back to long-polling if websockets don't work. If websockets aren't native, I want to try flash websockets and if those don't work I fall back to long-polling. I need this to be as fast as possible, the 15 second timeout is unacceptable. That's why I want to avoid calling loadPolicyFile at all, so it does the 3 second timeout.

I understand your situation. But Flash Player doesn't give option to "try port 843 for 3 seconds and then give up". As I mentioned in earlier post, the default behavior (without call to Security.loadPolicyFile) is:

  • Try port 843 for 3 seconds, then try loading policy file from the port you are connecting to (i.e. in this case the Web Socket port)

This worked for you probably because your Web Socket server doesn't provide socket policy file (so when it fails to connect to port 843, both attempts above fail).

And again, equivalence to default behavior above should be done by:

WebSocket.loadFlashPolicyFile("xmlsocket://example.com:80");

FYI Another way to achieve your purpose (to timeout quickly) is to timeout manually i.e. use setTimeout() to fall back to long poll if ws.onopen is not called in 3 seconds.

I'm having a problem with setting a custom port for the flash policy file. I suppose that all ports beside 80 and 443 could be blocked by corporate firewalls, so I need to setup the policy file on either of them. Also, the policy file needs to be on the same domain where the page HTML is loaded from, otherwise Flash does not make the request.

But that's a deadlock situation - ports 80 and 443 are used by the HTTP server to serve the page, so I can't use them for serving the policy file. Serving it from a different domain does not work.

What can I do to/what technology can I use to resolve this situation?

If you can modify the HTTP server, one idea is to modify the server to handle both HTTP request and socket policy file request. You can easily distinguish these two requests. Or maybe write a thin wrapper of existing HTTP server (e.g. Apache) which also handles socket policy file.

Hey @gimite, I'm having trouble getting this to work.

I've got a Node server running on Heroku. The Heroku endpoint is HTTPS, but Node is listening on an HTTP port which the Heroku environment provided. So I have a few questions:

  1. Is it possible to load a policy file over HTTPS?
  2. Why is everyone so focused on creating a lightweight net server on 843 if all Flash needs to do is load an xml file from the domain in question?
  3. What exactly does the xmlsocket scheme mean, and why can't I put http or https in there?
  4. Is wss supported?

I've tried the following combinations, but I can't get any of them to work. Do either of these methods look right? I've also tried putting a crossdomain.xml file at the root, although it seems like I should be able to name this file whatever I want.

WebSocket.loadFlashPolicyFile("xmlsocket://example.com:443");
WebSocket.loadFlashPolicyFile("xmlsocket://example.com:443/crossdomain.xml");
WebSocket.loadFlashPolicyFile("example.com:443/crossdomain.xml");
WebSocket.loadFlashPolicyFile("example.com/crossdomain.xml");
WebSocket.loadFlashPolicyFile("https://example.com/crossdomain.xml");

Thanks!

Does Heroku support listening on a port with a protocol other than HTTP or HTTPS? If not, I don't think you can make web-socket-js work on Heroku, unfortunately.

Is it possible to load a policy file over HTTPS?

No.

Why is everyone so focused on creating a lightweight net server on 843 if all Flash needs to do is load an xml file from the domain in question?

Because it's its own protocol, not HTTP.

What exactly does the xmlsocket scheme mean, and why can't I put http or https in there?

That's the name of its own protocol. Only xmlsocket is allowed. http and https are not supported. That's the spec of Flash.

Is wss supported?

Yes.

Ugh.. okay. Makes sense. So theoretically, in order to use web-socket-js on Heroku, I could spin up my own machine on AWS or Digital Ocean and run a small Node server that talks the xmlsocket protocol and serves the insecure version of the SWF object over HTTP. That should work, right?

I believe you need to host the web socket server in AWS too because the socket policy file and the web socket server must be in the same host. Socket policy file grants flash contents to access to the host where the policy file is located.