`
ssxxjjii
  • 浏览: 931920 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Openfire源码研究

    博客分类:
  • IM
 
阅读更多

Openfire源码研究

 Openfire源码目录结构

1.build目录:build目录下收录的是生成安装文件(例如:rpm)所要的一些文件,例如JRE等。

2.resources目录:resources目录下收录的是一些为实现国际化(i18n)和本地化的一些编码文件(例如:英文,中文,法文,德文等)。

3.documentation目录:documentation目录下收录的是一些关于Openfire安装和配置的信息,但最终要的是这里有Openfire开发的Javadoc

4.src目录:顾名思义这个src文件夹就是我们想要的Openfire源代码了,这下面又有许多文件夹,我们只要Java文件夹就好,这里面实现的Openfire的核心功能,通过它就可以调试Openfire了。

命名规则

Openfire中常见的类名后缀命名包括StarterPluginListenerDispatcherHandlerManagerProvider,通常情况下,这些命名类包括如下意义:

XXStarter

系统启动类,如org.jivesoftware.openfire.starter.ServerStarter,调用其start()方法可启动系统应用。

XXListener

业务的最终处理类。

XXDispatcher

调度类,其中有很多关键方法,如addListener(),以组合的方式,为类内定义的静态Set<XXListener>实例添加XXListener对象。以便调用dispatchEvent(String property, EventType eventType, Map<String, Object> params)方法遍历处理Set集中的XXListener对象(通过调用XXListener对象的各实际方法完成实际业务)。

XXPlugin

实现Plugin接口的插件类,需实现initializePlugin(PluginManager manager, File pluginDirectory)方法和destroyPlugin()方法。在其初始化方法中调用Dispatcher实现类的addListener()方法如PropertyEventDispatcher.addListener(this)

XXProvider

       实现面向接口编程方式的接口类,通过反射机制创建具体实现类的对象,反射类名配置在ofproperty表对应的记录propvalue属性中。若没有相关配置,则调用默认实现类,默认实现类类名命名规则为DefaultXXProvider

XXHandler

实际处理类,以ConnectionHandler为例,在org.jivesoftware.openfire.spi. ConnectionManagerImpl类的startClientSSLListeners(String localIPAddress)方法中,有这样一段代码:sslSocketAcceptor.bind(new InetSocketAddress(bindInterface, port), new ClientConnectionHandler(serverName));其中bind方法的第二个参数是新创建的一个ClientConnectionHandler的实例,而它就是ConnectionHandler的一个子类。

 

系统配置项

Openfire的系统配置项采用文件结合数据库表的方式配置,也有部分默认配置项通过Java硬编码方式配置(如org.jivesoftware.openfire. ConnectionManager接口类中定义的DEFAULT_PORTDEFAULT_SSL_PORTDEFAULT_COMPONENT_PORT等),Openfire中比较重要的配置位置包括:

一、      src/conf目录下的openfire.xml配置文件。该配置文件为系统核心配置文件。在第一次启动Openfire并通过管理控制台完成安装配置后会往该配置文件中填入相应的配置信息。

二、      plugin.xml配置文件。该配置文件为各插件包下的核心配置文件,由它确定插件核心处理类和相应页面插件的展现等。配置项及含义详见官方插件开发说明部分。

三、      web.xmlweb-custom.xml配置文件。用于配置servlet和用户自定义servlet(插件页面用,放在插件对应目录下)

四、      ofproperty中的各条记录,该表中包括两个字段namepropvalue,分别代表配置项名和配置项值。

 

系统启动流程

系统启动时调用ServerStarter类中的start()方法,通过反射加载org.jivesoftware.openfire.XMPPServer类文件,创建实例时调用其构造函数,在其构造函数中调用其start()方法实际启动服务应用程序。Start()方法中首先调用verifyDataSource()方法验证并确保数据库可以访问,然后会调用                loadModules();initModules();startModules();方法来对Module接口的实现类的各子类进行操作,依次完成模块的加载、初始化和启动操作。loadModules()方法中会调用loadModule(String module)方法通过反射加载各模块类,参数字符串module为对应的模块核心处理类的类名。

客户端

Openfiresocket网络连接包括:

1.       服务器和服务器之间的连接(监听在端口5269

2.       外部组件和服务器之间的连接(监听在端口5275

3.       多元(complex)连接(监听在端口5269

4.       客户端和服务器的连接(监听在端口5222

5.       和客户端通过TLS/SSL3.0和服务器的连接。(监听在端口5223

 这些连接都是通过ConnectionManager接口实现管理的,程序中对ConnectionManager接口的实现类是ConnectionManagerImpl,它是作为一个模块(Module)类加载到服务器中的。

客户端和服务器的连接

ConnectionManagerImpl中是通过调用startClientListeners方法来初始化和开始端口监听的。

startClientListeners方法使用的是ApacheMina框架来实现网络连接的,Mina框架的模式如下:

IoFilter

IoFilterMINA的功能扩展提供了接口。它拦截所有的IO事件进行事件的预处理和后处理。它与Servlet中的filter机制十分相似。多个IoFilter存放在IoFilterChain      

IoFilter能够实现以下功能:

              数据转换

              事件日志

              性能检测

    Openfire中主要用filter(过虐器)这种机制来进行数据转换。

   Protocol Codec Factory

       Protocol Codec Factory提供了方便的Protocol支持,通过它的EncoderDecoder,可以方便的扩展并支持各种基于Socket的网络协议,比如HTTP服务器、FTP服务器、Telnet服务器等等。

       要实现自己的编码/解码器(codec)只需要实现interface: ProtocolCodecFactory即可,在Openfire中实现ProtocolCodecFactory的类为XMPPCodecFactory

   IoHandler:

   MINA中,所有的业务逻辑都有实现了IoHandlerclass完成    ,当事件发生时,将触发IoHandler中的方法:

      sessionCreated

sessionOpened

sessionClosed

sessionIdle

exceptionCaught

messageReceived

messageSent

       Openfire中客户端和服务器连接的IoHandler实现类是ClientConnectionHandler,它是从ConnectionHandler中继承来的。

       startClientListeners方法首先为Mian框架设置线程池,再将一个由XMPPCodecFactory作为Protocol Codec FactoryFilter放入到FilterChain中,然后绑定到端口5222,并将ClientConnectionHandler作为IoHandler对数据进行处理。完成这些步骤后Openfire就在5222等待客户端的连接。

IOSession

Session可以理解为服务器与客户端的特定连接,该连接由服务器地址、端口以及客户端地址、端口来决定。客户端发起请求时,指定服务器地址和端口,客户端也会指定或者根据网络路由信息自动指定一个地址、自动分配一个端口。这个地址、端口对构成一个Session

 

客户端连接的处理过程:

1、当有客户端进行连接时根据Mina框架的模式首先调用的是sessionOpened方法。

sessionOpened首先为此新连接构造了一个parserXMLLightWeightParser),这个parser是专门给XMPPDecoder(是XMPPCodecFactory的解码器类)使用的,再创建一个OpenfireConnection类实例connection和一个StanzaHandler的实例。最后将以上的parser, connectionStanzaHandler的实例存放在Minasession中,以便以后使用。

2当有数据发送过来时,Mina框架会调用messageReceived方法

messageReceived首先从Minasession中得到在sessionOpened方法中创建的StanzaHandler实例handler,然后从parsers中得到一个parser(如果parsers中没有可以创建一个新的实例)(注意这个parser和在sessionOpened方法中创建的parser不同,这个parser是用来处理Stanza的,而在sessionOpened方法中创建的parser是在filter中用来解码的,一句话说就是在sessionOpened方法中创建的parser是更低一层的parser)。最后将xml数据包交给StanzaHander的实例hander进行处理。

3StanzaHander的实例hander处理xml数据包的过程

StanzaHander首先判断xml数据包的类型,.如果数据包以“<stream:stream”打头那么说明客户端刚刚连接,需要初始化通信(符合XMPP协议)Openfire首先为此客户端建立一个与客户端JID相关的ClientSession,而后与客户端交互协商例如是否使用SSL,是否使用压缩等问题。当协商完成之后进入正常通信阶段,则可以将xml数据包交给PacketRouteImpl模块进行处理。

4PacketRouteImpl中包将进一步被细化处理

       PacketRouteImp1packet分成MessageIqPresence,分别交由MessageRouterIqRouterPresenceRouter进行下一步路由。

 

MessageRoute处理

       调用routetableImp1进行处理,然后交由通过getRoute方法获取session,最后调用NIOConnectiondeliver方法。

IQRoute 处理

       根据IQ的不同的命名空间通过getHandler方法找到相应的iq处理方法进行处理。

       注意:在IQRouterinitialize方法中,iqHandlers.addAll方法会将iq的命名空间与其对应的处理方法存储到一个map中。

PresenceRoute处理

    调用PresenceUpdateHandlerprocess方法(处理数据库的更新和缓存的更新),然后调用RosterboradcastPresence方法(检查privacy list(隐身及黑名单用户)然后路由给所有在线好友),再调用routeTablegetRoutes()获取session,最后调用NIOConnectiondeliver方法。

 

数据库处理

Openfire的数据库处理采用直接调用JDBC 的方式。核心类为org.jivesoftware.database.DbConnectionManager。数据库的处理与业务处理耦合,没有划分出专门的业务逻辑层。

ConnectionProvider

       此类为数据库提供者接口,如需连接mysqlhsqldb等数据库,需首先实现些接口

处理方式

    通常直接调用XXManager中的实例方法,XXManager中又调用的是对应的接口XXProvider的方法,实际操作在该接口的实现类中实现。实现类是动态绑定的(默认的实现类通常命名规则为DefaultXXProvider),在运行时根据ofproperty表中对应配置项值选择。下面以添加用户组为例进行说明。

       首先获得GroupManager的一个实例,在调用其构造函数时调用initProvider()方法,在该方法中获取数据库中配置项的值,若不为空则根据该值通过反射机制获取GroupProvider接口的实现类实例对象。

常用类

org.jivesoftware.database.DbConnectionManager

    连接管理类

org.jivesoftware.util.JiveGlobals

    通常用于操作ofproperty表中记录

 

用户登录

服务器告诉客户端,服务器支持的认证方法列表。

客户端就可以选其中一个发起真正的认证。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics