summaryrefslogblamecommitdiffstats
path: root/src/main/java/org/openslx/imagemaster/serverconnection/ConnectionHandler.java
blob: 7fa9c4e8eefff64aa74fc95fd237cdad65b398d6 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12

                                                 
                    








                                               
                      
                     
                                              










                                              


                                                         
                                                                       


                                                       
 

                                                                                

                                                                                       
                                                                            


                                         
                
                                                                                       
                     











                                                                                                                         
                                                                
                                         

                                                                             
                                         

                                                                     
                                         

                                                            
                                         

                                                              
                                         

                                                                    
                                         

                                                                      
                                         

                 
 

                                                    

                                                    


                                                          
                                         
           
                                                                                             
         






                                                                                                                                 
         
 

                                                           
                                                        
         
 

                                                           


                                                                                                       







                                                                            
                                        

                                               






                                                                        
                 






                                                                                                
 
                                                                                                       


                                                                    
                                                
                                                           
                                                                                                                                                   
                                                      
                 

                                 
         
 





                                                                                  
                                                      
                                      
                                  
                                        
                                                     
                                                             

                                                                  



                                                                                  
 
                                                                    
 


                                                                 
 
                                                             
                                                                                        

                                                                                                          

                                       

                                                                                     



                                                                                                                                           

                                                                                          
                                                
                 
                                   

         
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.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

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.
 * Also handles the authentication and the saving/delivering of images.
 */
public class ConnectionHandler implements IncomingEvent
{

	private static Logger log = Logger.getLogger( ConnectionHandler.class );
	private static SSLContext sslContext;

	private static Map<String, Connection> connections = new ConcurrentHashMap<>();
	private static IncomingEvent eventHandler = new ConnectionHandler();

	private static Listener listener;

	static {
		log.debug( "Starting listener on port " + Globals.getSslSocketPort() );
		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 );
			listener = new Listener( eventHandler, sslContext, Globals.getSslSocketPort() );
			listener.start();
		} 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.
	 * To up- or download the file in file path.
	 * 
	 * @param token The unique token
	 * @param filepath The file to up- or download
	 * @param type True if upload or false if download
	 * @return The created connection
	 */
	public static Connection addConnection( String token, String filepath, boolean type )
	{
		log.debug( "Added connection (" + ( ( type ) ? "uploading" : "downloading" ) + ") with token: '" + token + "'" );

		Connection connection = new Connection( filepath, type );
		synchronized ( connections ) {
			connections.put( token, connection );
		}
		return connection;
	}

	public static boolean hasConnection( String token )
	{
		return connections.containsKey( token );
	}

	public static void removeConnection( String token )
	{
		synchronized ( connections ) {
			connections.remove( token );	// token is remove, so connections are rejected
		}
	}

	/**
	 * Server is uploading - client is downloading!
	 */
	@Override
	public void incomingUploader( Uploader uploader ) throws IOException
	{
		// try to read meta data
		if ( !uploader.readMetaData() )
			return;
		String token = uploader.getToken();
		log.debug( "Got token :'" + token + "'" );
		// check token to identify the client
		if ( !connections.containsKey( token ) ) {
			uploader.sendErrorCode( "Token not accepted." );
			uploader.close();
			return;
		}

		// check if he was a downloading client
		if ( connections.get( token ).type == Connection.UPLOADING ) {
			uploader.sendErrorCode( "You can not download, if you are uploading." );
			uploader.close();
			return;
		}

		List<Integer> blocks = connections.get( token ).client.getLastRequestedBlocks( token );
		String fileName = connections.get( token ).filepath;
		long fileSize = new File( fileName ).length();
		long actual;
		for ( Integer block : blocks ) {
			actual = block * Globals.blockSize;
			uploader.sendRange( actual, ( ( fileSize - actual ) < Globals.blockSize ) ? fileSize : ( block + 1 ) * Globals.blockSize );
			uploader.sendFile( fileName );
		}
		uploader.close();

	}

	/**
	 * Server is downloading - client is uploading!
	 */
	@Override
	public void incomingDownloader( Downloader downloader ) throws IOException
	{
		log.debug( "Client wants to upload" );
		long startOfRange = 0;
		String token = "";
		// try to read meta data
		while ( downloader.readMetaData() ) {
			// check token to identify the client
			token = downloader.getToken();
			if ( !connections.containsKey( token ) ) {
				downloader.sendErrorCode( "Token not accepted." );
				downloader.close();
				return;
			}

			startOfRange = downloader.getStartOfRange();

			if ( downloader.getDiffOfRange() <= 0 ) {
				return;
			}

			// check if he was a uploading client
			if ( connections.get( token ).type == Connection.DOWNLOADING ) {
				downloader.sendErrorCode( "You can not upload, if you are downloading." );
				downloader.close();
				return;
			}

			int blockNumber = (int) ( startOfRange / Globals.blockSize );
			UploadingImage image = connections.get( token ).image;
			image.setNeedsCheck( blockNumber );
			image.increaseTransmittedTimes( blockNumber );
			log.debug( "Block " + blockNumber + " was transmitted " + image.getTimesTransmitted( blockNumber ) + " time(s)." );

			downloader.setOutputFilename( connections.get( token ).filepath );
			downloader.readBinary();
		}
		downloader.close();
	}
}