Java tutorial
/* * Copyright (c) 2008 Massimiliano Ziccardi * * 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 it.jnrpe.server; import it.jnrpe.server.config.CBinding; import it.jnrpe.server.config.CHost; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.net.BindException; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; import java.security.KeyManagementException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.net.ServerSocketFactory; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLException; import javax.net.ssl.SSLServerSocket; import javax.net.ssl.SSLServerSocketFactory; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Thread that listen on a given IP:PORT. * * @author Massimiliano Ziccardi */ public class CBindingThread extends Thread { private Log m_Logger = LogFactory.getLog(CBindingThread.class); private ServerSocket m_serverSocket = null; private CBinding m_Binding = null; private List m_vAcceptedHosts = new ArrayList(); private CThreadFactory m_threadFactory = null; public CBindingThread(CBinding binding) throws IOException { m_Binding = binding; try { init(); } catch (Exception e) { throw new BindException(e.getMessage()); } } /** * Returns the SSL factory to be used to create the Server Socket * @throws KeyStoreException * @throws IOException * @throws FileNotFoundException * @throws CertificateException * @throws UnrecoverableKeyException * @throws KeyManagementException * * @see it.intesa.fi2.client.network.ISSLObjectsFactory#getSSLSocketFactory(String, String, String) */ public SSLServerSocketFactory getSSLSocketFactory(String sKeyStoreFile, String sKeyStorePwd, String sKeyStoreType) throws KeyStoreException, CertificateException, FileNotFoundException, IOException, UnrecoverableKeyException, KeyManagementException { if (sKeyStoreFile == null) throw new KeyStoreException("KEYSTORE HAS NOT BEEN SPECIFIED"); if (this.getClass().getClassLoader().getResourceAsStream(sKeyStoreFile) == null) throw new KeyStoreException("COULD NOT FIND KEYSTORE '" + sKeyStoreFile + "'"); if (sKeyStorePwd == null) throw new KeyStoreException("KEYSTORE PASSWORD HAS NOT BEEN SPECIFIED"); SSLContext ctx; KeyManagerFactory kmf; try { ctx = SSLContext.getInstance("SSLv3"); kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); //KeyStore ks = getKeystore(sKeyStoreFile, sKeyStorePwd, sKeyStoreType); KeyStore ks = KeyStore.getInstance(sKeyStoreType); ks.load(this.getClass().getClassLoader().getResourceAsStream(sKeyStoreFile), sKeyStorePwd.toCharArray()); char[] passphrase = sKeyStorePwd.toCharArray(); kmf.init(ks, passphrase); ctx.init(kmf.getKeyManagers(), null, new java.security.SecureRandom()); } catch (NoSuchAlgorithmException e) { throw new SSLException("Unable to initialize SSLSocketFactory.\n" + e.getMessage()); } return ctx.getServerSocketFactory(); } private void init() throws IOException, KeyManagementException, KeyStoreException, CertificateException, UnrecoverableKeyException { InetAddress addr = InetAddress.getByName(m_Binding.getIP()); ServerSocketFactory sf = null; if (m_Binding.useSSL()) sf = getSSLSocketFactory(m_Binding.getKeyStoreFile(), m_Binding.getKeyStorePassword(), "JKS"); else sf = ServerSocketFactory.getDefault(); m_serverSocket = sf.createServerSocket(m_Binding.getPort(), 0, addr); //m_serverSocket.setSoTimeout(10000); //Ten seconds timeout added by oriol.lopez if (m_serverSocket instanceof SSLServerSocket) ((SSLServerSocket) m_serverSocket) .setEnabledCipherSuites(((SSLServerSocket) m_serverSocket).getSupportedCipherSuites()); // Init the thread factory m_threadFactory = new CThreadFactory(m_Binding.getThreadFactoryConfig()); } public void setAcceptedHosts(List vHosts) { m_vAcceptedHosts = vHosts; } @Override public void run() { if (m_Logger.isInfoEnabled()) m_Logger.info("LISTENING TO " + m_Binding.getIP() + ":" + m_Binding.getPort()); try { while (!this.isInterrupted()) { Socket clientSocket = m_serverSocket.accept(); if (clientSocket != null) { if (!canAccept(clientSocket.getInetAddress())) { if (m_Logger.isInfoEnabled()) m_Logger.info("REFUSING CONNECTION FROM " + clientSocket.getInetAddress()); clientSocket.close(); continue; } if (m_Logger.isDebugEnabled()) m_Logger.trace("ACCEPTING CONNECTION FROM " + clientSocket.getInetAddress()); // JNRPEServerThread kk = new JNRPEServerThread(clientSocket); JNRPEServerThread kk = m_threadFactory.createNewThread(clientSocket); // CJNRPEServer.getThreadTimeoutWatcher().watch(kk); kk.start(); } } } catch (SocketException se) { // This exception is thrown when the server socket is closed. // Ignoring } catch (Exception e) { m_Logger.error("INTERNAL ERROR: " + e.getMessage(), e); } m_Logger.info("STOP LISTENING TO " + m_Binding.getIP() + ":" + m_Binding.getPort()); exit(); } private synchronized void exit() { notify(); } public synchronized void close() { m_Logger.warn("CLOSING THREAD"); try { m_serverSocket.close(); m_threadFactory.shutdown(); } catch (IOException e) { } } private boolean canAccept(InetAddress inetAddress) { for (Iterator iterator = m_vAcceptedHosts.iterator(); iterator.hasNext();) { CHost host = (CHost) iterator.next(); if (host.getInetAddress() != null && host.getInetAddress().equals(inetAddress)) return true; } return false; } }