ヘッダーをスキップ
Oracle Communication and Mobility Server開発者ガイド
リリース10.1.3
E05480-02
  目次
目次
索引
索引

戻る
戻る
 
次へ
次へ
 

2 SIPサーブレット

この章では、SIPサーブレットおよびJSR-116で説明されているSIP Servlet APIの概要を説明します。内容は次のとおりです。

SIPサーブレットの概要

この章では、SIP Servlet API、SIPコンテナ、SIPサーブレット環境、SIPクラスおよびメソッド、SIPアプリケーションの構成の概要を説明します。

SIP Servlet APIは、JSR 116で定義され、SIPサービスおよびアプリケーションのプログラミング用標準インタフェースを記述します。SIPサーブレットはJava HTTPサーブレットと比較されますが、SIPプロトコル関連メソッドを備えています。実際、SIP Servlet APIは、HTTP Servlet APIと同様、一般的なServlet APIの上にビルドされています。

SIPサーブレットは、4つのカテゴリに分類されます。

SIPコンテナ

この項では、SIPコンテナ(図2-1)の次のコンポーネントについて説明します。

図2-1 SIPコンテナ・オブジェクト・モデル

SIPコンテナ・オブジェクト・モデル
「図2-1 SIPコンテナ・オブジェクト・モデル」の説明

サーブレット・コンテキスト

サーブレット・コンテキストは、そのコンテキストが属するSIPアプリケーションのサーブレット・ビューです。サーブレット・コンテキストを使用して、サーブレットはリスナーやコンテキストのinitパラメータなどのグローバル・アプリケーション・サービスにアクセスできます。

アプリケーションのグローバルinitパラメータは、デプロイメント・ディスクリプタのsip.xmlファイルで設定され、<context-param>マーカーで示されます。グローバル・アプリケーション・パラメータの例としては、データベースやバックエンド・アプリケーションのアドレスなどの共通リソース・アドレスがあります。

サーブレット・コンテキストには、実装済および構成済リスナーへのすべての参照も含まれます。セッションとプロキシのタイムアウトは、サーブレット・コンテキストで維持されます。これらはsip.xmlファイルで構成されます。セッション・タイムアウトは<session-config>内の<session-timeout>セクションにあります。プロキシ・タイムアウトは<proxy-config>内の<sequential-search-timeout>セクションにあります。サーブレット・コンテキストは、サーブレットからgetServletContextメソッドをコールして取得します。次に例を示します。

ServletContext servletContext = getServletContext();

SIPアプリケーション・セッション

アプリケーションでは複数のタイプのサーブレット・セッション(SIPやHTTPなど)が処理される場合がありますが、これらのセッションは同じアプリケーションに関連している必要があります。これは、SIPアプリケーション・セッションを通して行います。SIPアプリケーション・セッションでは複数のプロトコル・セッションを維持できます。プロトコル・セッションは同じタイプでも異なるタイプ(SIP、HTTP)でもかまいません。

SIPアプリケーション・セッションでは、そのアプリケーション・セッションに関連するすべてのプロトコル・セッションで使用できる属性を維持できます。1つのSIPアプリケーション・セッションで複数のプロトコル・セッションを維持できます。たとえば、B2BUAは、同じSIPアプリケーション・セッションに置かれる2つのセッションを作成します。

SIPアプリケーション・セッションは、タイムアウトになるまで、またはアプリケーションが明示的にinvalidateメソッドをコールするまで存在します。適切に動作するアプリケーションは、不要になったセッションを常に無効化します。SIPアプリケーション・セッションが無効化されると、すべてのプロトコル・セッション・オブジェクトも一緒に無効化されます。セッションのタイムアウト値は、sip.xmlファイルで<session-timeout>パラメータを使用して設定します。この要素内でタイムアウト値が定義されていない場合、コンテナのデフォルト値が使用されます(デフォルトは15分)。

セッションが無効化された後にリクエストが届いた場合、サーバーは、481「Call transaction does not exist」メッセージを返します。SIPアプリケーション・セッションに対応するリクエストとレスポンスは、リクエスト(SipServletRequest)またはレスポンス(SipServletResponse)オブジェクトでgetApplicationSession()メソッドを使用して取得できます。

プロトコル・セッション

プロトコル・セッションは、特定のプロトコルのためのセッションです。アプリケーションで複数のプロトコルを扱う場合、SIPアプリケーション・セッションには複数のプロトコル・セッションが含まれます。

SipSessionオブジェクトは、ポイント間のSIP関係、確立したSIPダイアログ、または初期状態のSIPダイアログを表すことができます。初期状態は、sipFactoryクラスでcreateRequestメソッドを使用して受信または作成されたリクエストとして説明されます。SIPセッション・オブジェクトは、最初のリクエストによって1つのサーブレットが起動されたときに、コンテナによって作成されます。

