openfire 节错误 的类型与情形(条件)
节错误
节相关的错误处理的方式类似流错误流错误, 但是不像流错误那样,节错误是可恢复的; 所以, 他们不会导致XML和当前TCP连接的中止. 反之, 发现错误条件的实体返回一个错误节, 它是一个这样的节:
- 是和触发这个错误的已生成的节同种类型(message, presence, 或 IQ)
- 'type'属性值设为"error"
- 通常是把已生成的节的'from'和'to'互换
- 镜像触发这个错误的已生成的节的'id'属性(如果有的话)
- 包含一个<error/>子元素以指明错误条件并且对发送者可以采取的补救措施提供一个暗示(然而, 不可能总是能够不补救这个错误)
规则
以下规则适用于节错误:
- 检测到和节相关的错误条件的接收或处理实体应该返回一个错误节(对于IQ节必须这么做).
- 该错误节应该简单地把生成的节中的'from'和'to'地址互换, 除非这么做将会 (1) 导致信息泄漏(参见[RFC6120#信息泄露|13.10]])或其他违反安全, 或 (2) 强迫错误节的发送者在该错误节的'from'或'to'地址中包含一个异常的JID.
- 如果生成的节是<message/>或<presence/>并且包含了'id'属性,那么该错误节必须也包含'id'属性. 如果生成的节是<iq/>,那么该错误节必须包含一个'id'属性. 在所有情况下, 'id'属性的值必须和生成节的相同(或者是空,如果生成的节没有包含'id'属性).
- 错误节必须包含一个<error/>子元素.
- 返回错误节的实体可以传递它的JID给生成节的发送者(例如, 为了诊断或跟踪的目的),通过附加一个'by'属性到<error/>子元素.
- 返回错误节的实体可以包含被发送的原始XML,这样发送者能够检查, 如果必要的话, 并在尝试重发之前纠正该XML(然而, 这只是出于礼貌,并且原实体不能(MUST NOT)依赖接收到的原始载荷). 自然地, 该实体不能(MUST NOT)包含原始数据,如果它不是格式良好的XML, 违反XMPP的XML限制(见11.1), 或反而是有害的(例如, 超出大小限制).
- 如果'type'属性值不是"error"(或如果没有'type'属性), 不能(MUST NOT)包含一个<error/>子元素.
- 接收到错误节的实体不能(MUST NOT)以更多的错误节来应答这个节; 这有助于防止死循环.
语法
节相关的错误的语法如下, 这里展示的用方括号'['和']'括起来的XML数据是可选的, 'intended-recipient' 是原始节指定的地址的那个实体的JID, 'sender' 是原始实体的JID, 而 'error-generator' 是检测到错误的并方会错误节的那个实体.
<stanza-kind from='intended-recipient' to='sender' type='error'><error [by='error-generator'] type='error-type'> <defined-condition xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/><text xmlns='urn:ietf:params:xml:ns:xmpp-stanzas' xml:lang='langcode'></text</error</stanza-kind已定义的条件以下条件是已定义好用于节错误的.
error-type 的值是被推荐用于每个已定义的条件通常预期的类型; 无论如何, 在某些情况下不同的类型可能更合适.
bad-request
发送者发送的节里包含的XML不符合适当的schema或不能被拥有(例如, IQ节的'type'属性包含一个不能识别的值, 或一个被已知的命名空间限定的元素但是违反了该元素的已定义的语法); 相关的错误类型应该是"modify".
<iq from='juliet@im.example.com/balcony' id='zj3v142b' to='im.example.com' type='subscribe'> <ping xmlns='urn:xmpp:ping'/> </iq<iq from='im.example.com' id='zj3v142b' to='juliet@im.example.com/balcony' type='error'> <error type='modify'> <bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error</iqconflict访问未被授权,因为一个现存的资源使用了相同的名字或地址; 相关的错误类型应该是"cancel".
<iq id='wy2xa82b4' type='set'> <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'> <resource</resource</bind</iq<iq id='wy2xa82b4' type='error'> <error type='cancel'> <conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error</iqfeature-not-implemented出现在XML节里的特性没有被预定的接收方或中间服务器实现,所以该节无法被处理(例如, 该实体知道该命名空间但是不认识元素名); 相关的错误类型应该是"cancel" 或 "modify".
<iq from='juliet@im.example.com/balcony' id='9u2bax16' to='pubsub.example.com' type='get'> <pubsub xmlns='http://jabber.org/protocol/pubsub'> <subscriptions/> </pubsub</iq<iq from='pubsub.example.com' id='9u2bax16' to='juliet@im.example.com/balcony' type='error'> <error type='cancel'> <feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> <unsupported xmlns='http://jabber.org/protocol/pubsub#errors' feature='retrieve-subscriptions'/> </error</iqforbidden请求的实体没有必要的许可来执行一个只允许特定授权角色或个体来完成的动作(即, 它通常和授权而不是验证有关); 相关的错误类型应该是"auth".
<presence from='juliet@im.example.com/balcony' id='y2bs71v4' to='characters@muc.example.com/JulieC'> <x xmlns='http://jabber.org/protocol/muc'/> </presence<presence from='characters@muc.example.com/JulieC' id='y2bs71v4' to='juliet@im.example.com/balcony' type='error'> <error type='auth'> <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error</presencegone接收者或服务器无法再用这个地址联系到, 通常是永久意义上的(和<redirect/>错误条件相反, 它被用于临时的地址失败); 相关的错误类型应该是"cancel"并且该错误节应该包含一个新的地址(如果可用的话)作为<gone/>元素的XML字符串数据(它必须是一个实体可以联系的唯一资源标识符URI或国际化资源标识符IRI, 典型的是一个XMPP?URI定义的XMPP IRI.
<message from='juliet@im.example.com/churchyard' id='sj2b371v' to='romeo@example.net' type='chat'> <body</body</message<message from='romeo@example.net' id='sj2b371v' to='juliet@im.example.com/churchyard' type='error'> <error by='example.net' type='cancel'> <gone xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'></gone</error</messageinternal-server-error服务器发生了错误的配置或其他阻止它处理改节的内部错误; 相关的错误类型应该是"cancel".
<presence from='juliet@im.example.com/balcony' id='y2bs71v4' to='characters@muc.example.com/JulieC'> <x xmlns='http://jabber.org/protocol/muc'/> </presence<presence from='characters@muc.example.com/JulieC' id='y2bs71v4' to='juliet@im.example.com/balcony' type='error'> <error type='cancel'> <internal-server-error xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error</presenceitem-not-found找不到请求的JID地址或条目; 相关的错误类型应该是"cancel".
<presence from='userfoo@example.com/bar' id='pwb2n78i' to='nosuchroom@conference.example.org/foo'/><presence from='nosuchroom@conference.example.org/foo' id='pwb2n78i' to='userfoo@example.com/bar' type='error'> <error type='cancel'> <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error</presencejid-malformed发送的实体所提供(例如, 在资源绑定的时候)或与之通讯(例如, 一个节的'to'地址)的XMPP地址或其中一部分违反了XMPP?ADDR定义的规则; 相关的错误类型应该是"modify".
<presence from='juliet@im.example.com/balcony' id='y2bs71v4' to='ch@r@cters@muc.example.com/JulieC'> <x xmlns='http://jabber.org/protocol/muc'/> </presence<presence from='ch@r@cters@muc.example.com/JulieC' id='y2bs71v4' to='juliet@im.example.com/balcony' type='error'> <error by='muc.example.com' type='modify'> <jid-malformed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error</presencenot-acceptable接收者或服务器理解该请求但是不能处理它,因为该请求不符合该接收者或服务器的标准(例如, 请求订阅信息但是未同时包含接收者需要的配置参数); 相关的错误类型应该是"modify".
<message to='juliet@im.example.com' id='yt2vs71m'> <body</body</message<message from='juliet@im.example.com' id='yt2vs71m'> <error type='modify'> <not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error</messagenot-allowed接收者或服务器不允许任何实体执行该动作(例如, 向列入黑名单的域发送消息); 相关的错误类型应该是"cancel".
<presence from='juliet@im.example.com/balcony' id='y2bs71v4' to='characters@muc.example.com/JulieC'> <x xmlns='http://jabber.org/protocol/muc'/> </presence<presence from='characters@muc.example.com/JulieC' id='y2bs71v4' to='juliet@im.example.com/balcony' type='error'> <error type='cancel'> <not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error</presencenot-authorized发送者在被允许执行某动作之前需要提供凭证, 或已经提供了错误的凭证("not-authorized"的提法, 来源于HTTP的"401 Unauthorized"错误, 可能导致读者认为这个条件是和授权相关的, 但其实它通常用于验证相关的领域); 相关的错误类型应该是"auth".
<presence from='juliet@im.example.com/balcony' id='y2bs71v4' to='characters@muc.example.com/JulieC'> <x xmlns='http://jabber.org/protocol/muc'/> </presence<presence from='characters@muc.example.com/JulieC' id='y2bs71v4' to='juliet@im.example.com/balcony'> <error type='auth'> <not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error</presencepolicy-violation实体违反了一些本地服务策略(例如, 一个消息包含了服务禁止的单词)而服务器可以选择在<text/>元素里或在应用特有的条件元素里指定策略; 相关的错误类型应该是"modify"或"wait",取决于被违反的策略.
(在下例中, 客户端发送一个包含了根据服务器的本地服务策略被禁止的单词的XMPP消息.)
<message from='romeo@example.net/foo' to='bill@im.example.com' id='vq71f4nb'> <body</body</message<message from='bill@im.example.com' id='vq71f4nb' to='romeo@example.net/foo'> <error by='example.net' type='modify'> <policy-violation xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error</messagerecipient-unavailable预期的接收者暂时不可用, 正在维护, 等等; 相关的错误类型应该是"wait".
<presence from='juliet@im.example.com/balcony' id='y2bs71v4' to='characters@muc.example.com/JulieC'> <x xmlns='http://jabber.org/protocol/muc'/> </presence<presence from='characters@muc.example.com/JulieC' id='y2bs71v4' to='juliet@im.example.com/balcony'> <error type='wait'> <recipient-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error</presenceredirect接收者或服务器重定向该信息的请求到另一个实体, 典型的临时发生的情形(和<gone/>错误条件相反, 它用于永久性的地址错误); 相关的错误类型应该是"modify",并且该错误节应该在<redirect/>元素的XML字符串数据中包含替代的地址(它必须是一个发送者可以与之通讯的URI或IRI, 通常是一个XMPP?URI定义的XMPP IRI).
<presence from='juliet@im.example.com/balcony' id='y2bs71v4' to='characters@muc.example.com/JulieC'> <x xmlns='http://jabber.org/protocol/muc'/> </presence<presence from='characters@muc.example.com/JulieC' id='y2bs71v4' to='juliet@im.example.com/balcony' type='error'> <error type='modify'> <redirect xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'></redirect</error</presenceregistration-required请求的实体没有被授权访问请求的服务,因为需要事先注册(提前注册的例子包括XMPP多用户聊天 XEP-0045 中仅限会员的房间和到非XMPP即时消息服务的网关, 传统上使用网关XEP?0100是需要注册的); 相关的错误类型应该是"auth".
<presence from='juliet@im.example.com/balcony' id='y2bs71v4' to='characters@muc.example.com/JulieC'> <x xmlns='http://jabber.org/protocol/muc'/> </presence<presence from='characters@muc.example.com/JulieC' id='y2bs71v4' to='juliet@im.example.com/balcony'> <error type='auth'> <registration-required xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error</presenceremote-server-not-found一个远程服务器或预期的接收者的JID的一部分所代表的服务不存在或不能解析(例如, 没有 _xmpp-server._tcp DNS SRV记录, A记录或AAAA记录解析也失败了, 或A/AAAA查询成功了但是在IANA注册了的端口5269上没有应答); 相关错误类型应该是"cancel".
<message from='romeo@example.net/home' id='ud7n1f4h' to='bar@example.org' type='chat'> <body</body</message<message from='bar@example.org' id='ud7n1f4h' to='romeo@example.net/home' type='error'> <error type='cancel'> <remote-server-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error</messageremote-server-timeout远程服务器或作为预定的接收者的全JID的一部分(或履行请求所需要的)的服务能被解析但是无法在合理的时间内与之建立通讯(例如, 无法在解析到的IP地址和端口上建立一个XML流, 或可以建立一个XML流但是因为TLS, SASL, Server Dialback的问题导致流协商失败, 等等); 相关的错误类型应该是"wait" (除非该错误是更永久性的, 例如, 远程服务器能被找到但是无法被认证或它违反了安全策略).
<message from='romeo@example.net/home' id='ud7n1f4h' to='bar@example.org' type='chat'> <body</body</message<message from='bar@example.org' id='ud7n1f4h' to='romeo@example.net/home' type='error'> <error type='wait'> <remote-server-timeout xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error</messageresource-constraint服务器或接收者忙或缺乏必要的系统资源来服务该请求; 相关的错误类型应该是"wait".
<iq from='romeo@example.net/foo' id='kj4vz31m' to='pubsub.example.com' type='get'> <pubsub xmlns='http://jabber.org/protocol/pubsub'> <items node='my_musings'/> </pubsub</iq<iq from='pubsub.example.com' id='kj4vz31m' to='romeo@example.net/foo' type='error'> <error type='wait'> <resource-constraint xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error</iqservice-unavailable服务器或接收者当前未提供被请求的服务; 相关的错误类型应该是"cancel".
<message from='romeo@example.net/foo' to='juliet@im.example.com'> <body</body</message<message from='juliet@im.example.com/foo' to='romeo@example.net'> <error type='cancel'> <service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error</messagesubscription-required提出请求的实体没有被授权访问所请求的服务,因为需要事先订阅(事先订阅的例子包括授权接收XMPP?IM定义的联机状态信息和用于XEP?0060定义的XMPP发布-订阅的 opt-in 数据种子); 相关的错误类型应该是"auth".
<message from='romeo@example.net/orchard' id='pa73b4n7' to='playwright@shakespeare.example.com' type='chat'> <subject</subject<body</body</message<message from='playwright@shakespeare.example.com' id='pa73b4n7' to='romeo@example.net/orchard' type='error'> <error type='auth'> <subscription-required xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error</messageundefined-condition该错误条件不在本列表中的其他错误条件之中; 任何错误类型都可能和本条件有关, 并且除非和应用特有的条件联合在一起,它应该不被使用.
<message from='northumberland@shakespeare.example' id='richard2-4.1.247' to='kingrichard@royalty.england.example'> <body</body<amp xmlns='http://jabber.org/protocol/amp'> <rule action='notify' condition='deliver' value='stored'/> </amp</message<message from='example.org' id='amp1' to='northumberland@example.net/field' type='error'> <amp xmlns='http://jabber.org/protocol/amp' from='kingrichard@example.org' status='error' to='northumberland@example.net/field'> <rule action='error' condition='deliver' value='stored'/> </amp<error type='modify'> <undefined-condition xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> <failed-rules xmlns='http://jabber.org/protocol/amp#errors'> <rule action='error' condition='deliver' value='stored'/> </failed-rules</error</messageunexpected-request接收者或服务器理解这个请求但是不希望它在这个时候出现(即, 该请求顺序错了); 相关的错误类型应该是"wait"或"modify".
<iq from='romeo@example.net/foo' id='o6hsv25z' to='pubsub.example.com' type='set'> <pubsub xmlns='http://jabber.org/protocol/pubsub'> <unsubscribe node='my_musings' jid='romeo@example.net'/> </pubsub</iq<iq from='pubsub.example.com' id='o6hsv25z' to='romeo@example.net/foo' type='error'> <error type='modify'> <unexpected-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> <not-subscribed xmlns='http://jabber.org/protocol/pubsub#errors'/> </error</iq应用特有的条件大家知道, 一个应用可以提供应用特有的节错误信息,通过在错误元素中包含一个正确的命名空间的子元素. 典型的, 该应用特有的元素补充或进一步限定一个已定义的元素. 从而, 该<error/>元素将包含两个或三个子元素.
<iq id='ixc3v1b9' type='error'> <error type='modify'> <bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> <too-many-parameters xmlns='http://example.org/ns'/> </error</iq<message type='error' id='7h3baci9'> <error type='modify'> <undefined-condition xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> <text xml:lang='en' xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'></text<too-many-parameters xmlns='http://example.org/ns'/> </error</message>一个接收到它不理解的应用特有的错误条件的实体必须忽略那个条件但适当处理该错误节的其他部分.