常见消息部件(Common Message Components)

在SIP消息中,有一些很长用的部件。(甚至在SIP消息外,这些部件也存在)。这些部件值得我们单独讨论一下。

 

1.   SIP和SIPS统一资源标记

SIP或者SIPS 的URI用来标记一个通讯用的资源。就像其他所有的URI一样,SIP和SIPS URI可以放在网页上,email消息里,或者打印出来的名片上等等。在这些URI里边包含了足够的信息来发起和维持到这个资源的一个通讯会话。

 

一个通讯资源的例子包含下列内容:

 

Ø  一个在线服务的用户

Ø  一个多线电话

Ø  消息系统中的邮箱

Ø  网关服务的PSTN电话号码

Ø  一个组织中的一个部门(比如“销售”,或者“helpdesk”)

 

SIPS URI定义了对资源的访问是安全的。这就意味着,特别是,在UAC和这个资源的主机之间的通讯是基于TLS的。从资源的主机到用户之间的通讯是加密安全的,这个安全机制是依赖于主机的实现的。任何用SIP URI描述的资源,只要想通过加密的形式进行通讯,都可以通过简单改变一下资源描述符就可以升级成为一个SIPS URI。

 

1.1.     SIP和SIPS部件

“sip:”和“sips:”描述符是遵循RFC2396的规范定义的。他们使用类似mailto URL的格式定义,允许有SIP请求头域字段和SIP消息体的规范。这使得在网页上或者email中,可以用URI来初始化一个会话,这个会话有特定的主题,媒体类别,紧急类型。这个SIP或者SIPS URI的格式规范。一个SIP URI的通常格式是这样的:

sip: user:password@host:port;uri-parameters?headers

这个和SIPS URI的格式是相同的,只是SIPS用“sips”来代替sip。这些符号和符号的扩展,具有下列意义:

 

user:这是在主机的特定资源地址。主机(host)在这里通常指的是一个域名。URI中的“userinfo”包含了这个用户域,口令域,并且包含其后的一个@URI的用户信息部分是可选的,或者说是可以没有的;当目的主机没有用户的概念或者主机本身就是资源的目标,那么这个URI的用户信息部分就是可以没有的。如果在SIP或者SIPS,那么用户部分必须不能为空的。如果主机部分可以处理电话号码地址,比如说是一个internet电话网关,那么根据RFC2806定义的电话号码域应当出现在用户信息部分。在1.2节有关于在SIP或者SIPS URI中的电话号码描述域的额外说明 URI中有@

 

password:password字段是和用户相关的。SIP或者SIPS URI语法允许增加password这个字段,这种用法我们是不推荐的,因为把身份认证信息放在明码表示的地方(比如URI)会带来很大的安全风险。比如,通讯层在这个字段用了一个PIN码,那么就会暴露这个PIN码而带来安全隐患。

 

注意密码字段只是一个用户信息扩展的一部分。实现上并没有标记一个特别的密码部分,可以简单的把“user:password”当作一个简单的用户串来对待。

 

host:主机提供了SIP资源。host部分包含了一个完整的主机名字或者IPV4/IPV6的地址。我们强烈建议如果可能,就使用完整格式的主机名字。

 

port:端口号是请求将被送出的端口。

 

URI 参数:请求将使用这个URI来构造。

 

URI参数在hostport部件之后增加,用分号分开。

URI参数有如下格式:参数名=参数值

 

虽然在同一个URI中允许有任意多个URI的参数,但是同一个参数名只能出现1次。

 

这个扩展机制包括了transport、maddr、ttl、user、method和lr参数

 

transport参数决定发送SIP消息的通讯机制。SIP可以使用任何网络通讯协议。参数名字是为UDP(RFC 768)、TCP(RFC 761)和SCTP(RFC2960)定义的。对于一个SIPS URI,transport参数必须指向一个可靠的通讯协议。

 

maddr参数指明了联系这个用户的服务器的地址,它会覆盖在host域中的地址。当给定了一个maddr参数,URI中的port和transport部件将会在maddr中指出。描述了正确的transport、maddr和hostport规范,用于获得发送请求到目的地所需要的目的地址、端口和通讯协议。

 

