From 673655830b0325d964e67fa835ea83f485e9beeb Mon Sep 17 00:00:00 2001 From: Tarun Gupta Date: Fri, 17 Jul 2015 07:52:32 +0530 Subject: Complete StreamStack and add tests. TLSLayer could not be updated because it requires TLS to be ported first. Updates other classes, only for having compatibility with SafeByteArray because of updates in Stream Stack. License: This patch is BSD-licensed, see Documentation/Licenses/BSD-simplified.txt for details. Test-Information: Tests added for StreamStack and XMPPLayer, which passes. Change-Id: I8707fc1f16d622d2a90f6f39f671b7e7c46aa170 diff --git a/src/com/isode/stroke/base/SafeByteArray.java b/src/com/isode/stroke/base/SafeByteArray.java index 74c1848..ac8960f 100644 --- a/src/com/isode/stroke/base/SafeByteArray.java +++ b/src/com/isode/stroke/base/SafeByteArray.java @@ -22,83 +22,93 @@ public class SafeByteArray extends ByteArray { super(s); } - public SafeByteArray(ByteArray b) { - this.append(b.getData()); - } + public SafeByteArray(ByteArray b) { + this.append(b.getData()); + } - /** - * Creates a new SafeByteArray object containing all - * the elements from two existing ByteArrays (immutable add). - * - * @param a an existing SafeByteArray. Must not be null, but may be empty. - * @param b an existing SafeByteArray. Must not be null, but may be empty. - * @return a new SafeByteArray containing all the elements of a - * followed by all the elements of b. - */ - public static SafeByteArray plus(SafeByteArray a, SafeByteArray b) { - SafeByteArray x = new SafeByteArray().append(a.getData()); - x.append(b); - return x; - } - - /** - * Updates the SafeByteArray by adding all the elements - * of another SafeByteArray to the end of the array (mutable add). - * @param b an existing SafeByteArray. Must not be null, but may be empty - * @return a reference to the updated object - */ - public SafeByteArray append(ByteArray b) { - append(b.getData()); - return this; - } + /** + * Constructs a new ByteArray containing the bytes in a user-supplied + * byte[] + * @param c an array of bytes, which must not be null, but may contain + * zero elements. + */ + public SafeByteArray(byte[] c) { + super(c); + } - /** - * Updates the SafeByteArray by adding all the bytes - * in a byte[] to the end of the array (mutable add). - * - * @param b an array of bytes. Must not be null, but may contain zero - * elements. - * - * @return a reference to the updated object - */ - public SafeByteArray append(byte[] b) { - return append(b, b.length); - } + /** + * Creates a new SafeByteArray object containing all + * the elements from two existing ByteArrays (immutable add). + * + * @param a an existing SafeByteArray. Must not be null, but may be empty. + * @param b an existing SafeByteArray. Must not be null, but may be empty. + * @return a new SafeByteArray containing all the elements of a + * followed by all the elements of b. + */ + public static SafeByteArray plus(SafeByteArray a, SafeByteArray b) { + SafeByteArray x = new SafeByteArray().append(a.getData()); + x.append(b); + return x; + } + + /** + * Updates the SafeByteArray by adding all the elements + * of another SafeByteArray to the end of the array (mutable add). + * @param b an existing SafeByteArray. Must not be null, but may be empty + * @return a reference to the updated object + */ + public SafeByteArray append(ByteArray b) { + append(b.getData()); + return this; + } - /** Mutable add */ - public SafeByteArray append(byte[] b, int len) { - for (int i = 0; i < len; i++) { - append(b[i]); - } - return this; - } + /** + * Updates the SafeByteArray by adding all the bytes + * in a byte[] to the end of the array (mutable add). + * + * @param b an array of bytes. Must not be null, but may contain zero + * elements. + * + * @return a reference to the updated object + */ + public SafeByteArray append(byte[] b) { + return append(b, b.length); + } - /** - * Updates the SafeByteArray by adding a single byte - * value to the end of the array (mutable add). - * @param b a single byte - * @return a reference to the updated object - */ - public SafeByteArray append(byte b) { - dataCopy_ = null; /* Invalidate cache */ - data_.add(Byte.valueOf(b)); - return this; - } + /** Mutable add */ + public SafeByteArray append(byte[] b, int len) { + for (int i = 0; i < len; i++) { + append(b[i]); + } + return this; + } + + /** + * Updates the SafeByteArray by adding a single byte + * value to the end of the array (mutable add). + * @param b a single byte + * @return a reference to the updated object + */ + public SafeByteArray append(byte b) { + dataCopy_ = null; /* Invalidate cache */ + data_.add(Byte.valueOf(b)); + return this; + } - /** - * Updates the SafeByteArray by adding all the bytes - * obtained by UTF-8 encoding the provided String to the end of the array (mutable add). - * @param s a String that must not be null. - * @return a reference to the updated object. - */ - public SafeByteArray append(String s) { - byte[] bytes; - try { - bytes = s.getBytes("UTF-8"); - } catch (UnsupportedEncodingException ex) { - throw new IllegalStateException("JVM has no 'UTF-8' encoding"); - } - append(bytes); - return this; - } + /** + * Updates the SafeByteArray by adding all the bytes + * obtained by UTF-8 encoding the provided String to the end of the array (mutable add). + * @param s a String that must not be null. + * @return a reference to the updated object. + */ + public SafeByteArray append(String s) { + byte[] bytes; + try { + bytes = s.getBytes("UTF-8"); + } catch (UnsupportedEncodingException ex) { + throw new IllegalStateException("JVM has no 'UTF-8' encoding"); + } + append(bytes); + return this; + } } \ No newline at end of file diff --git a/src/com/isode/stroke/compress/ZLibCodecompressor.java b/src/com/isode/stroke/compress/ZLibCodecompressor.java index 3925949..fed1f33 100644 --- a/src/com/isode/stroke/compress/ZLibCodecompressor.java +++ b/src/com/isode/stroke/compress/ZLibCodecompressor.java @@ -9,7 +9,7 @@ */ package com.isode.stroke.compress; -import com.isode.stroke.base.ByteArray; +import com.isode.stroke.base.SafeByteArray; import com.jcraft.jzlib.JZlib; import com.jcraft.jzlib.ZStream; @@ -17,8 +17,8 @@ public abstract class ZLibCodecompressor { protected static final int CHUNK_SIZE = 1024; protected final ZStream stream_ = new ZStream(); - public ByteArray process(ByteArray input) throws ZLibException { - ByteArray output = new ByteArray(); + public SafeByteArray process(SafeByteArray input) throws ZLibException { + SafeByteArray output = new SafeByteArray(); stream_.avail_in = input.getSize(); stream_.next_in = input.getData(); stream_.next_in_index = 0; diff --git a/src/com/isode/stroke/network/Connection.java b/src/com/isode/stroke/network/Connection.java index dbda1b7..b0e4799 100644 --- a/src/com/isode/stroke/network/Connection.java +++ b/src/com/isode/stroke/network/Connection.java @@ -9,7 +9,7 @@ */ package com.isode.stroke.network; -import com.isode.stroke.base.ByteArray; +import com.isode.stroke.base.SafeByteArray; import com.isode.stroke.signals.Signal; import com.isode.stroke.signals.Signal1; @@ -30,11 +30,11 @@ public abstract class Connection { public abstract void disconnect(); - public abstract void write(ByteArray data); + public abstract void write(SafeByteArray data); public abstract HostAddressPort getLocalAddress(); public final Signal1 onConnectFinished = new Signal1(); public final Signal1 onDisconnected = new Signal1(); - public final Signal1 onDataRead = new Signal1(); + public final Signal1 onDataRead = new Signal1(); public final Signal onDataWritten = new Signal(); } diff --git a/src/com/isode/stroke/network/JavaConnection.java b/src/com/isode/stroke/network/JavaConnection.java index 4e7503b..66f068f 100644 --- a/src/com/isode/stroke/network/JavaConnection.java +++ b/src/com/isode/stroke/network/JavaConnection.java @@ -18,6 +18,7 @@ import java.util.Collections; import java.util.List; import com.isode.stroke.base.ByteArray; +import com.isode.stroke.base.SafeByteArray; import com.isode.stroke.eventloop.Event.Callback; import com.isode.stroke.eventloop.EventLoop; import com.isode.stroke.eventloop.EventOwner; @@ -30,16 +31,16 @@ public class JavaConnection extends Connection implements EventOwner { * got closed. */ private static class ReadResult { - public ByteArray dataRead_; + public SafeByteArray dataRead_; public boolean socketClosed_; ReadResult(boolean socketClosed) { - dataRead_ = new ByteArray(); + dataRead_ = new SafeByteArray(); socketClosed_ = socketClosed; } ReadResult(ByteArrayOutputStream byteArrayOutputStream, boolean socketClosed) { - dataRead_ = new ByteArray(byteArrayOutputStream.toByteArray()); + dataRead_ = new SafeByteArray(byteArrayOutputStream.toByteArray()); socketClosed_ = socketClosed; } } @@ -95,7 +96,7 @@ public class JavaConnection extends Connection implements EventOwner { } { /* Handle any reading */ - ByteArray dataRead; + SafeByteArray dataRead; if (readNeeded) { ReadResult rr = doRead(); @@ -299,7 +300,7 @@ public class JavaConnection extends Connection implements EventOwner { } } - private void handleDataRead(final ByteArray data) { + private void handleDataRead(final SafeByteArray data) { if (synchroniseReads_) { selectionKey_.interestOps(0); } @@ -372,7 +373,7 @@ public class JavaConnection extends Connection implements EventOwner { } @Override - public void write(ByteArray data) { + public void write(SafeByteArray data) { worker_.writeBuffer_.add(data.getData()); // Check "isOpen" to Avoid Android crash see // https://code.google.com/p/android/issues/detail?id=80785 diff --git a/src/com/isode/stroke/session/BasicSessionStream.java b/src/com/isode/stroke/session/BasicSessionStream.java index f1e7bf1..4f0e75b 100644 --- a/src/com/isode/stroke/session/BasicSessionStream.java +++ b/src/com/isode/stroke/session/BasicSessionStream.java @@ -10,6 +10,7 @@ package com.isode.stroke.session; import java.util.List; import com.isode.stroke.base.ByteArray; +import com.isode.stroke.base.SafeByteArray; import com.isode.stroke.elements.Element; import com.isode.stroke.elements.ProtocolHeader; import com.isode.stroke.elements.StreamType; @@ -71,15 +72,15 @@ public class BasicSessionStream extends SessionStream { handleXMPPError(); } }); - xmppLayer.onDataRead.connect(new Slot1() { + xmppLayer.onDataRead.connect(new Slot1() { - public void call(ByteArray p1) { + public void call(SafeByteArray p1) { handleDataRead(p1); } }); - xmppLayer.onWriteData.connect(new Slot1() { + xmppLayer.onWriteData.connect(new Slot1() { - public void call(ByteArray p1) { + public void call(SafeByteArray p1) { handleDataWritten(p1); } }); diff --git a/src/com/isode/stroke/session/Session.java b/src/com/isode/stroke/session/Session.java index eb64051..815be02 100644 --- a/src/com/isode/stroke/session/Session.java +++ b/src/com/isode/stroke/session/Session.java @@ -10,6 +10,7 @@ package com.isode.stroke.session; import com.isode.stroke.base.ByteArray; +import com.isode.stroke.base.SafeByteArray; import com.isode.stroke.elements.Element; import com.isode.stroke.elements.ProtocolHeader; import com.isode.stroke.elements.StreamType; @@ -81,8 +82,8 @@ public abstract class Session { } public final Signal1 onElementReceived = new Signal1(); public final Signal1 onSessionFinished = new Signal1(); - public final Signal1 onDataWritten = new Signal1(); - public final Signal1 onDataRead = new Signal1(); + public final Signal1 onDataWritten = new Signal1(); + public final Signal1 onDataRead = new Signal1(); protected void setRemoteJID(JID j) { remoteJID = j; diff --git a/src/com/isode/stroke/session/SessionTracer.java b/src/com/isode/stroke/session/SessionTracer.java index 7db165d..8b878a8 100644 --- a/src/com/isode/stroke/session/SessionTracer.java +++ b/src/com/isode/stroke/session/SessionTracer.java @@ -9,29 +9,29 @@ */ package com.isode.stroke.session; -import com.isode.stroke.base.ByteArray; +import com.isode.stroke.base.SafeByteArray; import com.isode.stroke.signals.Slot1; public class SessionTracer { public SessionTracer(Session session) { this.session = session; - session.onDataRead.connect(new Slot1() { + session.onDataRead.connect(new Slot1() { - public void call(ByteArray p1) { + public void call(SafeByteArray p1) { printData('<', p1); } }); - session.onDataWritten.connect(new Slot1() { + session.onDataWritten.connect(new Slot1() { - public void call(ByteArray p1) { + public void call(SafeByteArray p1) { printData('>', p1); } }); } - private void printData(char direction, ByteArray data) { + private void printData(char direction, SafeByteArray data) { System.err.print("" + direction + direction + " " + session.getLocalJID().toString() + " "); for (int i = 0; i < 72 - session.getLocalJID().toString().length() - session.getRemoteJID().toString().length(); ++i) { System.err.print(direction); diff --git a/src/com/isode/stroke/streamstack/CompressionLayer.java b/src/com/isode/stroke/streamstack/CompressionLayer.java index d08f105..b89b3d2 100644 --- a/src/com/isode/stroke/streamstack/CompressionLayer.java +++ b/src/com/isode/stroke/streamstack/CompressionLayer.java @@ -9,7 +9,7 @@ */ package com.isode.stroke.streamstack; -import com.isode.stroke.base.ByteArray; +import com.isode.stroke.base.SafeByteArray; import com.isode.stroke.compress.ZLibCompressor; import com.isode.stroke.compress.ZLibDecompressor; import com.isode.stroke.compress.ZLibException; @@ -17,7 +17,7 @@ import com.isode.stroke.signals.Signal; public class CompressionLayer extends StreamLayer { - public void writeData(ByteArray data) { + public void writeData(SafeByteArray data) { try { writeDataToChildLayer(compressor_.process(data)); } @@ -26,7 +26,7 @@ public class CompressionLayer extends StreamLayer { } } - public void handleDataRead(ByteArray data) { + public void handleDataRead(SafeByteArray data) { try { writeDataToParentLayer(decompressor_.process(data)); } diff --git a/src/com/isode/stroke/streamstack/ConnectionLayer.java b/src/com/isode/stroke/streamstack/ConnectionLayer.java index 0927a32..d003b52 100644 --- a/src/com/isode/stroke/streamstack/ConnectionLayer.java +++ b/src/com/isode/stroke/streamstack/ConnectionLayer.java @@ -4,7 +4,7 @@ */ package com.isode.stroke.streamstack; -import com.isode.stroke.base.ByteArray; +import com.isode.stroke.base.SafeByteArray; import com.isode.stroke.network.Connection; import com.isode.stroke.signals.Slot1; @@ -12,15 +12,15 @@ public class ConnectionLayer implements LowLayer { public ConnectionLayer(Connection connection) { this.connection = connection; - connection.onDataRead.connect(new Slot1() { + connection.onDataRead.connect(new Slot1() { - public void call(ByteArray p1) { + public void call(SafeByteArray p1) { writeDataToParentLayer(p1); } }); } - public void writeData(ByteArray data) { + public void writeData(SafeByteArray data) { connection.write(data); } @@ -29,11 +29,11 @@ public class ConnectionLayer implements LowLayer { /* Work around multiple inheritance workaround again */ StreamLayer fakeStreamLayer_ = new StreamLayer() { - public void writeData(ByteArray data) { + public void writeData(SafeByteArray data) { connection.write(data); } - public void handleDataRead(ByteArray data) { + public void handleDataRead(SafeByteArray data) { throw new UnsupportedOperationException("Not supported yet."); } }; @@ -46,7 +46,7 @@ public class ConnectionLayer implements LowLayer { fakeStreamLayer_.setParentLayer(parentLayer); } - public void writeDataToParentLayer(ByteArray data) { + public void writeDataToParentLayer(SafeByteArray data) { fakeStreamLayer_.writeDataToParentLayer(data); } } diff --git a/src/com/isode/stroke/streamstack/HighLayer.java b/src/com/isode/stroke/streamstack/HighLayer.java index 1ff36e1..c95e21f 100644 --- a/src/com/isode/stroke/streamstack/HighLayer.java +++ b/src/com/isode/stroke/streamstack/HighLayer.java @@ -9,7 +9,7 @@ */ package com.isode.stroke.streamstack; -import com.isode.stroke.base.ByteArray; +import com.isode.stroke.base.SafeByteArray; /** * Because of the lack of multiple inheritance in Java, this has to be done @@ -18,7 +18,7 @@ import com.isode.stroke.base.ByteArray; */ public interface HighLayer { - void handleDataRead(ByteArray data); + void handleDataRead(SafeByteArray data); /* Should be protected */ @@ -26,6 +26,6 @@ public interface HighLayer { void setChildLayer(LowLayer childLayer); - void writeDataToChildLayer(ByteArray data); + void writeDataToChildLayer(SafeByteArray data); } diff --git a/src/com/isode/stroke/streamstack/LowLayer.java b/src/com/isode/stroke/streamstack/LowLayer.java index dcead38..37b04d4 100644 --- a/src/com/isode/stroke/streamstack/LowLayer.java +++ b/src/com/isode/stroke/streamstack/LowLayer.java @@ -9,7 +9,7 @@ */ package com.isode.stroke.streamstack; -import com.isode.stroke.base.ByteArray; +import com.isode.stroke.base.SafeByteArray; /** * Because of the lack of multiple inheritance in Java, this has to be done @@ -18,7 +18,7 @@ import com.isode.stroke.base.ByteArray; */ public interface LowLayer { - void writeData(ByteArray data); + void writeData(SafeByteArray data); /* Should be protected */ @@ -26,5 +26,5 @@ public interface LowLayer { void setParentLayer(HighLayer parentLayer); - void writeDataToParentLayer(ByteArray data); + void writeDataToParentLayer(SafeByteArray data); } diff --git a/src/com/isode/stroke/streamstack/StreamLayer.java b/src/com/isode/stroke/streamstack/StreamLayer.java index ac9538b..a947400 100644 --- a/src/com/isode/stroke/streamstack/StreamLayer.java +++ b/src/com/isode/stroke/streamstack/StreamLayer.java @@ -9,7 +9,7 @@ package com.isode.stroke.streamstack; -import com.isode.stroke.base.ByteArray; +import com.isode.stroke.base.SafeByteArray; /** * Because of the lack of multiple inheritance in Java, this implements @@ -26,7 +26,7 @@ public abstract class StreamLayer implements LowLayer, HighLayer { this.parentLayer = parentLayer; } - public void writeDataToParentLayer(final ByteArray data) { + public void writeDataToParentLayer(final SafeByteArray data) { assert parentLayer != null; parentLayer.handleDataRead(data); } @@ -39,7 +39,7 @@ public abstract class StreamLayer implements LowLayer, HighLayer { this.childLayer = childLayer; } - public void writeDataToChildLayer(final ByteArray data) { + public void writeDataToChildLayer(final SafeByteArray data) { assert childLayer != null; childLayer.writeData(data); } diff --git a/src/com/isode/stroke/streamstack/StreamStack.java b/src/com/isode/stroke/streamstack/StreamStack.java index 08f986c..96fe2fd 100644 --- a/src/com/isode/stroke/streamstack/StreamStack.java +++ b/src/com/isode/stroke/streamstack/StreamStack.java @@ -49,4 +49,4 @@ public class StreamStack { private XMPPLayer xmppLayer_; private LowLayer physicalLayer_; private List layers_ = new ArrayList(); -} +} \ No newline at end of file diff --git a/src/com/isode/stroke/streamstack/TLSLayer.java b/src/com/isode/stroke/streamstack/TLSLayer.java index 70bcd1a..8244766 100644 --- a/src/com/isode/stroke/streamstack/TLSLayer.java +++ b/src/com/isode/stroke/streamstack/TLSLayer.java @@ -11,7 +11,7 @@ package com.isode.stroke.streamstack; import java.util.List; -import com.isode.stroke.base.ByteArray; +import com.isode.stroke.base.SafeByteArray; import com.isode.stroke.signals.Signal; import com.isode.stroke.signals.Slot1; import com.isode.stroke.tls.Certificate; @@ -24,15 +24,15 @@ public class TLSLayer extends StreamLayer { public TLSLayer(TLSContextFactory factory) { context = factory.createTLSContext(); - context.onDataForNetwork.connect(new Slot1() { + context.onDataForNetwork.connect(new Slot1() { - public void call(ByteArray p1) { + public void call(SafeByteArray p1) { writeDataToChildLayer(p1); } }); - context.onDataForApplication.connect(new Slot1() { + context.onDataForApplication.connect(new Slot1() { - public void call(ByteArray p1) { + public void call(SafeByteArray p1) { writeDataToParentLayer(p1); } }); @@ -44,11 +44,11 @@ public class TLSLayer extends StreamLayer { context.connect(); } - public void writeData(ByteArray data) { + public void writeData(SafeByteArray data) { context.handleDataFromApplication(data); } - public void handleDataRead(ByteArray data) { + public void handleDataRead(SafeByteArray data) { context.handleDataFromNetwork(data); } @@ -72,7 +72,7 @@ public class TLSLayer extends StreamLayer { return context; } - public final Signal onError = new Signal(); + public final Signal onError = new Signal();//needs port public final Signal onConnected = new Signal(); private final TLSContext context; diff --git a/src/com/isode/stroke/streamstack/WhitespacePingLayer.java b/src/com/isode/stroke/streamstack/WhitespacePingLayer.java index 53c360a..3a1805c 100644 --- a/src/com/isode/stroke/streamstack/WhitespacePingLayer.java +++ b/src/com/isode/stroke/streamstack/WhitespacePingLayer.java @@ -9,7 +9,7 @@ */ package com.isode.stroke.streamstack; -import com.isode.stroke.base.ByteArray; +import com.isode.stroke.base.SafeByteArray; import com.isode.stroke.network.Timer; import com.isode.stroke.network.TimerFactory; import com.isode.stroke.signals.Slot; @@ -28,17 +28,17 @@ public class WhitespacePingLayer extends StreamLayer { }); } - public void writeData(ByteArray data) { + public void writeData(SafeByteArray data) { writeDataToChildLayer(data); } - public void handleDataRead(ByteArray data) { + public void handleDataRead(SafeByteArray data) { writeDataToParentLayer(data); } private void handleTimerTick() { timer.stop(); - writeDataToChildLayer(new ByteArray(" ")); + writeDataToChildLayer(new SafeByteArray(" ")); timer.start(); } diff --git a/src/com/isode/stroke/streamstack/XMPPLayer.java b/src/com/isode/stroke/streamstack/XMPPLayer.java index 4e7a265..6d14b9b 100644 --- a/src/com/isode/stroke/streamstack/XMPPLayer.java +++ b/src/com/isode/stroke/streamstack/XMPPLayer.java @@ -4,7 +4,7 @@ */ package com.isode.stroke.streamstack; -import com.isode.stroke.base.ByteArray; +import com.isode.stroke.base.SafeByteArray; import com.isode.stroke.elements.Element; import com.isode.stroke.elements.ProtocolHeader; import com.isode.stroke.elements.StreamType; @@ -25,8 +25,8 @@ import com.isode.stroke.signals.Signal1; public class XMPPLayer implements HighLayer, XMPPParserClient { public final Signal1 onStreamStart = new Signal1(); public final Signal1 onElement = new Signal1(); - public final Signal1 onWriteData = new Signal1(); - public final Signal1 onDataRead = new Signal1(); + public final Signal1 onWriteData = new Signal1(); + public final Signal1 onDataRead = new Signal1(); public final Signal onError = new Signal(); private PayloadParserFactoryCollection payloadParserFactories_; @@ -59,19 +59,19 @@ public class XMPPLayer implements HighLayer, XMPPParserClient { } public void writeHeader(ProtocolHeader header) { - writeDataInternal(new ByteArray(xmppSerializer_.serializeHeader(header))); + writeDataInternal(new SafeByteArray(xmppSerializer_.serializeHeader(header))); } public void writeFooter() { - writeDataInternal(new ByteArray(xmppSerializer_.serializeFooter())); + writeDataInternal(new SafeByteArray(xmppSerializer_.serializeFooter())); } public void writeElement(Element element) { - writeDataInternal(new ByteArray(xmppSerializer_.serializeElement(element))); + writeDataInternal(new SafeByteArray(xmppSerializer_.serializeElement(element))); } public void writeData(String data) { - writeDataInternal(new ByteArray(data)); + writeDataInternal(new SafeByteArray(data)); } public void resetParser() { @@ -87,11 +87,11 @@ public class XMPPLayer implements HighLayer, XMPPParserClient { * Should be protected, but can't because of interface implementation. * @param data */ - public void handleDataRead(ByteArray data) { + public void handleDataRead(SafeByteArray data) { handleDataReadInternal(data); } - protected void writeDataInternal(ByteArray data) { + protected void writeDataInternal(SafeByteArray data) { onWriteData.emit(data); writeDataToChildLayer(data); } @@ -115,16 +115,16 @@ public class XMPPLayer implements HighLayer, XMPPParserClient { /* Multiple-inheritance workarounds */ private StreamLayer fakeStreamLayer_ = new StreamLayer() { - public void writeData(ByteArray data) { + public void writeData(SafeByteArray data) { throw new UnsupportedOperationException("Not supported yet."); } - public void handleDataRead(ByteArray data) { + public void handleDataRead(SafeByteArray data) { handleDataReadInternal(data); } }; - private void handleDataReadInternal(ByteArray data) { + private void handleDataReadInternal(SafeByteArray data) { onDataRead.emit(data); inParser_ = true; if(!xmppParser_.parse(data.toString())) { @@ -146,7 +146,7 @@ public class XMPPLayer implements HighLayer, XMPPParserClient { fakeStreamLayer_.setChildLayer(childLayer); } - public void writeDataToChildLayer(ByteArray data) { + public void writeDataToChildLayer(SafeByteArray data) { fakeStreamLayer_.writeDataToChildLayer(data); } } diff --git a/src/com/isode/stroke/tls/TLSContext.java b/src/com/isode/stroke/tls/TLSContext.java index 738c8b6..3f5e8d7 100644 --- a/src/com/isode/stroke/tls/TLSContext.java +++ b/src/com/isode/stroke/tls/TLSContext.java @@ -12,6 +12,7 @@ package com.isode.stroke.tls; import java.util.List; import com.isode.stroke.base.ByteArray; +import com.isode.stroke.base.SafeByteArray; import com.isode.stroke.signals.Signal; import com.isode.stroke.signals.Signal1; @@ -21,8 +22,8 @@ public abstract class TLSContext { public abstract boolean setClientCertificate(CertificateWithKey cert); - public abstract void handleDataFromNetwork(ByteArray data); - public abstract void handleDataFromApplication(ByteArray data); + public abstract void handleDataFromNetwork(SafeByteArray data); + public abstract void handleDataFromApplication(SafeByteArray data); /** * The peer certificate, as presented by the remote entity @@ -38,8 +39,8 @@ public abstract class TLSContext { public abstract ByteArray getFinishMessage(); - public Signal1 onDataForNetwork = new Signal1(); - public Signal1 onDataForApplication = new Signal1(); + public Signal1 onDataForNetwork = new Signal1(); + public Signal1 onDataForApplication = new Signal1(); public Signal onError = new Signal(); public Signal onConnected = new Signal(); } diff --git a/src/com/isode/stroke/tls/java/JSSEContext.java b/src/com/isode/stroke/tls/java/JSSEContext.java index da8316a..17b7d4d 100644 --- a/src/com/isode/stroke/tls/java/JSSEContext.java +++ b/src/com/isode/stroke/tls/java/JSSEContext.java @@ -45,6 +45,7 @@ import javax.net.ssl.SSLException; import javax.net.ssl.X509ExtendedKeyManager; import com.isode.stroke.base.ByteArray; +import com.isode.stroke.base.SafeByteArray; import com.isode.stroke.tls.CAPICertificate; import com.isode.stroke.tls.Certificate; import com.isode.stroke.tls.CertificateVerificationError; @@ -238,7 +239,7 @@ public class JSSEContext extends TLSContext { int bytesToUnwrap = 0; int lastConsumed = 0; HandshakeStatus handshakeStatus = null; - ByteArray byteArray = null; + SafeByteArray byteArray = null; synchronized(recvMutex) { try { @@ -353,7 +354,7 @@ public class JSSEContext extends TLSContext { byte[] result = new byte[unwrappedReceived.remaining()]; unwrappedReceived.get(result); unwrappedReceived.compact(); - byteArray = new ByteArray(result); + byteArray = new SafeByteArray(result); } } @@ -377,7 +378,7 @@ public class JSSEContext extends TLSContext { private int wrapAndSendData() { int bytesSentToSocket = 0; - ByteArray byteArray = null; + SafeByteArray byteArray = null; SSLEngineResult sslEngineResult = null; Status status = null; HandshakeStatus handshakeStatus = null; @@ -394,7 +395,7 @@ public class JSSEContext extends TLSContext { if (wrappedToSend.hasRemaining()) { byte[] b = new byte[(wrappedToSend.remaining())]; wrappedToSend.get(b); - byteArray = new ByteArray(b); + byteArray = new SafeByteArray(b); } wrappedToSend.compact(); } /* end synchronized */ @@ -480,7 +481,7 @@ public class JSSEContext extends TLSContext { if (wrappedToSend.hasRemaining()) { byte[] b = new byte[(wrappedToSend.remaining())]; wrappedToSend.get(b); - byteArray = new ByteArray(b); + byteArray = new SafeByteArray(b); } wrappedToSend.compact(); break; @@ -917,7 +918,7 @@ public class JSSEContext extends TLSContext { } @Override - public void handleDataFromNetwork(ByteArray data) { + public void handleDataFromNetwork(SafeByteArray data) { if (hasError()) { /* We have previously seen, and reported, an error. Emit again */ onError.emit(); @@ -995,7 +996,7 @@ public class JSSEContext extends TLSContext { } @Override - public void handleDataFromApplication(ByteArray data) { + public void handleDataFromApplication(SafeByteArray data) { if (hasError()) { /* We have previously seen, and reported, an error. Emit again */ onError.emit(); diff --git a/test/com/isode/stroke/compress/ZLibCompressorTest.java b/test/com/isode/stroke/compress/ZLibCompressorTest.java index 5767415..c9d1f69 100644 --- a/test/com/isode/stroke/compress/ZLibCompressorTest.java +++ b/test/com/isode/stroke/compress/ZLibCompressorTest.java @@ -9,7 +9,7 @@ */ package com.isode.stroke.compress; -import com.isode.stroke.base.ByteArray; +import com.isode.stroke.base.SafeByteArray; import com.isode.stroke.stringcodecs.Hexify; import javax.xml.bind.annotation.adapters.HexBinaryAdapter; @@ -27,7 +27,7 @@ public class ZLibCompressorTest { @Test public void testProcess() throws Exception { ZLibCompressor testling = new ZLibCompressor(); - ByteArray result = testling.process(new ByteArray("foo")); + SafeByteArray result = testling.process(new SafeByteArray("foo")); assertEquals("78da4acbcf07000000ffff", Hexify.hexify(result)); } @@ -35,14 +35,14 @@ public class ZLibCompressorTest { @Test public void testProcess_Twice() throws ZLibException { ZLibCompressor testling = new ZLibCompressor(); - testling.process(new ByteArray("foo")); - ByteArray result = testling.process(new ByteArray("bar")); + testling.process(new SafeByteArray("foo")); + SafeByteArray result = testling.process(new SafeByteArray("bar")); assertEquals("4a4a2c02000000ffff", Hexify.hexify(result)); } - public static ByteArray unhex(String string) { + public static SafeByteArray unhex(String string) { HexBinaryAdapter adaptor = new HexBinaryAdapter(); - return new ByteArray(adaptor.unmarshal(string)); + return new SafeByteArray(adaptor.unmarshal(string)); } } diff --git a/test/com/isode/stroke/compress/ZLibDecompressorTest.java b/test/com/isode/stroke/compress/ZLibDecompressorTest.java index f4f5e06..d691363 100644 --- a/test/com/isode/stroke/compress/ZLibDecompressorTest.java +++ b/test/com/isode/stroke/compress/ZLibDecompressorTest.java @@ -9,7 +9,7 @@ */ package com.isode.stroke.compress; -import com.isode.stroke.base.ByteArray; +import com.isode.stroke.base.SafeByteArray; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -24,48 +24,48 @@ public class ZLibDecompressorTest { @Test public void testProcess() throws ZLibException { ZLibDecompressor testling = new ZLibDecompressor(); - ByteArray result = testling.process(ZLibCompressorTest.unhex("78da4acbcf07000000ffff")); + SafeByteArray result = testling.process(ZLibCompressorTest.unhex("78da4acbcf07000000ffff")); - assertEquals(new ByteArray("foo"), result); + assertEquals(new SafeByteArray("foo"), result); } @Test public void testProcess_Twice() throws ZLibException { ZLibDecompressor testling = new ZLibDecompressor(); testling.process(ZLibCompressorTest.unhex("78da4acbcf07000000ffff")); - ByteArray result = testling.process(ZLibCompressorTest.unhex("4a4a2c02000000ffff")); + SafeByteArray result = testling.process(ZLibCompressorTest.unhex("4a4a2c02000000ffff")); - assertEquals(new ByteArray("bar"), result); + assertEquals(new SafeByteArray("bar"), result); } @Test(expected = ZLibException.class) public void testProcess_Invalid() throws ZLibException { ZLibDecompressor testling = new ZLibDecompressor(); - testling.process(new ByteArray("invalid")); + testling.process(new SafeByteArray("invalid")); } @Test public void testProcess_Huge() throws ZLibException { - ByteArray data = new ByteArray(); + SafeByteArray data = new SafeByteArray(); for (int i = 0; i < 2048; ++i) { data.append((byte) i); } - ByteArray original = new ByteArray(data); - ByteArray compressed = new ZLibCompressor().process(original); - ByteArray decompressed = new ZLibDecompressor().process(compressed); + SafeByteArray original = new SafeByteArray(data); + SafeByteArray compressed = new ZLibCompressor().process(original); + SafeByteArray decompressed = new ZLibDecompressor().process(compressed); assertEquals(original, decompressed); } @Test public void testProcess_ChunkSize() throws ZLibException { - ByteArray data = new ByteArray(); + SafeByteArray data = new SafeByteArray(); for (int i = 0; i < 1024; ++i) { data.append((byte) i); } - ByteArray original = new ByteArray(data); - ByteArray compressed = new ZLibCompressor().process(original); - ByteArray decompressed = new ZLibDecompressor().process(compressed); + SafeByteArray original = new SafeByteArray(data); + SafeByteArray compressed = new ZLibCompressor().process(original); + SafeByteArray decompressed = new ZLibDecompressor().process(compressed); assertEquals(original, decompressed); } diff --git a/test/com/isode/stroke/streamstack/StreamStackTest.java b/test/com/isode/stroke/streamstack/StreamStackTest.java new file mode 100644 index 0000000..b868a59 --- /dev/null +++ b/test/com/isode/stroke/streamstack/StreamStackTest.java @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2010-2014 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ +/* + * Copyright (c) 2015 Tarun Gupta. + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +package com.isode.stroke.streamstack; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import org.junit.Test; +import org.junit.Before; +import com.isode.stroke.base.SafeByteArray; +import com.isode.stroke.streamstack.StreamStack; +import com.isode.stroke.streamstack.LowLayer; +import com.isode.stroke.streamstack.XMPPLayer; +import com.isode.stroke.streamstack.StreamLayer; +import com.isode.stroke.parser.PlatformXMLParserFactory; +import com.isode.stroke.parser.payloadparsers.FullPayloadParserFactoryCollection; +import com.isode.stroke.serializer.payloadserializers.FullPayloadSerializerCollection; +import com.isode.stroke.elements.Element; +import com.isode.stroke.elements.StreamType; +import com.isode.stroke.signals.Slot1; +import java.util.Vector; + +public class StreamStackTest { + + private class MyStreamLayer extends StreamLayer { + + public MyStreamLayer(final String prepend) { + this.prepend_ = prepend; + } + + public void writeData(final SafeByteArray data) { + writeDataToChildLayer(new SafeByteArray(prepend_).append(data)); + } + + public void handleDataRead(final SafeByteArray data) { + writeDataToParentLayer(new SafeByteArray(prepend_).append(data)); + } + + private String prepend_ = ""; + }; + + /* Multiple-inheritance workarounds */ + + private StreamLayer fakeStreamLayer_ = new StreamLayer() { + public void writeData(SafeByteArray data) { + throw new UnsupportedOperationException("Not supported yet."); + } + + public void handleDataRead(SafeByteArray data) { + writeDataToParentLayer(data); + } + }; + + private class TestLowLayer implements LowLayer { + + public Vector data_ = new Vector(); + + public TestLowLayer() { + + } + + public void writeData(final SafeByteArray data) { + data_.add(data); + } + + public void onDataRead(SafeByteArray data) { + writeDataToParentLayer(data); + } + + public HighLayer getParentLayer() { + return fakeStreamLayer_.getParentLayer(); + } + + public void setParentLayer(HighLayer highLayer) { + fakeStreamLayer_.setParentLayer(highLayer); + } + + public void writeDataToParentLayer(SafeByteArray data) { + fakeStreamLayer_.writeDataToParentLayer(data); + } + }; + + private FullPayloadParserFactoryCollection parserFactories_ = new FullPayloadParserFactoryCollection(); + private FullPayloadSerializerCollection serializers_ = new FullPayloadSerializerCollection(); + private TestLowLayer physicalStream_; + private XMPPLayer xmppStream_; + private int elementsReceived_; + private int dataWriteReceived_; + + @Before + public void setUp() { + physicalStream_ = new TestLowLayer(); + xmppStream_ = new XMPPLayer(parserFactories_, serializers_, StreamType.ClientStreamType); + elementsReceived_ = 0; + dataWriteReceived_ = 0; + } + + public void handleElement(Element element) { + ++elementsReceived_; + } + + public void handleWriteData(final SafeByteArray SafeByteArray) { + ++dataWriteReceived_; + } + + @Test + public void testWriteData_NoIntermediateStreamStack() { + StreamStack testling = new StreamStack(xmppStream_, physicalStream_); + + xmppStream_.writeData("foo"); + + assertEquals(1, physicalStream_.data_.size()); + assertEquals(new SafeByteArray("foo"), physicalStream_.data_.get(0)); + } + + @Test + public void testWriteData_OneIntermediateStream() { + StreamStack testling = new StreamStack(xmppStream_, physicalStream_); + MyStreamLayer xStream = new MyStreamLayer("X"); + testling.addLayer(xStream); + + xmppStream_.writeData("foo"); + + assertEquals(1, physicalStream_.data_.size()); + assertEquals(new SafeByteArray("Xfoo"), physicalStream_.data_.get(0)); + } + + @Test + public void testWriteData_TwoIntermediateStreamStack() { + StreamStack testling = new StreamStack(xmppStream_, physicalStream_); + MyStreamLayer xStream = new MyStreamLayer("X"); + MyStreamLayer yStream = new MyStreamLayer("Y"); + testling.addLayer(xStream); + testling.addLayer(yStream); + + xmppStream_.writeData("foo"); + + assertEquals(1, physicalStream_.data_.size()); + assertEquals(new SafeByteArray("XYfoo"), physicalStream_.data_.get(0)); + } + + @Test + public void testReadData_NoIntermediateStreamStack() { + StreamStack testling = new StreamStack(xmppStream_, physicalStream_); + xmppStream_.onElement.connect(new Slot1() { + @Override + public void call(Element e1) { + handleElement(e1); + } + }); + physicalStream_.onDataRead(new SafeByteArray("")); + + assertEquals(1, elementsReceived_); + } + + @Test + public void testReadData_OneIntermediateStream() { + StreamStack testling = new StreamStack(xmppStream_, physicalStream_); + xmppStream_.onElement.connect(new Slot1() { + @Override + public void call(Element e1) { + handleElement(e1); + } + }); + MyStreamLayer xStream = new MyStreamLayer("<"); + testling.addLayer(xStream); + + physicalStream_.onDataRead(new SafeByteArray("stream:stream xmlns:stream='http://etherx.jabber.org/streams'>")); + + assertEquals(1, elementsReceived_); + } + + @Test + public void testReadData_TwoIntermediateStreamStack() { + StreamStack testling = new StreamStack(xmppStream_, physicalStream_); + xmppStream_.onElement.connect(new Slot1() { + @Override + public void call(Element e1) { + handleElement(e1); + } + }); + MyStreamLayer xStream = new MyStreamLayer("s"); + MyStreamLayer yStream = new MyStreamLayer("<"); + testling.addLayer(xStream); + testling.addLayer(yStream); + + physicalStream_.onDataRead(new SafeByteArray("tream:stream xmlns:stream='http://etherx.jabber.org/streams'>")); + + assertEquals(1, elementsReceived_); + } + + @Test + public void testAddLayer_ExistingOnWriteDataSlot() { + StreamStack testling = new StreamStack(xmppStream_, physicalStream_); + xmppStream_.onWriteData.connect(new Slot1() { + @Override + public void call(SafeByteArray b1) { + handleWriteData(b1); + } + }); + MyStreamLayer xStream = new MyStreamLayer("X"); + testling.addLayer(xStream); + + xmppStream_.writeData("foo"); + + assertEquals(1, dataWriteReceived_); + } +} \ No newline at end of file diff --git a/test/com/isode/stroke/streamstack/XMPPLayerTest.java b/test/com/isode/stroke/streamstack/XMPPLayerTest.java new file mode 100644 index 0000000..1043291 --- /dev/null +++ b/test/com/isode/stroke/streamstack/XMPPLayerTest.java @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2010-2014 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ +/* + * Copyright (c) 2015 Tarun Gupta. + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +package com.isode.stroke.streamstack; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import org.junit.Test; +import org.junit.Before; +import com.isode.stroke.base.SafeByteArray; +import com.isode.stroke.streamstack.XMPPLayer; +import com.isode.stroke.streamstack.StreamStack; +import com.isode.stroke.streamstack.LowLayer; +import com.isode.stroke.streamstack.XMPPLayer; +import com.isode.stroke.streamstack.StreamLayer; +import com.isode.stroke.parser.PlatformXMLParserFactory; +import com.isode.stroke.parser.payloadparsers.FullPayloadParserFactoryCollection; +import com.isode.stroke.serializer.payloadserializers.FullPayloadSerializerCollection; +import com.isode.stroke.parser.PayloadParserFactoryCollection; +import com.isode.stroke.serializer.PayloadSerializerCollection; +import com.isode.stroke.elements.ProtocolHeader; +import com.isode.stroke.elements.Element; +import com.isode.stroke.elements.StreamType; +import com.isode.stroke.elements.Presence; +import com.isode.stroke.signals.Slot1; +import com.isode.stroke.signals.Slot; +import java.util.Vector; + +public class XMPPLayerTest { + + private class XMPPLayerExposed extends XMPPLayer { + + public XMPPLayerExposed(PayloadParserFactoryCollection payloadParserFactories, PayloadSerializerCollection payloadSerializers, StreamType streamType) { + super(payloadParserFactories, payloadSerializers, streamType); + } + + //using XMPPLayer::handleDataRead; + //using HighLayer::setChildLayer; + }; + + /* Multiple-inheritance workarounds */ + + private StreamLayer fakeStreamLayer_ = new StreamLayer() { + public void writeData(SafeByteArray data) { + throw new UnsupportedOperationException("Not supported yet."); + } + + public void handleDataRead(SafeByteArray data) { + writeDataToParentLayer(data); + } + }; + + private class DummyLowLayer implements LowLayer { + + public String writtenData = ""; + + public DummyLowLayer() { + + } + + public void writeData(final SafeByteArray data) { + writtenData += data.toString(); + } + + public HighLayer getParentLayer() { + return fakeStreamLayer_.getParentLayer(); + } + + public void setParentLayer(HighLayer highLayer) { + fakeStreamLayer_.setParentLayer(highLayer); + } + + public void writeDataToParentLayer(SafeByteArray data) { + fakeStreamLayer_.writeDataToParentLayer(data); + } + }; + + private FullPayloadParserFactoryCollection parserFactories_ = new FullPayloadParserFactoryCollection(); + private FullPayloadSerializerCollection serializers_ = new FullPayloadSerializerCollection(); + private DummyLowLayer lowLayer_; + private XMPPLayerExposed testling_; + private PlatformXMLParserFactory xmlParserFactory_; + private int elementsReceived_; + private int errorReceived_; + + @Before + public void setUp() { + lowLayer_ = new DummyLowLayer(); + testling_ = new XMPPLayerExposed(parserFactories_, serializers_, StreamType.ClientStreamType); + testling_.setChildLayer(lowLayer_); + elementsReceived_ = 0; + errorReceived_ = 0; + } + + public void handleElement(Element element) { + ++elementsReceived_; + } + + public void handleElementAndReset(Element element) { + ++elementsReceived_; + testling_.resetParser(); + } + + public void handleError() { + ++errorReceived_; + } + + @Test + public void testParseData_Error() { + testling_.onError.connect(new Slot() { + @Override + public void call() { + handleError(); + } + }); + + testling_.handleDataRead(new SafeByteArray("")); + + assertEquals(1, errorReceived_); + } + + @Test + public void testResetParser() { + testling_.onElement.connect(new Slot1() { + @Override + public void call(Element e1) { + handleElement(e1); + } + }); + testling_.onError.connect(new Slot() { + @Override + public void call() { + handleError(); + } + }); + + testling_.handleDataRead(new SafeByteArray("")); + testling_.resetParser(); + testling_.handleDataRead(new SafeByteArray("")); + testling_.handleDataRead(new SafeByteArray("")); + + assertEquals(1, elementsReceived_); + assertEquals(0, errorReceived_); + } + + @Test + public void testResetParser_FromSlot() { + testling_.onElement.connect(new Slot1() { + @Override + public void call(Element e1) { + handleElementAndReset(e1); + } + }); + testling_.handleDataRead(new SafeByteArray("")); + testling_.handleDataRead(new SafeByteArray("")); + + assertEquals(2, elementsReceived_); + assertEquals(0, errorReceived_); + } + + @Test + public void testWriteHeader() { + ProtocolHeader header = new ProtocolHeader(); + header.setTo("example.com"); + testling_.writeHeader(header); + + assertEquals("", lowLayer_.writtenData); + } + + @Test + public void testWriteElement() { + testling_.writeElement(new Presence()); + + assertEquals("", lowLayer_.writtenData); + } + + @Test + public void testWriteFooter() { + testling_.writeFooter(); + + assertEquals("", lowLayer_.writtenData); + } +} \ No newline at end of file -- cgit v0.10.2-6-g49f6