SIPセッションに対応するリクエストまたはレスポンスは、リクエスト(SipServletRequest)またはレスポンス(SipServletResponse)オブジェクトでgetSession()メソッドを使用して取得できます。アプリケーション・セッション内のすべてのプロトコル・セッションは、SipApplicationSessionオブジェクトでgetSessions()メソッドを使用して取得できます。

トランザクション

SIPトランザクションは、1つのSIPリクエストとそのリクエストに対するすべてのレスポンス(暫定的なレスポンスと最終レスポンスを含む)で構成されます。

SipServletRequestSipServletResponseは常にSIPトランザクションに属します。サーブレットがSIPトランザクション状態モデルに違反するメッセージを送信しようとすると、コンテナによってIllegalStateExceptionがスローされます。SIP Servlet APIは、開発者がトランザクションを気にせずに、リクエストとレスポンスのみを考慮できるように設計されています。

サーブレット

デプロイメント・ディスクリプタで定義されている各サーブレットには、1つのインスタンスがあります。サーブレットはマルチスレッド環境で実行されるため、initパラメータなど、すべてのリクエストとレスポンスに共通のデータのみがメンバー変数として格納されます。

サーブレットのモジュラー化

各デプロイメント・ディスクリプタ・ファイル(sip.xml)に<servlet>および<servlet-mapping>セクションを含むサーブレットには、<security-constraint>セクションもあります。これらのセクションはサーブレットとともに作成されるため、これらのサーブレットはOCMS SCEのServlet Creationウィザードを通して再使用できるようになっています。

JBossアプリケーション・サーバーのSARファイルの名前変更

OCMSでは、Servlet archive format(SAR)ファイルは、Sip Servlet aRchive(SSR)に名前が変更されます。2つのファイルの形式は同じで、名前が異なる理由はOCMSのサード・パーティ・アプリケーション・サーバーの要件にあります。アプリケーション・サーバーではSARファイルを処理できないため、SIP ASではかわりにSSRファイルをチェックします。この名前変更によって、異なるSIPアプリケーション・サーバー間の移植が可能になります。


注意:

Oracle 10g Application Server Controlまたはadmin_client.jarコマンドライン・ツールを介してSIPアプリケーションをデプロイする場合は、サーブレット・アーカイブ・ファイル(SARファイル)をWARに名前変更し、WARアーカイブのようにapplication.xmlにWARファイルをリストする必要があります。また、WARにはweb.xmlファイルが含まれている必要があり、それによってOC4Jにデプロイできます。

SARファイルのパッケージングおよびEARファイルのデプロイの詳細は、『Oracle Communication and Mobility Server管理者ガイド』を参照してください。


リスナー

リスナーを登録して、イベントをリスニングし、メソッドを起動できます。各デプロイメント・ディスクリプタには、タイプごとに1つのリスナーのみ定義できます。これらの各リスナーは、開発者が実装する必要があります。次に各種リスナーを示します。

  • SipApplicationSessionListener: SipApplicationSessionの作成および無効化用のリスナーです。セッション拡張の依頼に使用できます。SipApplicationSessionListenerインタフェースを実装し、sip.xmlを更新する必要があります。

  • SipSessionListener: SIPサーブレット・アプリケーションのアクティブなSipSessionsの変化用のリスナーです。SipSessionListenerインタフェースを実装し、sip.xmlで構成する必要があります。

  • SipSessionAttributeListener: SipSession属性の変化用のリスナーです。SipSessionAttributeListenerインタフェースを実装する必要があります。

  • TimerListener: TimerListenerインタフェースが実装されている場合のみ、タイマー・サービスはサーブレットの遅延アクションを有効にします。アプリケーションごとに1つのタイマー・リスナーを使用できます(sip.xml)。

  • SipSessionActivationListener: SipSessionActivationListenerインタフェースが実装されている場合、セッションに依存するオブジェクトは、アクティブかどうかのステータスをリスニングできます。

SIPサーブレットとSIPアプリケーション

SIPアプリケーションは、SIPプロトコルを使用してアクセスするJ2EE準拠アプリケーションです。Webアプリケーションが着信HTTPプロトコル・リクエストによってトリガーされるように、アプリケーションは着信SIPプロトコル・リクエストによってトリガーされます。

アプリケーションには、サーブレットや他のビジネス・オブジェクト(論理層)に達するSIPやHTTPなどのプロトコル・インタフェース(プレゼンテーション層)があり、さらにサーブレットや他のビジネス・オブジェクトは管理され、データベース(データ層)へのリソース接続を行います。ユーザーおよびアプリケーション・データには、J2EE仕様の該当するパートによって表されるデータ層を介してアクセスします。アプリケーションは、デプロイメント・ディスクリプタのsip.xmlファイルのスコープによって区切られます。

SIPサーブレット環境

この項では、SIPサーブレットの環境と、アプリケーション・サーバー(AS)の起動中およびリクエストがSIPコンテナに入ったときに発生する処理について説明します。

