Capturing client parameters in a Red5pro application

Capturing parameters passed from client to Red5pro server application is a very simple and useful step if you wish to capture data from the client on connection for authentication, validation etc:.

When working with Red5pro, you have different types of clients that can connect to Red5pro – Flash(RTMP), Android/IOS(RTSP), and HTML5(RTC) clients. Each client transmits parameters in a different way. Hence for proper handling, it is recommended to check the client connection type and then devise your parameter collection logic.

In this article, we shall see how to build a simple logic that checks for client type and extract connection parameters accordingly. The recommended parameters capturing point is the appConnect method of your application adapter class. This is the method which gets invoked when a compatible client tried to connect to Red5pro.


PASSING PARAMETERS FOR RTMP CLIENTS (PASSED IN VIA QUERY STRING IN RTMP URL)

An RTMP client can send parameters through the connect method (as an array) or via the query string (as name value params).

var nc:NetConnection = new NetConnection();
nc.connect("rtmp://localhost/live?param1=value1&param2=value2");

CAPTURING PARAMETERS FOR RTMP CLIENTS (PASSED IN VIA QUERY STRING IN RTMP URL): ON CONNECT

@Override
public boolean appConnect(IConnection conn, Object[] params)
{
      IConnection connection = Red5.getConnectionLocal();
      Map<String, Object> map = getParametersMap(connection.getConnectParams());
      return super.appConnect(conn, params);
}

private Map<String, Object> getParametersMap(Map<String, Object> content)
{
  Map<String, Object> map = new HashMap<String, Object>();
  Iterator<Entry<String, Object>> it = content.entrySet().iterator();
  while (it.hasNext())
  {
    Map.Entry<String, Object> pair = it.next();
    String key = pair.getKey();
    Object value = pair.getValue();

    if(key.equals("queryString"))
    {
      Map<String, Object> qmap = new HashMap<String, Object>();
      String[] parameters = String.valueOf(value).split("&");
      for(int i = 0; i<parameters.length;i++)
      {
        String[] param = String.valueOf(parameters[i]).split("=");
        String name = param[0];
        if(name.indexOf("?") == 0) name = name.replace("?", "");
        String val = param[1];
        qmap.put(name, val);
      }

      map.putAll(qmap);
    }

    map.put(key, value);
  }

  return map;

}

PASSING PARAMETERS FOR RTSP CLIENTS (THROUGH RED5PRO SDK)

An Android/IOS, the client can send parameters through the official SDK to the Red5pro server application. An example is provided in the public github repository containing test-examples

CAPTURING PARAMETERS FOR RTSP CLIENTS (PASSED VIA SDK): ON CONNECT

@Override
public boolean appConnect(IConnection conn, Object[] params)
{
  IConnection connection = Red5.getConnectionLocal();
  Map<String, Object> map = new HashMap<String, Object>();
  for(int i = 0; i<params.length;i++)
  {
    String[] param = String.valueOf(params[i]).split("=");
    map.put(param[0], param[1]);
  }

  return super.appConnect(conn, params);
}

PASSING PARAMETERS FOR WEBRTC CLIENTS (THROUGH RED5PRO HTML5 SDK)

Sample configuration object used to initialize the WebRTC publisher client. The snippet is taken from the Red5pro server distribution ‘live’ app.

var baseConfiguration = {
    host: window.targetHost,
    app: 'live',
    iceServers: iceServers,
    bandwidth: desiredBandwidth,
    connectionParams: {param1:"<value-1>", param-n:"value-n"}
  };

CAPTURING PARAMETERS FOR WebRTC CLIENTS (PASSED VIA RED5PRO HTML5 SDK): ON CONNECT

@Override
public boolean appConnect(IConnection conn, Object[] params)
{
  IConnection connection = Red5.getConnectionLocal();
  Map<String, Object> map = getParametersMap(connection.getConnectParams());

  return super.appConnect(conn, params);
}


private Map<String, Object> getParametersMap(Map<String, Object> content)
{
  Map<String, Object> map = new HashMap<String, Object>();

  Iterator<Entry<String, Object>> it = content.entrySet().iterator();
  while (it.hasNext())
  {
    Map.Entry<String, Object> pair = it.next();
    String key = pair.getKey();
    Object value = pair.getValue();

    if(key.indexOf("?") == 0) key = key.replace("?", "");
    map.put(key, value);
  }

  return map;
}

Now that we know how to capture parameters for each connection type using the appConnect handler it is time to aggregate the code snippets in one place so that we can check for client type and extract parameters, depending on client type in one place. As we have been discussing till now Red5pro currently supports three types of connections that are registered as streaming connection types – RTMP, RTSP and RTC.

So inside our appConnect handler, we shall now write an aggregated approach which checks and collects parameters from a Red5pro connection on connect event and stores it inside a java Map Object.

AGGREGATED LOGIC TO EXTRACT PARAMETERS FROM A RED5PRO CONNECTION

static String RTSPCONNECTION = "com.red5pro.server.stream.rtsp.RTSPMinaConnection";

static String RTMPCONNECTION = "org.red5.server.net.rtmp.RTMPMinaConnection";

static String RTCCONNECTION = "com.red5pro.webrtc.RTCConnection";

public boolean appConnect(IConnection conn, Object[] params)
{
  IConnection connection = Red5.getConnectionLocal();
  String connectionClassName = connection.getClass().getCanonicalName();
  Map<String, Object> params;

  if(connectionClassName.equalsIgnoreCase(RTMPCONNECTION))
  {
    params = getRTMPParameters(connection.getConnectParams());
  }
  else if(connectionClassName.equalsIgnoreCase(RTSPCONNECTION))
  {
    params = getRTSPParameters(params);
  }
  else if(connectionClassName.equalsIgnoreCase(RTCCONNECTION))
  {
    params = getRTCParameters(connection.getConnectParams());
  }

  return super.appConnect(conn, params);
}

private Map<String, Object> getRTCParameters(Map<String, Object> content)
{
  Map<String, Object> map = new HashMap<String, Object>();

  Iterator<Entry<String, Object>> it = content.entrySet().iterator();
  while (it.hasNext())
  {
    Map.Entry<String, Object> pair = it.next();
    String key = pair.getKey();
    Object value = pair.getValue();

    if(key.indexOf("?") == 0) key = key.replace("?", "");
    map.put(key, value);
  }

  return map;
}

private Map<String, Object> getRTSPParameters(Object[] params)
{
  Map<String, Object> map = new HashMap<String, Object>();
  for(int i = 0; i<params.length;i++)
  {
    String[] param = String.valueOf(params[i]).split("=");
    map.put(param[0], param[1]);
  }
}

private Map<String, Object> getRTMPParameters(Map<String, Object> content)
{
  Map<String, Object> map = new HashMap<String, Object>();
  Iterator<Entry<String, Object>> it = content.entrySet().iterator();
  while (it.hasNext())
  {
    Map.Entry<String, Object> pair = it.next();
    String key = pair.getKey();
    Object value = pair.getValue();

    if(key.equals("queryString"))
    {
      Map<String, Object> qmap = new HashMap<String, Object>();
      String[] parameters = String.valueOf(value).split("&");
      for(int i = 0; i<parameters.length;i++)
      {
        String[] param = String.valueOf(parameters[i]).split("=");
        String name = param[0];
        if(name.indexOf("?") == 0) name = name.replace("?", "");
        String val = param[1];
        qmap.put(name, val);
      }

      map.putAll(qmap);
    }

    map.put(key, value);
  }

  return map;

}
No Comments - Leave a comment

Leave a Reply

Your email address will not be published. Required fields are marked *

*