mirror of
https://github.com/vanitasvitae/Smack.git
synced 2025-09-10 17:49:38 +02:00
merged branch improve_bytestreams in trunk
git-svn-id: http://svn.igniterealtime.org/svn/repos/smack/trunk@11821 b35dd754-fafc-0310-a699-88a17e54d16e
This commit is contained in:
parent
ef74695a1b
commit
8b54f34153
74 changed files with 11866 additions and 1902 deletions
|
@ -0,0 +1,429 @@
|
|||
/**
|
||||
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.bytestreams.socks5;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
|
||||
import org.jivesoftware.smack.Connection;
|
||||
import org.jivesoftware.smack.SmackConfiguration;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
import org.jivesoftware.smack.packet.Packet;
|
||||
import org.jivesoftware.smack.packet.XMPPError;
|
||||
import org.jivesoftware.smackx.bytestreams.socks5.Socks5BytestreamManager;
|
||||
import org.jivesoftware.smackx.bytestreams.socks5.Socks5BytestreamRequest;
|
||||
import org.jivesoftware.smackx.bytestreams.socks5.Socks5Utils;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Tests for the Socks5BytestreamRequest class.
|
||||
*
|
||||
* @author Henning Staib
|
||||
*/
|
||||
public class Socks5ByteStreamRequestTest {
|
||||
|
||||
// settings
|
||||
String initiatorJID = "initiator@xmpp-server/Smack";
|
||||
String targetJID = "target@xmpp-server/Smack";
|
||||
String xmppServer = "xmpp-server";
|
||||
String proxyJID = "proxy.xmpp-server";
|
||||
String proxyAddress = "127.0.0.1";
|
||||
String sessionID = "session_id";
|
||||
|
||||
Protocol protocol;
|
||||
|
||||
Connection connection;
|
||||
|
||||
/**
|
||||
* Initialize fields used in the tests.
|
||||
*/
|
||||
@Before
|
||||
public void setup() {
|
||||
|
||||
// build protocol verifier
|
||||
protocol = new Protocol();
|
||||
|
||||
// create mocked XMPP connection
|
||||
connection = ConnectionUtils.createMockedConnection(protocol, targetJID, xmppServer);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepting a SOCKS5 Bytestream request should fail if the request doesn't contain any Socks5
|
||||
* proxies.
|
||||
*
|
||||
* @throws Exception should not happen
|
||||
*/
|
||||
@Test
|
||||
public void shouldFailIfRequestHasNoStreamHosts() throws Exception {
|
||||
|
||||
try {
|
||||
|
||||
// build SOCKS5 Bytestream initialization request with no SOCKS5 proxies
|
||||
Bytestream bytestreamInitialization = Socks5PacketUtils.createBytestreamInitiation(
|
||||
initiatorJID, targetJID, sessionID);
|
||||
|
||||
// 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);
|
||||
|
||||
// accept the stream (this is the call that is tested here)
|
||||
byteStreamRequest.accept();
|
||||
|
||||
fail("exception should be thrown");
|
||||
}
|
||||
catch (XMPPException e) {
|
||||
assertTrue(e.getMessage().contains("Could not establish socket with any provided host"));
|
||||
}
|
||||
|
||||
// verify targets response
|
||||
assertEquals(1, protocol.getRequests().size());
|
||||
Packet targetResponse = protocol.getRequests().remove(0);
|
||||
assertTrue(IQ.class.isInstance(targetResponse));
|
||||
assertEquals(initiatorJID, targetResponse.getTo());
|
||||
assertEquals(IQ.Type.ERROR, ((IQ) targetResponse).getType());
|
||||
assertEquals(XMPPError.Condition.item_not_found.toString(),
|
||||
((IQ) targetResponse).getError().getCondition());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepting a SOCKS5 Bytestream request should fail if target is not able to connect to any of
|
||||
* the provided SOCKS5 proxies.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void shouldFailIfRequestHasInvalidStreamHosts() throws Exception {
|
||||
|
||||
try {
|
||||
|
||||
// build SOCKS5 Bytestream initialization request
|
||||
Bytestream bytestreamInitialization = Socks5PacketUtils.createBytestreamInitiation(
|
||||
initiatorJID, targetJID, sessionID);
|
||||
// add proxy that is not running
|
||||
bytestreamInitialization.addStreamHost(proxyJID, proxyAddress, 7778);
|
||||
|
||||
// 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);
|
||||
|
||||
// accept the stream (this is the call that is tested here)
|
||||
byteStreamRequest.accept();
|
||||
|
||||
fail("exception should be thrown");
|
||||
}
|
||||
catch (XMPPException e) {
|
||||
assertTrue(e.getMessage().contains("Could not establish socket with any provided host"));
|
||||
}
|
||||
|
||||
// verify targets response
|
||||
assertEquals(1, protocol.getRequests().size());
|
||||
Packet targetResponse = protocol.getRequests().remove(0);
|
||||
assertTrue(IQ.class.isInstance(targetResponse));
|
||||
assertEquals(initiatorJID, targetResponse.getTo());
|
||||
assertEquals(IQ.Type.ERROR, ((IQ) targetResponse).getType());
|
||||
assertEquals(XMPPError.Condition.item_not_found.toString(),
|
||||
((IQ) targetResponse).getError().getCondition());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Target should not try to connect to SOCKS5 proxies that already failed twice.
|
||||
*
|
||||
* @throws Exception should not happen
|
||||
*/
|
||||
@Test
|
||||
public void shouldBlacklistInvalidProxyAfter2Failures() throws Exception {
|
||||
|
||||
// build SOCKS5 Bytestream initialization request
|
||||
Bytestream bytestreamInitialization = Socks5PacketUtils.createBytestreamInitiation(
|
||||
initiatorJID, targetJID, sessionID);
|
||||
bytestreamInitialization.addStreamHost("invalid." + proxyJID, "127.0.0.2", 7778);
|
||||
|
||||
// get SOCKS5 Bytestream manager for connection
|
||||
Socks5BytestreamManager byteStreamManager = Socks5BytestreamManager.getBytestreamManager(connection);
|
||||
|
||||
// try to connect several times
|
||||
for (int i = 0; i < 2; i++) {
|
||||
try {
|
||||
// build SOCKS5 Bytestream request with the bytestream initialization
|
||||
Socks5BytestreamRequest byteStreamRequest = new Socks5BytestreamRequest(
|
||||
byteStreamManager, bytestreamInitialization);
|
||||
|
||||
// set timeouts
|
||||
byteStreamRequest.setTotalConnectTimeout(600);
|
||||
byteStreamRequest.setMinimumConnectTimeout(300);
|
||||
|
||||
// accept the stream (this is the call that is tested here)
|
||||
byteStreamRequest.accept();
|
||||
|
||||
fail("exception should be thrown");
|
||||
}
|
||||
catch (XMPPException e) {
|
||||
assertTrue(e.getMessage().contains(
|
||||
"Could not establish socket with any provided host"));
|
||||
}
|
||||
|
||||
// verify targets response
|
||||
assertEquals(1, protocol.getRequests().size());
|
||||
Packet targetResponse = protocol.getRequests().remove(0);
|
||||
assertTrue(IQ.class.isInstance(targetResponse));
|
||||
assertEquals(initiatorJID, targetResponse.getTo());
|
||||
assertEquals(IQ.Type.ERROR, ((IQ) targetResponse).getType());
|
||||
assertEquals(XMPPError.Condition.item_not_found.toString(),
|
||||
((IQ) targetResponse).getError().getCondition());
|
||||
}
|
||||
|
||||
// create test data for stream
|
||||
byte[] data = new byte[] { 1, 2, 3 };
|
||||
Socks5TestProxy socks5Proxy = Socks5TestProxy.getProxy(7779);
|
||||
|
||||
assertTrue(socks5Proxy.isRunning());
|
||||
|
||||
// add a valid SOCKS5 proxy
|
||||
bytestreamInitialization.addStreamHost(proxyJID, proxyAddress, 7779);
|
||||
|
||||
// build SOCKS5 Bytestream request with the bytestream initialization
|
||||
Socks5BytestreamRequest byteStreamRequest = new Socks5BytestreamRequest(byteStreamManager,
|
||||
bytestreamInitialization);
|
||||
|
||||
// set timeouts
|
||||
byteStreamRequest.setTotalConnectTimeout(600);
|
||||
byteStreamRequest.setMinimumConnectTimeout(300);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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());
|
||||
Packet 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());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Target should not not blacklist any SOCKS5 proxies regardless of failing connections.
|
||||
*
|
||||
* @throws Exception should not happen
|
||||
*/
|
||||
@Test
|
||||
public void shouldNotBlacklistInvalidProxy() throws Exception {
|
||||
|
||||
// disable blacklisting
|
||||
Socks5BytestreamRequest.setConnectFailureThreshold(0);
|
||||
|
||||
// build SOCKS5 Bytestream initialization request
|
||||
Bytestream bytestreamInitialization = Socks5PacketUtils.createBytestreamInitiation(
|
||||
initiatorJID, targetJID, sessionID);
|
||||
bytestreamInitialization.addStreamHost("invalid." + proxyJID, "127.0.0.2", 7778);
|
||||
|
||||
// get SOCKS5 Bytestream manager for connection
|
||||
Socks5BytestreamManager byteStreamManager = Socks5BytestreamManager.getBytestreamManager(connection);
|
||||
|
||||
// try to connect several times
|
||||
for (int i = 0; i < 10; i++) {
|
||||
try {
|
||||
// build SOCKS5 Bytestream request with the bytestream initialization
|
||||
Socks5BytestreamRequest byteStreamRequest = new Socks5BytestreamRequest(
|
||||
byteStreamManager, bytestreamInitialization);
|
||||
|
||||
// set timeouts
|
||||
byteStreamRequest.setTotalConnectTimeout(600);
|
||||
byteStreamRequest.setMinimumConnectTimeout(300);
|
||||
|
||||
// accept the stream (this is the call that is tested here)
|
||||
byteStreamRequest.accept();
|
||||
|
||||
fail("exception should be thrown");
|
||||
}
|
||||
catch (XMPPException e) {
|
||||
assertTrue(e.getMessage().contains(
|
||||
"Could not establish socket with any provided host"));
|
||||
}
|
||||
|
||||
// verify targets response
|
||||
assertEquals(1, protocol.getRequests().size());
|
||||
Packet targetResponse = protocol.getRequests().remove(0);
|
||||
assertTrue(IQ.class.isInstance(targetResponse));
|
||||
assertEquals(initiatorJID, targetResponse.getTo());
|
||||
assertEquals(IQ.Type.ERROR, ((IQ) targetResponse).getType());
|
||||
assertEquals(XMPPError.Condition.item_not_found.toString(),
|
||||
((IQ) targetResponse).getError().getCondition());
|
||||
}
|
||||
|
||||
// enable blacklisting
|
||||
Socks5BytestreamRequest.setConnectFailureThreshold(2);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* If the SOCKS5 Bytestream request contains multiple SOCKS5 proxies and the first one doesn't
|
||||
* respond, the connection attempt to this proxy should not consume the whole timeout for
|
||||
* connecting to the proxies.
|
||||
*
|
||||
* @throws Exception should not happen
|
||||
*/
|
||||
@Test
|
||||
public void shouldNotTimeoutIfFirstSocks5ProxyDoesNotRespond() throws Exception {
|
||||
|
||||
// start a local SOCKS5 proxy
|
||||
Socks5TestProxy socks5Proxy = Socks5TestProxy.getProxy(7778);
|
||||
|
||||
// create a fake SOCKS5 proxy that doesn't respond to a request
|
||||
ServerSocket serverSocket = new ServerSocket(7779);
|
||||
|
||||
// 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 };
|
||||
|
||||
// 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);
|
||||
|
||||
// set timeouts
|
||||
byteStreamRequest.setTotalConnectTimeout(2000);
|
||||
byteStreamRequest.setMinimumConnectTimeout(1000);
|
||||
|
||||
// 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 = serverSocket.accept();
|
||||
assertNotNull(socket);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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());
|
||||
Packet 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();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepting the SOCKS5 Bytestream request should be successfully.
|
||||
*
|
||||
* @throws Exception should not happen
|
||||
*/
|
||||
@Test
|
||||
public void shouldAcceptSocks5BytestreamRequestAndReceiveData() throws Exception {
|
||||
|
||||
// start a local SOCKS5 proxy
|
||||
Socks5TestProxy socks5Proxy = Socks5TestProxy.getProxy(7778);
|
||||
|
||||
// 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 };
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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());
|
||||
Packet 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();
|
||||
SmackConfiguration.setLocalSocks5ProxyEnabled(true);
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue