summaryrefslogblamecommitdiffstats
path: root/src/main/java/org/openslx/filetransfer/Uploader.java
blob: 6766ba7da82f28efc8820c5496cb3dcd99bfb5b4 (plain) (tree)
1
2
3
4
5
6
7
8
9

                                 
                    
                                     

                                
                       

                                
 

                               
                                      
 
 
                                                                             
 

                                                                                 
                                                              
           


                                                                          
                              
           
                                                                                                                        
         
                                                                 


                                                                        
         


                                                                                 

                                                  

                              
           
                                                           
         
                                     
         


                                                                                 
                                                 
           
                          
           
                                                
         





                                                                               

                                                                     

                                     
                                             
                     


                                                                                         
                                                                                                       

                                             
                                                                                                                                              


                                                                                                                 
                                                                                                                

                                                     




                                                                                       
                                                                                                                 
                                                     
                                 


                                                                                         
                                                                                                                                    


                                                             
                                                                                                                          





                                                                                
                                                                                                                                                                      





                                                                                                                        
                                                                                                  


                                                             
                                                                                                                 










                                                                                                                      
                                                                                                         


                                                             
                                                                                                                                                      





                                                                                
                                                                                       

                                                             

                                                                               
                                 
                         
                           
                                                                   

                            
         
 
 
package org.openslx.filetransfer;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.Socket;

import javax.net.ssl.SSLContext;

import org.apache.log4j.Logger;

public class Uploader extends Transfer
{

	private static final Logger log = Logger.getLogger( Uploader.class );

	/***********************************************************************/
	/**
	 * Actively establish upload connection to given peer.
	 * 
	 * @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
	 */
	public Uploader( String host, int port, int readTimeoutMs, SSLContext context, String token ) throws IOException
	{
		super( host, port, readTimeoutMs, context, log );
		outStream.writeByte( 'U' );
		if ( !sendToken( token ) || !sendEndOfMeta() )
			throw new IOException( "Sending token failed" );
	}

	/***********************************************************************/
	/**
	 * Constructor for master uploader.
	 * Sends back the socket for datatransfer.
	 * 
	 * @throws IOException
	 */
	public Uploader( Socket socket ) throws IOException
	{
		super( socket, log );
	}

	/***********************************************************************/
	/**
	 * Method for sending File with filename.
	 * 
	 * @param filename
	 */
	public boolean upload( String filename )
	{
		return upload( filename, null );
	}

	@SuppressWarnings( "resource" )
	public boolean upload( String filename, UploadStatusCallback callback )
	{
		if ( shouldGetToken() ) {
			log.error( "You didn't call getToken yet!" );
			return false;
		}
		RandomAccessFile file = null;
		try {
			try {
				file = new RandomAccessFile( new File( filename ), "r" );
			} catch ( FileNotFoundException e ) {
				this.close( "Could not open given file for reading.", callback, true );
				return false;
			}
			while ( !Thread.currentThread().isInterrupted() ) { // Loop as long as remote peer is requesting chunks from this file
				// Read meta data of remote peer - either new range, or it's telling us it's done
				MetaData meta = readMetaData();
				if ( meta == null ) {
					this.close( "Did not get meta data from remote peer.", callback, true );
					return false;
				}
				if ( meta.isDone() ) // Download complete?
					break;
				// Not complete, so there must be another range request
				FileRange requestedRange = meta.getRange();
				if ( requestedRange == null ) {
					this.close( "Peer did not include RANGE in meta data.", callback, true );
					return false;
				}
				// Range inside file?
				try {
					if ( requestedRange.endOffset > file.length() ) {
						this.close( "Requested range is larger than file size, aborting.", callback, true );
						return false;
					}
				} catch ( IOException e ) {
					this.close( "Could not get current length of file " + filename, callback, false );
					return false;
				}
				// Seek to requested chunk
				try {
					file.seek( requestedRange.startOffset );
				} catch ( IOException e ) {
					this.close( "Could not seek to start of requested range in given file (" + requestedRange.startOffset + ")", callback, true );
					return false;
				}
				// Send confirmation of range we're about to send
				try {
					long ptr = file.getFilePointer();
					if ( !sendRange( ptr, ptr + requestedRange.getLength() ) || !sendEndOfMeta() ) {
						this.close( "Could not send range confirmation" );
						return false;
					}
				} catch ( IOException e ) {
					this.close( "Could not determine current position in file " + filename );
					return false;
				}
				// Finally send requested chunk
				byte[] data = new byte[ 500000 ]; // 500kb
				int hasRead = 0;
				int length = requestedRange.getLength();
				while ( hasRead < length ) {
					int ret;
					try {
						ret = file.read( data, 0, Math.min( length - hasRead, data.length ) );
					} catch ( IOException e ) {
						this.close( "Error reading from file ", callback, true );
						return false;
					}
					if ( ret == -1 ) {
						this.close( "Error occured in Uploader.sendFile() while reading from File to send.", callback, true );
						return false;
					}
					hasRead += ret;
					try {
						outStream.write( data, 0, ret );
					} catch ( IOException e ) {
						this.close( "Sending payload failed" );
						return false;
					}
					if ( callback != null )
						callback.uploadProgress( ret );
				}
			}
		} finally {
			Transfer.safeClose( file, transferSocket );
		}
		return true;
	}

}