views:

1307

answers:

9

I get a Flex 3 sandbox error #2048 after connecting to a Socket on a Java (1.5) server. The server code is all mine, i.e. not running under Apache. Flash Player 10.0 r32.

The sequence is as follows...

1 Java server starts, listens on port 843 for policy file request and on port 45455 for my other requests.

2 Flex client served by Apache (although I get the same result if I run it from the file system), socket connection made on host:45455.

3 Flash Player requests policy file from port 843. This is the standard behaviour with the new security settings looking for a master file. It happens regardless of whether a different policy file has been specified.

4 I serve the following XML from Java through port 843:

<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd"&gt;
<cross-domain-policy>
<site-control permitted-cross-domain-policies="all"/>
<allow-access-from domain="*" to-ports="*" secure="false"/>
</cross-domain-policy>

5 The player writes the following into the debug policy log...

OK: Root-level SWF loaded: http://localhost/bst/BasicSocketTest.swf
OK: Searching for <allow-access-from> in policy files to authorize data loading from resource at xmlsocket://192.168.2.3:45455 by requestor from http://localhost/bst/BasicSocketTest.swf
OK: Policy file accepted: xmlsocket://192.168.2.3:843
OK: Request for resource at xmlsocket://192.168.2.3:45455 by requestor from http://localhost/bst/BasicSocketTest.swf is permitted due to policy file at xmlsocket://192.168.2.3:843

6 I send a text message from the client to the server on port 45455 using writeUTFBytes() and flush() (this is my own home-baked message protocol, and is correctly processed at each end)

REG/REGISTER;simon;Si

7 Java server thread listening on port 45455 responds with

REG:0/REGISTER:SUCCESS;simon;Si

8 The Flex client receives a ProgressEvent and the event listener I bound to the socket gets called. I process the message (write it to a text box on the screen)

9 The Flash player throws a 2048 sandbox error and the socket is disconnected! This is after the message is received and processed successfully. In fact it is about 12 seconds after. Nothing else works through the socket.

I have tried explicitly loading a policy file with a call to Security.loadPolicyFile() in the Flex client, but the reality of the new player security is that it is basically ignored. The steps are that the policy request will not get sent until a socket i/o operation occurs. At that point the player always goes to port 843 first looking for a master policy file. If it finds one, and it is permissive, it goes no further.

I have tried a variety of alternative ways of terminating the policy file and policy file contents, including deliberate errors just to see if the Flash Player is awake.

I can see no reason why I would have a 2048 being thrown. I accurately serve a socket policy file on the designated master security port, which the player itself logs as correct. The socket then successfully sends and receives a message from the server the contents of which are available to my code.

Does anyone have any clue why this may be happening? Flash Player bug?

P.S. Please don't tell me to use BlazeDS or LCDS or Granite, or something else as a server, I'm looking for a solution to this problem, not a redesign. And please don't ask me to use an XMLSocket instead - I tried that and get exactly the same result. I have chosen my architecture carefully and deliberately and I want a binary socket.

EDIT In response to James Ward's request in his comment, here is the entire error message:

Error #2048: Security sandbox violation: http://localhost/bst/BasicSocketTest.swf cannot load data from 192.168.2.3:45455.

I have a stripped down test client which has a handler for each socket event and outputs a message to the screen. This is what it shows:

RequestPolicy: 192.168.2.3:843
Create Socket: 192.168.2.3:45455
Connect: [Event type="connect" bubbles=false cancelable=false eventPhase=2]
Sending: REG/REGISTER;[email protected];Si
Receiving: REG:0/REGISTER:SUCCESS;[email protected];Si/
Close: [Event type="close" bubbles=false cancelable=false eventPhase=2]
Error #2048: Security sandbox violation: http://localhost/bst/BasicSocketTest.swf cannot load data from 192.168.2.3:45455.

The close event is fired immediately after successfully receiving a response from the server, however the Error #2048 does not appear until about 20 seconds later. If I try and send a further message after close, but before the error, the Flash Player throws an invalid socket exception.

I have logged a bug at Adobe about this.

I can provide full source code of both client and server if anyone is interested.

+1  A: 

A similar problem here indicates that localhost was not being resolved to 127.0.0.1.

You might try changing over to the IP address and see if that helps.

Phil Hayward
thanks for the suggestion, but I only ever use IP addresses when binding the socket, so the localhost resolution in the other thread is not applicable
Simon
True but the output log says http://localhost/bst/BasicSocketTest.swfAnother way to test it to put it on a public server somewhere and test that url rather than from localhost.
Ryan Christensen
+1  A: 

You might try a few things further in the code with the Security class in addition to yoru crossdomain.xml

Try:

Security.allowDomain("*")
Security.allowInsecureDomain("*")

Or if you are loading from external servers outside the aporoved allowed host:

Security.allowDomain(loader.contentLoaderInfo.url)

Then slowly turn it back on until you hit the error.

Make sure you can hit the policy file directly and there is no block or other app running on that port. Typically when I run sockets I go higher than 5000 just to make sure nothing is using up the port. Or try a few different ports.

Also just as a simple check make sure you named it crossdomain.xml and it is all lower case. I have had programmers pull their hair out and this turned out to be the cause.

Ryan Christensen
thanks for the code suggestions, I tried adding both to my code and I get the same sandbox error. My server successfully opens 843 and 45455, so I don't have any port blocking issues. As I say in my question, the first message gets through, which wouldn't happen unless the sockets were working. Also I am not using HTTP, so crossdomain.xml is irrelevant as the player is looking for teh socket master policy file on port 843. That works and I serve an open policy file. I still get the sandbox error. http://www.adobe.com/devnet/flashplayer/articles/fplayer9_security_04.html
Simon
+1  A: 

Have you tried adding the allow-http-request-headers-from element?

<allow-http-request-headers-from domain="*" headers="*" />

Or specifying the actual ports instead of * for the allow-access-from element?

<allow-access-from domain="*" to-ports="843,45455" />
dan_nl
I tried specifying the ports without any success. The first one is not applicable since the socket policy file specification does not require the tag. Remember, I am not making HTTP requests, I am going directly against a port with a binary socket.http://www.adobe.com/devnet/flashplayer/articles/socket_policy_files.html
Simon
Here is what policyfiles.txt looks likeOK: Searching for <allow-access-from> in policy files to authorize data loading from resource at xmlsocket://192.168.2.3:45455 by requestor from http://localhost/bst/BasicSocketTest.swfWarning: Ignoring invalid <allow-http-request-headers-from> tag for domain '*' in policy file at xmlsocket://192.168.2.3:843OK: Policy file accepted: xmlsocket://192.168.2.3:843OK: Request for resource at xmlsocket://192.168.2.3:45455 by requestor from http://localhost/bst/BasicSocketTest.swf is permitted due to policy file at xmlsocket://192.168.2.3:843then 2048
Simon
That is odd about allow-http-request-headers-from since it follows the dtd and an example - http://kb2.adobe.com/cps/403/kb403185.html; that one line and specifying the actual ports helped on a previous project. This may be trivial, but have you added the local folder to the Global Security settings http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html?
dan_nl
Have you had a chance to double check the Global Security settings?http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html
dan_nl
+1  A: 

try to put a blank before xml closing tag "/>", just like in dan_nl suggestions, eg:

<allow-access-from domain="*" />

Don't laugh at it, I just solved a problem very similar to yours like this (and it really looks like a parsing bug IMHO)

Luca Bortot
thanks for the suggestion, tried it and nothing changed.
Simon
+1  A: 

By any chance... is this occurring on Windows Vista? Is the IP address specified as a host name? If so, see this.

Or maybe it's occurring while the profiler is active? If so, see this.

wallyk
Thanks, but nope, XP. Your first link was posted by @Phil Hayward too. I can't say for sure that this would no go away on the public internet and I am just about to rent a public server to try it out - an expensive bug investigation. No profiler in play.
Simon
+1  A: 

When sending the policy file, the server should always send a zero byte after policy xml. It is not clear from the description above whether the zero byte is sent, and this may confuse the Flash player eventually.

Vladimir Grigorov
I was aware of the null terminating byte and have tried it without any effect. However I tried it amidst some other changes so maybe I'll try again. Thanks for your answer.
Simon
+1  A: 

This may or may not help you but we were having similar issues. We were getting the Security error but it was inconsistent. I built the front end and worked with a developer who was dealing with the Socket written in PHP. The problem seemed to be that there was indeed a race condition where Flash would try to connect to the socket prior to receiving the Policy File. So on the front end I created a re-try in the Security error handler which would run a set number of times before giving up, also set the timeout from the default 20 seconds down to 6 or 8. It would usually catch on the 2nd try and this did help but there were times where it would take 8-10 seconds to connect, not an optimal solution.

Came across a few links in my searches and this one said something about setting up a delay on the server, 7th post down: http://projectdarkstar.com/forum/?action=printpage;topic=1134.0

In the end we downloaded and used the Python policy file server from this Adobe article and it has been working flawlessly, I can't explain why, I'm not a server guy, but it might be worth a shot:

ok, I can only post 1 hyperlink since I'm a new user, strange. Search 'Setting up a socket policy file server' and it should come right up, there are example files in that article on Adobe's site.

Duncan
this is a very useful lead, thanks very much. I'll shift my server code around a bit to try some of these things. How do you change the timeout?
Simon
hopefully your requiring Flash 10, seems that is when it was introduced:http://help.adobe.com/en_US/AS3LCR/Flash_10.0/flash/net/Socket.html#timeout
Duncan
I tried the same thing as the OP on that thread, i.e. adding a delay and making sure the socket gets closed on the server end and I get slightly different timings, but the same net result. I should have put the flash player version in the original question - thanks for pointing that out, I'll make an edit.
Simon
+3  A: 

I've been testing this locally and everything seems to be working fine until the socket gets closed. Shouldn't the socket not get closed? After the message is sent to the Flex client, the Java code does:

_in.close();
_out.close();
_socket.close();

Then the Flex client gets the sandbox violation the next time it tries to communicate with the socket. If I create a new socket connection again then send and receive works fine, followed by a close. But after a minute or so I get another sandbox violation. I wonder if Flash is trying to ping the socket and since it's closed it throws the sandbox violation?

James Ward
_in and _out are just print streams which should be closed, but _socket is the TCP socket returned by the SocketServer listening on port 843. I'll comment out all the `close`s and see what happens. Thanks very much for looking at it.
Simon
Progress! I no longer get the sandbox error, but the socket is no longer functional either, so second and subsequent messages sent through it do not get to the server. I am investigating further, but this feels like a step forwards. Thanks James.
Simon
For some reason I was still getting a close event even after I commented out the _socket.close() line. Not sure why it would close. Strange.
James Ward
A: 

I think James Ward is right--I'm working with Sockets now and I ran into this issue the other day. I found a post that suggested that if the Flash client does not close the Socket when the COMPLETE event is dispatched, this can result in the error you're seeing. I've added code to close the client Socket on COMPLETE, and everything is working fine so far.

Maciek Sakrejda
That's interesting, if a little perplexing. So do you create a new client socket for every request? I am trapping all the events that emanate from the client socket and I don't get a COMPLETE event at all - in fact I can't quite spot which event that might be, can you give the precise event detail? I process the data on a ProgressEvent.SOCKET_DATA event fired by the socket.
Simon