出家如初,成佛有余

Jabber协议分析之Subscriptions运行机制-Presence subscription

Posted in Uncategorized by chuanliang on 2008/07/23

    手机客户端需要实现即时通信功能,在通信协议上采用开放的Jabber(XMPP)协议,整个XMPP协议最为核心也是最为复杂的部分是Subscription的运行机制,抓取了一下相关的通信协议报文,供开发时候参考。

  

1. 测试环境

1.1. 测试软件环境:

    Jabber服务器:Openfire 3.5.2

    Jabber客户端:Spark 2.5.8

抓包:Wireshark

1.2. 服务器环境:

    Jabber服务器:192.168.1.12,安装Openfire,域为home1

    Jabber用户客户端:192.168.1.10,安装Spark客户端,Jabber用户为chuanliang。

    Jabber联系人客户端:192.168.1.11,安装Spark客户端,Jabber用户为liangchuan

1.3. 测试场景:

测试1:

    Jabber用户chuanliang和Jabber联系人liangchuan被彼此的presence订阅,且允许把彼此加入自己的Roster

测试2

    Jabber联系人liangchuan接受Jabber用户chuanliang的订阅,但是不允许chuanliang加入自己的Roster

测试3

    Jabber联系人liangchuan不接受Jabber用户chuanliang的订阅,同时不允许chuanliang加入自己的Roster

以测试用例“测试1”说明一下测试过程:

1、 chuanliang@home1在192.168.1.10客户端上新增联系人liangchuan@home1

2、 liangchuan@home1在192.168.1.11客户端上“准许chuanliang@home1新增liangchuan@home1到chuanlian的联系人名单中”,同时”Add user to liangchuan’s  roster”

clip_image002

3、 chuanliang@home1在192.168.1.10客户端上“准许liangchuan@home1新增chuanliang@home1到chuanlian的联系人名单中”,同时”Add user to chuanliang’s  roster”

clip_image004

2. 测试1- contact accept subscription and allow add user to it’s roster

2.1. Jabber用户客户端发送一个type=’set’ 的Roster Update请求给Jabber服务器端

Ø 192.168.1.10->192.168.1.12

Jabber用户客户端发送一个<iq/>包给Jabber服务器端,其jabber:iq:roster名字空间中包含一个type=’set’,用于更新自己的roster

<iq id="7SJ55-63" type="set">

    <query xmlns="jabber:iq:roster">

        <item jid="liangchuan@home1" name="liangchuan">

            <group>Friends</group>

        </item>

    </query>

</iq>

Ø 192.168.1.12->192.168.1.10

Jabber用户客户端从服务器接收到一个“roster push”,产生一个新的roster条目,其subscription状态置为“none”:

<iq type="set" id="308-51" to="chuanliang@home1/spark">

    <query xmlns="jabber:iq:roster">

        <item jid="liangchuan@home1" name="liangchuan" subscription="none">

            <group>Friends</group>

        </item>

    </query>

</iq>

Ø 192.168.1.12->192.168.1.10

Jabber用户客户端在成功的情况下,从服务器接收到一个<iq/>包,其type=’result’。

<iq type="result" id="7SJ55-63" to="chuanliang@home1/spark"/>

2.2. Jabber用户客户端发送一个type=’subscribe’的<presence/>的包给联系人客户端

Jabber用户客户端发送一个type=’subscribe’的<presence/>的包给联系人(发送给到Jabber服务器)

Ø 192.168.1.10->192.168.1.12

<presence id="7SJ55-64" to="liangchuan@home1" type="subscribe"/>

Ø 192.168.1.12->192.168.1.10

Jabber用户客户端接着从服务器收到包含联系人待定子状态的’none’订阅状态的“roster push”;这个待定子状态在其联系人名单中包含一个ask=’subscribe’属性:

<iq type="set" id="132-52" to="chuanliang@home1/spark">

<query xmlns="jabber:iq:roster">

<item jid="liangchuan@home1" name="liangchuan" ask="subscribe" subscription="none">

<group>Friends</group>

</item>

</query>

</iq>

2.3. Jabber服务器发送一个type=’subscribe’的<presence/>的Roster push包给联系人客户端

Ø 192.168.1.12->192.168.1.11

