Sipservlet 1 1 FR Spec
Sipservlet 1 1 FR Spec
Sipservlet 1 1 FR Spec
1
JSR 289 Expert Group
Specification Lead:
Mihir Kulkarni and Yannis Cosmadopoulos Oracle Corporation Please send comments to jsr-289-comments@jcp.org
License
BEA SYSTEMS, INC. ("BEA") IS WILLING TO LICENSE THIS SPECIFICATION TO YOU ONLY UPON THE CONDITION THAT YOU ACCEPT ALL OF THE TERMS CONTAINED IN THIS LICENSE AGREEMENT ("AGREEMENT"). PLEASE READ THE TERMS AND CONDITIONS OF THIS AGREEMENT CAREFULLY. BY DOWNLOADING THIS SPECIFICATION, YOU ACCEPT THE TERMS AND CONDITIONS OF THE AGREEMENT. IF YOU ARE NOT WILLING TO BE BOUND BY IT, SELECT THE "DECLINE" BUTTON AT THE BOTTOM OF THIS PAGE AND THE DOWNLOADING PROCESS WILL NOT CONTINUE. JSR 289 Specification ("Specification") Version: 1.1 Status: Final Release Release: August 1, 2008 Copyright 2008 BEA Systems, Inc. 2315 North First Street, San Jose, CA 95131, U.S.A. All rights reserved. NOTICE; LIMITED LICENSE GRANTS 1. License for Evaluation Purposes. BEA hereby grants you a fully-paid, non-exclusive, non-transferable, worldwide, limited license (without the right to sublicense), under BEA's applicable intellectual property rights to view, download, use and reproduce the Specification only for the purpose of internal evaluation, which shall be understood to include developing applications intended to run on an implementation of the Specification provided that such applications do not themselves implement any portion(s) of the Specification. 2. License for the Distribution of Compliant Implementations. BEA also grants you a perpetual, non-exclusive, non-transferable, worldwide, fully paid-up, royalty free, limited license (without the right to sublicense) under any applicable copyrights or, subject to the provisions of subsection 3 below, patent rights it may have covering the Specification to create and/or distribute an implementation of the Specification that: (a) fully implements the Specification including all its required interfaces and functionality, and (b) passes the Technology Compatibility Kit for such Specification (Compliant Implementation). 3. Reciprocity Concerning Patent Licenses. a. With respect to any patent claims covered by the license granted under subparagraph 2 above that would be infringed by all technically feasible implementations of the Specification, such license is conditioned upon your offering on fair, reasonable and non-discriminatory terms, to any party seeking it from You, a perpetual, non-exclusive, non-transferable, worldwide license under Your patent rights which are or would be infringed by all technically feasible implementations of the Specification to develop, distribute and use a Compliant Implementation.
b With respect to any patent claims owned by BEA and covered by the license granted under subparagraph 2, whether or not their infringement can be avoided in a technically feasible manner when implementing the Specification, such license shall terminate with respect to such claims if You initiate a claim against BEA that it has, in the course of performing its responsibilities as the Specification Lead, induced any other entity to infringe Your patent rights. c Also with respect to any patent claims owned by BEA and covered by the license granted under subparagraph, where the infringement of such claims can be avoided in a technically feasible manner when implementing the Specification such license, with respect to such claims, shall terminate if You initiate a claim against BEA that its making, having made, using, offering to sell, selling or importing a Compliant Implementation infringes Your patent rights. 4. Definitions. For the purposes of this Agreement: Technology Compatibility Kit or TCK shall mean the test suite and accompanying documentation provided by BEA which corresponds to the particular version of the Specification being tested. BEA shall have the right to terminate this Agreement immediately notice if you fail to comply with any material provision of or act outside the scope of the licenses granted above. TRADEMARKS No right, title, or interest in or to any trademarks, service marks, or trade names of BEA or BEA's licensors is granted hereunder. Java is a registered trademark of Sun Microsystems, Inc. in the United States and other countries. DISCLAIMER OF WARRANTIES THE SPECIFICATION IS PROVIDED "AS IS". BEA MAKES NO REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT (INCLUDING AS A CONSEQUENCE OF ANY PRACTICE OR IMPLEMENTATION OF THE SPECIFICATION), OR THAT THE CONTENTS OF THE SPECIFICATION ARE SUITABLE FOR ANY PURPOSE. THE SPECIFICATION COULD INCLUDE TECHNICAL INACCURACIES OR TYPOGRAPHICAL ERRORS. CHANGES ARE PERIODICALLY ADDED TO THE INFORMATION THEREIN; THESE CHANGES WILL BE INCORPORATED INTO NEW VERSIONS OF THE SPECIFICATION, IF ANY. BEA MAY MAKE IMPROVEMENTS AND/OR CHANGES TO THE PRODUCT(S) AND/OR THE PROGRAM(S) DESCRIBED IN THE SPECIFICATION AT ANY TIME. Any use of such changes in the Specification will be governed by the then-current license for the applicable version of the Specification. LIMITATION OF LIABILITY TO THE EXTENT NOT PROHIBITED BY LAW, IN NO EVENT WILL BEA OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES, INCLUDING WITHOUT LIMITATION, LOST REVENUE, PROFITS OR DATA, OR FOR SPECIAL, INDIRECT, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF OR RELATED TO ANY FURNISHING, PRACTICING, MODIFYING OR ANY USE OF THE SPECIFICATION, EVEN IF BEA AND/OR ITS BEAS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
You will indemnify, hold harmless, and defend BEA and its licensors from any claims arising or resulting from: (i) your use of the Specification; (ii) the use or distribution of your application or applet written to and/or Your implementation of the Specification; and/or (iii) any claims that later versions or releases of any Specification furnished to you are incompatible with the Specification provided to you under this license. RESTRICTED RIGHTS LEGEND U.S. Government: If this Specification is being acquired by or on behalf of the U.S. Government or by a U.S. Government prime contractor or subcontractor (at any tier), then the Government's rights in the Software and accompanying documentation shall be only as set forth in this license; this is in accordance with 48 C.F.R. 227.7201 through 227.7202-4 (for Department of Defense (DoD) acquisitions) and with 48 C.F.R. 2.101 and 12.212 (for non-DoD acquisitions). REPORT You may wish to report any ambiguities, inconsistencies or inaccuracies you may find in connection with your use of the Specification ("Feedback"). To the extent that you provide BEA with any Feedback, you hereby: (i) agree that such Feedback is provided on a non-proprietary and non-confidential basis, and (ii) grant BEA a perpetual, non-exclusive, worldwide, fully paid-up, irrevocable copyright license, with the right to sublicense through multiple levels of sublicensees, to incorporate, disclose, and use without limitation the Feedback for any purpose related to the Specification and future versions, implementations, and test suites thereof.
Contents
Preface Overview
Goals of the SIP Servlet API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-1 What is a SIP Servlet? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-2 What is a SIP Servlet Container? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-2 Relationship with the HTTP Servlet API. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-3 Differences from the HTTP Servlet API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-3 Use of Servlet.service() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-4 Asynchronicity. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-4 Application Composition. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-5 Converged Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-5 Deployment Models . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-5 Standalone SIP Servlet Container. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-5 SIP and HTTP Converged Servlet Container . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-5 SIP and Java EE Convergence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-6 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-6 A Location Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-6 A Multi-Protocol Servlet Application. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-7 A Java EE Converged Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-10
Servlet Life Cycle Listener . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-2 Processing SIP Messages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-3 SIP Specific Request Handling Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-3 Receiving Requests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-5 SIP Specific Response Handling Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-6 Number of Instances . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-6
Servlet Context
The SipFactory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-1 Extensions Supported . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-2 RFCs Supported . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-2 Context Path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-2 Context Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-3
Addressing
The Address Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-1 The Parameterable Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-2 The From and To Header Fields. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-3 The Contact Header Field . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-4 Transport Parameters in Contact Header . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-6 URIs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-6 SipURI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-6 TelURL. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-7
Headers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-4 Parameterable and Address Header Fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-5 System Headers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-6 TLS Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-6 Transport Level Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-7 Requests. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-7 Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-7 Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-8 Popped Route Header . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-9 Responses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-10 Reliable Provisional Responses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-10 Buffering. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-11 Accessibility of SIP Servlet Messages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-11 Internationalization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-12 Indicating Preferred Language . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-12 Indicating Language of Message Content . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-13
Sessions
SipApplicationSession. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-2 Protocol Sessions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-2 SipApplicationSession Lifetime. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-3 SipApplicationSession Timer Operation and SipApplicationSession Expiration 6-4 SipApplicationSession Invalidation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-4 Binding Attributes into a SipApplicationSession. . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-7 SipSession . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-7 Relationship to SIP Dialogs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-7 Cancel Message Processing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-11 Maintaining Dialog State in the SipSession . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-11
When in a Dialog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-11 When in the INITIAL SipSession State . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-11 Creation of SipSessions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-12 Extensions Creating Dialogs. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-13 Derived SipSessions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-13 SipSession Lifetime . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-14 SipSession Invalidation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-14 Important Semantics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-18 The RequestDispatcher Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-19 The SipSession Handler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-19 Binding Attributes into a SipSession . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-19 Last Accessed Times. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-20 Important Session Semantics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-20 Message Context . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-20 Threading Issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-21 Distributed Environments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-21
Servlet Application Classloader . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-6 Replacing a Servlet Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-6 Servlet Application Environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-7
Timer Service
TimerService . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-1 ServletTimer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-2 TimerListener . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-3
Proxying
Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-1 Operation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-3 Proxy Branches. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-4 Pushing Route headers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-6 Sending Responses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-6 Receiving Responses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-7 Handling 2xx Responses to INVITE. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-8 Correlating responses to proxy branches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-9 Sequential Search Timeout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-10 Handling 3xx responses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-10 Sending CANCEL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-11 Receiving CANCEL. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-11 Sending ACK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-12 Receiving ACK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-12 Handling Subsequent Requests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-12 Max-Forwards Check . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-13
Proxying and Sessions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-13 Record-Route Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-14 Path Header and Path Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-15
Linked SipSessions And Linked Requests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-3 Explicit Session Linkage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-3 Implicit Session Linkage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-5 Access to Un-Committed Messages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-5 Original Request and Session Cloning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-6 Cloning and Linking. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-6
Container Functions
Division of Responsibility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-1 Protocol Compliance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-2 Multihomed Host Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-3 Application Composition on Multihomed Container . . . . . . . . . . . . . . . . . . . . . . . . 14-4
Application Independence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-4 Subscriber Identity and Routing Regions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-5 Routing Directives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-7 Application Environment and Behaviour . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-7 Receiving an Initial Request . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-7 Sending an Initial Request . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-7 Application Router Behavior . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-11 Order of Routing Regions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-13 Inter-Container Application Routing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-14 Container Behavior . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-14 Procedure for Routing an Initial Request. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-15 Application Router Packaging and Deployment . . . . . . . . . . . . . . . . . . . . . . . . . . 15-17 Application Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-17 Responses, Subsequent Requests and Application Path . . . . . . . . . . . . . . . . . . . . . . . . 15-18 Transport Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-20 Popping of Top Route Header. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-21 Container Behavior . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-21 Top Route Processing Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-21 Request with two route headers arriving at the container. . . . . . . . . . . . . . . . 15-21 Application pushes route pointing back at the container . . . . . . . . . . . . . . . . 15-22 Application pushes external route. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-23 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-23 Example with Two Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-24 Simple call with no modifications of requests . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-26 Modification of Headers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-27 Reversing the Direction of the Call . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-28 Initiating a New Request . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-29 Loop Detection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-29
8 JSR 289: SIP Servlet Specification v1.1
Session Targeting. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-29 Session Targeting and Application Selection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-30 Session Key Based Targeting Mechanism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-31 The Encode URI Mechanism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-33 Join and Replaces Targeting Mechanism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-34 Resolving Session Targeting Conflicts. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-36
Security
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17-1 Declarative Security. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17-2 Programmatic Security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17-2 Roles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17-3 Authentication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17-4 Server Tracking of Authentication Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17-4 Propagation of Security Identity in EJBTM Calls. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17-5 Specifying Security Constraints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17-5 Default Policies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17-7 Authentication of Servlet Initiated Requests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17-8 Description of the Procedure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17-9
@SipServlet Annotation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18-4 @SipApplication Annotation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18-6 @SipListener Annotation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18-9 @SipApplicationKey Annotation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18-10 Annotation for SipFactory Injection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18-11 Annotation for SipSessionsUtil Injection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18-11 Annotation for TimerService Injection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18-12 Annotation Parsing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18-13
Deployment Descriptor
Differences from the HTTP Servlet Deployment Descriptor . . . . . . . . . . . . . . . . . . . . . 19-1 Converged SIP and HTTP Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19-2 Deployment Descriptor Elements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19-2 Rules for Processing the Deployment Descriptor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19-3 The SIP Servlet XSD. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19-4
10
References Glossary
11
12
Preface
This specification defines version 1.1 of the SIP Servlet API. The specification requires J2SE 5.0 and support for SIP as defined in [RFC 3261]. The following IETF specifications referenced in this specification provide information relevant to the development and implementation of the SIP Servlet API and SIP Servlet containers: [RFC 3265], [RFC 3262], [RFC 2976], [RFC 3311], [RFC 3515], [RFC 3903], [RFC 3841], [RFC 3966], [RFC 3327], [RFC 3725], [RFC 3856], [RFC 4028], [RFC 3326] Online versions of these RFCs are available at http://www.ietf.org/rfc.
Terminology
In this document, the key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" are to be interpreted as described in BCP 14, RFC 2119 [2] and indicate requirement levels for compliant JSR 289 implementations.
xiii
P re fa c e
Typographic Conventions
Java classes, method names, parameters, literal values, and fragments of code are printed in constant width as are XML elements and documents.
Providing Feedback
Feedback on this specification is welcome. Please e-mail your comments to jsr-289-comments@jcp.org
Acknowledgements
This specification was developed under the Java Community Process 2.6 as JSR 289. The JSR 289 expert group consists of the following members: Hira Agrawal (Telcordia Technologies Inc.), Bartosz Baranowski (Red Hat Middleware LLC), Diego Besposvan (Mailvision LTD), Chris Boulton (Avaya, Inc), Matthias Britsch (T-Mobile International AG & Co. KG), Erik Burckart (IBM), Eric Cheung (AT&T), David Connelly, Christophe Dejouhanet (Orange France SA), Jean Deruelle (Red Hat Middleware LLC), Simon Dutkowski (Fraunhofer-Gesellschaft Institute FIRST), Sreeram Duvur (Sun Microsystems, Inc.), Tomas Ericson (Oracle), Jarek Wilkiewicz (Hewlett-Packard), Goran Eriksson (Ericsson AB), Ian Evans (Avaya, Inc), Anat Fradin (IBM), Kristoffer Gronowski (Ericsson AB),
xiv JSR 289: SIP Servlet Specification v1.1
Robert Handl (Ericsson AB), Avshalom Houri (IBM), Ivelin Ivanov (Red Hat Middleware LLC), Akinori Iwakawa (Fujitsu Limited), Hakan Jonsson (Appium Technologies AB), Nasir Khan, Yueh Lee (Cisco Systems), Thomas Leseney (Nexcom Systems), Johan Liseborn (Oracle), Stephane H. Maes (Oracle), Roger N. Mahler (Cingular Wireless), Gines Gomez Martinez (Voztelecom Sistemas S.L.), Remy Maucherat (Apache Software Foundation), Francesco Moggia (Telecom Italia), Phelim O'Doherty (Oracle), Amir Perlman (IBM), Marc Petit-Huguenin (8x8), Per Pettersson (Ericsson AB), Jean-Pierre Pinal (Nexcom Systems), Kermit Hal Purdy (AT&T), Uri Segev (IBM), James Steadman (Oracle), Prasad Subramanian (Sun Microsystems, Inc.), Atul Varshneya, Lebing Xie (Fraunhofer-Gesellschaft Institute FIRST), Sami Samandi (Netcentrex) Damian ONeill (Aepona Technologies AB)
xv
P re fa c e
We would like to thank Anders Kristensen (Cisco Systems Inc.) and the members of the JSR 116 Expert Group who developed the Sip Servlet Specification v1.0 that contributed immensely to the development of the v1.1 specification. This specification builds on the Sip Servlet Specification v1.0 and for this reason, this specification copies text from the v1.0 specification in many places [SIP Servlet API]. Additionally, Rhys Ulerich of IBM, Paul Devine, Michael Palmeter, Vinod Mehra and Anno Langen of BEA Systems made enormous contributions to this specification. We would like to thank Paul Sydell of Oracle for his help with Java EE schema alignment, Adrian Kalaveshi of Oracle for his help with administrating the collaborative site used by the JSR 289 expert group and David Yozie of Oracle for his help in drafting this specification as a PDF. An important goal of the SIP Servlet API is to build on the work of the well-established (HTTP) Servlet API. For this reason, this specification copies text from the Java Servlet Specification in many places [Servlet API]. The glossary includes a large number of entries copied from the SIP specification [RFC 3261]. This specification draws and adapts the the principles of application independence, composition, and selection from Distributed Feature Composition [DFC1998], [CN2004], [SE2005]. This specification makes use of Java annotations introduced in J2SE 5.0 and re-uses common annotations for Java platform [JSR250].
xvi
SECTION
1 Overview
The Session Initiation Protocol (SIP) is used to establish, modify, and tear down IP multimedia sessions including IP telephony, presence, instant messaging besides other SIP applications. An important aspect of any communication infrastructure is programmability and the purpose of the SIP Servlet API is to standardize the platform for delivering SIP based services. The term platform is used here to include the Java API itself as well as standards covering the packaging and deployment of applications.
1-1
Overvie w
Application composition: It is possible for several applications to execute on the same incoming or outgoing request or response. Each application has its own set of rules and executes independently of other applications in a well-defined and orderly fashion. Carrier grade: Servlets store application data in container managed session objects. Implementations may persist and/or replicate this data to achieve high availability.
1-2
R e l at i o ns h i p w i t h th e H T T P Ser v l e t AP I
1-3
Overvie w
generate multiple response (for example, one or more 1xx followed by a final response) proxying requests, possibly to multiple destinations initiate requests receive responses as well as requests
This is the application entry point used by the HTTP Servlet API also, but it is used slightly differently here. When used to process SIP traffic only one of the request and response objects is non-null. When invoked to handle incoming requests, the response argument will be null and vice versa, when invoked to handle incoming responses the request argument will be null. Note: This caters for the fact that there is not necessarily a one-to-one correspondence between requests and responses in SIP applications.
1.4.1.2 Asynchronicity
Another important difference is the fact that the SIP Servlet API event model is asynchronous rather than synchronous as in the HTTP API. This means that applications are not obliged to respond to incoming requests in the upcall reporting the event. They may initiate some other action, return control to the container, and then respond to the request at some later point in time. The container relies on timeout of the application instance as a whole in order to guarantee that resources are always recovered eventually, even if an application fails to respond to the request in a timely manner. Asynchronicity simplifies the programming of event driven services and allows an application such as a B2BUA not to hog threads while waiting for a potentially long-lived transaction to complete.
1-4
Dep loyme nt Mo de ls
Overvie w
reason, it is an important goal that it be possible to implement a servlet container that supports both the SIP and HTTP Servlet APIs at the same time and in a manner that allows applications to include both SIP and HTTP components.
1.6 Examples
1.6.1 A Location Service
Routing is an integral part of SIP and is a common function of SIP services. This example is a Location Service SIP application that performs a database lookup on the request URI of incoming requests and proxies the request to a set of destination addresses associated with that URI. The steps performed by the application and container are as follows: 1. Alice makes a call to sip:bob@example.com. The INVITE is received by the servlet container which invokes the Location Service. 2. The Location Service application determines, using non-SIP means, that the callee (Bob) is registered with two locations, identified by, say, two SIP URIs. 3. The service proxies to those two destinations in parallel, without record-routing, and in unsupervised mode. One of the destinations return 200 (OK) response and the other branch is cancelled by the container. 4. The 200 response is forwarded upstream to Alice and the call setup is completed as usual. In this example, the application (and the host application server) is involved only in establishing the SIP dialog and will not be involved in subsequent signaling within that dialog.
1-6
Exa mpl es
1-7
Overvie w
10. Alice gasps at the sight of this amazing application and hits the Submit button on the HTML page thus causing an HTTP request to be sent to the application server. 11. The service sends a SIP SUBSCRIBE request to Bobs SIP UA. This will allow the service to know when Bob becomes available again. 12. Bobs UA accepts the subscription. 13. The HTTP CSBNA servlet returns a Web page to Alice which she can subsequently use to modify or cancel the scheduled call. 14. At some later point in time, Bob hangs up and his UA sends a notification of his new availability status to the CSBNA subscriber servlet in a SIP NOTIFY request. 15. The CSBNA application responds to the NOTIFY. (The application will unsubscribe from Bobs status at this pointthis is not shown in the diagram.)
1-8
Exa mpl es
In steps 16 through 24, the application establishes a call between Alice and Bob using the third party call control mechanisms described in [3pcc]. In this case, a call is established and media is exchanged over RTP. In steps 25 through 28, the call is terminated. In addition to illustrating the functioning of a converged container, this example demonstrates the need for the concept of application sessions. Over the lifetime of an instance of the CSBNA application, some 5 point-to-point SIP signaling relationships are created. Each of these correspond to a SipSession instance. Additionally, one HttpSession is createdthis also corresponds to a point-to-point signaling relationship between the container and the HTTP client. Obviously, all of these protocol sessions are related and need to share state. The application session represents an instance of the application and binds together the protocol sessions representing individual signaling relationships and allows for sharing of state between them. The session model is further discussed in chapter 6 Sessions.
1-9
Overvie w
1-10
Exa mpl es
4. The SIP Servlet sends a 200 OK to the SUBSCRIBE and a NOTIFY according to the SIP procedures defined in [RFC 3265]. 5. At some later time the user profile changes. The UA profile is managed by an abstract database which sends a JMS message to the application server whenever the profile is modified. The EJB (which is actually a MDB) in the application gets a JMS message on its queue. The message contains an identifier which tells us which UA this profile update is for. 6. The EJB maintains a map of UAs and the current sip-application-session-id. On getting the JMS message for a certain UA, it retrieves the sip-application-session-id from its map. 7. The MDB, which has access to the SipSessionsUtil utility, retrieves the SipApplicationSession reference using the sip-application-session-id. 8. Since the MDB also knows the SipSession id (previously set by the SipServlet and stored alongside the sip-application-session-id), it gets to the right SIP dialog from the SipApplicationSession. 9. Using normal in-session request creating mechanism the bean creates a new SIP NOTIFY request and sends the profile changes as payload on the dialog to the SIP UA 10. The SIP UA gets this SIP NOTIFY with profile data and sends a 200 OK. This 200 OK gets delivered to the SIP Servlet and the process completes.
1-11
Overvie w
1-12
SECTION
The Servlet interface is the central abstraction of the Servlet API and hence of the SIP Servlet API. All servlets implement this interface either directly or, more commonly, by extending a class that implements the interface. The generic Servlet API defines a class GenericServlet that is an implementation of the Servlet interface. The SIP Servlet API defines a class SipServlet that extends the GenericServlet interface and performs dispatching based on the type of message received. For most purposes, developers will extend SipServlet to implement their servlets.
Very briefly, the servlet container loads the servlet class, instantiates it and invokes the init() method on it, passing along configuration information in the form of a ServletConfig object. Having been successfully initialized, the servlet is available for service, and the container repeatedly invokes the service by calling the service() method with arguments representing
2-1
The Se r vlet In t er fa ce
incoming requests and responses. When the container decides to deactivate the servlet instance it invokes the destroy() method the servlet frees up resources allocated in init() and becomes garbage collected. The failure to initialize any of the servlet within the application MUST be taken as failure of the entire application and the application MUST be taken out of service. If the failed servlet was a load-on-startup servlet then the Application Router MUST NOT be notified of this application's deployment using SipApplicationRouter.applicationDeployed(). The Application Router component is described in detail in 15 Application Selection And Composition Model. If the servlet happened to not be a load-on-startup but the initialization of it failed then the Applictaion Router MUST be informed of this application's undeployment using SipApplicationRouter.applicationUndeployed().
The following sequence of intialization MUST be followed for a load-on-startup servlet. 1. Deploy the application. 2. Invoke Servlet.init(), the initialization method on the servlet. Invoke the init() on all the load-on-startup servlets in the application. 3. Invoke SipApplicationRouter.applicationDeployed() for this application. 4. If present, invoke SipServletListener.servletInitialized() on each of initialized servlet's listeners. For applications without any servlets declared as load-on-startup, the SipApplicationRouter.applicationDeployed() MUST be invoked right after the
2-2
deployment has succeeded. The init() method on these servlets and servletInitialized() callback methods on their listener's would be called just before getting the first request.
If the message is a request the response argument MUST be null, and if the message is a response, the request argument MUST be null. When invoked to process a SIP event, the arguments must implement the SipServletRequest or SipServletResponse interfaces as the case may be. The SipServlet implementation of the service method dispatches incoming messages to methods doRequest and doResponse for requests and responses, respectively:
protected void doRequest(SipServletRequest req); protected void doResponse(SipServletResponse resp);
These methods then dispatch further as described in the following sections. Note: Section 18.2.2 @SipServlet Annotation describes an alternative mechanism of declaring the Servlet class by using annotations.
2-3
The Se r vlet In t er fa ce
doAck for handling SIP ACK requests doOptions for handling SIP OPTIONS requests doBye for handling SIP BYE requests doCancel for handling SIP CANCEL requests doRegister for handling SIP REGISTER requests doPrack for handling SIP PRACK requests doSubscribe for handling SIP SUBSCRIBE requests doNotify for handling SIP NOTIFY requests doMessage for handling SIP MESSAGE requests doInfo for handling SIP INFO requests doUpdate for handling SIP UPDATE requests doRefer for handling SIP REFER requests doPublish for handling SIP PUBLISH requests
The first six Java methods correspond to request methods defined in the baseline SIP specification [RFC 3261]. The following methods correspond to request methods defined in various SIP extensions. PRACK is defined in [RFC 3262] and is discussed in 5.7.1 Reliable Provisional Responses. The SUBSCRIBE and NOTIFY methods are defined in the SIP event notification framework [RFC 3265] upon which the SIP presence framework is defined [simple]. The MESSAGE method supports instant messaging [IM], the INFO method is a general purpose mid-dialog signaling transport mechanism [RFC 2976], the UPDATE method is used as a mechanism to update SIP session parameters without affecting dialog state [RFC 3311], the REFER method is used for transfer of SIP calls [RFC 3515] and the PUBLISH method introduced in [RFC 3903] is a mechanism for SIP specific event state publication. The SipServlet implementation of these methods is as follows. The doAck and doCancel methods do nothing. All other methods check whether the request is an initial request, as described in 10.2.9 Handling Subsequent Requests. If the request is initial, it is rejected with status code 501; otherwise the method does nothing (if the application proxied the initial request, the container will proxy the subsequent request when the method call returns). A servlet will typically override only those methods that are relevant for the service it is providing.
2-4
Note: The handling of incoming requests is asynchronous in the sense that servlets are not required to fully process incoming requests in the containers invocation of the service method. The request may be stored in a SipSession or SipApplicationSession object to be retrieved and responded to latertypically triggered by some other event. The container will not generate a response of its own if a servlet returns control to the container without having responded to an incoming request. Applications wishing to handle SIP methods unknown to SipServlet.doRequest can override this method and invoke super as follows:
protected void doRequest(SipServletRequest request) throws ServletException, IOException { if ("STORE".equals(request.getMethod())) { doStore(request); } else { super.doRequest(request); } }
2-5
The Se r vlet In t er fa ce
Chapters 10 and 11 describe, in detail, the rules surrounding the invocation of these methods.
2-6
SECTION
3 Servlet Context
The ServletContext defines a servlets view of the SIP application within which the servlet is running. Chapter 3 of the Java Servlet Specification describes the ServletContext [Servlet API] and it applies to the SIP servlet API, also. The following sections address issues specific to the SIP Servlet API.
3-1
Containers compliant with this specification MUST make the SipFactory instance available via this annotation as described in 13.2 Accessing SIP Factory.
As far as resource loading is concerned, the context path of a SIP-only servlet is always /. For a combined HTTP and SIP application executing in an HTTP Servlet capable container, the context path is defined by the HTTP Servlet API and resource loading proceeds according to the Java Servlet Specification [Servlet API].
3-2
Co nt e x t Pa r am e t e r s
Description
An immutable instance of the java.util.List interface containing the String names of SIP extensions supported by the container. An immutable instance of the java.util.List interface containing the RFC numbers represented as Strings of SIP RFCs supported by the container. Parameter whose value suggests whether the container supports the 100rel extension i.e. RFC 3262. This parameter has been deprecated in this specification in favor of the javax.servlet.sip.supported parameter.
javax.servlet.sip.supportedRf cs javax.servlet.sip.100rel
A container class SipSessionsUtil for ID based lookup of SipApplicationSession instances. Instance of the applications SipFactory. An immutable instance of the java.util.List interface containing the SipURI representation of IP addresses which are used by the container to send out the messages.
3-3
3-4
SECTION
4 Addressing
Addressing plays a role in many SIP functions and so, in addition to the request URI, many header fields are defined to carry one or more addresses, for example, From, To, and Contact. The format of these addresses is generally the same. They consist of a URI with an optional display name and an optional set of parameters. Figure 4-1 shows the addressing abstractions of the SIP Servlet API and the relationship between them. Figure 4-1 Addressing Abstractions
The SipFactory interface described in 3.1 The SipFactory is used to construct instances of these interfaces.
4-1
Ad dr ess in g
The constituent non-terminals are defined in RFC 3261, chapter 25, and are (incompletely) given below for ease of reference.
name-addr= [ display-name ] LAQUOT addr-spec RAQUOT addr-spec = SIP-URI / SIPS-URI / absoluteURI display-name = *(token LWS)/ quoted-string
The baseline SIP specification defines the following set of header fields that conform to this grammar: From, To, Contact, Route, Record-Route, Reply-To, Alert-Info, Call-Info, and Error-Info [RFC 3261]. The SipServletMessage interface defines a set of methods which operate on any address header field (see 5.4.1 Parameterable and Address Header Fields). This includes the RFC 3261 defined header fields listed above as well as extension headers such as Refer-To [refer] and P-Asserted-Identity [privacy]. It is highly likely that future SIP extensions will define more such header fields and so it is useful to have a set of generic methods that can be used by applications to access header fields as Address objects rather than as Strings. SIP Servlet containers will typically have built in knowledge of certain headers but are required to be able to handle unknown headers as well. When an application attempts to access an unknown header as an address header (by calling one of the methods discussed in 5.4.1 Parameterable and Address Header Fields), the container MUST try to parse all values of that header field as Address objects according to the address rule. The actual definition of address-based header fields differs in small ways: some define specific parameters and possibly limit the set of values they can take, for example, the From and To headers define a tag parameter which, when present, must be a token. some may not have parameters at all, for example, Reply-To. some may not have a display name The address BNF rule can be thought of as defining a superset of all legal values for a large number of header fields. If the SIP Servlet container knows the actual, possibly more restrictive, definition for a particular address-based header it should enforce any such constraint when serializing a message.
4-2
where the field-value may be in name-addr or addr-spec format as defined in RFC 3261 or may be any sequence of tokens till the first semicolon. The list of headers in RFC 3261 that follow this form are Accept, Accept-Encoding, Accept-Language, Alert-Info, Call-Info, Content-Disposition, Content-Type, Error-Info, Retry-After and Via. The Address API manifests a specialized form of this BNF for Address headers like Contact, From, To, Route, Record-Route and Reply-To. Besides these there are a number of other extensions where this form is applicable like Accept-Contact and Reject-Contact from RFC 3841. A generic Parameterable interface caters to all the SIP headers of this form. The Address interface extends this interface. Methods are available in SipFactory to create a Parameterable object from a String object and SipServletMessage to read/write Parameterable objects. In general any SIP header having parameters as in form described above, MUST be available as Parameterable to the application.
4-3
Ad dr ess in g
Applications can change all parts of the Address returned by the above methods except the tag parameter. The tag parameter MUST NOT be modified by applications and containers MUST throw an IllegalStateException if an attempt is made to set the tag parameter for these headers. The following methods operating on the From and To headers MUST continue to throw IllegalArgumentException:
SipServletMessage.setAddressHeader("From", fromHdr) SipServletMessage.addAddressHeader("To", toHdr) SipServletMessage.removeAddressHeader("From", fromHdr)
Note: Containers that need to support [RFC 2543] MUST NOT allow modification of the From and To headers as that RFC requires the entire URI for dialog identification. Container support for Connected Identity [RFC 4916] is optional in this specification and is indicated by the presence of the "from-change" option tag in the javax.servlet.sip.supported list. (see 3.2 Extensions Supported).
4-4
The special Contact value * is used in REGISTER requests when the UAC wishes to remove all bindings associated with an address-of-record without knowing their precise values. The isWildcard method returns true for Address objects representing the wildcard Contact value and SipFactory.createAddress will return a wildcard Address given a value of *. Note that wildcard Address objects are legal only in Contact header fields. Contact header is a system header which means that it is managed by the container and cannot be modified or set by the applications except for the following messages: 1. REGISTER requests and responses 2. 3xx responses 3. 485 responses 4. 200/OPTIONS responses Unlike other system headers defined in this specification some of the Contact header constituents are modifiable by applications as described below : 1. A UA application MUST be able to set parameters in the Contact header. 2. A UA application MUST be able to set the user part of the Contact header. 3. Also as per Sec 11.2 of RFC 3261 "Contact header fields MAY be present in a 200 (OK) response and have the same semantics as in a 3xx response. That is, they may list a set of alternative names and methods of reaching the user." So UAs responding to OPTIONS must be capable of setting Contact header(s) like in a 3xx response. The UA applications can perform the above 3 operations on the Contact URI as retrieved using the following API:
SipServletMessage.getAddressHeader("Contact");
Note that the Address returned should be good only for specifying a set of parameters that the application can set on Address and/or URI and set the user part in the URI. The host component of the URI and URI Scheme are irrelevant and cannot be trusted to reflect the actual values that the container will be using when inserting a Contact header into Request or Response. The container MUST ignore or overwrite any host/port set on the Contact URI accessed as above. This is because the container is responsible for managing the actual network listen points and uses these to create Contact headers' host/port. Further following list of URI parameters MUST NOT be modified by the applications and containers MUST ignore any value for these parameters if set by applications.
JSR 289: SIP Servlet Specification v1.1 4-5
Ad dr ess in g
method ttl maddr lr The applications may set any other SIP URI parameter or Contact header parameter relevant for the message. The following method MUST continue to throw IllegalArgumentException wherever the Contact header is defined as system header by this specification:
SipServletMessage.setAddressHeader("Contact", contactHdr);
In case the application modifies the Contact as specified above but decides to proxy the request subsequently, the containers MUST ignore any modification made to the Contact header.
4.2 URIs
SIP entities are addressed by URI. When initiating or proxying a request, SIP servlets identify the destination by specifying a URI. SIP defines its own URI scheme that SIP containers are required to support. Particular implementations may know how to handle other URI schemes, e.g. tel URLs [RFC 3966]. Implementations are required to be able to represent URIs of any scheme, so that if, for example, a 3xx response contains a Contact header with a mailto or http URL, the container is able to construct Address objects containing URIs representing those Contact URIs. Also, SipFactory.createURI should return a URI instance given any valid URI string. The container may not be able to route SIP requests based on such URIs but must be able to present them to applications.
4.2.1 SipURI
This interface represents SIP and SIPS URIs. Implementations are required to be able to route requests based on SIP URIs.
4-6
URIs
SIP and SIPS URIs are similar to email addresses in that they are of the form user@host where user is either a user name or telephone number, and host is a host or domain name, or a numeric IP address. Additionally, SIP/SIPS URIs may contain parameters and headers. See RFC 3261, section 19.1.1 for restrictions on the contexts in which various parameters are allowed. Headers are allowed only in SIP/SIPS URIs appearing in Contact headers or in external URIs, for example when being used as a link on a Web page. As an example, the following SIP URI:
sip:alice@example.com;transport=tcp?Subject=SIP%20Servlets
contains a transport parameter with value tcp and a Subject header with value SIP Servlets. The string form of SIP/SIPS URIs may contain escaped characters. The SIP servlet container is responsible for unescaping those characters before presenting URIs to servlets. Likewise, string values passed to setters for various SIP/SIPS URI components may contain reserved or excluded characters that need escaping before being used. The container is responsible for escaping those values as necessary. Syntactically, SIP and SIPS URIs are identical except for the name of the URI scheme. The semantics differ in that the SIPS scheme implies that the identified resource is to be contacted using TLS. Quoting from RFC 3261: A SIPS URI specifies that the resource be contacted securely. This means, in particular, that TLS is to be used between the UAC and the domain that owns the URI. From there, secure communications are used to reach the user, where the specific security mechanism depends on the policy of the domain. Any resource described by a SIP URI can be upgraded to a SIPS URI by just changing the scheme, if it is desired to communicate with that resource securely. SIP and SIPS URIs are both represented by the SipURI interface as theyre syntactically identical and are used the same way. The isSecure method can be used to test whether a SipURI represents a SIP or a SIPS URI and the setSecure method can be used to change the scheme.
4.2.2 TelURL
This interface represents tel URLs as defined in [RFC 3966]. The tel URL scheme is used to represent addresses of terminals in the telephone network, i.e. telephone numbers. SIP servlet containers may or may not be able to route SIP requests based on tel URLs, but must be able to parse and represent them. SipFactory.createURI must return an instance of the TelURL interface when presented with a valid tel URL.
4-7
Ad dr ess in g
4-8
SECTION
This chapter describes the structure of SIP servlet message objects. Chapters 10 and 11 describe operational aspects of message processing.
5-1
A SipServletMessage for which one of the following conditions is true is called committed: the message is an incoming request for which a final response has been generated the message is an outgoing request which has been sent the message is an incoming non-reliable provisional response received by a servlet acting as a UAC the message is an incoming reliable provisional response for which PRACK has already been generated. (Note that this scenario applies to containers that support the 100rel extension.) the message is an incoming final response received by a servlet acting as a UAC for a Non INVITE transaction the message is a response which has been forwarded upstream message is an incoming final response to an INVITE transaction and an ACK has been generated message is an outgoing request, the client transaction has timed out and no response was received from the UAS and the container generates a 408 response locally The semantics of committed message is that it cannot be further modified or sent in any way. Also see 5.8 Accessibility of SIP Servlet Messages.
5-2
The interface parallels how the JavaMail API defines access to message content in the javax.mail.Part interface [JavaMail]. The getRawContent method is not present in JavaMail but is useful when writing back-to-back user agents (B2BUA) as these may wish to copy content from one message to another without incurring the overhead of parsing it (as they may not actually care what is in the body). Which type of Object is returned by getContent depends on the messages Content-Type. It is required to return a String object for MIME type text/plain as well as for other text MIME media types for which the container does not have specific knowledge. It is encouraged that the object returned for multipart MIME content is a javax.mail.Multipart object. For unknown content types other than text, the container must return a byte[]. Likewise, setContent is required to accept byte[] content with any MIME type, and String content when used with a text content type. When invoked with non-String objects and a text content type, containers should invoke toString() on the content Object in
5-3
order to obtain the body's character data. Again, it is recommended that implementations know how to handle javax.mail.Multipart content when used together with multipart MIME types.
Character encodings are identified by strings and generally follow the conventions documented in [RFC 2278]. The character encoding may affect the behavior of methods getContent and setContent. A messages character encoding may be changed by calls to setCharacterEncoding and setContentType. For incoming messages, the character encoding is specified by the charset parameter of the Content-Type header field, if such a parameter is present. Note: Because of evolution of servlet spec 2.4,
SipServletResponse.setCharacterEncoding() which extends both SipServletMessage and ServletResponse now does not throw the UnsupportedEncodingException because it inherits a more generic method from ServletResponse. This is a binary compatibile change, meaning that the compiled
applications shall run on the v1.1 containers without change but it is not a source compatibile change if the application is explicitly catching the UnsupportedEncodingException on
SipServletResponse.setCharacterEncoding().
5.4 Headers
A servlet can access the headers of a SIP message through the following methods of the SipServletMessage interface (see also [Servlet API, sections 4.3 and 5.2]):
String getHeader(String name); ListIterator getHeaders(String name); Iterator getHeaderNames(); void setHeader(String name, String value); void addHeader(String name, String value);
5-4
Headers
The getHeader method allows access to the value of a named header field. Some header fields, for example Warning, may have multiple values in a SIP message. In this case getHeader returns the first value of the header field. The getHeaders method allow access to all values of a specified header field by returning an iterator over String objects representing those values. The setHeader method sets a header with a given name and value. If a previous header exists, it is replaced by the new header. In the case where a set of header values exist for the given name, all values are cleared and replaced with the new value. The addHeader method adds a header with the specified name and value to the message. If one or more headers with the given name already exists, the new value is appended to the existing list.
If a header field has multiple Parameterable values in a message, the getParameterableHeader method returns the first value. The getParameterableHeaders method allows access to all values of the specified header field returning an iterator over Parameterable objects. The same explanation applies to the getAddressHeader and getAddressHeaders methods if a header field has multiple Address values.
Parameterable and Address objects obtained from, or added to messages are live in the sense that modifications made to them cause the corresponding header field value of the underlying message or messages to be modified accordingly.
5-5
Parameterable and Address objects may belong to more than one SipServletMessage at a
time. In this case modification of any Parameterable or Address object will result in modification of the value of the underlying header field for both messages. This sort of aliasing can result in bugs when not intended. Application writers may practice defensive programming by deep cloning the Parameterable and Address objects to avoid sharing.
5-6
connection is hop-by-hop this TLS certificate is not available beyond the first application in case of application composition chain as described in 15.7 Transport Information.
These methods have meaning for incoming messages only, in which case they return the IP address/port number on which the message was received locally (getLocalAddr, getLocalPort), or the IP address/port number of the sender of the message (getRemoteAddr, getRemotePort, getInitialRemoteAddr, getInitialRemotePort), as well as the transport protocol used, e.g. UDP, TCP, TLS, or SCTP.
5.6 Requests
The SipServletRequest object encapsulates information of a SIP request, including headers and the message body.
5.6.1 Parameters
Request parameters are strings sent by the client to a servlet container as part of a request. The parameters are made available to applications as a set of name-value pairs. Multiple parameter values can exist for any given parameter name. The following ServletRequest methods are available to access parameters:
String getParameter(String name); Enumeration getParameterNames(); String[] getParameterValues(String name);
5-7
The getParameterValues method returns an array of String objects containing all the parameter values associated with a parameter name. The value returned from the getParameter method must always equal the first value in the array of String objects returned by getParameterValues. Note: Support for multi-valued parameters is defined mainly for HTTP because HTML forms may contain multi-valued parameters in form submissions. When passing an incoming SipServletRequest to an application, the container populates the parameter set in a manner that depends on the nature of the request itself: For initial requests where the application is invoked the parameters are those present on the request URI, if this is a SIP or a SIPS URI. For other URI schemes, the parameter set is undefined. For initial requests where a preloaded Route header specified the application to be invoked, the parameters are those of the SIP or SIPS URI in that Route header. For subsequent requests in a dialog, the parameters presented to the application are those that the application itself set on the Record-Route header for the initial request or response (see 10.4 Record-Route Parameters). These will typically be the URI parameters of the top Route header field but if the upstream SIP element is a strict router they may be returned in the request URI (see RFC 3261). It is the containers responsibility to recognize whether the upstream element is a strict router and determine the right parameter set accordingly. Note: In addition, this specification introduces the access to popped Route header which is popped by the container when the Route header points towards the container. This new mechanism allows the application to have complete access to the popped route header and all parameters. See 5.6.3 Popped Route Header. It is recommended that applications access the Route parameters from the popped route rather than from the request parameters, in future this mechanism may be deprecated.
5.6.2 Attributes
Attributes are objects associated with a message. Attributes may be set by the container to express information that otherwise could not be expressed via the API, or may be set by a servlet to communicate information to another servlet (via RequestDispatcher). Attributes set on a message by a servlet MUST be available to other servlets within the same application only when RequestDispatcher is used to forward the message. Attributes are accessed with the following methods of the ServletRequest interface:
Object getAttribute(String name);
5-8
Re quests
Enumeration getAttributeNames(); void setAttribute(String name, Object o); void removeAttribute(String name);
Only one attribute value may be associated with an attribute name. Attribute names beginning with the prefix javax.servlet.sip. are reserved for definition by this specification. It is suggested that all attributes placed into the attribute set be named in accordance with the reverse package name convention suggested by the Java Programming Language Specification for package naming [JLS].
If application composition is being used, the values returned by these methods may differ. The first method (getPoppedRoute) returns the route popped before current application invocation in the composition chain. The second one (getInitialPoppedRoute) returns the route popped by the container when it first received the request. If no header has been popped by the SIP Servlet container on an initial request, then both methods return null. Note that the above methods return the Route header as an Address. So, parameters added to the Record-Route header using the Proxy.getRecordRouteURI() API should be retrieved not from the popped route Address directly but from the URI of the popped route Address.
JSR 289: SIP Servlet Specification v1.1 5-9
5.7 Responses
Response objects encapsulate headers and content sent from UA servers upstream to the client. Unlike the case for HTTP, a single request may result in multiple responses. The SipServletResponse.getRequest() method returns the request object associated with a response. For UAC and UAS applications this is the original SipServletRequest. For proxying applications it is an object representing the request that was sent on the branch on which the response was received - getProxy().getOriginalRequest() can be used to obtain the original request object (see also 10.2.4.2 Correlating responses to proxy branches and 6.2.3 Creation of SipSessions).
5-10
SipServletRequest createPrack();
Since different PRACKs can be generated on different reliable responses and since RAck is system header, this method must be used to correctly to create a PRACK request. If no PRACK is received for a reliable provisional response within the time specified by RFC 3262, the container will inform the application through the noPrackReceived method of the SipErrorListener interface if this is implemented by the application. It is then up to the application to generate the 5xx response recommended by RFC 3262 for the INVITE transaction. The original INVITE request as well as the unacknowledged reliable response is available from the SipErrorEvent passed to the SipErrorListener. When a container supporting 100rel receives a retransmission of a reliable provisional response, it does not invoke the application(s) again. Also, containers supporting 100rel are responsible for guaranteeing that UAC applications receive incoming reliable provisional responses in the order defined by the RSeq header field.
5.7.2 Buffering
The Servlet API defines a number of ServletResponse methods related to buffering of content returned by a server in responses [Servlet API, section 5.1]:
getBufferSize setBufferSize reset flushBuffer
These methods can improve performance of HTTP servlets significantly. However, unlike HTTP, SIP is not intended as a content transfer protocol and buffering is not usually an issue of concern. Therefore, it is not expected that these methods will yield any useful result and implementations may simply do nothing. It is recommended that getBufferSize return 0. The isCommitted() method returns true if the message is committed in the sense of 5.2 Implicit Transaction State.
5-11
(either timer events or any other thread in the system) outside the scope of the Servlet's service method. E.g. An application can respond to a request based on an event delivered via JMS. A SipServletMessage cannot be sent again after it has been committed as defined in 5.2 Implicit Transaction State. Further since the committed message belongs to a context which has completed its state machine or lifecycle, any modification of the message is meaningless. Containers SHOULD throw an IllegalStateException for any mutation attempt on a committed message. However, the URI and other headers of the committed messages can be used to construct a new message subject to following restriction: In case the URI or any other header is modified for use it MUST be cloned by the application as it is not guaranteed that containers will return a deep copy on access, even if a message is committed the container may still access them for handling a retransmission.
5.9 Internationalization
Language identification tags are used in several places in SIP, notably Accept-Language and Content-Language headers and the charset parameter of various Content-Type header values. In the SIP Servlet API, languages are identified by instances of java.util.Locale. Note: While the javax.servlet interfaces ServletRequest and ServletResponse contains methods related to internationalization, these assume that servlets only respond to incoming requests and are insufficient for the SIP Servlet API.
The setAcceptLanguage method sets the preferred language of the Accept-Language header and removes any existing Accept-Language header, while addAcceptLanguage adds another (least preferred) locale to the list of acceptable locales. The following SipServletMessage methods are used to determine the preferred locale of the sender of the message:
5-12 JSR 289: SIP Servlet Specification v1.1
In te rn at ion al izat io n
The getAcceptLanguage method will return the preferred locale that the client will accept content in. See section 14.4 of RFC 2616 (HTTP/1.1) for more information about how the Accept-Language header must interpreted to determine the preferred language of the client. If no preferred locale is specified by the client, getAcceptLanguage() must return null and getAcceptLanguages() must return an empty Iterator. (Note that this behavior has changed from JSR 116 and is noted in Appendix A.) The getLocales method will return an Iterator over the set of Locale objects indicating, in decreasing order starting with the preferred locale, the locales that are acceptable to the UA originating the message. If no preferred locale is specified by the client, getLocale must return the default locale for the servlet container and getLocales must return an Iterator over a single Locale element of the default locale.
This method must correctly set the Content-Language header (along with other mechanisms described in the SIP specification), to accurately communicate the Locale to the client. Note that a call to the setContent or setContentType methods with a charset component for a particular content type, will set the messages character encoding. The default encoding of message content is UTF-8 if none has been specified by the servlet programmer. Upon receiving messages, servlets can obtain information regarding the locale of the message content using the following SipServletMessage method:
Locale getContentLanguage();
5-13
5-14
SECTION
6 Sessions
SIP applications typically must process multiple messages in order to provide the intended service. As servlets themselves are stateless (or rather, contain no per-dialog or per-transaction data), the API provides a mechanism that allows messages to be correlated and specify how containers associate application data with subsequent messages processed in an application instance. The HTTP Servlet API provides such a mechanism in the form of HTTP sessions. The HttpSession interface allows servlets to correlate a series of HTTP requests from a particular client and also acts as a store for application data. The SipSession interface is the SIP Servlet API equivalent of HttpSession. It represents a point-to-point relationship between two user agents and roughly corresponds to a SIP dialog [RFC 3261]. However, SIP applications are typically more complicated than Web applications: many services involve multiple dialogs, for example conferencing applications and applications acting as back-to-back user agents and third-party controllers converged applications communicate with other network elements using multiple protocols, for example SIP, HTTP, email, etc. application composition allows for many applications active on one call. This implies that there may be more than one application invoked on a single call and any one application instance may consist of multiple point-to-point relationships, and that these relationships may employ different protocols. This is reflected in the SIP Servlet API through the notions of protocol sessions and application sessions. A protocol session is a protocol specific
6-1
Se ssio ns
session object typically representing a point-to-point relationship. The SipSession and HttpSession interfaces are both examples of protocol sessions. An application session in a sense represents an application instance. It contains a number of protocol sessions and is also used as a container for application data. All protocol sessions belonging to the same application instance belong to the same SipApplicationSession. For example, a SIP servlet acting as a back-to-back user agent will consist of two SipSessions and one SipApplicationSession for each application instance. Containers may, as an optimization, create application session and SIP session objects lazily, for example postpone creation until requested by the application. The result should be indistinguishable from an implementation that always creates the session objects.
6.1 SipApplicationSession
The application session serves two purposes: it provides storage for application data and correlates a number of protocol sessions. Note: The application session is not SIP specific, but for practical reasons, this version of the SIP Servlet API defines the application session as javax.servlet.sip.SipApplicationSession, whereas the more logical choice would be javax.servlet.ApplicationSession. It is our hope that a future version of the Servlet API will adopt the notion of application sessions, in which case the SipApplicationSession will be deprecated and/or refactored to extend ApplicationSession.
v1.1)
getSession(java.lang.String id, Protocol protocol) returns a child session
6-2
6-3
Se ssio ns
6-4
be garbage collected. The container MUST invoke the listener callback sessionDestroyed() if a listener exists for both SipSessions and SipApplicationSessions when they are destroyed.
6-5
Se ssio ns
This specification introduces new methods to help applications invalidate SipApplicationSessions cleanly. The methods introduced are: 1. isReadyToInvalidate() - returns true if the SipApplicationSession is in the ready-to-invalidate state and false otherwise. 2. setInvalidateWhenReady(boolean flag) - allows applications to indicate to the container to notify it when the SipApplicationSession is in the ready-to-invalidate state. The container notifies the application using the
SipApplicationSessionListener.sessionReadyToInvalidate(SipApplicationSe ssionEvent se) callback method.
3. getInvalidateWhenReady() - returns true if the container will notify the application when the SipApplicationSession is in the ready-to-invalidate state. An application willing to invalidate a SipApplicationSession cleanly could use the callback mechanism to perform any application clean up before the SipApplicationSession gets invalidated by the container. Servlets can register for sessionReadyToInvalidate notifications on the SipApplicationSessionListener interface. In the sessionReadyToInvalidate callback method, an application may choose to invalidate the SipApplicationSession or perform any other cleanup activities. If the application does not explicitly invalidate the SipApplicationSession in the callback or has not defined a listener, the container will invalidate the SipApplicationSession. Applications may also use the callback to call setInvalidateWhenReady(false) to indicate to the container to not observe this SipApplicationSession anymore. In this case, the containers MUST not invalidate the SipApplicationSession after the callback. Applications could then either rely on explicit invalidation mechanism or again call setInvalidateWhenReady(true). This parallels the expiry callback mechanism defined above in 6.1.2.1 SipApplicationSession Timer Operation and SipApplicationSession Expiration. The firing of the SipApplicationSession expiry timer influences the lifetime of a SipApplicationSession and overrides the behavior of a SipApplicationSession marked with invalidateWhenReady(true). If the SipApplicationSession times out when it is not yet ready to be invalidated state, an application could detect it in the sessionExpired callback of the SipApplicationSessionListener and extend the lifetime of the SipApplicationSession using setExpires. Failing to do so will cause the SipApplicationSession expiry to explicitly invalidate all the contained sessions and itself. Conversely, a SipApplicationSession that transitions to the ready-to-invalidate state may
6-6
S i p Se s s i o n
have an active expiry timer. The container MUST cancel the expiry timer before it invalidates the SipApplicationSession.
The valueBound method must be called before the object is made available via the getAttribute method of the SipApplicationSession interface. The valueUnbound method must be called after the object is no longer available via the getAttribute method of the SipApplicationSession interface.
6.2 SipSession
SipSession objects represent point-to-point SIP relationships, either as established dialogs or in
the stage before a dialog is actually established. The SipSession can be obtained from a
SipServletMessage by calling the getSession method.
Se ssio ns
The SIP dialog state machine is shown in Figure 6-1. Figure 6-1 The SIP Dialog State Machine
The undefined state in Figure 6-1 is not a real state. For dialogs created as the result of an INVITE, the dialog springs into existence on receipt of a 1xx or 2xx with a To tag. Figure 6-2 The SipSession State Machine
SipSession objects are in one of the four states: INITIAL, EARLY, CONFIRMED, or
TERMINATED. These states represent the state of a dialog that may be associated with the SipSession object. A new method on the SipSession class is defined that allows the application to have access to the dialog state. The SipSession state depends not only the state of an underlying SIP dialog but also on whether the servlet has acted as a UAC, UAS or a proxy. The rules governing the state of a SipSession object are given below. Note that for any state transition caused by the receipt of a SIP message, the state change must be accomplished by the container before calling the service() method of any SipServlet to handle the incoming message. 1. Before a dialog creating request is received or sent on a SipSession, the SipSession state is defined to be INITIAL. 2. In general, whenever a non-dialog creating request is sent or received, the SipSession state remains unchanged. Similarly, a response received for a non-dialog creating request also
6-8
S i p Se s s i o n
leaves the SipSession state unchanged. The exception to the general rule is that it does not apply to requests (e.g. BYE, CANCEL) that are dialog terminating according to the appropriate RFC rules relating to the kind of dialog. 3. If the servlet acts as a UAC and sends a dialog creating request, then the SipSession state tracks directly the SIP dialog state except that non-2XX final responses received in the EARLY or INITIAL states cause the SipSession state to return to the INITIAL state rather than going to TERMINATED. 4. If the servlet acts as a UAS and receives a dialog creating request, then the SipSession state directly tracks the SIP dialog state. Unlike a UAC, a non-2XX final response sent by the UAS in the EARLY or INITIAL states causes the SipSession state to go directly to the TERMINATED state. 5. If the servlet acts as a proxy for a dialog creating request then the SipSession state tracks the SIP dialog state except that non-2XX final responses received from downstream in the EARLY or INITIAL states cause the SipSession state to return to the INITIAL state rather than going to the TERMINATED state. This enables proxy servlets to proxy requests to additional destinations when called by the container in the doResponse() method for a tentative non-2XX best response. After all such additional proxy branches have been responded to and after considering any servlet created responses, the container eventually arrives at the overall best response and forwards this response upstream. If this best response is a non-2XX final response, then when the forwarding takes place, the state of the SipSession object becomes TERMINATED. If this best response is a 2XX final response, then the SipSession state becomes CONFIRMED. 6. Because setting the supervised flag to false affects only whether responses are seen for the transaction associated with the current request, the value of the supervised flag has no effect on the SipSession state. An enum that defines the possible SIP dialog states is defined for use with the SipSession interface:
public enum SipSession.State {INITIAL, EARLY, CONFIRMED, TERMINATED }
The following new method is introduced on the SipSession interface to return the current SIP dialog state:
public SipSession.State getState()
6-9
Se ssio ns
This method returns one of the SipSession.State enum values - INITIAL, EARLY, CONFIRMED or TERMINATED. These values represent the SIP dialog related state of the SipSession when the method is called. The standard SIP rules governing when a second or subsequent response cause a single request to establish multiple dialogs hold unmodified for SipSessions. If, for example, two 200 responses are received for an initial INVITE, the container will create a second SipSession on receipt of the second 200 response. This second SipSession will be derived from the one in which the INVITE was generated as described in 6.2.3.2 Derived SipSessions below. Both SipSessions will then represent dialogs in the CONFIRMED state. The INITIAL state is introduced to allow a UAC to generate multiple requests with the same Call-ID, From (including tag), and To (excluding tag), and within the same CSeq space. This is useful, for example, in the following situations: When a UAC receives a 3xx for a request initiated outside of a dialog and decides to retry with the Contact addresses received in the 3xx, it is recommended to reuse the same To, From and Call-ID for the new request [RFC 3261, section 8.1.3.4]. When a UAC receives certain non-failure 4xx responses indicating that the request can be retried, e.g. 401, 407, 413, 415, 416, and 420 [RFC 3261, section 8.1.3.5]. REGISTER requests sent from a UAC to the same registrar should all use the same Call-ID header field value and should increment the CSeq by one for each request sent [RFC 3261, section 10.2]. When a UAC using the session timer extension receives a 422 response to an initial INVITE it retries with the same Call-ID and a higher Min-SE value [timer]. These examples have in common, a need to create similar requests without an established dialog being in place. There may well be other scenarios where its desirable to correlate non-dialog requests by Call-ID and ensuring proper sequencing by using the CSeq header field. A new request can be created from the INITIAL state only when there is no ongoing transaction. The request URI should be changed if the request is to be sent to different target than previous request. Note that the pseudo dialog semantics presented here is defined for use in UAC applications only. Containers treat incoming requests as subsequent requests, i.e., routes to existing sessions, only if those requests belong to an actual established SIP dialog. There is no expectation, for example, that a container treat an incoming INVITE as a subsequent request after it has previously sent a 3xx response to another INVITE with the same Call-ID, CSeq, and From (including tag).
6-10
S i p Se s s i o n
Se ssio ns
As a consequence of these rules, requests generated in the same SipSession have the following characteristics: they all have the same Call-ID they all have the same From header field value including the same non-empty tag the CSeq of requests generated in the same SipSession will monotonically increase by one for each request created, regardless of the state of the SipSession all requests generated in the same SipSession in the initial state have the same To header field value which will not have a tag parameter
SipSession objects in the initial state have no route set, the remote sequence number is
undefined, the secure flag is false, and the remote target URI is the URI of the To header field value.
6-12
S i p Se s s i o n
Responses to an initial request that do not establish a dialog, belong to the original SipSession of the request. The first message that establishes a SIP dialog (for example, a 2xx to an initial INVITE request) is associated with the original SipSession as are all other messages belonging to that dialog. Subsequent messages that establish dialogs are associated with new SipSessions derived from the original SipSession, see 6.2.3.2 Derived SipSessions below. When a proxying application receives a response that is associated with a new SipSession (say, because it is a second 2xx response to an INVITE request), the getSession method of that response returns a new derived SipSession. The original SipSession continues to be available through the original request object itself available through the getOriginalRequest method on the Proxy interface.
Se ssio ns
original SipSession of the request continues to be available through the original request object.
time out with it. In general, the lifetime of a SipSession can be controlled in the following ways: 1. The parent SipApplicationSession times out or is invalidated explicitly and this invalidates all child protocol sessions. 2. Application explicitly invalidates the SipSession using the invalidate() API. 3. Application marks the SipSession to be invalidated and the container invalidates it when the session is in the ready-to-invalidate state. Any attempt to retrieve or store data on an invalidated SipSession causes an IllegalStateException to be thrown by the container as does any call to createRequest. When a SipSession terminates, either because the parent application session timed out or because the SipSession was explicitly invalidated, the container MUST purge all state of that SipSession from its memory. In such a case, if a subsequent request or response belonging to the corresponding dialog is received, the container is free to handle it in either of the following ways: 1. Reject the request by sending a 481 error response or 2. Route the request or response without application involvement It is quite possible that different application instances on the same application path have different lifetimes. Containers handling subsequent requests and responses on a dialog corresponding to a partially invalidated application path would invoke all applications up to the first invalidated session instance and reject them if the session acts as an UA or proxy them statelessly if the session acts as a Proxy.
6-14
S i p Se s s i o n
2. Invalidate When Ready Mechanism Once a SipSession object is invalidated either by the application or the container, it may no longer be used. On invalidation, the container MUST invoke the sessionDestroyed() callback on implementations of the SipSessionListener interface, if any exist.
6-15
Se ssio ns
2. setInvalidateWhenReady(boolean flag) - allows applications to indicate to the container to notify it when the SipSession is in the ready-to-invalidate state. The container notifies the application using the SipSessionListener.sessionReadyToInvalidate(SipSessionEvent se) callback. 3. getInvalidateWhenReady() - returns true if the container will notify the application when the SipSession is in the ready-to-invalidate state. An application willing to invalidate a SipSession cleanly could use the callback mechanism to perform any other application clean up before the SipSession gets invalidated by the container. Servlets can register for sessionReadyToInvalidate notifications on the SipSessionListener interface. In the sessionReadyToInvalidate callback method, an application may choose to invalidate the session and perform any other cleanup activities. If the application does not explicitly invalidate the session in the callback or has not defined a listener, the container will invalidate the session. Applications may call setInvalidateWhenReady(false) at any time to indicate to the container to not observe this session anymore. In such a case, the containers MUST not invalidate the session after the callback. Applications could then either rely on explicit invalidation mechanism or again call setInvalidateWhenReady(true). This parallels the expiry callback mechanism defined above in 6.1.2.1 SipApplicationSession Timer Operation and SipApplicationSession Expiration. For example: An application registers a SipSession for a callback using session.setInvalidateWhenReady(true) and handles the callback in the SipSessionListener as follows:
@SipListener public class MySessionListener implements SipSessionListener { ... sessionReadyToInvalidate(SipSessionEvent se) { Session sess = se.getSession(); // directs the container to stop observing this session and // not invalidate it when this callback returns. sess.setInvalidateWhenReady(false); } ... }
The container determines the SipSession to be in the ready-to-invalidate state under any of the following conditions:
6-16 JSR 289: SIP Servlet Specification v1.1
S i p Se s s i o n
1. A dialog corresponding to a SipSession terminates when the SipSession transitions to the TERMINATED state. If derived sessions (sub-dialogs) were created, it is up to container implementations to declare the original SipSession to be in ready-to-invalidate state either when the original SipSession (primary dialog) terminates or when all the derived sessions (sub-dialogs) terminate. 2. A SipSession transitions to the CONFIRMED state when it is acting as a non-record-routing proxy. 3. A SipSession acting as a UAC transitions from the EARLY state back to the INITIAL state on account of receiving a non-2xx final response (6.2.1 Relationship to SIP Dialogs, point 4) and has not initiated any new requests (does not have any pending transactions). The container MUST NOT treat SipSession objects to be in the ready-to-invalidate state if the session has any underlying transactions in progress. The firing of the parent SipApplicationSession timer influences the lifetime of a child SipSession and overrides the behavior of a SipSession marked with invalidateWithReady(true). If the parent SipApplicationSession times out when it contains a child SipSession that is not yet ready to be invalidated, an application could detect it in the sessionExpired callback of the SipApplicationSessionListener and extend the lifetime of the SipApplicationSession using setExpires. Failing to do so will cause the SipApplicationSession expiry to forcefully invalidate the child SipSession even if it is not yet ready to be invalidated. For example, to extend the lifetime of a SipApplicationSession when one of its child sessions is not yet in the ready-to-invalidate state, one could handle the callback in the SipApplicationSessionListener as follows:
@SipListener public class MySipApplicationSessionListener implements SipApplicationSessionListener { ... sessionExpired(SipApplicationSessionEvent sase) { SipApplicationSession sas = sase.getApplicationSession(); Iterator sessions = sas.getSessions("SIP"); while (sessions.hasNext()) { SipSession ss = (SipSession) sessions.next(); if (! ss.isReadyToInvalidate()) { sas.setExpires(extensionTime); return; } } }
6-17
Se ssio ns
... }
If an application invokes any method on an invalidated SipSession object, the container SHOULD throw an IllegalStateException. Note that the methods introduced on the SipSession and SipApplicationSession classes in this specification throw IllegalStateException when invoked against invalid session objects. However, some of the existing methods (from v1.0) which did not throw this exception will continue to not throw it in this specification for backwards-compatibility reasons. A new isValid() method is provided on both SipApplicationSession and SipSession interfaces to check whether the session object has been invalidated.
6-18
S i p Se s s i o n
The argument is the same as in the call to ServletContext.getNamedDispatcher, i.e., it is a servlet name. Servlet names are typically associated with servlets through the deployment descriptor or using the @SipServlet(name) annotation.
Se ssio ns
Some objects may require notification when they are placed into, or removed from, a session. This information can be obtained by having the object implement the SipSessionBindingListener interface. This interface defines the following methods that will signal an object being bound into, or being unbound from, a session.
valueBound valueUnbound
The valueBound method must be called before the object is made available via the getAttribute method of the SipSession interface. The valueUnbound method must be called after the object is no longer available via the getAttribute method of the SipSession interface.
I m p o r ta nt S e s s i o n Se m an ti c s
is received, the same application is invoked and in the same context, that is, getApplicationSession and getSession are required to return the same session objects when invoked on the INVITE and BYE requests as well as on corresponding response objects. Note that while logically all SIP messages passed to applications have SipApplicationSession and SipSession objects associated with them, for performance reasons, containers may choose to defer creation of session objects when applications cannot observe the difference.
Se ssio ns
These restrictions mean that the developer is ensured that there are no additional concurrency issues beyond those encountered in a non-distributed container. The container provider can ensure scalability and quality of service features like load-balancing and failover by having the ability to move a session object and its contents from any active node of the distributed system to a different node of the system. If distributed containers persist or migrate sessions to provide quality of service features, they are not restricted to using the native JVM serialization mechanism for serializing sesssion and their attributes, however the containers MUST provide consistent environment after de-serialization as one would expect Java serialization mechanism to provide. Developers are not guaranteed that containers will call readObject() and writeObject() methods on session attributes if they implement them, but are guaranteed that the Serializable closure of each attribute will be preserved. Defining closure around individual attributes mean that each individual attribute can be saved independently without having to save the entire SipSession or SipApplicationSession on an attribute addition or update, of course the shared objects accross the attributes shall be referenced as in normal Java serialization mechanism. Containers MUST notify any session attributes implementing the SipSessionActivationListener and SipApplicationSessionActivationListener during migration of a session. They MUST notify listeners of passivation prior to serialization of a session, and of activation after deserialization of a session when such a migration takes place. Developers writing distributed applications should be aware that since the container may run in more than one Java VM, the developer cannot depend on static or instance variables for storing application states. They should store such states using an EJB or a database. In addition to this the containers MUST also ensure that the Serializable "info" object associated with the ServletTimer is also migrated or persisted alongside the sessions if the ServletTimer is chosen to be persistent.
6-22
SECTION
A SIP servlet application is a collection of servlets, class files, and other resources that comprise a complete application on a SIP server. The SIP application can be bundled and run on multiple containers from multiple vendors. By default, an instance of a SIP application must run on one VM at any one time. This behavior can be overridden if the application is marked as distributable via its deployment descriptor or via the @SipApplication(distributable) annotation. An application marked as distributable must obey a more restrictive set of rules than is required of a normal servlet application. These rules are set out throughout this specification.
7-1
7-2
The /WEB-INF/classes/* directory for servlet and utility classes. The classes in this directory are available to the application classloader. The /WEB-INF/lib/*.jar area for Java Archive files. These files contain servlets, beans, and other utility classes useful to the web application. The web application classloader can load class from any of these archive files. The application classloader must load classes from the WEB-INF/ classes directory first, and then from library JARs in the WEB-INF/ lib directory.
7-3
If the aforementioned application was a v1.0 style application with similar packaging and were to be deployed on a container compliant with this specification, the application name SHOULD be "myj2eeapp/mysipapp". The containers MAY further distinguish these names by adding their own versioning tokens. If the application is specified by annotation, chapter 18 Java Enterprise Edition 5 Container provides the procedures for determining the name of such applications.
The following is the same example but with an HTTP servlet component included:
/wakeup.html /register.html /WEB-INF/sip.xml /WEB-INF/web.xml /WEB-INF/wakeup.wav /WEB-INF/lib/foo.jar /WEB-INF/classes/RegisterWakeupCall.class /WEB-INF/classes/WakeupServlet.class
In this latter case there are separate SIP and HTTP deployment descriptors: sip.xml and web.xml, respectively. Resources not under WEB-INF/ will be part of the content served from the HTTP part of the converged application.
7-4
one or a few applications will be made part of the servlet application to be available for access. Application developers need to know what extensions are installed on a servlet container, and containers need to know what dependencies on such libraries servlets in a SAR/WAR may have, in order to preserve portability. Servlet containers are recommended to have a mechanism by which servlet applications can learn what JAR files containing resources and code are available, and for making them available to the application. Containers should provide a convenient procedure for editing and configuring library files or extensions. It is recommended that application developers provide a META-INF/MANIFEST.MF entry in the SAR/WAR file listing extensions, if any, needed by the SAR/WAR. The format of the manifest entry should follow standard JAR manifest format. In expressing dependencies on extensions installed on the servlet container, the manifest entry should follow the specification for standard extensions defined at http://java.sun.com/j2se/1.5.0/docs/guide/extensions/versioning.html. Servlet containers should be able to recognize declared dependencies expressed in the optional manifest entry in a SAR/WAR file, or in the manifest entry of any of the library JARs under the WEB-INF/lib entry in a SAR/WAR. If a servlet container is not able to satisfy the dependencies declared in this manner, it should reject the application with an informative error message.
7-6
Se rv l e t A pp l i c a ti o n En v i r o n m e nt
The env-entry element contains information to set up basic environment entry names relative to the java:comp/env context, the expected Java type of the environment entry value (the type of object returned from the JNDI lookup method), and an optional environment entry value. The ejb-ref element contains the information needed to allow a servlet to locate the home interfaces of an enterprise bean. The resource-ref element contains the information needed to set up a resource factory. The requirements of the Java EE environment with regards to setting up the environment are described in chapter 5 of the Java Platform, Enterprise Edition 5 (Java EE 5) Specification. Servlet containers that are not part of a Java EE compliant implementation are encouraged, but not required, to implement the application environment functionality described in the Java EE specification. If they do not implement the facilities required to support this environment, upon deploying an application that relies on them, the container should provide a warning. Since Servlet specification v2.5 introduced the usage of annotations based resource injection and this specification is based on it, the annotations defined in Servlet specification v2.5 are supported, like @Resource, @EJB etc. see 18.2.1 Servlet 2.5 alignment for details.
7-7
7-8
SECTION
Version 2.3 of the Java Servlet Specification introduced the notion of application listeners [Servlet API, chapter 10]. The SIP Servlet API requires full support for application listeners and events as defined in that document, except for the HTTP specific events defined in package javax.servlet.http. The servlet context events defined in javax.servlet must be supported. Additionally, this specification defines some SIP specific events for which support is also required. For full details on application listeners and events, see [Servlet API, chapter 10].
8-1
javax.servlet.sip.SipApplicationSessionActivationListener: Implementations of this interface will receive notifications when a SipApplicationSession has been activated or passivated. Listeners on SipSession: javax.servlet.sip.SipSessionListener : Implementations of this interface will receive notifications when a SipSession has been created, destroyed or is in the ready-to-invalidate state. javax.servlet.sip.SipSessionActivationListener : Implementations of this interface will receive notifications when a SipSession has been activated or passivated. javax.servlet.sip.SipSessionAttributeListener: Implementations of this interface will receive notifications when attributes are added, removed or replaced from a SipSession. javax.servlet.sip.SipSessionBindingListener: Attributes implementing this interface will receive notifications when they are bound or unbound from a SipSession. Error listener: javax.servlet.sip.SipErrorListener: Implementations of this interface will receive notification when an expected ACK or PRACK is not received. Timer listener: javax.servlet.sip.TimerListener : Implementations of this interface will receive notification when a ServletTimer has fired. SipServlet listener: javax.servlet.sip.SipServletListener : Implementations of this interface will receive notification on SipServlet initialization.
8-2
SECTION
9 Timer Service
The timer service is a container-provided service that allows applications to schedule timers and to receive notifications when timers expire. Timers are managed by the container like other resources, and may optionally be persistent in which case they are stored along with session data. Timers can be scheduled to expire once after a specified time, or repeatedly at specified intervals. The timer support consists of three interfaces: TimerService which is used when creating timers, ServletTimer which represents timers and is passed to callbacks, and TimerListener which is the callback interface implemented by the application and invoked by the container on timer expiration.
9.1 TimerService
The TimerService interface is implemented by containers and is made available to applications as a ServletContext parameter with the name javax.servlet.sip.TimerService. The TimerService provides the following methods:
ServletTimer createTimer(SipApplicationSession appSession, long delay, boolean isPersistent, java.io.Serializable info); ServletTimer createTimer(SipApplicationSession appSession, long delay, long period, boolean fixedDelay, boolean isPersistent, java.io.Serializable info);
9-1
Ti mer S er vice
ServletTimer objects are associated with an application session. The application may store data
in the application session and retrieve it later when the timer fires. The getTimers method of the SipApplicationSession interface returns a java.util.Collection containing all ServletTimer objects currently scheduled and associated with that session. Similarly, the getTimer(String id) method on the SipApplicationSession returns the specific ServletTimer object that is currently scheduled and is associated with that session. The meaning of the arguments to the createTimer method is:
appSession the application session that the new ServletTimer will be associated with delay delay in milliseconds before the ServletTimer is to expire the first time period time in milliseconds between successive timer expirations fixedDelay specifies whether a repeating timer is fixed-delay or fixed-rate. The semantics are similar to those of java.util.Timer: in both cases the repeating timer
expires at approximately regular intervals but with fixed-delay execution rescheduling of the repeating timer ignores any lateness in previous expirations whereas fixed-rate timers are rescheduled based on absolute time.
isPersistent if true the ServletTimer should be reinstantiated if the server is shut down and subsequently restarted. During the restart, the container will call the TimerInterface for a timer that has expired during the shutdown. The SipApplicationSession associated with the ServletTimer should be persistent. info application information to be delivered along with the timer expiration. This is
useful for determining the significance of a timer expiration in applications that sets multiple timers per application session.
9.2 ServletTimer
The ServletTimer interface represents scheduled timers. The application session, timer id and the serializable information object can be retrieved from the ServletTimer in the expiration callback. The ServletTimer interface also lets applications cancel timers and obtain information regarding last and next scheduled expiration time. The ServletTimer interface provides the following methods:
SipApplicationSession getApplicationSession(); java.io.Serializable getInfo(); String getId();
9-2
TimerLis te ner
9.3 TimerListener
Applications are notified of expiration of timers through the TimerListener interface. This interface has a single method:
void timeout(ServletTimer timer);
Applications using timers must implement the TimerListener interface and must declare the implementation class in a listener element of the SIP deployment descriptor (as described below) or use the @SipListener annotation (as described in 18.2.4 @SipListener Annotation). For example, an application might include a class com.example.MyTimerListener that implements javax.servlet.sip.TimerListener. It would then declare this listener in the SIP deployment descriptor as follows:
<listener> <listener-class>com.example.MyTimerListener</listener-class> </listener>
There may be at most one TimerListener implementation declared in the deployment descriptor.
9-3
Ti mer S er vice
9-4
S E C T I O N 10
10 Proxying
One important function of SIP is the ability to route requests, that is, for incoming requests to decide which destination or destinations should receive the request. The ability to proxy requests is essential to many SIP services. In some cases the service may have a choice between proxying and redirecting but many services require proxying because they need to see responses and/or stay on the signaling path. One of the most important differences between the HTTP and SIP Servlet APIs is that whereas HTTP servlets execute on origin servers only and are concerned only with responding to incoming requests, SIP servlets are typically located on proxy servers and must be able to proxy incoming requests as well as respond to them directly. Proxying is initiated and controlled via a Proxy object obtained from an incoming SipServletRequest and its associated ProxyBranch object. There is at most one Proxy object per SIP transaction, meaning that SipServletRequest.getProxy() will return the same Proxy instance whenever invoked on the original request object or on any other message belonging to that transaction.
10.1 Parameters
A number of Proxy parameters control various aspects of the proxying operation:
recurse: flag specifying whether the servlet engine will automatically recurse or not. If
recursion is enabled the servlet engine will automatically attempt to proxy to contact addresses received in redirect (3xx) responses. The default value is true.
10-1
Proxyi n g
recordRoute: flag controlling whether the application stays on the signaling path for this dialog or not. This should be set to true if the application wishes to see subsequent requests belonging to the dialog. The default value is false. parallel: flag specifying whether to proxy to multiple destinations in parallel (true) or
sequentially (false). In the case of parallel search, the server may proxy the request to multiple destinations without waiting for final responses to previous requests. The default value is true.
supervised: whether the servlet is invoked to handle responses. Note that setting the supervised flag to false affects only the transaction to which the Proxy object relates. The default value is true. proxyTimeout: The timeout for the proxy in general. In case the proxy is a sequential proxy then this value behaves like the sequential-search-timeout which is deprecated since v1.1. In case the proxy is a parallel proxy then this timeout acts as the timeout for the entire proxy i.e each of its parallel branches before it starts to send out CANCELs waiting for final responses on all INVITE branches and sends the best final response upstream. The default value is the value of the proxy-timeout element of the deployment descriptor or a container specific value, if this is not specified. addToPath: flag controlling whether the application adds a Path header to the request,
thereby adding itself into the Path thus created by the REGISTER requests as per RFC3327. The recordRoute flag may only be set before the first call to Proxy.proxyTo or Proxy.startProxy(). Any attempt to set it afterwards results in an IllegalStateException being thrown. The recurse, parallel, and supervised flags as well as the proxyTimeout parameter may be modified by applications while a proxying operation is in progress. Note: Deprecation of Stateless Proxy in SIP Servlet Specifiaction: The Proxy implemented on containers compliant with this specification MUST always be transactional stateful and they MUST NOT allow an application to change the transactional behaviour of Proxy. Therefore both Proxy.setStateful() and Proxy.getStateful() are deprecated in this specification. For backward compatibility purposes:
Proxy.setStateful(boolean stateful) now does nothing. Proxy.getStateful now always returns true.
10-2
Op er at io n
Though stateless proxying by applications is deprecated in this release, a proxy implemented on containers compliant with this specification MUST forward messages statelessly under certain conditions as described in [RFC 3261, Section 16.7, point 10 and 16.10]
10.2 Operation
There are two ways in which an application can perform proxying operation using the Proxy object obtained from an incoming SipServletRequest: 1. By calling proxyTo() method on the Proxy object and passing the URI(s) to proxy the request to. 2. By creating ProxyBranch object(s) from the Proxy and then invoking startProxy() method on the Proxy. When creating the Proxy object for an incoming INVITE request, the server also sends a 100 provisional response upstream. This is done to stop retransmissions from the client. The server MAY choose to send the 100 provisional response irrespective of the application type for the same reason. Before proxying the request the application may modify the Proxy parameters as appropriate and may also modify the request object itself. This includes adding or removing headers but the proxy MUST NOT add to, modify or remove the message body as per [RFC 3261 16.6.1]. The proxyTo() method is overloaded to take either a single URI or a List of URIs specifying downstream destination(s). If the list of URIs passed to the proxyTo() method contains any duplicates (based on the definition of equality for the URI type), the proxy MUST ignore proxying to the duplicate URIs as per [RFC 3261 16.5]. Compliant servlet engines are required to be able to handle SIP and SIPS URIs and may know how to handle other URI schemes, for example, Tel URIs. For each URI passed to it in one of the proxyTo methods, the container creates a new branch on which the request is proxied. The proxied request will have the request URI replaced with that of the specified destination URI and is routed either based on that modified request URI, or based on the top Route header field value, if one is specified. Until a final response is forwarded upstream, the application may invoke the proxyTo method any number of times to add additional addresses to the set of destinations the container should proxy to.
10-3
Proxyi n g
Applications that wish to stay on the signaling path but which do not perform any routing decisions or otherwise influence the call setup may proxy with record-routing enabled without changing the request URI, specifically it will do the following:
public void doInvite(SipServletRequest req) { ... Proxy p = req.getProxy(); p.setRecordRoute(true); p.proxyTo(req.getRequestURI()); ... }
The request will be proxied either to other applications according to the application composition mechanism or towards the external destination specified by the request URI. Note that the SIP servlet programming model is asynchronous, therefore the application code may not process a request in the context of the service method upcall, but save the request instead and act on it asynchronously. For example, it is perfectly fine for an application to obtain the Proxy object from a request in the context of a service method, but defer the act of starting the Proxy until later, for instance trigger it by an application timer expiration. In other words, there is no expectation that the Proxy will be started by the application code in the context of the service method.
As an example .. public void doInvite(SipServletRequest req) { ... Proxy p = req.getProxy(); p.setRecordRoute(true); p.createProxyBranches(targetList); p.startProxy();
10-4
Op er at io n
... }
The effect of the above operation is same as p.proxyTo(targetList); The proxy branch will not be used directly by the proxy application in most cases except when the application requires having some branch specific changes to the request. Only the following operations are allowed on the ProxyBranch and the associated SipServletRequest object. 1. push different route headers to the associated SipServletRequest with the proxy branch. 2. cancel a certain proxy branch, by issuing a CANCEL request. The mechanism that the container uses to resolve the race condition of receiving a final response of the branch and mechanism of not sending CANCEL until the provisional response is received are same as defined for Proxy.cancel() method which cancels all the proxy branches and all branches created recursively. 3. set different record-route, path parameter, recurse flag or proxy timeout for the branch. 4. add/remove non system headers from the SipServletRequest before the request is proxied. 5. any other method invoked on SipServletRequest object (like send(), createCancel() etc), not relevant for this context MUST throw IllegalStateException. Until a final response is forwarded upstream, the application may invoke the createProxyBranches() and startProxy() methods any number of times to add additional addresses to the set of destinations the container should proxy to. The createProxyBranches() method explicitly and the proxyTo() method implicitly create the ProxyBranch(es). These proxy branches can be retrieved from the Proxy object using the ProxyBranch Proxy.getProxyBranch(URI) on the Proxy interface. These are the top level branches created by user code providing a single URI or a list of URIs. Further java.util.List<ProxyBranch> Proxy.getProxyBranches() on Proxy interface returns all the top level branches associated with the Proxy. Additionally any ProxyBranch might recurse if the recurse flag is true for the proxy/branch and the branch received the 3xx class response with alternate Contact headers. It is possible to retrieve the recursed branches by using the ProxyBranch method java.util.List getRecursedProxyBranches().
10-5
Proxyi n g
10-6
Op er at io n
If the best response received was a non-2xx and the application generated its own final response in the doResponse callback (be it a 2xx or non-2xx), then that response is sent immediately without invoking the application again for its own generated response. This last item allows applications to create, for example, a different error response from the one chosen by the container as the best response. Note that if an application does generate its own final response when passed the best response received, it cannot also proxy to more destinations. These rules are designed to guarantee that SIP servlet containers, when observed from the outside, do not violate the SIP specification. From the container perspective when a response from the virtual branch is sent upstream, a derived SipSession is created for the virtual branch as per 6.2.3.2 Derived SipSessions. The original SipSession associated with the incoming request corresponds to the Proxy while the derived one represents the virtual UAS. Containers MUST restrict to creating only one virtual branch for each Proxy. If the final response sent upstream was generated by the application itself, the container must update SipSession state as if it was a UAS (which in fact it is). Alternative to sending a response itself, a proxy could use application composition to delegate the responsibility of sending the response to another application. The composition approach is recommended in cases where more than one virtual branch may be required. However, the virtual branch approach is simpler in that it makes sure that no other application is invoked between the proxy and the UAS.
10-7
Proxyi n g
for example, for application level gateways that need to modify addresses in the body of responses. As in the UAC case, applications are not invoked for incoming 100 responses. When a 6xx response is received, the server CANCELs all outstanding branches and will not create new branches. Similarly, when a 2xx response is received, the server CANCELs all outstanding branches and will not create new branches unless the proxy is configured to not cancel branches with setNoCancel(true). When an application is invoked to handle the best final response received and it is not a 2xx or 6xx, the application may add addresses for further destinations through the Proxy.proxyTo method or by creating additional proxy branches and re-starting the proxy. The effect is that a new branch is created for each additional destination, as if the method had been invoked before a (tentative) best answer had been passed to the application. If, in the upcall informing a servlet of the best response received, the servlet proxies to one or more additional destinations, the container does not immediately forward the best response received so far as the new branch may result in a better response. The ability to call proxyTo in the callback for best response received is useful, for example, for writing call-forward-no-answer type services. A consequence of the described behavior is that an application may be notified of more than one final response for a transaction. This can happen either because 1. the application proxied to more destinations in the notification for a final response 2. one or more 2xx retransmissions were received, see 10.2.4.1 Handling 2xx Responses to INVITE below 3. multiple destinations returned 2xx responses. In the first two cases, the application may end up being notified of the same final response more than once.
10-8
Op er at io n
In this case its necessary to ensure that 2xx retransmissions are modified in the exact same way as the 2xx first received for the INVITE. This can be achieved in several different ways and it is left to implementations to choose one. One solution is to not terminate INVITE client and server transactions when first seeing a 2xx for an INVITE. This enables the application server to handle 2xx retransmissions in a manner similar to the original 2xx, that is, invoke applications as necessary and then forward it upstream. For this reason, applications proxying INVITEs must be prepared to receive retransmissions of 2xx responses and must modify such retransmissions the same way they did the 2xx originally received.
10-9
Proxyi n g
doBranchResponse method would be to create and proxy to additional branches on the receipt
of a non-2xx final response. Any attempt to add additional branches in doBranchResponse() for a cancelled branch or a cancelled proxy will result in IllegalStateException. Only after the last branch has received a final response, the container must determine the best final response and pass it to the doResponse() method. Note that if the doBranchResponse() is not overridden then doResponse() method will be invoked only for the best final response as before.
Op er at io n
If the recurse flag of the proxy is set to true then the container SHOULD proxy only to unique contact address ignoring any duplicates. This may result in a case where a branch does not recurse on receiving a 3xx response with an alternate contact as a branch for that contact already exists. Calling getRecursedProxyBranches() on such a branch would result in an empty list. Every recursed contact results in a new branch and duplicate contacts are ignored as per [RFC 3261, Section 16.5]. The container MUST remove the redirect contacts from the 3xx response since they have produced new branches. A 3xx response without any contacts can never be a best response of a proxy according to [RFC 3261 16.7, point 4] and should never be propagated up to the application.
Proxyi n g
if the original request has not been proxied yet the container responds to it with a 487 final response otherwise, all branches are cancelled, and response processing continues as usual In either case, the application is subsequently invoked with the CANCEL request. This is a notification only, as the server has already responded to the CANCEL and cancelled outstanding branches as appropriate. The race condition between the server sending the 487 response and the application proxying the request is handled as in the UAS case as discussed in 11.2.3 Receiving CANCEL.
10-12
The application is still passed the request object, though, and may modify it in the upcall before the server proxies it downstream. Applications should not attempt to explicitly proxy subsequent requests, any attempt to do so results in an IllegalStateException. The isInitial method on the SipServletRequest interface returns true if the request is initial as defined above, and can be used as an indication of whether the application should explicitly proxy an incoming request or not. Applications are allowed to reject subsequent requests, but only when doing so in the upcall notifying the application of the subsequent request. After having performed the upcall the container will proxy the request unless the application generated a final response for it. The ability of proxy applications to respond to subsequent requests is needed, for example, for applications wishing to perform proxy authentication programmatically.
10-13
Proxyi n g
and/or SipSession, the container must ensure that those same session objects are associated with subsequent requests and responses that the application is invoked to handle. Also, as a result of forking proxies an initial request may result in multiple dialogs being established. 6.2.3 Creation of SipSessions discusses under which circumstances a container must associate an incoming response or even a subsequent request with a SipSession cloned from that of an existing dialog.
The URI returned by the getRecordRouteURI method should be used only for pushing application state in the form of URI parameters to the user agents. Applications must not set SIP URI parameters defined in RFC 3261. This includes transport, user, method, ttl, maddr, and lr. Other components of the URI, e.g. host, port, and URI scheme must also not by modified by the application. These Record-Route URI components will be populated by the container and may or may not have valid values at the time an application proxies a request. Parameters added to Record-Route header field values in this manner can be retrieved from subsequent requests using the getParameter method of SipServletRequest or through access to the popped Route header, discussed in 5.6.1 Parameters. Note that this mechanism guarantees that when a proxy application adds parameters to a URI obtained through the getRecordRouteURI method, the value of those parameters can be retrieved by the same application using SipServletRequest.getParameter on subsequent requests in that dialog (assuming the user agents involved are well-behaved). However, there is no guarantee that the parameters go unchanged into an actual Record-Route header. For example,
10-14
Pa t h H e a d e r an d P at h Pa r am e t e r s
due to application composition, the parameters may in some cases go into a Contact header, and also, the container may choose to insert only one Record-Route header when there are multiple record-routing proxies on the application path. In this case the container would have to encode parameters so as to avoid name clashes between applications. Implementations may even choose to store the parameter set locally, possibly along with other dialog related data, and retrieve it based on a dialog ID computed for subsequent incoming requests. There is no hard bound defined for the size of data that can be pushed to endpoints in Record-Route header fields but it is recommended that application writers keep in mind that some implementations may not function correctly with large size data. This version of the SIP Servlet API does not allow proxy applications to push different state to the two endpoints of a dialog. The UAS will copy the Record-Route header field of requests unchanged into 2xx responses and the proxy application is not given the opportunity to modify its own previously inserted Record-Route parameters when processing 2xx responses. This would effectively rewrite the Record-Route header field value and cause state received in subsequent requests from the caller to differ from that received in subsequent requests from the callee. Such a feature would potentially be useful but may have an adverse effect on performance and security as the Record-Route header in responses cannot be protected end-to-end if rewritten by proxies.
10-15
Proxyi n g
The SIP option tag "path" should be present in immutable List of extensions supported as described in section 3.2 Extensions Supported in addition to the 100rel option tag. Path is no different from Record-Route in semantics, except that it creates a path for subsequent dialogs, therefore Path header is a "System Header" (see 5.4.2 System Headers), managed by SIP Servlet Container. A pushPath() method is defined on SipServletRequest similar to pushRoute() method. However, pushPath() shall throw an IllegalStateException on non-REGISTER Requests.
10-16
S E C T I O N 11
This chapter describes how SIP servlets perform various UA operations such as initiating and responding to requests. The SIP specification lists client and server transaction state machines that define at which points in processing various actions are allowed. As mentioned in 5.2 Implicit Transaction State, when an application attempts to perform an action that would violate the SIP state machine, an IllegalStateException is thrown by the container. The notions of SIP client and server are meaningful only in relation to a particular transaction. An application acting as a UA will often have to be able to act as both a client and a server in a dialog.
11-1
Ac tin g as a Us er Ag en t
modify the resulting SipServletRequest as appropriate, for example, set the content invoke send on the request object The SipFactory interface defines the following methods for creating new requests:
SipServletRequest createRequest( SipApplicationSession appSession, String method, Address from, Address to); SipServletRequest createRequest( SipApplicationSession appSession, String method, URI from, URI to); SipServletRequest createRequest( SipApplicationSession appSession, String method, String from, String to) throws ServletParseException;
The returned SipServletRequest exists in a new SipSession which belongs to the specified SipApplicationSession. The handler for the newly created SipSession is the applications default servlet for v1.0 applications, see 6.2.6 The SipSession Handler and the main servlet for v1.1 applications, see 16.2 Servlet Selection. This can be changed by the application by invoking SipSession.setHandler. The container is required to assign the returned request a fresh, globally unique Call-ID as defined by the SIP specification. The From and To headers are as specified by the from and to parameters, respectively. The container is responsible for adding a CSeq header. The request method is given by the method parameter. The default value of the request URI is the URI of the To header, with the additional requirement that for REGISTER requests the user part of a SIP request URI is empty. The application can change this by invoking setRequestURI on the newly created SipServletRequest. Note: ACK and CANCEL requests have special status in SIP. 11.1.7 Sending ACK and 11.1.9 Sending CANCEL discuss how and when applications generate those requests. The SipFactory methods listed above MUST throw an IllegalArgumentException when invoked to create ACK or CANCEL requests. Once constructed, the application may modify the request object, for example, by setting the request URI, adding headers, or setting the content. The request is then sent by invoking the
11-2
C l i e n t F un c t i o n s
send() method on SipServletRequest. The request is routed by the container based on the
request URI and any Route headers present in the request, as per the SIP specification. A fourth version of SipFactory.createRequest is intended specifically for writing back-to-back user agents, and is discussed in 12.1 B2BUA Helper Class.
This method constructs a request with container provided values for request URI and Call-ID, From, To, CSeq, and Route headers. Again, the application may modify the request before invoking it by invoking the send method on the request object.
11-3
Ac tin g as a Us er Ag en t
Route values before being delivered to the destination. This is what is known as a pre-loaded Route in the SIP specification. The SipServletRequest interface defines the pushRoute method for adding entries to the Route header field:
void pushRoute(SipURI uri);
The pushRoute method is applicable to be used by UAs only till the time when the dialog has not yet been established. This means that pushRoute can only be done on the initial requests. Subsequent requests within a dialog follow the route set. Any attempt to do a pushRoute on a subsequent request in a dialog MUST throw an IllegalStateException. The Route header behaves like a stack pushRoute adds items to the head of the list and the SIP routing algorithm pops items from the top. Therefore, if pushRoute is called more than once, the request will visit the most recently added proxy first. The same mechanism is available for proxying applications and is discussed in 10.2.2 Pushing Route headers.
If the send method call throws an exception it means the request was not successfully sent and the application will not receive any callbacks pertaining to that transaction, that is, the application will not receive any responses for this request. If the send method does not throw an exception, the container is obliged to present the application with a final response except for an ACK request. Containers may send the request asynchronously in which case sending may fail after the send method has returned successfully. In this type of situation, the container will generate its own final response except for an ACK request. In this particular case, a 503 (Service Unavailable) response would be appropriate as per [RFC 3261 8.1.3.1 and 16.9].
11-4
C l i e n t F un c t i o n s
with SipServletResponse and a null value for the request argument. If the servlet extends the SipServlet abstract class, the response will be further dispatched based on the value of the status code.
The application may modify the returned ACK object before invoking send on it. It is the containers responsibility to retransmit application generated ACKs for 2xxs when a 2xx retransmission is received and the container must not deliver the 2xx retransmission to the UAC
11-5
Ac tin g as a Us er Ag en t
application. It is recommended that containers generate ACKs for non-2xx final responses prior to invoking the application, so as to stop response retransmission as soon as possible.
is to be used on the SipServletResponse. The RAck header will be populated by the container in such PRACKs according to procedures specified in RFC 3262.
The application sends the returned CANCEL request by invoking send on it. Note that responses to CANCEL requests are not passed to the application. UACs and proxies are not allowed to cancel an INVITE request before a 1xx response has been received [RFC 3261, section 9.1]. SIP Servlet applications may do so, though. It is the containers responsibility to delay sending of the CANCEL until a provisional response has been received.
Ser v e r F un c t i o n s
retransmitted end-to-end. The SIP specification is defined in terms of a layered software model in which the transaction user (a UAS in this case) accepting an INVITE is responsible for periodically retransmitting the 2xx [RFC 3261, section 13.3.1.4]. In the SIP Servlet API this task must be handled by the container. This is fully within the scope of the logical model used for purposes of presentation in RFC 3261.
Ac tin g as a Us er Ag en t
11-8
S E C T I O N 12
A back-to-back user agent (B2BUA) is a SIP element which acts as an endpoint for two or more dialogs and forwards requests and responses between those two dialogs in some fashion. Experience has shown that they are one of the most frequently used application types. B2BUAs are sometimes considered undesirable because of their potential to break services. This potential stems from the fact that they sit between two endpoints and in some way mediate the signaling between the endpoints. If the B2BUA doesnt know about an end-to-end service being used between those two endpoints it may inadvertently break it. B2BUAs are, however, an important tool for SIP application developers and as such are supported by the SIP Servlet API. This specification adds a new helper class and some new methods to the SIP Servlet API making the B2BUA pattern very easy to implement.
This also indicates to the container that this application wishes to be a B2BUA. Any UA operation would be permitted by the application but the application cannot act as Proxy after that, so any invocation to getProxy() must then throw IllegalStateException.
12-1
Similarly the getB2buaHelper() method would throw an IllegalStateException if the application has already retrieved a proxy handle by an earlier invocation of getProxy().
This method creates a request identical to the one provided as the first argument according to the following rules: All unknown headers and Route, From and To headers are copied from original request to the new one. A new From tag is assigned by the container to this newly created request. Record-Route and Via header fields are not copied. As usual, the container will add its own Via header field to the request when its actually sent outside the application server. The headers in the new request can be taken for the optional headerMap which is a Map of headers that will be used in place of the ones from origRequest. eg.
{From => {sip:myname@myhost.com}, To => {sip:yourname@yourhost.com} }
where "From" and "To" are keys in the map. The only headers that can be set using this headerMap are non-system headers and From, To and Route headers. For Contact header if present only the user part and some parameters are to be used as defined in 4.1.3 The Contact Header Field. The values in the map is a java.util.Set to account for multi-valued headers. The values in headerMap MUST override the values in the request derived from the origRequest. Specifically they do not append header values. Attempt to set any other system header results in an IllegalArgumentException.
12-2
The "linked" boolean flag indicates whether the ensuing SipSession and SipServletRequest are to be linked to the original ones. The concept of linking is discussed in 12.3 Linked SipSessions And Linked Requests. For non-REGISTER requests, the Contact header field is not copied but is populated by the container as usual. These methods are included for convenience and performance. Like other createRequest methods, the returned request belongs to a new SipSession. Note: The SipFactory.createRequest(SipServletRequest origRequest, boolean sameCallId) method has been deprecated in this specification as the usage of this method with sameCallId flag as "true" actually breaks the provisions of [RFC 3261] where the Call-ID value is to be unique accross dialogs. Instead, the use of B2buaHelper.createRequest(SipServletRequest origRequest) is recommended.
The effect of this method when the linked parameter is true, is to create a new SipServletRequest using the original request, such that the two SipSessions and the two SipServletRequests are linked together. When the two SipSessions and requests are linked then you may be able to navigate from one to the other. The sessions linked can then later be accessed as doSuccessResponse(SipServletResponse response) { .... otherSession = B2buaHelper.getLinkedSession(response.getSession());
12-3
The getLinkedSession is a method defined on the B2buaHelper class. The helper works like a Visitor to the SipSession (and other classes) and encapsulates the functionality useful to a B2BUA implementation. Note that 1-1 linking is a convenience function and in no way mandatory for B2BUA functionality, in other words, the old style B2BUAs using just v1.0 API, where the peer session/request was stored as attributes, are also supported without any change. Similar to SipSessions, the linked SipServletRequest can be obtained from the method: B2buaHelper.getLinkedSipServletRequest(SipServletRequest). Besides the B2buaHelper.createRequest() method, the linking can also be explicitly achieved by calling:
B2buaHelper.linkSipSessions(session1, session2) throws IllegalArgumentExcetion;
The IllegalArgumentException is thrown when the sessions cannot be linked together, such as one or both sessions have terminated or belong to different SipApplicationSessions or one or both have been linked to some different SipSessions. Also for unlinking B2buaHelper.unLinkSipSessions(session) throws IllegalArgumentException;
unlinks other session linked with this session. One SipSession at any given time can be linked to only one other SipSession belonging to the same SipApplicationSession. The linkage at the SipServletRequest level is implicit whenever a new request is created based on the original with link argument as true. There is no explicit linking/unlinking of SipServletRequests.
12-4
Here the session is the SipSession on which this subsequent request is to be sent, the origRequest is the request received on another SipSession using which this request is to be created and the headerMap can contain any non system header which needs to be overridden in the resulting request, any attempt to set any system header results in an IllegalArgumentException. The semantics of this method is similar to the SipSession.createRequest This also results in automatically linking the two SipSessions (if they are not already linked) and the two SipServletRequests
The conditions under which a message is considered committed is detailed under 5.2 Implicit Transaction State. A method defined on the new B2BUA Helper class would give the application a list of un-committed messages in the order of increasing CSeq based on the UA mode. This is because there may be more than one request/response uncommitted on a SipSession.
List<SipServletMessage> B2buaHelper.getPendingMessages(SipSession, UAMode);
The UAMode is an enum with values of UAC or UAS. The same session can act as UAC or UAS, the UAMode indicates messages pertaining to which mode is queried. For example, consider a B2BUA involved in a typical INV-200-ACK scenario that receives an ACK on one leg and wishes to forward it to the other. The B2BUA could call B2buaHelper.getPendingMessages(leg2Session, UAMode.UAC) to retrieve the pending messages which (as per 5.2 Implicit Transaction State, point 7) would contain the original 200 response received on the second leg. The B2BUA could then create the ACK using the
JSR 289: SIP Servlet Specification v1.1 12-5
The response thus generated MUST have a different "To" tag from the other responses generated to the request and must result in a different SipSession. In this (and similar) cases the container clones the original SipSession for the second and subsequent dialogs, as detailed in 6.2.3.2 Derived SipSessions. The cloned session object will contain the same application data but its createRequest method will create requests belonging to that second or subsequent dialog, that is, with a "To" tag specific to that dialog.
O ri gi n al R e q ue s t a nd S e s s i o n C l o n i n g
SipSession lazily. The applications then can create the response to the original request but now
in the context of UAS-2 by invoking the method SipServletResponse B2buaHelper.createResponseToOriginalRequest(SipSession session-uas-2, int status, String reasonPhrase) throws IllegalStateException;
12-7
12-8
S E C T I O N 13
SIP Servlet API is designed to facilitate the creation of SIP based applications in an easy servlet programming model. The SIP Servlet API was based on the Servlet API and thus was a peer to the HTTP Servlet API. Many of the interesting applications require the use of both SIP and HTTP protocols in a single application use-case, as an example a conference call application providing a web portal for management and monitoring, a classic click-to-call application, a CBSNA application etc. Therefore the usage of SIP Servlet API and HTTP Servlet API together in a converged application is a natural fit. Based on the fact that HTTP Servlet API is closely associated with the Java EE standards and also based on the real world requirements to have a comprehensive convergence model, a number of features are required to be supported by a converged container to enable not only SIP and HTTP convergence but also SIP Servlets and rest of Java EE. This section details the converged container features in detail.
13-1
If the application.xml deployment descriptor is not present, then all files in the application package with a filename extension of .war or .sar and which contain the sip.xml deployment descriptor are considered converged SIP components. This application scope is used to determine the extent of availability of convergence features in Java classes as we will see in the following sections on SipFactory and SipSessionsUtil injections.
Application class-loader Application scoped JNDI, which can be looked up against "java:comp/env" on the InitialContext. A converged SIP and Web applications MAY also be packaged as independent sar/war and war files respectively, within a single application ear file. If such a packaging structure is used then the convergence features are similar to SIP and Java EE components, specifically the benefits of a single sar/war file of shared context are not available.
are equivalent. For converged containers, the injected SipFactory would appear as sip/<appname>/SipFactory in the application scoped JNDI tree, where the appname is the name of the application as identified by the container (see 7.6 Application Names). In this example, this annotation can be used in any SIP Servlet or a Java EE application component deployed on the converged container in the same EAR archive file. The container must inject an instance of SipFactory into the field ("sf" in this example) at the time of
JSR 289: SIP Servlet Specification v1.1 13-3
application initialization. For the purposes of associating a Servlet, with, say the responses received to the request created using the SipFactory, the container must use the application's main servlet as defined in 16.2 Servlet Selection. This can be changed to another servlet through the setHandler method of the SipSession. Note that containers MAY allow the @Resource annotation to be present outside of SIP applications. In such cases, the name element of the @Resource annotation MUST identify the JNDI name of the desired factory to inject. Otherwise, an invocation of SipFactory.createApplicationSession() would be unable to determine the intended SIP application.
MUST provide a SipSessionsUtil lookup object using which the converged applications can access the SipApplicationSession instance by its ID. The reference to this lookup utility can be obtained from the ServletContext attribute javax.servlet.sip.SipSessionsUtil or by use of the @Resource annotation as described in 18.2.7 Annotation for SipSessionsUtil Injection. Similar to the constraints on injection on SipFactory, the SipSessionsUtil lookup MUST NOT return the SipApplicationSession instance across application boundaries. Specifically if
getApplicationSessionById(java.lang.String applicationSessionId)
is invoked for an applicationSessionId not belonging to a certain application, the invocation MUST return null. The application boundary or scope as used in this application is the packaging structure of an ear archive file. Similarly, a SipApplicationSession instance created with a specific session key (using SipFactory.createApplicationSessionByKey) can be looked up by :
getApplicationSessionByKey(java.lang.String applicationSessionKey, boolean create)
13-4
E nc o din g U R L s
The converged containers MUST make available the javax.servlet.sip.ConvergedHttpSession, an extension of javax.servlet.http.HttpSession to the applications. The effect of invoking this method is that the application session if currently associated is returned, however if no application session is associated it is created, associated with the HttpSession and returned.
JSR 289: SIP Servlet Specification v1.1 13-5
Another way a new ConvergedHttpSession gets associated with a SipApplicationSession is when the HTTP request has an URL encoded with an existing SipApplicationSession as described in 13.4 Encoding URLs.
13.7 Encoding HTTP URLs With HTTP Sessions In Non HTTP Scope
Given an application with multiple sessions (SIP and HTTP) it is often required to create an encoded HTTP URL such that the subsequent HTTP requests are routed to the correct HTTP session. This encoding is different from the one defined in 13.4 Encoding URLs because in this case the HttpSession ID is encoded with parameter "jsessionid" as defined in the HTTP Servlet specification. The methods for this are defined on the ConvergedHttpSession interface.
13-6
S E C T I O N 14
14 Container Functions
14-1
also it is possible for the application to accept the Subscription for a shorter duration and convey the same in a 200 OK Response's "Expires" header. Container however provides primitives like a Timer API, access to Session, Request etc to facilitate the applications carrying out such functions. The above two examples illustrate that due care has been taken to provide the right level of abstraction to the application developer. Having said that, it is expected that some repetitive use cases will be found, some patterns which shall have to be re-used within SIP Servlet Applications. With this specification is provided a powerful mechanism for application composition [chapter 15 Application Selection And Composition Model], we are hopeful that future applications shall use this feature to re-use application features or patterns.
14-2
M ul ti h o m e d H o s t S up p o rt
Throw an IllegalStateException where the method receiver (object on which the method is called) is not in a state where the invocation is suitable. Throw a ConcurrentModificationException if the base collection gete modified when the Iterator is being used unless the collection is otherwise concurrent. The idea is to provide an environment of least surprise to the application developer.
The applications can access the list of SIP URIs which can be used by the application to send the outbound requests. The applications can access this through a ServletContext attribute javax.servlet.sip.outboundInterfaces. The container MUST implement a method to set the outbound interface for a certain session: setOutboundInterface(InetAddress address), this interface must then be used by the container for all messages associated with that SipSession. This method is provided on Proxy, ProxyBranch and SipSession object. Invocation of this method also impacts the system headers generated by the container for this SipSession, such as the Via and the Contact headers. The supplied IP address is used to construct these system headers. This setting may be overwritten by subsequent calls to the method. In case there is no specific outbound interface set, the container shall apply default behaviour of interface selection. Once the interface is selected on a multihomed host, the SIP servlet container must populate the Systems Headers (see 5.4.2 System Headers) accordingly.
14-4
S E C T I O N 15
SIP servlet application servers are typically provisioned with many different applications. Each application provides specific functionality, but, by invoking multiple applications to service a call, the deployer can build a complex and complete service. This modular and compositional approach makes it easier for application developers to develop new applications and for the deployer to combine applications from different sources and manage feature interaction. A typical example from traditional telephony is a call-screening application and a call-forwarding application. If the application server receives an incoming INVITE destined to a callee who subscribes to both services, both applications should be invoked. One key requirement for application composition is that the correct set of applications be invoked in the correct order to service a call. Therefore, an important function of SIP servlet application servers is to select applications for invocation and route SIP messages to them. When determining which applications to invoke and in which order, containers treat initial requests, subsequent requests and responses differently. Generally speaking, an initial request is a request for which the container has no a priori knowledge. It may or may not be a request capable of establishing a dialog [RFC 3261, Section 12]. Appendix B contains a precise definition of initial requests. Initial requests are routed based on an application selection process. The routing of an initial request establishes a path of applications. Subsequent requests and responses are then routed along the path taken by the initial request. The principles of application independence and composition described in this section are adapted from the Distributed Feature Composition (DFC) architecture [DFC1998], [CN2004], [SE2005]. The original definition of DFC [DFC1998] has been improved as a result of extensive experience with it.
15-1
15-2
A pp l i c at i o n S e l e c ti o n Pr o c e s s
implementation. Giving the deployer control over application composition is desirable because it is the deployer who is most aware of and responsible for the totality of services provided to his or her subscribers. Furthermore, this specification intentionally allows the Application Router implementation to consult arbitrary information or data stores. This is because the deployer maintains subscriber information and this information is often private and valuable.
15-4
A pp l i c at i o n S e l e c ti o n Pr o c e s s
Figure 15-2 Maintaining SIP Context with Multiple Applications Active on Same Container
Note: The SIP Servlet Applications are modeled as isolated, individually deployable component of larger composite applications or services. It is foreseeable that in large systems which maximally benefit from the innovations of unrelated developers and development projects, the relationship between deployed SIP Servlet application implementations will be defined solely by the deployer and/or the implementor of the Application Router. Composition of those SIP Servlet Applications into application usages of the SIP network itself is facilitated in this way, and the developer of a given SIP Servlet application should make no assumptions about the model for deployment and method of composition of these composite applications. In such cases it is possible that SIP Servlet applications may be deployed within a single SIP Servlet container or may be deployed in multiple SIP Servlet containers, each representing a different but compliant implementation of this specification.
The concepts of Subscriber Identity and Routing Region are introduced here so that an application may learn in which region it is invoked and on behalf of which subscriber. When the Application Router selects an application to service a request, it MUST specify the routing region in the SipApplicationRouterInfo object that it returns to the container. The routing region can be one of ORIGINATING_REGION, TERMINATING_REGION, NEUTRAL_REGION or one of their sub-regions. The Application Router MUST also specify the subscriber identity in the SipApplicationRouterInfo object when the routing region is set to either ORIGINATING_REGION or TERMINATING_REGION. The Application Router MAY specify the subscriber identity when the routing region is set to NEUTRAL_REGION. The subscriber identity is a javax.servlet.sip.URI object. The container MUST make the subscriber identity and routing region values as set by the Application Router available to the selected application using the SipSession.getSubscriberURI() and SipSession.getRegion() methods. In most cases, an application selected to serve the calling subscriber is invoked in the originating region while an application selected to serve the called subscriber is invoked in the terminating region. Often, an application not designed to serve any specific subscriber (such as the call logging application mentioned above) will be invoked in the neutral region and the subscriber identity will not be set by the Application Router. (Note that the Application Router sets the routing region and subscriber identity along with the application name on the SipApplicationRouterInfo object that is returned to the container as part of the SipApplicationRouter.getNextApplication() call.) The routing regions are extensible and an implementation of the Application Router may further subdivide these regions into smaller regions if necessary. For example, one may define new sub-regions - TERMINATING_REGISTERED and TERMINATING_UNREGISTERED within the terminating region by extending SipApplicationRoutingRegion as shown below:
TerminatingRegisteredRegion extends SipApplicationRoutingRegion { public TerminatingRegisteredRegion () { super("TERMINATING_REGISTERED",TERMINATING_REGION); } } TerminatingUnRegisteredRegion extends SipApplicationRoutingRegion { public TerminatingUnRegisteredRegion () { super("TERMINATING_UNREGISTERED",TERMINATING_REGION); } }
15-6
Ap pl i c a ti o n En v i r o n me nt a nd B e h av i o ur
Deployers could thus define applications to be invoked in the above sub-regions. An application like the Location Service application defined in the TERMINATING_REGISTERED sub-region would be invoked for subsribers whose termials have registered with the registrar; while applications like the Voicemail application defined in the TERMINATING_UNREGISTERED region would be invoked only for those subscribers who have not yet registered.
15-7
This is crucial to the selection of applications. As an example, consider a deployment where all initial INVITE requests received by the container are serviced by two applications, A and B, in this order. When an INVITE request is received externally, or if an application Z acts as a UAC and sends a INVITE request, the container invokes the Application Router. The Application Router starts the selection process from the beginning and selects A. When A is invoked and proxies the INVITE request, again the container invokes the Application Router. Now, the Application Router must be made aware that this is related to the previous request so that it can determine that A has already been invoked and that B must be invoked as the next application. When an application acts as a UAC and sends a request, the request is not based on any previously received request. That is, the application intends the request to be regarded as a new request unrelated to any other request. Although the application intention is implicit in this case, it is clear that a new application selection process should take place. Listing 15-1 Application acts as UAC and sends initial request
+-------------------------------------+ | | | req = factory.createRequest | | (appSession, | req | "INVITE", from, to); |------> | req.send(); | | | +-------------------------------------+ req starts a new selection process
In the case of a proxy application, there is no ambiguity. It is clear that the application's intention is to send the request along the way, or in other words to continue the call. Listing 15-2 Application proxies an initial request
+-----------------------------+ req1 | | req2 ------->| proxy = req1.getProxy(); |---------> | proxy.proxyTo(...); | | | +-----------------------------+ req2 is a continuation of req1
15-8
Ap pl i c a ti o n En v i r o n me nt a nd B e h av i o ur
If the application acts a B2BUA, and uses the SipFactory.createRequest(SipServletRequest origRequest, boolean sameCallId) or B2buaHelper.createRequest(SipServletRequest origRequest, Map headers) methods, then again it is clear the the application's intention is to continue the call. Listing 15-3 Application acts as B2BUA to relay initial request
+------------------------------------------+ req1 | | req2 ------->| req2 = factory.createRequest(req1, ...); |---------> | req2.send(); | | | +------------------------------------------+ req2 is a continuation of req1
In the cases encountered so far, the application intentions are clear from context. Such intentions are referred to as routing directives. In the first case the application implicitly signaled a NEW directive, and in the second and third cases the application implicitly signaled a CONTINUE directive. Unlike the cases described above, there are times where an explicit directive is required. Listing 15-4 Application acts as B2BUA to relay initial request and signals the CONTINUE directive explcitly
+------------------------------------------+ | | req1 | req2 = factory.createRequest(appSession, | req2 ------->| "INVITE", newFrom, req1.getTo()); |---------> | // copy headers and content from req1 | | req2.setRoutingDirective(CONTINUE, req1);| | req2.send(); | +------------------------------------------+ req is a CONTINUE
In case, an application wishes to send a new request based on a received request but intends the request to be regarded as a new request, thereby initiating a new selection process. The application could create the new request separately and copy all the headers and content, but it is far easier to create the request based on an existing request and then indicate a routing directive explicitly by making use of a method in the SipServletRequest class introduced in version 1.1,
JSR 289: SIP Servlet Specification v1.1 15-9
In the above case, a new application selection process will begin for the req2. Finally, a third directive, REVERSE, is necessary but is used less commonly. REVERSE is used when an application reverses the direction of the call. There are two cases. In the first case, an application invoked to service the caller for an initial request now wishes to place a call back to the caller. A practical example is a Call Waiting (CW) application. When a subscriber to CW places a call, CW is invoked to serve the caller. When this call is still up, the subscriber receives an incoming call. CW alerts the subscriber, who then activates CW to put the first callee on hold, and switch to the new caller. If the subscriber finishes the conversation with the new caller and hangs up the phone, forgetting that there is another call on hold, the CW feature places a call to the subscriber. In this call, the subscriber is now the callee. In the second case, an application which is invoked to service the callee in a request, now wishes to place a call on behalf of that same subscriber as the caller. A practical example is a three-way calling (3WC) application. When the subscriber receives a call, the 3WC application is invoked to serve the subscriber as the callee. In the middle of the call, the subscriber activates the 3WC application to call a third person, with the subscriber as the caller. In both cases, the direction of the call is reversed, and the applications must specify the REVERSE directive so the Application Router is able to select the next application correctly. Listing 15-6 Application reversing the call direction by placing a call back to the caller
+------------------------------------------+ | | | req2 = factory.createRequest(appSession, |
req1
15-10
A pp l i c at i o n R o u te r B e ha v i o r
Caller
------->| "INVITE", newFrom, req1.getFrom(),...);| | // copy headers and content from req1 | req2 | req2.setRoutingDirective(REVERSE, req1); | <-------| req2.send(); | +------------------------------------------+ req2 is a REVERSE
It is important to note that in the cases where an application is sending a request based on a previously received request, the transaction of the received request may have completed, or indeed the SIP dialog may have completed and terminated. Indeed, in 3WC the transaction is already completed, and in busy retry the SIP dialog has already terminated. The application may store the request for later use. Note also that the second argument to setRoutingDirective must be an initial request received by the application, i.e.SipServletRequest.isInitial() must be true. The following table summarizes the routing directive under different scenarios: Table 15-1 Routing Directives Application Action
Req = factory.createRequest(appSession, "INVITE", from, to); request.getProxy().proxyTo() req2 = factory.createRequest(req1, ...); req2.send(); req2.setRoutingDirective(directive, req1);
Directive
NEW
Note: If recursion is enabled, and the container automatically proxies to contact addresses received in redirect (3xx) responses, these requests are treated as if the application explicitly called proxyTo() to proxy to these contact addresses. Therefore they also have the CONTINUE directive.
15-11
process is started fresh. In this case, the Application Router is called with the following information: The SipServletRequest The routing directive which is NEW Based on the supplied information, and its configuration of which subscriber subscribes to which set of applications, and any other information that it may wish to use (e.g. time of day, network condition, external subscriber profile database), the Application Router returns the following information: the name of the selected application the subscriber identity that the selected application is to serve the routing region that the application serves in an optional route, which can be local or remote a route modifier which tells the container how to interpret the route an optional stateInfo Serializable object The Application Router can return routes to the container via its SipApplicationRouterInfo.getRoutes() method. The routes can be external or internal. External routes are used by the Application Router to instruct the container to send the request externally. Internal route is returned when the Application Router wishes to modify the popped route header as seen by the application code (through the SipServletRequest.getPoppedRoute() API call). When the request is received by the container the request may have had a Route header belonging to the container, which the container removes and makes available through the provisions of 5.6.3 Popped Route Header . The route modifier returned by the Application Router tells the container how to make use of the routes returned by it and also how the popped route needs to be presented. The route modifier can be one of the following enum values - ROUTE, ROUTE_BACK, NO_ROUTE. ROUTE modifier indicates that SipApplicationRouterInfo.getRoutes() returns valid routes. It is up to the container to decide whether they are external or if an internal route was returned. All of the routes returned MUST be of the same type, so the container can make the determination by examining the first route only. ROUTE_BACK directs the container to push its own route before pushing the external routes obtained from SipApplicationRouterInfo.getRoutes().
15-12
A pp l i c at i o n R o u te r B e ha v i o r
NO_ROUTE indicates that Application Router is not returning any routes and the SipApplicationRouterInfo.getRoutes() value, if any, should be disregarded. The behavior of container with respect to the route modifiers is explained in 15.4.1 Procedure for Routing an Initial Request. The stateInfo Serializable object is useful for the Application Router to store state information from one invocation to the next. An Application Router implementation may choose to put any information in the stateInfo object, and this object is opaque to the container, and not accessible to the applications. Typically, an Application Router implementation may store information such as subscriber identity, routing region, the name of the application last invoked, and a precomputed list of applications that are to be invoked next. If the selected application subsequently proxies or sends a new initial request based on the first one with a CONTINUE or REVERSE routing directive, again the Application Router is called. This time, in addition to the SipServletRequest and routing directive, it is also supplied with the stateInfo object that it previously returned. In this way, the Application Router delegates the maintenance of the application selection state to the container, and thus it can be stateless with respect to each initial request it processes. If the Application Router determines that no application is selected to service a request, it returns null as the name.
15-13
arbitrary, opaque state information returned from the Application Router The next section details the procedures for routing an initial request and when the above fields are set, followed by a description of the appliction router packaging and deployment model.
The following procedure is then executed: 1. Call the SipApplicationRouter.getNextApplication() method of the Application Router object. The Application Router returns a SipApplicationRouterInfo object, named 'result' for this discussion. 2. Check the result.getRouteModifier() If result.getRouteModifier() is ROUTE, then get the routes using result.getRoutes(). If the first returned route is external (does not belong to this container) then push all of the routes on the Route header stack of the request and send the request externally. Note that the first returned route becomes the top route header of the request. If the first returned route is internal then the container MUST make it available to the applications via the SipServletRequest.getPoppedRoute() method and
JSR 289: SIP Servlet Specification v1.1 15-15
ignore the remaining ones, if any. This allows the AR modify the popped route before passing it to the application. If result.getRouteModifier() is ROUTE_BACK then push a route back to the container followed by the external routes obtained from result.getRoutes() and send the request externally. Note that the container route SHOULD include AR state encoded as a route parameter in order for the AR to continue processing the application chain once the request returns back to the container. If result.getRouteModifier() is NO_ROUTE then disregard the result.getRoutes() and proceed. 3. Check the result.getNextApplicationName() If result.getNextApplicationName() is not null: set the application selection state on the SipSession: stateInfo to result.getStateInfo(), region to result.getRegion(), and URI to result.getSubscriberURI(). follow the procedures of Chapter 16 to select a servlet from the application. If result.getNextApplicationName() is null: If the Request-URI points to a different domain, or if there are one or more Route headers, send the request externally according to standard SIP mechanism. If the Request-URI does not point to another domain, and there is no Route header, the container should not send the request as it will cause a loop. Instead, the container must reject the request with 404 Not Found final response with no Retry-After header. While routing requests within the container to the next application in the chain if the route modifier as returned by the Application Router is not ROUTE then the container MUST NOT push routes just to route the requests to the applications. SIP servlet applications, however, are free to push internal and external routes if they so require. Note: As a guideline it is strongly recommended for applications do not rely on Via or Record-Route headers for their application logic, as within the container the container implementations may chose to optimize the handling of the system headers by either aggregating them while going out or just replacing them with one container level header and maintaining the state internally. The applications SHOULD instead use the SipServletMessage methods getLocalXXX, getRemoteXXX methods if they are interested in the upstream entity. If SipApplicationRouter.getNextApplication() throws an exception, the container should send a 500 Server Internal Error final response to the initial request.
15-16 JSR 289: SIP Servlet Specification v1.1
file. The contents of the file indicate the name of the concrete public subclass of the javax.servlet.sip.ar.spi.SipApplicationRouterProvider class. The concrete subclass must have a no-arg public constructor. As specified by the Service Provider framework, the providers may be installed by : 1. Including the provider jar in the system classpath 2. Including the provider jar in the extension class path 3. Container-specific means If the container uses classpath-based deployment, the first Application Router jar file found in the classpath is installed. In order to avoid ambiguity when multiple Application Router implementations are present in the classpath, this specification also defines a system property which instructs the container to load a given provider. The javax.servlet.sip.ar.spi.SipApplicationRouterProvider system property can be used to override loading behavior and force a specific provider implementation to be used. For portability reasons, containers that provide their own deployment mechanism for the Application Router SHOULD observe the system property, if specified by the deployer.
"myj2eeapp/mysipapp/org_sipservlet_app_voicemail" where the voice mail application with the following deployment descriptor is packaged in a war archive by the name of "mysipapp.war" which is packaged in an ear archive by the name of "myj2eeapp.ear". Listing 15-7 Example of sip.xml file illustrating app-name and servlet-name
<sip-app> <app-name>org.sipservlet.app.voicemail</app-name> ... <servlet> <servlet-name>depositServlet</servlet-name> <servletclass>org.sipservlet.app.voicemail.DepositServlet</servlet-class> ... </servlet> <servlet> <servlet-name>retrievalServlet</servlet-name> <servletclass>org.sipservlet.app.voicemail.RetrievalServlet</servletclass> ... </servlet> ... </sip-app>
If the aforementioned application was a v1.0 style application with similar packaging and were to be deployed on a container compliant with this specification, the application name SHOULD be "myj2eeapp/mysipapp". The containers MAY further distinguish these names by adding their own versioning tokens. If the application is specified by annotation, Chapter 18 provides the procedures for determining the name of such applications.
15-18
called subsequent requests in this specification. Subsequent requests are not dispatched to applications based on the application selection process. Correct routing of subsequent requests and responses can be achieved in several ways, and it is up to implementations to choose one. It is recommended that when routing messages internally between the applications the container SHOULD make use of the SIP mechanism of adding the Via header and adding the Record-Route (if it is record-routing proxy or a B2BUA) to allow for a robust stateless composition chain. However it is entirely possible that the implementations MAY chose to hide the internal topology by maintaining the application path state outside of SIP message. The implementation MUST however make sure that the parameters added to the Record-Route headers by individual applications are made available through the Route header on the subsequent request. The goal is to provide SIP consistency both at the application interface level and external SIP entity level. Subsequent requests originated from the caller follow the path, or more precisely a subset of the path, of the corresponding initial request. Subsequent requests originated from the callee as opposed to the caller follow the reverse path. Responses always follow the reverse of the path taken by the corresponding request. This is true for responses to both initial and subsequent requests. The application path is a logical concept and as such may or may not be explicitly represented within containers. For illustration, suppose three applications, A, B, and C, are invoked one after another to process an initial INVITE request. All three applications proxy but only A and C record-route, and so the application path consists of A and C along with associated contexts (sessions). A subsequent BYE request received from the callee will then be routed based on this application path, and will be passed first to C and then to A. The distinction between initial and subsequent requests also applies to dispatching of locally initiated requests. If, for example, application A initiates an INVITE, and this is passed to application B which proxies it with record-routing enabled towards a destination outside the application server, then a subsequent BYE from A for the same dialog will be passed to B and then further downstream. Proxying of subsequent requests is discussed in 10.2.9 Handling Subsequent Requests. It is worth noting that a SipSession can belong to at most one application path. This is because initial requests are processed in the context of new SipSessions and because there is a one-to-one correspondence between application paths and SIP dialogs. If the initial request results in more than one dialog being set up, the container will create derived SipSessions for the second and subsequent paths being created, see 6.2.3.2 Derived SipSessions.
15-19
When a SipSession terminates, either because the SipApplicationSession it belongs to times out or is explicitly invalidated or because the SipSession itself is explicitly invalidated, it is removed from the application path it was on, if any. If application paths are represented explicitly within containers, they are removed when the path becomes empty.
received from an external entity but if the request was internally routed (from one application to the next on the same container) then it MUST return the address of the container's SIP interface
getRemotePort() - MUST return port of the remote SIP interface if the request was
received from an external entity but for the internally routed message the container is free to choose any port value consistent with one that would be chosen were the container to have actually sent the message out and back to itself through the local TCP/IP stack
getLocalAddr() - address of the SIP listening interface on which this message was
originally received from the external SIP entity throughout the chain.
getLocalPort() - port number of the SIP listening interface on which this message was
originally received from the external SIP entity throughout the chain.
getTransport() - actual transport on which this message was received from the external entity and for the internally routed request - TCP or TLS to indicate that this is a reliable transport. getInitialRemoteAddr() - the IP address of the upstream/downstream hop from which this message was initially received by the container. This method returns the same value regardless of which application invokes it in the same application composition chain. getInitialRemotePort() - the port number of the upstream/downstream hop from which this message was initially received by the container. This method returns the same value regardless of which application invokes it in the same application composition chain. getInitialTransport() - the name of the protocol with which this message was
initially received by the container. This method returns the same value regardless of which application invokes it in the same application composition chain.
15-20
P o p pi n g o f T o p R o u te H e a de r
for the incoming TLS connection the X.509 certificate MUST be made available only to the first application that receives the message from outside of the container through the javax.servlet.request.X509Certificate for requests and javax.servlet.response.X509Certificate for responses. However, if the container is able to authenticate the remote user based on the credentials in the certificate then that authentication information MUST be made available to all the applications as described in 17.6 Server Tracking of Authentication Information
1. Request R from Alice arrives at the container. 2. The request contains two route headers, A_i and B_e. A_i represents a route pointing to the container, B_e means it is an external route. The AR receives the request R.
15-21
3. Inside of the AR, R.getPoppedRoute() returns A_i as A_i is popped by the container prior to passing the request onto the AR. Also, R.getInitialPoppedRoute() returns A_i. R still contains B_e route header. The AR returns App1, and NO_ROUTE modifier to the container. 4. App1 executes. 5. Inside of App1, R.getPoppedRoute() returns A_i and R's top route is B_e. R.getInitialPoppedRoute() returns A_i. App1 proxies request to Bob, without calling pushRoute(). 6. The AR intercepts the request again. 7. Inside of the AR, R.getPoppedRoute() returns null and R still contains B_e as its top route. R.getInitialPoppedRoute() still returns A_i. AR returns App2 and NO_ROUTE modifier to the container. 8. App2 executes. 9. In App2, R.getPoppedRoute() returns null, and R's top route is B_e. R.getInitialPoppedRoute() returns A_i. App2 proxies R to R's Request-URI (Bob). The AR executes. AR returns null application to the container, and NO_ROUTE. This causes the container to send the request to B_e, as per 15.4.1 Procedure for Routing an Initial Request, point 3.
1. Request R from Alice arrives at the container. 2. The request contains two route headers, A_i and B_e. A_i represents a route pointing to the container, B_e means it is an external route. The AR receives the request R. 3. Inside of the AR, R.getPoppedRoute() returns A_i as A_i is popped by the container prior to passing the request onto the AR. R.getInitialPoppedRoute() returns A_i. R still contains B_e route header. The AR returns App1, and NO_ROUTE modifier to the container. 4. App1 executes.
15-22
Exa mpl es
5. Inside of App1, R.getPoppedRoute() returns A_i and R's top route is B_e. R.getInitialPoppedRoute() returns A_i. App1 calls R.pushRoute(C_i), where C_i represents a Route header pointing back at the container. Next, App1 proxies the request to Bob. The AR intercepts the request again. Inside of the AR, R.getPoppedRoute() returns C_i, and R's top route header is B_e. R.getInitialPoppedRoute() returns A_i. AR decides to return null application to the container, and NO_ROUTE. This causes the container to send the request to B_e, as per 15.4.1 Procedure for Routing an Initial Request, point 3.
1. Request R from Alice arrives at the container. 2. The request contains two Route headers, A_i and B_e. A_i represents a Route pointing to the container, B_e means it is an external Route. The AR receives the request R. 3. Inside of the AR, R.getPoppedRoute() returns A_i as A_i is popped by the container prior to passing the request onto the AR. R.getInitialPoppedRoute() returns A_i. R still contains B_e Route header. The AR returns App1, and NO_ROUTE modifier to the container. 4. App1 executes. 5. Inside of App1, R.getPoppedRoute() returns A_i and R's top route is B_e. R.getInitialPoppedRoute() returns A_i. App1 calls R.pushRoute(D_e), where D_e represents a Route header pointing to an external address. Next, App1 proxies the request to Bob. The AR intercepts the request again. Inside of the AR, R.getPoppedRoute() returns null, and R's top route header is D_e. R.getInitialPoppedRoute() returns A_i. AR decides to return null application to the container, and NO_ROUTE. This causes the container to send the request to D_e, as per 15.4.1 Procedure for Routing an Initial Request, point 3.
15.9 Examples
The first example uses a simple two applications scenario to illustrate the interactions between container, Application Router and applications along with the concept of application path and routing of subsequent requests and responses. It also serves to illustrate the concept of message
JSR 289: SIP Servlet Specification v1.1 15-23
context discussed in 6.4.1 Message Context. The examples that follow the first examine more complex application composition scenarios.
1. The container receives an INVITE request. The INVITE does not belong to an existing SIP dialog and so the container calls the Application Router with the request to obtain the name of the application to invoke. 2. The Application Router determines SD is the first application to serve the caller. The Application Router returns the name "SD", the caller's identity, and the originating region to the container together with some state information. 3. The container invokes the SD application in the context of (SD, as1, ss1). 4. SD, based on the caller's identity, performs database lookup to obtain the caller's speed-dial settings and proxies to the full address that corresponds to the speed-dial number. 5. The container receives the proxied request and again calls the Application Router with the request and the state information. 6. Based on the state information, the Application Router determines that SD has already been invoked and there are no other applications for the caller. Assuming that there are no applications in the neutral region, the Application Router proceeds to the terminating region and determines that LS is needed to service the callee. It returns the name "LS", the callee's identity, and the terminating region to the container, together with some state information.
15-24 JSR 289: SIP Servlet Specification v1.1
Exa mpl es
7. The container invokes the LS application in the context of (LS, as2, ss2). 8. LS, based on the callee's identity, performs database lookup to obtain the callee's location settings and proxies the request to destination d1. 9. The container receives the proxied request and calls the Application Router with the request and state information. 10. The Application Router determines that no applications are required for d1, and returns null to the container indicating there is no further application to be invoked. 11. The container proxies the request towards d1, that is, outside the application server. 12. The container receives a 200 (OK) response for the INVITE. The 200 response is passed upstream along the reverse path of the request, i.e. the container passes it first to the LS application in context (LS, as2, ss2) and then to the SD application in context (SD, as1, ss1), and then sends it to the caller. 13. Since the 200 response establishes a dialog, an application path is created. This means that the container will route subsequent requests in this dialog to applications along the signaling path. In this case the application path consists of (SD, as1, as2) and (LS, as2, ss2). 14. An ACK for the 200 is received. This is recognized as being a subsequent request and is associated with the previously established application path. (Incoming ACKs for non-2xx final responses are needed for protocol reasons only and are simply dropped.) 15. The container passes the ACK to the SD application in the context (SD, as1, ss1) and when the upcall to SD returns, it passes the ACK to the LS application in the context (LS, as2, ss2). When the upcall to LS returns, the container proxies the ACK outside the application server according to standard SIP routing rules. 16. Assuming that the callee hangs up first, the BYE is passed along the application path in the reverse direction, i.e. it is passed to LS first, then SD. Note that, logically, each application has its own set of SIP client and server transaction objects operating in accordance with the transaction state machines specified in the SIP specification [RFC 3261, chapter 17]. Likewise, logically, each proxy application executes its own instance of the proxy logic, for example, it has its own response context [RFC 3261, section 16]. This specification then "augments" the RFC 3261 defined state machines with additional rules, for example, that 100 responses, ACKs for non-2xx responses, and responses for CANCELs are not delivered to the applications.
15-25
15-26
Exa mpl es
The following is an example where the caller's address information is modified, resulting in a different set of originating applications being selected. Consider that Alice works at home as a customer care agent for her employer. She now subscribes to an additional originating application - Agent Identification (AI). If Alice is not working, this application does nothing. However, after Alice logs on to the employer's system, when Alice places a call this application modifies the caller URI (e.g. the From header) in the INVITE request to be sip:customer-care@employer.com and relays the request. The Application Router would then select originating applications subscribed to by the new caller URI, for example a Supervisor Monitor (SM) application may be selected so the supervisor may listen in and coach Alice.
(Alice) - AI ---------------- SM - ... Alice's Originating customer-care's originating
As another example, consider the case when Alice calls Carol and they are engaged in a conversation. The application path looks like:
(Alice) - CW - 3WC - OCS ------ ICL - CF - 3WC - CW - (Carol) Alice's Originating Carol's Terminating
15-27
When Alice activates 3WC to call Bob, 3WC continues the INVITE request it received previously, but modifies the callee to Bob. Because 3WC is in the originating region and the caller address is not modified, the application selection is not affected at this point and the remaining originating application, OCS, is selected. Then the terminating applications of Bob are selected. The resulting application path would then look like:
(Alice) - CW - 3WC - OCS ------ ICL - CF - 3WC - CW - (Carol) \ \ - OCS ------- ICL- CF - 3WC - CW - (Bob) Alice's Originating Bob's Terminating
Note that this usually happens some time after the initial Alice-Carol call was established. 3WC maintains a reference to the INVITE request it received initially so that it may use it to initiate a call to another party if it is ever activated. The application selection state information associated with that INVITE request has the same lifetime as the request.
In this state, Alice's 3WC application was invoked in a call where Alice is the callee. However, if Alice activates 3WC to call Bob, 3WC sends a new INVITE request where Alice is the caller and Bob is the callee. This distinction affects the application selection process. Normally, if 3WC is simply continuing the request in the same direction towards Alice as the callee, the next application invoked to serve Alice would be CW. However, in this case, the correct next application is OCS, followed by Bob's terminating region applications. The resulting application paths should look like:
(Carol) - CW - 3WC - OCS ------ ICL - CF - 3WC - CW - (Alice) \ \ - OCS ------ ICL - CF - 3WC - CW - (Bob)
15-28
L oop Detectio n
In other words, 3WC was previously operating in Alice's terminating region, but for the new call, 3WC is operating in Alice's originating region. Therefore, the Application Router selects Alice's originating applications, and in this case the next such application is OCS. In fact, one would observe that the application path from Alice's 3WC to Bob is identical to the corresponding portion.
has been deprecated in v1.1 of this specification as it is problematic and does not mesh well with the v1.1 application composition mechanism. The Session Key based targeting mechanism introduced in v1.1 of this specification is now the preferred mechanism to associate a request with a particular SipApplicationSession. It is also more powerful than the deprecated encode URI mechanism. Finally, the optional Join [RFC 3911] and Replaces [RFC 3891] mechanisms also allow an initial request (INVITE) to be targeted to a specific SipSession (SIP dialog) thereby targeting its parent SipApplicationSession. For this discussion, any request that invokes one of these three session targeting mechanisms is termed a targeted request. Unlike normal initial requests, targeted requests target a particular SipApplicationSession object and hence, implicitly, a particular application. Further, for two of these mechanisms, the encode URI and the Join/Replaces support, the session targeting includes the targeting to an application in addition to the SipApplicationSession object. That is, a targeted request to an encoded URI or a request with either a Join or a Replaces header is targeted to a particular application before the Application Router has been invoked to perform application selection. Thus, in addition to describing the mechanisms themselves, the sections below must address how targeted request mechanisms are harmonized with Application Router based application composition.
targeted application is a v1.0 based application). The sections below describe each of these three session targeting mechanisms in more detail.
to get the key and generate a application-session-id by appending some unique identifier. If the resultant application-session-id identifies an existing SipApplicationSession within the container JVM, then the container MUST associate this request with that SipApplicationSession rather than creating a new one. If the application-session-id thus generated does not identify an existing SipApplicationSession instance then a new instance MUST be created. The absence of the @SipApplicationKey method annotation indicates that the application does not want to use the Session Key based targeting mechanism and so the container MUST (by default) create a new SipApplicationSession instance for every initial request. It is strongly recommended that the same application-session-id be returned by the getId() method of the SipApplicationSession. If the annotation exists then the container should use the return value of the @SipApplicationKey annotated method in the return value of getId() after having added a unique prefix as required. As an example, consider that there is a chat room application which desires that all requests with request URI "sip:mychatroom1@example.com" be handled using the same SipApplicationSession. The application defines a method with annotation @SipApplicationKey that takes the SipServletRequest as the argument. 1. An initial request comes into the container and the Application Router is consulted by the container. 2. The Application Router indicates to the container that the chat application needs to be invoked for this request. 3. The container calls the method annotated with @SipApplicationKey and gets an application session key. (Since the application wishes to send all requests with a certain Request-URI to the same SipApplicationSession it returns some key, based on the Request-URI, like a hash or perhaps just the Request-URI itself). 4. The container prefixes the key with the application name for uniqueness and then uses the resultant application-session-id to check if a SipApplicationSession already exists. 5. If found, that SipApplicationSession is used to associate the SipServletRequest and SipSession with, otherwise a new SipApplicationSession is created. So in this example the first request with the Request-URI, "sip:mychatroom1@example.com", causes the creation of a SipApplicationSession object. Other requests with the same Request-URI, though still initial, are routed to the same SipApplicationSession instance through the use of Session Key targeting.
15-32
Note that since it is left up to applications to generate the keys for session association, they are free to make use of any information at their disposal to generate such a key. This accords tremendous flexibility to applications to associate initial requests or new SipSessions with existing SipApplicationSessions. Similar to the other session targeting mechanisms described below, further processing of the request can result in an application chain different from the already existing chain of which the targeted SipApplicationSession is a part. As noted above, this Session Key based targeting mechanism is different from the other two session targeting mechanisms described below. This is because this targeting mechanism does not operate until after the Application Router has selected an application to be invoked. That is, the session key based targeting mechanism does not constrain the Application Router in any way as regards to its selection of which application to invoke. Consequently, for targeted requests that make use of session keys, the SipTargetedRequestInfo argument passed to the Application Router's getNextApplication() method is set to null.
container MUST use the encoded URI to locate the targeted SipApplicationSession object. If a valid SipApplicationSession is found, the container must determine the name of the application that owns the SipApplicationSession object. When calling the Application Router's getNextApplication() method, the SipTargetedRequestInfo object must be populated to indicate that this request is a targeted request of type, "ENCODED_URI", and must supply the application name that owns the identified SipApplicationSession object. If the container is unable to identify the SipApplicationSession object with the encoded URI, it MUST not identify this request as a targeted one and the SipTargetedRequestInfo argument in the getNextApplication() method is set to null. If an application receives a request targeted to an encoded URI and subsequently either proxies it or relays it onwards as a B2BUA without having changed the encoded URI appearing in the Request-URI, the container will once again receive the targeted request for processing. In such a case, the container MUST handle the request in the same manner as described in the paragraph above. Note: It is unexpected that an application receiving a request targeted to an encoded URI would proxy it or relay it onwards. Depending upon application and Application Router implementations, such behavior could result in a routing loop. By mandating that the container handle such requests in a consistent manner, the policy is established that it is not the container's responsibility to detect and/or remedy the possibility of routing loops due to unexpected treatment of targeted requests by applications.
15-34
must locate the corresponding SipApplicationSession object along with the application name of the application that owns the SipApplicationSession. 3. The container MUST populate a SipTargetedRequestInfo object with the type corresponding to whichever header appears in the request (e.g. JOIN or REPLACES) and with the application name that owns the identified SipApplicationSession and SipSession. The container MUST then pass the request to the Application Routers getNextApplication() method as a targeted request i.e., along with the populated SipTargetedRequestInfo object. 4. If no SipSession matching the tuple is found, the container MUST pass the request to the Application Router as an untargeted request, i.e., where the SipTargetedRequestInfo argument to getNextApplication() is null. 5. If the Application Router returns an application name that matches the application name found in step 2, then the container must create a SipSession object and associate it with the SipApplicationSession identified in step 2. The association of this newly created SipSession with the one found in step 2 is made available to the application through the
SipSessionsUtil.getCorrespondingSipSession(SipSession session, String headerName) method.
6. If the Application Router returns an application name that does not match the application name found in step 2, then the container invokes the application using its normal procedure, creating a new SipSession and SipApplicationSession. 7. If the Application Router returns an application name of null, then the container MUST follow the procedure given in 15.4.1 Procedure for Routing an Initial Request with the following modification: If the Request-URI does not point to another domain, and there is no Route header, the container should not send the request as it will cause a loop. Instead, the container must reject the request with a 404 Not Found final response with no Retry-After header. If an application receives a request targeted to a particular SipApplicationSession because of the presence of a Join or Replaces header, and that application subsequently proxies it or relays it onwards as a B2BUA without having changed or removed the Join/Replaces header, the container will once again receive the targeted request for processing. In such a case, the container MUST handle the request in the same manner as described in the procedure defined above. Note: As with applications handling encoded URI requests, it is unexpected that an application receiving a targeted request due to a Join/Replaces header would proxy it or relay it onwards leaving the Join/Replaces header intact in the request. Depending upon application and Application Router implementations, such behavior could result in a routing loop. By mandating that the container handle such requests in a consistent
JSR 289: SIP Servlet Specification v1.1 15-35
manner, the policy is established that it is not the containers responsibility to detect and/or remedy the possibility of routing loops due to unexpected treatment of targeted requests by applications. Container implementations MAY allow configuration options to automatically reject all requests with Replaces and Join headers unconditionally or else when no matching SipSession is found.
15-36
S E C T I O N 16
15 Application Selection And Composition Model described the Application Router component and how it is intrumental in application selection process. The Servlet mapping is a mechanism for the selection of a servlet after the application has been determined by the container.
declaration is optional and the lone servlet becomes the main servlet. However, if there are multiple servlets present in the application while using this mechanism then one of those servlets MUST be declared as the main servlet. This declaration can be done in the @SipApplication annotations mainServlet element (see 18.2.3 @SipApplication Annotation) or by the presence of the element <main-servlet /> in the deployment descriptor. The main servlet thus declared MUST then be invoked for the initial request of the selected application. The main servlet is tasked with the responsibility of processing the initial request. The main servlet can also forward the request to another servlet within the application. It can do that by using the RequestDispatcher interface, see 6.2.6 The SipSession Handler. If need be, the servlets can pass request attributes while passing requests back and forth amongst them to convey some information. The servlet that handles the request becomes the handler for the SipSession that may come into existence and will be delivered the subsequent requests and responses directly by the container. The handling servlet or the main servlet can also designate any other servlet as the handler for subsequent request or responses by calling SipSession.setHandler() method. Note: The servlet mapping mechanism defined in version 1.0 of this specification based on an XML rules language can be used in this version of the specification. Developers familiar with the v1.0 servlet mapping scheme who find it sufficient for servlet selection can make use of it even in applications compliant with v1.1 (or later) of this specification. Developers who find the v1.0 scheme insufficient for servlet selection could use the new main servlet mechanism for servlet selection. However, this specification makes a restriction that only one servlet selection mechanism, either the <main-servlet /> OR <servlet-mapping /> shall be employed for a given application. Once the Application Router chooses a particular application for an initial request, the container chooses the servlet to be invoked either using the <main-servlet /> declaration OR the <servlet-mapping /> rules. Applications employing both mechanisms via annotations or descriptor declarations MUST fail to deploy. If multiple servlets are present in applications, one of the two servlet selection mechanisms MUST be used.
16-2
S E C T I O N 17
17 Security
Servlet applications are created by application developers who give, sell, or otherwise transfer the application to a deployer for installation into a runtime environment. Application developers need to communicate to deployers how the security is to be set up for the deployed application. This is accomplished declaratively by use of the deployment descriptor mechanism. This chapter describes deployment representations for security requirements. Similar to servlet application directory layouts and deployment descriptors, this chapter does not describe requirements for runtime representations. It is recommended, however, that containers implement the elements set out here as part of their runtime representations.
17.1 Introduction
A servlet application represents resources that can be accessed by many users. These resources are accessed over unprotected, open networks such as the Internet. In such an environment, a substantial number of servlet applications will have security requirements. Although the quality assurances and implementation details may vary, servlet containers have mechanisms and infrastructure for meeting these requirements that share some of the following characteristics: Authentication: The means by which communicating entities prove to one another that they are acting on behalf of specific identities that are authorized for access. Access control for resources: The means by which interactions with resources are limited to collections of users or programs for the purpose of enforcing integrity, confidentiality, or availability constraints.
17-1
Se curity
Data integrity: The means used to prove that information has not been modified by a third party while in transit. Confidentiality or data privacy: The means used to ensure that information is made available only to users who are authorized to access it.
The getRemoteUser method returns the user name the client used for authentication. The isUserInRole method determines if a remote user is in a specified security role. The getUserPrincipal method determines the principal name of the current user and returns a java.security.Principal object. These APIs allow servlets to make business logic decisions based on the information obtained. If no user has been authenticated, the getRemoteUser method returns null, the isUserInRole method always returns false, and the getUserPrincipal method returns null. Note: A response may contain credentials of the UAS. For this reason, the programmatic security methods apply to responses as well as to requests. However, since there is no mechanism for a
17-2 JSR 289: SIP Servlet Specification v1.1
Ro l e s
proxy to challenge a UAS upon unsuccessful response authentication, the SIP deployment descriptor cannot express a requirement that responses be authenticated. The isUserInRole method expects a String user role-name parameter. A security-role-ref element should be declared in the deployment descriptor with a role-name sub-element containing the rolename to be passed to the method. A security-role element should contain a role-link sub-element whose value is the name of the security role that the user may be mapped into. The container uses the mapping of security-role-ref to security-role when determining the return value of the call. For example, to map the security role reference "FOO" to the security role with role-name "manager" the syntax would be:
<security-role-ref> <role-name>FOO</role-name> <role-link>manager</role-link> </security-role-ref>
In this case, if the servlet called by a user belonging to the "manager" security role made the API call isUserInRole("FOO"), the result would be true. If no security-role-ref element matching a security-role element has been declared, the container must default to checking the role-name element argument against the list of security-role elements for the servlet application. The isUserInRole method references the list to determine whether the caller is mapped to a security role. The developer must be aware that the use of this default mechanism may limit the flexibility in changing rolenames in the application without having to recompile the servlet making the call.
17.4 Roles
A security role is a logical grouping of users defined by the application developer or assembler. When the application is deployed, roles are mapped by a deployer to principals or groups in the runtime environment. A servlet container enforces declarative or programmatic security for the principal associated with an incoming request based on the security attributes of the principal. This may happen in either of the following ways: 1. A deployer has mapped a security role to a user group in the operational environment. The user group to which the calling principal belongs is retrieved from its security attributes. The principal is in the security role only if the principals user group matches the user group to which the security role has been mapped by the deployer.
17-3
Se curity
2. A deployer has mapped a security role to a principal name in a security policy domain. In this case, the principal name of the calling principal is retrieved from its security attributes. The principal is in the security role only if the principal name is the same as a principal name to which the security role was mapped.
17.5 Authentication
A SIP user agent can authenticate a user to a SIP server using, for example, one of the following mechanisms: SIP digest authentication The P-Asserted-Identity header, thus trusting an upstream/downstream proxy to have authenticated the caller/callee, as specified in [privacy] The Identity and Identity-Info headers, as specified in [RFC 4474] The HTTP Servlet specification also allows user authentication based on SSL. With SSL, TLS, and IPSec, it is actually the previous hop that is being authenticated and from which the user-data constraints are enforced. As proxies are more common in SIP, and may not be strongly associated with the UAC, the entity authenticating itself on an incoming TLS connection is not, generally speaking, the UAC itself. For this reason SIP servlet containers will not typically perform authentication based on credentials received as part of a TLS handshake. However, it is possible that in some environments it is known that the TLS connection really does identify the UAC and in such cases it is reasonable for the container to reflect this knowledge in its implementation of the declarative and programmatic security features discussed here. These security features relate to end-users, not proxies, but it is up to individual containers to determine what constitutes an authenticated message.
17-4
Pr op ag at ion of S e c u r i ty I de nt i t y i n EJ B T M C al l s
3. Require re-authentication of users only when a security policy domain boundary has been crossed. Therefore, a servlet container is required to track authentication information at the container level (rather than at the servlet application level). This allows users authenticated for one servlet application to access other resources managed by the container permitted to the same security identity.
17-5
Se curity
user data constraint A resource collection is a set of servlets and SIP methods. A servlet may have one or more security constraints associated with it. Before invoking a servlet to handle an incoming request, the container must ensure that all security constraints associated with that servlet are satisfied. If this is not the case, the request must be rejected with a 401 or 407 status code. Note: SIP servlet resource collections are identified by names of servlets being invoked instead of URL patterns as in the HTTP Servlet API. The authentication type is an indication of whether the container should return a 401 (Unauthorized) or 407 (Proxy Authentication Required) response status code when authenticating an incoming request. An authorization constraint is a set of security roles at least one of which users must belong to for access to resources described by the resource collection. If the user does not belong to an allowed role, the user must be denied access to the resource. If the authorization constraint defines no roles, no user is allowed access to the portion of the servlet application defined by the security constraint. A user data constraint describes requirements for the transport layer of the client server. The requirement may be for content integrity (preventing data tampering in the communication process) or for confidentiality (preventing reading while in transit). The container must at least use TLS to respond to requests to resources marked integral or confidential. If the original request was over TCP, the container must redirect the client to the TLS port. The login-config element allows for configuration of the authentication method that should be used, the realm name that should be used for this application, and the configuration of a identity assertion scheme. This specification introduces the identity-assertion element in login-config to specify in the deployment descriptor the mechanism to be used for identity assertion. This element can use one of the two identity assertion mechanisms: P-Asserted-Identity: Identity MUST be asserted using the P-Asserted-Identity header as described in [RFC 3325]. This mechanism is limited to trusted domains. Identity: Identity MUST be asserted using the Identity and Identity-Info headers as described in [RFC 4474]. This mechanism provides a cryptographic approach to assure the identity of the end users that originate SIP requests, especially in an interdomain context.
17-6
An application can also choose if the identity assertion scheme specified is REQUIRED by the application or just SUPPORTED using the element. When P-Asserted-Identity scheme is REQUIRED by the application, the P-Asserted-Identity header MUST be present in the request. If the P-Asserted-Identity header is not present the container MUST reject the request with a 403 response. If authorization of the Identity specified by P-Asserted-Identity header fails, the container MUST return a 403 response. When P-Asserted-Identity scheme is SUPPORTED by the application, the container checks the presence of the P-Asserted-Identity header in the message. If the header is not present then any other authentication mechanism configured by the user as part of the login configuration is used, for example, Digest Authentication. When using the Identity mechanism, the Identity and Identity-Info headers are used to assert the identity of the user as defined in RFC 4474. The REQUIRED or SUPPORTED behavior is same as described above for the P-Asserted-Identity mechanism except that the container MUST return a 428 error response if the required headers are not present in the request. For example, here is a sample configuration for the login-config element:
<login-config> <auth-method>DIGEST</auth-method> <realm-name>example.com</realm-name> <identity-assertion> <identity-assertion-scheme>P-Asserted-Identity</identity-assertion-scheme> <identity-assertion-support>SUPPORTED</identity-assertion- support> </identity-assertion> </login-config>
In the above example, for every servlet that has a security constraint configured in the application, the container would use the P-Asserted-Identity header for authorization, if present. If P-Asserted-Identity header is absent then the request will be subjected to the Digest authentication mechanism configured in the element.
17-7
Se curity
Following new APIs are added to support this mechanism Iterator SipServletResponse.getChallengeRealms() Returns an iterator over all the realm(s) associated with the current challenge response. AuthInfo.addAuthInfo(int statusCode, java.lang.String realm, java.lang.String userName, java.lang.String passWord) - statusCode is the 401/407 that was returned in the challenge that is being provided for in the API call. - realm is the realm that was returned in the challenge the is being provided for in this API call
17-8
This adds authentication info in the AuthInfo object for the challenge of Type and Realm.
SipServletRequest.addAuthHeader(SipServletResponse challengeResponse, AuthInfo authInfo)
This adds the appropriate authentication header to the request. After doing this the application can resend the request again. Note that if the request contains multiple challenges the container can add multiple authentication headers.
SipServletRequest.addAuthHeader(SipServletResponse challengeResponse, java.lang.String userName, java.lang.String passWord)
This adds the appropriate authentication header to the request. After doing this the application can resend the request again.This is a shortcut API to be used in cases where the application does not want or needs to use the AuthInfo object.
17-9
Se curity
17-10
S E C T I O N 18
18.1 Java 5
J2SE 5.0 is the minimum version of the underlying Java platform with which SIP Servlet containers compliant with this specification must be built. Even though the API may be revised to make use of new J2SE 5.0 constructs it must remain fully backwards compatible for the applications written for the 1.0 version of this specification.
Deployment descriptor
small-icon or large-icon
Annotation element
@SipApplication smallIcon or largeIcon
18-1
Not applicable.
@SipServlet loadOnStartup @SipApplication proxyTimeout @SipApplication sessionTimeout @Resource , @Resources @DeclaresRole @EJB @RunAs @WebServiceRef
Not applicable
18-2
of this writing, the annotations defined in the Servlet 2.5 specification included @Resource, @Resources, @PostConstruct, @EJB, @WebServiceRef, @DeclaresRole, and @RunAs. Those definitions in the Servet 2.5 specification remain the same with the following additional classes required to be injected. Table 18-2 Interfaces and Classes which Require Annotation Support
Servlet Listeners
javax.servlet.sip.SipServlet javax.servlet.sip.SipApplicationSessionListener javax.servlet.sip.SipApplicationSessionActivatio nListener javax.servlet.sip.SipSessionAttributeListener javax.servlet.sip.SipSessionListener javax.servlet.sip.SipSessionActivationListener javax.servlet.sip.SipErrorListener javax.servlet.sip.TimerListener
With this specification, annotations defined as part of Servlet specification 2.5 and some common Java EE annotations as defined in JSR 250 are also included. For a description of annotations listed but not described here please refer to Servlet specification 2.5 and JSR 250. The complete list of annotations required to be supported is @RunAs @DeclaresRole @Resource @Resources @EJB @WebServiceRef @PostConstruct @PreDestroy @SipServlet @SipApplication
18-3
@SipListener @SipApplicationKey
Resource Injection is supported for classes whose lifecycle is controlled by the container. A non Java EE compliant implementation of this specification MUST support SIP specific annotations but it is not required to support the Java EE specific annotations.
18-4
package javax.servlet.sip.annotation; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.RUNTIME; @Target({TYPE}) @Retention(RUNTIME) @Inherited public @interface SipServlet { String name() default ""; String applicationName() default ""; String description() default ""; int loadOnStartup() default -1; }
The first example is a basic annotated class to become a SipServlet. Here, because no elements are specified, the name and display name of the servlet will be "Weather"
package com.example; import javax.servlet.sip.SipServlet; @SipServlet public class Weather extends SipServlet {
Here in the second example, the servlet name is "WeatherService" and in the absence of application name, the display name defaults to "WeatherService".
package com.example; import javax.servlet.sip.SipServlet; @SipServlet (name = "WeatherService") public class Weather extends SipServlet {
In this next example, the servlet name is "WeatherService" and since the application name is specified, the display name is "WeatherApplication".
package com.example; import javax.servlet.sip.SipServlet; @SipServlet (name = "WeatherService", applicationName = "WeatherApplication") public class Weather extends SipServlet {
18-5
The class annotated by the @SipServlet annotation must override all methods it wishes to implement functionality for. For example, if the class wanted to perform some action on INVITE methods, it would do the following:
package com.example; import javax.servlet.sip.annotation.SipServlet; import javax.servlet.sip.SipServletRequest; import javax.servlet.sip.SipServlet; @SipServlet (name = "WeatherService", applicationName = "WeatherApplication", description = "Provides weather information", loadOnStartup=1) public class Weather extends SipServlet { public void doInvite(SipServletRequest req){ //perform action
18-6
deployment descriptor. Each takes a simple string specifying the location of the image relative to the root path of the archive this class exists within. These elements are optional. The description element in this annotation is equivalent to the description element in the deployment descriptor. This can help the consumer of this application understand better what the application is and what it does. Often, tools that consume applications will provide the descriptions to better understand what the application does. This element is optional and a empty string will be used in its place if one is not provided. The distributable element indicates to the container whether this application is developed to properly function in a distributed environment. This element set equal to true is the equivalent to the distributable attribute in the deployment descriptor. Just as the descriptor without the distributable element defaults the application to not be distributable, the distributable element in the annotation defaults to false and must be set to true if the servlet developer wishes the application to function in a distributed environment. The proxyTimeout element is equivalent to the proxy-timeout element of the deployment descriptor. The proxyTimeout should specify, in whole seconds, the default timeout for all proxy operations in this application. The container may override this value as a result of its own local policy. The sessionTimeout element is equivalent to the session-timeout element in the deployment descriptor. The sessionTimeout should specify, in whole minutes, the default session timeout for all application sessions created in this servlet. SipSessions have no timeout independent of that of the containing application session. The lifetime of a SipSession is tied to that of the parent application session. If the timeout is zero or a negative number, the container must ensure the default behavior of the sessions is to never time out. The mainServlet element of the annotation specifies which servlet is designated as the main servlet of the application. The concept of main servlet is described in 16 Mapping Requests To Servlets of this specification. This corresponds to main-servlet element of the deployment descriptor.
package javax.servlet.sip.annotation; import java.lang.annotation.Retention; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.RUNTIME; @Target({PACKAGE}) @Retention(RUNTIME) public @interface SipApplication { String name(); String displayName() default "";
18-7
String smallIcon() default ""; String largeIcon() default ""; String description() default ""; boolean distributable() default false; int proxyTimeout() default 180; // seconds int sessionTimeout() default 3; // minutes String mainServlet() default ""; }
To use the package level @SipApplication annotation, define it in a package-info.java file as follows:
@javax.servlet.sip.annotation.SipApplication( name="WeatherApplication", sessionTimeout=30, distributable=true) package com.example; The WeatherService servlet below does not define the applicationName element in the @SipServlet annotation: package com.example; import javax.servlet.sip.annotation.SipServlet; import javax.servlet.sip.SipServletRequest; import javax.servlet.sip.SipServletResponse; @SipServlet (name = "WeatherService") public class Weather extends SipServlet { public void doInvite(SipServletRequest){ //perform action The HumidityChecker servlet below defines the applicationName element in the @SipServlet annotation: package com.example.humidity; import javax.servlet.sip.annotation.SipServlet; import javax.servlet.sip.SipServletRequest; import javax.servlet.sip.SipServletResponse; import javax.servlet.sip.SipServlet; @SipServlet (name = "HumidityChecker", applicationName="WeatherApplication") public class Humidity extends SipServlet { . }
In the above example, the WeatherService servlet is automatically bound to the WeatherApplication application in its package, com.example. The HumdityChecker servlet
18-8
is in another package and has to specify the application name explicitly to be bound into the same application.
@Target({TYPE}) @Retention(RUNTIME) @Inherited public @interface SipListener { String applicationName() default ""; String description() default ""; }
The class annotated by the @SipListener must implement at least one of the listener interfaces described in this specification.
package com.example; import javax.servlet.sip.annotation.SipListener; import javax.servlet.sip.SipApplicationSessionListener; import javax.servlet.sip.SipApplicationSessionEvent; @SipListener (applicationName = "WeatherService") public class MyApplicationSessionListener implements SipApplicationSessionListener { public void sessionDestroyed(SipApplicationSessionEvent ev) {.} public void sessionCreated (SipApplicationSessionEvent ev){.} public void sessionExpired (SipApplicationSessionEvent ev){.} }
18-9
For example:
@javax.servlet.sip.annotation.SipApplication package com.example; import javax.servlet.sip.annotation.SipApplicationKey; import javax.servlet.sip.SipServletRequest; public class WeatherMapper { @SipApplicationKey public static String sessionKey(SipServletRequest req){ return hash(req.getRequestURI + getDomain(req.getFrom()); } }
Note that only one @SipApplicationKey annotation can be present in a given SIP application (packaged as a SAR/WAR) and the container MUST enforce this restriction.
18-10
are equivalent. For converged containers, the injected SipFactory would appear as sip/<appname>/SipFactory in the application scoped JNDI tree, where the appname is the name of the application as identified by the container (see 7.6 Application Names). In this example, this annotation can be used in any SIP Servlet or a Java EE application component deployed on the converged container in the same EAR archive file. The container must inject an instance of SipFactory into the field ("sf" in this example) at the time of application initialization. For the purposes of associating a Servlet, with, say the responses received to the request created using the SipFactory, the container must use the application's main servlet as defined in 16.2 Servlet Selection. This can be changed to another servlet through the setHandler mechanism in the SipSession. Note that containers MAY allow the @Resource annotation to be present outside of SIP applications. In such cases, the name element of the @Resource annotation MUST identify the JNDI name of the desired factory to inject. Otherwise, an invocation of SipFactory.createApplicationSession() would be unable to determine the intended SIP application.
18-11
This annotation can be used in place of the following ServletContext based lookup for the SipSessionsUtil.
SipSessionsUtil s = (SipSessionsUtil) getServletContext().getAttribute("javax.servlet.sip.SipSessionsUtil");
are equivalent. The injected SipSessionsUtil appears as sip/<appname>/SipSessionsUtil in the application scoped JNDI tree, where the appname is the name of the application as identified by the container (see 7.6 Application Names). When multiple applications are packaged in the same EAR, access to SipSessionsUtil for a specific application is possible by specifying the JNDI name element of the @Resource annotation in a manner similar to 18.2.6 Annotation for SipFactory Injection. The SipSessionsUtil is described in chapter 13 Converged Container and Applications.
are equivalent. The injected TimerService appears as sip/<appname>/TimerService in the application scoped JNDI tree, where the appname is the name of the application as identified by the container (see 7.6 Application Names). The TimerService is described in 9 Timer Service.
18-12
An n o ta t i o n Pa r s i n g
18-13
18-14
S E C T I O N 19
19 Deployment Descriptor
This chapter specifies the SIP Servlet Specification, v1.1 requirements for SIP servlet container support of deployment descriptors. The deployment descriptor conveys the elements and configuration information of a servlet application between application developers, application assemblers, and deployers.
19-1
execute on a single request and, while this is not exactly the same as filters, it does meet many of the same requirements. A SIP servlet application which does not use annotations (18.2 Annotations and Resource Injection) must have a deployment descriptor that conforms to the XML XSD. This deployment descriptor exists as a file sip.xml in the /WEB-INF directory of the SIP Servlet application.
in the SIP and HTTP deployment descriptors. A parameter may be configured in both descriptors but in that case must have the same value in both declarations.
listener: the set of listeners of an application is the union of listeners defined in the SIP
and HTTP deployment descriptors. Also, the application display-name and icons should be identical and, if present, in one should be present in the other. The app-name element is defined only in sip.xml. It is to be taken as the logical name for the SIP Servlet Application.
19-2
Application lifecycle listener classes Error handler Security Also, elements exist in the SIP servlet application deployment descriptor to support the additional requirements of servlet containers that are part of a Java EE application server. These elements allow for looking up JNDI objects (env-entry, ejb-ref, ejb-local-ref, resource-ref, resource-env-ref), and are not required to be supported by containers wishing to support only the servlet specification. See the schema comments for further description of these elements.
19-3
19-4
APPENDIX
Changes in this specification since v1.0 in the order of appearance in the specification 1. Servlet Life Cycle Listener - Added to remove any possibility of race conditions during initialization of the servlet. Also defined how servlet initialization relate to application deployment. 2.1.1 Servlet Life Cycle Listener 2. Clear definition of Initial Request under various condition. Appendix B Definition of Initial Request 3. Parameterable interface - Support for SIP headers that can have parameters by providing easy accessors and mutators. 4.1.1 The Parameterable Interface 4. Ability to add Contact header parameters and set user part. 4.1.3 The Contact Header Field 5. Change to committed state of SipServletMessage. 5.2 Implicit Transaction State 6. Because of evolution of servlet spec 2.4,
SipServletResponse.setCharacterEncoding() which extends SipServletMessage does not throw the UnsupportedEncodingException.
7. Specification for container to remove its own Route header and making the popped Route header availale to applications. 5.6.3 Popped Route Header 8. Changes in lifetime and accesiblity of SipServletMessage. 5.8 Accessibility of SIP Servlet Messages 9. The behavior of SipServletMessage.getAcceptLanguage() and SipServletMessage.getAcceptLanguages() has changed when no preferred locale is specified by the client. This is so that a caller of these methods can distinguish the case where
JSR 289: SIP Servlet Specification v1.1 A-1
no preferred locale is specified by the client from one where a preferred locale is specified. If no preferred locale is specified by the client, getAcceptLanguage returns null and getAcceptLanguages returns an empty Iterator. 5.9.1 Indicating Preferred Language 10. New getSipSession(Id) method on SipApplicationSession to access the SipSession by its Id. 6.1.1 Protocol Sessions 11. Addition of a new mechanism for SipApplicationSession invalidation called Invalidate When Ready mechanism. 6.1.2.2.2 Invalidate When Ready Mechanism 12. Addition of a new mechanism for SipSession invalidation called Invalidate When Ready mechanism. 6.2.4.1.2 Invalidate When Ready Mechanism 13. Distributed containers to support not only Serializable objects but also instances of SipServletMessage as attributes. Also extent of serializable closure clarified. 6.4.3 Distributed Environments. 14. Equivalence of .sar and .war archive formats for SIP Servlet Containers. 7.7 Servlet Application Archive File 15. New listeners for SipApplicationSession attributes. 8.1 SIP Servlet Event Types and Listener Interfaces 16. New listener for SipApplicationSession activation. 8.1 SIP Servlet Event Types and Listener Interfaces 17. New listener for SipServlet lifetime to receive initialization callback servletInitialized(). 8.1 SIP Servlet Event Types and Listener Interfaces 18. SipSession attribute listeners can be any class defined in the deployment descriptor. 8.1 SIP Servlet Event Types and Listener Interfaces 19. Support for RFC3327 (Path header) by extending the Proxy object. 10.5 Path Header and Path Parameters 20. Deprecation of transaction stateless proxy. 10.1 Parameters 21. Support for explicit Proxy branch creation and manipulation. 10.2.1 Proxy Branches 22. A general purpose proxyTimeout parameter applicable for both sequential and parallel proxy, deprecation of sequential-search-timeout parameter (not feature), optional override of proxyTimeout values for branches. 10.1 Parameters 23. Change in Sequential search timeout behavior. 10.2.4.3 Sequential Search Timeout
A-2
24. Clarification that a 503 error response to be sent to the servlet if the sending of the message fails after the send() returns. 11.1.4 Sending a Request as a UAC 25. Specification of Transaction timeout handling. 11.1.6 Transaction Timeout 26. Removal of the stateless record routing section. Record routing applications by very nature are stateful. 27. Support for creating PRACK request by providing createPrack() method. 11.1.8 Sending PRACK and 5.7.1 Reliable Provisional Responses 28. Introduction of a B2BUA helper functionality in specification. The helper simplifies the writing of B2BUA applications by abstracting features like Session linkage, Request access on Sessions, Session cloning etc. 12 Back To Back User Agents 29. SIP/HTTP and in general SIP/Java EE convergence. The features introduced in this specification bridge the gap between SIP Servlet applications and other Java EE components. 13 Converged Container and Applications 30. A clear definition of a converged application scope and features available within that scope. 13.1 Converged Application 31. Support for multihomed hosts. 14.2 Multihomed Host Support 32. Detailed specification of Application selection and composition model. 15 Application Selection And Composition Model 33. Specification of encodeURI mechanism in context of application composition. 15.11.1 Session Targeting and Application Selection 34. The new Session Key based session targeting mechanism. 15.11.2 Session Key Based Targeting Mechanism 35. Introduction of a designated "main" servlet in the application. 16.2 Servlet Selection 36. Specification that only one servlet to be invoked in case of multiple servlets in mapping element. 16.2 Servlet Selection 37. Modified Servlet triggering mechanism obviating the mapping rules. 16.2 Servlet Selection 38. Mechanism for authentication of application initiated request. 17.10 Authentication of Servlet Initiated Requests 39. Java 5 support. 18.1 Java 5 40. Annotations for SIP Servlet container. 18.2 Annotations and Resource Injection
JSR 289: SIP Servlet Specification v1.1 A-3
41. New method for obtaining the application name from a SipApplicationSession. 7.6 Application Names
applications shall run on the v1.1 containers without change but it is not a source compatibile change if the application is explicitly catching the UnsupportedEncodingException on
SipServletResponse.setCharacterEncoding()
7. In absence of SipServletRequest.getPoppedRoute() API, some implementations of JSR 116 popped the Route header after the request visited the servlet. In these implementations, the applications may still have access to the Route header through existing methods such as getHeader("Route") . The applications using the old mechanism will have to change to use the new SipServletRequest.getPoppedRoute() and SipServletRequest.getInitialPoppedRoute() API.
A-4 JSR 289: SIP Servlet Specification v1.1
object behavior Table 19-1 New classes for application router support
SipApplicationRouter SipApplicationRouterInfo SipApplicationRoutingDirecti ve SipApplicationRoutingRegion SipApplicationRoutingRegionT ype SipRouteModifier
application router interface application routing information application routing directive application routing region enum for routing region types enum used to influence route value
session management for converged apps extension to HttpSession for converged apps
support for B2BUA applications represents SIP header field value with parameters proxy branch information
A-5
get notifications of changes to the attribute lists of application sessions. new listener to support application session activation and passivation events event for attribute binding/unbinding on SipApplicationSession listener for binding events SIP Servlet specific context event. listener for post init() event enum for header forms enum for session states enum for different UA modes, UAC or UAS.
now implements Parameterable added new support for creating proxy branches added new support for setting outbound interface added new Path header support added Proxy timeout deprecated methods 'setStateful' and 'getStateful' deprecated sequential search attribute
added new methods for setting and getting uri parameters moved parameter-related methods to URI now supports RFC 3966, also added new 'setPhoneNumber' method
A-6
added new support for 'B2buaHelper' class added new 'isValid' method added method to query session state added new methods required for invalidation when ready mechanism added new method to supprt outbound interfaces added new method to support application composition
SipServletMessage
added new methods to support 'Parameterable' header types added ability to specify default use of compact or long header names in message
added support for new 'B2buaHelper' class added new method to retrieve previously popped route header added new methods to support new application composition added new method to support Path header
SipServletResponse
added new 'createPrack' method added new predefined response code constants
SipServlet
A-7
added new method to parse 'Parameterable' header types added new 'isValid' method added new 'encodeURL' method to support converged apps added new getExpirationTime()
setExpires() now accepts 0 or negative argument getSessions(protocol) now throws IllegalArgumentException if the protocol is not understood
added getSipSession(id) and getSession(String id, String protocol) deprecated the use of encodeURI() method added new methods required for invalidation when ready mechanism
ServletParseExcept ion TooManyHopsExcepti on
added support for nested exceptions added support for nested exceptions
A-8
APPENDIX B
Since the determination that a request is an initial request determines when the application selection process is started, a well defined procedure for making this determination is necessary. This appendix provides a precise specification of what an initial request is. The following procedure is used by a compliant container implementation to determine if a request is an initial request and will therefore require the application selection process to start: 1. Request Detection - Upon reception of a SIP message, determine if the message is a SIP request. If it is not a request, stop. The message is not an initial request. 2. Ongoing Transaction Detection - Employ methods of Section 17.2.3 in RFC 3261 to see if the request matches an existing transaction. If it does, stop. The request is not an initial request. 3. Examine Request Method. If it is CANCEL, BYE, PRACK, ACK, UPDATE or INFO, stop. The request is not an initial request for which application selection occurs. 4. Existing Dialog Detection - If the request has a tag in the To header field, the container computes the dialog identifier (as specified in section 12 of RFC 3261) corresponding to the request and compares it with existing dialogs. If it matches an existing dialog, stop. The request is not an initial request. The request is a subsequent request and must be routed to the application path associated with the existing dialog. If the request has a tag in the To header field, but the dialog identifier does not match any existing dialogs, the container must reject the request with a 481 (Call/Transaction Does Not Exist). Note: When this occurs, RFC 3261 says either the UAS has crashed or the request was misrouted. In the latter case, the misrouted request is best handled by rejecting the request. For the Sip Servlet environment, a UAS crash may mean either an application crashed or the container itself crashed. In either case, it is
B-1
impossible to route the request as a subsequent request and it is inappropriate to route it as an initial request. Therefore, the only viable approach is to reject the request. 5. Detection of Requests Sent to Encoded URIs - Requests may be sent to a container instance addressed to a URI obtained by calling the encodeURI() method of a SipApplicationSession managed by this container instance. When a container receives such a request, stop. This request is not an initial request. Refer to section 15.11.1 Session Targeting and Application Selection for more information on how a request sent to an encoded URI is handled by the container. 6. Initial Request - The request is an initial request and the application invocation process commences. In this case and in this case only SipServletRequest.isInitial() MUST return true.
REGISTER Requests
that response is subsequently acknowledged. Normally, when a transaction reaches the Terminated state, the container implementation would be free to release the resources associated with keeping track of the transaction. In fact, RFC 3261 dictates that the transaction be destroyed immediately upon the Terminated state being reached. However, because there is no specified time limit on how long a UAC may wait before sending a "retried" request, the container must keep such terminated transactions around. Although such a time limit could be configured, a retried request received after the time limit had expired would be treated as an initial request. In any case, keeping terminated transactions around would impose a significant burden on container implementations. That retried requests are treated by the container as initial requests does unfortunately mean that some applications are going to be burdened with having to maintain the state required to detect such requests. This seems particularly true for applications that return the 401 (Unauthorized) or 407 (Proxy Authentication Required) expecting a retried request with the proper credentials included.
B-3
B-4
APPENDIX C
As an Application Router component is essential for the functioning of the container the following application router logic SHOULD be available with every container compliant with this specification. The container implementations MAY choose to provide a much richer Application Router component. For the purpose of this discussion the Application Router defined in this appendix is termed as Default Application Router (DAR). The Application Router and the Container have a simple contract defined by the SipApplicationRouter interface. The DAR MUST implement all the methods of that interface as described in this document.
The properties file is first read by the DAR when the init() is first called on the DAR. The arguments passed in the init() are ignored.
C-1
The properties file is refreshed each time applicationDeployed() or applicationUndeployed() is called. Similar to init(), the argument of these two invocations are ignored, these callbacks act just as a trigger to read the file afresh. The sip-router-info data that goes in the properties file is a stringified version of the SipApplicationRouterInfo object. It consists of the following information : The name of the application as known to the container. The identity of the subscriber that the DAR returns. It can return any header in the SIP request using the DAR directive DAR:SIP_HEADER e.g "DAR:From" would return the SIP URI in From header. Or alternatively it can return any string. The routing region, one of the strings "ORIGINATING", "TERMINATING" or "NEUTRAL" A SIP URI indicating the route as returned by the Application Router, it can be an empty string. A route modifier which can be any one of the strings "ROUTE", "ROUTE_BACK" or "NO_ROUTE" A string representing stateInfo. As stateInfo is for Application Router's internal use only, what goes in this is up to the individual DAR implementations. As a hint the stateInfo could contain the index into the list of sip-router-info that was returned last. Following is an example of the DAR configuration file:
INVITE: ("OriginatingCallWaiting", "DAR:From", "ORIGINATING", "", "NO_ROUTE", "0"), ("CallForwarding", "DAR:To", "TERMINATING", "", "NO_ROUTE", "1")
In this example, the DAR is setup to invoke two applications on INVITE request, one each in the originating and the terminating half. The applications are identified by their names as defined in the application deployment descriptors and used here. The subscriber identity returned in this case is the URI from the From and To header respectively for the two applications. The DAR does not return any route to the container and maintains the invocation state in the stateInfo as the index of the last application in the list.
C-2
SipApplicationRouterInfo getNextApplication (SipServletRequest initialRequest, SipApplicationRoutingRegion region, SipApplicationRoutingDirective directive, SipTargetedRequestInfo targetedRequestInfo, Serializable stateInfo);
This method is invoked when an initial request is received by the container. When this method is invoked on DAR it will make use of the stateInfo and the initial request parameters and find out what SIP method is in the request. Next it will create the object SipApplicationRouterInfo from the sip-router-info information in the properties file, starting from the first in the list. The stateInfo could contain the index of the last sip-router-info returned so on next invocation of getNextApplication the DAR proceeds to the next sip-router- info in the list. The order of declaration of sip-router-info becomes the priority order of invocation. As you would notice, this is a minimalist Application Router with no processing logic besides the declaration of the application order. It is expected that in real world deployments, the Application Router shall play an extremely important role in application orchestration and composition. It is likely to make use of complex rules and diverse data repositories. The DAR is intended to be a very simple implementation that is available as part of the reference implementation, and could be used instead of a real world Application Router.
C-3
C-4
APPENDIX D
D References
[3pcc] [CPL] [IM] [JAF] [JLS] [JavaMail] [JAXP] [privacy] [refer] [RFC 1738] [RFC 2278] [RFC 2327]
J. Rosenberg, J. Peterson, H. Schulzrinne and G. Camarillo, RFC 3725 - Best Current Practices for Third Party Call Control (3pcc) in the Session Initiation Protocol (SIP) J. Lennox, X. Wu and H. Schulzrinne, RFC 3380 - CPL: A Language for User Control of Internet Telephony Services J. Rosenberg et al., RFC 3428 - Session Initiation Protocol (SIP) Extension for Instant Messaging. B. Calder and B. Shannon, JavaBeans Activation Framework Specification, May 27, 1999. The Java Programming Language Specification, http://java.sun.com/docs/books/jls. Sun Microsystems, JavaMail API Design Specification v1.2, September 2000. R. Mordani, J. D. Davidson, and S. Boag, Java API for XML Processing, February 6, 2001. C. Jennings, J. Peterson, and M. Watson, RFC 3325 - Private Extensions to the Session Initiation Protocol (SIP) for Asserted Identity within Trusted Networks. R. Sparks, RFC 3515 - The Session Initiation Protocol (SIP) Refer Method. T. Berners-Lee, L. Masinter, and M. McCahill, Uniform Resource Locators (URL), RFC 1738, December 1994. N. Freed and J. Postel, IANA Charset Registration Procedures, RFC 2278, January 1998. M. Handley and V. Jacobson, SDP: Session Description Protocol, RFC 2327, April 1998.
D-1
Referenc es
[3pcc] [RFC 2976] [RFC 3261] [RFC 3262] [RFC 3265] [SERL] [Servlet API] [simple] [timer] [DFC1998]
J. Rosenberg, J. Peterson, H. Schulzrinne and G. Camarillo, RFC 3725 - Best Current Practices for Third Party Call Control (3pcc) in the Session Initiation Protocol (SIP) S. Donovan, The SIP INFO Method, RFC 2976, October 2000. J. Rosenberg, H. Schulzrinne, G. Camarillo, A. Johnston, J. Peterson, R. Sparks, M. Handley, and E. Schooler, SIP: Session Initiation Protocol, RFC 3261, June 2002. J. Rosenberg and H. Schulzrinne, Reliability of Provisional Responses in the Session Initiation Protocol (SIP), RFC 3262, June 2002. A. B.Roach, Session Initiation Protocol (SIP)-Specific Event Notification, RFC 3265, June 2002. R. W. Steenfeldt and H. Smith, SIP Service Execution Rule Language Framework and Requirements, Internet Engineering Task Force, May 2001. Work in progress. D. Coward, Java Servlet Specification, Version 2.3, September, 2001. Rosenberg et al., RFC 3856 - A Presence Event Package for the Session Initiation Protocol (SIP) S. Donovan and J. Rosenberg, RFC 4028 - Session Timers in the Session Initiation Protocol (SIP) "Distributed feature composition: A virtual architecture for telecommunications services" Michael Jackson and Pamela Zave. IEEE Transactions on Software Engineering XXIV(10):831-847, October 1998. "Component coordination: A telecommunication case study" Pamela Zave and Healfdene H. Goguen and Thomas M. Smith. Computer Networks XXXXV(5):645-664, August 2004. "Experience with component-based development of a telecommunication service" Gregory W. Bond and Eric Cheung and Healfdene H. Goguen and Karrie J. Hanson and Don Henderson and Gerald M. Karam and K. Hal Purdy and Thomas M. Smith and Pamela Zave. Proceedings of the Eighth International Symposium on Component-Based Software Engineering, May 2005. R. Mordani, Common Annotations for the JavaTM Platform D. Willis and B. Hoeneisen, Session Initiation Protocol (SIP) Extension Header Field for Registering Non-Adjacent Contacts. H. Schulzrinne, The tel URI for Telephone Numbers.
[CN2004] [SE2005]
D-2
J. Rosenberg, J. Peterson, H. Schulzrinne and G. Camarillo, RFC 3725 - Best Current Practices for Third Party Call Control (3pcc) in the Session Initiation Protocol (SIP) D. Petrie, A Framework for Session Initiation Protocol User Agent Profile Delivery. H. Schulzrinne, D. Oran and G. Camarillo, The Reason Header Field for the Session Initiation Protocol (SIP). A. Kristensen, SIP Servlet API, Version 1.0, February, 2003.
D-3
Referenc es
D-4
APPENDIX
E Glossary
Address-of-Record An address-of-record (AOR) is a SIP or SIPS URI that points to a domain with a location service that can map the URI to another URI where the user might be available. Typically, the location service is populated through registrations. An AOR is frequently thought of as the public address of the user. Application developer The producer of a SIP application. The output of an application developer is a set of servlet classes and supporting libraries and files (such as images, compressed archive files, etc.) for the servlet application. The application developer is typically an application domain expert. The developer is required to be aware of the servlet environment and its consequences when programming, including concurrency considerations, and create the SIP application accordingly. Application assembler Takes the output of the application developer and ensures that it is a deployable unit. Thus, the input of the application assembler is the servlet classes, JSP pages, HTML pages, and other supporting libraries and files for the servlet application. The output of the application assembler is a servlet application archive or a servlet application in an open directory structure. Application path A list of application instances to be invoked for incoming messages belonging to a particular dialog. This list is constructed as a side effect of the handling of the initial request and consists of the application acting as a UAC if the initial request was created within the container, the application acting as UAS if an application responded to the initial request, as well as all
E-1
Gloss ary
applications that proxied with record-routing enabled. The application path is a logical concept and may or may not be explicitly represented by implementations. Application Router Application Router is a component which is essential for container's functioning. The contract between the Container and Application Router is an interface defined in this specification. On initial requests the Application Router is consulted by the Container to find which application to invoke, after any application completes processing of the request the Container again consults the Application Router to find which application to invoke next. The Application Router is thus the central place for determination of application invocation order. Application session Represents application instances. Application sessions acts as a store for application data and provides access to contained protocol sessions. Back-To-Back User Agent A back-to-back user agent (B2BUA) is a logical entity that receives a request and processes it as an user agent server (UAS). In order to determine how the request should be answered, it acts as an user agent client (UAC) and generates requests. Unlike a proxy server, it maintains dialog state and must participate in all requests sent on the dialogs it has established. Since it is a concatenation of a UAC and UAS, no explicit definitions are needed for its behavior. Call A call is an informal term that refers to some communication between peers generally set up for the purposes of a multimedia conversation. Call leg Another name for a dialog [RFC 2543]; not used in the revised SIP specification [RFC 3261]. Call Stateful A proxy is call stateful if it retains state for a dialog from the initiating INVITE to the terminating BYE request. A call stateful proxy is always transaction stateful, but the converse is not necessarily true. Client A client is any network element that sends SIP requests and receives SIP responses. Clients may or may not interact directly with a human user. User agent clients and proxies are clients.
E-2
Committed message A SIP message object that has been fully processed according to this specification and that should not be further modified, see 5.2 Implicit Transaction State. Conference A multimedia session that contains multiple participants. Default servlet The first servlet listed in the deployment descriptor. Deployer The deployer takes one or more servlet application archive files or other directory structures provided by an application developer and deploys the application into a specific operational environment. The operational environment includes a specific servlet container and SIP server. The deployer must resolve all the external dependencies declared by the developer. To perform his role, the deployer uses tools provided by the servlet container provider. The deployer is an expert in a specific operational environment. For example, the deployer is responsible for mapping the security roles defined by the application developer to the user groups and accounts that exist in the operational environment where the servlet application is deployed. Dialog A dialog is a peer-to-peer SIP relationship between two UAs that persists for some time. A dialog is established by SIP messages, such as a 2xx response to an INVITE request. A dialog is identified by a call identifier, local tag, and a remote tag. A dialog was formerly known as a call leg in RFC 2543. The baseline SIP specification defines only INVITEBYE as a mechanism of establishing and terminating dialogs but allows extensions to define other methods capable of initiating dialogs. The SUBSCRIBE/NOTIFY methods defined by the event framework is an example of this [RFC 3265]. Downstream A direction of message forwarding within a transaction that refers to the direction that requests flow from the user agent client to user agent server. Final response A response that terminates a SIP transaction, as opposed to a provisional response that does not. All 2xx, 3xx, 4xx, 5xx and 6xx responses are final.
E-3
Gloss ary
Header A header is a component of a SIP message that conveys information about the message. It is structured as a sequence of header fields. Header field A header field is a component of the SIP message header. It consists of one or more header field values separated by comma or having the same header field name. Header field value: A header field value is a singular value, which can be one of many in a header field. Home Domain The domain providing service to a SIP user. Typically, this is the domain present in the URI in the address-of-record of a registration. Informational Response Same as a provisional response. Initial request A request that is dispatched to applications based on rule matching rather than on an existing application path. Compare with subsequent request. Initiator, calling party, caller The party initiating a session (and dialog) with an INVITE request. A caller retains this role from the time it sends the initial INVITE that established a dialog until the termination of that dialog. Invitation An INVITE request. Invitee, invited user, called party, callee The party that receives an INVITE request for the purposes of establishing a new session. A callee retains this role from the time it receives the INVITE until the termination of the dialog established by that INVITE. Location server See Location service. Location service A location service is used by a SIP redirect or proxy server to obtain information about a callee's possible location(s). It contains a list of bindings of address-of-record keys to zero or more
E-4 JSR 289: SIP Servlet Specification v1.1
contact addresses. The bindings can be created and removed in many ways; this specification defines a REGISTER method that updates the bindings. Loose Routing A proxy is said to be loose routing if it follows the procedures defined in this specification for processing of the Route header field. These procedures separate the destination of the request (present in the Request-URI) from the set of proxies that need to be visited along the way (present in the Route header field). A proxy compliant to these mechanisms is also known as a loose router. Message Data sent between SIP elements as part of the protocol. SIP messages are either requests or responses. Method The method is the primary function that a request is meant to invoke on a server. The method is carried in the request message itself. Example methods are INVITE and BYE. Outbound proxy A proxy that receives requests from a client, even though it may not be the server resolved by the Request-URI. Typically, a UA is manually configured with an outbound proxy, or can learn about one through auto-configuration protocols. Parallel search In a parallel search, a proxy issues several requests to possible user locations upon receiving an incoming request. Rather than issuing one request and then waiting for the final response before issuing the next request as in a sequential search, a parallel search issues requests without waiting for the result of previous requests. Principal A principal is an entity that can be authenticated by an authentication protocol. A principal is identified by a principal name and authenticated by using authentication data. The content and format of the principal name and the authentication data depend on the authentication protocol. Protocol session Common name for protocol specific session objects. A protocol session represents a point-to-point signaling relationship and serves as a repository for application data relating to that relationship. Examples include the SipSession and HttpSession interfaces defined by the SIP
E-5
Gloss ary
and HTTP servlet specifications, respectively. A number of protocol sessions may belong to a single application session. Provisional response A response used by the server to indicate progress, but that does not terminate a SIP transaction. 1xx responses are provisional, other responses are considered final. Provisional responses are not sent reliably. Proxy, proxy server An intermediary entity that acts as both a server and a client for the purpose of making requests on behalf of other clients. A proxy server primarily plays the role of routing, which means its job is to ensure that a request is sent to another entity "closer" to the targeted user. Proxies are also useful for enforcing policy (for example, making sure a user is allowed to make a call). A proxy interprets, and, if necessary, rewrites specific parts of a request message before forwarding it. Recursion A client recurses on a 3xx response when it generates a new request to one or more of the URIs in the Contact header field in the response. Redirect server A redirect server is a user agent server that generates 3xx responses to requests it receives, directing the client to contact an alternate set of URIs. Registrar A registrar is a server that accepts REGISTER requests and places the information it receives in those requests into the location service for the domain it handles. Regular transaction A regular transaction is any transaction with a method other than INVITE, ACK, or CANCEL. Request A SIP message sent from a client to a server, for the purpose of invoking a particular operation. Response A SIP message sent from a server to a client, for indicating the status of a request sent from the client to the server. Ringback Ringback is the signaling tone produced by the calling party's application indicating that a called party is being alerted (ringing).
E-6 JSR 289: SIP Servlet Specification v1.1
Role (development) The actions and responsibilities taken by various parties during the development, deployment, and running of a servlet application. In some scenarios, a single party may perform several roles; in others, each role may be performed by a different party. Role (security) An abstract notion used by an application developer in an application that can be mapped by the Deployer to a user, or group of users, in a security policy domain. Route set A route set is a collection of ordered SIP or SIPS URI which represent a list of proxies that must be traversed when sending a particular request. A route set can be learned, through headers like Record-Route, or it can be configured. Security policy domain The scope over which security policies are defined and enforced by a security administrator of the security service. A security policy domain is also sometimes referred to as a realm. Security technology domain The scope over which the same security mechanism, such as Kerberos, is used to enforce a security policy. Multiple security policy domains can exist within a single technology domain. Server A server is a network element that receives requests in order to service them and sends back responses to those requests. Examples of servers are proxies, user agent servers, redirect servers, and registrars. Sequential Search In a sequential search, a proxy server attempts each contact address in sequence, proceeding to the next one only after the previous has generated a final response or has timed out. A 2xx or 6xx class final response always terminates a sequential search. Servlet application archive A single file that contains all of the components of a servlet application. This archive file is created by using standard JAR tools which allow any or all of the application components to be signed. Servlet application archive files are identified by the .sar extension. The SAR file layout is derived from the Web application archive (.war) file format but may contain servlets and deployment descriptors pertaining to different protocols, for example SIP and HTTP. With this specification either .sar or .war file formats can be used to package SIP Servlet applications.
JSR 289: SIP Servlet Specification v1.1 E-7
Gloss ary
Servlet Container Provider A vendor that provides the runtime environment, namely the servlet container and possibly the SIP server, in which a servlet application runs as well as the tools necessary to deploy servlet applications. The expertise of the container provider is in HTTP-level programming. Since this specification does not specify the interface between the SIP server and the servlet container, it is left to the container provider to split the implementation of the required functionality between the container and the server. Servlet definition A unique name associated with a fully qualified class name of a class implementing the Servlet interface. A set of initialization parameters can be associated with a servlet definition. Servlet mapping A servlet definition that is associated by a servlet container with a URL path pattern. All requests to that path pattern are handled by the servlet associated with the servlet definition. Session From the SDP specification: A multimedia session is a set of multimedia senders and receivers and the data streams flowing from senders to receivers. A multimedia conference is an example of a multimedia session. [RFC 2327] (A session as defined for SDP can comprise one or more RTP sessions.) As defined, a callee can be invited several times, by different calls, to the same session. If SDP is used, a session is defined by the concatenation of the user name, session id, network type, address type and address elements in the origin field. SIP application A collection of SIP servlets and static resources which might include voice prompts, grammars, VoiceXML scripts, and other data. A SIP application may be packaged into an archive or exist in an open directory structure. All compatible servlet containers must accept a SIP application and perform a deployment of its contents into their runtime. This may mean that a container can run the application directly from a servlet application archive file or it may mean that it will move the contents of a servlet application into the appropriate locations for that particular container. SIP applications are to the SIP Servlet API what web applications are to the HTTP Servlet API. SIP transaction A SIP transaction occurs between a client and a server and comprises all messages from the first request sent from the client to the server up to a final (non-1xx) response sent from the server to the client. If the request is INVITE and the final response is a non-2xx, the transaction also
E-8
includes an ACK to the response. The ACK for a 2xx response to an INVITE request is a separate transaction. SIP/web application, distributable A SIP or web application that is written so that it can be deployed in a servlet container distributed across multiple Java virtual machines running on the same host or different hosts. The deployment descriptor for such an application uses the distributable element. Stateful Proxy A logical entity that maintains the client and server transaction state machines defined by this specification during the processing of a request. Also known as a transaction stateful proxy. The behavior of a stateful proxy is further defined in 10 Proxying. A (transaction) stateful proxy is not the same as a call stateful proxy. Stateless Proxy A logical entity that does not maintain the client or server transaction state machines defined in this specification when it processes requests. A stateless proxy forwards every request it receives downstream and every response it receives upstream. This specification deprecates the use of SIP Servlet application as transaction stateless proxy. Strict routing A proxy is said to be strict routing if it follows the Route processing rules of RFC 2543 and many prior Internet Draft versions of RFC 3261. That rule caused proxies to destroy the contents of the Request-URI when a Route header field was present. Strict routing behavior is not used in RCF 3261, in favor of a loose routing behavior. Proxies that perform strict routing are also known as strict routers. Subsequent request A request that is dispatched to applications, not by matching it against rules, but based on an existing application path created while processing an earlier initial request establishing the dialog. System Administrator The person responsible for the configuration and administration of the servlet container. The administrator is also responsible for overseeing the well-being of the deployed applications at run time. This specification does not define the contracts for system management and administration. The administrator typically uses runtime monitoring and management tools provided by the container provider and server vendors to accomplish these tasks.
E-9
Gloss ary
System headers Headers that are managed by the SIP servlet container and which servlets must not attempt to modify directly via calls to setHeader or addHeader. This includes Call-ID, From, To, CSeq, Via, Record-Route, Route, as well as Contact when used to specify a session signaling address, for example, in INVITEs and 200 response to INVITEs. System headers are discussed in section 5.4.2 System Headers. TLS Transport Layer Security. A layer four means of protecting TCP connections providing integrity, confidentiality, replay protection, and authentication. Uniform resource locator (URL) A compact string representation of information for location and access of resources via the Internet [RFC 1738]. SIP and SIPS URIs are syntactically similar to mailto URLs, that is, they are typically of the form sip:user@host. The user part is a user name or a telephone number. The host part is either a fully qualified domain name or a numeric IP address. SIP URIs are used within SIP messages to indicate the originator (From), current destination (Request-URI) and final recipient (To) of a SIP request, and to specify redirection addresses (Contact). When used as a hyperlink (for example in a Web page) a SIP URI indicates that the specified user or service can be contacted using SIP. Upstream The direction of message forwarding within a transaction that refers to the direction that responses flow from the user agent server back to the user agent client. URL-encoded A character string encoded according to RFC 1738 [RFC 1738, section 2.2]. User agent client (UAC) A user agent client is a logical entity that creates a new request, and then uses the client transaction state machinery to send it. The role of UAC lasts only for the duration of that transaction. In other words, if a piece of software initiates a request, it acts as a UAC for the duration of that transaction. If it receives a request later, it assumes the role of a user agent server for the processing of that transaction. User agent server (UAS) A user agent server is a logical entity that generates a response to a SIP request. The response accepts, rejects, or redirects the request. This role lasts only for the duration of that transaction. In other words, if a piece of software responds to a request, it acts as a UAS for the duration of
E-10 JSR 289: SIP Servlet Specification v1.1
that transaction. If it generates a request later, it assumes the role of a user agent client for the processing of that transaction.
User agent (UA) A logical entity that can act as both a user agent client and user agent server. Web application A collection of servlets, JSP pages, HTML documents, and other web resources which might include image files, compressed archives, and other data. A web application may be packaged into an archive or exist in an open directory structure. All compatible servlet containers must accept a web application and perform a deployment of its contents into their runtime. This may mean that a container can run the application directly from a web application archive file or it may mean that it will move the contents of a web application into the appropriate locations for that particular container.
E-11
Gloss ary
E-12