Howto reject connections while playing streams

We have an issue rejecting streaming connections to Wowza. Our validation of the connection happens in the IMediaStreamActionNotify2.onPlay() function. The rejection is executed using stream.getClient().setShutdownClient(true). The problem is that the client (FlowPlayer 3.2.5) doesn’t get notified that the connection is shut down. The player is therefore acting as if the connection is still being established. We would like to send a http-errorcode, just like the case when a missing file is rejected (errorcode 201).

We have tried sending messages using:

  • sendClientOnStatusError(client, code, description);

  • stream.getClient().getAppInstance().broadcastMsg(clients, “onStreamCreate: broadcastMsg(…)”);

  • sendClientOnStatusError(client, “onConnect”, “Hello World!”);

  • sendResult(client, params, string)

But none of them gave any result at the client side.

Is there any way to notify the player (and the user) that the connection was rejected?

how about

[php]

client.rejectConnection("Connection Rejected : ");

[/php]

You can send notification codes, the standard messages that most player process, at least the basic ones. Like this:

sendClientOnStatusError(client, "NetConnection.Connect.Rejected", "You were disconnected, sorry");

It will work anywhere in a application module that you have access to the client. Any function with a IClient or IMediaStream param.

Richard

It’s not a good idea to close the stream server-side. The client should close it.

Richard

interesting as I have

[php]

public void play(IClient client, RequestFunction function, AMFDataList params) {

getLogger().info("Play called for client id was "+client.getClientId());

client.rejectConnection(“Secure connection required.”);

client.shutdownClient();

}

[/php]

I do always add a shutdown anyway, but the reject should work for play.

Does the above still allow clients to connect and play ?

Shamrock

just basic module instance, no listener etc, but this does only work for rtmp. Yes the PHP stated by the forums I just put those tags around it so it stands out better. I have been told that setShutdownClient(true) is the best way to close a client as well, so this may do what you need.

[php]

package uk.org.shamrock.test;

import com.wowza.wms.application.*;

import com.wowza.wms.amf.*;

import com.wowza.wms.client.*;

import com.wowza.wms.module.*;

import com.wowza.wms.request.*;

import com.wowza.wms.stream.*;

import com.wowza.wms.rtp.model.*;

import com.wowza.wms.httpstreamer.model.*;

import com.wowza.wms.httpstreamer.cupertinostreaming.httpstreamer.*;

import com.wowza.wms.httpstreamer.smoothstreaming.httpstreamer.*;

public class PlayJingle extends ModuleBase {

public void doSomething(IClient client, RequestFunction function,

AMFDataList params) {

getLogger().info(“doSomething”);

sendResult(client, params, “Hello Wowza”);

}

public void onAppStart(IApplicationInstance appInstance) {

String fullname = appInstance.getApplication().getName() + “/”

  • appInstance.getName();

}

public void play(IClient client, RequestFunction function, AMFDataList params) {

getLogger().info("Play called for client id was "+client.getClientId());

client.rejectConnection(“Secure connection required.”);

client.setShutdownClient(true);

}

public void onAppStop(IApplicationInstance appInstance) {

String fullname = appInstance.getApplication().getName() + “/”

  • appInstance.getName();

getLogger().info("onAppStop: " + fullname);

}

public void onConnect(IClient client, RequestFunction function,

AMFDataList params) {

getLogger().info("onConnect: " + client.getClientId());

}

public void onConnectAccept(IClient client) {

getLogger().info("onConnectAccept: " + client.getClientId());

}

public void onConnectReject(IClient client) {

getLogger().info("onConnectReject: " + client.getClientId());

}

public void onDisconnect(IClient client) {

getLogger().info("onDisconnect: " + client.getClientId());

}

}

[/php]

Shamrock

the only thing I can think of is do you have a listener in the client code to check for errors ? as this may be why the client is not seeing them ?

Shamrock

i’ll put together a Flash client and try and reproduce and error code and get back you. It will be later today at some point.

Shamrock

after much testing with all sorts of rejection methods, and a somewhat limited knowledge of what could be sent back in the AMF structure, the best method to send a ‘Custom’ message would be to use a

[php]

client.call(“msgFromSrvr”,null,“your message here”);

[/php]

function.

The client side code would look something like this

[php]

function msgFromSrvr(msg:String):void

{

debuger.appendText(“Status: “+msg+”\n”);

}

[/php]

