diff --git a/ConnectionManager.iml b/ConnectionManager.iml
index 90f2de7..95c0b9b 100644
--- a/ConnectionManager.iml
+++ b/ConnectionManager.iml
@@ -8,6 +8,7 @@
+
@@ -45,7 +46,9 @@
-
+
+
+
@@ -54,7 +57,11 @@
-
+
+
+
+
+
@@ -102,6 +109,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/build/lib/merge/xpp3.jar b/build/lib/merge/xpp3.jar
index c9822e6..451ac82 100644
--- a/build/lib/merge/xpp3.jar
+++ b/build/lib/merge/xpp3.jar
Binary files differ
diff --git a/build/lib/versions.txt b/build/lib/versions.txt
index da0365f..f5f9027 100644
--- a/build/lib/versions.txt
+++ b/build/lib/versions.txt
@@ -15,4 +15,4 @@
pack200task.jar | August 5, 2004
servlet-api.jar | 2.5-6.0.1
xmltask.jar | 1.11
-xpp3.jar | XPP_3 1.1.3.8
\ No newline at end of file
+xpp3.jar | XPP_3 1.1.4c
\ No newline at end of file
diff --git a/src/conf/manager.xml b/src/conf/manager.xml
index 1849d54..5c7c397 100644
--- a/src/conf/manager.xml
+++ b/src/conf/manager.xml
@@ -25,7 +25,7 @@
This property is optional. A random name is generated if none was defined. -->
- 5
+ 1
5
@@ -73,7 +73,34 @@
+
+
+ 50
+
+
+ -1
+
+ -1
+
+
+ -1
+
+
+
+
+
+
+
+
false
diff --git a/src/java/org/dom4j/io/XMPPPacketReader.java b/src/java/org/dom4j/io/XMPPPacketReader.java
index d0b3d79..31e381f 100644
--- a/src/java/org/dom4j/io/XMPPPacketReader.java
+++ b/src/java/org/dom4j/io/XMPPPacketReader.java
@@ -273,23 +273,6 @@
return lastActive > lastHeartbeat ? lastActive : lastHeartbeat;
}
- /*
- * DANIELE: Add parse document by string
- */
- public Document parseDocument(String xml) throws DocumentException {
- /*
- // Long way with reuse of DocumentFactory.
- DocumentFactory df = getDocumentFactory();
- SAXReader reader = new SAXReader( df );
- Document document = reader.read( new StringReader( xml );*/
-
- // Simple way
- // TODO Optimize. Do not create a sax reader for each parsing
- Document document = DocumentHelper.parseText(xml);
-
- return document;
- }
-
// Implementation methods
//-------------------------------------------------------------------------
public Document parseDocument() throws DocumentException, IOException, XmlPullParserException {
diff --git a/src/java/org/jivesoftware/multiplexer/ClientSession.java b/src/java/org/jivesoftware/multiplexer/ClientSession.java
index 9c6221b..15f6bf6 100644
--- a/src/java/org/jivesoftware/multiplexer/ClientSession.java
+++ b/src/java/org/jivesoftware/multiplexer/ClientSession.java
@@ -12,13 +12,9 @@
package org.jivesoftware.multiplexer;
import org.dom4j.Element;
-import org.dom4j.io.XMPPPacketReader;
-import org.jivesoftware.multiplexer.net.SocketConnection;
-import org.jivesoftware.multiplexer.net.SocketReader;
import org.jivesoftware.multiplexer.spi.ClientFailoverDeliverer;
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.util.Log;
-import org.jivesoftware.util.JiveGlobals;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -32,30 +28,8 @@
private static final String ETHERX_NAMESPACE = "http://etherx.jabber.org/streams";
private static final String FLASH_NAMESPACE = "http://www.jabber.com/streams/flash";
- /**
- * Milliseconds a connection has to be idle to be closed. Default is 30 minutes. Sending
- * stanzas to the client is not considered as activity. We are only considering the connection
- * active when the client sends some data or hearbeats (i.e. whitespaces) to the server.
- * The reason for this is that sending data will fail if the connection is closed. And if
- * the thread is blocked while sending data (because the socket is closed) then the clean up
- * thread will close the socket anyway.
- */
- private static long idleTimeout;
-
- /**
- * Socket reader that is processing incoming packets from the client.
- */
- private SocketReader socketReader;
-
- static {
- // Set the default read idle timeout. If none was set then assume 30 minutes
- idleTimeout = JiveGlobals.getIntProperty("xmpp.client.idle", 30 * 60 * 1000);
- }
-
- public static Session createSession(String serverName, SocketReader socketReader,
- XMPPPacketReader reader, SocketConnection connection)
+ public static Session createSession(String serverName, XmlPullParser xpp, Connection connection)
throws XmlPullParserException {
- XmlPullParser xpp = reader.getXPPParser();
boolean isFlashClient = xpp.getPrefix().equals("flash");
connection.setFlashClient(isFlashClient);
@@ -125,17 +99,20 @@
// Indicate the compression policy to use for this connection
connection.setCompressionPolicy(serverSurrogate.getCompressionPolicy());
- // Set the max number of milliseconds the connection may not receive data from the
- // client before closing the connection
- connection.setIdleTimeout(idleTimeout);
-
// Create a ClientSession for this user.
String streamID = idFactory.createStreamID();
ClientSession session = new ClientSession(serverName, connection, streamID);
connection.init(session);
- session.socketReader = socketReader;
// Set the stream ID that identifies the client when forwarding traffic to a client fails
((ClientFailoverDeliverer) connection.getPacketDeliverer()).setStreamID(streamID);
+ // Listen when the connection is closed
+ connection.registerCloseListener(new ConnectionCloseListener() {
+ public void onConnectionClose(Object handback) {
+ ClientSession session = (ClientSession) handback;
+ // Mark the session as closed
+ session.close(false);
+ }
+ }, session);
// Register that the new session is associated with the specified stream ID
Session.addSession(streamID, session);
// Send to the server that a new client session has been created
@@ -207,13 +184,13 @@
}
StringBuilder sb = new StringBuilder(200);
-
+ // TODO Fix compression with MINA and re-enable this code
// Include Stream Compression Mechanism
- if (conn.getCompressionPolicy() != Connection.CompressionPolicy.disabled &&
+ /*if (conn.getCompressionPolicy() != Connection.CompressionPolicy.disabled &&
!conn.isCompressed()) {
sb.append(
"zlib");
- }
+ }*/
if (getStatus() != Session.STATUS_AUTHENTICATED) {
ServerSurrogate serverSurrogate = ConnectionManager.getInstance().getServerSurrogate();
@@ -247,16 +224,14 @@
if ("success".equals(tag)) {
// Session has been authenticated (using SASL). Update status
setStatus(Session.STATUS_AUTHENTICATED);
- // Notify the socket reader that sasl authentication has finished
- socketReader.clientAuthenticated(true);
}
else if ("failure".equals(tag)) {
- // Notify the socket reader that sasl authentication has finished
- socketReader.clientAuthenticated(false);
+ // Sasl authentication has failed
+ // Ignore for now
}
else if ("challenge".equals(tag)) {
- // Notify the socket reader that client needs to respond to challenge
- socketReader.clientChallenged();
+ // A challenge was sent to the client. Client needs to respond
+ // Ignore for now
}
}
// Deliver stanza to client
@@ -284,6 +259,8 @@
*/
public void close(boolean systemStopped) {
if (status != STATUS_CLOSED) {
+ // Change the status to closed
+ status = STATUS_CLOSED;
// Close the connection of the client
if (systemStopped) {
conn.systemShutdown();
@@ -291,8 +268,6 @@
else {
conn.close();
}
- // Changhe the status to closed
- status = STATUS_CLOSED;
// Remove session from list of sessions
removeSession(getStreamID());
// Tell the server that the client session has been closed
diff --git a/src/java/org/jivesoftware/multiplexer/Connection.java b/src/java/org/jivesoftware/multiplexer/Connection.java
index 6fbface..a5aa158 100644
--- a/src/java/org/jivesoftware/multiplexer/Connection.java
+++ b/src/java/org/jivesoftware/multiplexer/Connection.java
@@ -32,9 +32,25 @@
public boolean validate();
/**
+ * Registers a new listener that will react when this connection is closed.
+ *
+ * @param listener the new listener.
+ * @param handbackMessage the object to send back when notifying that the connection was closed.
+ */
+ public void registerCloseListener(ConnectionCloseListener listener, Object handbackMessage);
+
+ /**
+ * Removes a listener that was reacting when this connection was closed.
+ *
+ * @param listener the listener to remove.
+ */
+ public void removeCloseListener(ConnectionCloseListener listener);
+
+ /**
* Returns the InetAddress describing the connection.
*
* @return the InetAddress describing the underlying connection properties.
+ * @throws java.net.UnknownHostException if IP address of host could not be determined.
*/
public InetAddress getInetAddress() throws UnknownHostException;
@@ -102,6 +118,16 @@
public boolean isFlashClient();
/**
+ * Sets whether the connected client is a flash client. Flash clients need to
+ * receive a special character (i.e. \0) at the end of each xml packet. Flash
+ * clients may send the character \0 in incoming packets and may start a
+ * connection using another openning tag such as: "flash:client".
+ *
+ * @param flashClient true if the if the connection is a flash client.
+ */
+ public void setFlashClient(boolean flashClient);
+
+ /**
* Returns the major version of XMPP being used by this connection
* (major_version.minor_version. In most cases, the version should be
* "1.0". However, older clients using the "Jabber" protocol do not set a
@@ -122,6 +148,16 @@
public int getMinorXMPPVersion();
/**
+ * Sets the XMPP version information. In most cases, the version should be "1.0".
+ * However, older clients using the "Jabber" protocol do not set a version. In that
+ * case, the version is "0.0".
+ *
+ * @param majorVersion the major version.
+ * @param minorVersion the minor version.
+ */
+ public void setXMPPVersion(int majorVersion, int minorVersion);
+
+ /**
* Returns the language code that should be used for this connection
* (e.g. "en").
*
@@ -130,6 +166,13 @@
public String getLanguage();
/**
+ * Sets the language code that should be used for this connection (e.g. "en").
+ *
+ * @param language the language code.
+ */
+ public void setLanaguage(String language);
+
+ /**
* Returns true if the connection is using compression.
*
* @return true if the connection is using compression.
@@ -144,6 +187,13 @@
CompressionPolicy getCompressionPolicy();
/**
+ * Sets whether compression is enabled or is disabled.
+ *
+ * @param compressionPolicy whether Compression is enabled or is disabled.
+ */
+ void setCompressionPolicy(CompressionPolicy compressionPolicy);
+
+ /**
* Returns whether TLS is mandatory, optional or is disabled. When TLS is mandatory clients
* are required to secure their connections or otherwise their connections will be closed.
* On the other hand, when TLS is disabled clients are not allowed to secure their connections
@@ -155,6 +205,54 @@
TLSPolicy getTlsPolicy();
/**
+ * Sets whether TLS is mandatory, optional or is disabled. When TLS is mandatory clients
+ * are required to secure their connections or otherwise their connections will be closed.
+ * On the other hand, when TLS is disabled clients are not allowed to secure their connections
+ * using TLS. Their connections will be closed if they try to secure the connection. in this
+ * last case.
+ *
+ * @param tlsPolicy whether TLS is mandatory, optional or is disabled.
+ */
+ void setTlsPolicy(TLSPolicy tlsPolicy);
+
+ /**
+ * Returns the packet deliverer to use when delivering a packet over the socket fails. The
+ * packet deliverer will retry to send the packet using some other connection, will store
+ * the packet offline for later retrieval or will just drop it.
+ *
+ * @return the packet deliverer to use when delivering a packet over the socket fails.
+ */
+ PacketDeliverer getPacketDeliverer();
+
+ /**
+ * Secures the plain connection by negotiating TLS with the client. When connecting
+ * to a remote server then clientMode will be true
and
+ * remoteServer is the server name of the remote server. Otherwise clientMode
+ * will be false
and remoteServer null.
+ *
+ * @param clientMode boolean indicating if this entity is a client or a server.
+ * @param remoteServer server name of the remote server we are connecting to or null
+ * when not in client mode.
+ * @throws Exception if an error occured while securing the connection.
+ */
+ void startTLS(boolean clientMode, String remoteServer) throws Exception;
+
+ /**
+ * Start using compression for this connection. Compression will only be available after TLS
+ * has been negotiated. This means that a connection can never be using compression before
+ * TLS. However, it is possible to use compression without TLS.
+ */
+ void startCompression();
+
+ /**
+ * Initializes the connection that is related to the specified session. The session is the
+ * only owner of this connection.
+ *
+ * @param session the Session that owns this connection.
+ */
+ void init(Session session);
+
+ /**
* Enumeration of possible compression policies required to interact with the server.
*/
enum CompressionPolicy {
diff --git a/src/java/org/jivesoftware/multiplexer/ConnectionManager.java b/src/java/org/jivesoftware/multiplexer/ConnectionManager.java
index 93eee10..1c7ccf7 100644
--- a/src/java/org/jivesoftware/multiplexer/ConnectionManager.java
+++ b/src/java/org/jivesoftware/multiplexer/ConnectionManager.java
@@ -11,24 +11,39 @@
package org.jivesoftware.multiplexer;
+import org.apache.mina.common.ExecutorThreadModel;
+import org.apache.mina.filter.SSLFilter;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+import org.apache.mina.transport.socket.nio.SocketAcceptor;
+import org.apache.mina.transport.socket.nio.SocketAcceptorConfig;
+import org.apache.mina.transport.socket.nio.SocketSessionConfig;
import org.dom4j.Document;
import org.dom4j.io.SAXReader;
-import org.jivesoftware.multiplexer.net.SSLSocketAcceptThread;
-import org.jivesoftware.multiplexer.net.SocketAcceptThread;
+import org.jivesoftware.multiplexer.net.ClientConnectionHandler;
+import org.jivesoftware.multiplexer.net.SSLConfig;
import org.jivesoftware.multiplexer.net.SocketSendingTracker;
+import org.jivesoftware.multiplexer.net.XMPPCodecFactory;
import org.jivesoftware.multiplexer.net.http.HttpBindManager;
import org.jivesoftware.util.*;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManagerFactory;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.InetAddress;
+import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
+import java.util.concurrent.Executor;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
/**
* Connection managers handle connections of clients that want to connect to a server. Each
@@ -101,8 +116,8 @@
"org.tanukisoftware.wrapper.WrapperManager";
private ServerSurrogate serverSurrogate;
- private SocketAcceptThread socketThread;
- private SSLSocketAcceptThread sslSocketThread;
+ private SocketAcceptor socketAcceptor;
+ private SocketAcceptor sslSocketAcceptor;
private HttpBindManager httpBindManager;
/**
@@ -255,6 +270,8 @@
}
private void startClientListeners(String localIPAddress) {
+ // TODO Does MINA uses MAX_PRIORITY for threads?
+ // TODO Are threads running as daemon? Can we stop de server?
// Start clients plain socket unless it's been disabled.
int port = 5222;
// Check if old property is being used for storing c2s port
@@ -265,16 +282,32 @@
else if (JiveGlobals.getXMLProperty("xmpp.socket.default.port") != null) {
port = JiveGlobals.getIntProperty("xmpp.socket.default.port", 5222);
}
- ServerPort serverPort = new ServerPort(port, serverName, localIPAddress,
- false, null, ServerPort.Type.client);
+ // Create SocketAcceptor with correct number of processors
+ socketAcceptor = buildSocketAcceptor();
+ // Customize Executor that will be used by processors to process incoming stanzas
+ ExecutorThreadModel threadModel = ExecutorThreadModel.getInstance("client");
+ int eventThreads = JiveGlobals.getIntProperty("xmpp.processor.threads.standard", 16);
+ Executor eventExecutor = new ThreadPoolExecutor(
+ eventThreads + 1, eventThreads + 1, 60, TimeUnit.SECONDS, new LinkedBlockingQueue() );
+ threadModel.setExecutor(eventExecutor);
+ socketAcceptor.getDefaultConfig().setThreadModel(threadModel);
+ // Add the XMPP codec filter
+ socketAcceptor.getFilterChain().addFirst("xmpp", new ProtocolCodecFilter(new XMPPCodecFactory()));
+
try {
- socketThread = new SocketAcceptThread(serverPort);
- //socketThread.setDaemon(true);
- socketThread.setPriority(Thread.MAX_PRIORITY);
- socketThread.start();
+ // Listen on a specific network interface if it has been set.
+ String interfaceName = JiveGlobals.getXMLProperty("xmpp.socket.network.interface");
+ InetAddress bindInterface = null;
+ if (interfaceName != null) {
+ if (interfaceName.trim().length() > 0) {
+ bindInterface = InetAddress.getByName(interfaceName);
+ }
+ }
+ // Start accepting connections
+ socketAcceptor.bind(new InetSocketAddress(bindInterface, port), new ClientConnectionHandler());
List params = new ArrayList();
- params.add(Integer.toString(socketThread.getPort()));
+ params.add(Integer.toString(port));
Log.info(LocaleUtils.getLocalizedString("startup.plain", params));
}
catch (Exception e) {
@@ -285,9 +318,9 @@
}
private void stopClientListeners() {
- if (socketThread != null) {
- socketThread.shutdown();
- socketThread = null;
+ if (socketAcceptor != null) {
+ socketAcceptor.unbindAll();
+ socketAcceptor = null;
}
}
@@ -298,16 +331,45 @@
if ("".equals(algorithm) || algorithm == null) {
algorithm = "TLS";
}
- ServerPort serverPort = new ServerPort(port, serverName, localIPAddress,
- true, algorithm, ServerPort.Type.client);
+ // Create SocketAcceptor with correct number of processors
+ sslSocketAcceptor = buildSocketAcceptor();
+ // Customize thread model for c2s (old ssl port)
+ ExecutorThreadModel threadModel = ExecutorThreadModel.getInstance("client_ssl");
+ int eventThreads = JiveGlobals.getIntProperty("xmpp.processor.threads.ssl", 16);
+ Executor eventExecutor = new ThreadPoolExecutor(
+ eventThreads + 1, eventThreads + 1, 60, TimeUnit.SECONDS, new LinkedBlockingQueue() );
+ threadModel.setExecutor(eventExecutor);
+ sslSocketAcceptor.getDefaultConfig().setThreadModel(threadModel);
+ // Add the XMPP codec filter
+ sslSocketAcceptor.getFilterChain().addFirst("xmpp", new ProtocolCodecFilter(new XMPPCodecFactory()));
+
try {
- sslSocketThread = new SSLSocketAcceptThread(serverPort);
- //sslSocketThread.setDaemon(true);
- sslSocketThread.setPriority(Thread.MAX_PRIORITY);
- sslSocketThread.start();
+ // Add the SSL filter now since sockets are "borned" encrypted in the old ssl method
+ SSLContext sslContext = SSLContext.getInstance(algorithm);
+ KeyManagerFactory keyFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+ keyFactory.init(SSLConfig.getKeyStore(), SSLConfig.getKeyPassword().toCharArray());
+ TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ trustFactory.init(SSLConfig.getTrustStore());
+
+ sslContext.init(keyFactory.getKeyManagers(),
+ trustFactory.getTrustManagers(),
+ new java.security.SecureRandom());
+
+ sslSocketAcceptor.getFilterChain().addFirst("tls", new SSLFilter(sslContext));
+
+ // Listen on a specific network interface if it has been set.
+ String interfaceName = JiveGlobals.getXMLProperty("xmpp.socket.network.interface");
+ InetAddress bindInterface = null;
+ if (interfaceName != null) {
+ if (interfaceName.trim().length() > 0) {
+ bindInterface = InetAddress.getByName(interfaceName);
+ }
+ }
+ // Start accepting connections
+ sslSocketAcceptor.bind(new InetSocketAddress(bindInterface, port), new ClientConnectionHandler());
List params = new ArrayList();
- params.add(Integer.toString(sslSocketThread.getPort()));
+ params.add(Integer.toString(port));
Log.info(LocaleUtils.getLocalizedString("startup.ssl", params));
}
catch (Exception e) {
@@ -318,9 +380,9 @@
}
private void stopClientSSLListeners() {
- if (sslSocketThread != null) {
- sslSocketThread.shutdown();
- sslSocketThread = null;
+ if (sslSocketAcceptor != null) {
+ sslSocketAcceptor.unbindAll();
+ sslSocketAcceptor = null;
}
}
@@ -488,6 +550,41 @@
return name;
}
+ private SocketAcceptor buildSocketAcceptor() {
+ SocketAcceptor socketAcceptor;
+ // Create SocketAcceptor with correct number of processors
+ int ioThreads = JiveGlobals.getIntProperty("xmpp.processor.count", Runtime.getRuntime().availableProcessors());
+ // Set the executor that processors will use. Note that processors will use another executor
+ // for processing events (i.e. incoming traffic)
+ Executor ioExecutor = new ThreadPoolExecutor(
+ ioThreads + 1, ioThreads + 1, 60, TimeUnit.SECONDS, new LinkedBlockingQueue() );
+ socketAcceptor = new SocketAcceptor(ioThreads, ioExecutor);
+ // Set that it will be possible to bind a socket if there is a connection in the timeout state
+ SocketAcceptorConfig socketAcceptorConfig = (SocketAcceptorConfig) socketAcceptor.getDefaultConfig();
+ socketAcceptorConfig.setReuseAddress(true);
+ // Set the listen backlog (queue) length. Default is 50.
+ socketAcceptorConfig.setBacklog(JiveGlobals.getIntProperty("xmpp.socket.backlog", 50));
+
+ // Set default (low level) settings for new socket connections
+ SocketSessionConfig socketSessionConfig = socketAcceptorConfig.getSessionConfig();
+ //socketSessionConfig.setKeepAlive();
+ int receiveBuffer = JiveGlobals.getIntProperty("xmpp.socket.buffer.receive", -1);
+ if (receiveBuffer > 0 ) {
+ socketSessionConfig.setReceiveBufferSize(receiveBuffer);
+ }
+ int sendBuffer = JiveGlobals.getIntProperty("xmpp.socket.buffer.send", -1);
+ if (sendBuffer > 0 ) {
+ socketSessionConfig.setSendBufferSize(sendBuffer);
+ }
+ int linger = JiveGlobals.getIntProperty("xmpp.socket.linger", -1);
+ if (linger > 0 ) {
+ socketSessionConfig.setSoLinger(linger);
+ }
+ socketSessionConfig.setTcpNoDelay(
+ JiveGlobals.getBooleanProperty("xmpp.socket.tcp-nodelay", socketSessionConfig.isTcpNoDelay()));
+ return socketAcceptor;
+ }
+
/**
* Verifies that the given home guess is a real Connection Manager home directory.
* We do the verification by checking for the Connection Manager config file in
diff --git a/src/java/org/jivesoftware/multiplexer/ConnectionWorkerThread.java b/src/java/org/jivesoftware/multiplexer/ConnectionWorkerThread.java
index 54470a1..0e2fbea 100644
--- a/src/java/org/jivesoftware/multiplexer/ConnectionWorkerThread.java
+++ b/src/java/org/jivesoftware/multiplexer/ConnectionWorkerThread.java
@@ -18,7 +18,6 @@
import org.dom4j.io.XMPPPacketReader;
import org.jivesoftware.multiplexer.net.DNSUtil;
import org.jivesoftware.multiplexer.net.MXParser;
-import org.jivesoftware.multiplexer.net.SocketAcceptThread;
import org.jivesoftware.multiplexer.net.SocketConnection;
import org.jivesoftware.multiplexer.spi.ServerFailoverDeliverer;
import org.jivesoftware.util.JiveGlobals;
@@ -50,6 +49,10 @@
* The utf-8 charset for decoding and encoding Jabber packet streams.
*/
private static String CHARSET = "UTF-8";
+ /**
+ * The default XMPP port for connection multiplex.
+ */
+ public static final int DEFAULT_MULTIPLEX_PORT = 5262;
private static DocumentFactory docFactory = DocumentFactory.getInstance();
// Sequence and random number generator used for creating unique IQ ID's.
@@ -121,7 +124,7 @@
private boolean createConnection() {
String realHostname = null;
int port =
- JiveGlobals.getIntProperty("xmpp.port", SocketAcceptThread.DEFAULT_MULTIPLEX_PORT);
+ JiveGlobals.getIntProperty("xmpp.port", DEFAULT_MULTIPLEX_PORT);
Socket socket = new Socket();
try {
// Get the real hostname to connect to using DNS lookup of the specified hostname
@@ -189,20 +192,6 @@
return false;
}
}
- /*if (features != null && features.element("mechanisms") != null) {
- // Try to authenticate with the server using SASL authentication
- // TODO Compression should be done before SASL
- if (!doSASLAuthentication(reader, openingStream)) {
- // Failed to authenticate with the server
- connection = null;
- return false;
- }
- }
- else {
- // Server didn't offer SASL authentication
- connection = null;
- return false;
- }*/
if (features != null && features.element("compression") != null) {
// Try to use stream compression since the server supports it
if (!compressConnection(reader, openingStream)) {
diff --git a/src/java/org/jivesoftware/multiplexer/net/ServerTrustManager.java b/src/java/org/jivesoftware/multiplexer/net/ServerTrustManager.java
index fa757ec..b386f86 100644
--- a/src/java/org/jivesoftware/multiplexer/net/ServerTrustManager.java
+++ b/src/java/org/jivesoftware/multiplexer/net/ServerTrustManager.java
@@ -7,6 +7,7 @@
package org.jivesoftware.multiplexer.net;
+import org.jivesoftware.util.CertificateManager;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.Log;
@@ -80,7 +81,7 @@
if (verify) {
int nSize = x509Certificates.length;
- List peerIdentities = TLSStreamHandler.getPeerIdentities(x509Certificates[0]);
+ List peerIdentities = CertificateManager.getPeerIdentities(x509Certificates[0]);
if (JiveGlobals.getBooleanProperty("xmpp.server.certificate.verify.chain", true)) {
// Working down the chain, for every certificate in the chain,
diff --git a/src/java/org/jivesoftware/multiplexer/net/SocketConnection.java b/src/java/org/jivesoftware/multiplexer/net/SocketConnection.java
index 189dafb..043d31d 100644
--- a/src/java/org/jivesoftware/multiplexer/net/SocketConnection.java
+++ b/src/java/org/jivesoftware/multiplexer/net/SocketConnection.java
@@ -29,8 +29,8 @@
import java.nio.channels.Channels;
import java.util.Collection;
import java.util.Date;
-import java.util.Map;
import java.util.HashMap;
+import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -145,17 +145,6 @@
return tlsStreamHandler;
}
- /**
- * Secures the plain connection by negotiating TLS with the client. When connecting
- * to a remote server then clientMode will be true
and
- * remoteServer is the server name of the remote server. Otherwise clientMode
- * will be false
and remoteServer null.
- *
- * @param clientMode boolean indicating if this entity is a client or a server.
- * @param remoteServer server name of the remote server we are connecting to or null
- * when not in client mode.
- * @throws IOException if an error occured while securing the connection.
- */
public void startTLS(boolean clientMode, String remoteServer) throws IOException {
if (!secure) {
secure = true;
@@ -173,27 +162,26 @@
}
}
- /**
- * Start using compression for this connection. Compression will only be available after TLS
- * has been negotiated. This means that a connection can never be using compression before
- * TLS. However, it is possible to use compression without TLS.
- *
- * @throws IOException if an error occured while starting compression.
- */
- public void startCompression() throws IOException {
+ public void startCompression() {
compressed = true;
- if (tlsStreamHandler == null) {
- ZOutputStream out = new ZOutputStream(socket.getOutputStream(), JZlib.Z_BEST_COMPRESSION);
- out.setFlushMode(JZlib.Z_PARTIAL_FLUSH);
- writer = new BufferedWriter(new OutputStreamWriter(out, CHARSET));
- xmlSerializer = new XMLSocketWriter(writer, this);
- }
- else {
- ZOutputStream out = new ZOutputStream(tlsStreamHandler.getOutputStream(), JZlib.Z_BEST_COMPRESSION);
- out.setFlushMode(JZlib.Z_PARTIAL_FLUSH);
- writer = new BufferedWriter(new OutputStreamWriter(out, CHARSET));
- xmlSerializer = new XMLSocketWriter(writer, this);
+ try {
+ if (tlsStreamHandler == null) {
+ ZOutputStream out = new ZOutputStream(socket.getOutputStream(), JZlib.Z_BEST_COMPRESSION);
+ out.setFlushMode(JZlib.Z_PARTIAL_FLUSH);
+ writer = new BufferedWriter(new OutputStreamWriter(out, CHARSET));
+ xmlSerializer = new XMLSocketWriter(writer, this);
+ }
+ else {
+ ZOutputStream out = new ZOutputStream(tlsStreamHandler.getOutputStream(), JZlib.Z_BEST_COMPRESSION);
+ out.setFlushMode(JZlib.Z_PARTIAL_FLUSH);
+ writer = new BufferedWriter(new OutputStreamWriter(out, CHARSET));
+ xmlSerializer = new XMLSocketWriter(writer, this);
+ }
+ } catch (IOException e) {
+ // TODO Would be nice to still be able to throw the exception and not catch it here
+ Log.error("Error while starting compression", e);
+ compressed = false;
}
}
@@ -228,19 +216,17 @@
session = owner;
}
- public Object registerCloseListener(ConnectionCloseListener listener, Object handbackMessage) {
- Object status = null;
+ public void registerCloseListener(ConnectionCloseListener listener, Object handbackMessage) {
if (isClosed()) {
listener.onConnectionClose(handbackMessage);
}
else {
- status = listeners.put(listener, handbackMessage);
+ listeners.put(listener, handbackMessage);
}
- return status;
}
- public Object removeCloseListener(ConnectionCloseListener listener) {
- return listeners.remove(listener);
+ public void removeCloseListener(ConnectionCloseListener listener) {
+ listeners.remove(listener);
}
public InetAddress getInetAddress() {
@@ -374,13 +360,6 @@
return null;
}
- /**
- * Returns the packet deliverer to use when delivering a packet over the socket fails. The
- * packet deliverer will retry to send the packet using some other connection, will store
- * the packet offline for later retrieval or will just drop it.
- *
- * @return the packet deliverer to use when delivering a packet over the socket fails.
- */
public PacketDeliverer getPacketDeliverer() {
return backupDeliverer;
}