図2-2 起動時のSIPコンテナ

起動時のSIPコンテナ
「図2-2 起動時のSIPコンテナ」の説明

  1. 起動時には次の処理が発生します。

    1. コンテナがデプロイメント・ディスクリプタ(sip.xmlを読み取ります。

    2. サーブレット・コンテナが作成されます。

      • グローバルinitパラメータが設定されます。これらには、sip.xmlファイルで<context-param>というマークが付けられます。

      • セッション構成値が設定されます。これらには、sip.xmlファイルで<session-config>というマークが付けられます。

      • プロキシ構成値が設定されます。これらには、sip.xmlファイルで<proxy-config>というマークが付けられます。

      • コンテナが、TimerListenerSipApplicationSessionListenerSipSessionActivationListenerSipSessionAttributeListenerおよびSipSessionListenerをインスタンス化します。各リスナーには1つのインスタンスがあります(定義されている場合)。

    3. Servlet Configオブジェクトが作成されます。Servlet Configには、サーブレットごとにすべてのinitパラメータが保存されます。これらには、sip.xmlファイルで<init-param>というマークが付けられます。グローバルinitパラメータ(context-param)も含まれます。

    4. サーブレットは、Servlet Configが提供するinitパラメータで作成および初期化されます。各サーブレットは1つのインスタンスとして実行されます。サーブレットのinitメソッドが実行されます。

    5. SipApplicationSessionsおよびSipFactoryの参照を含むSIPアプリケーション・マネージャが作成されます。

      図2-3 SIPコンテナによって処理される初期リクエスト

      SIPコンテナによって処理される初期リクエスト
      「図2-3 SIPコンテナによって処理される初期リクエスト」の説明

  2. コンテナは初期リクエストと後続リクエストを区別します。初期リクエストはサーブレットの起動条件(またはルール)に従ってサーブレットを起動し、後続リクエストは初期リクエストで起動されたサーブレットに直接転送されます。初期リクエスト時には、次の手順が発生します。

    1. コンテナは、「初期リクエストの処理」で説明する処理に基づいて、特定のアプリケーションを選択します。

    2. 起動するサーブレットは、サーブレット起動順序の各サーブレットのルールを評価して決定されます(図2-3)。ルールの実行順序は、sip.xmlファイルの各サーブレットの<servlet-mapping>の順序によって決まります。最上位のサーブレット・マッピングを持つサーブレットのルールが最初にチェックされます。詳細は、次の「サーブレットのマッピング」を参照してください。

    3. SIPアプリケーション・セッションがSIPセッションとともに作成されます。

    4. トランザクションとリクエストが作成され、作成されたSIPセッション・オブジェクトに関連付けられます。

  3. 後続リクエストの場合、コンテナがすでにダイアログ(ダイアログはLocal-tag + Remote-tag + CallIdで定義されます)を保持しているので、リクエストは初期リクエストで実行されたサーブレットに転送されます。リクエストは、初期リクエストと同じメッセージ・コンテキスト(SIPアプリケーション・セッション+SIPセッション)で機能します。

サーブレットのマッピング

SIPアプリケーションには、1つ以上のSIPサーブレットを含めることができます。SIPコンテナがSIPリクエストを受け取ると、コンテナはリクエストを処理するSIPアプリケーションを選択します。その後、SIPアプリケーションはルール(sip.xmlファイルで定義されたサーブレットのマッピング)を評価し、リクエストに応答する適切なSIPサーブレットを見つけます。検出後、リクエストに適合する最初のSIPサーブレットを使用します。


注意:

SIPサーブレットは、javax.servlet.ServletRequest.getRequestDispatcher()を使用して、別のSIPサーブレットにリクエストを転送できます。

さらに、Application Routerを使用して、アプリケーションをつなげることができます。『Oracle Communication and Mobility Server管理者ガイド』を参照してください。


たとえば、SIPコンテナがINVITEリクエストを受信した場合、コンテナはリクエストに適合する次のSIPサーブレットを含むSIPアプリケーションを選択します。

  • サーブレット1: INVITEリクエストに対して起動されます。

  • サーブレット2: MESSAGEリクエストに対して起動されます。

  • サーブレット3: すべてのリクエストに対して起動されます。

SIPアプリケーションは、上から下までルールを評価して、適合するサーブレットを検索します。この場合、サーブレット1とサーブレット3の両方がINVITEリクエストに適合します。これらのサーブレットの1つのみがリクエストを処理でき、アプリケーションはルールを順番に調べるため、アプリケーションはサーブレット1を選択します。サーブレット1はサーブレット3より優先されます。SIPコンテナがMESSAGEリクエストを受信すると、アプリケーションはサーブレット2を起動します。REGISTERリクエストを受信すると、このタイプのリクエストを処理できる唯一のサーブレットであるサーブレット3が起動されます。アプリケーションにサーブレット3が含まれていない場合、アプリケーションのmatchメソッドがREGISTERリクエストにnullを返し、SIPコンテナは403レスポンス「Application choose not to service the request」を発行します。このメッセージはログ・ファイルに書き込まれます。


注意:

SIPアプリケーションは1つのリクエストに対して1つのSIPサーブレットしか起動できませんが、SIPコンテナはApplication Routerを使用して、着信リクエストに対して複数のSIPアプリケーションを起動できます。

クラスとメソッド

この項では、SIP Servlet APIのクラスとメソッドについて説明します。

SIPサーブレットは、javax.servlet.sip.SipServletクラスを拡張するクラスで、SIPアプリケーション・サーバーと対話して、SIPメッセージを送受信します。

リクエストとレスポンスの処理メソッド

サーブレットは特定サービスに必要なメソッドをオーバーライドします。SIPサーブレットがオーバーライドの実行に使用する主要な2つのメソッドは次のとおりです。

  • protected void doRequest(SipServletRequest req)

  • protected void doResponse(SipServletResponse resp)

doRequest()メソッドはすべてのリクエストを処理し、doResponse()メソッドはすべてのレスポンスを処理します。

serviceメソッド以外では、doRequest()doResponse()が、SipServletクラスが提供する最も幅広いメソッドです。これらのメソッドを使用して、受信したメソッドまたはレスポンスと関係のないタスクを有効にできます。特定のリクエストおよびレスポンス処理タスクを実行するようにメソッドを拡張できます。

リクエストを処理するには、次のメソッドを拡張します。

  • doInvite: SIP INVITEリクエスト用

  • doAck: SIP ACKリクエスト用

  • doCancel: SIP CANCELリクエスト用

  • doBye: SIP BYEリクエスト用

  • doOptions: SIP OPTIONSリクエスト用

  • doRegister: SIP REGISTERリクエスト用

  • doSubscribe: SIP SUBSCRIBEリクエスト用

  • doNotify: SIP NOTIFYリクエスト用

  • doMessage: SIP MESSAGEリクエスト用

  • doInfo: SIP INFOリクエスト用

  • doPrack: SIP PRACKリクエスト用

レスポンスの処理の場合は、次のクラスを拡張します。

  • doProvisionalResponse: SIP 1xx情報レスポンス用

  • doSuccessResponse: SIP 2xxレスポンス用

  • doRedirectResponses: SIP 3xxレスポンス用

  • doErrorResponse: SIP 4xx、5xxおよび6xxレスポンス用


注意:

これらのレスポンス処理メソッドは、doAckおよびdoCancelリクエスト処理メソッドと同様、空白です。残りのリクエスト処理メソッドは、500レスポンス(「Internal Server Error」)でリクエストに応答します。

メッセージ

SIPメッセージは、RFC 822標準に従います。ヘッダー、値および内容には、javax.servlet.sip.SipServletMessageインタフェースのメソッドからアクセスできます。

SipServletRequestおよびSipServletResponseクラスはどちらも、SipServletMessageインタフェースを拡張します。

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

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

リクエスト

SIPサーブレット・メソッドdoRequestおよびdoResponseSipServletRequestおよびSipServletResponseオブジェクトは、SipServletRequestインタフェースとSipServletResponseインタフェースの実装で、両方ともjavax.servlet.sipパッケージのSipServletMessageインタフェースを拡張します。

SIPリクエストは次のもので構成されます。

  • リクエスト行

  • ヘッダー

  • 空白行

  • メッセージ・ボディ

SIPリクエストのすべての部分、つまりリクエストURI、ヘッダーおよびパラメータには、これらのインタフェースからアクセスできます。SIPコンテナはこれらのシステム・ヘッダーの多くを処理します。アプリケーションは、次のシステム・ヘッダーを追加、削除または変更することはできません。

  • From

  • To

  • Call ID

  • CSeq

  • Via

  • Route(pushRouteからを除く)

  • Record Route

  • Contact(Contactは、REGISTERリクエストおよびレスポンス、3xxおよび485レスポンス以外のメッセージのシステム・ヘッダー・フィールド)

レスポンス

着信リクエストへのレスポンスは、リクエスト・オブジェクト上でcreateResponseメソッドを使用して作成します。リクエストに従ってすべてのSIPヘッダーが設定されたレスポンスが自動的に作成されます。SIPレスポンスの構造は、リクエスト行のかわりにStatus行がある点を除いて、SIPリクエストと同じです。たとえば、doResponseメソッドからレスポンスを受け取った場合は、レスポンス・オブジェクト上でgetStatus()などのメソッドを使用して、実行するアクションを決定できます。

内容

リクエストまたはレスポンスの内容は、例2-1で示すsetContent()メソッドを使用して設定できます。

例2-1 setConentメソッドを使用したリクエストの内容の設定

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

SIPヘッダーの操作

javax.servlet.sip.SipServletMessageには、SIPヘッダーを操作するためのメソッドが含まれています。getHeaderNames()メソッドは、メッセージのSIPヘッダーのイテレータを返す最も一般的なメソッドです。setHeaderメソッドは、ヘッダーにアドレスを設定または追加します。getHeaders(name)メソッドでヘッダーの名前を指定すると、そのヘッダーのすべての値を含むStringオブジェクトの別のイテレータが返されます。

AddressHeaderに準拠するヘッダーの場合、getAddressHeader(name)メソッドは、Addressオブジェクトとして解析されたヘッダーを返します。

setAddressHeader(name, address)addAddressHeader(name, address, first)を使用して、ヘッダーにアドレスを追加または設定できます。nameはヘッダーの名前、addressは追加するアドレス、firstはブール値です。firstをtrueに設定すると、アドレスが最初に追加されます。falseの場合は最後に追加されます。

例2-2にSIPヘッダーの操作方法を示します。

例2-2 SIPヘッダーの操作

javax.servlet.sip.SipServletRequest req;

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

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

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

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

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

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

SipURI

ベース・クラスjavax.servlet.sip.URIには、2つのサブ・クラスjavax.servlet.sip.SipURIjavax.servlet.sip.TelURLがあります。これらは、RFC 3261およびRFC 2806で定義されたURLに従ってSIP URIとTEL URLを表します。Addressクラスは、ユーザーのアドレスとしてSipURIまたはTelURLを格納します。

URIはuser@hostとして記述できます。user部分はユーザー名または電話番号、host部分はドメイン名またはIPアドレスです。

パラメータにはgetterとsetterを使用してアクセスできます。getParameterNamesメソッドは、パラメータ名とともにイテレータを返します。パラメータには、一般的なgetParameterメソッド、またはgetUsergetHostgetLrParamなどの特定のパラメータ・メソッドを使用してアクセスできます。これらはユーザー、ホスト、およびルーズ・ルートlrが設定されている場合はtrueを返します。パラメータは、例2-3に示すように、対応するsetMethod()を使用して設定できます。

例2-3 SipURIのパラメータへのアクセス

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

アドレス

From、To、ContactなどのヘッダーにあるSIPアドレスは、javax.servlet.sip Addressオブジェクトとして格納されます。例2-4に示すように、オブジェクトにはURIの他に、オプションで表示名と、nameおよびvalueパラメータのセットが含まれます。

例2-4 java.servlet.sip Addressオブジェクトに格納されるSIPアドレス

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

前の例のmyNewAddressの内容は次のとおりです。

DisplayName: "Bob's display name"

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

parameter myparameter: 42

Addressクラスは、次のメソッドを提供します。

  • getDisplayName()

  • setDisplayName()

  • getURI()

  • setURI()

  • clone()

  • toString()

SIP詳細

SIP Servlet APIを操作する場合、多くのSIP詳細は隠され、OCMS SIP Application Serverによって自動的に実行されます。

  • 送信プロトコルがUDPの場合、再転送は自動的に処理されます。

  • SIPメッセージのタグ、連絡先、Cseqなどのダイアログ関連の情報は自動的に処理されます。

  • 発信リクエストの場合、OCMSはDNS参照を実行し、NAPTR-、SRV-およびA-レコードをサポートします(RFC 3263に準拠)。

データをセッション属性として格納

SIP Servlet APIでは、データをセッション属性として格納できます。セッション属性は、レスポンスおよび後続リクエストまたはリスナー・クラスから使用されるセッション固有のデータの格納に使用できます。属性は、セッション・オブジェクトでsetterとgetterを使用して直接格納およびアクセスします。セッションは、SipSessionまたはSipApplicationSessionです。属性は、設定されたセッションからのみ取得できます。次に例を示します。

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

セッション属性には任意のオブジェクトを格納できますが、属性とそのキーは、分散可能なアプリケーション(高可用性のために)用にシリアライズ化できる必要があります。getAttributeNamesメソッドを使用して、設定されたすべての属性を取得します。次に例を示します。

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

構成パラメータの追加

SIPサーブレット・アプリケーション・ディスクリプタ(sip.xml)の<servlet>セクションにパラメータを追加して、サーブレットを構成できます。サーブレットは、getInitParameterメソッドを使用してこれらのパラメータにアクセスできます。例2-5に、レスポンス・コードの構成方法を示します。

例2-5 サーブレットのパラメータの構成

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

sip.xmlでのSIPアプリケーションの構成

SIPサーブレットは、アプリケーションのデプロイメント・ディスクリプタのsip.xmlファイルで宣言する必要があります。sip.xmlファイルでは、initパラメータと、初期リクエストをSIPサーブレットと照合するルールを構成できます。

デプロイメント・ディスクリプタは、次のセクションに別れています。

グローバルInitパラメータの設定およびアクセス

<context-param>および<env-entry>要素は、アプリケーションで使用するデータベースやアプリケーション全体に共通の他のリソースなど、アプリケーションのグローバル・パラメータを設定し、これらにアクセスする手段を提供します。これらの要素は、グローバル・パラメータへのアクセス方法が異なります。

<context-param>要素は、サーブレット・コンテキスト全体にグローバルなサーブレットのinitパラメータを宣言します。例2-6に、<context-param>要素内でアプリケーションのデータベースを設定する方法を示します。

例2-6 <context-param>内でのデータベース名の設定

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

アプリケーション・セッションの設定

SIPアプリケーション・セッションは、<session-config>句内で構成されます。セッション構成では、セッションのタイムアウト値を構成できます。この構成は、次の例に示すように、<session-timeout>句内で行います。タイムアウトは分で設定します。0以下に設定すると、アプリケーション・セッションのタイムアウトは発生しないため、明示的に無効化する必要があります。<session-timeout>内で値を設定しない場合、SIPサーブレット・コンテナに設定されているデフォルトのタイムアウト・セッションがかわりに使用されます(15分)。

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

サーブレットの定義

<servlet>要素では、SIPコンテナのサーブレットを定義します。サーブレットには、サーブレット名<servlet-name>とサーブレット・クラス<servlet-class>が必要です。例2-7に示すように、名前にはアプリケーション内で一意の名前、クラスにはサーブレット・クラスの完全修飾名を指定する必要があります。

例2-7 サーブレット名とサーブレット・クラス

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

サーブレットには、独自のinitパラメータ<init-param>と説明<description>を含めることもできます。コンテナが起動すると、例2-8に示すように、<load-on-startup>要素が設定されているサーブレットのinit()メソッドのみがインスタンス化され、コールされます。

例2-8 サーブレットの定義

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

サーブレットのマッピングの定義

SIPサーブレット・アプリケーションのデプロイメント・ディスクリプタの<servletmapping>要素では、サーブレットを起動する条件を定義します。例2-9に、着信MESSAGEリクエストにMySipServletというサーブレットのみを起動する方法を示します。詳細は、「サーブレットのマッピング」を参照してください。

例2-9 サーブレットのマッピング

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

リクエスト・オブジェクト構造を使用したルールの作成

リクエスト・オブジェクト・モデルでは、SIPリクエストを処理するためのルールを定義できます。この項では、オブジェクト・モデルとルールを作成するための基礎を説明します。

リクエスト・オブジェクトには、URIオブジェクトを拡張するSipURIなど、多くのサブ・オブジェクトが含まれます。

リクエスト・オブジェクトには次の要素があります。

  • method: リクエストのメソッドは、文字列として表されます。

  • uri: リクエスト・オブジェクトのURIオブジェクト、SipURIやTelURIなどです。

  • from: Addressとして表されるFromヘッダー・アドレスです。

  • to: Addressとして表されるToヘッダー・アドレスです。

URIオブジェクトはURIスキームで構成されます。

SipURIオブジェクトには次の要素があります。

  • scheme: 文字列sipまたはsipssipsは、TLSを使用する必要があることを示します)。

  • user: SIPまたはSIPS URIのユーザー部分です。SIPアドレスがsip:alice@example.comの場合、request.uri.useraliceを返します。

  • host: SIPまたはSIPS URIのホスト部分です。SIPアドレスがsip:alice@example.comの場合、request.uri.hostexample.comを返します。

  • port: SIP URIポートです。存在しない場合、UDPおよびTCPのデフォルト値は5060、TLSのデフォルト値は5061です。

  • tel: パラメータuserがURIの電話に設定されている場合、SIPまたはSIPS URIのユーザー部分を返します。最初の視覚セパレータ+と-は取り除かれます。たとえば、SIP URIがsip:+12345@example.com;user=phoneの場合、request.uri.tel12345を返します。

  • param.name: 名前がnameのSipURIパラメータの値です。たとえば、リクエストURI: INVITE sip:23479234@oracle.com;user=phone SIP/2.0の場合、request.uri.param.userphoneを返します。

