XMPP--XML流

上一篇 / 下一篇  2010-12-06 00:13:28 / 个人分类:XMPP

两个基本概念,XML流和XML节,使得在出席信息已知的实体之间,异步交换低负载的结构化信息成为可能。这两个术语定义如下:
XML流的定义:一个XML流是一个容器,包含了两个实体之间通过网络交换的XML元素。一个XML流是由一个XML打开标签 <stream> (包含适当的属性和名字空间声明)开始的,流的结尾则是一个XML关闭L标签 </stream> 。在流的整个生命周期,初始化它的实体可以通过流发送大量的XML元素,用于流的握手(例如 TLS 握手(第五章) 或 SASL 握手(第六章))或XML节(在这里指符合缺省名字空间的元素,包括<message/>,<presence/>, 或 <iq/> 元素)。“初始的流”由初始化实体(通常是一个客户端或服务器)和接收实体(通常是一个服务器)握手,从接收实体来看,它就是那个初始实体的"会话".初始化流允许从初始化实体到接收实体的单向通信;为了使接收实体能够和初始实体交换信息,接收实体必须发起一个反向的握手(应答流).
XML节的定义: 一个XML节是一个实体通过 XML 流向另一个实体发送的结构化信息中的一个离散的语义单位。一个XML节直接存在于根元素<stream/>的下一级,这样可以说是很好的匹配了[XML](译者注:在标准参考一节)的第43条.任何XML节都是从一个XML流的下一级的某个打开标签(如 <presence>)开始,到相应的关闭标签(如 </presence>)。一个XML节可以(MAY)包含子元素(相关的属性,元素, 和 XML 字符数据等) 以表达完整的信息.在这里定义的XML节仅限于<message/>, <presence/>, 和 <iq/> 元素,具体描述间见 XML Stanzas(第九章);为TLS握手(第五章)、SASL握手(第六章)、服务器回拨(第八章)的需要而发送的XML元素,不被认为是一个XML节。
设想一个客户端和服务器会话的例子。为了连接一个服务器,一个客户端必须(MUST)发送一个打开标签<stream>给服务器,初始化一个XML流,也可选择(OPTIONAL)在这之前发送一段文本声明XML版本和支持的字符集(参见文本声明的内容(第十一章第四节); 也可看字符编码(第十一章第五节))。视本地化策略和提供的服务而定,服务器应该(SHOULD)回复一个XML流给客户端,同样的,也可选择在这之前发送一段文本声明。一旦客户端完成了SASL握手(第六章),客户端可以(MAY)通过流发送不限量的XML节给网络中的任何接收者。当客户端想关闭这个流,它只需要简单的发送一个关闭标签</stream>给服务器(或者作为另一个选择,可能由服务器关闭这个流)。然后,客户端和服务器都应该(SHOULD)彻底地终止这个连接(通常是一个TCP连接)。
那些习惯认为XML是一个以文本为中心风格的人可能希望看看一个与服务器连接的客户端会话,包含两个 打开-关闭 XML文档:一个是从客户端到服务器,一个是从服务器到客户端。下图中,根元素<stream/> 可以被认为是每个“文档”的文档实体,这两个“文档”通过累积那些在XML上传输的XML节来搭建的。无论如何,下图只是方便理解;实际上XMPP并不处理文档而是处理XML流和XML节。
基本上,一个XML流相当于一个会话期间所有XML节的一个信封。我们可以简单的把它描述成下图:
|----------------------------
| <stream>
|----------------------------
| <presence>
| <show/>
| </presence>
|----------------------------
| <message to='foo'>
| <body/>
| </message>
|----------------------------
| <iq to='bar'>
| <query/>
| </iq>
|----------------------------
| ...
|----------------------------
| </stream>
|----------------------------

绑定到TCP

