The following sections provide an overview of using the Oracle Communications Converged Application Server Diameter Base protocol implementation to create your own Diameter applications:
Diameter is a peer-to-peer protocol that involves delivering attribute-value pairs (AVPs). A Diameter message includes a header and one or more AVPs. The collection of AVPs in each message is determined by the type of Diameter application, and the Diameter protocol also allows for extension by adding new commands and AVPs. Diameter enables multiple peers to negotiate their capabilities with one another, and defines rules for session handling and accounting functions.
Oracle Communications Converged Application Server includes an implementation of the base Diameter protocol that supports the core functionality and accounting features described in RFC 3588. Oracle Communications Converged Application Server uses the base Diameter functionality to implement multiple Diameter applications, including the Sh, Rf, and Ro applications described later in this document.
You can also use the base Diameter protocol to implement additional client and server-side Diameter applications. The base Diameter API provides a simple, Servlet-like programming model that enables you to combine Diameter functionality with SIP or HTTP functionality in a converged application.
The sections that follow provide an overview of the base Diameter protocol packages, classes, and programming model used for developing client and server-side Diameter applications. See also the following sections for information about using the provided Diameter protocol applications in your SIP Servlets:
All classes in the Diameter base protocol API reside in the root com.bea.wcp.diameter
package. Table 1-1 describes the key classes, interfaces, and exceptions in this package.
In addition to these base Diameter classes, accounting-related classes are stored in the com.bea.wcp.diameter.accounting
package, and credit-control-related classes are stored in com.bea.wcp.diameter.cc
. See Using the Diameter Ro Interface Application for Online Charging and Using the Diameter Rf Interface Application for Offline Charging for more information about classes in these packages.
A diameter node is represented by the com.bea.wcp.diameter.Node
class. A Diameter node may host one or more Diameter applications, as configured in the diameter.xml
file. In order to access a Diameter application, a deployed application (such as a SIP Servlet) must obtain the diameter Node instance and request the application. Listing 1-1 shows the sample code used to access the Rf application.
ServletContext sc = getServletConfig().getServletContext();
Node node = sc.getAttribute(“com.bea.wcp.diameter.Node”);
RfApplication rfApp = (RfApplication) node.getApplication(Charging.RF_APPLICATION_ID);
Diameter Nodes are generally configured and started as part of a Oracle Communications Converged Application Server instance. However, for development and testing purposes, you can also run a Diameter node as a standalone process. To do so:
cd ~/bea/user_projects/domains/diameter/bin
. ./setDomainEnv.sh
diameter.xml
configuration file for the Node you want to start:cd ../config/custom
diameter.xml
configuration file to use:java com.bea.wcp.diameter.Node diameter.xml
All Diameter applications must extend either the base Application
class or, for client applications, the ClientApplication
class. The model for creating a Diameter application is similar to that for implementing Servlets in the following ways:
Diameter applications must also implement the getId()
method to return the proper application ID. This ID is used to deliver Diameter messages to the correct application.
Applications can optionally implement rcvRequest()
or rcvAnswer()
as needed. By default, rcvRequest()
answers with UNABLE_TO_COMPLY, and rcvRequest()
drops the Diameter message.
Listing 1-2 shows a simple Diameter client application that does not use sessions.
public class TestApplication extends ClientApplication {
protected void init() {
log(“Test application initialized.”);
}
public ApplicationId getId() {
return ApplicationId.BASE_ACCOUNTING;
}
public void rcvRequest(Request req) throws IOException {
log(“Got request: “ + req.getHopByHopId());
req.createAnswer(ResultCode.SUCCESS).send();
}
}
The base Session class represents a Diameter session. If you extend the base Session class, you must implement either rcvRequest()
or rcvAnswer()
, and may implement both methods.
The base Application class is used to generate new Session objects. After a session is created, all session-related messages are delivered directly to the session object. The Oracle Communications Converged Application Server container automatically generates the session ID and encodes the ID in each message. Session attributes are supported much in the same fashion as attributes in SipApplicationSession
.
Listing 1-3 shows a simple Diameter session implementation.
public class TestSession extends Session {
public TestSession(TestApplication app) {
super(app);
}
public void rcvRequest(Request req) throws IOException {
getApplication().log(“rcvReuest: “ + req.getHopByHopId());
req.createAnswer(ResultCode.SUCCESS).send();
}
}
To use the sample session class, the TestApplication
in Listing 1-2
would need to add a factory method:
public class TestApplication extends Application {
...
public TestSession createSession() {
return new TestSession(this);
}
}
TestSession
could then be used to create new requests as follows:
TestSession session = testApp.createSession();
Request req = session.creatRequest();
req.sent();
The answer is delivered directly to the Session object.
The base Message
class is used for both Request and Answer message types. A Message always includes an application ID, and optionally includes a session ID. By default, messages are handled in the following manner:
rcvMessage()
method is called.rcvMessage()
method is called
The message type is determined from the Diameter command code. Certain special message types, such as RAR, RAA, ACR, ACA, CCR, and CCA, have getter and setter methods in the Message
object for convenience.
Either a Session
or Application
can originate and receive request messages. Requests are generated using the createRequest()
method. You must supply a command code for the new request message. For routing purposes, the destination host or destination realm AVPs are also generally set by the originating session or application.
Requests can be sent asynchronously using the send()
method, or synchronously using the blocking sendAndWait()
method. Answers for requests that were sent asynchronously are delivered to the originating session or application. You can specify a request timeout value when sending the message, or can use the global request-timeout
configuration element in diameter.xml
. An UNABLE_TO_DELIVER result code is generated if the timeout value is reached before an answer is delivered. getResultCode()
on the resulting Answer returns the result code.
New answer messages are generated from the Request
object, using createAnswer()
. All generated answers should specify a ResultCode and an optional Error-Message AVP value. The ResultCode
class contains pre-defined result codes that can be used.
Answers are delivered using the send()
method, which is always asynchronous (non-blocking).
Received answers can be obtained using Request.getAnswer()
. After receiving an answer, you can use getSession()
to obtain the relevant session ID and getResultCode()
to determine the result. You can also use Answer.getRequest()
to obtain the original request message.
The Command
class represents pre-defined commands codes for the Diameter base protocol, and can be used to create new command codes. Command codes share a common name space based on the code itself.
The define()
method enables you to define codes, as in:
static final Command TCA = Command.define(1234, “Test-Request”, true, true);
The define()
method registers a new Command, or returns a previous command definition if one was already defined. Commands can be compared using the reference equality operator (==).
The Avp
class represents a Diameter attribute-value pair. You can create new AVPs with an attribute value in the following way:
Avp avp = new Avp(Attribute.ERROR_MESSAGE, “Bad request”);
You can also specify the attribute name directly, as in:
Avp avp = new Avp(“Error-Message”, “Bad request”);
The value that you specify must be valid for the specified attribute type.
To create a grouped AVP, use the AvpList
class, as in:
AvpList avps = new AvpList();
avps.add(new Avp(“Event-Timestamp”, 1234));
avps.add(new Avp(“Vendor-Id”, 1111));
The Attribute class represents an AVP attribute, and includes the AVP code, name, flags, optional vendor ID, and type of attribute. The class also maintains a registry of defined attributes. All attributes share a common namespace based on the attribute code and vendor ID.
The define()
method enables you to define new attributes, as in:
static final Attribute TEST = Attribute.define(1234, “Test-Attribute”, 0, Attribute.FLAG_MANDATORY, Type.INTEGER32);
Table 1-2 lists the available attribute types and describes how they are mapped to Java types.
The define()
method registers a new attribute, or returns a previous definition if one was already defined. Attributes can be compared using the reference equality operator (==).
The Diameter API enables you to create converged applications that utilize both SIP and Diameter functionality. A SIP Servlet can access an available Diameter application via the Diameter Node, as shown in Listing 1-4.
ServletContext sc = getServletConfig().getServletContext();
Node node = (Node) sc.getAttribute(“com.bea.wcp.diameter.Node”);
RfApplication rfApp = (RfApplication) node.getApplication(Charging.RF_APPLICATION_ID);
Oracle Communications Converged Application Server automatically links the Diameter session to the currently-active call state by encoding the Call-id into the Diameter session ID. When a Diameter message is received, the container automatically retrieves the associated call state and locates the Diameter session. A Diameter session is are serializable, so you can store the session as an attribute in a the SipApplicationSession
object, or vice versa.
Converged applications can use the Diameter SessionListener
interface to receive notification when a Diameter message is received by the session. The SessionListener
interface defines a single method, rcvMessage()
. Listing 1-5
shows an example of how to implement the method.
Session session = app.createSession();
session.setListener(new SessionListener() {
public void rcvMessage(Message msg) {
if (msg.isRequest()) System.out.println(“Got request!”);
}
});
Note: | The SessionListener implementation must be serializable for distributed applications. |