• No results found

Creating a Custom Module

What is a Wowza Media Server Pro Custom Module?

his chapter describes in detail how custom server side modules work. A server side module is a Java Archive (jar) file that encapsulates a set of functionality that is dynamically linked into the server at runtime. All modules must be compiled and built using a Java Development Kit (JDK) version 5 (aka 1.5) or greater. Wowza Media Systems provides an Eclipse based integrated development environment called the Wowza IDE that automates much of the process of creating a server side module.

Getting Started

The first tool you need for Java development is a Java Development Kit (JDK) version 5 (aka 1.5) or greater. This kit can be obtained from the Sun website at http://java.sun.com/javase/downloads. Next, you will need the Wowza IDE. The Wowza IDE can be downloaded from the Wowza Labs page at http://www.wowzamedia.com/labs.html. The “Creating a Wowza Media Server Pro Module”

chapter of the Wowza IDE: User’s Guide is a great starting point for learning how to create your first server side module.

Note

Before you read the rest of this chapter it might be a good idea to browse Wowza Media Server Pro javadocs to get a feel for the server side API. These Java docs can be opened from the

“Start” menu by selecting “Wowza Media Server Pro>Documentation>Server Side API”.

Note

Debug logging is useful during module development to debug module and method loading issues.

To turn on debug logging, edit your conf/log4j.properties file and change the log level (in the first configuration property) from “INFO” to “DEBUG”.

Chapter

7

T

Module Basics

A server side module is Java Archive or jar file that contains a set of classes. These classes are dynamically loaded at runtime based on settings in Wowza Media Server Pro’s configuration files.

A module (or jar file) is made available to the server by placing it in the “[install-dir]/lib” directory of the Wowza Pro server.

A single module or jar file can expose multiple module classes. A module class is a public class that extends the com.wowza.wms.module.ModuleBase abstract class. A new module class instance is created for each application instance that is started by the server. So if you define a module for the application “myapplication” and two clients connect to the server with the following connection strings:

rtmp://localhost/myapplication/instance1 rtmp://localhost/myapplication/instance2

Two instances of your module class will be instantiated. One for each application instance. All class level properties will be unique to each application instance.

The public methods defined for a module class define the classes interface to the player client.

There are three types of public methods that are callable by the server and/or the Flash player client: event methods (onApp, onConnect and onStream), custom methods and the onCall method. Each is described below:

Event Methods (onApp, onConnect and onStream)

Event methods are invoked by the server based on events that occur during server processing.

There are three sets of event methods; onApp, onConnection and onStream. Each of these sets are represented by an interface class in the server side API; IModuleOnApp, IModuleOnConnect and IModuleOnStream. All event methods defined in all modules are invoked when an event occurs. What this means is that if two modules implement the onAppStart event method, then both modules onAppStart methods will be invoked when a new application instance is created.

Module methods are invoked starting at the bottom of the <Modules> list defined in Application.xml. So the last <Modules> entry in the list will be called first and it will work its way up to the first item in the list.

IModuleOnApp

public abstract void onAppStart(IApplicationInstance appInstance);

public abstract void onAppStop(IApplicationInstance appInstance);

onAppStart: Invoked when an application instance is started onAppStop: Invoked when an application instance is stopped

IModuleOnConnect

public abstract void onConnect(IClient client,

RequestFunction function, AMFDataList params);

public abstract void onDisconnect(IClient client);

public abstract void onConnectAccept(IClient client);

public abstract void onConnectReject(IClient client);

onConnect: Invoked when a Flash player connects to an application instance

onDisconnected: Invoked when a Flash player disconnect from an application instance onConnectAccept: Invoked when a Flash player connection is accepted

onConnectReject: Invoked when a Flash player connection is refused

IModuleOnStream

public abstract void onStreamCreate(IMediaStream stream);

public abstract void onStreamDestroy(IMediaStream stream);

onStreamCreate Invoked when a new IMediaStream object is created : onStreamDestroy: Invoked when a IMediaStream object is closed

Note

The onStreamCreate event method is invoked before “play” or “publish” has been called for this IMediaStream object. For this reason the IMediaStream object does not have a name. See the IMediaStreamActionNotify2 interface to implement a server listener that is invoked when actions occur on this IMediaStream object.

To implement one of these interfaces, you can either use the Java “implements” keyword followed by a comma delimited list of interfaces that you wish to implement or you can simply use the interface definitions as a reference for your method signatures and define them in your class as public methods. Below is a sample class that implements the IModuleOnApp methods.

package com.mycompany.module;

import com.wowza.wms.module.*;

import com.wowza.wms.client.*;

import com.wowza.wms.amf.*;

import com.wowza.wms.request.*;

public class MyModule extends ModuleBase implements IModuleOnApp {

public void onAppStart(IApplicationInstance appInstance) {

getLogger().info(“onAppStart”);

}

public void onAppStop(IApplicationInstance appInstance) {

getLogger().info(“onAppStop”);

} }

