1、sip 中的 subscribe 和 notify 扩展应用技术编辑:jackyhwei 时间:2011-03-08 10:07 点击:187 次会话发起协议研究工作组提出 3 种协议功能扩展方式:方法扩展、头部扩展和消息体扩展。文章深入探讨了包含这 3 种扩展方法的事件通告机制,给出了基于这一机制的自动回叫业务实例,并讨论了该机制的安全性。收藏到: TAG: SIP 摘要:会话启动协议研究工作组提出 3 种协议功能扩展方式:方法扩展、头部扩展和消息体扩展。文章深入探讨了包含这 3 种扩展方法的事件通告机制,给出了基于这一机制的自动回叫业务实例,并讨论了该机制的安全性。 关键词:会话启动协议;
2、事件通告机制;IP 通信网协议;增值业务 Abstract:IETF SIPPING (Session Initiation Protocol Investigation) working group has proposed 3 approaches to extend the base functions of SIP: method extension, header extension and body extension. The article goes deeply into the SIP event notification mechanism involving these
3、 three approaches. An example is given to illustrate the automatic “call-back“ service based on this mechanism. Considerations on the security of the mechanism are also included. Key words:SIP; event notification mechanism; IP communication network protocol; value-added service 众所周知,会话启动协议(SIP)是建立、修
4、改和终结多媒体会话或呼叫的应用层控制协议。自 1999 年至今,会话启动协议基础协议已从最初的 RFC 2543 发展到了现在的 RFC 3261,协议内容得到了很大的扩充,其描述的信令框架也更加完善。随着会话启动协议被第 3 代移动通信合作计划和微软公司正式采用,人们已不再满足于使用会话启动协议完成基本的呼叫控制,更多的是关注如何利用会话启动协议灵活实现增值业务。在此背景下,会话启动协议研究工作组提出了 3 种会话启动协议功能扩展方式:消息(方法)扩展、头部扩展和消息体扩展。本文讨论的异步请求事件通告机制就是由上述 3 种扩展方式构成的,可以应用于如自动回叫、在席、代答等多种富有市场前景的增
5、值业务,是有代表性的会话启动协议功能扩展技术,体现了会话启动协议实现增值业务的基本思路和方法。 1 基于会话启动协议的事件通告机制 1.1 事件通告机制的概念 所谓事件通告机制是指网络中的一些实体可以订阅网络中某些资源或呼叫的状态信息,当那些被订阅的资源的状态发生改变时,负责这一资源的网络实体将向订阅者发送通告,通报当前资源状态的变化情况。 为了实现这一机制,因特网工程任务组(IETF)的 SIP 工作组对基本的会话启动协议进行了扩充,提出了基于会话启动协议的事件通告机制规范:RFC 32651。 在规范中定义了两个扩展方法:订阅(SUBSCRIBE)和通告(NOTIFY)。SUBSCRIBE
6、 方法用于发起订阅请求,NOTIFY 方法用于通告当前资源状态。 会话启动协议事件通告机制涉及以下几个概念: (1)订阅者 订阅者负责接收 NOTIFY 消息的会话启动协议用户代理(SIP UA)2。这些 NOTIFY 消息中包含订阅者订阅的资源信息。订阅者典型的动作是向通告者发送 SUBSCRIBE 消息以请求创建一次订阅关系。 (2)通告者 通告者负责产生 NOTIFY 请求的 SIP UA。通告者在 NOTIFY 消息中向订阅者回馈当前资源的状态。通告者典型的动作是接收 SUBSCRIBE 消息并创建相应的订阅关系。 (3)订阅 所谓订阅就是一组与某个对话相关联的应用状态的集合。订阅关系
7、既存在于订阅者中,又存在于通告者中。 (4)事件包 事件包是通告者向订阅者发送的一组资源的状态信息。RFC 3265 中给出了抽象的事件包模板定义,对应具体业务可定义相应的事件包类型,例如:在席事件包、对话事件包等,这些事件包可使用不同的语法并具有各自的语义。这种框架赋予会话启动协议事件通告机制极大的生命力和灵活性,有助于快速提供新的业务。 1.2 事件通告机制的流程 典型的会话启动协议事件通告机制流程如图 1 所示。 SUBSCRIBE 方法和会话启动协议基本规范3-4中定义的邀请(INVITE)方法都可以创建一个对话。当订阅者想得到网络中某一资源的状态时,便向负责这一资源的会话启动协议实体
8、发起 SUBSCRIBE 请求,如图 1 中的 F1 所示。SUBSCRIBE 消息中的请求统一资源标识符(Request-URI)就是所要请求的资源的统一资源标识符(URI),这一 URI 同时还为会话启动协议代理服务器路由请求提供线索。SUBSCRIBE 请求中必须包含一个扩展的 Event 头部,其中注明要订阅的事件类型,即事件包标记,如,dialog(用于代答业务)、refer(用于呼叫转交)等。还可包含扩展的Allowed-Event 头部,指示本节点能够支持的事件包类型。如果在一个对话中有多次订阅,则如图 2 所示,在Event 头部还要增设标识参数 id 予以区分。 对于订阅者来
9、说,它总是在一定的时间段内对它感兴趣的某一资源进行观察,因此,SUBSCRIBE 消息中应包含expires 头部,这一头部值表明订阅者期望的有效订阅时长。为了延长某一订阅的时间,订阅者可以在有效期内再次发送 SUBSCRIBE 消息来刷新这一订阅。具体某次订阅的有效时长,最终是由对 SUBSCRIBE 请求的 2XX 响应中的expires 头部值或 NOTIFY 消息中的 Subscription-State 头部的 expires 参数决定的。expires 头部值等于 0 的SUBSCRIBE 请求表示撤消订阅。如果订阅关系能够建立,SUBSCRIBE 消息将会触发通告资源状态的 NO
10、TIFY 消息立即回送。订阅者想要获得的资源状态信息封装在后继通告消息 NOTIFY 的消息体中,为了能够正确地解释这部分信息,订阅者应该向通告者指明自己支持的消息体格式,因此,在 SUBSCRIBE 消息中应携带 Accept 头部,比如:Accept: application/dialog-info+xml,这表明订阅者支持用可扩展标识语言(XML)描述的对话事件包5,实际上就是一种通用 Internet 邮件扩展(MIME)格式消息体。如果 SUBSCRIBE 消息中没有携带 Accept 头部,则通告者根据SUBSCRIBE 消息中 Event 头部指明的事件包标记选择默认的格式传送资
11、源状态信息。 SUBSCRIBE 请求通过 2XX 响应确认,如图 1 中的 F2 所示。不同的 2XX 响应具有不同的语义: (1)200 OK 表示订阅已被接受且用户已被授权订阅请求的资源。 (2)202 Accepted(接受)是事件通知机制扩展的响应码,表示订阅请求已被理解,但是否授权给订阅者未确定。 2XX 响应中必须包含 expires 头部,这个值指明通告者确定的此次订阅的有效时长,且必须满足:expires 200 OK = expires SUBSCRIBE,即禁止通告者延长订阅时长。如果返回非 2XX 响应,则表示订阅失败,将没有后继的NOTIFY 消息。 通告者收到 SU
12、BSCRIBE 请求时,首先判定是否理解消息中的 Event 头部,如果不理解,则通告者返回扩展的“489 Bad Event”(错误事件)响应。通告者还会检查消息中的 expires 头部,如果其值满足:(0 expires SUBSCRIBE 1 hour) & ( 0 expires SUBSCRIBE Min 通告者- config),其中,Min 通告者- config 为通告者最小配置订阅时长,则通告者向订阅者返回“423 Interval too small”(时间间隔太短)响应,表示提出的订阅时长太短。此外,通告者还应根据本地策略对提出 SUBSCRIBE 请求的用户进行鉴权。
13、 与订阅相关的信息由 NOTIFY 消息传送。通告者在成功创建订阅关系后,必须立即发送 NOTIFY 消息,向订阅者通告当前订阅资源的状态,如图 1 中的 F3 所示。通告者使用 SUBSCRIBE 消息中 Accept 头部明确允许的或者 Event 头部隐含指明的消息体格式将资源的状态信息或指向该资源状态的 URI 封装在消息中。消息也可包含扩展的 Allowed-Events 头部,指示本节点能够支持的事件包类型。NOTIFY 消息中必须包含扩展的 Subscription-State 头部,指示创建的订阅的状态。共有 3 种订阅状态,分别是: (1)active:订阅已被接受且授权成功
14、。 (2)pending:SUBSCRIBE 请求已收到,但还没有足够的信息决定接受或拒绝此次订阅。 (3)terminated:订阅未激活,或创建的订阅关系终止。 对应 active 状态或 peding 状态,该头部还带有 expires 参数指示此次订阅的有效时长。对应 terminated 状态,该头部应包含 reason 参数指示订阅被终止的原因,或者包含 Retry-After 参数,指示订阅者过一段时间后重新发起订阅请求。 订阅者收到通告者 NOTIFY 请求后,将进行匹配检查。 如果找到相应的匹配,且 NOTIFY 消息中的 Subscription-State 头部指示的订阅
15、状态是 active 或 pending,订阅者创建新的订阅或对话,并对 NOTIFY 请求回送 200 OK 响应,如图 1 中的 F4 所示。如果匹配失败,则发送“481 Subscription does not exist”(订阅不存在)响应。 在订阅有效期内,如果资源状态发生变化,则通告者使用 NOTIFY 请求及时将变化信息通告订阅者,如图 1 中的 F5和 F6 所示。 扩展的 SUBSCRIBE 方法和基本的 INVITE 方法都可以创建对话。在某一对话中,SUBSCRIBE 请求将创建和该对话关联的订阅,而该对话有可能是由 INVITE 建立起来的。因此,如果订阅终止,且当前
16、无其他应用状态(如由 INVITE 请求建立起来的应用状态)和该对话关联,则该对话结束。如果仍有订阅和该对话关联,虽然其他的应用状态已结束,但该对话并没有结束。换句话说,由 INVITE 创建的对话并不会因为收到或发送了再见请求而结束,因为仍有订阅关系和此对话相关联。与此类似,当多个订阅和同一对话关联时,必须当与此对话相关联的所有订阅都结束时,该对话才结束。这一概念非常类似于程序设计里对文件描述符的引用,其中文件描述符相当于对话,对文件描述符引用的进程相当于建立的订阅关系。 SUBSCRIBE 请求可以触发通告者对其资源状态的立即回送,因此,订阅者可以利用这一特性实现对资源状态的轮询。当订阅处
17、于激活状态时,订阅者在 SUBSCRIBE 请求的 expires 头部写入当前剩下的订阅有效时长的秒数,这样,能够立即触发通告者产生 NOTIFY 消息,将当前资源的状态通告给订阅者。需要指出的是,这种对资源的轮询会导致网络、通告者和订阅者负荷的增加。在如移动通信这样的特定应用中,订阅者一般是数据处理能力较慢、需要额外供电的移动终端设备,随着事件通告频度的增加和通告事件包的增大,将消耗很多宝贵的带宽资源,造成网络拥塞和订阅者的过载。因此,订阅者需要对通告者的状态通告频率作出限制6。另外,订阅者还可以在 SUBSCRIBE 消息中指定一些事件包的过滤规则,使得通告者能够根据这一过滤规则产生通告
18、事件,而不是任何状态发生变化时都发起通告。 一般说来,订阅者使用 SUBSCRIBE 请求建立一次订阅,称为显式订阅创建,与此相对应的还有一种隐式的订阅创建,即订阅者不是通过 SUBSCRIBE 请求来创建订阅。而是通过转交(REFER)方法3,一种由 RFC 3515 定义的用于实现呼叫转交等业务的方法。REFER 请求隐式地在被转交用户处创建订阅,所要观察的资源是转交请求的状态。 2 自动回叫业务示例 如前所述,会话启动协议的事件通告机制非常灵活,针对不同的应用可以定义不同的事件包,事件包被封装在NOTIFY 消息中通告资源状态,这一机制为实现各种功能强大的业务提供了坚实的基础。现给出使用
19、这一机制实现的自动回叫业务流程。 (1)业务描述 用户呼叫用户 B,而 B 正在会话,A 希望 B 在通话结束后能够立刻通知他,这样 A 就能够及时地和 B 建立会话了。这里,A 使用事件通告机制来获取 B 的会话状态。 (2)业务流程 如图 3 所示,用户 A 向用户 B 发起呼叫请求 INVITE(F1),此时 B 正在通话,因此返回“486 Busy Here”(现在正忙)响应(F2)。A 希望 B 能够在通话结束后通知他,于是 A 向 B 发起 SUBSCRIBE 请求(F4),其 Event 头部指明事件类型为 dialog,即订阅 B 正在进行中的对话状态;Accept 头部指明
20、A 支持使用 XML 语言封装的 dialog 事件包。SUBSCRIBE 的消息片断如下: SUBSCRIBE sip: userBfoo.bar SIP/2.0 Event: dialog Accept: application/dialog-info+xml B 的通告者根据本地策略对 A 进行鉴权后授权 A 订阅这一资源,返回 200 OK(F5),并立即回送通告当前对话状态的NOTIFY 消息。当 B 结束通话时,A 订阅的对话资源状态发生了变化,从确认状态迁移至了终结状态,B 的通告者生成 NOTIFY 消息,向 A 通告当前 B 的对话状态(F8)。A 得到这一信息后,立即向 B
21、 发起 INVITE 请求,与 B 建立新的会话。 3 事件通告机制的安全性考虑 (1)接纳控制 在事件通告机制中,通告者需要将资源的状态信息通告给订阅者,然而在通告的事件包中,有些信息对于用户来说是敏感的或者是隐私,因此,通告者应能够根据订阅者的身份,选择性地拒绝某些用户的订阅请求,并使用标准的会话启动协议鉴权机制2对用户进行鉴权。订阅请求的最终决定权应该由用户(自然人)作出。 (2)通告者的策略安全 在某些情况下,对 SUBSCRIBE 请求回应 200 OK 或 4XX、6XX 响应可能会导致通告者某些敏感策略信息的泄漏。因此,在这些情况下,通告者应总是对 SUBSCRIBE 请求回送
22、202 Accepted 响应。后继的 NOTIFY 中可能并不携带真正的资源状态,但从订阅者的角度来看,这并无任何异常。例如,在“在席”应用中,用户 A 向用户 B 发送 SUBSCRIBE 请求获取用户 B 是否在席的信息,B 在席,但他拒绝了 A 的订阅请求,因为 B 并不想让 A 知道他正在网上。如果 B 直接使用 4XX 或 6XX 响应拒绝,则会泄漏 B 的策略。为此,B 可对 SUBSCRIBE 回送 202 Acceptted 响应,在随后的NOTIFY 消息的 Subscription-State 头部指明订阅终结,原因为没有资源,即 A 想订阅的资源不存在,其Subscri
23、ption-State 头部为:Subscription-State:terminated;reason=noresource,这样既拒绝订阅请求又不会暴露通告者的策略信息。 (3)防止恶意攻击 随着事件通告机制的进一步应用,要逐步考虑应对各种 Internet 上惯用的恶意攻击。比如,拒绝服务(DoS)攻击,在当前的基于会话启动协议的事件通告模型中,一个 SUBSCRIBE 请求将触发一个或多个通告资源状态的 NOTIFY 消息,通告者接收到 SUBSCRIBE 请求,要创建相应的状态,消耗一定的系统资源。有恶意的订阅者会利用这一点发起过多的订阅请求,就有可能使通告者因创建过多的订阅而资源耗
24、尽。为了减少这种攻击的机会,通告者的实现必须包含鉴权,以过滤恶意的订阅请求。 4 结束语 IETF 通过引入 SUBSCRIBE 和 NOTIFY 两个扩展方法,Event、Allowed-Events 和 Subscription-State 3 个扩展头部,并在定义事件包引入必要的扩展消息体,形成了会话启动协议事件通知机制,基于此机制可以灵活地实现许多新的增值业务。 5 参考文献 1 IETF RFC 3265. Session Initiation Protocol SIP Specific Event Notification S. 2 IETF RFC 3261. SIP: Sess
25、ion Initiation Protocol S. 3 IETF RFC 3515. The Session Initiation Protocol (SIP) Refer Method S. 4 Alan Johnston. Session Initiation Protocol Service Examples EB/OL http:/www1.ietf.org/mail-archive/working-groups/sip-ping/current/msg04068.html. 5 Jonathan Rosenberg. An INVITE Inititiated Dialog Event Package for the Session Initiation Protocol (SIP) EB/OL. http:/www1.ietf.org/mail-archive/ietf-announce/current/msg23154.html. 6 Niemi A. Requirements for Limiting the Rate of Event Notifications EB/OL. http:/www1.ietf.org/mail-archive/ietf-announce/current/msg23061.html.