TelURLオブジェクトには次の要素があります。

  • scheme: 文字列telです。

  • tel: tel URLサブスクライバ名です。

  • param.name: 名前がnameのSipURIパラメータの値です。

Addressには次の要素があります。

  • uri: URIオブジェクトです。

  • display-name: ヘッダーのToまたはFrom表示名です。

条件

表2-1は、演算子のリストです。

表2-1 演算子

条件名 説明

equal

変数の値をリテラル値と比較します。変数が定義され、その値がリテラルの値と等しい場合trueと評価されます。それ以外の場合、結果はfalseです。

exists

変数名を調べます。変数が定義されている場合はtrueに評価され、変数が定義されていない場合はfalseに評価されます。

contains

最初の引数である変数に、2番目の引数で指定されたリテラル文字列が含まれている場合、trueを返します。

subdomain of

ドメイン名(SIP/SIPS URIホスト)または電話サブスクライバ(SIPまたはTel URLのtelプロパティ)を示す変数とリテラル値が指定され、変数がリテラル値のドメインのサブ・ドメインを表す場合、trueを返します。


表2-2は、論理コネクタのリストです。

表2-2 論理コネクタ

論理 説明

and

複数の条件が含まれ、含まれるすべての条件がtrueに評価された場合、trueに評価されます。

