Openfire (Wildfire) Connnection Manager 协议分析

Openfire (Wildfire) Connnection Manager目前还没有公开的JEP,所以把它的协议分析了一遍如下:

第一步:建立 socket 连接握手,一个 connection manager 可以跟服务器建立多个连接
1. 连接c2s
// to="cm1/socket1" 实际是是填写cm的名称(cm1)和当前 socket 的别名(socket1)
<stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:connectionmanager" to="cm1/socket1" version="1.0">

s2c:
// id="d2a9bc17" 中的 stream id 用来下一步验证
<?xml version='1.0' encoding='UTF-8'?>
<stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:connectionmanager" from="cm1/socket1" id="d2a9bc17" version="1.0" >

s2c: (tls, compress, etc)
<stream:features></stream:features>

2. 验证
c2s:
// 密码算法:sha1(streamid + password)
<handshake>f182e437fd8fbb0dec51667ff6e8ffd657cab9bb</handshake>

s2c:
<handshake></handshake>
// 表示验证通过,其他格式表示失败。


3. features

last step: server 告诉cm, server支持的features, 如果多个 socket 连接可能后面的 socket 不会收到这个包
s2c:
<iq type="set" id="143-23">
<configuration xmlns="http://jabber.org/protocol/connectionmanager">
   <starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"/>
   <mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
    <mechanism>PLAIN</mechanism>
    <mechanism>CRAM-MD5</mechanism>
    <mechanism>DIGEST-MD5</mechanism>
    <mechanism>ANONYMOUS</mechanism>
   </mechanisms>
   <compression xmlns="http://jabber.org/features/compress"><method>zlib</method></compression>
   <auth xmlns="http://jabber.org/features/iq-auth"/>
   <register xmlns="http://jabber.org/features/iq-register"/>
</configuration>
</iq>

c2s: cm 简单原包应答即可
<iq type="result" id="143-23" to="wildfire.server" from="cm1/socket1">
<configuration xmlns="http://jabber.org/protocol/connectionmanager">
    <starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"/>
    <mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
      <mechanism>PLAIN</mechanism>
      <mechanism>CRAM-MD5</mechanism>
      <mechanism>DIGEST-MD5</mechanism>
      <mechanism>ANONYMOUS</mechanism>
    </mechanisms>
    <compression xmlns="http://jabber.org/features/compress"><method>zlib</method></compression>
    <auth xmlns="http://jabber.org/features/iq-auth"/>
    <register xmlns="http://jabber.org/features/iq-register"/>
</configuration>
</iq>


第二步:代理 Jabber client 登录

1. 有个 client 连接过来了, CM 通知 Server open session
c2s:
<iq type="set" to="wildfire.server" from="cm1/socket1" id="90-0">
<session xmlns="http://jabber.org/protocol/connectionmanager" id="cm1d99f71af"><create/></session>
</iq>

s2c:
<iq type="result" id="90-0" from="wildfire.server" to="cm1/socket1">
<session xmlns="http://jabber.org/protocol/connectionmanager" id="cm1d99f71af"><create/></session>
</iq>

这时候 wildfire cm 的界面看到 client sessions = 1, 但是 sessions 的界面看不到 client
注意 cm1d99f71af 就是 client 的 streamid, 用来区分 client
在以后的包都放在 route streamid 中


2. auth client 客户端验证
c2s:
<route to="wildfire.server" from="cm1/socket2" streamid="cm1d99f71af">
<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="PLAIN">dGVzdDFi4zZwB0ZXN0TimsFakePacket</auth>
</route>
// 算法: base64.encode(username+@+host+/0+username+/0+password)<

s2c: success
<route from="wildfire.server" to="cm1" streamid="cm1d99f71af">
<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>
</route>

3. bind resource 便于c/s正式沟通
c2s:
// 从现在开始, iq id 从一个随机数递增
<route to="wildfire.server" from="cm1/socket3" streamid="cm1d99f71af">
<iq xmlns="jabber:client" id="cF25i-1" type="set">
    <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">
      <resource>TimAtHome</resource>
    </bind>
</iq>
</route>

s2c:
<route streamid="cm1d99f71af" from="wildfire.server" to="cm1">
<iq type="result" id="cF25i-1" to="wildfire.server/cm1d99f71af">
    <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"><jid>[email protected]/TimAtHome</jid></bind>
</iq>
</route>

4. create session
按照 xmpp 这个应该在 auth 之后发出, 放在auth后第1步 (rfc3921 section[3])
但是为了构建完整的jid, 具备 resource, 所以放在 resource bind 之后

c2s:
<route to="wildfire.server" from="cm1/socket4" streamid="cm1d99f71af">
<iq xmlns="jabber:client" id="cF25i-0" type="set">
    <session xmlns="urn:ietf:params:xml:ns:xmpp-session"/>
</iq>
</route>

s2c
<route streamid="cm1d99f71af" from="wildfire.server" to="cm1">
<iq type="result" id="cF25i-0" to="[email protected]/TimAtHome"><session xmlns="urn:ietf:params:xml:ns:xmpp-session"/></iq>
</route>


5. send presense, 用户的好友看到用户在线
c2s:
<route to="wildfire.server" from="cm1/socket1" streamid="cm1d99f71af">
<presence xmlns="jabber:client" id="cF25i-8"><status>Online</status>
</presence>
</route>

以后所有c/s之间的包 cm 只是简单封装,不再描述。

注意 cm 的客户端异常断线后,收到服务器发给该client的包需要给服务器回复一个错误信息。

你可能感兴趣的:(xml,session,manager,Stream,socket,compression)