package com.limegroup.gnutella.util;
import java.io.IOException;
import java.net.Socket;
import junit.framework.Test;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.SimpleHttpConnectionManager;
import org.apache.commons.httpclient.methods.GetMethod;
import com.limegroup.gnutella.RouterService;
import com.limegroup.gnutella.http.HTTPHeaderName;
import com.limegroup.gnutella.http.HttpClientManager;
import com.limegroup.gnutella.io.StubConnectObserver;
import com.limegroup.gnutella.settings.ConnectionSettings;
import com.limegroup.gnutella.stubs.ActivityCallbackStub;
public class ProxyTest extends BaseTestCase {
private final static byte V4 = (byte) 4;
private final static byte V5 = (byte) 5;
private final static String HTTP_STR = "CONNECT";
private static final int PROXY_PORT = 9990;
static final int DEST_PORT = 9999;
final static int SOCKS4 = 0;
final static int SOCKS5 = 1;
final static int HTTP = 2;
final static int NONE = -1;
private static FakeProxyServer fps;
public ProxyTest(String name) {
super(name);
}
public static Test suite() {
return buildTestSuite(ProxyTest.class);
}
public static void main(String[] args) {
junit.textui.TestRunner.run(suite());
}
public static void globalSetUp() throws Exception {
RouterService rs = new RouterService(new ActivityCallbackStub());
fps = new FakeProxyServer(9990, 9999);
}
public void setUp() {
ConnectionSettings.LOCAL_IS_PRIVATE.setValue(false);
ConnectionSettings.PROXY_HOST.setValue("127.0.0.1");
ConnectionSettings.PROXY_PORT.setValue(PROXY_PORT);
fps.setMakeError(false);
}
public static void globalTeardown() {
fps.killServers();
}
/**
* If Proxy is off we should connect directly
*/
public void testConnectionsWithProxyOff() throws Exception {
ConnectionSettings.CONNECTION_METHOD.setValue(ConnectionSettings.C_NO_PROXY);
fps.setProxyOn(false);
fps.setAuthentication(false);
fps.setProxyVersion(NONE);
Socket s = Sockets.connect("localhost", DEST_PORT, 0);
// we should be connected to something, NPE is an error
s.close();
}
/**
* connect with socks 5
*/
public void testSOCKS5Connection() throws Exception {
runSOCKS5Connection(false);
}
public void testSOCKS5ConnectionNB() throws Exception {
runSOCKS5Connection(true);
}
private void runSOCKS5Connection(boolean nb) throws Exception {
ConnectionSettings.CONNECTION_METHOD.setValue(ConnectionSettings.C_SOCKS5_PROXY);
fps.setProxyOn(true);
fps.setAuthentication(false);
fps.setProxyVersion(SOCKS5);
connect(nb, true);
}
/**
* connect with socks 5 connection fails with bad code.
*/
public void testSOCKS5ConnectionWithError() throws Exception {
runSOCKS5ConnectionWithError(false);
}
public void testSOCKS5ConnectionWithErrorNB() throws Exception {
runSOCKS5ConnectionWithError(true);
}
private void runSOCKS5ConnectionWithError(boolean nb) throws Exception {
ConnectionSettings.CONNECTION_METHOD.setValue(ConnectionSettings.C_SOCKS5_PROXY);
fps.setProxyOn(true);
fps.setAuthentication(false);
fps.setProxyVersion(SOCKS5);
fps.setMakeError(true);
connect(nb, false);
fps.setMakeError(false);
}
/**
* connect with socks5 with auth
*/
public void testSOCKS5WithAuth() throws Exception {
runSOCKS5WithAuth(false);
}
public void testSOCKS5WithAuthNB() throws Exception {
runSOCKS5WithAuth(true);
}
private void runSOCKS5WithAuth(boolean nb) throws Exception {
ConnectionSettings.CONNECTION_METHOD.setValue(ConnectionSettings.C_SOCKS5_PROXY);
ConnectionSettings.PROXY_AUTHENTICATE.setValue(true);
ConnectionSettings.PROXY_USERNAME.setValue(FakeProxyServer.USER);
ConnectionSettings.PROXY_PASS.setValue(FakeProxyServer.PASS);
fps.setProxyOn(true);
fps.setAuthentication(true);
fps.setProxyVersion(SOCKS5);
connect(nb, true);
}
public void testSOCKS4Connection() throws Exception {
runSOCKS4Connection(false);
}
public void testSOCKS4ConnectionNB() throws Exception {
runSOCKS4Connection(true);
}
private void runSOCKS4Connection(boolean nb) throws Exception {
ConnectionSettings.CONNECTION_METHOD.setValue(ConnectionSettings.C_SOCKS4_PROXY);
fps.setProxyOn(true);
fps.setAuthentication(false);
fps.setProxyVersion(SOCKS4);
connect(nb, true);
}
public void testSOCKS4ConnectionWithError() throws Exception {
runSOCKS4ConnectionWithError(false);
}
public void testSOCKS4ConnectionWithErrorNB() throws Exception {
runSOCKS4ConnectionWithError(true);
}
private void runSOCKS4ConnectionWithError(boolean nb) throws Exception {
ConnectionSettings.CONNECTION_METHOD.setValue(ConnectionSettings.C_SOCKS4_PROXY);
fps.setProxyOn(true);
fps.setAuthentication(false);
fps.setProxyVersion(SOCKS4);
fps.setMakeError(true);
connect(nb, false);
fps.setMakeError(false);
}
public void testSOCKS4WithAuth() throws Exception {
runSOCKS4WithAuth(false);
}
public void testSOCKS4WithAuthNB() throws Exception {
runSOCKS4WithAuth(true);
}
private void runSOCKS4WithAuth(boolean nb) throws Exception {
ConnectionSettings.CONNECTION_METHOD.setValue(ConnectionSettings.C_SOCKS4_PROXY);
ConnectionSettings.PROXY_AUTHENTICATE.setValue(true);
ConnectionSettings.PROXY_USERNAME.setValue(FakeProxyServer.USER);
ConnectionSettings.PROXY_PASS.setValue(FakeProxyServer.PASS);
fps.setProxyOn(true);
fps.setAuthentication(true);
fps.setProxyVersion(SOCKS4);
connect(nb, true);
}
/**
* Tests that HTTP proxies are used correctly
*/
public void testHTTPProxy() throws Exception {
runHTTPProxy(false);
}
public void testHTTPProxyNB() throws Exception {
runHTTPProxy(true);
}
private void runHTTPProxy(boolean nb) throws Exception {
ConnectionSettings.CONNECTION_METHOD.setValue(ConnectionSettings.C_HTTP_PROXY);
fps.setProxyOn(true);
fps.setAuthentication(false);
fps.setProxyVersion(HTTP);
connect(nb, true);
}
public void testHTTPProxyWithError() throws Exception {
runHTTPProxyWithError(false);
}
public void testHTTPProxyWithErrorNB() throws Exception {
runHTTPProxyWithError(true);
}
private void runHTTPProxyWithError(boolean nb) throws Exception {
ConnectionSettings.CONNECTION_METHOD.setValue(ConnectionSettings.C_HTTP_PROXY);
fps.setProxyOn(true);
fps.setAuthentication(false);
fps.setProxyVersion(HTTP);
fps.setMakeError(true);
connect(nb, false);
}
private void connect(boolean nb, boolean success) throws Exception {
if (success) {
Socket s;
if (!nb) {
s = Sockets.connect("localhost", DEST_PORT, 0);
} else {
StubConnectObserver o = new StubConnectObserver();
s = Sockets.connect("localhost", DEST_PORT, 0, o);
o.waitForResponse(5000);
assertEquals(s, o.getSocket());
assertNull(o.getIoException());
assertFalse(o.isShutdown());
}
// Must connect somewhere, NPE is an error
s.close();
} else {
if (!nb) {
try {
Sockets.connect("localhost", DEST_PORT, 0);
fail("acceptedConnection from a bad proxy server");
} catch (IOException iox) {
// Good -- expected behaviour
}
} else {
StubConnectObserver o = new StubConnectObserver();
Sockets.connect("localhost", DEST_PORT, 0, o);
o.waitForResponse(5000);
assertNull(o.getSocket());
assertNull(o.getIoException());
assertTrue(o.isShutdown());
}
}
}
public void testHTTPClientWithProxyOff() throws Exception {
ConnectionSettings.CONNECTION_METHOD.setValue(ConnectionSettings.C_NO_PROXY);
fps.setProxyOn(false);
fps.setAuthentication(false);
fps.setProxyVersion(NONE);
fps.setHttpRequest(true);
String connectTo = "http://" + "localhost:" + DEST_PORT + "/myFile.txt";
HttpClient client = HttpClientManager.getNewClient();
HttpMethod get = new GetMethod(connectTo);
get.addRequestHeader(HTTPHeaderName.CONNECTION.httpStringValue(), "close");
client.executeMethod(get);
byte[] resp = get.getResponseBody();
assertEquals("invalid response from server", "hello", new String(resp));
get.abort();
}
public void testHTTPClientProxiesWithHttpProxy() throws Exception {
// ConnectionSettings.PROXY_SIMPLE_HTTP_CONNECTIONS.setValue(true);
ConnectionSettings.CONNECTION_METHOD.setValue(ConnectionSettings.C_HTTP_PROXY);
fps.setProxyOn(true);
fps.setAuthentication(false);
fps.setProxyVersion(HTTP);
fps.setHttpRequest(true);
String connectTo = "http://" + "localhost:" + DEST_PORT + "/myFile2.txt";
HttpMethod get = new GetMethod(connectTo);
get.addRequestHeader(HTTPHeaderName.CONNECTION.httpStringValue(), "close");
HttpClient client = HttpClientManager.getNewClient();
// release the connections.
client.setHttpConnectionManager(new SimpleHttpConnectionManager());
client.executeMethod(get);
String resp = new String(get.getResponseBody());
assertEquals("invalid response from server", "hello", resp);
get.abort();
}
public void testHTTPClientProxiesWithSocks4() throws Exception {
// ConnectionSettings.PROXY_SIMPLE_HTTP_CONNECTIONS.setValue(true);
ConnectionSettings.CONNECTION_METHOD.setValue(ConnectionSettings.C_SOCKS4_PROXY);
fps.setProxyOn(true);
fps.setAuthentication(false);
fps.setProxyVersion(SOCKS4);
fps.setHttpRequest(true);
String connectTo = "http://" + "localhost:" + DEST_PORT + "/myFile3.txt";
HttpMethod get = new GetMethod(connectTo);
get.addRequestHeader(HTTPHeaderName.CONNECTION.httpStringValue(), "close");
HttpClient client = HttpClientManager.getNewClient();
// release the connections.
client.setHttpConnectionManager(new SimpleHttpConnectionManager());
client.executeMethod(get);
String resp = new String(get.getResponseBody());
assertEquals("invalid response from server", "hello", resp);
get.abort();
}
public void testHTTPClientProxiesWithSocks5() throws Exception {
// ConnectionSettings.PROXY_SIMPLE_HTTP_CONNECTIONS.setValue(true);
ConnectionSettings.CONNECTION_METHOD.setValue(ConnectionSettings.C_SOCKS5_PROXY);
fps.setProxyOn(true);
fps.setAuthentication(false);
fps.setProxyVersion(SOCKS5);
fps.setHttpRequest(true);
String connectTo = "http://" + "localhost:" + DEST_PORT + "/myFile4.txt";
HttpMethod get = new GetMethod(connectTo);
get.addRequestHeader(HTTPHeaderName.CONNECTION.httpStringValue(), "close");
HttpClient client = HttpClientManager.getNewClient();
// release the connections.
client.setHttpConnectionManager(new SimpleHttpConnectionManager());
client.executeMethod(get);
String resp = new String(get.getResponseBody());
assertEquals("invalid response from server", "hello", resp);
get.abort();
}
public void testHTTPClientProxiesWithAuthSocks4() throws Exception {
// ConnectionSettings.PROXY_SIMPLE_HTTP_CONNECTIONS.setValue(true);
ConnectionSettings.CONNECTION_METHOD.setValue(ConnectionSettings.C_SOCKS4_PROXY);
ConnectionSettings.PROXY_AUTHENTICATE.setValue(true);
ConnectionSettings.PROXY_USERNAME.setValue(FakeProxyServer.USER);
ConnectionSettings.PROXY_PASS.setValue(FakeProxyServer.PASS);
fps.setProxyOn(true);
fps.setAuthentication(true);
fps.setProxyVersion(SOCKS4);
fps.setHttpRequest(true);
String connectTo = "http://" + "localhost:" + DEST_PORT + "/myFile3.txt";
HttpMethod get = new GetMethod(connectTo);
get.addRequestHeader(HTTPHeaderName.CONNECTION.httpStringValue(), "close");
HttpClient client = HttpClientManager.getNewClient();
// release the connections.
client.setHttpConnectionManager(new SimpleHttpConnectionManager());
client.executeMethod(get);
String resp = new String(get.getResponseBody());
assertEquals("invalid response from server", "hello", resp);
get.abort();
}
public void testHTTPClientProxiesWithAuthSocks5() throws Exception {
// ConnectionSettings.PROXY_SIMPLE_HTTP_CONNECTIONS.setValue(true);
ConnectionSettings.CONNECTION_METHOD.setValue(ConnectionSettings.C_SOCKS5_PROXY);
ConnectionSettings.PROXY_AUTHENTICATE.setValue(true);
ConnectionSettings.PROXY_USERNAME.setValue(FakeProxyServer.USER);
ConnectionSettings.PROXY_PASS.setValue(FakeProxyServer.PASS);
fps.setProxyOn(true);
fps.setAuthentication(true);
fps.setProxyVersion(SOCKS5);
fps.setHttpRequest(true);
String connectTo = "http://" + "localhost:" + DEST_PORT + "/myFile4.txt";
HttpMethod get = new GetMethod(connectTo);
get.addRequestHeader(HTTPHeaderName.CONNECTION.httpStringValue(), "close");
HttpClient client = HttpClientManager.getNewClient();
// release the connections.
client.setHttpConnectionManager(new SimpleHttpConnectionManager());
client.executeMethod(get);
String resp = new String(get.getResponseBody());
assertEquals("invalid response from server", "hello", resp);
get.abort();
}
}