maddr字段用作简单的去掉源路由的方法来使用的。它允许一个URI指定一个必须经过的proxy来到达目的地。我们强烈建议不要把maddr参数用于这个目的(我们反对把maddr用于这个机制)。在实现上应当使用本文中描述的Route机制,如果有需要,则建立一个pre-existing(预先设置的)路由集合。它提供了一个完整的URI来描述需要经过的节点。

 

ttl参数决定了UDP多点报文的生存周期,并且只能用于maddr是一个多点地址并且通讯协议是UDP的情况。例如,为了指定一个到alice@atlanta.com的呼叫,使用多点广播到239.255.255.1,并且ttl15,那么应该使用下边的一个URI

 

sip:alice@atlanta.com;maddr=239.255.255.1;ttl=15

 

有效的电话描述(telephone-subscriber)的字串一个集合是有效的用户字串的子集。我们用用户URI参数来区别电话号码和用户名(长得像电话号码的用户名)。如果用户串使用了电话号码描述的字串,用户参数值“phone”应当增加。即使没有这个参数,如果本地用户名的命名限制机制允许的情况下,SIP和SIPSURI的接受方也可以把这个@以前的部分解释为电话号码。

 

从URI中构建SIP请求所需要的method域,可以由method参数指定。

 

如果指定了lr参数,就标志着这个资源的拥有者是根据本规范来实现的路由机制。这个参数会用于proxy放在Record-Route头域的URI中,也可以出现在pre-existing(预先设置)的路由集合中。

 

这个参数是用来和RFC2543定义中的严格路由机制向后兼容所使用的,并且rfc2543中的bis 改变为bis-05。如果一个元素准备发送一个基于没有包含这个参数的URI请求,那么我们可以假定这个请求的接受方是根据严格路由的规范实现的,并且会重新规格化这个消息来保护在Request-URI中的内容。

 

由于URI参数机制是可以扩展的,SIP元素应当悄悄跳过那些不认识的uri参数。

 

Headers:头域是从给定URI创造的请求的头域部分。

在SIP请求中的头域可以在URI中用“?”来给出。头域名(hname)和头域值(hvalue)都是用&符号间隔的头域名=头域值的格式。特定的头域名“body”的头域值就是SIP请求的消息体。

 

表1总结了在URI的不同情况下SIP和SIPS URI的部件用法。扩展的列描述了在SIP消息中的URI,例如在网页上或者名片上的情况。项目中的“m”是强制必须的意思,“o”是可选的,“-”是不允许的。处理URI的元素应当忽略掉URI中出现的任何不允许的部件。在表格中的第二列是如果该元素不存在的时候的缺省值。“—”表示本元素不是可选的,或者没有缺省值的意思。

 

在Contact头域中的URI在头域出现的不同地方,有着不同的约束。一个是在消息建立和维持一个对话的时候(INVITE请求以及它对应的200(OK)应答),一个是在注册和转发消息的时候(REGISTER,以及对应的200(ok)应答,以及给任何方法的3xx系列的应答)

1.2.     CharacterEscaping Requirements(字符转码要求)

 

default

Req-URI

To

From

reg./redir.

Contact

dialog

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):缺省的通讯端口是依赖于通讯协议的。对于使用UDP,TCP,SCTP的sip来说,是5060,对于使用基于TCP的TLS来说,是5061。

(2) 缺省的通讯协议是和sip/sips相关的,对于sip来说,是UDP,对于sips来说,是TCP。

 

表1:对于SIP头域值,Request-URI及其引用的使用和缺省值。

 

基于RFC2396的要求和指引,当需要把字符串封装到SIP URI的时候,使用“‘%’HEX HEX”机制来进行转码。根据RFC2396:

 

任何指定URI部件保留的字符集都是由这个部件定义的。通常,如果URI的语义由于组成字符被它的US-ACII编码的escape码替代而改变的时候,这个字符就是保留字符。除了USASCII字符(RFC2396[5])之外,比如空格和控制字符,以及URI所使用的分隔符,必须进行转码。URI必须不能包含任何未经转码的空白和控制字符。

 

