Unhandled Socket securityError even when (seemingly) handling it - actionscript-3

I Have a problem where I occasionally (i.e. not always) see the below error popup from the Debug Flash Player after launching my app:
Error #2044: Unhandled securityError:. text=Error #2048: Security sandbox violation: http://example.com/myApp.swf cannot load data from localhost:4499.
at org.mydomain.mypackage::MyClassUsingSocket()
at MyMainApplicationClass$cinit()
at global$init()
at global$init()
at flash.system::ApplicationDomain/hasDefinition()
at mx.managers::SystemManager/getDefinitionByName()
at _MyMainApplicationClass_mx_managers_SystemManager/create()
at mx.managers::SystemManager/initializeTopLevelWindow()
at mx.managers::SystemManager/http://www.adobe.com/2006/flex/mx/internal::docFrameHandler()
I have some code in this app that tries to connect to localhost:4499 via a Socket, and this error occurs when the socket server is not running and listening for the connections, which is to be expected. What I don't understand, however, is why Flash Player is complaining about unhandled securityErrors when I have try/catch blocks to catch the SecurityErrors when trying to connect the socket (as well as listeners for the SecurityErrorEvents, which this error message doesn't seem to point to, though).
The constructor of the relevant class is below:
/**
* Constructor.
*/
public function MyClassUsingSocket(aHost:String = null, aPort:int = -1):void
{
super();
var hostToConnectTo:String = (aHost != null) ? aHost : DEFAULT_HOST;
var portToConnectTo:int = (aPort != -1) ? aPort : DEFAULT_PORT;
try
{
_out_socket = new Socket();
// note: the event handlers used below are private functions within the same class
_out_socket.addEventListener(Event.CONNECT, _socketConnectEventHandler, false,0,true);
_out_socket.addEventListener(IOErrorEvent.IO_ERROR, _socketIOErrorEventHandler, false,0,true);
_out_socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, _socketSecurityErrorEventHandler, false,0,true);
_out_socket.connect(hostToConnectTo, portToConnectTo);
}
catch(e:IOError)
{
enabled = false;
}
catch(e:SecurityError)
{
enabled = false;
}
}
Any ideas on why this might be occurring? What am I missing?

I too struggled with this for a couple of hours. The solution is to listen for SecurityErrorEvent.SECURITY_ERROR. Apparently the SecurityError is only raised if there isn't such an event handler.

I don't think the errors that show in the dialog box are synchronous. I'm almost certain that they are thrown outside of your code path (during an async network event), so catching them with a try-catch is impossible.
So you'd think that listening for the right event on the right dispatcher would catch the error? I've tried listening to the stage, root, the object (the socket), but nothing suppresses the error.
Yep, it's pretty horrendous. I've been looking for a way to catch these little critters for a while now. The only consolation is that I think it is suppressed in the release version of the player. Still, it's cryptic huh? Not much documentation either (that I've found).
This isn't really an answer. Sorry.

This may not be the issue but you're catching SecurityError and its throwing securityError. Maybe try lowercasing the s.

Shot in the dark: try catching a generic Error?
try
{
_out_socket = new Socket();
// note: the event handlers used below are private functions within the same class
_out_socket.addEventListener(Event.CONNECT, _socketConnectEventHandler, false,0,true);
_out_socket.addEventListener(IOErrorEvent.IO_ERROR, _socketIOErrorEventHandler, false,0,true);
_out_socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, _socketSecurityErrorEventHandler, false,0,true);
_out_socket.connect(hostToConnectTo, portToConnectTo);
}
catch(e:IOError)
{
enabled = false;
}
catch(e:SecurityError)
{
enabled = false;
}
catch( e:Error )
{
trace( e );
}

Related

NetConnection unhandled NetStatusEvent

