package com.limegroup.gnutella.handshaking; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.InetAddress; import java.net.Socket; import java.nio.ByteBuffer; import java.util.Map; import java.util.Properties; import junit.framework.Test; import com.limegroup.gnutella.connection.ReadBufferChannel; import com.limegroup.gnutella.connection.WriteBufferChannel; import com.limegroup.gnutella.io.ChannelReadObserver; import com.limegroup.gnutella.io.ChannelWriter; import com.limegroup.gnutella.io.InterestReadChannel; import com.limegroup.gnutella.io.InterestWriteChannel; import com.limegroup.gnutella.io.NIOMultiplexor; import com.limegroup.gnutella.io.ReadObserver; import com.limegroup.gnutella.io.WriteObserver; import com.limegroup.gnutella.util.BaseTestCase; public class AsyncOutgoingHandshakerTest extends BaseTestCase { public AsyncOutgoingHandshakerTest(String name) { super(name); } public static Test suite() { return buildTestSuite(AsyncOutgoingHandshakerTest.class); } public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } public void testSimpleSuccess() throws Exception { ReadBufferChannel reader = new ReadBufferChannel( ("GNUTELLA/0.6 200 OK DOKIE\r\n" + "ResponseHeader: ResponseValue\r\n" + "\r\n").getBytes()); WriteBufferChannel writer = new WriteBufferChannel(2048); MultiplexingSocket socket = new MultiplexingSocket(reader, writer); Properties outRequestProps = new Properties(); outRequestProps.put("OutRequest", "OutRequestValue"); Properties outResponseProps = new Properties(); outResponseProps.put("OutResponse", "OutResponseValue"); StubHandshakeResponder responder = new StubHandshakeResponder(new StubHandshakeResponse(200, "OK!", outResponseProps)); StubHandshakeObserver observer = new StubHandshakeObserver(); Handshaker shaker = new AsyncOutgoingHandshaker(outRequestProps, responder, socket, observer); shaker.shake(); socket.exchange(); // simulates NIODispatcher setting interest assertFalse(observer.isNoGOK()); assertFalse(observer.isBadHandshake()); assertTrue(observer.isHandshakeFinished()); assertEquals(shaker, observer.getShaker()); HandshakeResponse responseTo = responder.getRespondedTo(); Map respondedTo = responder.getRespondedToProps(); assertEquals(1, respondedTo.size()); assertEquals("ResponseValue", respondedTo.get("ResponseHeader")); assertEquals(200, responseTo.getStatusCode()); assertEquals("OK DOKIE", responseTo.getStatusMessage()); assertTrue(responder.isOutgoing()); HandshakeResponse read = shaker.getReadHeaders(); assertEquals(1, read.props().size()); assertEquals("ResponseValue", read.props().get("ResponseHeader")); HandshakeResponse written = shaker.getWrittenHeaders(); assertEquals(2, written.props().size()); assertEquals("OutRequestValue", written.props().get("OutRequest")); assertEquals("OutResponseValue", written.props().get("OutResponse")); ByteBuffer buffer = writer.getBuffer(); assertEquals("GNUTELLA CONNECT/0.6\r\nOutRequest: OutRequestValue\r\n\r\n" + "GNUTELLA/0.6 200 OK!\r\nOutResponse: OutResponseValue\r\n\r\n", new String(buffer.array(), 0, buffer.limit())); } public void testDiscoOnBadResponder() throws Exception { ReadBufferChannel reader = new ReadBufferChannel( ("GNUTELLA/0.6 200 OK DOKIE\r\n" + "ResponseHeader: ResponseValue\r\n" + "\r\n").getBytes()); WriteBufferChannel writer = new WriteBufferChannel(2048); MultiplexingSocket socket = new MultiplexingSocket(reader, writer); Properties outRequestProps = new Properties(); outRequestProps.put("OutRequest", "OutRequestValue"); Properties outResponseProps = new Properties(); outResponseProps.put("OutResponse", "OutResponseValue"); StubHandshakeResponder responder = new StubHandshakeResponder(new StubHandshakeResponse(322, "AARGH!", outResponseProps)); StubHandshakeObserver observer = new StubHandshakeObserver(); Handshaker shaker = new AsyncOutgoingHandshaker(outRequestProps, responder, socket, observer); shaker.shake(); socket.exchange(); // simulates NIODispatcher setting interest assertTrue(observer.isNoGOK()); assertEquals(322, observer.getCode()); assertFalse(observer.isBadHandshake()); assertFalse(observer.isHandshakeFinished()); assertNull(observer.getShaker()); HandshakeResponse responseTo = responder.getRespondedTo(); Map respondedTo = responder.getRespondedToProps(); assertEquals(1, respondedTo.size()); assertEquals("ResponseValue", respondedTo.get("ResponseHeader")); assertEquals(200, responseTo.getStatusCode()); assertEquals("OK DOKIE", responseTo.getStatusMessage()); assertTrue(responder.isOutgoing()); HandshakeResponse read = shaker.getReadHeaders(); assertEquals(1, read.props().size()); assertEquals("ResponseValue", read.props().get("ResponseHeader")); HandshakeResponse written = shaker.getWrittenHeaders(); assertEquals(2, written.props().size()); assertEquals("OutRequestValue", written.props().get("OutRequest")); assertEquals("OutResponseValue", written.props().get("OutResponse")); ByteBuffer buffer = writer.getBuffer(); assertEquals("GNUTELLA CONNECT/0.6\r\nOutRequest: OutRequestValue\r\n\r\n" + "GNUTELLA/0.6 322 AARGH!\r\nOutResponse: OutResponseValue\r\n\r\n", new String(buffer.array(), 0, buffer.limit())); } public void testDiscoOnBadResponseCode() throws Exception { ReadBufferChannel reader = new ReadBufferChannel( ("GNUTELLA/0.6 544 SHUCKS\r\n" + "ResponseHeader: ResponseValue\r\n" + "\r\n").getBytes()); WriteBufferChannel writer = new WriteBufferChannel(2048); MultiplexingSocket socket = new MultiplexingSocket(reader, writer); Properties outRequestProps = new Properties(); outRequestProps.put("OutRequest", "OutRequestValue"); StubHandshakeResponder responder = new StubHandshakeResponder(); StubHandshakeObserver observer = new StubHandshakeObserver(); Handshaker shaker = new AsyncOutgoingHandshaker(outRequestProps, responder, socket, observer); shaker.shake(); socket.exchange(); // simulates NIODispatcher setting interest assertTrue(observer.isNoGOK()); assertEquals(544, observer.getCode()); assertFalse(observer.isBadHandshake()); assertFalse(observer.isHandshakeFinished()); assertNull(observer.getShaker()); HandshakeResponse responseTo = responder.getRespondedTo(); assertNull(responseTo); HandshakeResponse read = shaker.getReadHeaders(); assertEquals(1, read.props().size()); assertEquals("ResponseValue", read.props().get("ResponseHeader")); HandshakeResponse written = shaker.getWrittenHeaders(); assertEquals(1, written.props().size()); assertEquals("OutRequestValue", written.props().get("OutRequest")); ByteBuffer buffer = writer.getBuffer(); assertEquals("GNUTELLA CONNECT/0.6\r\nOutRequest: OutRequestValue\r\n\r\n", new String(buffer.array(), 0, buffer.limit())); } public void testDiscoOnBadResponseConnectLine() throws Exception { ReadBufferChannel reader = new ReadBufferChannel( ("HTTP/1.1 345 GET OFF\r\n" + "ResponseHeader: ResponseValue\r\n" + "\r\n").getBytes()); WriteBufferChannel writer = new WriteBufferChannel(2048); MultiplexingSocket socket = new MultiplexingSocket(reader, writer); Properties outRequestProps = new Properties(); outRequestProps.put("OutRequest", "OutRequestValue"); StubHandshakeResponder responder = new StubHandshakeResponder(); StubHandshakeObserver observer = new StubHandshakeObserver(); Handshaker shaker = new AsyncOutgoingHandshaker(outRequestProps, responder, socket, observer); shaker.shake(); socket.exchange(); // simulates NIODispatcher setting interest assertFalse(observer.isNoGOK()); assertTrue(observer.isBadHandshake()); assertFalse(observer.isHandshakeFinished()); assertNull(observer.getShaker()); HandshakeResponse responseTo = responder.getRespondedTo(); assertNull(responseTo); HandshakeResponse read = shaker.getReadHeaders(); assertEquals(0, read.props().size()); HandshakeResponse written = shaker.getWrittenHeaders(); assertEquals(1, written.props().size()); assertEquals("OutRequestValue", written.props().get("OutRequest")); ByteBuffer buffer = writer.getBuffer(); assertEquals("GNUTELLA CONNECT/0.6\r\nOutRequest: OutRequestValue\r\n\r\n", new String(buffer.array(), 0, buffer.limit())); } private static class MultiplexingSocket extends Socket implements NIOMultiplexor { private InterestReadChannel baseReader; private InterestWriteChannel baseWriter; private ReadObserver reader; private WriteObserver writer; MultiplexingSocket(InterestReadChannel baseReader, InterestWriteChannel baseWriter) { this.baseReader = baseReader; this.baseWriter = baseWriter; } public InetAddress getInetAddress() { try { return InetAddress.getByName("127.0.0.1"); } catch(IOException iox) { return null; } } public void setReadObserver(ChannelReadObserver reader) { reader.setReadChannel(baseReader); this.reader = reader; } public void setWriteObserver(ChannelWriter writer) { writer.setWriteChannel(baseWriter); this.writer = writer; } public void exchange() throws IOException { writer.handleWrite(); reader.handleRead(); writer.handleWrite(); } } }