XEP-0124
本文的英文原文来自XEP-0124
XEP-0124: 基于同步HTTP的双向流
摘要: | 本协议定义了一个传输协议来模拟两个实体 (例如一个客户端和一个服务器) 之间的长连双向TCP连接的语义,它有效地运用多个同步的HTTP"请求/应答"对,而不需要使用频繁的轮询或者分块响应. |
---|---|
作者: | Ian Paterson, Dave Smith, Peter Saint-Andre, Jack Moffitt |
版权: | © 1999 - 2011 XMPP标准化基金会(XSF). 参见法律通告. |
状态: | 草案 |
类型: | 标准跟踪 |
版本: | 1.10 |
最后更新日期: | 2010-07-02 |
注意: 这里定义的协议是XMPP标准化基金会的一个 草案标准 .对本协议的执行是被鼓励的,也适于部署到生产系统,但是在它成为最终标准之前可能还会有一些变动.
简介
传输控制协议 (TCP; RFC 793 1 ) 经常用来建立两个实体之间的面向流的连接. 这些连接可以保持常连,使得实体之间的 "会话" 能够交互式的进行. 无论如何, 有时候设备或网络的性质可能会阻止一个应用程序去维护一个常连的TCP连接到一个服务器或对端. 在这种情况下, 需要使用一个替代的连接方法,使用排序的一系列请求和应答在短连的连接上交换信息来模拟常连的TCP连接. 通过 RFC1945 2 和 RFC2616 3 定义的超文本传输协议(HTTP)可以获得很多可用的合适的 请求-应答 语义.
BOSH, 本文定义的这种技术, 实质上为常连的双向TCP连接提供了一个 "drop-in" 的替代品. 它是一个成熟的, 全功能的技术,自2004年以来已经被广泛实现和布署. 据我们所知它是众多类似技术中的第一个, 它现在包含了正规化的Bayeux协议 4 的 彗星(Comet) 方法(译者注:Comet就是Ajax web应用程序的服务器推送技术的结合),以及 Web Socket协议 5 和 反向HTTP 6.
BOSH被设计成有效地传输任何数据并且在两个方向上都保持最小延迟. 对应用程序来讲那同时需要 "推" 和 "拉" 语义, BOSH显然比其他大多数双向的基于HTTP的传输协议更节省带宽和响应更迅速,这个技术现在通常称为 "Ajax". BOSH通过对多个同步的"HTTP请求/响应对"使用所谓"长轮询"来达到高效. 此外, 通过使用不需要"cookies"而全兼容HTTP 1.0 (见 RFC 2965 7 ) 8 或甚至访问HTTP头,BOSH可以解决受限客户端的需要 .
BOSH原本是由 Jabber/XMPP 社区开发出来替代更早的基于HTTP的技术 Jabber HTTP轮询 9 . 尽管BOSH假定HTTP请求和应答的 "载荷" 是XML, 载荷的格式未受XMPP节 (见 XMPP Core 10 ) 的限制,并且可以包含不同协议定义的命名空间的元素的混合物 (例如, 同时包含 XMPP 和 JSON). 这种混合是必要的,因为一些连接管理者可能不支持多重流,而受限的客户端经常无法访问HTTP流水线 (这限制同一时间只能拥有一个BOSH会话). BOSH连接管理者通常不需要理解它们所传输的XML的任何内容,除了确保每个XML载荷被正确的命名空间所限定.
注意: XMPP Over BOSH 11 记录了一些以前包含在本协议中的XMPP特有的扩展.
需求
以下的设计需求反映了提供接近标准TCP连接的性能的需要.
- 和受约束的运行时环境兼容* (例如, 手机和基于浏览器的客户端).
- 和缓冲了部分HTTP应答的代理兼容.
- 高效的通过那些限制HTTP响应时间的代理.
- 完全兼容HTTP/1.0.
- 兼容受限的网络连接 (例如, 防火墙, 代理, 以及网关).
- 容错 (例如, 在HTTP请求的任何阶段,底层TCP连接中断之后,会话恢复).
- 可扩展.
- 带宽消耗显著低于基于轮询的协议.
- 比基于轮询的协议显著快速响应 (低延迟).
- 支持轮询 (支持那些限制同一时间只有一个HTTP连接的客户端轮询).
- 顺序递送数据.
- 防范未经授权的用户会话注入HTTP请求.
- 防止拒绝服务攻击.
- 复用数据流.
- 注意: 和受约束的运行环境兼容意味着以下限制:
- 客户端不需要编程访问每个HTTP请求和应答的头 (例如, cookies 或 状态码).
- 每个HTTP请求和应答的 body 是一个可解析的根元素的XML.
- 客户端可以指定它们接收的HTTP应答的 Content-Type.
架构假设
本文假定大部分实现使用专门的连接管理者 ("CM") 来处理HTTP连接,而非有关应用的本地连接类型 (例如, XMPP里的TCP连接). 为了效率, 这样一个连接管理者是一个专门的HTTP服务器,用来把这里定义的HTTP请求和应答和与之通讯的服务器实现的数据流(或API)之间进行翻译, 因此使得客户端能通过HTTP的80或443端口连接到一个服务器而不是一个特定应用的端口. 我们可以图形说明如下:
服务器 | | [未封装的数据流] | HTTP连接管理器 | | [HTTP + <body/> 封装器] | 客户端
本协议仅涵盖了客户端和连接管理器的通讯. 没有涉及连接管理器和服务器之间的通讯, 因为这类通讯是和特定实现相关的 (例如, 服务器可能原生支持HTTP绑定, 在这种情况下连接管理器是一个逻辑实体而不是物理实体; 另外连接管理器可以是独立翻译代理,这样该服务器认为它在直接和客户端通过TCP交谈; 或者连接管理器和服务器可能使用组件协议或服务器定义的API).
此外, 本协议并没有限定只用于客户端和服务器之间的通讯. 例如, 它可以用于服务器之间的通讯,如果有关的应用(例如, 在XMPP里)发生了这样的通讯. 无论如何, 本文只专注于那些无法和服务器随时维护持久的TCP连接的客户端传输的使用. 我们假定服务器和组件不受那些限制,并且因此相关的应用将使用原生的连接传输. (无论如何, 在一些不可靠的网络中, BOSH可以让服务器之间的通讯更加稳定.)
BOSH技术
因为HTTP是一个同步请求/应答协议, 传统的通过HTTP模拟双向流的解决方案是让客户端HTTP间歇性地轮询连接管理器来查询是否有任何等待发送给客户端的数据. 当没有数据需要传输的时候,这种幼稚的做法在轮询的时候浪费了很多网络带宽. 它也降低了应用程序的响应,因为数据要花时间排队直到连接管理器从客户端接收下一次轮询 (HTTP 请求) . 这导致了响应速度和带宽之间难免顾此失彼, 因为增加轮询频率将在减少延迟的同时增加带宽消耗 (如果轮询频率降低的话,反之亦然).
BOSH使用的技术通过鼓励连接管理器在它确实有数据发送给客户端之前不去应答请求,同时达到低延迟和低带宽消耗的目的. 一旦客户端从连接管理器接收到一个应答,它发送另一个请求, 从而确保连接管理器 (几乎) 总是持有一个可以用来 "推送" 数据给客户端的请求.
如果客户端需要发送一些数据给连接管理器,那么它只要简单地发送第二个包含数据的请求. 不幸的是大部分受约束的客户端不支持HTTP流水线 (通过单个的连接的并发请求), 所以客户端通常需要通过第二个HTTP连接发送这个数据. 连接管理器总是应答它持有的第一个连接的请求,一旦从客户端接收到一个新的请求 -- 甚至即使没有数据发送给客户端. 它这么做可以确保客户端能在必要的时候立刻发送更多数据. (客户端同一时间不应该打开超过两个HTTP连接到连接管理器, 12 ,否则它不得不等待连接管理器应答请求中的一个.)
即使网络情况迫使每个HTTP请求都要通过不同的TCP连接,BOSH也会可靠地工作. 无论如何, 如果经常发生这种情况, 客户端可以使用HTTP/1.1, 然后 (假定网络情况稳定) 一个会话中的所有请求将在同样的两个持久TCP连接上通过. 几乎任何时候 (见下文) 客户端都可以推送数据到这两个连接中的一个, 而连接管理器能推送数据到另一个连接 (所以延迟和一个标准的TCP连接一样低). 有意思的是,注意这两个连接的角色每当客户端发送数据到连接管理器的时候就会互换.
如果在一个规定时间内(通常是几分钟)两个方向上都没有流量, 那么连接管理器以无数据来应答客户端, 并且那个应答立即触发一个新的客户端请求. 连接管理器这么做来确认是否网络连接已经中断,并且双方都在一个合理的时间内明白到这一点. 这一交换类似大部分持久TCP连接中的通用的 "keep-alive" 或 "ping" . 因为BOSH技术未使用轮询, 带宽消耗不会比标准TCP连接大很多. 13
大部分时候数据可以被立刻推送. 无论如何, 如果其中一个端点刚推送了一些数据,在它再次推送之前将不得不等待网络往返. 如果客户端可以使用HTTP流水线,那么就可以拥有多个并发的请求了. 这样客户端就总能立刻推送数据了. 它也能保证连接管理器总是持有足够的请求,这样甚至在连续发送的时候它也绝不需要在发送数据之前等待. 此外, 如果连接管理器持有的请求池太大, 那么客户端从连接管理器接收数据之后在压力之下将不能立刻发送一个新的空请求. 它只能等待,除非需要发送数据. 所以, 如果随着时间的推移,客户端接收和发出的流量平衡了, 带宽消耗将和使用标准的TCP连接相同.
连接管理器推送的每一个数据块都是一个完整的HTTP应答. 所以, 和Comet技术不像, BOSH技术是通过中间代理缓冲部分HTTP请求来工作的. 它也完全兼容HTTP/1.0 -- 不提供分块传输编码.
HTTP概述
所有信息被编码到标准的HTTP POST请求和应答的body中. 每个HTTP body包含一个单独的 <body/> 封装器用来封装被传输的XML元素 (见 XEP-0124#<body/>封装器元素 ).
客户端应该使用HTTP流水线通过一个持久的HTTP/1.1连接发送所有的HTTP请求. 不过, 客户端也可以用任何 RFC 1945 或 RFC 2616 允许的方式递送这些POST请求. 例如, 受约束的客户端可能期望打开不止多个持久连接而不是使用HTTP流水线, 或者在某些情况下打开一个新的HTTP/1.0连接来发送每个请求. 无论如何, 客户端和连接管理器不应该使用分块传输编码, 因为中间代理可能缓冲每部分的HTTP请求或应答并且在可以发送的时候只传输完整的请求或应答.
客户端可以在任何请求中包含一个HTTP Accept-Encoding头. 如果连接管理器接收到一个拥有Accept-Encoding头的请求, 它可以在应答中包含一个HTTP Content-Encoding头 (指定请求中说明的编码之一) 并据此压缩应答body.
请求和应答可以包含未在本文提到的HTTP头. 接收者应该忽略那些HTTP头.
每个BOSH会话可以分享其他用途的HTTP流量的HTTP连接, 包括其他BOSH会话以及和本协议完全无关的HTTP请求和应答 (例如, web页面下载). 无论如何, 使用HTTP流水线通过同一个连接对不是本会话一部分的请求的应答(或同一个连接中的发送队列)可能会导致对于本会话的一部分的请求的应答的延迟 (因为连接管理器必须以和接收到的请求相同的顺序来发送它的应答, 并且连接管理器通常会延迟它的某些应答).
所有客户端请求的HTTP Content-Type头应该是 "text/xml; charset=utf-8". 无论如何, 如果客户端受到某些约束,它们也可以指定其他的值 (例如, "application/x-www-form-urlencoded" 或 "text/plain"). 客户端和连接管理器应该忽略所有接收到的HTTP Content-Type头.
<body/>封装器元素
每个HTTP请求和应答的body包含一个单独的由 'http://jabber.org/protocol/httpbind' 命名空间限定的<body/>封装器元素. 这个封装器的内容就是被传输的数据. <body/>元素和它的内容都必须符合 XML 1.0 14 的一系列规格. 它们也应该符合 Namespaces in XML 15. 内容必须不包含任何以下的东西 (都定义于 XML 1.0 ):
- 部分XML元素
- XML注释
- XML处理指令
- 内部或外部DTD亚群
- 内部或外部实体引用 (预定义的实体除外)
<body/>封装器必须不包含任何XML字符串数据, 尽管它的子元素可以包含字符串数据. <body/>封装器必须包含零或多个完整的XML直接子元素(本文称为 "载荷" , 例如, 定义于 RFC 6120 的XMPP节或使用定义于 RFC 4627 16 的JSON数据交换格式来代表对象的包含XML字符串数据的元素).每个<body/>封装器可以包含各种广泛的命名空间限定的载荷.
每个客户端请求的<body/>元素必须拥有一个通过'rid'属性封装的顺序的请求ID; 具体信息, 参考本文的 请求IDs 章节.
发起BOSH会话
会话创建请求
从客户端到连接管理器的第一个请求是请求一个新的会话.
第一个请求的<body/>元素应该拥有以下属性 (它们应该不被包含在其他请求中,除非在 添加流到一个会话 时候指定):
- 'to' -- 这个属性指定第一个流的目标域.
- 'xml:lang' -- 这个属性 (定义于 XML 1.0 17 的2.12) 指定会话期间发送或接收的任何人类可读的字符串数据的缺省语言.
- 'ver' -- 这个属性指定客户端支持的BOSH协议的最高版本. 编号方案是 "<主版本号>.<小版本号>" (这里小版本号可以递增到不止一位数子, 所以它必须被当成一个单独的整数来处理). 注意: 'ver' 属性应该不被误解成任何正被传输的协议的版本.
- 'wait' -- 这个属性指定连接管理器在会话中应答任何请求之前被允许的等待时间(以秒计数). 这使客户端能限制它察觉任何网络失败之前的延迟, 并且阻止它的HTTP/TCP连接因为不活跃而过期.
- 'hold' -- 这个属性指定连接管理器在会话中被允许同时保持的请求的最大数量. 如果客户端不能使用HTTP流水线那么它应该设为 "1".
注意: 仅支持轮询会话的客户端可以通过设置'wait' 或 'hold' 为 "0" 来阻止连接管理器等待. 无论如何, 轮询是不推荐的,因为带宽消耗的增加和响应能力的降低都会达到一到两个数量级!
连接管理器可以被配置成允许在不同的域里和多个服务器进行会话. 当以一个"代理"连接管理器请求一个会话的时候, 客户端应该包含一个'route'属性来指定它想通讯的服务器的协议, 主机名, 和端口, 格式为 "proto:host:port" (例如, "xmpp:example.com:9999"). 18 一个配置成只和一个 (或只和预定义的域列表以及服务于那些域的相关主机和端口列表的) 服务器配合工作的连接管理器可以忽略 'route' 属性. (注意 'to' 属性指定服务的域, 而不是服务于那个域的机器的主机名.)
第一个请求的 <body/> 元素也可以拥有 'from' 属性, 它指定第一个流的发起者并允许连接管理器转发发起者实体的身份到应用服务器 (例如, 连接到一个XMPP服务器上的实体的 JabberID ; 见 XEP-0206 ).
客户端可以包含一个 'ack' 属性 (设为 "1") 来指示它将在会话中始终使用确认机制并且任何请求中缺少'ack'属性都是有特定意义的 (见 确认 ).
一些客户端被约束只能接受特定Content-Types (例如, "text/html")的HTTP应答. 第一个请求的<body/>元素可以拥有一个'content'属性. 它指定在会话期间必须在所有连接管理器的应答中出现的HTTP Content-Type头的值. 如果该客户端请求没有'content'属性, 那么应答的HTTP Content-Type头必须是"text/xml; charset=utf-8".
示例1. 请求一个BOSH会话
POST /webclient HTTP/1.1 Host: httpcm.example.com Accept-Encoding: gzip, deflate Content-Type: text/xml; charset=utf-8 Content-Length: 104 <body content='text/xml; charset=utf-8' from='user@example.com' hold='1' rid='1573741820' to='example.com' route='xmpp:example.com:9999' ver='1.6' wait='60' ack='1' xml:lang='en' xmlns='http://jabber.org/protocol/httpbind'/>
注意: 在第一个之后的所有请求必须包含一个有效的'sid'属性 (由连接管理器在会话创建应答中提供). 发起方请求是唯一的,在那个<body/>元素中必须没有'sid'属性.
会话创建应答
在接收到到一个新的会话请求之后, 连接管理器必须生成一个不透明的不可预测的会话标识符 (或称为 SID). 这个SID在该连接管理器应用中的上下文中必须是唯一的. 该连接管理器对客户端的会话创建请求的应答中的 <body/> 元素必须拥有以下属性 (它们应该不被包含在任何其他应答中):
- 'sid' -- 该属性指定SID
- 'wait' -- 这是连接管理器在会话期间应答任何请求之前等待的最长时间 (以秒计数) . 这个时间必须小于或等于该会话请求的指定的值.
<body/>元素也应该包含以下属性 (它们应该不被包含在任何其他应答中):
- 'ver' -- 这个属性指定连接管理器支持的BOSH协议的最高版本, 或客户端在它的请求中指定的版本, 取其中较低的版本.
- 'polling' -- 这个属性指定最小可允许的轮询借个(以秒计数). 这使得客户端不需要以超出预期的频率发送空的请求元素 (见 轮询会话 和 过度活跃 ).
- 'inactivity' -- 这个属性指定最长可允许的闲置期时间(以秒计数). 这使客户端能确保没有请求待发的时间段永远不会太长 (见 轮询会话 和 闲置 ).
- 'requests' -- 这个属性使得连接管理器能限制客户端产生的并发请求的数量 (见 过度活跃 和 轮询会话 ). 推荐的值是 "2" 或者比会话请求中指定的'hold' 属性值大一.
- 'hold' -- 这个属性通知客户端连接管理器在会话期间的任何时间将会保持等待的请求的最大数量. 这个值必须不大于客户端在会话请求中指定的值.
- 'to' -- 这个属性指定客户端尝试连接的后台服务器的通讯身份.
连接管理器可以在会话创建应答元素中包含一个'accept'属性, 来指定一个以空格分隔的可被解压的内容编码的列表. 在接收到一个带有'accept'属性的会话创建应答之后, 客户端可以在随后的请求中包含一个HTTP Content-Encoding头 (指示 'accept' 属性指定的编码之一) 并且据此压缩该请求的bodies.
连接管理器可以包含一个'ack'属性 (值设为会话创建请求中的'rid'属性值) 来指示它将在该会话中始终使用确认机制,并且任何应答中缺少'ack'属性都是有特定意义的 (见 确认 ).
如果连接管理器支持会话暂停 (见 闲置 ) 那么它应该通过在会话创建应答元素中包含一个'maxpause'属性来向客户端声明. 这个属性的值指示客户端可以请求的一个临时会话暂停的最大长度(以秒计数) .
对请求和应答都一样, <body/>元素和它的内容应该以UTF-8编码. 如果请求/应答的HTTP Content-Type头指定了一个不同于UTF-8的字符编码, 那么连接管理器可以在UTF-8和该字符编码之间转换. 无论如何, 即使在这种情况下, 连接管理器转换编码也是可选的. 连接管理器可以通知客户端哪些编码它能够转换,通过在会话创建应答元素中设置可选的'charsets'属性为以空格分隔的编码列表. 19
一旦连接管理器建立了一个连接到服务器并发现它的身份, 它可以在应答中包含一个'from'属性来转发这个身份给客户端, 要么在它的会话创建应答中, 要么 (如果那个时候它还没有从服务器接收到它的身份) 任何随后给客户端的应答中. 如果它建立了一个安全连接到服务器 (定义于 发起BOSH会话 ), 那么在同一个应答中连接管理器也应该包含'secure'属性并把值设为 "true" 或 "1".
示例2. 会话创建应答
HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: 128 <body wait='60' inactivity='30' polling='5' requests='2' hold='1' ack='1573741820' accept='deflate,gzip' maxpause='120' sid='SomeSID' charsets='ISO_8859-1 ISO-2022-JP' ver='1.6' from='example.com' xmlns='http://jabber.org/protocol/httpbind'/>
示例3. 随后的包含'from'和'secure'属性的应答
HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: 128 <body from='example.com' xmlns='http://jabber.org/protocol/httpbind'/>
发送和接收XML载荷
客户端成功完成所有必需的前提条件之后, 它就可以通过HTTP绑定来发送和接收XML载荷了.
示例4. 传输载荷
POST /webclient HTTP/1.1 Host: httpcm.example.com Accept-Encoding: gzip, deflate Content-Type: text/xml; charset=utf-8 Content-Length: 188 <body rid='1249243562' sid='SomeSID' xmlns='http://jabber.org/protocol/httpbind'> <message to='contact@example.com' xmlns='jabber:client'> <body>Good morning!</body> </message> <message to='friend@example.com' xmlns='jabber:client'> <body>Hey, what's up?</body> </message> </body>
在收到一个请求之后,一旦有可能连接管理器应该转发<body/>元素的内容到服务器. 在任何情况下它必须按照它们的'rid'属性指定的顺序来从不同的请求转发内容.
连接管理器也必须在<body/>元素中返回一个HTTP 200 OK应答给客户端. 注意: 这并不表示载荷已经被成功发送到应用服务器.
建议连接管理器在载荷已经从服务器到达客户端之前不要返回HTTP结果. 无论如何, 连接管理器不应该让等待时间超过客户在它的会话创建请求中指定的'wait'属性的值 , 而且在同一时间它保持的HTTP请求数量不应该多于会话创建请求中的'hold'属性的值. 任何情况下它必须以它们的'rid'属性指定的顺序来应答请求.
如果在等待周期里没有载荷等待或准备好发送, 那么连接管理器应该在HTTP结果中包含一个空的<body/>元素:
示例5. 空应答
HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: 64 <body xmlns='http://jabber.org/protocol/httpbind'/>
如果连接管理器已经从应用服务器收到一个或多个载荷要发送给客户端, 那么在它从服务器收到它们之后一旦有可能它应该立即在它的应答的bodu中返回这些载荷. 以下这个例子包含被不同命名空间限定的载荷:
示例6. 排队节的应答
HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: 185 <body xmlns='http://jabber.org/protocol/httpbind' xmlns:json='http://json.org/'> <message from='contact@example.com' to='user@example.com' xmlns='jabber:client'> <body>Good morning to you!</body> </message> <message from='friend@example.com' to='user@example.com' xmlns='jabber:client'> <body>Not much, how about with you?</body> </message> <json:json> [ { "precision": "zip", "Latitude": 37.7668, "Longitude": -122.3959, "Address": "", "City": "SAN FRANCISCO", "State": "CA", "Zip": "94107", "Country": "US" }, { "precision": "zip", "Latitude": 37.371991, "Longitude": -122.026020, "Address": "", "City": "SUNNYVALE", "State": "CA", "Zip": "94085", "Country": "US" } ] </json:json> </body>
客户端可以通过发送空的<body/>元素来轮询连接管理器的输入节.
示例7. 请求XML载荷
POST /webclient HTTP/1.1 Host: httpcm.example.com Accept-Encoding: gzip, deflate Content-Type: text/xml; charset=utf-8 Content-Length: 88 <body rid='1249243563' sid='SomeSID' xmlns='http://jabber.org/protocol/httpbind'/>
连接管理器必须以和它从客户端接收载荷同样的方法等待并应.
确认
请求确认
当应答一个保持的请求时, 如果连接管理器发现它已经接收了另一个更高'rid'属性的请求(通常此时它正在保持第一个请求), 那么它可以向客户端确认已收到. 当连接管理器也接收了所有更低的'rid'属性的请求时,它可以设置任何应答的 'ack' 属性高于它已经接收到的最高的'rid'属性.
示例8. 应答请求的确认
HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: 64 <body ack='1249243564' xmlns='http://jabber.org/protocol/httpbind'/>
如果连接管理器在一个会话过程中将要包含'ack'属性, 那么它必须在它的会话创建应答中包含一个'ack'属性, 并且在会话过程中始终设置应答的'ack'属性. 唯一的例外是, 在它的会话创建应答之后, 如果这个值和任何要应答的请求的'rid'值相同,连接管理器不应该包含一个'ack'属性在应答之中.
如果连接管理器被允许同一时间保持多个请求, then the reception of a lower-than-expected 'ack' value from the connection manager (or the unexpected abscence of an 'ack' attribute) can give the client an early warning that a network failure might have occurred (e.g., if the client believes the connection manager should have received another request by the time it responded).
应答确认
The client MAY similarly inform the connection manager about the responses it has received by setting the 'ack' attribute of any request to the value of the highest 'rid' of a request for which it has already received a response in the case where it has also received all responses associated with lower 'rid' values. If the client will be including 'ack' attributes on requests during a session, then it MUST include an 'ack' attribute (set to '1') in its session creation request, and set the 'ack' attribute of requests throughout the session. The only exception is that, after its session creation request, the client SHOULD NOT include an 'ack' attribute in any request if it has received responses to all its previous requests.
Example 9. Request with response acknowledgement
POST /webclient HTTP/1.1 Host: httpcm.example.com Accept-Encoding: gzip, deflate Content-Type: text/xml; charset=utf-8 Content-Length: 88 <body rid='1249243566' sid='SomeSID' ack='1249243564' xmlns='http://jabber.org/protocol/httpbind'/>
After receiving a request with an 'ack' value less than the 'rid' of the last request that it has already responded to, the connection manager MAY inform the client of the situation by sending its next response immediately instead of waiting until it has payloads to send to the client (e.g., if some time has passed since it responded). In this case it SHOULD include a 'report' attribute set to one greater than the 'ack' attribute it received from the client, and a 'time' attribute set to the number of milliseconds since it sent the response associated with the 'report' attribute.
Example 10. Response with report
HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: 64 <body report='1249243565' time='852' xmlns='http://jabber.org/protocol/httpbind'/>
Upon reception of a response with 'report' and 'time' attributes, if the client has still not received the response associated with the request identifier specified by the 'report' attribute, then it MAY choose to resend the request associated with the missing response (see Broken Connections).
Inactivity
After receiving a response from the connection manager, if none of the client's requests are still being held by the connection manager (and if the session is not a Polling Session), the client SHOULD make a new request as soon as possible. In any case, if no requests are being held, the client MUST make a new request before the maximum inactivity period has expired. The length of this period (in seconds) is specified by the 'inactivity' attribute in the session creation response.
If the connection manager has responded to all the requests it has received within a session and the time since its last response is longer than the maximum inactivity period, then it SHOULD assume the client has been disconnected and terminate the session without informing the client. If the client subsequently makes another request, then the connection manager SHOULD respond as if the session does not exist.
If the connection manager did not specify a maximum inactivity period in the session creation response, then it SHOULD allow the client to be inactive for as long as it chooses.
If the session is not a polling session then the connection manager SHOULD specify a relatively short inactivity period to ensure that disconnections are discovered as quickly as possible. The RECOMMENDED time would be a little more than the number of seconds for a comfortable network round trip between the connection manager and the client under difficult network conditions (since the client can be expected to make a new request immediately -- see above).
If a client encounters an exceptional temporary situation during which it will be unable to send requests to the connection manager for a period of time greater than the maximum inactivity period (e.g., while a runtime environment changes from one web page to another), and if the connection manager included a 'maxpause' attribute in its Session Creation Response, then the client MAY request a temporary increase to the maximum inactivity period by including a 'pause' attribute in a request. Note: If the connection manager did not specify a 'maxpause' attribute at the start of the session then the client MUST NOT send a 'pause' attribute during the session.
Example 11. Requesting a Session Pause
POST /webclient HTTP/1.1 Host: httpcm.example.com Accept-Encoding: gzip, deflate Content-Type: text/xml; charset=utf-8 Content-Length: 98 <body rid='1249243564' sid='SomeSID' pause='60' xmlns='http://jabber.org/protocol/httpbind'/>
Upon reception of a session pause request, if the requested period is not greater than the maximum permitted time, then the connection manager SHOULD respond immediately to all pending requests (including the pause request) and temporarily increase the maximum inactivity period to the requested time. Note: The response to the pause request MUST NOT contain any payloads.
Note: If the client simply wants the connection manager to return all the requests it is holding then it MAY set the value of the 'pause' attribute to be the value of the 'inactivity' attribute in the connection manager's session creation response. (If the client believes it is in danger of becoming disconnected indefinitely then it MAY even request a temporary reduction of the maximum inactivity period by specifying a 'pause' value less than the 'inactivity' value, thus enabling the connection manager to discover any subsequent disconnection more quickly.)
The connection manager SHOULD set the maximum inactivity period back to normal upon reception of the next request from the client (assuming the connection manager has not already terminated the session).
Overactivity
The client SHOULD NOT make more simultaneous requests than specified by the 'requests' attribute in the connection manager's Session Creation Response. However the client MAY make one additional request if it is to pause or terminate a session.
If during any period the client sends a sequence of new requests (i.e. requests with incremented rid attributes, not repeat requests) longer than the number specified by the 'requests' attribute, and if the connection manager has not yet responded to any of the requests, and if the last request did not include either a 'pause' attribute or a 'type' attribute set to "terminate", then the connection manager SHOULD consider that the client is making too many simultaneous requests, and terminate the HTTP session with a 'policy-violation' terminal binding error to the client. Note: This behavior applies to equally to normal and polling sessions.
Example 12. Too many simultaneous requests response
HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: 68 <body type='terminate' condition='policy-violation' xmlns='http://jabber.org/protocol/httpbind'/>
Note: If the connection manager did not specify a 'requests' attribute in the session creation response, then it MUST allow the client to send as many simultaneous requests as it chooses.
If during any period the client sends a sequence of new requests equal in length to the number specified by the 'requests' attribute, and if the connection manager has not yet responded to any of the requests, and if the last request was empty and did not include either a 'pause' attribute or a 'type' attribute set to "terminate", and if the last two requests arrived within a period shorter than the number of seconds specified by the 'polling' attribute in the session creation response, then the connection manager SHOULD consider that the client is making requests more frequently than it was permitted and terminate the HTTP session and return a 'policy-violation' terminal binding error to the client. Note: the behavior for Polling Sessions is slightly different.
Example 13. Too frequent requests response
HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: 68 <body type='terminate' condition='policy-violation' xmlns='http://jabber.org/protocol/httpbind'/>
Note: If the connection manager did not specify a 'polling' attribute in the session creation response, then it MUST allow the client to send requests as frequently as it chooses.
Polling Sessions
It is not always possible for a constrained client to either use HTTP Pipelining or open more than one HTTP connection with the connection manager at a time. In this case the client SHOULD inform the connection manager by setting the values of the 'wait' and/or 'hold' attributes in its session creation request to "0", and then "poll" the connection manager at regular intervals throughout the session for payloads it might have received from the server. Note: Even if the client does not request a polling session, the connection manager MAY require a client to use polling by setting the 'requests' attribute (which specifies the number of simultaneous requests the client can make) of its Session Creation Response to "1", however this is NOT RECOMMENDED.
If a session will use polling, the connection manager SHOULD specify a higher than normal value for the 'inactivity' attribute (see Inactivity) in its session creation response. The increase SHOULD be greater than the value it specifies for the 'polling' attribute.
If the client sends two consecutive empty new requests (i.e. requests with incremented rid attributes, not repeat requests) within a period shorter than the number of seconds specified by the 'polling' attribute (the shortest allowable polling interval) in the session creation response, and if the connection manager's response to the first request contained no payloads, then upon reception of the second request the connection manager SHOULD terminate the HTTP session and return a 'policy-violation' terminal binding error to the client.
Example 14. Too frequent polling response
HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: 68 <body type='terminate' condition='policy-violation' xmlns='http://jabber.org/protocol/httpbind'/>
Note: If the connection manager did not specify a 'polling' attribute in the session creation response, then it MUST allow the client to poll as frequently as it chooses.
Terminating the HTTP Session
At any time, the client MAY gracefully terminate the session by sending a <body/> element with a 'type' attribute set to "terminate". The termination request MAY include one or more payloads that the connection manager MUST forward to the server to ensure graceful logoff.
Example 15. Session termination by client
POST /webclient HTTP/1.1 Host: httpcm.example.com Accept-Encoding: gzip, deflate Content-Type: text/xml; charset=utf-8 Content-Length: 153 <body rid='1249243565' sid='SomeSID' type='terminate' xmlns='http://jabber.org/protocol/httpbind'> <presence type='unavailable' xmlns='jabber:client'/> </body>
The connection manager SHOULD respond to this request with an HTTP 200 OK containing an empty <body/> element.
Example 16. Connection manager acknowledges termination
HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: 72 <body type='terminate' xmlns='http://jabber.org/protocol/httpbind'/>
Upon receiving the response, the client MUST consider the HTTP session to have been terminated.
Request IDs
Generation
The client MUST generate a large, random, positive integer for the initial 'rid' (see Security Considerations) and then increment that value by one for each subsequent request. The client MUST take care to choose an initial 'rid' that will never be incremented above 9007199254740991 [21] within the session. In practice, a session would have to be extraordinarily long (or involve the exchange of an extraordinary number of packets) to exceed the defined limit.
In-Order Message Forwarding
When a client makes simultaneous requests, the connection manager might receive them out of order. The connection manager MUST forward the payloads to the server and respond to the client requests in the order specified by the 'rid' attributes. The client MUST process responses received from the connection manager in the order the requests were made.
The connection manager SHOULD expect the 'rid' attribute to be within a window of values greater than the 'rid' of the previous request. The size of the window is equal to the maximum number of simultaneous requests allowed by the connection manager. If it receives a request with a 'rid' greater than the values in the window, then the connection manager MUST terminate the session with an error:
Example 17. Unexpected rid error
HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: 68 <body type='terminate' condition='item-not-found' xmlns='http://jabber.org/protocol/httpbind'/>
Broken Connections
Unreliable network communications or client constraints can result in broken connections. The connection manager SHOULD remember the 'rid' and the associated HTTP response body of the client's most recent requests which were not session pause requests (see Inactivity) and which did not result in an HTTP or binding error. The number of responses to non-pause requests kept in the buffer SHOULD be either the same as the maximum number of simultaneous requests allowed by the connection manager or, if Acknowledgements are being used, the number of responses that have not yet been acknowledged.
If the network connection is broken or closed before the client receives a response to a request from the connection manager, then the client MAY resend an exact copy of the original request. Whenever the connection manager receives a request with a 'rid' that it has already received, it SHOULD return an HTTP 200 (OK) response that includes the buffered copy of the original XML response to the client (i.e., a <body/> wrapper possessing appropriate attributes and optionally containing one or more XML payloads). If the original response is not available (e.g., it is no longer in the buffer), then the connection manager MUST return an 'item-not-found' terminal binding error:
Example 18. Response not in buffer error
HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: 68 <body type='terminate' condition='item-not-found' xmlns='http://jabber.org/protocol/httpbind'/>
Note: The error is the same whether the 'rid' is too large or too small. This makes it more difficult for an attacker to discover an acceptable value.
Protecting Insecure Sessions
Applicability
The OPTIONAL key sequencing mechanism described here MAY be used if the client's session with the connection manager is not secure. The session SHOULD be considered secure only if all client requests are made via SSL (or TLS) HTTP connections and the connection manager generates an unpredictable session ID. If the session is secure, it is not necessary to use this key sequencing mechanism.
Even if the session is not secure, the unpredictable session and request IDs specified in the preceding sections of this document already provide a level of protection similar to that provided by a connection bound to a single pair of persistent TCP/IP connections, and thus provide sufficient protection against a 'blind' attacker. However, in some circumstances, the key sequencing mechanism defined below helps to protect against a more determined and knowledgeable attacker.
It is important to recognize that the key sequencing mechanism defined below helps to protect only against an attacker who is able to view the contents of all requests or responses in an insecure session but who is not able to alter the contents of those requests (in this case, the mechanism prevents the attacker from injecting HTTP requests into the session, e.g., termination requests or responses). However, the key sequencing mechanism does not provide any protection when the attacker is able to alter the contents of insecure requests or responses.
Introduction
The HTTP requests of each session MAY be spread across a series of different socket connections. This would enable an unauthorized user that obtains the session ID and request ID of a session to then use their own socket connection to inject <body/> request elements into the session and receive the corresponding responses.
The key sequencing mechanism below protects against such attacks by enabling a connection manager to detect <body/> request elements injected by a third party.
Generating the Key Sequence
Prior to requesting a new session, the client MUST select an unpredictable counter ("n") and an unpredictable value ("seed"). The client then processes the "seed" through a cryptographic hash and converts the resulting 160 bits to a hexadecimal string K(1). It does this "n" times to arrive at the initial key K(n). The hashing algorithm MUST be SHA-1 as defined in RFC 3174 [22].
Example 19. Creating the key sequence
K(1) = hex(SHA-1(seed)) K(2) = hex(SHA-1(K(1))) ... K(n) = hex(SHA-1(K(n-1)))
Use of Keys
The client MUST set the 'newkey' attribute of the first request in the session to the value K(n).
Example 20. Session Request with Initial Key
POST /webclient HTTP/1.1 Host: httpcm.example.com Accept-Encoding: gzip, deflate Content-Type: text/xml; charset=utf-8 Content-Length: 104 <body content='text/xml; charset=utf-8' hold='1' rid='1573741820' to='example.com' wait='60' xml:lang='en' newkey='ca393b51b682f61f98e7877d61146407f3d0a770' xmlns='http://jabber.org/protocol/httpbind'/>
The client MUST set the 'key' attribute of all subsequent requests to the value of the next key in the generated sequence (decrementing from K(n-1) towards K(1) with each request sent).
Example 21. Request with Key
POST /webclient HTTP/1.1 Host: httpcm.example.com Accept-Encoding: gzip, deflate Content-Type: text/xml; charset=utf-8 Content-Length: 88 <body rid='1573741821' sid='SomeSID' key='bfb06a6f113cd6fd3838ab9d300fdb4fe3da2f7d' xmlns='http://jabber.org/protocol/httpbind'/>
The connection manager MAY verify the key by calculating the SHA-1 hash of the key and comparing it to the 'newkey' attribute of the previous request (or the 'key' attribute if the 'newkey' attribute was not set). If the values do not match (or if it receives a request without a 'key' attribute and the 'newkey' or 'key' attribute of the previous request was set), then the connection manager MUST NOT process the element, MUST terminate the session, and MUST return an 'item-not-found' terminal binding error.
Example 22. Invalid Key Sequence Error
HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: 68 <body type='terminate' condition='item-not-found' xmlns='http://jabber.org/protocol/httpbind'/>
Switching to Another Key Sequence
A client SHOULD choose a high value for "n" when generating the key sequence. However, if the session lasts long enough that the client arrives at the last key in the sequence K(1) then the client MUST switch to a new key sequence.
The client MUST:
1. Choose new values for "seed" and "n". 2. Generate a new key sequence using the algorithm defined above. 3. Set the 'key' attribute of the request to the next value in the old sequence (i.e. K(1), the last value). 4. Set the 'newkey' attribute of the request to the value K(n) from the new sequence.
Example 23. New Key Sequence
POST /webclient HTTP/1.1 Host: httpcm.example.com Accept-Encoding: gzip, deflate Content-Type: text/xml; charset=utf-8 Content-Length: 188 <body rid='1573741822' sid='SomeSID' key='6f825e81f4532b2c5fa2d12457d8a1f22e8f838e' newkey='113f58a37245ec9637266cf2fb6e48bfeaf7964e' xmlns='http://jabber.org/protocol/httpbind'> <message to='contact@example.com' xmlns='jabber:client'> <body>I said "Hi!"</body> </message> </body>
Multiple Streams
Introduction
The OPTIONAL feature described in this section enables multiple XML streams to be contained within a single HTTP session. This feature is essential in runtime environments that prevent HTTP Pipelining, thereby constraining the number of simultaneous HTTP requests a client can make to each connection manager, since clients running in such environments need multi-stream sessions if they are to connect using more than one account at the same time. This feature also reduces network traffic for any client that needs to establish parallel streams over HTTP.
Discovery
If a connection manager supports the multi-streams feature, it MUST include a 'stream' attribute in its Session Creation Response. If a client does not receive the 'stream' attribute then it MUST assume that the connection manager does not support the feature. [23]
The 'stream' attribute identifies the first stream to be opened for the session. The value of each 'stream' attribute MUST be an opaque and unpredictable name that is unique within the context of the connection manager application.
Example 24. Session creation response with stream name
HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: 128 <body wait='60' inactivity='30' polling='5' requests='2' hold='1' accept='deflate,gzip' stream='firstStreamName' maxpause='120' sid='SomeSID' charsets='ISO_8859-1 ISO-2022-JP' ver='1.6' from='example.com' xmlns='http://jabber.org/protocol/httpbind'/>
Adding Streams To A Session
If the connection manager included a 'stream' attribute in its session creation response then the client MAY ask it to open another stream at any time by sending it an empty <body/> element with a 'to' attribute. The request MUST include valid 'sid' and 'rid' [24] attributes, and SHOULD also include an 'xml:lang' attribute. The request MAY include 'route', 'from' and 'secure' attributes (see Session Creation Request), but it SHOULD NOT include 'ver', 'content', 'hold' or 'wait' attributes (since a new session is not being created).
Example 25. Requesting another stream
POST /webclient HTTP/1.1 Host: httpcm.example.com Accept-Encoding: gzip, deflate Content-Type: text/xml; charset=utf-8 Content-Length: 104 <body sid='SomeSID' rid='1573741820' to='example.com' route='xmpp:example.com:9999' xml:lang='en' xmlns='http://jabber.org/protocol/httpbind'/>
If the connection manager did not indicate its support for multiple streams at the start of the session, then it MUST ignore the extra attributes and treat the request as a normal empty request for payloads (see Sending and Receiving XML Payloads). [25] Otherwise it MUST open a new stream with the specified server (see Session Creation Response), generate a new stream name, and respond to the client with the name. The response MAY also include 'from' and 'secure' attributes, but it SHOULD NOT include 'sid', 'requests', 'polling', 'hold', 'inactivity', 'maxpause', 'accept', 'charsets', 'ver' or 'wait' attributes.
Example 26. Add stream response
HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: 128 <body stream='secondStreamName' from='example.com' xmlns='http://jabber.org/protocol/httpbind'/>
Note: If the response did not include either 'from' or 'secure' attributes then they MAY be sent in a subsequent response instead (see Session Creation Response). In that case the 'stream' attribute MUST also be specified.
Transmitting Payloads
If more than one stream has been opened within a session, then all non-empty <body/> elements sent by the connection manager MUST include a 'stream' attribute that specifies which stream all the payloads it contains belong to. The client SHOULD include a 'stream' attribute for the same purpose. The client MAY omit the 'stream' attribute if it wants the connection manager to broadcast the payloads over all open streams. Note: A <body/> element MUST NOT contain different payloads for different streams.
If a stream name does not correspond to one of the session's open streams, then the receiving connection manager SHOULD return an 'item-not-found' terminal binding error, or the receiving client SHOULD terminate the session. However, if the receiving entity has only just closed the stream (and the sender might not have been aware of that when it sent the payloads), then it MAY instead simply silently ignore any payloads the <body/> element contains.
Note: Empty <body/> elements that do not include a 'from' or 'secure' attribute SHOULD NOT include a 'stream' attribute (since nothing is being transmitted for any stream). If such a <body/> element does include a 'stream' attribute then the receiving entity SHOULD ignore the attribute.
Example 27. Client sends payload with a stream name
POST /webclient HTTP/1.1 Host: httpcm.example.com Accept-Encoding: gzip, deflate Content-Type: text/xml; charset=utf-8 Content-Length: 188 <body rid='1249243562' sid='SomeSID' stream='secondStreamName' xmlns='http://jabber.org/protocol/httpbind'> <message to='contact@example.com' xmlns='jabber:client'> <body>I said hello.</body> </message> </body>
Note: The value of the 'stream' attribute of the response MAY be different than the corresponding request. [26]
Example 28. Connection manager responds with a different stream name
HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: 185 <body stream='firstStreamName' xmlns='http://jabber.org/protocol/httpbind'> <message from='contact@example.com' to='user@example.com' xmlns='jabber:client'> <body>Hi yourself!</body> </message> </body>
If no stream name is specified by the connection manager then the client MUST assume the payloads are associated with the first stream (even if the first stream has been closed).
If no stream name is specified by the client then the connection manager MUST broadcast the payloads over all open streams. [27]
Example 29. Client asks for a payload to be broadcast
POST /webclient HTTP/1.1 Host: httpcm.example.com Accept-Encoding: gzip, deflate Content-Type: text/xml; charset=utf-8 Content-Length: 188 <body rid='1249243562' sid='SomeSID' xmlns='http://jabber.org/protocol/httpbind'> <presence xmlns='jabber:client'> <show>away</show> </presence> </body>
Closing a Stream
If more than one stream is open within a session, the client MAY close one open stream at any time using the procedure described in the section Terminating the HTTP Session above, taking care to specify the stream name with a 'stream' attribute. If the client closes the last stream the connection manager MUST terminate the session. If the client does not specify a stream name then the connection manager MUST close all open streams (sending any payloads the terminate request contains to all streams), and terminate the session.
Example 30. Client closes one stream
POST /webclient HTTP/1.1 Host: httpcm.example.com Accept-Encoding: gzip, deflate Content-Type: text/xml; charset=utf-8 Content-Length: 153 <body rid='1249243564' sid='SomeSID' stream='secondStreamName' type='terminate' xmlns='http://jabber.org/protocol/httpbind'> <presence type='unavailable' xmlns='jabber:client'/> </body>
Error Conditions
If more than one stream is open within a session, the connection manager MAY include a 'stream' attribute in a fatal binding error (see Terminal Binding Conditions). If a 'stream' attribute is specified then the stream MUST be closed by both entities but the session SHOULD NOT be terminated.
Example 31. Fatal stream error
HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: 68 <body type='terminate' condition='remote-connection-failed' stream='secondStreamName' xmlns='http://jabber.org/protocol/httpbind'/>
Note: If the connection manager does not include a 'stream' attribute in a fatal binding error then all the session's open streams MUST be closed by both entities and the session MUST be terminated.
Error and Status Codes
There are four types of error and status reporting in HTTP responses:
Table 1: Error Condition Types
Condition Type | Description |
---|---|
HTTP Conditions (Deprecated) | The connection manager responds to an invalid request from a legacy client with a standard HTTP error. These are used for binding syntax errors, possible attacks, etc. Note that constrained clients are unable to differentiate between HTTP errors. |
Terminal Binding Conditions | These error conditions can be read by constrained clients. They are used for connection manager problems, abstracting stream errors, communication problems between the connection manager and the server, and invalid client requests (binding syntax errors, possible attacks, etc.) |
Recoverable Binding Conditions | These report communication problems between the connection manager and the client. They do not terminate the session. Clients recover from these errors by resending all the preceding <body/> wrappers that have not received responses. |
Transported Protocol Conditions | Errors relating to the XML payloads within <body/> wrappers are, in general, defined in the documentation of the protocol being transported. They do not terminate the session. |
Full descriptions are provided below.
HTTP Conditions
Note: All HTTP codes except 200 have been superseded by Terminal Binding Conditions to allow clients to determine whether the source of errors is the connection manager application or an HTTP intermediary.
A legacy client (or connection manager) is a client (or connection manager) that did not include a 'ver' attribute in its session creation request (or response). A legacy client (or connection manager) will interpret (or respond with) HTTP error codes according to the table below. Non-legacy connection managers SHOULD NOT send HTTP error codes unless they are communicating with a legacy client. Upon receiving an HTTP error (400, 403, 404), a legacy client or any client that is communicating with a legacy connection manager MUST consider the HTTP session to be null and void. A non-legacy client that is communicating with a non-legacy connection manager MAY consider that the session is still active.
Table 2: HTTP Error and Status Codes
Code | Name | Superseded by | Purpose |
---|---|---|---|
200 | OK | - | Response to valid client request. |
400 | Bad Request | bad-request | Inform client that the format of an HTTP header or binding element is unacceptable (e.g., syntax error). |
403 | Forbidden | policy-violation | Inform client that it has broken the session rules (polling too frequently, requesting too frequently, too many simultaneous requests). |
404 | Not Found | item-not-found | Inform client that (1) 'sid' is not valid, (2) 'stream' is not valid, (3) 'rid' is larger than the upper limit of the expected window, (4) connection manager is unable to resend response, (5) 'key' sequence is invalid. |
Note: No other HTTP error and status codes were defined in the early versions of BOSH (e.g., Internal Server Error).
Terminal Binding Conditions
In any response it sends to the client, the connection manager MAY return a fatal error by setting a 'type' attribute of the <body/> element to "terminate". These binding errors imply that the HTTP session is terminated (unless a 'stream' attribute is specified -- see Multiple Stream Error Conditions).
Note: Although many of these conditions are similar to the XMPP stream error conditions specified in RFC 6120, they are not to be confused with XMPP stream errors. In cases where BOSH is being used to transport XMPP, any fatal XMPP stream error conditions experienced between the connection manager and the XMPP server SHOULD only be reported using the "remote-stream-error" condition as described below.
Example 32. Remote connection failed error
HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: 68 <body type='terminate' condition='remote-connection-failed' xmlns='http://jabber.org/protocol/httpbind'/>
The following values of the 'condition' attribute are defined:
Table 3: Terminal Binding Error Conditions
Condition | Purpose |
---|---|
bad-request* | The format of an HTTP header or binding element received from the client is unacceptable (e.g., syntax error). |
host-gone | The target domain specified in the 'to' attribute or the target host or port specified in the 'route' attribute is no longer serviced by the connection manager. |
host-unknown | The target domain specified in the 'to' attribute or the target host or port specified in the 'route' attribute is unknown to the connection manager. |
improper-addressing | The initialization element lacks a 'to' or 'route' attribute (or the attribute has no value) but the connection manager requires one. |
internal-server-error | The connection manager has experienced an internal error that prevents it from servicing the request. |
item-not-found* | (1) 'sid' is not valid, (2) 'stream' is not valid, (3) 'rid' is larger than the upper limit of the expected window, (4) connection manager is unable to resend response, (5) 'key' sequence is invalid. |
other-request | Another request being processed at the same time as this request caused the session to terminate. |
policy-violation* | The client has broken the session rules (polling too frequently, requesting too frequently, sending too many simultaneous requests). |
remote-connection-failed | The connection manager was unable to connect to, or unable to connect securely to, or has lost its connection to, the server. |
remote-stream-error | Encapsulates an error in the protocol being transported. |
see-other-uri | The connection manager does not operate at this URI (e.g., the connection manager accepts only SSL or TLS connections at some https: URI rather than the http: URI requested by the client). The client can try POSTing to the URI in the content of the <uri/> child element. |
system-shutdown | The connection manager is being shut down. All active HTTP sessions are being terminated. No new sessions can be created. |
undefined-condition | The error is not one of those defined herein; the connection manager SHOULD include application-specific information in the content of the <body/> wrapper. |
- If the client did not include a 'ver' attribute in its session creation request then the connection manager SHOULD send a deprecated HTTP Error Condition instead of this terminal binding condition. If the connection manager did not include a 'ver' attribute in its session creation response then the client SHOULD expect it to send a deprecated HTTP Error Condition instead of this terminal binding condition.
The following is an example of a "see-other-uri" condition:
Example 33. See other URI error
HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: 68 <body condition='see-other-uri' type='terminate' xmlns='http://jabber.org/protocol/httpbind'> <uri>https://secure.jabber.org/xmppcm</uri> </body>
The following is an example including a "remote-stream-error" condition:
Example 34. Remote error
HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-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>
Naturally, the client MAY report binding errors to the connection manager as well, although this is unlikely.
Recoverable Binding Conditions
In any response it sends to the client, the connection manager MAY return a recoverable error by setting a 'type' attribute of the <body/> element to "error". These errors do not imply that the HTTP session is terminated.
If it decides to recover from the error, then the client MUST repeat the HTTP request that resulted in the error, as well as all the preceding HTTP requests that have not received responses. The content of these requests MUST be identical to the <body/> elements of the original requests. This enables the connection manager to recover a session after the previous request was lost due to a communication failure.
Example 35. Recoverable error
HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: 68 <body type='error' xmlns='http://jabber.org/protocol/httpbind'/>
XML Payload Conditions
Application-level error conditions described in the documentation of the protocol being transported are routed to the client through the connection manager. They are transparent to the connection manager, and therefore out of scope for the transport binding defined herein.
Implementation Notes
HTTP Pipelining
Even if the client requests HTTP Pipelining and the connection manager supports it, there is no guarantee that pipelining will succeed, because it might not be supported by intermediate proxies.
The best the client can do is to request the use of HTTP Pipelining by setting the 'hold' attribute to a value of "1". If HTTP Pipelining does not work (because the server returns HTTP 1.0 or connection:close), then the client SHOULD degrade gracefully by using multiple connections.
Security Considerations
Connection Between Client and BOSH Service
All communications between a client and a BOSH service SHOULD occur over encrypted HTTP connections. Negotiation of encryption between the client and the connection manager SHOULD occur at the transport layer or the HTTP layer, not the application layer; such negotiation SHOULD follow the HTTP/SSL protocol defined in SSL [28], although MAY follow the HTTP/TLS protocol defined in RFC 2818 [29] or the TLS Within HTTP protocol defined in RFC 2817 [30].
If the HTTP connection used to send the initial session request is encrypted, then all the other HTTP connections used within the session MUST also be encrypted. Furthermore, if authentication certificates are exchanged when establishing the encrypted connection that is used to send the initial session request, then the client and/or connection manager SHOULD ensure that the same authentication certificates are employed for all subsequent connections used by the session. Once such a "secure session" has been established:
- If the connection manager refuses to establish an encrypted connection or offers a different certificate, then the client SHOULD close the connection and terminate the session without sending any more requests.
- If the client sends a wrapper element that is part of a "secure session" over a connection that either is not encrypted or uses a different certificate, then the connection manager SHOULD simply close the connection. The connection manager SHOULD NOT terminate the session since that would facilitate denial of service attacks.
Connection Between BOSH Service and Application
A BOSH service SHOULD encrypt its connection to the backend application using appropriate technologies such as Secure Sockets Layer (SSL), Transport Layer Security (TLS), and StartTLS if supported by the backend application. Alternatively, the BOSH service can be considered secure (1) if it is running on the same physical machine as the backend application or (2) if it running on the same private network as the backend application and the administrators are sure that unknown individuals or processes do not have access to that private network.
If data privacy is desired, the client SHOULD encrypt its messages using an application-specific end-to-end encryption technology, because there is no way for the client to be sure that the BOSH service encrypts its connection to the application; methods for doing so are outside the scope of this specification.
Unpredictable SID and RID
The session identifier (SID) and initial request identifier (RID) are security-critical and therefore MUST be both unpredictable and nonrepeating (see RFC 1750 [31] for recommendations regarding randomness of SIDs and initial RIDs for security purposes).
Use of SHA-1
Recent research has shown that in select cases it is possible to compromise the hashes produced by the SHA-1 hashing algorithm (see RFC 4270 [32]). However, the use to which SHA-1 is put in BOSH will likely minimize the applicability of the attacks described in the literature. Furthermore, current estimates suggest that even with the recently-discovered attack, it would still take one year of computing by a government-sized entity to produce a collision.
IANA Considerations
TCP port 5280, conventially used for communication between BOSH clients and BOSH connection mangers, is registered with the Internet Assigned Numbers Authority (IANA) [33] in its port registry at IANA Port Numbers Registry [34], with a keyword of "xmpp-bosh". (Although use of this port is OPTIONAL, it is helpful to define this port in a standardized way so that BOSH clients can contact any given XMPP service via BOSH without the need either for DNS TXT records as described in Discovering Alternative XMPP Connection Methods [35] or for more advanced methods such as U-NAPTR.
XMPP Registrar Considerations
Protocol Namespaces
The XMPP Registrar includes 'http://jabber.org/protocol/httpbind' in its registry of protocol namespaces.
XML Schema
<?xml version='1.0' encoding='UTF-8'?> <xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema' xmlns:stream='http://etherx.jabber.org/streams' targetNamespace='http://jabber.org/protocol/httpbind' xmlns='http://jabber.org/protocol/httpbind' elementFormDefault='qualified'> <xs:annotation> <xs:documentation> The protocol documented by this schema is defined in XEP-0124: http://www.xmpp.org/extensions/xep-0124.html </xs:documentation> </xs:annotation> <xs:import namespace='http://www.w3.org/XML/1998/namespace' schemaLocation='http://www.w3.org/2001/03/xml.xsd'/> <xs:element name='body'> <xs:complexType> <xs:choice> <xs:element name='uri' minOccurs='0' maxOccurs='1' type='xs:string'/> <xs:any namespace='##other' minOccurs='0' maxOccurs='unbounded' processContents='lax'/> </xs:choice> <xs:attribute name='accept' type='xs:string' use='optional'/> <xs:attribute name='ack' type='xs:positiveInteger' use='optional'/> <xs:attribute name='authid' type='xs:string' use='optional'/> <xs:attribute name='charsets' type='xs:NMTOKENS' use='optional'/> <xs:attribute name='condition' use='optional'> <xs:simpleType> <xs:restriction base='xs:NCName'> <xs:enumeration value='bad-request'/> <xs:enumeration value='host-gone'/> <xs:enumeration value='host-unknown'/> <xs:enumeration value='improper-addressing'/> <xs:enumeration value='internal-server-error'/> <xs:enumeration value='item-not-found'/> <xs:enumeration value='other-request'/> <xs:enumeration value='policy-violation'/> <xs:enumeration value='remote-connection-failed'/> <xs:enumeration value='remote-stream-error'/> <xs:enumeration value='see-other-uri'/> <xs:enumeration value='system-shutdown'/> <xs:enumeration value='undefined-condition'/> </xs:restriction> </xs:simpleType> </xs:attribute> <xs:attribute name='content' type='xs:string' use='optional'/> <xs:attribute name='from' type='xs:string' use='optional'/> <xs:attribute name='hold' type='xs:unsignedByte' use='optional'/> <xs:attribute name='inactivity' type='xs:unsignedShort' use='optional'/> <xs:attribute name='key' type='xs:string' use='optional'/> <xs:attribute name='maxpause' type='xs:unsignedShort' use='optional'/> <xs:attribute name='newkey' type='xs:string' use='optional'/> <xs:attribute name='pause' type='xs:unsignedShort' use='optional'/> <xs:attribute name='polling' type='xs:unsignedShort' use='optional'/> <xs:attribute name='report' type='xs:positiveInteger' use='optional'/> <xs:attribute name='requests' type='xs:unsignedByte' use='optional'/> <xs:attribute name='rid' type='xs:positiveInteger' use='optional'/> <xs:attribute name='route' type='xs:string' use='optional'/> <xs:attribute name='sid' type='xs:string' use='optional'/> <xs:attribute name='stream' type='xs:string' use='optional'/> <xs:attribute name='time' type='xs:unsignedShort' use='optional'/> <xs:attribute name='to' type='xs:string' use='optional'/> <xs:attribute name='type' use='optional'> <xs:simpleType> <xs:restriction base='xs:NCName'> <xs:enumeration value='error'/> <xs:enumeration value='terminate'/> </xs:restriction> </xs:simpleType> </xs:attribute> <xs:attribute name='ver' type='xs:string' use='optional'/> <xs:attribute name='wait' type='xs:unsignedShort' use='optional'/> <xs:attribute ref='xml:lang' use='optional'/> <xs:anyAttribute namespace='##other' processContents='lax'/> </xs:complexType> </xs:element> </xs:schema>
Acknowledgements
Thanks to Mike Cumings, Tomas Karasek, Tobias Markmann, Chris Seymour, Safa Sofuoğlu, Stefan Strigler, Matthew Wild, Kevin Winters, and Christopher Zorn for their feedback.
Appendices
Appendix A: Document Information
Series: XEP Number: 0124 Publisher: XMPP Standards Foundation Status: Draft Type: Standards Track Version: 1.10 Last Updated: 2010-07-02 Approving Body: XMPP Council Dependencies: RFC 1945, RFC 2616, RFC 3174 Supersedes: None Superseded By: None Short Name: bosh Schema: <http://www.xmpp.org/schemas/httpbind.xsd> Source Control: HTML RSS This document in other formats: XML PDF
Appendix B: Author Information
Ian Paterson
Email: ian.paterson@clientside.co.uk JabberID: ian@zoofy.com Dave Smith
Email: dizzyd@jabber.org JabberID: dizzyd@jabber.org Peter Saint-Andre
Email: stpeter@jabber.org JabberID: stpeter@jabber.org URI: https://stpeter.im/ Jack Moffitt
Email: jack@chesspark.com JabberID: jack@chesspark.com
附录C:法律通告
- 版权
- XMPP扩展协议的版权(1999 - 2011)归XMPP标准化基金会(XSF)所有.
- 权限
- 特此授权,费用全免,对任何获得本协议副本的人,对使用本协议没有限制,包括不限制在软件程序中实现本协议,不限制在网络服务中布署本协议,不限制拷贝,修改,合并,发行,翻译,分发,转授,或销售本协议的副本,被允许使用本协议做了以上工作的人士,应接受前述的版权声明和本许可通知并且必须包含在所有的副本或实质性部分的规格中.除非单独的许可,被重新分发的修改工作,不得含有关于作者,标题,编号,或出版者的规格的误导性资料,并不得宣称修改工作是由本文的作者,作者所属的任何组织或项目,或XMPP标准基金会签注。
- 免责声明
- ##特别注意:本协议是提供的“原样”的基础,没有担保或任何形式的条件,明示或暗示,包括,但不限于任何担保或关于名称,非侵权性,适销性或适合作某一特定目的的条件. ##
- 责任限制
- 在任何情况下以及没有任何法律规定时,不论是侵权行为(包括疏忽),合同或其它方面,除非根据适用法律的要求(如蓄意和有严重疏忽行为)或以书面形式同意,XMPP标准基金会或任何作者不对本协议所造成的损失承担责任,包括任何直接,间接,特殊,偶发,或任何从本协议出,入,连接的字符产生的或实现,布署或其他对本协议的使用导致的相应的损害赔偿(包括但不限于善意的损失,停止作业,电脑失灵或故障,或任何和所有其他商业损害或损失) ,即使XMPP标准基金会或作者已被告知此类损害的可能性。
- 知识产权的一致性
- XMPP扩展协议完全遵守XSF的知识产权策略(可在<http://www.xmpp.org/extensions/ipr-policy.shtml>找到副本或写信给XMPP标准基金会, 1899 Wynkoop Street, Suite 600, Denver, CO 80202 USA).
附录D:和XMPP的关系
可扩展的消息和出席信息协议 (XMPP) 定义于 XMPP Core (RFC 3920) 和 XMPP IM (RFC 3921) 规范里,由 XMPP标准基金会贡献到由依据RFC 2026成立的互联网工程人物组管理的互联网标准流程 Internet Standards Process. 本文定义的任何协议已在互联网标准流程之外开发,并且被理解为 XMPP 的扩展而不是一个XMPP本身的演化, 开发, 或修改.
附录E:讨论地点
主要的XMPP扩展协议讨论地点是 <standards@xmpp.org> 讨论列表.
在 xmpp.org 的其它讨论列表中的讨论可能也有合适的; 所有的列表见 <http://xmpp.org/about/discuss.shtml> .
Given that this XMPP Extension Protocol normatively references IETF technologies, discussion on the <xsf-ietf@xmpp.org> list might also be appropriate.
勘误表可以发送邮件到 <editor@xmpp.org>.
附录F:需求一致性
以下用于本文的需求关键字的解释见于 RFC 2119: "MUST", "SHALL", "REQUIRED"; "MUST NOT", "SHALL NOT"; "SHOULD", "RECOMMENDED"; "SHOULD NOT", "NOT RECOMMENDED"; "MAY", "OPTIONAL".
Appendix G: Notes
1. RFC 793: Transmission Control Protocol <http://tools.ietf.org/html/rfc0793>.
2. RFC 1945: Hypertext Transfer Protocol -- HTTP/1.0 <http://tools.ietf.org/html/rfc1945>.
3. RFC 2616: Hypertext Transport Protocol -- HTTP/1.1 <http://tools.ietf.org/html/rfc2616>.
4. Bayeux Protocol <http://svn.cometd.org/trunk/bayeux/bayeux.html>.
5. The Web Socket Protocol <http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol>.
6. Reverse HTTP <http://tools.ietf.org/html/draft-lentczner-rhttp>.
7. RFC 2965: HTTP State Management Mechanism <http://tools.ietf.org/html/rfc2965>.
8. Requiring cookies is sub-optimal because several significant computing platforms provide only limited access to underlying HTTP requests/responses; worse, some platforms hide or remove cookie-related headers.
9. XEP-0025: Jabber HTTP Polling <http://xmpp.org/extensions/xep-0025.html>.
10. RFC 6120: Extensible Messaging and Presence Protocol (XMPP): Core <http://tools.ietf.org/html/rfc6120>.
11. XEP-0206: XMPP Over BOSH <http://xmpp.org/extensions/xep-0206.html>.
12. In order to reduce network congestion, RFC 2616 recommends that clients SHOULD NOT keep more than two HTTP connections to the same HTTP server open at the same time. Clients running in constrained enviroments typically have no choice but to abide by that recommendation.
13. If there is no traffic other than the "pings" then bandwidth consumption will be double that of a TCP connection (although double nothing is still nothing). If data is sent in large packets then bandwidth consumption will be almost identical.
14. Extensible Markup Language (XML) 1.0 (Fourth Edition) <http://www.w3.org/TR/REC-xml/>.
15. Namespaces in XML <http://www.w3.org/TR/REC-xml-names/>.
16. RFC 4627: The application/json Media Type for JavaScript Object Notation (JSON) <http://tools.ietf.org/html/rfc4627>.
17. Extensible Markup Language (XML) 1.0 (Fourth Edition) <http://www.w3.org/TR/REC-xml/>.
18. Although the syntax of the 'route' attribute bears a superficial resemblance to a URI or IRI, it is not a URI/IRI and MUST NOT be processed in accordance with the rules specified in RFC 3986, RFC 3987, or (for XMPP) RFC 5122.
19. Each character set name (or character encoding name -- we use the terms interchangeably) SHOULD be of type NMTOKEN, where the names are separated by the white space character #x20, resulting in a tokenized attribute type of NMTOKENS (see Section 3.3.1 of XML 1.0 [20]). Strictly speaking, the Character Sets registry maintained by the Internet Assigned Numbers Authority (see <http://www.iana.org/assignments/character-sets>) allows a character set name to contain any printable US-ASCII character, which might include characters not allowed by the NMTOKEN construction of XML 1.0; however, the only existing character set name which includes such a character is "NF_Z_62-010_(1973)".
20. Extensible Markup Language (XML) 1.0 (Fourth Edition) <http://www.w3.org/TR/REC-xml/>.
21. 9007199254740991 is 253-1. Some weakly typed languages use IEEE Standard 754 Doubles to represent all numbers. These Doubles cannot represent integers above 253 accurately.
22. RFC 3174: US Secure Hash Algorithm 1 (SHA1) <http://tools.ietf.org/html/rfc3174>.
23. Therefore a client and a connection manager will be compatible even if one or the other offers no support for multi-stream sessions.
24. The 'rid' attribute is always incremented normally without reference to any 'stream' attribute.
25. This helps to ensure backwards-compatibility with older implementations.
26. Each HTTP response MUST belong to the same session as the request that triggered it, but not necessarily to the same stream.
27. The broadcast payloads can be of any type.
28. SSL V3.0 <http://wp.netscape.com/eng/ssl3/draft302.txt>.
29. RFC 2818: HTTP Over TLS <http://tools.ietf.org/html/rfc2818>.
30. RFC 2817: Upgrading to TLS Within HTTP/1.1 <http://tools.ietf.org/html/rfc2817>.
31. RFC 1750: Randomness Recommendations for Security <http://tools.ietf.org/html/rfc1750>.
32. RFC 4270: Attacks on Cryptographic Hashes in Internet Protocols <http://tools.ietf.org/html/rfc4270>.
33. The Internet Assigned Numbers Authority (IANA) is the central coordinator for the assignment of unique parameter values for Internet protocols, such as port numbers and URI schemes. For further information, see <http://www.iana.org/>.
34. IANA registry of port numbers <http://www.iana.org/assignments/port-numbers>.
35. XEP-0156: Discovering Alternative XMPP Connection Methods <http://xmpp.org/extensions/xep-0156.html>.
Appendix H: Revision History
Note: Older versions of this specification might be available at http://xmpp.org/extensions/attic/
- Version 1.10 (2010-07-02)
- Further clarified use of 'from' and 'to' attributes; added missing condition values to the schema.
- (psa)
- Version 1.9 (2009-11-06)
- Added information for registration of port 5280 with IANA.
- (psa)
- Version 1.8 (2009-04-30)
- Removed secure attribute because it did not solve the problem it was intended to solve; added security consideration regarding link between connection manager and application server; changed "stanza" to "payload" for disambiguation with XMPP; clarified design objectives and relationship to similar technologies; corrected several errors in the schema.
- (psa/jm)
- Version 1.7 (2008-10-29)
- Moved alternative script syntax to historical specification; added implementation note about HTTP Pipelining; adjusted architectural description.
- (psa)
- Version 1.6 (2007-02-21)
- Multiple clarifications and restructuring without changes to protocol itself; changed title to BOSH; added section that fully explains the technique underlying the protocol; separated XMPP-specific features into new XEP-0206; added optional new Script Syntax and session pauses; added Acknowledgements section; added from and ver attributes; added hold attribute to session creation response; clarified polling too-frequently error; recommended that clients use HTTP Pipelining.
- (ip)
- Version 1.5 (2006-04-28)
- Added optional Multiple Streams section; added security considerations about encrypted HTTP connections; recommended use of SSL rather than HTTP over TLS; specified that request ID values must not exceed 9007199254740991; corrected datatypes of inactivity, polling, rid, and wait attributes in the schema; added <any/> and <anyAttribute/> elements to schema to optionally support non-XMPP XML elements and attributes; deprecated HTTP error codes in favor of new terminal binding conditions.
- (ip/psa)
- Version 1.4 (2005-12-14)
- Modified syntax of route attribute to be proto:host:port rather than XMPP URI/IRI.
- (psa)
- Version 1.3 (2005-11-02)
- Corrected stream:features namespace and the Recoverable Binding Conditions section; recommended that connection manager shall return secure attribute to client; recommended end-to-end encryption through proxy connection managers.
- (ip)
- Version 1.2 (2005-06-16)
- Specified optional use of route and secure attributes in session request. Minor correction: the stream features element should be included in the response that contains the authid attribute (this is not necessarily the session creation response).
- (ip)
- Version 1.1 (2005-06-02)
- Specified optional use of HTTP Accept-Encoding and Content-Encoding headers for compression at HTTP binding level.
- (ip)
- Version 1.0 (2005-03-03)
- Per a vote of the Jabber Council, advanced status to Draft.
- (psa)
- Version 0.10 (2004-11-08)
- Changed HTTP 401 errors to HTTP 404.
- (ip)
- Version 0.9 (2004-10-26)
- Added charset attribute.
- (ip/psa)
- Version 0.8 (2004-10-26)
- Specified that wait attribute must be included in the session creation response.
- (ip)
- Version 0.7 (2004-08-12)
- Defined appropriate XMPP stanza error conditions.
- (psa/ip)
- Version 0.6 (2004-07-19)
- Added xml:lang attribute to the session request; added recoverable binding error conditions.
- (ip)
- Version 0.5 (2004-05-07)
- Protocol refactored to enable simultaneous requests (request identifier attribute, wait attribute, hold attribute, requests attribute) and recovery of broken connections; added content attribute; removed all wrapper types except 'terminate'; updated error handling; made key mechanism optional (should use SSL/TLS instead).
- (ip/psa)
- Version 0.4 (2004-02-23)
- Fixed typos; removed "resource-constraint" binding error; added HTTP 403 error to table.
- (psa/ip)
- Version 0.3 (2004-02-19)
- Added 'authid' attribute to enable communication of XMPP stream ID (used in digest authentication); specified that Content-Types other than "text/xml" are allowed to support older HTTP clients; specified business rule for connection manager queueing of client requests; changed <packet/> to <body/> to support older HTTP clients; changed 'to' attribute on initialization element from MAY to SHOULD; recommended inclusion of unavailable presence in termination element sent from client; described architectural assumptions; specified binding-specific error handling.
- (psa/ip)
- Version 0.2 (2004-01-13)
- Added 'to' attribute on the initialization element; specified that 'text/html' is allowable for backwards-compatibility.
- (dss/psa/ip)
- Version 0.1 (2003-11-06)
- Initial version.
- (dss/psa)
结束