Occasionally I'm getting an unhanded NetStatusEvent when using NetConnection to connect to a Red5 server:
Error #2044: Unhandled NetStatusEvent:. level=error, code=NetConnection.Call.Failed
This is how I am connecting (the only place where NetConnection.connect() is called):
public function Connect(callBack:Function = null):void
{
if (IsConnected())
{
if (callBack != null)
{
callBack.call();
}
}
else // Not connected
{
netConnect.addEventListener(NetStatusEvent.NET_STATUS, function(e:NetStatusEvent):void
{
// OnConnect called whenever there is a net status event
OnConnect(e, callBack);
netConnect.removeEventListener(NetStatusEvent.NET_STATUS, arguments.callee);
});
try
{
// Attempt to connect to Media Server
netConnect.connect(MEDIA_SERVER_URI, true);
}
catch(error:Error)
{
logger.LogError("NetConnection.connect threw an exception.", error);
}
}
}
I am adding an event listener for NetStatusEvent.NET_STATUS. How is it possible that sometimes my listener called?
You're removing your listener in your NetStatusEvent handler. You should keep it until the connection is closed. This is why NetStatusEvent is only handled once before its listener is removed. Any other than first event will throw that error.
So remove netConnect.removeEventListener(NetStatusEvent.NET_STATUS, arguments.callee);
NetConnection dispatches that event quite a lot, depending on what is happening. You have to handle the event until every time. For a list of possible values of the info property visit this Link. There's also a little example of how to handle the event at the end of the page.
You may see this if your client does not handle the onBWCheck or onBWDone methods. This will also happen if you have bandwidth detection turned on; turn it off on the server by changing this parameter in the red5.properties file and restart the server.
rtmp.bandwidth_detection=false
Blockquote
Just an additional piece of information. Dispatching NetStatusEvent objects with info.level = "error" will always throw an Unhandled Exception. Its a special use case. I, for example, wrap all of this functionality and change the level to "info" before re-dispatching the event.

Adobe Cirrus Error on Direct Connect"Property startTransmit not found on flash.net.NetStream"

The error:
ReferenceError: Error #1069: Property startTransmit not found on flash.net.NetStream and there is no default value.
I've played around with cirrus plenty of times before and have yet to see this error before. But now I cant get it to go away.
My p2p Direct connect works great just fine. But every single time i see this error pop up. It throws an exception. I can't figure out where it's exactly happening.
Has anyone encountered this before? Any ideas where I should look?
Every client object needs to have the following functions defined.
client.stopTransmit=function($p1:*,$p2:*):void{
trace("stopTransmit called",$p1,$p2);
}
client.startTransmit=function():void{
trace("startTransmit called");
}
For example, set these in the onPeerConnect function:
sendStream.client = new Object();
sendStreamClient.onPeerConnect = function(subscriber:NetStream): Boolean{
var client:Object=new Object();
client.stopTransmit=function($p1:*,$p2:*):void{
trace("stopTransmit called",$p1,$p2);
}
client.startTransmit=function():void{
trace("startTransmit called");
}
subscriber.client=farStreamClient;
}
Additionally these need to be set on your sendStreamClient's client property:
sendStreamClient.client.stopTransmit=function($p1:*,$p2:*):void{
trace("stopTransmit called",$p1,$p2);
}
sendStreamClient.client.startTransmit=function():void{
trace("startTransmit called");
}
And they need to be set on your recieveStreamClient's client property.
On the server side script, you probably (or somebody else) have set up the application, so that it calls back a function -this time it is startTransmit-, and it isn't handled on the client side.
Remove the code from the server, or add a default value, or add a function to your code.
In my similar program, i had to add the function to my code (in my case it was not 'startTransmit') :
if ("NetConnection.Connect.Success" == e.info.code) {
netConnection.client=new Object();
netConnection.client.startTransmit=startTransmit; //no columns!
}
where startTransmit is
private function startTransmit():Boolean{
return true;
}
Are you sending h264 videos? I think it is to do with that...
If you add
public function startTransmit($p1:*,$p2:*):void{
}
public function stopTransmit():void{
}
where you have your media server connection it should work fine, at least it does for me :)
There is another netstream other than receiveStream and sendStream. You should set startTransmit and stopTransmit functions on the callerns netstream, something like this:
sendStreamClient.onPeerConnect = function(callerns:NetStream): Boolean{
var farStreamClient:Object=new Object();
farStreamClient.stopTransmit=function($p1:*,$p2:*):void{
trace("-------------farStream stopTransmit called!",$p1,$p2);
}
farStreamClient.startTransmit=function():void{
trace("-------------farStream startTransmit called!");
}
callerns.client=farStreamClient;
}
The problem is not on AMS or Red5 server. Even transmitting a video on P2P from an Android device triggers the same error.
The solution worked.
Actually the stopTransmit() sends a Boolean and an integer.
It would be amazing to know what they mean.
I have opened a bug on adobe bugbase in order to have it documented or removed.
Please vote:
https://bugbase.adobe.com/index.cfm?event=bug&id=3844856

How to handle security error and time out error of UrlLoader.load() in actionscript3?

