package com.limegroup.gnutella; import java.io.ByteArrayInputStream; import java.io.InterruptedIOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.ServerSocket; import java.net.Socket; import java.util.Iterator; import junit.framework.Test; import com.limegroup.gnutella.handshaking.UltrapeerHeaders; import com.limegroup.gnutella.messages.Message; import com.limegroup.gnutella.messages.PingRequest; import com.limegroup.gnutella.messages.vendor.MessagesSupportedVendorMessage; import com.limegroup.gnutella.messages.vendor.TCPConnectBackRedirect; import com.limegroup.gnutella.messages.vendor.TCPConnectBackVendorMessage; import com.limegroup.gnutella.messages.vendor.UDPConnectBackRedirect; import com.limegroup.gnutella.messages.vendor.UDPConnectBackVendorMessage; import com.limegroup.gnutella.routing.QueryRouteTable; import com.limegroup.gnutella.routing.RouteTableMessage; import com.limegroup.gnutella.stubs.ActivityCallbackStub; import com.limegroup.gnutella.util.EmptyResponder; /** * Tests that an Ultrapeer correctly handles connect back redirect messages. * * ULTRAPEER_1 ---- CENTRAL TEST ULTRAPEER ---- ULTRAPEER_2 * | * | * | * LEAF * * This test only covers Ultrapeer behavior - leaves don't participate in * server side connect back stuff. */ public final class ServerSideIntermediateRedirectTest extends ServerSideTestCase { protected static int TIMEOUT = 2000; /** * Ultrapeer 1 UDP connection. */ private static DatagramSocket UDP_ACCESS; /** * Just a TCP connection to use for testing. */ private static ServerSocket TCP_ACCESS; /** * The port for TCP_ACCESS */ private static final int TCP_ACCESS_PORT = 10776; public ServerSideIntermediateRedirectTest(String name) { super(name); } public static Test suite() { return buildTestSuite(ServerSideIntermediateRedirectTest.class); } public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } public static Integer numUPs() { return new Integer(2); } public static Integer numLeaves() { return new Integer(1); } public static ActivityCallback getActivityCallback() { return new ActivityCallbackStub(); } public static void setUpQRPTables() throws Exception { } // BEGIN TESTS // ------------------------------------------------------ public void testNoRedirectCandidates() throws Exception { UDP_ACCESS = new DatagramSocket(); TCP_ACCESS = new ServerSocket(TCP_ACCESS_PORT); // ok, currently there are no redirect ultrapeers, so we've changed // the behavior - the Ultrapeer should just drop them on the floor TCPConnectBackVendorMessage tcp = new TCPConnectBackVendorMessage(TCP_ACCESS_PORT); LEAF[0].send(tcp); LEAF[0].flush(); try { TCP_ACCESS.setSoTimeout(TIMEOUT); TCP_ACCESS.accept(); fail("got a socket"); } catch (InterruptedIOException expected) {} GUID cbGuid = new GUID(GUID.makeGuid()); UDPConnectBackVendorMessage udp = new UDPConnectBackVendorMessage(UDP_ACCESS.getLocalPort(), cbGuid); LEAF[0].send(udp); LEAF[0].flush(); try { DatagramPacket pack = new DatagramPacket(new byte[1000], 1000); UDP_ACCESS.setSoTimeout(TIMEOUT); UDP_ACCESS.receive(pack); ByteArrayInputStream bais = new ByteArrayInputStream(pack.getData()); PingRequest ping = (PingRequest) Message.read(bais); fail("Got a message"); } catch (InterruptedIOException expected) {} catch (ClassCastException fine) {} } public void testSendsRedirect() throws Exception { Connection redirUP = new Connection("localhost", PORT); redirUP.initialize(new UltrapeerHeaders("localhost"), new EmptyResponder()); assertTrue(redirUP.isOpen()); drain(redirUP); Message msvm = MessagesSupportedVendorMessage.instance(); redirUP.send(msvm); redirUP.flush(); Thread.sleep(1000); ConnectionManager cm = ROUTER_SERVICE.getConnectionManager(); // now actually test.... { // make sure tcp vm's are redirected TCPConnectBackVendorMessage tcp = new TCPConnectBackVendorMessage(TCP_ACCESS_PORT); LEAF[0].send(tcp); LEAF[0].flush(); TCPConnectBackRedirect tcpR = (TCPConnectBackRedirect) getFirstInstanceOfMessageType(redirUP, TCPConnectBackRedirect.class, TIMEOUT); assertNotNull(tcpR); assertEquals(TCP_ACCESS_PORT, tcpR.getConnectBackPort()); assertEquals("127.0.0.1", tcpR.getConnectBackAddress().getHostAddress()); } { // make sure udp vm's are redirected GUID cbGuid = new GUID(GUID.makeGuid()); UDPConnectBackVendorMessage udp = new UDPConnectBackVendorMessage(UDP_ACCESS.getLocalPort(), cbGuid); LEAF[0].send(udp); LEAF[0].flush(); UDPConnectBackRedirect udpR = (UDPConnectBackRedirect) getFirstInstanceOfMessageType(redirUP, UDPConnectBackRedirect.class, TIMEOUT); assertNotNull(udpR); assertEquals(UDP_ACCESS.getLocalPort(), udpR.getConnectBackPort()); assertEquals("127.0.0.1", udpR.getConnectBackAddress().getHostAddress()); assertEquals(cbGuid, udpR.getConnectBackGUID()); } redirUP.close(); } public void testSendsRedirectMultiple() throws Exception { Connection redirUP1 = new Connection("localhost", PORT); redirUP1.initialize(new UltrapeerHeaders("localhost"), new EmptyResponder()); assertTrue(redirUP1.isOpen()); drain(redirUP1); Message msvm = MessagesSupportedVendorMessage.instance(); redirUP1.send(msvm); redirUP1.flush(); Connection redirUP2 = new Connection("localhost", PORT); redirUP2.initialize( new UltrapeerHeaders("localhost"), new EmptyResponder()); assertTrue(redirUP2.isOpen()); drain(redirUP2); msvm = MessagesSupportedVendorMessage.instance(); redirUP2.send(msvm); redirUP2.flush(); Thread.sleep(1000); ConnectionManager cm = ROUTER_SERVICE.getConnectionManager(); // now actually test.... { // make sure tcp vm's are redirected TCPConnectBackVendorMessage tcp = new TCPConnectBackVendorMessage(TCP_ACCESS_PORT); LEAF[0].send(tcp); LEAF[0].flush(); TCPConnectBackRedirect tcpR = (TCPConnectBackRedirect) getFirstInstanceOfMessageType(redirUP1, TCPConnectBackRedirect.class, TIMEOUT); if (tcpR == null) tcpR = (TCPConnectBackRedirect) getFirstInstanceOfMessageType(redirUP2, TCPConnectBackRedirect.class, TIMEOUT); assertNotNull(tcpR); assertEquals(TCP_ACCESS_PORT, tcpR.getConnectBackPort()); assertEquals("127.0.0.1", tcpR.getConnectBackAddress().getHostAddress()); } { // make sure udp vm's are redirected GUID cbGuid = new GUID(GUID.makeGuid()); UDPConnectBackVendorMessage udp = new UDPConnectBackVendorMessage(UDP_ACCESS.getLocalPort(), cbGuid); LEAF[0].send(udp); LEAF[0].flush(); UDPConnectBackRedirect udpR = (UDPConnectBackRedirect) getFirstInstanceOfMessageType(redirUP1, UDPConnectBackRedirect.class, TIMEOUT); if (udpR == null) udpR = (UDPConnectBackRedirect) getFirstInstanceOfMessageType(redirUP2, UDPConnectBackRedirect.class, TIMEOUT); assertNotNull(udpR); assertEquals(UDP_ACCESS.getLocalPort(), udpR.getConnectBackPort()); assertEquals("127.0.0.1", udpR.getConnectBackAddress().getHostAddress()); assertEquals(cbGuid, udpR.getConnectBackGUID()); } redirUP1.close(); redirUP2.close(); } // ------------------------------------------------------ }