Skip Headers
Oracle® Communication and Mobility Server Developer's Guide
Release 10.1.3

Part Number E10293-02
Go to Documentation Home
Home
Go to Book List
Book List
Go to Table of Contents
Contents
Go to Index
Index
Go to Feedback page
Contact Us

Go to previous page
Previous
Go to next page
Next
View PDF

2 SIP Servlets

This chapter provides an overview of SIP Servlets and the SIP Servlet API (as described in JSR-116) in the following sections:

Introduction to SIP Servlets

This chapter provides an overview the SIP Servlet API, the SIP container, the SIP servlet environment, SIP classes and methods, and SIP application configuration.

The SIP Servlet API is defined in JSR 116, and describes a standard interface for programming SIP services and applications. A SIP servlet can be compared with a Java HTTP servlet but with SIP protocol-related methods. In fact, the SIP Servlet API builds on the general Servlet API in the same way as the HTTP Servlet API

SIP Servlets are grouped into four categories:

The SIP Container

This section describes the SIP Container (Figure 2-1) by discussing the following components:

Figure 2-1 The SIP Container Object Model

SIP Container Object Model
Description of "Figure 2-1 The SIP Container Object Model"

Servlet Context

The Servlet Context is a servlet view of the SIP application to which it belongs. Using the Servlet Context, the servlet can access such global application services as listeners and context init parameters.

The application global init parameters are set in the deployment descriptor, the sip.xml file, and are marked with the <context-param> marker. Examples of global application parameters are common resource addresses, like addresses to a database and backend applications.

The Servlet Context also holds all references to any implemented and configured listeners. Session and proxy timeouts are held by the Servlet Context. These are configured in the sip.xml file and the session timeout is found within the <session-config> and marked in the <session-timeout> section. The proxy timeout is found within the <proxy-config> and marked in the <sequential-search-timeout> section.The Servlet Context is retrieved by calling the getServletContext method from the servlet. For example:

ServletContext servletContext = getServletContext();

SIP Application Sessions

While an application may involve several types of servlet sessions (for example, SIP and HTTP), these sessions must be related to the same application. This is done through a SIP Application Session. The SIP Application Session can hold multiple protocol sessions; the protocol sessions can be of the same type or different types (SIP, HTTP).

A SIP Application Session can hold attributes available to all protocol sessions related to that application session. A SIP Application Session can hold multiple protocol sessions. For example, B2BUA creates two sessions that are located in the same SIP Application Session.

A SIP Application Session exists until it times out or when the application explicitly calls the invalidate method. A well-behaved application should always invalidate a session when it does not need it anymore. If the SIP Application Session is invalidated, all Protocol Session objects are invalidated together with it. The timeout value of a session is set with the <session-timeout> parameter in the sip.xml file. If no timeout value is defined within this element, then the default value for the container is used (the default is 15 minutes).

If a subsequent request arrives after a session has been invalidated, then the server will respond with a 481 "Call transaction does not exist" message. Requests and responses that correspond to a SIP application session can be retrieved with the getApplicationSession() method on the request (SipServletRequest) or the response (SipServletResponse) object.

Protocol Sessions

A Protocol Session is a session for a certain protocol. If an application involves several protocols, the SIP application session would then hold several protocol sessions.

A SipSession object can represent a point-to-point SIP relationship, an established SIP dialog, or an initial state SIP dialog. The initial state is described as a request that has been received or created with the createRequest method in the sipFactory class. The SIP session object is created by the container when an initial request has invoked one servlet.

A request or a response corresponding a SIP session can be retrieved with the getSession() method on the request (SipServletRequest) or the response (SipServletResponse) object. All of the protocol sessions in an application session can be retrieved with the getSessions() method on the SipApplicationSession object.

Transactions

A SIP transaction consists of a single SIP request and all responses to that request, including the provisional responses and a final response.

A SipServletRequest and a SipServletResponse always belong to a SIP transaction. If a servlet tries to send a message that violates the SIP transaction state model, the container throws an IllegalStateException. The SIP Servlet API is designed in such a way that a developer does not need to consider transactions, only requests and responses.

Servlets

Each servlet defined in the deployment descriptor has one instantiation. Because servlets are run in a multi-threaded environment, only data that is common to all requests and responses, such as init parameters, are stored as member variables.

Increased Servlet Modularity