You could then call this prior to disconnecting someone when they attempt to play an asset.

As a further observation point

[php]

client.shutdownClient();

[/php]

appears to be the cleanest from the client side for disconnecting and should make the client aware of the disconnection. I have tested this with the JWPlayer and appears to stop the Spinning Connection wheel, other methods although disconect the client do not do this.

Hope this helps a little.

Shamrock

I think the problem you are encountering is that the Flash Players, such as JW and FlowPlayer have ‘standard’ messages built in for certain events, such as Failed to connect, File Not Found etc, so if you want to add a custom message you will need to change the Flash Client code.

Both JW Player and FlowPlayer offer a plugin system so you could write a very small plugin to handle message sent from the server to the client.

Shamrock

Thank you for the quick response.

We have tried it, but without success in the onPlay() event. My guess is that It only works in the IModuleOnConnect.onConnect() event. In the onPlay event, the rejectConnection is completely ignored and the stream is played as if nothing happened.

Interesting. I assume that it is an error that the box states PHP-code, and that it is actually plugin-code written in Java.

To fully understand the code, I need som context. Which interface are you using when implementing the play() method? We use the IMediaStreamActionNotify2.onPlay() function, which reacts on stream events (play, pause, stop, etc.). The implementation of IMediaStreamActionNotify2 interface is registered as a client listener on the stream in the onStreamCreate event. Does something similar happen with the play() method?

-Henning

Thank you for the clarification. I have tested the code, but get the same result as in our original setup. The server disconnects the stream, but the client doesn’t get notified that the conenction has been closed.

The only way that we have succesfully notified the client that it has been disconnected is by calling the client.rejectConnection from the onConnect event. Then the client gets the message: “Connection failed: Application rejected connection.” (in the SimpleVideoStreaming example), which is the desired behavior.

The person that is responsible for our client has the following comment:

“We are using Flowplayer as our client and using Flowplayers ‘onError’ error handler object. If e.g. we try to connect with a wrong URL to Wowza or a wrong filename we will get a response with errorcode 201 and Flowplayers debug log will show a ‘connection rejected’ error. All this is picked up by Flowplayers error-handler and we can act on it but we can’t seem to get our “own rejections” to show op as error codes or messeges in the log.”

The Wowza simplevideostreaming.html example has the same behavior as Flowplayer. This suggests that it is a general issue, and not only for Flowplayer.

Shamrock, do you see messages from your client, when the client connection is rejected from the play method? If so, which flash-client are you using?

Great service. That would be really great and we look forward to hear the result. We sincerely hope that your experiments are successful!

Henning

Interesting. I assume that the client code is flash-code and not javascript. We will test it and get back to you as soon as possible. But it will not be before the weekend.

Hi Shamrock

We have looked the proposed solution and it seems like a solution that could work in our context. The solution has one drawback, in that the flash client has to be altered and thereby distancing us from the standard client (in our concrete case, Flowplayer). We would prefer a solution that consist of standard components with plugins, rather than change and recompile whole components. When using standard components, it is easier to search for help and components can to some extent easily be interchanged. Furthermore, when using standard components with a plugin mechanism, the risc of errors are kept to a minimum.

My knowledge of the streaming flash-client framework or interface is rather limited. So I don’t know if it is actually possible to implement a standardized error handling solution between a streaming server and a flash client. Do you know if the flash streaming framework supports it and if Wowza will support it in the future?

Sincerely, Henning

Shamrock. That matches our experience with the client. Only the basic low level events from Wowza that are not in the plugin event loop, are signaled by the client (except for connectionReject). Sounds like we probably have to write plugins to the flash client if we want the user the experience we aim for.

Richard. We have already tried the sendClientOnStatusError (see initial posting). I tried it again though, using Wowzas SimpleVideoStreaming client (out of the box). Still I do not get any message through to the client. (Called from IMediaStreamActionNotify2.onPlay event). I do not have experience writing flash-code or using flash-players, so I only check for responses that are visually presented in the browser. I suspect that the client has to be augmented with additional code to get the message through to the user, just as Shamrock points out. Does the sendClientOnStatusError message get presented to the user in the SimpleVideoStreaming example (out of the box) in your setup?

Henning

If you do this first wouldn’t help?

if(appClient.getPlayStreams().size() == 1) {
  IMediaStream stream = (IMediaStream) appClient.getPlayStreams().get(0);
  stream.close();
}