RFC3265
RFC3265 中文译稿
收件人:
发件人: 崮山路上走 9 遍
抄送:
日期: 2005-06-08
关于: 基于 SIP 的事件通知,RFC3265 中文译稿
摘要
本文档描述了会话初始协议(SIP)的一个扩展。这个扩展提供了一个用于某 sip 节点向其他 sip 节点
订阅关于其他节点发生某件事情时候的一种通知的可扩展的平台。
本文档描述具体实现机制可能在将来会形成规范。
需要注意的是,在这里定义的事件通知机制,并不是为了所有通用的事件订阅和通知而制作的。
1. 简介
在很多 SIP 服务中,都可能会有终端之间的协作,在这些情况下,要求异步的事件通知就显得相当有
用。这样的服务包括了自动回叫服务(基于终端的状态事件),好友列表(基于用户的出席状态事件),
消息等待通知(基于邮箱状态变更时间),以及 PSTN 和 Internetworking(PINT)[2]状态(基于胡椒
状态事件)。
本文档描述的方法提供了一个框架,基于这个框架可以实现订阅这些事件的通知。
本文介绍的消息通知机制并不是为了一个处理所有类型事件的订阅和通知的通用的基础框架而设计
的。处理所有类型事件的订阅和通知太复杂了,仅仅凭一个协议描述是远远不够的。我们的目标是提
供一个基于 SIP 的不那么复杂的事件通知机制框架,并且有着比较好的扩展性,能够覆盖简单的事件
通知情况到提供强大的订阅通知服务。注意,基于本框架的事件包将可以有任意的细节约定,规定他
们所订阅和通知的事件或者事件的类别描述。
本文档并没有描述可能用到的直接扩展;他必须用其他的文档来描述这个扩展(这里指的是”事件
包”event packages)。用面向对象的设计来描述的话,他可以被看成一个抽象的基类,必须被派生
出一个扩展的实例类才能使用。在第四节讲述了如何创建这种扩展。
1.1 操作概览
基本概念是:在网络上的实体可以向在网络上的某个资源或者呼叫状态预订不同的资源或者呼叫状
态,并且这些网络实体(或者表现形式是网络实体的)在状态变化的时候,可以发出这些通知。
典型的消息流如下:
第 1 页
通知者
|-------------SUBSCRIBE------> | 请求状态订阅
|<------------ 200 OK ---------
| 确认订阅请求
|<----------- NOTIFY --------- | 返回当前状态信息
|-------------- 200 OK ---------> |
|<----------- NOTIFY --------- | 返回当前状态信息
|-------------- 200 OK ---------> |
订阅者
如果订阅已经过期了,那么就必须重新发起 SUBSCRIBE 消息来重新订阅
1.2 文档约定
略
2 名词定义
Event Package: 事件包。一个事件包就是一个附加的规定。这个规定定义了一个对订阅者的通知
消息里的状态信息集合。事件包并且在基于本文档约定的框架下定义了扩展的语法和语义,用来描述
这些状态信息。
Event Template-Package:事件模板包。事件模板包是一个特殊的事件包,它定义了一组包括他自己
在内的可能可以适用于全部事件包的状态集合。
Notification: 通知。通知是通知者发送一个 NOTIFY 消息给这个消息的订阅者,知会这个订阅者资源
的状态。
Notifier: 通知者。通知者是一个 ua,他负责产生通知资源状态订阅者的 NOTIFY 请求,通知者通常
接受 SUBSCRIBE 请求来创建订阅信息。
State Agent: 状态代理,状态代理是一个通知者,他负责通知某个资源的状态信息,他可能需要从多
个源地点搜集状态信息。状态代理在给出通知的时候,一定是给出制定资源的完整的状态信息。
Subscriber: 订阅者。订阅者是一个 ua,他从通知者接收 NOTIFY 请求;这些 NOTIFY 请求包含了
该订阅者所关心的指定资源的状态信息。订阅者通常会对通知者发起 SUBSCRIBE 来发起订阅请求。
Subscription:订阅信息。一个订阅信息是一组与对话有关的应用状态集合。这个应用状态包含了一个
指向关联对话的指针,一个事件包名字,并且可能包含一个标志串。事件包定义了附加的订阅状态信
息。根据定义,订阅信息将会出现在订阅者和通知者两边。
Subscription Migration:订阅信息移动。订阅移动是指一种把订阅信息从一个通知者移往另外一个通知
者的动作。
第 2 页
3 节点行为
3.1 SUBSCRIBE行为描述
SUBSCRIBE 是一个用来请求对方节点的当前状态以及后续状态变化的请求方法。
3.1.1 订阅有效期
SUBSCRIBE 请求应当包含一个”Expires”头域(SIP[1]中定义)。这个有效期头域指出了这个订阅的
有效期,在有效期内,保持订阅有效,订阅者需要定期通过一个新的在相同对话内(参见 SIP[1])的
SUBSCRIBE 消息来重新刷新这个订阅的有效期。
如果在 SUBSCRIBE 请求中没有”Expires”头域,那么实现上缺省应当由事件包来定义。
并且给 SUBSCRIBE 的 200 类的应答必须包含一个”Expires”头域。这个应答中的头域定义的时间可
以比请求中的时间短,但是不能比请求中的时间长。应答中的”Expires”头域给出的时间是最终订阅的
实际有效期。
在”Contact”头域中的”expires”参数,在 SUBSCRIBE 请求/应答中没有实际的语义,并且也和
SUBSCRIBE 请求或者应答中的”Expires”头域完全的不同。
SUBSCRIBE 请求中,如果带了一个”Expires”为 0 的头域,那么自然的结果就是取消这个事件的订阅。
对于取消订阅的补充,一个带了”Expires”为 0 的 SUBSCRIBE 消息也会导致取得状态,参
见 3.3.6 节
3.1.2 如何辨认订阅事件和事件类别的
分辨事件是通过三方面的信息来进行的:Request URI,Event Type,和(可选)消息体。
SUBSCRIBE 请求的 Request URI 是非常重要的,包含了足够的信息,通过 SIP[1]中规定的请求路
由策略,来路由这个请求到合适的实体。它也包含了足够的信息来鉴别这个 SUBSCRIBE 希望订阅
的事件通知的资源。但是仅凭借这个 Request URI 不足以区分事件的种类(比
如”sip:adam@dynamicsoft.com”既是订阅我的出席状态消息的 URI,也是订阅我语音邮箱状态的
URI)
订阅者必须在 SUBSCRIBE 请求中包括一个”Event”头域,标志了订阅者希望订阅的事件或者事件类
型。”Event”头域包含一个 token,这个 token 指出了请求订阅的状态类型。这个 token 将会通过 IANA
来登记,并且对应一个事件包,这个事件包描述了这个事件或者事件类的具体语义。”Event”头域可能
包含一个”id”参数。如果出现了这个”id”参数,意味着这个订阅是在一个对话内的,并且这个 id 参数包
含了一个标志这个对话的 opaque 串。”id”参数值在单个对话范围内有效。
如果事件所关连的事件包要求有一个相关的 SUBSCRIBE 请求包体,那么就在语义上就要求提供一
个 SUBSCRIBE 请求包体。
事件包可以在”Event”头域定义一些参数,如果定义了这些参数,那么必须定义与这些参数相关的具体
语义。
3.1.3 附加的SUBSCRIBE头域值
第 3 页
由于 SUBSCRIBE 请求创建了一个对话(基于 SIP[1]的定义),他们可以包含一个”Accept”头域。如
果提供了这个头域,那么就意味着在后续的 NOTIFY 请求中允许的包体格式。事件包必须定义在
SUBSCRIBE 请求中没有提供”Accept”头域时候的行为,通常都是定义一个单个的缺省的包体类型。
在这里没有描述的头域可以在 SIP[1]中找到对应的描述。
3.1.4 订阅者的SUBSCRIBE行为
3.1.4.1 请求一个订阅信息
SUBSCRIBE 是一个会创建会话的方法,在 SIP[1]中描述。
当订阅者希望订阅某一个资源的特定状态信息时,他构造一个 SUBSCRIBE 消息。如果初始的
SUBSCRIBE 是一个对话外的请求(典型的情况),他的构造遵循 SIP[1]中描述的 UAC 的会话外请
求的构造方法进行构造。
这个 SUBSCRIBE 请求会通过一个终结应答进行确认。一个 200 类的应答表示这个订阅已经被接受,
并且一个 NOTIFY 请求将被立刻发送。一个 200 应答表示这个订阅请求已经被接受并且这个用户已
经通过炎症可以订阅请求的资源。202 应答仅仅描述这个订阅请求被理解了,但是身份认证还没有确
定,可能会或者可能不会被授权访问这个请求的资源。
给 SUBSCRIBE 请求的 200 类的应答中的“Expires”头域表示了实际的订阅请求的有效期(如果不刷
新,那么将会多久以后过期)
非 200 类的终结应答表示了没有订阅成功或者对话没有创建成功,并且没有后续的 NOTIFY 消息会
发送。所有非 200 类的应答(”489”例外,在这里有描述),有着和 SIP[1]中定义的相同的含义和处
理方式。
SUBSCRIBE 请求可以在”Event”头域中包含一个”id”参数,通过这个参数允许在同一个对话中发起多
重订阅。
3.1.4.2 刷新订阅
在订阅过期前,订阅者都可以通过发送另一个在同一个对话中的 SUBSCRIBE 请求来刷新这个订阅
的过期定时器,这个 SUBSCRIBE 请求的”Event”头域以及”id”参数(如果初始的订阅请求有这个参数)
和初始的订阅请求相同。处理这个请求和处理初始的订阅请求方法一样:
如果初始的 SUBSCRIBE 消息在”Event”头域中,包含了一个”id”参数,那么刷新订阅的请求
也必须包含相同的”id”参数;否则就会被认作是一个对当前对话的一个新的订阅请求。
如果一个刷新订阅的 SUBSCRIBE 请求收到了一个”481”应答,这就意味着这个订阅已经终止了,并
且订阅者并没有收到这个消息的通知。在这种情况下,订阅者应当认为订阅非法。如果订阅者希望重
新订阅这个状态,它应当发起一个和原来请求无关的初始 SUBSCRIBE,这个 SUBSCRIBE 请求具
有一个全新的 Call-ID 和一个新的,唯一的”From”tag(参见 3.1.4.1)。
如果一个 SUBSCRIBE 请求刷新一个订阅失败了,并且得到了一个非 481 应答,原始的订阅将在剩
余的有效期内继续有效,这个剩余的有效期是基于原始的 SUBSCRIBE 以及其应答的”Expires”头域
得到的,或者是基于 NOTIFY 的”Subscrition-State”头域的”expires”参数得到的。
注意,在这里的很多错误都表明由于网络故障或者通知者的问题,将不会收到新的 NOTIFY
消息了。
3.1.4.3 取消订阅
第 4 页
取消订阅是和刷新订阅采用的相同的处理方式,只是”Expires”头域设置成为”0”。注意一个成功的取消
订阅也会触发一个最后一个 NOTIFY 消息。
3.1.4.4 确认订阅的创建
订阅者在订阅成功或者刷新订阅成功以后,希望从每一个订阅成功的节点都收到一个NOTIFY消息。
在收到了第一个NOTIFY消息,订阅者应当把被订阅的资源状态设置成为一个未决1状态。定义新的事
物包的文档必须定义这个”未决状态”,这样应用程序处理起来才有意义(参见 4.4.7)。
由于可能存在顺序颠倒的消息和分支,订阅者必须有在SUBSCRIBE 事务结束前接受 NOTIFY 消息
的能力。
除了上边讲的情况,处理 NOTIFY 请求和 3.2.4 讲述的一样。
3.1.5 Proxy SUBSCRIBE行为
Proxy 在 SIP[1]中约定的行为下,不需要额外的行为就可以支持 SUBSCRIBE。如果 proxy 希望侦测
某一个对话中所有的 SUBSCRIBE 和 NOTIFY,他必须把自己放置到初始的SUBSCRIBE 和所有建
立对话的 NOTIFY 请求中的 record-route 头域。这些 proxy 应当同样在其他的 SUBSCRIBE 和
NOTIFY 请求中放置 record-route 头域。
注意订阅者和通知者可能会选择 S/MIME 来加密 SUBSCRIBE 和 NOTIFY 请求;因此,proxy
不能依赖访问除了 SIP[1]中明确规定需要使用到的信息以外的资料来完成处理。
3.1.6 通知者SUBSCRIBE行为
3.1.6.1 初始SUBSCRIBE事务处理
没有任何情况下会导致 SUBSCRIBE 事务持续超过需要自动处理的时间。特别是,通知者必须不能
在给出对 SUBSCRIBE 请求的终结应答之前等待用户确认。
这个要求是用来放置在 SUBSCRIBE 事务处理中发生非 INVITE 事务触发 timer F(参见[1])
的情况,因为往往和用户交互会导致超过 64*T1 秒。
通知者应当检查是否自己支持”Event”头域中给出的事件包。如果不支持,通知者应当给出一个”489
Bad Event”应答来表示不支持特定的事件/事件类型。
通知者应当也同样应当检查必须的身份认证信息。参见 3.1.6.3
通知者可以检查”Expires”头域给出的有效期,看看是否过小。只有当这个有效期大于 0 并且小于 1 个
小时,而且还小于通知者配置的最小时间,通知者可以返回一个”423 间隔太小”的错误给订阅者,并
且在这个应答中包含一个”Min-Expires”头域。”Min Expires”头域在 SIP[1]中定义。
如果通知者可以立刻决定他是否支持请求中给出的事件包,并且身份认证同意订阅者来订阅这个事件
包,而且其他条件也都具备产生这个订阅,那么通知者创建一个订阅信息和一个对话(如果需要创建
对话的话),并且返回一个”200OK”的应答(除非是由于授权策略等的原因导致不能给与订阅;参见
5.2)。
1 Neutral stat。
第 5 页
如果通知者不能立刻创建这个订阅信息(比如,它需要等待用户认可身份认证,或者代理的另外一个
节点现在无法访问),或者希望屏蔽掉权限信息,它会返回一个”202Accepted”应答。这个应答表示
请求已经被接受,并且也支持这样的订阅,但是需要进一步的授权处理。
当通知者创建了一个订阅信息,这个请求的事件包名字和”Event”头域以及”id”参数(如果存在)将被
作为订阅信息的一部分加以保存。
SUBSCRIBE 的 200 类应答的”Expires”头域值得处理和 REGISTER 应答中的”Expires”的头域值处理
方式一样,服务端可以减小这个值,但是不能增加这个值。
如果 SUBSCRIBE 消息中的有效期过小,通知者可以发送一个 423 应答,这点在前边有介
绍。
SUBSCRIBE 请求的 200 类的应答一般除了订阅的有效期外不会包含有用的信息;他们的主要目的
是维持一个可靠的机制。状态信息将会通过后续的来自通知者的 NOTIFY 请求发送过来。
其他 SIP[1]中定义的应答代码也可能会在 SUBSCRIBE 的应答中使用。
3.1.6.2 确认订阅信息的创建/刷新
在成功接受了或者刷新了订阅信息之上,通知者必须立刻发送一个 NOTIFY 消息通知订阅者当前指定
资源的状态。这个 NOTIFY 消息通过 SUBSCRIBE 应答所创建的相同的对话进行发送。如果在处理
SUBSCRIBE 消息的时候,这个资源的状态没有意义,那么这个 NOTIFY 消息可以包含一个空的或
者未决包体。关于 NOTIFY 消息的产生细节请参见 3.2.2
注意,在给 SUBSCRIBE 请求的任何 200 类的应答之后,NOTIFY 消息总是立刻发送,无论这个订
阅信息是否已经通过身份认证。
3.1.6.3 SUBSCRIBE请求的认证/授权
基于隐私的要求,通知者需要应用检查策略来验证订阅者是否有授权来订阅某个事件集合。这个策略
可以是访问控制列表或者是实时地和用户进行交互。一般情况下,在对订阅者身份认证之前就授权没
有多大意义。
SIP 身份认证机制在 SIP[1]中讲述。需要注意的是,即使是通知者是一个 proxy,对 SUBSCRIBE 请
求的身份认证挑战通常是通过一个”401”应答给回的,而不是"407",通知者通常在接受订阅和通知事
件的时候,是作为一个 ua 存在的。
当然,当作为一个 proxy 的时候,这个节点应当提供通常 proxy 挑战的方式(使用 407)。
前边讲述的介绍时提醒这个通知者总是作为 UA 存在,并且提供的是基于 UA 的身份验证挑
战。
如果基于访问列表或者其他自动验证机制的身份验证挑战失败(例如,程序自动判定这个订阅者的身
份不合法等等),除非是程序在展示上做出控制2(参见 5.2),通知者应当给出一个”403 Forbidden”
应答或者一个”603 Decline”应答,
如果通知者是通过交互的方式来决定是否允许一个订阅信息,那么应当立刻给出一个”202 Accept”应
答。注意,就像前边几节描述的那样,在这种情况下,同样应当构造和发送一个 NOTIFY 消息。
如果订阅信息的身份认证被延迟认证(比如通过交互的方式进行认证),并且这个身份认证后来被拒
绝,那么应当构造一个 NOTIFY 消息,包含一个“Subscription-State”头域,在这个头域中,应当包
含一个”terminated”值,以及一个原因短语:”rejected”
2 保留隐私,就是说,给出的事件通知已经作了处理,防止未授权的隐私暴露。
第 6 页
3.1.6.4 刷新订阅信息
当一个通知者收到了一个订阅信息的刷新,假定订阅者依旧处于通过身份认证和授权状态,通知者更
新这个订阅信息的有效期。和处理初始订阅信息一样,服务器可以缩小有效期,但是不能增加有效期。
最终的有效期放在应答的”Expires”头域。如果接受的 SUBSCRIBE 消息太短了,那么通知者应当给
出一个”423 Subscription Too Brief”应答消息。
如果在有效期内没有收到刷新的请求,订阅信息将被删除。当删除一个订阅信息,通知者应当发送一
个带有”Subscrition-State”头域,并且这个头域有”terminated”值得 NOTIFY 消息来通知这个订阅信息
已经被删除了。如果这样一个消息被发送,那么这个”Subscription-State”头域应当还有一
个”reason=timeout”参数。
当订阅信息过期后,在适当的情况下,发送一个 NOTIFY 意味着这个对应的对话终止了。
3.2 NOTIFY的行为描述
NOTIFY 消息用于通知订阅者关于订阅者订阅信息的状态发生了改变,订阅信息通常是由
SUBSCRIBE 方法所构建的,不过,也不排除有通过其他手段构造的。
如果是通过任何非 SUBSCRIBE 机制构造的订阅信息,那么订阅者以及通知者都必须事前定义好与
这种订阅消息所对应的 NOTIFY 消息。同时,这种方式的设计者也必须留意到这样两种情况的区别,
发送一个 NOTIFY 消息到一个已经知道这个订阅信息的节点,和,发送一个 NOTIFY 消息到一个不
确定是否支持这种订阅信息的节点。后一种方式是不合法的,并且如同在 3.2.4 节描述的一样,必须
接受到一个”481 Subscription does not exitst”应答(除非有更合适的 400 类或者 500 类的错误代码)。
换一句话说,即使基于非 SUBSCRIBE 的机制,对于一个订阅信息的知识,必须在订阅者和通知者
双边都知道。
NOTIFY 并不终止它所对应的订阅信息,换句话说,单个 SUBSCRIBE 请求可以触发多个 NOTIFY
请求。
3.2.1 鉴定报告的事件,事件类别,和当前状态。
在一个通知中区分事件和区分订阅的信息很类似(参见 3.1.2)。
类似在 SUBSCRIBE 请求中描述的那样,NOTIFY 的”Event”头域将包含一个单个事件包名字,这个
NOTIFY 通知就是基于这个事件包的。在”Event”头域中的事件包必须和它对应的SUBSCRIBE 消息
的”Event”头域所匹配。如果在对应 SUBSCRIBE 中的”Event”头域有一个”id”参数,那么这个”id”参数
也必须在对应的 NOTIFY 消息中出现。
事件包可以定义在 NOTIFY 请求中的包体的语义,如果定义了,那么应当在这个 NOTIFY 包体上应
用这个语义。NOTIFY 包体使用来提供额外的关于资源状态变化的事件细节。
当 NOTIFY 消息提供了包体,这个包体必须规格化到一个对应SUBSCRIBE 的 Accept 头域所指出的
格式。这个包体既可以包含一个订阅的资源状态,也可以是一个指向这个状态的 URI 指针(参见
4.4.13)。
3.2.2 通知者的NOTIFY行为
当一个 SUBSCRIBE 请求有一个 200 系列的应答,那么通知者就必须立刻给订阅者构造和发送一个
NOTIFY 请求。当被订阅的状态发生了变化,发送者应当立刻构造和发送一个NOTIFY 请求,并且这
个请求遵循身份认证,本地隐私策略,以及其他需要考虑的控制。
第 7 页
如果 NOTIFY 应答超时,或者收到一个没有”Retry-After”头域的非 200 类的应答,以及没有其他的什
么隐含的重试动作要求(比如”401 Authorization Required”这样的应答),那么他应当认为是通知失
败了。
如果 NOTIFY 请求失败了(依照上边的定义),并且是由于超时失败的,而且这个订阅信息是基于
soft-state 机制的(比如通过 SUBSCRIBE 建立的),通知者应当移除这个订阅信息。
这种方式防止了由于订阅者宕机或者断网而导致的不必要的状态信息传送。由于这样的传送
可能会发送数次,每次的重传算法在 SIP[1]中定义(而不是典型的向客户端的单次传送),
所以如果继续向不能给出应答的非在线的客户端提供通知服务,会导致网络带宽的紧张。基
于客户端的重启动或者网络的重新链接,我们可以期望客户端发起 SUBSCRIBE 消息来刷新
可能已经失效的状态信息;而这些重新刷新的信息会在有关节点重新建立订阅信息。
如果 NOTIFY 请求失败了(依照上边的定义),并且是由于一个错误的应答失败的,并且这个订阅信
息是基于 soft-state 机制创建的,那么通知者必须删除相关的订阅信息。
一个 NOTIFY 的错误应答意味着订阅者或者到订阅者的中间 proxy 出现了什么错误。如果订
阅者出现故障,那么错误处理的时候,让订阅者来修正错误(重新发起 SUBSCRIBE)将会
比较合理。如果中间节点的 proxy 出现了故障,那么一旦网络故障恢复了,定期的
SUBSCRIBE 刷新也会重新创建订阅信息。
如果 NOTIFY 请求收到了一个 481 应答,通知者必须以除相关的订阅信息,甚至订阅信息是由非
SUBSCRIBE 建立的(比如由管理界面设定的)。
如果没有要求上述的行为,那么订阅者收到了一个对不知道的订阅信息的通知,它会发送一
个给 NOTIFY 的错误应答,并且也要发送一个 SUBSCRIBE 来取消这个订阅信息。这样,
会导致订阅者起到一个拒绝服务攻击的放大器的作用,我们现在赋予 481 应答以特定的含
义,它用于标志这个订阅在所有情况下都必须要取消。
NOTIFY 请求必须包含”Subscription-State”头域,这个头域的取值有”active”,”pending”,或
者”terminated”。”active”值表示这个订阅信息已经接受,并且也通过了身份认证(绝大部分情况,参
见 5.2)。”pending”值表示这个订阅信息已经接收到,但是当前的策略信息不足以接受或者拒绝这个
订阅信息。”terminated”意味着这个订阅信息已经终结,不再有效。
如果”Subscription-State”头域的值是”active”或者”pending”,通知者应当同时在这个头域中包括一
个”expires”参数,用来表示本订阅信息距离失效的时间。通知者可以使用这个机制来减小订阅信息的
有效期,不过,这个机制不能用于增加订阅信息的有效期。
当 SUBSCRIBE 请求分支的情况下,由于对一个分支的 SUBSCRIBE 的应答可能不会到达
订阅者,在”active”和”pending”状态下的订阅信息中包含有效期信息十分有用。需要注意的
是,这个”expires”值是”Subscription-State”头域的参数,而不是”Expires”头域。
如果”Subscription-State”的值是”terminated”,这个通知应当包含一个”reason”参数。如果有需要,通知
者也可以包含一个”retry-after”参数。对于这个”reason”,”retry-after”参数的语义细节,参见 3.2.4。
3.2.3 Proxy NOTIFY行为
Proxy 在 SIP[1]中约定的行为下,不需要额外的行为就可以支持 SUBSCRIBE。如果 proxy 希望侦测
某一个对话中所有的 SUBSCRIBE 和 NOTIFY,他必须把自己放置到初始的SUBSCRIBE 和所有建
立对话的 NOTIFY 请求中的 record-route 头域。这些 proxy 应当同样在其他的 SUBSCRIBE 和
NOTIFY 请求中放置 record-route 头域。
注意订阅者和通知者可能会选择 S/MIME 来加密 SUBSCRIBE 和 NOTIFY 请求;因此,proxy
不能依赖访问除了 SIP[1]中明确规定需要使用到的信息以外的资料来完成处理。
第 8 页