package org.openslx.satellitedaemon.filetransfer;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.security.InvalidKeyException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.List;
import org.apache.log4j.Logger;
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TNonblockingSocket;
import org.apache.thrift.transport.TTransport;
import org.openslx.imagemaster.crcchecker.CrcFile;
import org.openslx.imagemaster.thrift.iface.AuthorizationError;
import org.openslx.imagemaster.thrift.iface.AuthorizationException;
import org.openslx.imagemaster.thrift.iface.DownloadInfos;
import org.openslx.imagemaster.thrift.iface.ImageData;
import org.openslx.imagemaster.thrift.iface.ImageDataError;
import org.openslx.imagemaster.thrift.iface.ImageDataException;
import org.openslx.imagemaster.thrift.iface.ImageServer;
import org.openslx.imagemaster.thrift.iface.ServerAuthenticationException;
import org.openslx.imagemaster.thrift.iface.ServerSessionData;
import org.openslx.imagemaster.thrift.iface.UploadError;
import org.openslx.imagemaster.thrift.iface.UploadException;
import org.openslx.imagemaster.thrift.iface.UploadInfos;
import org.openslx.satellitedaemon.Globals;
import org.openslx.satellitedaemon.Globals.PropInt;
import org.openslx.satellitedaemon.Globals.PropString;
import org.openslx.satellitedaemon.db.DbImage;
import org.openslx.satellitedaemon.util.EncryptWithServerIdPublicKey;
// TODO: Handle all the auto-generated catch blocks in a meaningful way
/***********************************************************************************************/
/**
* Handles the authentication with the Satellite Server and sends the FILTRANSFERCredentials, which
* are necessary for the upload of the image.
*/
public class ThriftConnection
{
private static ImageServer.Client client = null;
private static ServerSessionData sSD = null;
private static Logger log = Logger.getLogger( ThriftConnection.class );
private static CrcFile crc = null;
/***********************************************************************************************/
/**
* Method for getting UploadeInfos
*
* !! on the first Call !!
*
* when the CRCsum need to be transfered.
* The method calls getConnection() to check if the connection is ok
* and to get the ServerSessionData. If connection is ok, it calls
* submitImage with CRCsum in List<Integer>.
*
* @return returns 'null' if there is a problem.
*/
public static UploadInfos getUploadInfos( ImageData imDat, String filename )
{
ImageServer.Client theClient = null;
try {
theClient = getConnection();
if ( theClient == null ) {
log.error( "Client was null!" );
return null;
}
// .submitImage needs the List<Integer> from CRCFile.getCRCs() only
// on the first time called. null afterwards.
log.info( "First call of submitImage following..." );
crc = new CrcFile( filename );
log.info( "Made CRCFile from " + filename );
log.info( "crc.getCrcSums( ).size = " + crc.getCrcSums().size() );
// log.info( "crc.getMasterSum() : " + crc.getMasterSum() );
// for ( int i = 0; i < crc.getCrcSums().size() - 1; i++ ) {
// log.info( "crc.getCRCSum() : " + crc.getCRCSum( i ) );
// }
return theClient.submitImage( sSD.sessionId, imDat, crc.getCrcSums() );
} catch ( ImageDataException e ) {
if ( e.isSetNumber() && e.getNumber().equals( ImageDataError.INVALID_DATA ) ) {
// Data in the db is not valid
// TODO: add e.message into DB;
} else {
e.printStackTrace();
}
} catch ( UploadException e ) {
if ( e.isSetNumber() && e.getNumber().equals( UploadError.BROKEN_BLOCK ) ) {
// A Block was transmitted 20 times unsuccessfully.
// TODO: Mark the Image as corrupted.
} else if ( e.getNumber().equals( UploadError.INVALID_CRC ) ) {
// The CRC sum contained errors
crc = new CrcFile( filename );
try {
if ( !crc.isValid() ) {
//TODO: Mark CRC-file as corrupted.
}
} catch ( IOException e1 ) {
log.error( "IOERROR, while reading from CRC File" + filename );
}
} else {
e.printStackTrace();
}
} catch ( AuthorizationException e ) {
if ( e.isSetNumber() && e.getNumber().equals( AuthorizationError.NOT_AUTHENTICATED ) ) {
// SessionID is not valid
// TODO: Code for new SSID
} else if ( e.getNumber().equals( AuthorizationError.NO_PERMISSION ) ) {
//Gibts noch gar nicht
} else {
e.printStackTrace();
}
} catch ( UnrecoverableKeyException e ) {
log.error( "UnrecoverableKeyException" );
e.printStackTrace();
} catch ( InvalidKeyException e ) {
log.error( "InvalidKeyException" );
e.printStackTrace();
} catch ( NoSuchAlgorithmException e ) {
log.error( "NoSuchAlgorithmException" );
e.printStackTrace();
} catch ( CertificateException e ) {
log.error( "CertificateException" );
e.printStackTrace();
} catch ( FileNotFoundException e ) {
log.error( "FileNotFoundException" );
e.printStackTrace();
} catch ( KeyStoreException e ) {
log.error( "KeyStoreException" );
e.printStackTrace();
} catch ( SignatureException e ) {
log.error( "SignatureException" );
e.printStackTrace();
} catch ( IOException e ) {
log.error( "IOException" );
e.printStackTrace();
} catch ( TException e ) {
log.error( "TException" );
e.printStackTrace();
}
return null;
}
/***********************************************************************************************/
/**
* Method for getting UploadeInfos when CRCsum was already transfered on first call.
* The method calls getConnection() to check if the connection is ok
* and to get the ServerSessionData. If connection is ok, it calls
* submitImage with sSD.sessionId, imDat and !!null!!
*
* @return returns 'null' if there is a problem.
*/
public static UploadInfos getUploadInfos( ImageData imDat )
{
ImageServer.Client theClient = null;
try {
theClient = getConnection();
if ( theClient == null ) {
log.error( "Client was null!" );
return null;
}
// .submitImage needs the List<Integer> from CRCFile.getCRCs() only
// on the first time called. null afterwards. --Was the plan. So far not working I guess.
return theClient.submitImage( sSD.sessionId, imDat, crc.getCrcSums() );
} catch ( ImageDataException e ) {
if ( e.isSetNumber() && e.getNumber().equals( ImageDataError.INVALID_DATA ) ) {
// Data in the db is not valid
//TODO: add e.message into DB;
} else {
e.printStackTrace();
}
} catch ( UploadException e ) {
if ( e.isSetNumber() && e.getNumber().equals( UploadError.BROKEN_BLOCK ) ) {
// A Block was transmitted 20 times unsuccessfully.
// TODO: Mark the Image as corrupted.
} else if ( e.getNumber().equals( UploadError.INVALID_CRC ) ) {
// The CRC sum contained errors
try {
if ( !crc.isValid() ) {
//TODO: Mark CRC-file as corrupted.
}
} catch ( IOException e1 ) {
log.error( "IOERROR, while reading from CRC File" );
}
} else {
e.printStackTrace();
}
} catch ( AuthorizationException e ) {
if ( e.isSetNumber() && e.getNumber().equals( AuthorizationError.NOT_AUTHENTICATED ) ) {
// SessionID is not valid
// TODO: Code for new SSID
} else if ( e.getNumber().equals( AuthorizationError.NO_PERMISSION ) ) {
} else {
e.printStackTrace();
}
} catch ( UnrecoverableKeyException e ) {
log.error( "UnrecoverableKeyException" );
e.printStackTrace();
} catch ( InvalidKeyException e ) {
log.error( "InvalidKeyException" );
e.printStackTrace();
} catch ( NoSuchAlgorithmException e ) {
log.error( "NoSuchAlgorithmException" );
e.printStackTrace();
} catch ( CertificateException e ) {
log.error( "CertificateException" );
e.printStackTrace();
} catch ( FileNotFoundException e ) {
log.error( "FileNotFoundException" );
e.printStackTrace();
} catch ( KeyStoreException e ) {
log.error( "KeyStoreException" );
e.printStackTrace();
} catch ( SignatureException e ) {
log.error( "SignatureException" );
e.printStackTrace();
} catch ( IOException e ) {
log.error( "IOException" );
e.printStackTrace();
} catch ( TException e ) {
log.error( "TException" );
e.printStackTrace();
}
return null;
}
/***********************************************************************************************/
/**
* Method for getting DonwloadInfos. Calls getConnection if client was null.
* You need to spezifie all Blocks you want to have in an List.
*
* @return returns 'null' if there is a problem.
*/
public static DownloadInfos getDownloadInfos( DbImage imDat, List<Integer> range )
{
ImageServer.Client theClient = null;
try {
theClient = getConnection();
if ( theClient == null ) {
log.error( "Client was null!" );
return null;
}
return theClient.getImage( imDat.guid, sSD.sessionId, range );
} catch ( ImageDataException e ) {
if ( e.isSetNumber() && e.getNumber().equals( ImageDataError.INVALID_DATA ) ) {
// Data in the db is not valid
//TODO: add e.message into DB;
} else if ( e.getNumber().equals( ImageDataError.UNKNOWN_IMAGE ) ) {
// The image requested is not known.
//TODO: change field image_syncMode, so the image is not asked for again.
// Plus add a note in some way to mark as unknown by Server
} else {
e.printStackTrace();
}
} catch ( AuthorizationException e ) {
if ( e.isSetNumber() && e.getNumber().equals( AuthorizationError.NOT_AUTHENTICATED ) ) {
// SessionID is not valid
// TODO: Code for new SSID
} else if ( e.getNumber().equals( AuthorizationError.NO_PERMISSION ) ) {
} else {
e.printStackTrace();
}
} catch ( UnrecoverableKeyException e ) {
log.error( "UnrecoverableKeyException" );
e.printStackTrace();
} catch ( InvalidKeyException e ) {
log.error( "InvalidKeyException" );
e.printStackTrace();
} catch ( NoSuchAlgorithmException e ) {
log.error( "NoSuchAlgorithmException" );
e.printStackTrace();
} catch ( CertificateException e ) {
log.error( "CertificateException" );
e.printStackTrace();
} catch ( FileNotFoundException e ) {
log.error( "FileNotFoundException" );
e.printStackTrace();
} catch ( KeyStoreException e ) {
log.error( "KeyStoreException" );
e.printStackTrace();
} catch ( SignatureException e ) {
log.error( "SignatureException" );
e.printStackTrace();
} catch ( IOException e ) {
log.error( "IOException" );
e.printStackTrace();
} catch ( TException e ) {
log.error( "TException" );
e.printStackTrace();
}
return null;
}
/***********************************************************************************************/
/**
* This method checks if there is already a working connection. If not,
* newClient() establishes one. Also it does the Authentication if not done
* yet.
*
* @return returns the client if successful.
*/
private static ImageServer.Client getConnection()
throws UnrecoverableKeyException, NoSuchAlgorithmException, CertificateException,
FileNotFoundException, KeyStoreException, IOException, InvalidKeyException, SignatureException
{
ImageServer.Client theClient = null;
boolean isAuthenticated = false;
if ( client == null ) {
log.info( "The global client was null. Making a new client ..." );
theClient = newClient();
if ( theClient == null ) {
log.debug( "ThriftConnection: The client was null after newClient()" );
return null;
}
} else {
log.info( "The global Client was already used. Setting isAuthenticated = true." );
theClient = client;
isAuthenticated = true;
}
// try {
// isAuthenticated = theClient.ping();
// } catch ( TException x ) {
// theClient = newClient();
// if ( theClient == null ) {
// return null;
// }
// }
if ( !isAuthenticated ) {
log.info( "ThriftConnection: Client not yet Authenticated. Trying..." );
String toEncrypt;
if ( theClient == null ) {
log.debug( "The client was null" );
return null;
}
try {
toEncrypt = theClient.startServerAuthentication( Globals.getPropertyString( PropString.THRIFTORGANIZATIONNAME ) );
log.info( "The random String we want to encrypt: " + toEncrypt );
EncryptWithServerIdPublicKey rse = new EncryptWithServerIdPublicKey( Globals.getPropertyString( PropString.RNDSTRINGENCRYPTALIAS ),
Globals.getPropertyString( PropString.RNDSTRINGENCRYPTPASSWORD ),
Globals.getPropertyString( PropString.RNDSTRINGENCRYPTPATH ) );
byte[] byteArray = rse.encryptString( toEncrypt );
sSD = theClient.serverAuthenticate(
Globals.getPropertyString( PropString.THRIFTORGANIZATIONNAME ), ByteBuffer.wrap( byteArray ) );
} catch ( ServerAuthenticationException e ) {
log.error( "ThriftConnection: ServerAuthenticationException: Server Authetication was not sucessful." );
e.printStackTrace();
return null;
} catch ( TException e ) {
log.error( "ThriftConnection: TException: Server Authetication was not sucessful." );
e.printStackTrace();
return null;
}
log.info( "is Authenticated." );
}
client = theClient;
return theClient;
}
/***********************************************************************************************/
/**
*
* @return
* @throws IOException
*/
private static ImageServer.Client newClient() throws IOException
{
ImageServer.Client newClient = null;
try {
TTransport transport;
transport = new TNonblockingSocket( Globals.getPropertyString( PropString.FILETRANSFERSERVERIP ), Globals.getPropertyInt( PropInt.THRIFTPORT ) );
transport.open();
TProtocol protocol = new TBinaryProtocol( transport );
newClient = new ImageServer.Client( protocol );
log.debug( "ThriftConnection: Made a new Client" );
} catch ( TException x ) {
log.error( "ThriftConnection coudn't create new client." );
x.printStackTrace();
return null;
}
return newClient;
}
}