Jabber服务器在接收到192.168.1.10发送的type=’subscribe’的<presence/>的包后,然后发送一个type=’subscribe’的<presence/>的包给联系人客户端

<presence id="7SJ55-64" to="liangchuan@home1" type="subscribe" from="chuanliang@home1"/>

Ø 192.168.1.11->192.168.1.12

Jabber联系人客户端发送一个<iq/>包给Jabber服务器,其jabber:iq:roster名字空间中包含一个type=’set’,用于更新自己的roster:

<iq id="8SAVC-26" type="set">

<query xmlns="jabber:iq:roster">

<item jid="chuanliang@home1" name="chuanliang">

<group>Friends</group>

</item>

</query>

</iq>

Ø 192.168.1.12->192.168.1.11

Jabber联系人客户端从服务器接收到一个<iq/>包,其type=’result’

<iq type="result" id="8SAVC-26" to="liangchuan@home1/spark"/>

2.4. Jabber联系人客户端发送一个type=’subscribe’的<presence/>的包给用户客户端

此部分请求发生在联系人客户端“准许chuanliang@home1新增liangchuan@home1到chuanlian的联系人名单中”时候同时选择了:“Add user to liangchuan’s  roster”选项。如果没有选择,则无此部分请求。

Ø 192.168.1.11->192.168.1.12

<presence id="8SAVC-27" to="chuanliang@home1" type="subscribe"/>

Ø 192.168.1.12->192.168.1.10

服务器传递请求给Jabber用户端

<presence id="8SAVC-27" to="chuanliang@home1" type="subscribe" from="liangchuan@home1"/>

Ø 192.168.1.12->192.168.1.10

<iq type="set" id="867-55" to="chuanliang@home1/spark">

<query xmlns="jabber:iq:roster">

<item jid="liangchuan@home1" name
="liangchuan" subscription="to">

<group>Friends</group>

</item>

</query>

</iq>

2.5. Jabber联系人客户端接收订阅请求,发送一个type=’subscribed’的<presence/>的包给用户客户端

联系人下一步要做的就是决定是否接受订阅请求。我们假定联系人接受订阅请求

Ø 192.168.1.11->192.168.1.12

联系人的Jabber客户端发送一个type=’subscribed’的<presence/>的包给Jabber用户(通过服务器端)

<presence id="8SAVC-28" to="chuanliang@home1" type="subscribed"/>

Ø 192.168.1.12->192.168.1.10

<presence id="8SAVC-28" to="chuanliang@home1" type="subscribed" from="liangchuan@home1"/>

<presence id="8SAVC-6" from="liangchuan@home1/spark" to="chuanliang@home1/spark">

<status/>

<priority>1</priority>

</presence>

Ø 192.168.1.12->192.168.1.11

联系人的Jabber客户端从服务器接收一个“roster push”包含Jabber用户的条目,其中subscription状态置为“from”

<iq type="set" id="14-54" to="liangchuan@home1/spark">

<query xmlns="jabber:iq:roster">

<item jid="chuanliang@home1" name="chuanliang" ask="subscribe" subscription="from">

<group>Friends</group>

</item>

</query>

</iq>

2.6. Jabber用户客户端接收订阅请求,发送一个type=’subscribed’的<presence/>的包给联系人客户端

Ø 192.168.1.10->192.168.1.12

<presence id="7SJ55-65" to="liangchuan@home1" type="subscribed"/>

Ø 192.168.1.12->192.168.1.10

<iq type="set" id="382-56" to="chuanliang@home1/spark">

<query xmlns="jabber:iq:roster">

<item jid="liangchuan@home1" name="liangchuan" subscription="both">

<group>Friends</group>

</item>

</query>

</iq>

Ø 192.168.1.12->192.168.1.11

<iq type="set" id="697-57" to="liangchuan@home1/spark">

<query xmlns="jabber:iq:roster">

<item jid="chuanliang@home1" name="chuanliang" subscription="both">

<group>Friends</group>

</item>

</query>

</iq>

Ø 192.168.1.12->192.168.1.11

<presence id="7SJ55-65" to="liangchuan@home1" type="subscribed" from="chuanliang@home1"/>

<presence id="7SJ55-51" from="chuanliang@home1/spark" to="liangchuan@home1/spark">

<status/>

<priority>1</priority>

</presence>

