会话初始协议ISP技术要求-中国通信行业标准(7)

时间:2008-10-19 来源: 作者: 点击:
在所有情况下,m= 行中格式必须按照优先级排列, 第一个格式是优选格式。优选意味着应使用能够接受的具有最高优先级的格式接收提供。 如果对于媒体流包含属性ptime,那么它指示提供者希望接收期望的分组的间隔。Pti
  
在所有情况下,"m=" 行中格式必须按照优先级排列, 第一个格式是优选格式。优选意味着应使用能够接受的具有最高优先级的格式接收提供。
如果对于媒体流包含属性ptime,那么它指示提供者希望接收期望的分组的间隔。Ptime 属性的值必须大于0。
如果对于媒体流包含属性bandwidth, 那么它指示提供者期望使用的接收带宽。该属性的值可以为零,但不建议。0 值指示不应发送任何媒体。在使用RTP 的情况下,也不允许发送RTCP 分组。
如果包含多个不同类型的媒体流,那么它意味着提供者期望同时使用这些媒体流。一个典型的情况就是在视频会议中同时使用音频和视频媒体流。
如果在提供中包含多个相同类型的媒体流,那么它意味着提供者期望同时发送(或/和接收)多个该类型的媒体流。当发送多个同一类型的媒体流时, 如何将该类型的每个媒体源( 例如: 视频画面和视频中的VCR) 映射到每个媒体流上取决于本地策略。当对于一个特定的媒体类型,用户端只有一个源时,只使用一个策略是合理的: 源被发送到相同类型的每一个流上。每个流可以使用不同的编码。但接收多个同一类型的媒体流时, 如何将每个媒体流映射到该类型的各种媒体接收器(例如:音频中的扬声器或录音装置)上取决于本地策略。但是对策略还是有些限制。首先,当接收多个相同类型的媒体流时,每个流必须至少映射到一个接收器, 以便显示给用户。也就是说, 接收多个相同类型的媒体流意味着这些媒体应该同时显示给用户而不是只选择其中的一个显示。另外一个限制是,当收到多个媒体流并向相同的接收器发送时, 这些媒体流必须以特定的媒体方式相组合。例如: 在有两个音频流的情况下,从任何一个媒体流接收的媒体都可能映射到扬声器。在这种情况下, 组合操作将混合这两个媒体流。在有多个实时消息流的情况下, 当接收器是显示屏幕时, 组合操作应向用户显示所有媒体流。第三个限制是,如果将多个源映射到相同的流,在向流发送这些源之前必须以特定媒体方式组合这些源。虽然超越这些限制的策略具有很大的灵活性,但是代理通常不希望一个策略是从接收器向源拷贝媒体( 即不应将从一个流上收到的媒体拷贝到另一个媒体流上),除非该代理是会议服务器。
使用多个相同类型媒体流的典型应用实例是预付费卡类呼叫应用,此时用户可能在呼叫过程中随时按下"#"键来挂断电话并且使用该卡发送一个新的呼叫。这要求来自用户的媒体到达两个目的地——远端网关和监视该按键的DTMF 处理应用。这可以通过使用两个媒体流来完成,一个流到网关采用收发方式,另一个流到DTMF 应用采用只发方式。
一旦提供者发送了提供,它就必须准备在提供描述的任何只收方式的流上接收媒体,准备在提供描述的任何收发方式的流上接收媒体, 并且准备在提供描述的任何只发方式的流上发送媒体( 当然, 实际上还不能发送媒体,必须要等到收到对等发送的包含需要的地址的端口号信息的应答)。在使用RTP 的情况下, 即使在收到应答之前收到媒体,提供者也不能发送RTCP 接收者报告,而必须要等到收到应答。
F.4.2 组播媒体流
如果会话描述包含组播媒体流,并且该媒体流为只收( 或只发) 方式, 那么这意味着参加者, 包括提供者和应答者, 只能在该流上接收(或发送) 媒体。这点和单播不同, 单播中方向性指的是在提供者和应答者之媒体的流向。
除了这点之外,提供的组播媒体流的语义和RFC 2327 中的描述相同。
F.5 产生应答
对提供的会话描述的应答基于提供的会话描述。如果应答和提供有任何不同(不同的IP 地址、端口号等等),那么应答中的首行必须不同,因为应答是由不同的实体产生的。在这种情况下,应答中"o=" 行上的版本号和提供中"o=" 行上的版本号不相关。
对于提供中的每个"m="行,在应答中必须有相应的"m=" 行。应答应包含和提供中相同数目的"m=" 行。这使得可以基于"m=" 行的顺序来匹配媒体流。这意味着如果提供包含零个"m="行,那么应答也必须包含0 个"m=" 行。
应答中的"t=" 行应等于提供中的"t="行。会话的时间不能协商。
出于某些原因, 在应答中可以拒绝提供的媒体流。如果媒体流被拒绝, 那么提供者和应答者不应对该媒体流产生媒体(或者RTCP 分组)。要拒绝提供的媒体流,应答中相应媒体流的端口号必须置为0。所有列出的媒体格式被忽略。至少应该提供一个媒体流,并满足SDP 的规定。
对每个提供的媒体流产生的应答对于单播和组播应不同。
F.5.1 单播媒体流
如果媒体流被提供的是单播地址,那么对于该媒体流的应答应包含单播地址。在应答中的媒体流的媒体类型必须和提供中的媒体流的媒体类型相匹配。
如果提供中媒体流为只发, 那么在应答中对应的媒体流必须被标记为只收或未激活。如果提供中媒体流为只收, 那么在应答中对应的媒体流必须被标记为只发或未激活。如果提供中媒体流为收发( 如果在媒体或会话描述中没有方向属性,那么在这种情况下媒体流默认为收发), 那么在应答中对应的媒体流可以标记为只发、只收、收发或未激活。如果提供中媒体流为未激活, 那么在应答中该媒体流必须标记为未激活。
对于应答中被标记为只收的媒体流,"m=" 行应至少包含一种媒体格式, 指明应答者期望接收的媒体格式, 该媒体格式包含在提供中列出的媒体格式中。媒体流可以指示其他的媒体格式, 该媒体格式在提供的对应媒体流中未列出,但应答者期望接收该媒体格式。对于应答中被标记为只发的媒体流,"m=" 行应至少包含一种媒体格式,指明应答着期望发送的媒体格式,该媒体格式包含在提供中列出的媒体格式中。对于应答中标记为收发的媒体流,"m=" 行应至少包含一个编解码, 指明应答着期望发送和接收的编解码, 该编解码包含在提供中列出的编解码中。媒体流也可以指示其他的媒体格式, 该媒体格式在提供的对应媒体流中未列出,但应答者期望发送或接收该媒体格式(当然,此时还不能发送该媒体格式, 因为该媒体格式没有列在提供中)。对于应答中标记为未激活的媒体流,根据提供形成媒体格式列表。如果提供中媒体流为只发, 那么将应答中的媒体流作为只收来形成媒体格式列表。同样,如果提供中媒体流为只收, 那么将应答中的媒体流作为只发来形成媒体格式列表; 如果提供中媒体流为收发, 那么将应答中的媒体流作为收发来形成媒体格式列表。如果提供中媒体流为未激活,那么以提供中的媒体流为收发应答中的媒体流也为收发来形成列表。
应答中的连接地址和端口号指示应答者期望从哪里接收媒体( 在使用RTP 的情况下, 将在比该端口号大一的端口上接收RTCP 分组,除非有其他明确的指示)。即使对于只发的媒体流也必须提供地址和端口号;在使用RTP 的情况下,仍然使用较大一个的端口号来接收RTCP 分组。
在使用RTP 的情况下,如果提供中对于特定的载荷类型值优选某个特定的编解码, 那么对于应答中对应的编解码也应该使用相同的载荷类型值。即使使用相同的载荷类型值,应答也必须包含rtpmap 属性,定义载荷类型到动态载荷类型的映射, 同时也应该包含到静态载荷类型的映射。"m=" 行中的媒体格式应按照优先级的顺序列出, 其中第一个媒体格式是优选的。在这种情况下,优选指的是提供者应该使用应答中具有最高优先级的媒体格式。
即使应答者可以按照期望的优选顺序来列出媒体格式,但是建议除非有特殊的原因,应答者应该以提供中这些媒体格式的排列顺序来列出这些媒体格式。也就是说,如果提供中媒体流列出的音频编解码为8、22 和48, 而应答者只支持编解码8 和48,并且如果应答者没有理由改变所支持的编解码,那么建议应答中编解码的顺序应该是8、48,而不是48、8。这样将有助于在双向上使用相同的编解码。
提供中fmtp 参数的解释依赖于该参数本身。在许多情况下,这些参数描述媒体格式的特殊配置, 因此对这些参数应该像处理媒体格式一样处理。也就是说,如果应答中包含fmtp 参数所描述的媒体格式,那么在应答中对于相同的媒体格式必须有相同的fmtp 参数。如果fmtp 参数描述其他内容, 这是对于fmtp 参数每个代理可以使用不同的值。在这种情况下,应答可以包含fmtp 参数, 并且参数的值可以和提供中这些参数的值相同,也可以不同。应答/提供中定义新参数的SDP 扩展同时应该规定如何正确地解释这些参数。
对于任何媒体流,应答可以包含取值非0 的ptime 属性,该属性指示应答者希望接收分组的间隔。对于特定的媒体流,不要求双向上分组间隔相同。
对于任何媒体流,应答者可以包含bandwidth 属性, 该属性指示应答者希望提供者用来发送媒体的带宽。该属性的值允许为0。
如果对于提供中特定的媒体流, 应答者没有相同的媒体格式, 那么应答者必须通过将端口号设置为0 来拒绝该媒体流。
如果对于所有的媒体流都没有相同的媒体格式,那么将拒绝整个提供的会话。
一旦应答者发送了应答,它就必须准备在应答中描述的所有只收媒体流上接收媒体。它必须准备在应答中描述的所有收发媒体流上发送和接收媒体,当然应答者可以立即发送媒体。它必须准备在应答中描述的所有只收或收发媒体流上使用对这些媒体流列出的任何媒体格式接收媒体,当然应答者可以立即发送媒体。当发送媒体时,如果提供中包含ptime 属性,那么应答者应该以该属性的值为间隔发送分组。如果提供中包含bandwidth 属性,那么应答者应该使用不大于该属性值的带宽发送媒体。应答者必须使用在提供中和应答中同时列出的媒体格式来发送媒体,并且应使用在提供中和应答中同时列出的最优选的媒体格式。在使用RTP 的情况下,应答者必须使用提供中的载荷类型值,即使该值和应答中的不同。
F.5.2 组播媒体流
和单播不同, 单播中的媒体流有双向的概念,但在组播中, 媒体流只有单向的概念。因此,对于组播提供要产生应答通常包括修改媒体流的受限属性集。
如果接受组播媒体流, 应答中的地址和端口号必须和提供中的相匹配。类似地, 应答中的方向性信息( 只发、只收或收发) 也必须和提供中的相同。这是因为组播会话中的所有参加者需要使用相同的会话参数,以下关于组播的假设基于RFC 2327 。
应答中的媒体格式集必须等于提供中媒体格式集或是该格式集的子集。删除某个媒体格式表明应答者不支持该媒体格式。
如果提供中包含ptime 和 bandwidth 属性,那么应答中的这些属性值必须等于提供中的属性值。如果提供中不包含这些属性,那么应答中可以增加值为非0 的ptime 属性。
F.6 提供者处理应答
当提供者收到应答时,它可以在接收的媒体流上发送媒体( 假设在应答中该媒体流工作在收发或只收方式)。它必须使用应答中列出的媒体格式来发送媒体,并且应使用应答中列出的最优选的媒体格式。
提供者应根据应答中ptime 和 bandwidth 的属性值发送媒体。
提供者可以立即停止监听初始提供中列出但应答中未列出的媒体格式。
F.7 修改会话
会话中的任何时刻,任何一个参加者都可以发送新的提供修改会话特性。这是提供/应答模式最基本的操作,和上面定义的用于修改一个已经存在的会话参数的提供/应答程序完全相同。
提供可以和最后提供给另一方的SDP 相同(即该SDP 曾经包含在提供或应答中),也可以不相同。称最后提供的SDP 为“先前的SDP”。如果提供相同,应答可以和应答者先前的SDP 相同,当然也可以不同。如果提供的SDP 和先前的SDP 不同,那么在构建提供的SDP 时将有一些限制。对限制的描述如下。
几乎会话的所有属性都可能被修改。可以增加新的媒体流, 删除已经存在的媒体流, 或者改变已经存在的媒体流的参数。当发送提供来修改会话时, 新SDP 的"o=" 必须和先前的SDP 的"o=" 相同,除了初始字段中的版本号必须比先前的SDP 的版本号大一。如果初始行中的版本号不增加,则新的SDP 必须和
139
具有相同版本号的先前的SDP 相同。应答者必须准备接收包含具有不变版本号的SDP 的提供。这是非常有效的no-op 。但是,应答者必须根据第6 节定义的程序产生一个有效的应答( 可以和应答者先前的SDP 相同,也可以不同)。
如果提供的SDP 和先前的SDP 不同,对于先前的SDP 中的每个媒体流新的SDP 必须有一个匹配的媒体流。也就是说,如果先前的SDP 有N 个"m="行, 那么新的SDP 也必须至少有N 个"m="行。先前的SDP 中的第I 个媒体流(从上往下数) 必须和新的SDP 中的第I 个媒体流( 从上往下数) 匹配。这种匹配是必需的,以便应答者确定新的SDP 中的哪个媒体流和先前的SDP 中的哪个媒体流相对应。由于这些要求,媒体流中"m=" 行的数目不会减少, 但可能不变或者增加。要删除先前的SDP 中的媒体流, 该媒体流也必须包含在新的SDP 中, 但是不必提供这些媒体流的属性。
F.7.1 增加媒体流
通过在存在的媒体描述之下增加新的媒体描述可以创建新的媒体流,或者通过重新使用通过设置端口号为0 而变为不可用的媒体流的“位置”创建新的媒体流。
重新使用位置指的是用新的媒体描述代替旧的媒体描述, 但是保留该媒体描述在SDP 中的位置。新的媒体描述必须出现在所有已经存在的媒体描述的下面。排列这些媒体描述的规则和第5 节中描述的相同。
当应答者收到比提供者先前的SDP 包含更多媒体描述的SDP 时,或者应答者收到在先前端口号被置为0 的位置上包含媒体流的SDP 时,应答者就知道SDP 中增加了新的媒体流。可以通过在应答中包含适当的结构化的媒体描述来拒绝或接收这些媒体流。在应答中构建新的媒体描述的程序在第6 节中描述。
F.7.2 删除媒体流
可以通过创建新的SDP, 并将其中该媒体流的端口号设置为0 来删除存在的媒体流。媒体描述可以省略掉先前提供的所有属性,而只列出一个媒体格式。
提供中端口号为0 的媒体流在应答中也必须标记为端口号为0。和提供类似, 应答也可以在媒体描述中省略掉先前提供的所有属性,而只列出来自提供的一个媒体格式。
删除媒体流意味着对该媒体流将不再发送媒体,所有收到的媒体也将被丢弃。在使用RTP 的情况下, 要停止发送RTCP 分组, 并且停止处理所有收到的RTCP 分组。可以释放和该媒体流相关的所有资源。在用户接口上可以指示该媒体流已经被终止,例如通过关闭相关的PC 窗口。
F.7.3 修改媒体流
媒体流的所有特定几乎都可以被修改。
F.7.3.1 修改地址、端口号或传输协议
可以修改媒体流的端口号。为此,提供者可以创建新的媒体描述,并且”m=”行上的端口号和先前的SDP 中相应流的端口号不同。如果仅仅改变端口号, 媒体流描述的其他部分应保持不变。一旦发送了提供, 提供者必须在旧端口号和新端口号上同时准备接收媒体。在收到应答且媒体到达新端口之前, 提供者不应停止对媒体的监听。但是这样处理有可能在转移的过程中丢失媒体。
在这种情况下, 收到媒体指的是媒体已经传送到了媒体接收器。如果存在playout 缓冲区,代理应继续在旧端口上监听媒体直到来自新端口的媒体到达playout 缓冲区的顶端。此时,代理可以停止在旧端口上监听媒体。
应答中的媒体流可以和应答者先前SDP 中相应的媒体流相同,但也可以不同。如果应答者接受更新的媒体流,那么对于该媒体流应答者应该立即发送业务到新端口上。如果应答者改变来自先前SDP 的端口号,那么它必须准备一发送应答就在新端口和旧端口上同时接收媒体。在媒体到达新端口之前应答者不能停止在旧端口上对媒体的监听。对于提供者也一样,当提供者发送了包含新端口号的更新的提供, 在媒体到达新端口之前,提供者也不能停止在旧端口上对媒体的监听。
当然,如果提供中的媒体流被拒绝,一收到拒绝消息提供者就可以停止准备用新端口号接收媒体。
要改变媒体发往的IP 地址,除了此时要更新连接行而不是端口号之外,其他和改变端口号的程序相同。
140
也可以改变媒体流的传输协议。除了要更新传输协议而不是端口号之外,其他和改变端口号的程序相同。
F.7.3.2 改变媒体格式集
可以改变会话中使用的媒体格式列表。为此, 提供者可以创建新的媒体描述, 其中"m=" 中的媒体格式列表和先前的SDP 中相应媒体流的媒体格式列表不同。该列表可以包含新的媒体格式,并且可以删除先前的SDP 中的媒体格式。但是, 在使用RTP 的情况下,在会话过程中, 特定动态载荷类型值到媒体流中特定编解码的映射不能改变。例如,如果A 产生提供,并且对G.711 指定动态载荷类型值46,那么在会话过程中,对于该媒体流的提供或应答,载荷类型值46 必须一直映射到G.711 。但是,多个载荷类型值可以映射到同一个编解码,所以更新的提供也可以对G.711 使用载荷类型值72。
在会话过程中映射需要保持不变是因为SDP 的信令交互和媒体流之间松散的同步
应答中相应的媒体流按照第6 节中的描述排列,并可能导致媒体格式的改变。同样,和第6 节中的描述相同,一旦应答者发送了应答,它就必须使用同时包含在提供中和应答中的媒体格式开始发送媒体,且应该使用同时包含在提供中和应答中的最优选的格式(假设媒体流允许发送媒体),但不能使用任何提供中未包含的媒体格式发送媒体, 即使这些媒体格式包含在提供者先前的SDP 中。同样, 当提供者接收到应答,它必须使用应答中的任何媒体格式开始发送媒体,且应该使用最优选的媒体格式(假设该媒体流允许发送媒体),但不能使用任何应答中未包含的媒体格式发送媒体,即使这些媒体包含在应答者先前的SDP 中。
当代理停止使用某个媒体格式时( 通过在提供或应答中不再包含该媒体格式, 即使该媒体格式包含在先前的SDP 中), 代理仍然需要准备在一小段时间内接收该媒体格式的媒体。代理可以通过三种方式知道何时准备停止接收该媒体格式。第一种, 代理除了改变媒体格式还可以改变端口号。当媒体到达新端口时,代理知道对等已经停止使用旧的媒体格式发送媒体,那么代理可以停止准备接收该媒体格式。这种方式利用了媒体格式的独立性。但是,改变端口号可能要求改变资源预留或者是改变安全协议的密钥。第二种方式, 当丢弃一种媒体格式时, 对所有的编解码使用一个完全新的动态载荷类型集。当收到使用某个新的载荷类型的媒体时,代理知道对等已经停止使用旧的媒体格式发送媒体。这种方式不影响资源预留或安全上下文,但是必须用于使用RTP 的情况下并且会浪费少量的载荷类型空间。第三种方式是使用定时器。当从对等收到SDP 时,启动定时器。当定时器超时时,代理停止准备接收旧的媒体格式。定时器的典型值为一分钟。在某些情况下,代理可以忽略定时器而继续准备接收旧的媒体格式。在这种情况下不必采取任何动作。
当然,如果拒绝提供中的媒体流,一旦收到拒绝消息,提供者可以停止准备接收新的媒体格式。
F.7.3.3 改变媒体类型
可以改变媒体流的媒体类型(音频、视频等等)。建议当使用不同的媒体格式传送相同的逻辑数据时改变媒体类型(相对于增加新的媒体流)。当在语音频带内传送传真和在单个媒体流上传送传真之间相互进行转移时非常有用, 此时使用的是不同媒体类型。为此, 提供者使用新的媒体类型创建新的媒体描述,替换要改变的先前SDP 中的媒体描述。
应答中相应的媒体流按照第6 节中的描述进行排列。假设接受该媒体流, 那么应答者一收到提供就应开始使用新的媒体类型和新的媒体格式发送媒体。提供者必须准备同时接收旧媒体类型和新媒体类型,直到已经收到应答,同时已经收到新类型的媒体且该媒体已经到达playout 缓冲区顶部。
F.7.3.4 改变属性
在提供或应答中可以更新媒体描述中的任何其他属性。通常, 一旦收到改变的SDP, 代理必须使用新的参数发送媒体(如果媒体流允许发送媒体)。
F.8.4 设置单播媒体流处于保持状态
如果呼叫中的某一方想使另一方处于“ 保持”状态, 即请求另一方暂时停止发送一个或多个单播媒体流,那么它应向另一方提供更新的SDP。
如果要进入保持状态的媒体流先前为收发媒体流,那么通过将该媒体流标记为只发使对端进入保持状态。如果要进入保持状态的媒体流先前为只收媒体流,那么通过将该媒体流标为未激活使对端进入保持状态。
媒体流可以在双向上分别处于“ 保持”状态。每个流都可以独立地处于保持状态。对于处于保持状态的流, 提供的接收者不应自动返回包含该流的应答。如果SDP 中所有的流都处于保持状态那么该SDP 称为保持的SDP。
当应答者对保持的SDP 响应保持的SDP, 那么某些第三方呼叫控制将不再起作用。
典型地, 当用户启动保持时, 代理将产生提供,SDP 中所有的媒体流为只发, 同时本地静音, 以便不向远端发送媒体,也不播放任何媒体。
当提供者在创建初始提供时想使用特定一组媒体流和媒体格式,但不知道媒体流的地址和端口号, 此时可以将连接地址设置为0.0.0.0 。但此时端口号不能设置为0。代理必须能够接收连接地址为
0.0.0.0 的SDP,此时不应向对等发送RTP 和RTCP 。
F.8 指示能力集
代理发送提供前, 如果知道应答者是否可接受提供中的媒体格式将很有用。某些协议, 如SIP ,提供一种查询能力集的方式。在对查询的响应中可以使用SDP 指示能力集。本节描述如何创建该SDP 消息。SDP 不能指示该消息用于能力集指示,需要从高层协议上下文中确定。SDP 指示能力集的能力非常有限。它不能表示允许的参数范围或参数值,也不能在相关的提供/应答中指示。
指示媒体能力集的SDP 组成如下。除了可以省略"e=" 和"p=" 之外, 它必须是有效的SDP 。"t="行必须等于"0 0" 。对于代理支持的每个媒体类型,必须有相应的媒体描述。对于每个用于指示媒体能力集的SDP 初始字段中的会话ID 都必须唯一。端口号必须等于0, 但是连接地址可以为任意值。如果该消息被当作提供或应答,端口号为0 确保用于指示媒体能力集的SDP 不会引起媒体流的建立。
"m="行的传输协议部分指示媒体类型的传输协议。对于代理所支持的媒体类型的每个媒体格式, 在"m="行都应列出。在使用RTP 的情况下, 如果使用动态载荷类型,那么必须包含rtpmtp 属性,以便将媒体类型绑定到特定的格式。这里没有办法对限制进行描述,例如对于特定的编解码可以同时支持多少媒体流,等等。
v=0
o=carol 28908764872 28908764872 IN IP4 100.3.6.6
s=-
t=0 0
c=IN IP4 192.0.2.4
m=audio 0 RTP/AVP 0 1 3
a=rtpmap:0 PCMU/8000
a=rtpmap:1 1016/8000
a=rtpmap:3 GSM/8000
m=video 0 RTP/AVP 31 34
a=rtpmap:31 H261/90000
a=rtpmap:34 H263/90000
图1 指示能力集的SDP
图1 中的SDP 指示代理可以指示三种音频编码(PCMU 、1016 和GSM) 以及两种视频编码(H.261 和H.263)。
.F.9 提供/应答交互示例
.F.9.1 基本的交互

