summaryrefslogblamecommitdiffstats
path: root/src/main/java/org/openslx/imagemaster/serverconnection/ConnectionHandler.java
blob: 61edf86e894ffdd62c514b5ab298c17574690710 (plain) (tree)
1
2
3

                                                 
                    























                                               











                                                                                
                                                                                     

                                                                            
                                                                                                                  


























                                                                                                          
                                         

                                                                             
                                         

                                                                     
                                         

                                                            
                                         

                                                              
                                         

                                                                    
                                         

                                                                      
                                         


                 





                                                          
                                                              
           
                                                                                    
         
                                                                                           



                                                                                   
                                                                                           
                            








                                                            
                                                                            









                                                                                           











                                                                                              
                                                                                                                          









                                                                                                     








                                                                                  
                                                     

                                                             








                                                                                                          

                                       

                                                                                              
                                                
                 
                                   

         
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<String, ConnectionData> activeListeners = new HashMap<>();
	private static List<Integer> possiblePorts = new LinkedList<>();
	private static IncomingEvent eventHandler = new ConnectionHandler();
	// TODO: There should only ever be one Listener instance in the whole application, running on a fixed port
	
	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
	 * @return The port that was used for this connection.
	 */
	public static int addConnection(String token, String filepath, boolean type)
	{
		int port = possiblePorts.remove( 0 );	//TODO: handle if no ports are left
		Listener listener = new Listener( eventHandler, sslContext, port );
		
		listener.start();
		
		activeListeners.put( token, new ConnectionData(filepath, type, listener) );
		return port;
	}
	
	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." ); // TODO: Why not?
				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();
	}
}