summaryrefslogblamecommitdiffstats
path: root/src/main/java/org/openslx/imagemaster/serverconnection/ConnectionHandler.java
blob: 0fb52f504a4342f858a83cf704ea63d914087fa3 (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.FileRange;
import org.openslx.filetransfer.IncomingEvent;
import org.openslx.filetransfer.Listener;
import org.openslx.filetransfer.Uploader;
import org.openslx.filetransfer.WantRangeCallback;
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
	{
		String token = uploader.getToken();
		log.debug( "Got token :'" + token + "'" );
		// check token to identify the client
		if (token == null)
		{
			uploader.sendErrorCode( "No token available." );
			uploader.close(null);
			return;
		}
		if ( !connections.containsKey( token ) ) {
			uploader.sendErrorCode( "Token not accepted." );
			uploader.close(null);
			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(null);
			return;
		}

		String fileName = connections.get( token ).filepath;
		uploader.upload(fileName);
	}

	/**
	 * Server is downloading - client is uploading!
	 */
	@Override
	public void incomingDownloader( Downloader downloader ) throws IOException
	{
		log.debug( "Client wants to upload" );
		String token = downloader.getToken();
		if (token == null)
		{
			downloader.sendErrorCode( "No token available." );
		    downloader.close(null);
			return;
		}
		// Check token to identify the client.
		if ( !connections.containsKey( token ) ) {
			downloader.sendErrorCode( "Token not accepted." );
			downloader.close(null);
			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(null);
			return;
		}
		
		String destinationFileName = connections.get( token ).filepath;
		final UploadingImage image = connections.get( token ).image;
		downloader.download( destinationFileName, new WantRangeCallback() {
			
			@Override
			public FileRange get() {
				// get start of range.
				int blockNumber = image.getNextMissingBlock();
				if (blockNumber == -1)
					return null;
				
				image.setNeedsCheck( blockNumber );
				image.increaseTransmittedTimes( blockNumber );
				log.debug( "Block " + blockNumber + " was transmitted " + image.getTimesTransmitted( blockNumber ) + " time(s)." );
				
				long startOfRange =  image.getNextMissingBlock() * Globals.blockSize;
				long endOfRange = Math.min(startOfRange + Globals.blockSize, image.getImageFile().length());
				FileRange range = new FileRange(startOfRange, endOfRange);
				return range;
			}
		});
//		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(null);
//				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(null);
//				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.receiveBinary();
//		}
		downloader.close(null);
	}
}