PageRenderTime 51ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/src/java/org/jivesoftware/openfire/spi/ConnectionManagerImpl.java

https://gitlab.com/javajamesb08/Openfire
Java | 955 lines | 744 code | 95 blank | 116 comment | 117 complexity | 97ae455ab232b32ad84d1ec71d150cf1 MD5 | raw file
Possible License(s): MIT, GPL-2.0
  1. /**
  2. * $RCSfile: ConnectionManagerImpl.java,v $
  3. * $Revision: $
  4. * $Date: $
  5. *
  6. * Copyright (C) 2005-2008 Jive Software. All rights reserved.
  7. *
  8. * Licensed under the Apache License, Version 2.0 (the "License");
  9. * you may not use this file except in compliance with the License.
  10. * You may obtain a copy of the License at
  11. *
  12. * http://www.apache.org/licenses/LICENSE-2.0
  13. *
  14. * Unless required by applicable law or agreed to in writing, software
  15. * distributed under the License is distributed on an "AS IS" BASIS,
  16. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17. * See the License for the specific language governing permissions and
  18. * limitations under the License.
  19. */
  20. package org.jivesoftware.openfire.spi;
  21. import java.io.IOException;
  22. import java.lang.management.ManagementFactory;
  23. import java.net.InetAddress;
  24. import java.net.InetSocketAddress;
  25. import java.net.Socket;
  26. import java.net.UnknownHostException;
  27. import java.security.KeyStore;
  28. import java.security.KeyStoreException;
  29. import java.security.cert.X509Certificate;
  30. import java.util.ArrayList;
  31. import java.util.Collection;
  32. import java.util.List;
  33. import java.util.concurrent.ThreadFactory;
  34. import java.util.concurrent.ThreadPoolExecutor;
  35. import java.util.concurrent.TimeUnit;
  36. import java.util.concurrent.atomic.AtomicInteger;
  37. import javax.management.JMException;
  38. import javax.management.MBeanServer;
  39. import javax.management.ObjectName;
  40. import javax.net.ssl.KeyManagerFactory;
  41. import javax.net.ssl.SSLContext;
  42. import javax.net.ssl.TrustManagerFactory;
  43. import org.apache.mina.core.buffer.IoBuffer;
  44. import org.apache.mina.core.buffer.SimpleBufferAllocator;
  45. import org.apache.mina.core.service.IoService;
  46. import org.apache.mina.core.service.IoServiceListener;
  47. import org.apache.mina.core.session.IdleStatus;
  48. import org.apache.mina.core.session.IoSession;
  49. import org.apache.mina.filter.codec.ProtocolCodecFilter;
  50. import org.apache.mina.filter.executor.ExecutorFilter;
  51. import org.apache.mina.filter.ssl.SslFilter;
  52. import org.apache.mina.integration.jmx.IoServiceMBean;
  53. import org.apache.mina.integration.jmx.IoSessionMBean;
  54. import org.apache.mina.transport.socket.SocketSessionConfig;
  55. import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
  56. import org.jivesoftware.openfire.ConnectionManager;
  57. import org.jivesoftware.openfire.JMXManager;
  58. import org.jivesoftware.openfire.PacketDeliverer;
  59. import org.jivesoftware.openfire.PacketRouter;
  60. import org.jivesoftware.openfire.RoutingTable;
  61. import org.jivesoftware.openfire.ServerPort;
  62. import org.jivesoftware.openfire.SessionManager;
  63. import org.jivesoftware.openfire.XMPPServer;
  64. import org.jivesoftware.openfire.container.BasicModule;
  65. import org.jivesoftware.openfire.container.PluginManager;
  66. import org.jivesoftware.openfire.container.PluginManagerListener;
  67. import org.jivesoftware.openfire.http.HttpBindManager;
  68. import org.jivesoftware.openfire.net.SSLConfig;
  69. import org.jivesoftware.openfire.net.ServerSocketReader;
  70. import org.jivesoftware.openfire.net.SocketAcceptThread;
  71. import org.jivesoftware.openfire.net.SocketConnection;
  72. import org.jivesoftware.openfire.net.SocketReader;
  73. import org.jivesoftware.openfire.net.SocketSendingTracker;
  74. import org.jivesoftware.openfire.net.StalledSessionsFilter;
  75. import org.jivesoftware.openfire.nio.ClientConnectionHandler;
  76. import org.jivesoftware.openfire.nio.ComponentConnectionHandler;
  77. import org.jivesoftware.openfire.nio.MultiplexerConnectionHandler;
  78. import org.jivesoftware.openfire.nio.XMPPCodecFactory;
  79. import org.jivesoftware.openfire.session.ConnectionSettings;
  80. import org.jivesoftware.util.CertificateEventListener;
  81. import org.jivesoftware.util.CertificateManager;
  82. import org.jivesoftware.util.JiveGlobals;
  83. import org.jivesoftware.util.LocaleUtils;
  84. import org.slf4j.Logger;
  85. import org.slf4j.LoggerFactory;
  86. public class ConnectionManagerImpl extends BasicModule implements ConnectionManager, CertificateEventListener {
  87. private static final int MB = 1024 * 1024;
  88. public static final String EXECUTOR_FILTER_NAME = "threadModel";
  89. public static final String TLS_FILTER_NAME = "tls";
  90. public static final String COMPRESSION_FILTER_NAME = "compression";
  91. public static final String XMPP_CODEC_FILTER_NAME = "xmpp";
  92. public static final String CAPACITY_FILTER_NAME = "outCap";
  93. private static final String CLIENT_SOCKET_ACCEPTOR_NAME = "client";
  94. private static final String CLIENT_SSL_SOCKET_ACCEPTOR_NAME = "client_ssl";
  95. private static final String COMPONENT_SOCKET_ACCEPTOR_NAME = "component";
  96. private static final String MULTIPLEXER_SOCKET_ACCEPTOR_NAME = "multiplexer";
  97. private static final Logger Log = LoggerFactory.getLogger(ConnectionManagerImpl.class);
  98. private NioSocketAcceptor socketAcceptor;
  99. private NioSocketAcceptor sslSocketAcceptor;
  100. private NioSocketAcceptor componentAcceptor;
  101. private SocketAcceptThread serverSocketThread;
  102. private NioSocketAcceptor multiplexerSocketAcceptor;
  103. private ArrayList<ServerPort> ports;
  104. private SessionManager sessionManager;
  105. private PacketDeliverer deliverer;
  106. private PacketRouter router;
  107. private RoutingTable routingTable;
  108. private String serverName;
  109. private String localIPAddress = null;
  110. // Used to know if the sockets have been started
  111. private boolean isSocketStarted = false;
  112. public ConnectionManagerImpl() {
  113. super("Connection Manager");
  114. ports = new ArrayList<ServerPort>(4);
  115. }
  116. private synchronized void createListeners() {
  117. if (isSocketStarted || sessionManager == null || deliverer == null || router == null || serverName == null) {
  118. return;
  119. }
  120. // Create the port listener for s2s communication
  121. createServerListener(localIPAddress);
  122. // Create the port listener for Connections Multiplexers
  123. createConnectionManagerListener();
  124. // Create the port listener for external components
  125. createComponentListener();
  126. // Create the port listener for clients
  127. createClientListeners();
  128. // Create the port listener for secured clients
  129. createClientSSLListeners();
  130. }
  131. private synchronized void startListeners() {
  132. if (isSocketStarted || sessionManager == null || deliverer == null || router == null || serverName == null) {
  133. return;
  134. }
  135. // Check if plugins have been loaded
  136. PluginManager pluginManager = XMPPServer.getInstance().getPluginManager();
  137. if (!pluginManager.isExecuted()) {
  138. pluginManager.addPluginManagerListener(new PluginManagerListener() {
  139. public void pluginsMonitored() {
  140. // Stop listening for plugin events
  141. XMPPServer.getInstance().getPluginManager().removePluginManagerListener(this);
  142. // Start listeners
  143. startListeners();
  144. }
  145. });
  146. return;
  147. }
  148. isSocketStarted = true;
  149. // Setup port info
  150. try {
  151. localIPAddress = InetAddress.getLocalHost().getHostAddress();
  152. }
  153. catch (UnknownHostException e) {
  154. if (localIPAddress == null) {
  155. localIPAddress = "Unknown";
  156. }
  157. }
  158. // Start the port listener for s2s communication
  159. startServerListener();
  160. // Start the port listener for Connections Multiplexers
  161. startConnectionManagerListener(localIPAddress);
  162. // Start the port listener for external components
  163. startComponentListener();
  164. // Start the port listener for clients
  165. startClientListeners(localIPAddress);
  166. // Start the port listener for secured clients
  167. startClientSSLListeners(localIPAddress);
  168. // Start the HTTP client listener
  169. startHTTPBindListeners();
  170. }
  171. private void createServerListener(String localIPAddress) {
  172. // Start servers socket unless it's been disabled.
  173. if (isServerListenerEnabled()) {
  174. int port = getServerListenerPort();
  175. try {
  176. serverSocketThread = new SocketAcceptThread(this, new ServerPort(port, serverName,
  177. localIPAddress, false, null, ServerPort.Type.server));
  178. ports.add(serverSocketThread.getServerPort());
  179. serverSocketThread.setDaemon(true);
  180. serverSocketThread.setPriority(Thread.MAX_PRIORITY);
  181. }
  182. catch (Exception e) {
  183. System.err.println("Error creating server listener on port " + port + ": " +
  184. e.getMessage());
  185. Log.error(LocaleUtils.getLocalizedString("admin.error.socket-setup"), e);
  186. }
  187. }
  188. }
  189. private void startServerListener() {
  190. // Start servers socket unless it's been disabled.
  191. if (isServerListenerEnabled()) {
  192. int port = getServerListenerPort();
  193. try {
  194. serverSocketThread.start();
  195. List<String> params = new ArrayList<String>();
  196. params.add(Integer.toString(serverSocketThread.getPort()));
  197. Log.info(LocaleUtils.getLocalizedString("startup.server", params));
  198. }
  199. catch (Exception e) {
  200. System.err.println("Error starting server listener on port " + port + ": " +
  201. e.getMessage());
  202. Log.error(LocaleUtils.getLocalizedString("admin.error.socket-setup"), e);
  203. }
  204. }
  205. }
  206. private void stopServerListener() {
  207. if (serverSocketThread != null) {
  208. serverSocketThread.shutdown();
  209. ports.remove(serverSocketThread.getServerPort());
  210. serverSocketThread = null;
  211. }
  212. }
  213. private void createConnectionManagerListener() {
  214. // Start multiplexers socket unless it's been disabled.
  215. if (isConnectionManagerListenerEnabled()) {
  216. // Create SocketAcceptor with correct number of processors
  217. multiplexerSocketAcceptor = buildSocketAcceptor(MULTIPLEXER_SOCKET_ACCEPTOR_NAME);
  218. // Customize Executor that will be used by processors to process incoming stanzas
  219. int maxPoolSize = JiveGlobals.getIntProperty("xmpp.multiplex.processing.threads", 16);
  220. ExecutorFilter executorFilter = new ExecutorFilter(getCorePoolSize(maxPoolSize), maxPoolSize, 60, TimeUnit.SECONDS);
  221. ThreadPoolExecutor eventExecutor = (ThreadPoolExecutor)executorFilter.getExecutor();
  222. ThreadFactory threadFactory = eventExecutor.getThreadFactory();
  223. threadFactory = new DelegatingThreadFactory("Multiplexer-Thread-", threadFactory);
  224. eventExecutor.setThreadFactory(threadFactory);
  225. multiplexerSocketAcceptor.getFilterChain().addFirst(EXECUTOR_FILTER_NAME, executorFilter);
  226. // Add the XMPP codec filter
  227. multiplexerSocketAcceptor.getFilterChain().addAfter(EXECUTOR_FILTER_NAME, XMPP_CODEC_FILTER_NAME, new ProtocolCodecFilter(new XMPPCodecFactory()));
  228. }
  229. }
  230. private void startConnectionManagerListener(String localIPAddress) {
  231. // Start multiplexers socket unless it's been disabled.
  232. if (isConnectionManagerListenerEnabled()) {
  233. int port = getConnectionManagerListenerPort();
  234. try {
  235. // Listen on a specific network interface if it has been set.
  236. String interfaceName = JiveGlobals.getXMLProperty("network.interface");
  237. InetAddress bindInterface = null;
  238. if (interfaceName != null) {
  239. if (interfaceName.trim().length() > 0) {
  240. bindInterface = InetAddress.getByName(interfaceName);
  241. }
  242. }
  243. // Start accepting connections
  244. multiplexerSocketAcceptor.setHandler(new MultiplexerConnectionHandler(serverName));
  245. multiplexerSocketAcceptor.bind(new InetSocketAddress(bindInterface, port));
  246. ports.add(new ServerPort(port, serverName, localIPAddress, false, null, ServerPort.Type.connectionManager));
  247. List<String> params = new ArrayList<String>();
  248. params.add(Integer.toString(port));
  249. Log.info(LocaleUtils.getLocalizedString("startup.multiplexer", params));
  250. }
  251. catch (Exception e) {
  252. System.err.println("Error starting multiplexer listener on port " + port + ": " +
  253. e.getMessage());
  254. Log.error(LocaleUtils.getLocalizedString("admin.error.socket-setup"), e);
  255. }
  256. }
  257. }
  258. private void stopConnectionManagerListener() {
  259. if (multiplexerSocketAcceptor != null) {
  260. multiplexerSocketAcceptor.unbind();
  261. for (ServerPort port : ports) {
  262. if (port.isConnectionManagerPort()) {
  263. ports.remove(port);
  264. break;
  265. }
  266. }
  267. multiplexerSocketAcceptor = null;
  268. }
  269. }
  270. private void createComponentListener() {
  271. // Start components socket unless it's been disabled.
  272. if (isComponentListenerEnabled() && componentAcceptor == null) {
  273. // Create SocketAcceptor with correct number of processors
  274. componentAcceptor = buildSocketAcceptor(COMPONENT_SOCKET_ACCEPTOR_NAME);
  275. int maxPoolSize = JiveGlobals.getIntProperty("xmpp.component.processing.threads", 16);
  276. ExecutorFilter executorFilter = new ExecutorFilter(getCorePoolSize(maxPoolSize), maxPoolSize, 60, TimeUnit.SECONDS);
  277. ThreadPoolExecutor eventExecutor = (ThreadPoolExecutor)executorFilter.getExecutor();
  278. ThreadFactory threadFactory = eventExecutor.getThreadFactory();
  279. threadFactory = new DelegatingThreadFactory("Component-Thread-", threadFactory);
  280. eventExecutor.setThreadFactory(threadFactory);
  281. componentAcceptor.getFilterChain().addFirst(EXECUTOR_FILTER_NAME, executorFilter);
  282. // Add the XMPP codec filter
  283. componentAcceptor.getFilterChain().addAfter(EXECUTOR_FILTER_NAME, XMPP_CODEC_FILTER_NAME, new ProtocolCodecFilter(new XMPPCodecFactory()));
  284. }
  285. }
  286. private void startComponentListener() {
  287. // Start components socket unless it's been disabled.
  288. if (isComponentListenerEnabled() && componentAcceptor != null &&
  289. componentAcceptor.getManagedSessionCount() == 0) {
  290. int port = getComponentListenerPort();
  291. try {
  292. // Listen on a specific network interface if it has been set.
  293. String interfaceName = JiveGlobals.getXMLProperty("network.interface");
  294. InetAddress bindInterface = null;
  295. if (interfaceName != null) {
  296. if (interfaceName.trim().length() > 0) {
  297. bindInterface = InetAddress.getByName(interfaceName);
  298. }
  299. }
  300. // Start accepting connections
  301. componentAcceptor.setHandler(new ComponentConnectionHandler(serverName));
  302. componentAcceptor.bind(new InetSocketAddress(bindInterface, port));
  303. ports.add(new ServerPort(port, serverName, localIPAddress, false, null, ServerPort.Type.component));
  304. List<String> params = new ArrayList<String>();
  305. params.add(Integer.toString(port));
  306. Log.info(LocaleUtils.getLocalizedString("startup.component", params));
  307. }
  308. catch (Exception e) {
  309. System.err.println("Error starting component listener on port " + port + ": " +
  310. e.getMessage());
  311. Log.error(LocaleUtils.getLocalizedString("admin.error.socket-setup"), e);
  312. }
  313. }
  314. }
  315. private void stopComponentListener() {
  316. if (componentAcceptor != null) {
  317. componentAcceptor.unbind();
  318. for (ServerPort port : ports) {
  319. if (port.isComponentPort()) {
  320. ports.remove(port);
  321. break;
  322. }
  323. }
  324. componentAcceptor = null;
  325. }
  326. }
  327. private void createClientListeners() {
  328. // Start clients plain socket unless it's been disabled.
  329. if (isClientListenerEnabled()) {
  330. // Create SocketAcceptor with correct number of processors
  331. socketAcceptor = buildSocketAcceptor(CLIENT_SOCKET_ACCEPTOR_NAME);
  332. // Customize Executor that will be used by processors to process incoming stanzas
  333. int maxPoolSize = JiveGlobals.getIntProperty(ConnectionSettings.Client.MAX_THREADS, 16);
  334. ExecutorFilter executorFilter = new ExecutorFilter(getCorePoolSize(maxPoolSize), maxPoolSize, 60, TimeUnit.SECONDS);
  335. ThreadPoolExecutor eventExecutor = (ThreadPoolExecutor)executorFilter.getExecutor();
  336. ThreadFactory threadFactory = eventExecutor.getThreadFactory();
  337. threadFactory = new DelegatingThreadFactory("C2S-Thread-", threadFactory);
  338. eventExecutor.setThreadFactory(threadFactory);
  339. // Add the XMPP codec filter
  340. socketAcceptor.getFilterChain().addFirst(EXECUTOR_FILTER_NAME, executorFilter);
  341. socketAcceptor.getFilterChain().addAfter(EXECUTOR_FILTER_NAME, XMPP_CODEC_FILTER_NAME, new ProtocolCodecFilter(new XMPPCodecFactory()));
  342. // Kill sessions whose outgoing queues keep growing and fail to send traffic
  343. socketAcceptor.getFilterChain().addAfter(XMPP_CODEC_FILTER_NAME, CAPACITY_FILTER_NAME, new StalledSessionsFilter());
  344. // Throttle sessions who send data too fast
  345. int maxBufferSize = JiveGlobals.getIntProperty(ConnectionSettings.Client.MAX_READ_BUFFER, 10 * MB);
  346. socketAcceptor.getSessionConfig().setMaxReadBufferSize(maxBufferSize);
  347. Log.debug("Throttling read buffer for connections from socketAcceptor={} to max={} bytes",
  348. socketAcceptor, maxBufferSize);
  349. }
  350. }
  351. private void startClientListeners(String localIPAddress) {
  352. // Start clients plain socket unless it's been disabled.
  353. if (isClientListenerEnabled()) {
  354. int port = getClientListenerPort();
  355. try {
  356. // Listen on a specific network interface if it has been set.
  357. String interfaceName = JiveGlobals.getXMLProperty("network.interface");
  358. InetAddress bindInterface = null;
  359. if (interfaceName != null) {
  360. if (interfaceName.trim().length() > 0) {
  361. bindInterface = InetAddress.getByName(interfaceName);
  362. }
  363. }
  364. // Start accepting connections
  365. socketAcceptor.setHandler(new ClientConnectionHandler(serverName));
  366. socketAcceptor.bind(new InetSocketAddress(bindInterface, port));
  367. ports.add(new ServerPort(port, serverName, localIPAddress, false, null, ServerPort.Type.client));
  368. List<String> params = new ArrayList<String>();
  369. params.add(Integer.toString(port));
  370. Log.info(LocaleUtils.getLocalizedString("startup.plain", params));
  371. }
  372. catch (Exception e) {
  373. System.err.println("Error starting XMPP listener on port " + port + ": " +
  374. e.getMessage());
  375. Log.error(LocaleUtils.getLocalizedString("admin.error.socket-setup"), e);
  376. }
  377. }
  378. }
  379. private void stopClientListeners() {
  380. if (socketAcceptor != null) {
  381. socketAcceptor.unbind();
  382. for (ServerPort port : ports) {
  383. if (port.isClientPort() && !port.isSecure()) {
  384. ports.remove(port);
  385. break;
  386. }
  387. }
  388. socketAcceptor = null;
  389. }
  390. }
  391. private void createClientSSLListeners() {
  392. // Start clients SSL unless it's been disabled.
  393. if (isClientSSLListenerEnabled()) {
  394. int port = getClientSSLListenerPort();
  395. String algorithm = JiveGlobals.getProperty(ConnectionSettings.Client.TLS_ALGORITHM, "TLS");
  396. try {
  397. // Customize Executor that will be used by processors to process incoming stanzas
  398. int maxPoolSize = JiveGlobals.getIntProperty(ConnectionSettings.Client.MAX_THREADS_SSL, 16);
  399. ExecutorFilter executorFilter = new ExecutorFilter(getCorePoolSize(maxPoolSize), maxPoolSize, 60, TimeUnit.SECONDS);
  400. ThreadPoolExecutor eventExecutor = (ThreadPoolExecutor)executorFilter.getExecutor();
  401. ThreadFactory threadFactory = eventExecutor.getThreadFactory();
  402. threadFactory = new DelegatingThreadFactory("LegacySSL-Thread-", threadFactory);
  403. eventExecutor.setThreadFactory(threadFactory);
  404. // Create SocketAcceptor with correct number of processors
  405. sslSocketAcceptor = buildSocketAcceptor(CLIENT_SSL_SOCKET_ACCEPTOR_NAME);
  406. sslSocketAcceptor.getFilterChain().addFirst(EXECUTOR_FILTER_NAME, executorFilter);
  407. // Add the XMPP codec filter
  408. sslSocketAcceptor.getFilterChain().addAfter(EXECUTOR_FILTER_NAME, XMPP_CODEC_FILTER_NAME, new ProtocolCodecFilter(new XMPPCodecFactory()));
  409. // Kill sessions whose outgoing queues keep growing and fail to send traffic
  410. sslSocketAcceptor.getFilterChain().addAfter(XMPP_CODEC_FILTER_NAME, CAPACITY_FILTER_NAME, new StalledSessionsFilter());
  411. // Throttle sessions who send data too fast
  412. int maxBufferSize = JiveGlobals.getIntProperty(ConnectionSettings.Client.MAX_READ_BUFFER_SSL, 10 * MB);
  413. sslSocketAcceptor.getSessionConfig().setMaxReadBufferSize(maxBufferSize);
  414. Log.debug("Throttling read buffer for connections from sslSocketAcceptor={} to max={} bytes",
  415. sslSocketAcceptor, maxBufferSize);
  416. // Add the SSL filter now since sockets are "borned" encrypted in the old ssl method
  417. SSLContext sslContext = SSLContext.getInstance(algorithm);
  418. KeyManagerFactory keyFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
  419. keyFactory.init(SSLConfig.getKeyStore(), SSLConfig.getKeyPassword().toCharArray());
  420. TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
  421. trustFactory.init(SSLConfig.getc2sTrustStore());
  422. sslContext.init(keyFactory.getKeyManagers(),
  423. trustFactory.getTrustManagers(),
  424. new java.security.SecureRandom());
  425. SslFilter sslFilter = new SslFilter(sslContext);
  426. if (JiveGlobals.getProperty(ConnectionSettings.Client.AUTH_PER_CLIENTCERT_POLICY,"disabled").equals("needed")) {
  427. sslFilter.setNeedClientAuth(true);
  428. }
  429. else if(JiveGlobals.getProperty(ConnectionSettings.Client.AUTH_PER_CLIENTCERT_POLICY,"disabled").equals("wanted")) {
  430. sslFilter.setWantClientAuth(true);
  431. }
  432. sslSocketAcceptor.getFilterChain().addAfter(EXECUTOR_FILTER_NAME, TLS_FILTER_NAME, sslFilter);
  433. }
  434. catch (Exception e) {
  435. System.err.println("Error starting SSL XMPP listener on port " + port + ": " +
  436. e.getMessage());
  437. Log.error(LocaleUtils.getLocalizedString("admin.error.ssl"), e);
  438. }
  439. }
  440. }
  441. private void startClientSSLListeners(String localIPAddress) {
  442. // Start clients SSL unless it's been disabled.
  443. if (isClientSSLListenerEnabled()) {
  444. int port = getClientSSLListenerPort();
  445. try {
  446. // Listen on a specific network interface if it has been set.
  447. String interfaceName = JiveGlobals.getXMLProperty("network.interface");
  448. InetAddress bindInterface = null;
  449. if (interfaceName != null) {
  450. if (interfaceName.trim().length() > 0) {
  451. bindInterface = InetAddress.getByName(interfaceName);
  452. }
  453. }
  454. // Start accepting connections
  455. sslSocketAcceptor.setHandler(new ClientConnectionHandler(serverName));
  456. sslSocketAcceptor.bind(new InetSocketAddress(bindInterface, port));
  457. ports.add(new ServerPort(port, serverName, localIPAddress, true, null, ServerPort.Type.client));
  458. List<String> params = new ArrayList<String>();
  459. params.add(Integer.toString(port));
  460. Log.info(LocaleUtils.getLocalizedString("startup.ssl", params));
  461. }
  462. catch (Exception e) {
  463. System.err.println("Error starting SSL XMPP listener on port " + port + ": " +
  464. e.getMessage());
  465. Log.error(LocaleUtils.getLocalizedString("admin.error.ssl"), e);
  466. }
  467. }
  468. }
  469. private void stopClientSSLListeners() {
  470. if (sslSocketAcceptor != null) {
  471. sslSocketAcceptor.unbind();
  472. for (ServerPort port : ports) {
  473. if (port.isClientPort() && port.isSecure()) {
  474. ports.remove(port);
  475. break;
  476. }
  477. }
  478. sslSocketAcceptor = null;
  479. }
  480. }
  481. private void restartClientSSLListeners() {
  482. if (!isSocketStarted) {
  483. return;
  484. }
  485. // Setup port info
  486. try {
  487. localIPAddress = InetAddress.getLocalHost().getHostAddress();
  488. }
  489. catch (UnknownHostException e) {
  490. if (localIPAddress == null) {
  491. localIPAddress = "Unknown";
  492. }
  493. }
  494. stopClientSSLListeners();
  495. createClientSSLListeners();
  496. startClientSSLListeners(localIPAddress);
  497. }
  498. public Collection<ServerPort> getPorts() {
  499. return ports;
  500. }
  501. public SocketReader createSocketReader(Socket sock, boolean isSecure, ServerPort serverPort,
  502. boolean useBlockingMode) throws IOException {
  503. if (serverPort.isServerPort()) {
  504. SocketConnection conn = new SocketConnection(deliverer, sock, isSecure);
  505. return new ServerSocketReader(router, routingTable, serverName, sock, conn,
  506. useBlockingMode);
  507. }
  508. return null;
  509. }
  510. private void startHTTPBindListeners() {
  511. HttpBindManager.getInstance().start();
  512. }
  513. @Override
  514. public void initialize(XMPPServer server) {
  515. super.initialize(server);
  516. serverName = server.getServerInfo().getXMPPDomain();
  517. router = server.getPacketRouter();
  518. routingTable = server.getRoutingTable();
  519. deliverer = server.getPacketDeliverer();
  520. sessionManager = server.getSessionManager();
  521. // Check if we need to configure MINA to use Direct or Heap Buffers
  522. // Note: It has been reported that heap buffers are 50% faster than direct buffers
  523. if (JiveGlobals.getBooleanProperty("xmpp.socket.heapBuffer", true)) {
  524. IoBuffer.setUseDirectBuffer(false);
  525. IoBuffer.setAllocator(new SimpleBufferAllocator());
  526. }
  527. }
  528. public void enableClientListener(boolean enabled) {
  529. if (enabled == isClientListenerEnabled()) {
  530. // Ignore new setting
  531. return;
  532. }
  533. if (enabled) {
  534. JiveGlobals.setProperty(ConnectionSettings.Client.SOCKET_ACTIVE, "true");
  535. // Start the port listener for clients
  536. createClientListeners();
  537. startClientListeners(localIPAddress);
  538. }
  539. else {
  540. JiveGlobals.setProperty(ConnectionSettings.Client.SOCKET_ACTIVE, "false");
  541. // Stop the port listener for clients
  542. stopClientListeners();
  543. }
  544. }
  545. public boolean isClientListenerEnabled() {
  546. return JiveGlobals.getBooleanProperty(ConnectionSettings.Client.SOCKET_ACTIVE, true);
  547. }
  548. public void enableClientSSLListener(boolean enabled) {
  549. if (enabled == isClientSSLListenerEnabled()) {
  550. // Ignore new setting
  551. return;
  552. }
  553. if (enabled) {
  554. JiveGlobals.setProperty(ConnectionSettings.Client.ENABLE_OLD_SSLPORT, "true");
  555. // Start the port listener for secured clients
  556. createClientSSLListeners();
  557. startClientSSLListeners(localIPAddress);
  558. }
  559. else {
  560. JiveGlobals.setProperty(ConnectionSettings.Client.ENABLE_OLD_SSLPORT, "false");
  561. // Stop the port listener for secured clients
  562. stopClientSSLListeners();
  563. }
  564. }
  565. public boolean isClientSSLListenerEnabled() {
  566. try {
  567. return JiveGlobals.getBooleanProperty(ConnectionSettings.Client.ENABLE_OLD_SSLPORT, false) && SSLConfig.getKeyStore().size() > 0;
  568. } catch (KeyStoreException e) {
  569. return false;
  570. } catch (IOException e) {
  571. return false;
  572. }
  573. }
  574. public void enableComponentListener(boolean enabled) {
  575. if (enabled == isComponentListenerEnabled()) {
  576. // Ignore new setting
  577. return;
  578. }
  579. if (enabled) {
  580. JiveGlobals.setProperty(ConnectionSettings.Component.SOCKET_ACTIVE, "true");
  581. // Start the port listener for external components
  582. createComponentListener();
  583. startComponentListener();
  584. }
  585. else {
  586. JiveGlobals.setProperty(ConnectionSettings.Component.SOCKET_ACTIVE, "false");
  587. // Stop the port listener for external components
  588. stopComponentListener();
  589. }
  590. }
  591. public boolean isComponentListenerEnabled() {
  592. return JiveGlobals.getBooleanProperty(ConnectionSettings.Component.SOCKET_ACTIVE, false);
  593. }
  594. public void enableServerListener(boolean enabled) {
  595. if (enabled == isServerListenerEnabled()) {
  596. // Ignore new setting
  597. return;
  598. }
  599. if (enabled) {
  600. JiveGlobals.setProperty(ConnectionSettings.Server.SOCKET_ACTIVE, "true");
  601. // Start the port listener for s2s communication
  602. createServerListener(localIPAddress);
  603. startServerListener();
  604. }
  605. else {
  606. JiveGlobals.setProperty(ConnectionSettings.Server.SOCKET_ACTIVE, "false");
  607. // Stop the port listener for s2s communication
  608. stopServerListener();
  609. }
  610. }
  611. public boolean isServerListenerEnabled() {
  612. return JiveGlobals.getBooleanProperty(ConnectionSettings.Server.SOCKET_ACTIVE, true);
  613. }
  614. public void enableConnectionManagerListener(boolean enabled) {
  615. if (enabled == isConnectionManagerListenerEnabled()) {
  616. // Ignore new setting
  617. return;
  618. }
  619. if (enabled) {
  620. JiveGlobals.setProperty(ConnectionSettings.Multiplex.SOCKET_ACTIVE, "true");
  621. // Start the port listener for s2s communication
  622. createConnectionManagerListener();
  623. startConnectionManagerListener(localIPAddress);
  624. }
  625. else {
  626. JiveGlobals.setProperty(ConnectionSettings.Multiplex.SOCKET_ACTIVE, "false");
  627. // Stop the port listener for s2s communication
  628. stopConnectionManagerListener();
  629. }
  630. }
  631. public boolean isConnectionManagerListenerEnabled() {
  632. return JiveGlobals.getBooleanProperty(ConnectionSettings.Multiplex.SOCKET_ACTIVE, false);
  633. }
  634. public void setClientListenerPort(int port) {
  635. if (port == getClientListenerPort()) {
  636. // Ignore new setting
  637. return;
  638. }
  639. JiveGlobals.setProperty(ConnectionSettings.Client.PORT, String.valueOf(port));
  640. // Stop the port listener for clients
  641. stopClientListeners();
  642. if (isClientListenerEnabled()) {
  643. // Start the port listener for clients
  644. createClientListeners();
  645. startClientListeners(localIPAddress);
  646. }
  647. }
  648. public NioSocketAcceptor getSocketAcceptor() {
  649. return socketAcceptor;
  650. }
  651. public int getClientListenerPort() {
  652. return JiveGlobals.getIntProperty(ConnectionSettings.Client.PORT, DEFAULT_PORT);
  653. }
  654. public NioSocketAcceptor getSSLSocketAcceptor() {
  655. return sslSocketAcceptor;
  656. }
  657. public void setClientSSLListenerPort(int port) {
  658. if (port == getClientSSLListenerPort()) {
  659. // Ignore new setting
  660. return;
  661. }
  662. JiveGlobals.setProperty(ConnectionSettings.Client.OLD_SSLPORT, String.valueOf(port));
  663. // Stop the port listener for secured clients
  664. stopClientSSLListeners();
  665. if (isClientSSLListenerEnabled()) {
  666. // Start the port listener for secured clients
  667. createClientSSLListeners();
  668. startClientSSLListeners(localIPAddress);
  669. }
  670. }
  671. public int getClientSSLListenerPort() {
  672. return JiveGlobals.getIntProperty(ConnectionSettings.Client.OLD_SSLPORT, DEFAULT_SSL_PORT);
  673. }
  674. public void setComponentListenerPort(int port) {
  675. if (port == getComponentListenerPort()) {
  676. // Ignore new setting
  677. return;
  678. }
  679. JiveGlobals.setProperty(ConnectionSettings.Component.PORT, String.valueOf(port));
  680. // Stop the port listener for external components
  681. stopComponentListener();
  682. if (isComponentListenerEnabled()) {
  683. // Start the port listener for external components
  684. createComponentListener();
  685. startComponentListener();
  686. }
  687. }
  688. public NioSocketAcceptor getComponentAcceptor() {
  689. return componentAcceptor;
  690. }
  691. public int getComponentListenerPort() {
  692. return JiveGlobals.getIntProperty(ConnectionSettings.Component.PORT, DEFAULT_COMPONENT_PORT);
  693. }
  694. public void setServerListenerPort(int port) {
  695. if (port == getServerListenerPort()) {
  696. // Ignore new setting
  697. return;
  698. }
  699. JiveGlobals.setProperty(ConnectionSettings.Server.PORT, String.valueOf(port));
  700. // Stop the port listener for s2s communication
  701. stopServerListener();
  702. if (isServerListenerEnabled()) {
  703. // Start the port listener for s2s communication
  704. createServerListener(localIPAddress);
  705. startServerListener();
  706. }
  707. }
  708. public int getServerListenerPort() {
  709. return JiveGlobals.getIntProperty(ConnectionSettings.Server.PORT, DEFAULT_SERVER_PORT);
  710. }
  711. public NioSocketAcceptor getMultiplexerSocketAcceptor() {
  712. return multiplexerSocketAcceptor;
  713. }
  714. public void setConnectionManagerListenerPort(int port) {
  715. if (port == getConnectionManagerListenerPort()) {
  716. // Ignore new setting
  717. return;
  718. }
  719. JiveGlobals.setProperty(ConnectionSettings.Multiplex.PORT, String.valueOf(port));
  720. // Stop the port listener for connection managers
  721. stopConnectionManagerListener();
  722. if (isConnectionManagerListenerEnabled()) {
  723. // Start the port listener for connection managers
  724. createConnectionManagerListener();
  725. startConnectionManagerListener(localIPAddress);
  726. }
  727. }
  728. public int getConnectionManagerListenerPort() {
  729. return JiveGlobals.getIntProperty(ConnectionSettings.Multiplex.PORT, DEFAULT_MULTIPLEX_PORT);
  730. }
  731. // #####################################################################
  732. // Certificates events
  733. // #####################################################################
  734. public void certificateCreated(KeyStore keyStore, String alias, X509Certificate cert) {
  735. restartClientSSLListeners();
  736. }
  737. public void certificateDeleted(KeyStore keyStore, String alias) {
  738. restartClientSSLListeners();
  739. }
  740. public void certificateSigned(KeyStore keyStore, String alias, List<X509Certificate> certificates) {
  741. restartClientSSLListeners();
  742. }
  743. private NioSocketAcceptor buildSocketAcceptor(String name) {
  744. NioSocketAcceptor socketAcceptor;
  745. // Create SocketAcceptor with correct number of processors
  746. int processorCount = JiveGlobals.getIntProperty("xmpp.processor.count", Runtime.getRuntime().availableProcessors());
  747. socketAcceptor = new NioSocketAcceptor(processorCount);
  748. // Set that it will be possible to bind a socket if there is a connection in the timeout state
  749. socketAcceptor.setReuseAddress(true);
  750. // Set the listen backlog (queue) length. Default is 50.
  751. socketAcceptor.setBacklog(JiveGlobals.getIntProperty("xmpp.socket.backlog", 50));
  752. // Set default (low level) settings for new socket connections
  753. SocketSessionConfig socketSessionConfig = socketAcceptor.getSessionConfig();
  754. //socketSessionConfig.setKeepAlive();
  755. int receiveBuffer = JiveGlobals.getIntProperty("xmpp.socket.buffer.receive", -1);
  756. if (receiveBuffer > 0 ) {
  757. socketSessionConfig.setReceiveBufferSize(receiveBuffer);
  758. }
  759. int sendBuffer = JiveGlobals.getIntProperty("xmpp.socket.buffer.send", -1);
  760. if (sendBuffer > 0 ) {
  761. socketSessionConfig.setSendBufferSize(sendBuffer);
  762. }
  763. int linger = JiveGlobals.getIntProperty("xmpp.socket.linger", -1);
  764. if (linger > 0 ) {
  765. socketSessionConfig.setSoLinger(linger);
  766. }
  767. socketSessionConfig.setTcpNoDelay(
  768. JiveGlobals.getBooleanProperty("xmpp.socket.tcp-nodelay", socketSessionConfig.isTcpNoDelay()));
  769. if (JMXManager.isEnabled()) {
  770. configureJMX(socketAcceptor, name);
  771. }
  772. return socketAcceptor;
  773. }
  774. private void configureJMX(NioSocketAcceptor acceptor, String suffix) {
  775. final String prefix = IoServiceMBean.class.getPackage().getName();
  776. // monitor the IoService
  777. try {
  778. IoServiceMBean mbean = new IoServiceMBean(acceptor);
  779. MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
  780. ObjectName name = new ObjectName(prefix + ":type=SocketAcceptor,name=" + suffix);
  781. mbs.registerMBean( mbean, name );
  782. // mbean.startCollectingStats(JiveGlobals.getIntProperty("xmpp.socket.jmx.interval", 60000));
  783. } catch (JMException ex) {
  784. Log.warn("Failed to register MINA acceptor mbean (JMX): " + ex);
  785. }
  786. // optionally register IoSession mbeans (one per session)
  787. if (JiveGlobals.getBooleanProperty("xmpp.socket.jmx.sessions", false)) {
  788. acceptor.addListener(new IoServiceListener() {
  789. public void sessionCreated(IoSession session) {
  790. try {
  791. IoSessionMBean mbean = new IoSessionMBean(session);
  792. MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
  793. ObjectName name = new ObjectName(prefix + ":type=IoSession,name=" +
  794. session.getRemoteAddress().toString().replace(':', '/'));
  795. mbs.registerMBean(mbean, name);
  796. } catch(JMException ex) {
  797. Log.warn("Failed to register MINA session mbean (JMX): " + ex);
  798. }
  799. }
  800. public void sessionDestroyed(IoSession session) {
  801. try {
  802. ObjectName name = new ObjectName(prefix + ":type=IoSession,name=" +
  803. session.getRemoteAddress().toString().replace(':', '/'));
  804. ManagementFactory.getPlatformMBeanServer().unregisterMBean(name);
  805. } catch(JMException ex) {
  806. Log.warn("Failed to unregister MINA session mbean (JMX): " + ex);
  807. }
  808. }
  809. public void serviceActivated(IoService service) throws Exception { }
  810. public void serviceDeactivated(IoService service) throws Exception { }
  811. public void serviceIdle(IoService service, IdleStatus idleStatus) throws Exception { }
  812. public void sessionClosed(IoSession ioSession) throws Exception { }
  813. });
  814. }
  815. }
  816. private int getCorePoolSize(int maxPoolSize) {
  817. return (maxPoolSize/4)+1;
  818. }
  819. // #####################################################################
  820. // Module management
  821. // #####################################################################
  822. @Override
  823. public void start() {
  824. super.start();
  825. createListeners();
  826. startListeners();
  827. SocketSendingTracker.getInstance().start();
  828. CertificateManager.addListener(this);
  829. }
  830. @Override
  831. public void stop() {
  832. super.stop();
  833. stopClientListeners();
  834. stopClientSSLListeners();
  835. stopComponentListener();
  836. stopConnectionManagerListener();
  837. stopServerListener();
  838. HttpBindManager.getInstance().stop();
  839. SocketSendingTracker.getInstance().shutdown();
  840. CertificateManager.removeListener(this);
  841. serverName = null;
  842. }
  843. private static class DelegatingThreadFactory implements ThreadFactory {
  844. private final AtomicInteger threadId;
  845. private final ThreadFactory originalThreadFactory;
  846. private String threadNamePrefix;
  847. public DelegatingThreadFactory(String threadNamePrefix, ThreadFactory originalThreadFactory) {
  848. this.originalThreadFactory = originalThreadFactory;
  849. threadId = new AtomicInteger(0);
  850. this.threadNamePrefix = threadNamePrefix;
  851. }
  852. public Thread newThread(Runnable runnable)
  853. {
  854. Thread t = originalThreadFactory.newThread(runnable);
  855. t.setName(threadNamePrefix + threadId.incrementAndGet());
  856. t.setDaemon(true);
  857. return t;
  858. }
  859. }
  860. }