要約
- RFC 2543のbranchは主にforkした複製を区別する印だった。RFC 3261はそれを必須とし、原則として時空間で一意なtransaction識別子へ変えた。
z9hG4bKは認証情報ではなく互換性マーカーである。存在すれば新しい照合を、なければ複数fieldを使う旧手順を選べる。- 同じ試行の再送はbranchを保ち、新しい宛先への試行は別の値を持つ。CANCELと非2xx ACKだけは相関のため意図的に再利用する。
かつてbranchが区別したのはforkの内側だけだった
SIP requestは複数のproxyを通る。各hopは先頭にViaを積み、responseはその層を逆順にたどる。stateful proxyが一つのINVITEを複数の宛先へ分ければ、返ってきた結果を外向きの試行ごとに整理しなければならない。
1999年の RFC 2543 は、この用途に branch を置いた。forkするproxyには必須だったが、一方向だけへ送るproxyでは任意だった。一意性も、同じforkで作られたisomorphic requestの集合内で足りた。
responseの照合にはTo、From、Call-ID、CSeqと最初のVia branchを組み合わせた。つまりbranchは便利な枝札ではあっても、受信した任意の値がtransaction全体で一意だと宣言する証拠ではなかった。
同じfield名のまま意味だけを強くすると、旧実装と新実装が交わる場所で推測が必要になる。送信側は自分が守った規則を知るが、推測を誤ってstateを変更するのは受信側である。
7文字が適用すべき規則を示した
RFC 3261 は2002年、UACが作るrequestの先頭Viaにbranchを必須とした。CANCELと非2xx responseへのACKという限定例外を除き、その値はUAが送るrequestの間で時空間にわたり一意でなければならない。
そのbranchは z9hG4bK で始まる。文字列は時刻、vendor、user、経路を符号化しない。RFC 2543実装が偶然選ぶには十分に不自然な7文字として、新しい生成規則を示す。
magic cookieという呼び名に反して、秘密でもchallengeでもない。解釈が変わったfieldの中に、互換集合を明記したのである。receiverは相手の所属や製品名を信じず、messageを見てlocalに規則を選べる。
新方式でも一つのtokenだけを信じない
cookie付きrequestをserver transactionへ照合する条件は、先頭Viaのbranch、その sent-by、methodである。ACKには定義済みの例外がある。別clientが誤って、あるいは故意に同じbranchを使う可能性があるため、sent-byも残る。
cookieがなければ、Request-URI、To/From tag、Call-ID、CSeq、Viaを使うRFC 2543互換手順へ戻る。旧branchに後から強い約束を付け足さず、新branchを古い曖昧さへ引き戻さない設計である。
response側はbranchとCSeq methodを使う。CANCELは対象requestとbranchを共有しながら別transactionなので、methodが両者を分ける。RFC 3665 のcall flowでは、各proxyがViaとbranchを追加し、responseが戻る際に自分の層を外す。branchはcall全体ではなく、隣接するclientとserverのtransactionを指す。
再送は同じ値、別の試行は別の値
stateful proxyが別のtargetを試すたび、新しいclient transactionとbranchが生まれる。一方、同じ試行の再送は値を変えてはならない。既存stateに着地してresponseを再送させるためであり、新しい処理を起動するためではない。
stateless proxyには記憶がない。受信のたび乱数を振れば、同じrequestの再送を別transactionへ割ってしまう。そのためRFC 3261は、再送で変わらないmessage fieldとtime-invariantな設定から安定部分を導くよう求める。一意性だけでなく再現性も必要である。
loop検出を行うproxyは、処理判断に影響する入力をbranchの別部分へ反映できる。同じ条件で戻るrequestはloopかもしれないが、Request-URIなどが変わった再訪は正当なspiralになり得る。hashは判断材料を圧縮するだけで、入れなかった事実まで証明しない。
CANCELは対象を共有しても完了を共有しない
CANCELは対象requestのRequest-URI、Call-ID、tag、CSeq番号、Route、先頭Viaとbranchを写し、CSeq methodだけをCANCELにする。これでstateless proxyも元requestと同じ経路判断を再現できる。
しかしCANCEL自身は独立transactionである。CANCELへの200は取消requestを処理したことを示すが、元のINVITEには487、既に決まった別のfinal response、または固有のtimeoutが残る。RFC 3261はRFC 2543で混在していた二つの終了を分離した。同じ参照先は同じ結果を意味しない。
ACKの所属は2xxを境に変わる
非2xx final responseへのACKはINVITE transactionに含まれる。INVITEのViaとbranchを再利用し、methodをACKへ変え、失敗を扱ったtransaction state machineが吸収する。
2xxではfork先が複数受諾する場合がある。すべての成功をUACへ届けるため、ACKはproxyごとのINVITE transaction外でUA coreがend-to-endに扱い、新しいVia branchを構成する。成功と失敗の非対称性は、信頼性の責任主体が違うために生じた。
後の修正は保持時間を変え、識別規則を残した
RFC 4320 はnon-INVITE transactionのresponseとtimeoutを修正した。RFC 6026 はAccepted stateとTimer Lを加え、2xx送信後のINVITE再送を既存stateで吸収できるようにした。
RFC 6026はcookieを持たない旧ACKにも特別手順を残す。stateをいつ捨てるかと、messageを何に照合するかは別問題だからである。RFC 5359 のservice exampleは後代の記述例であって、世界の実装率を測ったものではない。
markerが証明しなかったこと
z9hG4bK は誰でも書ける。senderを認証せず、callを許可せず、完全性を守らず、後続部分の真の一意性も監査しない。transaction matchが正しくても、dialog、user identity、route全体、media negotiation、通話品質は別の証拠を要する。
歴史的な強さは、この狭さにある。senderは従った規則を可視化し、receiverは自分がstateを動かす境界で検証する。markerは解釈を選ぶが、callに対する権力を得ない。
出典と証拠の限界
閉じた出典集合は RFC 2543、RFC 3261、RFC 3665、RFC 4320、RFC 5359、RFC 6026 である。規則、例、変更履歴は示すが、現在の製品準拠率、deployment share、通話品質、collision頻度は示さない。
会員向け解説
プロフィールの詳細
適切な会員レベルでログインすると、解説全文と出典メモをご覧いただけます。
Strategic Circle 限定
Strategic Circle
すべての読者に公開されています。参加してログインすると プロフィール解説 を閲覧できます。
Strategic Circle に参加Leadership Alliance 会員限定
Leadership Alliance
対象となる IP 資産の所有者・管理者向けです。ログインすると Leadership Alliance の解説を閲覧できます。
Leadership Alliance に参加
