|
|
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);
}
}
|