Commit 8c9d8d79 authored by Gaston Dombiak's avatar Gaston Dombiak Committed by gato

server-2-server is now clusterable.

git-svn-id: http://svn.igniterealtime.org/svn/repos/openfire/trunk@8417 b35dd754-fafc-0310-a699-88a17e54d16e
parent 092b00b3
......@@ -17,12 +17,14 @@ import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.session.LocalOutgoingServerSession;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.lock.LockManager;
import org.xmpp.packet.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.*;
import java.util.concurrent.locks.Lock;
/**
* An OutgoingSessionPromise provides an asynchronic way for sending packets to remote servers.
......@@ -195,8 +197,16 @@ public class OutgoingSessionPromise implements RoutableChannelHandler {
private void sendPacket(Packet packet) throws Exception {
// Create a connection to the remote server from the domain where the packet has been sent
boolean created = LocalOutgoingServerSession
.authenticateDomain(packet.getFrom().getDomain(), packet.getTo().getDomain());
boolean created;
// Make sure that only one cluster node is creating the outgoing connection
Lock lock = LockManager.getLock(domain + "oss");
try {
lock.lock();
created = LocalOutgoingServerSession
.authenticateDomain(packet.getFrom().getDomain(), packet.getTo().getDomain());
} finally {
lock.unlock();
}
if (created) {
// A connection to the remote server was created so get the route and send the packet
routingTable.routePacket(packet.getTo(), packet);
......
......@@ -27,6 +27,9 @@ import org.jivesoftware.openfire.spi.BasicStreamIDFactory;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.StringUtils;
import org.jivesoftware.util.cache.Cache;
import org.jivesoftware.util.cache.CacheFactory;
import org.jivesoftware.util.lock.LockManager;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
......@@ -37,6 +40,7 @@ import java.io.*;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
/**
* Implementation of the Server Dialback method as defined by the RFC3920.
......@@ -65,9 +69,11 @@ public class ServerDialback {
*/
protected static String CHARSET = "UTF-8";
/**
* Secret key to be used for encoding and decoding keys used for authentication.
* Cache (unlimited, never expire) that holds the secret key to be used for
* encoding and decoding keys used for authentication.
* Key: constant hard coded value, Value: random generated string
*/
private static final String secretKey = StringUtils.randomString(10);
private static Cache<String, String> secretKeyCache;
private static XmlPullParserFactory FACTORY = null;
......@@ -78,6 +84,7 @@ public class ServerDialback {
catch (XmlPullParserException e) {
Log.error("Error creating a parser factory", e);
}
secretKeyCache = CacheFactory.createCache("Secret Keys Cache");
}
private Connection connection;
......@@ -245,7 +252,7 @@ public class ServerDialback {
*/
public boolean authenticateDomain(OutgoingServerSocketReader socketReader, String domain,
String hostname, String id) {
String key = AuthFactory.createDigest(id, secretKey);
String key = AuthFactory.createDigest(id, getSecretkey());
Log.debug("OS - Sent dialback key to host: " + hostname + " id: " + id + " from domain: " +
domain);
......@@ -655,7 +662,7 @@ public class ServerDialback {
// Verify the received key
// Created the expected key based on the received ID value and the shared secret
String expectedKey = AuthFactory.createDigest(id, secretKey);
String expectedKey = AuthFactory.createDigest(id, getSecretkey());
boolean verified = expectedKey.equals(key);
// Send the result of the key verification
......@@ -673,5 +680,28 @@ public class ServerDialback {
id);
return verified;
}
/**
* Returns the secret key that was randomly generated. When running inside of a cluster
* the key will be unique to all cluster nodes.
*
* @return the secret key that was randomly generated.
*/
private static String getSecretkey() {
String key = "secretKey";
Lock lock = LockManager.getLock(key);
try {
lock.lock();
String secret = secretKeyCache.get(key);
if (secret == null) {
secret = StringUtils.randomString(10);
secretKeyCache.put(key, secret);
}
return secret;
}
finally {
lock.unlock();
}
}
}
......@@ -73,6 +73,7 @@ public class DefaultLocalCacheStrategy implements CacheFactoryStrategy {
cacheNames.put("Connection Managers Sessions", "connManagerSessions");
cacheNames.put("Incoming Server Sessions", "incServerSessions");
cacheNames.put("Sessions by Hostname", "sessionsHostname");
cacheNames.put("Secret Keys Cache", "secretKeys");
cacheProps.put("cache.fileTransfer.size", 128 * 1024l);
cacheProps.put("cache.fileTransfer.expirationTime", 1000 * 60 * 10l);
......@@ -122,6 +123,8 @@ public class DefaultLocalCacheStrategy implements CacheFactoryStrategy {
cacheProps.put("cache.incServerSessions.expirationTime", -1l);
cacheProps.put("cache.sessionsHostname.size", -1l);
cacheProps.put("cache.sessionsHostname.expirationTime", -1l);
cacheProps.put("cache.secretKeys.size", -1l);
cacheProps.put("cache.secretKeys.expirationTime", -1l);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment