19. 通用消息组件
19 通用消息组件
SIP消息的某些组件出现在SIP消息中的不同位置(有时在SIP消息之外),值得单独讨论.
19.1 SIP和SIPS统一资源指标
SIP或SIPS URI标识通信资源.与所有URI一样,SIP和SIPS URI可以放在网页,电子邮件或印刷文献中.它们包含足够的信息来启动和维护与资源的通信会话.
通信资源的示例包括:
o 在线服务的用户
o 出现在多线电话上
o 消息传递系统上的邮箱
o 网关服务上的PSTN号码
o 组织中的一个组(如"销售"或"帮助台")
SIPS URI指定安全地联系资源.这特别意味着,将在UAC和拥有URI的域之间使用TLS.从那里,使用安全通信到达用户,其中特定的安全机制取决于域的策略.如果希望安全地与SIP URI资源通信,那么SIP URI描述的任何资源都可以通过更改方案"升级"为SIPS URI.
19.1.1 SIP和SIPS URI组件
"sip:"和"sips:"方案遵循RFC 2396[5]中的指南.它们使用类似于mailto URL的表单,允许指定SIP请求头字段和SIP消息体.这使得通过在网页或电子邮件中使用URI来指定会话的主题,媒体类型或紧急程度成为可能.SIP或SIPS URI的正式语法见第25节.对于SIP URI,其一般形式为:
sip:user:password@host:port;uri-parameters?headers
SIPS URI的格式相同,只是方案是"SIPS"而不是sip.这些标记及其扩展中的一些标记具有以下含义:
用户:正在寻址的主机上特定资源的标识符.在此上下文中,术语"主机"通常指域.URI的"userinfo"由这个用户字段,密码字段和它们后面的@符号组成.URI的userinfo部分是可选的,当
目标主机没有用户的概念,或者当主机本身是被标识的资源时,目标主机没有用户的概念.如果在SIP或SIPS URI中存在@符号,则用户字段不得为空.
如果被寻址的主机可以处理电话号码,例如互联网电话网关,则RFC 2806[9]中定义的电话订户字段可用于填充用户字段.第19.1.2节中描述的SIP和SIPS URI中的电话用户字段编码有特殊转义规则.
密码:与用户关联的密码.虽然SIP和SIPS URI语法允许显示此字段,但不建议使用此字段,因为以明文形式传递身份验证信息(如URI)已被证明在几乎所有使用过它的情况下都存在安全风险.例如,在该字段中传输管脚号会暴露管脚.
请注意,密码字段只是用户部分的扩展.不希望对字段的密码部分赋予特殊意义的实现可以简单地将"user:password"视为单个字符串.
主机:提供SIP资源的主机.主机部分包含完全限定的域名或数字IPv4或IPv6地址.建议尽可能使用完全限定的域名形式.
端口:发送请求的端口号.
URI参数:影响从URI构造的请求的参数.
URI参数添加在hostport组件之后,并用分号分隔.
URI参数的形式如下:
参数名称"="参数值
即使URI中可能包含任意数量的URI参数,任何给定的参数名称也不能出现多次.
该可扩展机制包括传输,maddr,ttl,用户,方法和lr参数.
transport参数确定用于发送SIP消息的传输机制,如[4]中所述.SIP可以使用任何网络传输协议.为UDP(RFC 768[14]),TCP(RFC 761[15])和SCTP(RFC 2960[16])定义了参数名称.对于SIPS URI,传输参数必须指示可靠传输.
maddr参数指示此用户要联系的服务器地址,覆盖从主机字段派生的任何地址.当存在maddr参数时,URI的端口和传输组件将应用于maddr参数值中指示的地址.[4] 描述传输,maddr和主机端口的正确解释,以获取发送请求的目标地址,端口和传输.
maddr字段已被用作松散源路由的一种简单形式.它允许URI指定一个在到达目的地的途中必须遍历的代理.强烈反对继续以这种方式使用maddr参数(不推荐使用启用该参数的机制).实施应改为使用本文件中描述的路由机制,如有必要,建立预先存在的路由集(见第8.1.1.1节).这提供了一个完整的URI来描述要遍历的节点.
ttl参数确定UDP多播数据包的生存时间值,仅当maddr是多播地址且传输协议为UDP时,才必须使用该参数.例如,指定对的调用[email protected]使用ttl为15的多播到239.255.255.1,将使用以下URI:
sip:[email protected];maddr=239.255.255.1;ttl=15
有效电话用户字符串集是有效用户字符串的子集.用户URI参数用于区分电话号码和看起来像电话号码的用户名.如果用户字符串包含格式化为电话用户的电话号码,则应显示用户参数值"phone".即使没有这个参数,SIP和SIPS URI的接收者也可以将pre-@部分解释为电话号码,如果用户名的名称空间的本地限制允许的话.
可以使用method参数指定从URI构造的SIP请求的方法.
lr参数(如果存在)表示负责此资源的元素实现了本文档中指定的路由机制.此参数将在URI代理中用于Record-Route头字段值,并可能出现在预先存在的路由集中的URI中.
该参数用于实现与实现RFC 2543和rfc2543bis严格路由机制的系统的向后兼容性,直至bis-05.准备基于不包含此参数的URI发送请求的元素可以假定接收元素实现严格路由并重新格式化消息以保留Request-URI中的信息.
由于uri参数机制是可扩展的,SIP元素必须默默地忽略它们不理解的任何uri参数.
Headers:要包含在从URI构造的请求中的头字段.
SIP请求中的头字段可以通过URI中的"?"机制指定.标头名称和值以符号和分隔的hname=hvalue对进行编码.特殊的hname"body"表示关联的hvalue是SIP请求的消息体.
表1根据URI出现的上下文总结了SIP和SIPS URI组件的使用."外部"列描述出现在SIP消息之外任何位置的URI,例如网页或名片上.标有"m"的条目是强制性的,标有"o"的条目是可选的,标有"-"的条目是不允许的.处理URI的元素应该忽略任何不允许的组件(如果存在).第二列指示可选元素(如果不存在)的默认值."--"表示元素不是可选的,或者没有默认值.
Contact 头字段中的URI具有不同的限制,具体取决于头字段出现的上下文.一组适用于建立和维护对话的消息(INVITE及其200(OK)响应).另一种适用于REGISTER和重定向消息(REGISTER,其200(OK)响应以及对任何方法的3xx类响应).
19.1.2 字符转义要求
dialog
reg./redir. Contact/
default Req.-URI To From Contact R-R/Route external
user -- o o o o o o password -- o o o o o o host -- m m m m m m port (1) o - - o o o user-param ip o o o o o o method INVITE - - - - - o maddr-param -- o - - o o o ttl-param 1 o - - o - o transp.-param (2) o - - o o o lr-param -- o - - - o o other-param -- o o o o o o headers -- - - - o - o
(1) :默认端口值取决于传输和方案.sip的默认值为5060:使用UDP,TCP或SCTP.sip:using TLS over TCP和sips:over TCP的默认值为5061.
(2) :默认传输取决于方案.对于sip:,它是UDP.对于sips:,它是TCP.
表1:SIP头字段值,Request-URI和引用的URI组件的使用值和默认值
SIP在定义SIP URI中必须转义的字符集时遵循RFC 2396[5]的要求和指导原则,并使用其"%"十六进制机制进行转义.来自RFC 2396[5]:
任何给定URI组件中实际保留的字符集由该组件定义.通常,如果用转义的US-ASCII编码替换了URI的语义,则该字符将被保留[5].排除的US-ASCII字符(RFC 2396[5]),例如空格和控制字符以及用作URI分隔符的字符,也必须转义.URI不得包含未转义的空格和控制字符.
对于每个组件,有效的BNF扩展集精确地定义了哪些字符可能会显示为未转换.所有其他字符都必须转义.
For example, "@" is not in the set of characters in the user component, so the user "j@s0n" must have at least the @ sign encoded, as in "j%40s0n".
展开第25节中的hname和hvalue标记可以看出,头字段名称和值中的所有URI保留字符都必须转义.
用户组件的电话用户子集有特殊的转义注意事项.电话用户的RFC 2806[9]描述中未保留的字符集包含许多不同语法元素中的字符,这些字符在SIP URI中使用时需要转义.电话用户中出现的任何字符如果没有出现在用户规则的BNF扩展中,则必须转义.
请注意,SIP或SIPS URI的主机组件中不允许字符转义(%字符在其扩展中无效).随着对国际化域名的要求最终确定,这种情况在未来可能会发生变化.当前的实现决不能试图通过将主机组件中接收到的转义字符视为其未转义对应字符的字面等价物来提高健壮性.满足IDN要求所需的行为可能会明显不同.
19.1.3 示例SIP和SIPS URI
sip:[email protected] sip:alice:[email protected];transport=tcp sips:[email protected]?subject=project%20x&priority=urgent sip:+1-212-555-1212:[email protected];user=phone sips:[email protected] sip:[email protected] sip:atlanta.com;method=REGISTER?to=alice%40atlanta.com sip:alice;day=[email protected]
上面最后一个示例URI的用户字段值为"alice;day=周二".上面定义的转义规则允许分号在此字段中显示为非转义.就本协议而言,该字段是不透明的.该值的结构仅对负责资源的SIP元素有用.
19.1.4 URI比较
本规范中的某些操作需要确定两个SIP或SIPS URI是否等效.在本规范中,REGISTER者需要在REGISTER request中比较联系人URI中的绑定(参见第10.3节).根据以下规则比较SIP和SIPS URI是否相等:
o SIP和SIPS URI从来都不是等价的.
o SIP和SIPS URI的用户信息比较区分大小写.这包括包含密码或格式化为电话订户的用户信息.除非另有明确定义,否则URI的所有其他组件的比较不区分大小写.
o 在比较SIP和SIPS URI时,参数和头字段的顺序并不重要.
o 除"保留"集合中的字符(参见RFC 2396[5])之外的其他字符等效于其"%"十六进制编码.
o 作为主机名DNS查找结果的IP地址与该主机名不匹配.
o 要使两个URI相等,用户,密码,主机和端口组件必须匹配.
省略用户组件的URI与包含用户组件的URI不匹配.省略密码组件的URI与包含密码组件的URI不匹配.
忽略具有默认值的任何组件的URI将不会将显式包含该组件的URI与其默认值匹配.例如,省略可选端口组件的URI将与显式声明端口5060的URI不匹配.传输参数,ttl参数,用户参数和方法组件也是如此.
定义sip:user@host不等同于sip:user@host:5060是对RFC 2543的更改.当从URI派生地址时,需要从等效URI获得等效地址.URI sip:user@host:5060将始终解析为端口5060.URI sip:user@host可通过[4]中详述的DNS SRV机制解析到其他端口.
o URI参数组件的比较如下所示:
- 两个uri中出现的任何uri参数都必须匹配.
- 仅出现在一个uri中的用户,ttl或方法uri参数永远不匹配,即使它包含默认值.
- 包含maddr参数的URI与不包含maddr参数的URI不匹配.
- 比较uri时,将忽略仅在一个uri中出现的所有其他uri参数.
o URI头组件永远不会被忽略.任何当前标头组件必须同时存在于URI和match中,URI才能匹配.第20节中为每个头字段定义了匹配规则.
以下每组中的URI是等效的:
sip:%[email protected];transport=TCP sip:[email protected];Transport=tcp
sip:[email protected] sip:[email protected];newparam=5 sip:[email protected];security=on
sip:biloxi.com;transport=tcp;method=REGISTER?to=sip:bob%40biloxi.com sip:biloxi.com;method=REGISTER;transport=tcp?to=sip:bob%40biloxi.com
sip:[email protected]?subject=project%20x&priority=urgent sip:[email protected]?priority=urgent&subject=project%20x
以下每个集合中的URI不等效:
SIP:[email protected];Transport=udp (different usernames) sip:[email protected];Transport=UDP
sip:[email protected] (can resolve to different ports) sip:[email protected]:5060
sip:[email protected] (can resolve to different transports) sip:[email protected];transport=udp
sip:[email protected] (can resolve to different port and transports) sip:[email protected]:6000;transport=tcp
sip:[email protected] (different header component) sip:[email protected]?Subject=next%20meeting
sip:[email protected] (even though that's what sip:[email protected] phone21.boxesbybob.com resolves to)
请注意,相等不是可传递的:
o 抿:[email protected]及sip:[email protected];security=on是等效的
o 抿:[email protected]及sip:[email protected];安全=关闭是等效的
o 抿:[email protected];安全性=on和sip:[email protected];security=off不是等效的
19.1.5 从URI生成请求
直接从URI生成请求时,实现需要小心.来自名片,网页甚至协议内部源(如REGISTER联系人)的URI可能包含不适当的头字段或正文部分.
实现必须在所形成请求的Request-URI中包含任何提供的传输,maddr,ttl或用户参数.如果URI包含方法参数,则其值必须用作请求的方法.方法参数不能放在Request-URI中.消息的Request-URI中必须放置未知的URI参数.
实现应该将URI中存在的任何头或主体部分视为希望将它们包含在消息中,并选择在每个组件的基础上满足请求.
实现不应该遵守这些明显危险的头字段:From,Call-ID,CSeq,Via 和Record-Route.
实现不应遵守任何请求的路由头字段值,以便在恶意攻击中不被用作无意中的代理.
实现不应接受包含头字段的请求,这可能会导致它错误地公布其位置或功能.这些包括:接受,接受编码,接受语言,允许,联系人(在其对话使用中),组织,支持和用户代理.
实现应验证任何请求的描述性头字段的准确性,包括:Content-Disposition,Content-Encoding,Content-Language,Content-Length,Content-Type,日期,Mime版本和时间戳.
如果从给定URI构造消息形成的请求不是有效的SIP请求,则URI无效.实现不能继续发送请求.相反,由于发生上下文中的URI无效,它应该继续执行操作过程.
构造的请求可能在许多方面无效.这些包括但不限于头字段中的语法错误,URI参数的无效组合或消息体的错误描述.
发送由给定URI形成的请求可能需要实现无法使用的功能.例如,URI可能表示使用了未实现的传输或扩展.实现应该拒绝发送这些请求,而不是修改它们以匹配它们的功能.实现不能发送需要其不支持的扩展的请求.
例如,这样的请求可以通过存在Require头参数或具有未知或显式不支持的值的方法URI参数来形成.
19.1.6 关联SIPURI和tel URL
当tel URL(RFC 2806[9])转换为SIP或SIPS URI时,tel URL的整个电话订户部分(包括任何参数)被放入SIP或SIPS URI的userinfo部分.
Thus, tel:+358-555-1234567;postd=pp22 becomes
sip:+358-555-1234567;[email protected];user=phone
or sips:+358-555-1234567;postd=[email protected];user=phone
not sip:[email protected];postd=pp22;user=phone
或
sips:[email protected];postd=pp22;user=phone
通常,以这种方式转换为SIP或SIPS URI的等效"tel"URL可能不会产生等效的SIP或SIPS URI.SIP和SIPS URI的userinfo作为区分大小写的字符串进行比较.tel URL不区分大小写部分的差异和tel URL参数的重新排序不会影响tel URL的等效性,但会影响由它们形成的SIPURI的等效性.
例如
tel:+358-555-1234567;postd=pp22
tel:+358-555-1234567;POSTD=PP22
是等价的,而
sip:+358-555-1234567;[email protected];user=phone
sip:+358-555-1234567;[email protected];user=phone
不是.
同样地
tel:+358-555-1234567;postd=pp22;isub=1411
tel:+358-555-1234567;isub=1411;postd=pp22
是等价的,而
sip:+358-555-1234567;postd=pp22;[email protected];user=phone
sip:+358-555-1234567;isub=1411;[email protected];user=phone
不是.
为了缓解此问题,构造要放置在SIP或SIPS URI的userinfo部分的电话用户字段的元素应将电话用户的任何不区分大小写的部分折叠为小写,并按参数名称按词汇顺序排列电话用户参数,isdn子地址和后拨除外,先发生,然后按顺序发生.(tel URL的所有组件(未来扩展参数除外)都定义为不区分大小写进行比较.)
根据这一建议,双方
tel:+358-555-1234567;postd=pp22
tel:+358-555-1234567;POSTD=PP22
成为
sip:+358-555-1234567;[email protected];user=phone
两者都有
tel:+358-555-1234567;tsp=a.b;phone-context=5
tel:+358-555-1234567;phone-context=5;tsp=a.b
成为
sip:+358-555-1234567;phone-context=5;[email protected];user=phone
19.2 OPTIONS标签
OPTIONS标记是用于在SIP中指定新OPTIONS(扩展)的唯一标识符.这些标签用于Require(第20.32节),Proxy Require(第20.29节),Supported(第20.37节)和Unsupported(第20.40节)头字段.请注意,这些OPTIONS在option tag=token表单中的头字段中显示为参数(有关token的定义,请参阅第25节).
OPTIONS标记在标准跟踪RFC中定义.这与过去的做法不同,旨在确保多供应商的持续互操作性(见第20.32节和第20.37节的讨论).OPTIONS标记的IANAREGISTER表用于确保易于引用.
19.3 标签
"tag"参数用于SIP消息的To和From头字段.它作为识别对话的一般机制,是Call-ID和两个标签的组合,每个标签来自对话中的每个参与者.当UA在对话外部发送请求时,它仅包含From标记,提供对话ID的"一半".对话通过响应完成,每个响应在To头字段中提供第二部分.SIP请求的分叉意味着可以从单个请求建立多个对话.这也解释了双面对话标识符的必要性;如果没有收件人的贡献,发起者无法消除从单个请求建立的多个对话的歧义.
当UA生成用于插入请求或响应的标记时,该标记必须是全局唯一的,并且具有至少32位随机性的加密随机性.此选择要求的一个特性是,UA将在INVITE的From标头中放置与在同一INVITE响应的To标头中放置不同的标记.这是UAINVITE自己参加会话所必需的,这是PSTN网关中呼叫"发夹"的常见情况.类似地,不同呼叫的两个INVITE将具有不同的To标记,不同呼叫的两个响应将具有不同的To标记.
除了对全局唯一性的要求外,生成标记的算法是特定于实现的.标签在容错系统中很有用,在容错系统中,对话在发生故障后将在备用服务器上恢复.UAS可以这样选择标记:备份可以将请求识别为故障服务器上对话的一部分,从而确定它应该尝试恢复对话以及与之相关的任何其他状态.