I use UrlLoader.load() in my flash app.
And I'm handling UncaughtErrorEvent.UNCAUGHT_ERROR to stop the app when an uncaught exception occured.
UrlLoader.load() works when you are connecting the internet normally.
But if the connection to the internet was lost after your browser loaded the app,
SecurityError happens when UrlLoader.load() is called.
I can not catch the SecurityError by using try catch and UNCAUGHT_ERROR happens and it stops my app.
I don't want to stop the app when UrlLoader.load() failed because I'm just using UrlLoader.load() to log some unimportant information.
And I think timeout error also can be ocurred if it takes a long time to load.
And I also don't want to stop my app due to the time out error.
How can I solve those problems?
And are there more other type of errors which can be ocurred and stop my app?
The SecurityError exception is thrown when some type of security violation takes place.
Examples of security errors:
An unauthorized property access or method call is made across a security sandbox boundary.
An attempt was made to access a URL not permitted by the security sandbox.
A socket connection was attempted to an unauthorized port number, e.g. a port above 65535.
An attempt was made to access the user’s camera or microphone, and the request to access the device was denied by the user.
Lets say we have to load an swf from any external URL then:
// URL of the external movie content
var myRequest:URLRequest=new URLRequest("glow2.swf");
// Create a new Loader to load the swf files
var myLoader:Loader=new Loader();
// 1st level IO_ERROR input and output error checking
// Listen error events for the loading process
myLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioError);
function ioError(event:ErrorEvent):void
{
// Display error message to user in case of loading error.
output_txt.text = "Sorry that there is an IO error during the loading of an
external movie. The error is:" + "\n" + event;
}
function checkComplete(evt:MouseEvent)
{
// 2nd level SecurityError error checking
// Use the try-catch block
try
{
// Load the external movie into the Loader
myLoader.load(myRequest);
}
catch (error:SecurityError)
{
// catch the error here if any
// Display error message to user in case of loading error.
output_txt.text = "Sorry that there is a Security error during the
loading of an external movie. The error is:" + "\n" +
error;
}
}
movie1_btn.addEventListener(MouseEvent.CLICK, checkComplete);
// Listen when the loading of movie (glow.swf) is completed
myLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadMovie1);
function loadMovie1(myEvent:Event):void
{
// Display the Loader on the MainTimeline when the loading is completed
addChild(myLoader);
// Set display location of the Loader
myLoader.x = 200;
myLoader.y = 80;
}
Hope this will work for you.

Selecting Input TextField throws Security sandbox violation in loaded swf in Adobe AIR

