XEP-0206: XMPP Over BOSH

来源:互联网 发布:国际船舶网络 编辑:程序博客网 时间:2024/06/10 04:20

转载:http://hi.baidu.com/zqhhshs/blog/item/495df024c2c77920d5074253.html


1.介绍

BOSH协议定义了如何能够有效并可靠地通过HTTP在客户端和服务器之间双向传输任意XML元素。本文档定义了一些BOSH的小扩展来将XMPP流绑定到HTTP上。

2.<body/>元素

如果BOSH的<body/>元素不为空,它应该包含以下内容之一:

* 一个完整的<stream:features/> 元素 (此时BOSH <body/> 元素一定要包含命名空间 xmlns:stream='http://etherx.jabber.org/streams')。

* 一个用于通过SASL验证的完整元素,并且要由'urn:ietf:params:xml:ns:xmpp-sasl'命名空间认定。

* 一个或者多个完整的<message/>, <presence/>, 和/或者 <iq/> 元素,由'jabber:client'命名空间认定。

* 一个<stream:error/>元素(在这种情况下, BOSH <body/>元素一定要包含命名空间 xmlns:stream='http://etherx.jabber.org/streams' 并且它一定要着重说明'remote-stream-error' 终端错误的条件),在它之前可以有0个或多个完整的<message/>, <presence/>, 和/或者 <iq/> 元素,由'jabber:client'命名空间认定。

注 意:许多BOSH客户端和连接管理器现有的特殊XMPP实现没有指定<message/>,<presence/>,或 者<iq/>元素的命名空间,因为它允许它们传输不经修改的数据节(XMPP <stream:stream/> 元素和TCP一起代表性地设置了默认的命名空间'jabber:client')。作为替代,它们只是简单地假定'jabber:client'命名空间 的所有内容都是'http://jabber.org/protocol/httpbind'命名空间的子集。

注意:可以包含TLS验证元素,但是并不推荐。有关TLS如何通过BOSH来实施的内容目前已经超过了本文档的范围。作为替代,通道加密应该在HTTP传输层完成,而不是在XMPP应用层。

3.会话创建请求

客 户端应该在会话创建请求中包含由'urn:xmpp:xbosh'命名空间认定的'version'属性。这个属性相当于定义在RFC 3920文档中XMPP <stream:stream/>元素的'version'属性。连接管理器应该相应地将其值传给XMPP服务器。

例1 使用version属性请求会话

POST /webclient HTTP/1.1Host: httpcm.jabber.orgAccept-Encoding: gzip, deflateContent-Type: text/xml; charset=utf-8Content-Length: 104<body content='text/xml; charset=utf-8'      hold='1'      rid='1573741820'      to='jabber.org'      route='xmpp:jabber.org:9999'      secure='true'      wait='60'      xml:lang='en'      xmpp:version='1.0'      xmlns='http://jabber.org/protocol/httpbind'      xmlns:xmpp='urn:xmpp:xbosh'/>
注意:与Jabber HTTP Polling中的定义的协议不同,一个开放的<stream:stream>标签并没有发送给连接管理器(因为BOSH <body/>元素一定不能包含部分XML元素)。连接管理器负责管理任何在它和XMPP服务器之间的数据流(它超越了本文档的范围)。

4.会话创建响应

连接管理器一旦收到服务器的数据,应该在它的会话创建响应或是任何后继响应中包含一个'version'属性(由'urn:xmpp:xbosh'命名空 间认定)和一个<stream:features/>元素(由'http://etherx.jabber.org/streams'命名空 间认定)。

注意:同样的程序也应用于BOSH <body/>元素中过时的特殊XMPP 'authid'属性,它包含了由XMPP服务器产生的XMPP流ID的值。这个值只在旧系统的XMPP客户端使用过时的非SASL认证协议完成摘要认证 时使用。

例2 具有流特征的会话创建响应
HTTP/1.1 200 OKContent-Type: text/xml; charset=utf-8Content-Length: 674<body wait='60'      inactivity='30'      polling='5'      requests='2'      hold='1'      accept='deflate,gzip'      sid='SomeSID'      secure='true'      charsets='ISO_8859-1 ISO-2022-JP'      xmpp:version='1.0'      authid='ServerStreamID'      xmlns='http://jabber.org/protocol/httpbind'      xmlns:xmpp='urn:xmpp:xbosh'      xmlns:stream='http://etherx.jabber.org/streams'>  <stream:features>    <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>      <mechanism>DIGEST-MD5</mechanism>      <mechanism>PLAIN</mechanism>    </mechanisms>  </stream:features></body>
如果在连接管理器的会话创建响应中没有<stream:features/>元素,客户端应该发送空的请求元素,直到它收到含有<stream:features/>元素的响应为止。