3. 测试2- contact accept subscribption and not allow add user to it’s roster

3.1. Jabber用户客户端发送一个type=’set’ 的Roster Update请求给Jabber服务器端

Ø 192.168.1.10->192.168.1.12

Jabber用户客户端发送一个<iq/>包给Jabber服务器端,其jabber:iq:roster名字空间中包含一个type=’set’,用于更新自己的roster

<iq id="xHk99-51" type="set">

<query xmlns="jabber:iq:roster">

<item jid="liangchuan@home1" name="liangchuan">

<group>Friends</group>

</item>

</query>

</iq>

Ø 192.168.1.12->192.168.1.10

Jabber用户客户端从服务器接收到一个“roster push”,产生一个新的roster条目,其subscription状态置为“none”:

<iq type="set" id="133-130" to="chuanliang@home1/spark">

<query xmlns="jabber:iq:roster">

<item jid="liangchuan@home1" name="liangchuan" subscription="none">

<group>Friends</group>

</item>

</query>

</iq>

Ø 192.168.1.12->192.168.1.10

Jabber用户客户端在成功的情况下,从服务器接收到一个<iq/>包,其type=’result’。

<iq type="result" id="xHk99-51" to="chuanliang@home1/spark"/>

3.2. Jabber用户客户端发送一个type=’subscribe’的<presence/>的包给联系人客户端

Jabber用户客户端发送一个type=’subscribe’的<presence/>的包给联系人(发送给到Jabber服务器)

Ø 192.168.1.10->192.168.1.12

<presence id="xHk99-52" to="liangchuan@home1" type="subscribe"></presence>

Ø 192.168.1.12->192.168.1.10

Jabber用户客户端接着从服务器收到包含联系人待定子状态的’none’订阅状态的“roster push”;这个待定子状态在其联系人名单中包含一个ask=’subscribe’属性:

<iq type="set" id="35-132" to="chuanliang@home1/spark">

<query xmlns="jabber:iq:roster">

<item jid="liangchuan@home1" name="liangchuan" ask="subscribe" subscription="none">

<group>Friends</group>

</item>

</query>

</iq>

3.3. Jabber服务器发送一个type=’subscribe’的<presence/>的Roster push包给联系人客户端

Ø 192.168.1.12->192.168.1.11

Jabber服务器在接收到192.168.1.10发送的type=’subscribe’的<presence/>的包后,然后发送一个type=’subscribe’的<presence/>的包给联系人客户端

<presence id="xHk99-52" to="liangchuan@home1" type="subscribe" from="chuanliang@home1"/>

3.4. Jabber联系人客户端接收订阅请求,发送一个type=’subscribed’的<presence/>的包给用户客户端

联系人下一步要做的就是决定是否接受订阅请求。我们这里联系人接受订阅请求,但是取消”Add user to chuanliang’s  roster”操作。

Ø 192.168.1.11->192.168.1.12

联系人的Jabber客户端发送一个type=’subscribed’的<presence/>的包给Jabber用户(通过服务器端)

<presence id="8SAVC-90" to="chuanliang@home1" type="subscribed"></presence>

Ø 192.168.1.12->192.168.1.10

<presence id="8SAVC-90" to="chuanliang@home1" type="subscribed" from="liangchuan@home1"/>

<presence id="8SAVC-30" from="liangchuan@home1/spark" to="chuanliang@home1/spark">

<status/>

<priority>1</priority>

</presence>

Ø 192.168.1.12->192.168.1.11

联系人的Jabber客户端从服务器接收一个“roster push”包含Jabber用户的条目,其中subscription状态置为“from”

<iq type="set" id="585-135" to="liangchuan@home1/spark">

<query xmlns="jabber:iq:roster">

<item jid="chuanliang@home1" subscription="from"/>

</query>

</iq>

4. 测试3- contact not accept subscription and  not allow add user to it’s roster

4.1. Jabber用户客户端发送一个type=’set’ 的Roster Update请求给Jabber服务器端


192.168.1.10->192.168.1.12

Jabber用户客户端发送一个<iq/>包给Jabber服务器端,其jabber:iq:roster名字空间中包含一个type=’set’,用于更新自己的roster

<iq id="n7NDl-39" type="set">

<query xmlns="jabber:iq:roster">

<item jid="liangchuan@home1" name="liangchuan">

