Expand my Community achievements bar.

Learn about Edge Delivery Services in upcoming GEM session

This bug has been around for over a year: SecurityError: Error #2123: Security sandbox violation

Avatar

Level 2

Hi,

The bug of 'SecurityError: Error #2123: Security sandbox violation: BitmapData.draw: file:///xxx/xxx.swf cannot access rtmfp://fms4.acrobat.com/cocomo/na2-sdk-xxx/xxx. No policy files granted access.' was first reported in lccs forum over a year ago:

http://forums.adobe.com/message/2803074

But the bug is still around. The bug can be generated by calling BitmapData.draw() on a flash.media.Video object which is attached to a p2p stream. It looks like the solution is to have the publisher to call:

send("|RtmpSampleAccess", true, true)

on the NetStream object _before_ the subscriber calls NetStream.play(), in order to give the permission to subscribers for audio and video streams.

In lccs library, the above permission authorisation happens in WebcamPublisher:

protected function onNetStatus(p_evt:NetStatusEvent):void

{

if (p_evt.info.code=="NetStream.Connect.Success") {

setTimeout(sendSnapShotPermission, 500);

_stream.send("|RtmpSampleAccess", true, true);

}

}

protected function sendSnapShotPermission():void

{

_stream.send("|RtmpSampleAccess", true, true);

}

but it doesn't help the problem. In fact, it is not clear to me when this 'snap shot permission' is sent to the subscriber.

One more note: This is not a critisism for the lccs development quality, but rather a question on how ready lccs is for production use. After encountering this bug, I had to go through the lccs code (the open source parts), and found out that the library is not really written, well, carefully, and it is full of temporary quick-n-dirty fixes.

For instance in the above example, sendSnapShotPermission() is called after 500 milliseconds, probably to allow something to happen before calling the method, but how can you be sure that it will happen in 500 milliseconds? Probably,an event listener should have been used. Immediately in the next line, we see:

_stream.send("|RtmpSampleAccess", true, true);

which is a duplicate of sendSnapShotPermission(). many examples like this can be found throughout the library.

Aureliano

10 Replies

Avatar

Former Community Member

Hi there,

To the best of my knowledge, this bug was fixed - can you give more precise

steps to reproduce? If it's still reproduced, there's likely still some

tricky timing case.

I don't want to criticize you (you can always tell when someone starts a

sentence this way, they're about to say something indelicate), but based on

your post I'd suggest that you don't really understand the code well enough

to critique it - which event listener would you need to listen to to make

this work? There's actually a pretty good reason why the message is sent on

a regular interval. Can you tell me what it is? And please, if you're

looking for help from us, try to refrain from insulting us in the same post.

respect

nigel

Avatar

Level 2

Hi Nigel,

Two questions:

1. When the publisher sends the access permission to the subcriber by:

netStream.send("|RtmpSampleAccess", true, true)

, on the subscriber side, what event or function can handle the guaranteed receipt of the access permission? Currently it is possible to draw the incoming stream video upon receiving NetStream.Play.Star and waiting for 5 seconds or so:

public class MyWebcamSubscriber extends WebcamSubscriber {

override protected function layoutCameraStreams():void

{

// trying the event listener seems to work here.

_streamManager.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);

}

override protected function onNetStatus(e:NetStatusEvent):void

{

super.onNetStatus(e);

case "NetStream.Play.Start":

setTimeout(function():void {

// draw the video from the incoming stream here.

}, 5000);

}

}

The questions is, which event can let the subscriber know that it has the access permission to the video stream?

2. In WebcamPublisher, why is that the access permission is sent 3 times?

a. Once on receiving NetStream.Connect.Success with 0.5 second delay, as in below.

b. Once immediately upon receiving NetStream.Connect.Success, as in below.

protected function onNetStatus(p_evt:NetStatusEvent):void

{

if (p_evt.info.code=="NetStream.Connect.Success") {

setTimeout(sendSnapShotPermission, 500);

_stream.send("|RtmpSampleAccess", true, true);

}

}

protected function sendSnapShotPermission():void

{

_stream.send("|RtmpSampleAccess", true, true);

}

c. Once in onConnectionTypeChange() with 2 seconds delay:

protected function onConnectionTypeChange(p_evt:StreamEvent):void

{

//...

if ( _streamManager.isP2P) {

_stream= new NetStream(_connectSession.sessionInternals.session_internal::connection as NetConnection,NetStream.DIRECT_CONNECTIONS);

setTimeout(sendSnapShotPermission, 2000);

     }

//...

}

Avatar

Level 2

Any updates on the above two questions?

Avatar

Level 2

Could someone from the lccs team address the above 2 questions.

Avatar

Level 2

A week later, still waiting for a response about the above 2 questions.

Avatar

Former Community Member

In all seriousness, could you answer my original question - how are you

reproducing this issue? The more precise the better. I've just done a quick

test, and was able to get a snapshot working. There must be some timing

element here - anything you can do to narrow it down would be appreciated.

nigel

Avatar

Level 2

I tried to answer that question in my previous post, I explain it here again. Consider this subclass of WebcamSubscriber:

public class MyWebcamSubscriber extends WebcamSubscriber {

override protected function onNetStatus(e:NetStatusEvent):void

{

super.onNetStatus(e);

     case "NetStream.Play.Start":

          var t:int = 5000;

          setTimeout(function():void {

               // draw the video from the incoming stream here, using BitmapData#draw()

          }, t);

}

}

In the above, if you decrease t to 0, you'll get the security sandbox violation error.

You need to use BitmapData#draw() to get the error. The VideoComponent class does not seem to call this method explicitly.

Maybe it's a good idea to define and dispatch a snapshot permission event after:

_stream.send("|RtmpSampleAccess", true, true);

so that calling BitmapData#draw() can be done with more confidence, rather than trying an ad hoc timeout.

Avatar

Level 2

Nigel: any updates on the above two questions?

Avatar

Former Community Member

Hi,

Not sure what your answer to my question is - you say that if you mess with

the code, you get the error? I realize you need to do a BitmapData.draw -

I'm asking when are you calling this? Decreasing the interval to 0 means

that the permissions message will never get received, so, yeah, you'll hit

the error.

Here's the deal (I honestly don't know why I'm helping here) - for each

subscriber, they need to receive the permissions message AFTER they connect

to the stream but BEFORE they take a snapshot. To accomplish this, we have

the publisher send a regular permissions message on a 5s interval - this

does mean that there's a window of time where the stream is connected but

not snapshot-ready. An easy way to workaround the issue is to use a

try-catch block around your BitmapData.draw, and, should it catch the error,

try again in a few seconds.

I'll try to preempt your complaint here : yes, there's a way you could make

this more precise. You could have each subscriber send a message to the

publisher each time a subscriber connects to the stream. That message would

tell the publisher to please send the permissions message to the new

subscriber. Upon doing so, the publisher could then send another message to

the subscriber to tell it that it has done so. When the subscriber receives

the message, it could dispatch an event notifying the dev that Bitmap

capture is now enabled. But ultimately, this is a fairly intricate piece of

coordination, and would likely introduce even further timing issues and

bugs. And at the end of the day for the dev, doing a try-catch solution

isn't a significant amount more work than waiting for an event to declare

the stream is ready (they're both asynchronous, ultimately). We considered

both solutions, and opted for the simpler one.

hope that helps

nigel