diff options
Diffstat (limited to 'src/main/java/org/openslx/filetransfer')
5 files changed, 64 insertions, 29 deletions
diff --git a/src/main/java/org/openslx/filetransfer/ClassTest.java b/src/main/java/org/openslx/filetransfer/ClassTest.java index 37b37c0..9d5bc82 100644 --- a/src/main/java/org/openslx/filetransfer/ClassTest.java +++ b/src/main/java/org/openslx/filetransfer/ClassTest.java @@ -65,7 +65,7 @@ public class ClassTest context.init( keyManagers, null, null ); - Listener listener = new Listener( new Test(), context, 6789 ); + Listener listener = new Listener( new Test(), context, 6789, 10000 ); listener.start(); Thread.sleep( 2000 ); @@ -78,7 +78,7 @@ public class ClassTest context.init( null, trustManagers, null ); - Downloader d = new Downloader( "localhost", 6789, context, "xyz" ); + Downloader d = new Downloader( "localhost", 6789, 10000, context, "xyz" ); boolean res = d.download( outFile, new WantRangeCallback() { long pos = 0; long size = -1; diff --git a/src/main/java/org/openslx/filetransfer/Downloader.java b/src/main/java/org/openslx/filetransfer/Downloader.java index 20a50e6..acd70a7 100644 --- a/src/main/java/org/openslx/filetransfer/Downloader.java +++ b/src/main/java/org/openslx/filetransfer/Downloader.java @@ -23,9 +23,9 @@ public class Downloader extends Transfer * @param port Port to connect to * @throws IOException */ - public Downloader( String host, int port, SSLContext context, String token ) throws IOException + public Downloader( String host, int port, int readTimeoutMs, SSLContext context, String token ) throws IOException { - super( host, port, context, log ); + super( host, port, readTimeoutMs, context, log ); outStream.writeByte( 'D' ); if ( !sendToken( token ) || !sendEndOfMeta() ) throw new IOException( "Sending token failed" ); diff --git a/src/main/java/org/openslx/filetransfer/Listener.java b/src/main/java/org/openslx/filetransfer/Listener.java index e4e99e9..e6bbb62 100644 --- a/src/main/java/org/openslx/filetransfer/Listener.java +++ b/src/main/java/org/openslx/filetransfer/Listener.java @@ -1,8 +1,9 @@ package org.openslx.filetransfer; -import java.io.IOException; +import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; +import java.net.SocketTimeoutException; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLServerSocketFactory; @@ -16,6 +17,7 @@ public class Listener private final int port; private ServerSocket listenSocket = null; private Thread acceptThread = null; + private final int readTimeoutMs; private static final byte U = 85; // hex - code 'U' = 85. private static final byte D = 68; // hex - code 'D' = 68. @@ -30,12 +32,14 @@ public class Listener * @param context the SSL context used for encryption; if null, unencrypted connections will be * used * @param port port to listen on + * @param timeoutMs socket timeout for accepted connections */ - public Listener( IncomingEvent e, SSLContext context, int port ) + public Listener( IncomingEvent e, SSLContext context, int port, int readTimeoutMs ) { this.incomingEvent = e; this.context = context; this.port = port; + this.readTimeoutMs = readTimeoutMs; } /***********************************************************************/ @@ -48,13 +52,15 @@ public class Listener { try { if ( this.context == null ) { - listenSocket = new ServerSocket( this.port ); + listenSocket = new ServerSocket(); } else { SSLServerSocketFactory sslServerSocketFactory = context.getServerSocketFactory(); - listenSocket = sslServerSocketFactory.createServerSocket( this.port ); + listenSocket = sslServerSocketFactory.createServerSocket(); } + listenSocket.setReuseAddress( true ); + listenSocket.bind( new InetSocketAddress( this.port ) ); } catch ( Exception e ) { - log.error( "Cannot listen on port " + this.port ); + log.error( "Cannot listen on port " + this.port, e ); return false; } return true; @@ -63,7 +69,7 @@ public class Listener private void run() { final Listener instance = this; - acceptThread = new Thread() { + acceptThread = new Thread( "BFTP-Listen-" + this.port ) { @Override public void run() { @@ -72,34 +78,44 @@ public class Listener Socket connectionSocket = null; try { connectionSocket = listenSocket.accept(); + } catch ( SocketTimeoutException e ) { + continue; + } catch ( Exception e ) { + log.warn( "Some exception when accepting! Trying to resume...", e ); + Transfer.safeClose( listenSocket ); + if ( !listen() ) { + log.error( "Could not re-open listening socket" ); + break; + } + continue; + } + try { connectionSocket.setSoTimeout( 2000 ); // 2 second timeout enough? Maybe even use a small thread pool for handling accepted connections byte[] b = new byte[ 1 ]; int length = connectionSocket.getInputStream().read( b ); + if ( length == -1 ) + continue; - connectionSocket.setSoTimeout( 10000 ); - - log.debug( "Length (Listener): " + length ); + connectionSocket.setSoTimeout( readTimeoutMs ); if ( b[0] == U ) { - log.debug( "recognized U --> starting Downloader" ); // --> start Downloader(socket). Downloader d = new Downloader( connectionSocket ); incomingEvent.incomingUploadRequest( d ); } else if ( b[0] == D ) { - log.debug( "recognized D --> starting Uploader" ); // --> start Uploader(socket). Uploader u = new Uploader( connectionSocket ); incomingEvent.incomingDownloadRequest( u ); } else { - log.debug( "Got invalid option ... close connection" ); + log.debug( "Got invalid init-byte ... close connection" ); connectionSocket.close(); } - } catch ( IOException e ) { - // TODO Auto-generated catch block - e.printStackTrace(); + } catch ( Exception e ) { + log.warn( "Error accepting client", e ); + Transfer.safeClose( connectionSocket ); } } } finally { @@ -110,6 +126,7 @@ public class Listener } } }; + acceptThread.setDaemon( true ); acceptThread.start(); log.info( "Starting to accept " + ( this.context == null ? "UNENCRYPTED" : "encrypted" ) + " connections on port " + this.port ); } diff --git a/src/main/java/org/openslx/filetransfer/Transfer.java b/src/main/java/org/openslx/filetransfer/Transfer.java index 3e278c8..fc3d1d8 100644 --- a/src/main/java/org/openslx/filetransfer/Transfer.java +++ b/src/main/java/org/openslx/filetransfer/Transfer.java @@ -34,7 +34,7 @@ public abstract class Transfer * @param log Logger to use * @throws IOException */ - protected Transfer( String host, int port, SSLContext context, Logger log ) throws IOException + protected Transfer( String host, int port, int readTimeoutMs, SSLContext context, Logger log ) throws IOException { this.log = log; // create socket. @@ -44,7 +44,7 @@ public abstract class Transfer SSLSocketFactory sslSocketFactory = context.getSocketFactory(); transferSocket = sslSocketFactory.createSocket(); } - transferSocket.setSoTimeout( 10000 ); // set socket timeout. + transferSocket.setSoTimeout( readTimeoutMs ); transferSocket.connect( new InetSocketAddress( host, port ) ); outStream = new DataOutputStream( transferSocket.getOutputStream() ); @@ -196,7 +196,7 @@ public abstract class Transfer * Method for closing connection, if download has finished. * */ - public void close( String error, UploadStatusCallback callback, boolean sendToPeer ) + protected void close( String error, UploadStatusCallback callback, boolean sendToPeer ) { if ( error != null ) { if ( sendToPeer ) @@ -205,14 +205,30 @@ public abstract class Transfer callback.uploadError( error ); log.info( error ); } - safeClose( dataFromServer, outStream, transferSocket ); + synchronized ( transferSocket ) { + safeClose( dataFromServer, outStream, transferSocket ); + } } - public void close( String error ) + protected void close( String error ) { close( error, null, false ); } + public void cancel() + { + synchronized ( transferSocket ) { + if ( isValid() ) { + try { + transferSocket.shutdownInput(); + transferSocket.shutdownOutput(); + } catch ( Exception e ) { + // Silence + } + } + } + } + /** * Returns whether this transfer/connection is considered valid or usable, * which means the socket is still properly connected to the remote peer. @@ -221,8 +237,10 @@ public abstract class Transfer */ public boolean isValid() { - return transferSocket.isConnected() && !transferSocket.isClosed() - && !transferSocket.isInputShutdown() && !transferSocket.isOutputShutdown(); + synchronized ( transferSocket ) { + return transferSocket.isConnected() && !transferSocket.isClosed() + && !transferSocket.isInputShutdown() && !transferSocket.isOutputShutdown(); + } } /** diff --git a/src/main/java/org/openslx/filetransfer/Uploader.java b/src/main/java/org/openslx/filetransfer/Uploader.java index 748b1e2..92da8ea 100644 --- a/src/main/java/org/openslx/filetransfer/Uploader.java +++ b/src/main/java/org/openslx/filetransfer/Uploader.java @@ -24,9 +24,9 @@ public class Uploader extends Transfer * @param context ssl context for establishing a secure connection * @throws IOException */ - public Uploader( String host, int port, SSLContext context, String token ) throws IOException + public Uploader( String host, int port, int readTimeoutMs, SSLContext context, String token ) throws IOException { - super( host, port, context, log ); + super( host, port, readTimeoutMs, context, log ); outStream.writeByte( 'U' ); if ( !sendToken( token ) || !sendEndOfMeta() ) throw new IOException( "Sending token failed" ); @@ -141,7 +141,7 @@ public class Uploader extends Transfer } } } finally { - Transfer.safeClose( file ); + Transfer.safeClose( file, transferSocket ); } return true; } |