or

複数の条件が含まれ、含まれている少なくとも1つの条件がtrueに評価された場合、trueに評価されます。

not

含まれる条件の値を否定します。


例2-10に、様々なタイプの変数で参照されるリクエストの部分を示します。

例2-10 リクエスト要素の参照

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

The message!

表2-3に、変数値の説明を示します。

表2-3 変数値

変数

request.method

MESSAGE

request.uri

sip:bob@example.com

request.uri.scheme

sip

request.uri.user

bob

request.uri.host

example.com

request.uri.port

5060

request.uri.tel


request.from

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

request.from.uri

sip:alice@example.com

request.from.uri.scheme

sip

request.from.uri.user

alice

request.from.uri.host

example.com

request.from.uri.port

5060

request.from.display-name

Alice

request.to

sip:bob@example.com

request.to.uri

sip:bob@example.com

request.to.uri.scheme

sip

request.to.uri.user

bob

request.to.uri.host

example.com

request.to.uri.port

5060

request.to.display-name



次の例は、falseに評価されます。

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

最初の条件equalは、trueに評価されます。2番目の条件containsも、trueに評価されます。3番目の条件では、otherexample.comに対するリクエストのみを処理することを示していますが、リクエストURIホストがexample.comのため、falseに評価されます。3番目の条件はすべてand条件内に含まれているので、ルール全体でもfalseと評価されます。

