diff options
22 files changed, 602 insertions, 174 deletions
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 <em>a</em> - * followed by all the elements of <em>b</em>. - */ - 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 <em>a</em> + * followed by all the elements of <em>b</em>. + */ + 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<Boolean /*error*/> onConnectFinished = new Signal1<Boolean>(); public final Signal1<Error> onDisconnected = new Signal1<Error>(); - public final Signal1<ByteArray> onDataRead = new Signal1<ByteArray>(); + public final Signal1<SafeByteArray> onDataRead = new Signal1<SafeByteArray>(); 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<ByteArray>() { + xmppLayer.onDataRead.connect(new Slot1<SafeByteArray>() { - public void call(ByteArray p1) { + public void call(SafeByteArray p1) { handleDataRead(p1); } }); - xmppLayer.onWriteData.connect(new Slot1<ByteArray>() { + xmppLayer.onWriteData.connect(new Slot1<SafeByteArray>() { - 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<Element> onElementReceived = new Signal1<Element>(); public final Signal1<SessionError> onSessionFinished = new Signal1<SessionError>(); - public final Signal1<ByteArray> onDataWritten = new Signal1<ByteArray>(); - public final Signal1<ByteArray> onDataRead = new Signal1<ByteArray>(); + public final Signal1<SafeByteArray> onDataWritten = new Signal1<SafeByteArray>(); + public final Signal1<SafeByteArray> onDataRead = new Signal1<SafeByteArray>(); 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<ByteArray>() { + session.onDataRead.connect(new Slot1<SafeByteArray>() { - public void call(ByteArray p1) { + public void call(SafeByteArray p1) { printData('<', p1); } }); - session.onDataWritten.connect(new Slot1<ByteArray>() { + session.onDataWritten.connect(new Slot1<SafeByteArray>() { - 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<ByteArray>() { + connection.onDataRead.connect(new Slot1<SafeByteArray>() { - 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<StreamLayer> layers_ = new ArrayList<StreamLayer>(); -} +}
\ 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<ByteArray>() { + context.onDataForNetwork.connect(new Slot1<SafeByteArray>() { - public void call(ByteArray p1) { + public void call(SafeByteArray p1) { writeDataToChildLayer(p1); } }); - context.onDataForApplication.connect(new Slot1<ByteArray>() { + context.onDataForApplication.connect(new Slot1<SafeByteArray>() { - 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<ProtocolHeader> onStreamStart = new Signal1<ProtocolHeader>(); public final Signal1<Element> onElement = new Signal1<Element>(); - public final Signal1<ByteArray> onWriteData = new Signal1<ByteArray>(); - public final Signal1<ByteArray> onDataRead = new Signal1<ByteArray>(); + public final Signal1<SafeByteArray> onWriteData = new Signal1<SafeByteArray>(); + public final Signal1<SafeByteArray> onDataRead = new Signal1<SafeByteArray>(); 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<ByteArray> onDataForNetwork = new Signal1<ByteArray>(); - public Signal1<ByteArray> onDataForApplication = new Signal1<ByteArray>(); + public Signal1<SafeByteArray> onDataForNetwork = new Signal1<SafeByteArray>(); + public Signal1<SafeByteArray> onDataForApplication = new Signal1<SafeByteArray>(); 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<SafeByteArray> data_ = new Vector<SafeByteArray>(); + + 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<Element>() { + @Override + public void call(Element e1) { + handleElement(e1); + } + }); + physicalStream_.onDataRead(new SafeByteArray("<stream:stream xmlns:stream='http://etherx.jabber.org/streams'><presence/>")); + + assertEquals(1, elementsReceived_); + } + + @Test + public void testReadData_OneIntermediateStream() { + StreamStack testling = new StreamStack(xmppStream_, physicalStream_); + xmppStream_.onElement.connect(new Slot1<Element>() { + @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'><presence/>")); + + assertEquals(1, elementsReceived_); + } + + @Test + public void testReadData_TwoIntermediateStreamStack() { + StreamStack testling = new StreamStack(xmppStream_, physicalStream_); + xmppStream_.onElement.connect(new Slot1<Element>() { + @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'><presence/>")); + + assertEquals(1, elementsReceived_); + } + + @Test + public void testAddLayer_ExistingOnWriteDataSlot() { + StreamStack testling = new StreamStack(xmppStream_, physicalStream_); + xmppStream_.onWriteData.connect(new Slot1<SafeByteArray>() { + @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("<iq>")); + + assertEquals(1, errorReceived_); + } + + @Test + public void testResetParser() { + testling_.onElement.connect(new Slot1<Element>() { + @Override + public void call(Element e1) { + handleElement(e1); + } + }); + testling_.onError.connect(new Slot() { + @Override + public void call() { + handleError(); + } + }); + + testling_.handleDataRead(new SafeByteArray("<stream:stream to=\"example.com\" xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\" >")); + testling_.resetParser(); + testling_.handleDataRead(new SafeByteArray("<stream:stream to=\"example.com\" xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\" >")); + testling_.handleDataRead(new SafeByteArray("<presence/>")); + + assertEquals(1, elementsReceived_); + assertEquals(0, errorReceived_); + } + + @Test + public void testResetParser_FromSlot() { + testling_.onElement.connect(new Slot1<Element>() { + @Override + public void call(Element e1) { + handleElementAndReset(e1); + } + }); + testling_.handleDataRead(new SafeByteArray("<stream:stream to=\"example.com\" xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\" ><presence/>")); + testling_.handleDataRead(new SafeByteArray("<stream:stream to=\"example.com\" xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\" ><presence/>")); + + assertEquals(2, elementsReceived_); + assertEquals(0, errorReceived_); + } + + @Test + public void testWriteHeader() { + ProtocolHeader header = new ProtocolHeader(); + header.setTo("example.com"); + testling_.writeHeader(header); + + assertEquals("<?xml version=\"1.0\"?><stream:stream xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\" to=\"example.com\" version=\"1.0\">", lowLayer_.writtenData); + } + + @Test + public void testWriteElement() { + testling_.writeElement(new Presence()); + + assertEquals("<presence/>", lowLayer_.writtenData); + } + + @Test + public void testWriteFooter() { + testling_.writeFooter(); + + assertEquals("</stream:stream>", lowLayer_.writtenData); + } +}
\ No newline at end of file |