虽然有很多非必需的连接使用XML流来绑定\[TCP\]连接(两个实体可以通过别的机制来互联,比如通过\[HTPP\]连接轮询),本规范只定义了 XMPP 到 TCP 的绑定。在客户和服务器通信的过程中,服务器必须(MUST)允许客户端共享一个TCP连接来传输XML节,包括从客户端传到服务器和从服务器传到客户端。在服务器之间的通信过程中,服务器必须(MUST)用一个 TCP连接 向对方发送 XML节,另一个 TCP连接(由对方初始化)接收对方的XML节,一共两个 TCP连接。

流的安全

在XMPP 1.0中,当XML流开始握手时,TLS应该(SHOULD)按 第五章:TLS的使用 中的规定来使用,SASL必须(MUST)按 第六章:SASL的使用 中的规定来使用。尽管可能(MAY)存在某种共有的机制能够保证双向安全,但是“初始化流”(比如从初始化实体发给接收实体的流)和“应答流”(比如从接收实体发给初始化实体的流)还是必须(MUST)安全的分开。在流被验证之间,实体不应该(SHOULD NOT) 尝试通过流发送XML节(第九章);就算它这样做了,对方的实体也不能(MUST NOT)接受这些XML节,并且应该(SHOULD)返回一个 <not-authorized/> 的流错误信息并且终止当前TCP连接上双方的XML流;注意,这仅仅是针对XML节(包含在缺省命名空间中的 <message/>, <presence/>, 和 <iq/> 元素),而不是指那些用于 TLS握手(第五章)、SASL握手(第六章)握手的流。

流的属性

流元素的属性如下:
to -- 'to'属性应该(SHOULD)仅用于从初始化实体到接收实体的XML流的头,并且必须(MUST)设成为接收实体提供服务的主机名。注意,不应该(SHOULD NOT)有'to'属性出现在接收实体应答初始实体的XML流的头中;无论如何,如果'to'属性出现在应答流中,初始化实体应该(SHOULD)忽略它。
from -- 'from'属性应该(SHOULD)仅用于接收实体应答初始化实体的XML流的头,并且必须(MUST)设成为接收实体(正在给初始实体授权)提供服务的主机名。注意,不应该(SHOULD NOT)有'from'属性出现在初始实体发送给接收实体的XML流的头中;无论如何,如果'from'属性出现在初始化流中,接收实体应该(SHOULD)忽略它。
id -- 'id'属性应该(SHOULD)仅用于接收实体发送给初始化实体XML流的头。这个属性是一个由接收实体创建的具有唯一性的ID,一个初始实体和接收实体之间的会话ID,并且它在接收方的应用程序中(通常是一个服务器)必须(MUST)是唯一的。注意,这个流ID 必须是足够安全的,所以它必须是不可预知的和不可重复的(参见[RANDOM] 了解如何获得随机性以保证安全性)。不应该(SHOULD NOT)有'id'属性出现在初始实体发送给接收实体的XML流的头中;无论如何,如果'id'属性出现在初始化流中,接收实体应该(SHOULD)忽略它。
xml:lang -- 'xml:lang'属性(定义在\[XML\]中的第二章第十二节)应该(SHOULD)包含在初始化实体发给接收实体的XML流的头中,以指定在流中传输的可读XML字符所使用的缺省语言。如果这个属性出现了,接收实体应该(SHOULD)记住它的值,作为初始化流和应答流的缺省属性;如果这个属性没有出现,接收实体应该(SHOULD)用一个可配置的缺省值用于双方的流,这个属性值必须(MUST)在应答流的头中传达。对于所有初始化流中传输的节,如果初始实体没有提供'xml:lang'属性,接收实体应该(SHOULD)应用缺省值;如果初始实体提供了'xml:lang'属性,接收实体不能(MUST NOT)修改或删除它(参见第九章第一节第五小节xml:lang)。'xml:lang'属性的值必须(MUST)是一个NMTOKEN (定义在\[XML\]的第二章第三节) 并且必须(MUST)遵守RFC 3066\[LANGTAGS\] 规定的格式。
version -- version属性(最少需要"1.0")为本规范中和流相关的协议提供了支持。关于这个属性的生成和处理的详细规则将在下文中定义。