OCMSのSIPサーブレット

この項では、SIP Servlet APIに対するOCMS拡張およびその実装について説明します。次の内容について説明します。

初期リクエストの処理

SIPコンテナは、初期リクエストを受信すると、SIPアプリケーションの起動を試みます。SIPコンテナは、appIdパラメータに基づいてアプリケーションを選択します。appIdの詳細は、第3章「高度なSIPサーブレットの構成」を参照してください。SIPコンテナのワークフローは次のとおりです。

  1. リクエストに、起動するアプリケーションの指示が含まれているかどうかを確認します。

  2. 起動するアプリケーションの名前がない場合、SIPコンテナはデフォルトのアプリケーションを選択します。

  3. リクエストによってアプリケーションが指定されている場合、SIPコンテナはアプリケーションを探し、起動します。


注意:

初期リクエストで起動するアプリケーションが指定されていない場合、コンテナはデフォルトのアプリケーションを選択します。

たとえば、着信リクエストに応答するために、SIPサーブレット・コンテナは次のSIPアプリケーションを評価します。

  • アプリケーションAのsip.xmlでは、次の2つのSIPサーブレットが定義されています。

    • サーブレット1はINVITEリクエストに適合します。

    • サーブレット2はMESSAGEリクエストに適合します。

  • アプリケーションBのsip.xmlでは、次のSIPサーブレットが定義されています。

    • サーブレット1はINVITEリクエストに適合します。

  • アプリケーションCのsip.xmlでは、次の2つのSIPサーブレットが定義されています。

    • サーブレット1はREGISTERリクエストに適合します。

    • サーブレット2はすべてのリクエストに適合します。

  • アプリケーションDのsip.xmlでは、次の2つのSIPサーブレットが定義されています。

    • サーブレット1はSUBSCRIBEリクエストに適合します。

    • サーブレット2はPUBLISHリクエストに適合します。

  • アプリケーションEのsip.xmlでは、次のSIPサーブレットが定義されています。

    • サーブレット1はすべてのリクエストに適合します。

これらすべてのアプリケーションがSIPコンテナにデプロイされていますが、デフォルト・アプリケーションは指定されていません。SIPコンテナは、検出したすべてのSIPアプリケーションをデフォルト・アプリケーションとして指定します。たとえば、起動するアプリケーションが指定されていないINVITEリクエストを受信した場合、SIPコンテナはデフォルト・アプリケーションをチェックします。しかし、コンテナにデプロイされたアプリケーションはどれもデフォルト・アプリケーションとして構成されていないので、コンテナはすべてのアプリケーションを取得します。これらのアプリケーションの順序は次のとおりです。

  • アプリケーションB

  • アプリケーションD

  • アプリケーションC

  • アプリケーションE

  • アプリケーションA

SIPコンテナはアプリケーションのリストを、アプリケーションBから順番に調べます。各アプリケーションで、着信リクエストを処理できるサーブレットを問い合せます。アプリケーションに適切なサーブレットが含まれている場合、そのサーブレットが起動され、このリクエストに関して他のアプリケーションは考慮されません。例2-11に、SIPコンテナのアプリケーション評価プロセスのコンセプト・コードを示します。

例2-11 着信リクエストのSIPアプリケーションの評価

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

この場合、SIPコンテナは、着信INVITEリクエストの処理にアプリケーションBを選択します。SIPコンテナがPUBLISHリクエストを受信した場合、もう一度リストを取得して、アプリケーションB(最初のアプリケーション)に問い合せます。アプリケーションBはリクエストに適合しないため、SIPコンテナは次のアプリケーション、アプリケーションDに移ります。このアプリケーションにはこのリクエストを処理するサーブレットがあるので、SIPコンテナはアプリケーションDを選択します。

