package org.openslx.satellitedaemon.filetransfer; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.ByteBuffer; 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.encryption.AsymEncryptionHandler; import org.openslx.imagemaster.crcchecker.CrcFile; import org.openslx.imagemaster.thrift.iface.AuthenticationException; 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.ServerSessionData; import org.openslx.imagemaster.thrift.iface.UploadData; import org.openslx.imagemaster.thrift.iface.UploadError; import org.openslx.imagemaster.thrift.iface.UploadException; import org.openslx.satellitedaemon.Globals; import org.openslx.satellitedaemon.db.DbImage; import org.openslx.satellitedaemon.db.DbImage.Status; // 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. * * @return returns 'null' if there is a problem. */ public static UploadData getUploadInfos( ImageData imDat, String path ) { ImageServer.Client theClient = null; String crcPath = path.concat( ".crc" ); theClient = getConnection(); if ( theClient == null ) { log.error( "Client was null!" ); return null; } List crcSums = null; try { crc = new CrcFile( crcPath ); log.info( "Made CRCFile from " + crcPath ); 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 ) ); // } crcSums = crc.getCrcSums(); } catch ( FileNotFoundException e ) { log.debug( "crcFile " + crcPath + " not found." ); } catch ( IOException e ) { log.error( "IOException", e ); } try { return theClient.submitImage( sSD.sessionId, imDat, crcSums ); } 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 ) ) { log.error( "No permission for uploading.", e ); // TODO: add error message into database. } else { e.printStackTrace(); } } 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( crcPath ); } catch ( IOException e1 ) { // TODO Auto-generated catch block e1.printStackTrace(); } if ( !crc.isValid() ) { // TODO: Mark CRC-file as corrupted. } } else { e.printStackTrace(); } } catch ( TException e ) { log.error( "TException", e ); } return null; } /***********************************************************************************************/ /** * Method for getting DonwloadInfos. Calls getConnection if client was null. * You need to specify 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; theClient = getConnection(); if ( theClient == null ) { log.error( "Client was null!" ); return null; } try { return theClient.getImage( sSD.sessionId, imDat.guid ); } catch ( ImageDataException e ) { log.debug( "In catch - blog of thrift connection" ); 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 ) ) { log.error( "Not authenticated. SessionID is not valid.", e ); // SessionID is not valid // TODO: Code for new SSID } else if ( e.getNumber().equals( AuthorizationError.NO_PERMISSION ) ) { log.error( "No permission error.", e ); // TODO: add e.message into database. } else { e.printStackTrace(); } } catch ( TException e ) { log.error( "TException", e ); } 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() { 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.isServerAuthenticated( sSD.sessionId ); } catch ( TException x ) { theClient = newClient(); if ( theClient == null ) { return null; } } if ( !isAuthenticated ) { log.info( "ThriftConnection: Client not yet Authenticated. Trying..." ); try { ByteBuffer tmpBuffer = theClient .startServerAuthentication( Globals .getOrganizationName() ); byte[] toEncrypt = new byte[ tmpBuffer.remaining() ]; tmpBuffer.get( toEncrypt ); log.info( "The random String we want to encrypt: " + toEncrypt ); log.info( "Length of the random String : " + toEncrypt.length ); AsymEncryptionHandler aeh = new AsymEncryptionHandler( Globals.getPrivateKey() ); byte[] byteArray = aeh.encryptMessage( 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 ( AuthenticationException e ) { log.error( "ThriftConnection: AuthenticationException: 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() { 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 e ) { log.error( "Transport could not be opened. Couldn't create new client.", e ); return null; } return newClient; } }