<group>Friends</group>

</item>

</query>

</iq>

Ø 192.168.1.12->192.168.1.10

Jabber用户客户端从服务器接收到一个“roster push”,产生一个新的roster条目,其subscription状态置为“none”:

<iq type="set" id="321-250" to="chuanliang@home1/spark">

<query xmlns="jabber:iq:roster">

<item jid="liangchuan@home1" name="liangchuan" subscription="none">

<group>Friends</group>

</item>

</query>

</iq>

Ø 192.168.1.12->192.168.1.10

Jabber用户客户端在成功的情况下,从服务器接收到一个<iq/>包,其type=’result’。

<iq type="result" id="n7NDl-39" to="chuanliang@home1/spark"/>

4.2. Jabber用户客户端发送一个type=’subscribe’的<presence/>的包给联系人客户端

Jabber用户客户端发送一个type=’subscribe’的<presence/>的包给联系人(发送给到Jabber服务器)

Ø 192.168.1.10->192.168.1.12

<presence id="n7NDl-40" to="liangchuan@home1" type="subscribe"/>

Ø 192.168.1.12->192.168.1.10

Jabber用户客户端接着从服务器收到包含联系人待定子状态的’none’订阅状态的“roster push”;这个待定子状态在其联系人名单中包含一个ask=’subscribe’属性:

<iq type="set" id="942-252" to="chuanliang@home1/spark">

<query xmlns="jabber:iq:roster">

<item jid="liangchuan@home1" name="liangchuan" ask="subscribe" subscription="none">

<group>Friends</group>

</item>

</query>

</iq>

4.3. Jabber服务器发送一个type=’subscribe’的<presence/>的Roster push包给联系人客户端

Ø 192.168.1.12->192.168.1.11

Jabber服务器在接收到192.168.1.10发送的type=’subscribe’的<presence/>的包后,然后发送一个type=’subscribe’的<presence/>的包给联系人客户端

<presence id="n7NDl-40" to="liangchuan@home1" type="subscribe" from="chuanliang@home1"/>

4.4. Jabber联系人客户端接收订阅请求,发送一个type=’ unsubscribe’的<presence/>的包给用户客户端

联系人下一步要做的就是决定是否接受订阅请求。我们这里联系人接受订阅请求,但是取消”Add user to chuanliang’s  roster”操作。

Ø 192.168.1.11->192.168.1.12

联系人的Jabber客户端发送一个type=’ unsubscribe的<presence/>的包给Jabber用户(通过服务器端)

<presence id="8SAVC-116" to="chuanliang@home1" type="unsubscribe"/>

Ø 192.168.1.12->192.168.1.10

<presence id="8SAVC-116" to="chuanliang@home1" type="unsubscribe" from="liangchuan@home1"/>

Ø 192.168.1.12->192.168.1.11

联系人的Jabber客户端从服务器接收一个“roster push”包含Jabber用户的条目,其中subscription状态置为“remove”

<iq type="set" id="190-258" to="liangchuan@home1/spark">

<query xmlns="jabber:iq:roster">

<item jid="chuanliang@home1" subscription="remove"/>

</query>

</iq>

4.5. Jabber用户客户端发送取消订阅请求,发送一个subscription =’ remove’的<iq/>的包给服务器端

Ø 192.168.1.10->192.168.1.12

用户的Jabber客户端发送一个subscription="remove"的包给服务器,取消订阅

<iq id="n7NDl-41" type="set">

<query xmlns="jabber:iq:roster">

<item jid="liangchuan@home1" name="liangchuan" subscription="remove" ask="subscribe">

<group>Friends</group>

</item>

</query>

</iq>

Ø 192.168.1.12->192.168.1.10

<iq type="set" id="872-256" to="chuanliang@home1/spark">

<query xmlns="jabber:iq:roster">

<item jid="liangchuan@home1" subscription="remove"/>

</query>

</iq>

Ø 192.168.1.12->192.168.1.10

<iq type="result" id="n7NDl-41" to="chuanliang@home1/spark"/>

5. 参考文档

http://www.xmpp.org/extensions/xep-0162.html

http://tools.ietf.org/html/rfc3921

http://www.xmpp.org/extensions/xep-0144.html

 

Tagged with: , , , , ,

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s

%d 博主赞过: