XMPP协议 好友管理(协议)
来源:互联网 发布:js实现幻灯片效果 编辑:程序博客网 时间:2024/05/21 10:54
XMPP好友管理-名册管理(RFC6121)
http://wiki.jabbercn.org/RFC6121
在XMPP中, 一个人的联系人列表被称为名册(roster), 它包括任意数量的特定名册条目, 每个名册条目被一个唯一的JID(通常格式是
C: <iq from='juliet@example.com/balcony' id='bv1bs71f' type='get'> <query xmlns='jabber:iq:roster'/> </iq>
发送一个roster get的预期结果是服务器返回一个roster result.
名册结果
一个”roster result”是服务器对一个名册获取的应答; 在语法构成上它是一个从服务器到客户端的类型为”result”的IQ节,并且包含一个由’jabber:iq:roster’命名空间限定的元素.
该 元素是一个名册结果,为每一个联系人包含一个 元素并且因而可以包含多个元素.
S: <iq id='bv1bs71f' to='juliet@example.com/chamber' type='result'> <query xmlns='jabber:iq:roster' ver='ver7'> <item jid='nurse@example.com'/> <item jid='romeo@example.net'/> </query> </iq>
如果该名册存在但是在名册中没有联系人, 那么该服务器必须返回一个IQ-result,包含一个子元素而不包含任何子元素(即, 服务器不能(MUST NOT)返回空的类型为”error”的节).
S: <iq id='bv1bs71f' to='juliet@example.com/chamber' type='result'> <query xmlns='jabber:iq:roster' ver='ver9'/> </iq>
如果该名册不存在, 那么该服务器必须返回一个节错误,条件为.
S: <iq id='bv1bs71f' to='juliet@example.com/chamber' type='error'> <error type='cancel'> <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
名册设置
一个”roster set”是一个客户端向服务器发出的编辑(即, 创建, 更新, 或删除)一个名册条目的请求; 在语法构成上它是一个从客户端到服务器的类型为”set”的IQ节,并且包含一个由’jabber:iq:roster’命名空间限定的元素.
以下规则适用于名册设置:
<query/>元素必须包含一个并且只含有一个<item/>元素. 服务器必须忽略'subscription'属性的除"remove"以外的任何值(见章节2.1.2.5). 安全警告: 传统上, 名册设置的IQ节不包含'to'地址, 结果是所有名册设置都那个需要更新名册的帐号的某个已验证资源(全JID)发出. 此外, RFC 3921 要求一个服务器执行名册设置的特定情景的检查来忽略'to'地址; 无论如何, 本协议移除了那个特定情景, 这意味着一个名册设置可以包含一个和发送者不同的'to'地址. 所以, 处理一个名册设置的实体必须验证名册设置的发送者已被授权更新该名册, 如果没有授权则返回一个<forbidden/>错误.
C: <iq from='juliet@example.com/balcony' id='rs1' type='set'> <query xmlns='jabber:iq:roster'> <item jid='nurse@example.com'/> </query> </iq>
名册推送
一个”roster push”是一个服务器向客户端发出的最新创建, 更新, 或删除的名册条目; 在语法构成上它是一个从服务器到客户端的类型为”set”的IQ节,并且包含一个由’jabber:iq:roster’命名空间限定的元素.
以下规则适用于名册推送:
1.在一个名册推送中的<query/>元素必须包含且仅包含一个<item/>元素. 2.一个接收的客户端必须忽略这个节,除非它满足以下条件:没有'from'属性(即, 隐式地来自该用户帐号的纯JID)或它有一个值和该用户的纯JID<user@domainpart>匹配的'from'属性.
S: <iq id='a78b4q6ha463' to='juliet@example.com/chamber' type='set'> <query xmlns='jabber:iq:roster'> <item jid='nurse@example.com'/> </query> </iq>
作为XMPP‑CORE定义的IQ节语义的强制要求, 每个接收一个来自服务器的名册推送的资源应该应答一个类型为”result”或”error”的IQ节(然而, 大家知道很多现有的客户端不应答名册推送).
C: <iq from='juliet@example.com/balcony' id='a78b4q6ha463' type='result'/>C: <iq from='juliet@example.com/chamber' id='a78b4q6ha463' type='result'/>
安全警告: 传统上, 名册推送不包含'from'地址, 结果是所有名册推送都隐式地从该帐号本身的纯JID发出. 无论如何, 本协议允许非该用户的服务器实体来维护名册信息, 这意味着一个名册推送可以包含不同于该用户帐号的纯JID的'from'地址. 所以, 该客户端必须检查'from'地址来验证名册推送的发送者被售前更新名册. 如果该客户端从一个未授权实体接收到了一个名册推送, 它不能(MUST NOT)处理被推送的数据; 此外, 该客户端要么返回一个节错误<service-unavailable/>要么干脆拒绝返回一个节错误(后面那个行为覆盖了一个来自XMPP‑CORE的 必须-级 的要求, 目的是防止出席信息泄露). 实现备注: 对于名册推送的客户端处理没有错误情景; 如果服务器在对名册推送的应答中接收到了一个类型为"error"的IQ,那么它应该忽略那个错误. **登陆时接收名册**
在通过一个服务器的验证并绑定一个资源之后(也就是成为一个XMPP‑CORE中定义的已连接资源), 一个客户端应该在发送初始的出席信息之前请求名册(无论如何, 因为接收名册不是对所有的资源都是必要的, 例如, 一个有限带宽的连接, 该客户端对名册的请求不是强制的). 在一个已连接的资源发送初始出席信息之后(见章节4.2), 它被称为一个”可用的资源”. 如果一个已连接资源或可用资源请求名册, 它被成为一个”有兴趣的资源”. 服务器必须发送名册推送到所有有兴趣的资源.
实现备注: 出席信息订阅请求被发送到可用的资源, 而和订阅状态改变相关的名册推送被发送到感兴趣的资源. 所以, 如果一个资源希望同时接收到订阅请求和名册推送, 它必须既发送初始出席信息又请求名册.
一个客户端通过向服务器发送一个roster get来请求名册.
C: <iq from='juliet@example.com/balcony' id='hu2bac18' type='get'> <query xmlns='jabber:iq:roster'/> </iq>S: <iq id='hu2bac18' to='juliet@example.com/balcony' type='result'> <query xmlns='jabber:iq:roster' ver='ver11'> <item jid='romeo@example.net' name='Romeo' subscription='both'> <group>Friends</group> </item> <item jid='mercutio@example.com' name='Mercutio' subscription='from'/> <item jid='benvolio@example.net' name='Benvolio' subscription='both'/> </query> </iq>
如果服务器不处理该roster get, 它必须返回一个XMPP‑CORE所述的适当的节错误(如果是名册命名空间不被支持则返回 ,如果该服务器处理过程或返回该名册时遇到麻烦则返回 ).
添加一个名册条目
请求
任何时候, 一个客户端可以添加一个条目到名册. 只要发送一个包含一个新条目的roster set就可以做到.
C: <iq from='juliet@example.com/balcony' id='ph1xaz53' type='set'> <query xmlns='jabber:iq:roster'> <item jid='nurse@example.com' name='Nurse'> <group>Servants</group> </item> </query> </iq>
成功情景
如果服务器成功地处理了关于该新条目的roster set(即, 如果没有错误发生), 它必须在该用户的名册中新增该条目并做如下处理.
该服务器必须返回一个类型为”result”的IQ节给发送该roster set的已连接资源.
S: <iq id='ph1xaz53' to='juliet@example.com/balcony' type='result'/>
该服务器也必须发送一个包含了该新名册条目的roster push到该用户的所有感兴趣的资源, 包括生成了该roster set的资源.
S: <iq to='juliet@example.com/balcony' id='a78b4q6ha463' type='set'> <query xmlns='jabber:iq:roster' ver='ver13'> <item jid='nurse@example.com' name='Nurse' subscription='none'> <group>Servants</group> </item> </query> </iq>S: <iq to='juliet@example.com/chamber' id='x81g3bdy4n19' type='set'> <query xmlns='jabber:iq:roster' ver='ver13'> <item jid='nurse@example.com' name='Nurse' subscription='none'> <group>Servants</group> </item> </query> </iq>
作为在XMPP‑CORE中定义的IQ节语义的强制要求, 建议每个从该服务器接收到一个roster push的资源应答一个类型为”result”或”error”的IQ节(无论如何, 大家知道很多现有的客户端不应答roster pushes).
C: <iq from='juliet@example.com/balcony' id='a78b4q6ha463' type='result'/>C: <iq from='juliet@example.com/chamber' id='x81g3bdy4n19' type='result'/>
章节2.3.3
错误情景
如果服务器未能成功处理roster set, 它必须返回一个节错误. 以下错误场景已被定义. 自然的, 可能会发生其他节错误, 例如,如果服务器在处理roster get(译者注:这里应该是roster set,疑为原文笔误)时发生了内部问题则返回 , 或甚至服务器只允许通过类似web接口这样的非XMPP方法来修改名册则返回.
如果roster set的发送者未被授权更新该名册(典型的情况是该帐号本身只有一个已验证的资源被授权),则服务器必须返回一个节错误给客户端.
服务器必须返回一个节错误给客户端,如果roster set包含以下任何违规情况:
<query/>元素包含不止一个<item/>子元素. <item/>元素包含不止一个<group/>元素, 但是有重复的groups (一个可能的用来确定重复的比较方法见于XMPP‑ADDR中关于XMPP资源部分的描述).
服务器必须返回一个节错误给客户端,如果roster set包含以下任何违规情况:
'name'属性的长度大于一个服务器配置的限制. <group/>元素的XML字符数据长度为零(为了把一个条目从所有组移除, 客户端需要从roster set排除任何<group/>元素). <group/>元素的XML字符数据长度大于一个服务器配置的限制.
错误: Roster set由未授权实体初始化
id='ix7s53v2' to='romeo@example.net' type='set'> <query xmlns='jabber:iq:roster'> <item jid='nurse@example.com'/> </query> </iq>S: <iq id='ix7s53v2' to='juliet@example.com/balcony' type='error'> <error type='auth'> <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
错误: Roster set包含多个条目
C: <iq from='juliet@example.com/balcony' id='nw83vcj4' type='set'> <query xmlns='jabber:iq:roster'> <item jid='nurse@example.com' name='Nurse'> <group>Servants</group> </item> <item jid='mother@example.com' name='Mom'> <group>Family</group> </item> </query> </iq>S: <iq id='nw83vcj4' to='juliet@example.com/balcony' type='error'> <error type='modify'> <bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
错误: Roster set包含的条目超长
C: <iq from='juliet@example.com/balcony' id='yl491b3d' type='set'> <query xmlns='jabber:iq:roster'> <item jid='nurse@example.com' name='[ ... some-very-long-handle ... ]'> <group>Servants</group> </item> </query> </iq>S: <iq id='yl491b3d' to='juliet@example.com/balcony' type='error'> <error type='modify'> <not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
错误: Roster set包含重复的groups
C: <iq from='juliet@example.com/balcony' id='tk3va749' type='set'> <query xmlns='jabber:iq:roster'> <item jid='nurse@example.com' name='Nurse'> <group>Servants</group> <group>Servants</group> </item> </query> </iq>S: <iq id='tk3va749' to='juliet@example.com/balcony' type='error'> <error type='modify'> <bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
错误: Roster set包含空group
C: <iq from='juliet@example.com/balcony' id='fl3b486u' type='set'> <query xmlns='jabber:iq:roster'> <item jid='nurse@example.com' name='Nurse'> <group></group> </item> </query> </iq>S: <iq id='fl3b486u' to='juliet@example.com/balcony' type='error'> <error type='modify'> <not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
错误: Roster set包含超长group名
C: <iq from='juliet@example.com/balcony' id='qh3b4v19' type='set'> <query xmlns='jabber:iq:roster'> <item jid='nurse@example.com' name='Nurse'> <group>[ ... some-very-long-group-name ... ]</group> </item> </query> </iq>S: <iq id='qh3b4v19' to='juliet@example.com/balcony' type='error'> <error type='modify'> <not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
互操作性备注: 如果元素的’jid’属性值和该用户的帐号的纯JID
<item jid='romeo@example.net' name='Romeo'> <group>Friends</group> </item>
在她的名册中拥有该用户的条目,她可能想把该条目添加到另一个组.
C: <iq from='juliet@example.com/balcony' id='di43b2x9' type='set'> <query xmlns='jabber:iq:roster'> <item jid='romeo@example.net' name='Romeo'> <group>Friends</group> <group>Lovers</group> </item> </query> </iq>
有时候晚些时候, 该用户可能希望从原有的组移除该条目.
C: <iq from='juliet@example.com/balcony' id='lf72v157' type='set'> <query xmlns='jabber:iq:roster'> <item jid='romeo@example.net' name='Romeo'> <group>Lovers</group> </item> </query> </iq>
该用户可能想从所有组移除该条目.
C: <iq from='juliet@example.com/balcony' id='ju4b62a5' type='set'> <query xmlns='jabber:iq:roster'> <item jid='romeo@example.net'/> </query> </iq>
该用户也可能想修改对该条目的操作.
C: <iq from='juliet@example.com/balcony' id='gb3sv487' type='set'> <query xmlns='jabber:iq:roster'> <item jid='romeo@example.net' name='MyRomeo'/> </query> </iq>
该用户然后可能想完全移除该操作.
C: <iq from='juliet@example.com/balcony' id='o3bx66s5' type='set'> <query xmlns='jabber:iq:roster'> <item jid='romeo@example.net' name=''/> </query> </iq>
实现备注: 包含一个空的’name’属性等价于不包含’name’属性; 两个操作都是把name设为空字符串
成功情景
和添加一个名册条目一样, 如果该名册条目能被成功处理那么服务器必须在该用户的名册中更新该条目, 发送一个roster push到所有该用户的感兴趣资源, 并且发送一个IQ result给初始的资源; 详见章节2.3.
错误情景
章节2.3.3 中错误情景的描述也适用于更新一个名册条目.
删除一个名册条目
请求
任何时候, 一个客户端可以通过发送一个并把’subscription’属性值设为”remove”来把一个条目从他或她的名册中删除.
C: <iq from='juliet@example.com/balcony' id='hm4hs97y' type='set'> <query xmlns='jabber:iq:roster'> <item jid='nurse@example.com' subscription='remove'/> </query> </iq>
成功情景
如同增加一个名册条目, 如果服务器能成功地处理roster set那么它必须在该用户的名册中更新该条目, 发送一个roster push到该用户的所有感兴趣的资源(其中的’subscription’属性值设为”remove”), 并发送一个IQ result给初始的资源; 详见章节2.3.
另外, 该用户的服务器可能需要生成一个或更多subscription相关的presence节, 如下:
1.如果该用户对该联系人有一个出席信息订阅, 那么该用户的服务器必须发送一个type为"unsubscribe"的presence节给该联系人(为了对该联系人的出席信息取消订阅). 2.如果该联系人对该用户有一个出席信息订阅, 那么该用户的服务器必须发送一个type为"unsubscribed"的presence节给该联系人(为了取消该联系人对该用户的订阅). 3.如果出席信息订阅是相互的, 那么该用户的服务器必须同时发送type为"unsubscribe"presence节和type为"unsubscribed"的的presence节给该联系人.
S: <presence from='juliet@example.com' id='lm3ba81g' to='nurse@example.com' type='unsubscribe'/>S: <presence from='juliet@example.com' id='xb2c1v4k' to='nurse@example.com' type='unsubscribed'/>
错误情景
如果’jid’属性的值指定的一个条目不在该名册中, 那么服务器必须返回一个 节错误.
错误: 未发现名册条目
C: <iq from='juliet@example.com/balcony' id='uj4b1ca8' type='set'> <query xmlns='jabber:iq:roster'> <item jid='[ ... non-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”可以作如下理解:
1.想想客户端在它缓存的名册版本(假设是, "ver14")和新的名册版本(假设是, "ver96")之间有一个活跃的出席信息会话. 2.在此期间, 该客户端可能已经接收到一个和各种名册版本相关的roster pushes(它可能已经发生, 假设是, "ver51" 和 "ver79"). 无论如何, 这些roster pushes中的一些可能已经包含了同一个名册条目的中间更新(例如, 把对bill@example.org的订阅状态从"none"改为"to"又从"to"改为"both"). 3.这个暂时的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协议 好友管理(协议)
- XMPP协议 好友管理(协议)
- XMPP协议获取花名册(好友列表)
- XMPP协议(-)
- XMPP协议
- XMPP协议
- XMPP协议
- XMPP协议
- XMPP协议
- XMPP协议
- XMPP协议
- XMPP协议
- XMPP协议
- XMPP协议
- xmpp协议
- xmpp协议
- xmpp协议
- XMPP协议
- Android Paint API总结和使用方法
- 结构体、共用体简单比较
- ExtJs4 基础必备
- zoj 2975 Kinds of Fuwas
- php openssl信息查看
- XMPP协议 好友管理(协议)
- Rails -- 时间的内置函数和格式说明
- git fetch, rebase,pull,merge 区别
- AWK系统化的教程
- Kth Largest Element in an Array
- app进入主页前的广告页面
- 【最佳实践系列】灵活使用单机应用程序中的数据库
- instanceof 与isAssignableFrom
- 实现底部tabhost