对于每一个部件来说,由BNF扩展的合法字符集合规定了那些字符是可以不经转码的。其他字符都必须经过转码。

 

比如,“@”不是user部件的字符集中的字符,所以,userj@sOn必须把@符号进行编码,成为”j%40sOn”

 

在以后章节中将描述,hname和hvalue的符号展示了,在URI的保留字符,在头域名和头域值中所有需要被转码的字符集合。

 

user部件的电话描述(telephone-subscriber)部分由特别的转码考虑。在RFC2806关于电话描述部分中未被保留的字符集,由很多字符组成,他们在SIP URI中的不同语法部分的时候,都需要做转码。在电话描述中出现的任何字符,只要不在BNF针对user部分的扩展规则中出现的,都需要做转码。

 

注意在SIP或者SIPS URI中,host部分不允许做字符的转码(%不在它的扩展部分中)。在以后的Inernationalized DomainNames完成以后,这个限制可能就会改了。当前实现中不允许把在host部分收到的转码字符进行转码处理。因为这个转码处理和IDN要求的处理不一样。

 

1.3.     SIP和SIPS URI例子

sip:alice@atlanta.com

sip:alice:secretword@atlanta.com;transport=tcp

sip:alice@atlanta.com?subject=project%20x&priority=urgent

sip:+1-212-555-1212:1234@gateway.com;user=phone

sips:1212@gateway.com

sip:alice@192.0.2.4

sip:atlanta.com;method=REGISTER?to=alice%40atlanta.com

sip:alice;day=Tuesday@atlanta.com

 

最后一个URI例子有一个user域“alice;day=Tuesday”。上边定义的转码规则中允许“;”在这个字段中不进行转码。在本协议的设计概念中,这个字段是不透明的。这个字段的值只对负责这个资源的SIP元素有用。

 

1.4.     URI比较

在本规范中,部分操作需要比较两个SIP或者SIPS URI是否相等。比如,在这个规范中,注册服务器需要比较在REGISTER 请求中绑定的Contact URI。SIP和SIPS URI根据如下步骤进行比较:

 

Ø  SIP和SIPS URI永远不等。

Ø  SIP/SIPS URI的userinfo是大小写敏感的。这包括了含有password或者按照电话描述格式的userinfo的比较。对于URI的其他部分的比较,除了有特别指出之外,都是大小写不敏感的。

Ø  参数的顺序和头域的顺序对于比较SIP/SIPS URI不起作用。

Ø  在保留字符集之外的字符(参见RFC2396),等同于他们的“‘%’ HEX HEX”格式。

Ø  IP地址就算是等同于通过DNS查找到的主机名对应的IP地址,IP地址也不能和主机名等同。

Ø  两个URI如果相同,那么user、password、host和port部分必须相同。

 

有user部分的URI和没有user部分的URI是不相等的。有password部分的URI和没有password部分的URI也是不同的。

 

一个不带可选部件的URI和带了这些部件但是值是缺省值的URI是不等的。例如,如果一个URI省略了port部件,并不等于一个定义了5060port部件的URI。同样的规则适用域transport-参数、ttl-参数、user-参数和method部件等等。

 

定义sip:user@host,和定义sip:user@host:5060(根据RFC2543的变体)不相等。当从URI中取得地址的时候,相同的URI可以取得相同的地址。sip:user@host:5060始终可以得到端口5060。URI: sip:user@host根据所定义的DNS SRV机制,可能可以得出其他的端口来。

 

o URI uri参数部件按照如下规则进行比较

-         任何在两个URI中出现的uri参数都必须一样

-         user、ttl或者方法uri参数如果只在一方出现,即使和缺省值相等,也判定为两个URI不相等。

-         包含maddr参数的URI和没有包含maddr参数的不相等。

-         其他uri参数,如果在一方出现,则在比较的时候忽略。

 

