18. トランスポート (Transport)
トランスポート層は、ネットワークトランスポートを介したリクエストおよびレスポンスの実際の送信を担当する。これには、コネクション指向トランスポートの場合におけるリクエストまたはレスポンスに使用する接続の決定が含まれる。
トランスポート層は、TCP や SCTP、またはそれら上の TLS のようなトランスポートプロトコルの永続的接続の管理を担当する。これには、トランスポート層に開かれたものも含まれる。これには、クライアントまたはサーバートランスポートによって開かれた接続が含まれるため、接続はクライアントとサーバーのトランスポート機能間で共有される。これらの接続は、接続の末端のアドレス、ポート、トランスポートプロトコルからなるタプルによってインデックス付けされる。トランスポート層によって接続が開かれたとき、このインデックスは宛先 IP、ポート、トランスポートに設定される。トランスポート層によって接続が受け入れられたとき、このインデックスは送信元 IP アドレス、ポート番号、トランスポートに設定される。送信元ポートはしばしば一時的であるが、それが一時的であるか [4] の手順を通じて選択されたかは不明である可能性があるため、トランスポート層によって受け入れられた接続は頻繁に再利用されないことに注意。その結果、コネクション指向トランスポートを使用する「ピアリング」関係にある 2 つのプロキシは、頻繁に 2 つの接続を使用中にし、それぞれの方向で開始されたトランザクション用に 1 つずつ持つことになる。
最後のメッセージがその接続を介して送信または受信されてから、実装定義の期間だけ接続を開いたままにしておくことが推奨される (RECOMMENDED)。この期間は、少なくとも、要素がトランザクションをインスタンス化から終了状態に至らしめるために必要な最長の時間に等しくあるべきである (SHOULD)。これは、トランザクションが開始されたのと同じ接続上で (たとえば、リクエスト、レスポンス、および INVITE の場合は非 2xx レスポンス用の ACK) 完了する可能性を高めるためである。これは通常少なくとも 64*T1 を意味する (T1 の定義についてはセクション 17.1.1.1 を参照)。ただし、たとえばタイマー C に大きな値を使用する TU を持つ要素では、それより大きくなる可能性がある。
すべての SIP 要素は UDP および TCP を実装しなければならない (MUST)。SIP 要素は他のプロトコルを実装してもよい (MAY)。
UA に TCP を必須とすることは、RFC 2543 からの実質的な変更である。これは、以下で説明するように、TCP を使用しなければならない大きなメッセージを処理する必要性から生じた。したがって、要素が大きなメッセージを決して送信しなくても、それを受信する可能性があり、それらを処理できる必要がある。
18.1 クライアント (Clients)
18.1.1 リクエストの送信 (Sending Requests)
トランスポート層のクライアント側は、リクエストの送信とレスポンスの受信を担当する。トランスポート層の利用者は、トランスポート層クライアントにリクエスト、IP アドレス、ポート、トランスポート、および必要に応じてマルチキャスト宛先用の TTL を渡す。
リクエストがパス MTU の 200 バイト以内である場合、または 1300 バイトより大きくパス MTU が不明な場合、リクエストは RFC 2914 [43] の輻輳制御付きトランスポートプロトコル (TCP など) を使用して送信されなければならない (MUST)。これにより最上位 Via のトランスポートプロトコルが示されたものから変更される場合、最上位 Via の値は変更されなければならない (MUST)。これは UDP 上でのメッセージの断片化を防ぎ、大きなメッセージに輻輳制御を提供する。ただし、実装は最大データグラムパケットサイズまでのメッセージを処理できなければならない (MUST)。UDP の場合、このサイズは IP および UDP ヘッダを含めて 65,535 バイトである。
メッセージサイズと MTU との間の 200 バイトの「バッファ」は、SIP のレスポンスがリクエストより大きくなる可能性があるという事実に対応する。これは、たとえば INVITE へのレスポンスへの Record-Route ヘッダフィールド値の追加により発生する。この余分なバッファにより、レスポンスはリクエストより約 170 バイト大きくても、IPv4 で断片化されない (IP/UDP で約 30 バイトが消費され、IPSec がないと想定)。1300 は、パス MTU が不明な場合、1500 バイトのイーサネット MTU を想定して選択される。
要素がこれらのメッセージサイズ制約によりリクエストを TCP 経由で送信し、そのリクエストがそうでなければ UDP 経由で送信されたはずである場合、接続の確立が ICMP Protocol Not Supported のいずれかを生成するか、TCP リセットをもたらす場合、要素は UDP を使用してリクエストを再試行すべきである (SHOULD)。これは、TCP をサポートしない RFC 2543 準拠実装との下位互換性を提供するためのみである。この動作は、この仕様の将来の改訂で非推奨になることが予想される。
マルチキャストアドレスにリクエストを送信するクライアントは、宛先マルチキャストアドレスを含む「maddr」パラメータをその Via ヘッダフィールド値に追加しなければならず (MUST)、IPv4 の場合は値 1 の「ttl」パラメータを追加すべきである (SHOULD)。IPv6 マルチキャストの使用はこの仕様では定義されておらず、必要性が生じたときに将来の標準化の対象となる。
これらの規則により、SIP におけるマルチキャストの意図的な制限が生じる。その主な機能は、「シングルホップディスカバリに似た」サービスを提供し、要求に対していずれか 1 つのみの応答を処理すればよい一連の同種サーバーにリクエストを配信することである。この機能は登録に最も有用である。実際、セクション 17.1.3 のトランザクション処理規則に基づき、クライアントトランザクションは最初のレスポンスを受け入れ、それらはすべて同じ Via branch 識別子を含むため他を再送信と見なす。
リクエストが送信される前に、クライアントトランスポートは Via ヘッダフィールドに「sent-by」フィールドの値を挿入しなければならない (MUST)。このフィールドは IP アドレスまたはホスト名とポートを含む。FQDN の使用が推奨される (RECOMMENDED)。このフィールドは、以下で説明される特定の条件でレスポンスの送信に使用される。ポートが存在しない場合、デフォルト値はトランスポートに依存する。UDP、TCP、SCTP では 5060、TLS では 5061 である。
信頼できるトランスポートの場合、レスポンスは通常、リクエストを受信した接続上で送信される。したがって、クライアントトランスポートは、リクエストの送信に使用したのと同じ接続でレスポンスを受信する準備をしなければならない (MUST)。エラー条件下では、サーバーは新しい接続を開いてレスポンスを送信しようとする場合がある。この場合に対処するため、トランスポート層は、リクエストの送信元 IP アドレスおよび「sent-by」フィールドのポート番号からの着信接続を受信する準備もしなければならない (MUST)。また、[4] のセクション 5 で説明される手順に基づいてサーバーが選択する任意のアドレスおよびポートで着信接続を受信する準備もしなければならない (MUST)。
信頼できないユニキャストトランスポートの場合、クライアントトランスポートは、リクエストの送信元 IP アドレス (レスポンスは送信元アドレスに送り返されるため) および「sent-by」フィールドのポート番号でレスポンスを受信する準備をしなければならない (MUST)。さらに、信頼できるトランスポートと同様に、特定の場合にはレスポンスは別の場所に送信される。クライアントは、[4] のセクション 5 で説明される手順に基づいてサーバーが選択する任意のアドレスおよびポートでレスポンスを受信する準備をしなければならない (MUST)。
マルチキャストの場合、クライアントトランスポートは、リクエストを送信するのと同じマルチキャストグループおよびポートでレスポンスを受信する準備をしなければならない (MUST) (つまり、リクエストを送信したマルチキャストグループのメンバーである必要がある)。
リクエストが、開かれた既存の接続がある IP アドレス、ポート、トランスポート宛てである場合、この接続を使用してリクエストを送信することが推奨される (RECOMMENDED) が、別の接続を開いて使用してもよい (MAY)。
リクエストがマルチキャストを使用して送信される場合、それはトランスポート利用者により提供されるグループアドレス、ポート、TTL に送信される。リクエストがユニキャスト信頼できないトランスポートを使用して送信される場合、それはトランスポート利用者により提供される IP アドレスおよびポートに送信される。
18.1.2 レスポンスの受信 (Receiving Responses)
レスポンスを受信したとき、クライアントトランスポートは最上位 Via ヘッダフィールド値を調べる。そのヘッダフィールド値の「sent-by」パラメータの値が、クライアントトランスポートがリクエストに挿入するように設定されている値と一致しない場合、レスポンスは黙って破棄されなければならない (MUST)。
存在するクライアントトランザクションがある場合、クライアントトランスポートはセクション 17.1.3 の一致手順を使用して、レスポンスを既存のトランザクションに一致させようとする。一致するものがあれば、レスポンスはそのトランザクションに渡されなければならない (MUST)。それ以外の場合、レスポンスはさらに処理するためにコア (ステートレスプロキシ、ステートフルプロキシ、UA のいずれであれ) に渡されなければならない (MUST)。これらの「迷子の」レスポンスの処理はコアに依存する (たとえば、プロキシはそれらを転送し、UA は破棄する)。
18.2 サーバー (Servers)
18.2.1 リクエストの受信 (Receiving Requests)
サーバーは、そのサーバーとの通信の目的で渡される SIP または SIPS URI [4] の DNS ルックアップの結果となり得る任意の IP アドレス、ポート、トランスポートの組み合わせでリクエストを受信する準備をしておくべきである (SHOULD)。この文脈における「渡す」には、REGISTER リクエストまたはリダイレクトレスポンスの Contact ヘッダフィールドへの URI の配置、あるいはリクエストまたはレスポンスの Record-Route ヘッダフィールドへの配置が含まれる。URI は、ウェブページや名刺に配置することでも「渡す」ことができる。また、サーバーがすべての公開インターフェース上のデフォルトの SIP ポート (TCP および UDP 用 5060、TLS over TCP 用 5061) でリクエストをリッスンすることが推奨される (RECOMMENDED)。典型的な例外は、プライベートネットワーク、または同じホスト上で複数のサーバーインスタンスが実行されている場合である。サーバーが UDP 用にリッスンする任意のポートおよびインターフェースについて、それはその同じポートおよびインターフェースで TCP をリッスンしなければならない (MUST)。これは、メッセージが大きすぎる場合、TCP ではなく UDP を使用して送信される必要がある可能性があるためである。その結果、逆は真ではない。サーバーは、同じアドレスおよびポートで TCP をリッスンしているからといって、その特定のアドレスおよびポートで UDP をリッスンする必要はない。もちろん、サーバーが特定のアドレスおよびポートで UDP をリッスンする必要がある他の理由があってもよい。
サーバートランスポートが任意のトランスポートを介してリクエストを受信したとき、最上位 Via ヘッダフィールド値の「sent-by」パラメータの値を調べなければならない (MUST)。「sent-by」パラメータのホスト部分にドメイン名が含まれている場合、またはパケットの送信元アドレスと異なる IP アドレスが含まれている場合、サーバーはその Via ヘッダフィールド値に「received」パラメータを追加しなければならない (MUST)。このパラメータは、パケットの受信元アドレスを含まなければならない (MUST)。これは、リクエストの送信元 IP アドレスに送信されなければならないため、レスポンスの送信を支援するためである。
サーバートランスポートが受信した、一部が次のように見えるリクエストを考えてみる:
INVITE sip:[email protected] SIP/2.0
Via: SIP/2.0/UDP bobspc.biloxi.com:5060
リクエストは送信元 IP アドレス 192.0.2.4 で受信される。リクエストを上に渡す前に、トランスポートは「received」パラメータを追加するため、リクエストは一部が次のように見えるようになる:
INVITE sip:[email protected] SIP/2.0
Via: SIP/2.0/UDP bobspc.biloxi.com:5060;received=192.0.2.4
次に、サーバートランスポートはリクエストをサーバートランザクションに一致させようとする。これはセクション 17.2.3 で説明される一致規則を使用して行う。一致するサーバートランザクションが見つかった場合、リクエストは処理のためにそのトランザクションに渡される。一致が見つからない場合、リクエストはコアに渡され、コアはそのリクエストの新しいサーバートランザクションを構築することを決定するかもしれない。UAS コアが INVITE に 2xx レスポンスを送信すると、サーバートランザクションが破棄されることに注意。これは、ACK が到着したとき、一致するサーバートランザクションがなく、この規則に基づき ACK が処理される UAS コアに渡されることを意味する。
18.2.2 レスポンスの送信 (Sending Responses)
サーバートランスポートは、レスポンスの送信先を決定するために最上位 Via ヘッダフィールドの値を使用する。以下の手順に従わなければならない (MUST):
o 「sent-protocol」が TCP または SCTP、またはそれら上の TLS のような信頼できるトランスポートプロトコルである場合、トランザクションを作成した元のリクエストの送信元への既存の接続がまだ開いていれば、その接続を使用してレスポンスを送信しなければならない (MUST)。これには、サーバートランスポートがサーバートランザクションとトランスポート接続間の関連付けを維持することが必要である。その接続がもはや開いていない場合、サーバーは「sent-by」値のポート、またはポートが指定されていない場合はそのトランスポートのデフォルトポートを使用して、「received」パラメータ内の IP アドレス (存在する場合) への接続を開くべきである (SHOULD)。その接続試行が失敗した場合、サーバーは [4] のサーバー用の手順を使用して、接続を開いてレスポンスを送信する IP アドレスおよびポートを決定すべきである (SHOULD)。
o それ以外で、Via ヘッダフィールド値に「maddr」パラメータが含まれている場合、レスポンスはそこにリストされたアドレスに、「sent-by」で示されたポート、または存在しない場合はポート 5060 を使用して転送されなければならない (MUST)。アドレスがマルチキャストアドレスの場合、レスポンスは「ttl」パラメータで示された TTL、またはそのパラメータが存在しない場合は TTL 1 を使用して送信されるべきである (SHOULD)。
o それ以外で (信頼できないユニキャストトランスポートの場合)、最上位 Via に「received」パラメータがある場合、レスポンスは「received」パラメータ内のアドレスに、「sent-by」値で示されたポート、または明示的に指定されていない場合はポート 5060 を使用して送信されなければならない (MUST)。これが失敗した場合 (たとえば ICMP「ポート到達不能」レスポンスを引き起こす場合)、[4] のセクション 5 の手順を使用してレスポンスの送信先を決定すべきである (SHOULD)。
o それ以外で、レシーバータグが付いていない場合、レスポンスは「sent-by」値で示されたアドレスに、[4] のセクション 5 の手順を使用して送信されなければならない (MUST)。
18.3 フレーミング (Framing)
メッセージ指向のトランスポート (UDP など) の場合、メッセージに Content-Length ヘッダフィールドがある場合、メッセージボディはそのバイト数を含むとみなされる。トランスポートパケットのボディの終わりを超えて追加のバイトがある場合、それらは破棄されなければならない (MUST)。トランスポートパケットがメッセージボディの終わりの前に終了する場合、これはエラーとみなされる。メッセージがレスポンスである場合、それは破棄されなければならない (MUST)。メッセージがリクエストである場合、要素は 400 (Bad Request) レスポンスを生成すべきである (SHOULD)。メッセージに Content-Length ヘッダフィールドがない場合、メッセージボディはトランスポートパケットの終わりで終了するとみなされる。
ストリーム指向のトランスポート (TCP など) の場合、Content-Length ヘッダフィールドはボディのサイズを示す。Content-Length ヘッダフィールドはストリーム指向トランスポートで使用しなければならない (MUST)。
18.4 エラー処理 (Error Handling)
エラー処理は、メッセージがリクエストであったかレスポンスであったかには依存しない。
トランスポート利用者がメッセージを信頼できないトランスポート経由で送信するよう要求し、結果が ICMP エラーである場合、動作は ICMP エラーの種類に依存する。ホスト、ネットワーク、ポート、またはプロトコル到達不能エラー、あるいはパラメータ問題エラーは、トランスポート層がトランスポート利用者に送信の失敗を通知すべきである (SHOULD)。Source quench および TTL 超過 ICMP エラーは無視されるべきである (SHOULD)。
トランスポート利用者がリクエストを信頼できるトランスポート経由で送信するよう要求し、結果が接続失敗である場合、トランスポート層はトランスポート利用者に送信の失敗を通知すべきである (SHOULD)。