假设主叫Alice 在她的提供中包含下列SDP 描述。其中包含一个双向音频流和两个双向视频流( 视频流分别使用编解码H.261(载荷类型31)和MPEG(载荷类型32 。
v=0
o=alice 2890844526 2890844526 IN IP4 host.anywhere.com
s=
c=IN IP4 host.anywhere.com
t=0 0
m=audio 49170 RTP/AVP 0
a=rtpmap:0 PCMU/8000
m=video 51372 RTP/AVP 31
a=rtpmap:31 H261/90000
m=video 53000 RTP/AVP 32
a=rtpmap:32 MPV/90000
被叫Bob 不希望接收或发送第一个视频流,那么他将在应答中返回如下SDP:
v=0
o=bob 2890844730 2890844730 IN IP4 host.example.com
s=
c=IN IP4 host.example.com
t=0 0
m=audio 49920 RTP/AVP 0
a=rtpmap:0 PCMU/8000
m=video 0 RTP/AVP 31
m=video 53000 RTP/AVP 32
a=rtpmap:32 MPV/90000
之后的某个时刻,Bob 想改变音频流的接收端口(从49920 改为65422),同时增加另外一个只收音频流,并使用RTP 载荷类型,那么Bob 将在提供中包含如下SDP:
v=0
o=bob 2890844730 2890844731 IN IP4 host.example.com
s=
c=IN IP4 host.example.com
t=0 0
m=audio 65422 RTP/AVP 0
a=rtpmap:0 PCMU/8000
m=video 0 RTP/AVP 31
m=video 53000 RTP/AVP 32
a=rtpmap:32 MPV/90000
m=audio 51434 RTP/AVP 110
a=rtpmap:110 telephone-events/8000
a=recvonly
Alice 接收增加的媒体流,将产生如下应答:
v=0
o=alice 2890844526 2890844527 IN IP4 host.anywhere.com
s=
c=IN IP4 host.anywhere.com
t=0 0
m=audio 49170 RTP/AVP 0
a=rtpmap:0 PCMU/8000
m=video 0 RTP/AVP 31
a=rtpmap:31 H261/90000
m=video 53000 RTP/AVP 32
a=rtpmap:32 MPV/90000
m=audio 53122 RTP/AVP 110
a=rtpmap:110 telephone-events/8000
a=sendonly

F.9.2 从N 个编解码中选择一个
嵌入式呼叫中的一个共同现象是用于压缩信号的数字信号处理器(DSP) 可以同时支持多个编解码, 但是一旦选择了一个编解码,就不能轻易地改变。下面的示例说明使用初始提供/应答交互如何建立对话,随后如何立即通过第二个提供/应答的交互来确定编解码。
从Alice 发送的Bob 的初始提供指示单个的音频流可以使用DSP 所支持的三个音频编解码。该流被标记为未激活,因为在确定下编解码之前不能接收媒体。
v=0
o=alice 2890844526 2890844526 IN IP4 host.anywhere.com
s=
c=IN IP4 host.anywhere.com
t=0 0
m=audio 62986 RTP/AVP 0 4 18
a=rtpmap:0 PCMU/8000
a=rtpmap:4 G723/8000
a=rtpmap:18 G729/8000
a=inactive
Bob 可以支持PCMU 和G.723 之间的动态交换,所以他发送以下应答:
v=0
o=bob 2890844730 2890844731 IN IP4 host.example.com
s=
c=IN IP4 host.example.com
t=0 0
m=audio 54344 RTP/AVP 0 4
a=rtpmap:0 PCMU/8000
a=rtpmap:4 G723/8000
a=inactive
Alice 可以选择这两个编解码中的任何一个。所以她发送更新的提供,媒体流为收发:
v=0
o=alice 2890844526 2890844527 IN IP4 host.anywhere.com
s=
c=IN IP4 host.anywhere.com
t=0 0
m=audio 62986 RTP/AVP 4
a=rtpmap:4 G723/8000
a=sendrecv

Bob 接收该编解码: v=0 o=bob 2890844730 2890844732 IN IP4 host.example.com s= c=IN IP4 host.example.com t=0 0 m=audio 54344 RTP/AVP 4 a=rtpmap:4 G723/8000 a=sendrecv 如果应答者(Bob) 只能支持N 个编解码中的一个,Bob 将选择这个编解码, 并且将包含在应答中。
此时Alice 将重新发送INVITE 方法来激活使用该编解码的媒体流。
一种替换方式是在初始的交互中使用"a=inactive", 并列出所有的编解码, 并且一旦从Bob 接收到媒体,Alice 就产生更新的提供, 并使用接收媒体的编解码。如果Bob 只支持N 个编解码中的一个,此时就不需要重新发送INVITE 方法来激活使用该编解码的媒体流。
F.10 安全考虑
如果攻击者在提供或应答交互过程中能够修改它们, 那么可能产生大量的攻击。通常包括转移媒体流(以便监听),使呼叫中止,以及插入不期望的媒体流。如果被叫方创建假的提供,并插入到交互过程中, 也可以产生类似的攻击。即使攻击者只能简单地观察提供者和应答者, 他们仍然能向存在的对话中插入媒体流。
提供/应答依赖于应用信令协议中的传输协议,如SIP 。也依赖于该传输协议提供的安全机制。为防止上述攻击,传输协议必须提供端到端的鉴权和对提供应答完整性的保护。该协议应提供对消息体的加密来防止监听。
重发攻击也是一个问题。攻击者可能重发过时的提供,如使媒体流进入保持状态的提供, 从而使对话中的媒体流不能传送媒体。因此应用协议必须提供安全机制来顺序排列提供和应答,以便检测并拒绝过时的提供或应答。
附录 G (标准性附录)
特定事件的通知
通过该机制SIP 节点可以请求远端节点发送通知指示某些事件已经发生。
G.1 简介
请求异步通知事件的能力在许多端节点间需要互操作的SIP 业务中非常有用。这类业务的例子包括自动回叫业务(基于终端状态事件)、朋友列表(基于用户presence 事件)、消息等待指示(基于邮箱状态改变事件)和PSTN 与Internet 互通(PINT) 状态(基于呼叫状态事件)。
本文描述的方法提供了规定通知这些事件的框架。
此处定义的事件通知机制不想作为所有类型事件定制和通知机制的基础。本文旨在对事件通知提供一种特定的SIP 框架。基于该框架的事件包可以任意定义详细的规则,规定事件或事件类别的定制和通知机制。
本文不描述可以直接使用的扩展,需要其他文档(本文称为“事件包”)进行扩展。
G.1.1 操作概述
对于网络中的各种资源或呼叫,网络中的实体可以定制资源或呼叫状态,当状态改变时这些实体可
能发送通知消息。
典型的消息流程如下所示:
定制者 通知者
|-----SUBSCRIBE---->| 请求状态定制
|<-------200--------| 证实定制
|<------NOTIFY----- | 返回当前状态信息
|--------200------->|
|<------NOTIFY----- | 返回当前状态信息
|--------200------->|

定制消息可能超时而必须使用后续的SUBSCRIBE 消息刷新。
G.2 定义
事件包: 事件包是附加的规范, 用于定义通知者向定制者报告的状态信息集。基于本文定义的框架事件包也定义用于传递状态信息的语法和语义。
事件模板包: 一种特定类型的事件包, 定义可用于所有可能事件包的一组状态,包括事件模板包本身。
通知:通知指的是通知者向定制者发送NOTIFY 消息以便通知定制者资源的状态。
通知者:通知者是产生NOTIFY 请求的用户代理,目的是通知定制者资源的状态。通常通知者接收SUBSCRIBE 请求来产生定制。
状态代理: 状态代理是发布表示资源状态信息的通知者; 为此状态代理可能需要从多个源搜集相关的状态信息。状态代理要一直为那些创建通知的资源保持完整的状态信息。
定制者:定制者是从通知者接收NOTIFY 请求的用户代理。这些通知请求包含定制者关心的资源的状态信息。通常定制者产生SUBSCRIBE 请求, 并向通知者发送该请求以便产生定制。
定制:定制是和对话相关的一组应用状态。该应用状态包含一个指向相关对话的指针和事件包名, 还可能包含一个标记。事件包定义附加的定制状态信息。通过定义,定制可以在定制者和通知者中同时存在。
146
定制转移:定制转移是将定制从一个通知者转移到另一个通知者的动作。
.G.3 节点行为
.G.3.1 SUBSCRIBE 行为定义

SUBSCRIBE 方法用于请求远端节点的当前状态和状态更新。
G.3.1.1 定制持续时间
SUBSCRIBE 请求应包含"Expires" 头部字段。该字段的值指示定制持续时间。为了在该持续时间之外保持该定制有效,定制者需要对同一个对话发送新的SUBSCRIBE 消息周期性地刷新定制。
如果SUBSCRIBE 请求中不包含"Expires" 头部字段, 那么将使用该事件包定义的缺省值。
SUBSCRIBE 请求的200 类响应也必须包含"Expires" 头部字段。响应中该字段的值可以较小,但不能大于请求中指定的值。响应中该字段的值定义了定制的持续时间。
对于SUBSCRIBE 请求"Contact" 头部字段中的"expires" 参数没有意义,并且不必和SUBSCRIBE 请求或响应中的"Expires" 头部字段相等。
"Expires" 等于0 的SUBSCRIBE 请求不定制事件,但可以使对端回送状态信息。
通知者可能想取消对事件的定制,例如定制涉及的资源不再有用。
G.3.1.2 定制事件或事件类别的标识
事件的标识包含三个信息:Request URI 、事件类型和消息体(任选的)。
SUBSCRIBE 请求的Request URI 最重要,其中包含足够的信息以便将请求选路到适当的实体,其中也包含足够的信息来标识定制者期望从它获得事件通知的资源,但是不需要该URI 必须唯一地标识事件特性(例如:"sip:adam@dynamicsoft.com" 可用于定制我的presence 状态也可以定制我语音信箱的当前状态)。
定制者在SUBSCRIBE 请求中必须包含且仅包含一个"Event" 头部字段,指示定制哪种事件或事件类型。"Event" 头部字段将包含一个标记指示定制所请求的状态类型。该标记将对应到一个事件包。"Event" 头部字段也可以包含"id"参数。如果包含该参数, 那么该参数中应包含标识对话中特定定制的标记。该参数仅在单个对话中有效。
如果事件标记对应的事件包定义和SUBSCRIBE 请求体相关的行为,应用这些语义。
事件包可以定义Event 头部字段的参数;若定义相关的参数也必须定义参数的语义。
G.3.1.3 其他的SUBSCRIBE 头部值
因为SUBSCRIBE 请求创建对话,所以该请求可以包含"Accept" 头部字段。该字段指示后续NOTIFY 请求中允许的消息体格式。事件包必须定义未包含"Accept" 字段的SUBSCRIBE 请求的行为和缺省的消息类型。
.G.3.1.4 定制者SUBSCRIBE 行为
.G.3.1.4.1 请求定制

SUBSCRIBE 是一种对话创建机制。
当定制者想定制某个资源的特定状态时, 将形成SUBSCRIBE 消息。如果初始SUBSCRIBE 表示对话之外的请求,创建该消息的程序和在对话外产生UAC 请求相同。
SUBSCRIBE 请求有最终响应确认。200 类响应指示定制被接受, 并立即发送NOTIFY 消息。200 响应指示定制被接受并且用户已经认可对请求资源的定制源。202 响应仅指示定制被接受, 但并不保证用户是否认可该定制。
200 类响应中的"Expires" 头部字段指示定制保持激活的实际持续时间(除非被刷新)。
非200 类最终响应指示没有创建任何订制或对话,并且不发送后续NOTIFY 消息。所有非200 类响应有相同的意义。
SUBSCRIBE 请求可以在"Event" 头部字段中包含"id"参数, 以便允许在同一个对话中区分多个定制。
G.3.1.4.2 刷新定制
定制超时之前的任何时刻,定制者可以通过在同一个对话上发送另一个与当前定制相同的SUBSCRIBE 请求来刷新定制的定时器,该定制具有相同的"Event"头部字段和"id"参数(如果初始提供中包含。除了下面的描述,对该请求的处理和对最初创建定制的处理相同。
如果初始SUBSCRIBE 消息在"Event"头部字段中包含"id"参数,那么刷新的定制也必须包含相同的"id"参数;否则该定制将被认为是对话中的新的定制。
如果用于刷新定制的SUBSCRIBE 请求收到"481"响应,那么表明定制已经终止但定制者没有收到相关的通知。在这种情况下,定制者应认为定制无效。如果定制者想重新订制该状态,可以创建一个不相关的初始SUBSCRIBE 请求,该请求包含新产生的Call-ID 和新的且唯一的"From"标记。
如果用于刷新定制的SUBSCRIBE 请求收到非481 类失败响应,那么通过SUBSCRIBE 请求及其响应协商,或通过在"Subscription-State"头部字段中包含"expires"参数的NOTIFY 的交互,最近确定的"Expires"持续时间之内原来的定制仍然有效。
在网络或通知者出现故障的情况下可以收不到NOTIFY 消息。
G.3.1.4. 未定制
对"Expires"头部字段为0 的未定制的处理和对刷新定制的处理相同。成功的未定制可能触发最后的NOTIFY 消息。
G.3.1.4.4 定制创建的确认
定制者可能期望从每个处理成功的定制或定制刷新的节点收到NOTIFY 消息。在收到第一个NOTIFY 消息之前,定制者认为被定制资源的状态处于中间状态。对应的事件包应对中间状态进行定义。
由于可能存在失序的消息和分支的消息,定制者必须准备在SUBSCRIBE 事务处理完成之间接收NOTIFY 消息。
G.3.1.5 代理服务器SUBSCRIBE 行为
除了要支持SUBSCRIBE 外,代理服务器不需要其他的行为。如果对于特定的对话代理服务器想看到所有的SUBSCRIBE 和NOTIFY 请求那么它必须在初始SUBSCRIBE 请求和任何建立对话的NOTIFY 请求中包含record-route 字段。同样代理服务器也应在所有其他SUBSCRIBE 和NOTIFY 请求中包含record-route 字段。
.G.3.1.6 通知者SUBSCRIBE 行为
.G.3.1.6.1 初始SUBSCRIBE 事务处理

SUBSCRIBE 事务处理不应比自动处理所需的时间长。特别是通知者在向SUBSCRIBE 请求返回最终响应之前不必等待用户响应。
这主要是防止非INVITE 事务处理超时定时器F 在SUBSCRIBE 事务处理期间不起作用,因为和用户交互的事务处理经常超过64*T1 秒。
通知者应确认"Event"头部字段中规定的事件包可理解。如果不能理解,通知者应返回"489 错误事件"响应来指示不理解规定的事件/事件包。
通知者应基于本地策略执行所有必需的鉴权和认证。
通知者也应确认"Expires"头部字段中的持续时间不太小。如果超时间隔大于0 小于一小时并且小于通知者配置的最小值,只有在这种情况下通知者可以返回"423 间隔太小",并且包含"Min-Expires" 头部字段。
如果通知者能够立即确认它理解该事件包确认通过认证的定制者有权定制,并且确认在创建定制前不再需要其它操作,那么通知者将创建定制和对话(如果需要)并返回"200 OK"响应(除非这样做不期望地暴露了认证策略。
如果通知者不能立即创建定制(例如:它需要等待用户的输入进行认证,或者正作为另一个节点而不能接入),或者想掩饰认证策略,那么它将返回"202 Accepted"。该响应指示SUBSCRIBE 请求已被接受和理解,但没有标明定制是否已经经过认证
当通知者创建了定制它将保存事件包名和"Event" 头部字段"id"参数(如果SUBSCRIBE 请求中包含)病最为定制信息的一部分。
SUBSCRIBE 200 类响应中的"Expires" 值和REGISTER 响应中的"Expires" 值同样处理:服务器可以缩短该间隔,但一定不能大于该间隔。
如果SUBSCRIBE 消息中规定的持续时间太短而不能接受,通知者可能发送响应423。
SUBSCRIBE 请求的200 类响应除了定制持续时间之外通常不包含任何有用信息。状态信息将通过通知者发送的后续NOTIFY 请求进行交互。
适当地,也可以使用其他的响应代码响应SUBSCRIBE 请求。
G.3.1.6.2 定制创建/刷新的确认
一旦成功地接受或刷新定制,通知者必须立即向定制者发送NOTIFY 消息来通知资源的当前状态。NOTIFY 消息可以在SUBSCRIBE 响应创建的相同对话上发送。如果在处理SUBSCRIBE 消息时资源所具有的状态没有意义,那么该NOTIFY 消息可以包含空的或中立的消息体。
对SUBSCRIBE 请求发送了某个200 类响应之后总是立即发送NOTIFY 消息, 而不管该定制是否已经经过认证。
G.3.1.6.3 SUBSCRIBE 请求的鉴权/认证
通知者用来确定特定的定制者是否有权定制某些事件的策略应该保密。可以通过接入控制列表或和用户进行实时交互等机制来定义相关策略。
当接收定制和发送通知时通知者总是作为用户代理。
如果根据接入列表或某自动机制( 即它能够自动进行认证确定定制者无权进行定制) 认证失败, 那么通知者应响应"403 Forbidden" 或"603 Decline", 除非这样做暴露和策略相关的信息。
如果需要查询提供者的用户来确定是否允许定制, 那么将立即返回"202 Accept" 响应, 此时仍要发送NOTIFY 消息。
如果定制的认证被推迟并且通知者希望传送该定制被拒绝的信息,那么它将发送包含"Subscription-State" 头部字段的NOTIFY 消息, 该字段的值为"terminated" 原因参数为"rejected" 。
G.3.1.6.4 定制的刷新
当通知者收到定制刷新时, 假设定制者仍然有权, 那么通知者将更新定制的超时时间。和初始定制相同,服务器可以缩短超时时间但不能增加。最终的超时时间包含在响应的"Expires" 头部字段中。如果SUBSCRIBE 消息中规定的持续时间太小而不能接受,那么通知者应响应"423 Subscription Too Brief" 消息。
如果在超时时间之前通知者没有收到定制的刷新, 那么应删除定制。当删除定制时, 通知者应发送包含"Subscription-State" 头部字段且其值为 "terminated" 的NOTIFY 消息,通知定制已经被删除,并且"Subscription-State" 头部字段应包含"reason=timeout" 参数。
当定制超时时,如果适当,NOTIFY 的发送允许终止相应的对话。
G.3.2 NOTIFY 行为的描述
发送NOTIFY 消息通知定制者它所订制的资源的状态发生改变。产生定制一般使用SUBSCRIBE 方法, 但是也有可能使用别的方式。
如果定义了产生定制的某些非SUBSCRIBE 机制,那么确保NOTIFY 消息和相应定制之间能够进行关联是定义这些机制的实体的责任。这些机制的设计者应注意区分向意识到定制的定制者发送NOTIFY 消息和向信任的节点发送NOTIFY 消息。后面的行为是无效的,必须接收响应"481 定制不存在"(除非其他的400 或500 类差错码更适当)。也就是说, 定制者和通知者必须都知道定制才有效,即使是通过非SUBSCRIBE 机制进行的定制。
NOTIFY 不能终止相应的定制, 即一个SUBSCRIBE 请求可能触发多个NOTIFY 请求。
G.3.2.1 报告的事件、事件类别和当前状态的标识
通知消息中报告的事件的标识和定制对事件的描述相似。
和SUBSCRIBE 请求相同,NOTIFY 消息中的"Event" 头部字段将包含一个事件包名,NOTIFY 消息就是针对该事件包产生的。"Event" 头部字段中的事件包名必须和相应SUBSCRIBE 消息中"Event" 头部字段中
149
的事件包名相匹配。如果SUBSCRIBE 消息中包含"id" 参数,那么在相应的NOTIFY 消息中也必须包含"id" 参数。
事件包可以定义和NOTIFY 请求的消息体相关的语义;若如此将遵循事件包定义的语义。期望消息体提供和发生事件的属性及导致的资源状态相关的其他详细信息。
NOTIFY 请求中的消息体必须按照相应SUBSCRIBE 请求中"Accept" 头部字段规定的某个消息体格式进行构造。该消息体将包含定制资源的状态或以URI 形式表示的到该状态的指针。
G.3.2.2 通知者NOTIFY 行为
当向SUBSCRIBE 请求发送了200 类响应,通知者必须立即创建并向定制者发送NOTIFY 请求。当定制的状态发生改变时,通知者应立即创建并发送NOTIFY 请求,并考虑到认证、本地策略和取消机制。
如果响应超时,或收到非200 类响应,该响应未包含"Retry-After" 头部字段且没有暗示可以采取进一步的动作以便重新尝试该请求(例如:响应"401 要求认证"),则认为NOTIFY 请求失败。
如果由于超时NOTIFY 请求失败,并且是使用软状态机制(如使用SUBSCRIBE 请求)进行的定制,那么通知者应删除该定制。
这种方式可以避免向已经故障或已经在网络中不存在的定制者发送不必要的状态信息。基于重传机制该消息可能被发送多次,但是没有用户端对消息进行证实,此时连续地发送这些消息可能会导致网络的过负荷。一旦客户端开始重启或重新建立网络连接,客户端应发送SUBSCRIBE 消息来刷新已经过时的状态信息,这些消息将在所有相关的节点中重新设置定制。
如果由于差错响应NOTIFY 请求失败,并且是使用软状态机制设置定制,那么通知者必须删除相应的定制。
通知的差错响应通常指示定制者或者是到定制者所经由的某个代理服务器上发生了差错。如果定制者发生差错, 一旦差错情况消除那么应允许定制者重新进行定制。如果代理服务器发生差错, 一旦该网络问题解决,那么周期性的SUBSCRIBE 刷新将重新设置定制状态。
如果NOTIFY 请求收到响应481, 那么通知者必须删除相应的定制,即使该定制时通过非SUBSCRIBE 方式(如通过管理接口)进行的设置。
NOTIFY 请求必须包含"Subscription-State" 头部字段,且该字段的值可以为"active" 、"pending" 或"terminated" 。值为"active" 指示已经接受定制并已经对定制进行了认证。值为"pending" 指示已经收到定制,但此时还没有足够的策略信息来接受或拒绝定制。值为"terminated" 指示定制未激活。
如果"Subscription-State" 头部字段的值为"active" 或"pending" ,那么通知者应在"Subscription-State" 头部字段中包含"expires" 参数指示定制还可以持续的时间。通知者可以使用该机制来缩短定制的持续时间,但是该机制不能用来增加定制的持续时间。
如果"Subscription-State" 头部字段的值为"terminated", 那么通知者应包含"reason" 参数。如果适当通知者也可以包含"retry-after" 参数。
G.3.2.3 代理服务器NOTIFY 行为
除了要支持NOTIFY 之外, 代理服务器不需要其它行为。如果对于某个对话代理服务器想看到所有的SUBSCRIBE 和NOTIFY 请求,那么它必须在初始SUBSCRIBE 和所有建立对话的NOTIFY 请求中包含record-route 字段。该代理在所有其它SUBSCRIBE 和NOTIFY 请求中也应包含record-route 字段。
G.3.2.4 定制者NOTIFY 行为
一旦收到NOTIFY 请求,定制者应确认该请求至少和一个已经存在的定制相匹配。如果没有相匹配的定制, 那么定制者必须返回响应"481 不存在", 除非其它更恰当的400 类或500 类响应。如果通知消息和在对话内创建的定制在相同的对话中且"Event" 头部字段相匹配,那么该通知消息和该定制相匹配。
如果由于某些原因不支持NOTIFY 请求中"Event" 头部字段指定的事件包,那么定制者将响应”489 错误事件”。
要防止虚假事件,应使用定义的SIP 鉴权机制对NOTIFY 请求进行鉴权。
NOTIFY 请求必须包含"Subscription-State" 头部字段来指示定制的状态。
如果"Subscription-State" 头部字段的值为"active", 那么表明该定制已经被接受( 通常)并且已经经过认证。如果该头部字段包含"expires" 参数, 那么定制者应将该参数的值作为定制的持续时间并相应地对定制进行调整。此时"retry-after" 参数和"reason" 参数没有意义。
如果"Subscription-State" 头部字段的值为"pending" ,那么表明通知者已经收到定制,但还没有足够的策略信息来接受或否定该定制。如果该头部字段包含"expires" 参数, 定制者应将该参数的值作为定制的持续时间并相应地对定制进行调整。定制者不需要采取进一步的动作。此时"retry-after" 参数和"reason" 参数没有意义。
如果"Subscription-State" 头部字段的值为"terminated", 那么定制者应认为该定制已经终止。此时"expires" 参数没有意义。如果包含原因码,那么定制者采取下面描述的行为。如果不包含原因码或不知道原因码,定制者应随时尝试重新进行定制(当包含"retry-after" 参数时,定制者应该在该参数规定的时间之后尝试重新进行定制)。定义的原因码有:
去激活:定制已经终止,但是定制者应该立即重试新的定制。该原因码主要用于在节点之间进行定制的转移。此时"retry-after" 参数没有意义。
试用:定制已经终止,但定制者应在一段时间之后重试。如果包含"retry-after" 参数,那么定制者在尝试重新定制之前至少应等待一段该参数规定的时间。
拒绝:由于认证策略的改变定制已经终止。定制者不应尝试重新进行定制。此时"retry-after" 没有意义。
超时:由于在定时器超时之前没有对定制进行刷新而导致该定制已经终止。定制者可以立即重新开始定制。此时"retry-after" 没有意义。
放弃:由于通知者不能及时获得认证而导致该定制已经终止。如果包含"retry-after" 参数,定制者在尝试重新定制之前应至少等待一段该参数规定的时间;否则,定制者可以立即进行尝试,但定制可能进入Pending 状态。
没有资源: 由于要监视的资源的状态不再存在而导致定制终止。定制者不应尝试重新进行定制。此时"retry-after" 没有意义。
一旦定制者确认通知可接受,那么定制者应返回响应200。通常,NOTIFY 的响应不包含消息体,但是如果NOTIFY 请求包含"Accept" 头部字段那么响应可以包含消息体。
如何适当,也可以返回其它响应。但是NOTIFY 事务处理不能比自动处理所需要的时间长。特别地, 在返回NOTIFY 请求的最终响应之前不必等待用户响应。
.G.3.3 综述
.G.3.3.1 确定对SUBSCRIBE 和NOTIFY 的支持

SUBSCRIBE 和NOTIFY 不一定要使用"Require" 、"Proxy-Require" 或"Supported" 头部字段。如果需要,客户端可以使用OPTIONS 请求来探测对SUBSCRIBE 和NOTIFY 的支持。
在消息中包含"Allow-Events" 头部字段足以指示对SUBSCRIBE 和NOTIFY 的支持。
注册时在Contact 字段中包含"methods" 参数也可以用来指示对SUBSCRIBE 和NOTIFY 的支持。
G.3.3.2 CANCEL 请求
没有和取消SUBSCRIBE 或NOTIFY 相关的语义。
G.3.3.3 分支
要符合代理非INVITE 请求的规则,成功的SUBSCRIBE 请求应只收到一个200 类响应,但是由于分支,可能有多个节点收到定制。因此定制者必须准备接收"From" 标记和SUBSCRIBE 的200 类响应中的"To" 标记不同的NOTIFY 请求。
如果在不同的对话中收到多个响应某个SUBSCRIBE 消息的NOTIFY 消息,那么每个对话表示SUBSCRIBE 请求分支到的不同目的地。
G.3.3.4 对话创建和终止
如果初始SUBSCRIBE 请求不在已经存在的对话上发送,那么定制者将等待SUBSCRIBE 请求的响应或者是匹配的NOTIFY 消息。
如果SUBSCRIBE 请求和响应中包含相同的"Call-ID" 、相同的"From" 标记和相同的"CSeq" ,那么该响应和该请求相匹配。如果200 类响应和该SUBSCRIBE 请求匹配,那么该响应将创建新的定制和新的对话(除非已经由匹配的NOTIFY 请求创建)。
如果NOTIFY 请求和该SUBSCRIBE 请求包含相同的"Call-ID" 、和SUBSCRIBE 请求中"From" 标记相同的"To" 标记、相同的"Event" 头部字段,那么该NOTIFY 请求和该SUBSCRIBE 请求相匹配。如果匹配的NOTIFY 请求包含"Subscription-State" 头部字段, 且该字段的值为"active" 或"pending", 那么该请求将创建新的定制和新的对话(除非已经由匹配的响应创建)。
如果初始SUBSCRIBE 请求是在已经存在的对话上发送,那么匹配的200 类响应或成功的NOTIFY 请求只创建和该对话相关的新的定制。
可能有多个定制和单个对话相关。定制也可能存在于由INVITE 创建的应用状态和由其他机制创建的应用状态相关的对话中。这些应用状态在对话的行为之外不进行交互(例如:路由组处理)。
当通知者发送包含"Subscription-State" 字段且该字段的值为"terminated" 的NOTIFY 请求时,该定制终止。
定制者可以发送包含"Expires" 头部字段且该字段的值为零的SUBSCRIBE 请求来触发NOTIFY 请求的发送。但是考虑到定制和对话的生存时间,在发送包含"Subscription-State" 字段且该字段的值为"terminated" 的NOTIFY 请求之前,将不认为定制已经终止。
如果定制终止后没有其他和对话相关的应用状态,那么对话也终止。如果仍然有定制和对话相关, 那么其他应用状态(如由INVITE 请求创建的应用状态)的终止将不会终止对话。
即当收到BYE 时不一定终止由INVITE 创建的对话。同样,如果一个对话有多个相关的定制,在该对话中的所有定制终止之前不终止对话。
G.3.3.5 状态代理和通知者转移
当使用状态代理时, 允许定制在状态代理和节点( 状态代理正在为这些节点提供状态汇聚, 或者在多个状态代理中提供状态汇聚)间进行转移将非常有用。通过发送包含"Subscription-State" 头部字段且值为"terminated" 原因参数为"去活"的NOTIFY 消息可以实现该类转移。
当收到这个NOTIFY 消息时,定制者应尝试重新进行定制。该定制将在新的对话上建立,并且不会再使用先前定制对话中的路由集。
通过改变一个或多个服务器向节点发送SUBSCRIBE 请求的策略(如选路策略),使另一个不同的节点来响应该SUBSCRIBE 请求,可以产生实际的转移。此时仅简单地利用通知者内的本地策略来实现定制的转移,此时通知者是作为代理服务器或重定向服务器。
是否执行通知者转移、什么时候执行、为什么执行转移可以在单独的事件包中进行描述; 另外决定转移是本地通知者的策略问题,将依赖于具体实现。
G.3.3.6 查询资源状态
可以通过发送包含"Expires" 字段且值为0 的SUBSCRIBE 消息实现不建立定制而立即返回相关的状态。
当定制激活时,也可以通过发送包含"Expires" 字段,且该字段的值等于定制剩余持续时间的SUBSCRIBE 消息实现立即返回相关的状态。
当收到这个SUBSCRIBE 请求时,通知者将在相同对话中发送包含资源状态的NOTIFY 请求。
由包含"Expires" 头部字段且值为0 的SUBSCRIBE 消息触发的NOTIFY 消息将包含值为“终止”的"Subscription-State" 字段且其中的原因参数为“超时”。
事件状态的查询将在很大程度上增加网络和通知者的负荷, 所以应该谨慎使用。特别地, 当查询导致比长期运行的定制还要多的网络消息时不应使用。
当使用事件状态的查询时,定制者应尝试缓存查询过程中的鉴权凭证以便减少发送消息的数目。
G.3.3.7 Allow-Events 头部字段的用法
"Allow-Events" 头部字段中包含一个标记列表,指示客户端( 如果在请求中发送)或服务器( 如果在响应中发送)所支持的事件包。也就是说,发送"Allow-Events" 头部字段的节点表明它能够处理SUBSCRIBE 请求并能对字段中列出的所有事件包产生NOTIFY 请求。
任何实现一个或多个事件包的节点都应包含适当的"Allow-Events" 头部字段,指示在所有启动对话、响应(如INVITE )和OPTIONS 响应的方法中所支持的所有事件。
这个信息非常有用, 例如,允许用户代理根据节点是否支持需要某些特定性能的事件而决定适当地放弃特定的接口单元,此时该信息非常有用。
代理服务器不能插入"Allow-Events" 头部字段。
G.3.3.8 PINT 兼容性
"Event" 头部字段是必需的。但是要保证和PINT 的兼容性,当请求定制PINT 事件时,服务器可能需要解释未包含"Event" 头部字段的SUBSCRIBE 请求。如果服务器不支持PINT,那么它应对未包含"Event" 头部字段的SUBSCRIBE 消息返回"489 错误事件"。
G.4 事件包
本节描述当设计基于SUBSCRIBE 和NOTIFY 的事件包时需要考虑的几个问题。
G.4.1 用法的适当
当使用本文中描述的方法为事件通知设计事件包时, 重点需要考虑:对于问题集SIP 是否是一个适当的机制;是否由于SIP 提供一些特殊的机制而选用它,或者仅仅是因为“它能够做到”。
另外在事件报告频率太快(例如:一秒多于一次)的应用中不要使用这个机制。
G.4.2 事件模板包
正常情况下, 事件包定义一组应用于特定资源类型的状态, 例如用户在线、呼叫状态和消息信箱状态。
事件模板包是一种特殊类型的包, 它定义的是一组应用于其他包的状态, 例如统计、接入策略和用户列表。事件模板包甚至可以应用于其它的事件模板包。
用于包的事件模板包的名字可以在该包名字之后加一个小圆点再加上事件模板包的名字。例如,如果事件模板包"winfo" 正应用于包"presence",那么"Event" 和"Allow-Events" 字段中使用的该事件标记应为"presence.winfo" 。
必须定义事件模板包,以便它们可用于任何包。事件模板包不能特定地绑定到一个或几个“ 父” 包上,这样该模板包将不能与其他包同时起作用。
G.4.3 要传送的状态的数量在设计事件包时,重点要考虑要在通知中传送的消息类型。一个很自然的考虑是只传送事件(例如:“收到新的语音消息”) 而不传送相关的状态(例如:“共
7 个语音消息”)。这样使定制实体的实现复杂化(因为这样它们必须维护所订制的实体的完整状态), 而且易产生同步问题。事件包可以选用两种解决方案。
G.4.3.1 全部的状态信息
包一般传送的状态信息很少(1kb 左右),因此可以设计事件包使得当事件发生时发送全部的状态信息。
在有些情况下, 仅传送当前状态信息对于特殊类型的事件来说可能是不够的。在这些情况下, 事件包应在包含发生的事件同时包含全部的状态信息。例如,传送“没有客户服务表示可用“可能没有传送“没有客户服务表示可用;表示层sip:46@cs.xyz.int 已注销”有用。
G.4.3.2 状态差异
当要传送的状态信息很大时,事件包可以选择采用细化的方案, 在NOTIFY 消息中包含状态差异而非全部的状态信息。
该方案可如下操作:在立即响应SUBSCRIBE 的NOTIFY 消息中包含所有的状态信息;由于状态改变而发送的NOTIFY 消息仅包含改变的状态信息,定制者将该信息合并到和资源的状态相关的当前证实中。
任何支持状态差异的事件包必须包含版本号,并且对于定制中的每个NOTIFY 事务处理该值递增。版本号包含在消息的消息体中,而不在SIP 的头部。
如果收到版本号增加值大于1 的NOTIFY 消息, 那么定制者就知道丢失了状态差异;此时它将忽略该消息(但记录版本号,以便于检测消息丢失), 并重新发送SUBSCRIBE 消息强制对方发送包含完全状态的NOTIFY 消息。
G.4.4 事件包的责任
不要求事件包实现本文中描述的所有行为。通常, 某些事件包只用于描述对本为中的行为进行扩展或修改的行为。
G.4.4.1 事件包名
必须要定义用于指示事件包的标记名且必须包含在标记的IANA 注册中的信息。
G.4.4.2 事件包参数
如果在"Event" 头部字段中使用参数来修改事件包的行为,必须明确定义该头部字段的语法和语义。
G.4.4.3 SUBSCRIBE 体
大部分事件包而不是所有的事件包将定义SUBSCRIBE 方法体的语法和语义, 这些消息体通常要修改、扩充、过滤、终止、和/或设置所请求的该类事件的门限。对消息体事件包的设计者应尽量使用存在的MIME 类型。
在事件包中必须定义在SUBSCRIBE 请求中包含的事件体的类型(或者规定不包含事件体)。对于引用的所有事件体类型应规定详细的语法和语义。
G.4.4.4 定制持续时间
建议事件包给出定制持续时间
G.4.4.5 NOTIFY 消息体
NOTIFY 消息体用于报告所监视的资源的状态。每个事件包必须定义在NOTIFY 请求中包含的事件体的类型。该事件包必须对和该事件体相关的语法和语义进行详细规定或者是引用详细的规定。
事件包必须定义当SUBSCRIBE 请求的"Accept" 头部字段中没有规定MIME 类型时所采用的默认MIME 类型。
G.4.4.6 处理SUBSCRIBE 请求的通知者
事件包中必须包含对通知者收到SUBSCRIBE 请求时执行处理的描述。
包括如何对定制者进行鉴权和对包进行认证的问题。例如,认证问题可以包括是否对该包的所有SUBSCRIBE 请求都用202 进行响应。
G.4.4.7 通知者产生NOTIFY 请求
在事件包中要求包含对通知者如何产生并发送NOTIFY 请求的描述,包括什么事件引起NOTIFY 的发送,如何计算NOTIFY 中的状态信息,如何产生中间的或者虚假的状态信息以便隐藏认证延迟和来自用户的判定,是否包含完整的状态信息还是包含状态差异信息。
事件包可以任选对处理后续响应的行为进行描述。
G.4.4.8 定制者处理NOTIFY 请求
事件包要描述当定制者收到NOTIFY 请求时执行的处理,包括形成相关资源状态要求的所有逻辑(如果可应用)。
G.4.4.9 分支请求的处理
每个事件包必须规定是否允许分支的SUBSCRIBE 请求设置多个定制。
如果不允许该行为,第一个隐含创建对话的消息将创建对话。对于所有的后续NOTIFY 消息,该消息和SUBSCRIBE 消息相匹配,但和对话不匹配,那么应用481 响应拒绝该消息。有可能在收到匹配的NOTIFY 消息之后收到SUBSCRIBE 的200 类响应,该响应可能不与NOTIFY 建立的对话相关联。除了要完成SUBSCRIBE 事务处理, 该响应将被忽略。
154
如果允许使用分支的SUBSCRIBE 设置多个定制,那么定制者可以通过对每个NOTIFY 消息返回200 类响应来建立到每个通知者的新的对话。每个对话处理自己所属的实体并且独立于其他对话单独进行刷新。
在允许多个定制的情况下, 事件包必须规定是否要求将多个通知合并成单独一个状态, 并且要规定如何进行合并。有些事件包可能将所有对话定义为互不关联,此时必须明确申明。
G.4.4.10 通知频率
每个事件包应定义允许单个通知者产生通知频率的最大值。
每个事件包可以进一步定义允许定制者进一步限制通知频率的终止机制。
G.4.4.11 状态代理
事件包的设计者应考虑该事件包是否能从网络汇聚点(状态代理)和/或代表其他节点的节点中获得信息(例如:当资源本身不能或不愿意提供状态信息时提供资源状态信息的节点)。该应用的一个实例是节点跟踪网络中用户在线和可用状态。
如果事件包使用状态代理,那么该事件包必须规定该状态代理如何产生信息,如何提供鉴权和认证。
事件包也可以简单规定何时进行通知者转移。
G.4.4.12 示例
事件包应包含几个用典型的、语法正确的、完整的消息进行说明的消息流图,
建议在描述事件包文档中明确指出该示例仅最为参考性示例。
G.4.4.13 使用URI 获得状态
某些类型事件包定义的状态信息可能很大而不适合在SIP 消息中传送。要解决这个问题,事件包可以定义传送URI 来代理传送状态信息;然后利用该URI 来获得实际的状态信息。
.G.5 安全考虑
.G.5.1 接入控制
------分隔线----------------------------
顶一下
(2)
100%
踩一下
(0)
0%
------分隔线----------------------------
最新评论 查看所有评论
发表评论 查看所有评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 密码: 验证码:
推荐内容
  • VoIP的配置选择

    前面,我们已经围绕Vo I P 讨论了一些问题。现在,让我们讨论几种Vo I P 的配置和拓扑...

  • SIP协议介绍

    介绍 通信提供商及其合作伙伴和用户越来越渴求新一代基于 IP 的服务。现在有了 SIP协...

  • IP电话协议H.323协议 MGCP协议 SIP协议比较

    随着IP电话应用的普及,建立终端设备和网关的可扩展网络已成为业界面临的一大技术挑战...