package com.limegroup.gnutella.uploader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ScheduledExecutorService;
import junit.framework.Test;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.message.BasicHttpResponse;
import org.limewire.collection.BitNumbers;
import org.limewire.io.Connectable;
import org.limewire.io.ConnectableImpl;
import org.limewire.io.IpPort;
import org.limewire.io.IpPortImpl;
import org.limewire.io.NetworkInstanceUtils;
import org.limewire.net.ConnectionDispatcher;
import org.limewire.net.SocketsManager;
import org.limewire.net.address.StrictIpPortSet;
import org.limewire.util.BaseTestCase;
import com.google.inject.AbstractModule;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import com.google.inject.name.Named;
import com.limegroup.gnutella.ConnectionManager;
import com.limegroup.gnutella.ConnectionManagerImpl;
import com.limegroup.gnutella.ConnectionServices;
import com.limegroup.gnutella.HostCatcher;
import com.limegroup.gnutella.LimeTestUtils;
import com.limegroup.gnutella.NetworkManager;
import com.limegroup.gnutella.NodeAssigner;
import com.limegroup.gnutella.QueryUnicaster;
import com.limegroup.gnutella.altlocs.AltLocManager;
import com.limegroup.gnutella.altlocs.AlternateLocationFactory;
import com.limegroup.gnutella.altlocs.DirectAltLoc;
import com.limegroup.gnutella.connection.ConnectionCheckerManager;
import com.limegroup.gnutella.connection.RoutedConnectionFactory;
import com.limegroup.gnutella.filters.IPFilter;
import com.limegroup.gnutella.helpers.UrnHelper;
import com.limegroup.gnutella.messages.PingRequestFactory;
import com.limegroup.gnutella.messages.vendor.CapabilitiesVMFactory;
import com.limegroup.gnutella.simpp.SimppManager;
import com.limegroup.gnutella.stubs.NetworkManagerStub;
public class HTTPHeaderUtilsTest extends BaseTestCase {
private StubConnectionManager connectionManager;
private AltLocManager altLocManager;
private HTTPHeaderUtils httpHeaderUtils;
private AlternateLocationFactory alternateLocationFactory;
private NetworkManagerStub networkManager;
public HTTPHeaderUtilsTest(String name) {
super(name);
}
public static Test suite() {
return buildTestSuite(HTTPHeaderUtilsTest.class);
}
@Override
public void setUp() throws Exception {
networkManager = new NetworkManagerStub();
Injector injector = LimeTestUtils.createInjector(new AbstractModule() {
@Override
protected void configure() {
bind(NetworkManager.class).toInstance(networkManager);
bind(ConnectionManager.class).to(StubConnectionManager.class);
}
});
alternateLocationFactory = injector.getInstance(AlternateLocationFactory.class);
connectionManager = (StubConnectionManager) injector.getInstance(ConnectionManager.class);
connectionManager.proxies = new StrictIpPortSet<Connectable>();
altLocManager = new AltLocManager();
httpHeaderUtils = injector.getInstance(HTTPHeaderUtils.class);
}
@Override
public void tearDown() throws Exception {
}
public void testWritesAltsWhenEmpty() throws Exception {
StubAltLocTracker altLocTracker = new StubAltLocTracker();
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
altLocTracker.setNextSetOfAltsToSend(new ArrayList<DirectAltLoc>());
httpHeaderUtils.addAltLocationsHeader(response, altLocTracker, altLocManager);
assertNull(response.getLastHeader("X-Alt"));
}
public void testWritesAltsNoTLS() throws Exception {
StubAltLocTracker altLocTracker = new StubAltLocTracker();
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
altLocTracker.setNextSetOfAltsToSend(altsFor("1.2.3.4:5", "2.3.4.6", "7.3.2.1", "2.1.5.3:6201", "1.2.65.2"));
httpHeaderUtils.addAltLocationsHeader(response, altLocTracker, altLocManager);
Header header = response.getLastHeader("X-Alt");
assertNotNull("Missing X-Alt header", header);
assertEquals("1.2.3.4:5,2.3.4.6,7.3.2.1,2.1.5.3:6201,1.2.65.2", header.getValue());
}
public void testWritesAltsWithTLS() throws Exception {
StubAltLocTracker altLocTracker = new StubAltLocTracker();
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
altLocTracker.setNextSetOfAltsToSend(altsFor("1.2.3.4:5", "T2.3.4.6", "T7.3.2.1", "2.1.5.3:6201", "T1.2.65.2"));
httpHeaderUtils.addAltLocationsHeader(response, altLocTracker, altLocManager);
Header header = response.getLastHeader("X-Alt");
assertNotNull("Missing X-Alt header", header);
assertEquals("tls=68,1.2.3.4:5,2.3.4.6,7.3.2.1,2.1.5.3:6201,1.2.65.2", header.getValue());
}
public void testWritePushProxiesWhenEmpty() throws Exception {
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
httpHeaderUtils.addProxyHeader(response);
assertNull(response.getLastHeader("X-Push-Proxy"));
}
public void testWritePushProxiesNoTLS() throws Exception {
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
connectionManager.proxies.add(new ConnectableImpl("1.2.3.4", 5, false));
connectionManager.proxies.add(new ConnectableImpl("2.3.4.5", 6, false));
httpHeaderUtils.addProxyHeader(response);
Header header = response.getLastHeader("X-Push-Proxy");
assertNotNull("Missing X-Push-Proxy header", header);
assertEquals("1.2.3.4:5,2.3.4.5:6", header.getValue());
}
public void testWritePushProxiesSomeTLS() throws Exception {
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
connectionManager.proxies.add(new ConnectableImpl("1.2.3.4", 5, true));
connectionManager.proxies.add(new ConnectableImpl("2.3.4.5", 6, false));
connectionManager.proxies.add(new ConnectableImpl("3.4.5.6", 7, true));
httpHeaderUtils.addProxyHeader(response);
Header header = response.getLastHeader("X-Push-Proxy");
assertNotNull("Missing X-Push-Proxy header", header);
assertEquals("pptls=A,1.2.3.4:5,2.3.4.5:6,3.4.5.6:7", header.getValue());
}
public void testWritePushProxiesLimitsAt4() throws Exception {
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
connectionManager.proxies.add(new ConnectableImpl("1.2.3.4", 5, false));
connectionManager.proxies.add(new ConnectableImpl("2.3.4.5", 6, false));
connectionManager.proxies.add(new ConnectableImpl("3.4.5.6", 7, false));
connectionManager.proxies.add(new ConnectableImpl("4.5.6.7", 8, false));
connectionManager.proxies.add(new ConnectableImpl("5.6.7.8", 9, false));
httpHeaderUtils.addProxyHeader(response);
Header header = response.getLastHeader("X-Push-Proxy");
assertNotNull("Missing X-Push-Proxy header", header);
assertEquals("1.2.3.4:5,2.3.4.5:6,3.4.5.6:7,4.5.6.7:8", header.getValue());
}
public void testWritePushProxiesLimitsAt4NoTLSIfLater() throws Exception {
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
connectionManager.proxies.add(new ConnectableImpl("1.2.3.4", 5, false));
connectionManager.proxies.add(new ConnectableImpl("2.3.4.5", 6, false));
connectionManager.proxies.add(new ConnectableImpl("3.4.5.6", 7, false));
connectionManager.proxies.add(new ConnectableImpl("4.5.6.7", 8, false));
connectionManager.proxies.add(new ConnectableImpl("5.6.7.8", 9, true));
httpHeaderUtils.addProxyHeader(response);
Header header = response.getLastHeader("X-Push-Proxy");
assertNotNull("Missing X-Push-Proxy header", header);
assertEquals("1.2.3.4:5,2.3.4.5:6,3.4.5.6:7,4.5.6.7:8", header.getValue());
}
public void testWritePushProxiesLimitsAt4TLSRight() throws Exception {
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
connectionManager.proxies.add(new ConnectableImpl("1.2.3.4", 5, true));
connectionManager.proxies.add(new ConnectableImpl("2.3.4.5", 6, true));
connectionManager.proxies.add(new ConnectableImpl("3.4.5.6", 7, true));
connectionManager.proxies.add(new ConnectableImpl("4.5.6.7", 8, true));
connectionManager.proxies.add(new ConnectableImpl("5.6.7.8", 9, true));
httpHeaderUtils.addProxyHeader(response);
Header header = response.getLastHeader("X-Push-Proxy");
assertNotNull("Missing X-Push-Proxy header", header);
assertEquals("pptls=F,1.2.3.4:5,2.3.4.5:6,3.4.5.6:7,4.5.6.7:8", header.getValue());
}
public void testGetFullFirewalledHeaders() throws Exception {
connectionManager.proxies.add(new ConnectableImpl("1.2.3.4", 5, true));
connectionManager.proxies.add(new ConnectableImpl("2.3.4.5", 6, true));
connectionManager.proxies.add(new ConnectableImpl("3.4.5.6", 7, true));
connectionManager.proxies.add(new ConnectableImpl("4.5.6.7", 8, true));
connectionManager.proxies.add(new ConnectableImpl("5.6.7.8", 9, true));
networkManager.setCanDoFWT(true);
networkManager.setStableUDPPort(4545);
List<Header> headers = httpHeaderUtils.getFirewalledHeaders();
assertEquals(2, headers.size());
assertEquals("pptls=F,1.2.3.4:5,2.3.4.5:6,3.4.5.6:7,4.5.6.7:8", headers.get(0).getValue());
assertEquals("4545", headers.get(1).getValue());
}
public void testGetEmptyFirewalledHeaders() {
assertTrue(httpHeaderUtils.getFirewalledHeaders().isEmpty());
}
public void testGetTLSIndices() throws Exception {
Collection<? extends IpPort> proxies = Arrays.asList(new ConnectableImpl("localhost", 4545, true),
new IpPortImpl("helloword.com", 6666),
new ConnectableImpl("192.168.0.1", 7777, true));
BitNumbers bn = HTTPHeaderUtils.getTLSIndices(proxies);
assertFalse(bn.isEmpty());
assertTrue(bn.isSet(0));
assertFalse(bn.isSet(1));
assertTrue(bn.isSet(2));
assertEquals(3, bn.getMax());
bn = HTTPHeaderUtils.getTLSIndices(proxies, 2);
assertFalse(bn.isEmpty());
assertTrue(bn.isSet(0));
assertFalse(bn.isSet(1));
assertFalse(bn.isSet(2));
assertEquals(2, bn.getMax());
// empty set
proxies = Collections.emptyList();
bn = HTTPHeaderUtils.getTLSIndices(proxies);
assertTrue(bn.isEmpty());
}
public void testFirewalledHeadersNoFWTPort() throws Exception {
connectionManager.proxies.add(new ConnectableImpl("4.5.6.7", 8, false));
connectionManager.proxies.add(new ConnectableImpl("5.6.7.8", 9, false));
networkManager.setCanDoFWT(false);
networkManager.setStableUDPPort(4545);
List<Header> headers = httpHeaderUtils.getFirewalledHeaders();
assertEquals(1, headers.size());
}
private Collection<DirectAltLoc> altsFor(String... locs) throws Exception {
List<DirectAltLoc> alts = new ArrayList<DirectAltLoc>(locs.length);
for(String loc : locs) {
boolean tls = false;
if(loc.startsWith("T")) {
tls = true;
loc = loc.substring(1);
}
alts.add((DirectAltLoc)alternateLocationFactory.create(loc, UrnHelper.SHA1, tls));
}
return alts;
}
/** A fake ConnectionManager with custom proxies. */
@Singleton
private static class StubConnectionManager extends ConnectionManagerImpl {
@Inject
public StubConnectionManager(NetworkManager networkManager,
Provider<HostCatcher> hostCatcher,
@Named("global") Provider<ConnectionDispatcher> connectionDispatcher,
@Named("backgroundExecutor") ScheduledExecutorService backgroundExecutor,
Provider<SimppManager> simppManager,
CapabilitiesVMFactory capabilitiesVMFactory,
RoutedConnectionFactory managedConnectionFactory,
Provider<QueryUnicaster> queryUnicaster,
SocketsManager socketsManager, ConnectionServices connectionServices,
Provider<NodeAssigner> nodeAssigner,
Provider<IPFilter> ipFilter,
ConnectionCheckerManager connectionCheckerManager,
PingRequestFactory pingRequestFactory,
NetworkInstanceUtils networkInstanceUtils) {
super(networkManager, hostCatcher, connectionDispatcher, backgroundExecutor, simppManager,
capabilitiesVMFactory, managedConnectionFactory, queryUnicaster,
socketsManager, connectionServices, nodeAssigner, ipFilter, connectionCheckerManager,
pingRequestFactory, networkInstanceUtils);
}
private Set<Connectable> proxies;
@Override
public Set<Connectable> getPushProxies() {
return proxies;
}
}
}