我们现在可以总结如下:
  初始化方发给接收方 接收方发给初始化方
to 接收方的主机名 忽略
from 忽略 接收方的主机名
id 忽略 会话键值
xml:lang 缺省语言 缺省语言
version 支持XMPP 1.0 支持XMPP 1.0

版本支持

在这里XMPP的版本是"1.0";准确地说,这里囊括了和流相关的所有协议(TLS的使用 (第五章),SASL的使用(第六章), 和流错误(第四章第七节)),以及三个定义好的XML节类型(<message/>,<presence/>,和 <iq/>)。XMPP版本号的编号顺序是“<主版本号>.<副版本号>”。主版本和副版本号必须(MUST)是独立的整数并且每个号码可以(MAY)单独以阿拉伯数字增长。这样,"XMPP 2.4"的版本将比"XMPP 2.13"更低。号码前面 的“0”(比如XMPP 6.01)必须(MUST)被接收方忽略并且不能(MUST NOT)被发送出去.
如果流和节的格式或者必需的处理方式有了显著的改变,以至于老版本的实体如果只是简单的忽略它不理解的节和属性并且继续像老版本一样的处理方式,会使得老版本的实体不能够和新版本的实体交互,只有在这时候主版本号才应该(SHOULD)增加。副版本号显示新的性能,它必须(MUST)被副版本号更低的实体忽略,但被高(副)版本号的实体用于了解信息。例如,一个副版本号显示处理某种新定义的"type"属性的值(用于message,presence或IQ节)的能力;副版本号高的实体将会了解到与之通信的对方不能够理解这个"type"属性的值,所以将不会发送它。
以下规则是用于'版本'属性在实现流的头信息时如何生成和处理:
初始化实体必须(MUST)在初始化流的头信息中把'版本'的值设置成它所支持的最高版本。(比如,如果最高版本支持就是本规范,那么它必须(MUST)设置成"1.0").
接收实体必须(MUST)在应答流的头信息中把'版本'的值设置成初始化实体所提供的版本或它所支持的最高版本,取其中版本号较低的那一个。接收实体必须(MUST)把主版本号和副版本号作为数字来比较,而不是对"主版本号.副版本号"这个字符串进行比较.
如果在应答流的头信息的版本号中至少有一个主版本号低于初始化流的头信息的版本号,并且如前所述,新版本的实体不能够和旧版本实体交互,初始化实体应该(SHUOULD)生成一个<unsupported-version/>的流错误信息并终止XML流和它的TCP连接。
如果一个实体收到一个头信息中没有'version'属性的流,这个实体必须(MUST)把对方实体的'version'当成'0.0'并且在它发送的应答流的头中也不应该(SHOULD NOT)包含'version'属性.

流的特性

如果初始化的实体在初始化流的头信息中设置'version'属性的信息为"1.0",接收实体必须(MUST)向初始化实体发送一个 <features/> 子元素以声明任何可供协商的流一级的特性(或者其他需要声明的能力).目前,这仅用于声明本文中定义的 TLS的使用(第五章),SASL的使用(第六章)和资源绑定(第七章),以及 [XMPP-IM|XMPP文档列表/XMPP正式RFC标准/RFC3921] 中定义的会话的建立;无论如何,流特性这一功能将来可以用于声明任何可协商的特性.如果一个实体不理解或支持安全特性,它应该(SHOULD)忽略它.如果要在一个非安全相关的特性(比如资源绑定)被提议之前,完成一个或多个安全特性(比如TLS和SASL)的协商,这个非安全相关的特性不应该(SHOULD NOT)在相应的安全特性协商完毕之前被声明.

流的错误

