消息处理流程总揽(该图来源于互联网,图片很大,不过类容还是挺清楚的。不方便查看,需要下载查看):
更为直观的流程描述:
在线chat
Test1---->test2
<message id="1coTi-29"
to="test2@8ntmorv1ep4wgcy/Smack"
from="test1@8ntmorv1ep4wgcy/Spark 2.6.3" type="chat">
<body>hello</body>
<thread>CLhNEh</thread>
<x xmlns="jabber:x:event">
<offline/>
<composing/>
</x>
</message>
Of系统发送消息会调用两次过滤器
InterceptorManager.getInstance().invokeInterceptors(packet, this, false, false);
deliver(packet);
// Invoke the interceptors after we have sent the packet
InterceptorManager.getInstance().invokeInterceptors(packet, this, false, true);
离线chat 会 调用数据存储方法,不会经过过滤器
消息路由
RoutingTable(路由表),用于存储客户端会话路线,即将离任的服务器会话和组件。当一个用户与服务器进行身份验证的客户端会话将被添加到路由表。每当客户端会话可用或不可用的路由表将被更新过。RoutingTable是维护服务器范围的知识,它包括任何节点(也是集群的主机)的路由。
路由只关心节点地址,目的地是数据包处理程序。通常情况下是指以下三个类型:
l Session 一个本地或远程会话属于服务器的域。远程会话可能在集群服务器。
l Chatbot 聊天机器人,将有各种各样的Chatbot数据包路由到它
l Transport 其他服务器域,它可能是驻留在同一服务器JVM
几乎在所有情况下,调用者都不必关心如何处理一个给定的节点。只需要简单地获得数据包处理程序和交付包节点,把细节的处理程序就可以了。在OpenFire中的路由使用字符串的预处理匹配规则来赋予的XMPP规范。一个特定名称的路由可以由通配符或者其他的资源来匹配,也可标示为null。例如:一个路由到任何地址(server.com)应该设置名称为空,主机“server.com”和资源都为null,一个路由到最好的资源,为(user@server.com)应该表明路由无效资源组件的XMPPAddress。在会话管理中,添加的路由最好用user@server.com和user@server.com/resource routes(路由资源)。
在容纳广播这一规则里,你还可以查询匹配个别的比如孩子节点。路由表包含很多的节点树。节点树是安排在以下等级秩序:
forest |
在路由表中的所有节点。一些XMPP与主机的地址,名字,和资源设置为null会匹配所有节点 存储在路由表。使用的时候应该注意,路由表可能包含成千上万条目和迭代器产品。 |
domain root |
这些节点树的根都是服务器的一个域。XMPP地址包含只是一个主机条目,空的名称和资源领域将匹配域根,所有孩子节点将包含两根条目(如果有的话)和所有条目相同的主机名。 |
user branches |
根的直接子元素是用户分支。一个XMPP地址仅包一个曾和名称条目,空在资源领域将匹配一个特定用户的分支。所有孩子节点将同时包含用户部门和所有条目相同的主机和名字,而可以其他忽视资源。这是给大多数的用户进行广播。注意,如果用户分支位于外国服务器,唯一的途径将服务器对服务的传输。
|
resource leaves |
每个用户分支可以有零个或多个资源叶子。部分匹配在XMPP地址和值在主机、名称和资源领域将相当于精确匹配调用因为只有一个路线可以被注册为一个特定的。如果你想搜索的资源叶路线,以及有效的用户部门对该节点如果没有叶的存在,可以看这个getBestRoute()方法的描述
|
任何组件或模块都会触发路由路由表的立即更新。
用户登陆
OF于spark的登陆对话
第一次对话:
客户端发送请求消息:
<stream:stream to="192.169.1.104" xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" version="1.0">
服务端处理:
1.通过ConnectionHandle的messageReceived方法进入process处理消息方法,然后调用create_
Session方法。该方法使用XPP抓住开放流标签和创建一个活跃的会话对象,这里会话创建取决于发送
者的名称空间,而且这个会话将获得打开流标签、检查错误、创建一个会话、返回一个错误或者杀死这 个
个连接。在这个方法中,首先会检查这个stream的“to“属性是否会匹配服务器的的子域名,如果这个
属性中to的值是个未知,或者连接关闭的话,则返回false进行下一步判断如果检查正确则拼装一个会
话对象的xml文件调用deliverRawText。当返回了false就会进行下一个的判定,在这样的判定中,
先用发送这个空间命名,判断客户端与服务端连接的安全型对话,服务端也会回复一串字符流。在登陆
会话中,因为stream的开始标签START_TAG不存在,则直接进入了下个方法。
2.通过NIOConnection中的方法deliverRawText()方法给客户端会话。它会给客户端返回两条信息:
1):<?xml version='1.0'encoding='UTF-8'?>
<stream:streamxmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client"
from="192.168.2.104"id="a8fdc215" xml:lang="en"
version="1.0">
2):<stream:features>
<starttlsxmlns="urn:ietf:params:xml:ns:xmpp-tls"></starttls>
<mechanismsxmlns="urn:ietf:params:xml:ns:xmpp-sasl">
<mechanism>DIGEST-MD5</mechanism>
<mechanism>JIVE-SHAREDSECRET</mechanism>
<mechanism>PLAIN</mechanism>
<mechanism>ANONYMOUS</mechanism>
<mechanism>CRAM-MD5</mechanism>
</mechanisms>
<compression xmlns="http://jabber.org/features/compress">
<method>zlib</method>
</compression>
<auth xmlns="http://jabber.o