アプリケーションAはデプロイされたアプリケーションのリストの最後にあり、すべての着信イベントを受け入れるアプリケーションCが前にあるため、起動されることはありません。また、アプリケーションCの最初のサーブレットがすべてのREGISTERリクエストを処理し、2番目のサーブレットが他のすべてのリクエストを処理するため、その後ろのアプリケーションが処理に使用されることはありません。

実装の決定

次の項では、SIPサーブレット仕様の実装オプションについて説明します。

プロトコル・セッション

SIPサーブレット仕様には、HTTPなどの他のプロトコル・セッションを同じSIPアプリケーション・セッションに置けると記載されています。しかし、OCMSは現在SIPプロトコルのみをサポートしています。


注意:

SIPとHTTPを収束したアプリケーションを作成できないわけではありません。例は、Oracle Technology Network(http://www.oracle.com/technology/index.html)でOracle Communication and Mobility Serverのドキュメントを参照してください。

拡張doRequestメソッド

OCMS SCEウィザードはdoPublish()メソッドを提供しています。ウィザードは、SIP PUBLISHリクエストも送信することで、doRequestメソッドを拡張しています(RFC 3903)。

SIP PUBLISHリクエストの処理にはdoPublish() メソッドが使用されます。

「リクエストとレスポンスの処理メソッド」も参照してください。

非同期送信

OCMSでは、SipServletRequestsend()メソッドは、IOExceptionをスローしません。コンテナはリクエストを送信キューに入れ、正常に返します。後で送信操作が失敗した場合、コンテナによって最終レスポンスが生成されます。DNS参照の失敗の場合は408(「Request Timeout」)、その他の失敗の場合は500(「Server Internal Error」)が返されます。

マルチスレッド

OCMSでは、サーブレットはマルチスレッド環境で実行され、複数のサーブレットが一度に同じセッション・オブジェクトにアクセスする可能性があります。リクエストとレスポンスは、コンテナのスレッド・プールから使用可能なスレッドを使用します。したがって、アプリケーション・ロジックで必要な場合は、開発者がセッションおよびそのリソースへのアクセスの同期を担当することがあります。

Sip Servlet API Javadoc

jcp.orgのWebページhttp://jcp.org/aboutJava/communityprocess/final/jsr116/index.htmlからJavadocをダウンロードできます。

zipファイルのダウンロードが完了したら、Javadocの新しい場所を含めるように、EclipseでのJavadocの場所を更新できます。

SIPサーブレットへの外部アクセス

SIPとHTTPを収束したアプリケーションを作成できるように、OCMS ContainerはJNDIを使用した参照によるjavax.servlet.sip.SipFactoryへのアクセスを可能にしています。SIPファクトリは、例2-12に示すように、SIPサーブレットと同じ表示名で登録されます。この場合、sip.xmlの<display-name>は「My sip app」です。

例2-12 JNDIを使用したSIPセッション・データへのアクセス

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

OCMS認証およびログイン・モジュール

OCMSは、TimesTen In-Memory Databaseに格納されているユーザー、ユーザー・ロール、ユーザー・データ、または外部RADIUS(Remote Authentication Dial-In User Service)サーバーに対してダイジェスト・アクセス認証を提供します。OCMSは、OID(Oracle Internet Directory)にプロビジョニングされたユーザーの認証および承認サービスもサポートします。

ログイン・モジュールのOCMSLoginModuleRADIUSLoginModuleは、JAASセキュリティ・プロバイダとして機能し、SIPアプリケーションにはダイジェスト認証、J2EEアプリケーションにはBasic認証を実行するカスタム・ログイン・モジュールです。OCMSLoginModuleは、TimesTenデータベースに格納されたユーザー・データに対する認証を、RadiusLoginModuleは、外部RADIUSサーバーに対する認証を実行します。Basicアクセス認証は、ファイルベースのログイン・モジュールFileLoginModuleを使用する場合のみサポートされ、テスト時のみ使用することをお薦めします。

詳細は、『Oracle Communication and Mobility Server管理者ガイド』を参照してください。