summaryrefslogtreecommitdiffstats
path: root/src/main/java/org/openslx/filetransfer
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/org/openslx/filetransfer')
-rw-r--r--src/main/java/org/openslx/filetransfer/ClassTest.java4
-rw-r--r--src/main/java/org/openslx/filetransfer/Downloader.java4
-rw-r--r--src/main/java/org/openslx/filetransfer/Listener.java47
-rw-r--r--src/main/java/org/openslx/filetransfer/Transfer.java32
-rw-r--r--src/main/java/org/openslx/filetransfer/Uploader.java6
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;
}