blob: 7fa9c4e8eefff64aa74fc95fd237cdad65b398d6 (
plain) (
tree)
|
|
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();
}
}
|