Each servlet, which includes a <servlet> and a <servlet-mapping> section in the deployment descriptor file (sip.xml) also has a <security-constraint> section. OCMS makes these servlets reusable through the Servlet Creation wizard in OCMS SCE, because these sections are created together with the servlet.

Renaming SAR Files for the JBoss Application Server

In OCMS, the Servlet archive format (SAR) file is renamed to a Sip Servlet aRchive (SSR). The format of the two files are the same, the difference in naming is because of the requirement for a third-party application server for OCMS. Because the application server cannot process SAR files, the SIP AS checks for SSR files instead. This name change enables portability between different SIP application servers.

Note:

When you deploy a SIP application through Oracle 10g Application Server Control or through the admin_client.jar command-line tool you must rename the Servlet archive file (SAR file) to WAR and list the WAR file in the application.xml just like a WAR archive. Also the WAR must contain a web.xml file, so that you can deploy it on OC4J.

For more information on packaging SAR files and deploying EAR files, see Oracle Communication and Mobility Server Administrator's Guide.

Listeners

Listeners can be registered to listen on events and invoke a method. Each deployment descriptor can only have one defined listener of each type. Each of these listeners must be implemented by the developer. The different types of listeners are as follows:

  • SipApplicationSessionListener: The listener for SipApplicationSession creation and invalidation. It can be used to ask for a session extension. The SipApplicationSessionListener interface must be implemented and the sip.xml updated.

  • SipSessionListener: The listener for changes in active SipSessions in the SIP servlet application. The SipSessionListener interface must be implemented and configured in the sip.xml file.

  • SipSessionAttributeListener: The listener for SipSession attribute changes. The SipSessionAttributeListener interface must be implemented.

  • TimerListener: The timer service enables delayed actions for a servlet if the TimerListener interface has been implemented. Only one timer listener exists per application (sip.xml).

  • SipSessionActivationListener: Objects that depend on a session can listen on their status about being active or passive if the SipSessionActivationListener interface is implemented.

SIP Servlets and SIP Applications

A SIP application is a J2EE-compliant application accessed over the SIP protocol. Applications are triggered by an inbound SIP protocol request, just as Web applications are triggered by an inbound HTTP protocol request.

An application has a protocol interface such as SIP or HTTP (presentation tier) that reaches servlets and other business objects (logic tier) which in turn are managed and have resource connections to the database (data tier). User and application data are accessed through the data tier which is represented by applicable parts from the J2EE specification. Applications are delimited by the scope of the deployment descriptor, the sip.xml file.

SIP Servlet Environment

This section describes the environment of a SIP servlet and what occurs during both the startup of the application server (AS) and when a request enters the SIP Container.

Figure 2-2 The SIP Container at Startup

SIP Container at startup
Description of "Figure 2-2 The SIP Container at Startup"

  1. The following occurs at startup:

    1. The container reads the deployment descriptor (sip.xml).

    2. A Servlet Context is created.

      • The global init parameters are set. These are marked with <context-param> in the sip.xml file.

      • Session Configuration values are set. These are marked with <session-config> in the sip.xml file.

      • Proxy Configuration values are set. These are marked with <proxy-config> in the sip.xml file.

      • The container instantiates the TimerListener, SipApplicationSessionListener, SipSessionActivationListener, SipSessionAttributeListener, and the SipSessionListener. Each listener has one instantiation (if defined).

    3. A Servlet Config object is created. The Servlet Config holds all init parameters per servlet. These are marked with <init-param> and are set per servlet in the sip.xml file. It also includes the global init parameters (context-param).

    4. The servlets are created and initiated with the init parameters prepared by the Servlet Config. Each servlet is run as one instance. The init method in the servlets is executed.

    5. A SIP Application Manager, which contains a reference to SipApplicationSessions and the SipFactory, is created.

      Figure 2-3 Initial Requests Processed by the SIP Container

      Initial Requests processed by SIP Container
      Description of "Figure 2-3 Initial Requests Processed by the SIP Container"

  2. The container distinguishes between initial requests and subsequent requests, where initial requests invoke a servlet depending on the invoke conditions (or rules) of the servlet and subsequent requests get forwarded directly to the same servlet as invoked for the initial request. At an Initial Request, the following steps occur:

    1. The container chooses a specific application based on the handling described in "Handling Initial Requests".

    2. Which servlet to invoke is decided by evaluating the rules of each servlet in the servlet invocation order (Figure 2-3). The rule execution order is decided by the order of the <servlet-mapping> order for each servlet in the sip.xml file. The servlet with the top-most servlet mapping is the one that get the rules checked first. For more information, see the following section, "Servlet Mapping".

    3. A SIP Application Session is created together with a SIP Session.

    4. A transaction and a request are created and associated with the SIP session object just created.

  3. For a subsequent request, one for which the container already holds a dialog (a dialog is defined by the Local-tag + Remote-tag + CallId), the request is forwarded to the same servlet executed at the initial request. The request works with the same Message Context (SIP-Application Session + SIP-Session) as it had in the initial request.