o URI头部件的比较是不能忽略的。任何在header部分出现的域都必须在双方URI中进行匹配和比较。

 

下列URI是相等的:

sip:%61lice@atlanta.com;transport=TCP

sip:alice@AtLanTa.CoM;Transport=tcp

 

sip:carol@chicago.com

sip:carol@chicago.com;newparam=5

sip:carol@chicago.com;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:alice@atlanta.com?subject=project%20x&priority=urgent

sip:alice@atlanta.com?priority=urgent&subject=project%20x

 

下列URI是不相等的:

 

SIP:ALICE@AtLanTa.CoM;Transport=udp           (用户名不同)

sip:alice@AtLanTa.CoM;Transport=UDP

 

 

sip:bob@biloxi.com                         (端口不同)

sip:bob@biloxi.com:5060

 

sip:bob@biloxi.com                (通讯协议不同)

sip:bob@biloxi.com;transport=udp

 

sip:bob@biloxi.com                  (通讯协议和端口不同)

sip:bob@biloxi.com:6000;transport=tcp

 

sip:carol@chicago.com            (header部件不同)

sip:carol@chicago.com?Subject=next%20meeting

 

sip:bob@phone21.boxesbybob.com            (就算是phone21.boxesbybob.com

sip:bob@192.0.2.4                解析到192.0.2.4也不能算相等的。)

 

注意相等性是不能传递的。

比如 sip:carol@chicago.com 和sip:carol@chicago.com;security=on相等

sip:carol@chicago.com 和sip:carol@chicago.com;security=off相等

但是:

sip:carol@chicago.com;security=on和sip:carol@chicago.com;security=off不等。

 

1.5.     从URI中产生请求

对于实现而言,需要能够直接从一个URI来构造请求。URI可以是从名片,网页,或者甚至从某些协议内部得到(比如登记的联系信息等等)。

 

协议的实现必须包括构造请求的Request-URI中的transport、maddr、ttl或者user参数。如果URI包含了method参数,那么它的值必须和构造的请求的方法一样。并且method参数不能放在Request-URI中。不认识的URI参数必须放在消息的Request-URI中。

 

实现中应当把URI中出现的header或者包体部分包含入消息本身,并且当作是请求自己的组成部分。

 

在实现中,不应当保留那些明显危险的头域字段:From、Call-ID、Cseq、Via和Record-Route。

 

并且实现中,也不应当保留任何请求的Route头域值,这样可以避免无知的客户端进行恶意攻击。

 

实现中也不应当保留那些可能会导致错误登记地址或者误导能力的头域字段,这些包括:Accept、Accept-Encoding、Accept-Language、Allow、Contact(在对话中使用)、Organization、Supported和User-Agent。

 

实现上应当检查每一个请求中所描述的头域的正确性,包括:Content-Disposition、Content-Encoding、Content-Language、Content-Length、Content-Type、Date、Mime-Version和Timestamp。

 

如果从给定URI构造的请求不是一个合法的SIP请求,那么这个URI就是非法的URI。实现上禁止处理和传送非法的SIP请求。它应当尝试追查为何会有一个非法的URI。

 

很多情况都可以得到一个非法的请求。这包括但是不限于,头域的语法错误,非法的URI参数合并,或者错误的消息体描述等等。

 

发送从URI构造的请求可能会导致实现上的能力不够。比如:URI可能指定了尚未实现的通讯协议或者通讯扩展。那个这个具体的实现上来说,应当拒绝发送这些请求,而不是修改这个请求来适应具体实现的处理能力。对于具体实现来说,它不能发送包含它自己不能理解的扩展部分的请求。

 

比如,从一个包含了未知的或者摆明了不支持的Request头域参数或者method参数的URI中,构造的请求就是不能发送的。

 

1.6.     关联SIP URI和tel URL

如果tel URL(RFC 2806)转换成为一个SIP或者SIPS URI,那么tel URL的整个电话描述(telephone-subscriber)和机器参数,都需要放在SIP或者SIPS URI的userinfo部分。

 

因此:tel:+358-555-1234567;postd=pp22会变成:

sip:+358-555-1234567;postd=pp22@foo.com;user=phone

或者

sips:+358-555-1234567;postd=pp22@foo.com;user=phone

而不是

sip:+358-555-1234567@foo.com;postd=pp22;user=phone

或者

sips:+358-555-1234567@foo.com;postd=pp22;user=phone

 

通常来说,相等的tel URL转换成为SIP或者SIPS URI以后,不一定能得到相同的SIP或者SIPS URI。因为SIP和SIPS URI的userinfo部分是根据大小写敏感的字串。由大小写不敏感的tel URL以及重新排序的tel URL参数并不改变tel URL的相等性,但是在转换成为SIP或者SIPS URI之后,却影响了他们的相等性。

 

例如:

tel:+358-555-1234567;postd=pp22

tel:+358-555-1234567;POSTD=PP22

是等价的,但是

sip:+358-555-1234567;postd=pp22@foo.com;user=phone

sip:+358-555-1234567;POSTD=PP22@foo.com;user=phone

却是不等价的。

 

类似的:

tel:+358-555-1234567;postd=pp22;isub=1411

tel:+358-555-1234567;isub=1411;postd=pp22

是等价的,但是

sip:+358-555-1234567;postd=pp22;isub=1411@foo.com;user=phone

sip:+358-555-1234567;isub=1411;postd=pp22@foo.com;user=phone

却不等价

 

为了避免这个问题,在构造放在SIP或者SIPS URI中的userinfo部分的电话描述域的时候,应当转换大小写不敏感的电话描述域为小写,并且除了isdn-subaddress和post-dial,把电话描述的参数按照参数名进行排序, 因为他们需要按顺序出现在参数的第一个。(在下边是除了未来扩展参数意外的全部tel URL大小写不敏感的部分)。

 

根据上边的描述,全部:

tel:+358-555-1234567;postd=pp22

tel:+358-555-1234567;POSTD=PP22

 

转换成为

sip:+358-555-1234567;postd=pp22@foo.com;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;tsp=a.b@foo.com;user=phone

 

2.   OptionTags

Option tags是一个唯一标志,用来指明SIP中的新options(扩展)的。这些tags在Require,Proxy-Require,Supported和Unsupported头域中使用。注意这些options是以option-tag=的形式作为这些头域的参数存在的。

 

Option tags是根据标准的RFC扩展定义的。这是和过去的试验有所不同,这是协会为了保证多个厂商之间能够持续互相协作。option tags的IANA注册可以保证查找很容易。

 

3.   Tags

tag参数用于SIP消息中的To和From头域。它作为一个通用的机制的一部分来唯一标志一个对话,这个机制用Call-ID和两个从对话参与者的tag来标志一个对话。当UA在对话外发出一个请求时,它只包含了From tag,提供了对话ID的一半。对话根据应答创建完成,这个应答在To头域中提供了对话ID的另一半。SIP请求的分支意味着一个单个请求可以创建多个对话。这个也解释了为何需要对话两方的标志;如果没有被叫方的标志,呼叫方不能分辩和消除由单个请求创建的多个对话。

 

当UA产生一个tag并且增加进一个请求或者应答的时候,它必须是一个全局唯一的,并且是密码随机数起码是32位的随机数。这个要求是为了让UA能够在同一个INVITE请求中,在给这个INVITE的应答中,在To头域产生一个不同的tag,和原始INVITE请求在From头域中产生的tag不同。这是因为UA可以邀请自己到一个会话,常见的是在PSTN网关的“hairpinning”呼叫。类似的,对不同呼叫的两个INVITE也有不同的From tag,并且给这两个呼叫的两个应答也有不同的To tag。

 

在全局唯一要求之外,产生tag的算法是实现相关的。Tag对于容错系统比较有用,在容错系统下,当主服务器故障的时候,对话会在另外一个服务器上进行恢复。UAS可以产生一个tag,让备用服务器能够认识到这个请求是在故障服务器上的对话,并且能够决定是否恢复对话和对话相关的状态。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值