XEP-0166
本文的英文原文来自XEP-0166
XEP-0166 Jingle
本文档定义了在Jabber/XMPP客户间初始化及管理点对点的多媒体会话(sessions)(比如,声音和图像的交换)框架,它在一定程度上与现有的Internet标准具有互操作性。
警告:本标准跟踪文档是实验性的。作为XMPP扩展协议发表,并不意味着XMPP标准基金会批准了这个协议。我们鼓励对本协议进行探索性的实现,但在本协议的状态发展为草稿之前,产品性的系统不应实现本协议。
文档信息
系列:XEP
序号:0166
发布者:XMPP标准基金会
状态:实验性的
类型:标准跟踪
版本:0.14
最后更新:2007-04-17
批准机构:XMPP理事会
依赖标准:XMPP核心标准
被替代标准:无
缩略名:未指派
Wiki页:[1]
作者信息
法律通告
讨论地点
相关的XMPP
术语
绪论
从Jabber/XMPP客户内部初始化和管理点到点(p2p)互操作(象声音、图像、或文件共享交换)的未广泛采用的标准已经有了。虽然,一些大的服务提供商和Jabber/XMPP客户已经写出和实现了他们自己独有的用于点对点信号处理的XMPP扩展,但这些技术没有公开,并且总是没有考虑到与公共转换电话网络(PSTN)或跨互联网声音协议(VoIP)的互操作性的需求。这些网络建立在IETF的 __会话初始化协议(SIP)__ 上,在RFC3261[\[注1\]|XMPP文档列表/XMPP扩展/XEP-0166]及其各种扩展中有详细说明。
与此相反,唯一存在的开放协议是{link:初始化及协商会话的传输|http://www.xmpp.org/extensions/xep-0111.html}[\[注2\]|XMPP文档列表/XMPP扩展/XEP-0166],它使得初始化及管理点对点会话成为可能,却没有提供足够多的在Jabber/XMPP客户端中能轻松地实现的关键性的信号处理语义。其结果导致在XMPP社区里有关信号处理的协议支离破碎。基本上,有两中方法可以解决这个问题:
- 推荐所有的客户端开发者实现双重(XMPP+SIP)解决方案.
- 定义一个XMPP信号处理的完整特征的协议。
实现经验表明,双重方法也许不会在所有的计算平台上都可行-也许Jabber客户端已经写完了,或者虽然可行但并不值当。因此,定义一个XMPP信号处理协议似乎合情合理,这个协议能提供所需的信号处理语义,同时也使得与现有互联网标准的互操作性相对简单。
作为收到的XEP-0111返馈的一个结果,文档的原作者(Joe Hildebrand 和Peter Saint-Andre)开始定义这样的一个信号处理协议,代码名为Jingle。通过与Google Talk小组\[4\]成员交流,发现形成的Jingle方法在概念上(甚至在句法上)都与在Google Talk程序中使用的信号处理协议非常相似。因此,为了保持互操作性和适用性,我们决定协调这两种方法。因此,由本文详细说明的信号处理协议基本上等同于现有的Google Talk协议,只是根据在XMPP标准基金会的标准化的实施及发表进程中收到的反馈作了一些调整。
Jingle的目的不是排挤或替代SIP。因为构建双重XMPP+SIP客户端非常困难,导致本质上程序控制的两个中心,所以,我们将Jingle设计成纯的XMPP信号处理协议。Jingle意欲与SIP相互作用,这样数百万已布置的XMPP客户端能够加到现有的开放的VoIP网络之中,而不是将XMPP用户限制在某个分离的独特的VoIP网络中。
需求
这里定义的协议的目标是满足如下需求:
- 使得XMPP内多种点对点会话(不限于声音和视频)的管理成为可能\[6\]。
- 明确分离信号处理通道(XMPP)与数据通道(例如,在RFC3550中说明的实时传输协议\[7\])。
- 明确分离内容描述格式(例如,用于语音聊天的)与内容传输方法(比如,在RFC768\[8\]中说明的用户数据报协议)。
- 使得从现有会话中加入、修改、删除内容类型成为可能。
- 使得实现支持标准的Jabber/XMPP客户端中的协议相对容易。
- 当需要与非XMPP实体通讯的时候,尽可能将复杂性推到XMPP网络与非XMPP网络间的服务器端网关上。
本文档仅定义了信号处理协议。其他文档详细说明了如下内容:
- 各种内容描述格式(音频、视频等),如有可能,将这些类型映射到会话描述协议(SDP,参见RFC4566[9])中;示例包括经由RTP的Jingle音频[10]及经由RTP的视频[11]。
- 各种内容传输方法;示例包括Jingle ICE传输方法\[12\]及Jingle原生UDP传输\[13\]。
- 映射Jingle信号处理协议到现有现有信号处理标准的方法,象IETF的会话初始化协议(SIP;参见RFC2361[14]),ITU的H.323协议(见H.323[15]);这些文档即将完成。
1.1 2.术语表{anchor:术语表}
{table}
术语|定义
会话 |连接两个实体的许多对已协商的内容传输方法和内容描述格式。它被限定在初始化请求和会话结束时间的时间段内。在一个会话的生命周期内,可加入或删除成对的内容描述和内容传输方法。在某一时刻,一个会话至少有一个已协商的内容类型。
内容类型|一个内容描述和一个内容传输方法的组合。
内容描述|内容类型将被建立的格式,从形式上声明了会话的一种用途(如,"voice"或"video")。这是会话的(即,传输的比特位)“是什么”,象建立语音通话时可接受的编码器等。按照Jingle XML语法,内容类型是元素<description/>的命名空间。
传输方法|实体间建立数据流的方法。可能的传输包括ICE-TCP,原生UDP,带内数据(inband data)等。这是关于会话“怎样”的部分。按照Jingle XML语法,这是元素<transport/>的命名空间。内容传输方法定义了怎样将比特位从一台主机传到另一台。每种传输方法必须指定是有损的(允许丢包)还是无损的(不允许丢包)。
组件|组件是需要在端点间传输的特定会话上下文中特定内容类型的编号的数据流。协商每个组件的细节是由传输负责。根据内容类型和内容描述,一个内容描述可能需要多个组件来通讯(例如,音频内容类型也许用两个组件:一个传输RTP流,另一个传输RTCP定时信息)。
{table}
1.1 4.概念及方法{anchor:概念和方法}
Jingle有三部分组成,每部分由自己的语法、语义及状态机:
1. 总会话管理
1. 内容描述格式("什么")
1. 内容传输方法("怎样")
本文档定义了总会话管理的语义和语法。另有单独的文档,详细说明了用于内容描述和内容传输方法的可插入式“槽(slots)”。基于完整性的考虑,本文档也包含了与描述格式和传输方法有关的全部动作的示例。
从最根本上来说,协商Jingle会话的过程是这样的:
1. 一个用户(“发起方”)向另一个用户(“接收方”)发送一个带内容类型的会话请求,会话请求至少包含一个内容类型。
1. 如果接收者想要处理,它会通过发送一个IQ结果暂时接受这个请求。
1. 发起方和接收方以尽可能快的速度交换可能的传输候选方法(进一步协商前的传输候选方法的快速发送,是为了缩短媒体数据可流动前的必要时间)。
1. 检查这些传输候选方法的连通性。
1. 一旦接收方找到了媒体数据可流动的候选方法,接收方会向初始方发出一个“会话接受”动作。
1. 双发开始通过协商好的候选方法发送媒体数据。
如果双方随后发现了更好的候选方法,他们会进行“内容修改”协商,然后转到这个更好的候选方法上。自然他们也会修改与会话相关的其他参数(如给语音聊天加入视频)。
1.1 4.1总会话管理{anchor:总会话管理}
总会话管理的状态机(也即每个Session ID的状态)如下:
{code}
o
|
|会话开始
|
| +-----------+
|/ |
阻塞 o----------+ |
| |内容接受 | |
| |内容修改 | |
| |内容移除 | |
| |会话信息 | |
| |传输信息 | |
| +--------+ |
| |
|会话接受 |
| |
活动 o----------+ |
| |内容接受 | |
| |内容增加 | |
| |内容修改 | |
| |内容移除 | |
| |会话信息 | |
| |传输信息 | |
| +--------+ |
| |
+-------------+
|
|会话中止
|
o 结束
{code}
总会话状态有三种:
1. 阻塞
1. 活动
1. 结束
与管理总体Jingle会话相关的动作如下:
__表2:Jingle动作__
{table}
动作|描述
内容接受|接受从另一方受到的内容增加或内容移除。
内容增加|增加一个或多个内容类型到会话中。这个动作 __不能__ 在会话的 __阻塞__ 状态时发出。当一方发出内容增加的时候,它 __必须__ 忽略从另一方收到的任何动作,直到收到内容增加的确认。
内容修改|改变现有的内容类型。接收方 __不能__ 以另一个内容修改来回应内容修改动作。
内容移除|从会话中移除一个或多个内容类型。
会话接受|最终接受会话协商。表明这个动作也适合内容接受(进而适合描述接受和传输接收)。
会话信息|发送会话级的信息/消息,如响铃消息(对Jingle音频来说)。
会话开始|请求一个新Jingle会话协商。
会话中止|结束现有会话。
传输信息|交换传输候选方法;主要用在XEP-0176中,也可以用在其他规范中。
{table}
1.1 5.会话流{anchor:会话流}
1.1 5.1资源确定{anchor:资源确定}
为了开始Jingle会话,发起方必须确定接收方的哪种XMPP资源最适合想要的内容描述格式。如果联系方仅有一种XMPP资源,这一任务 __必须__ 用服务发现\[18\]或用在实体能力\[19\]中说明的基于现身(presence-based)的简介(profile)的服务发现来完成。
很自然,用实体能力而不是向用户花名册中的每个联系人发送服务发现请求效率更高。由此,某个客户版本对Jingle及各种Jingle内容描述格式和内容传输方法的支持等一般性信息(而不是每个的JID的)都能确定下来,这些信息随后被缓存。具体细节参考EXP-0115。
如果联系方有不止一种XMPP资源,可能仅有一种资源支持Jingle和想要的内容描述格式,在这种情况下,用户 __必须__ 用这一资源初始化Jingle信号处理。
如果联系方有超过一种XMPP资源支持Jingle和想要的内容描述格式, __建议__ 用 ~~资源应用优先权~~ \[20\]来确定哪种资源最适合初始化Jingle会话。
1.1 5.2初始化{anchor:初始化}
一旦发起方发现了接收方哪种XMPP资源适合想要的内容描述格式,就向接收方发送一个会话初始化请求。这个请求是个包含<jingle/>元素的IQ集,元素的命名空间为‘http://www.xmpp.org/extensions/xep-0166.html#ns’。<jingle/>元素 __必须__ 有'action' 、'initiator'和'sid'属性(两个字符唯一区分会话)。初始化时,'action'属性 __必须__ 是"session-initiate",<jingle/>元素 __必须__ 包含一个或多个<content/>元素,每个元素定义会话期间的要传输的内容类型;每个<content/>元素分别包含<description/>子元素,指定想要的内容描述格式,<transport/>子元素,指定了可能的内容传输方法。如果任何一方想要对相同的内容描述使用多种传输方法,则必须发送多个<content/>元素。
下面是一个Jingle会话初始化请求的例子,会话包含了音频和视频:
__例1. 初始化示例__
{code:xml}
<iq from='romeo@montague.net/orchard' to='juliet@capulet.com/balcony' id='jingle1' type='set'>
<jingle xmlns='http://www.xmpp.org/extensions/xep-0166.html#ns'
action='session-initiate'
initiator='romeo@montague.net/orchard'
sid='a73sjjvkla37jfea'>
<content creator='initiator' name='this-is-the-audio-content'>
<description xmlns='http://www.xmpp.org/extensions/xep-0167.html#ns'>
...
</description>
<transport xmlns='http://www.xmpp.org/extensions/xep-0176.html#ns'/>
</content>
<content creator='initiator' name='this-is-the-video-content'>
<description xmlns='http://www.xmpp.org/extensions/xep-0180.html#ns'>
...
</description>
<transport xmlns='http://www.xmpp.org/extensions/xep-0176.html#ns'/>
</content>
</jingle>
</iq>
{code}
注意:元素<description/>和<transport/>的语法、语义超出了本规范的范围,它们在相关的规范中定义。
元素<jingle/>有如下属性:
- ‘action’属性是 __必需的__ ;它指定了本文中列出Jingle动作(如,"session-initiate")。
- 'initiator'属性是发起会话流的实体的完整JID(可能与IQ集中地址'from'不同)。
- ‘reasoncode’属性是 __可选的__ ,指定机器可读的动作发送目的(如,用在会话中止动作的"connectivity-error")。
- 'reasontext'属性是 __可选的__ ,指定人可读的动作发送目的(如,用于会话中止动作的"Sorry,gotta go")。
- 'responder'属性(见下面的例子)是回应发起的实体的完整JID(可能与IQ集中'to'地址不同)。
- ‘sid’属性是由发起方产生的随机的会话识别符;它 __应该__ 符合XML Nmtoken production\[21\],这样对&之类的字符就不需要进行XML字符的转义了。(注意:'sid'属性可有效地映射到SIP的‘Call-ID’参数)
元素<content/>有如下属性:
- 'creator'属性是 __必需的__ ;它指明了那一方最初产生的内容描述(用于防止修改时的竞态条件(race conditions)的发生)。
- ‘name’属性是 __必需的__ ;它指明了内容类型的独特的名字或识别符(这个识别符是不透明的,没有语义上的意义)。
- 'profile'属性是 __推荐的__ ;对有些内容类型,它说明了所用的简介(如,在实时传输协议上下文中的"RTP/AVP")
- ‘senders’属性是 __推荐的__ ;它说明了会话中那个实体将要产生内容;允许的值是"initiator","recipient"或"both"(缺省值是"both")。
注意:为了加速会话建立,发起方 __可以__ 在发送“session-initiate”消息后接到接收方响应之前,立即发送传输候选方法(如,用于ICE传输的协商),(也就是说,发起方 __必须__ 认定会话是存在的,即使还没有收到响应)。如果按顺序传输的话,接收方应在收到"session-initiate"消息后,应收到诸如"transport-info"之类的消息(如果没收到,那么接收方返回<unknown-session/>错误是恰当的,因为按照它的状态机,会话并不存在)。
1.1 5.3接收方响应{anchor:接收方响应}
除非有错误发生,接收方 __必须__ 收到的发起请求:
例2. 接收方响应发起请求
{code:xml}
<iq type='result' from='juliet@capulet.com/balcony' to='romeo@montague.net/orchard' id='jingle1'/>
{code}
如果接收方响应了发起请求,双方都必须认定会话处在 __阻塞__ 状态。
有几种原因接收方会返回一个错误,而不是响应发起请求:
- 对接收方来说发起方是未知的(比如,通过在线(presence)订阅),接收方不能与未知实体通讯。
- 接收方希望转到另一个地址。
- 接收方不支持Jingle。
- 接收方不支持任何指定的内容描述格式。
- 接收方不支持任何指定的内容传输方法。
- 发起请求格式是错误的。
如果对接收方来说发起方是未知的(比如,通过在线订阅),并且接收方有不与未知实体经由Jingle通讯的策略,则接收方 __应该__ 返回一个<service-unavailable/>错误。
例3. 发起方未知
{code:xml}
<iq type='error' from='juliet@capulet.com/balcony' to='romeo@montague.net/orchard' id='jingle1'>
<error type='cancel'>
<service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
{code}
如果接收方希望转向另一个地址,它 __应该__ 返回一个<redirect/>错误。
例4. 接收方转向
{code:xml}
<iq type='error' from='juliet@capulet.com/balcony' to='romeo@montague.net/orchard' id='jingle1'>
<error type='cancel'>
<redirect xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'>xmpp:voicemail@capulet.com</redirect>
</error>
</iq>
{code}
如果接收方不支持Jingle,则 __必须__ 返回一个错误。
例5. 接收方不支持Jingle
{code:xml}
<iq type='error' from='juliet@capulet.com/balcony' to='romeo@montague.net/orchard' id='jingle1'>
<error type='cancel'>
<service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
{code}
如果接收方不支持任何一种指定的内容描述格式,它 __必须__ 返回一个<feature-not-implemented/>错误,和具有Jingle特性的出错条件的<unsupported-content>。
例6. 接收方不支持任何内容描述格式
{code:xml}
<iq type='error' from='juliet@capulet.com/balcony' to='romeo@montague.net/orchard' id='jingle1'>
<error type='cancel'>
<feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<unsupported-content xmlns='http://www.xmpp.org/extensions/xep-0166.html#ns-errors'/>
</error>
</iq>
{code}
如果接收方不支持任何一种指定的内容传输方法,它 __必须__ 返回一个<feature-not-implemented/>错误,和具有Jingle特性的出错条件的<unsupported-transports>。
例7. 接收方不支持任何内容传输方法
{code:xml}
<iq type='error' from='juliet@capulet.com/balcony' to='romeo@montague.net/orchard' id='jingle1'>
<error type='cancel'>
<feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<unsupported-transports xmlns='http://www.xmpp.org/extensions/xep-0166.html#ns-errors'/>
</error>
</iq>
{code}
如果发起请求的格式错误,接收方 __必须__ 返回一个<bad-request/>错误。
例8. 发起请求的格式错误
{code:xml}
<iq type='error' from='juliet@capulet.com/balcony' to='romeo@montague.net/orchard' id='jingle1'>
<error type='cancel'>
<bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
{code}
1.1 5.4拒绝{anchor:拒绝}
为拒绝会话发起请求,接收方 __必须__ 响应收到的会话发起请求,然后按[中止|XMPP文档列表/XMPP扩展/XEP-0166#中止]中描述的方法中止会话。
1.1 5.5 协商{anchor:协商}
一般情况下,双方在达成可接受的一系列内容类型、内容描述格式和内容传输方法前,协商是必要的。可能要协商的这些参数的组合是很多的,这里并没有列出全部(有些在各种内容描述格式和内容传输方法规范中列出)。
一个会话级的协商是移除一种内容类型。例如,让我们设想,有一天朱丽叶的心情很糟糕,她当然不想在和罗密欧的Jingle会话中包含视频,所以她给罗密欧发送了一个“内容移除”请求:
例9. 内容类型移除
{code:xml}
<iq from='juliet@capulet.com/balcony' to='romeo@montague.net/orchard' id='reduce1' type='set'>
<jingle xmlns='http://www.xmpp.org/extensions/xep-0166.html#ns'
action='content-remove'
initiator='romeo@montague.net/orchard'
sid='a73sjjvkla37jfea'>
<content creator='initiator' name='this-is-the-video-content'/>
</jingle>
</iq>
{code}
实体收到了这个会话缩减请求,然后响应这个请求:
例10. 响应
{code:xml}
<iq from='romeo@montague.net/orchard' to='juliet@capulet.com/balcony' id='reduce1' type='result'/>
{code}
如果缩减的结果是会话不再有任何内容类型,收到会话缩减的实体 __应该__ 向另一方发送会话中止动作(因为没有内容类型的会话是无效的)。
另一个会话级的协商是增加一个内容类型;然而,这个动作 __必不能__ 在会话处于 __阻塞__ 状态时来做,只有在会话处于 __活动__ 状态时才可以。
1.1 5.6 接受{anchor:接受}
协商过内容传输方法和内容描述格式后,如果接收方确定能够建立连接,它将向发起方法送确定接受:
例11. 接收方确定接受呼叫
{code:xml}
<iq type='set' from='juliet@capulet.com/balcony' to='romeo@montague.net/orchard' id='accept1'>
<jingle xmlns='http://www.xmpp.org/extensions/xep-0166.html#ns'
action='session-accept'
initiator='romeo@montague.net/orchard'
responder='juliet@capulet.com/balcony'
sid='a73sjjvkla37jfea'>
<content creator='initiator' name='this-is-the-audio-content'>
<description xmlns='http://www.xmpp.org/extensions/xep-0167.html#ns'>
...
</description>
<transport xmlns='http://www.xmpp.org/extensions/xep-0177.html#ns'>
<candidate .../>
</transport>
</content>
</jingle>
</iq>
{code}
<jingle/>元素 __必须__ 包含一个或多个<content/>元素,后者 __必须__ 包含一个<description>元素和一个<transport/>元素。<jingle/>元素 __应该__ 有‘responder’属性,以明确指明响应实体的完整JID,有关当前Jingle会话的所有通讯,发起方应该向这个JID发送。
然后发起方响应接收方的确认接受:
例12. 发起方响应确认接受
{code:xml}
<iq type='result' to='juliet@capulet.com/balcony' from='romeo@montague.net/orchard' id='accept1'/>
{code}
此时,发起方和接收方可以通过协商好的连接开始发送内容了。
如果一方无法找到合适的内容传输方法,它 __应该__ 下面描述的那样中止会话。
1.1 5.7 修改活动会话{anchor:修改活动会话}
为修改一个活动会话,任一方都可向另一方发送"content-remove"、"content-add"、 "content-modify", "description-modify"、"transport-modify" 动作。然后接收方发送恰当的"-accept"或"-decline"动作,也可能首先发送一个"-info"动作。
如果双方同时发送了修改消息,那么会话发起方的修改消息 __必须__ 胜过接收方的修改消息,发起方 __应该__ 返回一个<unexpected-request/>错误。
修改活动会话的一个例子是增加一个会话内容。例如,设想一下朱丽叶的心情好了,现在想加入视频。于是向罗密欧发送"content-add"请求:
例13. 增加一个内容类型
{code:xml}
<iq from='juliet@capulet.com/balcony' to='romeo@montague.net/orchard' id='add1' type='set'>
<jingle xmlns='http://www.xmpp.org/extensions/xep-0166.html#ns'
action='content-add'
initiator='romeo@montague.net/orchard'
sid='a73sjjvkla37jfea'>
<content creator='responder' name='video-is-back'>
<description xmlns='http://www.xmpp.org/extensions/xep-0180.html#ns'>
...
</description>
<transport xmlns='http://www.xmpp.org/extensions/xep-0177.html#ns'>
<candidate .../>
</transport>
</content>
</jingle>
</iq>
{code}
实体接收到会话扩展请求,响应这个请求,如果可接受,返回一个内容接受:
The entity receiving the session extension request then acknowledges the request and, if it is acceptable, returns a content-accept:
例14. 响应
{code:xml}
<iq from='romeo@montague.net/orchard' to='juliet@capulet.com/balcony' id='add1' type='result'/>
{code}
例15. 内容接受
{code:xml}
<iq from='romeo@montague.net/orchard' to='juliet@capulet.com/balcony' id='add2' type='set'>
<jingle xmlns='http://www.xmpp.org/extensions/xep-0166.html#ns'
action='content-accept'
initiator='romeo@montague.net/orchard'
sid='a73sjjvkla37jfea'>
<content creator='responder' name='video-is-back'>
<description xmlns='http://www.xmpp.org/extensions/xep-0180.html#ns'>
...
</description>
<transport xmlns='http://www.xmpp.org/extensions/xep-0177.html#ns'>
<candidate .../>
</transport>
</content>
</jingle>
</iq>
{code}
另一方响应接受。
例16. 响应
{code:xmk}
<iq from='juliet@capulet.com/balcony' to='romeo@montague.net/orchard' id='add2' type='result'/>
{code}
1.1 5.8 中止{anchor:中止}
为了顺利地结束会话(在响应了初始化请求后的任何时候都 __可以__ 这么做,包括立即想立刻拒绝请求的时候),无论接收方还是初始方都 __必须__ 向对方发送一个“中止”动作。
例17 接收方中止会话
{code:xml}
<iq from='juliet@capulet.com/balcony'
id='term1'
to='romeo@montague.net/orchard'
type='set'>
<jingle xmlns='http://www.xmpp.org/extensions/xep-0166.html#ns'
action='session-terminate'
initiator='romeo@montague.net/orchard'
reason='Sorry, gotta go!'
sid='a73sjjvkla37jfea'/>
</iq>
{code}
另一方(这里是初始方)必须响应会话中止:
例18. 初始方响应中止
{code:xml}
<iq type='result' to='juliet@capulet.com/balcony' from='romeo@montague.net/orchard' id='term1'/>
{code}
注意:一旦实体发送了"会话中止"动作,它 __必须__ 认定会话已中止(即使在收到对方的响应之前)。如果中止方在发送了“会话中止”动作后收到了对方额外的IQ设置,它 __必须__ 返回一个<unknown-session/>错误。
不幸的是,并非所有会话都顺利地结束。下面的事件 __必须__ 认定为会话结束事件,对内容描述格式和内容传输方法的进一步协商 __必须__ 通过协商一个新会话来完成:
- 从对方那里收到‘会话转向’或'会话中止'动作。
- 从对方那收到<presence type='unavailable'/>。
特别地,如果一方从对方收到的在线(presence)类型是"未知(unavailable)"的话,则它 __必须__ 认定会话处于 __结束__ 状态。
例19. 接收方离线
{code:xml}
<presence from='juliet@capulet.com/balcony' to='romeo@montague.net/orchard' type='unavailable'/>
{code}
自然在这种情况下初始方没什么可响应的。
1.1 5.9 通知消息{anchor:通知消息}
Jingle会话开始后的任何时候,任一实体都 __可以__ 向对方发送通知消息,比如,改变内容传输方法或内容描述格式的参数,通知对方一个会话开始请求已经列队等待,设备正在响铃,或一个事先计划的事件已经发生或将要发生。通知消息 __必须__ 是带有<jingle/>元素的IQ设置(IQ-set)指令,<jingle/>元素的'action'属性的值是"session-info","description-info"或“transport-info”之一;<jingle/>元素 __必须__ 进一步包含有效的子元素(会话,内容描述格式或内容传输方法)来说明正在交流的信息。如果一个活动会话的任一方收到了一个空的“session-info”消息,它 __必须__ 返回一个空的IQ结果;这样,一个空的“session-info”消息可用作一个“ping”,来确定会话的活性。(本规范的未来版本也许会定义与“session-info”动作相关的内容载荷。)
1.1 6. 出错处理{anchor:出错处理}
Jingle专有的出错条件如下。
表3:其他出错条件
{table}
Jingle条件|xmpp条件|说明
<out-of-order/>|<unexpected-request/>|请求不可能在状态机的这一点发生(比如,会话接受后再次初始化)。
<unknown-session/>|<bad-request/>|指定会话的‘sid’属性对接收方未知(例如,根据接收方的状态机会话已经不再有效,因为接收方先前已中止了会话)
<unsupported-content/>|<not-acceptable/>|接收方不支持任何期望的内容描述格式。
<unsupported-transports/>|<not-acceptable/>|接收方不支持任何期望的内容传输方法。
{table}
1.1 7. 支持性检测{anchor:支持性检测}
如果一个实体支持Jingle,它 __必须__ 在响应{link:服务发现|http://www.xmpp.org/extensions/xep-0030.html}\[22\]信息请求时,通过返回特性“http://www.xmpp.org/extensions/xep-0166.html#ns”(见有关{link:协议命名空间%7Chttp://www.xmpp.org/extensions/xep-0166.html#ns})将这一事实公布出去。
例20. 服务发现信息请求
{code:xml}
<iq from='romeo@montague.net/orchard'
id='disco1'
to='juliet@capulet.com/balcony'
type='get'>
<query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>
{code}
例21. 服务发现信息响应
{code:xml}
<iq from='juliet@capulet.com/balcony'
id='disco1'
to='romeo@montague.net/orchard'
type='result'>
<query xmlns='http://jabber.org/protocol/disco#info'>
...
<feature var='http://www.xmpp.org/extensions/xep-0166.html#ns'/>
...
</query>
</iq>
{code}
1.1 8.使用协议的一致性{anchor:使用协议的一致性}
1.1 8.1 应用类型{anchor:应用类型}
说明某种Jingle应用类型的文档(比如,经由RTP的音频) __必须__ 定义:
1. 为封装进Jingle,如何成功地进行内容协商。
1. 用于表现内容的<description/>元素及相关语义。
1. 能否及怎样将内容描述映射到会话描述协议上。
1. 是通过可靠的还是有损的传输方式(或两者都是)来传输内容。
1. 通过可靠或有损传输来收发内容的精确说明。
1.1 8.2 传输方法{anchor:传输方法}
说明Jingle传输方法的文档(比如,纯UDP) __必须__ 定义:
1. 为封装进Jingle,怎样成功地进行传输协商。
1. 用于表现传输类型的<transport/>元素及相关语义。
1. 传输是可靠的还是有损的。
1. 传输是否及怎样处理在这定义的组件(例如,对实时控制协议来说)。
1.1 9. 安全性事项{anchor:安全性事项}
1.1 9.1 拒绝服务
Jingle会话可能是资源密集型的。因此,有可能用增加过多Jingle会话负担的方法向一个实体发动决绝服务攻击。必须小心地只从已知的实体那接受内容,并且只接受实体设备能处理的会话。
1.1 9.2 通过网关通讯{anchor:通过网关通讯}
Jingle通讯可通过网关与非XMPP网络完成,这些网络的安全特性与XMPP有很大的不同。(例如,在有些SIP网络中鉴定是可选的,“from”地址可轻易伪造。)与这些网通通讯时必须小心。
1.1 IANA事项{anchor:IANA事项}
本文档要求不与{link:互联网指派数字授权(IANA)|http://www.iana.org/}\[23\]相互作用。
1.1 11. XMPP注册处事项{anchor:XMPP注册处事项}
1.1 1\1.1 协议命名空间{anchor:协议命名空间}
在本规范成为草稿状态之前,其相关的命名空间是“http://www.xmpp.org/extensions/xep-0166.html#ns”和"http://www.xmpp.org/extensions/xep-0166.html#ns-errors“;随着规范的发展,{link:XMPP注册员\[24\]|http://www.xmpp.org/registrar/}将按照{link:XMPP注册处功能\[25\]|http://www.xmpp.org/extensions/xep-0053.html}的第四节中定义的过程来发布永久命名空间。
1.1 11.2 Jingle内容描述格式注册
XMPP注册处会维护Jingle内容描述格式的注册。整个内容描述格式的注册会在单独的规范中定义(不在本文档中)。定义在XEP系列里的内容描述格式也 __必须__ 在XMPP注册处注册,其结果是协议的URN的格式是“urn:xmpp:jingle:description:name”(其中“name”是内容描述格式的注册名)。
为提交注册的新值,注册人须按下面的格式定义一个XML段,内容包括相关的XMPP扩展协议,或者将它发送到<registrar@xmpp.org>。
{code:xml}
<content>
<name>the name of the content description format</name>
<desc>a natural-language summary of the content description format</desc>
<transport>whether the content should be sent over a "reliable" or "lossy" transport</transport>
<doc>the document in which this content description format is specified</doc>
</content>
{code}
1.1 11.3 Jingle内容传输方法注册
XMPP注册处会维护Jingle内容传输方法的注册。整个内容传输方法的注册会在单独的规范中定义(不在本文档中)。定义在XEP系列里的内容传输方法也 __必须__ 在XMPP注册处注册,其结果是协议的URN的格式是“urn:xmpp:jingle:transport:name”(其中“name”是内容传输方法的注册名)。
为提交注册的新值,注册人须按下面的格式定义一个XML段,内容包括相关的XMPP扩展协议,或者将它发送到<registrar@xmpp.org>。
{code:xml}
<transport>
<name>the name of the content transport method</name>
<desc>a natural-language summary of the content transport method</desc>
<type>whether the transport method is "reliable" or "lossy"</type>
<doc>the document in which this content transport method is specified</doc>
</transport>
{code}
1.1 11.4 Jingle原因代码注册{anchor:Jingle原因代码注册}
1.1 11.4.1 过程{anchor:过程}
XMPP注册处会维护一份Jingle动作原因的注册。
为提交注册的新值,注册人须按下面的格式定义一个XML段,内容包括相关的XMPP扩展协议,或者将它发送到<registrar@xmpp.org>。
{code:xml}
<reason>
the value of the 'reasoncode' attribute</name>
<desc>a natural-language summary of the reason code</desc>
<doc>the document in which this reason code is specified</doc>
</reason>
{code}
1.1 11.4.2 初始注册{anchor:初始注册}
下面提交的原因代码注册从2007年4月开始使用。完整内容和最新的原因代码列表参见注册。
{code:xml}
<reason>
<code>connectivity-error
<desc>the action (e.g., session-terminate) is related to connectivity problems</desc>
<doc>XEP-0166</doc>
</reason>
<reason>
general-error
<desc>the action (e.g., session-terminate) is related to a non-specific application error</desc>
<doc>XEP-0166</doc>
</reason>
<reason>
media-error
<desc>the action (e.g., session-terminate) is related to media processing problems</desc>
<doc>XEP-0166</doc>
</reason>
<reason>
no-error
<desc>the action is generated during the normal course of state management</desc>
<doc>XEP-0166</doc>
</reason>
{code}
1.1 12. XML方案(Schemas){anchor:XML Schemas}
1.1 12.1 Jingle{anchor:Jingle}
{code:xml}
<?xml version='1.0' encoding='UTF-8'?>
<xs:schema
xmlns:xs='http://www.w3.org/2001/XMLSchema'
targetNamespace='http://www.xmpp.org/extensions/xep-0166.html#ns'
xmlns='http://www.xmpp.org/extensions/xep-0166.html#ns'
elementFormDefault='qualified'>
<xs:element name='jingle'>
<xs:complexType>
<xs:sequence minOccurs='1' maxOccurs='unlimited'>
<xs:element ref='content'/>
</xs:sequence>
<xs:attribute name='action' use='required'>
<xs:simpleType>
<xs:restriction base='xs:NCName'>
<xs:enumeration value='content-accept'/>
<xs:enumeration value='content-add'/>
<xs:enumeration value='content-modify'/>
<xs:enumeration value='content-remove'/>
<xs:enumeration value='session-accept'/>
<xs:enumeration value='session-info'/>
<xs:enumeration value='session-initiate'/>
<xs:enumeration value='session-terminate'/>
<xs:enumeration value='transport-info'/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name='initiator' type='xs:string' use='required'/>
<xs:attribute name='reasoncode' type='xs:string' use='optional'/>
<xs:attribute name='reasontext' type='xs:string' use='optional'/>
<xs:attribute name='responder' type='xs:string' use='optional'/>
<xs:attribute name='sid' type='xs:NMTOKEN' use='required'/>
</xs:complexType>
</xs:element>
<xs:element name='content'>
<xs:complexType>
<xs:choice minOccurs='0'>
<xs:sequence>
<xs:any namespace='##other' minOccurs='0' maxOccurs='unbounded'/>
</xs:sequence>
</xs:choice>
<xs:attribute name='creator' use='required'>
<xs:simpleType>
<xs:restriction base='xs:NCName'>
<xs:enumeration value='initiator'>
<xs:enumeration value='responder'/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name='name' use='required' type='xs:string'/>
<xs:attribute name='profile' use='optional' type='xs:string'/>
<xs:attribute name='senders' use='optional' default='both'>
<xs:simpleType>
<xs:restriction base='xs:NCName'>
<xs:enumeration value='both'>
<xs:enumeration value='initiator'>
<xs:enumeration value='responder'/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>
{code}
1.1 12.2 Jingle出错信息{anchor:Jingle出错信息}
{code:xml}
<?xml version='1.0' encoding='UTF-8'?>
<xs:schema
xmlns:xs='http://www.w3.org/2001/XMLSchema'
targetNamespace='http://www.xmpp.org/extensions/xep-0166.html#ns-errors'
xmlns='http://www.xmpp.org/extensions/xep-0166.html#ns-errors'
elementFormDefault='qualified'>
<xs:element name='out-of-order' type='empty'/>
<xs:element name='unknown-session' type='empty'/>
<xs:element name='unsupported-content' type='empty'/>
<xs:element name='unsupported-transports' type='empty'/>
<xs:simpleType name='empty'>
<xs:restriction base='xs:string'>
<xs:enumeration value=/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
{code}
13. 致谢{anchor:致谢}"