摘要
- RFC 2543 的 branch 主要区分代理分叉出的多个副本;RFC 3261 才把它变成每个请求必须携带、原则上跨时空唯一的事务标识。
z9hG4bK是兼容性标记,不是秘密。看到它,服务器可使用新版紧凑匹配;看不到,就必须保留旧版多字段回退。- 同一次尝试的重传沿用 branch,新目标尝试生成新值;CANCEL 与非 2xx ACK 则在限定场景下故意复用,以便找到原事务而不混同结果。
旧 branch 只回答“这是哪条分叉”
SIP 请求可能依次经过多个代理。每一跳在顶部添加自己的 Via,响应再沿 Via 反向返回。若有状态代理把同一 INVITE 发往三个目标,它还要区分三条外发尝试。
1999 年的 RFC 2543 已定义 branch。分叉代理必须为各个同构副本提供不同值;只产生一个请求的代理却可以不写。所谓唯一,也只要求在这一组副本之内唯一。
因此,旧 branch 还不是一把可以单独索引事务的钥匙。响应匹配同时查看 To、From、Call-ID、CSeq 与第一条 Via 的 branch。它能整理一个代理刚刚制造的分支,却没有向任意接收方承诺“这个值在所有时间和空间都不会用于另一事务”。
协议演进的危险恰在这里:字段仍叫同一个名字,含义却变强。如果没有显式标记,接收方只能猜发送者遵守旧承诺还是新承诺,而猜错的一方正是执行状态变化的一方。
七个字符选择一套法律
2002 年的 RFC 3261 重写了边界。用户代理创建请求时,顶部 Via 必须带 branch。除 CANCEL 和非 2xx ACK 等明示例外外,值必须在该代理发出的所有请求中跨时空唯一。
新版 branch 还必须以 z9hG4bK 开头。七个字符没有编码厂商、日期、用户或路径;它们只是足够古怪,使旧 RFC 2543 实现不大可能偶然生成同样前缀。接收方据此知道,后续 token 声称按 RFC 3261 的唯一性规则构造。
“magic cookie”容易让人联想到凭据或浏览器状态,实际功能更接近兼容集标签。发送方把所采用的规则放进报文本身;接收方在本地检查后决定采用哪套匹配法,无需询问一个中心登记者,也无需根据设备名猜版本。
新匹配仍然不是只看一个字符串
对于带 cookie 的请求,服务器事务按三项匹配:顶部 Via 的 branch、同一 Via 的 sent-by、请求方法;ACK 有专门例外。sent-by 不能省,因为不同客户端仍可能意外或恶意复制相同 branch。
若 branch 缺失或没有 cookie,服务器回到旧兼容路径,比较 Request-URI、To/From tag、Call-ID、CSeq 与顶部 Via。旧流量没有被赋予它从未承诺的唯一性,新流量也无需永远承担多字段推断的成本。
响应侧用顶部 Via branch 加 CSeq method 找客户端事务。方法仍是证据,因为 CANCEL 与原请求共享 branch,却是独立事务。RFC 3665 的呼叫流程清楚显示:每个代理添加自己的 Via 与 branch,响应回来时逐层移除。它标识的是相邻两方之间的一次事务,不是整通电话的名字。
重传必须相同,重试必须不同
有状态代理每试一个新目标,就创建新的客户端事务和新 branch。同一尝试因丢包而重传时,则必须复用原值。这样服务器才能找到既有状态并重发响应,而不是再次执行一次请求。
无状态代理的约束更尖锐。它不保存“刚才见过这包”的表,因而不能每次收到请求就抽一个新随机数,否则一次重传会裂变成多笔事务。RFC 3261 要求它从重传期间不变的报文字段与稳定配置中推导可重复的 branch。这里同时需要唯一性与可复现性,随机并非自动正确。
可选的环路检测还要分清 loop 与 spiral。请求按完全相同的决策输入回到代理,才可能是应阻断的环;若 Request-URI 或影响路由的字段已经改变,它可能是合法的呼叫转移。branch 可以压缩这些输入,但压缩结果只和被纳入的事实一样可靠。
CANCEL 共用指针,却不共用结局
CANCEL 为了找到待处理请求,会复制其 Request-URI、Call-ID、tag、CSeq 数字、Route、顶部 Via 与 branch,只把 CSeq method 改为 CANCEL。无状态代理也因此能作出和原请求相同的转发选择。
但 CANCEL 有自己的事务。服务器对 CANCEL 返回 200,只证明取消请求本身匹配并得到处理;原 INVITE 仍须独立得到 487、早已生成的其他最终响应,或按自身时限结束。RFC 3261 特意拆开 RFC 2543 曾混在一起的两条生命周期。复用 branch 是相关性,不是共同命运。
ACK 在成功处换了责任人
非 2xx 最终响应的 ACK 属于 INVITE 事务。它沿用顶部 Via 和 branch,把方法改成 ACK,由处理失败的事务状态机吸收。
2xx 的情况不同。一次分叉可能产生多个成功对话,每个成功都必须抵达呼叫方。2xx ACK 因而由用户代理核心端到端处理,位于逐跳 INVITE 事务之外,并为这次发送构造新的 Via branch。分界遵循“谁负责可靠交付”,不是形式上的对称。
后来的修补改变状态寿命,没有改写身份
RFC 4320 修正非 INVITE 事务的响应和超时行为。RFC 6026 增加 Accepted 状态与 Timer L,使服务器发送 2xx 后仍能识别并吸收重传 INVITE。
RFC 6026 甚至继续为不带 cookie 的旧式 ACK 保留特殊处理。事务存多久,与收到的消息凭什么匹配到它,是两道不同问题。RFC 5359 提供后来的服务流程实例,证明的是文档化语法,而不是全球部署比例。
标记从未证明身份或授权
任何人都能写出 z9hG4bK。它不认证发送者,不保护完整性,不批准呼叫,也不能保证后半段真的唯一。正确匹配只说明一条消息按规定落进某个本地事务状态。
Dialog 由 Call-ID 与 tag 等对象界定,后续路由、用户身份、授权、媒体协商与服务质量各有自己的证据。这个设计的历史价值正是克制:标记选择一条可执行的解释规则,规则到匹配边界为止,不借机扩张成更大的权力。
来源与证据边界
封闭来源集为 RFC 2543、RFC 3261、RFC 3665、RFC 4320、RFC 5359 与 RFC 6026。它们证明规范演进、匹配规则、示例与修订,不能证明当前厂商实现、部署率、通话质量或实际碰撞频率。
会员简报
档案背景详情
使用相应会员等级登录,即可解锁完整简报与来源注释。
仅限 Strategic Circle
Strategic Circle
所有读者均可浏览。加入并登录后可解锁档案简报。
加入 Strategic Circle仅限 Leadership Alliance
Leadership Alliance
符合条件的 IP 资产所有者和管理层可登录查看 Leadership Alliance 简报。
加入 Leadership Alliance
