14 Using the Diameter Rf Interface API for Offline Charging

The following chapter describes how to use the Diameter Rf interface API, based on the OWLCS Diameter protocol implementation, in your own applications, and contains the following sections:

14.1 Overview of Rf Interface Support

Offline charging is used for network services that are paid for periodically. For example, a user may have a subscription for voice calls that is paid monthly. The Rf protocol allows an IMS Charging Trigger Function (CTF) to issue offline charging events to a Charging Data Function (CDF). The charging events can either be one-time events or may be session-based.

OWLCS provides a Diameter Offline Charging Application that can be used by deployed applications to generate charging events based on the Rf protocol. The offline charging application uses the base Diameter protocol implementation, and allows any application deployed on OWLCS to act as CTF to a configured CDF.

For basic information about offline charging, see RFC 3588: Diameter Base Protocol (http://www.ietf.org/rfc/rfc3588.txt). For more information about the Rf protocol, see 3GPP TS 32.299 (http://www.3gpp.org/ftp/Specs/html-info/32299.htm).

14.2 Understanding Offline Charging Events

For both event and session based charging, the CTF implements the accounting state machine described in RFC 3588. The server (CDF) implements the accounting state machine "SERVER, STATELESS ACCOUNTING" as specified in RFC 3588.

The reporting of offline charging events to the CDF is managed through the Diameter Accounting Request (ACR) message. Rf supports the ACR event types described in Table 14-1.

Table 14-1 Rf ACR Event Types

Request Description


Starts an accounting session.


Updates an accounting session.


Stops an accounting session


Indicates a one-time accounting event.

The START, INTERIM, and STOP event types are used for session-based accounting. The EVENT type is used for event based accounting, or to indicate a failed attempt to establish a session.

14.2.1 Event-Based Charging

Event-based charging events are reported through the ACR EVENT message. Example 14-1 shows the basic message flow.

Example 14-1 Message Flow for Event-Based Charging

        CTF (WLSS)           CDF (Server)
            |                     |
            | --- ACR (EVENT) --> |
            |                     |
            |                (Process accounting request)
            |                     |
            | <-- ACA (EVENT) --- |
            |                     |

14.2.2 Session-Based Charging

Session-based charging uses the ACR START, INTERIM, and STOP requests to report usage to the CDF. During a session, the CTF may report multiple ACR INTERIM requests depending on the session lifecycle. Example 14-2 shows the basic message flow

Example 14-2 Message Flow for Session-Based Charging

        CTF (WLSS)             CDF (Server)
            |                       |
            | --- ACR (START) ----> |
            |                       |
            |                  (Open CDR)
            |                       |
            | <-- ACA (START) ----- |
            |                       |
           ...                     ...
            | --- ACR (INTERIM) --> |
            |                       |
            |                  (Update CDR)
            |                       |
            | <-- ACA (INTERIM) --- |
           ...                     ...
            | --- ACR (STOP) -----> |
            |                       |
            |                  (Close CDR)
            |                       |
            | <-- ACA (STOP) ------ |
            |                       |

Here, ACA START is sent a receipt of a service request by OWLCS. ACA INTERIM is typically sent upon expiration of the AII timer. ACA STOP is issued upon request for service termination by OWLCS.

14.3 Configuring the Rf Application

The Rf API is packaged as a Diameter application similar to the Sh application used for managing profile data. The Rf Diameter API can be configured and enabled by editing the Diameter configuration file located in DOMAIN_ROOT/config/custom/diameter.xml, or by using the Diameter console extension. Additionally, configuration of both the CDF realm and host can be specified using the cdf.realm and cdf.host initialization parameters to the Diameter Rf application.

Example 14-3 shows a sample excerpt from diameter.xml that enables Rf with a CDF realm of "oracle.com" and host "cdf.oracle.com:"

Example 14-3 Sample Rf Application Configuration (diameter.xml)


Because the RfApplication uses the Diameter base accounting messages, its Diameter application id is 3 and there is no vendor ID.

14.4 Using the Offline Charging API

OWLCS provides an offline charging API to enable any deployed application to act as a CTF and issue offline charging events. This API supports both event-based and session-based charging events.

The classes in package com.bea.wcp.diameter.accounting provide general support for Diameter accounting messages and sessions. Table 14-2 summarizes the classes.

Table 14-2 Diameter Accounting Classes

Class Description


An Accounting-Request message.


An Accounting-Answer message.


A Client-based accounting session.


Accounting record type constants.

In addition, classes in package com.bea.wcp.diameter.charging support the Rf application specifically. Table 14-3 summarizes the classes.

Table 14-3 Diameter Rf Application Support Classes

Charging Common definitions for 3GPP charging functions


Offline charging application


Offline charging session

The RfApplication class can be used to directly send ACR requests for event-based charging. The application also has the option of directly modifying the ACR request before it is sent out. This is necessary in order for an application to add any custom AVPs to the request.

In particular, an application must set the Service-Information AVP it carries the service-specific parameters for the CDF. The Service-Information AVP of the ACR request is used to send the application-specific charging service information from the CTF (WLSS) to the CDF (Charging Server). This is a grouped AVP whose value depends on the application and its charging function. The Offline Charging API allows the application to set this information on the request before it is sent out.

For session-based accounting, the RfApplication class can also be used to create new accounting sessions for generating session-based charging events. Each accounting session is represented by an instance of RfSession, which encapsulates the accounting state machine for the session.

14.4.1 Accessing the Rf Application

If the Rf application is deployed, then applications deployed on OWLCS can obtain an instance of the application from the Diameter node (com.bea.wcp.diameter.Node class). Example 14-4 shows the sample Servlet code used to obtain the Diameter Node and access the Rf application.

Example 14-4 Accessing 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);

