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.TFramedTransport;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;
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.DownloadData;
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.UploadData;
import org.openslx.satellitedaemon.Globals;
import org.openslx.satellitedaemon.db.DbImage;
import org.openslx.satellitedaemon.db.DbImage.Status;
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
*
* 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 UploadData getUploadInfos(ImageData imDat, String filename) {
ImageServer.Client theClient = null;
try {
theClient = getConnection();
if (theClient == null) {
log.error("Client was null!");
return null;
}
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)) {
e.printStackTrace();
// 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 {
crc = new CrcFile(filename);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if (!crc.isValid()) {
// TODO: Mark CRC-file as corrupted.
}
} 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)) {
// not yet implemented.
} 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 DownloadData getDownloadInfos(DbImage imDat) {
ImageServer.Client theClient = null;
try {
theClient = getConnection();
if (theClient == null) {
log.error("Client was null!");
return null;
}
return theClient.getImage(imDat.guid, sSD.sessionId);
} 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.
// For now just changed status of image. Currently no possibility
// for creating new useful state in DB. (Offenburg)
log.info("Image not known. For skipping next time, mark as only_local.");
imDat.updateStatus(Status.only_local);
// 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;
}
// here the client was already used so we are just assuming that the client is still
// authenticated. Should be checked with the ping() method.
// 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
.getOrganizationName());
log.info("The random String we want to encrypt: " + toEncrypt);
log.info("Length of the random String : " + toEncrypt.length());
EncryptWithServerIdPublicKey rse = new EncryptWithServerIdPublicKey(
Globals.getThriftKeystoreAlias(),
Globals.getThriftKeystorePassword(),
Globals.getThriftKeystorePath());
byte[] byteArray = rse.encryptString(toEncrypt);
log.info( "Length of the byteArray of the random string after encryption :" + byteArray.length );
ByteBuffer b = ByteBuffer.wrap( byteArray );
log.info( "Length of the byteBuffer after encryption :" + b.remaining() );
sSD = theClient.serverAuthenticate(
Globals.getOrganizationName(),
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;
}
/***********************************************************************************************/
/**
* Method for creating a new Client for Thrift communication.
*
* @throws IOException
*/
private static ImageServer.Client newClient() throws IOException {
ImageServer.Client newClient = null;
try {
TTransport transport = new TFramedTransport( new TSocket(
Globals.getMasterserverHost(),
Globals.getThriftPort()));
transport.open();
TProtocol protocol = new TBinaryProtocol(transport);
newClient = new ImageServer.Client(protocol);
log.debug("ThriftConnection: Made a new Client");
} catch (TTransportException tte) {
log.error("Transport could not be opened. Couldn't create new client.");
tte.printStackTrace();
return null;
}
return newClient;
}
}