17. トランザクション (Transactions)
SIP はトランザクションプロトコルである。コンポーネント間のやり取りは、一連の独立したメッセージ交換において行われる。具体的には、SIP トランザクションは単一のリクエストと、そのリクエストに対する任意のレスポンス (ゼロ以上の暫定レスポンスと、1 つ以上の最終レスポンスを含む) からなる。リクエストが INVITE であったトランザクション (INVITE トランザクションと呼ばれる) の場合、最終レスポンスが 2xx でなかったときにのみ、そのトランザクションは ACK も含む。レスポンスが 2xx であった場合、ACK はトランザクションの一部とは見なされない。
この分離の理由は、INVITE に対するすべての 200 (OK) レスポンスを UAC に確実に届けるという重要性に根ざしている。それらすべてを UAC に届けるために、UAS 単独がそれらの再送信の責任を負い (セクション 13.3.1.4 参照)、UAC 単独が ACK による確認の責任を負う (セクション 13.2.2.4 参照)。この ACK は UAC によってのみ再送信されるため、実質的にそれ自身のトランザクションと見なされる。
トランザクションにはクライアント側とサーバー側がある。クライアント側はクライアントトランザクション、サーバー側はサーバートランザクションと呼ばれる。クライアントトランザクションはリクエストを送信し、サーバートランザクションはレスポンスを送信する。クライアントおよびサーバートランザクションは、任意の数の要素に組み込まれる論理関数である。具体的には、それらはユーザーエージェントおよびステートフルプロキシサーバー内に存在する。セクション 4 の例を考えてみる。この例では、UAC がクライアントトランザクションを実行し、そのアウトバウンドプロキシがサーバートランザクションを実行する。アウトバウンドプロキシもクライアントトランザクションを実行し、それがインバウンドプロキシのサーバートランザクションにリクエストを送信する。そのプロキシもクライアントトランザクションを実行し、それが UAS のサーバートランザクションにリクエストを送信する。これを図 4 に示す。
+---------+ +---------+ +---------+ +---------+ | +-+|Request |+-+ +-+|Request |+-+ +-+|Request |+-+ | | |C||------->||S| |C||------->||S| |C||------->||S| | | |l|| ||e| |l|| ||e| |l|| ||e| | | |i|| ||r| |i|| ||r| |i|| ||r| | | |e|| ||v| |e|| ||v| |e|| ||v| | | |n|| ||e| |n|| ||e| |n|| ||e| | | |t|| ||r| |t|| ||r| |t|| ||r| | | | || || | | || || | | || || | | | |T|| ||T| |T|| ||T| |T|| ||T| | | |r|| ||r| |r|| ||r| |r|| ||r| | | |a|| ||a| |a|| ||a| |a|| ||a| | | |n|| ||n| |n|| ||n| |n|| ||n| | | |s||Response||s| |s||Response||s| |s||Response||s| | | +-+|<-------|+-+ +-+|<-------|+-+ +-+|<-------|+-+ | +---------+ +---------+ +---------+ +---------+ UAC Outbound Inbound UAS Proxy Proxy
Figure 4: Transaction relationships
ステートレスプロキシはクライアントまたはサーバートランザクションを含まない。トランザクションは、一方の UA またはステートフルプロキシと、他方の UA またはステートフルプロキシとの間に存在する。SIP トランザクションに関する限り、ステートレスプロキシは実質的に透過的である。クライアントトランザクションの目的は、クライアントが組み込まれた要素 (この要素を「トランザクションユーザー」、TU と呼ぶ。UA またはステートフルプロキシであり得る) からリクエストを受信し、それを確実にサーバートランザクションに配信することである。
クライアントトランザクションはまた、レスポンスを受信してそれを TU に配信する責任を負い、任意のレスポンスの再送信や許可されていないレスポンス (ACK に対するレスポンスなど) を排除する。さらに、INVITE リクエストの場合、クライアントトランザクションは、2xx レスポンスを受け入れる最終レスポンスに対する ACK リクエストを生成する責任を負う。
同様に、サーバートランザクションの目的は、トランスポート層からリクエストを受信して TU に配信することである。サーバートランザクションは、ネットワークからの任意のリクエストの再送信を除外する。サーバートランザクションは TU からのレスポンスを受け入れ、それらをトランスポート層に配信してネットワーク経由で送信する。INVITE トランザクションの場合、2xx レスポンスを除く任意の最終レスポンスに対する ACK リクエストを吸収する。
2xx レスポンスとその ACK は特別な扱いを受ける。このレスポンスは UAS のみによって再送信され、その ACK は UAC のみによって生成される。このエンドツーエンドの扱いは、発信者が呼び出しを受け入れたすべてのユーザーの集合を知るために必要である。この特別な扱いのため、2xx レスポンスの再送信はトランザクション層ではなく UA コアによって処理される。同様に、2xx に対する ACK の生成は UA コアによって処理される。経路上の各プロキシは、単に各 2xx レスポンスを INVITE およびそれに対応する ACK に転送するだけである。
17.1 クライアントトランザクション (Client Transaction)
クライアントトランザクションは、状態マシンの保守を通じてその機能を提供する。
TU は、単純なインターフェースを通じてクライアントトランザクションと通信する。TU が新しいトランザクションを開始したい場合、クライアントトランザクションを作成し、送信する SIP リクエストと、それを送信する IP アドレス、ポート、トランスポートを渡す。クライアントトランザクションはその状態マシンの実行を開始する。有効なレスポンスはクライアントトランザクションから TU に渡される。
TU が渡すリクエストのメソッドに応じて、2 種類のクライアントトランザクション状態マシンがある。1 つは INVITE リクエストのクライアントトランザクションを処理する。この種のマシンは INVITE クライアントトランザクションと呼ばれる。もう 1 つの種類は、INVITE および ACK 以外のすべてのリクエストのクライアントトランザクションを処理する。これは非 INVITE クライアントトランザクションと呼ばれる。ACK のクライアントトランザクションは存在しない。TU が ACK を送信したい場合、それを直接トランスポート層に渡して送信する。
INVITE トランザクションは、その長期間にわたる持続時間のため、他のメソッドのものと異なる。通常、INVITE に応答するには人間の入力が必要である。応答を送信する際に予想される長い遅延は、3 ウェイハンドシェイクを主張する。一方、他のメソッドのリクエストは迅速に完了することが期待される。非 INVITE トランザクションは 2 ウェイハンドシェイクに依存しているため、TU は非 INVITE リクエストに直ちに応答すべきである (SHOULD)。
17.1.1 INVITE クライアントトランザクション (INVITE Client Transaction)
17.1.1.1 INVITE トランザクションの概要 (Overview of INVITE Transaction)
INVITE トランザクションは 3 ウェイハンドシェイクからなる。クライアントトランザクションは INVITE を送信し、サーバートランザクションはレスポンスを送信し、クライアントトランザクションは ACK を送信する。信頼できないトランスポート (UDP など) の場合、クライアントトランザクションは、T1 秒で始まり、各再送信後に 2 倍になる間隔でリクエストを再送信する。T1 は往復時間 (RTT) の推定値であり、デフォルトは 500 ms である。ここで説明するトランザクションタイマーのほぼすべては T1 に応じてスケーリングされ、T1 を変更するとそれらの値が調整される。リクエストは信頼できるトランスポート上では再送信されない。1xx レスポンスを受信後、すべての再送信は完全に停止し、クライアントはさらにレスポンスを待つ。サーバートランザクションは追加の 1xx レスポンスを送信できるが、それらはサーバートランザクションによって確実には送信されない。最終的に、サーバートランザクションは最終レスポンスの送信を決定する。信頼できないトランスポートの場合、そのレスポンスは定期的に再送信され、信頼できるトランスポートの場合は 1 回送信される。クライアントトランザクションで受信された各最終レスポンスに対して、クライアントトランザクションは ACK を送信し、その目的はレスポンスの再送信を消すことである。
17.1.1.2 形式記述 (Formal Description)
INVITE クライアントトランザクションの状態マシンを図 5 に示す。初期状態の "calling" は、TU が INVITE リクエストで新しいクライアントトランザクションを開始したときに必ず入力されなければならない (MUST)。クライアントトランザクションは、送信のためにリクエストをトランスポート層に渡さなければならない (MUST) (セクション 18 参照)。信頼できないトランスポートを使用している場合、クライアントトランザクションは T1 の値でタイマー A を開始しなければならない (MUST)。信頼できるトランスポートを使用している場合、クライアントトランザクションはタイマー A を開始すべきではない (SHOULD NOT) (タイマー A はリクエストの再送信を制御する)。いずれのトランスポートでも、クライアントトランザクションは 64*T1 秒の値でタイマー B を開始しなければならない (MUST) (タイマー B はトランザクションのタイムアウトを制御する)。
タイマー A が発火したとき、クライアントトランザクションはリクエストをトランスポート層に渡して再送信しなければならず (MUST)、タイマーを 2*T1 の値でリセットしなければならない (MUST)。トランザクション層の文脈における再送信の正式な定義は、以前にトランスポート層に送信したメッセージを取得し、それを再びトランスポート層に渡すことである。
タイマー A が 2*T1 秒後に発火したとき、リクエストは (クライアントトランザクションがまだこの状態にあると仮定して) 再び再送信されなければならない (MUST)。このプロセスは、各送信後に間隔が 2 倍になるようにリクエストが再送信されるよう継続しなければならない (MUST)。これらの再送信は、クライアントトランザクションが "calling" 状態にある間のみ実行されるべきである (SHOULD)。
T1 のデフォルト値は 500 ms である。T1 はクライアントとサーバーのトランザクション間の RTT の推定値である。要素は (一般インターネット接続を許可しない閉じたプライベートネットワーク内では) T1 のより小さい値を使用してもよい (MAY) (ただし推奨されない)。T1 はより大きく選択してもよく (MAY)、RTT がより大きいことが事前に分かっている場合 (高遅延のアクセス回線など) は推奨される。T1 の値がどうであれ、このセクションで説明する再送信の指数バックオフを使用しなければならない (MUST)。
クライアントトランザクションが "Calling" 状態のままタイマー B が発火した場合、クライアントトランザクションは TU にタイムアウトが発生したことを通知すべきである (SHOULD)。クライアントトランザクションは ACK を生成してはならない (MUST NOT)。64*T1 の値は、信頼できないトランスポートの場合に 7 つのリクエストを送信するのに必要な時間に等しい。
クライアントトランザクションが "Calling" 状態で暫定レスポンスを受信した場合、それは "Proceeding" 状態に遷移する。 "Proceeding" 状態では、クライアントトランザクションはリクエストを再送信すべきではない (SHOULD NOT)。さらに、暫定レスポンスは TU に渡されなければならない (MUST)。"Proceeding" 状態の間のさらに任意の暫定レスポンスは TU に渡されなければならない (MUST)。
"Calling" または "Proceeding" 状態のいずれかにあるとき、300-699 の状態コードを持つレスポンスを受信すると、クライアントトランザクションは "Completed" に遷移しなければならない (MUST)。クライアントトランザクションは受信したレスポンスを TU に渡さなければならず (MUST)、クライアントトランザクションは (トランスポートが信頼できる場合でも) ACK リクエストを生成しなければならない (MUST) (レスポンスから ACK を構成するためのガイドラインはセクション 17.1.1.3 にある)、そして ACK を送信のためにトランスポート層に渡さなければならない (MUST)。ACK は、元のリクエストが送信されたのと同じアドレス、ポート、トランスポートに送信されなければならない (MUST)。クライアントトランザクションは "Completed" 状態に入るとき、信頼できないトランスポートの場合は少なくとも 32 秒、信頼できるトランスポートの場合は 0 秒の値でタイマー D を開始すべきである (SHOULD)。タイマー D は、信頼できないトランスポートが使用されるときにサーバートランザクションが "Completed" 状態に留まることができる時間の量を反映する。これは INVITE サーバートランザクションのタイマー H に等しく、そのデフォルトは 64*T1 である。しかし、クライアントトランザクションはサーバートランザクションが使用している T1 の値を知らないため、タイマー D を T1 に基づかせる代わりに絶対最小値の 32 秒が使用される。
"Completed" 状態の間に受信される最終レスポンスの再送信はいずれも、ACK を再送信のためにトランスポート層に再渡しすることを引き起こさなければならない (MUST) が、新しく受信されたレスポンスは TU に渡してはならない (MUST NOT)。レスポンスの再送信は、セクション 17.1.3 の規則に基づいて同じクライアントトランザクションに一致する任意のレスポンスとして定義される。
|INVITE from TU
Timer A fires |INVITE sent
Reset A, V Timer B fires
INVITE sent +-----------+ or Transport Err.
+---------| |---------------+inform TU
| | Calling | |
+-------->| |-------------->|
+-----------+ 2xx |
| | 2xx to TU |
| |1xx |
300-699 +---------------+ |1xx to TU |
ACK sent | | | resp. to TU | 1xx V | | 1xx to TU -----------+ | | +---------| | | | | |Proceeding |-------------->| | +-------->| | 2xx | | +-----------+ 2xx to TU | | 300-699 | | | ACK sent, | | | resp. to TU| | | | | NOTE: | 300-699 V | | ACK sent +-----------+Transport Err. | transitions | +---------| |Inform TU | labeled with | | | Completed |-------------->| the event | +-------->| | | over the action | +-----------+ | to take | ^ | | | | | Timer D fires | +--------------+ | - | | | V | +-----------+ | | | | | Terminated|<--------------+ | | +-----------+
Figure 5: INVITE client transaction
"Completed" 状態のときにタイマー D が発火した場合、クライアントトランザクションは終了状態に移らなければならない (MUST)。
"Calling" または "Proceeding" 状態のいずれかにあるとき、2xx レスポンスを受信すると、クライアントトランザクションは "Terminated" 状態に入らなければならず (MUST)、レスポンスは TU に渡されなければならない (MUST)。このレスポンスの処理は、TU がプロキシコアか UAC コアかによって異なる。UAC コアはこのレスポンスに対する ACK の生成を処理し、プロキシコアは常に 200 (OK) を上流へ転送する。プロキシと UAC の間の 200 (OK) の異なる扱いが、その処理がトランザクション層で行われない理由である。
クライアントトランザクションは、"Terminated" 状態に入った瞬間に破棄されなければならない (MUST)。これは実際に正しい動作を保証するために必要である。その理由は、INVITE に対する 2xx レスポンスが異なる扱いを受けるためである。それぞれはプロキシによって転送され、UAC での ACK 処理は異なる。したがって、各 2xx はプロキシコア (転送できるように) と UAC コア (確認できるように) の両方に渡される必要がある。トランザクション層の処理は行われない。トランスポートがレスポンスを受信するたびに、トランスポート層が一致するクライアントトランザクションを見つけられない場合 (セクション 17.1.3 の規則を使用)、レスポンスは直接コアに渡される。一致するクライアントトランザクションは最初の 2xx によって破棄されるため、後続の 2xx は一致を見つけられず、したがってコアに渡される。
17.1.1.3 ACK リクエストの構成 (Construction of the ACK Request)
このセクションは、クライアントトランザクション内で送信される ACK リクエストの構成を規定する。2xx に対する ACK を生成する UAC コアは、代わりにセクション 13 で説明される規則に従わなければならない (MUST)。
クライアントトランザクションによって構成される ACK リクエストは、Call-ID、From、Request-URI の値が、クライアントトランザクションによってトランスポートに渡されたリクエスト (これを「元のリクエスト」と呼ぶ) のそれらのヘッダフィールドの値と等しくなければならなければならない (MUST)。ACK 内の To ヘッダフィールドは、確認されるレスポンス内の To ヘッダフィールドに等しくなければならず (MUST)、したがって通常、tag パラメータの追加によって元のリクエスト内の To ヘッダフィールドと異なる。ACK は単一の Via ヘッダフィールドを含まなければならず (MUST)、これは元のリクエストの最上位 Via ヘッダフィールドに等しくなければならない (MUST)。ACK 内の CSeq ヘッダフィールドは、元のリクエストに存在したものと同じシーケンス番号の値を含まなければならない (MUST) が、メソッドパラメータは "ACK" に等しくなければならない (MUST)。
確認されるレスポンスの INVITE リクエストに Route ヘッダフィールドがあった場合、それらのヘッダフィールドは ACK に現れなければならない (MUST)。これは、ACK が下流の任意のステートレスプロキシを経由して適切にルーティングできるようにするためである。
任意のリクエストはボディを含んでもよい (MAY) が、ACK 内のボディは特別である。なぜなら、ボディが理解されなくてもリクエストを拒否できないからである。したがって、非 2xx 用の ACK へのボディの配置は推奨されない (NOT RECOMMENDED) が、行う場合、ボディタイプは、INVITE に対するレスポンスが 415 でなかったと仮定して、INVITE に現れたものに制限される。そうであった場合、ACK 内のボディは 415 の Accept ヘッダフィールドにリストされた任意のタイプであってよい (MAY)。
たとえば、以下のリクエストを考える:
INVITE sip:[email protected] SIP/2.0
Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKkjshdyff
To: Bob <sip:[email protected]>
From: Alice <sip:[email protected]>;tag=88sja8x
Max-Forwards: 70
Call-ID: 987asjd97y7atg
CSeq: 986759 INVITE
このリクエストに対する非 2xx 最終レスポンスの ACK リクエストは次のようになる:
ACK sip:[email protected] SIP/2.0
Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKkjshdyff
To: Bob <sip:[email protected]>;tag=99sa0xk
From: Alice <sip:[email protected]>;tag=88sja8x
Max-Forwards: 70
Call-ID: 987asjd97y7atg
CSeq: 986759 ACK
17.1.2 非 INVITE クライアントトランザクション (Non-INVITE Client Transaction)
17.1.2.1 非 INVITE トランザクションの概要 (Overview of the non-INVITE Transaction)
非 INVITE トランザクションは ACK を使用しない。それらは単純なリクエスト-レスポンスのやり取りである。信頼できないトランスポートの場合、リクエストは T1 で始まり T2 に達するまで 2 倍になる間隔で再送信される。暫定レスポンスを受信した場合、信頼できないトランスポートの再送信は継続するが、T2 の間隔となる。サーバートランザクションは、送信した最後のレスポンス (暫定または最終) を、リクエストの再送信を受信したときにのみ再送信する。これが、暫定レスポンスの後もリクエストの再送信を継続する必要がある理由である。それらは最終レスポンスの確実な配信を保証するためである。
INVITE トランザクションと異なり、非 INVITE トランザクションは 2xx レスポンスに対する特別な扱いがない。その結果、非 INVITE に対する単一の 2xx レスポンスのみが UAC に配信される。
17.1.2.2 形式記述 (Formal Description)
非 INVITE クライアントトランザクションの状態マシンを図 6 に示す。これは INVITE の状態マシンと非常に似ている。
"Trying" 状態は、TU がリクエストで新しいクライアントトランザクションを開始したときに入力される。この状態に入るとき、クライアントトランザクションはタイマー F を 64T1 秒で発火するように設定すべきである (SHOULD)。リクエストは送信のためにトランスポート層に渡されなければならない (MUST)。信頼できないトランスポートを使用している場合、クライアントトランザクションはタイマー E を T1 秒で発火するように設定しなければならない (MUST)。この状態のままタイマー E が発火した場合、タイマーはリセットされるが、今回は MIN(2T1, T2) の値で。タイマーが再び発火したとき、MIN(4*T1, T2) でリセットされる。このプロセスは、再送信が指数関数的に増加する間隔で発生し、T2 で上限に達するよう継続する。T2 のデフォルト値は 4 秒であり、非 INVITE サーバートランザクションが直ちに応答しない場合、リクエストに応答するのに要する時間の量を表す。T1 と T2 のデフォルト値では、これは 500 ms、1 s、2 s、4 s、4 s、4 s などの間隔になる。
クライアントトランザクションがまだ "Trying" 状態のときにタイマー F が発火した場合、クライアントトランザクションは TU にタイムアウトを通知すべきであり (SHOULD)、そして "Terminated" 状態に入るべきである (SHOULD)。"Trying" 状態のときに暫定レスポンスを受信した場合、レスポンスは TU に渡されなければならず (MUST)、そしてクライアントトランザクションは "Proceeding" 状態に移るべきである (SHOULD)。"Trying" 状態のときに最終レスポンス (状態コード 200-699) を受信した場合、レスポンスは TU に渡されなければならず (MUST)、クライアントトランザクションは "Completed" 状態に遷移しなければならない (MUST)。
"Proceeding" 状態のときにタイマー E が発火した場合、リクエストは再送信のためにトランスポート層に渡されなければならず (MUST)、タイマー E は T2 秒の値でリセットされなければならない (MUST)。"Proceeding" 状態のときにタイマー F が発火した場合、TU にタイムアウトを通知しなければならず (MUST)、クライアントトランザクションは終了状態に遷移しなければならない (MUST)。"Proceeding" 状態のときに最終レスポンス (状態コード 200-699) を受信した場合、レスポンスは TU に渡されなければならず (MUST)、クライアントトランザクションは "Completed" 状態に遷移しなければならない (MUST)。
クライアントトランザクションが "Completed" 状態に入ると、信頼できないトランスポートの場合は T4 秒、信頼できるトランスポートの場合は 0 秒で発火するようにタイマー K を設定しなければならない (MUST)。"Completed" 状態は、受信される可能性のある追加のレスポンス再送信をバッファするために存在する (これが、クライアントトランザクションがそこに留まるのは信頼できないトランスポートの場合のみである理由である)。T4 は、クライアントとサーバーのトランザクション間でネットワークがメッセージをクリアするのに要する時間の量を表す。T4 のデフォルト値は 5 秒である。レスポンスは、セクション 17.1.3 で指定された規則を使用して同じトランザクションに一致するとき、再送信である。この状態のときにタイマー K が発火した場合、クライアントトランザクションは "Terminated" 状態に遷移しなければならない (MUST)。
トランザクションが終了状態になると、直ちに破棄されなければならない (MUST)。
17.1.3 レスポンスとクライアントトランザクションの一致 (Matching Responses to Client Transactions)
クライアントのトランスポート層がレスポンスを受信したとき、どのクライアントトランザクションがそのレスポンスを処理するかを決定しなければならない。これにより、セクション 17.1.1 および 17.1.2 の処理が行われる。この目的には、最上位 Via ヘッダフィールドの branch パラメータが使用される。レスポンスは、以下の 2 つの条件の下でクライアントトランザクションに一致する:
1. レスポンスの最上位 Via ヘッダフィールドの branch パラメータの値が、トランザクションを作成したリクエストの最上位 Via ヘッダフィールドの branch パラメータの値と等しいこと。
2. CSeq ヘッダフィールドのメソッドパラメータが、トランザクションを作成したリクエストのメソッドと一致すること。メソッドが必要なのは、CANCEL リクエストは異なるトランザクションを構成するが、同じ branch パラメータの値を共有するためである。
リクエストがマルチキャスト経由で送信された場合、異なるサーバーから複数のレスポンスを生成する可能性がある。これらのレスポンスはすべて最上位 Via で同じ branch パラメータを持つが、To tag が異なる。上記の規則に基づいて受信された最初のレスポンスが使用され、他は再送信と見なされる。それはエラーではない。マルチキャスト SIP は、単一のレスポンスの処理に限定された初歩的な「シングルホップディスカバリに似た」サービスのみを提供する。詳細はセクション 18.1.1 を参照。
17.1.4 トランスポートエラーの処理 (Handling Transport Errors)
|Request from TU
|send request
Timer E V
send request +-----------+
+---------| |-------------------+
| | Trying | Timer F |
+-------->| | or Transport Err.|
+-----------+ inform TU |
200-699 | | |
resp. to TU | |1xx |
+---------------+ |resp. to TU |
| | |
| Timer E V Timer F |
| send req +-----------+ or Transport Err. |
| +---------| | inform TU |
| | |Proceeding |------------------>|
| +-------->| |-----+ |
| +-----------+ |1xx |
| | ^ |resp to TU |
| 200-699 | +--------+ |
| resp. to TU | |
| | |
| V |
| +-----------+ |
| | | |
| | Completed | |
| | | |
| +-----------+ |
| ^ | |
| | | Timer K |
+--------------+ | - |
| |
V |
NOTE: +-----------+ |
| | |
transitions | Terminated|\<------------------+
labeled with | |
the event +-----------+
over the action
to take
Figure 6: non-INVITE client transaction
クライアントトランザクションが送信のためにリクエストをトランスポート層に送信するとき、トランスポート層が失敗を示した場合、以下の手順に従う。
クライアントトランザクションは TU にトランスポート障害が発生したことを通知すべきであり (SHOULD)、クライアントトランザクションは直接 "Terminated" 状態に遷移すべきである (SHOULD)。TU は [4] で説明されるフェイルオーバーメカニズムを処理する。
17.2 サーバートランザクション (Server Transaction)
サーバートランザクションは、リクエストの TU への配信とレスポンスの確実な送信に責任を持つ。これは状態マシンを通じて達成される。サーバートランザクションは、リクエストを受信したとき、およびそのリクエストに対するトランザクション処理が望まれるとき (常にそうとは限らない) にコアによって作成される。
クライアントトランザクションと同様に、状態マシンは受信したリクエストが INVITE リクエストかどうかに依存する。
17.2.1 INVITE サーバートランザクション (INVITE Server Transaction)
INVITE サーバートランザクションの状態図を図 7 に示す。
リクエストに対してサーバートランザクションが構成されると、それは "Proceeding" 状態に入る。サーバートランザクションは 100 (Trying) レスポンスを生成しなければならない (MUST)。ただし、TU が 200 ms 以内に暫定または最終レスポンスを生成することを知っている場合は、100 (Trying) レスポンスを生成してもよい (MAY)。この暫定レスポンスは、ネットワークの輻輳を避けるためにリクエストの再送信を迅速に消すために必要である。100 (Trying) レスポンスはセクション 8.2.6 の手順に従って構成されるが、(リクエストに存在しなかった場合に) レスポンスの To ヘッダフィールドへの tag の挿入は、MAY から SHOULD NOT に格下げされる点が例外である。リクエストは TU に渡されなければならない (MUST)。
TU は任意の数の暫定レスポンスをサーバートランザクションに渡す。サーバートランザクションが "Proceeding" 状態にある限り、それらの各々は送信のためにトランスポート層に渡されなければならない (MUST)。それらはトランザクション層によって確実には送信されず (再送信されず)、サーバートランザクションの状態の変化を引き起こさない。 "Proceeding" 状態の間にリクエストの再送信を受信した場合、TU から受信された最新の暫定レスポンスを再送信のためにトランスポート層に渡さなければならない (MUST)。リクエストは、セクション 17.2.3 の規則に基づいて同じサーバートランザクションに一致する場合、再送信である。
"Proceeding" 状態の間に、TU が 2xx レスポンスをサーバートランザクションに渡した場合、サーバートランザクションはこのレスポンスを送信のためにトランスポート層に渡さなければならない (MUST)。それはサーバートランザクションによって再送信されず、2xx レスポンスの再送信は TU によって処理される。サーバートランザクションはその後 "Terminated" 状態に遷移しなければならない (MUST)。
"Proceeding" 状態の間に、TU が 300 から 699 の状態コードのレスポンスをサーバートランザクションに渡した場合、そのレスポンスは送信のためにトランスポート層に渡されなければならず (MUST)、状態マシンは "Completed" 状態に入らなければならない (MUST)。信頼できないトランスポートの場合、タイマー G は T1 秒で発火するように設定され、信頼できるトランスポートの場合は発火するように設定されない。
これは RFC 2543 からの変更であり、以前はレスポンスが信頼できるトランスポート上でも常に再送信されていた。
"Completed" 状態に入るとき、すべてのトランスポートについてタイマー H は 64T1 秒で発火するように設定されなければならない (MUST)。タイマー H は、サーバートランザクションがレスポンスの再送信を放棄する時期を決定する。その値はタイマー B (クライアントトランザクションがリクエストの送信を再試行し続ける時間) に等しくなるように選択される。タイマー G が発火した場合、レスポンスは再送信のためにトランスポート層に再び渡され、タイマー G は MIN(2T1, T2) 秒で発火するように設定される。それ以降、タイマー G が発火するたびに、レスポンスは送信のためにトランスポートに再び渡され、タイマー G は 2 倍の値でリセットされるが、その値が T2 を超える場合は T2 の値でリセットされる。これは、非 INVITE クライアントトランザクションの "Trying" 状態でのリクエストの再送信動作と同一である。さらに、"Completed" 状態の間にリクエストの再送信を受信した場合、サーバーはレスポンスを再送信のためにトランスポートに渡すべきである (SHOULD)。
サーバートランザクションが "Completed" 状態にあるときに ACK を受信した場合、サーバートランザクションは "Confirmed" 状態に遷移しなければならない (MUST)。この状態ではタイマー G は無視されるため、レスポンスの再送信はいずれも停止する。
タイマー H が "Completed" 状態のときに発火した場合、ACK が受信されなかったことを意味する。この場合、サーバートランザクションは "Terminated" 状態に遷移しなければならず (MUST)、またトランザクション障害が発生したことを TU に示さなければならない (MUST)。
|INVITE
|pass INV to TU
INVITE V send 100 if TU won't in 200ms
send response+-----------+
+--------| |--------+101-199 from TU
| | Proceeding| |send response
+------->| |\<-------+
| | Transport Err.
| | Inform TU
| |--------------->+
+-----------+ |
300-699 from TU | |2xx from TU |
send response | |send response |
| +------------------>+
| |
INVITE V Timer G fires |
send response+-----------+ send response |
+--------| |--------+ |
| | Completed | | |
+------->| |\<-------+ |
+-----------+ |
| | |
ACK | | |
- | +------------------>+
| Timer H fires |
V or Transport Err.|
+-----------+ Inform TU |
| | |
| Confirmed | |
| | |
+-----------+ |
| |
|Timer I fires |
|- |
| |
V |
+-----------+ |
| | |
| Terminated|\<---------------+
| |
+-----------+
Figure 7: INVITE server transaction
"Confirmed" 状態の目的は、最終レスポンスの再送信によってトリガーされた追加の ACK メッセージを吸収することである。この状態に入ると、タイマー I は信頼できないトランスポートの場合は T4 秒、信頼できるトランスポートの場合は 0 秒で発火するように設定される。タイマー I が発火すると、サーバーは "Terminated" 状態に遷移しなければならない (MUST)。
トランザクションが "Terminated" 状態になると、直ちに破棄されなければならない (MUST)。クライアントトランザクションと同様に、これは INVITE に対する 2xx レスポンスの信頼性を確保するために必要である。
17.2.2 非 INVITE サーバートランザクション (Non-INVITE Server Transaction)
非 INVITE サーバートランザクションの状態マシンを図 8 に示す。
状態マシンは "Trying" 状態で初期化され、初期化時に INVITE または ACK 以外のリクエストが渡される。このリクエストは TU に渡される。一度 "Trying" 状態になると、さらに任意のリクエストの再送信は破棄される。リクエストは、セクション 17.2.3 で指定された規則を使用して同じサーバートランザクションに一致する場合、再送信である。
"Trying" 状態の間に、TU が暫定レスポンスをサーバートランザクションに渡した場合、サーバートランザクションは "Proceeding" 状態に入らなければならない (MUST)。レスポンスは送信のためにトランスポート層に渡されなければならない (MUST)。"Proceeding" 状態の間に TU から受信されたさらに任意の暫定レスポンスは、送信のためにトランスポート層に渡されなければならなければならない (MUST)。"Proceeding" 状態の間にリクエストの再送信を受信した場合、最も最近に送信された暫定レスポンスを再送信のためにトランスポート層に渡さなければならない (MUST)。TU が最終レスポンス (状態コード 200-699) を "Proceeding" 状態のサーバーに渡した場合、トランザクションは "Completed" 状態に入らなければならず (MUST)、レスポンスは送信のためにトランスポート層に渡されなければならない (MUST)。
サーバートランザクションが "Completed" 状態に入ると、信頼できないトランスポートの場合は 64*T1 秒、信頼できるトランスポートの場合は 0 秒で発火するようにタイマー J を設定しなければならない (MUST)。"Completed" 状態の間に、サーバートランザクションは、リクエストの再送信を受信するたびに最終レスポンスを再送信のためにトランスポート層に渡さなければならない (MUST)。"Completed" 状態の間に TU からサーバートランザクションに渡された他の最終レスポンスはいずれも破棄されなければならない (MUST)。サーバートランザクションは、タイマー J が発火するまでこの状態に留まり、その時点で "Terminated" 状態に遷移しなければならない (MUST)。
サーバートランザクションは、"Terminated" 状態に入った瞬間に破棄されなければならない (MUST)。
17.2.3 リクエストとサーバートランザクションの一致 (Matching Requests to Server Transactions)
サーバーがネットワークからリクエストを受信したとき、それを既存のトランザクションに一致させなければならない。これは以下の方法で達成される。
リクエストの最上位 Via ヘッダフィールドの branch パラメータが調べられる。それが存在し、マジッククッキー "z9hG4bK" で始まる場合、リクエストはこの仕様に準拠するクライアントトランザクションによって生成された。したがって、branch パラメータはそのクライアントが送信したすべてのトランザクション間で一意となる。リクエストは以下の場合にトランザクションに一致する:
1. リクエスト内の branch パラメータが、トランザクションを作成したリクエストの最上位 Via ヘッダフィールド内のものと等しく、かつ
2. リクエストの最上位 Via 内の sent-by 値が、トランザクションを作成したリクエスト内のものと等しく、かつ
3. リクエストのメソッドがトランザクションを作成したメソッドと一致する。ただし ACK の場合、トランザクションを作成したリクエストのメソッドは INVITE である。
この一致規則は、INVITE トランザクションと非 INVITE トランザクションの両方に等しく適用される。
sent-by 値は、異なるクライアントからの branch パラメータの偶発的または悪意のある重複があり得るため、一致プロセスの一部として使用される。
最上位 Via ヘッダフィールドの branch パラメータが存在しないか、マジッククッキーを含まない場合、以下の手順が使用される。これらは RFC 2543 準拠の実装との下位互換性を処理するために存在する。
INVITE リクエストは、Request-URI、To tag、From tag、Call-ID、CSeq、および最上位 Via ヘッダフィールドが、トランザクションを作成した INVITE リクエストのものと一致する場合、トランザクションに一致する。この場合、INVITE はトランザクションを作成した元のものの再送信である。ACK リクエストは、Request-URI、From tag、Call-ID、CSeq 番号 (メソッドではない)、および最上位 Via ヘッダフィールドが、トランザクションを作成した INVITE リクエストのものと一致し、かつ ACK の To tag がサーバートランザクションが送信したレスポンスの To tag と一致する場合、トランザクションに一致する。一致は、それらの各ヘッダフィールドに対して定義された一致規則に基づいて行われる。ACK 一致プロセスにおける To ヘッダフィールドの tag の包含は、2xx 用の ACK と他のレスポンス用の ACK をプロキシで曖昧さをなくすのに役立つ。プロキシは両方のレスポンスを転送した可能性がある (これは異常な条件下で発生し得る。具体的には、プロキシがリクエストをフォークし、その後クラッシュした場合、レスポンスは別のプロキシに配信され、それが複数のレスポンスを上流へ転送することになる可能性がある)。以前の ACK によって一致した INVITE トランザクションに一致する ACK リクエストは、その以前の ACK の再送信と見なされる。
|Request received
|pass to TU
V
+-----------+
| |
| Trying |-------------+
| | |
+-----------+ |200-699 from TU
| |send response
|1xx from TU |
|send response |
| |
Request V 1xx from TU |
send response+-----------+send response|
+--------| |--------+ |
| | Proceeding| | |
+------->| |\<-------+ |
+\<--------------| | |
|Trnsprt Err +-----------+ |
|Inform TU | |
| | |
| |200-699 from TU |
| |send response |
| Request V |
| send response+-----------+ |
| +--------| | |
| | | Completed |\<------------+
| +------->| |
+\<--------------| |
|Trnsprt Err +-----------+
|Inform TU |
| |Timer J fires
| |-
| |
| V
| +-----------+
| | |
+-------------->| Terminated|
| |
+-----------+
Figure 8: non-INVITE server transaction
他のすべてのリクエストメソッドについては、Request-URI、To tag、From tag、Call-ID、CSeq (メソッドを含む)、および最上位 Via ヘッダフィールドが、トランザクションを作成したリクエストのものと一致する場合、リクエストはトランザクションに一致する。一致は、それらの各ヘッダフィールドに対して定義された一致規則に基づいて行われる。非 INVITE リクエストが既存のトランザクションに一致する場合、それはそのトランザクションを作成したリクエストの再送信である。
一致規則には Request-URI が含まれるため、サーバーはレスポンスをトランザクションに一致させることはできない。TU がレスポンスをサーバートランザクションに渡すとき、そのレスポンスが対象とする特定のサーバートランザクションに渡さなければならない。
17.2.4 トランスポートエラーの処理 (Handling Transport Errors)
サーバートランザクションが送信のためにレスポンスをトランスポート層に送信するとき、トランスポート層が失敗を示した場合、以下の手順に従う。
まず、[4] の手順に従い、レスポンスをバックアップに配信しようとする。それらがすべて失敗した場合、[4] での失敗の定義に基づき、サーバートランザクションは TU に失敗が発生したことを通知すべきであり (SHOULD)、終了状態に遷移すべきである (SHOULD)。