package org.openslx.imagemaster.serverconnection; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; 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.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import javax.net.ssl.KeyManager; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import org.apache.log4j.Logger; import org.openslx.filetransfer.Downloader; import org.openslx.filetransfer.IncomingEvent; import org.openslx.filetransfer.Listener; import org.openslx.filetransfer.Uploader; import org.openslx.imagemaster.Globals; /** * Class to handle all incoming and outgoing connections. */ public class ConnectionHandler implements IncomingEvent { private static Logger log = Logger.getLogger( ConnectionHandler.class ); private static SSLContext sslContext; /** * Key: token, * Value: Tuple of the listener and the filepath. */ private static Map activeListeners = new HashMap<>(); private static List possiblePorts = new LinkedList<>(); private static IncomingEvent eventHandler = new ConnectionHandler(); static { possiblePorts.add( 1234 ); possiblePorts.add( 1235 ); possiblePorts.add( 1236 ); possiblePorts.add( 1237 ); possiblePorts.add( 1238 ); possiblePorts.add( 1239 ); possiblePorts.add( 1240 ); possiblePorts.add( 1241 ); possiblePorts.add( 1242 ); possiblePorts.add( 1243 ); possiblePorts.add( 1244 ); try { String pathToKeyStore = Globals.getSslKeystoreFile(); char[] passphrase = Globals.getSslKeystorePassword().toCharArray(); KeyStore keystore = KeyStore.getInstance("JKS"); keystore.load(new FileInputStream(pathToKeyStore), passphrase); KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); kmf.init(keystore, passphrase); sslContext = SSLContext.getInstance("SSLv3"); KeyManager[] keyManagers = kmf.getKeyManagers(); sslContext.init(keyManagers, null, null); } catch (FileNotFoundException e) { log.error( "Could not find keystore." ); System.exit( 2 ); } catch ( KeyStoreException e ) { log.error( "KeyStore implemenation not supported." ); System.exit( 2 ); } catch ( NoSuchAlgorithmException e ) { log.error( "Could not find such Algorithm" ); System.exit( 2 ); } catch ( CertificateException e ) { log.error( "Certificate unvalid." ); System.exit( 2 ); } catch ( IOException e ) { log.error( "Could not read keyfile" ); System.exit( 2 ); } catch ( UnrecoverableKeyException e ) { log.error( "Key in keystore is not valid" ); System.exit( 2 ); } catch ( KeyManagementException e ) { log.error( "Context initialization failed." ); System.exit( 2 ); } } /** * Add a new connection with a unique token. * Tp up- or download the file in filepath. * @param token The unique token * @param filepath The file to up- or download * @param type True if upload or false if download */ public static void addConnection(String token, String filepath, boolean type) { int port = possiblePorts.remove( 0 ); Listener listener = new Listener( eventHandler, sslContext, port ); listener.start(); activeListeners.put( token, new ConnectionData(filepath, type, listener) ); } public static boolean hasConnection( String token ) { return activeListeners.containsKey( token ); } public static void removeConnection( String token ) { Listener l = activeListeners.remove( token ).listenerThread; l.interrupt(); possiblePorts.add(l.getPort()); // add port back to possible's list } /** * Server is uploading - client is downloading! */ @Override public void incomingUploader( Uploader uploader ) throws IOException { // try to read meta data while ( uploader.readMetaData() ) { String token = uploader.getToken(); // check token to identify the client if ( !activeListeners.containsKey( token )) { uploader.sendErrorCode( "Token not accepted." ); uploader.close(); return; } // check if he was a downloading client if ( activeListeners.get( token ).type == ConnectionData.UPLOADING ) { uploader.sendErrorCode( "You can not download, if you are uploading." ); uploader.close(); return; } // TODO: check which range needs to be sent and send this range long length = ( new File( activeListeners.get( token ).filepath ) ).length(); uploader.sendRange(0, (int)length); uploader.sendFile( activeListeners.get( token ).filepath ); } uploader.close(); } /** * Server is downloading - client is uploading! */ @Override public void incomingDownloader( Downloader downloader ) throws IOException { // try to read meta data while ( downloader.readMetaData() ) { // check token to identify the client String token = downloader.getToken(); if ( !activeListeners.containsKey( token ) ) { downloader.sendErrorCode( "Token not accepted." ); downloader.close(); return; } // check if he was a uploading client if ( activeListeners.get( token ).type == ConnectionData.DOWNLOADING ) { downloader.sendErrorCode( "You can not upload, if you are downloading." ); downloader.close(); return; } downloader.setOutputFilename( activeListeners.get( token ).filepath ); downloader.readBinary(); } downloader.close(); } }