Applications can safely use a single instance of RfApplication to issue offline charging requests concurrently, in multiple threads. Each instance of RfSession actually holds the per-session state unique to each call.

14.4.2 Implementing Session-Based Charging

For session-based charging requests, an application first uses the RfApplication to create an instance of RfSession. The application can then use the session object to create one or more charging requests.

The first charging request must be an ACR START request, followed by zero or more ACR INTERIM requests. The session ends with an ACR STOP request. Upon receipt of the corresponding ACA STOP message, the RfApplication automatically terminates the RfSession.

Example 14-5 shows the sample code used to start a new session-based accounting session.

Example 14-5 Starting a Session-Based Account Session

  RfSession session = rfApp.createSession();
  sipRequest.getApplicationSession().setAttribute("RfSession", session);
  ACR acr = session.createACR(RecordType.START);
  acr.addAvp(Charging.SERVICE_INFORMATION, ...);
  ACA aca = acr.sendAndWait(1000);
  if (!aca.getResultCode().isSuccess()) {
    ... error ...

In Example 14-5, the RfSession is stored as a SIP application session attribute so that it can be used to send additional accounting requests as the call progresses. Example 14-6 shows how to send an INTERIM request.

Example 14-6 Sending an INTERIM request

  RfSession session = (RfSession) req.getApplicationSession().getAttribute("RfSession");
  ACR acr = session.createACR(RecordType.INTERIM);
  ACA aca = acr.sendAndWait(1000);
  if (!aca.getResultCode().isSuccess()) {
    ... error ...

An application may want to send one or more ACR INTERIM requests while a call is in progress. The frequency of ACR INTERIM requests is usually based on the Acct-Interim-Interval AVP value in the ACA START message sent by the CDF. For this reason, an application timer must be used to send ACR INTERIM requests at the requested interval. See 3GPP TS 32.299 for more details about interim requests. Specifying the Session Expiration

The Acct-Interim-Interval (AII) timer value is used to indicate the expiration time of an Rf accounting session. It is specified when ACR START is sent to the CDF to initiate the accounting session. The CDF responds with its own AII value, which must be used by the CTF to start a timer upon whose expiration an ACR INTERIM message must be sent. This INTERIM message informs the CDF that the session is still in use. Otherwise, the CDF terminates the session automatically.

It is the application's responsibility to send ACR INTERIM messages, because these are used to send updated Service-Information data to the CDF. Oracle recommends creating a ServletTimer that is set to expire according to the AII value. When the timer expires, the application must send an ACR INTERIM message with the updated service information data. Sending Asynchronous Events

Applications generally use the synchronous sendAndWait() method. However, if latency is critical, an asynchronous API is provided wherein the application Servlet is asynchronously notified when an answer message is received from the CDF. To use the asynchronous API, an application first registers an instance of SessionListener in order to asynchronously receive messages delivered to the session, as shown in Example 14-7.

Example 14-7 Registering a SessionListener

  RfSession session = rfApp.createSession();
  session.setAttribute("SAS", sipReq.getApplicationSession());

Attributes can be stored in an RfSession instance similar to the way SIP application session attributes are stored. In the above example, the associated SIP application was stored as an RfSession so that it is available to the listener callback.

When a Diameter request or answer message is received from the CDF, the application Servlet is notified by calling the rcvMessage(Message msg) method. The associated SIP application session can then be retrieved from the RfSession if it was stored as a session attribute, as shown in Example 14-8.

Example 14-8 Retrieving the RfSession after a Notification

  public void rcvMessage(Message msg) {
    if (msg.getCommand() != Command.ACA) {
      if (msg.isRequest()) {
        ((Request) msg).createAnswer(ResultCode.UNABLE_TO_COMPLY, "Unexpected request").send();
    ACA aca = (ACA) msg;
    RfSession session = (RfSession) aca.getSession();
    SipApplicationSession appSession = (SipApplicationSession) session.getAttribute("SAS");

14.4.3 Implementing Event-Based Charging

For an event-based charging request, the charging request is a one-time event and the session is automatically terminated upon receipt of the corresponding EVENT ACA message. The sendAndWait(long timeout) method can be used to synchronously send the EVENT request and block the thread until a response has been received from the CDF. Example 14-9 shows an example that uses an RfSession for sending an event-based charging request.

Example 14-9 Event-Based Charging Using RfSession

  RfSession session = rfApp.createSession();
  ACR acr = session.createACR(RecordType.EVENT);
  acr.addAvp(Charging.SERVICE_INFORMATION, ...);
  ACA aca = acr.sendAndWait(1000);
  if (!aca.getResultCode().isSuccess()) {
    ... send error response ...

For convenience, it is also possible send event-based charging requests using the RfApplication directly, as shown in Example 14-10.

Example 14-10 Event-Based Charging Using RfApplication

  ACR acr = rfApp.createEventACR();
  acr.addAvp(Charging.SERVICE_INFORMATION, ...);
  ACA aca = acr.sendAndWait(1000);

Internally, the RfApplication creates an instance of RfSession associated with the ACR request, so this method is equivalent to creating the session explicitly.

For both session and event based accounting, the RfSession class automatically handles creating session IDs, as well as updating the Accounting-Record-Number AVP used to sequence messages within the same accounting session.

In the above cases the applications waits for up to 1000 ms to receive an answer from the CDF. If no answer is received within that time, the Diameter core delivers an UNABLE_TO_COMPLY error response to the application, and cancels the request. If no timeout is specified with sendAndWait(), then the default request timeout of 30 seconds is used. This default value can be configured using the Diameter console extension.

14.4.4 Using the Accounting Session State

The accounting session state for offline charging is serializable, so it can be stored as a SIP application session attribute. Because the client APIs are synchronous, it is not necessary to maintain any state for the accounting session once the Servlet has finished handling the call.

For event-based charging events it is not necessary for the application to maintain any accounting session state because it is only used internally, and is disposed once the ACA response has been received.