Skip Headers

Oracle® Communication and Mobility Server Developer's Guide Release 10.1.3 Part Number E10293-02 |
Home | Contents | Index | Contact Us

Previous | 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"

- "The SIP Container"

- "SIP Servlets and SIP Applications"

- "SIP Servlet Environment"

- "Classes and Methods"

- "Configuring SIP Applications in sip.xml"

- "SIP Servlets in OCMS"

## 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:

- User Agent Server: A servlet that acts as a User Agent Server (UAS) receives incoming requests and sends responses.

- User Agent Client: A servlet that acts as a User Agent Client (UAC) initiates outgoing requests and receives responses to these requests.

- Proxy: A servlet that acts as a proxy receives incoming requests and proxies them to other end-points (other proxies or a UAS). A proxy servlet will manipulate the request URI and proxy the request to that destination.

- Back to Back User Agent: A servlet that acts as a Back to Back User Agent (B2BUA) acts as both a UAS and UAC on a request. It receives and answers back to one request (first session) and initiates and receives responses on another request (second session).

## The SIP Container

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

- Servlet Context

- SIP Application Sessions

- Protocol Sessions

- Transactions

- Servlets

- Listeners

Figure 2-1 The 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

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

      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:

- Global init parameters (ServletContext init parameters)

  `<context-param>`

- Session configurations

  `<session-config>`

- Servlet definitions

  `<servlet>`

- Servlet mappings, contains the invocation rules

  `<servlet-mapping>`

- Listeners

  `<listener>`

  - Application life cycle listener classes

  - Error handler

- Security

### 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 r`equest.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"

- "Implementation Decisions"

- "Multi-Threading"

- "Sip Servlet API Javadoc"

- "External Access to SIP Servlets"

- "OCMS Authentication and Login Modules"

### 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"

- "Extended doRequest Methods"

- "Asynchronous Send"

#### 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, `FileLoginModul`e, and is recommended only for test purposes.

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