blob: 61edf86e894ffdd62c514b5ab298c17574690710 (
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.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();
}
}
|