archive-org.com » ORG » J » JABBERCN.ORG

Total: 303

Choose link from "Titles, links and description words view":

Or switch to "Titles and links view".
  • XEP-0084 - Jabber/XMPP中文翻译计划
    带多内容类型的Metadata 以下例子展示指定头像数据的元数据可用的多种格式 image png image gif 和 image mng 这里 image png 内容类型只可用在数据节点而其他内容类型可用于 HTTP URLs 例子 10 发布头像元数据 多格式 iq type set from juliet capulet lit chamber id publish3 pubsub xmlns http jabber org protocol pubsub publish node urn xmpp avatar metadata item id 111f4b3c50d7b0df729d299bc6f8e9ef9066971f metadata xmlns urn xmpp avatar metadata info bytes 12345 height 64 id 111f4b3c50d7b0df729d299bc6f8e9ef9066971f type image png width 64 info bytes 12345 height 64 id e279f80c38f99c1e7e53e262b440993b2f7eea57 type image png url http avatars example org happy png width 64 info bytes 23456 height 64 id 357a8123a30844a3aa99861b6349264ba67a5694 type image gif url http avatars example org happy gif width 64 info bytes 78912 height 64 id 03a179fe37bd5d6bf9c2e1e592a14ae7814e31da type image mng url http avatars example org happy mng width 64 metadata item publish pubsub iq 在前述的例子中 以 image png 内容类型封装的图片同时可用于一个pubsub数据节点和一个HTTP URL 所以它被包含了两次 第二次带了一个 url 属性 带Pointer的Metadata 以下例子展示元数据指定在数据节点可用的 image png 头像数据 同时也带有一个指针指向外部服务 例子 11 发布头像元数据 带指针 iq type set from juliet capulet lit chamber id publish4 pubsub xmlns http jabber org protocol pubsub publish node urn xmpp avatar metadata item id 111f4b3c50d7b0df729d299bc6f8e9ef9066971f metadata xmlns urn xmpp avatar metadata info bytes 12345 height 64 id 111f4b3c50d7b0df729d299bc6f8e9ef9066971f type image png width 64 pointer x xmlns http example com virtualworlds game Ancapistan game character Kropotkin character x pointer metadata item publish pubsub iq 服务查询 查询头像可用性 pubsub auto subscribe 和 filtered notifications 特性允许一个联系人自动订阅一个用户的头像 无论如何 一个联系人也能显式地决定是否另一个用户使用本协议发布头像 通过发送一个 服务查询 13 条目 disco items 请求给该用户的春JID localpart domain tld 例子 12 查询条目请求 iq type get from romeo montague lit orchard to juliet capulet lit id items1 query xmlns http jabber org protocol disco items iq 如果该用户发布头像数据到一个PEP节点 结果必须包含适当的条目 例子 13 查询条目结果 iq type result from juliet capulet lit to romeo montague lit orchard id items1 query xmlns http jabber org protocol disco items item jid juliet capulet lit node urn xmpp avatar data item jid juliet capulet lit node urn xmpp avatar metadata query iq 该联系人接着可以根据 XEP 0060 中定义的协议订阅该元数据节点 无论如何 该联系人不应该 SHOULD NOT 订阅该数据节点 反之 它应该简单地在需要的时候从那个节点获取条目 如上所述 实现备注 多资源 如果一个用户同一时间有多个资源 每个资源可以发布一个不同的头像 PEP服务应该包含上述的正在发布的资源的 replyto 地址 这样易于区分这个头像和前一个资源的头像 头像同步 当一个用户以一个新的资源登陆并且之前发布了一个头像 它的客户端应该获取它最近发布的头像 要么通过自动发送带有合适的实体可用性信息的出席信息 见 XEP 0115 要么使用 XEP 0060 所述的 retrieve items 方法 图片处理 决定获取哪个头像格式 例如 image gif 而不是 image png 和决定获取的适当方法 例如 HTTP而不是pubsub 是接收的应用的责任 接收的应用显示一个图片的时候不应该 SHOULD NOT 拉伸它 如果一个头像对一个联系人不可用 接收应用可以显示该联系人的相片 例如 在联系人的vCard中提供的 见 vcard temp 14 或其他个人信息 安全事项 关于和基础的传输协议相关的安全事项见 XEP 0060 和 XEP 0163 有可能SHA 1哈希机制的输出会导致冲突 无论如何 使用SHA 1生成头像数据的哈希不是安全的关键 IANA事项 本文使用了IANA注册的内容类型 但是不要求和 互联网编号分配授权机构 IANA 15 交互 XMPP注册处事项 协议命名空间 XMPP注册处 16 已经把 urn xmpp avatar data 和 urn xmpp avatar metadata 包含在它的协议命名空间的注册项中 见 http xmpp org registrar namespaces html XML Schema Data命名空间 xml version 1 0 encoding UTF 8 xs schema xmlns xs http www w3 org 2001 XMLSchema targetNamespace urn xmpp avatar data xmlns urn xmpp avatar data elementFormDefault qualified xs annotation xs documentation The protocol documented by this schema is defined in XEP 0084 http www xmpp org extensions xep 0084 html xs documentation xs annotation xs element name data type xs base64Binary xs schema Metadata命名空间 xml version 1 0 encoding UTF 8 xs schema xmlns xs http www w3 org 2001 XMLSchema targetNamespace urn xmpp avatar metadata xmlns urn xmpp avatar

    Original URL path: http://wiki.jabbercn.org/index.php?title=XEP-0084&printable=yes (2016-04-25)
    Open archived version from archive


  • RFC6121 - Jabber/XMPP中文翻译计划
    existent jid subscription remove query iq S iq id uj4b1ca8 to juliet example com balcony type error error type modify item not found xmlns urn ietf params xml ns xmpp stanzas error iq 名册版本 流特性 如果一个服务器支持名册版本 那么它必须在流协商期间声明以下流特性 ver xmlns urn xmpp features rosterver 名册版本流特性很少见所以永远不会是强制协商的 请求 如果一个客户端支持名册版本并且它所连接的服务器如前一节说的那样声明支持名册版本 那么该客户端应该在它对名册请求中包含 ver 元素 如果该服务器没有声明支持名册版本 客户端不能 MUST NOT 包含 ver 属性 如果客户端在它的roster get中包含了 ver 属性 它就把该属性的值设成了它最后的名册缓存中的相关的版本ID C iq from romeo example net home id r1h3vzp7 to romeo example net type get query xmlns jabber iq roster ver ver14 iq 如果该客户端还未缓存该名册或该缓存遗失或被中断了 但是该客户端希望引导名册版本的使用 它必须把 ver 属性设为空字符串 即 ver 自然的 如果该客户端不支持名册版本或不希望引导名册版本的使用 它将不包含 ver 属性 成功情景 无论名册从被客户端列举版本ID之后是否被修改过 服务器必须要么如 章节2 1 4 包含一个 ver 属性代表最后的版本 所述返回完整的名册 要么返回一个空的IQ result 这样就表示任何名册的修改将通过roster pushes被发送 如下所述 通常 除非返回完整名册 1 将比发送独立的roster pushes给客户端使用更少的带宽 例如 如果名册只包含很少的条目 或 2 服务器不能把版本ID关联到任何之前已经在文件中有的版本 服务器应该发送一个空的IQ result然后通过roster pushes发送修改 如果有的话 S iq from romeo example net id r1h3vzp7 to romeo example net home type result 实现备注 这个空的IQ result不同于一个空的 query 元素 这和使用一个空名册是不同的 如果允许使用名册版本并且名册从被客户端列举版本ID之后未被修改过 服务器将简单地不发送任何roster pushes给客户端 直到并且除非在该客户端会话的生命周期中一些相关的事件触发一个roster push 如果名册从被客户端列举版本ID之后被修改过 那么该服务器必须为每一个从被客户端列举版本ID之后被修改过的条目发送一个roster push给该客户端 我们把一个用于名册版本同步的被发送的roster push称为一个 暂时的roster push 定义 一个 roster modification 表示对名册数据的任何改变并将导致一个roster push到已连接客户端 所以 和服务器对名册处理相关的内部状态将不会导致一个roster push到已连接客户端因而不需要改变版本 S iq from romeo example net id ah382g67 to romeo example net home type set query xmlns jabber iq roster ver ver34 item jid tybalt example org subscription remove query iq S iq from romeo example net id b2gs90j5 to romeo example net home type set query xmlns jabber iq roster ver ver42 item jid bill example org subscription both query iq S iq from romeo example net id c73gs419 to romeo example net home type set query xmlns jabber iq roster ver ver72 item jid nurse example org name Nurse subscription to group Servants group item query iq S iq from romeo example net id dh361f35 to romeo example net home type set query xmlns jabber iq roster ver ver96 item jid juliet example org name Juliet subscription both group VIPs group item query iq 这些 暂时的roster pushes 可以作如下理解 想想客户端在它缓存的名册版本 假设是 ver14 和新的名册版本 假设是 ver96 之间有一个活跃的出席信息会话 在此期间 该客户端可能已经接收到一个和各种名册版本相关的roster pushes 它可能已经发生 假设是 ver51 和 ver79 无论如何 这些roster pushes中的一些可能已经包含了同一个名册条目的中间更新 例如 把对bill example org的订阅状态从 none 改为 to 又从 to 改为 both 这个暂时的roster pushes将不包含所有中间步骤 而只有在该客户端实际上离线的时候每个条目修改后的最终结果 这可能发生 假设是 ver34 ver42 ver72 和 ver96 客户端必须和处理任何roster push一样处理一个 interim roster push 实际上 从客户端的视角不能说一个 暂时的 roster push和一个 live 的 roster push是不同的 因而当它没办法知道自己收到是否是暂时的roster pushes 当重连后请求名册 客户端应该请求和它在前一个会话中收到的最后的roster push相关的版本 而不是它在前一个会话的开始时收到的roster result的相关版本 当名册版本被允许 服务器必须在每一个roster push中包含更新的名册版本 Roster pushes必须按照变更的顺序产生并且在一个roster push中包含的版本必须是唯一的 即使客户端未在它的roster gets或sets 中包含 ver 属性 服务器也应该在它发送给客户端的所有roster pushes和results中包含 ver 属性 实现备注 名册版本的指南和详细例子见 XEP 0237 管理出席信息订阅 为了保护XMPP用户们的隐私 出席信息仅向某个用户已经批准的其他实体披露 当某个同意允许其他实体察看其出席信息时 该实体被称为对该用户的出席信息有一个 订阅 subscription 一个对某用户的出席信息有订阅的实体或一个用户对其有出席信息订阅的实体被称为 联系人 contact 在本文中术语 联系人 contact 在不严格的概念上也用于指代潜在的联系人或一个用户的名册中的任何条目 在XMPP中 一个订阅是超越出席信息会话存在的 实际上 直到联系人取消订阅或用户撤销之前已授权的订阅之前它都会持续存在 这个模式不同于会话初始协议 SIP 中对出新信息订阅的使用 参见 SIP PRES 在XMPP中订阅的管理是通过发送包含特别定义的属性 subscribe unsubscribe subscribed 和 unsubscribed 的presence节来实现的 实现备注 当一个服务器处理或生成一个类型为 subscribe subscribed unsubscribe 或 unsubscribed 的出站出席信息节 该服务器必须在出站出席信息节中标记发送的实体的纯JID localpart domainpart 而不是全JID localpart domainpart resourcepart 这个规则的强制性简化了出席信息订阅的模式并且有助于防止出席信息泄露 关于出席信息泄露的信息 参见 XMPP CORE 的安全事项 订阅状态在用户和联系人两边的名册中都可以被反映 本章不覆盖每个和出席信息订阅相关的可能的情景 而主要是讲述一个用户和一个联系人之间开启一个共同的订阅的协议流程 关于订阅状态的完整细节可以在 附录A 中找到 请求订阅 一个 订阅请求 subscription request 是一个某用户为了得到永久性地订阅某个联系人出席信息的授权而发出的请求 语法构成上它是一个 type 属性值为 subscribe 的presence节 一个订阅请求由某用户客户端生成 由 潜在的 联系人的服务器处理 从表现上来看则是联系人通过联系人的客户端来处理 以下章节描述其工作流程 实现备注 出席信息订阅请求被发送到可用的资源 然而和订阅状态变更相关的名册推送被发送到感兴趣的资源 所以 如果一个资源希望同时接收到订阅请求和名册推送 它必须同时发送初始出席信息和请求名册 客户端生成出站订阅请求 一个用户的客户端发送一个类型为 subscribe 并且指定了一个潜在联系人的纯JID contact domainpart 为 to 地址的presence节 生成一个订阅请求 UC presence id xk3h1v69 to juliet example com type subscribe 当一个用户发送一个出席信息订阅请求给一个潜在的即时消息和出席信息联系人 其 to 属性的值必须是一个纯JID contact domainpart 而不是一个全JID contact domainpart resourcepart 因为预期的结果是该用户从该联系人的所有资源接收出席信息 而不仅是在 to 属性中指定的特定资源 纯JIDs的使用也简化了该用户的服务器和联系人的服务器的订阅过程 出席信息探测 和出席信息通知 为了跟踪的目的 客户端应该在一个出席信息订阅请求中包含一个 id 属性 实现备注 很多XMPP客户端在生成一个出站出席信息订阅的时候向用户提示关于潜在联系人的信息 例如 handle 以及期望的名册组 因而在发送该出站出席信息订阅请求之前发送一个roster set 这个行为是可选的 因为客户端在上传用户提供的关于该联系人的信息之前可以先等待从服务器接收初始的roster push 服务器必须以任何顺序处理roster set和出站出席信息订阅请求 即 以客户端生成的任何顺序 服务器处理出站订阅请求 接收出站出席信息订阅请求之后 该用户的服务器必须处理如下 在处理该请求之前 该用户的服务器必须检查包含在 to 属性中的JID的语法 无论如何 据信一些现有的实现不执行这个检查 如果该JID的格式是 contact domainpart resourcepart 而不是 contact domainpart 该用户的服务器应该把该请求当成是指向该联系人的纯JID并据此修改 to 地址 该服务器也可以遵循 XMPP ADDR 定义的格式来检查该JID地址并可能返回一个 jid malformed 节错误 如果潜在的联系人位于和该用户相同的服务器上 那么在处理该订阅请求和递送它到本地联系人的时候该服务器必须遵循 章节3 1 3 定义的规则 如果潜在的联系人位于一个远端服务器 受本地服务策略的约束该用户的服务器必须接着按照核心XMPP节处理规则路由该节到那个远端的域 这可能导致返回一个适当的节错误给该用户 类似 remote server timeout 如上所述 在本地递送或远程路由该出席信息订阅请求之前 该用户的服务器必须给该出站订阅请求标记该用户的纯JID user domainpart US presence from romeo example net id xk3h1v69 to juliet example com type subscribe 如果该出席信息订阅请求不是本地递送或远程路由的 例如 因为该请求格式异常 该本地联系人不存在 该远程服务器不存在 尝试联系远端服务器超时 或任何被该用户的服务器经历或确认的其他错误 那么该用户的服务器必须返回一个适当的错误节给该用户 例子如下 US presence from juliet example com id xk3h1v69 to romeo example net type error error type modify remote server not found xmlns urn ietf params xml ns xmpp stanzas error presence 在本地递送或远程路由该出席信息订阅请求之后 该用户的服务器必须接着发送一个roster push给所有该用户的感兴趣的资源 包含带一个 none 订阅状态并且带一个表明订阅等待批准符号 一个值为 subscribe 的 ask 属性 的潜在联系人 US iq id b89c5r7ib574 to romeo example net foo type set query xmlns jabber iq roster item ask subscribe jid juliet example com subscription none query iq US iq id b89c5r7ib575 to romeo example net bar type set query xmlns jabber iq roster item ask subscribe jid juliet example com subscription none query iq 如果一个远端联系人在可配置的时间内不批准或拒绝该订阅请求 该用户的服务器应该基于一个实现特有的机制重新发送该订阅请求给该联系人 例如 任何该用户的一个新资源可用的时候 或在过了一个特定数量的时间之后 这有助于从原有的订阅请求被路由到远程域发生的短暂的 无声的错误中恢复 这样做的时候 建议该服务器包含一个 id 属性 这样它能跟踪重发的订阅请求的应答 服务器处理入站订阅请求 在处理入站出席信息订阅请求之前 联系人的服务器应该检查包含在 to 属性中的JID的语法 如果该JID的格式是 contact domainpart resourcepart 而不是 contact domainpart 该联系人的服务器应该把该请求当成是被指向该联系人的纯JID并据此修改 to 地址 该服务器也可以遵循 XMPP ADDR 定义的格式来检查该JID地址并可能返回一个 jid malformed 节错误 处理入站出席信息订阅请求的时候 联系人的服务器必须遵循以下规则 1 首先 联系人的服务器不能 MUST NOT 以联系人的身份批准订阅请求 除非该来联系人已经 a 如 章节3 4 所述预批准来自用户的订阅请求 b 配置它的账户自动批准订阅请求 或 c 从它的服务器提供者那里接受了一个协议以允许自动批准 例如 在一个企业部署之中通过一个雇佣协议 否则 如果一个订阅请求要求批准那么联系人的服务器必须递送那个请求到联系人的可用资源并由该联系人批准或拒绝 2 如果联系人存在并且该用户已经有一个对该联系人的出席信息的订阅 那么该联系人的服务器必须把一个类型为 subscribed 的presence节从该联系人的纯JID发送到该用户的纯JID以代表该联系人自动应答 同样 如果该联系人以前发送过一个类型为 subscribed 的presence节并且联系人的服务器假设对于该用户的出席信息订阅是 预批准的 见 章节3 4 那么该联系人的服务器也应该以该联系人的身份自动应答 CS presence from juliet example com id xk3h1v69 to romeo example net type subscribed 3 另外 如果在订阅请求被联系人的服务器接收到的时候该联系人有至少一个可用的资源 那么该联系人的服务器必须依据 第八章 发送那个订阅请求给所有可用的资源 作为获得该出席信息订阅请求的回执的一个方法 该联系人的服务器可以从该联系人的纯JID发送一个类型为 unavailable 的presence节到该用户的纯JID 该用户的客户端不能 MUST NOT 假定这个回执提供了关于该联系人的出席信息 因为它来自该联系人的纯JID并且在该订阅请求被批准之前就收到了 4 另外 如果在订阅请求被联系人的服务器接收到的时候该联系人没有可用的资源 那么该联系人的服务器必须保持一个完整的包括该订阅请求的presence节的记录 包括其中任何扩展的内容 见 XMPP CORE 的章节8 4 并且在该联系人接下来有一个可用的资源的时候递送该请求 无论何时该联系人建立了一个可用的资源该联系人的服务器必须继续递送该订阅请求 直到该联系人要么批准要么拒绝该请求 当该联系人接下来有一个可用的资源的时候 该联系人的服务器不能 MUST NOT 从任何给定用户递送多个订阅请求 例如 如果该用户发送多个订阅请求到该联系人而此时该联系人是离线的 该联系人的服务器应该只存储那些请求中的一个 比如第一个请求或最后一个请求 并且当该联系人接下来有一个可用资源的时候必须只递送这些请求中的一个 这有助于防止 垃圾订阅请求 安全警告 直到以及除非该联系人如 章节3 1 4 所述批准该订阅请求 该联系人的服务器不能 MUST NOT 在该联系人的名册上添加该用户的条目 安全警告 对于联系人的服务器存储完整的出席信息订阅请求的节的强制要求带来了一个应用程序资源衰竭攻击的可能性 见 DOS 的章节2 1 2 例如 由一个流氓服务器或一个协调好的用户群 例如 一个 botnet 攻击该联系人的服务器或特定联系人 提醒服务器实现者们关注这类攻击的可能性并为对抗它提供工具 比如允许服务管理员设置服务器整体或任何给定联系人存储的入站出席信息订阅请求的数量或大小的限制 客户端处理入站订阅请求 当一个可交互的客户端接收到一个订阅请求 它必须把该请求展示给控制该客户端的自然人 即 该 联系人 来批准 除非该联系人被显式地配置成该客户端自动批准或拒绝如上所述的某些或全部订阅请求 一个不是被自然人控制的自动客户端将有自己的应用特有的规则以批准或拒绝订阅请求 客户端通过发送一个类型为 subscribed 的presence节来批准一个订阅请求 联系人的服务器会作 章节3 1 5 所述的处理 用户的服务器会作 章节3 1 6 所述的处理 CC presence id h4v1c4kj to romeo example net type subscribed 客户端通过发送一个类型为 unsubscribed 的presence节来拒绝一个订阅请求 联系人的服务器和用户的服务器都会作 章节3 2 所述的处理 CC presence id tb2m1b59 to romeo example net type unsubscribed 为了跟踪的目的 客户端应该在一个订阅批准或订阅拒绝中包含一个 id 属性 这个 id 属性不能 MUST NOT 镜像该订阅请求的 id 属性 服务器处理出站订阅批准 当联系人的客户端发送订阅批准的时候 联系人的服务器必须以联系人的纯JID contact domainpart 标记这个出站的节并本地递送或远程路由该节到用户那里 CS presence from juliet example com id h4v1c4kj to romeo example net type subscribed 联系人的服务器接着必须发送一个updated roster push 更新名册推送 给所有联系人的感兴趣的资源 其中的 subscription 属性值设为 from 这里假定该联系人未曾订阅该用户 如果是那种情况 译者注 即该联系人已经订阅该用户 则 subscription 属性值将设置为 both 如 附录A 所述 CS iq id a78b4q6ha463 to juliet example com balcony type set query xmlns jabber iq roster item jid romeo example net subscription from query iq CS iq id x81g3bdy4n19 to juliet example com chamber type set query xmlns jabber iq roster item jid romeo example net subscription from query iq 从联系人的视角来看 现在存在一个来自用户的订阅 这就是为什么 subscription 属性值要设为 from 这里假定该联系人未曾订阅该用户 如果是那种情况 译者注 即该联系人已经订阅该用户 则 subscription 属性值将设置为 both 如 附录A 所述 该联系人的服务器接着也必须从该联系人的可用资源发送当前的出席信息给给该用户 CS presence from juliet example com balcony id pw72bc5j to romeo example net CS presence from juliet example com chamber id ux31da4q to romeo example net 为了订阅该用户的出席信息 该联系人需要发送一个订阅请求给该用户 XMPP客户端经常会自动发送订阅请求而不是要求联系人发起这个订阅请求 因为假定期望的结束状态是一个双向订阅 自然 当该联系人发送一个订阅请求给该用户 这个订阅状态将不同于前面示例中展示的状态 见 附录A 并且角色将被反转 服务器处理入站订阅批准 当用户的服务器收到一个订阅批准 它必须首先检查是否该联系人在该用户的名册中并且 subscription none 或 subscription from 以及 ask 标记设为 subscribe 即 订阅状态为 None Pending Out None Pending Out In 或 From Pending Out 见 附录A 如果这个检查成功了 那么该用户的服务器必须 1 递送入站订阅批准到该用户的所有感兴趣的资源 这有助于给该用户的客户端关于订阅批准的正确的上下文 使得它们能分辨由该用户的另一个资源生成的名册推送和从联系人收到的订阅批准的不同 这一步必须在下一步的发送名册推送之前去做 US presence from juliet example com id h4v1c4kj to romeo example net type subscribed 2 发起一个roster push给该用户的所有感兴趣的资源 包含一个该 联系人的更新的名册条目 其 subscription 属性值设为 to 如果订阅状态是 None Pending Out 或 None Pending Out In 或 both 如果订阅状态是 From Pending Out US iq id b89c5r7ib576 to romeo example net foo type set query xmlns jabber iq roster item jid juliet example com subscription to query iq US iq id b89c5r7ib577 to romeo example net bar type set query xmlns jabber iq roster item jid juliet example com subscription to query iq 3 该用户的服务器也必须把从该联系人的每个可用资源收到的可用的出席信息节递送给该用户的每个可用资源 to resource1 US presence from juliet example com balcony id pw72bc5j to romeo example net to resource2 US presence from juliet example com balcony id pw72bc5j to romeo example net to resource1 US presence from juliet example com chamber id ux31da4q to romeo example net to resource2 US presence from juliet example com chamber id ux31da4q to romeo example net 实现备注 如果在收到入站订阅批准通知的时候该用户的帐号没有可用资源 该用户的服务器可以保持该通知的记录 理想的是完整的出席信息节 并且等到该帐号有一个可用资源的时候再递送给它 这一行为向用户提供了当用户离线的时候发生名册变更的原因的更完整的信息 另外 就是 如果该用户不存在 如果该联系人不在该用户的名册中 或如果该联系人在该用户的名册中但是订阅状态不在前述的检查中描述的情况之中 那么该用户的服务器必须安静地忽略该订阅批准通知而不递送给该用户 也不修改该用户的名册 也不生成名册推送到该用户的感兴趣的资源 从该用户的角度来看 现在存在一个到该联系人的出席信息的订阅 这就是为什么 subscription 属性值要设为 to 撤销被订阅 客户端生成撤销被订阅 如果一个联系人想撤销它之前接受某个用户订阅的授权 以撤销一个预批准的被订阅 章节3 4 或拒绝一个订阅请求 它发送一个类型为 unsubscribed 的出席信息节 CC presence id ij5b1v7g to romeo example net type unsubscribed 服务器处理出站被订阅撤销 在接收到出站被订阅撤销之后 该联系人的服务器必须做如下处理 如果该用户的纯JID还不在该联系人的名册或在联系人名册中的状态是 None None Pending Out 或 To 该联系人的服务器不能 SHOULD NOT 路由或递送类型为 unsubscribed 的出席信息节给该用户 并且不能 MUST NOT 发送接下来所说的类型为 unavailable 的出席信息通知给该用户 如果该用户的纯JID在该联系人的名册的状态为 None None Pending Out 或 To 并且 approved 标记被设为 true 所以代表了 章节3 4 所述的订阅预批准 该联系人的服务器必须移除该 预批准 并且不能 MUST NOT 路由或递送类型为 unsubscribed 的出席信息节给该用户 否则 按如下的示例 该联系人的服务器必须同时路由或递送类型为 unavailable 的出席信息通知和类型为 unsubscribed 的出席信息节给该用户 并且必须发送一个名册推送给该联系人 因为该用户仍然订阅了该联系人的出席信息 即 在该联系人的服务器路由或递送类型为 unsubscribed 的出席信息给该用户之前 该联系人的服务器必须从该联系人的所有在线资源发送一个类型为 unavailable 的出席信息节给该用户 CS presence from juliet example com balcony id i8bsg3h3 type unavailable CS presence from juliet example com chamber id bvx2c9mk type unavailable 然后该联系人的服务器必须路由或递送类型为 unsubscribed 的出席信息节给该用户 确保在出站被订阅取消要带上该联系人的纯JID contact domainpart CS presence from juliet example com id ij5b1v7g to romeo example net type unsubscribed 该联系人从的服务器必须发送一个带有更新的名册条目的名册推送给该联系人的所有感兴趣的资源 这里订阅状态现在要么是 none 要么是 to 见 附录A CS iq id pw3f2v175b34 to juliet example com balcony type set query xmlns jabber iq roster item jid romeo example net subscription none query iq CS iq id zu2y3f571v35 to juliet example com chamber type set query xmlns jabber iq roster item jid romeo example net subscription none query iq 服务器处理入站被订阅撤销 当用户的服务器接收到入站被订阅撤销后 它必须首先检查该联系人是否在该用户的名册中并且 subscription to 或 subscription both 见 附录A 如果这个检查成功了 那么该服务器必须 1 递送该入站被订阅撤销到该用户的所有感兴趣的资源 这有助于给该用户的客户端正确的关于订阅被撤销的上下文 使得它们能区分由用户的另一个资源产生的名册推送和从该联系人收到的订阅被撤销 这个动作必须在发送下一步所述的名册推送之前进行 US presence from juliet example com id ij5b1v7g to romeo example net type unsubscribed 2 发起一个名册推送给该用户的所有感兴趣的资源 包含一个该联系人的更新的名册条目 其 subscription 属性值设为 none 如果之前的订阅状态为 To 或 To Pending In 或 from 如果订阅状态为 Both US iq id h37h3u1bv400 to romeo example net foo type set query xmlns jabber iq roster item jid juliet example com subscription none query iq US iq id h37h3u1bv401 to romeo example net bar type set query xmlns jabber iq roster item jid juliet example com subscription none query iq 该用户的服务器也必须递送类型为 unavailable 的入站出席信息节 实现备注 如果收到该入站被撤销订阅通知的时候 该用户的帐号没有可用的资源 该用户的服务器可以保持一个通知记录 理想的情况是完整的出席信息节 然后在该帐号下次有可用资源的时候递送该通知 这一行为把该用户离线期间发生的名册变更的原因提供了更完整的信号给该用户 另外 就是 如果该用户不存在 如果该联系人不在该用户的名册中 或如果该联系人在该用户的名册中的订阅状态不是前述检查所描述的那些状态 那么该用户的服务器必须安静地忽略该被取消订阅通知而不把它递送给该用户 也不修改该用户的名册 以及不生成名册推送给该用户的感兴趣的资源 取消订阅 客户端生成取消订阅 如果一个用户想取消订阅一个联系人的出席信息 它发送一个类型为 unsubscribe 的出席信息节 UC presence id ul4bs71n to juliet example com type unsubscribe 服务器处理出站取消订阅 在接收到出站取消订阅之后 该用户的服务器必须做如下处理 如果联系人和该用户在同一台服务器上 那么当该服务器处理订阅请求时必须遵循 3 3 3 定义的规则 如果联系人位于远端服务器上 按照本地服务策略 该用户的服务器必须接着把该节路由到那个远端域以满足核心XMPP节处理规则 这可能导致返回适当的节错误给该用户 类似 remote server timeout 如前所述 在本地递送或远程路由取消订阅之前 该用户的服务器必须在该节上标记该用户的纯JID user domainpart US presence from romeo example net id ul4bs71n to juliet example com type unsubscribe 该用户的服务器接着必须发送一个带有更新的名册条目的名册推送给该用户的所有感兴趣的资源 这里的订阅状态就变成要么是 none 要么是 from 见 RFC6121 附录 A 订阅状态 附录A US iq id h37h3u1bv402 to romeo example net foo type set query xmlns jabber iq roster item jid juliet example com subscription none query iq US iq to romeo example net bar type set id h37h3u1bv403 query xmlns jabber iq roster item jid juliet example com subscription none query iq 服务器处理入站取消订阅 当联系人的服务器收到取消订阅通知 它必须首先检查该用户的纯JID是否在该联系人的名册中且subscription from 或subscription both 即 订阅状态为 From From Pending Out 或 Both 见 附录A 如果这个检查成功了 接着该联系人的服务器必须 1 把入站取消订阅递送给该联系人的所有感兴趣的资源 这有助于向联系人的客户端们提供关于取消订阅的正确的上下文 这样它们就能区分是由联系人的另一个资源产生的名册推送还是从该用户收到的取消订阅 这个动作必须发生在下面所说的发送名册推送步骤之前 CS presence from romeo example net id ul4bs71n to juliet example com type unsubscribe 2 发起一个名册推送给该联系人的所有感兴趣的资源 为该用户包含一个更新的条目并把 subscription 属性值设为 none 如果之前的订阅状态是 From 或 From Pending Out 或 to 如果之前的订阅状态是 Both CS iq id tn2b5893g1s4 to juliet example com balcony type set query xmlns jabber iq roster item jid romeo example net subscription none query iq CS iq id sp3b56n27hrp to juliet example com chamber type set query xmlns jabber iq roster item jid romeo example net subscription none query iq 3 从该联系人的每一个可用资源生成一个类型为 unavailable 的出站出席信息节给该用户 CS presence from juliet example com balcony id o5v91w49 to romeo example net type unavailable CS presence from juliet example com chamber id n6b1c37k to romeo example net type unavailable 实现备注 如果在收到入站取消订阅通知的时候该联系人的帐号没有可用资源 该联系人的服务器可以保持一个通知记录 理想情况下是完整的出席信息节 并且接着在该帐号下次有一个可用资源的时候递送该通知 这一行为为该用户提供了关于该用户离线时发生的名册变更的更完整的信息 另外 就是 如果该联系人不存在 如果该用户不在该联系人的名册中 或如果该用户的纯JID在该联系人的名册中并且订阅状态不同于前面检查所述的结果 那么该联系人的服务器必须安静地忽略该取消订阅节 不递送给该联系人 不修改联系人的名册 也不生成名册推送给该联系人的所有感兴趣的资源 无论如何 如果该联系人的服务器持续跟踪一个从该用户到该联系人的入站出席信息订阅请求但是该用户仍不在该联系人的名册中 功能上相当于一个订阅状态 None Pending In 这里该联系人从未添加该用户到联系人的名册中 那么该联系人的服务器必须简单地移除该入站出新信息订阅请求的记录 它无法从该联系人的名册中移除该用户 因为该用户从未被加入到该联系人的名册中 实现备注 该用户的客户端不能 MUST NOT 依赖于从该联系人收到的取消订阅出席信息通知 因为它必须考虑对该联系人的出席信息订阅 以及关于该联系人的出席信息 当它发送类型为 unsubscribe 的出席信息节或它收到由取消订阅请求触发的名册推送的时候为无或空 预批准被订阅请求 如果一个用户还未从一个联系人那里接收到订阅请求 该用户可以 预批准 这样一个请求 这样它将被该用户的服务器自动地批准 对订阅预批准的支持在客户端和服务器上都是可选的 如果一个服务器支持订阅预批准 那么它必须在流协商时声明以下流特性 sub xmlns urn xmpp features pre approval 订阅预批准流特性只不过有一点用 所以永远不会强制协商 客户端生成被订阅预批准 如果客户端所连接的服务器声明了订阅预批准 该客户端可以通过发送一个类型为 subscribed 的节给该联系人以生成一个订阅预批准 UC presence id pg81vx64 to juliet example com type subscribed 如果该服务器未声明支持订阅预批准 该客户端不能 MUST NOT 尝试预批准来自潜在的或者实际的联系人的订阅请求 服务器处理被订阅预批准 在接收到类型为 subscribed 的出席信息节之后 该用户的服务器如果支持订阅预批准 必须做如下处理 如果该联系人在该用户的名册中且状态为 Both From 或 From Pending Out 该用户的服务器必须安静地忽略该节 如果该联系人在该用户的名册中且状态为 To Pending In None Pending In 或 None Pending Out In 该用户的服务器必须如普通的订阅批准那样处理该节 见 3 1 5 更新现有的名册条目的状态成为 Both From 或 From Pending Out 分别的 推送修改的名册条目到该用户的所有感兴趣的资源 并路由该类型为 subscribed 的出席信息节到该联系人 如果该联系人在该用户的名册中且状态为 To None 或 None Pending Out 该用户的服务器必须把 approved 标记的值设置为 true 来记录订阅预批准 然后推送修改的名册条目到该用户的所有感兴趣的资源 无论如何 该用户的服务器不能 MUST NOT 路由该类型为 subscribed 的出席信息节到该联系人 如果该联系人还不在该用户的名册中 那么该用户的服务器必须为该联系人创建一个名册条目且状态为 None 并且把 approved 标记的值设为 true 然后推送该名册条目到该用户的所有感兴趣的资源 无论如何 该用户的服务器不能 MUST NOT 路由该类型为 subscribed 的出席信息节到该联系人 一个名册推送的示例如下 US iq id h3bs81vs763f to romeo example net bar type set query xmlns jabber iq roster item approved true jid juliet example com subscription none query iq 当 approved 标记被设为 true 该用户的服务器不能 MUST NOT 从该联系人递送一个类型为 subscribe 的出席信息节给该用户 而是必须代表该用户自动应答这样一个节 即从该用户的纯JID返回一个类型为 subscribed 的出席信息节给该联系人的纯JID 实现备注 服务器在已经从该联系人接收到了一个出席信息订阅请求之后是否维护一个订阅批准记录 对于实现或本地服务策略来说是个问题 如果该服务器不维护这样一个记录 在接收该订阅请求之后它将在该名册条目中不为该联系人包含 approved 属性 即 在随后的名册推送和名册结果中 如果该服务器维护这样一个记录 它将在名册条目中总是为该联系人包含 approved 属性 设为 true 直到或除非该用户发送一个类型为 unsubscribed 的出席信息节到该联系人 或从名册中完全移除该联系人 实现备注 客户端能通过发送一个类型为 unsubscribed 的出席信息节取消一个预批准 更全面的描述在 3 2 在这种情况下 该用户的服务器将发送一个名册推送给该有用户的所有感兴趣的资源 而其 approved 属性是被移除的 另一种选择是 该客户端能简单地完全移除该名册条目 交换出席信息 出席信息原理 出席信息是指在网络上通讯的一个实体的可用性 在最基本的层面上 出席信息是一个 on off 的逻辑变量以标记一个实体可不可以通讯 也用术语 在线 和 离线 在XMPP中 当客户端生成一个不带 type 属性的 presence 节时就标记了一个实体的可用性 当它的客户端生成一个 type 属性值为 unavailable 的 presence 节时表示一个实体失去了可用性 XMPP出席信息典型地遵循一个 发布 订阅 或 观察者 模式 这里 一个实体发送出席信息给它的服务器 它的服务器接着广播那个信息给所有订阅了该实体的出席信息的联系人 在 IMP MODEL 的术语中 一个生成出席信息的实体就是一个 presentity 并且那些接收出席信息的实体们是 subscribers 一个客户端通过发送一个不带 to 地址的出席信息节给它的服务器来生成出席信息用于广播给所有已订阅的实体们 这里的出席信息既没有 type 属性又没有值为 unavailable 的 type 属性 这种出席信息被称为 广播出席信息 一个客户端也可以发送 定向出席信息 即 一个带 to 地址的出席信息节 这不太常见但是有时被用于发送出席信息给那些没有订阅该用户的出席信息的实体们 见 4 6 在一个客户端完成 XMPP CORE 定义的先决条件之后 它能通过发送初始化出席信息在它的服务器建立一个 出席信息会话 通过发送unavailable出席信息可以中止这个出席信息会话 在它的出席信息会话期间 一个已连接的资源 XMPP CORE 中的术语 被称为一个 可用的资源 在XMPP中 应用集合了消息和出席信息功能 它的出席信息标记的可用性的缺省通讯类型是消息 然而 对于XMPP应用来说把消息和出席信息功能集合到一起并不是必要的 它们能提供独立的不带消息的出席信息特性 另外 XMPP服务器们不会为了成功地路由message和IQ节而强制要求关于网络可用性的信息 提示备注 在接下来的例子中 用户是 juliet example com 她有两个可用的资源 balcony 和 chamber 而在她的名册中有三个联系人且订阅状态为 from 或 both romeo example net mercutio example com 和 benvolio example net 初始化出席信息 客户端生成初始化出席信息 在完成 XMPP CORE 必需的 中所述的前提条件并请求名册 推荐的 之后 一个客户端通过发送 初始化出席信息 给它的服务器来标记它的通讯可用性 即 一个不带 to 地址 意思是由该服务器代表该客户端广播它 和 type 属性 表示该用户的可用性 的出席信息节 UC presence 该初始化出席信息可以包含 priority 元素 show 元素 一个一个或多个 status 元素实例 以及扩展内容 细节见 4 7 服务器处理出站初始化出席信息 从一个客户端接收到初始化出席信息之后 该用户的服务器必须从该用户的全JID user domainpart resourcepart 发送该出席信息节给所有订阅了该用户的出席信息的联系人 这些联系人的JID目前正在该用户的名册中且 subscription 属性值为 from 或 both US presence from juliet example com balcony to romeo example net US presence from juliet example com balcony to mercutio example com US presence from juliet example com balcony to benvolio example net 该用户的服务器也必须从该用户的新的可用资源广播初始化出席信息给该用户的所有可用资源 包括在第一个地方生成该出席信息通知的那个资源 即 一个实体隐形地订阅了它自己的出席信息 to the balcony resource US presence from juliet example com balcony to juliet example com to the chamber resource US presence from juliet example com balcony to juliet example com 在缺少关于该用户的联系人的出席信息的情况下 该用户的服务器也必须代表该用户发送出席信息探测给该用户的联系人 如 4 3 所述 服务器处理入站初始化出席信息 在从该用户接收到出席信息之后 该联系人的服务器必须递送该用户的出席信息节给该联系人的所有可用资源 to resource1 CS presence from juliet example com balcony to romeo example net to resource2 CS presence from juliet example com balcony to romeo example net 客户端处理初始化出席信息 当该联系人的客户端从该用户接收到出席信息之后 对于可交互的客户端推荐以下行为 如果该用户的纯JID在该联系人的名册中 在一个适当的名册接口中显示该出席信息 如果该用户不在该联系人的名册中但是联系人正在交换message或IQ节 为了那个通讯会话在该用户的接口中显示该出席信息 参见 4 6 和 5 1 其他情况下 忽略出席信息并且不把它显示给该联系人 出席信息探测 一个 出席信息探测 是一个对某联系人的当前出席信息的请求 由代表某个用户的服务器代表该用户发送 语法上它是一个 type 属性值为 probe 的出席信息节 在出席信息订阅的上下文中 from 地址的值必须是订阅的用户的纯JID而 to 地址的值必须是被订阅的联系人的纯JID 因为出席信息订阅是基于纯JID的 US presence from juliet example com id ign291v5 to romeo example net type probe 互操作性备注 RFC 3921 定义了探测是从全JID发出的 而不是从纯JID 规则的改变是因为订阅是基于纯JID的 一些现存的实现仍然从全JID而不是纯JID发送 探测也能由一个从某个出席信息订阅上下文的外部接收到了出席信息的实体发送 典型的是当该联系人已经发送了 4 6 所述的定向出席信息的时候 在这种情况下 from 或 to 地址的值可以是一个全JID而不是一个纯JID 完整的讨论参见 4 6 出席信息探测不应该 SHOULD NOT 由一个客户端发送 因为通常一个客户端不需要发送它们 原因是从一个用户的联系人那里收集出席信息的任务是由该用户的服务器管理的 无论如何 如果一个用户的客户端生成了一个出站出席信息探测 那么该用户的服务器应该路由这个探测 如果该联系人位于另一个服务器上 或处理这个探测 如果该联系人在同一台服务器上 并且不能 MUST NOT 从一个已连接的客户端使用该出席信息探测的回执来作为唯一的理由来返回一个节错误或流错误给该客户端 服务器生成出站出席信息探测 当一个服务器需要查询一个用户的联系人的可用性的时候 它从该用户的纯JID user domainpart 发送一个出席信息探测到该联系人的纯JID contact domainpart 实现备注 尽管出席信息探测是用来发送给联系人的 即 一个用户所订阅的那些实体 一个服务器可以发送出席信息探测给该用户在当前会话时收到了出席信息的某个实体的全JID 当用户在任何时候通过发送初始化出席信息来开始一个新的出席信息会话 该用户的服务器应该发送一个出席信息探测 无论如何 如果它认为关于该用户的联系人的出席信息是可靠的和最新的 该服务器可以选择在那个时间点不发送出席信息探测 例如 因为该用户有另外一个可用资源或因为该用户在新的出席信息开始之前刚刚注销登陆 另外 如果一个服务器在一个可配置的时间段内没有从某个联系人收到出席信息或其他通讯 它可以定期发送出席信息探测给那个联系人 这有助于防止看起来在线但是实际上没有在线的 幽灵 联系人 US presence from juliet example com id ign291v5 to romeo example net type probe US presence from juliet example com id xv291f38 to mercutio example com type probe 自然的 该用户的服务器不需要发送一个出席信息探测给一个联系人 如果该联系人的帐号位于该用户的同一台服务器 因为该服务器本地就拥有该联系人的信息 服务器处理入站出席信息探测 在接收到一个用户的服务器代表该用户发送到该联系人的纯JID的出席信息探测之后 该联系人的服务器必须应答如下 1 如果该联系人帐号不存在或该用户的纯JID在该联系人的名册中并且订阅状态不是 From From Pending Out 或 Both 如 附录A 所述 那么该联系人的服务器应该在对该出席信息探测的应答中返回一个类型为 unsubscribed 的出席信息节 这将触发一个协议流用于 3 2 所述的撤销该用户对该联系人的订阅 无论如何 这不能 MUST NOT 导致 3 4 所述的订阅预批准的撤销 这里 from 地址必须是该联系人的纯JID 因为指定一个全JID则等同于出席信息泄露 XMPP CORE 中所说的 CS presence from mercutio example com id xv291f38 to juliet example com type unsubscribed 无论如何 如果一个服务器从一个该服务器本身的已配置的域或其他信任的服务收到一个出席信息探测 它可以提供关于该用户或那个实体的出席信息 2 或者 如果该联系人已经临时移动或永久移动到另一个地址 那么该服务器应该返回一个类型为 error 的出席信息节并带上一个节错误条件 redirect 临时的 或 gone 永久的 并包含该联系人的新地址 CS presence from mercutio example com id xv291f38 to juliet example com type error error type modify gone xmlns urn ietf params xml ns xmpp stanzas xmpp la mer example com gone error presence 3 或者 如果该联系人没有可用的资源 那么该服务器应该通过发送给该用户一个类型为 unavailable 的出席信息节来应答该出席信息探测 尽管在这里更倾向于发送unavailable出席信息 因为它能导致对该探测的确定的回答 但它不是强制性的 因为它极大地增加了该联系人的服务器生成的出席信息通知的数量 这里的 from 地址是纯JID 因为没有该联系人相关的可用资源 如果适当地遵循本地安全策略 该出席信息通知可以包含该服务器从该联系人收到的最近的unavailable出席信息节的全XML 包括原始节的 id 但是如果没有 那么该出席信息通知应该简单地表示该联系人是unavailable而没有任何原始提供的细节 在任何情况下 返回给该探测实体的出席信息节应该包含最近一次unavailable出席信息节被生成的时间信息 格式采用XMPP延迟递送扩展 DELAY CS presence from mercutio example com id xv291f38 to juliet example com type unavailable delay xmlns urn xmpp delay stamp 2002 09 10T23 41 07Z presence 4 或者 如果该联系人有至少一个可用资源 那么该服务器必须通过向该用户发送该服务器从该联系人的每个可用资源收到的最近的没有 to 属性的出席信息节的全XML 这里的 from 地址是每个可用资源的全JIDs CS presence from romeo example net foo id hzf1v27k to juliet example com CS presence from romeo example net bar id ps6t1fu3 to juliet example com show away show presence 实现备注 通过 full XML 意味着从开始的 presence 标签到关闭的 presence 标签之前的完整的节 包括所有的元素和属性 要么由内容命名空间限定要么由扩展命名空间限定 无论如何 根据 XMPP CORE 如果通过服务器 服务器流发送完整的节 该联系人的服务器将需要把内容命名空间从 jabber client 转换成 jabber server 如果该联系人的服务器接收到一个地址指向该联系人的某个全JID的出席信息探测 该服务器不能 MUST NOT 返回任何除了该探测的 to 地址之外的资源的出席信息 规则 1 和 2 中对一个纯JID的探测同样适用于一个全JID探测的情况 如果有一个匹配的全JID并且探测的实体通过一个出席信息订阅从而有权限察看该联系人的出席信息 那么该服务器必须返回一个available出席信息通知 它应该确切地只和那个available的资源通讯 没有详细信息 如 show status priority 或出席信息扩展 CS presence from romeo example net bar to lobby chat example com 实现备注 关于前述处理定向出席信息的补充请参阅 4 6 处理 id 属性 和出席信息探测相关的 id 属性的处理在 RFC 3921 中没有定义 尽管 发送一个探测并接收到一个应答 的模式可能看起来像一个类似XMPP iq 节的 请求 应答 协议 事实上它不是 因为对一个探测的应答可以包含多个出席信息节 分别对应该联系人当前活跃的每一个可用的资源 基于这个原因 如果该联系人当前有可用资源 那么该联系人的服务器应该保留当发送那些出席信息通知给探测实体的时候该联系人的原始出席信息节的 id 属性 如果有的话 相比之下 如果该联系人当前没有可用资源 探测实体未被授权 通过出席信息订阅 察看该联系人的出席信息 或发生了和该探测相关的错误 那么该联系人的服务器在应答探测实体的时候应该镜像该用户的出席信息探测的 id 以下示例展现这些不同之处 在第一个场景中 Juliet发送从她的 chamber 资源出席信息探测 CC presence from juliet example com chamber id pres1 show dnd show status busy status presence 她也从她的 balcony 资源发送出席信息 CC presence from juliet example com balcony id pres2 show away show status stepped away status presence Romeo的服务器接着发送一个探测给Juliet US presence from romeo example net id probe1 type probe Juliet的服务器接着同时发送她的两个出席信息通知给Romeo 保留她的客户端发送的节中的 id 属性 CS presence from juliet example com chamber id pres1 show dnd show status busy status presence CS presence from juliet example com balcony id pres2 show away show status stepped away status presence 在第二个场景中 当Romeo的服务器发送探测的时候Juliet离线了 US presence from romeo example net id probe2 type probe Juliet的服务器应答一个unavailable通知 镜像Rome的出席信息探测的 id 因为从她的客户端已经发送的available通知的 id 被保留 CS presence from juliet example com id probe2 type unavailable 随后的出席信息广播 客户端生成随后的出席信息广播 在发送初始化出席信息之后 在它的会话期间的任何时候该用户的客户端可以更新它的可用性并通过发送一个不带 to 地址并且没有 type 属性的出席信息节来广播 UC presence show away show presence 该出席信息广播可以包含 priority 元素 show 元素 和一个或多个 status 元素实例 同样的包括扩展内容 详情参见 4 7 无论如何 一个用户应该发送一个出席信息更新只广播该用户的通讯可用性或该资源的通讯能力相关的信息 和这些无关但是可能该用户的联系人同样感兴趣的信息应该通过其他方式来发送 例如 XEP 0163 所述的 发布 订阅 方法 服务器处理随后的出站出席信息 在接收到一个表达更新的可用性的出席信息节后 该用户的服务器必须广播那个出席信息节的完整XML给该用户名册中并且订阅类型为 from 或 both 的联系人们 互操作性备注 RFC 3921 定义在发送随后的出席信息通知之前该用户的服务器将检查并确认没有从该联系人收到一个出席信息错误 那个规则已经被移除 因为本协议使用类型为 unsubscribe 而不是 error 的出席信息节来解决订阅同步问题 部分也因为这类节使得该联系人在该用户的名册中的订阅状态变成了 none 或 to 见 3 3 和 附录A 所以没有了对错误检查的需要 互操作性备注 如果订阅类型为 both 一些现有的服务器实现根据该用户的服务器仅当该联系人在线时才发送随后的出席信息通知给一个联系人 就是说 如果该用户的服务器在它发给该联系人的出席信息探测的应答中从未收到过该联系人在线的肯定的标示 该用户的服务器不会从该用户向该联系人发送随后的出席信息通知 这一行为被理解为节省带宽 因为大部分出席信息订阅是双向的并且很多联系人在任何特定的时间都不在线 US presence from juliet example com balcony to romeo example net show away show presence US presence from juliet example com balcony to benvolio example net show away show presence US presence from juliet example com balcony to mercutio example com show away show presence 实现备注 关于上述处理用于定向出席信息的补充规则参见 4 6 该用户的服务器也必须发送该出席信息节给该用户的所有可用资源 包括首先生成该出席信息的那个资源 US presence from juliet example com balcony to juliet example com chamber show away show presence US presence from juliet example com balcony to juliet example com balcony show away show presence 服务器处理随后的入站出席信息 在从用户那接收到出席信息之后 该联系人的服务器必须递送该用户的出席信息节到该联系人的所有可用资源 to resource1 CS presence from juliet example com balcony to romeo example net show away show presence to resource2 CS presence from juliet example com balcony to romeo example net show away show presence 客户端处理随后的出席信息 从联系人的客户端的视角来看 初始化出席信息广播和随后的出席信息没有明显的不同 所以联系人的客户端遵循 4 4 3 定义的入站出席信息处理的规则 离线出席信息 客户端生成离线出席信息 在结束和一个服务器的出席信息会话之前 用户的客户端应该通过发送 unavailable 出席信息 优雅地变更为离线 即 一个没有 to 属性并且有一个值为 unavailable 的 type 属性的出席信息节 UC presence type unavailable 可选的 该离线出席信息节可以包含一个或多个 status 元素来定义为什么该用户不再在线的原因 UC presence type unavailable status going on vacation status presence 无论如何 该离线出席信息节不能 MUST NOT 包含 priority 元素或 show 元素 因为这些元素只适用于可用资源 服务器处理出站离线出席信息 该用户的服务器不能 MUST NOT 依赖于从一个可用的资源接收到的unavailable出席信息 因为该资源可能不优雅地离线了 例如 如 XMPP CORE 所述 该资源的XML流因为任何原因带或未带流错误地被关闭了 如果一个可用的资源因为任何原因离线了 优雅或不优雅的 该用户的服务器必须广播unavailable出席信息给所有在该用户的名册中的订阅状态为 from 或 both 的联系人 互操作性备注 RFC 3921 定义了该用户的服务器将检查并确认在发送unavailable出席信息通知之前它没有从该联系人收到一个出席信息错误 那个规则已经被移除 因为本协议使用类型为 unsubscribe 而不是 error 的出席信息节来解决订阅同步问题 部分也因为这类节使得该联系人在该用户的名册中的订阅状态变成了 none 或 to 见 3 3 和 附录A 所以没有了对错误检查的需要 互操作性备注 即使该用户的服务器不广播该用户随后的出席信息通知给离线的联系人们 如 4 4 2 所述 它必须广播该用户的unavailable出席信息通知 如果它不这么做 由该联系人的服务器最后收到的出席信息将是该用户用于这个出席信息会话的初始化出席信息 结果是该联系人将认为该用户在线 实现备注 关于上述处理用于定向出席信息的补充规则参见 4 6 如果该unavailable通知优雅地被从该客户端接收到 那么该服务器必须广播该出席信息节的完整XML US presence from juliet example com balcony to romeo example net type unavailable status going on vacation status presence US presence from juliet example com balcony to benvolio example net type unavailable status going on vacation status presence US presence from juliet example com balcony to mercutio example com type unavailable status going on vacation status presence 该用户的服务器也必须发送该unavailable通知给该用户的所有可用资源 以及最初生成该unavailable出席信息的那个资源 US presence from juliet example com balcony to juliet example com chamber type unavailable status going on vacation status presence 如果该服务器探测到那该用户已经不优雅地离线了 那么该服务器必须代表该用户生成该unavailable出席信息广播 实现备注 在该服务器广播或生成一个unavailable出席信息通知之后 该客户端发送的任何没有 type 属性且没有 to 属性的出席信息节 必须被该用户的服务器路由或递送到所有的订阅者 即 必须等同于为一个新的出席信息会话出发了初始化出席信息 服务器处理入站离线出席信息 在从用户接收到一个unavailable通知之后 该联系人的服务器必须递送该用户的出席信息节给该联系人的所有可用资源 to resource1 CS presence from juliet example com balcony to romeo example net type unavailable status going on vacation status presence to resource2 CS presence from juliet example com balcony to romeo example net type unavailable status going on vacation status presence 实现备注 如果该联系人的服务器没有广播随后的出席信息通知给离线的用户们 如 4 4 2 它也必须注意到该用户是离线的并更新它的关于哪些实体在线的内部存储 客户端处理离线出席信息 从联系人的客户端的视角来看 在线出席信息广播和离线出席信息广播没有明显的差别 所以通常联系人的客户端遵循定义的处理入站出席信息的规则 4 4 3 无论如何 如果该联系人从该用户的纯JID 而不是某个可用资源的全JID 接收到一个unavailable通知 该联系人的客户端应该视为该unavailable通知适用于所有资源 定向出席信息 本章是客户端和服务器处理出席信息通知和出席信息探测的规则的补充 但是仅用于定向出席信息的特定场景 总则 通常 当一个客户端希望分享可用性信息给一个没有订阅它的出席信息的实体的时候 它会发送定向出席信息 典型的是在一个临时基础上 定向出席信息的常规使用包括 5 1 所述的临时的一对一会话和 XEP 0045 所述的多用户聊天室 通过分享定向出席信息给另一个实体而建立的临时的关系比起通过出席信息订阅建立的永久关系来说是次要的 所以 建立 修改 或取消一个出席信息订阅的动作 必须优先于接下来的子章节定义的规则 例如 如果一个用户分享了定向出席信息给一个联系人 但是接着通过完成出席信息订阅 握手 来把该联系人加入到该用户的名册中 那么该用户的服务器必须把该联系人视为如 第三章 所述的任何一个普通的订阅者来处理 例如 发送随后的出席信息广播给该联系人 另一个例子是 如果该用户接着取消了该联系人对该用户的出席信息的订阅 该用户的服务器必须如 3 2 所述处理这个取消动作 这包括发送unavailable出席信息给该联系人 即使该用户曾经发送了定向出席信息给该联系人 XMPP服务器典型的实现定向出席信息的办法是通过保持一个用户在该用户的给定资源 全JID 的当前会话期间曾经对它们发送了定向出席信息的实体的列表 纯JIDs或全JIDs 然后在该用户下线的时候清除这个列表 例如 发送一个类型为 unavailable 的广播出席信息节 该服务器必须从定向出席信息列表 或它的功能等价物 移除任何该用户曾经对它们发送过定向unavailable出席信息的实体并且应该移除任何发送了unavailable出席信息给该用户的实体 客户端生成定向出席信息 大家知道 定向出席信息是一个客户端生成的presence节 这个节的 to 属性值是另一个实体的纯JID或全JID 并且这个节要么没有 type 属性 表示可用性 要么 type 属性值为 unavailable 服务器处理出站定向出席信息 当用户的服务器接收到一个定向出席信息节 它应该根据以下规则处理它 如果该用户在已经发送初始化出席信息之后并且在发送unavailable出席信息广播之前 即 在该用户的出席信息会话期间 发送定向的可用或不可用出席信息给一个在该用户的名册中并且订阅状态为 from 或 both 的联系人 该用户的服务器必须本地递送或远程路由那个出席信息节的完整XML给那个实体 但是应该不 SHOULD NOT 基于出席信息广播来修改该联系人的状态 即 它应该在任何随后由该用户初始化的的出席信息广播中包含该联系人的JID 如果该用户在已经发送初始化出席信息之后并且在发送unavailable出席信息广播之前 即 在该用户的出席信息会话期间 发送定向的可用或不可用出席信息给一个不在该用户的名册中并且订阅状态为 from 或 both 的联系人 该用户的服务器必须本地递送或远程路由那个出席信息节的完整XML给那个实体 但是不能 MUST NOT 基于available出席信息广播来修改该联系人的状态 即 它不能 MUST NOT 在任何随后由该用户初始化的available出席信息广播中包含该联系人的JID 无论如何 如果发送定向出席信息的用户的可用资源离线了 该用户的服务器必须路由那个离线出席信息给该实体 如果该用户还未发送定向unavailable出席信息给那个实体 如果该用户从未发送过初始化出席信息或在已经发送unavailable出席信息广播之后 即 该资源已连接但不可用 发送定向出席信息 该用户的服务器必须把该实体当作上面第二种情况下该用户发送定向出席信息的实体 服务器处理入站定向出席信息 从联系人的服务器的视角来看 在出席信息广播和定向出席信息之间没有显著差别 所以联系人的服务器遵循 4 3 2 4 4 3 和 4 5 3 定义的处理入站出席信息的规则 客户端处理入站定向出席信息 从联系人的客户端的视角来看 在出席信息广播和定向出席信息之间没有显著差别 所以联系人的客户端遵循定义的处理入站出席信息的规则 4 4 3 译者注 原文如此 疑为 4 4 4 之误 服务器处理出席信息探测 如果一个用户的客户端发送了定向出席信息给另一个实体 例如 一个一对一聊天伙伴或一个多用户聊天室 在一段时间之后该实体或它的服务器可能想知道该用户是否仍然在线 这个场景在多用户聊天室中特别常见 该用户可能在很长一段时间内在该聊天室中是一个参加者 如果该用户的客户端下线而没有 通过客户端或该客户端的服务器 通知该聊天室 该用户的在该房间里的表现可能成为一个 幽灵 看起来是参加者但实际上已经不在该房间了 为了查明这类 幽灵 一些聊天室实现会发送出席信息探测给这些已经加入房间的用户 在定向出席信息的案例中 探测的实体应该从接收到定向出席信息的那个JID 一个全JID或纯JID 发送探测 该探测应该被发送到那个用户的全JID 而不是那个用户的不带资源的纯JID 因为伴随定向出席信息的临时 授权 是基于曾经发送定向出席信息给该探测实体的那个用户的全JID 当该用户的服务器接收到一个探测 它必须首先应用任何和出席信息订阅相关的逻辑 如 4 3 2 所述 如果该探测实体未订阅该用户的出席信息 那么该服务器必须检查该用户是否曾经在当前会话中发送过定向出席信息给该实体 如果是 该服务器应该仅以纯粹的 available 或 unavailable 类型 即 不包含子元素 应答这个探测并且只用于那个全JID 即 不为任何可能与当前该用户的纯JID相关的其他资源 出席信息语法 Type属性 缺少 type 属性代表相关实体是可以通讯的 见 4 2 和 4 4 type 属性值为 unavailable 代表相关实体不可通讯 见 4 5 XMPP出席信息节也用于协商和管理对其他实体的出席信息的订阅 这些任务通过 第三章 所述的类型为 subscribe unsubscribe subscribed 和 unsubscribed 的出席信息节来完成 如果一个用户和联系人在不同的XMPP服务器上发生关系 那些服务器为了确定对端服务器上的那个实体的可用性 也使用一个类型为 probe 的特殊的出席信息节 详见 4 3 客户端不应 SHOULD NOT 发送类型为 probe 的出席信息节 type 属性的值可以归纳如下 error error发生在处理之前发送的出席信息节的时候 如果出席信息节的类型为 error 它必须包含一个 error 子元素 参考 XMPP CORE probe 请求一个实体当前的出席信息 应该只由一个服务器代表一个用户生成 subscribe 发送者希望订阅接收者的出席信息 subscribed 发送者已经允许接收者接收他们的出席信息 unavailable 发送者不再可通讯 unsubscribe 发送者取消订阅接收者的出席信息 unsubscribed 订阅请求已经被拒绝或撤销之前准许的被对方订阅 如果 type 属性的值不是前述的任何一个 接收方或一个中间的路由服务器应该返回一个节错误 bad request 实现备注 presence 元素的 type 属性没有缺省值 实现备注 presence 元素的 type 属性没有 available 这个值 子元素 根据缺省命名空间声明 一个出席信息节是由 jabber client 或 jabber server 命名空间限定的 它定义了明确的出席信息节的子元素 特别是 show status 和 priority 元素 这些子元素被用于提供关于一个实体的可用性的更详细的信息 典型情况下这些子元素只在该出席信息节没有 type 属性的时候被包含 尽管在接下来的文本里有一些例外 Show元素 可选的 show 元素定义了一个实体或它的一个特定资源的特定的可用性子状态 一个出席信息节不能 MUST NOT 包含多于一个的 show 元素 show 元素没有定义属性 show 元素不能 MUST NOT 包含混合内容 定义于 XML 3 2 2节 show 元素的XML字符数据不意味着它是用于展示给自然人用户看的 该XML字符数据必须是以下之一 更多的可用性状态可以通过扩展内容元素来定义 away 该实体或资源临时离开 chat 该实体或资源活跃并想聊天 dnd 该实体或资源忙 dnd Do Not Disturb 免打扰 xa 该实体或资源要离开相当长时间 xa eXtended Away 长时间离开 如果 show 元素未被提供 该实体被假定在线并且可用 任何由接收者和代理路由服务器对可用性状态的特别处理取决于该实现 例如 把可用性状态合并到节路由和递送逻辑中 Status元素 可选的 status 元素包含了自然人可读的定义实体可用性的自然语言描述的XML字符数据 通常在出席信息节不包含 type 属性的时候被用于和show元素结合一起提供某个可用性状态的细节 例如 In a meeting 开会中 presence from romeo example net orchard xml lang en show dnd show status Wooing Juliet status presence status 元素没有定义属性 除了从 XML 继承的 xml lang 属性 status 元素不能 MUST NOT 包含混合内容 定义于 XML 3 2 2节 status 元素可以包含多个实例 但是只能在每个实例的都有一个 xml lang 属性并且属性值为唯一的语言值 或者显式地 或者从一个元素的更高的XML级别的 xml lang 值继承 从发送者的视角来看 可能包括 XMPP CORE 描述的XML流头 presence from romeo example net orchard id jx62vs97 xml lang en show dnd show status Wooing Juliet status status xml lang cs Dvo x0159 x00ED m se Julii status presence 一个类型为 unavailable 的出席信息节也可以包含一个 status 元素来提供为什么该实体下线的详细原因 presence from romeo example net orchard id oy6sb241 type unavailable xml lang en status Busy IRL status presence status 子元素也可以在一个订阅相关的出席信息节中被发送 即 类型为 subscribe subscribed unsubscribe 或 unsubscribed 以提供该动作的描述 一个可交互的客户端可以展示这个 status 信息给一个自然人用户 见 第11章 presence from romeo example net id uc51xs63 to nurse example com type subscribe status Hi Juliet told me to add you to my buddy list status presence Priority元素 可选的 priority 元素包含定义该资源优先级的非自然人可读的XML字符数据 它的值必须是一个处于 128 和 127 之间的整数 一个出席信息不能 MUST NOT 包含多个 priority 元素 没有为 priority 定义属性 priority 元素不能 MUST NOT 包含混合内容 定义于 XML 3 2 2节 presence xml lang en show dnd show status Wooing Juliet status status xml lang cs Dvo x0159 x00ED m se Julii status priority 1 priority presence 如果没有提供优先级 处理的服务器或客户端必须视为优先级为零 0 该客户端的服务器可以覆写客户端提供的优先级的值 例如 为了给正在递送给预期的帐号的纯JID的消息强加一个消息处理规则以用于该帐号的所有可用资源 如果服务器这样做 当它回应该客户端的出席信息给自己并发送出席信息通知给该用户的联系人们的时候 它必须以修改过的优先级来通讯 因为修改过的优先级的值典型的缺省是零 以修改过的优先级的值来通讯可以不包含 priority 子元素 关于即时消息和出席信息应用中节处理过程中优先级值的语法信息 参见 第八章 扩展内容 如 XMPP CORE 所述 一个XML节可以包含任何由不同于缺省命名空间限定的子元素 这也适用于出席信息节 以下例子中 出席信息节包含定义于 XEP 0115 的实体能力信息 presence from romeo example net c xmlns http jabber org protocol caps hash sha 1 node http psi im org ver q07IKJEyjvHSyhy CH0CxmKi8w presence 包含在一个出席信息节中的任何扩展内容应该展示用于通讯的实体可用性的方方面面或提供和通讯相关的能力 交换消息 一旦一个客户端如 XMPP CORE 所述 已经在一个服务器上通过了验证并绑定了一个资源到一个XML流 一个XMPP服务器将路由XML节到和从那个客户端 一种可交换的节是 message 如果 也就是说 消息功能在该服务器上是允许的 交换消息是XMPP的一个基本用途 它发生在一个用户生成一个地址指向另一个实体的消息节的时候 如 第八章 所定义的 该发送者的服务器负责递送该消息到期望的接收者 如果该接收者在同一台本地服务器上 或路由该消息到该接收者的服务器 如果该接收者在一个远端服务器上 所以一个消息节是被用来 推送 信息给另一个实体 一对一聊天会话 在实践中 在自然人用户之间的即时消息活动倾向于以一个会话式的方式发生 我们称之为一个 聊天会话 在一个比较短暂的时间内双方的多个比较快速的消息交换是有继承的 当一个自然人用户倾向于和一个联系人进行这样一种聊天会话 而不是发送一个单独的消息给某人却不期望获得应答 由该用户的客户端生成的这个消息的类型应该是 chat 并且该联系人的客户端应该在随后的应答中保持那个消息类型 该用户的客户端也应该在它的初始化消息中包含一个 thread 元素 这样该联系人的客户端也应该在那个会话的生命周期中保持它 参见 5 2 5 该用户的客户端应该在一个聊天会话中把初始消息的地址指向该联系人的纯JID contact domainpart 而不是基于任何它可能之前从联系人那收到的出席信息通知的 show status 或 priority 值来尝试猜测一个适当的全JID contact domainpart resourcepart 直到和除非该用户的客户端从该联系人收到一个应答 它应该发送任何更多的消息给该联系人的纯JID 该联系人的客户端应该把它的应答的地址指向该用户的全JID user domainpart resourcepart 即初始消息中提供的 from 地址 一旦该用户的客户端从该联系人的全JID收到一个应答 它应该把它随后的消息指向该联系人的全JID 即在该联系人的应答中提供的 from 地址 从而 锁定 在那个全JID 一个客户端应该在接收到一个来自对方节点控制的任何其他资源的 message 或 presence 节 或一个来自已锁定的资源的出席信息节 的时候 解除锁定 结果是 它应该在聊天会话的下一个消息中指向对方节点的纯JID 从而 解锁 之前的 锁定 直到它从对方的全JIDs收到一个消息 当双方参加一个一个聊天会话但是没有基于一个出席信息订阅来互相分享出席信息 他们应该互相发送定向出席信息 这样双方能很容易地查询对方在该聊天会话期间是否下线 然而 一个客户端必须提供一个方法让一个用户能全局地禁止或只允许特定的实体进行这类出席信息分享 更进一步的 当出于某种原因相信该聊天会话结束了 例如 如果 在一段合理的时间之后 双方没有交换随后的消息 一方应该发送定向unavailable出席信息给另一方 聊天会话的例子参见 第7章 消息语法 以下章节描述 message 节的语法 To属性 即时消息客户端通过在 message 节中的 to 属性中提供预期的接收者的JID来为一个消息指定预期接收者 如果该消息在现有的聊天会话或已接收的消息的上下文之外被发送 to 地址的值的格式应该是 localpart domainpart 而不是 localpart domainpart resourcepart 见 5 1 message from juliet example com balcony id ktx72v49 to romeo example net type chat xml lang en body Art thou not Romeo and a Montague body message 如果该消息是作为对之前从格式 localpart domainpart resourcepart 收到的一个消息的应答来发送的 例如 在一个如 5 1 所述的一对一聊天会话的上下文中 该 to 地址的值的格式应该是 localpart domainpart resourcepart 而不是 localpart domainpart 除非发送者已经知道 例如 通过出席信息 接收者的资源不再可用 message from romeo example net orchard id sl3nx51f to juliet example com balcony type chat xml lang en body Neither fair saint if either thee dislike body message Type属性 在即时消息应用中消息节的常用的包括 单条消息 在一对一聊天会话的上下文中发送的消息 在一个多用户聊天室中发送的消息 警告 通知 或其他给不期望应答的人的信息 错误 这些用途通过 type 属性来区分 建议包含 type 属性 如果包含了它 type 属性必须是以下的值之一 chat 该消息在一个一对一聊天会话的上下文中被发送 典型的一个可交互的客户端将在一个界面上展示一个类型为 chat 的消息 这使得双方之间能够进行一对一聊天 同时包括一个适当的会话历史 关于一对一聊天会话的详细建议参见 5 1 error 该消息由一个从另一个实体接收到一个消息并在处理的时候发现了错误的实体生成 关于节错误语法的详情 参考 XMPP CORE 接收到一个类型为 error 的消息的客户端应该展示一个适当的界面来通知原始的发送者关于这个错误的类型 groupchat 该消息在一个多用户聊天环境的上下文中被发送 类似 IRC 典型的一个接收的客户端将在一个界面展示一个类型为 groupchat 的消息 这使得多方可以进行多对多的聊天 同时包含一个聊天室中的参与者的名册和适当的会话历史 关于基于XMPP的群聊的详细信息 参见 XEP 0045 headline 该消息提供一个警告 一个通知 或其他给那些不期望应答的人的临时信息 例如 新闻头条 运动更新 准实时的市场数据 或整合的内容 因为不期望对该消息的回复 典型的一个接收客户端将在一个界面展示一个类型为 headline 的消息以适当地把它们和独立消息 聊天消息 以及群聊消息区分开来 例如 不向该接收者提供应答能力 如果 to 地址是纯JID 该接收服务器应该递送该消息给该接收者的所有非负出席信息优先级的可用资源并且必须递送该消息给那些资源中的至少一个资源 如果该 to 地址是一个全JID并且有一个匹配的资源 该服务器必须递送该消息给那个资源 否则该服务器必须要么安静地忽略该消息要么返回一个错误 见 第8章 normal 该消息是一个在一对一聊天会话或群聊上下文之外的被发送的独立消息 并且它期望接收者应答 典型的一个接收客户端将在一个界面展示一个类型为 normal 的消息 这使得接收方能够应答 但没有会话历史 type 属性的缺省值是 normal 一个IM应用应该支持所有前述的消息类型 如果一个应用接收了一个没有 type 属性的消息或该应用不理解被提供的 type 属性的值 它必须认为该消息的类型为 normal 即 normal 是缺省的 不同消息类型的服务器处理指南参见 第8章 尽管 type 属性是可选的 出于礼貌在任何对一个消息的应答之中会镜像其类型 更进一步 一些专门的应用 例如 一个多用户聊天服务 可以基于他们的自主判断来强制使用特定消息类型 例如 type groupchat Body元素 body 元素包含自然人可读的XML字符数据以指定该消息的正文 这个子元素通常会被包含但是可选的 message from juliet example com balcony id b4vs9km4 to romeo example net type chat xml lang en body Wherefore art thou Romeo body message 没有为 body 元素定义属性 除了 xml lang 属性例外 在一个消息节中可以包括多个 body 元素实例用来为同一body提供替代版本 但是每个实例只允许拥有一个 xml lang 属性并且其值为一个唯一性的语言 要么显性的 要么从更高层次的XML继承 xml lang 值 从发送者角度看是包含在 XMPP CORE 所述的XML流头中 message from juliet example com balcony id z94nb37h to romeo example net type chat xml lang en body Wherefore art thou Romeo body body xml lang cs Pro x010D e x017D jsi ty Romeo body message body 元素不能 MUST NOT 包含混合内容 定义于 XML 的3 2 2节 Subject元素 subject 元素包含自然人可读的XM字符数据以指定该消息的标题 message from juliet example com balcony id c8xg3nf8 to romeo example net type chat xml lang en subject I implore you subject body Wherefore art thou Romeo body message 没有为 subject 元素定义属性 从 XML 继承的 xml lang 属性例外 可以包含多个 subject 元素实例以提供同意标题的替代版本 但是每个实例只允许拥有一个 xml lang 属性并且其值为一个唯一性的语言 要么显性的 要么从更高层次的XML继承 xml lang 值 从发送者角度看是包含在 XMPP CORE 所述的XML流头中 message from juliet example com balcony id jk3v47gw to romeo example net type chat xml lang en subject I implore you subject subject xml lang cs x00DA p x011B nliv x011B pros x00ED m subject body Wherefore art thou Romeo body body xml lang cs Pro x010D e x017E jsi ty Romeo body message subject 元素不能 MUST NOT 包含混合内容 定义于 XML 的3 2 2节 Thread元素 XMPP thread 元素主要用于唯一性地标识一个由类型为 chat 的 message 节实例化的两个实体之间的交谈线索或 聊天会话 然而 XMPP thread 元素也可以被用于唯一性地标识一个由类型为 headline 或 normal 的 message 节实例化的两个实体之间 或由类型为 groupchat 的 message 节实例化的在一个多用户聊天室上下文中的多个实体之间的类似线索 它也可用于和自然人无关的会话的 message 节 类似一个游戏会话或一个插件之间的互动 thread 元素不被用于标识个别的消息 只用于交谈或消息会话 thread 元素是可选的 因为 thread 元素标识了一个消息所属的特定交谈线索 一个消息节不能 MUST NOT 多个 thread 元素 thread 元素可以拥有一个 parent 属性以标识另一个线索 当前线索是那个线索的分支或子线索 该 parent 属性必须遵循 thread 元素本身的语法并且它的值必须和包含了该 parent 属性的那个 thread 元素的XML字符数据不同 实现备注 同时指定一个父线索和一个子线索的能力可能会因为重叠的线索而导致线索标识的冲突 例如 一个 thread 元素可能包含XML字符数据 foo 以及一个值为 bar 的 parent 属性 第二个 thread 元素可能包含XML字符数据 bar 和一个值为 baz 的 parent 属性 而第三个 thread 元素可能包含XML字符数据 baz 和一个值再次为 foo 的 parent 属性 如果处理这类重叠的线索标识之间的冲突取决于实现 例如 要么它将线索标识符 链在一起 在一个多级用户界面中把 foo 同时显示成 baz 的一个父线索和一个孙线索 要么它将在一次只显示依赖的一层 thread 元素的值不是自然人可读的且必须被实体当成不透明的来处理 从它那里不能获得语义 并且对它只能做精确比较 thread 元素的值必须唯一地标识该交谈线索 在交谈伙伴之间或更更广泛 一个确保唯一性的办法是生成一个 UUID 所述的全局唯一标识符 UUID 安全警告 一个生成ThreadID的应用必须确保它不会泄露关于这个实体的身份信息 例如 该XMPP应用正在运行的设备的MAC地址 thread 元素不能 MUST NOT 包含混合内容 定义于 XML 的3 2 2节 message from juliet example com balcony to romeo example net type chat xml lang en subject I implore you subject subject xml lang cs x00DA p x011B nliv x011B pros x00ED m subject body Wherefore art thou Romeo body body xml lang cs Pro x010D e x017E jsi ty Romeo body thread parent e0ffe42b28561960c6b12b944a092794b9683a38 0e3141cd80894871a68e6fe6b1ec56fa thread message 关于使用 thread 元素的详细建议 参考 XEP 0201 扩展内容 如 XMPP CORE 所述 一个XML节可以包含任何不同于缺省命名空间的命名空间所限定的子元素 这也适用于message节 处理扩展内容的指南参见 XMPP CORE 的8 4节中提供的路由服务器和最终接收者部分 在下面的例子中 该message节包含一个 XEP 0071 定义的该消息的XHTML格式版本 message from juliet example com balcony to romeo example net type chat xml lang en body Wherefore art thou Romeo body html xmlns http jabber org protocol xhtml im body xmlns http www w3 org 1999 xhtml p Wherefore span style font style italic art span thou span style color red Romeo span p body html message 交换IQ节 如 XMPP CORE 所述 IQ节提供一个结构化的 请求 应答 机制 那一机制的基本语法 例如 id 属性是强制性的 定义于 XMPP CORE 特定语法需要完成限定类型为 get 或 set 的IQ节的直接子元素的扩展命名空间的所有实例中定义的用例 jabber client 和 jabber server 命名空间不定义除了 error 元素之外的所有节类型的任何IQ节的子元素 本文定义一个这样的扩展命名空间 用于 管理名册 无论如何 IQ节可以包含由一个扩展命名空间限定的结构化的信息 示例会话 本节的例子展示一个可能的即时消息和出席信息会话 用户是 romeo example net 他有一个可用资源 其资源部分是 orchard 并且在他的名册中有以下人员 juliet example com 订阅状态 both 并且她有两个可用资源 chamber 和 balcony benvolio example net 订阅状态 to mercutio example org 订阅状态 from 首先 该用户完成如 XMPP CORE 所述的前提条件 流建立 TLS和SASL协商 以及资源绑定 那些协议流程在这里不复述了 接下来 该用户请求他的名册 示例1 用户向服务器请求当前名册 UC iq from romeo example net orchard id hf61v3n7 type get query xmlns jabber iq roster iq 示例2 用户从服务器接收到名册 US iq id hf61v3n7 to romeo example net orchard type result query xmlns jabber iq roster item jid juliet example com name Juliet subscription both group Friends group item item jid benvolio example org name Benvolio subscription to item jid mercutio example org name Mercutio subscription from query iq 现在该用户开始一个出席信息会话 示例3 用户发送初始出席信息 UC presence 示例4 用户的服务器代表该用户发送出席信息探测给订阅状态 to 和订阅状态 both 的联系人们 US presence from romeo example net to juliet example com type probe US presence from romeo example net to benvolio example org type probe 示例5 用户的服务器代表该用户的可用资源发送初始出席信息给订阅状态 from 和订阅状态 both 的联系人们 以及用户自己 US presence from romeo example net orchard to juliet example com US presence from romeo example net orchard to mercutio example org US presence from romeo example net orchard to romeo example net 示例6 联系人的服务器代表所有可用资源应答该出席信息探测 CS presence from juliet example com balcony to romeo example net xml lang en show away show status be right back status priority 0 priority presence CS presence from juliet example com chamber to romeo example net priority 1 priority presence CS presence from benvolio example org pda to romeo example net xml lang en show dnd show status gallivanting status presence 示例7 联系人的服务器们递送用户的初始出席信息给所有可用资源 CS presence from romeo example net orchard to juliet example com CS presence from romeo example net orchard to juliet example com CS presence from romeo example net orchard to mercutio example org 示例8 用户发送定向出席信息给另一个不在他的名册中的用户 UC presence from romeo example net orchard to nurse example com xml lang en show dnd show status courting Juliet status priority 0 priority presence 现在该用户和他的联系人之一进入一个聊天会话 示例9 一个带线索的交谈 CC message from juliet example com balcony to romeo example net type chat xml lang en body My ears have not yet drunk a hundred words body thread e0ffe42b28561960c6b12b944a092794b9683a38 thread message CC message from juliet example com balcony to romeo example net type chat xml lang en body Of that tongue s utterance yet I know the sound body thread e0ffe42b28561960c6b12b944a092794b9683a38 thread message CC message from juliet example com balcony to romeo example net type chat xml lang en body Art thou not Romeo and a Montague body thread e0ffe42b28561960c6b12b944a092794b9683a38 thread message UC message from romeo example net orchard to juliet example com balcony type chat xml lang en body Neither fair saint if either thee dislike body thread e0ffe42b28561960c6b12b944a092794b9683a38 thread message CC message from juliet example com balcony to romeo example net orchard type chat xml lang en body How cam st thou hither tell me and wherefore body thread e0ffe42b28561960c6b12b944a092794b9683a38 thread message 以此类推 该用户也能发送随后的出席信息广播 示例10 用户发送更新的可用信息用于广播 UC presence xml lang en show away show status I shall return status priority 1 priority presence 示例11 用户的服务器广播更新的出席信息给订阅类型为 both 或 from 的联系人 但是不包括该用户向其发送过定向出席信息的实体 US presence from romeo example net orchard to juliet example com xml lang en show away show status I shall return status priority 1 priority presence US presence from romeo example net orchard to mercutio example org xml lang en show away show status I shall return status priority 1 priority presence 示例12 联系人们的服务器递送更新的出席信息 CS presence from romeo example net orchard to juliet example com xml lang en show away show status I shall return status priority 1 priority presence CS presence from romeo example net orchard to juliet example com xml lang en show away show status I shall return status priority 1 priority presence CS presence from romeo example net orchard to mercutio example org xml lang en show away show status I shall return status priority 1 priority presence 示例13 联系人们的可用资源之一广播不可用 离线 通知 CC presence from juliet example com chamber type unavailable 示例14 联系人的服务器发送不可用 离线 通知给用户 CS presence from juliet example com chamber to romeo example net type unavailable 现在该用户结束他的出席信息会话 示例15 用户发送不可用 离线 通知 UC presence type unavailable xml lang en status gone home status presence 示例16 用户的服务器广播离线通知给联系人们以及该用户曾经发送过定向出席信息的那个实体 US presence from romeo example net orchard to juliet example com type unavailable xml lang en status gone home status presence US presence from romeo example net orchard to mercutio example org type unavailable xml lang en status gone home status presence US presence from romeo example net orchard to nurse example com type unavailable xml lang en status gone home status presence 最后该用户关闭他的流并且他的服务器以同样方式应答 示例17 用户关闭流 UC stream stream 示例18 用户的服务器关闭流 US stream stream 结束 处理XML节的服务器规则 处理XML节的基本服务器规则定义于 XMPP CORE 读者可以参考那个协议的基础规则和安全含义 本章定义用于XMPP即时消息和出席信息服务器的附加规则 本章定义的一些递送规则指定了 离线存储 的使用 即 该服务器代表该用户存储一个消息节的行为以及当该用户下次上线的时候递送它 关于离线消息存储的建议 参考 XEP 0160 常规事项 XMPP CORE 讨论了节递送的常规事项 特别是在 i 提供一个关于节递送的服务的可接受级别 和 ii 防止目录捕获攻击和出席信息泄露 之间的平衡 无论如何 目录捕获攻击的概念不适用于一个已知并被一个用户信任的联系人 因为如 第2章 所述该联系人在该用户的名册中 类似的 出席信息泄露的概念不适用于一个已被授权知道一个用户的出席信息的联系人 通过 第3章 所述的所谓出席信息订阅 或该用户曾经自发的发送出席信息给它的那个实体 如 4 6 所述的的所谓定向出席信息 所以 下面章节的场景中用来防止目录捕获和出席信息泄露的替代方式有 a 安静地忽略一个节 或 b 返回一个错误 如果发起的实体在该用户的名册 当该错误将泄露该用户的帐号是否存在 或被授权从该用户接收出席信息 或已经从该用户接收到定向出席信息 当该错误将泄露一个用户的资源的出席信息 服务器应该返回一个错误 安全事项 接下来描述的所有节处理规则的定义 要理解它们将的应用 将遵循相关的隐私和安全行策略的强制检查 类似那些 XEP 0016 或 XEP 0191 的部署 接下来的章节中的一致性语言 MUST SHOULD 等等 不意味着覆盖任何本地服务策略 无 to 地址 如果该节无 to 属性 适用规则定义于 XMPP CORE 远端域 如果包含在一个出站节的 to 属性中的地址的域部分和该服务器本身配置的域不匹配 则适用的规则见于 XMPP CORE 的10 4节 互操作性备注 RFC 3921 定义了如何使用 im xmpp 和 pres xmpp SRV记录 IMP SRV 作为一个应急方法来查询是否一个远端的即时消息和出席信息服务能通过以XMPP通讯 因为那些SRV记录未被广泛部署 本文不再定义它们的使用 并且不鼓励新的实现 本地域 如果在 to 属性中包含的JID的域部分和该服务器配置的域之一匹配 该域由该服务器本身 而不是由一个特别的本地服务 提供服务 并且该JID的格式为 domainpart 或 domainpart resourcepart 适用规则定义于 XMPP CORE 本地用户 如果 to 地址指定了一个纯JID localpart domainpart 或全JID localpart domainpart resourcepart 该JID的域部分和由该服务器本身提供服务的已配置的域匹配 该服务器必需做如下处理 无该用户 如果由 to 属性而来的该用户帐号标识符不存在 该节如何处理取决于节类型 对于一个IQ节 该服务器必须返回一个 service unavailable 节错误给该发送者 对于一个message节 该服务器必需要么 a 安静地忽略该消息 要么 b 返回一个 service unavailable 节错误给该发送者 对于一个不带 type 属性或 type 属性为 unavailable 的的presence节 该服务器必须安静地忽略该节 对于一个类型为 subscribe subscribed unsubscribe 或 unsubscribed 的presence节 该服务器必须安静地忽略该节 对于一个类型为 probe 的presence节 该服务器必需要么 a 安静地忽略该节 要么 b 返回一个类型为 unsubscribed 的presence节 本地部分 域部分 如果 to 属性中包含的JID的格式为 localpart domainpart 那么该服务器必需遵循以下规则 可用或已连接的资源 如果至少有一个可用资源或已连接资源 如何处理该节取决于该节的类型 Message 对于一个类型为 normal 的消息节 如果所有可用资源有一个负的出席信息优先级 那么该服务器应该要么 a 存储该消息为离线用于晚些时候递送 要么 b 返回一个节错误给该发送者 该错误应该是 service unavailable 如果有一个可用资源而它是非负的出席信息优先级 那么该服务器必须递送该消息给那个资源 如果有多个可用资源都有非负的出席信息优先级 那么该服务器必须要么 a 递送该消息给 最可用的 资源或资源们 根据服务器的实现特有的机制 例如 认为拥有最高出席信息优先级的资源或资源们是 最可用的 要么 b 递送该消息给所有非负的资源 对于一个类型为 chat 的消息节 如果这个唯一的可用资源有一个负的出席信息优先级 那么该服务器应该要么 a 存储该消息为离线用于晚些时候递送 要么 b 返回一个节错误给该发送者 该错误应该是 service unavailable 如果这个唯一的可用资源有一个非负的出席信息优先级 那么该服务器必须递送该消息给那个资源 如果有多个可用资源都有非负的出席信息优先级 那么该服务器必须要么 a 递送该消息给 最可用的 资源或资源们 根据服务器的实现特有的机制 例如 认为拥有最高出席信息优先级的资源或资源们是 最可用的 要么 b 递送该消息给所有曾经被选择接收了聊天消息的非负的资源 对于类型为 groupchat 的消息节 该服务器不能 MUST NOT 递送该节给任何可用资源 而必须返回一个节错误给该发送者 该错误应该是 service unavailable 对于一个类型为 headline 的消息节 如果这个唯一的可用资源有一个负的出席信息优先级 那么该服务器必须安静地忽略该节 如果这个唯一的可用资源有一个非负的出席信息优先级 那么该服务器必须递送该消息给那个资源 如果有多个可用资源都有非负的出席信息优先级 那么该服务器必须递送该消息给所有非负的资源 对于类型为 error 的消息节 该服务器必须安静地忽略该消息 无论如何 对于任何消息类型 该服务器不能 MUST NOT 递送该节给任何负优先级的可用资源 如果只有一个可用资源且优先级为负 该服务器应该如 8 5 2 2 所述 视同没有可用资源或已连接资源那样处理该消息 在所有情况下 该服务器不能 MUST NOT 重写 to 属性 即 它必须让它就是 localpart domainpart 而不是把它改成 localpart domainpart resourcepart Presence 对于一个没有类型或类型为 unavailable 的出席信息节 该服务器必须递送它到所有可用资源 对于一个类型为 subscribe subscribed unsubscribe 或 unsubscribed 的出席信息节 该服务器必须遵循 第3章 定义的规则和 附录A 的总结 对于一个类型为 probe 的出席信息节 该服务器必须如 4 3 所述直接处理它 在所有情况下 该服务器不能 MUST NOT 重写 to 属性 即 它必须让它就是 localpart domainpart 而不是把它改成 localpart domainpart resourcepart IQ 对于一个IQ节 该服务器本身必须代表该用户应答一个IQ result 或一个IQ error 并且不能 MUST NOT 递送该IQ节给该用户的任何可用资源 特别是 如果限定的命名空间的语义定义了一个该服务器能代表该用户提供应答 那么该服务器必须代表该用户应答该节 要么返回一个类型为 result 的IQ节要么是一个类型为 error 的适合原始载荷的IQ节 否则 该服务器必须应答一个 service unavailable 节错误 无可用或已连接的资源 如果没有可用资源或已连接资源 如何处理该节取决于该节的类型 Message 对于一个类型为 normal 或 chat 的消息节 该服务器应该要么 a 添加该消息到离线存储 要么 b 返回一个节错误给该发送者 该错误应该为 service unavailable 对于一个类型为 groupchat 的消息节 该服务器必须返回一个节错误给该发送者 该错误应该为 service unavailable 对于一个类型为 headline 或 error 的消息节 该服务器必须安静地忽略该消息 Presence 对于一个没有类型或类型为 unavailable 的出席信息节 该服务器应该安静地忽略该节 不把它存下来用于晚些时候递送 也不代表该用户应答它 对于一个类型为 subscribe subscribed unsubscribe 或 unsubscribed 的出席信息节 该服务器必须遵循 第3章 定义的规则和 附录A 的总结 对于一个类型为 probe 的出席信息节 该服务器必须如 4 3 所述直接处理它 IQ 对于一个IQ节 该服务器本身必须代表该用户应答一个IQ result 或一个IQ error 并且不能 MUST NOT 递送该IQ节给该用户的任何可用资源 特别是 如果限定的命名空间的语义定义了一个该服务器能代表该用户提供应答 那么该服务器必须代表该用户应答该节 要么返回一个类型为 result 的IQ节要么是一个类型为 error 的适合原始载荷的IQ节 否则 该服务器必须应答一个 service unavailable 节错误 本地部分 域部分 资源部分 如果一个入站节的 to 属性中包含的JID的域部分和该服务器本身配置的域之一匹配并且包含在 to 属性中的JID的格式为 localpart domainpart resourcepart 那么该服务器必须遵循以下规则 资源匹配 如果一个可用的资源或已连接的资源准确地匹配该全JID 如何处理该节取决于该节的类型 对于一个类型为 get 或 set 的IQ节 如果预期的接收者未通过类型为 both 或 from 的所谓出席信息订阅或通过所谓定向出席信息来分享出席信息给请求实体 那么该服务器不应该 SHOULD NOT 递送该IQ节 而应该返回一个 service unavailable 节错误给请求实体 这个策略帮助防止出席信息泄漏 见 第11章 对于一个类型为 result 或 error 的IQ节 该服务器必须递送该节给该资源 对于一个消息节 该服务器必须递送该节给该资源 对于一个没有 type 属性或 type 属性为 unavailable 的出席信息节 该服务器必须递送该节给该资源 对于一个类型为 subscribe subscribed unsubscribe 或 unsubscribed 的出席信息节 该服务器必须遵循 第3章 提供的指南 对于一个类型为 probe 的出席信息节 该服务器必需跟随 4 3 提供的指南 无资源匹配 如果没有可用资源或已连接的资源准确匹配该全JID 如何处理该节取决于该节的类型 Message 对于一个类型为 normal groupchat 或 headline 的消息节 该服务器必须要么 a 安静地忽略该节 要么 b 返回一个错误节给该发送者 该节错误应该是 service unavailable 对于一个类型为 chat 的消息节 如果没有可用或已连接的资源 该服务器必须要么 a 存储该消息到离线用于晚些时候递送 要么 b 返回一个错误节给该发送者 该节错误应该是 service unavailable 如果所有可用资源都有一个负的出席信息优先级那么该服务器应该 a 存储该消息到离线用于晚些时候递送 或 b 返回一个错误节给该发送者

    Original URL path: http://wiki.jabbercn.org/index.php?title=RFC6121&oldid=3578 (2016-04-25)
    Open archived version from archive

  • 查看源代码 - Jabber/XMPP中文翻译计划
    如果潜在的联系人位于和该用户相同的服务器上 那么在处理该订阅请求和递送它到本地联系人的时候该服务器必须遵循 RFC6121 入站订阅信息请求的服务器处理 章节3 1 3 定义的规则 如果潜在的联系人位于一个远端服务器 受本地服务策略的约束该用户的服务器必须接着按照核心XMPP节处理规则路由该节到那个远端的域 这可能导致返回一个适当的节错误给该用户 类似 remote server timeout 如上所述 在本地递送或远程路由该出席信息订阅请求之前 该用户的服务器必须给该出站订阅请求标记该用户的纯JID user domainpart source lang xml US presence from romeo example net id xk3h1v69 to juliet example com type subscribe source 如果该出席信息订阅请求不是本地递送或远程路由的 例如 因为该请求格式异常 该本地联系人不存在 该远程服务器不存在 尝试联系远端服务器超时 或任何被该用户的服务器经历或确认的其他错误 那么该用户的服务器必须返回一个适当的错误节给该用户 例子如下 source lang xml US presence from juliet example com id xk3h1v69 to romeo example net type error error type modify remote server not found xmlns urn ietf params xml ns xmpp stanzas error presence source 在本地递送或远程路由该出席信息订阅请求之后 该用户的服务器必须接着发送一个roster push给所有该用户的感兴趣的资源 包含带一个 none 订阅状态并且带一个表明订阅等待批准符号 一个值为 subscribe 的 ask 属性 的潜在联系人 source lang xml US iq id b89c5r7ib574 to romeo example net foo type set query xmlns jabber iq roster item ask subscribe jid juliet example com subscription none query iq US iq id b89c5r7ib575 to romeo example net bar type set query xmlns jabber iq roster item ask subscribe jid juliet example com subscription none query iq source 如果一个远端联系人在可配置的时间内不批准或拒绝该订阅请求 该用户的服务器应该基于一个实现特有的机制重新发送该订阅请求给该联系人 例如 任何该用户的一个新资源可用的时候 或在过了一个特定数量的时间之后 这有助于从原有的订阅请求被路由到远程域发生的短暂的 无声的错误中恢复 这样做的时候 建议该服务器包含一个 id 属性 这样它能跟踪重发的订阅请求的应答 服务器处理入站订阅请求 在处理入站出席信息订阅请求之前 联系人的服务器应该检查包含在 to 属性中的JID的语法 如果该JID的格式是 contact domainpart resourcepart 而不是 contact domainpart 该联系人的服务器应该把该请求当成是被指向该联系人的纯JID并据此修改 to 地址 该服务器也可以遵循 RFC6121 参考文献 XMPP ADDR 定义的格式来检查该JID地址并可能返回一个 jid malformed 节错误 处理入站出席信息订阅请求的时候 联系人的服务器必须遵循以下规则 1 首先 联系人的服务器不能 MUST NOT 以联系人的身份批准订阅请求 除非该来联系人已经 a 如 RFC6121 预批准被订阅请求 章节3 4 所述预批准来自用户的订阅请求 b 配置它的账户自动批准订阅请求 或 c 从它的服务器提供者那里接受了一个协议以允许自动批准 例如 在一个企业部署之中通过一个雇佣协议 否则 如果一个订阅请求要求批准那么联系人的服务器必须递送那个请求到联系人的可用资源并由该联系人批准或拒绝 2 如果联系人存在并且该用户已经有一个对该联系人的出席信息的订阅 那么该联系人的服务器必须把一个类型为 subscribed 的presence节从该联系人的纯JID发送到该用户的纯JID以代表该联系人自动应答 同样 如果该联系人以前发送过一个类型为 subscribed 的presence节并且联系人的服务器假设对于该用户的出席信息订阅是 预批准的 见 RFC6121 预批准被订阅请求 章节3 4 那么该联系人的服务器也应该以该联系人的身份自动应答 source lang xml CS presence from juliet example com id xk3h1v69 to romeo example net type subscribed source 3 另外 如果在订阅请求被联系人的服务器接收到的时候该联系人有至少一个可用的资源 那么该联系人的服务器必须依据 RFC6121 处理XML节的服务器规则 第八章 发送那个订阅请求给所有可用的资源 作为获得该出席信息订阅请求的回执的一个方法 该联系人的服务器可以从该联系人的纯JID发送一个类型为 unavailable 的presence节到该用户的纯JID 该用户的客户端不能 MUST NOT 假定这个回执提供了关于该联系人的出席信息 因为它来自该联系人的纯JID并且在该订阅请求被批准之前就收到了 4 另外 如果在订阅请求被联系人的服务器接收到的时候该联系人没有可用的资源 那么该联系人的服务器必须保持一个完整的包括该订阅请求的presence节的记录 包括其中任何扩展的内容 见 RFC6121 规范引用 XMPP CORE 的章节8 4 并且在该联系人接下来有一个可用的资源的时候递送该请求 无论何时该联系人建立了一个可用的资源该联系人的服务器必须继续递送该订阅请求 直到该联系人要么批准要么拒绝该请求 当该联系人接下来有一个可用的资源的时候 该联系人的服务器不能 MUST NOT 从任何给定用户递送多个订阅请求 例如 如果该用户发送多个订阅请求到该联系人而此时该联系人是离线的 该联系人的服务器应该只存储那些请求中的一个 比如第一个请求或最后一个请求 并且当该联系人接下来有一个可用资源的时候必须只递送这些请求中的一个 这有助于防止 垃圾订阅请求 安全警告 直到以及除非该联系人如 RFC6121 客户端处理入站订阅请求 章节3 1 4 所述批准该订阅请求 该联系人的服务器不能 MUST NOT 在该联系人的名册上添加该用户的条目 安全警告 对于联系人的服务器存储完整的出席信息订阅请求的节的强制要求带来了一个应用程序资源衰竭攻击的可能性 见 RFC6121 参考文献 DOS 的章节2 1 2 例如 由一个流氓服务器或一个协调好的用户群 例如 一个 botnet 攻击该联系人的服务器或特定联系人 提醒服务器实现者们关注这类攻击的可能性并为对抗它提供工具 比如允许服务管理员设置服务器整体或任何给定联系人存储的入站出席信息订阅请求的数量或大小的限制 客户端处理入站订阅请求 当一个可交互的客户端接收到一个订阅请求 它必须把该请求展示给控制该客户端的自然人 即 该 联系人 来批准 除非该联系人被显式地配置成该客户端自动批准或拒绝如上所述的某些或全部订阅请求 一个不是被自然人控制的自动客户端将有自己的应用特有的规则以批准或拒绝订阅请求 客户端通过发送一个类型为 subscribed 的presence节来批准一个订阅请求 联系人的服务器会作 RFC6121 服务器处理出站订阅批准 章节3 1 5 所述的处理 用户的服务器会作 RFC6121 服务器处理入站订阅批准 章节3 1 6 所述的处理 source lang xml CC presence id h4v1c4kj to romeo example net type subscribed source 客户端通过发送一个类型为 unsubscribed 的presence节来拒绝一个订阅请求 联系人的服务器和用户的服务器都会作 RFC6121撤销被订阅 章节3 2 所述的处理 source lang xml CC presence id tb2m1b59 to romeo example net type unsubscribed source 为了跟踪的目的 客户端应该在一个订阅批准或订阅拒绝中包含一个 id 属性 这个 id 属性不能 MUST NOT 镜像该订阅请求的 id 属性 服务器处理出站订阅批准 当联系人的客户端发送订阅批准的时候 联系人的服务器必须以联系人的纯JID contact domainpart 标记这个出站的节并本地递送或远程路由该节到用户那里 source lang xml CS presence from juliet example com id h4v1c4kj to romeo example net type subscribed source 联系人的服务器接着必须发送一个updated roster push 更新名册推送 给所有联系人的感兴趣的资源 其中的 subscription 属性值设为 from 这里假定该联系人未曾订阅该用户 如果是那种情况 译者注 即该联系人已经订阅该用户 则 subscription 属性值将设置为 both 如 RFC6121 附录A 订阅状态 附录A 所述 source lang xml CS iq id a78b4q6ha463 to juliet example com balcony type set query xmlns jabber iq roster item jid romeo example net subscription from query iq CS iq id x81g3bdy4n19 to juliet example com chamber type set query xmlns jabber iq roster item jid romeo example net subscription from query iq source 从联系人的视角来看 现在存在一个来自用户的订阅 这就是为什么 subscription 属性值要设为 from 这里假定该联系人未曾订阅该用户 如果是那种情况 译者注 即该联系人已经订阅该用户 则 subscription 属性值将设置为 both 如 RFC6121 附录A 订阅状态 附录A 所述 该联系人的服务器接着也必须从该联系人的可用资源发送当前的出席信息给给该用户 source lang xml CS presence from juliet example com balcony id pw72bc5j to romeo example net CS presence from juliet example com chamber id ux31da4q to romeo example net source 为了订阅该用户的出席信息 该联系人需要发送一个订阅请求给该用户 XMPP客户端经常会自动发送订阅请求而不是要求联系人发起这个订阅请求 因为假定期望的结束状态是一个双向订阅 自然 当该联系人发送一个订阅请求给该用户 这个订阅状态将不同于前面示例中展示的状态 见 RFC6121 附录A 订阅状态 附录A 并且角色将被反转 服务器处理入站订阅批准 当用户的服务器收到一个订阅批准 它必须首先检查是否该联系人在该用户的名册中并且 subscription none 或 subscription from 以及 ask 标记设为 subscribe 即 订阅状态为 None Pending Out None Pending Out In 或 From Pending Out 见 RFC6121 附录A 订阅状态 附录A 如果这个检查成功了 那么该用户的服务器必须 1 递送入站订阅批准到该用户的所有感兴趣的资源 这有助于给该用户的客户端关于订阅批准的正确的上下文 使得它们能分辨由该用户的另一个资源生成的名册推送和从联系人收到的订阅批准的不同 这一步必须在下一步的发送名册推送之前去做 source lang xml US presence from juliet example com id h4v1c4kj to romeo example net type subscribed source 2 发起一个roster push给该用户的所有感兴趣的资源 包含一个该 联系人的更新的名册条目 其 subscription 属性值设为 to 如果订阅状态是 None Pending Out 或 None Pending Out In 或 both 如果订阅状态是 From Pending Out source lang xml US iq id b89c5r7ib576 to romeo example net foo type set query xmlns jabber iq roster item jid juliet example com subscription to query iq US iq id b89c5r7ib577 to romeo example net bar type set query xmlns jabber iq roster item jid juliet example com subscription to query iq source 3 该用户的服务器也必须把从该联系人的每个可用资源收到的可用的出席信息节递送给该用户的每个可用资源 source lang xml to resource1 US presence from juliet example com balcony id pw72bc5j to romeo example net to resource2 US presence from juliet example com balcony id pw72bc5j to romeo example net to resource1 US presence from juliet example com chamber id ux31da4q to romeo example net to resource2 US presence from juliet example com chamber id ux31da4q to romeo example net source 实现备注 如果在收到入站订阅批准通知的时候该用户的帐号没有可用资源 该用户的服务器可以保持该通知的记录 理想的是完整的出席信息节 并且等到该帐号有一个可用资源的时候再递送给它 这一行为向用户提供了当用户离线的时候发生名册变更的原因的更完整的信息 另外 就是 如果该用户不存在 如果该联系人不在该用户的名册中 或如果该联系人在该用户的名册中但是订阅状态不在前述的检查中描述的情况之中 那么该用户的服务器必须安静地忽略该订阅批准通知而不递送给该用户 也不修改该用户的名册 也不生成名册推送到该用户的感兴趣的资源 从该用户的角度来看 现在存在一个到该联系人的出席信息的订阅 这就是为什么 subscription 属性值要设为 to 撤销被订阅 客户端生成撤销被订阅 如果一个联系人想撤销它之前接受某个用户订阅的授权 以撤销一个预批准的被订阅 RFC6121 预批准被订阅请求 章节3 4 或拒绝一个订阅请求 它发送一个类型为 unsubscribed 的出席信息节 source lang xml CC presence id ij5b1v7g to romeo example net type unsubscribed source 服务器处理出站被订阅撤销 在接收到出站被订阅撤销之后 该联系人的服务器必须做如下处理 如果该用户的纯JID还不在该联系人的名册或在联系人名册中的状态是 None None Pending Out 或 To 该联系人的服务器不能 SHOULD NOT 路由或递送类型为 unsubscribed 的出席信息节给该用户 并且不能 MUST NOT 发送接下来所说的类型为 unavailable 的出席信息通知给该用户 如果该用户的纯JID在该联系人的名册的状态为 None None Pending Out 或 To 并且 approved 标记被设为 true 所以代表了 RFC6121 预批准被订阅请求 章节3 4 所述的订阅预批准 该联系人的服务器必须移除该 预批准 并且不能 MUST NOT 路由或递送类型为 unsubscribed 的出席信息节给该用户 否则 按如下的示例 该联系人的服务器必须同时路由或递送类型为 unavailable 的出席信息通知和类型为 unsubscribed 的出席信息节给该用户 并且必须发送一个名册推送给该联系人 因为该用户仍然订阅了该联系人的出席信息 即 在该联系人的服务器路由或递送类型为 unsubscribed 的出席信息给该用户之前 该联系人的服务器必须从该联系人的所有在线资源发送一个类型为 unavailable 的出席信息节给该用户 source lang xml CS presence from juliet example com balcony id i8bsg3h3 type unavailable CS presence from juliet example com chamber id bvx2c9mk type unavailable source 然后该联系人的服务器必须路由或递送类型为 unsubscribed 的出席信息节给该用户 确保在出站被订阅取消要带上该联系人的纯JID contact domainpart source lang xml CS presence from juliet example com id ij5b1v7g to romeo example net type unsubscribed source 该联系人从的服务器必须发送一个带有更新的名册条目的名册推送给该联系人的所有感兴趣的资源 这里订阅状态现在要么是 none 要么是 to 见 RFC6121 附录A 订阅状态 附录A source lang xml CS iq id pw3f2v175b34 to juliet example com balcony type set query xmlns jabber iq roster item jid romeo example net subscription none query iq CS iq id zu2y3f571v35 to juliet example com chamber type set query xmlns jabber iq roster item jid romeo example net subscription none query iq source 服务器处理入站被订阅撤销 当用户的服务器接收到入站被订阅撤销后 它必须首先检查该联系人是否在该用户的名册中并且 subscription to 或 subscription both 见 RFC6121 附录A 订阅状态 附录A 如果这个检查成功了 那么该服务器必须 1 递送该入站被订阅撤销到该用户的所有感兴趣的资源 这有助于给该用户的客户端正确的关于订阅被撤销的上下文 使得它们能区分由用户的另一个资源产生的名册推送和从该联系人收到的订阅被撤销 这个动作必须在发送下一步所述的名册推送之前进行 source lang xml US presence from juliet example com id ij5b1v7g to romeo example net type unsubscribed source 2 发起一个名册推送给该用户的所有感兴趣的资源 包含一个该联系人的更新的名册条目 其 subscription 属性值设为 none 如果之前的订阅状态为 To 或 To Pending In 或 from 如果订阅状态为 Both source lang xml US iq id h37h3u1bv400 to romeo example net foo type set query xmlns jabber iq roster item jid juliet example com subscription none query iq US iq id h37h3u1bv401 to romeo example net bar type set query xmlns jabber iq roster item jid juliet example com subscription none query iq source 该用户的服务器也必须递送类型为 unavailable 的入站出席信息节 实现备注 如果收到该入站被撤销订阅通知的时候 该用户的帐号没有可用的资源 该用户的服务器可以保持一个通知记录 理想的情况是完整的出席信息节 然后在该帐号下次有可用资源的时候递送该通知 这一行为把该用户离线期间发生的名册变更的原因提供了更完整的信号给该用户 另外 就是 如果该用户不存在 如果该联系人不在该用户的名册中 或如果该联系人在该用户的名册中的订阅状态不是前述检查所描述的那些状态 那么该用户的服务器必须安静地忽略该被取消订阅通知而不把它递送给该用户 也不修改该用户的名册 以及不生成名册推送给该用户的感兴趣的资源 取消订阅 客户端生成取消订阅 如果一个用户想取消订阅一个联系人的出席信息 它发送一个类型为 unsubscribe 的出席信息节 source lang xml UC presence id ul4bs71n to juliet example com type unsubscribe source 服务器处理出站取消订阅 在接收到出站取消订阅之后 该用户的服务器必须做如下处理 如果联系人和该用户在同一台服务器上 那么当该服务器处理订阅请求时必须遵循 RFC6121 服务器处理入站取消订阅 3 3 3 定义的规则 如果联系人位于远端服务器上 按照本地服务策略 该用户的服务器必须接着把该节路由到那个远端域以满足核心XMPP节处理规则 这可能导致返回适当的节错误给该用户 类似 remote server timeout 如前所述 在本地递送或远程路由取消订阅之前 该用户的服务器必须在该节上标记该用户的纯JID user domainpart source lang xml US presence from romeo example net id ul4bs71n to juliet example com type unsubscribe source 该用户的服务器接着必须发送一个带有更新的名册条目的名册推送给该用户的所有感兴趣的资源 这里的订阅状态就变成要么是 none 要么是 from 见 RFC6121 附录 A 订阅状态 附录A source lang xml US iq id h37h3u1bv402 to romeo example net foo type set query xmlns jabber iq roster item jid juliet example com subscription none query iq US iq to romeo example net bar type set id h37h3u1bv403 query xmlns jabber iq roster item jid juliet example com subscription none query iq source 服务器处理入站取消订阅 当联系人的服务器收到取消订阅通知 它必须首先检查该用户的纯JID是否在该联系人的名册中且subscription from 或subscription both 即 订阅状态为 From From Pending Out 或 Both 见 RFC6121 附录 A 订阅状态 附录A 如果这个检查成功了 接着该联系人的服务器必须 1 把入站取消订阅递送给该联系人的所有感兴趣的资源 这有助于向联系人的客户端们提供关于取消订阅的正确的上下文 这样它们就能区分是由联系人的另一个资源产生的名册推送还是从该用户收到的取消订阅 这个动作必须发生在下面所说的发送名册推送步骤之前 source lang xml CS presence from romeo example net id ul4bs71n to juliet example com type unsubscribe source 2 发起一个名册推送给该联系人的所有感兴趣的资源 为该用户包含一个更新的条目并把 subscription 属性值设为 none 如果之前的订阅状态是 From 或 From Pending Out 或 to 如果之前的订阅状态是 Both source lang xml CS iq id tn2b5893g1s4 to juliet example com balcony type set query xmlns jabber iq roster item jid romeo example net subscription none query iq CS iq id sp3b56n27hrp to juliet example com chamber type set query xmlns jabber iq roster item jid romeo example net subscription none query iq source 3 从该联系人的每一个可用资源生成一个类型为 unavailable 的出站出席信息节给该用户 source lang xml CS presence from juliet example com balcony id o5v91w49 to romeo example net type unavailable CS presence from juliet example com chamber id n6b1c37k to romeo example net type unavailable source 实现备注 如果在收到入站取消订阅通知的时候该联系人的帐号没有可用资源 该联系人的服务器可以保持一个通知记录 理想情况下是完整的出席信息节 并且接着在该帐号下次有一个可用资源的时候递送该通知 这一行为为该用户提供了关于该用户离线时发生的名册变更的更完整的信息 另外 就是 如果该联系人不存在 如果该用户不在该联系人的名册中 或如果该用户的纯JID在该联系人的名册中并且订阅状态不同于前面检查所述的结果 那么该联系人的服务器必须安静地忽略该取消订阅节 不递送给该联系人 不修改联系人的名册 也不生成名册推送给该联系人的所有感兴趣的资源 无论如何 如果该联系人的服务器持续跟踪一个从该用户到该联系人的入站出席信息订阅请求但是该用户仍不在该联系人的名册中 功能上相当于一个订阅状态 None Pending In 这里该联系人从未添加该用户到联系人的名册中 那么该联系人的服务器必须简单地移除该入站出新信息订阅请求的记录 它无法从该联系人的名册中移除该用户 因为该用户从未被加入到该联系人的名册中 实现备注 该用户的客户端不能 MUST NOT 依赖于从该联系人收到的取消订阅出席信息通知 因为它必须考虑对该联系人的出席信息订阅 以及关于该联系人的出席信息 当它发送类型为 unsubscribe 的出席信息节或它收到由取消订阅请求触发的名册推送的时候为无或空 预批准被订阅请求 如果一个用户还未从一个联系人那里接收到订阅请求 该用户可以 预批准 这样一个请求 这样它将被该用户的服务器自动地批准 对订阅预批准的支持在客户端和服务器上都是可选的 如果一个服务器支持订阅预批准 那么它必须在流协商时声明以下流特性 source lang xml sub xmlns urn xmpp features pre approval source 订阅预批准流特性只不过有一点用 所以永远不会强制协商 客户端生成被订阅预批准 如果客户端所连接的服务器声明了订阅预批准 该客户端可以通过发送一个类型为 subscribed 的节给该联系人以生成一个订阅预批准 source lang xml UC presence id pg81vx64 to juliet example com type subscribed source 如果该服务器未声明支持订阅预批准 该客户端不能 MUST NOT 尝试预批准来自潜在的或者实际的联系人的订阅请求 服务器处理被订阅预批准 在接收到类型为 subscribed 的出席信息节之后 该用户的服务器如果支持订阅预批准 必须做如下处理 如果该联系人在该用户的名册中且状态为 Both From 或 From Pending Out 该用户的服务器必须安静地忽略该节 如果该联系人在该用户的名册中且状态为 To Pending In None Pending In 或 None Pending Out In 该用户的服务器必须如普通的订阅批准那样处理该节 见 RFC6121 服务器处理出站订阅批准 3 1 5 更新现有的名册条目的状态成为 Both From 或 From Pending Out 分别的 推送修改的名册条目到该用户的所有感兴趣的资源 并路由该类型为 subscribed 的出席信息节到该联系人 如果该联系人在该用户的名册中且状态为 To None 或 None Pending Out 该用户的服务器必须把 approved 标记的值设置为 true 来记录订阅预批准 然后推送修改的名册条目到该用户的所有感兴趣的资源 无论如何 该用户的服务器不能 MUST NOT 路由该类型为 subscribed 的出席信息节到该联系人 如果该联系人还不在该用户的名册中 那么该用户的服务器必须为该联系人创建一个名册条目且状态为 None 并且把 approved 标记的值设为 true 然后推送该名册条目到该用户的所有感兴趣的资源 无论如何 该用户的服务器不能 MUST NOT 路由该类型为 subscribed 的出席信息节到该联系人 一个名册推送的示例如下 source lang xml US iq id h3bs81vs763f to romeo example net bar type set query xmlns jabber iq roster item approved true jid juliet example com subscription none query iq source 当 approved 标记被设为 true 该用户的服务器不能 MUST NOT 从该联系人递送一个类型为 subscribe 的出席信息节给该用户 而是必须代表该用户自动应答这样一个节 即从该用户的纯JID返回一个类型为 subscribed 的出席信息节给该联系人的纯JID 实现备注 服务器在已经从该联系人接收到了一个出席信息订阅请求之后是否维护一个订阅批准记录 对于实现或本地服务策略来说是个问题 如果该服务器不维护这样一个记录 在接收该订阅请求之后它将在该名册条目中不为该联系人包含 approved 属性 即 在随后的名册推送和名册结果中 如果该服务器维护这样一个记录 它将在名册条目中总是为该联系人包含 approved 属性 设为 true 直到或除非该用户发送一个类型为 unsubscribed 的出席信息节到该联系人 或从名册中完全移除该联系人 实现备注 客户端能通过发送一个类型为 unsubscribed 的出席信息节取消一个预批准 更全面的描述在 RFC6121 撤销被订阅 3 2 在这种情况下 该用户的服务器将发送一个名册推送给该有用户的所有感兴趣的资源 而其 approved 属性是被移除的 另一种选择是 该客户端能简单地完全移除该名册条目 交换出席信息 出席信息原理 出席信息是指在网络上通讯的一个实体的可用性 在最基本的层面上 出席信息是一个 on off 的逻辑变量以标记一个实体可不可以通讯 也用术语 在线 和 离线 在XMPP中 当客户端生成一个不带 type 属性的 presence 节时就标记了一个实体的可用性 当它的客户端生成一个 type 属性值为 unavailable 的 presence 节时表示一个实体失去了可用性 XMPP出席信息典型地遵循一个 发布 订阅 或 观察者 模式 这里 一个实体发送出席信息给它的服务器 它的服务器接着广播那个信息给所有订阅了该实体的出席信息的联系人 在 http xmpp org rfcs rfc6121 html IMP MODEL IMP MODEL 的术语中 一个生成出席信息的实体就是一个 presentity 并且那些接收出席信息的实体们是 subscribers 一个客户端通过发送一个不带 to 地址的出席信息节给它的服务器来生成出席信息用于广播给所有已订阅的实体们 这里的出席信息既没有 type 属性又没有值为 unavailable 的 type 属性 这种出席信息被称为 广播出席信息 一个客户端也可以发送 定向出席信息 即 一个带 to 地址的出席信息节 这不太常见但是有时被用于发送出席信息给那些没有订阅该用户的出席信息的实体们 见 RFC6121 定向出席信息 4 6 在一个客户端完成 RFC6121 规范引用 XMPP CORE 定义的先决条件之后 它能通过发送初始化出席信息在它的服务器建立一个 出席信息会话 通过发送unavailable出席信息可以中止这个出席信息会话 在它的出席信息会话期间 一个已连接的资源 RFC6121 规范引用 XMPP CORE 中的术语 被称为一个 可用的资源 在XMPP中 应用集合了消息和出席信息功能 它的出席信息标记的可用性的缺省通讯类型是消息 然而 对于XMPP应用来说把消息和出席信息功能集合到一起并不是必要的 它们能提供独立的不带消息的出席信息特性 另外 XMPP服务器们不会为了成功地路由message和IQ节而强制要求关于网络可用性的信息 提示备注 在接下来的例子中 用户是 juliet example com 她有两个可用的资源 balcony 和 chamber 而在她的名册中有三个联系人且订阅状态为 from 或 both romeo example net mercutio example com 和 benvolio example net 初始化出席信息 客户端生成初始化出席信息 在完成 RFC6121 规范引用 XMPP CORE 必需的 中所述的前提条件并请求名册 推荐的 之后 一个客户端通过发送 初始化出席信息 给它的服务器来标记它的通讯可用性 即 一个不带 to 地址 意思是由该服务器代表该客户端广播它 和 type 属性 表示该用户的可用性 的出席信息节 source lang xml UC presence source 该初始化出席信息可以包含 priority 元素 show 元素 一个一个或多个 status 元素实例 以及扩展内容 细节见 RFC6121 出席信息语法 4 7 服务器处理出站初始化出席信息 从一个客户端接收到初始化出席信息之后 该用户的服务器必须从该用户的全JID user domainpart resourcepart 发送该出席信息节给所有订阅了该用户的出席信息的联系人 这些联系人的JID目前正在该用户的名册中且 subscription 属性值为 from 或 both source lang xml US presence from juliet example com balcony to romeo example net US presence from juliet example com balcony to mercutio example com US presence from juliet example com balcony to benvolio example net source 该用户的服务器也必须从该用户的新的可用资源广播初始化出席信息给该用户的所有可用资源 包括在第一个地方生成该出席信息通知的那个资源 即 一个实体隐形地订阅了它自己的出席信息 source lang xml to the balcony resource US presence from juliet example com balcony to juliet example com to the chamber resource US presence from juliet example com balcony to juliet example com source 在缺少关于该用户的联系人的出席信息的情况下 该用户的服务器也必须代表该用户发送出席信息探测给该用户的联系人 如 RFC6121 出席信息探测 4 3 所述 服务器处理入站初始化出席信息 在从该用户接收到出席信息之后 该联系人的服务器必须递送该用户的出席信息节给该联系人的所有可用资源 source lang xml to resource1 CS presence from juliet example com balcony to romeo example net to resource2 CS presence from juliet example com balcony to romeo example net source 客户端处理初始化出席信息 当该联系人的客户端从该用户接收到出席信息之后 对于可交互的客户端推荐以下行为 如果该用户的纯JID在该联系人的名册中 在一个适当的名册接口中显示该出席信息 如果该用户不在该联系人的名册中但是联系人正在交换message或IQ节 为了那个通讯会话在该用户的接口中显示该出席信息 参见 RFC6121 定向出席信息 4 6 和 RFC6121 一对一聊天会话 5 1 其他情况下 忽略出席信息并且不把它显示给该联系人 出席信息探测 一个 出席信息探测 是一个对某联系人的当前出席信息的请求 由代表某个用户的服务器代表该用户发送 语法上它是一个 type 属性值为 probe 的出席信息节 在出席信息订阅的上下文中 from 地址的值必须是订阅的用户的纯JID而 to 地址的值必须是被订阅的联系人的纯JID 因为出席信息订阅是基于纯JID的 source lang xml US presence from juliet example com id ign291v5 to romeo example net type probe source 互操作性备注 RFC 3921 定义了探测是从全JID发出的 而不是从纯JID 规则的改变是因为订阅是基于纯JID的 一些现存的实现仍然从全JID而不是纯JID发送 探测也能由一个从某个出席信息订阅上下文的外部接收到了出席信息的实体发送 典型的是当该联系人已经发送了 RFC6121 定向出席信息 4 6 所述的定向出席信息的时候 在这种情况下 from 或 to 地址的值可以是一个全JID而不是一个纯JID 完整的讨论参见 RFC6121 定向出席信息 4 6 出席信息探测不应该 SHOULD NOT 由一个客户端发送 因为通常一个客户端不需要发送它们 原因是从一个用户的联系人那里收集出席信息的任务是由该用户的服务器管理的 无论如何 如果一个用户的客户端生成了一个出站出席信息探测 那么该用户的服务器应该路由这个探测 如果该联系人位于另一个服务器上 或处理这个探测 如果该联系人在同一台服务器上 并且不能 MUST NOT 从一个已连接的客户端使用该出席信息探测的回执来作为唯一的理由来返回一个节错误或流错误给该客户端 服务器生成出站出席信息探测 当一个服务器需要查询一个用户的联系人的可用性的时候 它从该用户的纯JID user domainpart 发送一个出席信息探测到该联系人的纯JID contact domainpart 实现备注 尽管出席信息探测是用来发送给联系人的 即 一个用户所订阅的那些实体 一个服务器可以发送出席信息探测给该用户在当前会话时收到了出席信息的某个实体的全JID 当用户在任何时候通过发送初始化出席信息来开始一个新的出席信息会话 该用户的服务器应该发送一个出席信息探测 无论如何 如果它认为关于该用户的联系人的出席信息是可靠的和最新的 该服务器可以选择在那个时间点不发送出席信息探测 例如 因为该用户有另外一个可用资源或因为该用户在新的出席信息开始之前刚刚注销登陆 另外 如果一个服务器在一个可配置的时间段内没有从某个联系人收到出席信息或其他通讯 它可以定期发送出席信息探测给那个联系人 这有助于防止看起来在线但是实际上没有在线的 幽灵 联系人 source lang xml US presence from juliet example com id ign291v5 to romeo example net type probe US presence from juliet example com id xv291f38 to mercutio example com type probe source 自然的 该用户的服务器不需要发送一个出席信息探测给一个联系人 如果该联系人的帐号位于该用户的同一台服务器 因为该服务器本地就拥有该联系人的信息 服务器处理入站出席信息探测 在接收到一个用户的服务器代表该用户发送到该联系人的纯JID的出席信息探测之后 该联系人的服务器必须应答如下 1 如果该联系人帐号不存在或该用户的纯JID在该联系人的名册中并且订阅状态不是 From From Pending Out 或 Both 如 RFC6121 附录A 订阅状态 附录A 所述 那么该联系人的服务器应该在对该出席信息探测的应答中返回一个类型为 unsubscribed 的出席信息节 这将触发一个协议流用于 RFC6121 撤销被订阅 3 2 所述的撤销该用户对该联系人的订阅 无论如何 这不能 MUST NOT 导致 RFC6121 预批准被订阅请求 3 4 所述的订阅预批准的撤销 这里 from 地址必须是该联系人的纯JID 因为指定一个全JID则等同于出席信息泄露 RFC6121 规范引用 XMPP CORE 中所说的 source lang xml CS presence from mercutio example com id xv291f38 to juliet example com type unsubscribed source 无论如何 如果一个服务器从一个该服务器本身的已配置的域或其他信任的服务收到一个出席信息探测 它可以提供关于该用户或那个实体的出席信息 2 或者 如果该联系人已经临时移动或永久移动到另一个地址 那么该服务器应该返回一个类型为 error 的出席信息节并带上一个节错误条件 redirect 临时的 或 gone 永久的 并包含该联系人的新地址 source lang xml CS presence from mercutio example com id xv291f38 to juliet example com type error error type modify gone xmlns urn ietf params xml ns xmpp stanzas xmpp la mer example com gone error presence source 3 或者 如果该联系人没有可用的资源 那么该服务器应该通过发送给该用户一个类型为 unavailable 的出席信息节来应答该出席信息探测 尽管在这里更倾向于发送unavailable出席信息 因为它能导致对该探测的确定的回答 但它不是强制性的 因为它极大地增加了该联系人的服务器生成的出席信息通知的数量 这里的 from 地址是纯JID 因为没有该联系人相关的可用资源 如果适当地遵循本地安全策略 该出席信息通知可以包含该服务器从该联系人收到的最近的unavailable出席信息节的全XML 包括原始节的 id 但是如果没有 那么该出席信息通知应该简单地表示该联系人是unavailable而没有任何原始提供的细节 在任何情况下 返回给该探测实体的出席信息节应该包含最近一次unavailable出席信息节被生成的时间信息 格式采用XMPP延迟递送扩展 RFC6121 规范引用 DELAY source lang xml CS presence from mercutio example com id xv291f38 to juliet example com type unavailable delay xmlns urn xmpp delay stamp 2002 09 10T23 41 07Z presence source 4 或者 如果该联系人有至少一个可用资源 那么该服务器必须通过向该用户发送该服务器从该联系人的每个可用资源收到的最近的没有 to 属性的出席信息节的全XML 这里的 from 地址是每个可用资源的全JIDs source lang xml CS presence from romeo example net foo id hzf1v27k to juliet example com CS presence from romeo example net bar id ps6t1fu3 to juliet example com show away show presence source 实现备注 通过 full XML 意味着从开始的 presence 标签到关闭的 presence 标签之前的完整的节 包括所有的元素和属性 要么由内容命名空间限定要么由扩展命名空间限定 无论如何 根据 RFC6121 规范引用 XMPP CORE 如果通过服务器 服务器流发送完整的节 该联系人的服务器将需要把内容命名空间从 jabber client 转换成 jabber server 如果该联系人的服务器接收到一个地址指向该联系人的某个全JID的出席信息探测 该服务器不能 MUST NOT 返回任何除了该探测的 to 地址之外的资源的出席信息 规则 1 和 2 中对一个纯JID的探测同样适用于一个全JID探测的情况 如果有一个匹配的全JID并且探测的实体通过一个出席信息订阅从而有权限察看该联系人的出席信息 那么该服务器必须返回一个available出席信息通知 它应该确切地只和那个available的资源通讯 没有详细信息 如 show status priority 或出席信息扩展 source lang xml CS presence from romeo example net bar to lobby chat example com source 实现备注 关于前述处理定向出席信息的补充请参阅 RFC6121 定向出席信息 4 6 处理 id 属性 和出席信息探测相关的 id 属性的处理在RFC 3921中没有定义 尽管 发送一个探测并接收到一个应答 的模式可能看起来像一个类似XMPP iq 节的 请求 应答 协议 事实上它不是 因为对一个探测的应答可以包含多个出席信息节 分别对应该联系人当前活跃的每一个可用的资源 基于这个原因 如果该联系人当前有可用资源 那么该联系人的服务器应该保留当发送那些出席信息通知给探测实体的时候该联系人的原始出席信息节的 id 属性 如果有的话 相比之下 如果该联系人当前没有可用资源 探测实体未被授权 通过出席信息订阅 察看该联系人的出席信息 或发生了和该探测相关的错误 那么该联系人的服务器在应答探测实体的时候应该镜像该用户的出席信息探测的 id 以下示例展现这些不同之处 在第一个场景中 Juliet发送从她的 chamber 资源出席信息探测 source lang xml CC presence from juliet example com chamber id pres1 show dnd show status busy status presence source 她也从她的 balcony 资源发送出席信息 source lang xml CC presence from juliet example com balcony id pres2 show away show status stepped away status presence source Romeo的服务器接着发送一个探测给Juliet source lang xml US presence from romeo example net id probe1 type probe source Juliet的服务器接着同时发送她的两个出席信息通知给Romeo 保留她的客户端发送的节中的 id 属性 source lang xml CS presence from juliet example com chamber id pres1 show dnd show status busy status presence CS presence from juliet example com balcony id pres2 show away show status stepped away status presence source 在第二个场景中 当Romeo的服务器发送探测的时候Juliet离线了 source lang xml US presence from romeo example net id probe2 type probe source Juliet的服务器应答一个unavailable通知 镜像Rome的出席信息探测的 id 因为从她的客户端已经发送的available通知的 id 被保留 source lang xml CS presence from juliet example com id probe2 type unavailable source 随后的出席信息广播 客户端生成随后的出席信息广播 在发送初始化出席信息之后 在它的会话期间的任何时候该用户的客户端可以更新它的可用性并通过发送一个不带 to 地址并且没有 type 属性的出席信息节来广播 source lang xml UC presence show away show presence source 该出席信息广播可以包含 priority 元素 show 元素 和一个或多个 status 元素实例 同样的包括扩展内容 详情参见 RFC6121 出席信息语法 4 7 无论如何 一个用户应该发送一个出席信息更新只广播该用户的通讯可用性或该资源的通讯能力相关的信息 和这些无关但是可能该用户的联系人同样感兴趣的信息应该通过其他方式来发送 例如 RFC6121 参考文献 XEP 0163 所述的 发布 订阅 方法 服务器处理随后的出站出席信息 在接收到一个表达更新的可用性的出席信息节后 该用户的服务器必须广播那个出席信息节的完整XML给该用户名册中并且订阅类型为 from 或 both 的联系人们 互操作性备注 RFC 3921定义在发送随后的出席信息通知之前该用户的服务器将检查并确认没有从该联系人收到一个出席信息错误 那个规则已经被移除 因为本协议使用类型为 unsubscribe 而不是 error 的出席信息节来解决订阅同步问题 部分也因为这类节使得该联系人在该用户的名册中的订阅状态变成了 none 或 to 见 RFC6121 取消订阅 3 3 和 RFC6121 附录A 订阅状态 附录A 所以没有了对错误检查的需要 互操作性备注 如果订阅类型为 both 一些现有的服务器实现根据该用户的服务器仅当该联系人在线时才发送随后的出席信息通知给一个联系人 就是说 如果该用户的服务器在它发给该联系人的出席信息探测的应答中从未收到过该联系人在线的肯定的标示 该用户的服务器不会从该用户向该联系人发送随后的出席信息通知 这一行为被理解为节省带宽 因为大部分出席信息订阅是双向的并且很多联系人在任何特定的时间都不在线 source lang xml US presence from juliet example com balcony to romeo example net show away show presence US presence from juliet example com balcony to benvolio example net show away show presence US presence from juliet example com balcony to mercutio example com show away show presence source 实现备注 关于上述处理用于定向出席信息的补充规则参见 RFC6121 定向出席信息 4 6 该用户的服务器也必须发送该出席信息节给该用户的所有可用资源 包括首先生成该出席信息的那个资源 source lang xml US presence from juliet example com balcony to juliet example com chamber show away show presence US presence from juliet example com balcony to juliet example com balcony show away show presence source 服务器处理随后的入站出席信息 在从用户那接收到出席信息之后 该联系人的服务器必须递送该用户的出席信息节到该联系人的所有可用资源 source lang xml to resource1 CS presence from juliet example com balcony to romeo example net show away show presence to resource2 CS presence from juliet example com balcony to romeo example net show away show presence source 客户端处理随后的出席信息 从联系人的客户端的视角来看 初始化出席信息广播和随后的出席信息没有明显的不同 所以联系人的客户端遵循 RFC6121 服务器处理随后的出席信息 4 4 3 定义的入站出席信息处理的规则 离线出席信息 客户端生成离线出席信息 在结束和一个服务器的出席信息会话之前 用户的客户端应该通过发送 unavailable 出席信息 优雅地变更为离线 即 一个没有 to 属性并且有一个值为 unavailable 的 type 属性的出席信息节 source lang xml UC presence type unavailable source 可选的 该离线出席信息节可以包含一个或多个 status 元素来定义为什么该用户不再在线的原因 source lang xml UC presence type unavailable status going on vacation status presence source 无论如何 该离线出席信息节不能 MUST NOT 包含 priority 元素或 show 元素 因为这些元素只适用于可用资源 服务器处理出站离线出席信息 该用户的服务器不能 MUST NOT 依赖于从一个可用的资源接收到的unavailable出席信息 因为该资源可能不优雅地离线了 例如 如 RFC6121 规范引用 XMPP CORE 所述 该资源的XML流因为任何原因带或未带流错误地被关闭了 如果一个可用的资源因为任何原因离线了 优雅或不优雅的 该用户的服务器必须广播unavailable出席信息给所有在该用户的名册中的订阅状态为 from 或 both 的联系人 互操作性备注 RFC 3921 定义了该用户的服务器将检查并确认在发送unavailable出席信息通知之前它没有从该联系人收到一个出席信息错误 那个规则已经被移除 因为本协议使用类型为 unsubscribe 而不是 error 的出席信息节来解决订阅同步问题 部分也因为这类节使得该联系人在该用户的名册中的订阅状态变成了 none 或 to 见 RFC6121 取消订阅 3 3 和 RFC6121 附录A 订阅状态 附录A 所以没有了对错误检查的需要 互操作性备注 即使该用户的服务器不广播该用户随后的出席信息通知给离线的联系人们 如 RFC6121 服务器处理随后的出站出席信息 4 4 2 所述 它必须广播该用户的unavailable出席信息通知 如果它不这么做 由该联系人的服务器最后收到的出席信息将是该用户用于这个出席信息会话的初始化出席信息 结果是该联系人将认为该用户在线 实现备注 关于上述处理用于定向出席信息的补充规则参见 RFC6121 定向出席信息 4 6 如果该unavailable通知优雅地被从该客户端接收到 那么该服务器必须广播该出席信息节的完整XML source lang xml US presence from juliet example com balcony to romeo example net type unavailable status going on vacation status presence US presence from juliet example com balcony to benvolio example net type unavailable status going on vacation status presence US presence from juliet example com balcony to mercutio example com type unavailable status going on vacation status presence source 该用户的服务器也必须发送该unavailable通知给该用户的所有可用资源 以及最初生成该unavailable出席信息的那个资源 source lang xml US presence from juliet example com balcony to juliet example com chamber type unavailable status going on vacation status presence source 如果该服务器探测到那该用户已经不优雅地离线了 那么该服务器必须代表该用户生成该unavailable出席信息广播 实现备注 在该服务器广播或生成一个unavailable出席信息通知之后 该客户端发送的任何没有 type 属性且没有 to 属性的出席信息节 必须被该用户的服务器路由或递送到所有的订阅者 即 必须等同于为一个新的出席信息会话出发了初始化出席信息 服务器处理入站离线出席信息 在从用户接收到一个unavailable通知之后 该联系人的服务器必须递送该用户的出席信息节给该联系人的所有可用资源 source lang xml to resource1 CS presence from juliet example com balcony to romeo example net type unavailable status going on vacation status presence to resource2 CS presence from juliet example com balcony to romeo example net type unavailable status going on vacation status presence source 实现备注 如果该联系人的服务器没有广播随后的出席信息通知给离线的用户们 如 RFC6121 服务器处理随后的出站出席信息 4 4 2 它也必须注意到该用户是离线的并更新它的关于哪些实体在线的内部存储 客户端处理离线出席信息 从联系人的客户端的视角来看 在线出席信息广播和离线出席信息广播没有明显的差别 所以通常联系人的客户端遵循定义的处理入站出席信息的规则 RFC6121 服务器处理随后的入站出席信息 4 4 3 无论如何 如果该联系人从该用户的纯JID 而不是某个可用资源的全JID 接收到一个unavailable通知 该联系人的客户端应该视为该unavailable通知适用于所有资源 定向出席信息 本章是客户端和服务器处理出席信息通知和出席信息探测的规则的补充 但是仅用于定向出席信息的特定场景 总则 通常 当一个客户端希望分享可用性信息给一个没有订阅它的出席信息的实体的时候 它会发送定向出席信息 典型的是在一个临时基础上 定向出席信息的常规使用包括 RFC6121 一对一聊天会话 5 1 所述的临时的一对一会话和 XEP 0045 所述的多用户聊天室 通过分享定向出席信息给另一个实体而建立的临时的关系比起通过出席信息订阅建立的永久关系来说是次要的 所以 建立 修改 或取消一个出席信息订阅的动作 必须优先于接下来的子章节定义的规则 例如 如果一个用户分享了定向出席信息给一个联系人 但是接着通过完成出席信息订阅 握手 来把该联系人加入到该用户的名册中 那么该用户的服务器必须把该联系人视为如 RFC6121 管理出席信息订阅 第三章 所述的任何一个普通的订阅者来处理 例如 发送随后的出席信息广播给该联系人 另一个例子是 如果该用户接着取消了该联系人对该用户的出席信息的订阅 该用户的服务器必须如 RFC6121 撤销被订阅 3 2 所述处理这个取消动作 这包括发送unavailable出席信息给该联系人 即使该用户曾经发送了定向出席信息给该联系人 XMPP服务器典型的实现定向出席信息的办法是通过保持一个用户在该用户的给定资源 全JID 的当前会话期间曾经对它们发送了定向出席信息的实体的列表 纯JIDs或全JIDs 然后在该用户下线的时候清除这个列表 例如 发送一个类型为 unavailable 的广播出席信息节 该服务器必须从定向出席信息列表 或它的功能等价物 移除任何该用户曾经对它们发送过定向unavailable出席信息的实体并且应该移除任何发送了unavailable出席信息给该用户的实体 客户端生成定向出席信息 大家知道 定向出席信息是一个客户端生成的presence节 这个节的 to 属性值是另一个实体的纯JID或全JID 并且这个节要么没有 type 属性 表示可用性 要么 type 属性值为 unavailable 服务器处理出站定向出席信息 当用户的服务器接收到一个定向出席信息节 它应该根据以下规则处理它 如果该用户在已经发送初始化出席信息之后并且在发送unavailable出席信息广播之前 即 在该用户的出席信息会话期间 发送定向的可用或不可用出席信息给一个在该用户的名册中并且订阅状态为 from 或 both 的联系人 该用户的服务器必须本地递送或远程路由那个出席信息节的完整XML给那个实体 但是应该不 SHOULD NOT 基于出席信息广播来修改该联系人的状态 即 它应该在任何随后由该用户初始化的的出席信息广播中包含该联系人的JID 如果该用户在已经发送初始化出席信息之后并且在发送unavailable出席信息广播之前 即 在该用户的出席信息会话期间 发送定向的可用或不可用出席信息给一个不在该用户的名册中并且订阅状态为 from 或 both 的联系人 该用户的服务器必须本地递送或远程路由那个出席信息节的完整XML给那个实体 但是不能 MUST NOT 基于available出席信息广播来修改该联系人的状态 即 它不能 MUST NOT 在任何随后由该用户初始化的available出席信息广播中包含该联系人的JID 无论如何 如果发送定向出席信息的用户的可用资源离线了 该用户的服务器必须路由那个离线出席信息给该实体 如果该用户还未发送定向unavailable出席信息给那个实体 如果该用户从未发送过初始化出席信息或在已经发送unavailable出席信息广播之后 即 该资源已连接但不可用 发送定向出席信息 该用户的服务器必须把该实体当作上面第二种情况下该用户发送定向出席信息的实体 服务器处理入站定向出席信息 从联系人的服务器的视角来看 在出席信息广播和定向出席信息之间没有显著差别 所以联系人的服务器遵循 RFC6121 服务器处理入站出席信息探测 4 3 2 RFC6121 服务器处理随后的入站出席信息 4 4 3 和 RFC6121 服务器处理入站离线出席信息 4 5 3 定义的处理入站出席信息的规则 客户端处理入站定向出席信息 从联系人的客户端的视角来看 在出席信息广播和定向出席信息之间没有显著差别 所以联系人的客户端遵循定义的处理入站出席信息的规则 RFC6121 服务器处理随后的入站出席信息 4 4 3 译者注 原文如此 疑为 RFC6121 客户端处理随后的出席信息 4 4 4 之误 服务器处理出席信息探测 如果一个用户的客户端发送了定向出席信息给另一个实体 例如 一个一对一聊天伙伴或一个多用户聊天室 在一段时间之后该实体或它的服务器可能想知道该用户是否仍然在线 这个场景在多用户聊天室中特别常见 该用户可能在很长一段时间内在该聊天室中是一个参加者 如果该用户的客户端下线而没有 通过客户端或该客户端的服务器 通知该聊天室 该用户的在该房间里的表现可能成为一个 幽灵 看起来是参加者但实际上已经不在该房间了 为了查明这类 幽灵 一些聊天室实现会发送出席信息探测给这些已经加入房间的用户 在定向出席信息的案例中 探测的实体应该从接收到定向出席信息的那个JID 一个全JID或纯JID 发送探测 该探测应该被发送到那个用户的全JID 而不是那个用户的不带资源的纯JID 因为伴随定向出席信息的临时 授权 是基于曾经发送定向出席信息给该探测实体的那个用户的全JID 当该用户的服务器接收到一个探测 它必须首先应用任何和出席信息订阅相关的逻辑 如 RFC6121 服务器处理入站出席信息探测 4 3 2 所述 如果该探测实体未订阅该用户的出席信息 那么该服务器必须检查该用户是否曾经在当前会话中发送过定向出席信息给该实体 如果是 该服务器应该仅以纯粹的 available 或 unavailable 类型 即 不包含子元素 应答这个探测并且只用于那个全JID 即 不为任何可能与当前该用户的纯JID相关的其他资源 出席信息语法 Type属性 缺少 type 属性代表相关实体是可以通讯的 见 RFC6121 初始化出席信息 4 2 和 RFC6121 随后的出席信息广播 4 4 type 属性值为 unavailable 代表相关实体不可通讯 见 RFC6121 离线出席信息 4 5 XMPP出席信息节也用于协商和管理对其他实体的出席信息的订阅 这些任务通过 RFC6121 管理出席信息订阅 第三章 所述的类型为 subscribe unsubscribe subscribed 和 unsubscribed 的出席信息节来完成 如果一个用户和联系人在不同的XMPP服务器上发生关系 那些服务器为了确定对端服务器上的那个实体的可用性 也使用一个类型为 probe 的特殊的出席信息节 详见 RFC6121 出席信息探测 4 3 客户端不应 SHOULD NOT 发送类型为 probe 的出席信息节 type 属性的值可以归纳如下 error error发生在处理之前发送的出席信息节的时候 如果出席信息节的类型为 error 它必须包含一个 error 子元素 参考 RFC6121 规范引用 XMPP CORE probe 请求一个实体当前的出席信息 应该只由一个服务器代表一个用户生成 subscribe 发送者希望订阅接收者的出席信息 subscribed 发送者已经允许接收者接收他们的出席信息 unavailable 发送者不再可通讯 unsubscribe 发送者取消订阅接收者的出席信息 unsubscribed 订阅请求已经被拒绝或撤销之前准许的被对方订阅 如果 type 属性的值不是前述的任何一个 接收方或一个中间的路由服务器应该返回一个节错误 bad request 实现备注 presence 元素的 type 属性没有缺省值 实现备注 presence 元素的 type 属性没有 available 这个值 子元素 根据缺省命名空间声明 一个出席信息节是由 jabber client 或 jabber server 命名空间限定的 它定义了明确的出席信息节的子元素 特别是 show status 和 priority 元素 这些子元素被用于提供关于一个实体的可用性的更详细的信息 典型情况下这些子元素只在该出席信息节没有 type 属性的时候被包含 尽管在接下来的文本里有一些例外 Show元素 可选的 show 元素定义了一个实体或它的一个特定资源的特定的可用性子状态 一个出席信息节不能 MUST NOT 包含多于一个的 show 元素 show 元素没有定义属性 show 元素不能 MUST NOT 包含混合内容 定义于 RFC6121 规范引用 XML 3 2 2节 show 元素的XML字符数据不意味着它是用于展示给自然人用户看的 该XML字符数据必须是以下之一 更多的可用性状态可以通过扩展内容元素来定义 away 该实体或资源临时离开 chat 该实体或资源活跃并想聊天 dnd 该实体或资源忙 dnd Do Not Disturb 免打扰 xa 该实体或资源要离开相当长时间 xa eXtended Away 长时间离开 如果 show 元素未被提供 该实体被假定在线并且可用 任何由接收者和代理路由服务器对可用性状态的特别处理取决于该实现 例如 把可用性状态合并到节路由和递送逻辑中 Status元素 可选的 status 元素包含了自然人可读的定义实体可用性的自然语言描述的XML字符数据 通常在出席信息节不包含 type 属性的时候被用于和show元素结合一起提供某个可用性状态的细节 例如 In a meeting 开会中 source lang xml presence from romeo example net orchard xml lang en show dnd show status Wooing Juliet status presence source status 元素没有定义属性 除了从 RFC6121 规范引用 XML 继承的 xml lang 属性 status 元素不能 MUST NOT 包含混合内容 定义于 RFC6121 规范引用 XML 3 2 2节 status 元素可以包含多个实例 但是只能在每个实例的都有一个 xml lang 属性并且属性值为唯一的语言值 或者显式地 或者从一个元素的更高的XML级别的 xml lang 值继承 从发送者的视角来看 可能包括 RFC6121 规范引用 XMPP CORE 描述的XML流头 source lang xml presence from romeo example net orchard id jx62vs97 xml lang en show dnd show status Wooing Juliet status status xml lang cs Dvo x0159 x00ED m se Julii status presence source 一个类型为 unavailable 的出席信息节也可以包含一个 status 元素来提供为什么该实体下线的详细原因 source lang xml presence from romeo example net orchard id oy6sb241 type unavailable xml lang en status Busy IRL status presence source status 子元素也可以在一个订阅相关的出席信息节中被发送 即 类型为 subscribe subscribed unsubscribe 或 unsubscribed 以提供该动作的描述 一个可交互的客户端可以展示这个 status 信息给一个自然人用户 见 RFC6121 安全事项 第11章 source lang xml presence from romeo example net id uc51xs63 to nurse example com type subscribe status Hi Juliet told me to add you to my buddy list status presence source Priority元素 可选的 priority 元素包含定义该资源优先级的非自然人可读的XML字符数据 它的值必须是一个处于 128 和 127 之间的整数 一个出席信息不能 MUST NOT 包含多个 priority 元素 没有为 priority 定义属性 priority 元素不能 MUST NOT 包含混合内容 定义于 RFC6121 规范引用 XML 3 2 2节 source lang xml presence xml lang en show dnd show status Wooing Juliet status status xml lang cs Dvo x0159 x00ED m se Julii status priority 1 priority presence source 如果没有提供优先级 处理的服务器或客户端必须视为优先级为零 0 该客户端的服务器可以覆写客户端提供的优先级的值 例如 为了给正在递送给预期的帐号的纯JID的消息强加一个消息处理规则以用于该帐号的所有可用资源 如果服务器这样做 当它回应该客户端的出席信息给自己并发送出席信息通知给该用户的联系人们的时候 它必须以修改过的优先级来通讯 因为修改过的优先级的值典型的缺省是零 以修改过的优先级的值来通讯可以不包含 priority 子元素 关于即时消息和出席信息应用中节处理过程中优先级值的语法信息 参见 RFC6121 处理XML节的服务器规则 第八章 扩展内容 如 RFC6121 规范引用 XMPP CORE 所述 一个XML节可以包含任何由不同于缺省命名空间限定的子元素 这也适用于出席信息节 以下例子中 出席信息节包含定义于 RFC6121 参考文献 XEP 0115 的实体能力信息 source lang xml presence from romeo example net c xmlns http jabber org protocol caps hash sha 1 node http psi im org ver q07IKJEyjvHSyhy CH0CxmKi8w presence source 包含在一个出席信息节中的任何扩展内容应该展示用于通讯的实体可用性的方方面面或提供和通讯相关的能力 交换消息 一旦一个客户端如 RFC6121 规范引用 XMPP CORE 所述 已经在一个服务器上通过了验证并绑定了一个资源到一个XML流 一个XMPP服务器将路由XML节到和从那个客户端 一种可交换的节是 message 如果 也就是说 消息功能在该服务器上是允许的 交换消息是XMPP的一个基本用途 它发生在一个用户生成一个地址指向另一个实体的消息节的时候 如 RFC6121 处理XML节的服务器规则 第八章 所定义的 该发送者的服务器负责递送该消息到期望的接收者 如果该接收者在同一台本地服务器上 或路由该消息到该接收者的服务器 如果该接收者在一个远端服务器上 所以一个消息节是被用来 推送 信息给另一个实体 一对一聊天会话 在实践中 在自然人用户之间的即时消息活动倾向于以一个会话式的方式发生 我们称之为一个 聊天会话 在一个比较短暂的时间内双方的多个比较快速的消息交换是有继承的 当一个自然人用户倾向于和一个联系人进行这样一种聊天会话 而不是发送一个单独的消息给某人却不期望获得应答 由该用户的客户端生成的这个消息的类型应该是 chat 并且该联系人的客户端应该在随后的应答中保持那个消息类型 该用户的客户端也应该在它的初始化消息中包含一个 thread 元素 这样该联系人的客户端也应该在那个会话的生命周期中保持它 参见 RFC6121 Thread元素 5 2 5 该用户的客户端应该在一个聊天会话中把初始消息的地址指向该联系人的纯JID contact domainpart 而不是基于任何它可能之前从联系人那收到的出席信息通知的 show status 或 priority 值来尝试猜测一个适当的全JID contact domainpart resourcepart 直到和除非该用户的客户端从该联系人收到一个应答 它应该发送任何更多的消息给该联系人的纯JID 该联系人的客户端应该把它的应答的地址指向该用户的全JID user domainpart resourcepart 即初始消息中提供的 from 地址 一旦该用户的客户端从该联系人的全JID收到一个应答 它应该把它随后的消息指向该联系人的全JID 即在该联系人的应答中提供的 from 地址 从而 锁定 在那个全JID 一个客户端应该在接收到一个来自对方节点控制的任何其他资源的 message 或 presence 节 或一个来自已锁定的资源的出席信息节 的时候 解除锁定 结果是 它应该在聊天会话的下一个消息中指向对方节点的纯JID 从而 解锁 之前的 锁定 直到它从对方的全JIDs收到一个消息 当双方参加一个一个聊天会话但是没有基于一个出席信息订阅来互相分享出席信息 他们应该互相发送定向出席信息 这样双方能很容易地查询对方在该聊天会话期间是否下线 然而 一个客户端必须提供一个方法让一个用户能全局地禁止或只允许特定的实体进行这类出席信息分享 更进一步的 当出于某种原因相信该聊天会话结束了 例如 如果 在一段合理的时间之后 双方没有交换随后的消息 一方应该发送定向unavailable出席信息给另一方 聊天会话的例子参见 RFC6121 示例会话 第7章 消息语法 以下章节描述 message 节的语法 To属性 即时消息客户端通过在 message 节中的 to 属性中提供预期的接收者的JID来为一个消息指定预期接收者 如果该消息在现有的聊天会话或已接收的消息的上下文之外被发送 to 地址的值的格式应该是 localpart domainpart 而不是 localpart domainpart resourcepart 见 RFC6121 一对一聊天会话 5 1 source lang xml message from juliet example com balcony id ktx72v49 to romeo example net type chat xml lang en body Art thou not Romeo and a Montague body message source 如果该消息是作为对之前从格式 localpart domainpart resourcepart 收到的一个消息的应答来发送的 例如 在一个如 RFC6121 一对一聊天会话 5 1 所述的一对一聊天会话的上下文中 该 to 地址的值的格式应该是 localpart domainpart resourcepart 而不是 localpart domainpart 除非发送者已经知道 例如 通过出席信息 接收者的资源不再可用 source lang xml message from romeo example net orchard id sl3nx51f to juliet example com balcony type chat xml lang en body Neither fair saint if either thee dislike body message source Type属性 在即时消息应用中消息节的常用的包括 单条消息 在一对一聊天会话的上下文中发送的消息 在一个多用户聊天室中发送的消息 警告 通知 或其他给不期望应答的人的信息 错误 这些用途通过 type 属性来区分 建议包含 type 属性 如果包含了它 type 属性必须是以下的值之一 chat 该消息在一个一对一聊天会话的上下文中被发送 典型的一个可交互的客户端将在一个界面上展示一个类型为 chat 的消息 这使得双方之间能够进行一对一聊天 同时包括一个适当的会话历史 关于一对一聊天会话的详细建议参见 RFC6121 一对一聊天会话 5 1 error 该消息由一个从另一个实体接收到一个消息并在处理的时候发现了错误的实体生成 关于节错误语法的详情 参考 RFC6121 规范引用 XMPP CORE 接收到一个类型为 error 的消息的客户端应该展示一个适当的界面来通知原始的发送者关于这个错误的类型 groupchat 该消息在一个多用户聊天环境的上下文中被发送 类似 RFC6121 参考文献 IRC 典型的一个接收的客户端将在一个界面展示一个类型为 groupchat 的消息 这使得多方可以进行多对多的聊天 同时包含一个聊天室中的参与者的名册和适当的会话历史 关于基于XMPP的群聊的详细信息 参见 RFC6121 参考文献 XEP 0045 headline 该消息提供一个警告 一个通知 或其他给那些不期望应答的人的临时信息 例如 新闻头条 运动更新 准实时的市场数据 或整合的内容 因为不期望对该消息的回复 典型的一个接收客户端将在一个界面展示一个类型为 headline 的消息以适当地把它们和独立消息 聊天消息 以及群聊消息区分开来 例如 不向该接收者提供应答能力 如果 to 地址是纯JID 该接收服务器应该递送该消息给该接收者的所有非负出席信息优先级的可用资源并且必须递送该消息给那些资源中的至少一个资源 如果该 to 地址是一个全JID并且有一个匹配的资源 该服务器必须递送该消息给那个资源 否则该服务器必须要么安静地忽略该消息要么返回一个错误 见 RFC6121 处理XML节的服务器规则 第8章 normal 该消息是一个在一对一聊天会话或群聊上下文之外的被发送的独立消息 并且它期望接收者应答 典型的一个接收客户端将在一个界面展示一个类型为 normal 的消息 这使得接收方能够应答 但没有会话历史 type 属性的缺省值是 normal 一个IM应用应该支持所有前述的消息类型 如果一个应用接收了一个没有 type 属性的消息或该应用不理解被提供的 type 属性的值 它必须认为该消息的类型为 normal 即 normal 是缺省的 不同消息类型的服务器处理指南参见 RFC6121 处理XML节的服务器规则 第8章 尽管 type 属性是可选的 出于礼貌在任何对一个消息的应答之中会镜像其类型 更进一步 一些专门的应用 例如 一个多用户聊天服务 可以基于他们的自主判断来强制使用特定消息类型 例如 type groupchat Body元素 body 元素包含自然人可读的XML字符数据以指定该消息的正文 这个子元素通常会被包含但是可选的 source lang xml message from juliet example com balcony id b4vs9km4 to romeo example net type chat xml lang en body Wherefore art thou Romeo body message source 没有为 body 元素定义属性 除了 xml lang 属性例外 在一个消息节中可以包括多个 body 元素实例用来为同一body提供替代版本 但是每个实例只允许拥有一个 xml lang 属性并且其值为一个唯一性的语言 要么显性的 要么从更高层次的XML继承 xml lang 值 从发送者角度看是包含在 RFC6121 规范引用 XMPP CORE 所述的XML流头中 source lang xml message from juliet example com balcony id z94nb37h to romeo example net type chat xml lang en body Wherefore art thou Romeo body body xml lang cs Pro x010D e x017D jsi ty Romeo body message source body 元素不能 MUST NOT 包含混合内容 定义于 RFC6121 规范引用 XML 的3 2 2节 Subject元素 subject 元素包含自然人可读的XM字符数据以指定该消息的标题 source lang xml message from juliet example com balcony id c8xg3nf8 to romeo example net type chat xml lang en subject I implore you subject body Wherefore art thou Romeo body message source 没有为 subject 元素定义属性 从 RFC6121 规范引用 XML 继承的 xml lang 属性例外 可以包含多个 subject 元素实例以提供同意标题的替代版本 但是每个实例只允许拥有一个 xml lang 属性并且其值为一个唯一性的语言 要么显性的 要么从更高层次的XML继承 xml lang 值 从发送者角度看是包含在 RFC6121 规范引用 XMPP CORE 所述的XML流头中 source lang xml message from juliet example com balcony id jk3v47gw to romeo example net type chat xml lang en subject I implore you subject subject xml lang cs x00DA p x011B nliv x011B pros x00ED m subject body Wherefore art thou Romeo body body xml lang cs Pro x010D e x017E jsi ty Romeo body message source subject 元素不能 MUST NOT 包含混合内容 定义于 RFC6121 规范引用 XML 的3 2 2节 Thread元素 XMPP thread 元素主要用于唯一性地标识一个由类型为 chat 的 message 节实例化的两个实体之间的交谈线索或 聊天会话 然而 XMPP thread 元素也可以被用于唯一性地标识一个由类型为 headline 或 normal 的 message 节实例化的两个实体之间 或由类型为 groupchat 的 message 节实例化的在一个多用户聊天室上下文中的多个实体之间的类似线索 它也可用于和自然人无关的会话的 message 节 类似一个游戏会话或一个插件之间的互动 thread 元素不被用于标识个别的消息 只用于交谈或消息会话 thread 元素是可选的 因为 thread 元素标识了一个消息所属的特定交谈线索 一个消息节不能 MUST NOT 多个 thread 元素 thread 元素可以拥有一个 parent 属性以标识另一个线索 当前线索是那个线索的分支或子线索 该 parent 属性必须遵循 thread 元素本身的语法并且它的值必须和包含了该 parent 属性的那个 thread 元素的XML字符数据不同 实现备注 同时指定一个父线索和一个子线索的能力可能会因为重叠的线索而导致线索标识的冲突 例如 一个 thread 元素可能包含XML字符数据 foo 以及一个值为 bar 的 parent 属性 第二个 thread 元素可能包含XML字符数据 bar 和一个值为 baz 的 parent 属性 而第三个 thread 元素可能包含XML字符数据 baz 和一个值再次为 foo 的 parent 属性 如果处理这类重叠的线索标识之间的冲突取决于实现 例如 要么它将线索标识符 链在一起 在一个多级用户界面中把 foo 同时显示成 baz 的一个父线索和一个孙线索 要么它将在一次只显示依赖的一层 thread 元素的值不是自然人可读的且必须被实体当成不透明的来处理 从它那里不能获得语义 并且对它只能做精确比较 thread 元素的值必须唯一地标识该交谈线索 在交谈伙伴之间或更更广泛 一个确保唯一性的办法是生成一个 RFC6121 参考文献 UUID 所述的全局唯一标识符 UUID 安全警告 一个生成ThreadID的应用必须确保它不会泄露关于这个实体的身份信息 例如 该XMPP应用正在运行的设备的MAC地址 thread 元素不能 MUST NOT 包含混合内容 定义于 RFC6121 规范引用 XML 的3 2 2节 source lang xml message from juliet example com balcony to romeo example net type chat xml lang en subject I implore you subject subject xml lang cs x00DA p x011B nliv x011B pros x00ED m subject body Wherefore art thou Romeo body body xml lang cs Pro x010D e x017E jsi ty Romeo body thread parent e0ffe42b28561960c6b12b944a092794b9683a38 0e3141cd80894871a68e6fe6b1ec56fa thread message source 关于使用 thread 元素的详细建议 参考 RFC6121 参考文献 XEP 0201 扩展内容 如 RFC6121 规范引用 XMPP CORE 所述 一个XML节可以包含任何不同于缺省命名空间的命名空间所限定的子元素 这也适用于message节 处理扩展内容的指南参见 RFC6121 规范引用 XMPP CORE 的8 4节中提供的路由服务器和最终接收者部分 在下面的例子中 该message节包含一个 RFC6121 参考文献 XEP 0071 定义的该消息的XHTML格式版本 source lang xml message from juliet example com balcony to romeo example net type chat xml lang en body Wherefore art thou Romeo body html xmlns http jabber org protocol xhtml im body xmlns http www w3 org 1999 xhtml p Wherefore span style font style italic art span thou span style color red Romeo span p body html message source 交换IQ节 如 RFC6121 规范引用 XMPP CORE 所述 IQ节提供一个结构化的 请求 应答 机制 那一机制的基本语法 例如 id 属性是强制性的 定义于 RFC6121 规范引用 XMPP CORE 特定语法需要完成限定类型为 get 或 set 的IQ节的直接子元素的扩展命名空间的所有实例中定义的用例 jabber client 和 jabber server 命名空间不定义除了 error 元素之外的所有节类型的任何IQ节的子元素 本文定义一个这样的扩展命名空间 用于 RFC6121 管理名册 管理名册 无论如何 IQ节可以包含由一个扩展命名空间限定的结构化的信息 示例会话 本节的例子展示一个可能的即时消息和出席信息会话 用户是 romeo example net 他有一个可用资源 其资源部分是 orchard 并且在他的名册中有以下人员 juliet example com 订阅状态 both 并且她有两个可用资源 chamber 和 balcony benvolio example net 订阅状态 to mercutio example org 订阅状态 from 首先 该用户完成如 RFC6121 规范引用 XMPP CORE 所述的前提条件 流建立 TLS和SASL协商 以及资源绑定 那些协议流程在这里不复述了 接下来 该用户请求他的名册 示例1 用户向服务器请求当前名册 source lang xml UC iq from romeo example net orchard id hf61v3n7 type get query xmlns jabber iq roster iq source 示例2 用户从服务器接收到名册 source lang xml US iq id hf61v3n7 to romeo example net orchard type result query xmlns jabber iq roster item jid juliet example com name Juliet subscription both group Friends group item item jid benvolio example org name Benvolio subscription to item jid mercutio example org name Mercutio subscription from query iq source 现在该用户开始一个出席信息会话 示例3 用户发送初始出席信息 source lang xml UC presence source 示例4 用户的服务器代表该用户发送出席信息探测给订阅状态 to 和订阅状态 both 的联系人们 source lang xml US presence from romeo example net to juliet example com type probe US presence from romeo example net to benvolio example org type probe source 示例5 用户的服务器代表该用户的可用资源发送初始出席信息给订阅状态 from 和订阅状态 both 的联系人们 以及用户自己 source lang xml US presence from romeo example net orchard to juliet example com US presence from romeo example net orchard to mercutio example org US presence from romeo example net orchard to romeo example net source 示例6 联系人的服务器代表所有可用资源应答该出席信息探测 source lang xml CS presence from juliet example com balcony to romeo example net xml lang en show away show status be right back status priority 0 priority presence CS presence from juliet example com chamber to romeo example net priority 1 priority presence CS presence from benvolio example org pda to romeo example net xml lang en show dnd show status gallivanting status presence source 示例7 联系人的服务器们递送用户的初始出席信息给所有可用资源 source lang xml CS presence from romeo example net orchard to juliet example com CS presence from romeo example net orchard to juliet example com CS presence from romeo example net orchard to mercutio example org source 示例8 用户发送定向出席信息给另一个不在他的名册中的用户 source lang xml UC presence from romeo example net orchard to nurse example com xml lang en show dnd show status courting Juliet status priority 0 priority presence source 现在该用户和他的联系人之一进入一个聊天会话 示例9 一个带线索的交谈 source lang xml CC message from juliet example com balcony to romeo example net type chat xml lang en body My ears have not yet drunk a hundred words body thread e0ffe42b28561960c6b12b944a092794b9683a38 thread message CC message from juliet example com balcony to romeo example net type chat xml lang en body Of that tongue s utterance yet I know the sound body thread e0ffe42b28561960c6b12b944a092794b9683a38 thread message CC message from juliet example com balcony to romeo example net type chat xml lang en body Art thou not Romeo and a Montague body thread e0ffe42b28561960c6b12b944a092794b9683a38 thread message UC message from romeo example net orchard to juliet example com balcony type chat xml lang en body Neither fair saint if either thee dislike body thread e0ffe42b28561960c6b12b944a092794b9683a38 thread message CC message from juliet example com balcony to romeo example net orchard type chat xml lang en body How cam st thou hither tell me and wherefore body thread e0ffe42b28561960c6b12b944a092794b9683a38 thread message source 以此类推 该用户也能发送随后的出席信息广播 示例10 用户发送更新的可用信息用于广播 source lang xml UC presence xml lang en show away show status I shall return status priority 1 priority presence source 示例11 用户的服务器广播更新的出席信息给订阅类型为 both 或 from 的联系人 但是不包括该用户向其发送过定向出席信息的实体 source lang xml US presence from romeo example net orchard to juliet example com xml lang en show away show status I shall return status priority 1 priority presence US presence from romeo example net orchard to mercutio example org xml lang en show away show status I shall return status priority 1 priority presence source 示例12 联系人们的服务器递送更新的出席信息 source lang xml CS presence from romeo example net orchard to juliet example com xml lang en show away show status I shall return status priority 1 priority presence CS presence from romeo example net orchard to juliet example com xml lang en show away show status I shall return status priority 1 priority presence CS presence from romeo example net orchard to mercutio example org xml lang en show away show status I shall return status priority 1 priority presence source 示例13 联系人们的可用资源之一广播不可用 离线 通知 source lang xml CC presence from juliet example com chamber type unavailable source 示例14 联系人的服务器发送不可用 离线 通知给用户 source lang xml CS presence from juliet example com chamber to romeo example net type unavailable source 现在该用户结束他的出席信息会话 示例15 用户发送不可用 离线 通知 source lang xml UC presence type unavailable xml lang en status gone home status presence source 示例16 用户的服务器广播离线通知给联系人们以及该用户曾经发送过定向出席信息的那个实体 source lang xml US presence from romeo example net orchard to juliet example com type unavailable xml lang en status gone home status presence US presence from romeo example net orchard to mercutio example org type unavailable xml lang en status gone home status presence US presence from romeo example net orchard to nurse example com type unavailable xml lang en status gone home status presence source 最后该用户关闭他的流并且他的服务器以同样方式应答 示例17 用户关闭流 source lang xml UC stream stream source 示例18 用户的服务器关闭流 source lang xml US stream stream source 结束 处理XML节的服务器规则 处理XML节的基本服务器规则定义于 RFC6121 规范引用 XMPP CORE 读者可以参考那个协议的基础规则和安全含义 本章定义用于XMPP即时消息和出席信息服务器的附加规则 本章定义的一些递送规则指定了 离线存储 的使用 即 该服务器代表该用户存储一个消息节的行为以及当该用户下次上线的时候递送它 关于离线消息存储的建议 参考 RFC6121 参考文献 XEP 0160 常规事项 RFC6121 规范引用 XMPP CORE 讨论了节递送的常规事项 特别是在 i 提供一个关于节递送的服务的可接受级别 和 ii 防止目录捕获攻击和出席信息泄露 之间的平衡 无论如何 目录捕获攻击的概念不适用于一个已知并被一个用户信任的联系人 因为如 RFC6121 管理名册 第2章 所述该联系人在该用户的名册中 类似的 出席信息泄露的概念不适用于一个已被授权知道一个用户的出席信息的联系人 通过 RFC6121 管理出席信息订阅 第3章 所述的所谓出席信息订阅 或该用户曾经自发的发送出席信息给它的那个实体 如 RFC6121 定向出席信息 4 6 所述的的所谓定向出席信息 所以 下面章节的场景中用来防止目录捕获和出席信息泄露的替代方式有 a 安静地忽略一个节 或 b 返回一个错误 如果发起的实体在该用户的名册 当该错误将泄露该用户的帐号是否存在 或被授权从该用户接收出席信息 或已经从该用户接收到定向出席信息 当该错误将泄露一个用户的资源的出席信息 服务器应该返回一个错误 安全事项 接下来描述的所有节处理规则的定义 要理解它们将的应用 将遵循相关的隐私和安全行策略的强制检查 类似那些 RFC6121 参考文献 XEP 0016 或 RFC6121 参考文献 XEP 0191 的部署 接下来的章节中的一致性语言 MUST SHOULD 等等 不意味着覆盖任何本地服务策略 无 to 地址 如果该节无 to 属性 适用规则定义于 RFC6121 规范引用 XMPP CORE 远端域 如果包含在一个出站节的 to 属性中的地址的域部分和该服务器本身配置的域不匹配 则适用的规则见于 RFC6121 规范引用 XMPP CORE 的10 4节 互操作性备注 RFC 3921 定义了如何使用 im xmpp 和 pres xmpp SRV记录 RFC6121 参考文献 IMP SRV 作为一个应急方法来查询是否一个远端的即时消息和出席信息服务能通过以XMPP通讯 因为那些SRV记录未被广泛部署 本文不再定义它们的使用 并且不鼓励新的实现 本地域 如果在 to 属性中包含的JID的域部分和该服务器配置的域之一匹配 该域由该服务器本身 而不是由一个特别的本地服务 提供服务 并且该JID的格式为 domainpart 或 domainpart resourcepart 适用规则定义于 RFC6121 规范引用 XMPP CORE 本地用户 如果 to 地址指定了一个纯JID localpart domainpart 或全JID localpart domainpart resourcepart 该JID的域部分和由该服务器本身提供服务的已配置的域匹配 该服务器必需做如下处理 无该用户 如果由 to 属性而来的该用户帐号标识符不存在 该节如何处理取决于节类型 对于一个IQ节 该服务器必须返回一个 service unavailable 节错误给该发送者 对于一个message节 该服务器必需要么 a 安静地忽略该消息 要么 b 返回一个 service unavailable 节错误给该发送者 对于一个不带 type 属性或 type 属性为 unavailable 的的presence节 该服务器必须安静地忽略该节 对于一个类型为 subscribe subscribed unsubscribe 或 unsubscribed 的presence节 该服务器必须安静地忽略该节 对于一个类型为 probe 的presence节 该服务器必需要么 a 安静地忽略该节 要么 b 返回一个类型为 unsubscribed 的presence节 本地部分 域部分 如果 to 属性中包含的JID的格式为 localpart domainpart 那么该服务器必需遵循以下规则 可用或已连接的资源 如果至少有一个可用资源或已连接资源 如何处理该节取决于该节的类型 Message 对于一个类型为 normal 的消息节 如果所有可用资源有一个负的出席信息优先级 那么该服务器应该要么 a 存储该消息为离线用于晚些时候递送 要么 b 返回一个节错误给该发送者 该错误应该是 service unavailable 如果有一个可用资源而它是非负的出席信息优先级 那么该服务器必须递送该消息给那个资源 如果有多个可用资源都有非负的出席信息优先级 那么该服务器必须要么 a 递送该消息给 最可用的 资源或资源们 根据服务器的实现特有的机制 例如 认为拥有最高出席信息优先级的资源或资源们是 最可用的 要么 b 递送该消息给所有非负的资源 对于一个类型为 chat 的消息节 如果这个唯一的可用资源有一个负的出席信息优先级 那么该服务器应该要么 a 存储该消息为离线用于晚些时候递送 要么 b 返回一个节错误给该发送者 该错误应该是 service unavailable 如果这个唯一的可用资源有一个非负的出席信息优先级 那么该服务器必须递送该消息给那个资源 如果有多个可用资源都有非负的出席信息优先级 那么该服务器必须要么 a 递送该消息给 最可用的 资源或资源们 根据服务器的实现特有的机制 例如 认为拥有最高出席信息优先级的资源或资源们是 最可用的 要么 b 递送该消息给所有曾经被选择接收了聊天消息的非负的资源 对于类型为 groupchat 的消息节 该服务器不能 MUST NOT 递送该节给任何可用资源 而必须返回一个节错误给该发送者 该错误应该是 service unavailable 对于一个类型为 headline 的消息节 如果这个唯一的可用资源有一个负的出席信息优先级 那么该服务器必须安静地忽略该节 如果这个唯一的可用资源有一个非负的出席信息优先级 那么该服务器必须递送该消息给那个资源 如果有多个可用资源都有非负的出席信息优先级 那么该服务器必须递送该消息给所有非负的资源 对于类型为 error 的消息节 该服务器必须安静地忽略该消息 无论如何 对于任何消息类型 该服务器不能 MUST NOT 递送该节给任何负优先级的可用资源 如果只有一个可用资源且优先级为负 该服务器应该如 RFC6121 无可用或已连接的资源 8 5 2 2 所述 视同没有可用资源或已连接资源那样处理该消息 在所有情况下 该服务器不能 MUST NOT 重写 to 属性 即 它必须让它就是 localpart domainpart 而不是把它改成 localpart domainpart resourcepart Presence 对于一个没有类型或类型为 unavailable 的出席信息节 该服务器必须递送它到所有可用资源 对于一个类型为 subscribe subscribed unsubscribe 或 unsubscribed 的出席信息节 该服务器必须遵循 RFC6121 管理出席信息订阅 第3章 定义的规则和 RFC6121 附录A 订阅状态 附录A 的总结 对于一个类型为 probe 的出席信息节 该服务器必须如 RFC6121 出席信息探测 4 3 所述直接处理它 在所有情况下 该服务器不能 MUST NOT 重写 to 属性 即 它必须让它就是 localpart domainpart 而不是把它改成 localpart domainpart resourcepart IQ 对于一个IQ节 该服务器本身必须代表该用户应答一个IQ result 或一个IQ error 并且不能 MUST NOT 递送该IQ节给该用户的任何可用资源 特别是 如果限定的命名空间的语义定义了一个该服务器能代表该用户提供应答 那么该服务器必须代表该用户应答该节 要么返回一个类型为 result 的IQ节要么是一个类型为 error 的适合原始载荷的IQ节 否则 该服务器必须应答一个 service unavailable 节错误 无可用或已连接的资源 如果没有可用资源或已连接资源 如何处理该节取决于该节的类型 Message 对于一个类型为 normal 或 chat 的消息节 该服务器应该要么 a 添加该消息到离线存储 要么 b 返回一个节错误给该发送者 该错误应该为 service unavailable 对于一个类型为 groupchat 的消息节 该服务器必须返回一个节错误给该发送者 该错误应该为 service unavailable 对于一个类型为 headline 或 error 的消息节 该服务器必须安静地忽略该消息 Presence 对于一个没有类型或类型为 unavailable 的出席信息节 该服务器应该安静地忽略该节 不把它存下来用于晚些时候递送 也不代表该用户应答它 对于一个类型为 subscribe subscribed unsubscribe 或 unsubscribed 的出席信息节 该服务器必须遵循 RFC6121 管理出席信息订阅 第3章 定义的规则和 RFC6121 附录A 订阅状态 附录A 的总结 对于一个类型为 probe 的出席信息节 该服务器必须如 RFC6121 出席信息探测 4 3 所述直接处理它 IQ 对于一个IQ节 该服务器本身必须代表该用户应答一个IQ result 或一个IQ error 并且不能 MUST NOT 递送该IQ节给该用户的任何可用资源 特别是 如果限定的命名空间的语义定义了一个该服务器能代表该用户提供应答 那么该服务器必须代表该用户应答该节 要么返回一个类型为 result 的IQ节要么是一个类型为 error 的适合原始载荷的IQ节 否则 该服务器必须应答一个 service unavailable 节错误 本地部分 域部分 资源部分 如果一个入站节的 to 属性中包含的JID的域部分和该服务器本身配置的域之一匹配并且包含在 to 属性中的JID的格式为 localpart domainpart resourcepart 那么该服务器必须遵循以下规则 资源匹配 如果一个可用的资源或已连接的资源准确地匹配该全JID 如何处理该节取决于该节的类型 对于一个类型为 get 或 set 的IQ节 如果预期的接收者未通过类型为 both 或 from 的所谓出席信息订阅或通过所谓定向出席信息来分享出席信息给请求实体 那么该服务器不应该 SHOULD NOT 递送该IQ节 而应该返回一个 service unavailable 节错误给请求实体 这个策略帮助防止出席信息泄漏 见 RFC6121 安全事项 第11章 对于一个类型为 result 或 error 的IQ节 该服务器必须递送该节给该资源 对于一个消息节 该服务器必须递送该节给该资源 对于一个没有 type 属性或 type 属性为 unavailable

    Original URL path: http://wiki.jabbercn.org/index.php?title=RFC6121&action=edit (2016-04-25)
    Open archived version from archive

  • “RFC6121”的版本历史 - Jabber/XMPP中文翻译计划
    讨论 贡献 187 687字节 A 3 4 Unsubscribed 当前 先前 2013年7月23日 二 23 00 Admin 讨论 贡献 186 211字节 A 3 3 Subscribed 当前 先前 2013年7月23日 二 22 44 Admin 讨论 贡献 184 367字节 A 3 2 Unsubscribe 当前 先前 2013年7月23日 二 22 43 Admin 讨论 贡献 184 336字节 A 3 2 Unsubscribe 当前 先前 2013年7月23日 二 22 37 Admin 讨论 贡献 182 786字节 A 3 1 Subscribe 当前 先前 2013年7月23日 二 22 30 Admin 讨论 贡献 181 496字节 A 3 入站出席信息订阅节的服务器处理 当前 先前 2013年7月23日 二 22 21 Admin 讨论 贡献 180 944字节 A 2 4 Unsubscribed 当前 先前 2013年7月23日 二 22 19 Admin 讨论 贡献 179 877字节 A 2 3 Subscribed 当前 先前 2013年7月23日 二 22 16 Admin 讨论 贡献 178 834字节 A 2 2 Unsubscribe 当前 先前 2013年7月23日 二 22 15 Admin 讨论 贡献 177 878字节 A 2 1 Subscribe 当前 先前 2013年7月23日 二 22 10 Admin 讨论 贡献 176 798字节 A 2 出站出席信息订阅节的服务器处理 当前 先前 2013年7月23日 二 22 04 Admin 讨论 贡献 176 329字节 A 1 已定义的状态 当前 先前 2013年7月23日 二 17 30 Admin 讨论 贡献 173 267字节 附录A 订阅状态 当前 先前 2013年7月23日 二 17 28 Admin 讨论 贡献 173 072字节 参考文献 当前 先前 2013年7月23日 二 17 19 Admin 讨论 贡献 172 540字节 参考文献 当前 先前 2013年7月23日 二 17 18 Admin 讨论 贡献 168 024字节 参考 当前 先前 2013年7月23日 二 17 16 Admin 讨论 贡献 167 355字节 一致性需求 当前 先前 2013年7月23日 二 16 58 Admin 讨论 贡献 小 167 375字节 一致性需求 当前 先前 2013年7月23日 二 14 33 Admin 讨论 贡献 小 167 378字节 一致性需求 当前 先前 2013年7月23日 二 13 55 Admin 讨论 贡献 161 117字节 安全事项 当前 先前 2013年7月23日 二 13 12 Admin 讨论 贡献 157 886字节 国际化事项 当前 先前 2013年7月23日 二 13 11 Admin 讨论 贡献 157 802字节 URIs的处理 当前 先前 2013年7月23日 二 11 51 Admin

    Original URL path: http://wiki.jabbercn.org/index.php?title=RFC6121&action=history (2016-04-25)
    Open archived version from archive

  • 链接至“RFC6121”的页面 - Jabber/XMPP中文翻译计划
    隐藏 链接 隐藏 重定向 下列页面链接至 RFC6121 查看 上50个 下50个 20 50 100 250 500 首页 链入页面 RFC3921 链入页面 XEP 0144 链入页面 模板 最新消息 链入页面 RFC6120 链入页面 Jabber XMPP中文翻译计划 关于 链入页面 XEP 0016 链入页面 Jabber XMPP中文翻译计划 新闻动态 链入页面 RFC6121 链入页面 XEP 0147 链入页面 XEP 0134 链入页面 查看 上50个 下50个 20 50 100 250 500 来自 http wiki jabbercn org E7 89 B9 E6 AE 8A E9 93 BE E5 85 A5

    Original URL path: http://wiki.jabbercn.org/%E7%89%B9%E6%AE%8A:%E9%93%BE%E5%85%A5%E9%A1%B5%E9%9D%A2/RFC6121 (2016-04-25)
    Open archived version from archive

  • RFC6121 - Jabber/XMPP中文翻译计划
    to juliet example com balcony type error error type modify item not found xmlns urn ietf params xml ns xmpp stanzas error iq 名册版本 流特性 如果一个服务器支持名册版本 那么它必须在流协商期间声明以下流特性 ver xmlns urn xmpp features rosterver 名册版本流特性很少见所以永远不会是强制协商的 请求 如果一个客户端支持名册版本并且它所连接的服务器如前一节说的那样声明支持名册版本 那么该客户端应该在它对名册请求中包含 ver 元素 如果该服务器没有声明支持名册版本 客户端不能 MUST NOT 包含 ver 属性 如果客户端在它的roster get中包含了 ver 属性 它就把该属性的值设成了它最后的名册缓存中的相关的版本ID C iq from romeo example net home id r1h3vzp7 to romeo example net type get query xmlns jabber iq roster ver ver14 iq 如果该客户端还未缓存该名册或该缓存遗失或被中断了 但是该客户端希望引导名册版本的使用 它必须把 ver 属性设为空字符串 即 ver 自然的 如果该客户端不支持名册版本或不希望引导名册版本的使用 它将不包含 ver 属性 成功情景 无论名册从被客户端列举版本ID之后是否被修改过 服务器必须要么如 章节2 1 4 包含一个 ver 属性代表最后的版本 所述返回完整的名册 要么返回一个空的IQ result 这样就表示任何名册的修改将通过roster pushes被发送 如下所述 通常 除非返回完整名册 1 将比发送独立的roster pushes给客户端使用更少的带宽 例如 如果名册只包含很少的条目 或 2 服务器不能把版本ID关联到任何之前已经在文件中有的版本 服务器应该发送一个空的IQ result然后通过roster pushes发送修改 如果有的话 S iq from romeo example net id r1h3vzp7 to romeo example net home type result 实现备注 这个空的IQ result不同于一个空的 query 元素 这和使用一个空名册是不同的 如果允许使用名册版本并且名册从被客户端列举版本ID之后未被修改过 服务器将简单地不发送任何roster pushes给客户端 直到并且除非在该客户端会话的生命周期中一些相关的事件触发一个roster push 如果名册从被客户端列举版本ID之后被修改过 那么该服务器必须为每一个从被客户端列举版本ID之后被修改过的条目发送一个roster push给该客户端 我们把一个用于名册版本同步的被发送的roster push称为一个 暂时的roster push 定义 一个 roster modification 表示对名册数据的任何改变并将导致一个roster push到已连接客户端 所以 和服务器对名册处理相关的内部状态将不会导致一个roster push到已连接客户端因而不需要改变版本 S iq from romeo example net id ah382g67 to romeo example net home type set query xmlns jabber iq roster ver ver34 item jid tybalt example org subscription remove query iq S iq from romeo example net id b2gs90j5 to romeo example net home type set query xmlns jabber iq roster ver ver42 item jid bill example org subscription both query iq S iq from romeo example net id c73gs419 to romeo example net home type set query xmlns jabber iq roster ver ver72 item jid nurse example org name Nurse subscription to group Servants group item query iq S iq from romeo example net id dh361f35 to romeo example net home type set query xmlns jabber iq roster ver ver96 item jid juliet example org name Juliet subscription both group VIPs group item query iq 这些 暂时的roster pushes 可以作如下理解 想想客户端在它缓存的名册版本 假设是 ver14 和新的名册版本 假设是 ver96 之间有一个活跃的出席信息会话 在此期间 该客户端可能已经接收到一个和各种名册版本相关的roster pushes 它可能已经发生 假设是 ver51 和 ver79 无论如何 这些roster pushes中的一些可能已经包含了同一个名册条目的中间更新 例如 把对bill example org的订阅状态从 none 改为 to 又从 to 改为 both 这个暂时的roster pushes将不包含所有中间步骤 而只有在该客户端实际上离线的时候每个条目修改后的最终结果 这可能发生 假设是 ver34 ver42 ver72 和 ver96 客户端必须和处理任何roster push一样处理一个 interim roster push 实际上 从客户端的视角不能说一个 暂时的 roster push和一个 live 的 roster push是不同的 因而当它没办法知道自己收到是否是暂时的roster pushes 当重连后请求名册 客户端应该请求和它在前一个会话中收到的最后的roster push相关的版本 而不是它在前一个会话的开始时收到的roster result的相关版本 当名册版本被允许 服务器必须在每一个roster push中包含更新的名册版本 Roster pushes必须按照变更的顺序产生并且在一个roster push中包含的版本必须是唯一的 即使客户端未在它的roster gets或sets 中包含 ver 属性 服务器也应该在它发送给客户端的所有roster pushes和results中包含 ver 属性 实现备注 名册版本的指南和详细例子见 XEP 0237 管理出席信息订阅 为了保护XMPP用户们的隐私 出席信息仅向某个用户已经批准的其他实体披露 当某个同意允许其他实体察看其出席信息时 该实体被称为对该用户的出席信息有一个 订阅 subscription 一个对某用户的出席信息有订阅的实体或一个用户对其有出席信息订阅的实体被称为 联系人 contact 在本文中术语 联系人 contact 在不严格的概念上也用于指代潜在的联系人或一个用户的名册中的任何条目 在XMPP中 一个订阅是超越出席信息会话存在的 实际上 直到联系人取消订阅或用户撤销之前已授权的订阅之前它都会持续存在 这个模式不同于会话初始协议 SIP 中对出新信息订阅的使用 参见 SIP PRES 在XMPP中订阅的管理是通过发送包含特别定义的属性 subscribe unsubscribe subscribed 和 unsubscribed 的presence节来实现的 实现备注 当一个服务器处理或生成一个类型为 subscribe subscribed unsubscribe 或 unsubscribed 的出站出席信息节 该服务器必须在出站出席信息节中标记发送的实体的纯JID localpart domainpart 而不是全JID localpart domainpart resourcepart 这个规则的强制性简化了出席信息订阅的模式并且有助于防止出席信息泄露 关于出席信息泄露的信息 参见 XMPP CORE 的安全事项 订阅状态在用户和联系人两边的名册中都可以被反映 本章不覆盖每个和出席信息订阅相关的可能的情景 而主要是讲述一个用户和一个联系人之间开启一个共同的订阅的协议流程 关于订阅状态的完整细节可以在 附录A 中找到 请求订阅 一个 订阅请求 subscription request 是一个某用户为了得到永久性地订阅某个联系人出席信息的授权而发出的请求 语法构成上它是一个 type 属性值为 subscribe 的presence节 一个订阅请求由某用户客户端生成 由 潜在的 联系人的服务器处理 从表现上来看则是联系人通过联系人的客户端来处理 以下章节描述其工作流程 实现备注 出席信息订阅请求被发送到可用的资源 然而和订阅状态变更相关的名册推送被发送到感兴趣的资源 所以 如果一个资源希望同时接收到订阅请求和名册推送 它必须同时发送初始出席信息和请求名册 客户端生成出站订阅请求 一个用户的客户端发送一个类型为 subscribe 并且指定了一个潜在联系人的纯JID contact domainpart 为 to 地址的presence节 生成一个订阅请求 UC presence id xk3h1v69 to juliet example com type subscribe 当一个用户发送一个出席信息订阅请求给一个潜在的即时消息和出席信息联系人 其 to 属性的值必须是一个纯JID contact domainpart 而不是一个全JID contact domainpart resourcepart 因为预期的结果是该用户从该联系人的所有资源接收出席信息 而不仅是在 to 属性中指定的特定资源 纯JIDs的使用也简化了该用户的服务器和联系人的服务器的订阅过程 出席信息探测 和出席信息通知 为了跟踪的目的 客户端应该在一个出席信息订阅请求中包含一个 id 属性 实现备注 很多XMPP客户端在生成一个出站出席信息订阅的时候向用户提示关于潜在联系人的信息 例如 handle 以及期望的名册组 因而在发送该出站出席信息订阅请求之前发送一个roster set 这个行为是可选的 因为客户端在上传用户提供的关于该联系人的信息之前可以先等待从服务器接收初始的roster push 服务器必须以任何顺序处理roster set和出站出席信息订阅请求 即 以客户端生成的任何顺序 服务器处理出站订阅请求 接收出站出席信息订阅请求之后 该用户的服务器必须处理如下 在处理该请求之前 该用户的服务器必须检查包含在 to 属性中的JID的语法 无论如何 据信一些现有的实现不执行这个检查 如果该JID的格式是 contact domainpart resourcepart 而不是 contact domainpart 该用户的服务器应该把该请求当成是指向该联系人的纯JID并据此修改 to 地址 该服务器也可以遵循 XMPP ADDR 定义的格式来检查该JID地址并可能返回一个 jid malformed 节错误 如果潜在的联系人位于和该用户相同的服务器上 那么在处理该订阅请求和递送它到本地联系人的时候该服务器必须遵循 章节3 1 3 定义的规则 如果潜在的联系人位于一个远端服务器 受本地服务策略的约束该用户的服务器必须接着按照核心XMPP节处理规则路由该节到那个远端的域 这可能导致返回一个适当的节错误给该用户 类似 remote server timeout 如上所述 在本地递送或远程路由该出席信息订阅请求之前 该用户的服务器必须给该出站订阅请求标记该用户的纯JID user domainpart US presence from romeo example net id xk3h1v69 to juliet example com type subscribe 如果该出席信息订阅请求不是本地递送或远程路由的 例如 因为该请求格式异常 该本地联系人不存在 该远程服务器不存在 尝试联系远端服务器超时 或任何被该用户的服务器经历或确认的其他错误 那么该用户的服务器必须返回一个适当的错误节给该用户 例子如下 US presence from juliet example com id xk3h1v69 to romeo example net type error error type modify remote server not found xmlns urn ietf params xml ns xmpp stanzas error presence 在本地递送或远程路由该出席信息订阅请求之后 该用户的服务器必须接着发送一个roster push给所有该用户的感兴趣的资源 包含带一个 none 订阅状态并且带一个表明订阅等待批准符号 一个值为 subscribe 的 ask 属性 的潜在联系人 US iq id b89c5r7ib574 to romeo example net foo type set query xmlns jabber iq roster item ask subscribe jid juliet example com subscription none query iq US iq id b89c5r7ib575 to romeo example net bar type set query xmlns jabber iq roster item ask subscribe jid juliet example com subscription none query iq 如果一个远端联系人在可配置的时间内不批准或拒绝该订阅请求 该用户的服务器应该基于一个实现特有的机制重新发送该订阅请求给该联系人 例如 任何该用户的一个新资源可用的时候 或在过了一个特定数量的时间之后 这有助于从原有的订阅请求被路由到远程域发生的短暂的 无声的错误中恢复 这样做的时候 建议该服务器包含一个 id 属性 这样它能跟踪重发的订阅请求的应答 服务器处理入站订阅请求 在处理入站出席信息订阅请求之前 联系人的服务器应该检查包含在 to 属性中的JID的语法 如果该JID的格式是 contact domainpart resourcepart 而不是 contact domainpart 该联系人的服务器应该把该请求当成是被指向该联系人的纯JID并据此修改 to 地址 该服务器也可以遵循 XMPP ADDR 定义的格式来检查该JID地址并可能返回一个 jid malformed 节错误 处理入站出席信息订阅请求的时候 联系人的服务器必须遵循以下规则 1 首先 联系人的服务器不能 MUST NOT 以联系人的身份批准订阅请求 除非该来联系人已经 a 如 章节3 4 所述预批准来自用户的订阅请求 b 配置它的账户自动批准订阅请求 或 c 从它的服务器提供者那里接受了一个协议以允许自动批准 例如 在一个企业部署之中通过一个雇佣协议 否则 如果一个订阅请求要求批准那么联系人的服务器必须递送那个请求到联系人的可用资源并由该联系人批准或拒绝 2 如果联系人存在并且该用户已经有一个对该联系人的出席信息的订阅 那么该联系人的服务器必须把一个类型为 subscribed 的presence节从该联系人的纯JID发送到该用户的纯JID以代表该联系人自动应答 同样 如果该联系人以前发送过一个类型为 subscribed 的presence节并且联系人的服务器假设对于该用户的出席信息订阅是 预批准的 见 章节3 4 那么该联系人的服务器也应该以该联系人的身份自动应答 CS presence from juliet example com id xk3h1v69 to romeo example net type subscribed 3 另外 如果在订阅请求被联系人的服务器接收到的时候该联系人有至少一个可用的资源 那么该联系人的服务器必须依据 第八章 发送那个订阅请求给所有可用的资源 作为获得该出席信息订阅请求的回执的一个方法 该联系人的服务器可以从该联系人的纯JID发送一个类型为 unavailable 的presence节到该用户的纯JID 该用户的客户端不能 MUST NOT 假定这个回执提供了关于该联系人的出席信息 因为它来自该联系人的纯JID并且在该订阅请求被批准之前就收到了 4 另外 如果在订阅请求被联系人的服务器接收到的时候该联系人没有可用的资源 那么该联系人的服务器必须保持一个完整的包括该订阅请求的presence节的记录 包括其中任何扩展的内容 见 XMPP CORE 的章节8 4 并且在该联系人接下来有一个可用的资源的时候递送该请求 无论何时该联系人建立了一个可用的资源该联系人的服务器必须继续递送该订阅请求 直到该联系人要么批准要么拒绝该请求 当该联系人接下来有一个可用的资源的时候 该联系人的服务器不能 MUST NOT 从任何给定用户递送多个订阅请求 例如 如果该用户发送多个订阅请求到该联系人而此时该联系人是离线的 该联系人的服务器应该只存储那些请求中的一个 比如第一个请求或最后一个请求 并且当该联系人接下来有一个可用资源的时候必须只递送这些请求中的一个 这有助于防止 垃圾订阅请求 安全警告 直到以及除非该联系人如 章节3 1 4 所述批准该订阅请求 该联系人的服务器不能 MUST NOT 在该联系人的名册上添加该用户的条目 安全警告 对于联系人的服务器存储完整的出席信息订阅请求的节的强制要求带来了一个应用程序资源衰竭攻击的可能性 见 DOS 的章节2 1 2 例如 由一个流氓服务器或一个协调好的用户群 例如 一个 botnet 攻击该联系人的服务器或特定联系人 提醒服务器实现者们关注这类攻击的可能性并为对抗它提供工具 比如允许服务管理员设置服务器整体或任何给定联系人存储的入站出席信息订阅请求的数量或大小的限制 客户端处理入站订阅请求 当一个可交互的客户端接收到一个订阅请求 它必须把该请求展示给控制该客户端的自然人 即 该 联系人 来批准 除非该联系人被显式地配置成该客户端自动批准或拒绝如上所述的某些或全部订阅请求 一个不是被自然人控制的自动客户端将有自己的应用特有的规则以批准或拒绝订阅请求 客户端通过发送一个类型为 subscribed 的presence节来批准一个订阅请求 联系人的服务器会作 章节3 1 5 所述的处理 用户的服务器会作 章节3 1 6 所述的处理 CC presence id h4v1c4kj to romeo example net type subscribed 客户端通过发送一个类型为 unsubscribed 的presence节来拒绝一个订阅请求 联系人的服务器和用户的服务器都会作 章节3 2 所述的处理 CC presence id tb2m1b59 to romeo example net type unsubscribed 为了跟踪的目的 客户端应该在一个订阅批准或订阅拒绝中包含一个 id 属性 这个 id 属性不能 MUST NOT 镜像该订阅请求的 id 属性 服务器处理出站订阅批准 当联系人的客户端发送订阅批准的时候 联系人的服务器必须以联系人的纯JID contact domainpart 标记这个出站的节并本地递送或远程路由该节到用户那里 CS presence from juliet example com id h4v1c4kj to romeo example net type subscribed 联系人的服务器接着必须发送一个updated roster push 更新名册推送 给所有联系人的感兴趣的资源 其中的 subscription 属性值设为 from 这里假定该联系人未曾订阅该用户 如果是那种情况 译者注 即该联系人已经订阅该用户 则 subscription 属性值将设置为 both 如 附录A 所述 CS iq id a78b4q6ha463 to juliet example com balcony type set query xmlns jabber iq roster item jid romeo example net subscription from query iq CS iq id x81g3bdy4n19 to juliet example com chamber type set query xmlns jabber iq roster item jid romeo example net subscription from query iq 从联系人的视角来看 现在存在一个来自用户的订阅 这就是为什么 subscription 属性值要设为 from 这里假定该联系人未曾订阅该用户 如果是那种情况 译者注 即该联系人已经订阅该用户 则 subscription 属性值将设置为 both 如 附录A 所述 该联系人的服务器接着也必须从该联系人的可用资源发送当前的出席信息给给该用户 CS presence from juliet example com balcony id pw72bc5j to romeo example net CS presence from juliet example com chamber id ux31da4q to romeo example net 为了订阅该用户的出席信息 该联系人需要发送一个订阅请求给该用户 XMPP客户端经常会自动发送订阅请求而不是要求联系人发起这个订阅请求 因为假定期望的结束状态是一个双向订阅 自然 当该联系人发送一个订阅请求给该用户 这个订阅状态将不同于前面示例中展示的状态 见 附录A 并且角色将被反转 服务器处理入站订阅批准 当用户的服务器收到一个订阅批准 它必须首先检查是否该联系人在该用户的名册中并且 subscription none 或 subscription from 以及 ask 标记设为 subscribe 即 订阅状态为 None Pending Out None Pending Out In 或 From Pending Out 见 附录A 如果这个检查成功了 那么该用户的服务器必须 1 递送入站订阅批准到该用户的所有感兴趣的资源 这有助于给该用户的客户端关于订阅批准的正确的上下文 使得它们能分辨由该用户的另一个资源生成的名册推送和从联系人收到的订阅批准的不同 这一步必须在下一步的发送名册推送之前去做 US presence from juliet example com id h4v1c4kj to romeo example net type subscribed 2 发起一个roster push给该用户的所有感兴趣的资源 包含一个该 联系人的更新的名册条目 其 subscription 属性值设为 to 如果订阅状态是 None Pending Out 或 None Pending Out In 或 both 如果订阅状态是 From Pending Out US iq id b89c5r7ib576 to romeo example net foo type set query xmlns jabber iq roster item jid juliet example com subscription to query iq US iq id b89c5r7ib577 to romeo example net bar type set query xmlns jabber iq roster item jid juliet example com subscription to query iq 3 该用户的服务器也必须把从该联系人的每个可用资源收到的可用的出席信息节递送给该用户的每个可用资源 to resource1 US presence from juliet example com balcony id pw72bc5j to romeo example net to resource2 US presence from juliet example com balcony id pw72bc5j to romeo example net to resource1 US presence from juliet example com chamber id ux31da4q to romeo example net to resource2 US presence from juliet example com chamber id ux31da4q to romeo example net 实现备注 如果在收到入站订阅批准通知的时候该用户的帐号没有可用资源 该用户的服务器可以保持该通知的记录 理想的是完整的出席信息节 并且等到该帐号有一个可用资源的时候再递送给它 这一行为向用户提供了当用户离线的时候发生名册变更的原因的更完整的信息 另外 就是 如果该用户不存在 如果该联系人不在该用户的名册中 或如果该联系人在该用户的名册中但是订阅状态不在前述的检查中描述的情况之中 那么该用户的服务器必须安静地忽略该订阅批准通知而不递送给该用户 也不修改该用户的名册 也不生成名册推送到该用户的感兴趣的资源 从该用户的角度来看 现在存在一个到该联系人的出席信息的订阅 这就是为什么 subscription 属性值要设为 to 撤销被订阅 客户端生成撤销被订阅 如果一个联系人想撤销它之前接受某个用户订阅的授权 以撤销一个预批准的被订阅 章节3 4 或拒绝一个订阅请求 它发送一个类型为 unsubscribed 的出席信息节 CC presence id ij5b1v7g to romeo example net type unsubscribed 服务器处理出站被订阅撤销 在接收到出站被订阅撤销之后 该联系人的服务器必须做如下处理 如果该用户的纯JID还不在该联系人的名册或在联系人名册中的状态是 None None Pending Out 或 To 该联系人的服务器不能 SHOULD NOT 路由或递送类型为 unsubscribed 的出席信息节给该用户 并且不能 MUST NOT 发送接下来所说的类型为 unavailable 的出席信息通知给该用户 如果该用户的纯JID在该联系人的名册的状态为 None None Pending Out 或 To 并且 approved 标记被设为 true 所以代表了 章节3 4 所述的订阅预批准 该联系人的服务器必须移除该 预批准 并且不能 MUST NOT 路由或递送类型为 unsubscribed 的出席信息节给该用户 否则 按如下的示例 该联系人的服务器必须同时路由或递送类型为 unavailable 的出席信息通知和类型为 unsubscribed 的出席信息节给该用户 并且必须发送一个名册推送给该联系人 因为该用户仍然订阅了该联系人的出席信息 即 在该联系人的服务器路由或递送类型为 unsubscribed 的出席信息给该用户之前 该联系人的服务器必须从该联系人的所有在线资源发送一个类型为 unavailable 的出席信息节给该用户 CS presence from juliet example com balcony id i8bsg3h3 type unavailable CS presence from juliet example com chamber id bvx2c9mk type unavailable 然后该联系人的服务器必须路由或递送类型为 unsubscribed 的出席信息节给该用户 确保在出站被订阅取消要带上该联系人的纯JID contact domainpart CS presence from juliet example com id ij5b1v7g to romeo example net type unsubscribed 该联系人从的服务器必须发送一个带有更新的名册条目的名册推送给该联系人的所有感兴趣的资源 这里订阅状态现在要么是 none 要么是 to 见 附录A CS iq id pw3f2v175b34 to juliet example com balcony type set query xmlns jabber iq roster item jid romeo example net subscription none query iq CS iq id zu2y3f571v35 to juliet example com chamber type set query xmlns jabber iq roster item jid romeo example net subscription none query iq 服务器处理入站被订阅撤销 当用户的服务器接收到入站被订阅撤销后 它必须首先检查该联系人是否在该用户的名册中并且 subscription to 或 subscription both 见 附录A 如果这个检查成功了 那么该服务器必须 1 递送该入站被订阅撤销到该用户的所有感兴趣的资源 这有助于给该用户的客户端正确的关于订阅被撤销的上下文 使得它们能区分由用户的另一个资源产生的名册推送和从该联系人收到的订阅被撤销 这个动作必须在发送下一步所述的名册推送之前进行 US presence from juliet example com id ij5b1v7g to romeo example net type unsubscribed 2 发起一个名册推送给该用户的所有感兴趣的资源 包含一个该联系人的更新的名册条目 其 subscription 属性值设为 none 如果之前的订阅状态为 To 或 To Pending In 或 from 如果订阅状态为 Both US iq id h37h3u1bv400 to romeo example net foo type set query xmlns jabber iq roster item jid juliet example com subscription none query iq US iq id h37h3u1bv401 to romeo example net bar type set query xmlns jabber iq roster item jid juliet example com subscription none query iq 该用户的服务器也必须递送类型为 unavailable 的入站出席信息节 实现备注 如果收到该入站被撤销订阅通知的时候 该用户的帐号没有可用的资源 该用户的服务器可以保持一个通知记录 理想的情况是完整的出席信息节 然后在该帐号下次有可用资源的时候递送该通知 这一行为把该用户离线期间发生的名册变更的原因提供了更完整的信号给该用户 另外 就是 如果该用户不存在 如果该联系人不在该用户的名册中 或如果该联系人在该用户的名册中的订阅状态不是前述检查所描述的那些状态 那么该用户的服务器必须安静地忽略该被取消订阅通知而不把它递送给该用户 也不修改该用户的名册 以及不生成名册推送给该用户的感兴趣的资源 取消订阅 客户端生成取消订阅 如果一个用户想取消订阅一个联系人的出席信息 它发送一个类型为 unsubscribe 的出席信息节 UC presence id ul4bs71n to juliet example com type unsubscribe 服务器处理出站取消订阅 在接收到出站取消订阅之后 该用户的服务器必须做如下处理 如果联系人和该用户在同一台服务器上 那么当该服务器处理订阅请求时必须遵循 3 3 3 定义的规则 如果联系人位于远端服务器上 按照本地服务策略 该用户的服务器必须接着把该节路由到那个远端域以满足核心XMPP节处理规则 这可能导致返回适当的节错误给该用户 类似 remote server timeout 如前所述 在本地递送或远程路由取消订阅之前 该用户的服务器必须在该节上标记该用户的纯JID user domainpart US presence from romeo example net id ul4bs71n to juliet example com type unsubscribe 该用户的服务器接着必须发送一个带有更新的名册条目的名册推送给该用户的所有感兴趣的资源 这里的订阅状态就变成要么是 none 要么是 from 见 RFC6121 附录 A 订阅状态 附录A US iq id h37h3u1bv402 to romeo example net foo type set query xmlns jabber iq roster item jid juliet example com subscription none query iq US iq to romeo example net bar type set id h37h3u1bv403 query xmlns jabber iq roster item jid juliet example com subscription none query iq 服务器处理入站取消订阅 当联系人的服务器收到取消订阅通知 它必须首先检查该用户的纯JID是否在该联系人的名册中且subscription from 或subscription both 即 订阅状态为 From From Pending Out 或 Both 见 附录A 如果这个检查成功了 接着该联系人的服务器必须 1 把入站取消订阅递送给该联系人的所有感兴趣的资源 这有助于向联系人的客户端们提供关于取消订阅的正确的上下文 这样它们就能区分是由联系人的另一个资源产生的名册推送还是从该用户收到的取消订阅 这个动作必须发生在下面所说的发送名册推送步骤之前 CS presence from romeo example net id ul4bs71n to juliet example com type unsubscribe 2 发起一个名册推送给该联系人的所有感兴趣的资源 为该用户包含一个更新的条目并把 subscription 属性值设为 none 如果之前的订阅状态是 From 或 From Pending Out 或 to 如果之前的订阅状态是 Both CS iq id tn2b5893g1s4 to juliet example com balcony type set query xmlns jabber iq roster item jid romeo example net subscription none query iq CS iq id sp3b56n27hrp to juliet example com chamber type set query xmlns jabber iq roster item jid romeo example net subscription none query iq 3 从该联系人的每一个可用资源生成一个类型为 unavailable 的出站出席信息节给该用户 CS presence from juliet example com balcony id o5v91w49 to romeo example net type unavailable CS presence from juliet example com chamber id n6b1c37k to romeo example net type unavailable 实现备注 如果在收到入站取消订阅通知的时候该联系人的帐号没有可用资源 该联系人的服务器可以保持一个通知记录 理想情况下是完整的出席信息节 并且接着在该帐号下次有一个可用资源的时候递送该通知 这一行为为该用户提供了关于该用户离线时发生的名册变更的更完整的信息 另外 就是 如果该联系人不存在 如果该用户不在该联系人的名册中 或如果该用户的纯JID在该联系人的名册中并且订阅状态不同于前面检查所述的结果 那么该联系人的服务器必须安静地忽略该取消订阅节 不递送给该联系人 不修改联系人的名册 也不生成名册推送给该联系人的所有感兴趣的资源 无论如何 如果该联系人的服务器持续跟踪一个从该用户到该联系人的入站出席信息订阅请求但是该用户仍不在该联系人的名册中 功能上相当于一个订阅状态 None Pending In 这里该联系人从未添加该用户到联系人的名册中 那么该联系人的服务器必须简单地移除该入站出新信息订阅请求的记录 它无法从该联系人的名册中移除该用户 因为该用户从未被加入到该联系人的名册中 实现备注 该用户的客户端不能 MUST NOT 依赖于从该联系人收到的取消订阅出席信息通知 因为它必须考虑对该联系人的出席信息订阅 以及关于该联系人的出席信息 当它发送类型为 unsubscribe 的出席信息节或它收到由取消订阅请求触发的名册推送的时候为无或空 预批准被订阅请求 如果一个用户还未从一个联系人那里接收到订阅请求 该用户可以 预批准 这样一个请求 这样它将被该用户的服务器自动地批准 对订阅预批准的支持在客户端和服务器上都是可选的 如果一个服务器支持订阅预批准 那么它必须在流协商时声明以下流特性 sub xmlns urn xmpp features pre approval 订阅预批准流特性只不过有一点用 所以永远不会强制协商 客户端生成被订阅预批准 如果客户端所连接的服务器声明了订阅预批准 该客户端可以通过发送一个类型为 subscribed 的节给该联系人以生成一个订阅预批准 UC presence id pg81vx64 to juliet example com type subscribed 如果该服务器未声明支持订阅预批准 该客户端不能 MUST NOT 尝试预批准来自潜在的或者实际的联系人的订阅请求 服务器处理被订阅预批准 在接收到类型为 subscribed 的出席信息节之后 该用户的服务器如果支持订阅预批准 必须做如下处理 如果该联系人在该用户的名册中且状态为 Both From 或 From Pending Out 该用户的服务器必须安静地忽略该节 如果该联系人在该用户的名册中且状态为 To Pending In None Pending In 或 None Pending Out In 该用户的服务器必须如普通的订阅批准那样处理该节 见 3 1 5 更新现有的名册条目的状态成为 Both From 或 From Pending Out 分别的 推送修改的名册条目到该用户的所有感兴趣的资源 并路由该类型为 subscribed 的出席信息节到该联系人 如果该联系人在该用户的名册中且状态为 To None 或 None Pending Out 该用户的服务器必须把 approved 标记的值设置为 true 来记录订阅预批准 然后推送修改的名册条目到该用户的所有感兴趣的资源 无论如何 该用户的服务器不能 MUST NOT 路由该类型为 subscribed 的出席信息节到该联系人 如果该联系人还不在该用户的名册中 那么该用户的服务器必须为该联系人创建一个名册条目且状态为 None 并且把 approved 标记的值设为 true 然后推送该名册条目到该用户的所有感兴趣的资源 无论如何 该用户的服务器不能 MUST NOT 路由该类型为 subscribed 的出席信息节到该联系人 一个名册推送的示例如下 US iq id h3bs81vs763f to romeo example net bar type set query xmlns jabber iq roster item approved true jid juliet example com subscription none query iq 当 approved 标记被设为 true 该用户的服务器不能 MUST NOT 从该联系人递送一个类型为 subscribe 的出席信息节给该用户 而是必须代表该用户自动应答这样一个节 即从该用户的纯JID返回一个类型为 subscribed 的出席信息节给该联系人的纯JID 实现备注 服务器在已经从该联系人接收到了一个出席信息订阅请求之后是否维护一个订阅批准记录 对于实现或本地服务策略来说是个问题 如果该服务器不维护这样一个记录 在接收该订阅请求之后它将在该名册条目中不为该联系人包含 approved 属性 即 在随后的名册推送和名册结果中 如果该服务器维护这样一个记录 它将在名册条目中总是为该联系人包含 approved 属性 设为 true 直到或除非该用户发送一个类型为 unsubscribed 的出席信息节到该联系人 或从名册中完全移除该联系人 实现备注 客户端能通过发送一个类型为 unsubscribed 的出席信息节取消一个预批准 更全面的描述在 3 2 在这种情况下 该用户的服务器将发送一个名册推送给该有用户的所有感兴趣的资源 而其 approved 属性是被移除的 另一种选择是 该客户端能简单地完全移除该名册条目 交换出席信息 出席信息原理 出席信息是指在网络上通讯的一个实体的可用性 在最基本的层面上 出席信息是一个 on off 的逻辑变量以标记一个实体可不可以通讯 也用术语 在线 和 离线 在XMPP中 当客户端生成一个不带 type 属性的 presence 节时就标记了一个实体的可用性 当它的客户端生成一个 type 属性值为 unavailable 的 presence 节时表示一个实体失去了可用性 XMPP出席信息典型地遵循一个 发布 订阅 或 观察者 模式 这里 一个实体发送出席信息给它的服务器 它的服务器接着广播那个信息给所有订阅了该实体的出席信息的联系人 在 IMP MODEL 的术语中 一个生成出席信息的实体就是一个 presentity 并且那些接收出席信息的实体们是 subscribers 一个客户端通过发送一个不带 to 地址的出席信息节给它的服务器来生成出席信息用于广播给所有已订阅的实体们 这里的出席信息既没有 type 属性又没有值为 unavailable 的 type 属性 这种出席信息被称为 广播出席信息 一个客户端也可以发送 定向出席信息 即 一个带 to 地址的出席信息节 这不太常见但是有时被用于发送出席信息给那些没有订阅该用户的出席信息的实体们 见 4 6 在一个客户端完成 XMPP CORE 定义的先决条件之后 它能通过发送初始化出席信息在它的服务器建立一个 出席信息会话 通过发送unavailable出席信息可以中止这个出席信息会话 在它的出席信息会话期间 一个已连接的资源 XMPP CORE 中的术语 被称为一个 可用的资源 在XMPP中 应用集合了消息和出席信息功能 它的出席信息标记的可用性的缺省通讯类型是消息 然而 对于XMPP应用来说把消息和出席信息功能集合到一起并不是必要的 它们能提供独立的不带消息的出席信息特性 另外 XMPP服务器们不会为了成功地路由message和IQ节而强制要求关于网络可用性的信息 提示备注 在接下来的例子中 用户是 juliet example com 她有两个可用的资源 balcony 和 chamber 而在她的名册中有三个联系人且订阅状态为 from 或 both romeo example net mercutio example com 和 benvolio example net 初始化出席信息 客户端生成初始化出席信息 在完成 XMPP CORE 必需的 中所述的前提条件并请求名册 推荐的 之后 一个客户端通过发送 初始化出席信息 给它的服务器来标记它的通讯可用性 即 一个不带 to 地址 意思是由该服务器代表该客户端广播它 和 type 属性 表示该用户的可用性 的出席信息节 UC presence 该初始化出席信息可以包含 priority 元素 show 元素 一个一个或多个 status 元素实例 以及扩展内容 细节见 4 7 服务器处理出站初始化出席信息 从一个客户端接收到初始化出席信息之后 该用户的服务器必须从该用户的全JID user domainpart resourcepart 发送该出席信息节给所有订阅了该用户的出席信息的联系人 这些联系人的JID目前正在该用户的名册中且 subscription 属性值为 from 或 both US presence from juliet example com balcony to romeo example net US presence from juliet example com balcony to mercutio example com US presence from juliet example com balcony to benvolio example net 该用户的服务器也必须从该用户的新的可用资源广播初始化出席信息给该用户的所有可用资源 包括在第一个地方生成该出席信息通知的那个资源 即 一个实体隐形地订阅了它自己的出席信息 to the balcony resource US presence from juliet example com balcony to juliet example com to the chamber resource US presence from juliet example com balcony to juliet example com 在缺少关于该用户的联系人的出席信息的情况下 该用户的服务器也必须代表该用户发送出席信息探测给该用户的联系人 如 4 3 所述 服务器处理入站初始化出席信息 在从该用户接收到出席信息之后 该联系人的服务器必须递送该用户的出席信息节给该联系人的所有可用资源 to resource1 CS presence from juliet example com balcony to romeo example net to resource2 CS presence from juliet example com balcony to romeo example net 客户端处理初始化出席信息 当该联系人的客户端从该用户接收到出席信息之后 对于可交互的客户端推荐以下行为 如果该用户的纯JID在该联系人的名册中 在一个适当的名册接口中显示该出席信息 如果该用户不在该联系人的名册中但是联系人正在交换message或IQ节 为了那个通讯会话在该用户的接口中显示该出席信息 参见 4 6 和 5 1 其他情况下 忽略出席信息并且不把它显示给该联系人 出席信息探测 一个 出席信息探测 是一个对某联系人的当前出席信息的请求 由代表某个用户的服务器代表该用户发送 语法上它是一个 type 属性值为 probe 的出席信息节 在出席信息订阅的上下文中 from 地址的值必须是订阅的用户的纯JID而 to 地址的值必须是被订阅的联系人的纯JID 因为出席信息订阅是基于纯JID的 US presence from juliet example com id ign291v5 to romeo example net type probe 互操作性备注 RFC 3921 定义了探测是从全JID发出的 而不是从纯JID 规则的改变是因为订阅是基于纯JID的 一些现存的实现仍然从全JID而不是纯JID发送 探测也能由一个从某个出席信息订阅上下文的外部接收到了出席信息的实体发送 典型的是当该联系人已经发送了 4 6 所述的定向出席信息的时候 在这种情况下 from 或 to 地址的值可以是一个全JID而不是一个纯JID 完整的讨论参见 4 6 出席信息探测不应该 SHOULD NOT 由一个客户端发送 因为通常一个客户端不需要发送它们 原因是从一个用户的联系人那里收集出席信息的任务是由该用户的服务器管理的 无论如何 如果一个用户的客户端生成了一个出站出席信息探测 那么该用户的服务器应该路由这个探测 如果该联系人位于另一个服务器上 或处理这个探测 如果该联系人在同一台服务器上 并且不能 MUST NOT 从一个已连接的客户端使用该出席信息探测的回执来作为唯一的理由来返回一个节错误或流错误给该客户端 服务器生成出站出席信息探测 当一个服务器需要查询一个用户的联系人的可用性的时候 它从该用户的纯JID user domainpart 发送一个出席信息探测到该联系人的纯JID contact domainpart 实现备注 尽管出席信息探测是用来发送给联系人的 即 一个用户所订阅的那些实体 一个服务器可以发送出席信息探测给该用户在当前会话时收到了出席信息的某个实体的全JID 当用户在任何时候通过发送初始化出席信息来开始一个新的出席信息会话 该用户的服务器应该发送一个出席信息探测 无论如何 如果它认为关于该用户的联系人的出席信息是可靠的和最新的 该服务器可以选择在那个时间点不发送出席信息探测 例如 因为该用户有另外一个可用资源或因为该用户在新的出席信息开始之前刚刚注销登陆 另外 如果一个服务器在一个可配置的时间段内没有从某个联系人收到出席信息或其他通讯 它可以定期发送出席信息探测给那个联系人 这有助于防止看起来在线但是实际上没有在线的 幽灵 联系人 US presence from juliet example com id ign291v5 to romeo example net type probe US presence from juliet example com id xv291f38 to mercutio example com type probe 自然的 该用户的服务器不需要发送一个出席信息探测给一个联系人 如果该联系人的帐号位于该用户的同一台服务器 因为该服务器本地就拥有该联系人的信息 服务器处理入站出席信息探测 在接收到一个用户的服务器代表该用户发送到该联系人的纯JID的出席信息探测之后 该联系人的服务器必须应答如下 1 如果该联系人帐号不存在或该用户的纯JID在该联系人的名册中并且订阅状态不是 From From Pending Out 或 Both 如 附录A 所述 那么该联系人的服务器应该在对该出席信息探测的应答中返回一个类型为 unsubscribed 的出席信息节 这将触发一个协议流用于 3 2 所述的撤销该用户对该联系人的订阅 无论如何 这不能 MUST NOT 导致 3 4 所述的订阅预批准的撤销 这里 from 地址必须是该联系人的纯JID 因为指定一个全JID则等同于出席信息泄露 XMPP CORE 中所说的 CS presence from mercutio example com id xv291f38 to juliet example com type unsubscribed 无论如何 如果一个服务器从一个该服务器本身的已配置的域或其他信任的服务收到一个出席信息探测 它可以提供关于该用户或那个实体的出席信息 2 或者 如果该联系人已经临时移动或永久移动到另一个地址 那么该服务器应该返回一个类型为 error 的出席信息节并带上一个节错误条件 redirect 临时的 或 gone 永久的 并包含该联系人的新地址 CS presence from mercutio example com id xv291f38 to juliet example com type error error type modify gone xmlns urn ietf params xml ns xmpp stanzas xmpp la mer example com gone error presence 3 或者 如果该联系人没有可用的资源 那么该服务器应该通过发送给该用户一个类型为 unavailable 的出席信息节来应答该出席信息探测 尽管在这里更倾向于发送unavailable出席信息 因为它能导致对该探测的确定的回答 但它不是强制性的 因为它极大地增加了该联系人的服务器生成的出席信息通知的数量 这里的 from 地址是纯JID 因为没有该联系人相关的可用资源 如果适当地遵循本地安全策略 该出席信息通知可以包含该服务器从该联系人收到的最近的unavailable出席信息节的全XML 包括原始节的 id 但是如果没有 那么该出席信息通知应该简单地表示该联系人是unavailable而没有任何原始提供的细节 在任何情况下 返回给该探测实体的出席信息节应该包含最近一次unavailable出席信息节被生成的时间信息 格式采用XMPP延迟递送扩展 DELAY CS presence from mercutio example com id xv291f38 to juliet example com type unavailable delay xmlns urn xmpp delay stamp 2002 09 10T23 41 07Z presence 4 或者 如果该联系人有至少一个可用资源 那么该服务器必须通过向该用户发送该服务器从该联系人的每个可用资源收到的最近的没有 to 属性的出席信息节的全XML 这里的 from 地址是每个可用资源的全JIDs CS presence from romeo example net foo id hzf1v27k to juliet example com CS presence from romeo example net bar id ps6t1fu3 to juliet example com show away show presence 实现备注 通过 full XML 意味着从开始的 presence 标签到关闭的 presence 标签之前的完整的节 包括所有的元素和属性 要么由内容命名空间限定要么由扩展命名空间限定 无论如何 根据 XMPP CORE 如果通过服务器 服务器流发送完整的节 该联系人的服务器将需要把内容命名空间从 jabber client 转换成 jabber server 如果该联系人的服务器接收到一个地址指向该联系人的某个全JID的出席信息探测 该服务器不能 MUST NOT 返回任何除了该探测的 to 地址之外的资源的出席信息 规则 1 和 2 中对一个纯JID的探测同样适用于一个全JID探测的情况 如果有一个匹配的全JID并且探测的实体通过一个出席信息订阅从而有权限察看该联系人的出席信息 那么该服务器必须返回一个available出席信息通知 它应该确切地只和那个available的资源通讯 没有详细信息 如 show status priority 或出席信息扩展 CS presence from romeo example net bar to lobby chat example com 实现备注 关于前述处理定向出席信息的补充请参阅 4 6 处理 id 属性 和出席信息探测相关的 id 属性的处理在 RFC 3921 中没有定义 尽管 发送一个探测并接收到一个应答 的模式可能看起来像一个类似XMPP iq 节的 请求 应答 协议 事实上它不是 因为对一个探测的应答可以包含多个出席信息节 分别对应该联系人当前活跃的每一个可用的资源 基于这个原因 如果该联系人当前有可用资源 那么该联系人的服务器应该保留当发送那些出席信息通知给探测实体的时候该联系人的原始出席信息节的 id 属性 如果有的话 相比之下 如果该联系人当前没有可用资源 探测实体未被授权 通过出席信息订阅 察看该联系人的出席信息 或发生了和该探测相关的错误 那么该联系人的服务器在应答探测实体的时候应该镜像该用户的出席信息探测的 id 以下示例展现这些不同之处 在第一个场景中 Juliet发送从她的 chamber 资源出席信息探测 CC presence from juliet example com chamber id pres1 show dnd show status busy status presence 她也从她的 balcony 资源发送出席信息 CC presence from juliet example com balcony id pres2 show away show status stepped away status presence Romeo的服务器接着发送一个探测给Juliet US presence from romeo example net id probe1 type probe Juliet的服务器接着同时发送她的两个出席信息通知给Romeo 保留她的客户端发送的节中的 id 属性 CS presence from juliet example com chamber id pres1 show dnd show status busy status presence CS presence from juliet example com balcony id pres2 show away show status stepped away status presence 在第二个场景中 当Romeo的服务器发送探测的时候Juliet离线了 US presence from romeo example net id probe2 type probe Juliet的服务器应答一个unavailable通知 镜像Rome的出席信息探测的 id 因为从她的客户端已经发送的available通知的 id 被保留 CS presence from juliet example com id probe2 type unavailable 随后的出席信息广播 客户端生成随后的出席信息广播 在发送初始化出席信息之后 在它的会话期间的任何时候该用户的客户端可以更新它的可用性并通过发送一个不带 to 地址并且没有 type 属性的出席信息节来广播 UC presence show away show presence 该出席信息广播可以包含 priority 元素 show 元素 和一个或多个 status 元素实例 同样的包括扩展内容 详情参见 4 7 无论如何 一个用户应该发送一个出席信息更新只广播该用户的通讯可用性或该资源的通讯能力相关的信息 和这些无关但是可能该用户的联系人同样感兴趣的信息应该通过其他方式来发送 例如 XEP 0163 所述的 发布 订阅 方法 服务器处理随后的出站出席信息 在接收到一个表达更新的可用性的出席信息节后 该用户的服务器必须广播那个出席信息节的完整XML给该用户名册中并且订阅类型为 from 或 both 的联系人们 互操作性备注 RFC 3921 定义在发送随后的出席信息通知之前该用户的服务器将检查并确认没有从该联系人收到一个出席信息错误 那个规则已经被移除 因为本协议使用类型为 unsubscribe 而不是 error 的出席信息节来解决订阅同步问题 部分也因为这类节使得该联系人在该用户的名册中的订阅状态变成了 none 或 to 见 3 3 和 附录A 所以没有了对错误检查的需要 互操作性备注 如果订阅类型为 both 一些现有的服务器实现根据该用户的服务器仅当该联系人在线时才发送随后的出席信息通知给一个联系人 就是说 如果该用户的服务器在它发给该联系人的出席信息探测的应答中从未收到过该联系人在线的肯定的标示 该用户的服务器不会从该用户向该联系人发送随后的出席信息通知 这一行为被理解为节省带宽 因为大部分出席信息订阅是双向的并且很多联系人在任何特定的时间都不在线 US presence from juliet example com balcony to romeo example net show away show presence US presence from juliet example com balcony to benvolio example net show away show presence US presence from juliet example com balcony to mercutio example com show away show presence 实现备注 关于上述处理用于定向出席信息的补充规则参见 4 6 该用户的服务器也必须发送该出席信息节给该用户的所有可用资源 包括首先生成该出席信息的那个资源 US presence from juliet example com balcony to juliet example com chamber show away show presence US presence from juliet example com balcony to juliet example com balcony show away show presence 服务器处理随后的入站出席信息 在从用户那接收到出席信息之后 该联系人的服务器必须递送该用户的出席信息节到该联系人的所有可用资源 to resource1 CS presence from juliet example com balcony to romeo example net show away show presence to resource2 CS presence from juliet example com balcony to romeo example net show away show presence 客户端处理随后的出席信息 从联系人的客户端的视角来看 初始化出席信息广播和随后的出席信息没有明显的不同 所以联系人的客户端遵循 4 4 3 定义的入站出席信息处理的规则 离线出席信息 客户端生成离线出席信息 在结束和一个服务器的出席信息会话之前 用户的客户端应该通过发送 unavailable 出席信息 优雅地变更为离线 即 一个没有 to 属性并且有一个值为 unavailable 的 type 属性的出席信息节 UC presence type unavailable 可选的 该离线出席信息节可以包含一个或多个 status 元素来定义为什么该用户不再在线的原因 UC presence type unavailable status going on vacation status presence 无论如何 该离线出席信息节不能 MUST NOT 包含 priority 元素或 show 元素 因为这些元素只适用于可用资源 服务器处理出站离线出席信息 该用户的服务器不能 MUST NOT 依赖于从一个可用的资源接收到的unavailable出席信息 因为该资源可能不优雅地离线了 例如 如 XMPP CORE 所述 该资源的XML流因为任何原因带或未带流错误地被关闭了 如果一个可用的资源因为任何原因离线了 优雅或不优雅的 该用户的服务器必须广播unavailable出席信息给所有在该用户的名册中的订阅状态为 from 或 both 的联系人 互操作性备注 RFC 3921 定义了该用户的服务器将检查并确认在发送unavailable出席信息通知之前它没有从该联系人收到一个出席信息错误 那个规则已经被移除 因为本协议使用类型为 unsubscribe 而不是 error 的出席信息节来解决订阅同步问题 部分也因为这类节使得该联系人在该用户的名册中的订阅状态变成了 none 或 to 见 3 3 和 附录A 所以没有了对错误检查的需要 互操作性备注 即使该用户的服务器不广播该用户随后的出席信息通知给离线的联系人们 如 4 4 2 所述 它必须广播该用户的unavailable出席信息通知 如果它不这么做 由该联系人的服务器最后收到的出席信息将是该用户用于这个出席信息会话的初始化出席信息 结果是该联系人将认为该用户在线 实现备注 关于上述处理用于定向出席信息的补充规则参见 4 6 如果该unavailable通知优雅地被从该客户端接收到 那么该服务器必须广播该出席信息节的完整XML US presence from juliet example com balcony to romeo example net type unavailable status going on vacation status presence US presence from juliet example com balcony to benvolio example net type unavailable status going on vacation status presence US presence from juliet example com balcony to mercutio example com type unavailable status going on vacation status presence 该用户的服务器也必须发送该unavailable通知给该用户的所有可用资源 以及最初生成该unavailable出席信息的那个资源 US presence from juliet example com balcony to juliet example com chamber type unavailable status going on vacation status presence 如果该服务器探测到那该用户已经不优雅地离线了 那么该服务器必须代表该用户生成该unavailable出席信息广播 实现备注 在该服务器广播或生成一个unavailable出席信息通知之后 该客户端发送的任何没有 type 属性且没有 to 属性的出席信息节 必须被该用户的服务器路由或递送到所有的订阅者 即 必须等同于为一个新的出席信息会话出发了初始化出席信息 服务器处理入站离线出席信息 在从用户接收到一个unavailable通知之后 该联系人的服务器必须递送该用户的出席信息节给该联系人的所有可用资源 to resource1 CS presence from juliet example com balcony to romeo example net type unavailable status going on vacation status presence to resource2 CS presence from juliet example com balcony to romeo example net type unavailable status going on vacation status presence 实现备注 如果该联系人的服务器没有广播随后的出席信息通知给离线的用户们 如 4 4 2 它也必须注意到该用户是离线的并更新它的关于哪些实体在线的内部存储 客户端处理离线出席信息 从联系人的客户端的视角来看 在线出席信息广播和离线出席信息广播没有明显的差别 所以通常联系人的客户端遵循定义的处理入站出席信息的规则 4 4 3 无论如何 如果该联系人从该用户的纯JID 而不是某个可用资源的全JID 接收到一个unavailable通知 该联系人的客户端应该视为该unavailable通知适用于所有资源 定向出席信息 本章是客户端和服务器处理出席信息通知和出席信息探测的规则的补充 但是仅用于定向出席信息的特定场景 总则 通常 当一个客户端希望分享可用性信息给一个没有订阅它的出席信息的实体的时候 它会发送定向出席信息 典型的是在一个临时基础上 定向出席信息的常规使用包括 5 1 所述的临时的一对一会话和 XEP 0045 所述的多用户聊天室 通过分享定向出席信息给另一个实体而建立的临时的关系比起通过出席信息订阅建立的永久关系来说是次要的 所以 建立 修改 或取消一个出席信息订阅的动作 必须优先于接下来的子章节定义的规则 例如 如果一个用户分享了定向出席信息给一个联系人 但是接着通过完成出席信息订阅 握手 来把该联系人加入到该用户的名册中 那么该用户的服务器必须把该联系人视为如 第三章 所述的任何一个普通的订阅者来处理 例如 发送随后的出席信息广播给该联系人 另一个例子是 如果该用户接着取消了该联系人对该用户的出席信息的订阅 该用户的服务器必须如 3 2 所述处理这个取消动作 这包括发送unavailable出席信息给该联系人 即使该用户曾经发送了定向出席信息给该联系人 XMPP服务器典型的实现定向出席信息的办法是通过保持一个用户在该用户的给定资源 全JID 的当前会话期间曾经对它们发送了定向出席信息的实体的列表 纯JIDs或全JIDs 然后在该用户下线的时候清除这个列表 例如 发送一个类型为 unavailable 的广播出席信息节 该服务器必须从定向出席信息列表 或它的功能等价物 移除任何该用户曾经对它们发送过定向unavailable出席信息的实体并且应该移除任何发送了unavailable出席信息给该用户的实体 客户端生成定向出席信息 大家知道 定向出席信息是一个客户端生成的presence节 这个节的 to 属性值是另一个实体的纯JID或全JID 并且这个节要么没有 type 属性 表示可用性 要么 type 属性值为 unavailable 服务器处理出站定向出席信息 当用户的服务器接收到一个定向出席信息节 它应该根据以下规则处理它 如果该用户在已经发送初始化出席信息之后并且在发送unavailable出席信息广播之前 即 在该用户的出席信息会话期间 发送定向的可用或不可用出席信息给一个在该用户的名册中并且订阅状态为 from 或 both 的联系人 该用户的服务器必须本地递送或远程路由那个出席信息节的完整XML给那个实体 但是应该不 SHOULD NOT 基于出席信息广播来修改该联系人的状态 即 它应该在任何随后由该用户初始化的的出席信息广播中包含该联系人的JID 如果该用户在已经发送初始化出席信息之后并且在发送unavailable出席信息广播之前 即 在该用户的出席信息会话期间 发送定向的可用或不可用出席信息给一个不在该用户的名册中并且订阅状态为 from 或 both 的联系人 该用户的服务器必须本地递送或远程路由那个出席信息节的完整XML给那个实体 但是不能 MUST NOT 基于available出席信息广播来修改该联系人的状态 即 它不能 MUST NOT 在任何随后由该用户初始化的available出席信息广播中包含该联系人的JID 无论如何 如果发送定向出席信息的用户的可用资源离线了 该用户的服务器必须路由那个离线出席信息给该实体 如果该用户还未发送定向unavailable出席信息给那个实体 如果该用户从未发送过初始化出席信息或在已经发送unavailable出席信息广播之后 即 该资源已连接但不可用 发送定向出席信息 该用户的服务器必须把该实体当作上面第二种情况下该用户发送定向出席信息的实体 服务器处理入站定向出席信息 从联系人的服务器的视角来看 在出席信息广播和定向出席信息之间没有显著差别 所以联系人的服务器遵循 4 3 2 4 4 3 和 4 5 3 定义的处理入站出席信息的规则 客户端处理入站定向出席信息 从联系人的客户端的视角来看 在出席信息广播和定向出席信息之间没有显著差别 所以联系人的客户端遵循定义的处理入站出席信息的规则 4 4 3 译者注 原文如此 疑为 4 4 4 之误 服务器处理出席信息探测 如果一个用户的客户端发送了定向出席信息给另一个实体 例如 一个一对一聊天伙伴或一个多用户聊天室 在一段时间之后该实体或它的服务器可能想知道该用户是否仍然在线 这个场景在多用户聊天室中特别常见 该用户可能在很长一段时间内在该聊天室中是一个参加者 如果该用户的客户端下线而没有 通过客户端或该客户端的服务器 通知该聊天室 该用户的在该房间里的表现可能成为一个 幽灵 看起来是参加者但实际上已经不在该房间了 为了查明这类 幽灵 一些聊天室实现会发送出席信息探测给这些已经加入房间的用户 在定向出席信息的案例中 探测的实体应该从接收到定向出席信息的那个JID 一个全JID或纯JID 发送探测 该探测应该被发送到那个用户的全JID 而不是那个用户的不带资源的纯JID 因为伴随定向出席信息的临时 授权 是基于曾经发送定向出席信息给该探测实体的那个用户的全JID 当该用户的服务器接收到一个探测 它必须首先应用任何和出席信息订阅相关的逻辑 如 4 3 2 所述 如果该探测实体未订阅该用户的出席信息 那么该服务器必须检查该用户是否曾经在当前会话中发送过定向出席信息给该实体 如果是 该服务器应该仅以纯粹的 available 或 unavailable 类型 即 不包含子元素 应答这个探测并且只用于那个全JID 即 不为任何可能与当前该用户的纯JID相关的其他资源 出席信息语法 Type属性 缺少 type 属性代表相关实体是可以通讯的 见 4 2 和 4 4 type 属性值为 unavailable 代表相关实体不可通讯 见 4 5 XMPP出席信息节也用于协商和管理对其他实体的出席信息的订阅 这些任务通过 第三章 所述的类型为 subscribe unsubscribe subscribed 和 unsubscribed 的出席信息节来完成 如果一个用户和联系人在不同的XMPP服务器上发生关系 那些服务器为了确定对端服务器上的那个实体的可用性 也使用一个类型为 probe 的特殊的出席信息节 详见 4 3 客户端不应 SHOULD NOT 发送类型为 probe 的出席信息节 type 属性的值可以归纳如下 error error发生在处理之前发送的出席信息节的时候 如果出席信息节的类型为 error 它必须包含一个 error 子元素 参考 XMPP CORE probe 请求一个实体当前的出席信息 应该只由一个服务器代表一个用户生成 subscribe 发送者希望订阅接收者的出席信息 subscribed 发送者已经允许接收者接收他们的出席信息 unavailable 发送者不再可通讯 unsubscribe 发送者取消订阅接收者的出席信息 unsubscribed 订阅请求已经被拒绝或撤销之前准许的被对方订阅 如果 type 属性的值不是前述的任何一个 接收方或一个中间的路由服务器应该返回一个节错误 bad request 实现备注 presence 元素的 type 属性没有缺省值 实现备注 presence 元素的 type 属性没有 available 这个值 子元素 根据缺省命名空间声明 一个出席信息节是由 jabber client 或 jabber server 命名空间限定的 它定义了明确的出席信息节的子元素 特别是 show status 和 priority 元素 这些子元素被用于提供关于一个实体的可用性的更详细的信息 典型情况下这些子元素只在该出席信息节没有 type 属性的时候被包含 尽管在接下来的文本里有一些例外 Show元素 可选的 show 元素定义了一个实体或它的一个特定资源的特定的可用性子状态 一个出席信息节不能 MUST NOT 包含多于一个的 show 元素 show 元素没有定义属性 show 元素不能 MUST NOT 包含混合内容 定义于 XML 3 2 2节 show 元素的XML字符数据不意味着它是用于展示给自然人用户看的 该XML字符数据必须是以下之一 更多的可用性状态可以通过扩展内容元素来定义 away 该实体或资源临时离开 chat 该实体或资源活跃并想聊天 dnd 该实体或资源忙 dnd Do Not Disturb 免打扰 xa 该实体或资源要离开相当长时间 xa eXtended Away 长时间离开 如果 show 元素未被提供 该实体被假定在线并且可用 任何由接收者和代理路由服务器对可用性状态的特别处理取决于该实现 例如 把可用性状态合并到节路由和递送逻辑中 Status元素 可选的 status 元素包含了自然人可读的定义实体可用性的自然语言描述的XML字符数据 通常在出席信息节不包含 type 属性的时候被用于和show元素结合一起提供某个可用性状态的细节 例如 In a meeting 开会中 presence from romeo example net orchard xml lang en show dnd show status Wooing Juliet status presence status 元素没有定义属性 除了从 XML 继承的 xml lang 属性 status 元素不能 MUST NOT 包含混合内容 定义于 XML 3 2 2节 status 元素可以包含多个实例 但是只能在每个实例的都有一个 xml lang 属性并且属性值为唯一的语言值 或者显式地 或者从一个元素的更高的XML级别的 xml lang 值继承 从发送者的视角来看 可能包括 XMPP CORE 描述的XML流头 presence from romeo example net orchard id jx62vs97 xml lang en show dnd show status Wooing Juliet status status xml lang cs Dvo x0159 x00ED m se Julii status presence 一个类型为 unavailable 的出席信息节也可以包含一个 status 元素来提供为什么该实体下线的详细原因 presence from romeo example net orchard id oy6sb241 type unavailable xml lang en status Busy IRL status presence status 子元素也可以在一个订阅相关的出席信息节中被发送 即 类型为 subscribe subscribed unsubscribe 或 unsubscribed 以提供该动作的描述 一个可交互的客户端可以展示这个 status 信息给一个自然人用户 见 第11章 presence from romeo example net id uc51xs63 to nurse example com type subscribe status Hi Juliet told me to add you to my buddy list status presence Priority元素 可选的 priority 元素包含定义该资源优先级的非自然人可读的XML字符数据 它的值必须是一个处于 128 和 127 之间的整数 一个出席信息不能 MUST NOT 包含多个 priority 元素 没有为 priority 定义属性 priority 元素不能 MUST NOT 包含混合内容 定义于 XML 3 2 2节 presence xml lang en show dnd show status Wooing Juliet status status xml lang cs Dvo x0159 x00ED m se Julii status priority 1 priority presence 如果没有提供优先级 处理的服务器或客户端必须视为优先级为零 0 该客户端的服务器可以覆写客户端提供的优先级的值 例如 为了给正在递送给预期的帐号的纯JID的消息强加一个消息处理规则以用于该帐号的所有可用资源 如果服务器这样做 当它回应该客户端的出席信息给自己并发送出席信息通知给该用户的联系人们的时候 它必须以修改过的优先级来通讯 因为修改过的优先级的值典型的缺省是零 以修改过的优先级的值来通讯可以不包含 priority 子元素 关于即时消息和出席信息应用中节处理过程中优先级值的语法信息 参见 第八章 扩展内容 如 XMPP CORE 所述 一个XML节可以包含任何由不同于缺省命名空间限定的子元素 这也适用于出席信息节 以下例子中 出席信息节包含定义于 XEP 0115 的实体能力信息 presence from romeo example net c xmlns http jabber org protocol caps hash sha 1 node http psi im org ver q07IKJEyjvHSyhy CH0CxmKi8w presence 包含在一个出席信息节中的任何扩展内容应该展示用于通讯的实体可用性的方方面面或提供和通讯相关的能力 交换消息 一旦一个客户端如 XMPP CORE 所述 已经在一个服务器上通过了验证并绑定了一个资源到一个XML流 一个XMPP服务器将路由XML节到和从那个客户端 一种可交换的节是 message 如果 也就是说 消息功能在该服务器上是允许的 交换消息是XMPP的一个基本用途 它发生在一个用户生成一个地址指向另一个实体的消息节的时候 如 第八章 所定义的 该发送者的服务器负责递送该消息到期望的接收者 如果该接收者在同一台本地服务器上 或路由该消息到该接收者的服务器 如果该接收者在一个远端服务器上 所以一个消息节是被用来 推送 信息给另一个实体 一对一聊天会话 在实践中 在自然人用户之间的即时消息活动倾向于以一个会话式的方式发生 我们称之为一个 聊天会话 在一个比较短暂的时间内双方的多个比较快速的消息交换是有继承的 当一个自然人用户倾向于和一个联系人进行这样一种聊天会话 而不是发送一个单独的消息给某人却不期望获得应答 由该用户的客户端生成的这个消息的类型应该是 chat 并且该联系人的客户端应该在随后的应答中保持那个消息类型 该用户的客户端也应该在它的初始化消息中包含一个 thread 元素 这样该联系人的客户端也应该在那个会话的生命周期中保持它 参见 5 2 5 该用户的客户端应该在一个聊天会话中把初始消息的地址指向该联系人的纯JID contact domainpart 而不是基于任何它可能之前从联系人那收到的出席信息通知的 show status 或 priority 值来尝试猜测一个适当的全JID contact domainpart resourcepart 直到和除非该用户的客户端从该联系人收到一个应答 它应该发送任何更多的消息给该联系人的纯JID 该联系人的客户端应该把它的应答的地址指向该用户的全JID user domainpart resourcepart 即初始消息中提供的 from 地址 一旦该用户的客户端从该联系人的全JID收到一个应答 它应该把它随后的消息指向该联系人的全JID 即在该联系人的应答中提供的 from 地址 从而 锁定 在那个全JID 一个客户端应该在接收到一个来自对方节点控制的任何其他资源的 message 或 presence 节 或一个来自已锁定的资源的出席信息节 的时候 解除锁定 结果是 它应该在聊天会话的下一个消息中指向对方节点的纯JID 从而 解锁 之前的 锁定 直到它从对方的全JIDs收到一个消息 当双方参加一个一个聊天会话但是没有基于一个出席信息订阅来互相分享出席信息 他们应该互相发送定向出席信息 这样双方能很容易地查询对方在该聊天会话期间是否下线 然而 一个客户端必须提供一个方法让一个用户能全局地禁止或只允许特定的实体进行这类出席信息分享 更进一步的 当出于某种原因相信该聊天会话结束了 例如 如果 在一段合理的时间之后 双方没有交换随后的消息 一方应该发送定向unavailable出席信息给另一方 聊天会话的例子参见 第7章 消息语法 以下章节描述 message 节的语法 To属性 即时消息客户端通过在 message 节中的 to 属性中提供预期的接收者的JID来为一个消息指定预期接收者 如果该消息在现有的聊天会话或已接收的消息的上下文之外被发送 to 地址的值的格式应该是 localpart domainpart 而不是 localpart domainpart resourcepart 见 5 1 message from juliet example com balcony id ktx72v49 to romeo example net type chat xml lang en body Art thou not Romeo and a Montague body message 如果该消息是作为对之前从格式 localpart domainpart resourcepart 收到的一个消息的应答来发送的 例如 在一个如 5 1 所述的一对一聊天会话的上下文中 该 to 地址的值的格式应该是 localpart domainpart resourcepart 而不是 localpart domainpart 除非发送者已经知道 例如 通过出席信息 接收者的资源不再可用 message from romeo example net orchard id sl3nx51f to juliet example com balcony type chat xml lang en body Neither fair saint if either thee dislike body message Type属性 在即时消息应用中消息节的常用的包括 单条消息 在一对一聊天会话的上下文中发送的消息 在一个多用户聊天室中发送的消息 警告 通知 或其他给不期望应答的人的信息 错误 这些用途通过 type 属性来区分 建议包含 type 属性 如果包含了它 type 属性必须是以下的值之一 chat 该消息在一个一对一聊天会话的上下文中被发送 典型的一个可交互的客户端将在一个界面上展示一个类型为 chat 的消息 这使得双方之间能够进行一对一聊天 同时包括一个适当的会话历史 关于一对一聊天会话的详细建议参见 5 1 error 该消息由一个从另一个实体接收到一个消息并在处理的时候发现了错误的实体生成 关于节错误语法的详情 参考 XMPP CORE 接收到一个类型为 error 的消息的客户端应该展示一个适当的界面来通知原始的发送者关于这个错误的类型 groupchat 该消息在一个多用户聊天环境的上下文中被发送 类似 IRC 典型的一个接收的客户端将在一个界面展示一个类型为 groupchat 的消息 这使得多方可以进行多对多的聊天 同时包含一个聊天室中的参与者的名册和适当的会话历史 关于基于XMPP的群聊的详细信息 参见 XEP 0045 headline 该消息提供一个警告 一个通知 或其他给那些不期望应答的人的临时信息 例如 新闻头条 运动更新 准实时的市场数据 或整合的内容 因为不期望对该消息的回复 典型的一个接收客户端将在一个界面展示一个类型为 headline 的消息以适当地把它们和独立消息 聊天消息 以及群聊消息区分开来 例如 不向该接收者提供应答能力 如果 to 地址是纯JID 该接收服务器应该递送该消息给该接收者的所有非负出席信息优先级的可用资源并且必须递送该消息给那些资源中的至少一个资源 如果该 to 地址是一个全JID并且有一个匹配的资源 该服务器必须递送该消息给那个资源 否则该服务器必须要么安静地忽略该消息要么返回一个错误 见 第8章 normal 该消息是一个在一对一聊天会话或群聊上下文之外的被发送的独立消息 并且它期望接收者应答 典型的一个接收客户端将在一个界面展示一个类型为 normal 的消息 这使得接收方能够应答 但没有会话历史 type 属性的缺省值是 normal 一个IM应用应该支持所有前述的消息类型 如果一个应用接收了一个没有 type 属性的消息或该应用不理解被提供的 type 属性的值 它必须认为该消息的类型为 normal 即 normal 是缺省的 不同消息类型的服务器处理指南参见 第8章 尽管 type 属性是可选的 出于礼貌在任何对一个消息的应答之中会镜像其类型 更进一步 一些专门的应用 例如 一个多用户聊天服务 可以基于他们的自主判断来强制使用特定消息类型 例如 type groupchat Body元素 body 元素包含自然人可读的XML字符数据以指定该消息的正文 这个子元素通常会被包含但是可选的 message from juliet example com balcony id b4vs9km4 to romeo example net type chat xml lang en body Wherefore art thou Romeo body message 没有为 body 元素定义属性 除了 xml lang 属性例外 在一个消息节中可以包括多个 body 元素实例用来为同一body提供替代版本 但是每个实例只允许拥有一个 xml lang 属性并且其值为一个唯一性的语言 要么显性的 要么从更高层次的XML继承 xml lang 值 从发送者角度看是包含在 XMPP CORE 所述的XML流头中 message from juliet example com balcony id z94nb37h to romeo example net type chat xml lang en body Wherefore art thou Romeo body body xml lang cs Pro x010D e x017D jsi ty Romeo body message body 元素不能 MUST NOT 包含混合内容 定义于 XML 的3 2 2节 Subject元素 subject 元素包含自然人可读的XM字符数据以指定该消息的标题 message from juliet example com balcony id c8xg3nf8 to romeo example net type chat xml lang en subject I implore you subject body Wherefore art thou Romeo body message 没有为 subject 元素定义属性 从 XML 继承的 xml lang 属性例外 可以包含多个 subject 元素实例以提供同意标题的替代版本 但是每个实例只允许拥有一个 xml lang 属性并且其值为一个唯一性的语言 要么显性的 要么从更高层次的XML继承 xml lang 值 从发送者角度看是包含在 XMPP CORE 所述的XML流头中 message from juliet example com balcony id jk3v47gw to romeo example net type chat xml lang en subject I implore you subject subject xml lang cs x00DA p x011B nliv x011B pros x00ED m subject body Wherefore art thou Romeo body body xml lang cs Pro x010D e x017E jsi ty Romeo body message subject 元素不能 MUST NOT 包含混合内容 定义于 XML 的3 2 2节 Thread元素 XMPP thread 元素主要用于唯一性地标识一个由类型为 chat 的 message 节实例化的两个实体之间的交谈线索或 聊天会话 然而 XMPP thread 元素也可以被用于唯一性地标识一个由类型为 headline 或 normal 的 message 节实例化的两个实体之间 或由类型为 groupchat 的 message 节实例化的在一个多用户聊天室上下文中的多个实体之间的类似线索 它也可用于和自然人无关的会话的 message 节 类似一个游戏会话或一个插件之间的互动 thread 元素不被用于标识个别的消息 只用于交谈或消息会话 thread 元素是可选的 因为 thread 元素标识了一个消息所属的特定交谈线索 一个消息节不能 MUST NOT 多个 thread 元素 thread 元素可以拥有一个 parent 属性以标识另一个线索 当前线索是那个线索的分支或子线索 该 parent 属性必须遵循 thread 元素本身的语法并且它的值必须和包含了该 parent 属性的那个 thread 元素的XML字符数据不同 实现备注 同时指定一个父线索和一个子线索的能力可能会因为重叠的线索而导致线索标识的冲突 例如 一个 thread 元素可能包含XML字符数据 foo 以及一个值为 bar 的 parent 属性 第二个 thread 元素可能包含XML字符数据 bar 和一个值为 baz 的 parent 属性 而第三个 thread 元素可能包含XML字符数据 baz 和一个值再次为 foo 的 parent 属性 如果处理这类重叠的线索标识之间的冲突取决于实现 例如 要么它将线索标识符 链在一起 在一个多级用户界面中把 foo 同时显示成 baz 的一个父线索和一个孙线索 要么它将在一次只显示依赖的一层 thread 元素的值不是自然人可读的且必须被实体当成不透明的来处理 从它那里不能获得语义 并且对它只能做精确比较 thread 元素的值必须唯一地标识该交谈线索 在交谈伙伴之间或更更广泛 一个确保唯一性的办法是生成一个 UUID 所述的全局唯一标识符 UUID 安全警告 一个生成ThreadID的应用必须确保它不会泄露关于这个实体的身份信息 例如 该XMPP应用正在运行的设备的MAC地址 thread 元素不能 MUST NOT 包含混合内容 定义于 XML 的3 2 2节 message from juliet example com balcony to romeo example net type chat xml lang en subject I implore you subject subject xml lang cs x00DA p x011B nliv x011B pros x00ED m subject body Wherefore art thou Romeo body body xml lang cs Pro x010D e x017E jsi ty Romeo body thread parent e0ffe42b28561960c6b12b944a092794b9683a38 0e3141cd80894871a68e6fe6b1ec56fa thread message 关于使用 thread 元素的详细建议 参考 XEP 0201 扩展内容 如 XMPP CORE 所述 一个XML节可以包含任何不同于缺省命名空间的命名空间所限定的子元素 这也适用于message节 处理扩展内容的指南参见 XMPP CORE 的8 4节中提供的路由服务器和最终接收者部分 在下面的例子中 该message节包含一个 XEP 0071 定义的该消息的XHTML格式版本 message from juliet example com balcony to romeo example net type chat xml lang en body Wherefore art thou Romeo body html xmlns http jabber org protocol xhtml im body xmlns http www w3 org 1999 xhtml p Wherefore span style font style italic art span thou span style color red Romeo span p body html message 交换IQ节 如 XMPP CORE 所述 IQ节提供一个结构化的 请求 应答 机制 那一机制的基本语法 例如 id 属性是强制性的 定义于 XMPP CORE 特定语法需要完成限定类型为 get 或 set 的IQ节的直接子元素的扩展命名空间的所有实例中定义的用例 jabber client 和 jabber server 命名空间不定义除了 error 元素之外的所有节类型的任何IQ节的子元素 本文定义一个这样的扩展命名空间 用于 管理名册 无论如何 IQ节可以包含由一个扩展命名空间限定的结构化的信息 示例会话 本节的例子展示一个可能的即时消息和出席信息会话 用户是 romeo example net 他有一个可用资源 其资源部分是 orchard 并且在他的名册中有以下人员 juliet example com 订阅状态 both 并且她有两个可用资源 chamber 和 balcony benvolio example net 订阅状态 to mercutio example org 订阅状态 from 首先 该用户完成如 XMPP CORE 所述的前提条件 流建立 TLS和SASL协商 以及资源绑定 那些协议流程在这里不复述了 接下来 该用户请求他的名册 示例1 用户向服务器请求当前名册 UC iq from romeo example net orchard id hf61v3n7 type get query xmlns jabber iq roster iq 示例2 用户从服务器接收到名册 US iq id hf61v3n7 to romeo example net orchard type result query xmlns jabber iq roster item jid juliet example com name Juliet subscription both group Friends group item item jid benvolio example org name Benvolio subscription to item jid mercutio example org name Mercutio subscription from query iq 现在该用户开始一个出席信息会话 示例3 用户发送初始出席信息 UC presence 示例4 用户的服务器代表该用户发送出席信息探测给订阅状态 to 和订阅状态 both 的联系人们 US presence from romeo example net to juliet example com type probe US presence from romeo example net to benvolio example org type probe 示例5 用户的服务器代表该用户的可用资源发送初始出席信息给订阅状态 from 和订阅状态 both 的联系人们 以及用户自己 US presence from romeo example net orchard to juliet example com US presence from romeo example net orchard to mercutio example org US presence from romeo example net orchard to romeo example net 示例6 联系人的服务器代表所有可用资源应答该出席信息探测 CS presence from juliet example com balcony to romeo example net xml lang en show away show status be right back status priority 0 priority presence CS presence from juliet example com chamber to romeo example net priority 1 priority presence CS presence from benvolio example org pda to romeo example net xml lang en show dnd show status gallivanting status presence 示例7 联系人的服务器们递送用户的初始出席信息给所有可用资源 CS presence from romeo example net orchard to juliet example com CS presence from romeo example net orchard to juliet example com CS presence from romeo example net orchard to mercutio example org 示例8 用户发送定向出席信息给另一个不在他的名册中的用户 UC presence from romeo example net orchard to nurse example com xml lang en show dnd show status courting Juliet status priority 0 priority presence 现在该用户和他的联系人之一进入一个聊天会话 示例9 一个带线索的交谈 CC message from juliet example com balcony to romeo example net type chat xml lang en body My ears have not yet drunk a hundred words body thread e0ffe42b28561960c6b12b944a092794b9683a38 thread message CC message from juliet example com balcony to romeo example net type chat xml lang en body Of that tongue s utterance yet I know the sound body thread e0ffe42b28561960c6b12b944a092794b9683a38 thread message CC message from juliet example com balcony to romeo example net type chat xml lang en body Art thou not Romeo and a Montague body thread e0ffe42b28561960c6b12b944a092794b9683a38 thread message UC message from romeo example net orchard to juliet example com balcony type chat xml lang en body Neither fair saint if either thee dislike body thread e0ffe42b28561960c6b12b944a092794b9683a38 thread message CC message from juliet example com balcony to romeo example net orchard type chat xml lang en body How cam st thou hither tell me and wherefore body thread e0ffe42b28561960c6b12b944a092794b9683a38 thread message 以此类推 该用户也能发送随后的出席信息广播 示例10 用户发送更新的可用信息用于广播 UC presence xml lang en show away show status I shall return status priority 1 priority presence 示例11 用户的服务器广播更新的出席信息给订阅类型为 both 或 from 的联系人 但是不包括该用户向其发送过定向出席信息的实体 US presence from romeo example net orchard to juliet example com xml lang en show away show status I shall return status priority 1 priority presence US presence from romeo example net orchard to mercutio example org xml lang en show away show status I shall return status priority 1 priority presence 示例12 联系人们的服务器递送更新的出席信息 CS presence from romeo example net orchard to juliet example com xml lang en show away show status I shall return status priority 1 priority presence CS presence from romeo example net orchard to juliet example com xml lang en show away show status I shall return status priority 1 priority presence CS presence from romeo example net orchard to mercutio example org xml lang en show away show status I shall return status priority 1 priority presence 示例13 联系人们的可用资源之一广播不可用 离线 通知 CC presence from juliet example com chamber type unavailable 示例14 联系人的服务器发送不可用 离线 通知给用户 CS presence from juliet example com chamber to romeo example net type unavailable 现在该用户结束他的出席信息会话 示例15 用户发送不可用 离线 通知 UC presence type unavailable xml lang en status gone home status presence 示例16 用户的服务器广播离线通知给联系人们以及该用户曾经发送过定向出席信息的那个实体 US presence from romeo example net orchard to juliet example com type unavailable xml lang en status gone home status presence US presence from romeo example net orchard to mercutio example org type unavailable xml lang en status gone home status presence US presence from romeo example net orchard to nurse example com type unavailable xml lang en status gone home status presence 最后该用户关闭他的流并且他的服务器以同样方式应答 示例17 用户关闭流 UC stream stream 示例18 用户的服务器关闭流 US stream stream 结束 处理XML节的服务器规则 处理XML节的基本服务器规则定义于 XMPP CORE 读者可以参考那个协议的基础规则和安全含义 本章定义用于XMPP即时消息和出席信息服务器的附加规则 本章定义的一些递送规则指定了 离线存储 的使用 即 该服务器代表该用户存储一个消息节的行为以及当该用户下次上线的时候递送它 关于离线消息存储的建议 参考 XEP 0160 常规事项 XMPP CORE 讨论了节递送的常规事项 特别是在 i 提供一个关于节递送的服务的可接受级别 和 ii 防止目录捕获攻击和出席信息泄露 之间的平衡 无论如何 目录捕获攻击的概念不适用于一个已知并被一个用户信任的联系人 因为如 第2章 所述该联系人在该用户的名册中 类似的 出席信息泄露的概念不适用于一个已被授权知道一个用户的出席信息的联系人 通过 第3章 所述的所谓出席信息订阅 或该用户曾经自发的发送出席信息给它的那个实体 如 4 6 所述的的所谓定向出席信息 所以 下面章节的场景中用来防止目录捕获和出席信息泄露的替代方式有 a 安静地忽略一个节 或 b 返回一个错误 如果发起的实体在该用户的名册 当该错误将泄露该用户的帐号是否存在 或被授权从该用户接收出席信息 或已经从该用户接收到定向出席信息 当该错误将泄露一个用户的资源的出席信息 服务器应该返回一个错误 安全事项 接下来描述的所有节处理规则的定义 要理解它们将的应用 将遵循相关的隐私和安全行策略的强制检查 类似那些 XEP 0016 或 XEP 0191 的部署 接下来的章节中的一致性语言 MUST SHOULD 等等 不意味着覆盖任何本地服务策略 无 to 地址 如果该节无 to 属性 适用规则定义于 XMPP CORE 远端域 如果包含在一个出站节的 to 属性中的地址的域部分和该服务器本身配置的域不匹配 则适用的规则见于 XMPP CORE 的10 4节 互操作性备注 RFC 3921 定义了如何使用 im xmpp 和 pres xmpp SRV记录 IMP SRV 作为一个应急方法来查询是否一个远端的即时消息和出席信息服务能通过以XMPP通讯 因为那些SRV记录未被广泛部署 本文不再定义它们的使用 并且不鼓励新的实现 本地域 如果在 to 属性中包含的JID的域部分和该服务器配置的域之一匹配 该域由该服务器本身 而不是由一个特别的本地服务 提供服务 并且该JID的格式为 domainpart 或 domainpart resourcepart 适用规则定义于 XMPP CORE 本地用户 如果 to 地址指定了一个纯JID localpart domainpart 或全JID localpart domainpart resourcepart 该JID的域部分和由该服务器本身提供服务的已配置的域匹配 该服务器必需做如下处理 无该用户 如果由 to 属性而来的该用户帐号标识符不存在 该节如何处理取决于节类型 对于一个IQ节 该服务器必须返回一个 service unavailable 节错误给该发送者 对于一个message节 该服务器必需要么 a 安静地忽略该消息 要么 b 返回一个 service unavailable 节错误给该发送者 对于一个不带 type 属性或 type 属性为 unavailable 的的presence节 该服务器必须安静地忽略该节 对于一个类型为 subscribe subscribed unsubscribe 或 unsubscribed 的presence节 该服务器必须安静地忽略该节 对于一个类型为 probe 的presence节 该服务器必需要么 a 安静地忽略该节 要么 b 返回一个类型为 unsubscribed 的presence节 本地部分 域部分 如果 to 属性中包含的JID的格式为 localpart domainpart 那么该服务器必需遵循以下规则 可用或已连接的资源 如果至少有一个可用资源或已连接资源 如何处理该节取决于该节的类型 Message 对于一个类型为 normal 的消息节 如果所有可用资源有一个负的出席信息优先级 那么该服务器应该要么 a 存储该消息为离线用于晚些时候递送 要么 b 返回一个节错误给该发送者 该错误应该是 service unavailable 如果有一个可用资源而它是非负的出席信息优先级 那么该服务器必须递送该消息给那个资源 如果有多个可用资源都有非负的出席信息优先级 那么该服务器必须要么 a 递送该消息给 最可用的 资源或资源们 根据服务器的实现特有的机制 例如 认为拥有最高出席信息优先级的资源或资源们是 最可用的 要么 b 递送该消息给所有非负的资源 对于一个类型为 chat 的消息节 如果这个唯一的可用资源有一个负的出席信息优先级 那么该服务器应该要么 a 存储该消息为离线用于晚些时候递送 要么 b 返回一个节错误给该发送者 该错误应该是 service unavailable 如果这个唯一的可用资源有一个非负的出席信息优先级 那么该服务器必须递送该消息给那个资源 如果有多个可用资源都有非负的出席信息优先级 那么该服务器必须要么 a 递送该消息给 最可用的 资源或资源们 根据服务器的实现特有的机制 例如 认为拥有最高出席信息优先级的资源或资源们是 最可用的 要么 b 递送该消息给所有曾经被选择接收了聊天消息的非负的资源 对于类型为 groupchat 的消息节 该服务器不能 MUST NOT 递送该节给任何可用资源 而必须返回一个节错误给该发送者 该错误应该是 service unavailable 对于一个类型为 headline 的消息节 如果这个唯一的可用资源有一个负的出席信息优先级 那么该服务器必须安静地忽略该节 如果这个唯一的可用资源有一个非负的出席信息优先级 那么该服务器必须递送该消息给那个资源 如果有多个可用资源都有非负的出席信息优先级 那么该服务器必须递送该消息给所有非负的资源 对于类型为 error 的消息节 该服务器必须安静地忽略该消息 无论如何 对于任何消息类型 该服务器不能 MUST NOT 递送该节给任何负优先级的可用资源 如果只有一个可用资源且优先级为负 该服务器应该如 8 5 2 2 所述 视同没有可用资源或已连接资源那样处理该消息 在所有情况下 该服务器不能 MUST NOT 重写 to 属性 即 它必须让它就是 localpart domainpart 而不是把它改成 localpart domainpart resourcepart Presence 对于一个没有类型或类型为 unavailable 的出席信息节 该服务器必须递送它到所有可用资源 对于一个类型为 subscribe subscribed unsubscribe 或 unsubscribed 的出席信息节 该服务器必须遵循 第3章 定义的规则和 附录A 的总结 对于一个类型为 probe 的出席信息节 该服务器必须如 4 3 所述直接处理它 在所有情况下 该服务器不能 MUST NOT 重写 to 属性 即 它必须让它就是 localpart domainpart 而不是把它改成 localpart domainpart resourcepart IQ 对于一个IQ节 该服务器本身必须代表该用户应答一个IQ result 或一个IQ error 并且不能 MUST NOT 递送该IQ节给该用户的任何可用资源 特别是 如果限定的命名空间的语义定义了一个该服务器能代表该用户提供应答 那么该服务器必须代表该用户应答该节 要么返回一个类型为 result 的IQ节要么是一个类型为 error 的适合原始载荷的IQ节 否则 该服务器必须应答一个 service unavailable 节错误 无可用或已连接的资源 如果没有可用资源或已连接资源 如何处理该节取决于该节的类型 Message 对于一个类型为 normal 或 chat 的消息节 该服务器应该要么 a 添加该消息到离线存储 要么 b 返回一个节错误给该发送者 该错误应该为 service unavailable 对于一个类型为 groupchat 的消息节 该服务器必须返回一个节错误给该发送者 该错误应该为 service unavailable 对于一个类型为 headline 或 error 的消息节 该服务器必须安静地忽略该消息 Presence 对于一个没有类型或类型为 unavailable 的出席信息节 该服务器应该安静地忽略该节 不把它存下来用于晚些时候递送 也不代表该用户应答它 对于一个类型为 subscribe subscribed unsubscribe 或 unsubscribed 的出席信息节 该服务器必须遵循 第3章 定义的规则和 附录A 的总结 对于一个类型为 probe 的出席信息节 该服务器必须如 4 3 所述直接处理它 IQ 对于一个IQ节 该服务器本身必须代表该用户应答一个IQ result 或一个IQ error 并且不能 MUST NOT 递送该IQ节给该用户的任何可用资源 特别是 如果限定的命名空间的语义定义了一个该服务器能代表该用户提供应答 那么该服务器必须代表该用户应答该节 要么返回一个类型为 result 的IQ节要么是一个类型为 error 的适合原始载荷的IQ节 否则 该服务器必须应答一个 service unavailable 节错误 本地部分 域部分 资源部分 如果一个入站节的 to 属性中包含的JID的域部分和该服务器本身配置的域之一匹配并且包含在 to 属性中的JID的格式为 localpart domainpart resourcepart 那么该服务器必须遵循以下规则 资源匹配 如果一个可用的资源或已连接的资源准确地匹配该全JID 如何处理该节取决于该节的类型 对于一个类型为 get 或 set 的IQ节 如果预期的接收者未通过类型为 both 或 from 的所谓出席信息订阅或通过所谓定向出席信息来分享出席信息给请求实体 那么该服务器不应该 SHOULD NOT 递送该IQ节 而应该返回一个 service unavailable 节错误给请求实体 这个策略帮助防止出席信息泄漏 见 第11章 对于一个类型为 result 或 error 的IQ节 该服务器必须递送该节给该资源 对于一个消息节 该服务器必须递送该节给该资源 对于一个没有 type 属性或 type 属性为 unavailable 的出席信息节 该服务器必须递送该节给该资源 对于一个类型为 subscribe subscribed unsubscribe 或 unsubscribed 的出席信息节 该服务器必须遵循 第3章 提供的指南 对于一个类型为 probe 的出席信息节 该服务器必需跟随 4 3 提供的指南 无资源匹配 如果没有可用资源或已连接的资源准确匹配该全JID 如何处理该节取决于该节的类型 Message 对于一个类型为 normal groupchat 或 headline 的消息节 该服务器必须要么 a 安静地忽略该节 要么 b 返回一个错误节给该发送者 该节错误应该是 service unavailable 对于一个类型为 chat 的消息节 如果没有可用或已连接的资源 该服务器必须要么 a 存储该消息到离线用于晚些时候递送 要么 b 返回一个错误节给该发送者 该节错误应该是 service unavailable 如果所有可用资源都有一个负的出席信息优先级那么该服务器应该 a 存储该消息到离线用于晚些时候递送 或 b 返回一个错误节给该发送者 该节错误应该是 service unavailable 如果有一个可用资源的出席信息优先级不是负的那么该服务器必须递送该消息给那个资源 如果有多个资源的出席信息优先级是非负的那么该服务器必须要么 a 递送该消息给 最可用的 资源或资源们 根据服务器的实现特有的机制

    Original URL path: http://wiki.jabbercn.org/index.php?title=RFC6121&printable=yes (2016-04-25)
    Open archived version from archive

  • RFC3921 - Jabber/XMPP中文翻译计划
    名册推送 包括一个类型为 set 的IQ节 从服务器发送给客户端 使用户的所有可用资源保持和基于服务器的名册信息的同步 例子 服务器 1 推送更新的名册信息给所有已请求名册的可用资源 并且 2 以一个IO结果应答发送的资源 iq to juliet example com balcony type set id a78b4q6ha463 query xmlns jabber iq roster item jid nurse example com name Nurse subscription none group Servants group item query iq iq to juliet example com chamber type set id a78b4q6ha464 query xmlns jabber iq roster item jid nurse example com name Nurse subscription none group Servants group item query iq iq to juliet example com balcony type result id roster 2 正如IQ节类型 定义在 XMPP CORE XMPP文档列表 XMPP正式RFC标准 RFC3920 的语义所要求的 每个接收到了名册推送的资源必须 MUST 应答一个类型为 result 或 error 的IQ节 例子 资源应答一个IQ结果给服务器 iq from juliet example com balcony to example com type result id a78b4q6ha463 iq from juliet example com chamber to example com type result id a78b4q6ha464 更新名册条目 更新一个已有的名册条目 例如 改变组 的方法和增加一个新的名册条目是一样的 换言之 在IQ set 节中发送名册条目给服务器 例子 用户更新名册条目 增加组 iq from juliet example com chamber type set id roster 3 query xmlns jabber iq roster item jid romeo example net name Romeo subscription both group Friends group group Lovers group item query iq 正如增加一个名册条目 当更新一个名册条目时服务器必须 MUST 在持久信息存储机构中更新名册信息 并且也要初始化一个名册推送给这个用户的所有已请求名册的可用资源 删除一个名册条目 任何时候 用户可以 MAY 从他或她的名册中删除一个条目 只要发送一个 IQ set 给服务器并确保其 subscription 属性值为 remove 如果从一个客户端接收到 subscription 属性的任何其他值 一个兼容的服务器必须 MUST 忽略它 例子 客户端移除一个条目 iq from juliet example com balcony type set id roster 4 query xmlns jabber iq roster item jid nurse example com subscription remove query iq 和增加一个名册条目一样 删除一个名册条目的时候服务器必须 MUST 在持久信息存储机构中更新名册信息 初始化一个名册推送给这个用户的所有已请求名册的可用资源 伴随着把 subscription 属性值设为 remove 并且发送一个 IQ result 给初始化资源 关于这个命令的含义的更多信息 见 移除一个名册条目并取消所有订阅Removing a Roster Item and Cancelling All Subscriptions 第八章第六节 名册条目和出席信息订阅的集成 概览 关于用户从或向别的联系人订阅出席信息 一个即时消息用户通常希望在名册条目和出席信息订阅之间有某些层次的集成 本章描述了在XMPP即时消息应用中必须 MUST 支持的那些层次的集成 有四种主要的订阅状态 None 这个用户没有对这个联系人出席信息的订阅 这个联系人也没有订阅用户的出席信息 To 这个用户订阅了这个联系人的出席信息 但是这个联系人没有订阅用户的出席信息 From 这个联系人订阅了用户的出席信息 但是这个用户没有订阅这个联系人的出席信息 Both 用户和联系人互相订阅了对方的出席信息 例如 联合 from 和 to 这些状态的每一个都被反射到用户和联系人双方的名册中 从而导致持久的订阅状态 在以下的子章节中将叙述这些订阅状态如何为了完成特定的已定义的用例而进行交互 关于服务器和客户端处理所有订阅状态的细节 包括处于以上所列的状态之外的未决状态 在 订阅状态Subscription States 第九章 服务器不能 MUST NOT 发送出席信息订阅请求或名册推送给不可用的资源 也不能给没有已请求的名册的可用资源 在名册推送中 from 和 to 地址是可选的 OPTIONAL 如果包含了 它们的值应该 SHOULD 是那个会话的资源的全JID 一个客户端必须 MUST 以一个类型为 result 的IQ节来承认每个名册推送 为了暂时的原因 这些节不显示在以下的例子中但是按 XMPP CORE XMPP文档列表 XMPP正式RFC标准 RFC3920 定义的IQ语义学的规定它们是必需的 用户向联系人订阅 以下描述一个用户向一个联系人订阅的过程 包括名册条目和订阅状态之间的互动 1 为了能够在用户的客户端界面处理联系人以及在服务器跟踪订阅 用户的客户端应该 SHOULD 为新的名册条目执行一个 roster set 这个请求包括发送一个类型为 set 的IQ节并拥有符合 jabber iq roster 名字空间的 query 子元素 它 query 元素 再包含一个 item 子元素来定义新的名册条目 这个 item 元素必须 MUST 拥有一个 jid 属性 可以 MAY 拥有一个 name 属性 不能 MUST NOT 拥有一个 subscription 属性 并且可以 MAY 包含一个或多个 group 子元素 iq type set id set1 query xmlns jabber iq roster item jid contact example org name MyContact group MyBuddies group item query iq 2 作为结果 这个用户的服务器 1 必须 MUST 为这个新的名册条目初始化一个名册推送给这个用户的所有已经请求名册的可用资源 其 subscription 属性的值为 none 并且 2 必须 MUST 以一个 IQ result 应答发送的资源表明名册设置成功了 iq type set query xmlns jabber iq roster item jid contact example org subscription none name MyContact group MyBuddies group item query iq iq type result id set1 3 如果用户想向这个联系人请求出席信息的订阅 用户的客户端必须 MUST 发送一个类型为 subscribe 的出席信息节给联系人 presence to contact example org type subscribe 4 作为结果 用户的服务器必须 MUST 初始化第二个名册推送给这个用户的所有已经请求名册的可用资源 把这个联系人设置成 none 订阅状态的未决子状态 这个未决子状态是由名册条目中包含的ask subscribe 属性所指示的 iq type set query xmlns jabber iq roster item jid contact example org subscription none ask subscribe name MyContact group MyBuddies group item query iq 注意 如果用户在发送订阅请求之前没有新建一个名册条目 服务器必须 MUST 现在代替用户新建一个 然后发送一个名册推送给这个用户的所有已经请求名册的可用资源 不含以上所示的 name 属性和 group 子元素 5 用户的服务器也必须 MUST 把这个类型为 subscribe 的出席信息节的 from 地址设置为用户的纯JID 例如 user example com 如果用户提供了设置为用户的全JID的 from 地址 服务器应该 SHOULD 移除资源ID 如果联系人和用户在不同的主机上 用户的服务器必须 MUST 路由这个出席信息节到联系人的服务器来递送到这个联系人 这种情形的假定贯穿本文 无论如何 如果联系人在同一台主机 那么服务器可以简单地直接递送出席信息节 presence from user example com to contact example org type subscribe 注意 如果用户的服务器从联系人的服务器收到了一个类型为 error 的出席信息节 它必须 MUST 这个错误节给用户 用户的客户端可以 MAY 确定那个错误是否对于上次用户发出的 subscribe 类型的出席信息节 例如 通过跟踪 id 属性 的应答 然后选择重新发送 subscribe 请求还是发送一个 unsubscribe 类型的出席信息节给联系人以恢复到它的上一个状态 6 接收到指向联系人的 subscribe 类型的出席信息节之后 这个联系人的服务器必须 MUST 决定是否至少有一个已请求名册的联系人的可用资源 如果是 它必须 MUST 递送这个订阅请求给这个联系人 如果不是 联系人的服务器必须 MUST 离线存储这个订阅请求用于递送 when this condition is next met 通常这是通过增加一个关于这个联系人的名册条目到用户名册中来实现的 伴随着一个 None Pending In 的状态 定义在 订阅状态Subscription States 第九章 无论如何一个服务器不应该 SHOULD NOT 在那种状态下推送或递送名册条目给联系人 不论何时订阅请求被递送到了 联系人必须决定是否批准它 根据联系人的配置选项 联系人的客户端可以 MAY 批准或拒绝订阅请求而无需向联系人显示 这里我们假定这个 happy path 即联系人批准了订阅请求 替代的拒绝订阅请求的流程定义在第八章第二节第一小节 在这种情形下 这个联系人的客户端 1 应该 SHOULD 执行一个roster set 为这个用户指明期望的昵称和组 如果有的话 并且 2 必须 MUST 发送一个 subscribed 类型的出席信息节给这个用户以批准这个订阅请求 iq type set id set2 query xmlns jabber iq roster item jid user example com name SomeUser group SomeGroup group item query iq presence to user example com type subscribed 7 作为结果 联系人的服务器 1 必须 MUST 初始化一个名册推送给所有联系人已请求名册的可用资源 包含一个关于那个用户的名册条目 并且其订阅状态为 from 甚至联系人不执行roster set 服务器也必须 MUST 发送它 2 必须 MUST 返回一个 IQ result 给发送的资源表示名册设置 roster set 成功了 3 必须 MUST 路由这个 subscribed 类型的出席信息节给用户 首先把 from 地址设为联系人的纯JID contact example org 然后 4 必须 MUST 从所有联系人的可用资源向用户发送可用的出席信息 iq type set to contact example org resource query xmlns jabber iq roster item jid user example com subscription from name SomeUser group SomeGroup group item query iq iq type result to contact example org resource id set2 presence from contact example org to user example com type subscribed presence from contact example org resource to user example com 注意 如果联系人的服务器从用户的服务器收到一个 error 类型的出席信息节 它必须 MUST 递送这个错误节给联系人 联系人的客户端可以 MAY 确定那个错误是否对于上次联系人发出的 subscribe 类型的出席信息节 例如 通过跟踪 id 属性 的应答 然后选择重新发送 subscribe 请求还是发送一个 unsubscribe 类型的出席信息节给用户以恢复到它的上一个状态 8 接收到一个指向用户的 subscribed 类型的出席信息节之后 用户的服务器必须 MUST 首先检查在用户名册中的这个联系人的状态是 a subscription none and ask subscribe 还是 b subscription from and ask subscribe 如果联系人不是以上述的状态在用户的名册中 用户的服务器必须 MUST 安静的忽略这个 subscribed 类型的出席信息节 例如 服务器不能 MUST NOT 路由它到用户 修改用户的名册 或生成一个名册推送到用户的可用资源 如果联系人以上述任何一种状态存在于用户的名册中 用户的服务器 1 必须 MUST 从联系人向用户递送这个 subscribed 类型的出席信息节 2 必须 MUST 初始化一个名册推送给所有已请求名册的这个用户的可用资源 包含一个关于这个联系人的更新的名册条目 同时其 subscription 属性值设置为 to 并且 3 必须 MUST 从每一个联系人的可用资源向每一个用户的可用资源递送服务器接收到的可用的出席信息节 presence to user example com from contact example org type subscribed iq type set query xmlns jabber iq roster item jid contact example org subscription to name MyContact group MyBuddies group item query iq presence from contact example org resource to user example com resource 9 接收到 subscribed 类型的出席信息节之后 用户应该 SHOULD 承认接收到了订阅状态通知 要么发送一个 subscribe 类型的出席信息节给联系人证实它 要么发送一个 unsubscribe 类型的出席信息节给联系人否认它 这个步骤不一定影响订阅状态 见 订阅状态Subscription States 第九章 的细节 但是会让用户用户的服务器知道它必须 MUST 不再发送订阅状态改变通知给用户 见第九章第四节 从用户这方面看 现在存在一个向联系人的出席信息的订阅 从联系人的方面看 现在存在一个从用户的来的订阅 替代流程 联系人拒绝订阅请求 以上活动流程展示了关于用户向联系人的订阅请求的 happy path 如果联系人拒绝用户的订阅请求 那么主要的替代流程如下所述 1 如果联系人想拒绝这个请求 联系人的客户端必须 MUST 发送一个 unsubscribed 类型的出席信息节给用户 取代第八章第二节中步骤6发送的 subscribed 类型的出席信息节 presence to user example com type unsubscribed 2 作为结果 联系人的服务器必须 MUST 路由这个 unsubscribed 类型的出席信息节给用户 首先把 from 地址设为联系人的纯JID contact example org presence from contact example org to user example com type unsubscribed 注意 如果联系人的服务器之前把用户添加到了联系人的名册中用来跟踪 这时它必须 MUST 移除这个相关的条目 3 接收到指向用户的 unsubscribed 类型出席信息节之后 用户的服务器 1 必须 MUST 地送那个出席信息节给用户 并且 2 必须 MUST 初始化一个名册推送给这个用户的所有已请求名册的可用资源 包含一个关于这个联系人的一个更新条目 其 subscription 属性设为 none 并且没有 ask 属性 presence from contact example org to user example com type unsubscribed iq type set query xmlns jabber iq roster item jid contact example org subscription none name MyContact group MyBuddies group item query iq 4 接收到类型为 unsubscribed 出席信息节之后 用户应该 SHOULD 承认收到订阅状态通知 要么发送一个 unsubscribe 类型的出席信息节给联系人证实它 要么发送一个 subscribe 类型的出席信息节给联系人否认它 这一步骤不影响订阅状态 见 订阅状态Subscription States 第九章 的细节 但是让用户的服务器知道它必须 MUST 不再发送订阅状态改变的通知给用户 见第九章第四节 作为这一行为的结果 联系人现在在用户的名册中 状态为 none 而用户根本不在联系人的名册中 建立一个相互的订阅 用户和联系人可以在前述 happy path 的基础上建立一个相互的订阅 例如 一个 both 的订阅类型 流程如下 1 如果联系人想建立一个相互的订阅 联系人必须 MUST 发送一个订阅请求给用户 视联系人的配置选项而定 联系人的客户端可以 MAY 自动发送它 presence to user example com type subscribe 2 作为结果 联系人的服务器 1 必须 MUST 初始化一个名册推送给联系人的所有已请求名册的可用资源 伴随着用户仍在 from 订阅状态但同时有一个未决的 to 订阅状态 通过在名册条目中包含一个ask subscribe 的属性来指示 并且 2 必须 MUST 路由这个 subscribe 类型的出席信息节给用户 先把 from 地址设为联系人的纯JID contact example org iq type set query xmlns jabber iq roster item jid user example com subscription from ask subscribe name SomeUser group SomeGroup group item query iq presence from contact example org to user example com type subscribe 注意 如果联系人的服务器从用户的服务器收到一个 error 类型的出席信息节 它必须 MUST 递送这个错误节给联系人 它的客户端可以 MAY 确定这个错误是用来应答上次发送的 subscribe 类型的出席信息节 换言之 通过跟踪 id 属性 并且选择重发这个 subscribe 请求还是发送一个 unsubscribe 类型的出席信息节给用户以把名册恢复到它的前一个状态 3 接收到指向用户的 subscribe 类型出席信息节之后 用户的服务器必须确定是否至少有一个已请求名册可用资源 如果是 用户的服务器必须 MUST 递送这个订阅请求给用户 如果不是 它必须 MUST 离线存储这个订阅请求等这种情形再次发生时递送 无论何时订阅请求被递送了 用户必须决定是否批准它 视用户的配置选项而定 用户的客户端可以 MAY 批准或拒绝这个订阅请求而不需要向用户显示 这里我们假定这是 happy path 用户批准了订阅请求 替代的拒绝订阅请求的流程定义在第八章第三节第一小节 在这种情形下 用户的客户端必须 MUST 发送一个 subscribed 类型的出席信息节给联系人表示批准了订阅请求 presence to contact example org type subscribed 4 作为结果 用户的服务器 1 必须 MUST 初始化一个名册推送给用户的所有已请求名册的可用资源 包含一个关于联系人的名册条目 其 subscription 属性设为 both 2 必须 MUST 路由这个 subscribed 类型的出席信息节给联系人 先把 from 地址设为用户的纯JID user example com 并且 3 必须 MUST 向联系人发送它从用户的每个可用资源收到的最近一次出席信息节的全XML 不带 to 属性 强制每个会话遵守隐私列表 iq type set query xmlns jabber iq roster item jid contact example org subscription both name MyContact group MyBuddies group item query iq presence from user example com to contact example org type subscribed presence from user example com resource to contact example org 注意 如果用户的服务器从联系人的服务器接收到一个 error 类型的出席信息节 它必须 MUST 递送这个错误节给用户 它客户端可以 MAY 确定这个错误是用来应答上次发出去的 subscribed 类型的出席信息节 换言之 通过跟踪 id 属性 并且选择重发这个订阅请求还是发送一个 unsubscribed 类型的出席信息节给联系人以把名册恢复到上次的状态 5 接收到指向联系人的 subscribed 类型的出席信息节之后 联系人的服务器必须 MUST 首先检查用户在联系人的名册中的状态是否以下状态之一 a subscription none and ask subscribe 或 b subscription from and ask subscribe 如果用户不是以上述两种状态之一存在于联系人的名册中 联系人的服务器必须 MUST 安静地忽略这个 subscribed 类型的出席信息节 例如 它不能 MUST NOT 路由它给联系人 修改联系人的名册 或生成一个名册推送给联系人的可用资源 如果用户以上述两种状态之一存在于联系人的名册中 联系人的服务器 1 必须 MUST 从用户向联系人递送这个 subscribed 类型的出席信息节 2 必须 MUST 初始化一个名册推送给这个联系人的所有已请求名册的可用资源 包含一个关于这个用户的更新的名册条目 其 subscription 属性值设为 both 并且 3 必须 MUST 向这个联系人的每个可用资源递送它从这个用户的每个资源收到的可用出席信息节 presence from user example com to contact example org type subscribed iq type set query xmlns jabber iq roster item jid user example com subscription both name SomeUser group SomeGroup group item query iq presence from user example com resource to contact example org resource 6 收到 subscribed 类型的出席信息节之后 联系人应该 SHOULD 承认收到订阅请求通知 要么发送一个 subscribe 的出席信息节给用户证实它 要么发送一个 unsubscribe 类型的出席信息节给用户否认它 这一步骤不影响订阅状态 细节见 订阅状态Subscription States 第九章 但是让联系人的服务器知道它必须 MUST 不再发送订阅状态变更通知给联系人 见第九章第四节 用户和联系人现在有了对双方的出席信息的一个相互订阅 换言之 这个订阅类型为 both 替代流程 用户拒绝订阅请求 以上活动流程展示了关于联系人对用户的订阅请求的 happy path 如果用户拒绝了联系人的订阅请求 其主要流程如下 1 如果用户想拒绝请求 用户的客户端必须 MUST 发送一个 unsubscribed 类型的出席信息节给联系人 替代第八章第三节中的第三步中所发送的 subscribed 类型出席信息节 presence to contact example org type unsubscribed 2 作为结果 用户的服务器必须 MUST 路由这个 unsubscribed 类型的出席信息节给联系人 首先把 from 地址设为用户的纯JID user example com presence from user example com to contact example org type unsubscribed 3 接收到指向联系人的 unsubscribed 类型的出席信息节之后 联系人的服务器 1 必须 MUST 递送这个出席信息节给联系人 并且 2 必须 MUST 初始化一个名册推送给这个联系人的所有已请求名册的可用资源 包含关于这个用户的更新的名册条目 其 subscription 属性的值设为 from 并且没有 ask 属性 presence from user example com to contact example org type unsubscribed iq type set query xmlns jabber iq roster item jid user example com subscription from name SomeUser group SomeGroup group item query iq 4 接收到 unsubscribed 类型的出席信息节之后 联系人应该 SHOULD 承认收到那个订阅状态通知 要么向用户发送一个 unsubscribe 类型的出席信息节以证实它 要么向用户发送一个 subscribe 类型的出席信息以否认它 这个步骤不会影响订阅状态 详见 订阅状态Subscription States 第九章 但是让联系人的服务器知道它必须 MUST 不再发送订阅状态变更通知给联系人 见第九章第四节 作为这一活动的结果 订阅状态没有任何改变 换言之 联系人在用户的名册中的订阅状态为 to 并且用户在联系人的名册中的订阅状态为 from 取消订阅 在订阅了一个联系人的出席信息之后的任何时候 一个用户可以 MAY 取消订阅 在所有实例中用户发送来执行这一动作的XML是相同的 接下来的订阅状态根据发出取消订阅命令时获得的订阅状态的情况而不同 两种可能的情节描述如下 情形 1 当订阅不是相互的时候取消订阅 在第一种情形 用户有一个向联系人的出席信息的订阅但是联系人没有对用户的出席信息的订阅 换言之 订阅不是相互的 1 如果用户想取消对联系人的出席信息的订阅 用户必须 MUST 发送一个 unsubscribe 类型的出席信息节给联系人 presence to contact example org type unsubscribe 2 作为一个结果 用户的服务器 1 必须 MUST 发送一个名册推送给这个用户的所有已请求名册的可用资源 包含一个关于这个联系人的更新名册条目 其 subscription 属性设为 none 并且 2 必须 MUST 路由这个 unsubscribe 类型的出席信息节给联系人 首先把 from 地址设为用户的纯JID user example com iq type set query xmlns jabber iq roster item jid contact example org subscription none name MyContact group MyBuddies group item query iq presence from user example com to contact example org type unsubscribe 3 接收到指向联系人的 unsubscribe 类型出席信息节之后 联系人的服务器 1 必须 MUST 初始化一个名册推送给这个联系人的所有已请求名册的可用资源 包含一个关于这个用户的名册条目 其 subscription 属性值设为 none 如果联系人不可用或未曾请求名册 联系人的服务器必须 MUST 修改名册条目并在下次联系人请求名册时发送那个已修改的条目 并且 2 必须 MUST 递送这个 unsubscribe 状态改变通知给联系人 iq type set query xmlns jabber iq roster item jid user example com subscription none name SomeUser group SomeGroup group item query iq presence from user example com to contact example org type unsubscribe 4 接收到 unsubscribe 类型的出席信息节之后 联系人应该 SHOULD 承认收到那个订阅状态通知 要么发送一个 unsubscribed 类型的出席信息节给用户以证实它 要么发送一个 subscribed 类型的出席信息节给用户否认它 这个步骤不影响订阅状态 详见 订阅状态Subscription States 第九章 但是让联系人的服务器知道它必须 MUST 不再发送订阅状态变更通知给联系人 见第九章第四节 5 联系人的服务器接着 1 必须 MUST 发送一个 unsubscribed 类型的出席信息节给用户 并且 2 应该 SHOULD 向用户发送从这个联系人的所有可用资源收到的不可用出席信息 presence from contact example org to user example com type unsubscribed presence from contact example org resource to user example com type unavailable 6 当用户的服务器收到类型为 unsubscribed 和 unavailable 的出席信息节 它必须 MUST 递送它们给用户 presence from contact example org to user example com type unsubscribed presence from contact example org resource to user example com type unavailable 7 接收到 unsubscribed 类型的出席信息节之后 用户应该 SHOULD 承认收到那个订阅状态变更通知 要么向联系人发送一个 unsubscribe 类型的出席信息节以证实它 要么向联系人发送一个 subscribe 的出席信息节以否认它 这步骤不影响订阅状态 详见 订阅状态Subscription States 第九章 但是让用户的服务器知道它必须 MUST 不在发送订阅状态变更通知给用户 见第九章第四节 情形 2 当订阅是相互的时候取消订阅 在第二种情形下 用户有一个向联系人的出席信息的订阅并且联系人也有一个向用户的出席信息的订阅 换言之 订阅是相互的 1 如果用户想从联系人的出席信息取消订阅 用户必须 MUST 发送一个 unsubscribe 类型的出席信息节给联系人 presence to contact example org type unsubscribe 2 作为一个结果 用户的服务器 1 必须 MUST 发送一个名册推送给这个用户的所有已请求名册的可用资源 包含一个关于这个联系人的更新名册条目 其 subscription 属性值设为 from 并且 2 必须 MUST 路由这个 unsubscribe 类型的出席信息节给这个联系人 首先把 from 地址设为这个用户的纯 JID user example com iq type set query xmlns jabber iq roster item jid contact example org subscription from name MyContact group MyBuddies group item query iq presence from user example com to contact example org type unsubscribe 3 接收到指向联系人的 unsubscribe 类型的出席信息节之后 联系人的服务器 1 必须 MUST 初始化一个名册推送给这个联系人的所有已请求名册的可用资源 包含一个关于这个用户的名册条目 其 subscription 属性值设为 to 如果联系人不可用或未曾请求名册 联系人的服务去必须 MUST 修改这个名册条目并且等下次联系人请求名册的时候再发送这个修改过的名册条目 并且 2 必须 MUST 递送这个 unsubscribe 状态变更通知给联系人 iq type set query xmlns jabber iq roster item jid user example com subscription to name SomeUser group SomeGroup group item query iq presence from user example com to contact example org type unsubscribe 4 接收到这个 unsubscribe 类型的出席信息节之后 联系人应该 SHOULD 承认收到了那个订阅状态通知 要么向用户发送一个 unsubscribed 类型的出席信息节以证实它 要么向用户发送一个 subscribed 类型的出席信息节以否认它 这个步骤不影响订阅状态 详见 订阅状态Subscription States 第九章 但是让联系人的服务器知道它必须 MUST 不再发送订阅状态变更通知给联系人 见第九章第四节 5 联系人的服务器然后 1 必须 MUST 发送一个 unsubscribed 类型的出席信息节给用户 并且 2 应该 SHOULD 向用户发送它从联系人的所有可用资源收到的不可用出席信息 presence from contact example org to user example com type unsubscribed presence from contact example org resource to user example com type unavailable 6 当用户的服务器收到 unsubscribed 和 unavailable 类型的出席信息节 它必须 MUST 递送它们给用户 presence from contact example org to user example com type unsubscribed presence from contact example org resource to user example com type unavailable 7 接收到 unsubscribed 类型的出席信息节之后 用户应该 SHOULD 承认收到了那个订阅状态的通知 要么向联系人发送一个 unsubscribe 类型的出席信息节以证实它 要么向联系人发送一个 subscribe 类型的出席信息节以否认它 这个步骤不影响订阅状态 详见 订阅状态Subscription States 第九章 但是让用户的服务器知道它必须 MUST 不在发送订阅状态变更通知给用户 见第九章第四节 注意 显然这不会导致名册条目从用户的名册移除 并且联系人仍然有一个对用户的出席信息的订阅 为了完全取消双向的订阅并完全从用户的名册中移除名册条目 用户应该 SHOULD 使用subscription remove 定义在 移除一个名册条目并取消所有订阅项Removing a Roster Item and Cancelling All Subscriptions 第八章第六节 更新名册条目 取消一个订阅项 在批准来自一个用户的任何订阅请求之后的任何时候 一个联系人可以 MAY 取消那个订阅项 联系人在所有实例中执行这个动作中发送的XML是相同的 接下来的订阅状态根据取消命令发出当时所获得的订阅状态而有所不同 所有可能的情节描述如下 情形 1 当订阅不是相互的时候取消订阅项 在第一种情形下 用户有一个对联系人的出席信息的订阅但是联系人没有对于用户的出席信息的订阅 换言之 订阅还不是相互的 1 如果联系人想取消用户的订阅项 联系人必须 MUST 发送一个 unsubscribed 类型的出席信息节给用户 presence to user example com type unsubscribed 2 作为一个结果 联系人的服务器 1 必须 MUST 发送一个名册推送给这个联系人的所有已请求名册的可用资源 包含一个关于这个用户的更新的名册条目 其 subscription 属性值设为 none 2 必须 MUST 路由这个 unsubscribed 类型的出席信息节给用户 首先把 from 地址设为联系人的纯JID contact example org 并且 3 应该 SHOULD 向用户发送它从联系人的所有可用资源收到的不可用出席信息 iq type set query xmlns jabber iq roster item jid user example com subscription none name SomeUser group SomeGroup group item query iq presence from contact example org to user example com type unsubscribed presence from contact example org resource to user example com type unavailable 3 接收到指向用户的 unsubscribed 类型的出席信息节之后 用户的服务器 1 必须 MUST 初始化一个名册推送给这个用户的所有已请求名册的可用资源 包含一个关于这个联系人的名册条目更新 其 subscription 属性值设为 none 如果用户不可用或未曾请求名册 用户的服务器必须 MUST 修改这个名册条目并且等下次用户请求名册的时候发送修改过的名册条目 2 必须 MUST 递送这个 unsubscribed 状态改变通知给这个用户的所有可用资源 并且 3 必须 MUST 向这个用户的所有可用资源递送不可用出席信息 iq type set query xmlns jabber iq roster item jid contact example org subscription none name MyContact group MyBuddies group item query iq presence from contact example org to user example com type unsubscribed presence from contact example org resource to user example com type unavailable 4 接收到 unsubscribed 类型的出席信息节之后 用户应该 SHOULD 承认收到了那个订阅状态通知 要么向联系人发送一个 unsubscribe 出席信息节以证实它 要么向联系人发送一个 subscribe 类型的出席信息节以否认它 这个步骤不影响订阅状态 详见 订阅状态Subscription States 第九章 但是让服务器知道它必须 MUST 不再发送订阅状态变更通知给用户 见第九章第四节 情形 2 当订阅项是相互的时候取消 在这种情形下 用户有一个对联系人的出席信息的订阅并且联系人也有一个对用户的出席信息的订阅 换言之 订阅是相互的 1 如果联系人想取消用户的订阅 联系人必须 MUST 发送一个 unsubscribed 类型的出席信息节给用户 presence to user example com type unsubscribed 2 作为结果 联系人的服务器 1 必须 MUST 发送一个名册推送给这个联系人的所有已请求名册的可用资源 包含关于这个用户的一个更新的名册条目 其 subscription 属性值设为 to 2 必须 MUST 路由这个 unsubscribed 类型的出席信息节给用户 首先把 from 地址设为联系人的纯JID contact example org 并且 3 应该 SHOULD 向这个用户的所有可用资源发送它从联系人的所有可用资源收到的不可用出席信息 iq type set query xmlns jabber iq roster item jid user example com subscription to name SomeUser group SomeGroup group item query iq presence from contact example org to user example com type unsubscribed presence from contact example org resource to user example com type unavailable 3 接收到指向用户的 unsubscribed 类型出席信息节之后 用户的服务器 1 必须 MUST 初始化一个名册推送给这个用户的所有已请求名册的可用资源 包含关于这个联系人的更新的名册条目 其 subscription 属性值设为 from 如果这个用户不可用或未曾请求名册 用户的服务器必须 MUST 修改这个名册条目并且等下次用户请求名册的时候发送修改过的条目给它 并且 2 必须 MUST 递送这个 unsubscribed 状态变更通知给用户的所有可用资源 并且 3 必须 MUST 向这个用户的所有可用资源递送这个不可用出席信息 iq type set query xmlns jabber iq roster item jid contact example org subscription from name MyContact group MyBuddies group item query iq presence from contact example org to user example com type unsubscribed presence from contact example org resource to user example com type unavailable 4 接收到这个 unsubscribed 类型的出席信息节之后 用户应该 SHOULD 承认收到了那个订阅状态通知 要么向联系人发送一个 unsubscribe 类型的出席信息节以证实它 要么向联系人发送一个 subscribe 类型的出席信息节以否认它 这一步骤不影响订阅状态 详见 订阅状态Subscription States 第九章 但是让用户的服务器知道它必须 MUST 不再发送订阅状态变更通知给用户 见第九章第四节 注意 显然这不会使得名册条目从联系人的名册中移除 并且联系人仍然有一个对用户的出席信息的订阅 为了完全双向的取消一个相互的订阅并且从联系人的名册中完全移除这个名册条目 联系人应该以subscription remove 定义在 移除一个名册条目并取消所有订阅项Removing a Roster Item and Cancelling All Subscriptions 第八章第六节 更新名册条目 移除一个名册条目并取消所有订阅项 因为在双向完整移除一个名册条目和取消所有订阅的过程中可能有很多步骤 名册管理协议包含一个 shortcut 方法来做这件事 无论当前的订阅状态是什么 这个过程可以通过发送一个roster set 包含一个用于这个联系人的条目 其 subscription 属性值设为 remove 来初始化 iq type set id remove1 query xmlns jabber iq roster item jid contact example org subscription remove query iq 当用户从他或她的名册中移除一个联系人 通过把 subscription 属性值设为 remove 用户的服务器 1 必须 MUST 自动取消用户和联系人之间的任何现存的出席信息订阅项 包括相应的 to 和 from 2 必须 MUST 从用户的名册移除这个名册条目并且通知这个用户的所有已请求名册的可用资源这个名册条目被移除了 3 必须 MUST 通知初始化的资源移除成功了 并且 4 应该 SHOULD 向联系人发送它从这个用户的所有可用资源收到的不可用出席信息 presence from user example com to contact example org type unsubscribe presence from user example com to contact example org type unsubscribed iq type set query xmlns jabber iq roster item jid contact example org subscription remove query iq iq type result id remove1 presence from user example com resource to contact example org type unavailable 收到 unsubscribe 类型的出席信息后 联系人的服务器 1 必须 MUST 初始化一个名册推送给这个联系人的所有已请求名册的可用资源 包含关于这个用户的一个更新的名册条目 其 subscription 属性值设为 to 如果这个联系人不可用或未曾请求名册 联系人的服务器必须 MUST 修改这个名册条目并且等下次联系人请求名册的时候发送这个修改过的条目给它 并且 2 也必须 MUST 递送这个 unsubscribe 状态变更通知给这个联系人的所有可用资源 iq type set query xmlns jabber iq roster item jid user example com subscription to name SomeUser group SomeGroup group item query iq presence from user example com to contact example org type unsubscribe 收到这个 unsubscribed 类型的出席信息节之后 联系人的服务器 1 必须 MUST 初始化一个名册推送给这个联系人的所有已请求名册的可用资源 包含一个关于这个用户的更新的名册条目 其 subscription 属性值设为 none 如果这个联系人不可用或未曾请求名册 联系人的服务器必须 MUST 修改名册条目并且等下次联系人请求名册的时候把修改过的条目发送给它 并且 2 也必须 MUST 递送这个 unsubscribe 状态改变通知给这个联系人的所有可用资源 iq type set query xmlns jabber iq roster item jid user example com subscription none name SomeUser group SomeGroup group item query iq presence from user example com to contact example org type unsubscribed 接收到指向联系人的 unavailable 出席信息节之后 联系人的服务器必须 MUST 递送这个不可用出席信息给这个用户的所有可用资源 presence from user example com resource to contact example org type unavailable 注意 当用户从用户的名册中移除联系人的时候 这个联系人的名册最后状态是用户仍然在联系人名册中但是订阅状态为 none 为了完全移除关于这个用户的名册条目 联系人也需要发送一个名册移除请求 订阅状态 本章提供关于订阅状态以及和订阅相关的出席信息节 换言之 类型为 subscribe subscribed unsubscribe 和 unsubscribed 的出席信息节 的服务器处理过程的详细信息 已定义的状态 有九种可能的订阅状态 从用户的 不是联系人的 角度描述如下 None 联系人和用户互相没有被对方订阅 并且也都没有从对方那里请求一个订阅 None Pending Out 联系人和用户互相没有被对方订阅 用户已经向联系人发送了一个订阅请求但还没有收到回复 None Pending In 联系人和用户互相没有被对方订阅 联系人已经向用户发送了一个订阅请求但还没有收到回复 注意 在这种状态下联系人的服务器不应该 SHOULD NOT 推送或递送名册条目 但是应该 SHOULD 等待 直到联系人的订阅请求已经从用户那里得到批准 None Pending Out In 联系人和用户互相没有被对方订阅 联系人已经向用户发送了一个订阅请求但还没有收到回复 用户已经向联系人发送了一个订阅请求但还没有收到回复 To 用户已订阅联系人 单向 To Pending In 用户已订阅联系人 联系人已经向用户发送了一个订阅请求但还没有收到回复 From 联系人已订阅用户 单向 From Pending Out 联系人已订阅用户 单向 用户已经向联系人发送了一个订阅请求但还没有收到回复 Both 用户和联系人互相被对方订阅了 双向 出站出席信息订阅节的服务器处理过程 出站出席信息订阅节使用户能管理他或她对联系人的出席信息的订阅 通过 subscribe 和 unsubscribe 类型 并且管理联系人对用户的出席信息的访问 通过 subscribed 和 unsubscribed 类型 因为用户的服务器和联系人的服务器有可能失去对于订阅状态的同步 用户的服务器必须 MUST 毫无例外地路由所有 subscribe 或 unsubscribe 类型的出站出席信息节给联系人 使用户能在需要的时候重新同步他或她的对联系人的出席信息的订阅 如果从用户的角度来看 一个 subscribed 或 unsubscribed 类型的出席信息节不会导致一个订阅状态的变更 用户的服务器不应该 SHOULD NOT 路由这个节到联系人那里 并且不能 MUST NOT 做出一个状态变更 如果这个节导致一个订阅状态的变更 用户的服务器必须 MUST 路由这个节到联系人 并且必须 MUST 做出相应的状态变更 这些规则总结如下这些表 表 1 推荐的出站 subscribed 节的处理 当前状态 路由 新状态 None 否 状态不变 None Pending Out 否 状态不变 None Pending In 是 From None Pending Out In 是 From Pending Out To 否 状态不变 To Pending In 是 Both From 否 状态不变 From Pending Out 否 状态不变 Both 否 状态不变 表 2 推荐的出站 unsubscribed 节处理 当前状态 路由 新状态 None 否 状态不变 None Pending Out 否 状态不变 None Pending In 是 None None Pending Out In 是 None Pending Out To 否 状态不变 To Pending In 是 To From 是 None From Pending Out 是 None Pending Out Both 是 To 入站出席信息订阅节的服务器处理过程 入站出席信息订阅节从用户请求一个订阅相关的动作 通过 subscribe 类型 通知用户由联系人所做的订阅状态相关的动作 通过 unsubscribe 类型 或使联系人能够管理用户对联系人的出席信息的访问 通过 subscribed 和 unsubscribed 类型 当用户的服务器为用户从联系人那里接收到一个订阅请求 换言之 一个 subscribe 类型的出席信息节 如果用户未曾允许联系人访问用户的出席信息或者没有未决的入站订阅请求 它必须 MUST 递送那个请求给用户 无论如何 如果有一个未决的入站订阅请求 用户的服务器不应该 SHOULD NOT 递送这个新的请求 因为上一个订阅请求可能已经被记录下来了 如果用户已经允许联系人访问用户的出席信息 用户的服务器应该 SHOULD 对一个从联系人发来的 subscribe 类型的入站出席信息节自动回复 通过代替用户向联系人发送一个 subscribed 类型的出席信息节 这个规则使得联系人可以在需要的时候重新同步订阅状态 这些规则总结如下面这些表 表 3 推荐的入站 subscribe 节处理 当前状态 递送 新状态 None 是 None Pending In None Pending Out 是 None Pending Out In None Pending In 否 状态不变 None Pending Out In 否 状态不变 To 是 To Pending In To Pending In 否 状态不变 From 否 状态不变 From Pending Out 否 状态不变 Both 否 状态不变 服务器应该 SHOULD 以 subscribed 节自动回复 当用户的服务器为用户从联系人那里收到一个 unsubscribe 类型的出席信息节 如果从用户的角度看这个节会导致一个订阅状态变更 那么用户的服务器应该 SHOULD 代替用户自动应答 发送一个 unsubscribed 类型的出席信息节给联系人 必须 MUST 递送这个 unsubscribe 节给用户 并且必须 MUST 改变状态 如果不会导致订阅状态变更 用户的服务器不应该 SHOULD NOT 递送这个节并且不能 MUST NOT 改变状态 这些规则总结如下表 表 4 推荐的入站 unsubscribe 节处理 当前状态 递送 新状态 None 否 状态不变 None Pending Out 否 状态不变 None Pending In 是 None None Pending Out In 是 None Pending Out To 否 状态不变 To Pending In 是 To From 是 None From Pending Out 是 None Pending Out Both 是 To 服务器应该 SHOULD 以 unsubscribed 节自动应答 当用户的服务器为用户从联系人那里收到一个 subscribed 类型的出席信息节 如果没有一个为访问联系人的出席信息的未决的出站请求 它不能 MUST NOT 递送这个节给用户并且不能 MUST NOT 改变订阅状态 如果有一个为了访问联系人的出席信息的未决的出站请求并且这个 subscribed 类型的入站出席信息请求会导致一个订阅状态的改变 用户的服务器必须 MUST 递送这个节给用户并且必须 MUST 改变订阅状态 如果用户已经有授权可以访问联系人的出席信息 这个 subscribed 类型的入站出席信息节不导致一个订阅状态的变更 从而用户的服务器不应该 SHOULD NOT 递送这个节给用户并且不能 MUST NOT 改变订阅状态 这些规则总结如下表 表 5 推荐的入站 subscribed 节处理 当前状态 递送 新状态 None 否 状态不变 None Pending Out 是 To None Pending In 否 状态不变 None Pending Out In 是 To Pending In To 否 状态不变 To Pending In 否 状态不变 From 否 状态不变 From Pending Out 是 Both Both 否 状态不变 当用户的服务器为用户从联系人那里收到了一个 unsubscribed 类型的出席信息节 如果有一个为了访问联系人的出席信息的未决的出站请求或者用户当前已经有授权可以访问联系人的出席信息 它必须 MUST 递送这个节给用户并且必须 MUST 改变订阅状态 否则 用户的服务器不应该 SHOULD NOT 递送这个节并且不能 MUST NOT 改变订阅状态 这些规则总结如下表 表 6 推荐的入站 unsubscribed 节处理 当前状态 递送 新状态 None 否 状态不变 None Pending Out 是 None None Pending In 否 状态不变 None Pending Out In 是 None Pending In To 是 None To Pending In 是 None Pending In From 否 状态不变 From Pending Out 是 From Both 是 From 服务器递送和客户端承认订阅请求以及状态变更通知 当一个服务器收到一个 subscribe 类型的入站出席信息节 换言之 一个订阅请求 或 subscribed 类型 unsubscribe 类型 或 unsubscribed 类型 换言之 一个订阅状态变更通知 除了发送适当的名册推送 或当下次名册被一个可用资源请求时发送更新的名册 它必须 MUST 递送这个请求或通知给预定的接收者至少一次 一个服务器可以 MAY 要求接收者的回执以承认接收到了所有状态变更通知 并且必须 MUST 要求承认订阅请求的情形 换言之 类型的出席信息节 subscribe 为了要求回执 一个服务器应该 SHOULD 在每次接收者登陆的时候发送这个请求或通知给它 直到这个接收者承认收到这个通知 通过证实 affirming 或禁止 denying 这个通知 如下表 表 7 订阅状态变更通知的承认 节类型 接受 禁止 subscribe subscribed unsubscribed subscribed subscribe unsubscribe unsubscribe unsubscribed subscribed unsubscribed unsubscribe subscribe 显然 根据前述的订阅状态图表 一些回执节将被路由到联系人并且导致状态的变更 而其他的则不会 无论如何 任何这样的节必须 MUST 导致服务器不再发送订阅状态变更通知给用户 因为在接收到roster set 其 subscription 属性值设为 remove 见 移除一个名册条目并且取消所有订阅项 Removing a Roster Item and Cancelling All Subscriptions 第八章第六节 之后 用户的服务器必须 MUST 自动生成 unsubscribe 和 unsubscribed 类型的出站出席信息节 服务器必须 MUST 把一个名册移除请求视为发送所有这些出席信息节 以决定是否继续向用户发送 subscribe 或 subscribed 类型的订阅状态变更通知 屏蔽通信 大多数即时消息系统已发现有必要实现一些方法来为用户屏蔽来自某些特定的其他用户的通信 这在 IMP REQS 的第五章第一节第五小节 第五章第一节第十五小节 第五章第三节第二小节 和第五章第四节第十小节中也有要求 在XMPP中这是由管理某人的隐私列表来实现的 使用 jabber iq privacy 名字空间 服务器端的隐私列表使得以下用例能够完成 接收某人的隐私列表 增加 移除 和 编辑某人的隐私列表 设置 改变 或 取消 激活的列表 设置 改变 或 取消 缺省的列表 换言之 缺省激活的那个列表 基于JID group 或 subscription 类型 或全局的 允许或屏蔽消息 允许或屏蔽入站出席信息通知 基于 JID group 或 subscription 类型 或全局的 允许或屏蔽出站出席信息通知 基于 JID group 或 subscription 类型 或全局的 允许或屏蔽 IQ 节 基于 JID group 或 subscription 类型 或全局的 允许或屏蔽所有通信 基于 JID group 或 subscription 类型 或全局的 注意 出席信息通知不包括出席信息订阅 只包括广播给那些已订阅了用户出席信息的实体的出席信息 因而这包括没有 type 属性或只包含type unavailable 的的出席信息节 语法和语义 一个用户可以 MAY 定义一个或更多的隐私列表 它们由用户的服务器保存 每个 list 元素包含一个或多个格式为 item 元素的规则 并且每个 item 元素使用属性来定义一个隐私规则类型 一个适用于规则的特定值 相应的动作 和处理顺序相应的条目位置 语法如下 iq query xmlns jabber iq privacy list name foo item type jid group subscription value bar action allow deny order unsignedInt message presence in presence out iq item list query iq 如果类型是 jid 那么 value 属性必须 MUST 包含一个合法的Jabber ID JIDs 应该 SHOULD 满足以下顺序 user domain resource 仅为匹配的资源 user domain 任何匹配的资源 domain resource 仅匹配的资源 domain 匹配这个域本身 正如任何 user domain domain resource 或 包含一个子域的地址 如果类型为 group 那么 value 属性应该 SHOULD 包含组在用户的名册中的名字 如果一个客户端尝试更新 新建 或删除一个不在用户名册中的组的列表条目 服务器应该 SHOULD 返回给客户端一个 item not found 节错误 如果类型是 subscription 那么 value 属性必须 MUST 是 both to from 或 none 定义在 名册语法和语义Roster Syntax and Semantics 第七章第一节 中的一个人 在这里 none 包括对于用户来说完全未知和根本不在用户名册中的实体 如果没有包含 type 属性 这个规则提供 失败 fall through 情景 action 属性必须 MUST 被包含并且它的值必须 MUST 是 允许 allow 或 禁止 deny order 属性必须 MUST 被包含并且它的值必须 MUST 是一个在列表的所有条目中具有唯一性的非负整数 如果一个客户端尝试以一个非唯一的order值建立或更新一个列表 服务器必须 MUST 返回给客户端一个 bad request 节错误 item 元素可以 MAY 包含一个或更多子元素 使得一个实体可以指明更多的细微控制包括屏蔽哪些种类的节 换言之 不只是简单地屏蔽所有节 允许的子元素包括 message 屏蔽引入消息节 iq 屏蔽引入 IQ 节 presence in 屏蔽引入出席信息通知 presence out 屏蔽外出出席信息通知 在 jabber iq privacy 名字空间之内 一个 set 类型的IQ节的 query 子元素不能 MUST NOT 包含超过一个子元素 换言之 这个节必须 MUST 只包含一个 active 元素 一个 default 元素 或一个 list 元素 如果一个发送中的实体违反了这个规则 接收中的实体必须 MUST 返回一个 return a bad request 节错误 当一个客户端增加或更新一个隐私列表 list 元素应该 SHOULD 包含至少一个 item 子元素 当一个客户端移除一个隐私列表的时候 list 元素不能 MUST NOT 包含任何 item 子元素 当一个客户端更新一个隐私列表的时候 它必须包含所有想得到的条目 换言之 不是一个 delta 商业规则 如果有一个为某会话设置的激活的列表 它只影响为其激活的那个会话 并且只在那一个会话的持续期间有效 服务器必须 MUST 只应用激活列表 并且不能 MUST NOT 应用缺省列表 换言之 列表没有层次 layering 缺省列表总体适用于用户 并且如果没有为一个节指向的目标session resource设置激活列表 或用户当前没有会话 它会被处理 如果没有为一个会话设置激活列表 或用户当前没有会话 并且没有缺省列表 那么所有节应该被 SHOULD BE 接受或由服务器代替用户做适当的处理 遵守 用于处理XML节的服务器规则 Server Rules for Handling XML Stanzas 第十一章 隐私列表必须 MUST 是第一个由服务器应用的递送规则 替代 1 定义在 用于处理XML节的服务器规则Server Rules for Handling XML Stanzas 第十一章 的路由和递送规则 以及 2 和订阅相关的出席信息节的处理 和相应的名册推送的生成 定义在 名册条目和出席信息订阅的集成Integration of Roster Items and Presence Subscriptions 第八章 服务器处理隐私列表条目的顺序是很重要的 列表条目必须 MUST 按照每个 item 的 order 属性的整数值的升序来处理 一旦节和一个隐私列表规则匹配 服务器必须 MUST 按照这个规则适当地处理这个节 然后终止处理 如果在一个列表中没有提供一个fall through的条目 fall through 动作被假定为 允许 allow 如果一个用户为一个激活列表更新定义 之后的基于那个激活列表的操作必须 MUST 使用更新的定义 为了那些激活列表正应用的所有资源 如果在用户的会话期间 在激活的或缺省的列表中定义的名册条目中的订阅状态改变了 或名册组改变了 接下来基于那个列表的处理必须 MUST 考虑计入这个已改变的状态或组 对那个列表当前应用的所有资源 当一个规则的定义修改了的时候 服务器必须 MUST 发送一个类型为 set 的IQ节给所有已连接的资源 包括一个只有一个 list 子元素的 query 元素 其 name 属性设为已修改的隐私列表的名字 这些 隐私列表推送 privacy list pushes 遵守和用于名册管理的名册推送 roster pushes 同样的语义 除了被推送给已连接的资源的列表名字本身 不是完整的列表定义或那个 delta 是否接受这个修改了的列表定义最终由接收中的资源来决定 尽管如果这个列表正在应用于一个已连接的资源 它应该 SHOULD 这样做 当一个已连接的资源尝试移除一个列表或指定一个新的缺省列表 而那个列表应用于一个已连接的资源而不是正在发送的资源 服务器必须 MUST 返回一个 conflict 错误给发送中的资源并且不能 MUST NOT 执行这个请求的改变 接收某人的隐私列表 例子 客户端向服务器请求隐私列表的名字 iq from romeo example net orchard type get id getlist1 query xmlns jabber iq privacy iq 例子 服务器发送隐私列表的名字给客户端 激活列表和缺省列表放在前面 iq type result id getlist1 to romeo example net orchard query xmlns jabber iq privacy active name private default name public list name public list name private list name special query iq 例子 客户端向服务器请求一个隐私列表 iq from romeo example net orchard type get id getlist2 query xmlns jabber iq privacy list name public query iq 例子 服务器发送一个隐私列表给客户端 iq type result id getlist2 to romeo example net orchard query xmlns jabber iq privacy list name public item type jid value tybalt example com action deny order 1 item action allow order 2 list query iq 例子 客户端向服务器请求另一个隐私列表 iq from romeo example net orchard type get id getlist3 query xmlns jabber iq privacy list name private query iq 例子 服务器发送另一个隐私列表给客户端 iq type result id getlist3 to romeo example net orchard query xmlns jabber iq privacy list name private item type subscription value both action allow order 10 item action deny order 15 list query iq 例子 客户端再向服务器请求另一个隐私列表 iq from romeo example net orchard type get id getlist4 query xmlns jabber iq privacy list name special query iq 例子 服务器再发送另一个隐私列表给客户端 iq type result id getlist4 to romeo example net orchard query xmlns jabber iq privacy list name special item type jid value juliet example com action allow order 6 item type jid value benvolio example org action allow order 7 item type jid value mercutio example org action allow order 42 item action deny order 666 list query iq 在这个例子中 用户有三个列表 1 public 它允许所有人的通信 除了一个指定的实体 这是缺省列表 2 private 它只允许和这个用户有双向订阅的联系人的通信 这是激活的列表 还有 3 special 它只允许三个指定的实体通信 如果用户尝试接收一个列表但是这个列表的名字不存在 服务器必须 MUST 返回一个 item not found 节错误给用户 例子 客户端尝试接收不存在的列表 iq to romeo example net orchard type error id getlist5 query xmlns jabber iq privacy list name The Empty Set query error type cancel item not found xmlns urn ietf params xml ns xmpp stanzas error iq 用户在一次只被允许接收一个列表 如果用户尝试同一个请求中接收超过一个列表 服务器必须 MUST 返回一个 bad request 节错误给用户 例子 客户端尝试接收多于一个的列表 iq to romeo example net orchard type error id getlist6 query xmlns jabber iq privacy list name public list name private list name special query error type modify bad request xmlns urn ietf params xml ns xmpp stanzas error iq 管理激活列表 为了设置或改变服务器当前应用的激活列表 用户必须 MUST 发送一个类型为 set 的IQ节 包含一个符合 jabber iq privacy 名字空间的 query 元素 这个元素 query 又包含一个空的 active 子元素 而这个 active 拥有一个 name 属性 name 属性值则设为期望的列表名 例子 客户端请求激活列表变更 iq from romeo example net orchard type set id active1 query xmlns jabber iq privacy active name special query iq 服务器必须 MUST 在返回结果给客户端之前激活并应用这个已请求的列表 例子 服务器承认激活列表变更成功 iq type result id active1 to romeo example net orchard 如果用户尝试设置一个激活列表但是列表名不存在 服务器必须 MUST 返回一个 item not found 节错误给用户 例子 客户端尝试设置一个不存在的列表作为激活列表 iq to romeo example net orchard type error id active2 query xmlns jabber iq privacy active name The Empty Set query error type cancel item not found xmlns urn ietf params xml ns xmpp stanzas error iq 为了取消使用任何激活列表 已连接的资源必须 MUST 发送一个空的 active 元素 并且不带 name 属性 例子 客户端取消使用激活列表 iq from romeo example net orchard type set id active3 query xmlns jabber iq privacy active query iq 例子 服务器承认取消任何激活列表成功 iq type result id active3 to romeo example net orchard 管理缺省列表 为了改变它的缺省列表 它对用户来说是全局应用的 不只是发送中的资源 用户必须 MUST 发送一个类型为 set 的IQ节 它包含一个符合 jabber iq privacy 名字空间的 query 元素 这个 query 元素包含一个空的 default 子元素 这个 default 子元素拥有一个 name 属性 这个 name 属性的值设为期望的列表名 例子 用户请求变更缺省列表 iq from romeo example net orchard type set id default1 query xmlns jabber iq privacy default name special query iq 例子 服务器承认缺省列表变更成功 iq type result id default1 to romeo example net orchard 如果用户尝试变更一个缺省列表但是这个缺省列表正在由至少一个已连接的但不是当前发送中的这个资源使用着 服务器必须 MUST 返回一个 conflict 节错误给发送中的资源 例子 客户端尝试改变一个缺省列表但是这个列表正在被另一个资源使用 iq to romeo example net orchard type error id default1 query xmlns jabber iq privacy default name special query error type cancel conflict xmlns urn ietf params xml ns xmpp stanzas error iq 如果用户尝试设置一个缺省列表但是这个列表的名字不存在 服务器必须 MUST 返回一个 item not found 节错误给用户 例子 客户端尝试设置一个不存在的列表作为缺省列表 iq to romeo example net orchard type error id default1 query xmlns jabber iq privacy default name The Empty Set query error type cancel item not found xmlns urn ietf params xml ns xmpp stanzas error iq 为了取消使用缺省列表 换言之 任何时候都使用域的节路由规则 用户必须 MUST 发送一个空的不带 name 属性的 default 元素 例子 客户端取消使用缺省列表 iq from romeo example net orchard type set id default2 query xmlns jabber iq privacy default query iq 例子 服务器承认成功地取消了任何缺省列表 iq type result id default2 to romeo example net orchard 如果一个已连接的资源尝试取消一个用户全局的缺省列表但是这个缺省列表正在应用于另一个已连接的资源 服务器必须 MUST 返回一个 conflict 错误给发送中的资源 例子 客户端尝试取消一个缺省列表但是这个列表正在被另一个资源使用 iq to romeo example net orchard type error id default3 query xmlns jabber iq privacy default query error type cancel conflict xmlns urn ietf params xml ns xmpp stanzas error iq 编辑一个隐私列表 为了编辑一个隐私列表 用户必须 MUST 一个类型为 set 的IQ节 包含一个符合 jabber iq privacy 名字空间的 query 元素 这个 query 元素包含一个拥有一个 list 子元素 这个 list 子元素拥有一个 name 属性 这个 name 属性的值设为用户想编辑的列表名 这个 list 元素必须 MUST 包含一个或多个 item 元素 它们包含了列表中的所有元素以指明用户期望的对列表的变更 不是the delta 例子 客户端编辑隐私列表 iq from romeo example net orchard type set id edit1 query xmlns jabber iq privacy list name public item type jid value tybalt example com action deny order 3 item type jid value paris example org action deny order 5 item action allow order 68 list query iq 例子 服务器承认列表编辑成功 iq type result id edit1 to romeo example net orchard 注意 任何给定的条目的 order 属性值不是固定的 因而在前述的例子中如果用户想在 tybalt example com 条目和 paris example org 条目之间增加4个条目 用户的客户端必须 MUST 在向服务器提交列表之前对相关的条目重新编号 服务器必须 MUST 现在发送一个 隐私列表推送 privacy list push 给所有已连接的资源 例子 基于列表编辑的隐私列表推送 iq to romeo example net orchard type set id push1 query xmlns jabber iq privacy list name public query iq iq to romeo example net home type set id push2 query xmlns jabber iq privacy list name public query iq 按照定义在 XMPP CORE XMPP文档列表 XMPP正式RFC标准 RFC3920 的IQ节语义 每个已连接的子元素必须 MUST 返回一个如下的 IQ result 给服务器 例子 承认收到一个隐私列表推送 iq from romeo example net orchard type result id push1 iq from romeo example net home type result id push2 增加一个新的隐私列表 增加一个新的列表和编辑一个现有的列表使用的协议是相同的 如果列表名和现有的列表名吻合 这个增加新列表的请求将覆写那个旧的列表 正如编辑列表一样 服务器也必须 MUST 发送一个 隐私列表推送 privacy list push 给所有已连接的资源 移除一个隐私列表 为了移除一个隐私列表 用户必须 MUST 发送一个类型为 set 的IQ节 包含一个符合 jabber iq privacy 名字空间的 query 元素 这个 query 元素包含一个空的 list 子元素 这个 list 子元素拥有一个 name 属性 这个 name 属性的值设为用户想移除的列表名 例子 客户端移除一个隐私列表 iq from romeo example net orchard type set id remove1 query xmlns jabber iq privacy list name private query iq 例子 服务器承认成功地移除列表 iq type result id remove1 to romeo example net orchard 如果一个用户尝试移除一个列表而这个列表正在被应用于至少一个和发送中的资源不同的已连接的资源 服务器必须 MUST 返回一个 conflict 节错误给用户 换言之 用户在尝试移除它之前必须 MUST 先设置另一个列表成为激活或缺省列表 如果用户尝试移除一个列表但是列表名字不存在 服务器必须 MUST 返回一个 item not found 节错误给用户 如果用户尝试在同一个请求中移除超过一个的列表 服务器必须 MUST 反回一个 bad request 节错误给用户 屏蔽消息 服务器端的隐私列表使得一个用户可以基于实体的JID 名册组 或订阅状态 或全局地 来屏蔽从其他实体引入的消息 以下例子阐明这个协议 注意 为了精简 result 类型的IQ节没有在以下例子中显示 隐私列表推送也没有显示 例子 基于JID的用户屏蔽 iq from romeo example net orchard type set id msg1 query xmlns jabber iq privacy list name message jid example item type jid value tybalt example com action deny order 3 message item list query iq 作为建立和应用前述列表的结果 用户将不会接收到从特定JID发来的消息 例子 基于名册组的用户屏蔽 iq from romeo example net orchard type set id msg2 query xmlns jabber iq privacy list name message group example item type group value Enemies action deny order 4 message item list query iq 作为建立和应用前述列表的结果 用户将不会收到从指定名册组中的任何实体发来的消息 例子 基于订阅状态的用户屏蔽 iq from romeo example net orchard type set id msg3 query xmlns jabber iq privacy list name message sub example item type subscription value none action deny order 5 message item list query iq 作为建立和应用前述列表的结果 用户将不会收到从任何指定订阅状态的实体发来的消息 例子 全局的用户屏蔽 iq from romeo example net orchard type set id msg4 query xmlns jabber iq privacy list name message global example item action deny order 6 message item list query iq 作为建立和应用前述列表的结果 用户将不会收到从任何其他用户发来的消息 屏蔽入站出席信息通知 服务器端的隐私列表使得用户可以基于实体的JID 名册组 或订阅状态 或全局地 屏蔽来自其他实体的入站出席信息通知 以下例子阐明了这个协议 注意 出席信息通知不包括出席信息订阅 只是把出席信息广播给当前已订阅某个联系人的出席信息的用户 所以它只包括没有 type 属性的或type unavailable 的出席信息节 例子 基于JID的用户屏蔽 iq from romeo example net orchard type set id presin1 query xmlns jabber iq privacy list name presin jid example item type jid value tybalt example com action deny order 7 presence in item list query iq 作为建立和应用前述列表的结果 用户将不会收到从指定JID发来的出席信息通知 例子 基于名册组的用户屏蔽 iq from romeo example net orchard type set id presin2 query xmlns jabber iq privacy list name presin group example item type group value Enemies action deny order 8 presence in item list query iq 作为建立和应用前述列表的结果 用户将不会从指定的名册组中的任何实体收到出席信息通知 例子 基于订阅状态的用户屏蔽 iq from romeo example net orchard type set id presin3 query xmlns jabber iq privacy list name presin sub example item type subscription value to action deny order 9 presence in item list query iq 作为建立和应用前述列表的结果 用户将不会从指定订阅状态的任何实体收到出席信息通知 例子 全局的用户屏蔽 iq from romeo example net orchard type set id presin4 query xmlns jabber iq privacy list name presin global example item action deny order 11 presence in item list query iq 作为建立和应用前述列表的结果 用户将不会从任何其他实体收到出席信息通知 屏蔽出站出席信息通知 服务器端的隐私列表使用户能够屏蔽发出到其他实体的出席信息通知 基于实体的JID 名册组 或订阅状态 或全局的 以下例子阐明了这个协议 注意 出席信息通知不包括出席信息订阅 只把出席信息广播给已订阅了用户的出席信息的联系人 所以 只包括没有 type 属性或type unavailable 的出席信息节 例子 基于JID的用户屏蔽 iq from romeo example net orchard type set id presout1 query xmlns jabber iq privacy list name presout jid example item type jid value tybalt example com action deny order 13 presence out item list query iq 作为建立和应用前述列表的结果 用户将不会给指定JID发送出席信息通知 例子 基于名册组的用户屏蔽 iq from romeo example net orchard type set id presout2 query xmlns jabber iq privacy list name presout group example item type group value Enemies action deny order 15 presence out item list query iq 作为建立和应用前述列表的结果 用户将不会向指定名册组的任何实体发送出席信息通知 例子 基于订阅状态的用户屏蔽 iq from romeo example net orchard type set id presout3 query xmlns jabber iq privacy list name presout sub example item type subscription value from action deny order 17 presence out item list query iq 作为建立和应用前述列表的结果 用户将不会向指定订阅状态的任何实体发送出席信息通知 例子 全局的用户屏蔽 iq from romeo example net orchard type set id presout4 query xmlns jabber iq privacy list name presout global example item action deny order 23 presence out item list query iq 作为建立和应用前述列表的结果 用户将不会向任何其他用户发送出席信息通知 屏蔽IQ节 服务器端的隐私列表使用户能够屏蔽从其他实体进来的IQ节 基于实体的JID 名册组 或订阅状态 或全局地 以下例子阐明了这个协议 例子 基于JID的用户屏蔽 iq from romeo example net orchard type set id iq1 query xmlns jabber iq privacy list name iq jid example item type jid value tybalt example com action deny order 29 iq item list query iq 作为建立和应用这个列表的结果 用户将不会收到从指定JID发来的IQ节 例子 基于名册组的用户屏蔽 iq from romeo example net orchard type set id iq2 query xmlns jabber iq privacy list name iq group example item type group value Enemies action deny order 31 iq item list query iq 作为建立和应用前述列表的结果 用户将不会收到从指定名册组的任何实体发来的IQ节 例子 基于订阅状态的用户屏蔽 iq from romeo example net orchard type set id iq3 query xmlns jabber iq privacy list name iq sub example item type subscription value none action deny order 17 iq item list query iq 作为建立和应用前述列表的结果 用户将不会收到从指定订阅状态的任何实体发来的IQ节 例子 全局的用户屏蔽 iq from romeo example net orchard type set id iq4 query xmlns jabber iq privacy list name iq global example item action deny order 1 iq item list query iq 作为建立和应用前述列表的结果 用户将不会收到从任何其他用户发来的IQ节 屏蔽所有通信 服务器端的隐私列表使用户能够基于其他实体的JID 名册组 或订阅状态 或全局的 屏蔽所有进来和出去的节 注意那部包括订阅相关的出席信息节 它们被排除在外 定义在 屏蔽入站出席信息通知Blocking Inbound Presence Notifications 第十章第十节 以下例子阐明了这个协议 例子 基于JID的用户屏蔽 iq from romeo example net orchard type set id all1 query xmlns jabber iq privacy list name all jid example item type jid value tybalt example com action deny order 23 list query iq 作为建立和应用这个列表的结果 用户将不会收到和发送任何通信给指定JID 例子 基于名册组的用户屏蔽 iq from romeo example net orchard type set id all2 query xmlns jabber iq privacy list name all group example item type group value Enemies action deny order 13 list query iq 作为建立和应用前述列表的结果 用户将不会收到和发送和指定名册组的任何实体的通信 例子 基于订阅状态的用户屏蔽 iq from romeo example net orchard type set id all3 query xmlns jabber iq privacy list name all sub example item type subscription value none action deny order 11 list query iq 作为建立和应用前述列表的结果 用户将不会收到和发送和指定订阅状态的任何实体的通信 例子 全局的用户屏蔽 iq from romeo example net orchard type set id all4 query xmlns jabber iq privacy list name all global example item action deny order 7 list query iq 作为建立和应用前述列表的结果 用户将不会收到和发送和任何其他用户的通信 已被屏蔽的实体尝试和用户通信 如果一个已被屏蔽的实体尝试发送消息或出席信息给用户 用户的服务器应该 SHOULD 安静的丢掉这个节并且不能 MUST NOT 返回一个错误给发送的实体 如果一个已被屏蔽的实体尝试发送一个类型为 get 或 set 的IQ节给用户 用户的服务器必须 MUST 给发送的实体一个 service unavailable 节错误 因为这是一个客户端不理解IQ get或set的名字空间的时候所发送的标准错误码 其他类型的IQ节应该 SHOULD 被服务器安静的丢弃 例子 已被屏蔽的实体尝试发送 IQ get iq type get to romeo example net from tybalt example com pda id probing1 query xmlns jabber iq version iq 例子 服务器返回一个错误给已被屏蔽的实体 iq type error from romeo example net to tybalt example com pda id probing1 query xmlns jabber iq version error type cancel service unavailable xmlns urn ietf params xml ns xmpp stanzas error iq 高级启发 当建立一个高级隐私启发的表达式的时候 客户端应该 SHOULD 使用尽可能简单的表达式 例如 启发 屏蔽不在我名册中的任何用户的通信 可以使用以下任何一种方式来构造 允许任何来自我的名册中的JID的通信 换言之 列出每个JID成为单独的列表条目 但是屏蔽和其他任何人的通信 允许任何来自我的名册的某个组中的用户的通信 换言之 列出每个组作为单独的条目 但是屏蔽和任何其他人的通信 允许任何我的他 她 之间的订阅状态为 both 或 to 或 from 的用户的通信 换言之 单独列出每个订阅状态值 但是屏蔽和任何其他人的通信 屏蔽和任何订阅状态为 none 的用户的通信 最后一个表达式是最简单的并且应该 SHOULD 被使用 这种情形下将被发送的XML如下 iq type set id heuristic1 query xmlns jabber iq privacy list name heuristic example item type subscription value none action deny order 437 list query iq 服务器处理XML节的规则 用于服务器的基本路由和递送规则定义在 XMPP CORE XMPP文档列表 XMPP正式RFC标准 RFC3920 中 本章定义附加的用于XMPP兼容的即时消息和出席信息服务器规则 入站节 如果一个入站的节的 to 属性的JID中的域标识符部分的主机名和服务器自身的主机名相同并且 to 属性的JID的格式是 user example com 或 user example com resource 服务器必须 MUST 首先强制应用任何隐私列表 第十章 然后服从以下定义的规则 如果JID的格式是 user domain resource 并且有一个可用的资源和这个全JID吻合 接受这得服务器必须 MUST 递送这个节给那个资源 然后如果JID的格式是 user domain 或格式是 user domain resource 并且和用户相关的帐号不存在 接收者的服务器 a 如果它是一个出席信息节 应该 SHOULD 安静的忽略这个节 换言之 既不递送它也不返回一个错误 b 如果它是一个IQ节 必须 MUST 返回一个 service unavailable 节错误给发送者 并且 c 如果它是一个消息节 应该 SHOULD 返回一个 service unavailable 节错误给发送者 然后如果JID的格式是 user domain resource 并且没有可用的资源和它的全JID匹配 接收者的服务器 a 如果它是一个出席信息节 应该 SHOULD 安静地忽略这个节 换言之 既不递送它也不返回一个错误 b 如果它是一个IQ节 必须 MUST 返回一个 service unavailable 节错误给发送者 并且 c 如果它是一个消息节 应该 SHOULD 把这个节视为发往 user domain 然后如果JID的格式是 user domain 并且这个用户至少有一个可用的资源 接收者的服务器必须 MUST 遵守以下规则 对于消息节 服务器应该 SHOULD 递送这个节给高优先级的可用资源 如果这个资源没有提供 priority 元素的值 服务器应该 SHOULD 认为它提供的值为零 如果两个或更多的可用资源有相同的优先级 服务器可以 MAY 使用一些其他的规则 例如 最近的连接时间 最近的活动时间 或由一些 show 值的层次所定义的最高的可用性 来从它们中间选择 或可以 MAY 递送这个消息到所有这些资源 无论如何 服务器不能 MUST NOT 这个节到一个优先级为负数的可用资源 如果唯一的一个可用资源的优先级是负数 服务器应该 SHOULD 当成没有可用资源一样处理这个消息 定义在后面 另外 服务器不能 MUST NOT 重写 to 属性 换言之 它必须 MUST 让它保持 user domain 而不是改成 user domain resource 对于类型不是 probe 的出席信息节 服务器必须 MUST 递送这个节给所有可用的资源 对于出席信息调查 服务器应该 SHOULD 基于定义在 出席信息调查Presence Probes 第五章第一节第三小节 的规则来应答 另外 服务器不能 MUST NOT 重写 to 属性 换言之 它必须 MUST 保持 user domain 而不是改为 user

    Original URL path: http://wiki.jabbercn.org/index.php?title=RFC3921&oldid=3240 (2016-04-25)
    Open archived version from archive

  • 查看源代码 - Jabber/XMPP中文翻译计划
    set 这个请求包括发送一个类型为 set 的IQ节并拥有符合 jabber iq roster 名字空间的 query 子元素 它 query 元素 再包含一个 item 子元素来定义新的名册条目 这个 item 元素必须 MUST 拥有一个 jid 属性 可以 MAY 拥有一个 name 属性 不能 MUST NOT 拥有一个 subscription 属性 并且可以 MAY 包含一个或多个 group 子元素 source lang xml iq type set id set1 query xmlns jabber iq roster item jid contact example org name MyContact group MyBuddies group item query iq source 2 作为结果 这个用户的服务器 1 必须 MUST 为这个新的名册条目初始化一个名册推送给这个用户的所有已经请求名册的可用资源 其 subscription 属性的值为 none 并且 2 必须 MUST 以一个 IQ result 应答发送的资源表明名册设置成功了 source lang xml iq type set query xmlns jabber iq roster item jid contact example org subscription none name MyContact group MyBuddies group item query iq iq type result id set1 source 3 如果用户想向这个联系人请求出席信息的订阅 用户的客户端必须 MUST 发送一个类型为 subscribe 的出席信息节给联系人 source lang xml presence to contact example org type subscribe source 4 作为结果 用户的服务器必须 MUST 初始化第二个名册推送给这个用户的所有已经请求名册的可用资源 把这个联系人设置成 none 订阅状态的未决子状态 这个未决子状态是由名册条目中包含的ask subscribe 属性所指示的 source lang xml iq type set query xmlns jabber iq roster item jid contact example org subscription none ask subscribe name MyContact group MyBuddies group item query iq source 注意 如果用户在发送订阅请求之前没有新建一个名册条目 服务器必须 MUST 现在代替用户新建一个 然后发送一个名册推送给这个用户的所有已经请求名册的可用资源 不含以上所示的 name 属性和 group 子元素 5 用户的服务器也必须 MUST 把这个类型为 subscribe 的出席信息节的 from 地址设置为用户的纯JID 例如 user example com 如果用户提供了设置为用户的全JID的 from 地址 服务器应该 SHOULD 移除资源ID 如果联系人和用户在不同的主机上 用户的服务器必须 MUST 路由这个出席信息节到联系人的服务器来递送到这个联系人 这种情形的假定贯穿本文 无论如何 如果联系人在同一台主机 那么服务器可以简单地直接递送出席信息节 source lang xml presence from user example com to contact example org type subscribe source 注意 如果用户的服务器从联系人的服务器收到了一个类型为 error 的出席信息节 它必须 MUST 这个错误节给用户 用户的客户端可以 MAY 确定那个错误是否对于上次用户发出的 subscribe 类型的出席信息节 例如 通过跟踪 id 属性 的应答 然后选择重新发送 subscribe 请求还是发送一个 unsubscribe 类型的出席信息节给联系人以恢复到它的上一个状态 6 接收到指向联系人的 subscribe 类型的出席信息节之后 这个联系人的服务器必须 MUST 决定是否至少有一个已请求名册的联系人的可用资源 如果是 它必须 MUST 递送这个订阅请求给这个联系人 如果不是 联系人的服务器必须 MUST 离线存储这个订阅请求用于递送 when this condition is next met 通常这是通过增加一个关于这个联系人的名册条目到用户名册中来实现的 伴随着一个 None Pending In 的状态 定义在 订阅状态Subscription States 第九章 无论如何一个服务器不应该 SHOULD NOT 在那种状态下推送或递送名册条目给联系人 不论何时订阅请求被递送到了 联系人必须决定是否批准它 根据联系人的配置选项 联系人的客户端可以 MAY 批准或拒绝订阅请求而无需向联系人显示 这里我们假定这个 happy path 即联系人批准了订阅请求 替代的拒绝订阅请求的流程定义在第八章第二节第一小节 在这种情形下 这个联系人的客户端 1 应该 SHOULD 执行一个roster set 为这个用户指明期望的昵称和组 如果有的话 并且 2 必须 MUST 发送一个 subscribed 类型的出席信息节给这个用户以批准这个订阅请求 source lang xml iq type set id set2 query xmlns jabber iq roster item jid user example com name SomeUser group SomeGroup group item query iq presence to user example com type subscribed source 7 作为结果 联系人的服务器 1 必须 MUST 初始化一个名册推送给所有联系人已请求名册的可用资源 包含一个关于那个用户的名册条目 并且其订阅状态为 from 甚至联系人不执行roster set 服务器也必须 MUST 发送它 2 必须 MUST 返回一个 IQ result 给发送的资源表示名册设置 roster set 成功了 3 必须 MUST 路由这个 subscribed 类型的出席信息节给用户 首先把 from 地址设为联系人的纯JID contact example org 然后 4 必须 MUST 从所有联系人的可用资源向用户发送可用的出席信息 source lang xml iq type set to contact example org resource query xmlns jabber iq roster item jid user example com subscription from name SomeUser group SomeGroup group item query iq iq type result to contact example org resource id set2 presence from contact example org to user example com type subscribed presence from contact example org resource to user example com source 注意 如果联系人的服务器从用户的服务器收到一个 error 类型的出席信息节 它必须 MUST 递送这个错误节给联系人 联系人的客户端可以 MAY 确定那个错误是否对于上次联系人发出的 subscribe 类型的出席信息节 例如 通过跟踪 id 属性 的应答 然后选择重新发送 subscribe 请求还是发送一个 unsubscribe 类型的出席信息节给用户以恢复到它的上一个状态 8 接收到一个指向用户的 subscribed 类型的出席信息节之后 用户的服务器必须 MUST 首先检查在用户名册中的这个联系人的状态是 a subscription none and ask subscribe 还是 b subscription from and ask subscribe 如果联系人不是以上述的状态在用户的名册中 用户的服务器必须 MUST 安静的忽略这个 subscribed 类型的出席信息节 例如 服务器不能 MUST NOT 路由它到用户 修改用户的名册 或生成一个名册推送到用户的可用资源 如果联系人以上述任何一种状态存在于用户的名册中 用户的服务器 1 必须 MUST 从联系人向用户递送这个 subscribed 类型的出席信息节 2 必须 MUST 初始化一个名册推送给所有已请求名册的这个用户的可用资源 包含一个关于这个联系人的更新的名册条目 同时其 subscription 属性值设置为 to 并且 3 必须 MUST 从每一个联系人的可用资源向每一个用户的可用资源递送服务器接收到的可用的出席信息节 source lang xml presence to user example com from contact example org type subscribed iq type set query xmlns jabber iq roster item jid contact example org subscription to name MyContact group MyBuddies group item query iq presence from contact example org resource to user example com resource source 9 接收到 subscribed 类型的出席信息节之后 用户应该 SHOULD 承认接收到了订阅状态通知 要么发送一个 subscribe 类型的出席信息节给联系人证实它 要么发送一个 unsubscribe 类型的出席信息节给联系人否认它 这个步骤不一定影响订阅状态 见 订阅状态Subscription States 第九章 的细节 但是会让用户用户的服务器知道它必须 MUST 不再发送订阅状态改变通知给用户 见第九章第四节 从用户这方面看 现在存在一个向联系人的出席信息的订阅 从联系人的方面看 现在存在一个从用户的来的订阅 替代流程 联系人拒绝订阅请求 以上活动流程展示了关于用户向联系人的订阅请求的 happy path 如果联系人拒绝用户的订阅请求 那么主要的替代流程如下所述 1 如果联系人想拒绝这个请求 联系人的客户端必须 MUST 发送一个 unsubscribed 类型的出席信息节给用户 取代第八章第二节中步骤6发送的 subscribed 类型的出席信息节 source lang xml presence to user example com type unsubscribed source 2 作为结果 联系人的服务器必须 MUST 路由这个 unsubscribed 类型的出席信息节给用户 首先把 from 地址设为联系人的纯JID contact example org source lang xml presence from contact example org to user example com type unsubscribed source 注意 如果联系人的服务器之前把用户添加到了联系人的名册中用来跟踪 这时它必须 MUST 移除这个相关的条目 3 接收到指向用户的 unsubscribed 类型出席信息节之后 用户的服务器 1 必须 MUST 地送那个出席信息节给用户 并且 2 必须 MUST 初始化一个名册推送给这个用户的所有已请求名册的可用资源 包含一个关于这个联系人的一个更新条目 其 subscription 属性设为 none 并且没有 ask 属性 source lang xml presence from contact example org to user example com type unsubscribed iq type set query xmlns jabber iq roster item jid contact example org subscription none name MyContact group MyBuddies group item query iq source 4 接收到类型为 unsubscribed 出席信息节之后 用户应该 SHOULD 承认收到订阅状态通知 要么发送一个 unsubscribe 类型的出席信息节给联系人证实它 要么发送一个 subscribe 类型的出席信息节给联系人否认它 这一步骤不影响订阅状态 见 订阅状态Subscription States 第九章 的细节 但是让用户的服务器知道它必须 MUST 不再发送订阅状态改变的通知给用户 见第九章第四节 作为这一行为的结果 联系人现在在用户的名册中 状态为 none 而用户根本不在联系人的名册中 建立一个相互的订阅 用户和联系人可以在前述 happy path 的基础上建立一个相互的订阅 例如 一个 both 的订阅类型 流程如下 1 如果联系人想建立一个相互的订阅 联系人必须 MUST 发送一个订阅请求给用户 视联系人的配置选项而定 联系人的客户端可以 MAY 自动发送它 source lang xml presence to user example com type subscribe source 2 作为结果 联系人的服务器 1 必须 MUST 初始化一个名册推送给联系人的所有已请求名册的可用资源 伴随着用户仍在 from 订阅状态但同时有一个未决的 to 订阅状态 通过在名册条目中包含一个ask subscribe 的属性来指示 并且 2 必须 MUST 路由这个 subscribe 类型的出席信息节给用户 先把 from 地址设为联系人的纯JID contact example org source lang xml iq type set query xmlns jabber iq roster item jid user example com subscription from ask subscribe name SomeUser group SomeGroup group item query iq presence from contact example org to user example com type subscribe source 注意 如果联系人的服务器从用户的服务器收到一个 error 类型的出席信息节 它必须 MUST 递送这个错误节给联系人 它的客户端可以 MAY 确定这个错误是用来应答上次发送的 subscribe 类型的出席信息节 换言之 通过跟踪 id 属性 并且选择重发这个 subscribe 请求还是发送一个 unsubscribe 类型的出席信息节给用户以把名册恢复到它的前一个状态 3 接收到指向用户的 subscribe 类型出席信息节之后 用户的服务器必须确定是否至少有一个已请求名册可用资源 如果是 用户的服务器必须 MUST 递送这个订阅请求给用户 如果不是 它必须 MUST 离线存储这个订阅请求等这种情形再次发生时递送 无论何时订阅请求被递送了 用户必须决定是否批准它 视用户的配置选项而定 用户的客户端可以 MAY 批准或拒绝这个订阅请求而不需要向用户显示 这里我们假定这是 happy path 用户批准了订阅请求 替代的拒绝订阅请求的流程定义在第八章第三节第一小节 在这种情形下 用户的客户端必须 MUST 发送一个 subscribed 类型的出席信息节给联系人表示批准了订阅请求 source lang xml presence to contact example org type subscribed source 4 作为结果 用户的服务器 1 必须 MUST 初始化一个名册推送给用户的所有已请求名册的可用资源 包含一个关于联系人的名册条目 其 subscription 属性设为 both 2 必须 MUST 路由这个 subscribed 类型的出席信息节给联系人 先把 from 地址设为用户的纯JID user example com 并且 3 必须 MUST 向联系人发送它从用户的每个可用资源收到的最近一次出席信息节的全XML 不带 to 属性 强制每个会话遵守隐私列表 source lang xml iq type set query xmlns jabber iq roster item jid contact example org subscription both name MyContact group MyBuddies group item query iq presence from user example com to contact example org type subscribed presence from user example com resource to contact example org source 注意 如果用户的服务器从联系人的服务器接收到一个 error 类型的出席信息节 它必须 MUST 递送这个错误节给用户 它客户端可以 MAY 确定这个错误是用来应答上次发出去的 subscribed 类型的出席信息节 换言之 通过跟踪 id 属性 并且选择重发这个订阅请求还是发送一个 unsubscribed 类型的出席信息节给联系人以把名册恢复到上次的状态 5 接收到指向联系人的 subscribed 类型的出席信息节之后 联系人的服务器必须 MUST 首先检查用户在联系人的名册中的状态是否以下状态之一 a subscription none and ask subscribe 或 b subscription from and ask subscribe 如果用户不是以上述两种状态之一存在于联系人的名册中 联系人的服务器必须 MUST 安静地忽略这个 subscribed 类型的出席信息节 例如 它不能 MUST NOT 路由它给联系人 修改联系人的名册 或生成一个名册推送给联系人的可用资源 如果用户以上述两种状态之一存在于联系人的名册中 联系人的服务器 1 必须 MUST 从用户向联系人递送这个 subscribed 类型的出席信息节 2 必须 MUST 初始化一个名册推送给这个联系人的所有已请求名册的可用资源 包含一个关于这个用户的更新的名册条目 其 subscription 属性值设为 both 并且 3 必须 MUST 向这个联系人的每个可用资源递送它从这个用户的每个资源收到的可用出席信息节 source lang xml presence from user example com to contact example org type subscribed iq type set query xmlns jabber iq roster item jid user example com subscription both name SomeUser group SomeGroup group item query iq presence from user example com resource to contact example org resource source 6 收到 subscribed 类型的出席信息节之后 联系人应该 SHOULD 承认收到订阅请求通知 要么发送一个 subscribe 的出席信息节给用户证实它 要么发送一个 unsubscribe 类型的出席信息节给用户否认它 这一步骤不影响订阅状态 细节见 订阅状态Subscription States 第九章 但是让联系人的服务器知道它必须 MUST 不再发送订阅状态变更通知给联系人 见第九章第四节 用户和联系人现在有了对双方的出席信息的一个相互订阅 换言之 这个订阅类型为 both 替代流程 用户拒绝订阅请求 以上活动流程展示了关于联系人对用户的订阅请求的 happy path 如果用户拒绝了联系人的订阅请求 其主要流程如下 1 如果用户想拒绝请求 用户的客户端必须 MUST 发送一个 unsubscribed 类型的出席信息节给联系人 替代第八章第三节中的第三步中所发送的 subscribed 类型出席信息节 source lang xml presence to contact example org type unsubscribed source 2 作为结果 用户的服务器必须 MUST 路由这个 unsubscribed 类型的出席信息节给联系人 首先把 from 地址设为用户的纯JID user example com source lang xml presence from user example com to contact example org type unsubscribed source 3 接收到指向联系人的 unsubscribed 类型的出席信息节之后 联系人的服务器 1 必须 MUST 递送这个出席信息节给联系人 并且 2 必须 MUST 初始化一个名册推送给这个联系人的所有已请求名册的可用资源 包含关于这个用户的更新的名册条目 其 subscription 属性的值设为 from 并且没有 ask 属性 source lang xml presence from user example com to contact example org type unsubscribed iq type set query xmlns jabber iq roster item jid user example com subscription from name SomeUser group SomeGroup group item query iq source 4 接收到 unsubscribed 类型的出席信息节之后 联系人应该 SHOULD 承认收到那个订阅状态通知 要么向用户发送一个 unsubscribe 类型的出席信息节以证实它 要么向用户发送一个 subscribe 类型的出席信息以否认它 这个步骤不会影响订阅状态 详见 订阅状态Subscription States 第九章 但是让联系人的服务器知道它必须 MUST 不再发送订阅状态变更通知给联系人 见第九章第四节 作为这一活动的结果 订阅状态没有任何改变 换言之 联系人在用户的名册中的订阅状态为 to 并且用户在联系人的名册中的订阅状态为 from 取消订阅 在订阅了一个联系人的出席信息之后的任何时候 一个用户可以 MAY 取消订阅 在所有实例中用户发送来执行这一动作的XML是相同的 接下来的订阅状态根据发出取消订阅命令时获得的订阅状态的情况而不同 两种可能的情节描述如下 情形 1 当订阅不是相互的时候取消订阅 在第一种情形 用户有一个向联系人的出席信息的订阅但是联系人没有对用户的出席信息的订阅 换言之 订阅不是相互的 1 如果用户想取消对联系人的出席信息的订阅 用户必须 MUST 发送一个 unsubscribe 类型的出席信息节给联系人 source lang xml presence to contact example org type unsubscribe source 2 作为一个结果 用户的服务器 1 必须 MUST 发送一个名册推送给这个用户的所有已请求名册的可用资源 包含一个关于这个联系人的更新名册条目 其 subscription 属性设为 none 并且 2 必须 MUST 路由这个 unsubscribe 类型的出席信息节给联系人 首先把 from 地址设为用户的纯JID user example com source lang xml iq type set query xmlns jabber iq roster item jid contact example org subscription none name MyContact group MyBuddies group item query iq presence from user example com to contact example org type unsubscribe source 3 接收到指向联系人的 unsubscribe 类型出席信息节之后 联系人的服务器 1 必须 MUST 初始化一个名册推送给这个联系人的所有已请求名册的可用资源 包含一个关于这个用户的名册条目 其 subscription 属性值设为 none 如果联系人不可用或未曾请求名册 联系人的服务器必须 MUST 修改名册条目并在下次联系人请求名册时发送那个已修改的条目 并且 2 必须 MUST 递送这个 unsubscribe 状态改变通知给联系人 source lang xml iq type set query xmlns jabber iq roster item jid user example com subscription none name SomeUser group SomeGroup group item query iq presence from user example com to contact example org type unsubscribe source 4 接收到 unsubscribe 类型的出席信息节之后 联系人应该 SHOULD 承认收到那个订阅状态通知 要么发送一个 unsubscribed 类型的出席信息节给用户以证实它 要么发送一个 subscribed 类型的出席信息节给用户否认它 这个步骤不影响订阅状态 详见 订阅状态Subscription States 第九章 但是让联系人的服务器知道它必须 MUST 不再发送订阅状态变更通知给联系人 见第九章第四节 5 联系人的服务器接着 1 必须 MUST 发送一个 unsubscribed 类型的出席信息节给用户 并且 2 应该 SHOULD 向用户发送从这个联系人的所有可用资源收到的不可用出席信息 source lang xml presence from contact example org to user example com type unsubscribed presence from contact example org resource to user example com type unavailable source 6 当用户的服务器收到类型为 unsubscribed 和 unavailable 的出席信息节 它必须 MUST 递送它们给用户 source lang xml presence from contact example org to user example com type unsubscribed presence from contact example org resource to user example com type unavailable source 7 接收到 unsubscribed 类型的出席信息节之后 用户应该 SHOULD 承认收到那个订阅状态变更通知 要么向联系人发送一个 unsubscribe 类型的出席信息节以证实它 要么向联系人发送一个 subscribe 的出席信息节以否认它 这步骤不影响订阅状态 详见 订阅状态Subscription States 第九章 但是让用户的服务器知道它必须 MUST 不在发送订阅状态变更通知给用户 见第九章第四节 情形 2 当订阅是相互的时候取消订阅 在第二种情形下 用户有一个向联系人的出席信息的订阅并且联系人也有一个向用户的出席信息的订阅 换言之 订阅是相互的 1 如果用户想从联系人的出席信息取消订阅 用户必须 MUST 发送一个 unsubscribe 类型的出席信息节给联系人 source lang xml presence to contact example org type unsubscribe source 2 作为一个结果 用户的服务器 1 必须 MUST 发送一个名册推送给这个用户的所有已请求名册的可用资源 包含一个关于这个联系人的更新名册条目 其 subscription 属性值设为 from 并且 2 必须 MUST 路由这个 unsubscribe 类型的出席信息节给这个联系人 首先把 from 地址设为这个用户的纯 JID user example com source lang xml iq type set query xmlns jabber iq roster item jid contact example org subscription from name MyContact group MyBuddies group item query iq presence from user example com to contact example org type unsubscribe source 3 接收到指向联系人的 unsubscribe 类型的出席信息节之后 联系人的服务器 1 必须 MUST 初始化一个名册推送给这个联系人的所有已请求名册的可用资源 包含一个关于这个用户的名册条目 其 subscription 属性值设为 to 如果联系人不可用或未曾请求名册 联系人的服务去必须 MUST 修改这个名册条目并且等下次联系人请求名册的时候再发送这个修改过的名册条目 并且 2 必须 MUST 递送这个 unsubscribe 状态变更通知给联系人 source lang xml iq type set query xmlns jabber iq roster item jid user example com subscription to name SomeUser group SomeGroup group item query iq presence from user example com to contact example org type unsubscribe source 4 接收到这个 unsubscribe 类型的出席信息节之后 联系人应该 SHOULD 承认收到了那个订阅状态通知 要么向用户发送一个 unsubscribed 类型的出席信息节以证实它 要么向用户发送一个 subscribed 类型的出席信息节以否认它 这个步骤不影响订阅状态 详见 订阅状态Subscription States 第九章 但是让联系人的服务器知道它必须 MUST 不再发送订阅状态变更通知给联系人 见第九章第四节 5 联系人的服务器然后 1 必须 MUST 发送一个 unsubscribed 类型的出席信息节给用户 并且 2 应该 SHOULD 向用户发送它从联系人的所有可用资源收到的不可用出席信息 source lang xml presence from contact example org to user example com type unsubscribed presence from contact example org resource to user example com type unavailable source 6 当用户的服务器收到 unsubscribed 和 unavailable 类型的出席信息节 它必须 MUST 递送它们给用户 source lang xml presence from contact example org to user example com type unsubscribed presence from contact example org resource to user example com type unavailable source 7 接收到 unsubscribed 类型的出席信息节之后 用户应该 SHOULD 承认收到了那个订阅状态的通知 要么向联系人发送一个 unsubscribe 类型的出席信息节以证实它 要么向联系人发送一个 subscribe 类型的出席信息节以否认它 这个步骤不影响订阅状态 详见 订阅状态Subscription States 第九章 但是让用户的服务器知道它必须 MUST 不在发送订阅状态变更通知给用户 见第九章第四节 注意 显然这不会导致名册条目从用户的名册移除 并且联系人仍然有一个对用户的出席信息的订阅 为了完全取消双向的订阅并完全从用户的名册中移除名册条目 用户应该 SHOULD 使用subscription remove 定义在 移除一个名册条目并取消所有订阅项Removing a Roster Item and Cancelling All Subscriptions 第八章第六节 更新名册条目 取消一个订阅项 在批准来自一个用户的任何订阅请求之后的任何时候 一个联系人可以 MAY 取消那个订阅项 联系人在所有实例中执行这个动作中发送的XML是相同的 接下来的订阅状态根据取消命令发出当时所获得的订阅状态而有所不同 所有可能的情节描述如下 情形 1 当订阅不是相互的时候取消订阅项 在第一种情形下 用户有一个对联系人的出席信息的订阅但是联系人没有对于用户的出席信息的订阅 换言之 订阅还不是相互的 1 如果联系人想取消用户的订阅项 联系人必须 MUST 发送一个 unsubscribed 类型的出席信息节给用户 source lang xml presence to user example com type unsubscribed source 2 作为一个结果 联系人的服务器 1 必须 MUST 发送一个名册推送给这个联系人的所有已请求名册的可用资源 包含一个关于这个用户的更新的名册条目 其 subscription 属性值设为 none 2 必须 MUST 路由这个 unsubscribed 类型的出席信息节给用户 首先把 from 地址设为联系人的纯JID contact example org 并且 3 应该 SHOULD 向用户发送它从联系人的所有可用资源收到的不可用出席信息 source lang xml iq type set query xmlns jabber iq roster item jid user example com subscription none name SomeUser group SomeGroup group item query iq presence from contact example org to user example com type unsubscribed presence from contact example org resource to user example com type unavailable source 3 接收到指向用户的 unsubscribed 类型的出席信息节之后 用户的服务器 1 必须 MUST 初始化一个名册推送给这个用户的所有已请求名册的可用资源 包含一个关于这个联系人的名册条目更新 其 subscription 属性值设为 none 如果用户不可用或未曾请求名册 用户的服务器必须 MUST 修改这个名册条目并且等下次用户请求名册的时候发送修改过的名册条目 2 必须 MUST 递送这个 unsubscribed 状态改变通知给这个用户的所有可用资源 并且 3 必须 MUST 向这个用户的所有可用资源递送不可用出席信息 source lang xml iq type set query xmlns jabber iq roster item jid contact example org subscription none name MyContact group MyBuddies group item query iq presence from contact example org to user example com type unsubscribed presence from contact example org resource to user example com type unavailable source 4 接收到 unsubscribed 类型的出席信息节之后 用户应该 SHOULD 承认收到了那个订阅状态通知 要么向联系人发送一个 unsubscribe 出席信息节以证实它 要么向联系人发送一个 subscribe 类型的出席信息节以否认它 这个步骤不影响订阅状态 详见 订阅状态Subscription States 第九章 但是让服务器知道它必须 MUST 不再发送订阅状态变更通知给用户 见第九章第四节 情形 2 当订阅项是相互的时候取消 在这种情形下 用户有一个对联系人的出席信息的订阅并且联系人也有一个对用户的出席信息的订阅 换言之 订阅是相互的 1 如果联系人想取消用户的订阅 联系人必须 MUST 发送一个 unsubscribed 类型的出席信息节给用户 source lang xml presence to user example com type unsubscribed source 2 作为结果 联系人的服务器 1 必须 MUST 发送一个名册推送给这个联系人的所有已请求名册的可用资源 包含关于这个用户的一个更新的名册条目 其 subscription 属性值设为 to 2 必须 MUST 路由这个 unsubscribed 类型的出席信息节给用户 首先把 from 地址设为联系人的纯JID contact example org 并且 3 应该 SHOULD 向这个用户的所有可用资源发送它从联系人的所有可用资源收到的不可用出席信息 source lang xml iq type set query xmlns jabber iq roster item jid user example com subscription to name SomeUser group SomeGroup group item query iq presence from contact example org to user example com type unsubscribed presence from contact example org resource to user example com type unavailable source 3 接收到指向用户的 unsubscribed 类型出席信息节之后 用户的服务器 1 必须 MUST 初始化一个名册推送给这个用户的所有已请求名册的可用资源 包含关于这个联系人的更新的名册条目 其 subscription 属性值设为 from 如果这个用户不可用或未曾请求名册 用户的服务器必须 MUST 修改这个名册条目并且等下次用户请求名册的时候发送修改过的条目给它 并且 2 必须 MUST 递送这个 unsubscribed 状态变更通知给用户的所有可用资源 并且 3 必须 MUST 向这个用户的所有可用资源递送这个不可用出席信息 source lang xml iq type set query xmlns jabber iq roster item jid contact example org subscription from name MyContact group MyBuddies group item query iq presence from contact example org to user example com type unsubscribed presence from contact example org resource to user example com type unavailable source 4 接收到这个 unsubscribed 类型的出席信息节之后 用户应该 SHOULD 承认收到了那个订阅状态通知 要么向联系人发送一个 unsubscribe 类型的出席信息节以证实它 要么向联系人发送一个 subscribe 类型的出席信息节以否认它 这一步骤不影响订阅状态 详见 订阅状态Subscription States 第九章 但是让用户的服务器知道它必须 MUST 不再发送订阅状态变更通知给用户 见第九章第四节 注意 显然这不会使得名册条目从联系人的名册中移除 并且联系人仍然有一个对用户的出席信息的订阅 为了完全双向的取消一个相互的订阅并且从联系人的名册中完全移除这个名册条目 联系人应该以subscription remove 定义在 移除一个名册条目并取消所有订阅项Removing a Roster Item and Cancelling All Subscriptions 第八章第六节 更新名册条目 移除一个名册条目并取消所有订阅项 因为在双向完整移除一个名册条目和取消所有订阅的过程中可能有很多步骤 名册管理协议包含一个 shortcut 方法来做这件事 无论当前的订阅状态是什么 这个过程可以通过发送一个roster set 包含一个用于这个联系人的条目 其 subscription 属性值设为 remove 来初始化 source lang xml iq type set id remove1 query xmlns jabber iq roster item jid contact example org subscription remove query iq source 当用户从他或她的名册中移除一个联系人 通过把 subscription 属性值设为 remove 用户的服务器 1 必须 MUST 自动取消用户和联系人之间的任何现存的出席信息订阅项 包括相应的 to 和 from 2 必须 MUST 从用户的名册移除这个名册条目并且通知这个用户的所有已请求名册的可用资源这个名册条目被移除了 3 必须 MUST 通知初始化的资源移除成功了 并且 4 应该 SHOULD 向联系人发送它从这个用户的所有可用资源收到的不可用出席信息 source lang xml presence from user example com to contact example org type unsubscribe presence from user example com to contact example org type unsubscribed iq type set query xmlns jabber iq roster item jid contact example org subscription remove query iq iq type result id remove1 presence from user example com resource to contact example org type unavailable source 收到 unsubscribe 类型的出席信息后 联系人的服务器 1 必须 MUST 初始化一个名册推送给这个联系人的所有已请求名册的可用资源 包含关于这个用户的一个更新的名册条目 其 subscription 属性值设为 to 如果这个联系人不可用或未曾请求名册 联系人的服务器必须 MUST 修改这个名册条目并且等下次联系人请求名册的时候发送这个修改过的条目给它 并且 2 也必须 MUST 递送这个 unsubscribe 状态变更通知给这个联系人的所有可用资源 source lang xml iq type set query xmlns jabber iq roster item jid user example com subscription to name SomeUser group SomeGroup group item query iq presence from user example com to contact example org type unsubscribe source 收到这个 unsubscribed 类型的出席信息节之后 联系人的服务器 1 必须 MUST 初始化一个名册推送给这个联系人的所有已请求名册的可用资源 包含一个关于这个用户的更新的名册条目 其 subscription 属性值设为 none 如果这个联系人不可用或未曾请求名册 联系人的服务器必须 MUST 修改名册条目并且等下次联系人请求名册的时候把修改过的条目发送给它 并且 2 也必须 MUST 递送这个 unsubscribe 状态改变通知给这个联系人的所有可用资源 source lang xml iq type set query xmlns jabber iq roster item jid user example com subscription none name SomeUser group SomeGroup group item query iq presence from user example com to contact example org type unsubscribed source 接收到指向联系人的 unavailable 出席信息节之后 联系人的服务器必须 MUST 递送这个不可用出席信息给这个用户的所有可用资源 source lang xml presence from user example com resource to contact example org type unavailable source 注意 当用户从用户的名册中移除联系人的时候 这个联系人的名册最后状态是用户仍然在联系人名册中但是订阅状态为 none 为了完全移除关于这个用户的名册条目 联系人也需要发送一个名册移除请求 订阅状态 本章提供关于订阅状态以及和订阅相关的出席信息节 换言之 类型为 subscribe subscribed unsubscribe 和 unsubscribed 的出席信息节 的服务器处理过程的详细信息 已定义的状态 有九种可能的订阅状态 从用户的 不是联系人的 角度描述如下 None 联系人和用户互相没有被对方订阅 并且也都没有从对方那里请求一个订阅 None Pending Out 联系人和用户互相没有被对方订阅 用户已经向联系人发送了一个订阅请求但还没有收到回复 None Pending In 联系人和用户互相没有被对方订阅 联系人已经向用户发送了一个订阅请求但还没有收到回复 注意 在这种状态下联系人的服务器不应该 SHOULD NOT 推送或递送名册条目 但是应该 SHOULD 等待 直到联系人的订阅请求已经从用户那里得到批准 None Pending Out In 联系人和用户互相没有被对方订阅 联系人已经向用户发送了一个订阅请求但还没有收到回复 用户已经向联系人发送了一个订阅请求但还没有收到回复 To 用户已订阅联系人 单向 To Pending In 用户已订阅联系人 联系人已经向用户发送了一个订阅请求但还没有收到回复 From 联系人已订阅用户 单向 From Pending Out 联系人已订阅用户 单向 用户已经向联系人发送了一个订阅请求但还没有收到回复 Both 用户和联系人互相被对方订阅了 双向 出站出席信息订阅节的服务器处理过程 出站出席信息订阅节使用户能管理他或她对联系人的出席信息的订阅 通过 subscribe 和 unsubscribe 类型 并且管理联系人对用户的出席信息的访问 通过 subscribed 和 unsubscribed 类型 因为用户的服务器和联系人的服务器有可能失去对于订阅状态的同步 用户的服务器必须 MUST 毫无例外地路由所有 subscribe 或 unsubscribe 类型的出站出席信息节给联系人 使用户能在需要的时候重新同步他或她的对联系人的出席信息的订阅 如果从用户的角度来看 一个 subscribed 或 unsubscribed 类型的出席信息节不会导致一个订阅状态的变更 用户的服务器不应该 SHOULD NOT 路由这个节到联系人那里 并且不能 MUST NOT 做出一个状态变更 如果这个节导致一个订阅状态的变更 用户的服务器必须 MUST 路由这个节到联系人 并且必须 MUST 做出相应的状态变更 这些规则总结如下这些表 表 1 推荐的出站 subscribed 节的处理 border 1 cellspacing 0 当前状态 路由 新状态 None 否 状态不变 None Pending Out 否 状态不变 None Pending In 是 From None Pending Out In 是 From Pending Out To 否 状态不变 To Pending In 是 Both From 否 状态不变 From Pending Out 否 状态不变 Both 否 状态不变 表 2 推荐的出站 unsubscribed 节处理 border 1 cellspacing 0 当前状态 路由 新状态 None 否 状态不变 None Pending Out 否 状态不变 None Pending In 是 None None Pending Out In 是 None Pending Out To 否 状态不变 To Pending In 是 To From 是 None From Pending Out 是 None Pending Out Both 是 To 入站出席信息订阅节的服务器处理过程 入站出席信息订阅节从用户请求一个订阅相关的动作 通过 subscribe 类型 通知用户由联系人所做的订阅状态相关的动作 通过 unsubscribe 类型 或使联系人能够管理用户对联系人的出席信息的访问 通过 subscribed 和 unsubscribed 类型 当用户的服务器为用户从联系人那里接收到一个订阅请求 换言之 一个 subscribe 类型的出席信息节 如果用户未曾允许联系人访问用户的出席信息或者没有未决的入站订阅请求 它必须 MUST 递送那个请求给用户 无论如何 如果有一个未决的入站订阅请求 用户的服务器不应该 SHOULD NOT 递送这个新的请求 因为上一个订阅请求可能已经被记录下来了 如果用户已经允许联系人访问用户的出席信息 用户的服务器应该 SHOULD 对一个从联系人发来的 subscribe 类型的入站出席信息节自动回复 通过代替用户向联系人发送一个 subscribed 类型的出席信息节 这个规则使得联系人可以在需要的时候重新同步订阅状态 这些规则总结如下面这些表 表 3 推荐的入站 subscribe 节处理 border 1 cellspacing 0 当前状态 递送 新状态 None 是 None Pending In None Pending Out 是 None Pending Out In None Pending In 否 状态不变 None Pending Out In 否 状态不变 To 是 To Pending In To Pending In 否 状态不变 From 否 状态不变 From Pending Out 否 状态不变 Both 否 状态不变 服务器应该 SHOULD 以 subscribed 节自动回复 当用户的服务器为用户从联系人那里收到一个 unsubscribe 类型的出席信息节 如果从用户的角度看这个节会导致一个订阅状态变更 那么用户的服务器应该 SHOULD 代替用户自动应答 发送一个 unsubscribed 类型的出席信息节给联系人 必须 MUST 递送这个 unsubscribe 节给用户 并且必须 MUST 改变状态 如果不会导致订阅状态变更 用户的服务器不应该 SHOULD NOT 递送这个节并且不能 MUST NOT 改变状态 这些规则总结如下表 表 4 推荐的入站 unsubscribe 节处理 border 1 cellspacing 0 当前状态 递送 新状态 None 否 状态不变 None Pending Out 否 状态不变 None Pending In 是 None None Pending Out In 是 None Pending Out To 否 状态不变 To Pending In 是 To From 是 None From Pending Out 是 None Pending Out Both 是 To 服务器应该 SHOULD 以 unsubscribed 节自动应答 当用户的服务器为用户从联系人那里收到一个 subscribed 类型的出席信息节 如果没有一个为访问联系人的出席信息的未决的出站请求 它不能 MUST NOT 递送这个节给用户并且不能 MUST NOT 改变订阅状态 如果有一个为了访问联系人的出席信息的未决的出站请求并且这个 subscribed 类型的入站出席信息请求会导致一个订阅状态的改变 用户的服务器必须 MUST 递送这个节给用户并且必须 MUST 改变订阅状态 如果用户已经有授权可以访问联系人的出席信息 这个 subscribed 类型的入站出席信息节不导致一个订阅状态的变更 从而用户的服务器不应该 SHOULD NOT 递送这个节给用户并且不能 MUST NOT 改变订阅状态 这些规则总结如下表 表 5 推荐的入站 subscribed 节处理 border 1 cellspacing 0 当前状态 递送 新状态 None 否 状态不变 None Pending Out 是 To None Pending In 否 状态不变 None Pending Out In 是 To Pending In To 否 状态不变 To Pending In 否 状态不变 From 否 状态不变 From Pending Out 是 Both Both 否 状态不变 当用户的服务器为用户从联系人那里收到了一个 unsubscribed 类型的出席信息节 如果有一个为了访问联系人的出席信息的未决的出站请求或者用户当前已经有授权可以访问联系人的出席信息 它必须 MUST 递送这个节给用户并且必须 MUST 改变订阅状态 否则 用户的服务器不应该 SHOULD NOT 递送这个节并且不能 MUST NOT 改变订阅状态 这些规则总结如下表 表 6 推荐的入站 unsubscribed 节处理 border 1 cellspacing 0 当前状态 递送 新状态 None 否 状态不变 None Pending Out 是 None None Pending In 否 状态不变 None Pending Out In 是 None Pending In To 是 None To Pending In 是 None Pending In From 否 状态不变 From Pending Out 是 From Both 是 From 服务器递送和客户端承认订阅请求以及状态变更通知 当一个服务器收到一个 subscribe 类型的入站出席信息节 换言之 一个订阅请求 或 subscribed 类型 unsubscribe 类型 或 unsubscribed 类型 换言之 一个订阅状态变更通知 除了发送适当的名册推送 或当下次名册被一个可用资源请求时发送更新的名册 它必须 MUST 递送这个请求或通知给预定的接收者至少一次 一个服务器可以 MAY 要求接收者的回执以承认接收到了所有状态变更通知 并且必须 MUST 要求承认订阅请求的情形 换言之 类型的出席信息节 subscribe 为了要求回执 一个服务器应该 SHOULD 在每次接收者登陆的时候发送这个请求或通知给它 直到这个接收者承认收到这个通知 通过证实 affirming 或禁止 denying 这个通知 如下表 表 7 订阅状态变更通知的承认 border 1 cellspacing 0 节类型 接受 禁止 subscribe subscribed unsubscribed subscribed subscribe unsubscribe unsubscribe unsubscribed subscribed unsubscribed unsubscribe subscribe 显然 根据前述的订阅状态图表 一些回执节将被路由到联系人并且导致状态的变更 而其他的则不会 无论如何 任何这样的节必须 MUST 导致服务器不再发送订阅状态变更通知给用户 因为在接收到roster set 其 subscription 属性值设为 remove 见 移除一个名册条目并且取消所有订阅项 Removing a Roster Item and Cancelling All Subscriptions 第八章第六节 之后 用户的服务器必须 MUST 自动生成 unsubscribe 和 unsubscribed 类型的出站出席信息节 服务器必须 MUST 把一个名册移除请求视为发送所有这些出席信息节 以决定是否继续向用户发送 subscribe 或 subscribed 类型的订阅状态变更通知 屏蔽通信 大多数即时消息系统已发现有必要实现一些方法来为用户屏蔽来自某些特定的其他用户的通信 这在 IMP REQS 的第五章第一节第五小节 第五章第一节第十五小节 第五章第三节第二小节 和第五章第四节第十小节中也有要求 在XMPP中这是由管理某人的隐私列表来实现的 使用 jabber iq privacy 名字空间 服务器端的隐私列表使得以下用例能够完成 接收某人的隐私列表 增加 移除 和 编辑某人的隐私列表 设置 改变 或 取消 激活的列表 设置 改变 或 取消 缺省的列表 换言之 缺省激活的那个列表 基于JID group 或 subscription 类型 或全局的 允许或屏蔽消息 允许或屏蔽入站出席信息通知 基于 JID group 或 subscription 类型 或全局的 允许或屏蔽出站出席信息通知 基于 JID group 或 subscription 类型 或全局的 允许或屏蔽 IQ 节 基于 JID group 或 subscription 类型 或全局的 允许或屏蔽所有通信 基于 JID group 或 subscription 类型 或全局的 注意 出席信息通知不包括出席信息订阅 只包括广播给那些已订阅了用户出席信息的实体的出席信息 因而这包括没有 type 属性或只包含type unavailable 的的出席信息节 语法和语义 一个用户可以 MAY 定义一个或更多的隐私列表 它们由用户的服务器保存 每个 list 元素包含一个或多个格式为 item 元素的规则 并且每个 item 元素使用属性来定义一个隐私规则类型 一个适用于规则的特定值 相应的动作 和处理顺序相应的条目位置 语法如下 source lang xml iq query xmlns jabber iq privacy list name foo item type jid group subscription value bar action allow deny order unsignedInt message presence in presence out iq item list query iq source 如果类型是 jid 那么 value 属性必须 MUST 包含一个合法的Jabber ID JIDs 应该 SHOULD 满足以下顺序 user domain resource 仅为匹配的资源 user domain 任何匹配的资源 domain resource 仅匹配的资源 domain 匹配这个域本身 正如任何 user domain domain resource 或 包含一个子域的地址 如果类型为 group 那么 value 属性应该 SHOULD 包含组在用户的名册中的名字 如果一个客户端尝试更新 新建 或删除一个不在用户名册中的组的列表条目 服务器应该 SHOULD 返回给客户端一个 item not found 节错误 如果类型是 subscription 那么 value 属性必须 MUST 是 both to from 或 none 定义在 名册语法和语义Roster Syntax and Semantics 第七章第一节 中的一个人 在这里 none 包括对于用户来说完全未知和根本不在用户名册中的实体 如果没有包含 type 属性 这个规则提供 失败 fall through 情景 action 属性必须 MUST 被包含并且它的值必须 MUST 是 允许 allow 或 禁止 deny order 属性必须 MUST 被包含并且它的值必须 MUST 是一个在列表的所有条目中具有唯一性的非负整数 如果一个客户端尝试以一个非唯一的order值建立或更新一个列表 服务器必须 MUST 返回给客户端一个 bad request 节错误 item 元素可以 MAY 包含一个或更多子元素 使得一个实体可以指明更多的细微控制包括屏蔽哪些种类的节 换言之 不只是简单地屏蔽所有节 允许的子元素包括 message 屏蔽引入消息节 iq 屏蔽引入 IQ 节 presence in 屏蔽引入出席信息通知 presence out 屏蔽外出出席信息通知 在 jabber iq privacy 名字空间之内 一个 set 类型的IQ节的 query 子元素不能 MUST NOT 包含超过一个子元素 换言之 这个节必须 MUST 只包含一个 active 元素 一个 default 元素 或一个 list 元素 如果一个发送中的实体违反了这个规则 接收中的实体必须 MUST 返回一个 return a bad request 节错误 当一个客户端增加或更新一个隐私列表 list 元素应该 SHOULD 包含至少一个 item 子元素 当一个客户端移除一个隐私列表的时候 list 元素不能 MUST NOT 包含任何 item 子元素 当一个客户端更新一个隐私列表的时候 它必须包含所有想得到的条目 换言之 不是一个 delta 商业规则 如果有一个为某会话设置的激活的列表 它只影响为其激活的那个会话 并且只在那一个会话的持续期间有效 服务器必须 MUST 只应用激活列表 并且不能 MUST NOT 应用缺省列表 换言之 列表没有层次 layering 缺省列表总体适用于用户 并且如果没有为一个节指向的目标session resource设置激活列表 或用户当前没有会话 它会被处理 如果没有为一个会话设置激活列表 或用户当前没有会话 并且没有缺省列表 那么所有节应该被 SHOULD BE 接受或由服务器代替用户做适当的处理 遵守 用于处理XML节的服务器规则 Server Rules for Handling XML Stanzas 第十一章 隐私列表必须 MUST 是第一个由服务器应用的递送规则 替代 1 定义在 用于处理XML节的服务器规则Server Rules for Handling XML Stanzas 第十一章 的路由和递送规则 以及 2 和订阅相关的出席信息节的处理 和相应的名册推送的生成 定义在 名册条目和出席信息订阅的集成Integration of Roster Items and Presence Subscriptions 第八章 服务器处理隐私列表条目的顺序是很重要的 列表条目必须 MUST 按照每个 item 的 order 属性的整数值的升序来处理 一旦节和一个隐私列表规则匹配 服务器必须 MUST 按照这个规则适当地处理这个节 然后终止处理 如果在一个列表中没有提供一个fall through的条目 fall through 动作被假定为 允许 allow 如果一个用户为一个激活列表更新定义 之后的基于那个激活列表的操作必须 MUST 使用更新的定义 为了那些激活列表正应用的所有资源 如果在用户的会话期间 在激活的或缺省的列表中定义的名册条目中的订阅状态改变了 或名册组改变了 接下来基于那个列表的处理必须 MUST 考虑计入这个已改变的状态或组 对那个列表当前应用的所有资源 当一个规则的定义修改了的时候 服务器必须 MUST 发送一个类型为 set 的IQ节给所有已连接的资源 包括一个只有一个 list 子元素的 query 元素 其 name 属性设为已修改的隐私列表的名字 这些 隐私列表推送 privacy list pushes 遵守和用于名册管理的名册推送 roster pushes 同样的语义 除了被推送给已连接的资源的列表名字本身 不是完整的列表定义或那个 delta 是否接受这个修改了的列表定义最终由接收中的资源来决定 尽管如果这个列表正在应用于一个已连接的资源 它应该 SHOULD 这样做 当一个已连接的资源尝试移除一个列表或指定一个新的缺省列表 而那个列表应用于一个已连接的资源而不是正在发送的资源 服务器必须 MUST 返回一个 conflict 错误给发送中的资源并且不能 MUST NOT 执行这个请求的改变 接收某人的隐私列表 例子 客户端向服务器请求隐私列表的名字 source lang xml iq from romeo example net orchard type get id getlist1 query xmlns jabber iq privacy iq source 例子 服务器发送隐私列表的名字给客户端 激活列表和缺省列表放在前面 source lang xml iq type result id getlist1 to romeo example net orchard query xmlns jabber iq privacy active name private default name public list name public list name private list name special query iq source 例子 客户端向服务器请求一个隐私列表 source lang xml iq from romeo example net orchard type get id getlist2 query xmlns jabber iq privacy list name public query iq source 例子 服务器发送一个隐私列表给客户端 source lang xml iq type result id getlist2 to romeo example net orchard query xmlns jabber iq privacy list name public item type jid value tybalt example com action deny order 1 item action allow order 2 list query iq source 例子 客户端向服务器请求另一个隐私列表 source lang xml iq from romeo example net orchard type get id getlist3 query xmlns jabber iq privacy list name private query iq source 例子 服务器发送另一个隐私列表给客户端 source lang xml iq type result id getlist3 to romeo example net orchard query xmlns jabber iq privacy list name private item type subscription value both action allow order 10 item action deny order 15 list query iq source 例子 客户端再向服务器请求另一个隐私列表 source lang xml iq from romeo example net orchard type get id getlist4 query xmlns jabber iq privacy list name special query iq source 例子 服务器再发送另一个隐私列表给客户端 source lang xml iq type result id getlist4 to romeo example net orchard query xmlns jabber iq privacy list name special item type jid value juliet example com action allow order 6 item type jid value benvolio example org action allow order 7 item type jid value mercutio example org action allow order 42 item action deny order 666 list query iq source 在这个例子中 用户有三个列表 1 public 它允许所有人的通信 除了一个指定的实体 这是缺省列表 2 private 它只允许和这个用户有双向订阅的联系人的通信 这是激活的列表 还有 3 special 它只允许三个指定的实体通信 如果用户尝试接收一个列表但是这个列表的名字不存在 服务器必须 MUST 返回一个 item not found 节错误给用户 例子 客户端尝试接收不存在的列表 source lang xml iq to romeo example net orchard type error id getlist5 query xmlns jabber iq privacy list name The Empty Set query error type cancel item not found xmlns urn ietf params xml ns xmpp stanzas error iq source 用户在一次只被允许接收一个列表 如果用户尝试同一个请求中接收超过一个列表 服务器必须 MUST 返回一个 bad request 节错误给用户 例子 客户端尝试接收多于一个的列表 source lang xml iq to romeo example net orchard type error id getlist6 query xmlns jabber iq privacy list name public list name private list name special query error type modify bad request xmlns urn ietf params xml ns xmpp stanzas error iq source 管理激活列表 为了设置或改变服务器当前应用的激活列表 用户必须 MUST 发送一个类型为 set 的IQ节 包含一个符合 jabber iq privacy 名字空间的 query 元素 这个元素 query 又包含一个空的 active 子元素 而这个 active 拥有一个 name 属性 name 属性值则设为期望的列表名 例子 客户端请求激活列表变更 source lang xml iq from romeo example net orchard type set id active1 query xmlns jabber iq privacy active name special query iq source 服务器必须 MUST 在返回结果给客户端之前激活并应用这个已请求的列表 例子 服务器承认激活列表变更成功 source lang xml iq type result id active1 to romeo example net orchard source 如果用户尝试设置一个激活列表但是列表名不存在 服务器必须 MUST 返回一个 item not found 节错误给用户 例子 客户端尝试设置一个不存在的列表作为激活列表 source lang xml iq to romeo example net orchard type error id active2 query xmlns jabber iq privacy active name The Empty Set query error type cancel item not found xmlns urn ietf params xml ns xmpp stanzas error iq source 为了取消使用任何激活列表 已连接的资源必须 MUST 发送一个空的 active 元素 并且不带 name 属性 例子 客户端取消使用激活列表 source lang xml iq from romeo example net orchard type set id active3 query xmlns jabber iq privacy active query iq source 例子 服务器承认取消任何激活列表成功 source lang xml iq type result id active3 to romeo example net orchard source 管理缺省列表 为了改变它的缺省列表 它对用户来说是全局应用的 不只是发送中的资源 用户必须 MUST 发送一个类型为 set 的IQ节 它包含一个符合 jabber iq privacy 名字空间的 query 元素 这个 query 元素包含一个空的 default 子元素 这个 default 子元素拥有一个 name 属性 这个 name 属性的值设为期望的列表名 例子 用户请求变更缺省列表 source lang xml iq from romeo example net orchard type set id default1 query xmlns jabber iq privacy default name special query iq source 例子 服务器承认缺省列表变更成功 source lang xml iq type result id default1 to romeo example net orchard source 如果用户尝试变更一个缺省列表但是这个缺省列表正在由至少一个已连接的但不是当前发送中的这个资源使用着 服务器必须 MUST 返回一个 conflict 节错误给发送中的资源 例子 客户端尝试改变一个缺省列表但是这个列表正在被另一个资源使用 source lang xml iq to romeo example net orchard type error id default1 query xmlns jabber iq privacy default name special query error type cancel conflict xmlns urn ietf params xml ns xmpp stanzas error iq source 如果用户尝试设置一个缺省列表但是这个列表的名字不存在 服务器必须 MUST 返回一个 item not found 节错误给用户 例子 客户端尝试设置一个不存在的列表作为缺省列表 source lang xml iq to romeo example net orchard type error id default1 query xmlns jabber iq privacy default name The Empty Set query error type cancel item not found xmlns urn ietf params xml ns xmpp stanzas error iq source 为了取消使用缺省列表 换言之 任何时候都使用域的节路由规则 用户必须 MUST 发送一个空的不带 name 属性的 default 元素 例子 客户端取消使用缺省列表 source lang xml iq from romeo example net orchard type set id default2 query xmlns jabber iq privacy default query iq source 例子 服务器承认成功地取消了任何缺省列表 source lang xml iq type result id default2 to romeo example net orchard source 如果一个已连接的资源尝试取消一个用户全局的缺省列表但是这个缺省列表正在应用于另一个已连接的资源 服务器必须 MUST 返回一个 conflict 错误给发送中的资源 例子 客户端尝试取消一个缺省列表但是这个列表正在被另一个资源使用 source lang xml iq to romeo example net orchard type error id default3 query xmlns jabber iq privacy default query error type cancel conflict xmlns urn ietf params xml ns xmpp stanzas error iq source 编辑一个隐私列表 为了编辑一个隐私列表 用户必须 MUST 一个类型为 set 的IQ节 包含一个符合 jabber iq privacy 名字空间的 query 元素 这个 query 元素包含一个拥有一个 list 子元素 这个 list 子元素拥有一个 name 属性 这个 name 属性的值设为用户想编辑的列表名 这个 list 元素必须 MUST 包含一个或多个 item 元素 它们包含了列表中的所有元素以指明用户期望的对列表的变更 不是the delta 例子 客户端编辑隐私列表 source lang xml iq from romeo example net orchard type set id edit1 query xmlns jabber iq privacy list name public item type jid value tybalt example com action deny order 3 item type jid value paris example org action deny order 5 item action allow order 68 list query iq source 例子 服务器承认列表编辑成功 source lang xml iq type result id edit1 to romeo example net orchard source 注意 任何给定的条目的 order 属性值不是固定的 因而在前述的例子中如果用户想在 tybalt example com 条目和 paris example org 条目之间增加4个条目 用户的客户端必须 MUST 在向服务器提交列表之前对相关的条目重新编号 服务器必须 MUST 现在发送一个 隐私列表推送 privacy list push 给所有已连接的资源 例子 基于列表编辑的隐私列表推送 source lang xml iq to romeo example net orchard type set id push1 query xmlns jabber iq privacy list name public query iq iq to romeo example net home type set id push2 query xmlns jabber iq privacy list name public query iq source 按照定义在 XMPP CORE XMPP文档列表 XMPP正式RFC标准 RFC3920 的IQ节语义 每个已连接的子元素必须 MUST 返回一个如下的 IQ result 给服务器 例子 承认收到一个隐私列表推送 source lang xml iq from romeo example net orchard type result id push1 iq from romeo example net home type result id push2 source 增加一个新的隐私列表 增加一个新的列表和编辑一个现有的列表使用的协议是相同的 如果列表名和现有的列表名吻合 这个增加新列表的请求将覆写那个旧的列表 正如编辑列表一样 服务器也必须 MUST 发送一个 隐私列表推送 privacy list push 给所有已连接的资源 移除一个隐私列表 为了移除一个隐私列表 用户必须 MUST 发送一个类型为 set 的IQ节 包含一个符合 jabber iq privacy 名字空间的 query 元素 这个 query 元素包含一个空的 list 子元素 这个 list 子元素拥有一个 name 属性 这个 name 属性的值设为用户想移除的列表名 例子 客户端移除一个隐私列表 source lang xml iq from romeo example net orchard type set id remove1 query xmlns jabber iq privacy list name private query iq source 例子 服务器承认成功地移除列表 source lang xml iq type result id remove1 to romeo example net orchard source 如果一个用户尝试移除一个列表而这个列表正在被应用于至少一个和发送中的资源不同的已连接的资源 服务器必须 MUST 返回一个 conflict 节错误给用户 换言之 用户在尝试移除它之前必须 MUST 先设置另一个列表成为激活或缺省列表 如果用户尝试移除一个列表但是列表名字不存在 服务器必须 MUST 返回一个 item not found 节错误给用户 如果用户尝试在同一个请求中移除超过一个的列表 服务器必须 MUST 反回一个 bad request 节错误给用户 屏蔽消息 服务器端的隐私列表使得一个用户可以基于实体的JID 名册组 或订阅状态 或全局地 来屏蔽从其他实体引入的消息 以下例子阐明这个协议 注意 为了精简 result 类型的IQ节没有在以下例子中显示 隐私列表推送也没有显示 例子 基于JID的用户屏蔽 source lang xml iq from romeo example net orchard type set id msg1 query xmlns jabber iq privacy list name message jid example item type jid value tybalt example com action deny order 3 message item list query iq source 作为建立和应用前述列表的结果 用户将不会接收到从特定JID发来的消息 例子 基于名册组的用户屏蔽 source lang xml iq from romeo example net orchard type set id msg2 query xmlns jabber iq privacy list name message group example item type group value Enemies action deny order 4 message item list query iq source 作为建立和应用前述列表的结果 用户将不会收到从指定名册组中的任何实体发来的消息 例子 基于订阅状态的用户屏蔽 source lang xml iq from romeo example net orchard type set id msg3 query xmlns jabber iq privacy list name message sub example item type subscription value none action deny order 5 message item list query iq source 作为建立和应用前述列表的结果 用户将不会收到从任何指定订阅状态的实体发来的消息 例子 全局的用户屏蔽 source lang xml iq from romeo example net orchard type set id msg4 query xmlns jabber iq privacy list name message global example item action deny order 6 message item list query iq source 作为建立和应用前述列表的结果 用户将不会收到从任何其他用户发来的消息 屏蔽入站出席信息通知 服务器端的隐私列表使得用户可以基于实体的JID 名册组 或订阅状态 或全局地 屏蔽来自其他实体的入站出席信息通知 以下例子阐明了这个协议 注意 出席信息通知不包括出席信息订阅 只是把出席信息广播给当前已订阅某个联系人的出席信息的用户 所以它只包括没有 type 属性的或type unavailable 的出席信息节 例子 基于JID的用户屏蔽 source lang xml iq from romeo example net orchard type set id presin1 query xmlns jabber iq privacy list name presin jid example item type jid value tybalt example com action deny order 7 presence in item list query iq source 作为建立和应用前述列表的结果 用户将不会收到从指定JID发来的出席信息通知 例子 基于名册组的用户屏蔽 source lang xml iq from romeo example net orchard type set id presin2 query xmlns jabber iq privacy list name presin group example item type group value Enemies action deny order 8 presence in item list query iq source 作为建立和应用前述列表的结果 用户将不会从指定的名册组中的任何实体收到出席信息通知 例子 基于订阅状态的用户屏蔽 source lang xml iq from romeo example net orchard type set id presin3 query xmlns jabber iq privacy list name presin sub example item type subscription value to action deny order 9 presence in item list query iq source 作为建立和应用前述列表的结果 用户将不会从指定订阅状态的任何实体收到出席信息通知 例子 全局的用户屏蔽 source lang xml iq from romeo example net orchard type set id presin4 query xmlns jabber iq privacy list name presin global example item action deny order 11 presence in item list query iq source 作为建立和应用前述列表的结果 用户将不会从任何其他实体收到出席信息通知 屏蔽出站出席信息通知 服务器端的隐私列表使用户能够屏蔽发出到其他实体的出席信息通知 基于实体的JID 名册组 或订阅状态 或全局的 以下例子阐明了这个协议 注意 出席信息通知不包括出席信息订阅 只把出席信息广播给已订阅了用户的出席信息的联系人 所以 只包括没有 type 属性或type unavailable 的出席信息节 例子 基于JID的用户屏蔽 source lang xml iq from romeo example net orchard type set id presout1 query xmlns jabber iq privacy list name presout jid example item type jid value tybalt example com action deny order 13 presence out item list query iq source 作为建立和应用前述列表的结果 用户将不会给指定JID发送出席信息通知 例子 基于名册组的用户屏蔽 source lang xml iq from romeo example net orchard type set id presout2 query xmlns jabber iq privacy list name presout group example item type group value Enemies action deny order 15 presence out item list query iq source 作为建立和应用前述列表的结果 用户将不会向指定名册组的任何实体发送出席信息通知 例子 基于订阅状态的用户屏蔽 source lang xml iq from romeo example net orchard type set id presout3 query xmlns jabber iq privacy list name presout sub example item type subscription value from action deny order 17 presence out item list query iq source 作为建立和应用前述列表的结果 用户将不会向指定订阅状态的任何实体发送出席信息通知 例子 全局的用户屏蔽 source lang xml iq from romeo example net orchard type set id presout4 query xmlns jabber iq privacy list name presout global example item action deny order 23 presence out item list query iq source 作为建立和应用前述列表的结果 用户将不会向任何其他用户发送出席信息通知 屏蔽IQ节 服务器端的隐私列表使用户能够屏蔽从其他实体进来的IQ节 基于实体的JID 名册组 或订阅状态 或全局地 以下例子阐明了这个协议 例子 基于JID的用户屏蔽 source lang xml iq from romeo example net orchard type set id iq1 query xmlns jabber iq privacy list name iq jid example item type jid value tybalt example com action deny order 29 iq item list query iq source 作为建立和应用这个列表的结果 用户将不会收到从指定JID发来的IQ节 例子 基于名册组的用户屏蔽 source lang xml iq from romeo example net orchard type set id iq2 query xmlns jabber iq privacy list name iq group example item type group value Enemies action deny order 31 iq item list query iq source 作为建立和应用前述列表的结果 用户将不会收到从指定名册组的任何实体发来的IQ节 例子 基于订阅状态的用户屏蔽 source lang xml iq from romeo example net orchard type set id iq3 query xmlns jabber iq privacy list name iq sub example item type subscription value none action deny order 17 iq item list query iq source 作为建立和应用前述列表的结果 用户将不会收到从指定订阅状态的任何实体发来的IQ节 例子 全局的用户屏蔽 source lang xml iq from romeo example net orchard type set id iq4 query xmlns jabber iq privacy list name iq global example item action deny order 1 iq item list query iq source 作为建立和应用前述列表的结果 用户将不会收到从任何其他用户发来的IQ节 屏蔽所有通信 服务器端的隐私列表使用户能够基于其他实体的JID 名册组 或订阅状态 或全局的 屏蔽所有进来和出去的节 注意那部包括订阅相关的出席信息节 它们被排除在外 定义在 屏蔽入站出席信息通知Blocking Inbound Presence Notifications 第十章第十节 以下例子阐明了这个协议 例子 基于JID的用户屏蔽 source lang xml iq from romeo example net orchard type set id all1 query xmlns jabber iq privacy list name all jid example item type jid value tybalt example com action deny order 23 list query iq source 作为建立和应用这个列表的结果 用户将不会收到和发送任何通信给指定JID 例子 基于名册组的用户屏蔽 source lang xml iq from romeo example net orchard type set id all2 query xmlns jabber iq privacy list name all group example item type group value Enemies action deny order 13 list query iq source 作为建立和应用前述列表的结果 用户将不会收到和发送和指定名册组的任何实体的通信 例子 基于订阅状态的用户屏蔽 source lang xml iq from romeo example net orchard type set id all3 query xmlns jabber iq privacy list name all sub example item type subscription value none action deny order 11 list query iq source 作为建立和应用前述列表的结果 用户将不会收到和发送和指定订阅状态的任何实体的通信 例子 全局的用户屏蔽 source lang xml iq from romeo example net orchard type set id all4 query xmlns jabber iq privacy list name all global example item action deny order 7 list query iq source 作为建立和应用前述列表的结果 用户将不会收到和发送和任何其他用户的通信 已被屏蔽的实体尝试和用户通信 如果一个已被屏蔽的实体尝试发送消息或出席信息给用户 用户的服务器应该 SHOULD 安静的丢掉这个节并且不能 MUST NOT 返回一个错误给发送的实体 如果一个已被屏蔽的实体尝试发送一个类型为 get 或 set 的IQ节给用户 用户的服务器必须 MUST 给发送的实体一个 service unavailable 节错误 因为这是一个客户端不理解IQ get或set的名字空间的时候所发送的标准错误码 其他类型的IQ节应该 SHOULD 被服务器安静的丢弃 例子 已被屏蔽的实体尝试发送 IQ get source lang xml iq type get to romeo example net from tybalt example com pda id probing1 query xmlns jabber iq version iq source 例子 服务器返回一个错误给已被屏蔽的实体 source lang xml iq type error from romeo example net to tybalt example com pda id probing1 query xmlns jabber iq version error type cancel service unavailable xmlns urn ietf params xml ns xmpp stanzas error iq source 高级启发 当建立一个高级隐私启发的表达式的时候 客户端应该 SHOULD 使用尽可能简单的表达式 例如 启发 屏蔽不在我名册中的任何用户的通信 可以使用以下任何一种方式来构造 允许任何来自我的名册中的JID的通信 换言之 列出每个JID成为单独的列表条目 但是屏蔽和其他任何人的通信 允许任何来自我的名册的某个组中的用户的通信 换言之 列出每个组作为单独的条目 但是屏蔽和任何其他人的通信 允许任何我的他 她 之间的订阅状态为 both 或 to 或 from 的用户的通信 换言之 单独列出每个订阅状态值 但是屏蔽和任何其他人的通信 屏蔽和任何订阅状态为 none 的用户的通信 最后一个表达式是最简单的并且应该 SHOULD 被使用 这种情形下将被发送的XML如下 source lang xml iq type set id heuristic1 query xmlns jabber iq privacy list name heuristic example item type subscription value none action deny order 437 list query iq source 服务器处理XML节的规则 用于服务器的基本路由和递送规则定义在 XMPP CORE XMPP文档列表 XMPP正式RFC标准 RFC3920 中 本章定义附加的用于XMPP兼容的即时消息和出席信息服务器规则 入站节 如果一个入站的节的 to 属性的JID中的域标识符部分的主机名和服务器自身的主机名相同并且 to 属性的JID的格式是 user example com 或 user example com resource 服务器必须 MUST 首先强制应用任何隐私列表 第十章 然后服从以下定义的规则 如果JID的格式是 user domain resource 并且有一个可用的资源和这个全JID吻合 接受这得服务器必须 MUST 递送这个节给那个资源 然后如果JID的格式是 user domain 或格式是 user domain resource 并且和用户相关的帐号不存在 接收者的服务器 a 如果它是一个出席信息节 应该 SHOULD 安静的忽略这个节 换言之 既不递送它也不返回一个错误 b 如果它是一个IQ节 必须 MUST 返回一个 service unavailable 节错误给发送者 并且 c 如果它是一个消息节 应该 SHOULD 返回一个 service unavailable 节错误给发送者 然后如果JID的格式是 user domain resource 并且没有可用的资源和它的全JID匹配 接收者的服务器 a 如果它是一个出席信息节 应该 SHOULD 安静地忽略这个节 换言之 既不递送它也不返回一个错误 b 如果它是一个IQ节 必须 MUST 返回一个 service unavailable 节错误给发送者 并且 c 如果它是一个消息节 应该 SHOULD 把这个节视为发往 user domain 然后如果JID的格式是 user domain 并且这个用户至少有一个可用的资源 接收者的服务器必须 MUST 遵守以下规则 对于消息节

    Original URL path: http://wiki.jabbercn.org/index.php?title=RFC3921&action=edit (2016-04-25)
    Open archived version from archive



  •