Introduction
At university, I (co-)teach a fourth year computer science course called Realtime Multimedia in packet-based networks (RTMM). The course is a good fit for students who have done an introductory undergraduate course in networking and it goes a bit further to discuss the practical challenges involved in the delivery of time-sensitive, realtime media over networks such as the Internet. We examine protocols such as RTSP, SIP, SDP, RTP, RTCP and others and have fun with bandwidth calculations for different media codecs. The course aims to give students an appreciation for the "openness" of the Internet and the philosophy which is central to it which is intelligence at the endpoints.In addition to the practical component, the course has always had a strong emphasis on service creation. For this purpose, we used to employ the Asterisk PBX, but recently we have moved to the Mobicents Platform. Mobicents comprises several application services, among them the SIP Servlet container. SIP Servlets is a standard API for the creation of SIP applications based on the Java servlet model. It enables the convergence of SIP and HTTP to create interesting, web-integrated, multimedia applications.
In order to get acquainted with the servlet programming model and to understand the interactions that occur in the container, I recently assigned my students the task of studying the Click to Call servlet application. This application supports the establishment of SIP calls from a web page and controls voice sessions in Back to Back User Agent mode. The task is to examine the application from literally every angle and to generate a set of call flow diagrams that illustrate what is happening between the different parties involved.
As should happen in education, both my students and I learned a lot from the exercise. We were able to generate quite a few scenarios and to understand clearly what was going on using a combination of the source code, Wireshark, Twinkle SIP Client (we found that this client worked really well as it allows you to configure and use two SIP accounts at once) and good ol' server logs.
In this article, I have attached the scenario images for the various use cases of the application that we managed to come up with. Enjoy!
Scenario 1: UA1 Registers and Deregisters
In Scenario 1, the user agent registers by sending a SIP REGISTER request to the container. In order to determine what to do with the request, the container performs application selection which involves determining the list of servlet applications that must be invoked to handle a request. The container requests the DAR (Default Application Router) for a list of applications to invoke in order to handle the request. The list is ordered by priority (in this article, we will assume that click to call is the only application that has been deployed).
The list of applications is retrieved from a text file that is stored in the dars folder of the servlet container. This results in SimpleApplication (the name of the click to call servlet application) being returned to the container. Note that SimpleApplication is a servlet application that contains a SIP servlet called SimpleServlet. A servlet application is allowed to contain one or more SIP or HTTP servlets.
The container delivers the request to SimpleServlet (which is the servlet indicated in the configuration of the application [sip.xml] as the main servlet for this application) which processes the event in its doRegister() event handler. Once received, the servlet sends a 200 OK in response. The same thing happens when the user agent de-registers.
As a side note, according to the servlet model, requests and responses are handled by doRequest() and doResponse() methods respectively (see SIP servlets specification Section 2.2 and 2.3). These methods then pass on the events to corresponding event handlers such as doRegister() for REGISTER requests and doOptions() for OPTIONS requests.
The list of applications is retrieved from a text file that is stored in the dars folder of the servlet container. This results in SimpleApplication (the name of the click to call servlet application) being returned to the container. Note that SimpleApplication is a servlet application that contains a SIP servlet called SimpleServlet. A servlet application is allowed to contain one or more SIP or HTTP servlets.
The container delivers the request to SimpleServlet (which is the servlet indicated in the configuration of the application [sip.xml] as the main servlet for this application) which processes the event in its doRegister() event handler. Once received, the servlet sends a 200 OK in response. The same thing happens when the user agent de-registers.
As a side note, according to the servlet model, requests and responses are handled by doRequest() and doResponse() methods respectively (see SIP servlets specification Section 2.2 and 2.3). These methods then pass on the events to corresponding event handlers such as doRegister() for REGISTER requests and doOptions() for OPTIONS requests.
Scenario 2: UA1 Calls UA2 Directly
In Scenario 2, user agent 1 (caller) attempts to call user agent 2 (callee) directly. Hhowever, at this stage, there is not servlet application that has been configured to process the request. Though SimpleServlet has a doInvite()
event handler in the code, it is a dummy handler that does not do anything.
Furthermore, the INVITE method is not defined as an active event for
SimpleApplication according to DAR rules. According to the SIP servlets specification (see SIP Servlets specification Section 5.6), instead of returning an application name, the DAR returns null to the container and nothing happens. Eventually, the session is invalidated.
Scenario 3: Establishment of a call from the Browser
By registering a second user agent and navigating to the click to call web interface (\click2call) we can establish a call from the browser. With two user agents registered, the option of calling is provided by the call link. When this link is clicked, an HTTP GET request is sent toward the container. The request contains query string parameters (the portion after the ? in the URL) that identify 'to' and 'from' addresses for the call.
This is sent to the HTTP servlet portion of the servlet application called SimpleWebServlet (see the application's web.xml file). The servlet creates and sends a SIP INVITE request in its doGet() event handler toward the SIP address indicated in the 'to' parameter of the URL. Before it does so, it inserts the address of the caller in the application's context which will be used at a later stage. Application context is shared by all servlets (SIP or HTTP) in a given servlet application.
Depending on the user agent, it will probably generate a TRYING provisional response. This is received in the SimpleServlet's doProvisionalResponse() event handler which just logs the event to the console. The same thing goes for the TRYING response.
Note that when the servlet creates and sends a request, it itself is behaving as a user agent. When it does so, the container is required to keep dialog state according to SIP rules. This when the provisional requests are received, routing happens directly and application selection is not performed.
The callee answers the call and sends a final 200 OK response which is received in the doSuccessResponse() event handler. The servlet then creates and sends a SIP INVITE to the caller using the address stored in the servlet context. Once the second 200 OK is received, then ACKs are sent to both parties and communication begins.
The call can be ended using the browser by clicking the 'end' link in the click to call interface. This request works in a similar fashion to the 'call' link in Scenario 3. The doGet() event handler of the web servlet parses the request to find 'bye' attached as a query string parameter. Using a Call object, it sends BYE requests to both parties in sequence. Both parties respond with 200 OK responses. Each is received in the doSuccessResponse() event handler of the SIP servlet.
This is sent to the HTTP servlet portion of the servlet application called SimpleWebServlet (see the application's web.xml file). The servlet creates and sends a SIP INVITE request in its doGet() event handler toward the SIP address indicated in the 'to' parameter of the URL. Before it does so, it inserts the address of the caller in the application's context which will be used at a later stage. Application context is shared by all servlets (SIP or HTTP) in a given servlet application.
Depending on the user agent, it will probably generate a TRYING provisional response. This is received in the SimpleServlet's doProvisionalResponse() event handler which just logs the event to the console. The same thing goes for the TRYING response.
Note that when the servlet creates and sends a request, it itself is behaving as a user agent. When it does so, the container is required to keep dialog state according to SIP rules. This when the provisional requests are received, routing happens directly and application selection is not performed.
The callee answers the call and sends a final 200 OK response which is received in the doSuccessResponse() event handler. The servlet then creates and sends a SIP INVITE to the caller using the address stored in the servlet context. Once the second 200 OK is received, then ACKs are sent to both parties and communication begins.
Scenario 4: Teardown of the call from the Browser
Scenario 5: Teardown of the call from User Agent 1
The call can also be ended through the phone instead of the browser. A BYE request is sent to the container from a phone. This request is known as a subsequent request since it is a request that is sent as part of an already established SIP dialog. Such requests are not subject to application selection either and are routed using the container's state to the appropriate servlet (see Sip Servlet specification Section 15.6). The doBye() event handler of the SIP servlet sends a BYE to the remote party (callee) and sends a 200 OK to the caller. The remote party also sends back a 200 OK.
Scenario 6: Teardown of the call from User Agent 2
This call flow is similar to the above, with the order of events reversed.
Scenario 7: User Agent 2 rejects the Incoming Call
Following the initial call flow steps in scenario 3, it is possible for the callee to reject the incoming call. So instead of accepting the request with a 200 OK, the callee sends a 603 DECLINE in response to the INVITE. This is received in the doErrorResponse() event handler of the SIP servlet. This event handler is responsible for handling all 4xx, 5xx and 6xx error responses (see SIP servlets specification Section 2.5). The servlet removes its state about the call and the container sends an ACK on the application's behalf to the caller.
Scenario 8: User Agent 1 rejects the Incoming Call
Though it does not make much sense from the real world point of view, the caller can reject the incoming call that is initiated from the browser. Note that the ACK to the callee is never sent in this case since ACKs are only sent when both the caller and the callee have answered the calls created by the application. Therefore the callee keeps retransmitting 200 OK responses to the servlet until it times out. A 500 Server Internal Error results from a BYE being sent for a session that was never fully established.
Scenario 9: Call is ended in Browser before UA 2 answers
Following from Scenario 3 again, it is possible for the call to be ended from the browser before the callee answers the call. By clicking the 'end' link in the click to call interface, a BYE is sent to the callee. The callee will respond with a 487 Request Terminated, which is ACKed by the container. Technically, a CANCEL should be sent instead of a BYE. A discussion on this is related here.
Scenario 10: Call is ended in Browser before UA 1 answers
As a follow up to Scenario 9, the caller may opt to end the call before the call is answered on their SIP phone. The interactions are essentially the same as those in Scenario 9.
Scenario 11: UA 2 does not answer the call
In this scenario, the call is initiated through the browser, but the callee ignores it until the request times out. The container sends an ACK on the application's behalf.
Scenario 12: UA 1 does not answer the call
In the last scenario, the callee does not answer the call. The caller's user agent sends a BYE, but since the ACK was never sent to the callee, the callee's user agent responds with a 481 Call Leg does not Exist. This accords with the SIP RFC Sections 21.4.19 and 15.1.1.
Conclusion
The Mobicents SIP servlets container is a powerful platform for the development of web integrated, Internet telephony applications. By combining both HTTP and SIP servlets, interesting applications can be developed. Servlet applications can share a context so that seamless communication can be supported across all servlets in the application, be it HTTP or SIP. The container handles much of the tedious work of managing state.
Application selection also forms the basis for complex service construction in a simple prioritised manner. The platform allows developers to handle requests using a simple doRequest(), doResponse() model that hides some of the complexity of the underlying SIP protocol.
The click to call application is a simple example that effectively communicates the servlet model to provide beginners with the tools they need to enable them to develop converged applications of their own.
Application selection also forms the basis for complex service construction in a simple prioritised manner. The platform allows developers to handle requests using a simple doRequest(), doResponse() model that hides some of the complexity of the underlying SIP protocol.
The click to call application is a simple example that effectively communicates the servlet model to provide beginners with the tools they need to enable them to develop converged applications of their own.