Note

Use the IModuleOnConnect interface to authenticate client connections. To setup authentication edit your application’s Application.xml file and set Connections/AutoAccept to false. Next, in your applications server side module implement the IModuleOnConnect interface. Finally, in the onConnect event method you can validate the client connection by inspecting any extra parameters sent to the server from the client as part of the call to NetConnection.connect(). To accept/reject the client connection call client. acceptConnection() or client.rejectConnection().

Custom Methods

Custom methods are server side Java methods that you want to expose to the Flash player client through calls to the NetConnection.call() or are call that are part of the NetConnection or NetStream command set. For example “play” and “publish” are defined in ModuleCore as custom methods. These methods must be public and must have the following argument signature (IClient, RequestFunction, AMFDataList params). Only public methods with this signature will be available to be called from the client.

Processing for custom methods is different than that of event methods. When a given method such as “play” is invoked from the Flash player only the last module in the <Modules> list that defines that custom method will be invoked. For example the ModuleCore module defines the method “play” which is invoked when NetStream.play(streamName) is called from the Flash player. If you create your own custom module that defines the method “play” and add it to the

<Modules> list after the ModuleCore module, then your “play” method will be invoked rather than the “play” method defined in ModuleCore. If in your implementation of “play” you wish to invoke the “play” method of the next module up the list that precedes your module, you can call

“this.invokePrevious(client, function, params)”. Wowza Pro will search up the module list and find the next module that implements the “play” method and it will invoke that method in that module. This provides a means to create an adhoc stack of methods. Each implementation of a method in the <Modules> list can perform an operation based on the invocation of a given method and can choose to pass control to the next module that implement that method above them in the <Modules> list.

For example if in your implementation of “play” you wish to check the stream name of any calls made to NetStream.play(streamName). If the stream name starts with “goodstream/” you wish to append the phrase “_good” to the stream name and call “this.invokePrevious(client, function, params)”. All other connections will be disconnected. The code looks like this:

package com.mycompany.module;

import com.wowza.wms.module.*;

import com.wowza.wms.client.*;

import com.wowza.wms.amf.*;

import com.wowza.wms.request.*;

public class MyModule extends ModuleBase {

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

boolean disconnect = false;

if (params.get(PARAM1).getType() == AMFData.DATA_TYPE_STRING) {

String playName = params.getString(PARAM1);

if (playName.startsWith("goodstream/")) {

playName += "_good";

params.set(PARAM1, new AMFDataItem(playName));

}

this.invokePrevious(client, function, params);

} }

onCall

The onCall method is a catch-all for any methods that are undefined by custom methods. The interface for this method is defined in the IModuleOnCall interface class. The onCall method functions the same as an event method in that all onCall methods defined in all modules will be called. Example:

public class MyModule extends ModuleBase implements IModuleOnCall {

public void onCall(String handlerName, IClient client, RequestFunction function, AMFDataList params) {

getLogger().info("onCall: "+handlerName);

} }

Your modules are going to use a combination of the method types described above. When you are creating custom modules, you might want to group them according to functionality so they can be shared by your applications.

Custom Method Parameters

Parameters passed from the Flash player client to Wowza Media Server Pro need to be marshaled to Java primitive and object types. The com.wowza.wms.module.ModuleBase class includes a number of helper functions and constants for converting the parameter values. For more complex types the com.wowza.wms.amf package contains an API for object conversion. Consult the server API javadocs and the “Server Side Coding” example for more detailed information.

Below is a simple example of converting three incoming parameters:

package com.mycompany.module;

import com.wowza.wms.module.*;

import com.wowza.wms.client.*;

import com.wowza.wms.amf.*;

import com.wowza.wms.request.*;

public class MyModule extends ModuleBase {

public void myFunction(IClient client,

RequestFunction function, AMFDataList params) {

String param1 = getParamString(params, PARAM1);

int param2 = getParamInt(params, PARAM2);

boolean param3 = getParamBoolean(params, PARAM3);

} }

Returning Results from a Custom Method

A custom method may return a single result value. This value must be converted to an Action Message Format (AMF) object to be understood by the Flash player client. These value types can include simple types like strings, integers and booleans as well as more complex types like objects, arrays or arrays of objects. The com.wowza.wms.module.ModuleBase class includes a number of helper functions for returning simple types. For more complex types the com.wowza.wms.amf package contains an API for object creation and conversion. Consult the server API javadocs and the “Server Side Coding” example for more detailed information. Below is a simple example of three methods returning simple value types:

package com.mycompany.module;

import com.wowza.wms.module.*;

import com.wowza.wms.client.*;

import com.wowza.wms.amf.*;

import com.wowza.wms.request.*;

