Commit d8b68d1e authored by Alex Wenckus's avatar Alex Wenckus Committed by alex

First work on FileTransferInterceptor

git-svn-id: http://svn.igniterealtime.org/svn/repos/wildfire/trunk@4384 b35dd754-fafc-0310-a699-88a17e54d16e
parent 17f199b4
......@@ -49,7 +49,7 @@ public abstract class AbstractFileTransferManager
public AbstractFileTransferManager() {
super("File Transfer Manager");
fileTransferMap = createCache(CACHE_NAME, "fileTransfer", 128 * 1024, 1000 * 60 * 10);
InterceptorManager.getInstance().addInterceptor(new FileTransferInterceptor());
InterceptorManager.getInstance().addInterceptor(new MetaFileTransferInterceptor());
}
private Cache<String, FileTransfer> createCache(String name, String propertiesName, int size,
......@@ -120,10 +120,21 @@ public abstract class AbstractFileTransferManager
DEFAULT_IS_FILE_TRANSFER_ENABLED);
}
public void addFileTransferInterceptor(FileTransferInterceptor interceptor) {
}
public void removeFileTransferInterceptor(FileTransferInterceptor interceptor) {
}
public void fireFileTransferIntercept(String transferDigest)
throws FileTransferRejectedException
{
}
/**
* Interceptor to grab and validate file transfer meta information.
*/
private class FileTransferInterceptor implements PacketInterceptor {
private class MetaFileTransferInterceptor implements PacketInterceptor {
public void interceptPacket(Packet packet, Session session, boolean incoming,
boolean processed)
throws PacketRejectedException
......
/**
* $RCSfile: $
* $Revision: $
* $Date: $
*
* Copyright (C) 2006 Jive Software. All rights reserved.
* This software is the proprietary information of Jive Software. Use is subject to license terms.
*/
package org.jivesoftware.wildfire.filetransfer;
/**
* Interface used to capture a file transfer before it begins.
*
* @author Alexander Wenckus
*/
public interface FileTransferInterceptor {
/**
* Invokes the interceptor on the specified file transfer. The interceptor can either modify
* the file transfer or throw a FileTransferRejectedException.
*
* @param transfer
*/
void interceptFileTransfer(FileTransfer transfer) throws FileTransferRejectedException;
}
......@@ -28,22 +28,22 @@ public interface FileTransferManager extends Module {
* transfer is disabled all known file transfer related packets are blocked, it also goes
* with out saying that the file transfer proxy is then disabled.
*/
public static final String JIVEPROPERTY_FILE_TRANSFER_ENABLED = "xmpp.filetransfer.enabled";
static final String JIVEPROPERTY_FILE_TRANSFER_ENABLED = "xmpp.filetransfer.enabled";
/**
* Whether or not the file transfer is enabled by default.
*/
public static final boolean DEFAULT_IS_FILE_TRANSFER_ENABLED = true;
static final boolean DEFAULT_IS_FILE_TRANSFER_ENABLED = true;
/**
* Stream Initiation, SI, namespace
*/
public static final String NAMESPACE_SI = "http://jabber.org/protocol/si";
static final String NAMESPACE_SI = "http://jabber.org/protocol/si";
/**
* Bytestreams namespace
*/
public static final String NAMESPACE_BYTESTREAMS = "http://jabber.org/protocol/bytestreams";
static final String NAMESPACE_BYTESTREAMS = "http://jabber.org/protocol/bytestreams";
/**
* Checks an incoming file transfer request to see if it should be accepted or rejected.
......@@ -66,7 +66,7 @@ public interface FileTransferManager extends Module {
* @throws UnauthorizedException when in the current server configuration this transfer
* should not be permitted.
*/
public void registerProxyTransfer(String transferDigest, ProxyTransfer proxyTransfer)
void registerProxyTransfer(String transferDigest, ProxyTransfer proxyTransfer)
throws UnauthorizedException;
/**
......@@ -75,12 +75,18 @@ public interface FileTransferManager extends Module {
*
* @param isEnabled true if file transfer should be enabled and false if it should not be.
*/
public void enableFileTransfer(boolean isEnabled);
void enableFileTransfer(boolean isEnabled);
/**
* Returns whether or not file transfer is currently enabled in the server.
*
* @return true if file transfer is enabled and false if it is not
*/
public boolean isFileTransferEnabled();
boolean isFileTransferEnabled();
void addFileTransferInterceptor(FileTransferInterceptor interceptor);
void removeFileTransferInterceptor(FileTransferInterceptor interceptor);
void fireFileTransferIntercept(String transferDigest) throws FileTransferRejectedException;
}
......@@ -10,16 +10,59 @@
*/
package org.jivesoftware.wildfire.filetransfer;
import java.util.concurrent.Future;
import java.io.InputStream;
import java.io.OutputStream;
/**
* An interface to track the progress of a file transfer through the server. This interface is used
* by {@link FileTransfer} to make this information available if it is in the system.
*
* @author Alexander Wenckus
*/
public interface FileTransferProgress {
public long getAmountTransfered() throws UnsupportedOperationException;
/**
* Returns the fully qualified JID of the initiator of the file transfer.
*
* @return the fully qualified JID of the initiator of the file transfer.
*/
public String getInitiator();
public void setInitiator(String initiator);
/**
* Returns the full qualified JID of the target of the file transfer.
*
* @return the fully qualified JID of the target
*/
public String getTarget();
public void setTarget(String target);
/**
* Returns the unique session id that correlates to the file transfer.
*
* @return Returns the unique session id that correlates to the file transfer.
*/
public String getSessionID();
public void setSessionID(String streamID);
/**
* When the file transfer is being caried out by another thread this will set the Future
* relating to the thread that is carrying out the transfer.
*
* @param future the furute that is carrying out the transfer
*/
public void setTransferFuture(Future<?> future);
public void setInputStream(InputStream initiatorInputStream);
public InputStream getInputStream();
public void setOutputStream(OutputStream targetOutputStream);
public OutputStream getOutputStream();
}
/**
* $RCSfile: $
* $Revision: $
* $Date: $
*
* Copyright (C) 2006 Jive Software. All rights reserved.
* This software is the proprietary information of Jive Software. Use is subject to license terms.
*/
package org.jivesoftware.wildfire.filetransfer;
import java.io.PrintStream;
import java.io.PrintWriter;
/**
* Thrown by a FileTransferInterceptor when a file transfer is rejected my the Interceptor. The file
* transfer is aborted and the participating parties are notified.
*
* @author Alexander Wenckus
*/
public class FileTransferRejectedException extends Exception {
private static final long serialVersionUID = 1L;
private Throwable nestedThrowable = null;
/**
* Text to include in a message that will be sent to the sender of the packet that got
* rejected. If no text is specified then no message will be sent to the user.
*/
private String rejectionMessage;
public FileTransferRejectedException() {
super();
}
public FileTransferRejectedException(String msg) {
super(msg);
}
public FileTransferRejectedException(Throwable nestedThrowable) {
this.nestedThrowable = nestedThrowable;
}
public FileTransferRejectedException(String msg, Throwable nestedThrowable) {
super(msg);
this.nestedThrowable = nestedThrowable;
}
public void printStackTrace() {
super.printStackTrace();
if (nestedThrowable != null) {
nestedThrowable.printStackTrace();
}
}
public void printStackTrace(PrintStream ps) {
super.printStackTrace(ps);
if (nestedThrowable != null) {
nestedThrowable.printStackTrace(ps);
}
}
public void printStackTrace(PrintWriter pw) {
super.printStackTrace(pw);
if (nestedThrowable != null) {
nestedThrowable.printStackTrace(pw);
}
}
/**
* Retuns the text to include in a message that will be sent to the intitiator and target
* of the file transfer that got rejected or <tt>null</tt> if none was defined. If no text was
* specified then no message will be sent to the parties of the rejected file transfer.
*
* @return the text to include in a message that will be sent to the parties of the file
* transfer that got rejected or <tt>null</tt> if none was defined.
*/
public String getRejectionMessage() {
return rejectionMessage;
}
/**
* Sets the text to include in a message that will be sent to the intiator and target of the
* file transfer that got rejected or <tt>null</tt> if no message will be sent to the parties
* of the rejected file transfer. Bt default, no message will be sent.
*
* @param rejectionMessage the text to include in the notification message for the rejection.
*/
public void setRejectionMessage(String rejectionMessage) {
this.rejectionMessage = rejectionMessage;
}
}
......@@ -72,7 +72,7 @@ public class ProxyConnectionManager {
*/
synchronized void processConnections(final InetAddress bindInterface, final int port) {
if (socketProcess != null) {
if(proxyPort == port) {
if (proxyPort == port) {
return;
}
}
......@@ -92,7 +92,7 @@ public class ProxyConnectionManager {
socket = serverSocket.accept();
}
catch (IOException e) {
if(!serverSocket.isClosed()) {
if (!serverSocket.isClosed()) {
Log.error("Error accepting proxy connection", e);
continue;
}
......@@ -174,7 +174,7 @@ public class ProxyConnectionManager {
connectionMap.put(responseDigest, transfer);
}
else {
transfer.setInitiatorSocket(connection);
transfer.setInputStream(connection.getInputStream());
}
}
cmd = createOutgoingSocks5Message(0, responseDigest);
......@@ -187,7 +187,8 @@ public class ProxyConnectionManager {
}
}
private ProxyTransfer createProxyTransfer(String transferDigest, Socket initiatorSocket) {
private ProxyTransfer createProxyTransfer(String transferDigest, Socket targetSocket)
throws IOException {
ProxyTransfer provider;
try {
Class c = ClassUtils.forName(className);
......@@ -199,7 +200,7 @@ public class ProxyConnectionManager {
}
provider.setTransferDigest(transferDigest);
provider.setTargetSocket(initiatorSocket);
provider.setOutputStream(targetSocket.getOutputStream());
return provider;
}
......@@ -280,6 +281,13 @@ public class ProxyConnectionManager {
transfer.setSessionID(sid);
transfer.setTransferFuture(executor.submit(new Runnable() {
public void run() {
try {
transferManager.fireFileTransferIntercept(digest);
}
catch (FileTransferRejectedException e) {
notifyFailure(transfer, e);
return;
}
try {
transfer.doTransfer();
}
......@@ -293,6 +301,10 @@ public class ProxyConnectionManager {
}));
}
private void notifyFailure(ProxyTransfer transfer, FileTransferRejectedException e) {
}
/**
* Creates the digest needed for a byte stream. It is the SHA1(sessionID +
* initiator + target).
......
......@@ -11,59 +11,27 @@ package org.jivesoftware.wildfire.filetransfer;
import org.jivesoftware.util.Cacheable;
import java.net.Socket;
import java.io.IOException;
import java.util.concurrent.Future;
/**
* Tracks the different connections related to a proxy file transfer. There are two connections, the
* initiator and the target and when both connections are completed the transfer can begin.
*/
public interface ProxyTransfer extends Cacheable, FileTransferProgress {
/**
* Returns the fully qualified JID of the initiator of the file transfer.
*
* @return Returns the fully qualified JID of the initiator of the file transfer.
*/
public String getInitiator();
public void setInitiatorSocket(Socket initiatorSocket);
public Socket getInitiatorSocket();
public void setTargetSocket(Socket targetSocket);
public Socket getTargetSocket();
public void setTarget(String target);
public String getTarget();
public void setTransferDigest(String digest);
public String getTransferDigest();
public String getSessionID();
public void setSessionID(String streamID);
/**
* Returns true if the Bytestream is ready to be activated and the transfer can begin.
* Returns true if the Bytestream is ready to be activated and the proxy transfer can begin.
*
* @return Returns true if the Bytestream is ready to be activated.
*/
public boolean isActivatable();
public long getAmountTransfered();
public int getCachedSize();
public void setTransferFuture(Future<?> future);
/**
* Transfers the file from the initiator to the target.
*/
public void doTransfer() throws IOException;
void setInitiator(String s);
}
......@@ -14,7 +14,6 @@ import org.jivesoftware.util.CacheSizes;
import org.jivesoftware.wildfire.filetransfer.ProxyTransfer;
import org.jivesoftware.wildfire.filetransfer.ProxyOutputStream;
import java.net.Socket;
import java.util.concurrent.Future;
import java.io.IOException;
import java.io.InputStream;
......@@ -28,9 +27,9 @@ public class DefaultProxyTransfer implements ProxyTransfer {
private String initiator;
private Socket initiatorSocket;
private InputStream inputStream;
private Socket targetSocket;
private OutputStream outputStream;
private String target;
......@@ -51,29 +50,24 @@ public class DefaultProxyTransfer implements ProxyTransfer {
return initiator;
}
/**
* Sets the fully qualified JID of the initiator of the file transfer.
*
* @param initiator The fully qualified JID of the initiator of the file transfer.
*/
public void setInitiator(String initiator) {
this.initiator = initiator;
}
public Socket getInitiatorSocket() {
return initiatorSocket;
public InputStream getInputStream() {
return inputStream;
}
public void setInitiatorSocket(Socket initiatorSocket) {
this.initiatorSocket = initiatorSocket;
public void setInputStream(InputStream initiatorInputStream) {
this.inputStream = initiatorInputStream;
}
public Socket getTargetSocket() {
return targetSocket;
public OutputStream getOutputStream() {
return outputStream;
}
public void setTargetSocket(Socket targetSocket) {
this.targetSocket = targetSocket;
public void setOutputStream(OutputStream outputStream) {
this.outputStream = outputStream;
}
public String getTarget() {
......@@ -102,7 +96,7 @@ public class DefaultProxyTransfer implements ProxyTransfer {
public boolean isActivatable() {
return ((initiatorSocket != null) && (targetSocket != null));
return ((inputStream != null) && (outputStream != null));
}
public synchronized void setTransferFuture(Future<?> future) {
......@@ -120,8 +114,8 @@ public class DefaultProxyTransfer implements ProxyTransfer {
if(!isActivatable()) {
throw new IOException("Transfer missing party");
}
InputStream in = getInitiatorSocket().getInputStream();
OutputStream out = new ProxyOutputStream(getTargetSocket().getOutputStream());
InputStream in = getInputStream();
OutputStream out = new ProxyOutputStream(getOutputStream());
final byte[] b = new byte[BUFFER_SIZE];
int count = 0;
......@@ -137,8 +131,8 @@ public class DefaultProxyTransfer implements ProxyTransfer {
count = in.read(b);
} while (count >= 0);
getInitiatorSocket().close();
getTargetSocket().close();
getInputStream().close();
getOutputStream().close();
}
public int getCachedSize() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment