package com.limegroup.gnutella; import java.io.File; import java.net.DatagramSocket; import java.net.ServerSocket; import java.util.Iterator; import java.util.concurrent.TimeUnit; import junit.framework.Test; import org.limewire.core.settings.ConnectionSettings; import org.limewire.core.settings.FilterSettings; import org.limewire.core.settings.NetworkSettings; import org.limewire.core.settings.UltrapeerSettings; import org.limewire.gnutella.tests.LimeTestCase; import org.limewire.gnutella.tests.LimeTestUtils; import org.limewire.io.GUID; import org.limewire.util.TestUtils; import com.google.inject.Inject; import com.limegroup.gnutella.connection.BlockingConnection; import com.limegroup.gnutella.connection.BlockingConnectionFactory; import com.limegroup.gnutella.handshaking.HeadersFactory; import com.limegroup.gnutella.helpers.UrnHelper; import com.limegroup.gnutella.library.FileCollection; import com.limegroup.gnutella.library.GnutellaFiles; import com.limegroup.gnutella.messages.FeatureSearchData; import com.limegroup.gnutella.messages.QueryRequest; import com.limegroup.gnutella.messages.QueryRequestFactory; import com.limegroup.gnutella.messages.Message.Network; import com.limegroup.gnutella.messages.vendor.CapabilitiesVMFactory; import com.limegroup.gnutella.routing.QueryRouteTable; import com.limegroup.gnutella.routing.RouteTableMessage; import com.limegroup.gnutella.util.EmptyResponder; public final class ServerSideWhatIsRoutingTest extends LimeTestCase { /** * The port that the central Ultrapeer listens on, and that the other nodes * connect to it on. */ private final int PORT = 6667; /** * Leaf connection to the Ultrapeer. */ private BlockingConnection LEAF; /** * Ultrapeer connection. */ private BlockingConnection ULTRAPEER_1; /** * Ultrapeer 1 UDP connection. */ private DatagramSocket UDP_ACCESS; /** * Just a TCP connection to use for testing. */ private ServerSocket TCP_ACCESS; /** * The port for TCP_ACCESS */ private final int TCP_ACCESS_PORT = 10776; /** * Second Ultrapeer connection */ private BlockingConnection ULTRAPEER_2; @Inject private LifecycleManager lifecycleManager; @Inject private ConnectionServices connectionServices; @Inject private BlockingConnectionFactory blockingConnectionFactory; @Inject private HeadersFactory headersFactory; @Inject private QueryRequestFactory queryRequestFactory; @Inject private CapabilitiesVMFactory capabilitiesVMFactory; @Inject @GnutellaFiles private FileCollection gnutellaFileCollection; public ServerSideWhatIsRoutingTest(String name) { super(name); } public static Test suite() { return buildTestSuite(ServerSideWhatIsRoutingTest.class); } public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } private void buildConnections() throws Exception { ULTRAPEER_1 = blockingConnectionFactory.createConnection("localhost", PORT); UDP_ACCESS = new DatagramSocket(); TCP_ACCESS = new ServerSocket(TCP_ACCESS_PORT); ULTRAPEER_2 = blockingConnectionFactory.createConnection("localhost", PORT); } public void setSettings() { FilterSettings.BLACK_LISTED_IP_ADDRESSES.set( new String[] {"*.*.*.*"}); FilterSettings.WHITE_LISTED_IP_ADDRESSES.set( new String[] {"127.*.*.*"}); NetworkSettings.PORT.setValue(PORT); ConnectionSettings.CONNECT_ON_STARTUP.setValue(false); UltrapeerSettings.EVER_ULTRAPEER_CAPABLE.setValue(true); UltrapeerSettings.DISABLE_ULTRAPEER_MODE.setValue(false); UltrapeerSettings.FORCE_ULTRAPEER_MODE.setValue(true); UltrapeerSettings.MAX_LEAVES.setValue(4); ConnectionSettings.NUM_CONNECTIONS.setValue(3); ConnectionSettings.LOCAL_IS_PRIVATE.setValue(false); ConnectionSettings.WATCHDOG_ACTIVE.setValue(false); } @Override public void setUp() throws Exception { setSettings(); assertEquals("unexpected port", PORT, NetworkSettings.PORT.getValue()); LimeTestUtils.createInjector(LimeTestUtils.createModule(this)); lifecycleManager.start(); connectionServices.connect(); // get the resource file for com/limegroup/gnutella File berkeley = TestUtils.getResourceFile("com/limegroup/gnutella/berkeley.txt"); File susheel = TestUtils.getResourceFile("com/limegroup/gnutella/susheel.txt"); assertNotNull(gnutellaFileCollection.add(berkeley).get(1, TimeUnit.SECONDS)); assertNotNull(gnutellaFileCollection.add(susheel).get(1, TimeUnit.SECONDS)); connect(); assertEquals("unexpected port", PORT, NetworkSettings.PORT.getValue()); } @Override protected void tearDown() throws Exception { connectionServices.disconnect(); lifecycleManager.shutdown(); if ((LEAF != null) && LEAF.isOpen()) LEAF.close(); ULTRAPEER_1.close(); ULTRAPEER_2.close(); UDP_ACCESS.close(); TCP_ACCESS.close(); } private static void sleep() { try {Thread.sleep(300);}catch(InterruptedException e) {} } /** * Drains all messages */ private void drainAll() throws Exception { if(ULTRAPEER_1.isOpen()) { BlockingConnectionUtils.drain(ULTRAPEER_1); } if(ULTRAPEER_2.isOpen()) { BlockingConnectionUtils.drain(ULTRAPEER_2); } if((LEAF != null) && LEAF.isOpen()) { BlockingConnectionUtils.drain(LEAF); } } /** * Connects all of the nodes to the central test Ultrapeer. */ private void connect() throws Exception { buildConnections(); //1. first Ultrapeer connection ULTRAPEER_2.initialize(headersFactory.createUltrapeerHeaders("localhost"), new EmptyResponder(), 1000); //2. second Ultrapeer connection ULTRAPEER_1.initialize(headersFactory.createUltrapeerHeaders("localhost"), new EmptyResponder(), 1000); // for Ultrapeer 1 QueryRouteTable qrt = new QueryRouteTable(); qrt.add("leehsus"); qrt.add("berkeley"); for (Iterator iter=qrt.encode(null).iterator(); iter.hasNext(); ) { ULTRAPEER_1.send((RouteTableMessage)iter.next()); ULTRAPEER_1.flush(); } assertTrue("ULTRAPEER_2 should be connected", ULTRAPEER_2.isOpen()); assertTrue("ULTRAPEER_1 should be connected", ULTRAPEER_1.isOpen()); LEAF = blockingConnectionFactory.createConnection("localhost", PORT); //3. routed leaf, with route table for "test" LEAF.initialize(headersFactory.createLeafHeaders("localhost"), new EmptyResponder(), 1000); qrt = new QueryRouteTable(); qrt.add("berkeley"); qrt.add("susheel"); qrt.addIndivisible(UrnHelper.UNIQUE_SHA1.toString()); for (Iterator iter=qrt.encode(null).iterator(); iter.hasNext(); ) { LEAF.send((RouteTableMessage)iter.next()); LEAF.flush(); } assertTrue("LEAF should be connected", LEAF.isOpen()); // make sure we get rid of any initial ping pong traffic exchanges sleep(); drainAll(); //sleep(); drainAll(); sleep(); } public void testDoesNotRouteToLeafWhatIsNewQuery() throws Exception { drainAll(); // send the query QueryRequest whatIsNewQuery = queryRequestFactory.createQueryRequest(GUID.makeGuid(), (byte)2, QueryRequest.WHAT_IS_NEW_QUERY_STRING, "", null, null, false, Network.UNKNOWN, false, FeatureSearchData.WHAT_IS_NEW); ULTRAPEER_1.send(whatIsNewQuery); ULTRAPEER_1.flush(); // give time to process Thread.sleep(1000); // the Leaf should NOT get this query QueryRequest rQuery = BlockingConnectionUtils.getFirstInstanceOfMessageType(LEAF, QueryRequest.class); assertNull(rQuery); } public void testDoesRouteToLeafWhatIsNewQuery() throws Exception { drainAll(); // send the CapabilitiesVM LEAF.send(capabilitiesVMFactory.getCapabilitiesVM()); LEAF.flush(); // send the query QueryRequest whatIsNewQuery = queryRequestFactory.createQueryRequest(GUID.makeGuid(), (byte)2, QueryRequest.WHAT_IS_NEW_QUERY_STRING, "", null, null, false, Network.UNKNOWN, false, FeatureSearchData.WHAT_IS_NEW); ULTRAPEER_1.send(whatIsNewQuery); ULTRAPEER_1.flush(); // give time to process Thread.sleep(1000); // the Leaf should get this query QueryRequest rQuery = BlockingConnectionUtils.getFirstInstanceOfMessageType(LEAF, QueryRequest.class); assertNotNull(rQuery); assertEquals(new GUID(rQuery.getGUID()), new GUID(whatIsNewQuery.getGUID())); // send the LAST HOP query whatIsNewQuery = queryRequestFactory.createQueryRequest(GUID.makeGuid(), (byte)1, QueryRequest.WHAT_IS_NEW_QUERY_STRING, "", null, null, false, Network.UNKNOWN, false, FeatureSearchData.WHAT_IS_NEW); ULTRAPEER_2.send(whatIsNewQuery); ULTRAPEER_2.flush(); // give time to process Thread.sleep(1000); // the Leaf should get this query rQuery = BlockingConnectionUtils.getFirstInstanceOfMessageType(LEAF, QueryRequest.class); assertNotNull(rQuery); assertEquals(new GUID(rQuery.getGUID()), new GUID(whatIsNewQuery.getGUID())); } public void testDoesNotRouteToUltrapeerWhatIsNewQuery() throws Exception { drainAll(); // send the query QueryRequest whatIsNewQuery = queryRequestFactory.createQueryRequest(GUID.makeGuid(), (byte)2, QueryRequest.WHAT_IS_NEW_QUERY_STRING, "", null, null, false, Network.UNKNOWN, false, FeatureSearchData.WHAT_IS_NEW); ULTRAPEER_2.send(whatIsNewQuery); ULTRAPEER_2.flush(); // give time to process Thread.sleep(3000); // the UP should NOT get this query QueryRequest rQuery = BlockingConnectionUtils.getFirstInstanceOfMessageType(ULTRAPEER_1, QueryRequest.class); assertNull(rQuery); } public void testDoesRouteToUltrapeerWhatIsNewQuery() throws Exception { drainAll(); // send the CapabilitiesVM ULTRAPEER_1.send(capabilitiesVMFactory.getCapabilitiesVM()); ULTRAPEER_1.flush(); // send the query QueryRequest whatIsNewQuery = queryRequestFactory.createQueryRequest(GUID.makeGuid(), (byte)2, QueryRequest.WHAT_IS_NEW_QUERY_STRING, "", null, null, false, Network.UNKNOWN, false, FeatureSearchData.WHAT_IS_NEW); ULTRAPEER_2.send(whatIsNewQuery); ULTRAPEER_2.flush(); // give time to process Thread.sleep(1000); // the UP should get this query QueryRequest rQuery = BlockingConnectionUtils.getFirstInstanceOfMessageType(ULTRAPEER_1, QueryRequest.class); assertNotNull(rQuery); assertEquals(new GUID(rQuery.getGUID()), new GUID(whatIsNewQuery.getGUID())); } // Ultrapeer 1 should get the query, Ultrapeer 2 should not (because UP 1 // sent the capabilites VM) public void testLeafQueryRoutesCorrectly() throws Exception { drainAll(); // send the CapabilitiesVM ULTRAPEER_1.send(capabilitiesVMFactory.getCapabilitiesVM()); ULTRAPEER_1.flush(); // send the query QueryRequest whatIsNewQuery = queryRequestFactory.createQueryRequest(GUID.makeGuid(), (byte)2, QueryRequest.WHAT_IS_NEW_QUERY_STRING, "", null, null, false, Network.UNKNOWN, false, FeatureSearchData.WHAT_IS_NEW); LEAF.send(whatIsNewQuery); LEAF.flush(); // give time to process Thread.sleep(5000); // UP 1 should get this query QueryRequest rQuery = BlockingConnectionUtils.getFirstInstanceOfMessageType(ULTRAPEER_1, QueryRequest.class); assertNotNull(rQuery); assertEquals(new GUID(rQuery.getGUID()), new GUID(whatIsNewQuery.getGUID())); // UP 2 should NOT get this query rQuery = BlockingConnectionUtils.getFirstInstanceOfMessageType(ULTRAPEER_2, QueryRequest.class); assertNull(rQuery); } public void testUnsupportedQueryForwardedCorrectly() throws Exception { drainAll(); // send the CapabilitiesVM ULTRAPEER_1.send(capabilitiesVMFactory.getCapabilitiesVM()); ULTRAPEER_1.flush(); // send the query QueryRequest unknownFeatureQuery = queryRequestFactory.createQueryRequest(GUID.makeGuid(), (byte)3, QueryRequest.WHAT_IS_NEW_QUERY_STRING, "", null, null, false, Network.UNKNOWN, false, FeatureSearchData.FEATURE_SEARCH_MAX_SELECTOR+1); ULTRAPEER_2.send(unknownFeatureQuery); ULTRAPEER_2.flush(); // give time to process Thread.sleep(4000); // the Leaf should NOT get this query QueryRequest rQuery = BlockingConnectionUtils.getFirstInstanceOfMessageType(LEAF, QueryRequest.class); assertNull(rQuery); // Ultrapeer 1 should get it though rQuery = BlockingConnectionUtils.getFirstInstanceOfMessageType(ULTRAPEER_1, QueryRequest.class); assertNotNull(rQuery); assertEquals(new GUID(rQuery.getGUID()), new GUID(unknownFeatureQuery.getGUID())); } public void testLastHopUnsupportedQueryForwardedCorrectly() throws Exception { drainAll(); // send the CapabilitiesVM ULTRAPEER_1.send(capabilitiesVMFactory.getCapabilitiesVM()); ULTRAPEER_1.flush(); // send the query QueryRequest unknownFeatureQuery = queryRequestFactory.createQueryRequest(GUID.makeGuid(), (byte)2, QueryRequest.WHAT_IS_NEW_QUERY_STRING, "", null, null, false, Network.UNKNOWN, false, FeatureSearchData.FEATURE_SEARCH_MAX_SELECTOR+1); ULTRAPEER_2.send(unknownFeatureQuery); ULTRAPEER_2.flush(); // give time to process Thread.sleep(4000); // the Leaf should NOT get this query QueryRequest rQuery = BlockingConnectionUtils.getFirstInstanceOfMessageType(LEAF, QueryRequest.class); assertNull(rQuery); // Ultrapeer 1 should get it though rQuery = BlockingConnectionUtils.getFirstInstanceOfMessageType(ULTRAPEER_1, QueryRequest.class); assertNotNull(rQuery); assertEquals(new GUID(rQuery.getGUID()), new GUID(unknownFeatureQuery.getGUID())); } // ------------------------------------------------------ }