1、打开Tiagse源码,TigaseServer启动入口 start方法:
String config_class_name = System.getProperty( CONFIGURATOR_PROP_KEY,DEF_CONFIGURATOR ); config = (ConfiguratorAbstract) Class.forName( config_class_name ).newInstance(); config.init( args ); // config = new ConfiguratorOld(config_file, args); config.setName( "basic-conf" ); String mr_class_name = config.getMessageRouterClassName(); router = (MessageRouterIfc) Class.forName( mr_class_name ).newInstance(); router.setName( serverName ); router.setConfig( config );//初始化組件 router.start();//启动Server
说明:主要任务就是根据配置文件搜集所有的组件,构建XMPP路由服务环境;
MessageRouter.java
@Override public void setConfig(ConfiguratorAbstract config) { components.put(getName(), this);//将自身添加到自己的components成员变量 this.config = config; addRegistrator(config);//将自身注册进组件列表中,注意*registrators map类型。存放所有的组件 } public void addRegistrator(ComponentRegistrator registr) { registrators.put(registr.getName(), registr);//将自身注册到registrators表中 addComponent(registr);//将registr注册到components中 for (ServerComponent comp : components.values()) { registr.addComponent(comp); } }
A:addRegistrator();//获取所有可以连接到MesssageRouter的ServerComponent
B:addComponent(registr) ;//汇集registr中的组件
C:registr.addComponent(comp);//注册所有组件
1.2、组件的初始化
通过setProperties(Map<String, Object> props)方法完成组件的初始化。
过程:1、分离出所有的组件如果组件instances MessageReceiver(可以接收数据包)那么则添加到组件路由。
2、组件初始化完毕。调用comp.initializationCompleted();方法
2、ClientConnectionManager处理客户端发送过来的数据包的过程如下图
整个处理流程如下:
2.1.socket监听接收客户端报文
socket接收到tcp报文然后转换为xmpp packet的过程;
主处理组件:ClientConnectionManager
c2s在启动的时候创建了3类线程(创建过程参考启动篇):
socketReadThread():负责读socket的数据;
socketWriteThread():负责向socket写数据;
ResultsListener:负责componet执行结果的处理;
a.socketReadThread和socketWriteThread循环selector.select(),得到selectionKey->XMPPIOService放到队列等待完成。
b.把等待完成的XMPPIOService,通过completionService.submit(serv)提交执行,调用XMPPIOService.call();
c.XMPPIOService.call(),完成了接收的socket报文到packet,作为packet在内部处理的入口(后面介绍这些处理);
d.ResultsListener根据XMPPIOService.call()返回的XMPPIOService对象,如果对象不为空重新放回到waiting列表(用于重新注册到clientsSel(selector));
2.2.组件对packet的处理过程
a.从XMPPIOService.call();
processSocketData(); if ((receivedPackets() > 0) && (serviceListener != null)) { /** *serviceListener 这里是clientConnectManager;在connectionOpenTrhead里 设置 **/ serviceListener.packetsReady(this); }
b.processSocketData()把报文转成xml element;再把element转成对应的packet;
while ((elem = elems.poll()) != null) { //Message、Presence、IQ、其他Packet Packet pack = Packet.packetInstance(elem); addReceivedPacket(pack); sendAck(pack);//ack 模式,收到后发送ack }
c.serviceListener.packetsReady()---->ClientConnectManager.packetsReady()---->processSocketData([此时设置了packet的to和from属性,在messagerouter中决定由那个组件处理])---->addOutPacket(packet)---->放到c2s的输出队列中;
d.c2s中的输出消息队列由QueueListener线程来读取处理;
if ((packet = filterPacket(packet, outgoing_filters)) != null) { //out_filter处理 processOutPacket(packet); }
if (parent != null) { //parent指message_router,在初始化的时候设置 parent.addPacket(packet);//传递给clientConnectManager,把packet构建完成后,交给messageRouter 来处理,添加到它的in_queue; } else { // It may happen for MessageRouter and this is intentional addPacketNB(packet); }
f.MessageRouter对in_queue里的packet,通过QueueListener线程调用messageRouter.processPacket()轮训。
//根据to属性,查找local的component,普通聊天,一般是路由到SessionManager组件 ServerComponent comp = getLocalComponent(packet.getTo()); if (comp != null) { if (log.isLoggable(Level.FINEST)) { log.log(Level.FINEST, "1. Packet will be processed by: {0}, {1}", new Object[] { comp.getComponentId(), packet }); } Queue<Packet> results = new ArrayDeque<Packet>(); if (comp == this) { processPacketMR(packet, results); } else { comp.processPacket(packet, results); } if (results.size() > 0) { for (Packet res : results) { addOutPacketNB(res); } } return; } String host = packet.getTo().getDomain(); ServerComponent[] comps = getComponentsForLocalDomain(host); if (comps == null) { comps = getServerComponentsForRegex(packet.getTo().getBareJID().toString()); } if ((comps == null) &&!isLocalDomain(host)) { comps = getComponentsForNonLocalDomain(host); } if (comps != null) { Queue<Packet> results = new ArrayDeque<Packet>(); for (ServerComponent serverComponent : comps) { if (log.isLoggable(Level.FINEST)) { log.log(Level.FINEST, "2. Packet will be processed by: {0}, {1}", new Object[] { serverComponent.getComponentId(), packet }); } serverComponent.processPacket(packet, results); if (results.size() > 0) { for (Packet res : results) { addOutPacketNB(res); } } } } else { if (log.isLoggable(Level.FINEST)) { log.finest("There is no component for the packet, sending it back"); } try { addOutPacketNB(Authorization.SERVICE_UNAVAILABLE.getResponseMessage(packet, "There is no service found to process your request.", true)); } catch (PacketErrorTypeException e) { log.warning("Can't process packet to local domain, dropping..." + packet .toStringSecure()); } }
3、SessionManager对packet的处理,如下图,就不多说了