Openfire S2S 连接建立与消息发送
原文地址:http://yjl49.iteye.com/blog/1452569
发送给其它服务器的消息由@domain 部分区分,在进入到服务器路由后在RoutingTableImpl.routePacket(Packet packet) 中与发送给本地服务器的消息分离。
- public void routePacket(JID jid,......){
- boolean routed = false;
- if(serverName.equals(jid.getDomain())){
- routed = routeToLocalDomain(jid,packet,fromServer);
- }
- else if(jid.getDomain().contains(serverName)){
- routed = routeToComponent(jid,packet,routed);
- }
- else{
- routed = routeToRemoteDomain(jid,packet,routed);
- }
- }
- ......
在初次发送消息给外部服务器时两台服务器的连接还没有建立,这种情况下会将包交由一个OutgoingSessionPromise 对象来处理,将消息加入它的队列。
- private boolean routeToRomoteDomain(JID jid,Packet packet,boolean routed){
- byte[] nodeID = serverCache.get(jid.getDomain);
- if(nodeID!=null){
- ......
- }
- else{
- OutgoingSessionPromise.getInstance().process(packet);
- routed = true;
- }
- return routed;
- }
在OutgoingSessionPromise 中保有一个线程池和一个独立线程。
独立线程不断从消息队列中读取要处理的packet,并针对每个domain建立一个PacketsProcessor线程,将消息交给这个线程,然后把此线程放入线程池中运行。
- final Packet packet = packets.take();
- boolean newProcessor = false;
- PacketsProcessor packetsProcessor;
- String domain = packet.getTo().getDomain();
- synchronized (domain.intern()){
- packetsProcessor = packetsProcessors.get(domain);
- if(packetsProcessor == null){
- packetsProcessor = new PacketsProcessor(OutgoingSessionPromise.this,domain);
- packetsProcessors.put(domain,packetsProcessor);
- newProcessor = true;
- }
- packetsProcessor.addPacket(packet);
- }
- if(newProcessor){
- threadPool.execute(packetsProcessor);
- }
PacketsProcessor在发送消息包时会判断到外部服务器的连接是否已经建立。未建立的情况下会调用LocalOutgoingDServerSession.authenticateDomain() 方法建立连接。
具体的Socket连接建立是在authenticateDomain() 方法中经过一系列的验证和鉴权后调用createOutgoingSession(domain,hostname,port)来完成。
建立好连接后则重新调用routingTable.routePacket() 再进行一次路由。
------------------------------------------------------注意----------------------------------------------------
Openfire 中S2S 之间的链接有TLS 和 Dialback 两种加密验证方式。
如果使用TLS 方式则需要双方都有可信任的根证书,否则会出现General SSLEngine problem 异常。
Dialback则提供一种弱身份验证的方式,要使用这种方式可以将Openfire数据库中ofproperty 表中“xmpp.server.tls.enabled” 设置为false,并将“xmpp.server.dialback.enabled”设置为true。
另:Openfire 3.7.0 中的Dialback 方式有bug 会导致连接失败,已经在3.7.1中进行了修复。具体需要参照3.7.1中的代码修改LocalIncomingServerSession.java 和ServerDialback.java 两个文件。