Servlet Mapping

A SIP application can contain one or more SIP Servlets. When the SIP container receives SIP requests, the container selects a SIP application to serve the request. The SIP application then evaluates its rules (that is, the servlet-mapping defined in the sip.xml file) to find the appropriate SIP servlet that responds to the request. The SIP application then uses the first SIP servlet that matches the request.

Note:

SIP servlets can forward the request to another SIP servlet by using javax.servlet.ServletRequest.getRequestDispatcher()

Additionally, you can chain applications using the Application Router. Refer to the Oracle Communication and Mobility Server Administrator's Guide.

For example, if the SIP container receives an INVITE request, the container selects a SIP application containing the following SIP Servlets to match the request:

  • Servlet 1 - Invoked for INVITE requests.

  • Servlet 2 - Invoke for MESSAGE requests.

  • Servlet 3 - Invoked for all requests.

The SIP application then attempts to find a match by evaluating its rules from the top to the bottom. In this case, Servlet 1 and Servlet 3 both match the INVITE request. Since only one of these servlets can serve the request and since the application reviews the rules sequentially, the application selects Servlet 1. Servlet 1 starves out Servlet 3. If the SIP container receives a MESSAGE request, then the application invokes Servlet 2. For REGISTER requests, the application invokes Servlet 3, the only servlet able to serve this type of request. If the application does not include Servlet 3, the application's match method will return null for the REGISTER request and the SIP container will issue a 403 response, Application choose not to service the request, which will be written to the log file.

Note:

While a SIP application can invoke only one SIP Servlet for a request, the SIP container can invoke more than one SIP application for an incoming request using the Application Router.

Classes and Methods

This section introduces the classes and methods in the SIP servlet API.

A SIP Servlet is a class that extends the javax.servlet.sip.SipServlet class and thereby interacts with a SIP application server to send and receive SIP messages.

Request and Response Handling Methods

The servlet overrides the methods needed for the particular service. The two main methods that the SIP Servlet uses to perform overrides are:

  • protected void doRequest(SipServletRequest req)

  • protected void doResponse(SipServletResponse resp)

The doRequest() method handles all of the requests and the doResponse()method handles all of the responses.

Outside of the service method, the doRequest() and doResponse() are the broadest methods provided by the SipServlet class. These methods enable tasks that are independent of the received method or response. You can extend methods to perform specific request and response handling tasks.

Extend the following methods for request handling:

  • doInvite – for SIP INVITE requests

  • doAck – for SIP ACK requests

  • doCancel – for SIP CANCEL requests

  • doBye – for SIP BYE requests

  • doOptions – for SIP OPTIONS requests

  • doRegister – for SIP REGISTER requests

  • doSubscribe – for SIP SUBSCRIBE requests

  • doNotify – for SIP NOTIFY requests

  • doMessage – for SIP MESSAGE requests

  • doInfo – for SIP INFO requests

  • doPrack – for SIP PRACK requests

For response handling, extend the following:

  • doProvisionalResponse – for SIP 1xx informational responses

  • doSuccessResponse – for SIP 2xx responses

  • doRedirectResponses – for SIP 3xx responses

  • doErrorResponse – for SIP 4xx, 5xx, and 6xx responses

Note:

All of these response handling methods, as well as the doAck and doCancel request handling methods, are empty. The remaining request handling methods respond to a request with a 500 Response (Internal Server Error).

Messages

SIP Messages follow the RFC 822 standard. Headers, values and content can be accessed through the methods in the javax.servlet.sip.SipServletMessage interface.

Both the SipServletRequest and SipServletResponse classes extend the SipServletMessage interfaces:

  • public interface SipServletRequest extends javax.servlet.ServletRequest,SipServletMessage

  • public interface SipServletResponse extends javax.servlet.ServletResponse, SipServletMessage

Requests

SipServletRequest and SipServletResponse objects in the SIP servlet methods doRequest and doResponse are implementations of the SipServletRequest interface and the SipServletResponse interface which both extend the SipServletMessage interface from the javax.servlet.sip package.

A SIP request consists of the following:

  • Request line

  • Headers

  • Empty line

  • Message body

All parts of the SIP request for instance request URI, headers and parameters are accessible through these interfaces. The SIP container handles many of these system headers. Applications must not add, delete, or modify the following system headers:

  • From

  • To

  • Call ID

  • CSeq

  • Via

  • Route (except through pushRoute)

  • Record Route

  • Contact (Contact is a system header field in messages other than REGISTER requests and responses, as well as 3xx and 485 responses)

Responses

Responses to incoming requests are created using the createResponse method on the request object. It will automatically create a response with all SIP headers set according to the request. A SIP response has the same structure as a SIP request, except for a Status line instead of a request line. When receiving responses through, for instance the doResponse method, methods like getStatus() can be used on the response object to decide what action to take.

Content

The content in a request or a response can be set with the setContent() method as illustrated in Example 2-1.

Example 2-1 Setting the Content of a Request with the setConent Method

// Copy of the content from request A to request B
requestB.setContent(requestA.getContent(),
requestA.getContentType());
// Create new content
{
try
  req.setContent("Hello!", "text/plain");
}
catch (UnsupportedEncodingException e)
{  // Handle the exception}

Manipulating SIP headers

The javax.servlet.sip.SipServletMessage includes methods for manipulating SIP headers. The getHeaderNames() method is the most general method that returns an iterator of the SIP headers of the message. The setHeader method sets or adds an address for a header. Specifying the name of the header in getHeaders(name) method returns another iterator of String objects containing all of the values for that header.

For those headers that conform to AddressHeader, the getAddressHeader(name)method will return the header parsed as an Address object.

Addresses can be added or set for a header by using setAddressHeader(name, address), addAddressHeader(name, address, first), where name is the name of the header, the address to add, and first is a Boolean. If first is set to true, then the address will be added first, otherwise it will be added last.

Example 2-2 shows how to manipulate SIP headers:

Example 2-2 Manipulating SIP Headers

javax.servlet.sip.SipServletRequest req;

// Set a header with the given name and value.// Overwrites any previous header values.
req.setHeader("Accept", "application/sdp");

// Add a header value to the end of a header
req.addHeader("Accept", "text/html");

// Clear all header values
req.removeHeader("Accept");

// Add a Route header value ahead of the existing Route header// values.
req.pushRoute(sipURI);

// Get the first route as an Address object
Address first route = req.getAddressHeader("Route");

// Get all address header fields for a header
Iterator addrIter = req.getAddressHeaders("Route");
while (addrIter.hasNext()) 
{
Address addr = (Address) addrIter.next();
// ...
}

SipURI

A base class javax.servlet.sip.URI exists with two sub classes, javax.servlet.sip.SipURI and javax.servlet.sip.TelURL which represents SIP URIs and TEL URLs according to RFC 3261, and URLs defined by RFC 2806. The Address class stores a SipURI or a TelURL as the address of the user.

URIs can be described as user@host, where the user part is either a user name or a telephone number, and the host is a domain name or an IP address.

Parameters can be accessed with getters and setters. The getParameterNames method will return an iterator with the names of the parameters. A parameter can be accessed either with the general getParameter method or with specific parameter methods like getUser, getHost and getLrParam, which returns the user, the host, and true if the loose route, lr is set. Parameters can be set with its corresponding setMethod() as shown in Example 2-3.

Example 2-3 Accessing Parameters in SipURI

// Create a SipURI, set the port, the lr, and the transport
// protocol parameter
SipURI myURI;
myURI = sipFactory.createSipURI("bob", "10.0.0.10");
myURI.setPort(5072);
myURI.setLrParam(true);
myURI.setTransportParam("udp");

Address

SIP addresses found in headers, such as the From, To, and Contact headers, are stored as javax.servlet.sip Address objects. As shown in Example 2-4, the object holds, beside the URI, an optional display name and a set of name-value parameters.

Example 2-4 SIP Addresses Stored in java.servlet.sip Address Objects

Address contactAddress;
String displayName;
try
{
  // Get the contact address
  contactAdress = req.getAddressHeader("Contact");
  displayName = contactAdress.getDisplayName();
}
catch (ServletParseException spe)
{
  // Handle exception
}
// Create a new address
Address myNewAddress;
myNewAddress = sipFactory.createAddress(URI, "Bob's display name");
myNewAddress.setParameter("myparameter","42");

The content of myNewAddress in the preceding example is as follows:

DisplayName: "Bob's display name"

URI: <sip:bob@example.com;lr>;

parameter myparameter: 42

The Address class offers the following methods:

  • getDisplayName()

  • setDisplayName()

  • getURI()

  • setURI()

  • clone()

  • toString()

SIP Details

When working with the SIP Servlet API, many SIP details are hidden and performed automatically by the OCMS SIP Application Server.

  • When the transport protocol is UDP, retransmissions are handled automatically.

  • Dialog-related information such as tags, contacts, and CSeq in the SIP messages are handled automatically.

  • On outgoing requests, OCMS performs DNS lookups and supports NAPTR-, SRV-, and A-records (according to RFC 3263).

Storing Data as Session Attributes

The SIP Servlet API enables data to be stored as session attributes. Session attributes can be used to store session specific data to be used in responses and subsequent requests or from a listener class. The attributes are stored and accessed through setters and getters directly on the session object. The session can be either a SipSession or a SipApplicationSession. An attribute can only be retrieved from the same session it was set. For example:

session.setAttribute("key", "value");
session.getAttribute("key"); // Will return "value"
session.removeAttribute("key");

Although the session attributes can store any object, the attributes and their keys must be serializable for applications that are distributable (for High Availability). Use the getAttributeNames method to retrieve all of the set attributes. For example:

Enumeration attributes = session.getAttributeNames();
String attributeName = null;
while (attributes.hasMoreElements())
{
  attributeName = (String) attributes.nextElement();
  Object attribute = session.getAttribute(attributeName);
  log (attribute.toString());
}

Adding Configuration Parameters

A servlet can be configured by adding parameters to the <servlet> section in the SIP Servlet application descriptor (sip.xml). The servlet can then access these parameters through the getInitParameter method. Example 2-5 illustrates how to configure the response code.

Example 2-5 Configuring Servlet Parameters

package com.mydomain.test;
import javax.servlet.sip.SipServlet;
import javax.servlet.sip.SipServletRequest;
import javax.servlet.sip.SipServletResponse;
import java.io.IOException;
public class MySipServlet extends SipServlet
{
  protected void doRequest(SipServletRequest req) throws IOException 
  { 
    int responseCode = Integer.parseInt(getInitParameter("responseCode"));
    SipServletResponse resp = req.createResponse(responseCode);
    resp.send();
  }
}

Configuring SIP Applications in sip.xml

SIP servlets must be declared in the application's deployment descriptor, the sip.xml file. The sip.xml file enables you to configure the init parameters and the rules that match initial requests with SIP servlets.

The deployment descriptor is divided into the following sections:

Setting and Accessing Global Init Parameters

The <context-param> and the <env-entry> elements provide the means to set and access the application's global parameters, such as the database used with an application or other resources that are common to the entire application. These elements differ in how the global parameters are accessed.

The <context-param> element declares the servlet's init parameters that are global to the entire Servlet Context. Example 2-6 illustrates setting the database for an application within the <context-param> element.

Example 2-6 Setting a Database Name within the <context-param>

<context-param>
  <param-name>Database</param-name>
  <param-value>10.0.0.100</param-value>
  <description>The database to be used with this application.</description>
</context-param>

Configuring Application Sessions

SIP Application Sessions are configured within the <session-config> clause. The session configuration can configure a session timeout value, which is done within the <session-timeout> clause as shown in the following example. The timeout is set in minutes; if it set to 0 or below, an application session will never timeout and must be invalidated explicitly. If no value is set within <session-timeout>, the default timeout session set for the SIP Servlet Container is used instead (15 minutes).

<session-config>
   <session-timeout>10</session-timeout>
</session-config>

Defining a Servlet

The <servlet> element defines the SIP container's servlets. A servlet requires a servlet name <servlet-name>, and a servlet class, <servlet-class>. The name must be unique within the application and the class must be the fully qualified name of the servlet class, as illustrated in Example 2-7.

Example 2-7 Servlet Name and Servlet Class

<servlet>
   <servlet-name>MyServlet</servlet-name>
   <servlet-class>com.company.example.MyServlet</servlet-class>
</servlet>

A servlet can also have its own init parameters, <init-param> and a description <description>. When the container starts, it only instantiates and calls the init() method for the servlets which have set the <load-on-startup> element, as shown in Example 2-8.

Example 2-8 Defining a Servlet

<servlet>
   <servlet-name>MyServlet</servlet-name>
   <servlet-class>com.mydomain.test.MySipServlet</servlet-class>
   <init-param>
      <param-name>logging</param-name>
      <param-value>true</param-value>
      <description>
         Set if logging should be switched on (true) or not (false).   
      </description>
   </init-param>
   <init-param>
      <param-name>infotainment</param-name>
      <param-value>http://www.infotainmentsite.com</param-value>
      <description>
         The site to use as the infotainment content provider.
      </description>
   </init-param>
   <load-on-startup/>
</servlet>

Defining the Servlet Mapping

The <servletmapping> element of the SIP servlet application deployment descriptor defines the conditions for invoking a servlet. Example 2-9 illustrates how a servlet named MySipServlet can only be invoked for incoming MESSAGE requests. For more information, see "Servlet Mapping".

Example 2-9 Servlet Mapping

<!-- Servlet Mappings for incoming requests-->
<servlet-mapping>
   <servlet-name>My Sip Servlet</servlet-name>
   <pattern>
      <equal>
         <var>request.method</var>
         <value>MESSAGE</value>
      </equal>
   </pattern>
</servlet-mapping>

Creating Rules Using the Request Object Structure

The request object model enables you to define rules for processing SIP requests. This section describes the object model and the predicates for building the rules.

The Request object contains many sub objects, for example SipURI which extends the URI object.

The request object contains the following elements:

  • method: The method of the request is represented as String.

  • uri: The URI object of the request object, such as SipURI or a TelURI.

  • from: The From header address represented as Address.

  • to: The To header address represented as Address.

The URI object consists of the URI scheme.

The SipURI object consists of the following elements:

  • scheme: The string sip or sips (where sips indicates that TLS should be used).

  • user: The user part of the SIP or SIPS URI. If the SIP address is sip:alice@example.com, then request.uri.user will return alice.

  • host: The host part of the SIP or SIPS URI. If the SIP address is sip:alice@example.com, then request.uri.host will return example.com.

  • port: The SIP URI port. If it is not present, then the default value for UDP and TCP is 5060 and TLS is 5061.

  • tel: Returns the user part of the SIP or SIPS URI if the parameter user is set to phone for the URI. The initial visual separators as + and - are stripped away. For example, if the SIP URI is sip:+12345@example.com;user=phone, then the request.uri.tel would return 12345.

  • param.name: The value of the SipURI parameter with the name name. For example, given the following request URI: INVITE sip:23479234@oracle.com;user=phone SIP/2.0, the request.uri.param.user will return phone.

The TelURL consists of the following elements:

  • scheme: The string, tel.

  • tel: The tel URL subscriber name.

  • param.name: the value of the SipURI parameter with the name name.

Address consists of the following elements:

  • uri: The URI object

  • display-name: The To or From display name of the header.

Conditions

Table 2-1 lists the operators.

Table 2-1 Operators

Condition Name Description

equal

Compares the value of a variable with a literal value and evaluates to true if the variable is defined and its value equals that of the literal. Otherwise, the result is false.

exists

Takes a variable name and evaluates to true if the variable is defined, or to false if the variable has not been defined.

contains

Returns true if the first argument, a variable, contains the literal string specified as the second argument.

subdomain of

If given a variable denoting a domain name (SIP/SIPS URI host) or telephone subscriber (tel property of SIP or Tel URLs), and a literal value, this operator returns true if the variable denotes a sub domain of the domain given by the literal value.


Table 2-2 lists the logical connectors.

Table 2-2 Logical Connectors

Logic Description

and

Contains a number of conditions and evaluates to true if all of the contained conditions evaluate to true.

or

Contains a number of conditions and evaluates to true if and only if at least one contained condition evaluates to true.

not

Negates the value of the contained condition.


Examples

Example 2-10 describes the parts of a request which are referenced with the different types of variables.

Example 2-10 Referencing Request Elements

MESSAGE sip:bob@example.com SIP/2.0
Call-ID: a2412d22-161b-4cff-b4a5-a4c6c1f70f18
To: <sip:bob@example.com>
From: "Alice" <sip:alice@example.com>;tag=1234
Max-Forwards: 70
User-Agent: Oracle-CallTron/4.5.7.1445
Accept: text/plain
CSeq: 2 MESSAGE
Content-Type: text/plain; charset=UTF-8
Content-Length: 13
Via: SIP/2.0/TCP 10.0.0.20:3094;branch=z9hG4bK-477709c9-c064-4b95-
90bc-7391d0154368.1;rport
Route: <sip:messageapp@sipappserver.com;lr>
Proxy-Authorization: Digest username="alice", realm="example.com",
nonce="MTEzNDQwMzkwMDc3NDJiM2JkY2E1ZmRiY2M4YzBjYzQ2M2VhMTM2NWFlM2Fm",
uri="sip:bob@example.com", qop=auth, nc=00000001, cnonce="443857DE",
response="e5c48d5d2982cf3974260511218a246a",
opaque="4a94690f435b9049b896dce0b6ddb8fe"

The message!

Table 2-3 describes the variable values.

Table 2-3 Variable Values

Variable Value

request.method

MESSAGE

request.uri

sip:bob@example.com

request.uri.scheme

sip

request.uri.user

bob

request.uri.host

example.com

request.uri.port

5060

request.uri.tel


request.from

"Alice" <sip:alice@example.com>;tag=1234

request.from.uri

sip:alice@example.com

request.from.uri.scheme

sip

request.from.uri.user

alice

request.from.uri.host

example.com

request.from.uri.port

5060

request.from.display-name

Alice

request.to

sip:bob@example.com

request.to.uri

sip:bob@example.com

request.to.uri.scheme

sip

request.to.uri.user

bob

request.to.uri.host

example.com

request.to.uri.port

5060

request.to.display-name



The following example evaluates to false.

<pattern>
   <and>
      <equal>
         <var>request.method</var>
         <value>MESSAGE</value>
      </equal>
      <contains>
         <var>request.from</var>
         <value>tag=1234</value>
      </contains>
      <equal>
         <var>request.uri.host</var>
         <value>otherexample.com</value>
      </equal>
   </and>
</pattern>

The first condition, equal, evaluates to true. The second condition, contains, also evaluates to true. The third condition ensures that it only serves requests for the otherexample.com but the request URI host is example.com and then it evaluates to false as does the whole rule while the three conditions are all inside the and condition.

SIP Servlets in OCMS

This section describes the OCMS extensions to the SIP Servlet API as well as its implementation of it. Sections include:

Handling Initial Requests

When the SIP container receives an initial request, it attempts to invoke a SIP application. The SIP container selects the application based on the appId parameter. See Chapter 3, "Advanced SIP Servlet Configuration" for information on appId. The workflow of the SIP container is as follows:

  1. Check if the request contains an indication of which application to invoke.

  2. If there is no name of an application to invoke, then the SIP container selects default applications.

  3. If the application is named by the request, then the SIP container locates the application and then invokes it.

Note:

The container selects a default application when initial requests do not indicate which applications should be invoked.

For example, to respond to an incoming request, a SIP servlet container evaluates the following SIP applications:

  • Application A has the following two SIP servlets defined in its sip.xml:

    • Servlet 1 matches INVITE requests.

    • Servlet 2 matches MESSAGE requests.

  • Application B has the following SIP servlet defined in its sip.xml:

    • Servlet 1 matches INVITE requests.

  • Application C has the following two SIP servlets defined in its sip.xml:

    • Servlet 1 matches REGISTER requests.

    • Servlet 2 matches all requests.

  • Application D has the following two SIP servlets defined in its sip.xml:

    • Servlet 1 matches a SUBSCRIBE request.

    • Servlet 2 matches a PUBLISH request.

  • Application E has the following SIP servlet defined in its sip.xml.

    • Servlet 1 matches all requests.

All of these applications have been deployed into the SIP container, but no default application has been specified. The SIP container then designates all of the SIP applications that it locates as the default application. For example, when the SIP container receives an INVITE request which does not designate which application to invoke, the SIP container checks for default applications. However, because none of the applications deployed to the container have been configured as default applications, the container retrieves all of the applications. These applications are in the following order:

  • Application B

  • Application D

  • Application C

  • Application E

  • Application A

The SIP container reviews the list of applications sequentially, starting with Application B. It queries each application for a servlet that can process the incoming request. If the application contains the appropriate servlet, then the servlet is invoked and no other applications can be considered for this request. Example 2-11 illustrates the concept code for the SIP container's application evaluation process.

Example 2-11 Evaluating SIP Applications for Incoming Requests

List allDeployedApplications = retrieve all applications that have been deployed;
for each application in allDeployedApplications do:
   SipServlet servlet = application.match(incoming request);
   if servlet is not null then:
       servlet.processIncomingRequest(request);
       return;
   end if
end for

In this case, the SIP container selects Application B to serve the incoming INVITE request. If the SIP container received a PUBLISH request, it retrieves the list again and queries Application B (the first application). Since Application B does not match the request, the SIP Container moves to the next application, Application D. Because this application contains a servlet that processes this request, the SIP container selects Application D.

Application A can never be invoked, as it is the last on the list of deployed applications and will always be starved out by Application C, which accepts all incoming events. Application C starves out all of the subsequent applications as well, as its first servlet processes all REGISTER requests and its second servlet processes all other requests.

Implementation Decisions

The following sections describe implementation options in the SIP Servlet specification:

Protocol Sessions

The SIP Servlet specification infers that other protocol sessions, such as HTTP, can be placed in the same SIP Application Session. However, OCMS currently supports only the SIP protocol.

Note:

This does not prevent you from creating converged SIP and HTTP applications. Please refer to Oracle Communication and Mobility Server documents on Oracle Technology Network (http://www.oracle.com/technology/index.html) for examples.

Extended doRequest Methods

The OCMS SCE wizard offers a doPublish() method. The wizard extends the doRequest methods by also dispatching the SIP PUBLISH request (RFC 3903).

For request handling, the doPublish() method is used for SIP PUBLISH requests.

See also "Request and Response Handling Methods".

Asynchronous Send

In OCMS, the send() method on a SipServletRequest never throws an IOException. The container posts the request on a send queue and returns it successfully. If the send operation later fails, a final response will be generated by the container. Failure in a DNS lookup returns 408 (Request Timeout) or for other types of failures, a 500 (Server Internal Error).

Multi-Threading

In OCMS, a servlet runs in a multi-threaded environment and multiple servlets may have access to the same session object at the same time. The request and responses use an available thread from the thread pool of the container. Therefore the developer may be responsible for synchronizing access to sessions and their resources if required by the application logic.

Sip Servlet API Javadoc

The Javadoc can be downloaded from the jcp.org Web page, http://jcp.org/aboutJava/communityprocess/final/jsr116/index.html.

When the download of the zip file is complete, you can update the Javadoc location in Eclipse to include the new location of the Javadoc.

External Access to SIP Servlets

To enable convergent applications between SIP and HTTP, the OCMS Container allows you to get access to the javax.servlet.sip.SipFactory by looking it up through JNDI. The SIP Factory will be registered under the same name as the display name of your SIP servlet as illustrated in Example 2-12. The <display-name> in the sip.xml in this case must be "My sip app".

Example 2-12 Accessing the Data for a SIP Session through JNDI

InitialContext ic = new InitialContext();
SipFactory sipFactory = (SipFactory)ic.lookup("sip/My sip app");

OCMS Authentication and Login Modules

OCMS provides Digest Access Authentication against the users, user roles, and user data stored in the TimesTen In-Memory Database or against an external RADIUS (Remote Authentication Dial-In User Service) server. OCMS also supports authentication and authorization services for users provisioned to OID (Oracle Internet Directory).

The login modules, OCMSLoginModule and the RADIUSLoginModule are custom login modules that act as JAAS security providers to execute digest authentication for SIP applications and basic authentication for J2EE applications. OCMSLoginModule authenticates against user data stored in the TimesTen database, while RadiusLoginModule authenticates against an external RADIUS server. Basic Access Authentication is only supported when using the file-based login module, FileLoginModule, and is recommended only for test purposes.

For more information, see Oracle Communication and Mobility Server Administrator's Guide.