前言
OpenSIPS基本上只是一个基于事务的有状态代理,没有任何内置的对话支持。有许多特性、服务实际上需要感知对话的,例如在对话创建阶段存储信息,在整个对话存在期间将使用这些信息。
最迫切的例子是在处理对话的INVITE请求(re-INVITE)时的NAT遍历。在处理初始INVITE时,代理会检测主叫或被叫是否在某些NAT网络背后,并修复信令和媒体部分。因为不是所有的检测机制都可用于对话请求(如usrloc),所以为了能够相应地修复顺序请求,代理必须记住原始请求是NAT处理的。还有许多其他应用场景的情况,感知对话可以修复问题或帮助处理。
解决方案是在路由集合中存储额外的与对话相关的信息(Record-Route/Route headers),headers在相继的所有请求中展示。因此,添加到Record-Route头部的任何信息都将在Route头部(对应于代理地址)中找到(没有方向依赖性)。
函数:loose_route()
该函数对包含路由集的SIP请求执行路由。
这个函数的名称有一点迷惑人,因为这个函数还会对“strict router” 格式的请求进行路由。
此函数通常用于处理在对话中(in-dialog)的请求,如ACK、BYE、reINVITE等。尽管如此,对话外请求也可以有一个“预加载的路由集”,并且可以使用loose_route路由。它还负责严格路由器和松散路由器之间的转换。
loose_route()函数的作用是分析请求中的Route头部。如果没有Route头部,则函数返回FALSE,并且应该通过RURI以独占方式进行路由。如果找到Route头部,则函数返回TRUE,并按照RFC 3261第16.12节所述进行操作。唯一的例外是具有预加载Route报头的请求(初始请求,携带Route头):如果只有一个Route头部指示本地代理,则Route头部被删除,函数返回FALSE。
该函数能够自动检测它处理的是“严格”还是“松散”路由脚本(差异之处是SIP路径在RURI和Route 头部之间的存储方式)。为了区分这两种路由脚本,OpenSIPS必须确定哪个SIP URI持有其地址/域-RURI(如果是严格路由情况)或顶级路由URI(如果是松散路由情况)。为了检查SIP URI是否包含其地址/主机,OpenSIPS根据侦听IP/接口(作为静态组件)和“domain”的模块/表中列出的主机(作为动态组件)以检查主机URI。
如果存在一个Route头部,但出现了其他解析错误(比如解析TO标头以获取TAG),该函数也会返回FALSE。
确保你的loose_routing函数不能被攻击者用来绕过代理授权。
loose_routing主题非常复杂。有关详细信息请参见RFC3261,查找“route set”的关键词是阅读这个综合性RFC的一个很好的起点。