Spurious SecurityErrorEvent when using HttpClient

40 views
Skip to first unread message

Chadwick

unread,
Mar 24, 2009, 2:52:46 AM3/24/09
to AS3 HttpClient
I also get a SecurityErrorEvent 20sec after each HttpClient connect in
Flash 10/Air 1.5 (see http://groups.google.com/group/as3-httpclient/msg/2b8125a9edd975de
- I'm giving it it's own thread). Note that the connection works and
data is transferred fine, it's just a bogus error. For now I am
ignoring all SecurityErrorEvents, though this will hide any real
issues with the meta-socket-policy server (http://www.adobe.com/go/
strict_policy_files).

I've attached a sample which reproduces the SecurityErrorEvent with
HttpClient, but cannot reproduce it with a plain Socket sending my own
HTTP message. I assume it is an issue in HttpClient, not the Socket,
though the SecurityErrorEvent is always 20sec after initial connect,
which coincides to the Socket.timeout default value (introduced in
flash 10). I'm not using HTTPS (thus no TLSSocket), so assume the
issue is in as3httpclient, not as3crypto.

Did I miss something that might be causing the security error?

Is the 30 delay for the server to close the raw Socket interesting (or
maybe Jetty is waiting for pipelined requests)?

Should I always close HttpClient explicitly after use? When closed, my
error handler is not called, but HttpClient.close() will remove the
listeners... so maybe whatever causes the error is still happening.


Note I'm using Jetty 6.1.15 on Windows (with Cygwin). The data is
being sent chunked, explaining the two Socket.onSocketData events. I'm
using Adobe's flashpolicyd.pl to serve policyfile.xml. Hopefully
that's all irrelevant.

The examples below are from localhost (192.168.1.116 on my network),
but from a remote system gives the same results.


---------- Flexbuilder trace log ----------
[trace] 00:50:05 Clicked: Raw Socket (no close)
[trace] 00:50:05 Socket:Connecting to host: localhost, port: 80
[trace] 00:50:05 Socket:onConnect
[trace] 00:50:05 Socket:onSocketData: length=241
[trace] 00:50:05 Socket:onSocketData: length=246
[trace] 00:50:35 onClose
[trace] 00:50:40 Clicked: HttpClient (no close)
[trace] 00:50:40 HttpClient:onDataComplete: length=133
[trace] 00:51:00 HttpClient:onError: [SecurityErrorEvent
type="securityError" bubbles=false cancelable=false eventPhase=2
text="Error #2048: Security sandbox violation: file:///C:/proj/foobar/bin-debug/foobar.swf
cannot load data from localhost:80."]
[trace] 00:51:03 Clicked: HttpClient (close on data complete)
[trace] 00:51:03 HttpClient:onDataComplete: length=133
[trace] 00:51:03 HttpClient:onDataComplete: client closed

I waited but there were no further errors.

---------- Client trace log ----------
---------- ~/Application Data/Macromedia/Flash Player/Logs/
flashlog.txt ----------
[trace] 01:28:57 Clicked: Raw Socket (no close)
[trace] 01:28:57 Socket:Connecting to host: 192.168.1.116, port: 80
[trace] 01:28:57 Socket:onConnect
[trace] 01:28:57 Socket:onSocketData: length=241
[trace] 01:28:57 Socket:onSocketData: length=246
[trace] 01:29:27 onClose
[trace] 01:29:58 Clicked: HttpClient (no close)
[trace] 01:29:58 HttpClient:onDataComplete: length=133
[trace] 01:30:18 HttpClient:onError: [SecurityErrorEvent
type="securityError" bubbles=false cancelable=false eventPhase=2
text="Error #2048: Security sandbox violation: http://localhost/foobar.swf
cannot load data from 192.168.1.116:80."]
[trace] 01:31:27 Clicked: HttpClient (close on data complete)
[trace] 01:31:27 HttpClient:onDataComplete: length=133
[trace] 01:31:27 HttpClient:onDataComplete: client closed

Again, no further errors.

---------- Client policy file log ----------
---------- ~/Application Data/Macromedia/Flash Player/Logs/
policyfiles.txt ----------
OK: Root-level SWF loaded: http://localhost/foobar.swf
OK: Searching for <allow-access-from> in policy files to authorize
data loading from resource at xmlsocket://192.168.1.116:80 by
requestor from http://localhost/foobar.swf
OK: Policy file accepted: xmlsocket://192.168.1.116:843
OK: Request for resource at xmlsocket://192.168.1.116:80 by requestor
from http://localhost/foobar.swf is permitted due to policy file at
xmlsocket://192.168.1.116:843
OK: Searching for <allow-access-from> in policy files to authorize
data loading from resource at xmlsocket://192.168.1.116:80 by
requestor from http://localhost/foobar.swf
OK: Request for resource at xmlsocket://192.168.1.116:80 by requestor
from http://localhost/foobar.swf is permitted due to policy file at
xmlsocket://192.168.1.116:843
OK: Searching for <allow-access-from> in policy files to authorize
data loading from resource at xmlsocket://192.168.1.116:80 by
requestor from http://localhost/foobar.swf
OK: Request for resource at xmlsocket://192.168.1.116:80 by requestor
from http://localhost/foobar.swf is permitted due to policy file at
xmlsocket://192.168.1.116:843

---------- main mxml ----------
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute">

<mx:Script>
<![CDATA[
import mx.formatters.DateFormatter;
import org.httpclient.events.HttpDataListener;
import org.httpclient.events.HttpResponseEvent;
import org.httpclient.events.HttpListener;
import org.httpclient.HttpClient;
import com.adobe.net.URI;

private var _uri:URI = new URI("http://192.168.1.116/api/
user/c");

private var _socket:Socket = null;
private var _client:HttpClient = null;

private var _df:DateFormatter;
private function log(msg:String):void {
if (!_df) {
var df:DateFormatter = new DateFormatter();
df.formatString = "JJ:NN:SS";
}
trace("[trace] "+df.format(new Date())+" "+msg);
}

public function httpClientTest
(event:Event,closeOnDataComplete:Boolean):void {
log("Clicked: "+event.target.label);
_client = new HttpClient();
_client.get(_uri, createDataListener
(closeOnDataComplete));
}
public function rawSocketTest(event:Event):void {
log("Clicked: "+event.target.label);
connect(_uri);
}

protected function createDataListener
(closeOnDataComplete:Boolean) : HttpListener {
var listener:HttpDataListener = new HttpDataListener
();
listener.onDataComplete = function onDataComplete
(e:HttpResponseEvent, data:ByteArray):void {
log("HttpClient:onDataComplete:
length="+data.length);
if (closeOnDataComplete) {
_client.close();
log("HttpClient:onDataComplete: client
closed");
}
};
listener.onError = function onError
(error:ErrorEvent):void {
// seems using HttpClient will _always_ invoke the
onError listener
// with a SecurityErrorEvent.
log("HttpClient:onError: "+error);
};
return listener;
}


private function connect(uri:URI):void {
_socket = new Socket();
_socket.addEventListener(Event.CONNECT, onConnect);
_socket.addEventListener(Event.CLOSE, onClose);
_socket.addEventListener(IOErrorEvent.IO_ERROR,
onIOError);
_socket.addEventListener
(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
_socket.addEventListener(ProgressEvent.SOCKET_DATA,
onSocketData);

var port:int = Number(uri.port) || 80;
var host:String = uri.authority;

log("Socket:Connecting to host: " + host + ", port: "
+ port);
_socket.connect(host, port);
}

private function getHeader(uri:URI):ByteArray {
// Simple example: uri crafted for no escaping,
queries, etc...
var bytes:ByteArray = new ByteArray();
var version:String = "1.1";
var path:String = uri.path || "/";
var host:String = uri.authority;
if (uri.port) host += ":" + uri.port;

bytes.writeUTFBytes("GET " + path + " HTTP/" + version
+ "\r\n");
bytes.writeUTFBytes("Host: " + host + "\r\n");
bytes.writeUTFBytes("\r\n");
bytes.position = 0;
return bytes;
}

public function onConnect(event:Event):void {
log("Socket:onConnect");
// send the request
var headerBytes:ByteArray = getHeader(_uri);
_socket.writeBytes(headerBytes);
_socket.flush();
}
public function onSocketData(event:ProgressEvent):void {
log("Socket:onSocketData:
length="+_socket.bytesAvailable);
}
public function onClose(event:Event):void {log
("Socket:onClose");}
public function onIOError(event:IOErrorEvent):void {log
("Socket:onIOError");}
public function onSecurityError
(event:SecurityErrorEvent):void {log("Socket:onSecurityError:
"+event);}
]]>
</mx:Script>
<mx:HBox>
<mx:Button label="Raw Socket (no close)" click="rawSocketTest
(event)"/>
<mx:Button label="HttpClient (no close)" click="httpClientTest
(event,false)"/>
<mx:Button label="HttpClient (close on data complete)"
click="httpClientTest(event,true)"/>
</mx:HBox>

</mx:Application>

---------- ~/mm.cfg ----------
# Flex debugger configuration file
ErrorReportingEnable=1
# Enable flash in browser to save trace(...) messages to
# ~/Application Data/Macromedia/Flash Player/Logs/flashlog.txt
TraceOutputFileEnable=1
PolicyFileLog=1 # Enables policy file logging
PolicyFileLogAppend=1 # Optional; do not clear log at startup

---------- flashpolicy.xml served on port 843 ----------
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "/xml/dtds/cross-domain-
policy.dtd">
<cross-domain-policy>
<site-control permitted-cross-domain-policies="master-only"/>
<allow-access-from domain="*" to-ports="80,443" />
</cross-domain-policy>

gabe

unread,
Apr 14, 2009, 1:53:49 PM4/14/09
to AS3 HttpClient
Hey sorry I took so long to reply.

I have noticed the security error and haven't had too much time to
investigate. My gut feeling is that is has to do with socket timeouts
(if it only occurs after a delay of a certain amount), or perhaps
trying to start more than 1 socket at a time (perhaps there is a
restriction on the total number of open sockets), which either might
be encountered if the Socket not closing itself properly, maybe due to
a bug?

I think it may occur when dealing with connections which don't specify
a Content-Length since we have to wait for the server to close the
connection, and I have had to implement support for that in the dark
since I haven't had a chance to setup and configure a web server to
not send Content-Length yet.

Anyway, hopefully, I will get a chance to look at this soon.

On Mar 23, 11:52 pm, Chadwick <mchen...@gmail.com> wrote:
> I also get a SecurityErrorEvent 20sec after each HttpClient connect in
> Flash 10/Air 1.5 (seehttp://groups.google.com/group/as3-httpclient/msg/2b8125a9edd975de
> requestor fromhttp://localhost/foobar.swf
> OK: Policy file accepted: xmlsocket://192.168.1.116:843
> OK: Request for resource at xmlsocket://192.168.1.116:80 by requestor
> fromhttp://localhost/foobar.swfis permitted due to policy file at
> xmlsocket://192.168.1.116:843
> OK: Searching for <allow-access-from> in policy files to authorize
> data loading from resource at xmlsocket://192.168.1.116:80 by
> requestor fromhttp://localhost/foobar.swf
> OK: Request for resource at xmlsocket://192.168.1.116:80 by requestor
> fromhttp://localhost/foobar.swfis permitted due to policy file at
> xmlsocket://192.168.1.116:843
> OK: Searching for <allow-access-from> in policy files to authorize
> data loading from resource at xmlsocket://192.168.1.116:80 by
> requestor fromhttp://localhost/foobar.swf
> OK: Request for resource at xmlsocket://192.168.1.116:80 by requestor
> fromhttp://localhost/foobar.swfis permitted due to policy file at
Reply all
Reply to author
Forward
0 new messages