XMPP eJabberd 的花名册和出席 (2)

DavidAlphaFox · 发布于 2017年12月28日 · 292 次阅读
84794b

你是我的好友

前篇文章中介绍了,什么是花名册和出席的机制。从数据关系的层面上看,这样已经构成了好友关系。在仔细观察这个流程就会发现,用户A添加用B为好友根本就没有得到用户B的准许,但是实际上并不是这样的,要真正完成好友添加,不单单是在花名册上完成好友关系的添加,还要进行出席订阅。

什么是出席订阅

为了保护XMPP用户们的隐私, 出席信息仅向某个用户已经批准的其他实体披露。当某个同意允许其他实体察看其出席信息时, 该实体被称为对该用户的出席信息有一个"订阅"。 一个对某用户的出席信息有订阅的实体或一个用户对其有出席信息订阅的实体被称为"联系人" ,这才真正完成XMPP的好友添加。

从此处可以看出,当用A想要添加用B为好友的时候,是需要B用户同意的。从这也不难看出来,真正好友的添加流程都集中在XMPP的出席部分,而不是花名册部分,花名册只是在负责在服务器上保存和管理用户的联系人。换句话说,一个规范的客户端应当先进行出席订阅接着才会进行花名册保存。

eJabberd是如何处理出席的

mod_roster 如何处理出席订阅

eJabberd 对出席订阅和相关操作并没有重新定义,而是直接复用了roster记录

-record(roster, {usj,
                 us,
                 jid,
                 name = <<>>,
                 subscription = none :: both | from | to | none | remove,
                 ask = none,
                 groups = [],
                 askmessage = <<>>,
                 xs = []}).

在这里,subscription代表着订阅关系,ask代表正在进行出席的操作,当出席订阅结束后该字段的意义就不重要了。

所有出席的订阅处理都被mod_roster注册在roster_in_subscriptionroster_out_subscription这两个hook上,最终交给mod_roster:process_subscription_transaction函数进行处理

出席订阅

好友申请

用户A要添加用B为好友,首先要做的就是要生成一个出站的出席订阅请求,也就是我们说的好友申请

<presence id='xk3h1v69'
             to='[email protected]om'
             type='subscribe'/>
出站处理

出站指的是用户A将申请发送到服务器上,并要求服务器更新A相关状态并转发给用户B的过程。
eJabberd的服务器接收到该请求后,会使用roster_out_subscription的hook进行处理,在处理过程中如果发现roster的存储中没有用户到目标用的条目会在内存中建立一个默认条目。

并且根据下面的规则,将这个roster的ask状态更新为out,subscription状态不变,存储到roster存储中,并将该出席信息转发给目标用户。

out_state_change(none, none, subscribe) -> {none, out};
入站处理

入站指的是服务器将用户A的请求发送给用户B,并在服务器上更新B的相关状态的过程。
eJabberd在入站的过程中,ejabberd_sm会发现这个好友请求,并使用roster_in_subscription进行处理,在处理过程中如果发现roster的存储中没有用户到目标用的条目会在内存中建立一个默认条目。

并且根据下面的规则,将这个roster的ask状态更新为in,subscription状态不变,存储到roster存储中,并将该出席信息转发给目标用户。

in_state_change(none, none, subscribe) -> {none, in};

好友应答

用户B收到用户A的好友申请后,就要做出回答,也就是我们说的好友批准流程,好友应答有两种情况

<!-- 同意的情况 -->
<presence id='h4v1c4kj'
              to='[email protected]'
              type='subscribed'/>

<!-- 不同意的情况 -->
<presence id='tb2m1b59'
              to='[email protected]'
              type='unsubscribed'/>
出站处理

此时的出站,指的是用户B将好友应答发送给服务器,并要求服务器更新B的相关状态,并将申请转发给A的过程 同样eJabberd的服务器接收到该请求后,会使用roster_out_subscription的hook进行处理,这个时候会从roster存储中读取出ask状态为in,subscription状态为none的记录。

根据下面的规则进行状态更新

out_state_change(none, in, subscribed) -> {from, none};
out_state_change(none, in, unsubscribed) -> {none, none};
  • 不同意订阅,会返回{none,none},在mod_roster:process_subscription_transaction的处理过程中将会将记录删除
  • 如果同意订阅,会返回{from, none},会将subscription状态更新为from,ask状态更新为none并保存
入站处理

此时的入站,指服务器将B的应答发送给A,并将更新状态并将消息发送给A的过程 同样eJabberd在入站的过程中,ejabberd_sm会发现这个好友请求,并使用roster_in_subscription进行处理,这个时候会从roster存储中读取出ask状态为out,subscription状态为none的记录。

根据下面的规则进行状态更新

in_state_change(none, out, subscribed) -> {to, none};
in_state_change(none, out, unsubscribed) -> {none, none};
  • 不同意订阅,会返回{none,none},在mod_roster:process_subscription_transaction的处理过程中将会将记录删除
  • 如果同意订阅,会返回{from, none},会将subscription状态更新为to,ask状态更新为none并保存

总结

从整个出席订阅也就是我们常说的好友添加过程中,可以看出XMPP是非常严谨的,将好友添加合理分配给,请求方,服务器和被请求方进行处理,各司其职。本篇中还有几个处理并没有介绍,其中包括,出席订阅取消既好友删除,出席订阅预批准既好友添加白名单。

共收到 0 条回复
84794b DavidAlphaFox eJabberd 的花名册和出席 (3) 中提及了此贴 01月08日 15:16
需要 登录/注册 后方可回复, 如果你还没有账号请点击这里 注册