From 036807ab4006bf81188e5324fa53e34b1c7d5ae6 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Fri, 25 Jul 2014 14:20:00 +0200 Subject: [Filetransfer] Add more sanity checks and error handling, remodel class structure, introduce common base class for Uploader and Downloader --- .../java/org/openslx/filetransfer/Uploader.java | 327 +++------------------ 1 file changed, 33 insertions(+), 294 deletions(-) (limited to 'src/main/java/org/openslx/filetransfer/Uploader.java') diff --git a/src/main/java/org/openslx/filetransfer/Uploader.java b/src/main/java/org/openslx/filetransfer/Uploader.java index 60b9dd6..ff74a9a 100644 --- a/src/main/java/org/openslx/filetransfer/Uploader.java +++ b/src/main/java/org/openslx/filetransfer/Uploader.java @@ -1,65 +1,33 @@ package org.openslx.filetransfer; -import java.io.DataInputStream; -import java.io.DataOutputStream; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.net.SocketTimeoutException; -import java.net.UnknownHostException; -import java.nio.charset.StandardCharsets; -import java.security.KeyManagementException; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.cert.CertificateException; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocket; -import javax.net.ssl.SSLSocketFactory; import org.apache.log4j.Logger; -public class Uploader +public class Uploader extends Transfer { - // Some member variables. - private SSLSocketFactory sslSocketFactory; - private SSLSocket satelliteSocket; - private DataOutputStream dataToServer; - private DataInputStream dataFromServer; - private String TOKEN = null; - private String RANGE = null; - private String ERROR = null; - private static Logger log = Logger.getLogger( Uploader.class ); + private static final Logger log = Logger.getLogger( Uploader.class ); /***********************************************************************/ /** - * Constructor for satellite uploader. - * Tries to connect to specific ip and port and sending type of action. + * Actively establish upload connection to given peer. * - * @param ip - * @param port + * @param host Host name or address to connect to + * @param port Port to connect to + * @param context ssl context for establishing a secure connection * @throws IOException - * @throws KeyStoreException - * @throws CertificateException - * @throws NoSuchAlgorithmException - * @throws KeyManagementException - * @throws UnknownHostException */ - public Uploader( String ip, int port, SSLContext context ) + public Uploader( String host, int port, SSLContext context ) throws IOException { - try { - sslSocketFactory = context.getSocketFactory(); - - satelliteSocket = (SSLSocket)sslSocketFactory.createSocket( ip, port ); - satelliteSocket.setSoTimeout( 2000 ); // set socket timeout. - - dataToServer = new DataOutputStream( satelliteSocket.getOutputStream() ); - dataToServer.writeByte( 'U' ); - dataFromServer = new DataInputStream( satelliteSocket.getInputStream() ); - } catch ( Exception e ) { - e.printStackTrace(); - } + super( host, port, context, log ); + dataToServer.writeByte( 'U' ); } /***********************************************************************/ @@ -69,217 +37,23 @@ public class Uploader * * @throws IOException */ - public Uploader( SSLSocket socket ) - { - try { - satelliteSocket = socket; - dataToServer = new DataOutputStream( satelliteSocket.getOutputStream() ); - dataFromServer = new DataInputStream( satelliteSocket.getInputStream() ); - } catch ( IOException e ) { - e.printStackTrace(); - } - } - - /***********************************************************************/ - /** - * Method for sending token from satellite to master. - * Needfull for getting to know what should happens over connection. - * - * @param t - */ - public Boolean sendToken( String token ) - { - try { - TOKEN = token; - String sendToken = "TOKEN=" + TOKEN; - byte[] data = sendToken.getBytes( StandardCharsets.UTF_8 ); - dataToServer.writeByte( data.length ); - dataToServer.write( data ); - } catch ( SocketTimeoutException ste ) { - ste.printStackTrace(); - log.info( "Socket timeout occured ... close connection." ); - this.close(); - return false; - } catch ( IOException e ) { - e.printStackTrace(); - readMetaData(); - if ( ERROR != null ) { - if ( ERROR == "timeout" ) { - log.info( "Socket timeout occured ... close connection." ); - this.close(); - } - } - log.info( "Sending TOKEN in Uploader failed..." ); - return false; - } - return true; - } - - /***********************************************************************/ - /** - * Getter for TOKEN. - */ - public String getToken() + public Uploader( SSLSocket socket ) throws IOException { - return TOKEN; + super( socket, log ); } /***********************************************************************/ /** - * Method to send range of the file, which should be uploaded. - * Helpful for knowing how much was already uploaded if - * connection aborts. - * - * @param a - * @param b - */ - public Boolean sendRange( int a, int b ) - { - try { - RANGE = a + ":" + b; - String sendRange = "RANGE=" + RANGE; - byte[] data = sendRange.getBytes( StandardCharsets.UTF_8 ); - dataToServer.writeByte( data.length ); - dataToServer.write( data ); - dataToServer.writeByte( 0 ); - } catch ( SocketTimeoutException ste ) { - ste.printStackTrace(); - log.info( "Socket timeout occured ... close connection." ); - this.close(); - } catch ( IOException e ) { - e.printStackTrace(); - readMetaData(); - if ( ERROR != null ) { - if ( ERROR == "timeout" ) { - log.info( "Socket timeout occured ... close connection." ); - this.close(); - } - } - log.info( "Sending RANGE in Uploader failed..." ); - return false; - } - return true; - } - - /***********************************************************************/ - /** - * Getter for RANGE. + * Used by the peer that initiated the connection to tell the remote + * peer which part of the file is being uploaded * + * @param startOffset start offset in bytes in the file (inclusive) + * @param endOffset end offset in file (exclusive) * @return */ - public String getRange() + public boolean prepareSendRange( int startOffset, int endOffset ) { - return RANGE; - } - - /***********************************************************************/ - /** - * Getter for beginning of RANGE. - * - * @return - */ - public int getStartOfRange() - { - if ( RANGE != null ) { - String[] splitted = RANGE.split( ":" ); - return Integer.parseInt( splitted[0] ); - } - return -1; - } - - /***********************************************************************/ - /** - * Getter for end of RANGE. - * - * @return - */ - public int getEndOfRange() - { - if ( RANGE != null ) { - String[] splitted = RANGE.split( ":" ); - return Integer.parseInt( splitted[1] ); - } - return -1; - } - - /***********************************************************************/ - /** - * Method for returning difference of current Range. - * - * @return - */ - public int getDiffOfRange() - { - if ( getStartOfRange() == -1 || getEndOfRange() == -1 ) { - return -1; - } - int diff = Math.abs( getEndOfRange() - getStartOfRange() ); - return diff; - } - - /***********************************************************************/ - /** - * Method for reading MetaData, like TOKEN and FileRange. - * Split incoming bytes after first '=' and store value to specific - * variable. - * - */ - public Boolean readMetaData() - { - try { - while ( true ) { - byte[] incoming = new byte[ 255 ]; - - // First get length. - dataFromServer.read( incoming, 0, 1 ); - int length = incoming[0] & 0xFF; - - if ( length == 0 ) // Stop if 0 was read. - break; - - /** - * Read the next available bytes and split by '=' for - * getting TOKEN or RANGE. - */ - int hasRead = 0; - while ( hasRead < length ) { - int ret = dataFromServer.read( incoming, hasRead, length - hasRead ); - if ( ret == -1 ) { - log.info( "Error in reading Metadata occured!" ); - return false; - } - hasRead += ret; - } - String data = new String( incoming, "UTF-8" ); - - String[] splitted = data.split( "=" ); - if ( splitted[0] != null && splitted[0].equals( "TOKEN" ) ) { - if ( splitted[1] != null ) - TOKEN = splitted[1]; - log.info( "TOKEN: " + TOKEN ); - } - else if ( splitted[0].equals( "RANGE" ) ) { - if ( splitted[1] != null ) - RANGE = splitted[1]; - log.info( "RANGE: " + RANGE ); - } - else if ( splitted[0].equals( "ERROR" ) ) { - if ( splitted[1] != null ) - ERROR = splitted[1]; - log.info( "ERROR: " + ERROR ); - return false; - } - } - } catch ( SocketTimeoutException ste ) { - ste.printStackTrace(); - sendErrorCode( "timeout" ); - log.info( "Socket timeout occured ... close connection" ); - this.close(); - } catch ( Exception e ) { - e.printStackTrace(); - return false; - } - return true; + return super.sendRange( startOffset, endOffset ); } /***********************************************************************/ @@ -288,26 +62,28 @@ public class Uploader * * @param filename */ - public Boolean sendFile( String filename ) + public boolean sendFile( String filename ) { RandomAccessFile file = null; try { file = new RandomAccessFile( new File( filename ), "r" ); if ( getStartOfRange() == -1 ) { + this.close(); return false; } file.seek( getStartOfRange() ); - byte[] data = new byte[ 4000 ]; + byte[] data = new byte[ 64000 ]; int hasRead = 0; int length = getDiffOfRange(); -// System.out.println( "diff of Range: " + length ); + // System.out.println( "diff of Range: " + length ); while ( hasRead < length ) { int ret = file.read( data, 0, Math.min( length - hasRead, data.length ) ); if ( ret == -1 ) { - log.info( "Error occured in Uploader.sendFile()," + log.warn( "Error occured in Uploader.sendFile()," + " while reading from File to send." ); + this.close(); return false; } hasRead += ret; @@ -316,7 +92,7 @@ public class Uploader } catch ( SocketTimeoutException ste ) { ste.printStackTrace(); sendErrorCode( "timeout" ); - log.info( "Socket timeout occured ... close connection." ); + log.warn( "Socket timeout occured ... close connection." ); this.close(); return false; } catch ( IOException ioe ) { @@ -324,64 +100,27 @@ public class Uploader readMetaData(); if ( ERROR != null ) { if ( ERROR == "timeout" ) { - log.info( "Socket timeout occured ... close connection." ); + log.warn( "Socket timeout occured ... close connection." ); this.close(); } } - log.info( "Sending RANGE " + getStartOfRange() + ":" + getEndOfRange() + " of File " + log.warn( "Sending RANGE " + getStartOfRange() + ":" + getEndOfRange() + " of File " + filename + " failed..." ); + this.close(); return false; } catch ( Exception e ) { e.printStackTrace(); + this.close(); return false; } finally { - try { - file.close(); - } catch ( IOException e ) { + if ( file != null ) { + try { + file.close(); + } catch ( IOException e ) { + } } } return true; } - /***********************************************************************/ - /** - * Method for sending error Code to server. For example in case of wrong - * token, send code for wrong token. - * - */ - public Boolean sendErrorCode( String errString ) - { - try { - String sendError = "ERROR=" + errString; - byte[] data = sendError.getBytes( StandardCharsets.UTF_8 ); - dataToServer.writeByte( data.length ); - dataToServer.write( data ); - } catch ( IOException e ) { - e.printStackTrace(); - this.close(); - return false; - } - return true; - } - - /***********************************************************************/ - /** - * Method for closing connection, if upload has finished. - * - */ - public void close() - { - try { - if ( satelliteSocket != null ) { - this.satelliteSocket.close(); - satelliteSocket = null; - } - if ( dataFromServer != null ) - dataFromServer.close(); - if ( dataToServer != null ) - dataToServer.close(); - } catch ( IOException e ) { - e.printStackTrace(); - } - } } -- cgit v1.2.3-55-g7522