14,多个流
14.1 介绍
本章描述的OPTIONAL特性将使单一的HTTP session能够包含多个XMPP流。在限制客户端并发发送请求数量的环境下,该特性是必要的,因为如果客户端同时打开多个帐号,就需要多-流sessions。这个特性使得客户端在HTTP上建立平行的流时降低网络的传输量。
14.2 展开
如果连接管理器支持多-流特性,它在创建session响应时MUST包含‘stream‘属性。如果客户端没有收到‘stream‘属性,那么它MUST假定连接管理器不支持该特性。
‘stream‘属性指定了session需要打开的第一个流。每个‘stream‘的值MUST是一个不透明的、不可预知的名字,在连接管理器应用中是唯一的。
Example 30. 创建session响应,带有stream名字
charset=utf-8body authid=‘ServerStreamID‘ wait=‘60‘ inactivity=‘30‘ polling=‘5‘ requests=‘2‘ accept=‘deflate,gzip‘ sid=‘SomeSID‘ secure=‘true‘ stream=‘firstStreamName‘ charsets=‘ISO_8859-1 ISO-2022-JP‘ xmlns=‘http://jabber.org/protocol/httpbind‘/>
14.3 对一个Session新增流
如果连接管理器在创建session响应时包含了‘stream‘属性,那么客户端可以发送一个带有‘to‘属性的空<body/>元素来请求连接管理器打开另外一个流。该请求MUST包含有效的‘sid‘和‘rid‘属性,它SHOULD包含‘xml:lang‘属性。请求MAY包含‘route‘和‘secure‘属性,但SHOULD NOT包含‘content‘,‘hold‘或者‘wait‘属性。
Example 31. 请求另外一个流
charset=utf-8body sid=‘SomeSID‘ rid=‘1573741820‘ to=‘jabber.org‘ route=‘xmpp:jabber.org:9999‘ secure=‘true‘ xml:lang=‘en‘ xmlns=‘http://jabber.org/protocol/httpbind‘/>
如果连接管理器在session开始时没有指定它支持多流,那么它MUST忽略额外的属性,只当其是一个普通的空请求(参考发送和接收XML节)。否则,它MUST对服务器打开一个新的流(参考创建session),生成一个新的流名字并响应给客户端。响应MAY包含‘authid‘和‘secure‘属性,但是它SHOULD NOT包含‘sid‘, ‘requests‘, ‘polling‘, ‘inactivity‘, ‘accept‘, ‘charsets‘ 或者 ‘wait‘属性。
Example 32. 新增流的响应
charset=utf-8body stream=‘secondStreamName‘ authid=‘ServerStreamID‘ secure=‘true‘ xmlns=‘http://jabber.org/protocol/httpbind‘/>
Note:如果响应没有‘authid‘属性,那么其他属性MUST由之后的响应发送(参考创建session),‘stream‘属性也要被指定。
14.4 节的传输
如果一个session打开的流数目大于一个,那么连接管理器发送的所有非空<body>元素MUST包含‘stream’以指出它发送的节是属于哪个流的。相同的原因,客户端也SHOULD包含‘stream’属性。客户端MAY忽略‘stream’属性使连接管理器在所有打开的流上发送节。Note:一个<body/>元素MUST NOT含有针对不同流的不同节。
如果流的名字没有与session打开的流的某个名字相同,那么接收流的连接管理器SHOULD返回一个HTTP 404错误,或者接收流的客户端SHOULD终止session。如果接收者仅仅是关闭流(发送者在发送节的时候不可能注意到这情况),那么接受者只要简单的忽略<body/>元素包含的节就可以了。
Note:不包含‘authid‘属性的<body/>元素SHOULD NOT包含‘stream‘属性(因为没有任何信息要在流中传输)。如果这样的一个<body/>元素包含了‘stream‘属性,那么接收者SHOULD忽略该属性。
Example 33. 客户端发送的节,带有流的名字
charset=utf-8body rid=‘1249243562‘ sid=‘SomeSID‘ stream=‘secondStreamName‘ xmlns=‘http://jabber.org/protocol/httpbind‘> <message to=‘[email protected]‘ xmlns=‘jabber:client‘> <body>Hi there!</body> </message> </body>
Note:响应的‘stream’属性的值MAY与对应请求的值不同。
Example 34. 连接管理器以不同的流名字响应
charset=utf-8body stream=‘firstStreamName‘ xmlns=‘http://jabber.org/protocol/httpbind‘> <message from=‘[email protected]‘ to=‘[email protected]‘ xmlns=‘jabber:client‘> <body>Hi yourself!</body> </message> </body>
如果连接管理器没有指定流的名字,那么客户端MUST假定收到的节是与第一个流名字有关的信息(甚至在第一个流被关闭了也这样认为)。
如果客户端没有指定流的名字,那么连接管理器MUST在所有打开的流上发送节。
Example 35. 客户端请求一个节被发送(所有流上)
charset=utf-8body rid=‘1249243562‘ sid=‘SomeSID‘ xmlns=‘http://jabber.org/protocol/httpbind‘> <presence xmlns=‘jabber:client‘> <show>away</show> </presence> </body>
14.5 关闭一个流
如果一个session打开了多个流,客户端MAY在任何时候使用由终止HTTP Session中描述的方法关闭一个打开的流,要由‘stream’属性指定一个流名字。如果客户端关闭了最后一个流,连接管理器MUST终止session。如果客户端没有指定流名字,那么连接管理器MUST关闭所有打开的流(所有流发送终止请求),并且终止session。
Example 36. 客户端关闭一个流
charset=utf-8body rid=‘1249243564‘ sid=‘SomeSID‘ stream=‘secondStreamName‘ type=‘terminate‘ xmlns=‘http://jabber.org/protocol/httpbind‘> <presence type=‘unavailable‘ xmlns=‘jabber:client‘/> </body>
14.6 错误情形
如果一个session打开多个流,在失败的绑定错误中(参考终止绑定情况)连接管理器MAY包含‘stream’属性。如果‘stream’属性设置了,那么接收和发送端都MUST关闭流,但是session SHOULD NOT被终止。
Example 37. 失败的流错误
charset=utf-8body type=‘terminate‘ condition=‘remote-connection-failed‘ stream=‘secondStreamName‘ xmlns=‘http://jabber.org/protocol/httpbind‘/>
Note:如果在失败的绑定错误时,连接管理器不包含‘stream‘属性,那么session所有的流都要在接收和发送两端被关闭,session也MUST被终止。
15,错误和状态码
在HTTP响应中有4种错误和状态
表1:错误类型
Condition Type Description
HTTP Conditions 连接管理器对无效的客户端请求返回一个标准的HTTP error响应。无效的请求包括绑定语法错误,可能的攻击等。注意,受限制的客户端不能区别HTTP errors的区别。
Terminal Binding Conditions 这类错误可能由受限制的客户端读取到。用于连接管理器产生的问题,流问题以及连接管理器与XMPP服务器联络的问题。
Recoverable Binding Conditions 用于在连接管理器和客户端之间联络的问题。这种情况不需要终止session。客户端只要通过重新发送之前没有被响应的<body/>元素就可以恢复正常。
XMPP Stanza Conditions XMPP错误是与<body/>元素中XML节相关的,一般来说,由RFC或者XEP给出相应的情形。这种情况不需要终止session。(上面jabber:iq:auth给出了这样的一个例子。)
详细描述由下面提供
15.1 HTTP状况
下面给出的错误和状态码在本协议中有特别的意义(其他错误和状态码还是其本身的意义)。在收到HTTP 错误(400,403,404)时,HTTP客户端MUST认为HTTP session是空的。
Note:这些HTTP码都是在HTTP规范中定义的。在使用Jabber协议时,不要与传统的HTTP错误相混淆。
表2:HTTP错误和状态码
Code Name Purpose
200 OK 客户端请求的有效响应。
400 Bad Request 通知客户端HTTP头和绑定元素的格式是不被接受的。(比如,语法错误).
403 Forbidden 通知客户端它的请求不符合session的规则。(比如,请求太频繁,太多的并发连接)。
404 Not Found 通知客户端:(1) ‘sid‘是无效的, (2) ‘stream‘是无效的, (3) ‘rid‘值超过了希望的窗口数, (4) 连接管理器不能重新发送响应,(5) ‘key‘序列无效。
15.2 终止绑定情况
对于任意发送给客户端的响应,连接管理器MAY通过设置<body/>元素的属性‘type’值为‘terminate’来返回一个失败错误。这个错误暗示HTTP session被终止了(除非指定了‘stream’属性,参考多个流-错误情形)。(这种错误大多数也意味着RFC 3920定义的XMPP流错误,不过实际上在连接管理器与服务器之间的XMPP流错误是一个“remote-stream-error”,在下面有描述)。
Example 38. 远端连接失败的错误
charset=utf-8
body type=‘terminate‘
condition=‘remote-connection-failed‘
xmlns=‘http://jabber.org/protocol/httpbind‘/>
属性‘condition’值的定义如下。
表3:绑定错误情形
Condition Purpose
host-gone 属性‘to’指定的目标域或者属性‘route’指定的主机或者端口不在提供服务了。
host-unknown 连接管理器无法获知属性‘to’指定的目标域或者属性‘route’指定的主机或者端口。
improper-addressing 初始化元素缺少‘to’或者‘route’属性(或者属性没值),但是连接管理器需要其中之一。
internal-server-error 连接管理器收到一个内部错误,阻止其响应请求。
other-request 在请求终止session的时候,另一个请求正在被处理。
remote-connection-failed 连接管理器对XMPP服务器不能够连接、不能安全的连接、或者失去连接。
remote-stream-error 压缩一个XMPP流出错。流内容是一个从XMPP服务器接收到的<stream:error/>元素。
see-other-uri 在一个URI上(比如,连接管理器仅接收客户端在一些https:URI上的SSL或者TLS连接,而不支持在http:URI上的),连接管理器不能进行操作。客户端可以在<uri/>子元素的内容中post内容。
system-shutdown 连接管理器即将关闭。所有活动的sessions都要被终止。不能创建新的sessions。
undefined-condition 未在此定义的错误。连接管理器SHOULD在<body/>元素内容中包含一个应用程序指定的信息。
下面是一个"see-other-uri" 情形的例子:
Example 39. see-other-uri的错误
charset=utf-8body condition=‘see-other-uri‘ type=‘terminate‘ xmlns=‘http://jabber.org/protocol/httpbind‘> <uri>https://secure.jabber.org/xmppcm</uri> </body>
下面是一个"remote-stream-error"情形的例子:
Example 40. 远端错误
charset=utf-8body condition=‘remote-stream-error‘ type=‘terminate‘ xmlns=‘http://jabber.org/protocol/httpbind‘> <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‘/> </body>
当然,客户端也MAY通知连接管理器绑定错误,尽管这未必会有。
15.3 可恢复绑定情况
对于任意发送给客户端的响应,连接管理器MAY通过设置<body/>元素中属性‘type‘值为‘error‘来发送一个可恢复的错误。这种错误并不指session已经终止了。
如果决定从错误中恢复,那么客户端MUST重复发送HTTP请求以及之前所有没有收到响应的HTTP请求。这些请求的内容MUST与之前请求的<body/>元素内容相同。这就允许连接管理器由于联络失败而错过之前请求以后,可以恢复。
Example 41. 可恢复的错误
charset=utf-8body type=‘error‘ xmlns=‘http://jabber.org/protocol/httpbind‘/>
15.4 XMPP节的情况
应用级别的错误通常是由第3方产生的并且由连接管理器传递到客户端,因此他们就超出了这里定义的范围,他们在RFC或者XEP中有更详细的描述。
然而,连接管理器有可能收到一个需要发送到客户端的节,但是客户端的连接已经不在激活状态(比如在连接管理器要通知服务器该连接不在激活之前)。在此时,连接管理器要向服务器发送一个错误。由于这种情况与RFC 3920 11.1章定义的类似,因此RECOMMENDED连接管理器按照下面的做:
- 如果是<presence/>节,那么丢掉节,不必要向服务器发送错误。
- 如果是<iq/>节,那么向服务器返回<service-unavailable/>错误。
- 如果是<message/>节,那么向服务器返回<recipient-unavailable/>错误。
当服务器从连接管理器处收到一个带有<recipient-unavailable/>错误的<message/节>时,它SHOULD保存这些信息(不在线状态下允许发送消息),而不只是单单的将错误节传输给它。
16,实施备忘录
这里想象的只是将这个协议的实现作为XMPP服务器的一个连接管理器,也可能实现一个没有XMPP实现的连接管理。而且,它也可以简单的扮演处理XML结构的角色。因此在这定义的XML schemas不仅仅是针对XMPP服务器端的,使用连接管理器的应用程序应有责任处理这些错误,而不是连接管理器。
17,安全考虑
联络SHOULD在一个加密的HTTP连接上进行。客户端和连接管理器直接的加密协商SHOULD在传输层或HTTP层进行。这个协商SHOULD遵循SSL定义的HTTP/SSL协议,它MAY遵循RFC 2818定义的HTTP/TLS协议或者RFC 2817定义的HTTP协议中的TLS。
如果发送初始化session请求的连接是加密的,那么这个session的所有连接SHOULD都是加密的。如果验证检定在建立加密的连接(用来发送初始化session请求)中互换,客户端和/或连接管理器SHOULD确保相同的验证检定在session以后用到的连接中也被使用。一旦这样一个‘安全的session’建立好:
- 如果连接管理器拒绝建立一个加密的连接或者提供不同检定,那么客户端SHOULD关闭连接和终止session,无需发送其他请求。
- 如果客户端在连接(没有加密或者检定不同)中发送一个封装好的元素(是安全的session中的一部分),那么连接管理器SHOULD只要关闭连接,而SHOULD NOT终止session,因为这样已经可以帮助拒绝攻击了。
SID和RID是重要的安全因素,所以它们MUST是不可预知和不重复的(参考RFC 1750针对产生随机sid和rid的建议)。
当连接管理器独立于XMPP服务器作为一个代理时,它又有其他的安全漏洞。RECOMMENDED是:客户端通过加密确保发送的节的安全性(参考xep0116-加密的session)。
18,IANA考虑
参考IANA(The Internet Assigned Numbers Authority)
19,XMPP登记考虑
19.1 协议命名空间
参考XMPP登陆xep-0053
20,XML Schema
结束!这里是原文档。
原文转自:http://www.blogjava.net/howard/archive/2006/12/04/85309.html