diff --git a/smack-core/src/test/java/org/jivesoftware/smack/util/NetworkUtil.java b/smack-core/src/test/java/org/jivesoftware/smack/util/NetworkUtil.java
index d111963f9..ac58e8790 100644
--- a/smack-core/src/test/java/org/jivesoftware/smack/util/NetworkUtil.java
+++ b/smack-core/src/test/java/org/jivesoftware/smack/util/NetworkUtil.java
@@ -1,6 +1,6 @@
/**
*
- * Copyright 2016 Florian Schmaus
+ * Copyright 2016-2019 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,7 +27,7 @@ public class NetworkUtil {
private static final Logger LOGGER = Logger.getLogger(NetworkUtil.class.getName());
- public static ServerSocket getSocketOnLoopback() {
+ public static ServerSocket getSocketOnLoopback() throws IOException {
final InetAddress loopbackAddress = InetAddress.getLoopbackAddress();
final int portMin = 1024;
final int portMax = (1 << 16) - 1;
@@ -40,13 +40,12 @@ public class NetworkUtil {
break;
} catch (BindException e) {
LOGGER.log(Level.FINEST, "Could not bind port " + port + ", trying next", e);
- } catch (IOException e) {
- throw new IllegalStateException(e);
}
}
if (serverSocket == null) {
- throw new IllegalStateException();
+ throw new IOException("Could not bind any port between " + portMin + " and " + portMax
+ + " on loopback address" + loopbackAddress);
}
return serverSocket;
diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5BytestreamManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5BytestreamManager.java
index 7daf62c85..480c4251f 100644
--- a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5BytestreamManager.java
+++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5BytestreamManager.java
@@ -56,6 +56,7 @@ import org.jivesoftware.smackx.disco.packet.DiscoverItems;
import org.jivesoftware.smackx.disco.packet.DiscoverItems.Item;
import org.jivesoftware.smackx.filetransfer.FileTransferManager;
+import org.jxmpp.jid.EntityFullJid;
import org.jxmpp.jid.Jid;
/**
@@ -149,6 +150,8 @@ public final class Socks5BytestreamManager extends Manager implements Bytestream
/* flag to enable/disable prioritization of last working proxy */
private boolean proxyPrioritizationEnabled = true;
+ private boolean annouceLocalStreamHost = true;
+
/*
* list containing session IDs of SOCKS5 Bytestream initialization packets that should be
* ignored by the InitiationListener
@@ -375,6 +378,30 @@ public final class Socks5BytestreamManager extends Manager implements Bytestream
this.proxyPrioritizationEnabled = proxyPrioritizationEnabled;
}
+ /**
+ * Returns if the bytestream manager will announce the local stream host(s), i.e. the local SOCKS5 proxy.
+ *
+ * Local stream hosts will be announced if this option is enabled and at least one is running.
+ *
+ *
+ * @return true
if
+ * @since 4.4.0
+ */
+ public boolean isAnnouncingLocalStreamHostEnabled() {
+ return annouceLocalStreamHost;
+ }
+
+ /**
+ * Set whether or not the bytestream manager will annouce the local stream host(s), i.e. the local SOCKS5 proxy.
+ *
+ * @param announceLocalStreamHost
+ * @see #isAnnouncingLocalStreamHostEnabled()
+ * @since 4.4.0
+ */
+ public void setAnnounceLocalStreamHost(boolean announceLocalStreamHost) {
+ this.annouceLocalStreamHost = announceLocalStreamHost;
+ }
+
/**
* Establishes a SOCKS5 Bytestream with the given user and returns the Socket to send/receive
* data to/from the user.
@@ -592,10 +619,12 @@ public final class Socks5BytestreamManager extends Manager implements Bytestream
XMPPConnection connection = connection();
List streamHosts = new ArrayList<>();
- // add local proxy on first position if exists
- List localProxies = getLocalStreamHost();
- if (localProxies != null) {
- streamHosts.addAll(localProxies);
+ if (annouceLocalStreamHost) {
+ // add local proxy on first position if exists
+ List localProxies = getLocalStreamHost();
+ if (localProxies != null) {
+ streamHosts.addAll(localProxies);
+ }
}
// query SOCKS5 proxies for network settings
@@ -636,34 +665,33 @@ public final class Socks5BytestreamManager extends Manager implements Bytestream
* is not running
*/
public List getLocalStreamHost() {
- XMPPConnection connection = connection();
- // get local proxy singleton
- Socks5Proxy socks5Server = Socks5Proxy.getSocks5Proxy();
-
- if (!socks5Server.isRunning()) {
- // server is not running
- return null;
- }
- List addresses = socks5Server.getLocalAddresses();
- if (addresses.isEmpty()) {
- // local address could not be determined
- return null;
- }
- final int port = socks5Server.getPort();
-
List streamHosts = new ArrayList<>();
- outerloop: for (String address : addresses) {
- // Prevent loopback addresses from appearing as streamhost
- final String[] loopbackAddresses = { "127.0.0.1", "0:0:0:0:0:0:0:1", "::1" };
- for (String loopbackAddress : loopbackAddresses) {
- // Use 'startsWith' here since IPv6 addresses may have scope ID,
- // ie. the part after the '%' sign.
- if (address.startsWith(loopbackAddress)) {
- continue outerloop;
- }
+
+ XMPPConnection connection = connection();
+ EntityFullJid myJid = connection.getUser();
+
+ for (Socks5Proxy socks5Server : Socks5Proxy.getRunningProxies()) {
+ List addresses = socks5Server.getLocalAddresses();
+ if (addresses.isEmpty()) {
+ // local address could not be determined
+ return null;
+ }
+ final int port = socks5Server.getPort();
+
+ outerloop: for (String address : addresses) {
+ // Prevent loopback addresses from appearing as streamhost
+ final String[] loopbackAddresses = { "127.0.0.1", "0:0:0:0:0:0:0:1", "::1" };
+ for (String loopbackAddress : loopbackAddresses) {
+ // Use 'startsWith' here since IPv6 addresses may have scope ID,
+ // ie. the part after the '%' sign.
+ if (address.startsWith(loopbackAddress)) {
+ continue outerloop;
+ }
+ }
+ streamHosts.add(new StreamHost(myJid, address, port));
}
- streamHosts.add(new StreamHost(connection.getUser(), address, port));
}
+
return streamHosts;
}
diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5BytestreamRequest.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5BytestreamRequest.java
index 92e17a381..1dda14dd5 100644
--- a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5BytestreamRequest.java
+++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5BytestreamRequest.java
@@ -57,12 +57,14 @@ public class Socks5BytestreamRequest implements BytestreamRequest {
private static final Cache ADDRESS_BLACKLIST = new ExpirationCache(
BLACKLIST_MAX_SIZE, BLACKLIST_LIFETIME);
+ private static int DEFAULT_CONNECTION_FAILURE_THRESHOLD = 2;
+
/*
* The number of connection failures it takes for a particular SOCKS5 proxy to be blacklisted.
* When a proxy is blacklisted no more connection attempts will be made to it for a period of 2
* hours.
*/
- private static int CONNECTION_FAILURE_THRESHOLD = 2;
+ private int connectionFailureThreshold = DEFAULT_CONNECTION_FAILURE_THRESHOLD;
/* the bytestream initialization request */
private Bytestream bytestreamRequest;
@@ -76,6 +78,28 @@ public class Socks5BytestreamRequest implements BytestreamRequest {
/* minimum timeout to connect to one SOCKS5 proxy */
private int minimumConnectTimeout = 2000;
+ /**
+ * Returns the default connection failure threshold.
+ *
+ * @return the default connection failure threshold.
+ * @see #setConnectFailureThreshold(int)
+ * @since 4.4.0
+ */
+ public static int getDefaultConnectFailureThreshold() {
+ return DEFAULT_CONNECTION_FAILURE_THRESHOLD;
+ }
+
+ /**
+ * Sets the default connection failure threshold.
+ *
+ * @param defaultConnectFailureThreshold the default connection failure threshold.
+ * @see #setConnectFailureThreshold(int)
+ * @since 4.4.0
+ */
+ public static void setDefaultConnectFailureThreshold(int defaultConnectFailureThreshold) {
+ DEFAULT_CONNECTION_FAILURE_THRESHOLD = defaultConnectFailureThreshold;
+ }
+
/**
* Returns the number of connection failures it takes for a particular SOCKS5 proxy to be
* blacklisted. When a proxy is blacklisted no more connection attempts will be made to it for a
@@ -84,8 +108,8 @@ public class Socks5BytestreamRequest implements BytestreamRequest {
* @return the number of connection failures it takes for a particular SOCKS5 proxy to be
* blacklisted
*/
- public static int getConnectFailureThreshold() {
- return CONNECTION_FAILURE_THRESHOLD;
+ public int getConnectFailureThreshold() {
+ return connectionFailureThreshold;
}
/**
@@ -98,8 +122,8 @@ public class Socks5BytestreamRequest implements BytestreamRequest {
* @param connectFailureThreshold the number of connection failures it takes for a particular
* SOCKS5 proxy to be blacklisted
*/
- public static void setConnectFailureThreshold(int connectFailureThreshold) {
- CONNECTION_FAILURE_THRESHOLD = connectFailureThreshold;
+ public void setConnectFailureThreshold(int connectFailureThreshold) {
+ connectionFailureThreshold = connectFailureThreshold;
}
/**
@@ -234,7 +258,7 @@ public class Socks5BytestreamRequest implements BytestreamRequest {
// check to see if this address has been blacklisted
int failures = getConnectionFailures(address);
- if (CONNECTION_FAILURE_THRESHOLD > 0 && failures >= CONNECTION_FAILURE_THRESHOLD) {
+ if (connectionFailureThreshold > 0 && failures >= connectionFailureThreshold) {
continue;
}
diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5Client.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5Client.java
index 83965e7ca..c46f4af65 100644
--- a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5Client.java
+++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5Client.java
@@ -36,6 +36,7 @@ import org.jivesoftware.smack.SmackException.NoResponseException;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.SmackException.SmackMessageException;
import org.jivesoftware.smack.XMPPException;
+import org.jivesoftware.smack.util.Async;
import org.jivesoftware.smack.util.CloseableUtil;
import org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream.StreamHost;
@@ -111,27 +112,14 @@ public class Socks5Client {
}
});
- Thread executor = new Thread(futureTask);
- executor.start();
+ Async.go(futureTask, "SOCKS5 client connecting to " + streamHost);
// get connection to initiator with timeout
try {
return futureTask.get(timeout, TimeUnit.MILLISECONDS);
}
catch (ExecutionException e) {
- Throwable cause = e.getCause();
- if (cause != null) {
- // case exceptions to comply with method signature
- if (cause instanceof IOException) {
- throw (IOException) cause;
- }
- if (cause instanceof SmackMessageException) {
- throw (SmackMessageException) cause;
- }
- }
-
- // throw generic Smack exception if unexpected exception was thrown
- throw new IllegalStateException("Error while connecting to SOCKS5 proxy", e);
+ throw new IOException("ExecutionException while SOCKS5 client attempting to connect to " + streamHost, e);
}
}
diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5ClientForInitiator.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5ClientForInitiator.java
index 714e849af..adca9931f 100644
--- a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5ClientForInitiator.java
+++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5ClientForInitiator.java
@@ -79,8 +79,7 @@ public class Socks5ClientForInitiator extends Socks5Client {
// check if stream host is the local SOCKS5 proxy
if (this.streamHost.getJID().equals(this.connection.get().getUser())) {
- Socks5Proxy socks5Server = Socks5Proxy.getSocks5Proxy();
- socket = socks5Server.getSocket(this.digest);
+ socket = Socks5Proxy.getSocketForDigest(this.digest);
if (socket == null) {
throw new SmackException.SmackMessageException("target is not connected to SOCKS5 proxy");
}
diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5Proxy.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5Proxy.java
index effab8762..ed5d59597 100644
--- a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5Proxy.java
+++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5Proxy.java
@@ -35,6 +35,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -73,6 +74,8 @@ import org.jivesoftware.smack.util.CloseableUtil;
public final class Socks5Proxy {
private static final Logger LOGGER = Logger.getLogger(Socks5Proxy.class.getName());
+ private static final List RUNNING_PROXIES = new CopyOnWriteArrayList<>();
+
/* SOCKS5 proxy singleton */
private static Socks5Proxy socks5Server;
@@ -104,7 +107,7 @@ public final class Socks5Proxy {
/**
* Private constructor.
*/
- private Socks5Proxy() {
+ Socks5Proxy() {
this.serverProcess = new Socks5ServerProcess();
Enumeration networkInterfaces;
@@ -188,9 +191,9 @@ public final class Socks5Proxy {
/**
* Starts the local SOCKS5 proxy server. If it is already running, this method does nothing.
*/
- public synchronized void start() {
+ public synchronized ServerSocket start() {
if (isRunning()) {
- return;
+ return this.serverSocket;
}
try {
if (getLocalSocks5ProxyPort() < 0) {
@@ -213,6 +216,8 @@ public final class Socks5Proxy {
this.serverThread = new Thread(this.serverProcess);
this.serverThread.setName("Smack Local SOCKS5 Proxy [" + this.serverSocket + ']');
this.serverThread.setDaemon(true);
+
+ RUNNING_PROXIES.add(this);
this.serverThread.start();
}
}
@@ -220,6 +225,8 @@ public final class Socks5Proxy {
// couldn't setup server
LOGGER.log(Level.SEVERE, "couldn't setup local SOCKS5 proxy on port " + getLocalSocks5ProxyPort(), e);
}
+
+ return this.serverSocket;
}
/**
@@ -230,6 +237,8 @@ public final class Socks5Proxy {
return;
}
+ RUNNING_PROXIES.remove(this);
+
CloseableUtil.maybeClose(this.serverSocket, LOGGER);
if (this.serverThread != null && this.serverThread.isAlive()) {
@@ -483,4 +492,17 @@ public final class Socks5Proxy {
}
+ public static Socket getSocketForDigest(String digest) {
+ for (Socks5Proxy socks5Proxy : RUNNING_PROXIES) {
+ Socket socket = socks5Proxy.getSocket(digest);
+ if (socket != null) {
+ return socket;
+ }
+ }
+ return null;
+ }
+
+ static List getRunningProxies() {
+ return RUNNING_PROXIES;
+ }
}
diff --git a/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5ByteStreamManagerTest.java b/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5ByteStreamManagerTest.java
index aec522ead..7a6784bb8 100644
--- a/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5ByteStreamManagerTest.java
+++ b/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5ByteStreamManagerTest.java
@@ -28,6 +28,8 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ConnectException;
+import java.net.ServerSocket;
+import java.util.concurrent.TimeoutException;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.SmackException.FeatureNotSupportedException;
@@ -37,6 +39,7 @@ import org.jivesoftware.smack.XMPPException.XMPPErrorException;
import org.jivesoftware.smack.packet.ErrorIQ;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.StanzaError;
+import org.jivesoftware.smack.util.NetworkUtil;
import org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream;
import org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream.StreamHost;
@@ -49,8 +52,6 @@ import org.jivesoftware.smackx.disco.packet.DiscoverItems.Item;
import org.jivesoftware.util.ConnectionUtils;
import org.jivesoftware.util.Protocol;
import org.jivesoftware.util.Verification;
-import org.junit.After;
-import org.junit.Before;
import org.junit.Test;
import org.jxmpp.jid.DomainBareJid;
import org.jxmpp.jid.EntityFullJid;
@@ -71,30 +72,6 @@ public class Socks5ByteStreamManagerTest {
private static final DomainBareJid xmppServer = initiatorJID.asDomainBareJid();
private static final DomainBareJid proxyJID = JidTestUtil.MUC_EXAMPLE_ORG;
private static final String proxyAddress = "127.0.0.1";
- private static final String sessionID = "session_id";
-
- // protocol verifier
- private Protocol protocol;
-
- // mocked XMPP connection
- private XMPPConnection connection;
-
- /**
- * Initialize fields used in the tests.
- * @throws XMPPException
- * @throws SmackException
- * @throws InterruptedException
- */
- @Before
- public void setup() throws XMPPException, SmackException, InterruptedException {
-
- // build protocol verifier
- protocol = new Protocol();
-
- // create mocked XMPP connection
- connection = ConnectionUtils.createMockedConnection(protocol, initiatorJID);
-
- }
/**
* Test that {@link Socks5BytestreamManager#getBytestreamManager(XMPPConnection)} returns one
@@ -102,7 +79,6 @@ public class Socks5ByteStreamManagerTest {
*/
@Test
public void shouldHaveOneManagerForEveryConnection() {
-
// mock two connections
XMPPConnection connection1 = mock(XMPPConnection.class);
XMPPConnection connection2 = mock(XMPPConnection.class);
@@ -124,15 +100,21 @@ public class Socks5ByteStreamManagerTest {
// assertions
assertEquals(conn1ByteStreamManager1, conn1ByteStreamManager2);
assertNotSame(conn1ByteStreamManager1, conn2ByteStreamManager1);
-
}
/**
* The SOCKS5 Bytestream feature should be removed form the service discovery manager if Socks5
* bytestream feature is disabled.
+ *
+ * @throws InterruptedException
+ * @throws SmackException
+ * @throws XMPPErrorException
*/
@Test
- public void shouldDisableService() {
+ public void shouldDisableService() throws XMPPErrorException, SmackException, InterruptedException {
+ final Protocol protocol = new Protocol();
+ final XMPPConnection connection = ConnectionUtils.createMockedConnection(protocol, initiatorJID);
+
Socks5BytestreamManager byteStreamManager = Socks5BytestreamManager.getBytestreamManager(connection);
ServiceDiscoveryManager discoveryManager = ServiceDiscoveryManager.getInstanceFor(connection);
@@ -147,9 +129,15 @@ public class Socks5ByteStreamManagerTest {
* Invoking {@link Socks5BytestreamManager#establishSession(org.jxmpp.jid.Jid)} should throw an exception
* if the given target does not support SOCKS5 Bytestream.
* @throws XMPPException
+ * @throws InterruptedException
+ * @throws SmackException
+ * @throws IOException
*/
@Test
- public void shouldFailIfTargetDoesNotSupportSocks5() throws XMPPException {
+ public void shouldFailIfTargetDoesNotSupportSocks5()
+ throws XMPPException, SmackException, InterruptedException, IOException {
+ final Protocol protocol = new Protocol();
+ final XMPPConnection connection = ConnectionUtils.createMockedConnection(protocol, initiatorJID);
Socks5BytestreamManager byteStreamManager = Socks5BytestreamManager.getBytestreamManager(connection);
try {
@@ -165,24 +153,27 @@ public class Socks5ByteStreamManagerTest {
catch (FeatureNotSupportedException e) {
assertTrue(e.getFeature().equals("SOCKS5 Bytestream"));
assertTrue(e.getJid().equals(targetJID));
- } catch (Exception e) {
- fail(e.getMessage());
}
-
}
/**
* Invoking {@link Socks5BytestreamManager#establishSession(org.jxmpp.jid.Jid, String)} should fail if XMPP
* server doesn't return any proxies.
+ * @throws InterruptedException
+ * @throws SmackException
+ * @throws XMPPException
+ * @throws IOException
*/
@Test
- public void shouldFailIfNoSocks5ProxyFound1() {
-
- // disable clients local SOCKS5 proxy
- Socks5Proxy.setLocalSocks5ProxyEnabled(false);
+ public void shouldFailIfNoSocks5ProxyFound1()
+ throws SmackException, InterruptedException, IOException, XMPPException {
+ final Protocol protocol = new Protocol();
+ final XMPPConnection connection = ConnectionUtils.createMockedConnection(protocol, initiatorJID);
+ final String sessionID = "session_id_shouldFailIfNoSocks5ProxyFound1";
// get Socks5ByteStreamManager for connection
Socks5BytestreamManager byteStreamManager = Socks5BytestreamManager.getBytestreamManager(connection);
+ byteStreamManager.setAnnounceLocalStreamHost(false);
/**
* create responses in the order they should be queried specified by the XEP-0065
@@ -206,7 +197,6 @@ public class Socks5ByteStreamManagerTest {
Verification.requestTypeGET);
try {
-
// start SOCKS5 Bytestream
byteStreamManager.establishSession(targetJID, sessionID);
@@ -216,24 +206,27 @@ public class Socks5ByteStreamManagerTest {
protocol.verifyAll();
assertTrue(e.getMessage().contains("no SOCKS5 proxies available"));
}
- catch (Exception e) {
- fail(e.getMessage());
- }
-
}
/**
* Invoking {@link Socks5BytestreamManager#establishSession(org.jxmpp.jid.Jid, String)} should fail if no
* proxy is a SOCKS5 proxy.
+ *
+ * @throws InterruptedException
+ * @throws SmackException
+ * @throws XMPPException
+ * @throws IOException
*/
@Test
- public void shouldFailIfNoSocks5ProxyFound2() {
-
- // disable clients local SOCKS5 proxy
- Socks5Proxy.setLocalSocks5ProxyEnabled(false);
+ public void shouldFailIfNoSocks5ProxyFound2()
+ throws SmackException, InterruptedException, IOException, XMPPException {
+ final Protocol protocol = new Protocol();
+ final XMPPConnection connection = ConnectionUtils.createMockedConnection(protocol, initiatorJID);
+ final String sessionID = "session_id_shouldFailIfNoSocks5ProxyFound2";
// get Socks5ByteStreamManager for connection
Socks5BytestreamManager byteStreamManager = Socks5BytestreamManager.getBytestreamManager(connection);
+ byteStreamManager.setAnnounceLocalStreamHost(false);
/**
* create responses in the order they should be queried specified by the XEP-0065
@@ -269,7 +262,6 @@ public class Socks5ByteStreamManagerTest {
Verification.requestTypeGET);
try {
-
// start SOCKS5 Bytestream
byteStreamManager.establishSession(targetJID, sessionID);
@@ -279,25 +271,26 @@ public class Socks5ByteStreamManagerTest {
protocol.verifyAll();
assertTrue(e.getMessage().contains("no SOCKS5 proxies available"));
}
- catch (Exception e) {
- fail(e.getMessage());
- }
-
}
/**
* Invoking {@link Socks5BytestreamManager#establishSession(org.jxmpp.jid.Jid, String)} should fail if no
* SOCKS5 proxy can be found. If it turns out that a proxy is not a SOCKS5 proxy it should not
* be queried again.
+ * @throws InterruptedException
+ * @throws SmackException
+ * @throws XMPPException
+ * @throws IOException
*/
@Test
- public void shouldBlacklistNonSocks5Proxies() {
-
- // disable clients local SOCKS5 proxy
- Socks5Proxy.setLocalSocks5ProxyEnabled(false);
+ public void shouldBlacklistNonSocks5Proxies() throws SmackException, InterruptedException, IOException, XMPPException {
+ final Protocol protocol = new Protocol();
+ final XMPPConnection connection = ConnectionUtils.createMockedConnection(protocol, initiatorJID);
+ final String sessionID = "session_id_shouldBlacklistNonSocks5Proxies";
// get Socks5ByteStreamManager for connection
Socks5BytestreamManager byteStreamManager = Socks5BytestreamManager.getBytestreamManager(connection);
+ byteStreamManager.setAnnounceLocalStreamHost(false);
/**
* create responses in the order they should be queried specified by the XEP-0065
@@ -333,7 +326,6 @@ public class Socks5ByteStreamManagerTest {
Verification.requestTypeGET);
try {
-
// start SOCKS5 Bytestream
byteStreamManager.establishSession(targetJID, sessionID);
@@ -343,9 +335,6 @@ public class Socks5ByteStreamManagerTest {
protocol.verifyAll();
assertTrue(e.getMessage().contains("no SOCKS5 proxies available"));
}
- catch (Exception e) {
- fail(e.getMessage());
- }
/* retry to establish SOCKS5 Bytestream */
@@ -356,7 +345,6 @@ public class Socks5ByteStreamManagerTest {
Verification.requestTypeGET);
try {
-
// start SOCKS5 Bytestream
byteStreamManager.establishSession(targetJID, sessionID);
@@ -370,25 +358,26 @@ public class Socks5ByteStreamManagerTest {
protocol.verifyAll();
assertTrue(e.getMessage().contains("no SOCKS5 proxies available"));
}
- catch (Exception e) {
- fail(e.getMessage());
- }
-
}
/**
* Invoking {@link Socks5BytestreamManager#establishSession(org.jxmpp.jid.Jid, String)} should fail if the
* target does not accept a SOCKS5 Bytestream. See XEP-0065 Section 5.2 A2
+ * @throws InterruptedException
+ * @throws SmackException
+ * @throws XMPPException
+ * @throws IOException
*/
@Test
- public void shouldFailIfTargetDoesNotAcceptSocks5Bytestream() {
-
- // disable clients local SOCKS5 proxy
- Socks5Proxy.setLocalSocks5ProxyEnabled(false);
+ public void shouldFailIfTargetDoesNotAcceptSocks5Bytestream() throws SmackException, InterruptedException, IOException, XMPPException {
+ final Protocol protocol = new Protocol();
+ final XMPPConnection connection = ConnectionUtils.createMockedConnection(protocol, initiatorJID);
+ final String sessionID = "session_id_shouldFailIfTargetDoesNotAcceptSocks5Bytestream";
// get Socks5ByteStreamManager for connection
Socks5BytestreamManager byteStreamManager = Socks5BytestreamManager.getBytestreamManager(connection);
+ byteStreamManager.setAnnounceLocalStreamHost(false);
/**
* create responses in the order they should be queried specified by the XEP-0065
@@ -443,7 +432,6 @@ public class Socks5ByteStreamManagerTest {
Verification.requestTypeSET);
try {
-
// start SOCKS5 Bytestream
byteStreamManager.establishSession(targetJID, sessionID);
@@ -453,25 +441,28 @@ public class Socks5ByteStreamManagerTest {
protocol.verifyAll();
assertEquals(rejectPacket.getError(), e.getStanzaError());
}
- catch (Exception e) {
- fail(e.getMessage());
- }
-
}
/**
* Invoking {@link Socks5BytestreamManager#establishSession(org.jxmpp.jid.Jid, String)} should fail if the
* proxy used by target is invalid.
- * @throws XmppStringprepException
+ *
+ * @throws InterruptedException
+ * @throws SmackException
+ * @throws XMPPException
+ * @throws IOException
*/
@Test
- public void shouldFailIfTargetUsesInvalidSocks5Proxy() throws XmppStringprepException {
-
- // disable clients local SOCKS5 proxy
- Socks5Proxy.setLocalSocks5ProxyEnabled(false);
+ public void shouldFailIfTargetUsesInvalidSocks5Proxy()
+ throws SmackException, InterruptedException, IOException, XMPPException {
+ final Protocol protocol = new Protocol();
+ final XMPPConnection connection = ConnectionUtils.createMockedConnection(protocol, initiatorJID);
+ final String sessionID = "session_id_shouldFailIfTargetUsesInvalidSocks5Proxy";
// get Socks5ByteStreamManager for connection
Socks5BytestreamManager byteStreamManager = Socks5BytestreamManager.getBytestreamManager(connection);
+ // TODO: It appears that it is not required to disable the local stream host for this unit test.
+ byteStreamManager.setAnnounceLocalStreamHost(false);
/**
* create responses in the order they should be queried specified by the XEP-0065
@@ -526,7 +517,6 @@ public class Socks5ByteStreamManagerTest {
Verification.requestTypeSET);
try {
-
// start SOCKS5 Bytestream
byteStreamManager.establishSession(targetJID, sessionID);
@@ -536,24 +526,26 @@ public class Socks5ByteStreamManagerTest {
protocol.verifyAll();
assertTrue(e.getMessage().contains("Remote user responded with unknown host"));
}
- catch (Exception e) {
- fail(e.getMessage());
- }
-
}
/**
* Invoking {@link Socks5BytestreamManager#establishSession(org.jxmpp.jid.Jid, String)} should fail if
* initiator can not connect to the SOCKS5 proxy used by target.
+ *
+ * @throws InterruptedException
+ * @throws SmackException
+ * @throws XMPPException
*/
@Test
- public void shouldFailIfInitiatorCannotConnectToSocks5Proxy() {
-
- // disable clients local SOCKS5 proxy
- Socks5Proxy.setLocalSocks5ProxyEnabled(false);
+ public void shouldFailIfInitiatorCannotConnectToSocks5Proxy()
+ throws SmackException, InterruptedException, XMPPException {
+ final Protocol protocol = new Protocol();
+ final XMPPConnection connection = ConnectionUtils.createMockedConnection(protocol, initiatorJID);
+ final String sessionID = "session_id_shouldFailIfInitiatorCannotConnectToSocks5Proxy";
// get Socks5ByteStreamManager for connection
Socks5BytestreamManager byteStreamManager = Socks5BytestreamManager.getBytestreamManager(connection);
+ byteStreamManager.setAnnounceLocalStreamHost(false);
/**
* create responses in the order they should be queried specified by the XEP-0065
@@ -618,7 +610,6 @@ public class Socks5ByteStreamManagerTest {
}, Verification.correspondingSenderReceiver, Verification.requestTypeSET);
try {
-
// start SOCKS5 Bytestream
byteStreamManager.establishSession(targetJID, sessionID);
@@ -627,28 +618,30 @@ public class Socks5ByteStreamManagerTest {
catch (IOException e) {
// initiator can't connect to proxy because it is not running
protocol.verifyAll();
- assertEquals(ConnectException.class, e.getClass());
+ Throwable actualCause = e.getCause().getCause();
+ assertEquals(ConnectException.class, actualCause.getClass());
}
- catch (Exception e) {
- fail(e.getMessage());
- }
-
}
/**
* Invoking {@link Socks5BytestreamManager#establishSession(org.jxmpp.jid.Jid, String)} should successfully
* negotiate and return a SOCKS5 Bytestream connection.
*
- * @throws Exception should not happen
+ * @throws InterruptedException
+ * @throws SmackException
+ * @throws XMPPException
+ * @throws IOException
*/
@Test
- public void shouldNegotiateSocks5BytestreamAndTransferData() throws Exception {
-
- // disable clients local SOCKS5 proxy
- Socks5Proxy.setLocalSocks5ProxyEnabled(false);
+ public void shouldNegotiateSocks5BytestreamAndTransferData()
+ throws SmackException, InterruptedException, IOException, XMPPException {
+ final Protocol protocol = new Protocol();
+ final XMPPConnection connection = ConnectionUtils.createMockedConnection(protocol, initiatorJID);
+ final String sessionID = "session_id_shouldNegotiateSocks5BytestreamAndTransferData";
// get Socks5ByteStreamManager for connection
Socks5BytestreamManager byteStreamManager = Socks5BytestreamManager.getBytestreamManager(connection);
+ byteStreamManager.setAnnounceLocalStreamHost(false);
/**
* create responses in the order they should be queried specified by the XEP-0065
@@ -684,9 +677,10 @@ public class Socks5ByteStreamManagerTest {
// build a socks5 stream host info containing the address and the port of the
// proxy
+ ServerSocket proxyServerSocket = NetworkUtil.getSocketOnLoopback();
Bytestream streamHostInfo = Socks5PacketUtils.createBytestreamResponse(proxyJID,
initiatorJID);
- streamHostInfo.addStreamHost(proxyJID, proxyAddress, 7778);
+ streamHostInfo.addStreamHost(proxyJID, proxyAddress, proxyServerSocket.getLocalPort());
// return stream host info if it is queried
protocol.addResponse(streamHostInfo, Verification.correspondingSenderReceiver,
@@ -726,143 +720,146 @@ public class Socks5ByteStreamManagerTest {
}, Verification.correspondingSenderReceiver, Verification.requestTypeSET);
// start a local SOCKS5 proxy
- Socks5TestProxy socks5Proxy = Socks5TestProxy.getProxy(7778);
- socks5Proxy.start();
+ try (Socks5TestProxy socks5Proxy = new Socks5TestProxy(proxyServerSocket)) {
- // create digest to get the socket opened by target
- String digest = Socks5Utils.createDigest(sessionID, initiatorJID, targetJID);
+ // create digest to get the socket opened by target
+ String digest = Socks5Utils.createDigest(sessionID, initiatorJID, targetJID);
- // finally call the method that should be tested
- OutputStream outputStream = byteStreamManager.establishSession(targetJID, sessionID).getOutputStream();
+ // finally call the method that should be tested
+ OutputStream outputStream = byteStreamManager.establishSession(targetJID, sessionID).getOutputStream();
- // test the established bytestream
- InputStream inputStream = socks5Proxy.getSocket(digest).getInputStream();
+ // test the established bytestream
+ InputStream inputStream = socks5Proxy.getSocket(digest).getInputStream();
- byte[] data = new byte[] { 1, 2, 3 };
- outputStream.write(data);
+ byte[] data = new byte[] { 1, 2, 3 };
+ outputStream.write(data);
- byte[] result = new byte[3];
- inputStream.read(result);
+ byte[] result = new byte[3];
+ inputStream.read(result);
- assertArrayEquals(data, result);
+ assertArrayEquals(data, result);
+ }
protocol.verifyAll();
-
}
/**
* If multiple network addresses are added to the local SOCKS5 proxy, all of them should be
* contained in the SOCKS5 Bytestream request.
*
- * @throws Exception should not happen
+ * @throws InterruptedException
+ * @throws SmackException
+ * @throws IOException
+ * @throws XMPPException
+ * @throws TimeoutException
*/
@Test
- public void shouldUseMultipleAddressesForLocalSocks5Proxy() throws Exception {
-
- // enable clients local SOCKS5 proxy on port 7778
- Socks5Proxy.setLocalSocks5ProxyEnabled(true);
- Socks5Proxy.setLocalSocks5ProxyPort(7778);
+ public void shouldUseMultipleAddressesForLocalSocks5Proxy()
+ throws SmackException, InterruptedException, IOException, TimeoutException, XMPPException {
+ final Protocol protocol = new Protocol();
+ final XMPPConnection connection = ConnectionUtils.createMockedConnection(protocol, initiatorJID);
+ final String sessionID = "session_id_shouldUseMultipleAddressesForLocalSocks5Proxy";
// start a local SOCKS5 proxy
- Socks5Proxy socks5Proxy = Socks5Proxy.getSocks5Proxy();
+ Socks5Proxy socks5Proxy = new Socks5Proxy();
socks5Proxy.start();
- assertTrue(socks5Proxy.isRunning());
+ try {
+ assertTrue(socks5Proxy.isRunning());
- // get Socks5ByteStreamManager for connection
- Socks5BytestreamManager byteStreamManager = Socks5BytestreamManager.getBytestreamManager(connection);
+ // get Socks5ByteStreamManager for connection
+ Socks5BytestreamManager byteStreamManager = Socks5BytestreamManager.getBytestreamManager(connection);
- /**
- * create responses in the order they should be queried specified by the XEP-0065
- * specification
- */
+ /**
+ * create responses in the order they should be queried specified by the XEP-0065
+ * specification
+ */
- // build discover info that supports the SOCKS5 feature
- DiscoverInfo discoverInfo = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID);
- discoverInfo.addFeature(Bytestream.NAMESPACE);
+ // build discover info that supports the SOCKS5 feature
+ DiscoverInfo discoverInfo = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID);
+ discoverInfo.addFeature(Bytestream.NAMESPACE);
- // return that SOCKS5 is supported if target is queried
- protocol.addResponse(discoverInfo, Verification.correspondingSenderReceiver,
- Verification.requestTypeGET);
+ // return that SOCKS5 is supported if target is queried
+ protocol.addResponse(discoverInfo, Verification.correspondingSenderReceiver,
+ Verification.requestTypeGET);
- // build discover items containing no proxy item
- DiscoverItems discoverItems = Socks5PacketUtils.createDiscoverItems(xmppServer,
- initiatorJID);
+ // build discover items containing no proxy item
+ DiscoverItems discoverItems = Socks5PacketUtils.createDiscoverItems(xmppServer,
+ initiatorJID);
- // return the discover item if XMPP server is queried
- protocol.addResponse(discoverItems, Verification.correspondingSenderReceiver,
- Verification.requestTypeGET);
+ // return the discover item if XMPP server is queried
+ protocol.addResponse(discoverItems, Verification.correspondingSenderReceiver,
+ Verification.requestTypeGET);
- // build used stream host response
- Bytestream streamHostUsedPacket = Socks5PacketUtils.createBytestreamResponse(targetJID,
- initiatorJID);
- streamHostUsedPacket.setSessionID(sessionID);
- streamHostUsedPacket.setUsedHost(initiatorJID); // local proxy used
+ // build used stream host response
+ Bytestream streamHostUsedPacket = Socks5PacketUtils.createBytestreamResponse(targetJID,
+ initiatorJID);
+ streamHostUsedPacket.setSessionID(sessionID);
+ streamHostUsedPacket.setUsedHost(initiatorJID); // local proxy used
- // return used stream host info as response to the bytestream initiation
- protocol.addResponse(streamHostUsedPacket, new Verification() {
+ // return used stream host info as response to the bytestream initiation
+ protocol.addResponse(streamHostUsedPacket, new Verification() {
+ @Override
+ public void verify(Bytestream request, Bytestream response) {
+ assertEquals(response.getSessionID(), request.getSessionID());
+ StreamHost streamHost1 = request.getStreamHosts().get(0);
+ assertEquals(response.getUsedHost().getJID(), streamHost1.getJID());
+ StreamHost streamHost2 = request.getStreamHosts().get(request.getStreamHosts().size() - 1);
+ assertEquals(response.getUsedHost().getJID(), streamHost2.getJID());
+ assertEquals("localAddress", streamHost2.getAddress());
+ }
+ }, Verification.correspondingSenderReceiver, Verification.requestTypeSET);
- @Override
- public void verify(Bytestream request, Bytestream response) {
- assertEquals(response.getSessionID(), request.getSessionID());
- StreamHost streamHost1 = request.getStreamHosts().get(0);
- assertEquals(response.getUsedHost().getJID(), streamHost1.getJID());
- StreamHost streamHost2 = request.getStreamHosts().get(request.getStreamHosts().size() - 1);
- assertEquals(response.getUsedHost().getJID(), streamHost2.getJID());
- assertEquals("localAddress", streamHost2.getAddress());
+ // create digest to get the socket opened by target
+ String digest = Socks5Utils.createDigest(sessionID, initiatorJID, targetJID);
+
+ // connect to proxy as target
+ socks5Proxy.addTransfer(digest);
+ StreamHost streamHost = new StreamHost(targetJID,
+ socks5Proxy.getLocalAddresses().get(0),
+ socks5Proxy.getPort());
+ Socks5Client socks5Client = new Socks5Client(streamHost, digest);
+ InputStream inputStream = socks5Client.getSocket(2000).getInputStream();
+
+ // add another network address before establishing SOCKS5 Bytestream
+ socks5Proxy.addLocalAddress("localAddress");
+
+ // finally call the method that should be tested
+ OutputStream outputStream = byteStreamManager.establishSession(targetJID, sessionID).getOutputStream();
+
+ // test the established bytestream
+ byte[] data = new byte[] { 1, 2, 3 };
+ outputStream.write(data);
+
+ byte[] result = new byte[3];
+ inputStream.read(result);
+
+ assertArrayEquals(data, result);
+
+ protocol.verifyAll();
+ } finally {
+ socks5Proxy.stop();
}
-
- }, Verification.correspondingSenderReceiver, Verification.requestTypeSET);
-
- // create digest to get the socket opened by target
- String digest = Socks5Utils.createDigest(sessionID, initiatorJID, targetJID);
-
- // connect to proxy as target
- socks5Proxy.addTransfer(digest);
- StreamHost streamHost = new StreamHost(targetJID,
- socks5Proxy.getLocalAddresses().get(0),
- socks5Proxy.getPort());
- Socks5Client socks5Client = new Socks5Client(streamHost, digest);
- InputStream inputStream = socks5Client.getSocket(2000).getInputStream();
-
- // add another network address before establishing SOCKS5 Bytestream
- socks5Proxy.addLocalAddress("localAddress");
-
- // finally call the method that should be tested
- OutputStream outputStream = byteStreamManager.establishSession(targetJID, sessionID).getOutputStream();
-
- // test the established bytestream
- byte[] data = new byte[] { 1, 2, 3 };
- outputStream.write(data);
-
- byte[] result = new byte[3];
- inputStream.read(result);
-
- assertArrayEquals(data, result);
-
- protocol.verifyAll();
-
- // reset proxy settings
- socks5Proxy.stop();
- socks5Proxy.removeLocalAddress("localAddress");
- Socks5Proxy.setLocalSocks5ProxyPort(7777);
-
}
/**
* Invoking {@link Socks5BytestreamManager#establishSession(org.jxmpp.jid.Jid, String)} the first time
* should successfully negotiate a SOCKS5 Bytestream via the second SOCKS5 proxy and should
* prioritize this proxy for a second SOCKS5 Bytestream negotiation.
+ * @throws InterruptedException
+ * @throws SmackException
+ * @throws XMPPException
+ * @throws IOException
*
- * @throws Exception should not happen
*/
@Test
- public void shouldPrioritizeSecondSocks5ProxyOnSecondAttempt() throws Exception {
-
- // disable clients local SOCKS5 proxy
- Socks5Proxy.setLocalSocks5ProxyEnabled(false);
+ public void shouldPrioritizeSecondSocks5ProxyOnSecondAttempt() throws SmackException, InterruptedException, IOException, XMPPException {
+ final Protocol protocol = new Protocol();
+ final XMPPConnection connection = ConnectionUtils.createMockedConnection(protocol, initiatorJID);
+ final String sessionID = "session_id_shouldPrioritizeSecondSocks5ProxyOnSecondAttempt";
// get Socks5ByteStreamManager for connection
Socks5BytestreamManager byteStreamManager = Socks5BytestreamManager.getBytestreamManager(connection);
+ byteStreamManager.setAnnounceLocalStreamHost(false);
assertTrue(byteStreamManager.isProxyPrioritizationEnabled());
@@ -878,59 +875,58 @@ public class Socks5ByteStreamManagerTest {
}
};
- createResponses(streamHostUsedVerification1);
// start a local SOCKS5 proxy
- Socks5TestProxy socks5Proxy = Socks5TestProxy.getProxy(7778);
- socks5Proxy.start();
+ try (Socks5TestProxy socks5Proxy = new Socks5TestProxy()) {
+ createResponses(protocol, sessionID, streamHostUsedVerification1, socks5Proxy);
- // create digest to get the socket opened by target
- String digest = Socks5Utils.createDigest(sessionID, initiatorJID, targetJID);
+ // create digest to get the socket opened by target
+ String digest = Socks5Utils.createDigest(sessionID, initiatorJID, targetJID);
- // call the method that should be tested
- OutputStream outputStream = byteStreamManager.establishSession(targetJID, sessionID).getOutputStream();
+ // call the method that should be tested
+ OutputStream outputStream = byteStreamManager.establishSession(targetJID, sessionID).getOutputStream();
- // test the established bytestream
- InputStream inputStream = socks5Proxy.getSocket(digest).getInputStream();
+ // test the established bytestream
+ InputStream inputStream = socks5Proxy.getSocket(digest).getInputStream();
- byte[] data = new byte[] { 1, 2, 3 };
- outputStream.write(data);
+ byte[] data = new byte[] { 1, 2, 3 };
+ outputStream.write(data);
- byte[] result = new byte[3];
- inputStream.read(result);
+ byte[] result = new byte[3];
+ inputStream.read(result);
- assertArrayEquals(data, result);
+ assertArrayEquals(data, result);
- protocol.verifyAll();
+ protocol.verifyAll();
- Verification streamHostUsedVerification2 = new Verification() {
+ Verification streamHostUsedVerification2 = new Verification() {
- @Override
- public void verify(Bytestream request, Bytestream response) {
- assertEquals(response.getSessionID(), request.getSessionID());
- assertEquals(2, request.getStreamHosts().size());
- // verify that the used stream host is the first in list
- StreamHost streamHost = (StreamHost) request.getStreamHosts().toArray()[0];
- assertEquals(response.getUsedHost().getJID(), streamHost.getJID());
- }
+ @Override
+ public void verify(Bytestream request, Bytestream response) {
+ assertEquals(response.getSessionID(), request.getSessionID());
+ assertEquals(2, request.getStreamHosts().size());
+ // verify that the used stream host is the first in list
+ StreamHost streamHost = (StreamHost) request.getStreamHosts().toArray()[0];
+ assertEquals(response.getUsedHost().getJID(), streamHost.getJID());
+ }
- };
- createResponses(streamHostUsedVerification2);
+ };
+ createResponses(protocol, sessionID, streamHostUsedVerification2, socks5Proxy);
- // call the method that should be tested again
- outputStream = byteStreamManager.establishSession(targetJID, sessionID).getOutputStream();
+ // call the method that should be tested again
+ outputStream = byteStreamManager.establishSession(targetJID, sessionID).getOutputStream();
- // test the established bytestream
- inputStream = socks5Proxy.getSocket(digest).getInputStream();
+ // test the established bytestream
+ inputStream = socks5Proxy.getSocket(digest).getInputStream();
- outputStream.write(data);
+ outputStream.write(data);
- inputStream.read(result);
+ inputStream.read(result);
- assertArrayEquals(data, result);
-
- protocol.verifyAll();
+ assertArrayEquals(data, result);
+ protocol.verifyAll();
+ }
}
/**
@@ -938,18 +934,23 @@ public class Socks5ByteStreamManagerTest {
* should successfully negotiate a SOCKS5 Bytestream via the second SOCKS5 proxy. The second
* negotiation should run in the same manner if prioritization is disabled.
*
- * @throws Exception should not happen
+ * @throws IOException
+ * @throws InterruptedException
+ * @throws SmackException
+ * @throws XMPPException
+ *
*/
@Test
- public void shouldNotPrioritizeSocks5ProxyIfPrioritizationDisabled() throws Exception {
-
- // disable clients local SOCKS5 proxy
- Socks5Proxy.setLocalSocks5ProxyEnabled(false);
+ public void shouldNotPrioritizeSocks5ProxyIfPrioritizationDisabled() throws IOException, SmackException, InterruptedException, XMPPException {
+ final Protocol protocol = new Protocol();
+ final XMPPConnection connection = ConnectionUtils.createMockedConnection(protocol, initiatorJID);
+ final String sessionID = "session_id_shouldNotPrioritizeSocks5ProxyIfPrioritizationDisabled";
// get Socks5ByteStreamManager for connection
Socks5BytestreamManager byteStreamManager = Socks5BytestreamManager.getBytestreamManager(connection);
- byteStreamManager.setProxyPrioritizationEnabled(false);
+ byteStreamManager.setAnnounceLocalStreamHost(false);
+ byteStreamManager.setProxyPrioritizationEnabled(false);
assertFalse(byteStreamManager.isProxyPrioritizationEnabled());
Verification streamHostUsedVerification = new Verification() {
@@ -964,52 +965,51 @@ public class Socks5ByteStreamManagerTest {
}
};
- createResponses(streamHostUsedVerification);
// start a local SOCKS5 proxy
- Socks5TestProxy socks5Proxy = Socks5TestProxy.getProxy(7778);
- socks5Proxy.start();
+ try (Socks5TestProxy socks5Proxy = new Socks5TestProxy()) {
+ createResponses(protocol, sessionID, streamHostUsedVerification, socks5Proxy);
- // create digest to get the socket opened by target
- String digest = Socks5Utils.createDigest(sessionID, initiatorJID, targetJID);
+ // create digest to get the socket opened by target
+ String digest = Socks5Utils.createDigest(sessionID, initiatorJID, targetJID);
- // call the method that should be tested
- OutputStream outputStream = byteStreamManager.establishSession(targetJID, sessionID).getOutputStream();
+ // call the method that should be tested
+ OutputStream outputStream = byteStreamManager.establishSession(targetJID, sessionID).getOutputStream();
- // test the established bytestream
- InputStream inputStream = socks5Proxy.getSocket(digest).getInputStream();
+ // test the established bytestream
+ InputStream inputStream = socks5Proxy.getSocket(digest).getInputStream();
- byte[] data = new byte[] { 1, 2, 3 };
- outputStream.write(data);
+ byte[] data = new byte[] { 1, 2, 3 };
+ outputStream.write(data);
- byte[] result = new byte[3];
- inputStream.read(result);
+ byte[] result = new byte[3];
+ inputStream.read(result);
- assertArrayEquals(data, result);
+ assertArrayEquals(data, result);
+
+ protocol.verifyAll();
+
+ createResponses(protocol, sessionID, streamHostUsedVerification, socks5Proxy);
+
+ // call the method that should be tested again
+ outputStream = byteStreamManager.establishSession(targetJID, sessionID).getOutputStream();
+
+ // test the established bytestream
+ inputStream = socks5Proxy.getSocket(digest).getInputStream();
+
+ outputStream.write(data);
+
+ inputStream.read(result);
+
+ assertArrayEquals(data, result);
+ }
protocol.verifyAll();
-
- createResponses(streamHostUsedVerification);
-
- // call the method that should be tested again
- outputStream = byteStreamManager.establishSession(targetJID, sessionID).getOutputStream();
-
- // test the established bytestream
- inputStream = socks5Proxy.getSocket(digest).getInputStream();
-
- outputStream.write(data);
-
- inputStream.read(result);
-
- assertArrayEquals(data, result);
-
- protocol.verifyAll();
-
- byteStreamManager.setProxyPrioritizationEnabled(true);
-
}
- private void createResponses(Verification streamHostUsedVerification) throws XmppStringprepException {
+ private static void createResponses(Protocol protocol, String sessionID,
+ Verification streamHostUsedVerification, Socks5TestProxy socks5TestProxy)
+ throws XmppStringprepException {
// build discover info that supports the SOCKS5 feature
DiscoverInfo discoverInfo = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID);
discoverInfo.addFeature(Bytestream.NAMESPACE);
@@ -1056,7 +1056,7 @@ public class Socks5ByteStreamManagerTest {
*/
Bytestream streamHostInfo1 = Socks5PacketUtils.createBytestreamResponse(
JidCreate.from("proxy2.xmpp-server"), initiatorJID);
- streamHostInfo1.addStreamHost(JidCreate.from("proxy2.xmpp-server"), proxyAddress, 7778);
+ streamHostInfo1.addStreamHost(JidCreate.from("proxy2.xmpp-server"), proxyAddress, socks5TestProxy.getPort());
// return stream host info if it is queried
protocol.addResponse(streamHostInfo1, Verification.correspondingSenderReceiver,
@@ -1065,7 +1065,7 @@ public class Socks5ByteStreamManagerTest {
// build a SOCKS5 stream host info containing the address and the port of the proxy
Bytestream streamHostInfo2 = Socks5PacketUtils.createBytestreamResponse(proxyJID,
initiatorJID);
- streamHostInfo2.addStreamHost(proxyJID, proxyAddress, 7778);
+ streamHostInfo2.addStreamHost(proxyJID, proxyAddress, socks5TestProxy.getPort());
// return stream host info if it is queried
protocol.addResponse(streamHostInfo2, Verification.correspondingSenderReceiver,
@@ -1094,16 +1094,6 @@ public class Socks5ByteStreamManagerTest {
}
}, Verification.correspondingSenderReceiver, Verification.requestTypeSET);
-
- }
-
- /**
- * Stop eventually started local SOCKS5 test proxy.
- */
- @After
- public void cleanUp() {
- Socks5TestProxy.stopProxy();
- Socks5Proxy.setLocalSocks5ProxyEnabled(true);
}
}
diff --git a/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5ByteStreamRequestTest.java b/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5ByteStreamRequestTest.java
index 5f3b373b9..59d5f99c1 100644
--- a/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5ByteStreamRequestTest.java
+++ b/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5ByteStreamRequestTest.java
@@ -27,19 +27,16 @@ import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
-import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPConnection;
-import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smack.packet.StanzaError;
+import org.jivesoftware.smack.util.NetworkUtil;
import org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream;
import org.jivesoftware.util.ConnectionUtils;
import org.jivesoftware.util.Protocol;
-import org.junit.After;
-import org.junit.Before;
import org.junit.Test;
import org.jxmpp.jid.DomainBareJid;
import org.jxmpp.jid.EntityFullJid;
@@ -60,27 +57,6 @@ public class Socks5ByteStreamRequestTest {
private static final String proxyAddress = "127.0.0.1";
private static final String sessionID = "session_id";
- private Protocol protocol;
-
- private XMPPConnection connection;
-
- /**
- * Initialize fields used in the tests.
- * @throws XMPPException
- * @throws SmackException
- * @throws InterruptedException
- */
- @Before
- public void setup() throws XMPPException, SmackException, InterruptedException {
-
- // build protocol verifier
- protocol = new Protocol();
-
- // create mocked XMPP connection
- connection = ConnectionUtils.createMockedConnection(protocol, targetJID);
-
- }
-
/**
* Accepting a SOCKS5 Bytestream request should fail if the request doesn't contain any Socks5
* proxies.
@@ -89,6 +65,9 @@ public class Socks5ByteStreamRequestTest {
*/
@Test
public void shouldFailIfRequestHasNoStreamHosts() throws Exception {
+ final Protocol protocol = new Protocol();
+ final XMPPConnection connection = ConnectionUtils.createMockedConnection(protocol, targetJID);
+
assertThrows(Socks5Exception.NoSocks5StreamHostsProvided.class, () -> {
// build SOCKS5 Bytestream initialization request with no SOCKS5 proxies
Bytestream bytestreamInitialization = Socks5PacketUtils.createBytestreamInitiation(
@@ -113,7 +92,6 @@ public class Socks5ByteStreamRequestTest {
assertEquals(IQ.Type.error, ((IQ) targetResponse).getType());
assertEquals(StanzaError.Condition.item_not_found,
targetResponse.getError().getCondition());
-
}
/**
@@ -124,6 +102,9 @@ public class Socks5ByteStreamRequestTest {
*/
@Test
public void shouldFailIfRequestHasInvalidStreamHosts() throws Exception {
+ final Protocol protocol = new Protocol();
+ final XMPPConnection connection = ConnectionUtils.createMockedConnection(protocol, targetJID);
+
assertThrows(Socks5Exception.CouldNotConnectToAnyProvidedSocks5Host.class, () -> {
// build SOCKS5 Bytestream initialization request
Bytestream bytestreamInitialization = Socks5PacketUtils.createBytestreamInitiation(
@@ -150,7 +131,6 @@ public class Socks5ByteStreamRequestTest {
assertEquals(IQ.Type.error, ((IQ) targetResponse).getType());
assertEquals(StanzaError.Condition.item_not_found,
targetResponse.getError().getCondition());
-
}
/**
@@ -160,10 +140,13 @@ public class Socks5ByteStreamRequestTest {
*/
@Test
public void shouldBlacklistInvalidProxyAfter2Failures() throws Exception {
+ final Protocol protocol = new Protocol();
+ final XMPPConnection connection = ConnectionUtils.createMockedConnection(protocol, targetJID);
// build SOCKS5 Bytestream initialization request
Bytestream bytestreamInitialization = Socks5PacketUtils.createBytestreamInitiation(
initiatorJID, targetJID, sessionID);
+ // Add an unreachable stream host.
bytestreamInitialization.addStreamHost(JidCreate.from("invalid." + proxyJID), "127.0.0.2", 7778);
// get SOCKS5 Bytestream manager for connection
@@ -196,44 +179,44 @@ public class Socks5ByteStreamRequestTest {
// create test data for stream
byte[] data = new byte[] { 1, 2, 3 };
- Socks5TestProxy socks5Proxy = Socks5TestProxy.getProxy(7779);
- assertTrue(socks5Proxy.isRunning());
+ try (Socks5TestProxy socks5Proxy = new Socks5TestProxy()) {
+ assertTrue(socks5Proxy.isRunning());
- // add a valid SOCKS5 proxy
- bytestreamInitialization.addStreamHost(proxyJID, proxyAddress, 7779);
+ // add a valid SOCKS5 proxy
+ bytestreamInitialization.addStreamHost(proxyJID, proxyAddress, socks5Proxy.getPort());
- // build SOCKS5 Bytestream request with the bytestream initialization
- Socks5BytestreamRequest byteStreamRequest = new Socks5BytestreamRequest(byteStreamManager,
- bytestreamInitialization);
+ // build SOCKS5 Bytestream request with the bytestream initialization
+ Socks5BytestreamRequest byteStreamRequest = new Socks5BytestreamRequest(byteStreamManager,
+ bytestreamInitialization);
- // set timeouts
- byteStreamRequest.setTotalConnectTimeout(600);
- byteStreamRequest.setMinimumConnectTimeout(300);
+ // set timeouts
+ byteStreamRequest.setTotalConnectTimeout(600);
+ byteStreamRequest.setMinimumConnectTimeout(300);
- // accept the stream (this is the call that is tested here)
- InputStream inputStream = byteStreamRequest.accept().getInputStream();
+ // accept the stream (this is the call that is tested here)
+ InputStream inputStream = byteStreamRequest.accept().getInputStream();
- // create digest to get the socket opened by target
- String digest = Socks5Utils.createDigest(sessionID, initiatorJID, targetJID);
+ // create digest to get the socket opened by target
+ String digest = Socks5Utils.createDigest(sessionID, initiatorJID, targetJID);
- // test stream by sending some data
- OutputStream outputStream = socks5Proxy.getSocket(digest).getOutputStream();
- outputStream.write(data);
+ // test stream by sending some data
+ OutputStream outputStream = socks5Proxy.getSocket(digest).getOutputStream();
+ outputStream.write(data);
- // verify that data is transferred correctly
- byte[] result = new byte[3];
- inputStream.read(result);
- assertArrayEquals(data, result);
-
- // verify targets response
- assertEquals(1, protocol.getRequests().size());
- Stanza targetResponse = protocol.getRequests().remove(0);
- assertEquals(Bytestream.class, targetResponse.getClass());
- assertEquals(initiatorJID, targetResponse.getTo());
- assertEquals(IQ.Type.result, ((Bytestream) targetResponse).getType());
- assertEquals(proxyJID, ((Bytestream) targetResponse).getUsedHost().getJID());
+ // verify that data is transferred correctly
+ byte[] result = new byte[3];
+ inputStream.read(result);
+ assertArrayEquals(data, result);
+ // verify targets response
+ assertEquals(1, protocol.getRequests().size());
+ Stanza targetResponse = protocol.getRequests().remove(0);
+ assertEquals(Bytestream.class, targetResponse.getClass());
+ assertEquals(initiatorJID, targetResponse.getTo());
+ assertEquals(IQ.Type.result, ((Bytestream) targetResponse).getType());
+ assertEquals(proxyJID, ((Bytestream) targetResponse).getUsedHost().getJID());
+ }
}
/**
@@ -243,9 +226,8 @@ public class Socks5ByteStreamRequestTest {
*/
@Test
public void shouldNotBlacklistInvalidProxy() throws Exception {
-
- // disable blacklisting
- Socks5BytestreamRequest.setConnectFailureThreshold(0);
+ final Protocol protocol = new Protocol();
+ final XMPPConnection connection = ConnectionUtils.createMockedConnection(protocol, targetJID);
// build SOCKS5 Bytestream initialization request
Bytestream bytestreamInitialization = Socks5PacketUtils.createBytestreamInitiation(
@@ -265,6 +247,7 @@ public class Socks5ByteStreamRequestTest {
// set timeouts
byteStreamRequest.setTotalConnectTimeout(600);
byteStreamRequest.setMinimumConnectTimeout(300);
+ byteStreamRequest.setConnectFailureThreshold(0);
// accept the stream (this is the call that is tested here)
byteStreamRequest.accept();
@@ -279,10 +262,6 @@ public class Socks5ByteStreamRequestTest {
assertEquals(StanzaError.Condition.item_not_found,
targetResponse.getError().getCondition());
}
-
- // enable blacklisting
- Socks5BytestreamRequest.setConnectFailureThreshold(2);
-
}
/**
@@ -294,62 +273,65 @@ public class Socks5ByteStreamRequestTest {
*/
@Test
public void shouldNotTimeoutIfFirstSocks5ProxyDoesNotRespond() throws Exception {
+ final Protocol protocol = new Protocol();
+ final XMPPConnection connection = ConnectionUtils.createMockedConnection(protocol, targetJID);
// start a local SOCKS5 proxy
- Socks5TestProxy socks5Proxy = Socks5TestProxy.getProxy(7778);
+ try (Socks5TestProxy socks5Proxy = new Socks5TestProxy()) {
+ // create a fake SOCKS5 proxy that doesn't respond to a request
+ ServerSocket unresponsiveSocks5Socket = NetworkUtil.getSocketOnLoopback();
- // create a fake SOCKS5 proxy that doesn't respond to a request
- ServerSocket serverSocket = new ServerSocket(7779);
+ try {
+ // build SOCKS5 Bytestream initialization request
+ Bytestream bytestreamInitialization = Socks5PacketUtils.createBytestreamInitiation(
+ initiatorJID, targetJID, sessionID);
+ bytestreamInitialization.addStreamHost(proxyJID, proxyAddress, unresponsiveSocks5Socket.getLocalPort());
+ bytestreamInitialization.addStreamHost(proxyJID, proxyAddress, socks5Proxy.getPort());
- // build SOCKS5 Bytestream initialization request
- Bytestream bytestreamInitialization = Socks5PacketUtils.createBytestreamInitiation(
- initiatorJID, targetJID, sessionID);
- bytestreamInitialization.addStreamHost(proxyJID, proxyAddress, 7779);
- bytestreamInitialization.addStreamHost(proxyJID, proxyAddress, 7778);
+ // create test data for stream
+ byte[] data = new byte[] { 1, 2, 3 };
- // create test data for stream
- byte[] data = new byte[] { 1, 2, 3 };
+ // get SOCKS5 Bytestream manager for connection
+ Socks5BytestreamManager byteStreamManager = Socks5BytestreamManager.getBytestreamManager(connection);
- // get SOCKS5 Bytestream manager for connection
- Socks5BytestreamManager byteStreamManager = Socks5BytestreamManager.getBytestreamManager(connection);
+ // build SOCKS5 Bytestream request with the bytestream initialization
+ Socks5BytestreamRequest byteStreamRequest = new Socks5BytestreamRequest(byteStreamManager,
+ bytestreamInitialization);
- // build SOCKS5 Bytestream request with the bytestream initialization
- Socks5BytestreamRequest byteStreamRequest = new Socks5BytestreamRequest(byteStreamManager,
- bytestreamInitialization);
+ // set timeouts
+ byteStreamRequest.setTotalConnectTimeout(2000);
+ byteStreamRequest.setMinimumConnectTimeout(1000);
- // set timeouts
- byteStreamRequest.setTotalConnectTimeout(2000);
- byteStreamRequest.setMinimumConnectTimeout(1000);
+ // accept the stream (this is the call that is tested here)
+ InputStream inputStream = byteStreamRequest.accept().getInputStream();
- // accept the stream (this is the call that is tested here)
- InputStream inputStream = byteStreamRequest.accept().getInputStream();
+ // assert that client tries to connect to dumb SOCKS5 proxy
+ Socket socket = unresponsiveSocks5Socket.accept();
+ assertNotNull(socket);
- // assert that client tries to connect to dumb SOCKS5 proxy
- Socket socket = serverSocket.accept();
- assertNotNull(socket);
+ // create digest to get the socket opened by target
+ String digest = Socks5Utils.createDigest(sessionID, initiatorJID, targetJID);
- // create digest to get the socket opened by target
- String digest = Socks5Utils.createDigest(sessionID, initiatorJID, targetJID);
+ // test stream by sending some data
+ OutputStream outputStream = socks5Proxy.getSocket(digest).getOutputStream();
+ outputStream.write(data);
- // test stream by sending some data
- OutputStream outputStream = socks5Proxy.getSocket(digest).getOutputStream();
- outputStream.write(data);
-
- // verify that data is transferred correctly
- byte[] result = new byte[3];
- inputStream.read(result);
- assertArrayEquals(data, result);
-
- // verify targets response
- assertEquals(1, protocol.getRequests().size());
- Stanza targetResponse = protocol.getRequests().remove(0);
- assertEquals(Bytestream.class, targetResponse.getClass());
- assertEquals(initiatorJID, targetResponse.getTo());
- assertEquals(IQ.Type.result, ((Bytestream) targetResponse).getType());
- assertEquals(proxyJID, ((Bytestream) targetResponse).getUsedHost().getJID());
-
- serverSocket.close();
+ // verify that data is transferred correctly
+ byte[] result = new byte[3];
+ inputStream.read(result);
+ assertArrayEquals(data, result);
+ // verify targets response
+ assertEquals(1, protocol.getRequests().size());
+ Stanza targetResponse = protocol.getRequests().remove(0);
+ assertEquals(Bytestream.class, targetResponse.getClass());
+ assertEquals(initiatorJID, targetResponse.getTo());
+ assertEquals(IQ.Type.result, ((Bytestream) targetResponse).getType());
+ assertEquals(proxyJID, ((Bytestream) targetResponse).getUsedHost().getJID());
+ } finally {
+ unresponsiveSocks5Socket.close();
+ }
+ }
}
/**
@@ -359,57 +341,48 @@ public class Socks5ByteStreamRequestTest {
*/
@Test
public void shouldAcceptSocks5BytestreamRequestAndReceiveData() throws Exception {
+ final Protocol protocol = new Protocol();
+ final XMPPConnection connection = ConnectionUtils.createMockedConnection(protocol, targetJID);
// start a local SOCKS5 proxy
- Socks5TestProxy socks5Proxy = Socks5TestProxy.getProxy(7778);
+ try (Socks5TestProxy socks5Proxy = new Socks5TestProxy()) {
+ // build SOCKS5 Bytestream initialization request
+ Bytestream bytestreamInitialization = Socks5PacketUtils.createBytestreamInitiation(
+ initiatorJID, targetJID, sessionID);
+ bytestreamInitialization.addStreamHost(proxyJID, proxyAddress, socks5Proxy.getPort());
- // build SOCKS5 Bytestream initialization request
- Bytestream bytestreamInitialization = Socks5PacketUtils.createBytestreamInitiation(
- initiatorJID, targetJID, sessionID);
- bytestreamInitialization.addStreamHost(proxyJID, proxyAddress, 7778);
+ // create test data for stream
+ byte[] data = new byte[] { 1, 2, 3 };
- // create test data for stream
- byte[] data = new byte[] { 1, 2, 3 };
+ // get SOCKS5 Bytestream manager for connection
+ Socks5BytestreamManager byteStreamManager = Socks5BytestreamManager.getBytestreamManager(connection);
- // get SOCKS5 Bytestream manager for connection
- Socks5BytestreamManager byteStreamManager = Socks5BytestreamManager.getBytestreamManager(connection);
+ // build SOCKS5 Bytestream request with the bytestream initialization
+ Socks5BytestreamRequest byteStreamRequest = new Socks5BytestreamRequest(byteStreamManager,
+ bytestreamInitialization);
- // build SOCKS5 Bytestream request with the bytestream initialization
- Socks5BytestreamRequest byteStreamRequest = new Socks5BytestreamRequest(byteStreamManager,
- bytestreamInitialization);
+ // accept the stream (this is the call that is tested here)
+ InputStream inputStream = byteStreamRequest.accept().getInputStream();
- // accept the stream (this is the call that is tested here)
- InputStream inputStream = byteStreamRequest.accept().getInputStream();
+ // create digest to get the socket opened by target
+ String digest = Socks5Utils.createDigest(sessionID, initiatorJID, targetJID);
- // create digest to get the socket opened by target
- String digest = Socks5Utils.createDigest(sessionID, initiatorJID, targetJID);
+ // test stream by sending some data
+ OutputStream outputStream = socks5Proxy.getSocket(digest).getOutputStream();
+ outputStream.write(data);
- // test stream by sending some data
- OutputStream outputStream = socks5Proxy.getSocket(digest).getOutputStream();
- outputStream.write(data);
-
- // verify that data is transferred correctly
- byte[] result = new byte[3];
- inputStream.read(result);
- assertArrayEquals(data, result);
-
- // verify targets response
- assertEquals(1, protocol.getRequests().size());
- Stanza targetResponse = protocol.getRequests().remove(0);
- assertEquals(Bytestream.class, targetResponse.getClass());
- assertEquals(initiatorJID, targetResponse.getTo());
- assertEquals(IQ.Type.result, ((Bytestream) targetResponse).getType());
- assertEquals(proxyJID, ((Bytestream) targetResponse).getUsedHost().getJID());
+ // verify that data is transferred correctly
+ byte[] result = new byte[3];
+ inputStream.read(result);
+ assertArrayEquals(data, result);
+ // verify targets response
+ assertEquals(1, protocol.getRequests().size());
+ Stanza targetResponse = protocol.getRequests().remove(0);
+ assertEquals(Bytestream.class, targetResponse.getClass());
+ assertEquals(initiatorJID, targetResponse.getTo());
+ assertEquals(IQ.Type.result, ((Bytestream) targetResponse).getType());
+ assertEquals(proxyJID, ((Bytestream) targetResponse).getUsedHost().getJID());
+ }
}
-
- /**
- * Stop eventually started local SOCKS5 test proxy.
- */
- @After
- public void cleanUp() {
- Socks5TestProxy.stopProxy();
- Socks5Proxy.setLocalSocks5ProxyEnabled(true);
- }
-
}
diff --git a/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5ClientForInitiatorTest.java b/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5ClientForInitiatorTest.java
index 3b0a5faf8..fe3807eed 100644
--- a/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5ClientForInitiatorTest.java
+++ b/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5ClientForInitiatorTest.java
@@ -28,12 +28,12 @@ import java.net.Socket;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPConnection;
-import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
import org.jivesoftware.smack.packet.EmptyResultIQ;
import org.jivesoftware.smack.packet.ErrorIQ;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.StanzaError;
+import org.jivesoftware.smack.util.CloseableUtil;
import org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream;
import org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream.StreamHost;
@@ -41,8 +41,6 @@ import org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream.StreamHost;
import org.jivesoftware.util.ConnectionUtils;
import org.jivesoftware.util.Protocol;
import org.jivesoftware.util.Verification;
-import org.junit.After;
-import org.junit.Before;
import org.junit.Test;
import org.jxmpp.jid.DomainBareJid;
import org.jxmpp.jid.EntityFullJid;
@@ -63,31 +61,8 @@ public class Socks5ClientForInitiatorTest {
private static final int GET_SOCKET_TIMEOUT = 90 * 1000;
- private static final int proxyPort = 7890;
private static final String sessionID = "session_id";
- // protocol verifier
- private Protocol protocol;
-
- // mocked XMPP connection
- private XMPPConnection connection;
-
- /**
- * Initialize fields used in the tests.
- * @throws XMPPException
- * @throws SmackException
- * @throws InterruptedException
- */
- @Before
- public void setup() throws XMPPException, SmackException, InterruptedException {
-
- // build protocol verifier
- protocol = new Protocol();
-
- // create mocked XMPP connection
- connection = ConnectionUtils.createMockedConnection(protocol, initiatorJID);
- }
-
/**
* If the target is not connected to the local SOCKS5 proxy an exception should be thrown.
*
@@ -95,35 +70,36 @@ public class Socks5ClientForInitiatorTest {
*/
@Test
public void shouldFailIfTargetIsNotConnectedToLocalSocks5Proxy() throws Exception {
+ Protocol protocol = new Protocol();
+ XMPPConnection connection = ConnectionUtils.createMockedConnection(protocol, initiatorJID);
// start a local SOCKS5 proxy
- Socks5Proxy.setLocalSocks5ProxyPort(proxyPort);
- Socks5Proxy socks5Proxy = Socks5Proxy.getSocks5Proxy();
+ Socks5Proxy socks5Proxy = new Socks5Proxy();
socks5Proxy.start();
-
- // build stream host information for local SOCKS5 proxy
- StreamHost streamHost = new StreamHost(connection.getUser(),
- loopbackAddress,
- socks5Proxy.getPort());
-
- // create digest to get the socket opened by target
- String digest = Socks5Utils.createDigest(sessionID, initiatorJID, targetJID);
-
- Socks5ClientForInitiator socks5Client = new Socks5ClientForInitiator(streamHost, digest,
- connection, sessionID, targetJID);
-
try {
- socks5Client.getSocket(GET_SOCKET_TIMEOUT);
+ // build stream host information for local SOCKS5 proxy
+ StreamHost streamHost = new StreamHost(connection.getUser(),
+ loopbackAddress,
+ socks5Proxy.getPort());
- fail("exception should be thrown");
+ // create digest to get the socket opened by target
+ String digest = Socks5Utils.createDigest(sessionID, initiatorJID, targetJID);
+
+ Socks5ClientForInitiator socks5Client = new Socks5ClientForInitiator(streamHost, digest,
+ connection, sessionID, targetJID);
+
+ try {
+ socks5Client.getSocket(GET_SOCKET_TIMEOUT);
+
+ fail("exception should be thrown");
+ }
+ catch (SmackException e) {
+ assertTrue(e.getMessage().contains("target is not connected to SOCKS5 proxy"));
+ protocol.verifyAll(); // assert no XMPP messages were sent
+ }
+ } finally {
+ socks5Proxy.stop();
}
- catch (SmackException e) {
- assertTrue(e.getMessage().contains("target is not connected to SOCKS5 proxy"));
- protocol.verifyAll(); // assert no XMPP messages were sent
- }
-
- socks5Proxy.stop();
-
}
/**
@@ -133,65 +109,67 @@ public class Socks5ClientForInitiatorTest {
*/
@Test
public void shouldSuccessfullyConnectThroughLocalSocks5Proxy() throws Exception {
+ Protocol protocol = new Protocol();
+ XMPPConnection connection = ConnectionUtils.createMockedConnection(protocol, initiatorJID);
// start a local SOCKS5 proxy
- Socks5Proxy.setLocalSocks5ProxyPort(proxyPort);
- Socks5Proxy socks5Proxy = Socks5Proxy.getSocks5Proxy();
+ Socks5Proxy socks5Proxy = new Socks5Proxy();
socks5Proxy.start();
+ try {
+ // test data
+ final byte[] data = new byte[] { 1, 2, 3 };
- // test data
- final byte[] data = new byte[] { 1, 2, 3 };
+ // create digest
+ final String digest = Socks5Utils.createDigest(sessionID, initiatorJID, targetJID);
- // create digest
- final String digest = Socks5Utils.createDigest(sessionID, initiatorJID, targetJID);
+ // allow connection of target with this digest
+ socks5Proxy.addTransfer(digest);
- // allow connection of target with this digest
- socks5Proxy.addTransfer(digest);
+ // build stream host information
+ final StreamHost streamHost = new StreamHost(connection.getUser(),
+ loopbackAddress,
+ socks5Proxy.getPort());
- // build stream host information
- final StreamHost streamHost = new StreamHost(connection.getUser(),
- loopbackAddress,
- socks5Proxy.getPort());
-
- // target connects to local SOCKS5 proxy
- Thread targetThread = new Thread() {
-
- @Override
- public void run() {
- try {
- Socks5Client targetClient = new Socks5Client(streamHost, digest);
- Socket socket = targetClient.getSocket(10000);
- socket.getOutputStream().write(data);
- }
- catch (Exception e) {
- fail(e.getMessage());
+ // target connects to local SOCKS5 proxy
+ Thread targetThread = new Thread() {
+ @Override
+ public void run() {
+ try {
+ Socks5Client targetClient = new Socks5Client(streamHost, digest);
+ Socket socket = targetClient.getSocket(10000);
+ socket.getOutputStream().write(data);
+ }
+ catch (Exception e) {
+ // TODO: This does not work.
+ fail(e.getMessage());
+ }
}
+ };
+ targetThread.start();
+
+ // TODO: Replace this Thread.sleep().
+ Thread.sleep(200);
+
+ // initiator connects
+ Socks5ClientForInitiator socks5Client = new Socks5ClientForInitiator(streamHost, digest,
+ connection, sessionID, targetJID);
+
+ Socket socket = socks5Client.getSocket(GET_SOCKET_TIMEOUT);
+
+ // verify test data
+ InputStream in = socket.getInputStream();
+ for (int i = 0; i < data.length; i++) {
+ assertEquals(data[i], in.read());
}
- };
- targetThread.start();
+ targetThread.join();
- Thread.sleep(200);
+ protocol.verifyAll(); // assert no XMPP messages were sent
- // initiator connects
- Socks5ClientForInitiator socks5Client = new Socks5ClientForInitiator(streamHost, digest,
- connection, sessionID, targetJID);
-
- Socket socket = socks5Client.getSocket(GET_SOCKET_TIMEOUT);
-
- // verify test data
- InputStream in = socket.getInputStream();
- for (int i = 0; i < data.length; i++) {
- assertEquals(data[i], in.read());
+ socks5Proxy.removeTransfer(digest);
+ } finally {
+ socks5Proxy.stop();
}
-
- targetThread.join();
-
- protocol.verifyAll(); // assert no XMPP messages were sent
-
- socks5Proxy.removeTransfer(digest);
- socks5Proxy.stop();
-
}
/**
@@ -202,6 +180,8 @@ public class Socks5ClientForInitiatorTest {
*/
@Test
public void shouldFailIfActivateSocks5ProxyFails() throws Exception {
+ Protocol protocol = new Protocol();
+ XMPPConnection connection = ConnectionUtils.createMockedConnection(protocol, initiatorJID);
// build error response as reply to the stream activation
IQ error = new ErrorIQ(StanzaError.getBuilder(StanzaError.Condition.internal_server_error));
@@ -212,30 +192,25 @@ public class Socks5ClientForInitiatorTest {
Verification.requestTypeSET);
// start a local SOCKS5 proxy
- Socks5TestProxy socks5Proxy = Socks5TestProxy.getProxy(proxyPort);
- socks5Proxy.start();
+ try (Socks5TestProxy socks5Proxy = new Socks5TestProxy()) {
+ StreamHost streamHost = new StreamHost(proxyJID, loopbackAddress, socks5Proxy.getPort());
- StreamHost streamHost = new StreamHost(proxyJID,
- loopbackAddress, socks5Proxy.getPort());
+ // create digest to get the socket opened by target
+ String digest = Socks5Utils.createDigest(sessionID, initiatorJID, targetJID);
- // create digest to get the socket opened by target
- String digest = Socks5Utils.createDigest(sessionID, initiatorJID, targetJID);
+ Socks5ClientForInitiator socks5Client = new Socks5ClientForInitiator(streamHost, digest, connection,
+ sessionID, targetJID);
- Socks5ClientForInitiator socks5Client = new Socks5ClientForInitiator(streamHost, digest,
- connection, sessionID, targetJID);
+ try {
- try {
+ socks5Client.getSocket(GET_SOCKET_TIMEOUT);
- socks5Client.getSocket(GET_SOCKET_TIMEOUT);
-
- fail("exception should be thrown");
+ fail("exception should be thrown");
+ } catch (XMPPErrorException e) {
+ assertTrue(StanzaError.Condition.internal_server_error.equals(e.getStanzaError().getCondition()));
+ protocol.verifyAll();
+ }
}
- catch (XMPPErrorException e) {
- assertTrue(StanzaError.Condition.internal_server_error.equals(e.getStanzaError().getCondition()));
- protocol.verifyAll();
- }
-
- socks5Proxy.stop();
}
/**
@@ -246,6 +221,8 @@ public class Socks5ClientForInitiatorTest {
*/
@Test
public void shouldSuccessfullyEstablishConnectionAndActivateSocks5Proxy() throws Exception {
+ Protocol protocol = new Protocol();
+ XMPPConnection connection = ConnectionUtils.createMockedConnection(protocol, initiatorJID);
// build activation confirmation response
IQ activationResponse = new EmptyResultIQ();
@@ -265,45 +242,34 @@ public class Socks5ClientForInitiatorTest {
});
+ Socket initiatorSocket = null, targetSocket = null;
// start a local SOCKS5 proxy
- Socks5TestProxy socks5Proxy = Socks5TestProxy.getProxy(proxyPort);
- socks5Proxy.start();
+ try (Socks5TestProxy socks5Proxy = new Socks5TestProxy()) {
+ StreamHost streamHost = new StreamHost(proxyJID, loopbackAddress, socks5Proxy.getPort());
- StreamHost streamHost = new StreamHost(proxyJID,
- loopbackAddress, socks5Proxy.getPort());
+ // create digest to get the socket opened by target
+ String digest = Socks5Utils.createDigest(sessionID, initiatorJID, targetJID);
- // create digest to get the socket opened by target
- String digest = Socks5Utils.createDigest(sessionID, initiatorJID, targetJID);
+ Socks5ClientForInitiator socks5Client = new Socks5ClientForInitiator(streamHost, digest, connection,
+ sessionID, targetJID);
- Socks5ClientForInitiator socks5Client = new Socks5ClientForInitiator(streamHost, digest,
- connection, sessionID, targetJID);
+ initiatorSocket = socks5Client.getSocket(10000);
+ InputStream in = initiatorSocket.getInputStream();
- Socket initiatorSocket = socks5Client.getSocket(10000);
- InputStream in = initiatorSocket.getInputStream();
+ targetSocket = socks5Proxy.getSocket(digest);
+ OutputStream out = targetSocket.getOutputStream();
- Socket targetSocket = socks5Proxy.getSocket(digest);
- OutputStream out = targetSocket.getOutputStream();
+ // verify test data
+ for (int i = 0; i < 10; i++) {
+ out.write(i);
+ assertEquals(i, in.read());
+ }
- // verify test data
- for (int i = 0; i < 10; i++) {
- out.write(i);
- assertEquals(i, in.read());
+ protocol.verifyAll();
+ } finally {
+ CloseableUtil.maybeClose(initiatorSocket);
+ CloseableUtil.maybeClose(targetSocket);
}
-
- protocol.verifyAll();
-
- initiatorSocket.close();
- targetSocket.close();
- socks5Proxy.stop();
-
- }
-
- /**
- * Reset default port for local SOCKS5 proxy.
- */
- @After
- public void cleanup() {
- Socks5Proxy.setLocalSocks5ProxyPort(7777);
}
}
diff --git a/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5TestProxy.java b/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5TestProxy.java
index c40d037cf..3c4fb236e 100644
--- a/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5TestProxy.java
+++ b/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5TestProxy.java
@@ -31,6 +31,8 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import org.jivesoftware.smack.SmackException;
+import org.jivesoftware.smack.util.CloseableUtil;
+import org.jivesoftware.smack.util.NetworkUtil;
/**
* Simple SOCKS5 proxy for testing purposes. It is almost the same as the Socks5Proxy class but the
@@ -38,12 +40,9 @@ import org.jivesoftware.smack.SmackException;
*
* @author Henning Staib
*/
-public final class Socks5TestProxy {
+public final class Socks5TestProxy implements AutoCloseable {
private static final Logger LOGGER = Logger.getLogger(Socks5TestProxy.class.getName());
- /* SOCKS5 proxy singleton */
- private static Socks5TestProxy socks5Server;
-
/* reusable implementation of a SOCKS5 proxy server process */
private Socks5ServerProcess serverProcess;
@@ -51,64 +50,22 @@ public final class Socks5TestProxy {
private Thread serverThread;
/* server socket to accept SOCKS5 connections */
- private ServerSocket serverSocket;
+ private final ServerSocket serverSocket;
/* assigns a connection to a digest */
private final Map connectionMap = new ConcurrentHashMap();
- /* port of the test proxy */
- private int port = 7777;
-
private boolean startupComplete;
- /**
- * Private constructor.
- */
- private Socks5TestProxy(int port) {
+ Socks5TestProxy() throws IOException {
+ this(NetworkUtil.getSocketOnLoopback());
+ }
+
+ Socks5TestProxy(ServerSocket serverSocket) {
+ this.serverSocket = serverSocket;
this.serverProcess = new Socks5ServerProcess();
- this.port = port;
- }
-
- /**
- * Returns the local SOCKS5 proxy server.
- *
- * @param port of the test proxy
- * @return the local SOCKS5 proxy server
- */
- public static synchronized Socks5TestProxy getProxy(int port) {
- if (socks5Server == null) {
- socks5Server = new Socks5TestProxy(port);
- socks5Server.start();
- }
- return socks5Server;
- }
-
- /**
- * Stops the test proxy.
- */
- public static synchronized void stopProxy() {
- if (socks5Server != null) {
- socks5Server.stop();
- socks5Server = null;
- }
- }
-
- /**
- * Starts the local SOCKS5 proxy server. If it is already running, this method does nothing.
- */
- public synchronized void start() {
- if (isRunning()) {
- return;
- }
- try {
- this.serverSocket = new ServerSocket(this.port);
- this.serverThread = new Thread(this.serverProcess);
- this.serverThread.start();
- }
- catch (IOException e) {
- LOGGER.log(Level.SEVERE, "exception", e);
- // do nothing
- }
+ this.serverThread = new Thread(this.serverProcess);
+ this.serverThread.start();
}
/**
@@ -138,8 +95,6 @@ public final class Socks5TestProxy {
}
}
this.serverThread = null;
- this.serverSocket = null;
-
}
/**
@@ -173,16 +128,15 @@ public final class Socks5TestProxy {
*
* @param digest identifying the connection
* @return socket or null if there is no socket for the given digest
+ * @throws InterruptedException
*/
- @SuppressWarnings("WaitNotInLoop")
- public Socket getSocket(String digest) {
+ public Socket getSocket(String digest) throws InterruptedException {
synchronized (this) {
- if (!startupComplete) {
- try {
- wait(5000);
- } catch (InterruptedException e) {
- LOGGER.log(Level.SEVERE, "exception", e);
- }
+ long now = System.currentTimeMillis();
+ final long deadline = now + 5000;
+ while (!startupComplete && now < deadline) {
+ wait(deadline - now);
+ now = System.currentTimeMillis();
}
}
if (!startupComplete) {
@@ -197,7 +151,7 @@ public final class Socks5TestProxy {
* @return true if the local SOCKS5 proxy server is running, otherwise false
*/
public boolean isRunning() {
- return this.serverSocket != null;
+ return !this.serverSocket.isClosed();
}
/**
@@ -213,7 +167,7 @@ public final class Socks5TestProxy {
Socket socket = null;
try {
-
+ // TODO: Add !serverSocket.isClosed() into the while condition and remove the following lines.
if (Socks5TestProxy.this.serverSocket.isClosed()
|| Thread.currentThread().isInterrupted()) {
return;
@@ -227,20 +181,16 @@ public final class Socks5TestProxy {
synchronized (this) {
startupComplete = true;
- notify();
+ notifyAll();
}
}
catch (SocketException e) {
/* do nothing */
+ LOGGER.log(Level.FINE, "Socket exception in Socks5TestProxy " + this, e);
}
catch (Exception e) {
- try {
- LOGGER.log(Level.SEVERE, "exception", e);
- socket.close();
- }
- catch (IOException e1) {
- /* Do Nothing */
- }
+ LOGGER.log(Level.SEVERE, "exception", e);
+ CloseableUtil.maybeClose(socket, LOGGER);
}
}
@@ -309,4 +259,9 @@ public final class Socks5TestProxy {
}
+ @Override
+ public void close() {
+ stop();
+ }
+
}