From d05168ce96faaad75d79671e1cdf2eaccb884ed9 Mon Sep 17 00:00:00 2001 From: Nils Schwabe Date: Thu, 28 Aug 2014 15:14:26 +0200 Subject: Undo refactoring.. Classes are working again. Could not find the mistake :/ --- .../java/org/openslx/filetransfer/Downloader.java | 322 +++++++++++++++++++-- 1 file changed, 293 insertions(+), 29 deletions(-) (limited to 'src/main/java/org/openslx/filetransfer/Downloader.java') diff --git a/src/main/java/org/openslx/filetransfer/Downloader.java b/src/main/java/org/openslx/filetransfer/Downloader.java index d9e41a5..c860f5e 100644 --- a/src/main/java/org/openslx/filetransfer/Downloader.java +++ b/src/main/java/org/openslx/filetransfer/Downloader.java @@ -1,46 +1,74 @@ 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.nio.charset.StandardCharsets; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; import org.apache.log4j.Logger; -public class Downloader extends Transfer +public class Downloader { // Some instance variables. + private SSLSocketFactory sslSocketFactory; + private SSLSocket satelliteSocket; + private DataOutputStream dataToServer; + private DataInputStream dataFromServer; + private String TOKEN = null; + private String RANGE = null; private String outputFilename = null; + private String ERROR = null; - private static final Logger log = Logger.getLogger( Downloader.class ); + private static Logger log = Logger.getLogger( Downloader.class ); /***********************************************************************/ /** - * Actively initiate a connection to a remote peer for downloading. + * Constructor for satellite downloader. + * Tries to connect to specific ip and port and sending type of action. * - * @param host Host name or address to connect to - * @param port Port to connect to - * @throws IOException + * @param ip + * @param port */ - public Downloader( String host, int port, SSLContext context ) throws IOException + public Downloader( String ip, int port, SSLContext context ) { - super( host, port, context, log ); - dataToServer.writeByte( 'D' ); + try { + // create socket. + sslSocketFactory = context.getSocketFactory(); + + satelliteSocket = (SSLSocket)sslSocketFactory.createSocket( ip, port ); + satelliteSocket.setSoTimeout( 2000 ); // set socket timeout. + + dataToServer = new DataOutputStream( satelliteSocket.getOutputStream() ); + dataToServer.writeByte( 'D' ); + dataFromServer = new DataInputStream( satelliteSocket.getInputStream() ); + } catch ( Exception e ) { + e.printStackTrace(); + } } /***********************************************************************/ /** - * Constructor used by Listener to create an incoming download connection. + * Constructor for master downloader. + * Given parameter is the socket over which the transfer is going. * - * @param socket established connection to peer which requested an upload. - * @throws IOException + * @param socket */ - protected Downloader( SSLSocket socket ) throws IOException + public Downloader( SSLSocket socket ) { - super( socket, log ); + try { + satelliteSocket = socket; + dataToServer = new DataOutputStream( satelliteSocket.getOutputStream() ); + dataFromServer = new DataInputStream( satelliteSocket.getInputStream() ); + } catch ( IOException e ) { + e.printStackTrace(); + } } /***********************************************************************/ @@ -67,16 +95,211 @@ public class Downloader extends Transfer /***********************************************************************/ /** - * Method to request a byte range within the file to download. This - * method is called by the party that initiated the connection. + * Method for sending token for identification from satellite to master. + * + * @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(); + } 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 Downloader failed..." ); + return false; + } + return true; + } + + /***********************************************************************/ + /** + * 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 ); + } 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; + } + + /***********************************************************************/ + /** + * Method for reading incoming token for identification. * - * @param startOffset offset in file where to start the transfer (inclusive) - * @param endOffset end offset where to end the transfer (exclusive) - * @return success or failure */ - public boolean requestRange( long startOffset, long endOffset ) + public String getToken() { - return super.sendRange( startOffset, endOffset ); + return TOKEN; + } + + /***********************************************************************/ + /** + * Method for reading range of file, which is downloaded. + * Helpful for knowing how much is already downloaded if connection aborts. + */ + public String getRange() + { + 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() + { + 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 ]; // TODO: problematische Größe. + + // First get length. + int retLengthByte; + retLengthByte = dataFromServer.read( incoming, 0, 1 ); + if (retLengthByte != 1) { + this.close(); + return false; + } + + int length = incoming[0] & 0xFF; + log.info( "length (downloader): " + length ); + + if ( length == 0 ) + 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 occured while reading Metadata." ); + return false; + } + hasRead += ret; + } + + String data = new String( incoming, 0, length, "UTF-8" ); + // System.out.println(data); + + String[] splitted = data.split( "=" ); + // System.out.println("splitted[0]: " + splitted[0]); + // System.out.println("splitted[1]: " + splitted[1]); + 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 in Downloader." ); + this.close(); + return false; + } catch ( Exception e ) { + e.printStackTrace(); + this.close(); + return false; + } + return true; } /***********************************************************************/ @@ -84,20 +307,21 @@ public class Downloader extends Transfer * Method for reading Binary. Reading the current Range of incoming binary. * */ - public boolean receiveBinary() + public Boolean readBinary() { RandomAccessFile file = null; try { - int chunkLength = getDiffOfRange(); - byte[] incoming = new byte[ 64000 ]; + int length = getDiffOfRange(); + byte[] incoming = new byte[ 4000 ]; int hasRead = 0; file = new RandomAccessFile( new File( outputFilename ), "rw" ); file.seek( getStartOfRange() ); - while ( hasRead < chunkLength ) { - int ret = dataFromServer.read( incoming, 0, Math.min( chunkLength - hasRead, incoming.length ) ); + while ( hasRead < length ) { + int ret = dataFromServer.read( incoming, 0, Math.min( length - hasRead, incoming.length ) ); // log.info("hasRead: " + hasRead + " length: " + length + " ret: " + ret); if ( ret == -1 ) { - log.info( "Error occured while receiving payload." ); + log.info( "Error occured in Downloader.readBinary()," + + " while reading binary." ); return false; } hasRead += ret; @@ -109,7 +333,6 @@ public class Downloader extends Transfer sendErrorCode( "timeout" ); log.info( "Socket timeout occured ... close connection." ); this.close(); - return false; } catch ( Exception e ) { e.printStackTrace(); log.info( "Reading RANGE " + getStartOfRange() + ":" + getEndOfRange() @@ -124,8 +347,49 @@ public class Downloader extends Transfer e.printStackTrace(); } } - RANGE = null; // Reset range for next iteration } 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 download 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