/**
* $RCSfile: ConnectionManagerImpl.java,v $
* $Revision: $
* $Date: $
*
* Copyright (C) 2005-2008 Jive Software. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.openfire.spi;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import org.apache.mina.common.ByteBuffer;
import org.apache.mina.common.ExecutorThreadModel;
import org.apache.mina.common.SimpleByteBufferAllocator;
import org.apache.mina.common.ThreadModel;
import org.apache.mina.filter.SSLFilter;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.executor.ExecutorFilter;
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.jivesoftware.openfire.ConnectionManager;
import org.jivesoftware.openfire.PacketDeliverer;
import org.jivesoftware.openfire.PacketRouter;
import org.jivesoftware.openfire.RoutingTable;
import org.jivesoftware.openfire.ServerPort;
import org.jivesoftware.openfire.SessionManager;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.container.BasicModule;
import org.jivesoftware.openfire.container.PluginManager;
import org.jivesoftware.openfire.container.PluginManagerListener;
import org.jivesoftware.openfire.http.HttpBindManager;
import org.jivesoftware.openfire.net.SSLConfig;
import org.jivesoftware.openfire.net.ServerSocketReader;
import org.jivesoftware.openfire.net.SocketAcceptThread;
import org.jivesoftware.openfire.net.SocketConnection;
import org.jivesoftware.openfire.net.SocketReader;
import org.jivesoftware.openfire.net.SocketSendingTracker;
import org.jivesoftware.openfire.net.StalledSessionsFilter;
import org.jivesoftware.openfire.nio.ClientConnectionHandler;
import org.jivesoftware.openfire.nio.ComponentConnectionHandler;
import org.jivesoftware.openfire.nio.MultiplexerConnectionHandler;
import org.jivesoftware.openfire.nio.XMPPCodecFactory;
import org.jivesoftware.util.CertificateEventListener;
import org.jivesoftware.util.CertificateManager;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.LocaleUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ConnectionManagerImpl extends BasicModule implements ConnectionManager, CertificateEventListener {
private static final Logger Log = LoggerFactory.getLogger(ConnectionManagerImpl.class);
private SocketAcceptor socketAcceptor;
private SocketAcceptor sslSocketAcceptor;
private SocketAcceptor componentAcceptor;
private SocketAcceptThread serverSocketThread;
private SocketAcceptor multiplexerSocketAcceptor;
private ArrayList<ServerPort> ports;
private SessionManager sessionManager;
private PacketDeliverer deliverer;
private PacketRouter router;
private RoutingTable routingTable;
private String serverName;
private XMPPServer server;
private String localIPAddress = null;
// Used to know if the sockets have been started
private boolean isSocketStarted = false;
public ConnectionManagerImpl() {
super("Connection Manager");
ports = new ArrayList<ServerPort>(4);
}
private synchronized void createListeners() {
if (isSocketStarted || sessionManager == null || deliverer == null || router == null || serverName == null) {
return;
}
// Create the port listener for s2s communication
createServerListener(localIPAddress);
// Create the port listener for Connections Multiplexers
createConnectionManagerListener();
// Create the port listener for external components
createComponentListener();
// Create the port listener for clients
createClientListeners();
// Create the port listener for secured clients
createClientSSLListeners();
}
private synchronized void startListeners() {
if (isSocketStarted || sessionManager == null || deliverer == null || router == null || serverName == null) {
return;
}
// Check if plugins have been loaded
PluginManager pluginManager = XMPPServer.getInstance().getPluginManager();
if (!pluginManager.isExecuted()) {
pluginManager.addPluginManagerListener(new PluginManagerListener() {
public void pluginsMonitored() {
// Stop listening for plugin events
XMPPServer.getInstance().getPluginManager().removePluginManagerListener(this);
// Start listeners
startListeners();
}
});
return;
}
isSocketStarted = true;
// Setup port info
try {
localIPAddress = InetAddress.getLocalHost().getHostAddress();
}
catch (UnknownHostException e) {
if (localIPAddress == null) {
localIPAddress = "Unknown";
}
}
// Start the port listener for s2s communication
startServerListener();
// Start the port listener for Connections Multiplexers
startConnectionManagerListener(localIPAddress);
// Start the port listener for external components
startComponentListener();
// Start the port listener for clients
startClientListeners(localIPAddress);
// Start the port listener for secured clients
startClientSSLListeners(localIPAddress);
// Start the HTTP client listener
startHTTPBindListeners();
}
private void createServerListener(String localIPAddress) {
// Start servers socket unless it's been disabled.
if (isServerListenerEnabled()) {
int port = getServerListenerPort();
try {
serverSocketThread = new SocketAcceptThread(this, new ServerPort(port, serverName,
localIPAddress, false, null, ServerPort.Type.server));
ports.add(serverSocketThread.getServerPort());
serverSocketThread.setDaemon(true);
serverSocketThread.setPriority(Thread.MAX_PRIORITY);
}
catch (Exception e) {
System.err.println("Error creating server listener on port " + port + ": " +
e.getMessage());
Log.error(LocaleUtils.getLocalizedString("admin.error.socket-setup"), e);
}
}
}
private void startServerListener() {
// Start servers socket unless it's been disabled.
if (isServerListenerEnabled()) {
int port = getServerListenerPort();
try {
serverSocketThread.start();
List<String> params = new ArrayList<String>();
params.add(Integer.toString(serverSocketThread.getPort()));
Log.info(LocaleUtils.getLocalizedString("startup.server", params));
}
catch (Exception e) {
System.err.println("Error starting server listener on port " + port + ": " +
e.getMessage());
Log.error(LocaleUtils.getLocalizedString("admin.error.socket-setup"), e);
}
}
}
private void stopServerListener() {
if (serverSocketThread != null) {
serverSocketThread.shutdown();
ports.remove(serverSocketThread.getServerPort());
serverSocketThread = null;
}
}
private void createConnectionManagerListener() {
// Start multiplexers socket unless it's been disabled.
if (isConnectionManagerListenerEnabled()) {
// Create SocketAcceptor with correct number of processors
multiplexerSocketAcceptor = buildSocketAcceptor();
// Customize Executor that will be used by processors to process incoming stanzas
ExecutorThreadModel threadModel = ExecutorThreadModel.getInstance("connectionManager");
int eventThreads = JiveGlobals.getIntProperty("xmpp.multiplex.processing.threads", 16);
ThreadPoolExecutor eventExecutor = (ThreadPoolExecutor) threadModel.getExecutor();
eventExecutor.setCorePoolSize(eventThreads + 1);
eventExecutor.setMaximumPoolSize(eventThreads + 1);
eventExecutor.setKeepAliveTime(60, TimeUnit.SECONDS);
multiplexerSocketAcceptor.getDefaultConfig().setThreadModel(threadModel);
// Add the XMPP codec filter
multiplexerSocketAcceptor.getFilterChain().addFirst("xmpp", new ProtocolCodecFilter(new XMPPCodecFactory()));
}
}
private void startConnectionManagerListener(String localIPAddress) {
// Start multiplexers socket unless it's been disabled.
if (isConnectionManagerListenerEnabled()) {
int port = getConnectionManagerListenerPort();
try {
// Listen on a specific network interface if it has been set.
String interfaceName = JiveGlobals.getXMLProperty("network.interface");
InetAddress bindInterface = null;
if (interfaceName != null) {
if (interfaceName.trim().length() > 0) {
bindInterface = InetAddress.getByName(interfaceName);
}
}
// Start accepting connections
multiplexerSocketAcceptor.bind(new InetSocketAddress(bindInterface, port), new MultiplexerConnectionHandler(serverName));
ports.add(new ServerPort(port, serverName, localIPAddress, false, null, ServerPort.Type.connectionManager));
List<String> params = new ArrayList<String>();
params.add(Integer.toString(port));
Log.info(LocaleUtils.getLocalizedString("startup.multiplexer", params));
}
catch (Exception e) {
System.err.println("Error starting multiplexer listener on port " + port + ": " +
e.getMessage());
Log.error(LocaleUtils.getLocalizedString("admin.error.socket-setup"), e);
}
}
}
private void stopConnectionManagerListener() {
if (multiplexerSocketAcceptor != null) {
multiplexerSocketAcceptor.unbindAll();
for (ServerPort port : ports) {
if (port.isConnectionManagerPort()) {
ports.remove(port);
break;
}
}
multiplexerSocketAcceptor = null;
}
}
private void createComponentListener() {
// Start components socket unless it's been disabled.
if (isComponentListenerEnabled() && componentAcceptor == null) {
// Create SocketAcceptor with correct number of processors
componentAcceptor = buildSocketAcceptor();
// Customize Executor that will be used by processors to process incoming stanzas
ExecutorThreadModel threadModel = ExecutorThreadModel.getInstance("component");
int eventThreads = JiveGlobals.getIntProperty("xmpp.component.processing.threads", 16);
ThreadPoolExecutor eventExecutor = (ThreadPoolExecutor)threadModel.getExecutor();
eventExecutor.setCorePoolSize(eventThreads + 1);
eventExecutor.setMaximumPoolSize(eventThreads + 1);
eventExecutor.setKeepAliveTime(60, TimeUnit.SECONDS);
componentAcceptor.getDefaultConfig().setThreadModel(threadModel);
// Add the XMPP codec filter
componentAcceptor.getFilterChain().addFirst("xmpp", new ProtocolCodecFilter(new XMPPCodecFactory()));
}
}
private void startComponentListener() {
// Start components socket unless it's been disabled.
if (isComponentListenerEnabled() && componentAcceptor != null &&
componentAcceptor.getManagedServiceAddresses().isEmpty()) {
int port = getComponentListenerPort();
try {
// Listen on a specific network interface if it has been set.
String interfaceName = JiveGlobals.getXMLProperty("network.interface");
InetAddress bindInterface = null;
if (interfaceName != null) {
if (interfaceName.trim().length() > 0) {
bindInterface = InetAddress.getByName(interfaceName);
}
}
// Start accepting connections
componentAcceptor
.bind(new InetSocketAddress(bindInterface, port), new ComponentConnectionHandler(serverName));
ports.add(new ServerPort(port, serverName, localIPAddress, false, null, ServerPort.Type.component));
List<String> params = new ArrayList<String>();
params.add(Integer.toString(port));
Log.info(LocaleUtils.getLocalizedString("startup.component", params));
}
catch (Exception e) {
System.err.println("Error starting component listener on port " + port + ": " +
e.getMessage());
Log.error(LocaleUtils.getLocalizedString("admin.error.socket-setup"), e);
}
}
}
private void stopComponentListener() {
if (componentAcceptor != null) {
componentAcceptor.unbindAll();
for (ServerPort port : ports) {
if (port.isComponentPort()) {
ports.remove(port);
break;
}
}
componentAcceptor = null;
}
}
private void createClientListeners() {
// Start clients plain socket unless it's been disabled.
if (isClientListenerEnabled()) {
// 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.client.processing.threads", 16);
ThreadPoolExecutor eventExecutor = (ThreadPoolExecutor)threadModel.getExecutor();
eventExecutor.setCorePoolSize(eventThreads + 1);
eventExecutor.setMaximumPoolSize(eventThreads + 1);
eventExecutor.setKeepAliveTime(60, TimeUnit.SECONDS);
socketAcceptor.getDefaultConfig().setThreadModel(threadModel);
// Add the XMPP codec filter
socketAcceptor.getFilterChain().addFirst("xmpp", new ProtocolCodecFilter(new XMPPCodecFactory()));
// Kill sessions whose outgoing queues keep growing and fail to send traffic
socketAcceptor.getFilterChain().addAfter("xmpp", "outCap", new StalledSessionsFilter());
}
}
private void startClientListeners(String localIPAddress) {
// Start clients plain socket unless it's been disabled.
if (isClientListenerEnabled()) {
int port = getClientListenerPort();
try {
// Listen on a specific network interface if it has been set.
String interfaceName = JiveGlobals.getXMLProperty("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(serverName));
ports.add(new ServerPort(port, serverName, localIPAddress, false, null, ServerPort.Type.client));
List<String> params = new ArrayList<String>();
params.add(Integer.toString(port));
Log.info(LocaleUtils.getLocalizedString("startup.plain", params));
}
catch (Exception e) {
System.err.println("Error starting XMPP listener on port " + port + ": " +
e.getMessage());
Log.error(LocaleUtils.getLocalizedString("admin.error.socket-setup"), e);
}
}
}
private void stopClientListeners() {
if (socketAcceptor != null) {
socketAcceptor.unbindAll();
for (ServerPort port : ports) {
if (port.isClientPort() && !port.isSecure()) {
ports.remove(port);
break;
}
}
socketAcceptor = null;
}
}
private void createClientSSLListeners() {
// Start clients SSL unless it's been disabled.
if (isClientSSLListenerEnabled()) {
int port = getClientSSLListenerPort();
String algorithm = JiveGlobals.getProperty("xmpp.socket.ssl.algorithm");
if ("".equals(algorithm) || algorithm == null) {
algorithm = "TLS";
}
try {
// Create SocketAcceptor with correct number of processors
sslSocketAcceptor = buildSocketAcceptor();
// Customize Executor that will be used by processors to process incoming stanzas
int eventThreads = JiveGlobals.getIntProperty("xmpp.client_ssl.processing.threads", 16);
ExecutorFilter executorFilter = new ExecutorFilter();
ThreadPoolExecutor eventExecutor = (ThreadPoolExecutor)executorFilter.getExecutor();
final ThreadFactory originalThreadFactory = eventExecutor.getThreadFactory();
ThreadFactory newThreadFactory = new ThreadFactory()
{
private final AtomicInteger threadId = new AtomicInteger( 0 );
public Thread newThread( Runnable runnable )
{
Thread t = originalThreadFactory.newThread( runnable );
t.setName("Old SSL executor thread - " + threadId.incrementAndGet() );
t.setDaemon( true );
return t;
}
};
eventExecutor.setThreadFactory( newThreadFactory );
eventExecutor.setCorePoolSize(eventThreads + 1);
eventExecutor.setMaximumPoolSize(eventThreads + 1);
eventExecutor.setKeepAliveTime(60, TimeUnit.SECONDS);
sslSocketAcceptor.getDefaultConfig().setThreadModel(ThreadModel.MANUAL);
// Add the XMPP codec filter
sslSocketAcceptor.getFilterChain().addFirst("xmpp", new ProtocolCodecFilter(new XMPPCodecFactory()));
sslSocketAcceptor.getFilterChain().addFirst("threadModel", executorFilter);
// Kill sessions whose outgoing queues keep growing and fail to send traffic
sslSocketAcceptor.getFilterChain().addAfter("xmpp", "outCap", new StalledSessionsFilter());
// 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.getc2sTrustStore());
sslContext.init(keyFactory.getKeyManagers(),
trustFactory.getTrustManagers(),
new java.security.SecureRandom());
SSLFilter sslFilter = new SSLFilter(sslContext);
if (JiveGlobals.getProperty("xmpp.client.cert.policy","disabled").equals("needed")) {
sslFilter.setNeedClientAuth(true);
}
else if(JiveGlobals.getProperty("xmpp.client.cert.policy","disabled").equals("wanted")) {
sslFilter.setWantClientAuth(true);
}
sslSocketAcceptor.getFilterChain().addFirst("tls", sslFilter);
}
catch (Exception e) {
System.err.println("Error starting SSL XMPP listener on port " + port + ": " +
e.getMessage());
Log.error(LocaleUtils.getLocalizedString("admin.error.ssl"), e);
}
}
}
private void startClientSSLListeners(String localIPAddress) {
// Start clients SSL unless it's been disabled.
if (isClientSSLListenerEnabled()) {
int port = getClientSSLListenerPort();
try {
// Listen on a specific network interface if it has been set.
String interfaceName = JiveGlobals.getXMLProperty("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(serverName));
ports.add(new ServerPort(port, serverName, localIPAddress, true, null, ServerPort.Type.client));
List<String> params = new ArrayList<String>();
params.add(Integer.toString(port));
Log.info(LocaleUtils.getLocalizedString("startup.ssl", params));
}
catch (Exception e) {
System.err.println("Error starting SSL XMPP listener on port " + port + ": " +
e.getMessage());
Log.error(LocaleUtils.getLocalizedString("admin.error.ssl"), e);
}
}
}
private void stopClientSSLListeners() {
if (sslSocketAcceptor != null) {
sslSocketAcceptor.unbindAll();
for (ServerPort port : ports) {
if (port.isClientPort() && port.isSecure()) {
ports.remove(port);
break;
}
}
sslSocketAcceptor = null;
}
}
private void restartClientSSLListeners() {
if (!isSocketStarted) {
return;
}
// Setup port info
try {
localIPAddress = InetAddress.getLocalHost().getHostAddress();
}
catch (UnknownHostException e) {
if (localIPAddress == null) {
localIPAddress = "Unknown";
}
}
stopClientSSLListeners();
createClientSSLListeners();
startClientSSLListeners(localIPAddress);
}
public Collection<ServerPort> getPorts() {
return ports;
}
public SocketReader createSocketReader(Socket sock, boolean isSecure, ServerPort serverPort,
boolean useBlockingMode) throws IOException {
if (serverPort.isServerPort()) {
SocketConnection conn = new SocketConnection(deliverer, sock, isSecure);
return new ServerSocketReader(router, routingTable, serverName, sock, conn,
useBlockingMode);
}
return null;
}
private void startHTTPBindListeners() {
HttpBindManager.getInstance().start();
}
@Override
public void initialize(XMPPServer server) {
super.initialize(server);
this.server = server;
serverName = server.getServerInfo().getXMPPDomain();
router = server.getPacketRouter();
routingTable = server.getRoutingTable();
deliverer = server.getPacketDeliverer();
sessionManager = server.getSessionManager();
// Check if we need to configure MINA to use Direct or Heap Buffers
// Note: It has been reported that heap buffers are 50% faster than direct buffers
if (JiveGlobals.getBooleanProperty("xmpp.socket.heapBuffer", true)) {
ByteBuffer.setUseDirectBuffers(false);
ByteBuffer.setAllocator(new SimpleByteBufferAllocator());
}
}
public void enableClientListener(boolean enabled) {
if (enabled == isClientListenerEnabled()) {
// Ignore new setting
return;
}
if (enabled) {
JiveGlobals.setProperty("xmpp.socket.plain.active", "true");
// Start the port listener for clients
createClientListeners();
startClientListeners(localIPAddress);
}
else {
JiveGlobals.setProperty("xmpp.socket.plain.active", "false");
// Stop the port listener for clients
stopClientListeners();
}
}
public boolean isClientListenerEnabled() {
return JiveGlobals.getBooleanProperty("xmpp.socket.plain.active", true);
}
public void enableClientSSLListener(boolean enabled) {
if (enabled == isClientSSLListenerEnabled()) {
// Ignore new setting
return;
}
if (enabled) {
JiveGlobals.setProperty("xmpp.socket.ssl.active", "true");
// Start the port listener for secured clients
createClientSSLListeners();
startClientSSLListeners(localIPAddress);
}
else {
JiveGlobals.setProperty("xmpp.socket.ssl.active", "false");
// Stop the port listener for secured clients
stopClientSSLListeners();
}
}
public boolean isClientSSLListenerEnabled() {
try {
return JiveGlobals.getBooleanProperty("xmpp.socket.ssl.active", true) && SSLConfig.getKeyStore().size() > 0;
} catch (KeyStoreException e) {
return false;
} catch (IOException e) {
return false;
}
}
public void enableComponentListener(boolean enabled) {
if (enabled == isComponentListenerEnabled()) {
// Ignore new setting
return;
}
if (enabled) {
JiveGlobals.setProperty("xmpp.component.socket.active", "true");
// Start the port listener for external components
createComponentListener();
startComponentListener();
}
else {
JiveGlobals.setProperty("xmpp.component.socket.active", "false");
// Stop the port listener for external components
stopComponentListener();
}
}
public boolean isComponentListenerEnabled() {
return JiveGlobals.getBooleanProperty("xmpp.component.socket.active", false);
}
public void enableServerListener(boolean enabled) {
if (enabled == isServerListenerEnabled()) {
// Ignore new setting
return;
}
if (enabled) {
JiveGlobals.setProperty("xmpp.server.socket.active", "true");
// Start the port listener for s2s communication
createServerListener(localIPAddress);
startServerListener();
}
else {
JiveGlobals.setProperty("xmpp.server.socket.active", "false");
// Stop the port listener for s2s communication
stopServerListener();
}
}
public boolean isServerListenerEnabled() {
return JiveGlobals.getBooleanProperty("xmpp.server.socket.active", true);
}
public void enableConnectionManagerListener(boolean enabled) {
if (enabled == isConnectionManagerListenerEnabled()) {
// Ignore new setting
return;
}
if (enabled) {
JiveGlobals.setProperty("xmpp.multiplex.socket.active", "true");
// Start the port listener for s2s communication
createConnectionManagerListener();
startConnectionManagerListener(localIPAddress);
}
else {
JiveGlobals.setProperty("xmpp.multiplex.socket.active", "false");
// Stop the port listener for s2s communication
stopConnectionManagerListener();
}
}
public boolean isConnectionManagerListenerEnabled() {
return JiveGlobals.getBooleanProperty("xmpp.multiplex.socket.active", false);
}
public void setClientListenerPort(int port) {
if (port == getClientListenerPort()) {
// Ignore new setting
return;
}
JiveGlobals.setProperty("xmpp.socket.plain.port", String.valueOf(port));
// Stop the port listener for clients
stopClientListeners();
if (isClientListenerEnabled()) {
// Start the port listener for clients
createClientListeners();
startClientListeners(localIPAddress);
}
}
public SocketAcceptor getSocketAcceptor() {
return socketAcceptor;
}
public int getClientListenerPort() {
return JiveGlobals.getIntProperty("xmpp.socket.plain.port", DEFAULT_PORT);
}
public SocketAcceptor getSSLSocketAcceptor() {
return sslSocketAcceptor;
}
public void setClientSSLListenerPort(int port) {
if (port == getClientSSLListenerPort()) {
// Ignore new setting
return;
}
JiveGlobals.setProperty("xmpp.socket.ssl.port", String.valueOf(port));
// Stop the port listener for secured clients
stopClientSSLListeners();
if (isClientSSLListenerEnabled()) {
// Start the port listener for secured clients
createClientSSLListeners();
startClientSSLListeners(localIPAddress);
}
}
public int getClientSSLListenerPort() {
return JiveGlobals.getIntProperty("xmpp.socket.ssl.port", DEFAULT_SSL_PORT);
}
public void setComponentListenerPort(int port) {
if (port == getComponentListenerPort()) {
// Ignore new setting
return;
}
JiveGlobals.setProperty("xmpp.component.socket.port", String.valueOf(port));
// Stop the port listener for external components
stopComponentListener();
if (isComponentListenerEnabled()) {
// Start the port listener for external components
createComponentListener();
startComponentListener();
}
}
public SocketAcceptor getComponentAcceptor() {
return componentAcceptor;
}
public int getComponentListenerPort() {
return JiveGlobals.getIntProperty("xmpp.component.socket.port", DEFAULT_COMPONENT_PORT);
}
public void setServerListenerPort(int port) {
if (port == getServerListenerPort()) {
// Ignore new setting
return;
}
JiveGlobals.setProperty("xmpp.server.socket.port", String.valueOf(port));
// Stop the port listener for s2s communication
stopServerListener();
if (isServerListenerEnabled()) {
// Start the port listener for s2s communication
createServerListener(localIPAddress);
startServerListener();
}
}
public int getServerListenerPort() {
return JiveGlobals.getIntProperty("xmpp.server.socket.port", DEFAULT_SERVER_PORT);
}
public SocketAcceptor getMultiplexerSocketAcceptor() {
return multiplexerSocketAcceptor;
}
public void setConnectionManagerListenerPort(int port) {
if (port == getConnectionManagerListenerPort()) {
// Ignore new setting
return;
}
JiveGlobals.setProperty("xmpp.multiplex.socket.port", String.valueOf(port));
// Stop the port listener for connection managers
stopConnectionManagerListener();
if (isConnectionManagerListenerEnabled()) {
// Start the port listener for connection managers
createConnectionManagerListener();
startConnectionManagerListener(localIPAddress);
}
}
public int getConnectionManagerListenerPort() {
return JiveGlobals.getIntProperty("xmpp.multiplex.socket.port", DEFAULT_MULTIPLEX_PORT);
}
// #####################################################################
// Certificates events
// #####################################################################
public void certificateCreated(KeyStore keyStore, String alias, X509Certificate cert) {
restartClientSSLListeners();
}
public void certificateDeleted(KeyStore keyStore, String alias) {
restartClientSSLListeners();
}
public void certificateSigned(KeyStore keyStore, String alias, List<X509Certificate> certificates) {
restartClientSSLListeners();
}
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<Runnable>() );
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 = 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;
}
// #####################################################################
// Module management
// #####################################################################
@Override
public void start() {
super.start();
createListeners();
startListeners();
SocketSendingTracker.getInstance().start();
CertificateManager.addListener(this);
}
@Override
public void stop() {
super.stop();
stopClientListeners();
stopClientSSLListeners();
stopComponentListener();
stopConnectionManagerListener();
stopServerListener();
HttpBindManager.getInstance().stop();
SocketSendingTracker.getInstance().shutdown();
CertificateManager.removeListener(this);
serverName = null;
}
}