package com.limegroup.gnutella.updates; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InterruptedIOException; import java.io.OutputStream; import java.io.RandomAccessFile; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; import com.limegroup.gnutella.Assert; import com.limegroup.gnutella.ByteReader; import com.limegroup.gnutella.Constants; import com.limegroup.gnutella.ErrorService; import com.limegroup.gnutella.util.CommonUtils; public class TestConnection { private ServerSocket _server; public String _headerVersion; private Socket _socket; private int _port; private byte[] _updateData; // used to determine if the file should actually be sent. private boolean _sendUpdateData; private volatile boolean _testUpdateNotRequested; public TestConnection(int port, String headerVersion, int fileVersion) throws IOException { _headerVersion = headerVersion; _port = port; _updateData = readCorrectFile(fileVersion); _testUpdateNotRequested = false; _sendUpdateData = true;//we want to send in the default case } public void start() { //1. set up an incoming socket try { _server = new ServerSocket(); //_server.setReuseAddress(true); _server.bind(new InetSocketAddress(_port)); } catch (IOException iox) { ErrorService.error(iox); } Thread t = new Thread() { public void run() { try { loop(); } catch(Throwable t) { ErrorService.error(t); } } }; t.setDaemon(true); t.start(); try { Thread.sleep(500);//give the server socket a little time to start } catch(InterruptedException e) { ErrorService.error(e); } //2. Make an out going connection to the machine try { _socket = new Socket("localhost", UpdateManagerTest.PORT); doHandshake(); } catch (IOException iox) { ErrorService.error(iox); } } void killThread() { try { if(_server != null) _server.close(); if(_socket != null) _socket.close(); } catch(IOException iox) {} } private void doHandshake() { //throws IOException { try { 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:"+_port+"\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: "+_headerVersion+"\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 = "dummy"; while(!line.equals("")) line = reader.readLine(); //Phase 3 of handshake -- write 200 OK os.write("GNUTELLA/0.6 200 OK \r\n".getBytes()); os.write("\r\n".getBytes()); line = "dummy"; _socket.setSoTimeout(1000);//keep the socket open for a second. while(line!=null) {//read while the socket is open try { line = reader.readLine(); } catch (InterruptedIOException iox) { break; } } } catch (IOException iox) { iox.printStackTrace(); } } //Server side code that services requsts for update file. Note: this server //processes only one request private void loop() throws IOException { Socket incoming = null; incoming = _server.accept(); final Socket mySocket = incoming; try { handleRequest(incoming); } catch (IOException iox) { } } private void handleRequest(Socket socket) throws IOException { if(_testUpdateNotRequested) Assert.that(false, "Unexpected behaviour -- update requested"); InputStream is = socket.getInputStream(); OutputStream os = socket.getOutputStream(); ByteReader reader = new ByteReader(is); int b = 0; String line = "dummy"; while(line!=null && !line.equals("")) { line = reader.readLine(); } if(!_sendUpdateData)//simply close the socket throw new IOException(); //first write the headers os.write("HTTP/1.1 200 OK\r\n".getBytes()); os.write(("User-Agent: LimeWire/"+_headerVersion+"\r\n").getBytes()); os.write(("Content-Type: "+ Constants.QUERYREPLY_MIME_TYPE+"\r\n").getBytes()); os.write(("Content-Length: "+_updateData.length + "\r\n").getBytes()); os.write("\r\n".getBytes()); //then write the body os.write(_updateData); os.flush(); socket.close(); //thanks and bye bye } ////////////////////////////setter methods//////////////////////// public void setSendUpdateData(boolean sendData) { _sendUpdateData = sendData; } public void setTestUpdateNotRequested(boolean requested) { _testUpdateNotRequested = requested; } ////////////////////////utilities////////////////////// private byte[] readCorrectFile(int fileVersion) throws IOException { File file = null; String updateDir = "com/limegroup/gnutella/updates/"; if(fileVersion == UpdateManagerTest.OLD) file = CommonUtils.getResourceFile(updateDir+"old_verFile.xml"); else if(fileVersion == UpdateManagerTest.MIDDLE) file = CommonUtils.getResourceFile(updateDir+"middle_verFile.xml"); else if(fileVersion == UpdateManagerTest.NEW) file = CommonUtils.getResourceFile(updateDir+"new_verFile.xml"); else if(fileVersion == UpdateManagerTest.DEF_MESSAGE) file = CommonUtils.getResourceFile(updateDir+"def_messageFile.xml"); else if(fileVersion == UpdateManagerTest.DEF_SIGNATURE) file = CommonUtils.getResourceFile(updateDir+"def_verFile.xml"); else if(fileVersion == UpdateManagerTest.BAD_XML) file = CommonUtils.getResourceFile(updateDir+"bad_xmlFile.xml"); else if(fileVersion == UpdateManagerTest.RANDOM_BYTES) file =CommonUtils.getResourceFile(updateDir+"random_bytesFile.xml"); else Assert.that(false,"updateVersion set to wrong 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; } }