package com.limegroup.gnutella;
import java.io.IOException;
import java.io.OutputStream;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import junit.framework.Test;
import org.limewire.io.GUID;
import org.limewire.net.SocketsManager;
import org.limewire.service.ErrorService;
import com.limegroup.gnutella.connection.BlockingConnection;
import com.limegroup.gnutella.helpers.UrnHelper;
import com.google.inject.Injector;
import com.google.inject.Stage;
import com.limegroup.gnutella.messages.BadPacketException;
import com.limegroup.gnutella.messages.Message;
import com.limegroup.gnutella.messages.QueryReplyFactory;
import com.limegroup.gnutella.messages.QueryRequest;
import com.limegroup.gnutella.messages.vendor.MessagesSupportedVendorMessage;
import com.limegroup.gnutella.messages.vendor.QueryStatusResponse;
import com.limegroup.gnutella.stubs.NetworkManagerStub;
/**
* Checks whether (multi)leaves avoid forwarding messages to ultrapeers, do
* redirects properly, etc. The test includes a leaf attached to 3
* Ultrapeers.
*/
@SuppressWarnings("all")
public class ClientSideMixedOOBGuidanceTest extends ClientSideTestCase {
/**
* Ultrapeer 1 UDP connection.
*/
private static DatagramSocket UDP_ACCESS;
private NetworkManagerStub networkManagerStub;
private ResponseFactory responseFactory;
private SocketsManager socketsManager;
private UDPService udpService;
private Acceptor acceptor;
private SearchServices searchServices;
private QueryReplyFactory queryReplyFactory;
private MessagesSupportedVendorMessage messagesSupportedVendorMessage;
public ClientSideMixedOOBGuidanceTest(String name) {
super(name);
}
public static Test suite() {
return buildTestSuite(ClientSideMixedOOBGuidanceTest.class);
}
public static void main(String[] args) {
junit.textui.TestRunner.run(suite());
}
@Override
protected void setUp() throws Exception {
networkManagerStub = new NetworkManagerStub();
Injector injector = LimeTestUtils.createInjector(Stage.PRODUCTION, new LimeTestUtils.NetworkManagerStubModule(networkManagerStub));
super.setUp(injector);
responseFactory = injector.getInstance(ResponseFactory.class);
socketsManager = injector.getInstance(SocketsManager.class);
udpService = injector.getInstance(UDPService.class);
acceptor = injector.getInstance(Acceptor.class);
searchServices = injector.getInstance(SearchServices.class);
queryReplyFactory = injector.getInstance(QueryReplyFactory.class);
messagesSupportedVendorMessage = injector.getInstance(MessagesSupportedVendorMessage.class);
networkManagerStub.setCanReceiveSolicited(true);
networkManagerStub.setCanReceiveUnsolicited(true);
networkManagerStub.setOOBCapable(true);
}
/** @return The first QueryRequest received from this connection. If null
* is returned then it was never recieved (in a timely fashion).
*/
private QueryStatusResponse getFirstQueryStatus(BlockingConnection c)
throws IOException, BadPacketException {
return (QueryStatusResponse)
BlockingConnectionUtils.getFirstInstanceOfMessageType(c, QueryStatusResponse.class, TIMEOUT);
}
// TODO move setup stuff out to setUp method
public void testMixedProtocol() throws Exception {
UDP_ACCESS = new DatagramSocket();
for (int i = 0; i < testUP.length; i++) {
assertTrue("not open", testUP[i].isOpen());
assertTrue("not up->leaf", testUP[i].getConnectionCapabilities().isSupernodeClientConnection());
BlockingConnectionUtils.drain(testUP[i], 500);
if ((i==2)) { // i'll send 0 later....
testUP[i].send(messagesSupportedVendorMessage);
testUP[i].flush();
}
}
testUP[0].send(messagesSupportedVendorMessage);
testUP[0].flush();
// first we need to set up GUESS capability
UDP_ACCESS.setSoTimeout(TIMEOUT*2);
// ----------------------------------------
// you also have to set up TCP incoming....
{
Socket sock = null;
OutputStream os = null;
try {
sock=socketsManager.connect(new InetSocketAddress(InetAddress.getLocalHost().getHostAddress(),
SERVER_PORT), 12);
os = sock.getOutputStream();
os.write("CONNECT BACK\n\n".getBytes());
os.flush();
} catch (Throwable t) {
ErrorService.error(t);
} finally {
if(sock != null)
try { sock.close(); } catch(IOException ignored) {}
if(os != null)
try { os.close(); } catch(IOException ignored) {}
}
}
// ----------------------------------------
Thread.sleep(250);
// we should now be guess capable and tcp incoming capable....
// test directly on UPD service and acceptor, since networkmanager is stubbed
assertTrue("acceptor should have received a connection", acceptor.acceptedIncoming());
// get rid of any messages that are stored up.
drainAll();
// first of all, we should confirm that we are sending out a OOB query.
GUID queryGuid = new GUID(searchServices.newQueryGUID());
assertTrue(GUID.addressesMatch(queryGuid.bytes(),
networkManagerStub.getAddress(),
networkManagerStub.getPort()));
searchServices.query(queryGuid.bytes(), "susheel");
Thread.sleep(250);
// some connected UPs should get a OOB query
for (int i = 0; i < testUP.length; i++) {
QueryRequest qr = BlockingConnectionUtils.getFirstQueryRequest(testUP[i], TIMEOUT);
assertNotNull("up " + i + " didn't get query", qr);
assertEquals(new GUID(qr.getGUID()), queryGuid);
if ((i==0) || (i==2))
assertTrue(qr.desiresOutOfBandReplies());
else
assertTrue(!qr.desiresOutOfBandReplies());
}
// now confirm that we leaf guide the 'even' guys but not the others.
Message m = null;
// ensure that we'll get a QueryStatusResponse from the Responses
// we're sending.
for (int i = 0; i < testUP.length; i++) {
Response[] res = new Response[] {
responseFactory.createResponse(10, 10, "susheel"+i, UrnHelper.SHA1),
responseFactory.createResponse(10, 10, "susheel smells good"+i, UrnHelper.SHA1),
responseFactory.createResponse(10, 10, "anita is sweet"+i, UrnHelper.SHA1),
responseFactory.createResponse(10, 10, "anita is prety"+i, UrnHelper.SHA1),
responseFactory.createResponse(10, 10, "susheel smells bad" + i, UrnHelper.SHA1),
responseFactory.createResponse(10, 10, "renu is sweet " + i, UrnHelper.SHA1),
responseFactory.createResponse(10, 10, "prety is spelled pretty " + i, UrnHelper.SHA1),
responseFactory.createResponse(10, 10, "go susheel go" + i, UrnHelper.SHA1),
responseFactory.createResponse(10, 10, "susheel runs fast" + i, UrnHelper.SHA1),
responseFactory.createResponse(10, 10, "susheel jumps high" + i, UrnHelper.SHA1),
responseFactory.createResponse(10, 10, "sleepy susheel" + i, UrnHelper.SHA1),
};
m = queryReplyFactory.createQueryReply(queryGuid.bytes(), (byte) 1, 6355,
myIP(), 0, res, GUID.makeGuid(), new byte[0], false, false,
true, true, false, false, null);
testUP[i].send(m);
testUP[i].flush();
}
// all UPs should get a QueryStatusResponse
for (int i = 0; i < testUP.length; i++) {
QueryStatusResponse stat = getFirstQueryStatus(testUP[i]);
if ((i==0) || (i==2)) {
assertNotNull(stat);
assertEquals(new GUID(stat.getGUID()), queryGuid);
assertEquals(5, stat.getNumResults());
}
else
assertNull(stat);
}
// shut off the query....
searchServices.stopQuery(queryGuid);
// all UPs should get a QueryStatusResponse with 65535
for (int i = 0; i < testUP.length; i++) {
QueryStatusResponse stat = getFirstQueryStatus(testUP[i]);
if ((i==0) || (i==2)) {
assertNotNull(stat);
assertEquals(new GUID(stat.getGUID()), queryGuid);
assertEquals(65535, stat.getNumResults());
}
else
assertNull(stat);
}
}
//////////////////////////////////////////////////////////////////
private static byte[] myIP() {
return new byte[] { (byte)127, (byte)0, 0, 1 };
}
public int getNumberOfPeers() {
return 3;
}
}