以下规则适用于流级别的错误:
它假定所有流级别的错误都是不可恢复的;所以,如果一个错误发生在流级别,发现这个错误的实体必须(MUST)发送一个流错误信息给另一个实体,发送一个关闭标签 </stream>,并终止这个流所在的TCP连接。
如果这个错误发生在流刚开始设置的时候,接收实体必须(MUST)仍然发送一个开放标签 <stream> ,并在流元素中包含一个<error/>的子元素,然后发送一个关闭标签 </stream>,最后终止相应的TCP连接。在这种情况下,如果初始化实体在 'to' 属性中提供了一个未知的主机名,服务器应该(SHOULD)在终止之前,先在流的头信息的 'from' 属性中提供一个服务器认证的主机名.

流错误的语法如下:
   <stream:error>
     <defined-condition xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>
     <text xmlns='urn:ietf:params:xml:ns:xmpp-streams' xml:lang='langcode'>
       OPTIONAL descriptive text
     </text>
     [OPTIONAL application-specific condition element]
   </stream:error>
   <error/>元素:
必须(MUST)包含一个子元素以描述一个下文定义的节错误条件;这个子元素必须(MUST)符合'urn:ietf:params:xml:ns:xmpp-streams'名字空间.
可以(MAY)包含一个 <text/> 子元素,用XML字符数据描述错误的细节;这个元素必须(MUST)符合'urn:ietf:params:xml:ns:xmpp-streams'名字空间并且应该(SHOULD)拥有一个'xml:lang'属性表明XML字符数据的自然语言。
可以(MAY)包含一个子元素用于描述一个明确的应用程序错误条件;这个元素必须(MUST)符合一个应用程序定义的名字空间,并且它的结构是由那个名字空间定义的。
<text/> 元素是可选的(OPTIONAL)。如果有这个元素,它应该(SHOULD)仅用于提供描述或调试信息以补充一个已定义的条件或应用程序定义的条件。它不应该(SHOULD NOT)被一个应用程序当成一个可编程的信息。它不应该(SHOULD NOT)被用于向用户表达错误信息,但是可以(MAY)作为和条件元素相关的错误信息之外的附加说明。

以下流级别的错误条件是已定义的:
<bad-format/> --实体已经发送XML但是不能被处理;这个错误可以(可以)被更多特定的XML相关的错误替换,比如<bad-namespace-prefix/>, <invalid-xml/>, <restricted-xml/>, <unsupported-encoding/>, 以及<xml-not-well-formed/>,尽管更多特定的错误是首选的。
<bad-namespace-prefix/>-- 实体发送的名字空间前缀不被支持,或者在一个需要某种前缀的元素中没有发送一个名字空间前缀(参见XML Namespace Names and Prefixes (第十一章第二节)).
<conflict/> --服务器正在关闭为这个实体激活的流,因为一个和已经存在的流有冲突的新的流已经被初始化。
<connection-timeout/>-- 实体已经很长时间没有通过这个流发生任何通信流量(可由一个本地服务策略来配置).
<host-gone/> --初始化实体在流的头信息中提供的'to'属性的值所指定的主机已经不再由这台服务器提供
<host-unknown/> --由初始化实体在流的头信息中提供的'to' 属性的值和由服务器提供的主机名不一致.
<improper-addressing/>-- 一个在两台服务器之间传送的节缺少'to' 或'from' 属性(或者这个属性没有值).
<internal-server-error/>-- 服务器配置错误或者其他未定义的内部错误,使得服务器无法提供流服务.
<invalid-from/> --在'from'属性中提供的JID 或主机名地址,和认证的JID不匹配或服务器之间无法通过SASL(或回拨)协商出合法的域名,或客户端和服务器之间无法通过它进行认证和资源绑定。
<invalid-id/> --流ID 或回拨ID 是非法的或和以前提供的ID 不一致.
<invalid-namespace/>-- 流名字空间和"http://etherx.jabber.org/streams" 不相同或回拨名字空间和"jabber:server:dialback" 不相同.(参考XML Namespace Names and Prefixes (第十一章第二节)).
<invalid-xml/> --实体通过流发送了一个非法的XML给执行验证的服务器(参考Validation (第十一章第三节)).
<not-authorized/> --实体试图在流被验证之前发送数据或不被许可执行一个和流协商有关的动作,接收实体在发送错误信息之前不允许(MUST NOT)处理厌恶的节。
<policy-violation/>-- 实体违反了某些本地服务策略;服务器可以(MAY)选择在<text/> 元素或应用程序定义的错误条件(元素)中详细说明策略。
<remote-connection-failed/>-- 服务器无法正确连接到用于验证或授权的远程实体。
<resource-constraint/>-- 服务器缺乏必要的系统资源为流服务。
<restricted-xml/> --实体试图发送受限的XML特性,比如一个注释,处理指示,DTD,实体参考,或保留的字符(参考Restrictions (第十一章第一节)).
<see-other-host/> --服务器将不提供服务给初始化实体但是把它重定向到另一台主机;服务器应该(SHOULD)在<see-other-host/>元素的XML字符数据中指明替代服务器名或IP地址(它必须(必须)是合法的域名标识)。
<system-shutdown/>-- 服务器正在关机并且所有激活的流正在被关闭。
<undefined-condition/>-- 错误条件不在本文已定义的错误条件列表之中;这个错误条件应该(SHOULD)仅用于"应用程序定义条件"元素.
<unsupported-encoding/>-- 初始化实体以一个服务器不不支持的编码方式编码了一个流(参照Character Encoding (第十一章第五节)).
<unsupported-stanza-type/>-- 初始化实体发送了一个流的一级子元素但是服务器不支持.
<unsupported-version/>-- 由初始化实体在流的头信息中指定的'version'属性的值所指定的版本不被服务器支持;服务器可以(MAY)在<text/>元素中指定一个它支持的版本号.
<xml-not-well-formed/>-- 初始化实体发送了一个不规范的XML(参考[XML]).