I have a swf, loaded into the non-application sandbox in Adobe AIR 1.5 (the shell is already installed with our users so I can't update to version 2+).
On the stage in the swf are buttons, movieclips, animations etc - all of these work fine.
When we add an input TextField, selecting this TextField causes a Security Sandbox Violation.
Error message (in debug mode) is (I've edited the actual file names):
[trace] *** Security Sandbox Violation ***
[trace] SecurityDomain 'file:///path/to/local/loaded.swf' tried to access incompatible context 'app:/loadingApp-debug.swf'
The user then is unable to enter text into the TextField. The rest of the application is unaffected.
The FDB stacktrace only shows:
this = [Object 57216577, class='flash.utils::Timer'].Timer/tick() at <null>:0
Has anyone got a workaround for this?
I'm guessing it's either the TextField attempting to access the stage, or an event attempting to bubble / access global properties.
I understand the air sandbox restrictions and use them daily - with sandboxBridges from parent to child and child to parent etc - perhaps there is something I need to expose to allow this to work?
Any clues?
Edit:
I've now tracked down the problem to being that the TextField attempts to do
this.stage.focus = this;
or something equivalent when MouseDown happens.
It also appears that there is no access to KeyboardEvents in loaded swfs, so my thought of making the 'field' a button and then controlling input by listening to KeyboardEvents is dead in the water.
Now looking at whether to relay events to callbacks passed through the parent sandbox bridge, or whether minimal comps might save my butt.
Ok, I have an insane workaround, but it's pretty solid. I'm going to post it almost in full here, though I'll probably make it generic and upload it to github at some point.
In my shell, I have a view-with-mediator (I'm using robotlegs) which I'm calling EventRelayer and EventRelayerMediator.
The view's only purpose is to give the mediator access to the stage.
I exposed some functions on the parentSandboxBridge:
public function requestKeyboardEventRelay(eventType:String, callback:Function):void;
public function requestMouseEventRelay(eventType:String, callback:Function):void;
public function cancelKeyboardEventRelay(eventType:String, callback:Function):void;
public function cancelMouseEventRelay(eventType:String, callback:Function):void;
My sandbox bridges always just translate into strong typed events, so these fire events like:
RelayEvent(RelayEvent.START_RELAY_REQUESTED, KeyboardEvent, eventType, callback);
RelayEvent(RelayEvent.CANCEL_RELAY_REQUESTED, MouseEvent, eventType, callback);
These are picked up by the EventRelayerMediator, and translated into handlers in an eventMap:
override public function onRegister():void
{
createRelayHandlerFactories();
eventMap.mapListener(eventDispatcher, RelayEvent.START_RELAY_REQUESTED, startRelay);
}
protected function startRelay(e:RelayEvent):void
{
var handler:Function = createRelayHandler(e.relayEventClass, e.callback);
eventMap.mapListener(view.stage, e.relayEventType, handler, e.relayEventClass);
}
protected function createRelayHandler(relayEventClass:Class, callback:Function):Function
{
var handler:Function = relayHandlerFactoriesByEventClass[relayEventClass](callback);
return handler;
}
protected function createRelayHandlerFactories():void
{
relayHandlerFactoriesByEventClass = new Dictionary();
relayHandlerFactoriesByEventClass[KeyboardEvent] = createKeyboardEventRelayHandler;
relayHandlerFactoriesByEventClass[MouseEvent] = createMouseEventRelayHandler;
}
protected function createKeyboardEventRelayHandler(callback:Function):Function
{
var handler:Function = function(e:KeyboardEvent):void
{
trace("Relaying from shell: " + e.toString());
// passing an object because the sandbox bridge doesn't allow strong typed values, only primitives
var o:Object = {};
o.type = e.type;
o.charCode = e.charCode;
o.keyCode = e.keyCode;
o.altKey = e.altKey;
o.ctrlKey = e.ctrlKey;
o.shiftKey = e.shiftKey;
// no point adding other props as we can't pass them
// to the constructor of the KeyboardEvent
callback(o)
}
return handler;
}
The loaded swf passes a callback which just re-assembles and re-dispatches the events.
My input TextField is now just a dynamic field with a click handler that activates listening for keyboard events on the root of the swf, and then updates the dynamic field accordingly.
At the moment that is super-crude but I'll break it out into a robust, tested class now I know it works.
I've used a dictionary to manage the handlers because I'm sure that memory leakage hell is about to follow and I'm expecting to have to relay the FocusEvents to stop entering text.
I need to test memory leakage, return a binding from the parentSandboxBridge function so that I can make sure I don't add the same handler twice etc etc, but Adobe - you suck for not calling this out and providing a built in relay mechanism.

Socket error - sometimes?

so - I have this Socket (not XMLSocket, just Socket) client. I also have a custom PHP script on my server, that listens on port X. My client tries to connect to it.
Everything works fine, the security and communication, sync and whatever else. But - the Flash Player (AIR runtime actually) shoots an error when trying to connect, but ONLY when the server is not running... What? It is really weird - the error is actually handled by try catch (IOError), and even weirder, the line that is specified in the output as the error line is the line where I just CREATE the Socket...?
Hm...
Output:
Error #2044: Unhandled IOErrorEvent:. text=Error #2031: Socket Error.
at ---.server::Client()[---/server/Client.as:167]
at Function/<anonymous>()[---_fla.MainTimeline::frame1:430]
at Function/<anonymous>()
at Function/<anonymous>()[---_fla.MainTimeline::frame1:375]
Code:
try {
Sock = new Socket(); // THIS is line 167
} catch (e:IOError){
log("Could not connect!");
status = "disconnected";
}
It does not really matter - the server is supposed to be still online, the errors won't show up... But ignoring an error is not good.
One more thing: when I comment out the line where I actually connect using Sock.connect(...) - it does not throw the error, but it obviously does not work... Also, the connect part is also in try catch (IOError) block...
WHY does Flash say the problem is on line 167 when it is obviously elsewhere? And / or what can be the problem?
This might not seem obvious if you had not worked with Flash previously, but many Errors in the net api are asynchronous. Meaning, you cannot catch them with a catch block, because the error is not thrown when you execute the connect method, but at a later point.
In fact, the error message says you have an uncaught IOErrorEvent not an IOError.
This is covered here:
http://www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/flash/net/Socket.html#connect()
Basically, you have to add a handler for the IOErrorEvent (adding one for SecurityErrorEvent is a good idea as well). Something like this:
private function connect():void {
socket = new Socket(host,port);
// handle asynchronous errors in these handlers
socket.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
try {
socket.connect();
} catch(ioError:IOError) {
// handle synchronous errors here
} catch(secError:SecurityError) {
// and here
}
}
private function ioErrorHandler(event:IOErrorEvent):void {
trace("ioErrorHandler: " + event);
}
private function securityErrorHandler(event:SecurityErrorEvent):void {
trace("securityErrorHandler: " + event);
}
I came across a similar error. It was occurring because I had removed the handler ioErrorHandler (removeEventListener) before issuing a sock.close(). sock.close() can throw an IoErrorEvent.
Even though the ioErrorEvent was thrown by sock.close(), the debugger showed it as unhandled error at the line where the socket constructor was called.
Calling the removeEventListener() after the sock.close() solved the problem.
Hope this helps.
I got the error in the same situation with wizard, and fixed it by change the order of close and remove event listener.