Red5 Pro Scopes
- 1. What are scopes
- 2. Types of scopes
- 3. Scope Paths
- 4. Monitoring scope creation: The IScopeListener
- 5. Fetching a list of scope names from a Red5 Pro application
- 6. The IApplication interface: Intercepting connections to scopes
- 7. Finding out where the client is connected
- 8. Bonus: The ScopeUtils class
- 9. Conclusion:
1. What are scopes
A scope represents a virtual separation of resources on your server. Red5 Pro resources such as streams, connections, SharedObjects are all managed within the context of scopes.
If you know about the golden days of the Adobe Flash Platform, you would remember the popularity of socket servers for games. Socket servers were designed mainly for games and chat applications. A chat application with multiple rooms is hence a very good example of scopes. For example, there could be the main chat room and then there can be other private/public rooms. These rooms actually provide a virtual separation of resources to avoid collision and help in better management of resources.
Another close analogy would be a hard drive and its partitions. The purpose of creating partitions is nothing more than better management of files and folders for both users and the operating system itself. The fact however remains that partitions are logical and not physical in nature. All the partitions share the same physical drive space but virtually they are separate spaces. So you can have a file called “red5server.txt” on each partition.
2. Types of scopes
Red5 Pro has a few different types of scopes. Based on the purpose for which the scope is created, the following valid scope types are defined:
- GLOBAL => The global scope is the root scope of the entire server. All applications are created and managed inside the global scope.
- APPLICATION => The top-level scope which represents the Red5 Pro application.
- ROOM => A sublevel child scope within the application. All child scopes exist within the application scope. A ROOM scope can also be nested within another ROOM scope.
- BROADCAST => The broadcast scope is created for a broadcast stream. Similar to the ROOM scope the BROADCAST scope lives within an APPLICATION scope and may be nested within a ROOM scope.
- SHARED_OBJECT => A SHARED_OBJECT is created for a Red5 Pro SharedObject.
2.1 The global scope
The global scope is the core scope of the Red5 Pro server. It defaults to the name default
. This is the first scope that gets created as the server starts up. The global scope is declared in the Red5 Pro configuration red5-default.xml
located at RED5_HOME/webapps/red5-default.xml
as a JavaBean.
This is just for information. The bean should not be edited unless you know what you are doing.
2.2 The web scope
The web.scope
represents the APPLICATION scope. It is declared in every Red5 Pro application context file – red5-web.xml
located at RED5_HOME/webapps/{appname}/WEB-INF/red5-web.xml
. As the application scope is created, it gets injected with references to the server
object, the global scope
etc. The contextPath
is the absolute path of the scope which includes the global scope path.
Sample red5-web.xml of the live
application
<bean id="web.scope" class="org.red5.server.scope.WebScope" init-method="register">
<property name="server" ref="red5.server" />
<property name="parent" ref="global.scope" />
<property name="context" ref="web.context" />
<property name="handler" ref="web.handler" />
<property name="contextPath" value="${webapp.contextPath}" />
<property name="virtualHosts" value="${webapp.virtualHosts}" / : PATH>
bean>
3. Scope Paths
Each scope is identified by a unique path where it is created within the context of the server. Given below are some examples to illustrate how scopes are laid out within the server.
GLOBAL SCOPE ::
/default
APPLICATION SCOPE :: live
/default/live
A ROOM INSIDE THE APPLICATION SCOPE :: myroom
/default/live/myroom
4. Monitoring scope creation: The IScopeListener
Sometimes you may want to listen for application creation or removal. A good use case would be a Plugin that needs to be attached to one or more applications on the server. To do this, we need to listen for application creation as the server starts up and runs your plugin. The code snippet below shows how we can use IScopeListener
to listen for application startup and then do something with the scope object.
private void monitorApplicationStartup(){
IScopeListener scopeListener = new IScopeListener() {
@Override
public void notifyScopeCreated(IScope scope) {
if (scope.getType() == ScopeType.APPLICATION) {
log.info("application started " + scope.getName());
}
}
@Override
public void notifyScopeRemoved(IScope scope) {
if (scope.getType() == ScopeType.APPLICATION) {
log.info("application stopped " + scope.getName());
}
}
};
server.addListener(scopeListener);
}
A server-side application showcasing the usage of an IScopeListener
object is available on GitHub as an example.
5. Fetching a list of scope names from a Red5 Pro application
if you wish to fetch the names of all child Scopes created on your application, you can use the MultiThreadedApplicationAdapter
API. The MultiThreadedApplicationAdapter
extends the StatefulScopeWrappingAdapter
. you can also use getChildScopeNames
.
appAdapter.getChildScopeNames()
6. The IApplication interface: Intercepting connections to scopes
The IApplication
interface in Red5 Pro is used to tap into the Red5 Pro application adapter’s connection & scope events. The IApplication
interface can be immensely useful in tracking/validating connections on scopes.
You can create an IApplication
implementation by creating a java class that implements the IApplication
interface. To register the implementation to an application, use the addListener
method of the MultiThreadedApplicationAdapter
class.
A sample implementation of the IApplication
interface is given below:
public class ApplicationMonitor implements IApplication {
private static Logger log = Red5LoggerFactory.getLogger(ApplicationMonitor.class);
@Override
public boolean appStart(IScope app) {
log.info("appStart " +app.toString());
return true;
}
@Override
public boolean appConnect(IConnection conn, Object[] params) {
log.info("appConnect : Scope " +conn.getScope().toString());
return true;
}
@Override
public boolean appJoin(IClient client, IScope app) {
log.info("appJoin : Scope " +app.toString());
return true;
}
@Override
public void appDisconnect(IConnection conn) {
log.info("appDisconnect : Scope " +conn.getScope().toString());
}
@Override
public void appLeave(IClient client, IScope app) {
log.info("appDisconnect : Scope " + app.toString());
}
@Override
public void appStop(IScope app) {
log.info("appStop : Scope " + app.toString());
}
@Override
public boolean roomStart(IScope room) {
log.info("roomStart : Scope " + room.toString());
return true;
}
@Override
public boolean roomConnect(IConnection conn, Object[] params) {
log.info("roomConnect : Scope " + conn.getScope().toString());
return true;
}
@Override
public boolean roomJoin(IClient client, IScope room) {
log.info("roomJoin : Scope " + room.toString());
return true;
}
@Override
public void roomDisconnect(IConnection conn) {
log.info("roomDisconnect : Scope " + conn.getScope().toString());
}
@Override
public void roomLeave(IClient client, IScope room) {
log.info("roomLeave : Scope " + room.toString());
}
@Override
public void roomStop(IScope room) {
log.info("roomLeave : Scope " + room.toString());
}
}
The AppMonitor class can then be registered with your Application Adapter in your Application class like this:
@Override
public boolean appStart(IScope arg0) {
this.addListener(new ApplicationMonitor());
return super.appStart(arg0);
}
When attempting to register from a plugin, you need to first access the
MultiThreadedApplicationAdapter
class from the application scope using thegetHandler
method of theIScope
interface.
A very important thing to notice is that some of the methods return aBoolean
value. If you return afalse
or throw aClientRejectedException
then the client is unable to proceed through the connection process.
A detailed example application is available on github for reference. You can run the example on a live server instance to observe the sequence of method calls. The sample AppMonitor
class shows how to get information about a scope
whenever a client attempts to connect to the server application.
7. Finding out where the client is connected
At any time if you wish to find out which scope the current client is connected to, you can use the getScope()
method of IConnection
interface.
Example:
IConnection connection = Red.getConnectionLocal();
IScope scope = connection.getScope();
Every connection is an
IConnection
in Red5 Pro.Red.getConnectionLocal()
is a static method that returns a reference to the current client connection with respect to the executing thread.
8. Bonus: The ScopeUtils class
The ScopeUtils
is a static class provided in red5 that can be extremely useful when dealing with scopes.
Some of the common utilities include :
- Resolving the parent scope of a sub-scope.
- Tracing back to the application scope from any
IScope
in an application. - Locating the global scope in an application
- Checking what
type
a given scope is. - Finding a scope within a scope
8.1 Finding a sub-scope
[INFO] [NioProcessor-3] org.red5.scopes.examples.appmonitor.ApplicationMonitor - roomStart : Scope Scope [name=lastroom, path=/default/iapplication-demo/room, type=ROOM, autoStart=true, creationTime=1497875754784, depth=3, enabled=true, running=false]
The sample log statement above is the value of the scope
when we attempt inside the roomStart
method when we attempt to connect to a Red5 Pro application iapplication-demo
when connecting using the URL – rtmp://localhost/iapplication-demo/room/lastroom
.
To be able to find the scope named lastroom
from anywhere in your application at any time, you can use the ScopeUtils
method – resolveScope
.
The method requires two parameters. A parent scope and the relative path to the subscope to be resolved. For example, to resolve the IScope object for lastroom
use the following:
IScope scope = ScopeUtils.resolveScope(appScope, "room/lastroom");
Where appScope
is the application scope.
9. Conclusion
Scopes are the core object of the Red5 Pro architecture. Scopes are logical boundaries within which we define resources. If you are dealing with a simple streaming concept, you may not need to fiddle with scopes at all. However, as you dive deeper and requirements get more complex, you will see how having scopes simplify things a lot.