package com.limegroup.gnutella.simpp; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.RandomAccessFile; import java.net.Socket; import com.limegroup.gnutella.Assert; import com.limegroup.gnutella.ByteReader; import com.limegroup.gnutella.ErrorService; import com.limegroup.gnutella.messages.BadPacketException; import com.limegroup.gnutella.messages.Message; import com.limegroup.gnutella.messages.vendor.CapabilitiesVM; import com.limegroup.gnutella.messages.vendor.CapabilitiesVMStubHelper; import com.limegroup.gnutella.messages.vendor.SimppRequestVM; import com.limegroup.gnutella.messages.vendor.SimppVM; import com.limegroup.gnutella.util.BaseTestCase; import com.limegroup.gnutella.util.CommonUtils; public class TestConnection { private Socket _socket; private byte[] _simppData; // used to determine if the file should actually be sent. private boolean _sendSimppData; private volatile boolean _expectSimppRequest; //The simpp message number this connection is expected to send private int _simppMessageNumber; private int _capabilitySimppNo; private boolean _causeError; /** * When creating a TestConnection you want to specify 4 things * @param port The port on which the TestConnection should connect to LW * @param simppNumber The simppNumber the TestConnection should pretend to * have, this affects the simpp-data that this TestConnection eventually * sends. * @param expectSimppReq whether or not the TestConnection should expect to * receive a SimppRequestVM * @param sendSimppData whether or not the TestConnection should send the * simpp-data when it receives a SimppRequestVM */ public TestConnection(int simppNumber, boolean expectSimppReq, boolean sendSimppData) throws IOException { this(simppNumber, expectSimppReq, sendSimppData, simppNumber); } public TestConnection(int simppNumber, boolean expectSimppReq, boolean sendSimppData, int capabilitySimpp) throws IOException { _simppData = readCorrectFile(simppNumber); _simppMessageNumber = simppNumber; _expectSimppRequest = expectSimppReq; _sendSimppData = sendSimppData; _capabilitySimppNo = capabilitySimpp; _causeError = false; } public void start() { Thread t = new Thread() { public void run() { //Make an out going connection to the machine try { _socket = new Socket("localhost", SimppManagerTest.PORT); establishConnection(); } catch (IOException iox) { if(!_causeError) //if not expected, show errorservice ErrorService.error(iox); } }//end of run }; t.setDaemon(true); t.start(); } public void killConnection() { try { if(_socket != null) _socket.close(); } catch(IOException iox) {} } private void establishConnection() throws IOException { InputStream is = _socket.getInputStream(); OutputStream os = _socket.getOutputStream(); ByteReader reader = new ByteReader(is); int b = 0; //write out the headers this code needs to change if the definition of //what's considered a good connection //Phase 1 of the handshake os.write("GNUTELLA CONNECT/0.6\r\n".getBytes()); os.write("User-Agent: LimeWire/3.4.4\r\n".getBytes()); os.write("Listen-IP:127.0.0.1:6346\r\n".getBytes()); os.write("X-Query-Routing: 0.1\r\n".getBytes()); os.write("X-Max-TTL: 3\r\n".getBytes()); os.write("X-Dynamic-Querying: 0.1\r\n".getBytes()); os.write(("X-Version: @version@\r\n").getBytes()); os.write("X-Ultrapeer: False\r\n".getBytes()); os.write("X-Degree: 15\r\n".getBytes()); os.write("X-Ultrapeer-Query-Routing: 0.1\r\n".getBytes()); os.write("\r\n".getBytes()); //Phase 2 of handshake -- read String line = null; while((line = reader.readLine()) != null && !line.equals("")) { //System.out.println(line); } //Phase 3 of handshake -- write 200 OK os.write("GNUTELLA/0.6 200 OK \r\n".getBytes()); os.write("\r\n".getBytes()); //Handshake complete //Make sure Simpp code is behaving correctly. checkSimppBehaviour(is, os); } private void checkSimppBehaviour(InputStream is, OutputStream os) throws IOException { //This method will create a CapabilitiesVM and send it to the LimeWire //it is connected to, it will then test that LimeWire is responding //correctly, and if necessary upload simpp-bytes to the limewire so the //testing can be done. CapabilitiesVM capVM = makeCapabilitiesVM(); capVM.write(os); os.flush(); //Read the first message of type SimppRequest Message message = null; try { message = BaseTestCase.getFirstInstanceOfMessage( _socket, SimppRequestVM.class, 2000); } catch (BadPacketException bpx) { Assert.that(false, "limewire sent message with BPX"); } if(_expectSimppRequest) Assert.that(message != null, "should have gotten simpp message"); else Assert.that(message == null, "shouldn't have gotten simpp message"); //send back the simppdata if reqd. if( _sendSimppData) {//we dont want if(_causeError) throw new IOException(); Message simppVM = new SimppVM(_simppData); simppVM.write(os); os.flush(); } //Read messages, if (_expectSimppRequest) make sure we get it, otherwise //make sure we do not get it. Then based on _sendSimppData send the data //back once if we got the SimppRequestVM } private CapabilitiesVM makeCapabilitiesVM() { try { return CapabilitiesVMStubHelper.makeCapVM(_capabilitySimppNo); } catch (Exception e) { Assert.that(false, "couldn't set up test -- failed to manipulate CapabilitiesVM"); } return null; } ////////////////////////////setter methods//////////////////////// public void setSendSimppData(boolean sendData) { _sendSimppData = sendData; } public void setCauseError(boolean err) { _causeError = err; } public void setExpectSimppRequest(boolean expected) { _expectSimppRequest = expected; } public void setSimppMessageNumber(int number) { _simppMessageNumber = number; try { _simppData = readCorrectFile(number); } catch(IOException iox) { Assert.that(false, "unable to read correct simpp test data"); } } ////////////////////////utilities////////////////////// private byte[] readCorrectFile(int fileVersion) throws IOException { File file = null; String simppDir = "com/limegroup/gnutella/simpp/"; if(fileVersion == SimppManagerTest.OLD) file = CommonUtils.getResourceFile(simppDir+"oldFile.xml"); else if(fileVersion == SimppManagerTest.MIDDLE) file = CommonUtils.getResourceFile(simppDir+"middleFile.xml"); else if(fileVersion == SimppManagerTest.NEW) file = CommonUtils.getResourceFile(simppDir+"newFile.xml"); else if(fileVersion == SimppManagerTest.DEF_MESSAGE) file = CommonUtils.getResourceFile(simppDir+"defMessageFile.xml"); else if(fileVersion == SimppManagerTest.DEF_SIGNATURE) file = CommonUtils.getResourceFile(simppDir+"defSigFile.xml"); else if(fileVersion == SimppManagerTest.BAD_XML) file = CommonUtils.getResourceFile(simppDir+"badXmlFile.xml"); else if(fileVersion == SimppManagerTest.RANDOM_BYTES) file = CommonUtils.getResourceFile(simppDir+"randFile.xml"); else if(fileVersion == SimppManagerTest.ABOVE_MAX) file = CommonUtils.getResourceFile(simppDir+"aboveMaxFile.xml"); else if(fileVersion == SimppManagerTest.BELOW_MIN) file = CommonUtils.getResourceFile(simppDir+"belowMinFile.xml"); else Assert.that(false,"simpp version set to illegal value"); //read the bytes of the file and close it. RandomAccessFile raf = new RandomAccessFile(file,"r"); byte[] ret = new byte[(int)raf.length()]; raf.readFully(ret); raf.close(); return ret; } }