public class MyModule extends ModuleBase {

public void myFunctionString(IClient client,

RequestFunction function, AMFDataList params) {

sendResult(client, params, "Hello World");

}

public void myFunctionInt(IClient client,

RequestFunction function, AMFDataList params) {

sendResult(client, params, 536);

}

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

sendResult(client, params, true);

} }

Module Logging

A custom method can get access to the server’s logging interface using the getLogger() helper method that is implemented by the com.wowza.wms.module.ModuleBase base class. Log messages can be written to the log files by using one of the following four methods:

getLogger().debug(logStr);

getLogger().info(logStr);

getLogger().warn(logStr);

getLogger().error(logStr);

Server To Client Calls

A custom server side method can call a function in Flash player client directly by invoking the IClient.call() method. The client call can return a single variable that will be received by the server by creating a result object that implements the com.mycompany.module.IModuleCallResult interface. The IClient.call() method has two forms:

public abstract void call(String handlerName);

public abstract void call(String handlerName,

IModuleCallResult resultObj, Object ... params);

Methods on the client side are made available to the server by attaching them to the NetConnection object. Below is sample client side code:

var nc:NetConnection;

To call this method from the server, the custom method would look like this:

package com.mycompany.module;

String returnValue = getParamString(params, PARAM1);

getLogger().info("got Result: "+ returnValue);

} }

public class MyModule extends ModuleBase {

public void myFunction(IClient client,

RequestFunction function, AMFDataList params) {

client.call("serverToClientMethod", new MyResult(),

"param1: value", 1.5);

} }

Java Management Extensions (JMX)

All modules instantiated for a given application instance will be made available through the Java Management Extension’s (JMX) Interface. The path to the modules section in the MBean interface is:

WowzaMediaServerPro/VHosts/[vHostName]/Applications/[applicationName]/

ApplicationInstance/[applicationInstanceName]/Modules

All public methods and properties (wrapped in Java Bean get/set methods) will be made available through the “Instance” object found within each module definition. If you want to exclude a method or property from the JMX interface, import the “com.wowza.util.NoMBean” class and add the “@NoMBean” annotation to your method definition. So what this means is that your custom modules are instantly made available through the Wowza Pro administration interface without an additional programming. All property values can be inspected, properties with

“get[property-name]” accessors can be changed and methods with simple Java types can be invoked through JConsole or VisualVM.

Other Server Extension Options

There are several other ways of using custom modules to extend the functionality of Wowza Media Server Pro. This section will cover two of these extension points; ServerListeners and HTTPProviders.

ServerListeners

A ServerListener is a class that gets invoked during the initialization process of the Wowza Pro server. It is notified of events during the life cycle of the server. This extension point can be used to startup custom functionality that is going to co-exist along side the Wowza Pro server. This mechanism might be used to auto-start a servlet container that will handle http requests or a SOAP server for providing a custom SOAP interface to integrate with a Windows .NET application or non-Java application.

A ServerListener must implement the com.wowza.wms.server.IServerNotify2 interface.

Configuration for this extension point is done in the Server.xml file by adding an

<ServerListener> entry to the <ServerListeners> list and setting the <BaseClass> value to the full path to your ServerListener class. Below is a simple ServerListener class:

package com.mycompany.module;

import com.wowza.wms.application.*;

import com.wowza.wms.logging.*;

import com.wowza.wms.server.*;

public class TestServerListener implements IServerNotify2 {

public void onServerConfigLoaded(IServer server) {

WMSLoggerFactory.getLogger(Application.class).debug("onServerConfigLoaded ");

}

To add this ServerListener to Server.xml the XML snippet looks like this:

<ServerListeners>

<ServerListener>

<BaseClass>com.mycompany.module.TestServerListener</BaseClass>

</ServerListener>

</ServerListeners>

HTTPProviders

An HTTPProvider is a class bound to a HostPort definition in the VHost.xml configuration file.

This class is invoked when http requests are made to the serer over the port defined by the HostPort. The API for this extension point is very similar to the HTTPServlet API. This extension point can be used to provide an HTML interface into the Wowza Pro server. This mechanism might be used to create a custom administration interface to the server or provide query parameter output consumable by the Flash player LoadVars mechanism to provide a custom load balancing solution.

An HTTPProvider must implement the com.wowza.wms.http.IHTTPProvider interface.

Configuraiton for this extension point is done in the VHost.xml file. Below is a simple HTTPProvider class:

public class HTTPServerVersion implements IHTTPProvider {

private WMSProperties properties = null;

public void onBind(IVHost vhost, HostPort hostPort) {

}

public void onUnbind(IVHost vhost, HostPort hostPort) {

}

public void setProperties(WMSProperties properties) {

this.properties = properties;

}

public void onHTTPRequest(IVHost vhost, IHTTPRequest req, IHTTPResponse resp) {

OutputStream out = resp.getOutputStream();

byte[] outBytes = retStr.getBytes();

Chapter

8

Related documents