Commit 9f3f5ea7 authored by Alex Wenckus's avatar Alex Wenckus Committed by alex

1) Added ability to enable/disable file transfer. JM-675

2) Minor issue where socket wasn't being cleaned up correctly when the proxy was disabled. JM-710
3) Added proxy transfer statistic
4) File transfer cache is no longer public.

git-svn-id: http://svn.igniterealtime.org/svn/repos/wildfire/trunk@3959 b35dd754-fafc-0310-a699-88a17e54d16e
parent 88b3d5e2
......@@ -1484,6 +1484,15 @@ filetransferproxy.settings.label_enable=Povolena
filetransferproxy.settings.label_enable_info=Tento server bude fungovat jako prost\u0159edn\u00edk p\u0159enosu soubor\u016f na portu:
filetransferproxy.settings.valid.port=Pros\u00edm zadejte platn\u00fd port.
filetransferproxy.settings.confirm.updated=Nastaven\u00ed prost\u0159edn\u00edka p\u0159enosu soubor\u016f \u00fasp\u011b\u0161n\u011b zm\u011bn\u011bno.
filetransfer.error.disabled=File Transfer Has Been Disabled, Proxy Won't Function
# File Transfer Proxy Stats
stat.filetransferproxy.transfered.name = Proxy Transfer Rate
stat.filetransferproxy.transfered.desc = The amount of data in kilobytes being transfered through the file transfer\
proxy.
stat.filetransferproxy.transfered.units = Kb/s
# System Cache page
system.cache.title=P\u0159ehled ke\u0161e
......
......@@ -1482,6 +1482,14 @@ filetransferproxy.settings.label_enable=Enabled
filetransferproxy.settings.label_enable_info=This server will act as a file transfer proxy on port:
filetransferproxy.settings.valid.port=Please enter a valid port.
filetransferproxy.settings.confirm.updated=File transfer proxy settings updated succesfully.
filetransfer.error.disabled=File Transfer Has Been Disabled, Proxy Won't Function
# File Transfer Proxy Stats
stat.filetransferproxy.transfered.name = Proxy Transfer Rate
stat.filetransferproxy.transfered.desc = The amount of data in kilobytes being transfered through the file transfer\
proxy.
stat.filetransferproxy.transfered.units = Kb/s
# System Cache page
system.cache.title=Cache Summary
......
......@@ -178,6 +178,10 @@
## Added key: 'tab.tab-plugins.descr'
## Added key: 'sidebar.sidebar-plugin-admin'
## Added key: 'sidebar.plugin-settings'
## Added key: 'filetransfer.error.disabled'
## Added key: 'stat.filetransferproxy.transfered.name
## Added key: 'stat.filetransferproxy.transfered.desc
## Added key: 'stat.filetransferproxy.transfered.units
# Wildfire
......@@ -1674,6 +1678,14 @@ filetransferproxy.settings.label_enable=Enabled
filetransferproxy.settings.label_enable_info=This server will act as a file transfer proxy on port:
filetransferproxy.settings.valid.port=Please enter a valid port.
filetransferproxy.settings.confirm.updated=File transfer proxy settings updated succesfully.
filetransfer.error.disabled=File Transfer Has Been Disabled, Proxy Won't Function
# File Transfer Proxy Stats
stat.filetransferproxy.transfered.name = Proxy Transfer Rate
stat.filetransferproxy.transfered.desc = The amount of data in kilobytes being transfered through the file transfer\
proxy.
stat.filetransferproxy.transfered.units = Kb/s
# System Cache page
system.cache.title=Cache Summary
......
......@@ -1356,6 +1356,14 @@ filetransferproxy.settings.label_enable=Activado
filetransferproxy.settings.label_enable_info=Este servidor funcionar\u00e1 como proxy de transferencia de archivos en el puerto:
filetransferproxy.settings.valid.port=Ingrese un puerto v\u00e1lido.
filetransferproxy.settings.confirm.updated=Configuraci\u00f3n actualizada con \u00e9xito.
filetransfer.error.disabled=File Transfer Has Been Disabled, Proxy Won't Function
# File Transfer Proxy Stats
stat.filetransferproxy.transfered.name = Proxy Transfer Rate
stat.filetransferproxy.transfered.desc = The amount of data in kilobytes being transfered through the file transfer\
proxy.
stat.filetransferproxy.transfered.units = Kb/s
# System Cache page
......@@ -1447,4 +1455,4 @@ pubsub.command.pending-subscriptions.error.idrequired=ID del nodo no encontrado.
pubsub.command.pending-subscriptions.error.manyIDs=M\u00e1s de un nodo fue seleccionado.
pubsub.command.pending-subscriptions.success=Las Suscripciones Pendientes han sido enviadas.
pubsub.command.pending-subscriptions.error.forbidden=Permiso denegado.
pubsub.command.pending-subscriptions.error.badid=ID de nodo no v\u00e1lido fue seleccionado.
\ No newline at end of file
pubsub.command.pending-subscriptions.error.badid=ID de nodo no v\u00e1lido fue seleccionado.
\ No newline at end of file
......@@ -1597,6 +1597,14 @@ filetransferproxy.settings.label_enable=Activ\u00e9
filetransferproxy.settings.label_enable_info=Ce serveur sera un proxy pour transfert de fichiers sur le port :
filetransferproxy.settings.valid.port=Veuillez saisir un port valide.
filetransferproxy.settings.confirm.updated=Les param\u00e8tres de proxy de transfert de fichiers ont \u00e9t\u00e9 mis \u00e0 jour avec succ\u00e8s.=======
filetransfer.error.disabled=File Transfer Has Been Disabled, Proxy Won't Function
# File Transfer Proxy Stats
stat.filetransferproxy.transfered.name = Proxy Transfer Rate
stat.filetransferproxy.transfered.desc = The amount of data in kilobytes being transfered through the file transfer\
proxy.
stat.filetransferproxy.transfered.units = Kb/s
# System Cache page
system.cache.title=Cache
......
......@@ -1485,6 +1485,14 @@ filetransferproxy.settings.label_enable=Enabled
filetransferproxy.settings.label_enable_info=This server will act as a file transfer proxy on port:
filetransferproxy.settings.valid.port=Please enter a valid port.
filetransferproxy.settings.confirm.updated=File transfer proxy settings updated succesfully.
filetransfer.error.disabled=File Transfer Has Been Disabled, Proxy Won't Function
# File Transfer Proxy Stats
stat.filetransferproxy.transfered.name = Proxy Transfer Rate
stat.filetransferproxy.transfered.desc = The amount of data in kilobytes being transfered through the file transfer\
proxy.
stat.filetransferproxy.transfered.units = Kb/s
# System Cache page
system.cache.title=Cache Summary
......@@ -1574,4 +1582,4 @@ pubsub.command.pending-subscriptions.error.idrequired=ID of node is missing.
pubsub.command.pending-subscriptions.error.manyIDs=More than one nodeID was selected.
pubsub.command.pending-subscriptions.success=Pending subscriptions have been sent.
pubsub.command.pending-subscriptions.error.forbidden=Permission denied.
pubsub.command.pending-subscriptions.error.badid=Invalid node ID was selected.
\ No newline at end of file
pubsub.command.pending-subscriptions.error.badid=Invalid node ID was selected.
......@@ -1459,6 +1459,14 @@ filetransferproxy.settings.label_enable=Aktywny
filetransferproxy.settings.label_enable_info=Ten serwer b\u0119dzie pracowa\u0142 w trybie proxy na porcie:
filetransferproxy.settings.valid.port=Prosz\u0119 poda\u0107 poprawny numer portu.
filetransferproxy.settings.confirm.updated=Zaktualizowano ustawienia proxy.
filetransfer.error.disabled=File Transfer Has Been Disabled, Proxy Won't Function
# File Transfer Proxy Stats
stat.filetransferproxy.transfered.name = Proxy Transfer Rate
stat.filetransferproxy.transfered.desc = The amount of data in kilobytes being transfered through the file transfer\
proxy.
stat.filetransferproxy.transfered.units = Kb/s
# System Cache page
system.cache.title=W\u0142a\u015bciwo\u015bci cache
......
......@@ -1485,6 +1485,14 @@ filetransferproxy.settings.label_enable=Ativado
filetransferproxy.settings.label_enable_info=Este servidor atuar\u00e1 como um proxy de transfer\u00eancia de arquivos na porta:
filetransferproxy.settings.valid.port=Favor informar uma porta v\u00e1lida.
filetransferproxy.settings.confirm.updated=Configura\u00e7\u00f5es do proxy de transfer\u00eancia de arquivos atualizadas com sucesso.
filetransfer.error.disabled=File Transfer Has Been Disabled, Proxy Won't Function
# File Transfer Proxy Stats
stat.filetransferproxy.transfered.name = Proxy Transfer Rate
stat.filetransferproxy.transfered.desc = The amount of data in kilobytes being transfered through the file transfer\
proxy.
stat.filetransferproxy.transfered.units = Kb/s
# System Cache page
system.cache.title=Listagem de Cache
......@@ -1575,4 +1583,4 @@ pubsub.command.pending-subscriptions.error.idrequired=A ID do n\u00f3 est\u00e1
pubsub.command.pending-subscriptions.error.manyIDs=Mais de uma ID de n\u00f3 foi selecionada.
pubsub.command.pending-subscriptions.success=Subscri\u00e7\u00f5es pendentes foram enviadas.
pubsub.command.pending-subscriptions.error.forbidden=Permiss\u00e3o negada.
pubsub.command.pending-subscriptions.error.badid=Foi selecionada uma ID de n\u00f3 inv\u00e1lida.
pubsub.command.pending-subscriptions.error.badid=Foi selecionada uma ID de n\u00f3 inv\u00e1lida.
\ No newline at end of file
......@@ -1357,6 +1357,14 @@ filetransferproxy.settings.label_enable=\u4f7f\u7528
filetransferproxy.settings.label_enable_info=\u6b64\u670d\u52a1\u5668\u5728\u4e00\u4e2a\u6307\u5b9a\u7aef\u53e3\u505a\u4e3a\u4e00\u4e2a\u6587\u4ef6\u4ee3\u7406\u670d\u52a1\u5668\u4f7f\u7528:
filetransferproxy.settings.valid.port=\u8bf7\u8f93\u5165\u4e00\u4e2a\u6709\u6548\u7684\u7aef\u53e3\u3002
filetransferproxy.settings.confirm.updated=\u6587\u4ef6\u4f20\u9001\u4ee3\u7406\u8bbe\u7f6e\u66f4\u65b0\u6210\u529f\u3002
filetransfer.error.disabled=File Transfer Has Been Disabled, Proxy Won't Function
# File Transfer Proxy Stats
stat.filetransferproxy.transfered.name = Proxy Transfer Rate
stat.filetransferproxy.transfered.desc = The amount of data in kilobytes being transfered through the file transfer\
proxy.
stat.filetransferproxy.transfered.units = Kb/s
# System Cache page
system.cache.title=\u7f13\u5b58\u6458\u8981
......@@ -1441,3 +1449,4 @@ pubsub.command.pending-subscriptions.error.manyIDs=\u88ab\u9009\u7684\u8282\u70b
pubsub.command.pending-subscriptions.success=\u672a\u786e\u5b9a\u7684\u8ba2\u9605\u88ab\u4f20\u9001\u3002
pubsub.command.pending-subscriptions.error.forbidden=\u8bf7\u6c42\u88ab\u62d2\u7edd\u3002
pubsub.command.pending-subscriptions.error.badid=\u65e0\u6548\u7684\u8282\u70b9\u53f7\u88ab\u9009\u62e9\u3002
......@@ -10,8 +10,8 @@
*/
package org.jivesoftware.wildfire.filetransfer;
import org.jivesoftware.util.CacheManager;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.Cache;
import org.jivesoftware.wildfire.auth.UnauthorizedException;
import org.dom4j.Element;
......@@ -28,17 +28,18 @@ public abstract class AbstractFileTransferManager implements FileTransferManager
private final Map<String, FileTransfer> fileTransferMap;
/**
* True if a proxy transfer is required to have a matching file transfer.
*/
private boolean isMatchProxyTransfer;
/**
* Default constructor creates the cache.
*/
public AbstractFileTransferManager() {
fileTransferMap = CacheManager.initializeCache(CACHE_NAME, "fileTransfer", 128 * 1024, 1000 * 60 * 10);
isMatchProxyTransfer = JiveGlobals.getBooleanProperty("xmpp.proxy.transfer.required", true);
fileTransferMap = createCache(CACHE_NAME, "fileTransfer", 128 * 1024, 1000 * 60 * 10);
}
private Cache<String, FileTransfer> createCache(String name, String propertiesName, int size, long expirationTime) {
size = JiveGlobals.getIntProperty("cache." + propertiesName + ".size", size);
expirationTime = (long) JiveGlobals.getIntProperty(
"cache." + propertiesName + ".expirationTime", (int) expirationTime);
return new Cache<String, FileTransfer>(name, size, expirationTime);
}
/**
......@@ -47,7 +48,7 @@ public abstract class AbstractFileTransferManager implements FileTransferManager
* @return Returns true if the proxy transfer should be matched to an existing file transfer in the system.
*/
public boolean isMatchProxyTransfer() {
return isMatchProxyTransfer;
return JiveGlobals.getBooleanProperty("xmpp.proxy.transfer.required", true);
}
public void cacheFileTransfer(String key, FileTransfer transfer) {
......
......@@ -13,12 +13,14 @@ package org.jivesoftware.wildfire.filetransfer;
import org.jivesoftware.util.Cacheable;
import org.jivesoftware.util.CacheSizes;
import java.io.Serializable;
/**
* Contains all of the meta information associated with a file transfer.
*
* @author Alexander Wenckus
*/
public class FileTransfer implements Cacheable {
public class FileTransfer implements Cacheable, Serializable {
private String sessionID;
private String initiator;
......
......@@ -15,6 +15,8 @@ import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.PropertyEventDispatcher;
import org.jivesoftware.util.PropertyEventListener;
import org.jivesoftware.wildfire.*;
import org.jivesoftware.wildfire.filetransfer.spi.DefaultFileTransferManager;
import org.jivesoftware.wildfire.interceptor.InterceptorManager;
......@@ -43,8 +45,48 @@ import java.util.*;
public class FileTransferProxy extends BasicModule
implements ServerItemsProvider, DiscoInfoProvider, DiscoItemsProvider,
RoutableChannelHandler {
/**
* The JiveProperty relating to whether or not file transfer is currently enabled. If file 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";
/**
* The JiveProperty relating to whether or not the file treansfer proxy is enabled.
*/
public static final String JIVEPROPERTY_PROXY_ENABLED = "xmpp.proxy.enabled";
/**
* The JiveProperty relating to the port the proxy is operating on. Changing this value requires a restart of the
* proxy.
*/
public static final String JIVEPROPERTY_PORT = "xmpp.proxy.port";
/**
* Whether or not the file transfer proxy is enabled by default.
*/
public static final boolean DEFAULT_IS_PROXY_ENABLED = true;
/**
* Whether or not the file transfer is enabled.
*/
public static final boolean DEFAULT_IS_FILE_TRANSFER_ENABLED = true;
/**
* The default port of the file transfer proxy
*/
public static final int DEFAULT_PORT = 7777;
private static final String NAMESPACE_BYTESTREAMS = "http://jabber.org/protocol/bytestreams";
/**
* Stream Initiation, SI, namespace
*/
private static final String NAMESPACE_SI = "http://jabber.org/protocol/si";
private static final String NAMESPACE = "http://jabber.org/protocol/bytestreams";
private static final List<String> FILETRANSFER_NAMESPACES
= Arrays.asList(NAMESPACE_BYTESTREAMS, NAMESPACE_SI);
private String proxyServiceName;
......@@ -54,13 +96,15 @@ public class FileTransferProxy extends BasicModule
private String proxyIP;
private ProxyConnectionManager connectionManager;
private FileTransferManager transferManager;
private boolean isFileTransferEnabled;
public FileTransferProxy() {
super("SOCKS5 file transfer proxy");
info = new IQHandlerInfo("query", NAMESPACE);
info = new IQHandlerInfo("query", NAMESPACE_BYTESTREAMS);
InterceptorManager.getInstance().addInterceptor(new FileTransferInterceptor());
PropertyEventDispatcher.addListener(new FileTransferPropertyListener());
}
public boolean handleIQ(IQ packet) throws UnauthorizedException {
......@@ -96,10 +140,10 @@ public class FileTransferProxy extends BasicModule
// Do nothing. This error should never happen
}
}
else if (NAMESPACE.equals(namespace)) {
else if (NAMESPACE_BYTESTREAMS.equals(namespace)) {
if (packet.getType() == IQ.Type.get) {
IQ reply = IQ.createResultIQ(packet);
Element newChild = reply.setChildElement("query", NAMESPACE);
Element newChild = reply.setChildElement("query", NAMESPACE_BYTESTREAMS);
Element response = newChild.addElement("streamhost");
response.addAttribute("jid", getServiceDomain());
response.addAttribute("host", proxyIP);
......@@ -150,6 +194,7 @@ public class FileTransferProxy extends BasicModule
}
transferManager = getFileTransferManager();
connectionManager = new ProxyConnectionManager(transferManager);
isFileTransferEnabled = isFileTransferEnabled();
}
private FileTransferManager getFileTransferManager() {
......@@ -160,17 +205,21 @@ public class FileTransferProxy extends BasicModule
super.start();
if (isEnabled()) {
connectionManager.processConnections(getProxyPort());
routingTable.addRoute(getAddress(), this);
XMPPServer server = XMPPServer.getInstance();
server.getIQDiscoItemsHandler().addServerItemsProvider(this);
startProxy();
}
else {
XMPPServer.getInstance().getIQDiscoItemsHandler().removeServerItemsProvider(this);
}
}
private void startProxy() {
connectionManager.processConnections(getProxyPort());
routingTable.addRoute(getAddress(), this);
XMPPServer server = XMPPServer.getInstance();
server.getIQDiscoItemsHandler().addServerItemsProvider(this);
}
public void stop() {
super.stop();
......@@ -186,27 +235,63 @@ public class FileTransferProxy extends BasicModule
connectionManager.shutdown();
}
public void setEnabled(boolean isEnabled) {
JiveGlobals.setProperty("xmpp.proxy.enabled", Boolean.toString(isEnabled));
public void enableFileTransfer(boolean isEnabled) {
JiveGlobals.setProperty(JIVEPROPERTY_FILE_TRANSFER_ENABLED, Boolean.toString(isEnabled));
}
public void enableFileTransferProxy(boolean isEnabled) {
JiveGlobals.setProperty(FileTransferProxy.JIVEPROPERTY_PROXY_ENABLED, Boolean.toString(isEnabled));
}
private void setEnabled(boolean isEnabled) {
if (isEnabled) {
start();
startProxy();
}
else {
stop();
}
}
public boolean isEnabled() {
return connectionManager.isRunning() ||
JiveGlobals.getBooleanProperty("xmpp.proxy.enabled", true);
private void setEnabledFileTransfer(boolean isEnabled) {
isFileTransferEnabled = isEnabled;
setEnabled(isEnabled && JiveGlobals.getBooleanProperty(JIVEPROPERTY_PROXY_ENABLED, DEFAULT_IS_PROXY_ENABLED));
}
public boolean isFileTransferEnabled() {
return JiveGlobals.getBooleanProperty(JIVEPROPERTY_FILE_TRANSFER_ENABLED, DEFAULT_IS_FILE_TRANSFER_ENABLED);
}
/**
* Returns true if the file transfer proxy is currently enabled and false if it is not.
*
* @return Returns true if the file transfer proxy is currently enabled and false if it is not.
*/
public boolean isProxyEnabled() {
return connectionManager.isRunning() &&
JiveGlobals.getBooleanProperty(JIVEPROPERTY_PROXY_ENABLED, DEFAULT_IS_PROXY_ENABLED);
}
private boolean isEnabled() {
return isFileTransferEnabled() && (connectionManager.isRunning() ||
JiveGlobals.getBooleanProperty(JIVEPROPERTY_PROXY_ENABLED, DEFAULT_IS_PROXY_ENABLED));
}
/**
* Sets the port that the proxy operates on. This requires a restart of the file transfer proxy.
*
* @param port The port.
*/
public void setProxyPort(int port) {
JiveGlobals.setProperty("xmpp.proxy.port", Integer.toString(port));
JiveGlobals.setProperty(JIVEPROPERTY_PORT, Integer.toString(port));
}
/**
* Returns the port that the file transfer proxy is opertating on.
*
* @return Returns the port that the file transfer proxy is opertating on.
*/
public int getProxyPort() {
return JiveGlobals.getIntProperty("xmpp.proxy.port", 7777);
return JiveGlobals.getIntProperty(JIVEPROPERTY_PORT, DEFAULT_PORT);
}
/**
......@@ -272,7 +357,7 @@ public class FileTransferProxy extends BasicModule
}
public Iterator<String> getFeatures(String name, String node, JID senderJID) {
return Arrays.asList(new String[]{NAMESPACE, "http://jabber.org/protocol/disco#info"})
return Arrays.asList(NAMESPACE_BYTESTREAMS, "http://jabber.org/protocol/disco#info")
.iterator();
}
......@@ -317,8 +402,13 @@ public class FileTransferProxy extends BasicModule
if(childElement == null) {
return;
}
String namespace = childElement.getNamespaceURI();
if ("http://jabber.org/protocol/si".equals(namespace)) {
if(!isFileTransferEnabled && FILETRANSFER_NAMESPACES.contains(namespace)) {
throw new PacketRejectedException("File Transfer Disabled");
}
if (NAMESPACE_SI.equals(namespace)) {
// If this is a set, check the feature offer
if (iq.getType().equals(IQ.Type.set)) {
JID from = iq.getFrom();
......@@ -332,4 +422,35 @@ public class FileTransferProxy extends BasicModule
}
}
}
private class FileTransferPropertyListener implements PropertyEventListener {
public void propertySet(String property, Map params) {
if(JIVEPROPERTY_PROXY_ENABLED.equalsIgnoreCase(property)) {
Object value = params.get("value");
boolean isEnabled = (value != null ? Boolean.parseBoolean(value.toString()) : DEFAULT_IS_PROXY_ENABLED);
setEnabled(isEnabled && isFileTransferEnabled());
}
else if(JIVEPROPERTY_FILE_TRANSFER_ENABLED.equalsIgnoreCase(property)) {
Object value = params.get("value");
boolean isEnabled = (value != null ? Boolean.parseBoolean(value.toString())
: DEFAULT_IS_FILE_TRANSFER_ENABLED);
setEnabledFileTransfer(isEnabled);
}
}
public void propertyDeleted(String property, Map params) {
if(JIVEPROPERTY_PROXY_ENABLED.equalsIgnoreCase(property)) {
setEnabled(DEFAULT_IS_PROXY_ENABLED && isFileTransferEnabled());
}
else if(JIVEPROPERTY_FILE_TRANSFER_ENABLED.equalsIgnoreCase(property)){
setEnabledFileTransfer(DEFAULT_IS_FILE_TRANSFER_ENABLED);
}
}
public void xmlPropertySet(String property, Map params) {
}
public void xmlPropertyDeleted(String property, Map params) {
}
}
}
......@@ -13,6 +13,9 @@ package org.jivesoftware.wildfire.filetransfer;
import org.jivesoftware.util.*;
import org.jivesoftware.wildfire.auth.UnauthorizedException;
import org.jivesoftware.wildfire.filetransfer.spi.DefaultProxyTransfer;
import org.jivesoftware.wildfire.stats.Statistic;
import org.jivesoftware.wildfire.stats.StatisticsManager;
import org.jivesoftware.wildfire.stats.i18nStatistic;
import org.xmpp.packet.JID;
import java.io.*;
......@@ -33,6 +36,8 @@ import java.util.concurrent.Future;
*/
public class ProxyConnectionManager {
private static final String proxyTransferRate = "proxyTransferRate";
private Map<String, ProxyTransfer> connectionMap;
private final Object connectionLock = new Object();
......@@ -41,23 +46,26 @@ public class ProxyConnectionManager {
private Future<?> socketProcess;
private ServerSocket serverSocket;
private int proxyPort;
private FileTransferManager transferManager;
private String className;
static long amountTransfered = 0;
private ProxyTracker proxyTracker;
@SuppressWarnings({"unchecked"})
public ProxyConnectionManager(FileTransferManager manager) {
String cacheName = "File Transfer";
CacheManager.initializeCache(cacheName, "fileproxytransfer", -1, 1000 * 60 * 10);
connectionMap = CacheManager.getCache(cacheName);
connectionMap = CacheManager.initializeCache(cacheName, "fileproxytransfer", -1, 1000 * 60 * 10);
className = JiveGlobals.getProperty("provider.transfer.proxy",
"org.jivesoftware.wildfire.filetransfer.spi.DefaultProxyTransfer");
transferManager = manager;
this.proxyTracker = new ProxyTracker();
}
/*
......@@ -65,19 +73,13 @@ public class ProxyConnectionManager {
* This is the main loop of the manager which will run until the process is canceled.
*/
synchronized void processConnections(final int port) {
if (socketProcess != null) {
if (port != proxyPort) {
socketProcess.cancel(true);
socketProcess = null;
}
else {
return;
}
if (port == proxyPort) {
return;
}
reset(port);
socketProcess = executor.submit(new Runnable() {
public void run() {
ServerSocket serverSocket;
try {
serverSocket = new ServerSocket(port);
}
......@@ -115,6 +117,7 @@ public class ProxyConnectionManager {
}
});
proxyPort = port;
StatisticsManager.getInstance().addStatistic(proxyTransferRate, proxyTracker);
}
public int getProxyPort() {
......@@ -197,9 +200,9 @@ public class ProxyConnectionManager {
return provider;
}
@SuppressWarnings({"ResultOfMethodCallIgnored"})
private static String processIncomingSocks5Message(InputStream in)
throws IOException
{
throws IOException {
// read the version and command
byte[] cmd = new byte[5];
int read = in.read(cmd, 0, 5);
......@@ -215,8 +218,8 @@ public class ProxyConnectionManager {
}
String digest = new String(addr);
read = in.read();
read = in.read();
in.read();
in.read();
return digest;
}
......@@ -241,6 +244,7 @@ public class ProxyConnectionManager {
synchronized void shutdown() {
disable();
executor.shutdown();
StatisticsManager.getInstance().removeStatistic(proxyTransferRate);
}
/**
......@@ -296,8 +300,7 @@ public class ProxyConnectionManager {
* @return SHA-1 hash of the three parameters
*/
public static String createDigest(final String sessionID, final JID initiator,
final JID target)
{
final JID target) {
return StringUtils.hash(sessionID + initiator.getNode()
+ "@" + initiator.getDomain() + "/"
+ initiator.getResource()
......@@ -307,13 +310,40 @@ public class ProxyConnectionManager {
}
public boolean isRunning() {
return socketProcess != null;
return socketProcess != null && !socketProcess.isDone();
}
public void disable() {
reset(-1);
}
private void reset(int port) {
if (socketProcess != null) {
socketProcess.cancel(true);
socketProcess = null;
if (port != proxyPort) {
socketProcess.cancel(true);
socketProcess = null;
}
else {
return;
}
}
if (serverSocket != null) {
try {
serverSocket.close();
}
catch (IOException e) {
Log.warn("Error closing proxy listening socket", e);
}
}
}
private static class ProxyTracker extends i18nStatistic {
public ProxyTracker() {
super("filetransferproxy.transfered", Statistic.Type.rate);
}
public double sample() {
return (ProxyOutputStream.amountTransfered.getAndSet(0) / 1000);
}
}
}
}
\ No newline at end of file
/**
* $RCSfile $
* $Revision $
* $Date $
*
* Copyright (C) 1999-2005 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.OutputStream;
import java.io.IOException;
import java.io.DataOutputStream;
import java.util.concurrent.atomic.AtomicLong;
/**
* An output stream which tracks the amount of bytes transfered by proxy sockets.
*/
public class ProxyOutputStream extends DataOutputStream {
static AtomicLong amountTransfered = new AtomicLong(0);
public ProxyOutputStream(OutputStream out) {
super(out);
}
public synchronized void write(byte b[], int off, int len) throws IOException {
super.write(b, off, len);
amountTransfered.addAndGet(len);
}
}
......@@ -17,7 +17,9 @@ import org.jivesoftware.wildfire.filetransfer.FileTransfer;
import org.jivesoftware.wildfire.filetransfer.ProxyConnectionManager;
/**
*
* The default implementation of the file transfer manager. The only acceptance criteria for a proxy
* transfer is employed in the <i>ProxyConnectionManager</i>, it checks that the file transfers stored
* hre
*/
public class DefaultFileTransferManager extends AbstractFileTransferManager {
public boolean acceptIncomingFileTransferRequest(String packetID, JID from, JID to, Element siElement) {
......
......@@ -12,20 +12,19 @@ package org.jivesoftware.wildfire.filetransfer.spi;
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;
import java.io.OutputStream;
import java.io.DataOutputStream;
/**
* Tracks the different connections related to a file transfer. There are two connections, the
* initiator and the target and when both connections are completed the transfer can begin.
*/
public class DefaultProxyTransfer implements ProxyTransfer {
private static long amountTransfered;
private String initiator;
......@@ -158,14 +157,4 @@ public class DefaultProxyTransfer implements ProxyTransfer {
return size;
}
static class ProxyOutputStream extends DataOutputStream {
public ProxyOutputStream(OutputStream out) {
super(out);
}
public synchronized void write(byte b[], int off, int len) throws IOException {
super.write(b, off, len);
amountTransfered += len;
}
}
}
......@@ -8,10 +8,10 @@
- a copy of which is included in this distribution.
--%>
<%@ page import="org.jivesoftware.util.ParamUtils" %>
<%@ page import="org.jivesoftware.wildfire.XMPPServer" %>
<%@ page import="org.jivesoftware.wildfire.filetransfer.FileTransferProxy" %>
<%@ page import="java.util.HashMap" %>
<%@ page import="java.util.Map" %>
<%@ page import="org.jivesoftware.wildfire.XMPPServer"%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jstl/fmt_rt" prefix="fmt" %>
......@@ -20,9 +20,11 @@
<% webManager.init(request, response, session, application, out); %>
<%
Map errors = new HashMap();
Map<String, String> errors = new HashMap<String, String>();
FileTransferProxy transferProxy = XMPPServer.getInstance().getFileTransferProxy();
boolean isFileTransferEnabled = transferProxy.isFileTransferEnabled();
boolean isUpdated = request.getParameter("update") != null;
boolean isProxyEnabled = ParamUtils.getBooleanParameter(request, "proxyEnabled");
int port = ParamUtils.getIntParameter(request, "port", 0);
......@@ -38,12 +40,12 @@
if (isProxyEnabled) {
transferProxy.setProxyPort(port);
}
transferProxy.setEnabled(isProxyEnabled);
transferProxy.enableFileTransferProxy(isProxyEnabled);
}
}
if (errors.isEmpty()) {
isProxyEnabled = transferProxy.isEnabled();
isProxyEnabled = transferProxy.isProxyEnabled();
port = transferProxy.getProxyPort();
}
else {
......@@ -60,17 +62,18 @@
<p>
<fmt:message key="filetransferproxy.settings.info"/>
</p>
<% if (!errors.isEmpty()) { %>
<% if (!isFileTransferEnabled || !errors.isEmpty()) { %>
<div class="jive-error">
<table cellpadding="0" cellspacing="0" border="0">
<tbody>
<tr>
<td class="jive-icon"><img src="images/error-16x16.gif" width="16" height="16"
<td class="jive-icon"><img alt="error" src="images/error-16x16.gif" width="16" height="16"
border="0"/></td>
<td class="jive-icon-label">
<% if (errors.get("port") != null) { %>
<% if(!isFileTransferEnabled) { %>
<fmt:message key="filetransfer.error.disabled"/>
<% } else if (errors.get("port") != null) { %>
<fmt:message key="filetransferproxy.settings.valid.port"/>
<% } %>
</td>
......@@ -85,7 +88,7 @@ else if (isUpdated) { %>
<div class="jive-success">
<table cellpadding="0" cellspacing="0" border="0">
<tbody>
<tr><td class="jive-icon"><img src="images/success-16x16.gif" width="16" height="16"
<tr><td class="jive-icon"><img alt="Success" src="images/success-16x16.gif" width="16" height="16"
border="0"></td>
<td class="jive-icon-label">
<fmt:message key="filetransferproxy.settings.confirm.updated"/>
......@@ -110,20 +113,20 @@ else { %>
<tr valign="middle">
<td width="1%" nowrap>
<input type="radio" name="proxyEnabled" value="true" id="rb02"
<%= (isProxyEnabled ? "checked" : "") %>>
<%= (isProxyEnabled ? "checked" : "") %> <%=!isFileTransferEnabled ? "disabled" : ""%>>
</td>
<td width="99%">
<label for="rb02">
<b><fmt:message key="filetransferproxy.settings.label_enable"/></b>
- <fmt:message key="filetransferproxy.settings.label_enable_info"/>
</label> <input type="text" size="5" maxlength="10" name="port"
value="<%= port %>">
value="<%= port %>" <%=!isFileTransferEnabled ? "disabled" : ""%>>
</td>
</tr>
<tr valign="middle">
<td width="1%" nowrap>
<input type="radio" name="proxyEnabled" value="false" id="rb01"
<%= (!isProxyEnabled ? "checked" : "") %>>
<%= (!isProxyEnabled ? "checked" : "") %> <%=!isFileTransferEnabled ? "disabled" : ""%>>
</td>
<td width="99%">
<label for="rb01">
......@@ -139,7 +142,8 @@ else { %>
</fieldset>
<br>
<input type="submit" name="update" value="<fmt:message key="global.save_settings" />">
<input type="submit" name="update" value="<fmt:message key="global.save_settings" />"
<%=!isFileTransferEnabled ? "disabled" : ""%>>
</form>
</body>
......
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