大家知道,应用程序可以(MAY)在error元素中包含一个适当名字空间的子元素来提供一个应用程序定义流错误信息."应用程序定义"元素应该(SHOULD)补充或甚至限定一个已定义的元素.所以 <error/> 元素将包含两个或三个子元素:
   <stream:error>
     <xml-not-well-formed xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>
     <text xml:lang='en' xmlns='urn:ietf:params:xml:ns:xmpp-streams'>
       Some special application diagnostic information!
     </text>
     <escape-your-data xmlns='application-ns'/>
   </stream:error>
   </stream:stream>

简化流示例

这里包含两个简化的例子,描述了基于流的客户端在服务器上的“会话”(这里"C"表示从客户端发给服务器,"S"表示从服务器发给客户端);这些例子只是用于举例说明原理.
一个基本的 "会话":
   C: <?xml version='1.0'?>
      <stream:stream to='example.com' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>
 
   S: <?xml version='1.0'?>
      <stream:stream from='example.com' id='someid' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>
   ...  encryption, authentication, and resource binding ...
 
   C:   <messagefrom='juliet@example.com'to='romeo@example.net'xml:lang='en'>
 
   C:     <body>Art thou not Romeo, and a Montague?</body>
 
   C:   </message>
 
   S:   <messagefrom='romeo@example.net'to='juliet@example.com'xml:lang='en'>
 
   S:     <body>Neither, fair saint, if either thee dislike.</body>
 
   S:   </message>
 
   C: </stream:stream>
 
   S: </stream:stream>

一个不成功的 "会话" :
   C: <?xml version='1.0'?>
      <stream:stream to='example.com' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>
 
   S: <?xml version='1.0'?>
      <stream:stream from='example.com' id='someid' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>
   ...  encryption, authentication, and resource binding ...
 
   C: <message xml:lang='en'>
        <body>Bad XML, no closing body tag!
      </message>
 
   S: <stream:error>
       <xml-not-well-formed xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>
      </stream:error>
 
   S: </stream:stream>


TAG:

 

评分:0

我来说两句

日历

« 2024-05-05  
   1234
567891011
12131415161718
19202122232425
262728293031 

数据统计

  • 访问量: 86418
  • 日志数: 218
  • 书签数: 1
  • 建立时间: 2010-11-06
  • 更新时间: 2011-03-21

RSS订阅

Open Toolbar