http://akalius.javaeye.com/blog/174520
http://blog.youkuaiyun.com/dingpeng1978/archive/2008/07/15/2652380.aspx
http://www.tech-invite.com/Ti-sip-dialog.html
http://blog.youkuaiyun.com/dingpeng1978/archive/2009/07/23/4374050.aspx
From: 如果一个SIP消息中没有Contact或者Record-Route头域,那么callee就会根据From头域产生后续的Request。比如:如果 Alice打一个电话给Bob,From头域的内容是 From:Alice<sip:alice@example.org>。那么Bob打给Alice时就会使用 sip:alice@example.org作为To头域和Request-URI头域的内容。
Contact: 后续Request将根据Contact头域的内容决定目的地的地址,同时将Contact头域的内容放到Request-URI中。它还可以用来指示没 有在Record-Route头域中记录的Proxies的地址。同时它还可以被用在Redirect servers和REGISTER requests 和responses。
Route:Route和Via字段正好相反,它被用来作为Request消息的路由。当一个Proxy Server收到一个Request消息时,会检查Route字段的第一个地址是否等于自己,如果是,它将从Route字段中删去自己的地址信息,并将消 息转发到Route字段中指定的下个地址;如果Route字段为空,则转发到Request URI指定的地址。
Record-Route/Route: Record-Route头域一般是被proxies插入到request中的,这样后续的Request如何有着和前面一样的call-id就会被路由 到这些proxies。它也会被User Agent作为发送后续request的依据。这套机制很像source-route,Record-Route头域的信息被复制到Route头域中。并 且Request-URI头域会被设置为第一个Route头域的内容。
Record-Route字段实际上用于帮助UA建立Route Set,当UA发送Request时会用Route Set来设置上面提到的Route字段。当一个Request消息经过Proxy Server时,如果该Proxy Server希望通知UA相关的后续消息都能通过它来转发,此时它就会在消息中添加Record-Route字段,内容为自己的地址信息。当UAS发送 Resposne消息时它将复制Request中的Record-Route字段,而UAC在Response消息中检测到Record-Route字段 时,它就会用该字段的路由信息更新自己的Route Set。
Via: Via头域是被服务器插入request中,用来检查路由环的,并且可以使response根据via找到返回的路。它不会对未来的request 或者是response造成影响。
当UAC发起一个SIP Request消息时,消息经过的每一跳(包含发起方)都会在SIP消息中增加一个Via字段,内容为自己的地址信息,表示此消息通过此地址发往下一跳。
为什么要增加Via字段来记录Request消息经过的地址呢?实际上这个地址信息将被作为Request消息的Response消息的路由,Response将根据Via字段中记录的地址逐级返回,直到回到Request的发起方。
总的来说,如果有Route,request就应该根据Route发送,如果没有就根据Contact头域发送,如果连Contact都没有,就根据From头域发送。
IMS协议中增加的路由相关字段
Service-Route:Service-Route在S-CSCF向UE发送REGISTER成功应答时设置,作用和Record- Route类似,用于帮助UE建立Route Set,这样UE注册后的消息(例如INVITE)通过设置Route字段无需经过I-CSCF可直接送达S-CSCF。
Path :只能用于用户向注册服务器发送的Register请求。
1如果某代理服务器希望发往用户的任何后续请求仍能经过自己,就可以在Register请求中插入一个Path字段并赋值为自身的URI。
2如果要求拓扑隐藏,经过I-CSCF的时候要把这个 I 添加到Path字段中
在P-CSCF转发Register请求给S-CSCF时插入,S-CSCF通过 Path字段保存一个UE所使用的P-CSCF地址,这样当S-CSCF需要主动向UE发送消息时(例如网络端发起的De-register),S- CSCF就知道实际应该发往的P-CSCF地址了
To 字段总是包含被呼叫方的地址(通过sip代理时是公用地址,点对点时是真实ip),要注意的是区别该标题头 和sip消息请求行中的Request-URI。To在信令路径中不会被代理改变,然而Request-URI包含的是信令路径中下一跳的地址,因此在路 途中被每个代理改变。
3、Loose Router首先会检查Request URI是否为自己:如果不是,则不作处理;如果是,则取出Route字段的最后一个地址作为Request URI地址,并从Route字段中删去最后一个地址。
4、Loose Router其次会检查下一跳是否为Strict Router:如果不是,则不作处理;如果是,则将Request URI添加为Route的最后一个字段,并用下一跳Strict Router的地址更新Request URI。
可以看到步骤3、4其实是Loose Router为了兼容Strict Router而做的额外工作。
前面都是准备工作,下面该进行真正的路由了。如果还有Route头域,则Proxy会把消息路由给该头域中的URI,否则就路由给request-URI。
Contact: sip:caller@u1.example.com
INVITE sip:callee@domain.com SIP/2.0
Contact: sip:caller@u1.example.com
Record-Route: <sip:p1.example.com;lr>
Contact: sip:caller@u1.example.com
Record-Route: <sip:p2.domain.com;lr>
Record-Route: <sip:p1.example.com;lr>
Contact: sip:callee@u2.domain.com
Record-Route: <sip:p2.domain.com;lr>
Record-Route: <sip:p1.example.com;lr>
Route: <sip:p1.example.com;lr>,<sip:p2.domain.com;lr>
可以看到,BYE的Route头域正是主机的路由集构造来的。
Route: <sip:p2.domain.com;lr>
Contact: sip:caller@u1.example.com
Record-Route: <sip:p4.domain.com;lr>
Record-Route: <sip:p3.middle.com>
Record-Route: <sip:p2.example.com;lr>
Record-Route: <sip:p1.example.com;lr>
Route: <sip:p4.domain.com;lr>
Route: <sip:p3.middle.com>
Route: <sip:p2.example.com;lr>
Route: <sip:p1.example.com;lr>
BYE sip:p3.middle.com SIP/2.0
Route: <sip:p2.example.com;lr>
Route: <sip:p1.example.com;lr>
Route: <sip:caller@u1.example.com>
Route: <sip:p1.example.com;lr>
Route: <sip:caller@u1.example.com>
Route: <sip:p1.example.com;lr>
然后,P2发现自己不负责域u1.example.com,第一个Route中的URI也不是自己的,因此将消息转发给该URI,也就是P1。
BYE sip:caller@u1.example.com SIP/2.0