An Introduction to the JAIN SIP API
応答の受信
先ほど、受信メッセージのリスナーを登録しました。リスナーのインターフェースであるSipListenerには、SIPレスポンス・メッセージが到着したときにSIPスタックによってコールされるメソッドprocessResponse()が含まれています。processResponse()は、Responseオブジェクトをカプセル化するタイプResponseEventの単一パラメータを取ります。では、このメソッドを実装してみましょう。
public void processResponse(ResponseEvent evt) { Response response = evt.getResponse(); int status = response.getStatusCode(); if( (status >= 200) && (status < 300) ) { //Success! messageProcessor.processInfo("--Sent"); return; } messageProcessor.processError("Previous message not sent: " + status); }
この方法では、前のMESSAGEメッセージのレスポンスが成功(2xxステータス・コードの範囲)またはエラー(それ以外)を表しているかどうかを確認します。その後、コールバック・インタフェースを介してこの情報をユーザーにリレーします。
通常、processResponse()メソッドのResponseオブジェクトのみを読み取ります。唯一の例外は、INVITEメッセージに対する正常な応答のためです。この場合、次のようにACK要求をただちに送信する必要があります。
Dialog dialog = evt.getClientTransaction().getDialog() Request ack = dialog.createAck() dialog.sendAck( ack );
Responseインタフェースの詳細は、補足資料を参照してください。
リクエストの受信
SIPリクエスト メッセージの受信は、応答を受け取るのと同じくらい簡単です。SipListenerインタフェースの別のメソッドprocessRequest()を実装するだけで、SIPスタックによって自動的にコールされます。このメソッドの単一パラメータは、Requestオブジェクトを含む(想定した)RequestEventオブジェクトです。これは前に見たタイプと同じで、メソッドも同じです。ただし、受信リクエストにはあまり意味はないため、フィールドの設定はしないでください。
processRequest()の一般的な実装では、リクエストが分析され、適切なレスポンスが作成されて返されます。これから行う内容:
public void processRequest(RequestEvent evt) { Request req = evt.getRequest(); String method = req.getMethod(); if( ! method.equals("MESSAGE")) { //bad request type. messageProcessor.processError("Bad request type: " + method); return; } FromHeader from = (FromHeader)req.getHeader("From"); messageProcessor.processMessage( from.getAddress().toString(), new String(req.getRawContent())); Response response=null; try { //Reply with OK response = messageFactory.createResponse(200, req); ToHeader toHeader = (ToHeader)response.getHeader(ToHeader.NAME); toHeader.setTag("888"); //Identifier, specific to your application ServerTransaction st = sipProvider.getNewServerTransaction(req); st.sendResponse(response); } catch (Throwable e) { e.printStackTrace(); messageProcessor.processError("Can't send OK reply."); } }
この場合、常に成功レスポンス(200)で返しますが、エラー・レスポンス(通常は4xx範囲)を返すこともできます。ここに、SIPステータス・コードの有用なリストを示します。
エラー条件の処理
SipListenerインタフェースには、まだ実装していない他のメソッドがあります。特定の理由でリクエストを送信できない場合、SIPスタックによってコールされます。たとえば、processTimeout()は、メッセージを受信するエンド・ポイントが時間内に応答しない場合にコールされます。これはレスポンスがない特別な状況であるため、Responseオブジェクトは使用できません。TimeoutEventパラメータには、タイムアウトしたリクエストのClientTransactionが含まれます。必要に応じて、これを使用して元のリクエストにリンクすることができます。この実装では、コールバック・インタフェースを使用してユーザーに通知します。
public void processTimeout(TimeoutEvent evt) { messageProcessor.processError("Previous message not sent: " + "timeout"); }
同様に、入出力(IO)エラーは、次の方法を使って処理されます。
public void processIOException(IOExceptionEvent evt) { messageProcessor.processError("Previous message not sent: " + "I/O Exception"); }
ポイントツーポイントとクライアント/サーバー
SIPクライアント・アプリケーションは、スタンドアロン(ポイントツーポイント)またはサーバーと一緒に使用して、プロキシやコール・ルーティングなどの追加機能を提供することができます。
SIP Servletsに関する私の記事をご覧になることをお勧めします。この記事には、TextClientと連携してチャット・ルーム・タイプのサービスを提供するSIPサーバーのアプリケーションが含まれています。これはTextClientをBEA WebLogic SIP Serverと一緒に使うことで、その有用性が倍増することを説明したものです。
ダウンロード
TextClientソース・コードをここからダウンロードする
まとめ
この記事ではJAIN SIP APIの概要を説明し、このテクノロジーを使って簡単なアプリケーションを記述する方法を紹介しました。今、このページをご覧になっている方々は利用できるAPIについてかなり良いアイデアをお持ちで、SIPを使った独自のIMクライアントの記述方法をご理解いただいているはずです。
それにもかかわらず、なぜここで止まってしまうのでしょうか。このアプリケーションには、もっとたくさんの機能を追加することができます。そして前述の通り、クライアントがサーバーアプリケーションと通信ができれば、その有用性は倍増するのです。もしアイデアが必要な場合、次のことを検討してみてください。
- 自動テキスト回答、保存と転送(例えば、「ジョンは今オフラインです。再ログインした場合、すぐにあなたのメッセージを受け取ります」など)。
- ネットワークに接続された新しいチェッカーのビデオゲーム
- ノートパソコン向け位置情報サービス
- メディア共有クライアント
- RSSに類似したクライアント
付録
このセクションは JAIN SIP API で利用可能なさまざまなクラスとインターフェースのリファレンスです。
APIの概要
ここでは、JAIN SIP API リファレンス実装で見られる主なクラスとインターフェースの概要を説明します。
| Class / Interface | 内容 |
|---|---|
SipFactory / AddressFactory / HeaderFactory / MessageFactory |
システムのさまざまなオブジェクトを作成するためのファクトリークラスです。標準的なインターフェイスを実装したオブジェクトを返します。 |
SipStack |
ListeningPointとSipProviderを作成するために使用される、最初に必要となるインターフェースです。 |
ListeningPoint |
このインターフェースは、トランスポートとポートのペア(例えば、UDP/5060)をカプセル化します。 |
SipProvider |
このインターフェースは、SIPメッセージの送信に使用されます。また、このインターフェイスを使用して、受信したSIPメッセージのリスナーを登録することもできます。下記のSipListenerを参照してください。 |
SipListener |
SIPメッセージの受信を許可するには、このインターフェースを実装する必要があります。 |
RequestEvent / ResponseEvent |
受信SIPリクエスト、レスポンスを表します。処理のためにSipListenerに渡されます。それぞれRequestまたはResponseオブジェクトが含まれます。 |
TimeoutEvent |
送信リクエストに対する応答がないときの失敗状態を表します。処理のためにSipListenerに渡されます。 |
IOExceptionEvent |
送信リクエストの送信中に入出力の問題が発生した場合の障害状態を表します。処理のためにSipListenerに渡されます。 |
Request / Response |
SIPリクエスト、レスポンスを表します。どちらもMessageインタフェースのサブインタフェースです。ヘッダー、コンテンツ、およびSIPメッセージのその他の部分へのアクセスを提供します。 |
対話 |
このインタフェースのオブジェクトは、SIPダイアログをカプセル化します。(注: ダイアログでは、すべてのメッセージは同じコールに関連しています。多くの場合、ダイアログはINVITEで開始し、BYEで終了します。) |
ClientTransaction / ServerTransaction |
SIPトランザクションをカプセル化します。(注: トランザクションはリクエストで始まり、最終レスポンスで終了します。トランザクションはしばしばダイアログ内に存在します。) |
Messageインタフェース
Messageインタフェースは、SIPメッセージの基本インタフェースです。参考までに、利用可能なメソッドの概要を以下に示します。
| メソッド | 内容 |
|---|---|
|
ヘッダー・フィールドをSIPメッセージに設定します。最初のメソッドは、Contactヘッダーのように、繰り返し使用されるヘッダーや複数の値を持つことができるヘッダーに使用することができます。2番目のメソッドは、このタイプの既存のヘッダーを削除してから、1つのヘッダー値を追加します。 |
void removeHeader(Header) |
このタイプの既存のヘッダーを削除します。 |
ListIterator getHeaderNames() |
すべてのヘッダー名を返します。 |
ListIterator getUnrecognizedHeaders() |
非標準のヘッダー・タイプのヘッダー名を返します。 |
|
特定のヘッダーに対するゲッターです。2番目の形式は、繰り返し使用できるヘッダや、Contactヘッダのように複数の値を持つヘッダのすべての値を返します。 |
void setContent(Object, ContentTypeHeader) |
メッセージのペイロードとContent-Typeヘッダーを設定します。Content-Typeが文字列の場合はContent- Lengthも設定され、それ以外の場合はvoid setContentLength(ContentLengthHeader)を使用します。 |
|
メッセージのペイロードを取得します。 |
void removeContent() |
ペイロードを空にします。 |
|
ペイロード関連の特殊なヘッダー・アクセサです。ほとんど使用されません。 |
|
Expireヘッダーを管理します。 |
|
SIPバージョン要素のアクセサです。稀にしか使用されませんが、デフォルトはSIP/2.0です。 |
Object clone() |
メッセージのコピーを作成します。ほとんど使用されません。 |
Requestインタフェース
次に、Requestインタフェース(前述のMessageのサブインタフェース)を見てみましょう。
| メソッド | 内容 |
|---|---|
|
メソッド要素のアクセサです。Requestインタフェースの定数(ACK、BYE、CANCEL、INVITE、OPTIONS、REGISTER、NOTIFY、SUBSCRIBE、MESSAGE、REFER、INFO、PRACKおよびUPDATE)を含む任意のSIPメソッドを指定できます。 |
|
SIPリクエストの最初の行であるリクエストURIのためのアクセサです。通常、これはSipURIのインスタンスです。 |
Responseインタフェース
Responseインタフェースは、Messageインタフェースを継承しています。
| メソッド | 内容 |
|---|---|
|
ステータス・コード用のアクセサです。これは、Responseインタフェースの定数メンバーに含まれるものを含め、任意のSIPステータス・コードにできます。以下で例をいくつか紹介します。RINGING (180), OK (200), BAD_REQUEST (400), など。 |
|
人間が読めるステータス・コードの説明のためのアクセサです。 |
Emmanuel Proulxは、J2EEとSIPのエキスパートです。WebLogic Server の認定エンジニアでもあります。