例3 具有流特征的后继响应
HTTP/1.1 200 OKContent-Type: text/xml; charset=utf-8Content-Length: 483<body xmpp:version='1.0'      authid='ServerStreamID'      xmlns='http://jabber.org/protocol/httpbind'      xmlns:xmpp='urn:xmpp:xbosh'      xmlns:stream='http://etherx.jabber.org/streams'>  <stream:features>    <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>      <mechanism>DIGEST-MD5</mechanism>      <mechanism>PLAIN</mechanism>    </mechanisms>  </stream:features></body>
注意:客户端应该忽略任何传输层安全(TLS)特性,因为BOSH的通道加密应该在HTTP层讨论。

不推荐TLS压缩(在RFC 3920中定义)和流压缩(在流压缩中定义[7]),因为压缩应该使用BOSH会话创建响应中的'accept'属性在HTTP层协商。TLS压缩和流压 缩不应该在HTTP内容编码的同时使用。

注意:当添加新数据流到会话中时,由'urn:xmpp:xbosh'命名空间认定的'version'属性也应该包含在请求和响应中。

5. 认证,源绑定和即时通讯会话的建立

以下是成功的使用XMPP协议进行认证和源绑定的实例。需要这些协议的细节说明(包括错误实例),请参考RFC 3920。

例4 SASL认证步骤1

POST /webclient HTTP/1.1
Host: httpcm.jabber.org
Accept-Encoding: gzip, deflate
Content-Type: text/xml; charset=utf-8
Content-Length: 172

<body rid='1573741821'
sid='SomeSID'
xmlns='http://jabber.org/protocol/httpbind'>
<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='DIGEST-MD5'/>
</body>
 


例5 SASL认证步骤2

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 250

<body xmlns='http://jabber.org/protocol/httpbind'>
<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
cmVhbG09InNvbWVyZWFsbSIsbm9uY2U9Ik9BNk1HOXRFUUdtMmhoIixxb3A9
ImF1dGgiLGNoYXJzZXQ9dXRmLTgsYWxnb3JpdGhtPW1kNS1zZXNzCg==
</challenge>
</body>
 


例6 SASL认证步骤3

POST /webclient HTTP/1.1
Host: httpcm.jabber.org
Accept-Encoding: gzip, deflate
Content-Type: text/xml; charset=utf-8
Content-Length: 418

<body rid='1573741822'
sid='SomeSID'
xmlns='http://jabber.org/protocol/httpbind'>
<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
dXNlcm5hbWU9InNvbWVub2RlIixyZWFsbT0ic29tZXJlYWxtIixub25jZT0i
T0E2TUc5dEVRR20yaGgiLGNub25jZT0iT0E2TUhYaDZWcVRyUmsiLG5jPTAw
MDAwMDAxLHFvcD1hdXRoLGRpZ2VzdC11cmk9InhtcHAvZXhhbXBsZS5jb20i
LHJlc3BvbnNlPWQzODhkYWQ5MGQ0YmJkNzYwYTE1MjMyMWYyMTQzYWY3LGNo
YXJzZXQ9dXRmLTgK
</response>
</body>


例7 SASL认证步骤4

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 190

<body xmlns='http://jabber.org/protocol/httpbind'>
<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
cnNwYXV0aD1lYTQwZjYwMzM1YzQyN2I1NTI3Yjg0ZGJhYmNkZmZmZAo=
</challenge>
</body>
 


例8 SASL认证步骤5

POST /webclient HTTP/1.1
Host: httpcm.jabber.org
Accept-Encoding: gzip, deflate
Content-Type: text/xml; charset=utf-8
Content-Length: 152

<body rid='1573741823'
sid='SomeSID'
xmlns='http://jabber.org/protocol/httpbind'>
<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>
</body>


例9 SASL认证步骤6

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 121

<body xmlns='http://jabber.org/protocol/httpbind'>
<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>
</body>

