From 386b0abcdd1132635271374695de89d961f8736b Mon Sep 17 00:00:00 2001 From: Alex Wenckus Date: Wed, 5 Jul 2006 18:34:11 +0000 Subject: [PATCH] After 2 failed connection attempts file transfer will black list a stream host for 2 hours. SMACK-138 git-svn-id: http://svn.igniterealtime.org/svn/repos/smack/trunk@4261 b35dd754-fafc-0310-a699-88a17e54d16e --- .../Socks5TransferNegotiator.java | 46 +++++++++++++++++-- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/source/org/jivesoftware/smackx/filetransfer/Socks5TransferNegotiator.java b/source/org/jivesoftware/smackx/filetransfer/Socks5TransferNegotiator.java index 7e357d17f..fa893c33e 100644 --- a/source/org/jivesoftware/smackx/filetransfer/Socks5TransferNegotiator.java +++ b/source/org/jivesoftware/smackx/filetransfer/Socks5TransferNegotiator.java @@ -31,6 +31,7 @@ import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.Packet; import org.jivesoftware.smack.packet.XMPPError; import org.jivesoftware.smack.util.StringUtils; +import org.jivesoftware.smack.util.Cache; import org.jivesoftware.smackx.ServiceDiscoveryManager; import org.jivesoftware.smackx.packet.Bytestream; import org.jivesoftware.smackx.packet.Bytestream.StreamHost; @@ -72,6 +73,15 @@ public class Socks5TransferNegotiator extends StreamNegotiator { protected static final String NAMESPACE = "http://jabber.org/protocol/bytestreams"; + /** + * The number of connection failures it takes to a streamhost for that particular streamhost + * to be blacklisted. When a host is blacklisted no more connection attempts will be made to + * it for a period of 2 hours. + */ + private static final int CONNECT_FAILURE_THRESHOLD = 2; + + private static final long BLACKLIST_LIFETIME = 60 * 1000 * 120; + public static boolean isAllowLocalProxyHost = true; private final XMPPConnection connection; @@ -88,6 +98,8 @@ public class Socks5TransferNegotiator extends StreamNegotiator { // locks on the proxy process during its initiatilization process private final Object processLock = new Object(); + private final Cache addressBlacklist = new Cache(100, BLACKLIST_LIFETIME); + public Socks5TransferNegotiator(final XMPPConnection connection) { this.connection = connection; } @@ -169,9 +181,12 @@ public class Socks5TransferNegotiator extends StreamNegotiator { } /** - * @param streamHostsInfo - * @return - * @throws XMPPException + * Selects a host to connect to over which the file will be transmitted. + * + * @param streamHostsInfo the packet recieved from the initiator containing the available hosts + * to transfer the file + * @return the selected host and socket that were created. + * @throws XMPPException when there is no appropriate host. */ private SelectedHostInfo selectHost(Bytestream streamHostsInfo) throws XMPPException @@ -181,10 +196,16 @@ public class Socks5TransferNegotiator extends StreamNegotiator { Socket socket = null; while (it.hasNext()) { selectedHost = (StreamHost) it.next(); + String address = selectedHost.getAddress(); + // Check to see if this address has been blacklisted + int failures = getConnectionFailures(address); + if(failures >= CONNECT_FAILURE_THRESHOLD) { + continue; + } // establish socket try { - socket = new Socket(selectedHost.getAddress(), selectedHost + socket = new Socket(address, selectedHost .getPort()); establishSOCKS5ConnectionToProxy(socket, createDigest( streamHostsInfo.getSessionID(), streamHostsInfo @@ -193,6 +214,7 @@ public class Socks5TransferNegotiator extends StreamNegotiator { } catch (IOException e) { e.printStackTrace(); + incrementConnectionFailures(address); selectedHost = null; socket = null; } @@ -205,6 +227,22 @@ public class Socks5TransferNegotiator extends StreamNegotiator { return new SelectedHostInfo(selectedHost, socket); } + private void incrementConnectionFailures(String address) { + Integer count = (Integer) addressBlacklist.get(address); + if(count == null) { + count = new Integer(1); + } + else { + count = new Integer(count.intValue() + 1); + } + addressBlacklist.put(address, count); + } + + private int getConnectionFailures(String address) { + Integer count = (Integer) addressBlacklist.get(address); + return (count != null ? count.intValue() : 0); + } + /** * Creates the digest needed for a byte stream. It is the SHA1(sessionID + * initiator + target).