by Nasir Khan
This article is about the SIP servlet programming model, a model based on the SIP Servlet Specification for programming SIP applications. The article covers the SIP servlet container and SIP servlet API details. After reading this article you will be able to understand and appreciate the design motivations of the SIP servlet container. You will also learn about the various API constructs and how they can be used to create powerful SIP applications.
In this article you get a detailed look at the SIP servlet programming model and the SIP servlet API. If you are looking for an introduction to SIP servlets, read the two-part series published on Dev2Dev by Emmanuel Proulx: An Introduction to SIP, Part 1: Meet SIP and An Introduction to SIP, Part 2: SIP Servlets. The article assumes you have a basic understanding of the SIP protocol. It is also beneficial if you are familiar with the HTTP servlet model, although this is not a prerequisite. Other than the SIP protocol itself, efforts are made in this article to explain the concepts independent of other standards or specifications.
This article covers the SIP servlet programming model, API (SSAPI), and the containers that provide this API. It begins with the story behind the SIP servlet model and what it is best suited for. It then delves into the important artifacts of the API, how these artifacts are made available by the container, and what the container does and doesn't do. Then, by way of examples, the article gives you a flavor of what a SIP servlet application can do. Note that throughout this article I use the term SSAPI and SIP Servlet Specification interchangeably.
I will start by taking a step back and looking at why the SIP Servlet Specification is an extremely attractive proposition for the SIP Java developers and what the value proposition of the SSAPI is. What follows are some of the stated goals of the SSAPI from the JSR 116 specification.
The specification allows applications to perform a fairly complete set of SIP signaling. The SIP protocol defines different types of high-level SIP roles, namely the User Agents (UA referring specifically to UA Client, UA Server, and arguably Back to Back UA B2BUA), Proxy, Registrar, Redirect Server, and so on. The SSAPI is a powerful API that allows any of these roles to be coded as a SIP servlet application.
SIP is an extensible protocol, and one of the powers of SIP is that the base protocol can be extended to add new features to it. In fact, a number of such RFCs define extensions to the base SIP RFC (3261). This extension mechanism is by and large accomplished by dividing up the SIP processing between the container functions and the applications. Most of the base protocol processing is performed by the container, leaving some of the higher-level tasks for the applications to perform. This clever division is what lends a great deal of power and flexibility to the SSAPI.
The container handles the "non-essential" complexity like network, transactions, dialog management, via headers, and route processing. These are the tasks that are required across different applications, and it would be a redundant exercise to have these in each of the applications separately. All of these tasks are managed by the container leaving applications to provide higher-level functions.
An example would be a proxy application that is deployed on a SIP servlet container. In proxying it has to add its own via header to the request. The via header is required by the base SIP protocol and indicates the entities that were traversed by the request. The via header also contains the branch identifier that acts as the transaction identifier. As the maintenance of transactions and their associated state machine is all maintained by the containers, it is the containers that are required to insert the via headers to the request.
The downstream SIP entity receives the request and sends a response back along the same path. The container then receives the response, removes the via header it inserted in the original request, and processes the response. Note that the application did not have to bother about managing the via headers at all, which makes the life of application developer that much more easy. Several instances exist of a container taking care of mundane but essential protocol details, and some of these will be discussed in this article.
The specification allows for the building of applications that span over different protocols/specifications. This is one of the greatest value propositions of the SSAPI. The specification is also closely aligned with the Java EE specifications, and it is expected that the containers hosting the SIP servlet applications will also make other Java EE features available to the applications—the most notable of which is the HTTP servlet container.
The SSAPI specification is based on the servlet specification and is parallel to the HTTP Servlet specification as shown in Figure 1.
Figure 1. The SIP Servlet Specification, family tree.
The specification allows several applications to execute on the same request or response, so applications execute independently of each other. This is another very powerful feature of the SSAPI. The promise is that the application developers would be able to provide additional features, independent of other applications, and these applications can then be composed to provide a service on a call. This composition happens on the container. The SSAPI is again a little underspecified in this regard and leaves some scope for different implementations to implement this function. The hope is that any such deficiencies will be addressed in the next revision of the specification (JSR 289).
Application data can be stored in container-managed session objects, which can be used for replication or failover. Almost all applications that perform some useful functions have some state between different requests and responses. Some state is mandated by the SIP protocol itself: there is the transaction state machine with its server and client transactions, and then there is the dialog state machine. Then the container has this notion of message context, which encapsulates the SIP level state, and the concept of sessions, which are the SSAPI constructs. However, the applications can save their own state in the Session objects maintained by the container. A carrier grade container will replicate this state such that the call becomes fault tolerant of a container instance.
As you can see, the specification clearly defines the scope and behavior of both SIP servlet containers and SIP servlet applications. The next section explores the Container function.
As you have seen, the SSAPI specification not only specifies the API but also describes the container function. The container is a server that hosts SIP applications (contains them). The container performs a number of SIP functions as specified by various RFCs, therefore taking the burden off the applications; however, it exposes (through the SSAPI) the application to SIP-level messages on which the applications can perform various actions. Different applications therefore can be coded and deployed to the container providing various telecom or multimedia services.
Figure 2 shows the logical layers of a SIP servlet container. The five layers shown from the bottom are what are known as the SIP stack, the functionality of which is defined in the RFC 3261. As a transaction-based protocol, SIP has a well-defined transaction layer. SIP requests are always followed by one or more provisional responses and one final response (with the exception of the ACK, which doesn't have a response); the transaction machinery is designed to keep track of the provisional and final responses.
Figure 2. The SIP servlet container blocks
A concept of a SIP dialog is defined in the specifications. A dialog is a point-to-point session between two SIP endpoints and is uniquely identified by a dialog identifier. Not all SIP requests create dialogs. The requests that create the dialogs have a well-defined mechanism of establishing and tearing down the dialog (that is, INVITE, SUBSCRIBE/NOTIFY, and REFER requests).
The SIP stack shown in Figure 2 does not strictly accord to the RFC 3261—it differs in that there is a layer called the Transaction User (TU) above the Transaction layer, and the dialog management layer is not explicitly a layer in 3261. The layers shown here and as described in the RFC are logical layers; they do not necessarily translate to physical implementation.
The Dialog layer is a very visible constituent of a SIP servlet container because the dialog corresponds roughly to the
SipSession objects, which, in turn, are associated with the
SipApplicationSessions (these will be discussed soon). In the above diagram the Transaction User (TU from RFC 3261) layer is actually split between the Dialog Management layer and the big container block. The primary purpose of the container is to host SIP servlet applications that are written according to the SSAPI implemented by the container. The container exposes objects like
SipServletResponse, different types of sessions, and facilities like timers and logging, to the applications and thereby enables rapid development of powerful applications.
Even though SIP is a text-based protocol, which makes it very easy to understand (it and the base protocol are very nicely defined in RFC 3261), writing SIP applications can be a challenging task. The SSAPI is designed to make it very easy for application developers to build SIP applications. On the one hand, the SSAPI allows access to all the SIP headers present in a SIP request; on the other hand, it does not require the applications to understand or modify all of them for correct protocol behavior. In fact, some headers are strictly off limits for applications. The SSAPI defines the so-called System Headers that are to be managed by the containers only—namely From, To, Call-ID, CSeq, Via, Route (except through pushRoute), Record-Route, and Contact header. Applications can add attributes to the Record-Route header.
The Contact header is a system header field in messages other than REGISTER requests and responses, as well as 3xx and 485 responses. Additionally, for containers implementing the reliable provisional responses extension, RAck and RSeq are considered System headers. In short, the container takes away a lot of processing from the applications as the System header management actually requires a lot of SIP-level activities that otherwise an application had to worry about.
The From/To/Call-ID/CSeq headers together identify a SIP dialog. As you know, some SIP methods, like INVITE and SUBSCRIBE, establish a dialog. The SSAPI container keeps track of the dialog state and dialog-related data, therefore taking an enormous burden off the applications. The SSAPI container has been assigned the management of Record-Route, Contact, and Via headers because the network listen points, failure management of them, multihoming support, and transport switching all are performed by the container. Applications can still participate in the routing decisions of a request emanating from the container by virtue of Request-URI modification and/or Route header addition (pushRoute). This simplifies programming on a SSAPI container as applications using the network-level functionality like routing have no responsibility of managing the network-level resources.
The SSAPI draws heavily from the Java EE standards as it is based on the servlet specifications. One of the biggest advantage that comes from this heritage is the declarative usage of container features like security, mapping, and environment resources. But perhaps the greatest advantage of the SSAPI is the API itself which abstracts a large number of complex SIP tasks behind some intuitive constructs.
The Proxy interface, representing the proxy functionality in SIP, is one good example. A detailed explanation of proxy behavior is available in RFC 3261; a proxy can be stateful or stateless, it can recurse automatically (send requests automatically) on getting a 3xx class response to the Contact address(es) in the response, it can Record-Route to ensure that subsequent requests also go through it, it can act as a forking proxy to proxy to multiple destinations, and it can do that in parallel or in sequence. All these options are simple attributes on the Proxy object. The container-managed Proxy then deals with all low-level details like finding a target set (based on Request-URI or Route headers), applying RFC rules if a strict router is upstream or downstream, creating multiple client transactions, correlating responses, and choosing the best response.
The next section discusses some other important interfaces and constructs of the SSAPI with some examples.
Pages: 1, 2