在收到元素以后,客户端一定还要让连接管理器通过发送“重新开始请求”来重新发送数据流,“重新开始请求”的结构如下:

* BOSH <body/> 元素一定要包含布尔型的'restart'属性,(由'urn:xmpp:xbosh'命名空间认定) 其值为真。
* BOSH <body/> 元素应该包含'to'属性。
* BOSH <body/> 元素应该包含'xml:lang'属性。
* BOSH <body/> 元素应该为空 (比如不能包含XML数据节)。然而,如果客户端在body中包含了XML数据节,连接管理器应该忽略它。

下面的例子说明了重新开始请求的格式。

例10 重新开始请求

POST /webclient HTTP/1.1
Content-Type: text/xml; charset=utf-8
Content-Length: 240

<body rid='1573741824'
sid='SomeSID'
to='jabber.org'
xml:lang='en'
xmpp:restart='true'
xmlns='http://jabber.org/protocol/httpbind'
xmlns:xmpp='urn:xmpp:xbosh'/>
 

在收到一个重新开始请求后,连接管理器一定要考虑之前由即将关闭的XMPP服务器发送的数据流。之后它一定要在同样的TCP连接上发送一个开放的<stream:stream>标签到XMPP服务器来初始化一个新的数据流。如果连接管理器收到一个来自XMPP服务器的<stream:features/>元素,它一定要将这个元素发送到客户端:

例11 重新发送请求的

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 221

<body xmlns='http://jabber.org/protocol/httpbind'
xmlns:stream='http://etherx.jabber.org/streams'>
<stream:features>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>
</stream:features>
</body>
 

客户端之后能完成任何强制的或随意的数据流特性协商。

例12 源绑定请求

POST /webclient HTTP/1.1
Content-Type: text/xml; charset=utf-8
Content-Length: 240

<body rid='1573741825'
sid='SomeSID'
xmlns='http://jabber.org/protocol/httpbind'>
<iq id='bind_1'
type='set'
xmlns='jabber:client'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
<resource>httpclient</resource>
</bind>
</iq>
</body>
 


例13 源绑定结果

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 221

<body xmlns='http://jabber.org/protocol/httpbind'>
<iq id='bind_1'
type='result'
xmlns='jabber:client'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
<jid>stpeter@jabber.org/httpclient</jid>
</bind>
</iq>
</body>
 

6. 远程数据流错误

<body/>元素的内容是来自XMPP服务器的0个或多个数据节,伴随着一个<stream:error/>元素(由'http://etherx.jabber.org/streams'命名空间认定)复本:

例14 远程错误
HTTP/1.1 200 OKContent-Type: text/xml; charset=utf-8Content-Length: 68<body condition='remote-stream-error'      type='terminate'      xmlns='http://jabber.org/protocol/httpbind'      xmlns:stream='http://etherx.jabber.org/streams'>  <message from='contact@example.com'           to='user@example.com'           xmlns='jabber:client'>    <body>I said "Hi!"</body>  </message>  <stream:error>    <xml-not-well-formed xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>    <text xmlns='urn:ietf:params:xml:ns:xmpp-streams'          xml:lang='en'>      Some special application diagnostic information!    </text>    <escape-your-data xmlns='application-ns'/>  </stream:error></body>
7. 接收者不存在或断线

即使客户端的连接不存在了,连接管理器也有可能收到要发送给客户端的数据节(例如,在连接管理器通知XMPP服务器客户端的连接已断之前)。在这种情况下,连接管理器会向XMPP服务器返回一个错误信息,我们建议连接管理器进行以下操作,因为它与RFC 3921文档第11部分的第2点中的情况类似:

  1. 如果被传递的数据节是<presence/>,悄悄地抛弃这个数据节并且不向发送者返回错误信息。
  2. 如果被传递的数据节是 <iq/>,向发送者返回一个 <service-unavailable/>错误。
  3. 如果被传递的数据节是 <message/>,向发送者返回一个<recipient-unavailable/>错误。

当XMPP服务器收到来自连接管理器的包含<recipient-unavailable/>错误的<message/>数据节时,它应该将这个消息保存起来,以备日后支持线下存储 (参见 Best Practices for Handling Offline Messages [11])时的信息传递,否则应将这个错误数据节返回给发送者。


原创粉丝点击