You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by de...@apache.org on 2013/12/23 10:13:00 UTC
[06/22] CLOUDSTACK-5344: Update to allow rdp console to access
hyper-v vm virtual framebuffer.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4f3611f9/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/ByteBuffer.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/ByteBuffer.java b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/ByteBuffer.java
old mode 100644
new mode 100755
index 832c731..969f747
--- a/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/ByteBuffer.java
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/ByteBuffer.java
@@ -19,808 +19,1103 @@ package streamer;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
/**
* This class represents a slice in a buffer.
*/
public class ByteBuffer {
- public static final String SEQUENCE_NUMBER = "seq";
-
- public byte data[];
- public int offset = 0;
- public int length = 0;
- public int cursor = 0;
-
- private int refCount = 1;
- private ByteBuffer parentByteBuffer = null;
-
- private Order order;
-
- /**
- * Create buffer of size no less than length. Buffer can be a bit larger than
- * length. Offset also can be set to non-zero value to leave some place for
- * future headers.
- */
- public ByteBuffer(int minLength) {
- // Get buffer of acceptable size from buffer pool
- this.data = BufferPool.allocateNewBuffer(minLength);
- this.offset = 0;
- this.length = minLength;
- }
-
- public ByteBuffer(byte data[]) {
- if (data == null)
- throw new NullPointerException("Data must be non-null.");
-
- this.data = data;
- this.offset = 0;
- this.length = data.length;
- }
-
- public ByteBuffer(byte[] data, int offset, int length) {
- if (data == null)
- throw new NullPointerException("Data must be non-null.");
-
- this.data = data;
- this.offset = offset;
- this.length = length;
- }
-
- /**
- * Create byte buffer of requested size with some space reserved for future
- * headers.
- */
- public ByteBuffer(int minLength, boolean reserveSpaceForHeader) {
- // Get buffer of acceptable size from buffer pool
- this.data = BufferPool.allocateNewBuffer(128 + minLength);
- this.offset = 128; // 100 bytes should be enough for headers
- this.length = minLength;
- }
-
- /**
- * Create empty buffer with given order only.
- */
- public ByteBuffer(Order order) {
- this.order = order;
- }
-
- public void setOrder(Order order) {
- this.order = order;
- }
-
- public Order getOrder() {
- return order;
- }
-
- @Override
- public String toString() {
- return toString(100);
- }
-
- /**
- * Return string representation of this byte buffer.
- *
- * @param maxLength
- * number of bytes to show in string
- */
- public String toString(int maxLength) {
- return "ByteRange(){offset=" + offset + ", length=" + length + ", cursor=" + cursor + ", data=" + ((data == null) ? "null" : toHexString(maxLength))
- + ((metadata == null || metadata.size() == 0) ? "" : ", metadata=" + metadata) + "}";
- }
-
- /**
- * Return string representation of this byte buffer as hexadecimal numbers,
- * e.g. "[0x01, 0x02]".
- *
- * @param maxLength
- * number of bytes to show in string
- */
- public String toHexString(int maxLength) {
- StringBuilder builder = new StringBuilder(maxLength * 6);
- builder.append('[');
- for (int i = 0; i < maxLength && i < length; i++) {
- if (i > 0)
- builder.append(", ");
- int b = data[offset + i] & 0xff;
- builder.append("0x" + ((b < 16) ? "0" : "") + Integer.toString(b, 16));
- }
- builder.append(']');
- return builder.toString();
- }
-
- /**
- * Return string representation of this byte buffer as hexadecimal numbers,
- * e.g. "01 02".
- *
- * @param maxLength
- * number of bytes to show in string
- */
- public String toPlainHexString(int maxLength) {
- StringBuilder builder = new StringBuilder(maxLength * 3);
- for (int i = 0; i < maxLength && i < length; i++) {
- if (i > 0)
- builder.append(" ");
- int b = data[offset + i] & 0xff;
- builder.append(((b < 16) ? "0" : "") + Integer.toString(b, 16));
- }
- return builder.toString();
- }
-
- public void dump() {
- System.out.println(toString(length));
- }
-
- public void extend(int newLength) {
- if (data.length < newLength)
- Arrays.copyOf(data, newLength);
- }
-
- public void ref() {
- refCount++;
- }
-
- public void unref() {
- refCount--;
-
- if (refCount == 0) {
-
- if (parentByteBuffer != null) {
- parentByteBuffer.unref();
- parentByteBuffer = null;
- } else {
- // Return buffer to buffer pool
- BufferPool.recycleBuffer(data);
- }
-
- data = null;
- }
-
- }
-
- public boolean isSoleOwner() {
- return refCount == 1 && (parentByteBuffer == null);
- }
-
- /**
- * Create shared lightweight copy of part of this buffer.
- */
- public ByteBuffer slice(int offset, int length, boolean copyMetadata) {
- ref();
-
- if (this.length < (offset + length))
- throw new RuntimeException("Length of region is larger that length of this buffer. Buffer length: " + this.length + ", offset: " + offset
- + ", new region length: " + length + ".");
-
- ByteBuffer slice = new ByteBuffer(data, this.offset + offset, length);
-
- if (copyMetadata && this.metadata != null)
- slice.metadata = new HashMap<String, Object>(metadata);
-
- return slice;
- }
-
- private Map<String, Object> metadata = null;
-
- public Object putMetadata(String key, Object value) {
- if (metadata == null)
- metadata = new HashMap<String, Object>();
- return metadata.put(key, value);
- }
-
- public Object getMetadata(String key) {
- return (metadata != null) ? metadata.get(key) : null;
- }
-
- /**
- * Create new buffer, which holds data from both buffers. Expensive operation.
- *
- * @TODO if only one reference to this ByteBuffer exists, then extend this
- * buffer instead of creating new buffer
- * @TODO support list of buffers to avoid expensive joins until absolute
- * necessary
- */
- public ByteBuffer join(ByteBuffer buf) {
- // Extend byte array for new data
- int newLength = length + buf.length;
- byte newData[] = new byte[newLength];
-
- // Copy data from our buffer
- System.arraycopy(data, offset, newData, 0, length);
-
- // Copy data from other buffer
- System.arraycopy(buf.data, buf.offset, newData, length, buf.length);
-
- ByteBuffer newBuf = new ByteBuffer(newData);
-
- // Copy our (older) metadata to new buffer, because handler might store some
- // metadata in buffer, which is pushed back.
- if (metadata != null)
- newBuf.metadata = new HashMap<String, Object>(metadata);
-
- return newBuf;
- }
-
- /**
- * Copy used portion of buffer to new byte array. Expensive operation.
- */
- public byte[] toByteArray() {
- return Arrays.copyOfRange(data, offset, offset + length);
- }
-
- public short[] toShortArray() {
- if (length % 2 != 0)
- throw new ArrayIndexOutOfBoundsException("Length of byte array must be dividable by 2 without remainder. Array length: " + length + ", remainder: "
- + (length % 2) + ".");
-
- short[] buf = new short[length / 2];
-
- for (int i = 0, j = offset; i < buf.length; i++, j += 2) {
- buf[i] = (short) ((data[j + 0] & 0xFF) | ((data[j + 1] & 0xFF) << 8));
- }
- return buf;
- }
-
- /**
- * Return array of int's in little endian order.
- */
- public int[] toIntLEArray() {
- if (length % 4 != 0)
- throw new ArrayIndexOutOfBoundsException("Length of byte array must be dividable by 4 without remainder. Array length: " + length + ", remainder: "
- + (length % 4) + ".");
-
- int[] buf = new int[length / 4];
-
- for (int i = 0, j = offset; i < buf.length; i++, j += 4) {
- buf[i] = (data[j + 0] & 0xFF) | ((data[j + 1] & 0xFF) << 8) | ((data[j + 2] & 0xFF) << 16) | ((data[j + 3] & 0xFF) << 24);
- }
- return buf;
- }
-
- /**
- * Return array of int's in little endian order, but use only 3 bytes per int (3RGB).
- */
- public int[] toInt3LEArray() {
- if (length % 3 != 0)
- throw new ArrayIndexOutOfBoundsException("Length of byte array must be dividable by 3 without remainder. Array length: " + length + ", remainder: "
- + (length % 3) + ".");
-
- int[] buf = new int[length / 3];
-
- for (int i = 0, j = offset; i < buf.length; i++, j += 3) {
- buf[i] = (data[j + 0] & 0xFF) | ((data[j + 1] & 0xFF) << 8) | ((data[j + 2] & 0xFF) << 16);
- }
- return buf;
- }
-
- /**
- * Helper method for test cases to convert array of byte arrays to array of
- * byte buffers.
- */
- public static ByteBuffer[] convertByteArraysToByteBuffers(byte[]... bas) {
- ByteBuffer bufs[] = new ByteBuffer[bas.length];
-
- int i = 0;
- for (byte[] ba : bas) {
- bufs[i++] = new ByteBuffer(ba);
- }
- return bufs;
- }
-
- /**
- * Read signed int in network order. Cursor is advanced by 4.
- */
- public int readSignedInt() {
- if (cursor + 4 > length)
- throw new ArrayIndexOutOfBoundsException("Cannot read 4 bytes from this buffer: " + this + ".");
-
- int result = (((data[offset + cursor] & 0xff) << 24) + ((data[offset + cursor + 1] & 0xff) << 16) + ((data[offset + cursor + 2] & 0xff) << 8) + (data[offset
- + cursor + 3] & 0xff));
- cursor += 4;
- return result;
- }
-
- /**
- * Read signed int in little endian order. Cursor is advanced by 4.
- */
- public int readSignedIntLE() {
- if (cursor + 4 > length)
- throw new ArrayIndexOutOfBoundsException("Cannot read 4 bytes from this buffer: " + this + ".");
-
- int result = (((data[offset + cursor + 3] & 0xff) << 24) + ((data[offset + cursor + 2] & 0xff) << 16) + ((data[offset + cursor + 1] & 0xff) << 8) + (data[offset
- + cursor] & 0xff));
- cursor += 4;
- return result;
- }
-
- /**
- * Read unsigned int in little endian order. Cursor is advanced by 4.
- */
- public long readUnsignedIntLE() {
- if (cursor + 4 > length)
- throw new ArrayIndexOutOfBoundsException("Cannot read 4 bytes from this buffer: " + this + ".");
-
- long result = (((long) (data[offset + cursor + 3] & 0xff) << 24) + ((long) (data[offset + cursor + 2] & 0xff) << 16)
- + ((long) (data[offset + cursor + 1] & 0xff) << 8) + (long) (data[offset + cursor] & 0xff));
- cursor += 4;
- return result;
- }
-
- /**
- * Read signed int in variable length format. Top most bit of each byte
- * indicates that next byte contains additional bits. Cursor is advanced by
- * 1-5 bytes.
- */
- public int readVariableSignedIntLE() {
- int result = 0;
-
- for (int shift = 0; shift < 32; shift += 7) {
- int b = readUnsignedByte();
- result |= (b & 0x7f) << shift;
- if ((b & 0x80) == 0)
- break;
- }
-
- return result;
- }
-
- /**
- * Read unsigned int in network order in variable length format. Cursor is
- * advanced by 1 to 4 bytes.
- *
- * Two most significant bits of first byte indicates length of field: 0x00 - 1
- * byte, 0x40 - 2 bytes, 0x80 - 3 bytes, 0xc0 - 4 bytes.
- *
- * @see http://msdn.microsoft.com/en-us/library/cc241614.aspx
- */
- public int readEncodedUnsignedInt() {
- int firstByte = readUnsignedByte();
- int result;
- switch (firstByte & 0xc0) {
- default:
- case 0x00:
- result = firstByte & 0x3f;
- break;
- case 0x40:
- result = (firstByte & 0x3f << 8) | readUnsignedByte();
- break;
- case 0x80:
- result = (((firstByte & 0x3f << 8) | readUnsignedByte()) << 8) | readUnsignedByte();
- break;
- case 0xc0:
- result = ((((firstByte & 0x3f << 8) | readUnsignedByte()) << 8) | readUnsignedByte() << 8) | readUnsignedByte();
- break;
- }
-
- return result;
- }
-
- /**
- * Read unsigned byte. Cursor is advanced by 1.
- */
- public int readUnsignedByte() {
- if (cursor + 1 > length)
- throw new ArrayIndexOutOfBoundsException("Cannot read 1 byte from this buffer: " + this + ".");
-
- int b = data[offset + cursor] & 0xff;
- cursor += 1;
- return b;
- }
-
- /**
- * Read signed byte. Cursor is advanced by 1.
- */
- public byte readSignedByte() {
- if (cursor + 1 > length)
- throw new ArrayIndexOutOfBoundsException("Cannot read 1 byte from this buffer: " + this + ".");
-
- byte b = data[offset + cursor];
- cursor += 1;
- return b;
- }
-
- /**
- * Read unsigned short in network order. Cursor is advanced by 2.
- */
- public int readUnsignedShort() {
- if (cursor + 2 > length)
- throw new ArrayIndexOutOfBoundsException("Cannot read 2 bytes from this buffer: " + this + ".");
-
- int result = (((data[offset + cursor] & 0xff) << 8) | (data[offset + cursor + 1] & 0xff));
- cursor += 2;
- return result;
- }
-
- /**
- * Read signed short in little endian order. Cursor is advanced by 2.
- */
- public short readSignedShortLE() {
- if (cursor + 2 > length)
- throw new ArrayIndexOutOfBoundsException("Cannot read 2 bytes from this buffer: " + this + ".");
-
- short result = (short) (((data[offset + cursor + 1] & 0xff) << 8) | (data[offset + cursor] & 0xff));
- cursor += 2;
- return result;
- }
-
- /**
- * Read unsigned short in network order in variable length format. Cursor is
- * advanced by 1 or 2 bytes.
- *
- * Most significant bit of first byte indicates length of field: 0 - 1 byte, 1
- * - 2 bytes.
- */
- public int readVariableUnsignedShort() {
- int firstByte = readUnsignedByte();
-
- int result;
- if ((firstByte & 0x80) == 0)
- result = firstByte & 0x7f;
- else {
- int secondByte = readUnsignedByte();
- result = (((firstByte & 0x7f) << 8) | secondByte);
- }
-
- return result;
- }
-
- /**
- * Read unsigned short in little endian order. Cursor is advanced by 2.
- */
- public int readUnsignedShortLE() {
- if (cursor + 2 > length)
- throw new ArrayIndexOutOfBoundsException("Cannot read 2 bytes from this buffer: " + this + ".");
-
- int result = (((data[offset + cursor + 1] & 0xff) << 8) | (data[offset + cursor] & 0xff));
- cursor += 2;
- return result;
- }
-
- /**
- * Read unsigned short in network order in variable length format. Cursor is
- * advanced by 1 or 2 bytes.
- *
- * Most significant bit of first byte indicates length of field: 0x00 - 1
- * byte, 0x80 - 2 bytes.
- *
- * @see http://msdn.microsoft.com/en-us/library/cc241612.aspx
- */
- public int readEncodedUnsignedShort() {
- int firstByte = readUnsignedByte();
-
- int result;
- if ((firstByte & 0x80) == 0)
- result = firstByte & 0x7f;
- else {
- int secondByte = readUnsignedByte();
- result = (((firstByte & 0x7f) << 8) | secondByte);
- }
-
- return result;
- }
-
- /**
- * Read signed short in network order in variable length format. Cursor is
- * advanced by 1 or 2 bytes.
- *
- * Most significant bit of first byte indicates length of field: 0x00 - 1
- * byte, 0x80 - 2 bytes. Second most significant bit indicates is value
- * positive or negative.
- *
- * @see http://msdn.microsoft.com/en-us/library/cc241613.aspx
- */
- public int readEncodedSignedShort() {
- int firstByte = readUnsignedByte();
-
- int result;
- if ((firstByte & 0x80) == 0)
- result = firstByte & 0x3f;
- else {
- int secondByte = readUnsignedByte();
- result = (((firstByte & 0x3f) << 8) | secondByte);
- }
-
- if ((firstByte & 0x40) > 0)
- return -result;
- else
- return result;
- }
-
- /**
- * Read signed long in little endian order. Cursor is advanced by 8 bytes.
- */
- public long readSignedLongLE() {
- return (((long) readSignedIntLE()) & 0xffFFffFFL) | (((long) readSignedIntLE()) << 32);
- }
-
- /**
- * Read string from buffer. Cursor is advanced by string length.
- */
- public String readString(int length, Charset charset) {
- if (cursor + length > this.length)
- throw new ArrayIndexOutOfBoundsException("Cannot read " + length + " bytes from this buffer: " + this + ".");
-
- String string = new String(data, offset + cursor, length, charset);
- cursor += length;
- return string;
- }
-
- /**
- * Get bytes as lightweight slice. Cursor is advanced by data length.
- */
- public ByteBuffer readBytes(int dataLength) {
- if (cursor + dataLength > length)
- throw new ArrayIndexOutOfBoundsException("Cannot read " + dataLength + " bytes from this buffer: " + this + ".");
-
- ByteBuffer slice = slice(cursor, dataLength, false);
- cursor += dataLength;
- return slice;
- }
-
- /**
- * Cursor is advanced by given number of bytes.
- */
- public void skipBytes(int numOfBytes) {
- if (cursor + numOfBytes > length)
- throw new ArrayIndexOutOfBoundsException("Cannot read " + numOfBytes + " bytes from this buffer: " + this + ".");
-
- cursor += numOfBytes;
- }
-
- /**
- * Write byte. Cursor is advanced by 1.
- */
- public void writeByte(int b) {
- if (cursor + 1 > length)
- throw new ArrayIndexOutOfBoundsException("Cannot write 1 byte to this buffer: " + this + ".");
-
- data[offset + cursor] = (byte) b;
- cursor += 1;
- }
-
- /**
- * Write short in network order. Cursor is advanced by 2.
- */
- public void writeShort(int x) {
- if (cursor + 2 > length)
- throw new ArrayIndexOutOfBoundsException("Cannot write 2 bytes to this buffer: " + this + ".");
-
- data[offset + cursor] = (byte) (x >> 8);
- data[offset + cursor + 1] = (byte) x;
- cursor += 2;
- }
-
- /**
- * Write short in little endian order. Cursor is advanced by 2.
- */
- public void writeShortLE(int x) {
- if (cursor + 2 > length)
- throw new ArrayIndexOutOfBoundsException("Cannot write 2 bytes to this buffer: " + this + ".");
-
- data[offset + cursor + 1] = (byte) (x >> 8);
- data[offset + cursor] = (byte) x;
- cursor += 2;
- }
-
- /**
- * Write int in network order. Cursor is advanced by 4.
- */
- public void writeInt(int i) {
- if (cursor + 4 > length)
- throw new ArrayIndexOutOfBoundsException("Cannot write 4 bytes to this buffer: " + this + ".");
-
- data[offset + cursor] = (byte) (i >> 24);
- data[offset + cursor + 1] = (byte) (i >> 16);
- data[offset + cursor + 2] = (byte) (i >> 8);
- data[offset + cursor + 3] = (byte) i;
- cursor += 4;
- }
-
- public void writeIntLE(int i) {
- if (cursor + 4 > length)
- throw new ArrayIndexOutOfBoundsException("Cannot write 4 bytes to this buffer: " + this + ".");
-
- data[offset + cursor] = (byte) i;
- data[offset + cursor + 1] = (byte) (i >> 8);
- data[offset + cursor + 2] = (byte) (i >> 16);
- data[offset + cursor + 3] = (byte) (i >> 24);
- cursor += 4;
- }
-
- /**
- * Write int in variable length format. Cursor is advanced by number of bytes
- * written (1-5).
- *
- * Topmost bit of each byte is set to 1 to indicate that next byte has data.
- */
- public void writeVariableIntLE(int i) {
- while (i != 0) {
- // Get lower bits of number
- int b = i & 0x7f;
- i >>= 7;
-
- if (i > 0)
- // Set topmost bit of byte to indicate that next byte(s) contains
- // remainder bits
- b |= 0x80;
-
- writeByte(b);
- }
- }
-
- /**
- * Write short in variable length format. Cursor is advanced by number of
- * bytes written (1-2).
- *
- * Topmost bit of first byte is set to 1 to indicate that next byte has data.
- */
- public void writeVariableShort(int length) {
- if (length > 0x7f | length < 0)
- writeShort(length | 0x8000);
- else
- writeByte(length);
- }
-
- /**
- * Prepend given data to this byte buffer.
- */
- public void prepend(ByteBuffer buf) {
- prepend(buf.data, buf.offset, buf.length);
- }
-
- /**
- * Prepend given data to this byte buffer.
- */
- public void prepend(byte[] data) {
- prepend(data, 0, data.length);
- }
-
- /**
- * Prepend given data to this byte buffer.
- */
- public void prepend(byte[] data, int offset, int length) {
- if (!isSoleOwner()) {
- throw new RuntimeException("Create full copy of this byte buffer data for modification. refCount: " + refCount + ", parentByteBuffer: "
- + parentByteBuffer + ".");
- }
-
- // If there is no enough space for header to prepend
- if (!(this.offset >= length)) {
- throw new RuntimeException("Reserve data to have enough space for header.");
- }
-
- // Copy header
- System.arraycopy(data, offset, this.data, this.offset - length, length);
-
- // Extend byte range to include header
- this.offset -= length;
- this.length += length;
- this.cursor += length;
- }
-
- public void writeString(String str, Charset charset) {
- writeBytes(str.getBytes(charset));
- }
-
- /**
- * Write string of fixed size. When string is shorted, empty space is filled
- * with zeros. When string is larger, it is truncated.
- */
- public void writeFixedString(int length, String str, Charset charset) {
- byte[] bytes = str.getBytes(charset);
- writeBytes(bytes, 0, Math.min(bytes.length, length));
-
- for (int i = bytes.length; i < length; i++)
- writeByte(0);
- }
-
- public void writeBytes(ByteBuffer buf) {
- writeBytes(buf.data, buf.offset, buf.length);
- }
-
- public void writeBytes(byte[] bytes) {
- writeBytes(bytes, 0, bytes.length);
- }
-
- public void writeBytes(byte[] bytes, int offset, int length) {
- System.arraycopy(bytes, offset, this.data, this.offset + this.cursor, length);
- cursor += length;
- }
-
- // /**
- // * Write BER encoded definite long variant of the ASN.1 length field.
- // */
- // public void writeBerLength(int value) {
- // int fieldLength;
- // if (value > 0xFFffFF)
- // fieldLength = 4;
- // else if (value > 0xFFff)
- // fieldLength = 3;
- // else if (value > 0xFF)
- // fieldLength = 2;
- // else
- // fieldLength = 1;
- //
- // if (cursor + fieldLength + 1 > length)
- // throw new ArrayIndexOutOfBoundsException("Cannot write " + (fieldLength +
- // 1) + " byte(s) to this buffer: " + this + ".");
- //
- // // Write length of length field itself
- // writeByte(0x80 | fieldLength);
- //
- // switch (fieldLength) {
- // case 4:
- // data[offset + cursor++] = (byte) (value >> 24);
- // case 3:
- // data[offset + cursor++] = (byte) (value >> 16);
- // case 2:
- // data[offset + cursor++] = (byte) (value >> 8);
- // case 1:
- // data[offset + cursor++] = (byte) value;
- // }
- //
- // }
-
- /**
- * Reduce length of buffer to cursor position.
- */
- public void trimAtCursor() {
- length = cursor;
- }
-
- /**
- * Rewind cursor to beginning of buffer.
- */
- public void rewindCursor() {
- cursor = 0;
- }
-
- /**
- * Read RGB color in LE order. Cursor is advanced by 3.
- *
- * @return color as int, with red in lowest octet.
- */
- public int readRGBColor() {
- return readUnsignedByte() | (readUnsignedByte() << 8) | (readUnsignedByte() << 16);
- }
-
- public void assertThatBufferIsFullyRead() {
- if (cursor != length)
- throw new RuntimeException("Data in buffer is not read fully. Buf: " + this + ".");
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
-
- int end = offset + length;
- for (int i = offset; i < end; i++)
- result = 31 * result + data[i];
-
- result = prime * result + length;
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
-
- ByteBuffer other = (ByteBuffer) obj;
- if (length != other.length)
- return false;
-
- for (int i = 0; i < length; i++)
- if (data[offset + i] != other.data[other.offset + i])
- return false;
-
- return true;
- }
+ public static final String SEQUENCE_NUMBER = "seq";
+ public byte data[];
+ public int offset = 0;
+ public int length = 0;
+ public int cursor = 0;
+
+ private int refCount = 1;
+ private ByteBuffer parentByteBuffer = null;
+
+ private Order order;
+
+ /**
+ * Create buffer of size no less than length. Buffer can be a bit larger than
+ * length. Offset also can be set to non-zero value to leave some place for
+ * future headers.
+ */
+ public ByteBuffer(int minLength) {
+ // Get buffer of acceptable size from buffer pool
+ this.data = BufferPool.allocateNewBuffer(minLength);
+ this.offset = 0;
+ this.length = minLength;
+ }
+
+ public ByteBuffer(byte data[]) {
+ if (data == null)
+ throw new NullPointerException("Data must be non-null.");
+
+ this.data = data;
+ this.offset = 0;
+ this.length = data.length;
+ }
+
+ public ByteBuffer(byte[] data, int offset, int length) {
+ if (data == null)
+ throw new NullPointerException("Data must be non-null.");
+
+ this.data = data;
+ this.offset = offset;
+ this.length = length;
+ }
+
+ /**
+ * Create byte buffer of requested size with some space reserved for future
+ * headers.
+ */
+ public ByteBuffer(int minLength, boolean reserveSpaceForHeader) {
+ // Get buffer of acceptable size from buffer pool
+ this.data = BufferPool.allocateNewBuffer(128 + minLength);
+ this.offset = 128; // 100 bytes should be enough for headers
+ this.length = minLength;
+ }
+
+ /**
+ * Create empty buffer with given order only.
+ */
+ public ByteBuffer(Order order) {
+ this.order = order;
+ }
+
+ public void setOrder(Order order) {
+ this.order = order;
+ }
+
+ public Order getOrder() {
+ return order;
+ }
+
+ @Override
+ public String toString() {
+ return toString(length);
+ }
+
+ /**
+ * Return string representation of this byte buffer.
+ *
+ * @param maxLength
+ * number of bytes to show in string
+ */
+ public String toString(int maxLength) {
+ return "ByteRange(){offset=" + offset + ", length=" + length + ", cursor=" + cursor + ", data=" + ((data == null) ? "null" : toHexString(maxLength))
+ + ((metadata == null || metadata.size() == 0) ? "" : ", metadata=" + metadata) + "}";
+ }
+
+ /**
+ * Return string representation of this byte buffer as hexadecimal numbers,
+ * e.g. "[0x01, 0x02]".
+ *
+ * @param maxLength
+ * number of bytes to show in string
+ */
+ public String toHexString(int maxLength) {
+ StringBuilder builder = new StringBuilder(maxLength * 6);
+ builder.append('[');
+ for (int i = 0; i < maxLength && i < length; i++) {
+ if (i > 0)
+ builder.append(", ");
+ int b = data[offset + i] & 0xff;
+ builder.append("0x" + ((b < 16) ? "0" : "") + Integer.toString(b, 16));
+ }
+ builder.append(']');
+ return builder.toString();
+ }
+
+ /**
+ * Return string representation of this byte buffer as hexadecimal numbers,
+ * e.g. "01 02".
+ *
+ * @param maxLength
+ * number of bytes to show in string
+ */
+ public String toPlainHexString(int maxLength) {
+ StringBuilder builder = new StringBuilder(maxLength * 3);
+ for (int i = 0; i < maxLength && i < length; i++) {
+ if (i > 0)
+ builder.append(" ");
+ int b = data[offset + i] & 0xff;
+ builder.append(String.format("%02x", b));
+ }
+ return builder.toString();
+ }
+
+ /**
+ * Return string representation of this byte buffer as dump, e.g.
+ * "0000 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 .................".
+ *
+ * @param maxLength
+ * number of bytes to show in string
+ */
+ public String dump() {
+ StringBuilder builder = new StringBuilder(length * 4);
+ int i = 0;
+ for (; i < length && i < length; i++) {
+ if (i % 16 == 0) {
+ builder.append(String.format("%04x", i));
+ }
+
+ builder.append(' ');
+ int b = data[offset + i] & 0xff;
+ builder.append(String.format("%02x", b));
+
+ if (i % 16 == 15) {
+ builder.append(' ');
+ builder.append(toASCIIString(i - 15, i));
+ builder.append('\n');
+ }
+ }
+ int end = i - 1;
+ if (end % 16 != 15) {
+ int begin = end & ~0xf;
+ for (int j = 0; j < (15 - (end % 16)); j++) {
+ builder.append(" ");
+ }
+ builder.append(' ');
+ builder.append(toASCIIString(begin, end));
+ builder.append('\n');
+ }
+ return builder.toString();
+ }
+
+ private String toASCIIString(int start, int finish) {
+ StringBuffer sb = new StringBuffer(16);
+ for (int i = start; i <= finish; i++) {
+ char ch = (char)data[offset + i];
+ if (ch < ' ' || ch >= 0x7f) {
+ sb.append('.');
+ } else {
+ sb.append(ch);
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Return string representation of this byte buffer as hexadecimal numbers,
+ * e.g. "01 02".
+ */
+ public String toPlainHexString() {
+ return toPlainHexString(length);
+ }
+
+ public void extend(int newLength) {
+ if (data.length < newLength)
+ Arrays.copyOf(data, newLength);
+ }
+
+ public void ref() {
+ refCount++;
+ }
+
+ public void unref() {
+ refCount--;
+
+ if (refCount == 0) {
+
+ if (parentByteBuffer != null) {
+ parentByteBuffer.unref();
+ parentByteBuffer = null;
+ } else {
+ // Return buffer to buffer pool
+ BufferPool.recycleBuffer(data);
+ }
+
+ data = null;
+ }
+
+ }
+
+ public boolean isSoleOwner() {
+ return refCount == 1 && (parentByteBuffer == null);
+ }
+
+ /**
+ * Create shared lightweight copy of part of this buffer.
+ */
+ public ByteBuffer slice(int offset, int length, boolean copyMetadata) {
+ ref();
+
+ if (this.length < (offset + length))
+ throw new RuntimeException("Length of region is larger that length of this buffer. Buffer length: " + this.length + ", offset: " + offset
+ + ", new region length: " + length + ".");
+
+ ByteBuffer slice = new ByteBuffer(data, this.offset + offset, length);
+
+ if (copyMetadata && this.metadata != null)
+ slice.metadata = new HashMap<String, Object>(metadata);
+
+ return slice;
+ }
+
+ private Map<String, Object> metadata = null;
+
+ public Object putMetadata(String key, Object value) {
+ if (metadata == null)
+ metadata = new HashMap<String, Object>();
+ return metadata.put(key, value);
+ }
+
+ public Object getMetadata(String key) {
+ return (metadata != null) ? metadata.get(key) : null;
+ }
+
+ /**
+ * Create new buffer, which holds data from both buffers. Expensive operation.
+ *
+ * @TODO if only one reference to this ByteBuffer exists, then extend this
+ * buffer instead of creating new buffer
+ * @TODO support list of buffers to avoid expensive joins until absolute
+ * necessary
+ */
+ public ByteBuffer join(ByteBuffer buf) {
+ // Extend byte array for new data
+ int newLength = length + buf.length;
+ byte newData[] = new byte[newLength];
+
+ // Copy data from our buffer
+ System.arraycopy(data, offset, newData, 0, length);
+
+ // Copy data from other buffer
+ System.arraycopy(buf.data, buf.offset, newData, length, buf.length);
+
+ ByteBuffer newBuf = new ByteBuffer(newData);
+
+ // Copy our (older) metadata to new buffer, because handler might store some
+ // metadata in buffer, which is pushed back.
+ if (metadata != null)
+ newBuf.metadata = new HashMap<String, Object>(metadata);
+
+ return newBuf;
+ }
+
+ /**
+ * Copy used portion of buffer to new byte array. Expensive operation.
+ */
+ public byte[] toByteArray() {
+ return Arrays.copyOfRange(data, offset, offset + length);
+ }
+
+ public short[] toShortArray() {
+ if (length % 2 != 0)
+ throw new ArrayIndexOutOfBoundsException("Length of byte array must be dividable by 2 without remainder. Array length: " + length + ", remainder: "
+ + (length % 2) + ".");
+
+ short[] buf = new short[length / 2];
+
+ for (int i = 0, j = offset; i < buf.length; i++, j += 2) {
+ buf[i] = (short)((data[j + 0] & 0xFF) | ((data[j + 1] & 0xFF) << 8));
+ }
+ return buf;
+ }
+
+ /**
+ * Return array of int's in little endian order.
+ */
+ public int[] toIntLEArray() {
+ if (length % 4 != 0)
+ throw new ArrayIndexOutOfBoundsException("Length of byte array must be dividable by 4 without remainder. Array length: " + length + ", remainder: "
+ + (length % 4) + ".");
+
+ int[] buf = new int[length / 4];
+
+ for (int i = 0, j = offset; i < buf.length; i++, j += 4) {
+ buf[i] = (data[j + 0] & 0xFF) | ((data[j + 1] & 0xFF) << 8) | ((data[j + 2] & 0xFF) << 16) | ((data[j + 3] & 0xFF) << 24);
+ }
+ return buf;
+ }
+
+ /**
+ * Return array of int's in little endian order, but use only 3 bytes per int
+ * (3RGB).
+ */
+ public int[] toInt3LEArray() {
+ if (length % 3 != 0)
+ throw new ArrayIndexOutOfBoundsException("Length of byte array must be dividable by 3 without remainder. Array length: " + length + ", remainder: "
+ + (length % 3) + ".");
+
+ int[] buf = new int[length / 3];
+
+ for (int i = 0, j = offset; i < buf.length; i++, j += 3) {
+ buf[i] = (data[j + 0] & 0xFF) | ((data[j + 1] & 0xFF) << 8) | ((data[j + 2] & 0xFF) << 16);
+ }
+ return buf;
+ }
+
+ /**
+ * Helper method for test cases to convert array of byte arrays to array of
+ * byte buffers.
+ */
+ public static ByteBuffer[] convertByteArraysToByteBuffers(byte[]... bas) {
+ ByteBuffer bufs[] = new ByteBuffer[bas.length];
+
+ int i = 0;
+ for (byte[] ba : bas) {
+ bufs[i++] = new ByteBuffer(ba);
+ }
+ return bufs;
+ }
+
+ /**
+ * Read signed int in network order. Cursor is advanced by 4.
+ */
+ public int readSignedInt() {
+ if (cursor + 4 > length)
+ throw new ArrayIndexOutOfBoundsException("Cannot read 4 bytes from this buffer: " + this + ".");
+
+ int result = (((data[offset + cursor] & 0xff) << 24) + ((data[offset + cursor + 1] & 0xff) << 16) + ((data[offset + cursor + 2] & 0xff) << 8) + (data[offset
+ + cursor + 3] & 0xff));
+ cursor += 4;
+ return result;
+ }
+
+ /**
+ * Read signed int in little endian order. Cursor is advanced by 4.
+ */
+ public int readSignedIntLE() {
+ if (cursor + 4 > length)
+ throw new ArrayIndexOutOfBoundsException("Cannot read 4 bytes from this buffer: " + this + ".");
+
+ int result = (((data[offset + cursor + 3] & 0xff) << 24) + ((data[offset + cursor + 2] & 0xff) << 16) + ((data[offset + cursor + 1] & 0xff) << 8) + (data[offset
+ + cursor] & 0xff));
+ cursor += 4;
+ return result;
+ }
+
+ /**
+ * Read unsigned int in little endian order. Cursor is advanced by 4.
+ */
+ public long readUnsignedIntLE() {
+ if (cursor + 4 > length)
+ throw new ArrayIndexOutOfBoundsException("Cannot read 4 bytes from this buffer: " + this + ".");
+
+ long result = (((long)(data[offset + cursor + 3] & 0xff) << 24) + ((long)(data[offset + cursor + 2] & 0xff) << 16)
+ + ((long)(data[offset + cursor + 1] & 0xff) << 8) + (long)(data[offset + cursor + 0] & 0xff));
+ cursor += 4;
+ return result;
+ }
+
+ /**
+ * Read unsigned int in network order. Cursor is advanced by 4.
+ */
+ public long readUnsignedInt() {
+ if (cursor + 4 > length)
+ throw new ArrayIndexOutOfBoundsException("Cannot read 4 bytes from this buffer: " + this + ".");
+
+ long result = (((long)(data[offset + cursor + 0] & 0xff) << 24) + ((long)(data[offset + cursor + 1] & 0xff) << 16)
+ + ((long)(data[offset + cursor + 2] & 0xff) << 8) + (long)(data[offset + cursor + 3] & 0xff));
+ cursor += 4;
+ return result;
+ }
+
+ /**
+ * Read signed int in variable length format. Top most bit of each byte
+ * indicates that next byte contains additional bits. Cursor is advanced by
+ * 1-5 bytes.
+ */
+ public int readVariableSignedIntLE() {
+ int result = 0;
+
+ for (int shift = 0; shift < 32; shift += 7) {
+ int b = readUnsignedByte();
+ result |= (b & 0x7f) << shift;
+ if ((b & 0x80) == 0)
+ break;
+ }
+
+ return result;
+ }
+
+ /**
+ * Read unsigned int in network order in variable length format. Cursor is
+ * advanced by 1 to 4 bytes.
+ *
+ * Two most significant bits of first byte indicates length of field: 0x00 - 1
+ * byte, 0x40 - 2 bytes, 0x80 - 3 bytes, 0xc0 - 4 bytes.
+ *
+ * @see http://msdn.microsoft.com/en-us/library/cc241614.aspx
+ */
+ public int readEncodedUnsignedInt() {
+ int firstByte = readUnsignedByte();
+ int result;
+ switch (firstByte & 0xc0) {
+ default:
+ case 0x00:
+ result = firstByte & 0x3f;
+ break;
+ case 0x40:
+ result = (firstByte & 0x3f << 8) | readUnsignedByte();
+ break;
+ case 0x80:
+ result = (((firstByte & 0x3f << 8) | readUnsignedByte()) << 8) | readUnsignedByte();
+ break;
+ case 0xc0:
+ result = ((((firstByte & 0x3f << 8) | readUnsignedByte()) << 8) | readUnsignedByte() << 8) | readUnsignedByte();
+ break;
+ }
+
+ return result;
+ }
+
+ /**
+ * Read unsigned byte. Cursor is advanced by 1.
+ */
+ public int readUnsignedByte() {
+ if (cursor + 1 > length)
+ throw new ArrayIndexOutOfBoundsException("Cannot read 1 byte from this buffer: " + this + ".");
+
+ int b = data[offset + cursor] & 0xff;
+ cursor += 1;
+ return b;
+ }
+
+ /**
+ * Read signed byte. Cursor is advanced by 1.
+ */
+ public byte readSignedByte() {
+ if (cursor + 1 > length)
+ throw new ArrayIndexOutOfBoundsException("Cannot read 1 byte from this buffer: " + this + ".");
+
+ byte b = data[offset + cursor];
+ cursor += 1;
+ return b;
+ }
+
+ /**
+ * Read unsigned short in network order. Cursor is advanced by 2.
+ */
+ public int readUnsignedShort() {
+ if (cursor + 2 > length)
+ throw new ArrayIndexOutOfBoundsException("Cannot read 2 bytes from this buffer: " + this + ".");
+
+ int result = (((data[offset + cursor] & 0xff) << 8) | (data[offset + cursor + 1] & 0xff));
+ cursor += 2;
+ return result;
+ }
+
+ /**
+ * Read signed short in little endian order. Cursor is advanced by 2.
+ */
+ public short readSignedShortLE() {
+ if (cursor + 2 > length)
+ throw new ArrayIndexOutOfBoundsException("Cannot read 2 bytes from this buffer: " + this + ".");
+
+ short result = (short)(((data[offset + cursor + 1] & 0xff) << 8) | (data[offset + cursor] & 0xff));
+ cursor += 2;
+ return result;
+ }
+
+ /**
+ * Read signed short in network order. Cursor is advanced by 2.
+ */
+ public short readSignedShort() {
+ if (cursor + 2 > length)
+ throw new ArrayIndexOutOfBoundsException("Cannot read 2 bytes from this buffer: " + this + ".");
+
+ short result = (short)(((data[offset + cursor + 0] & 0xff) << 8) | (data[offset + cursor + 1] & 0xff));
+ cursor += 2;
+ return result;
+ }
+
+ /**
+ * Read unsigned short in network order in variable length format. Cursor is
+ * advanced by 1 or 2 bytes.
+ *
+ * Most significant bit of first byte indicates length of field: 0 - 1 byte, 1
+ * - 2 bytes.
+ */
+ public int readVariableUnsignedShort() {
+ int firstByte = readUnsignedByte();
+
+ int result;
+ if ((firstByte & 0x80) == 0) {
+ result = firstByte & 0x7f;
+ } else {
+ int secondByte = readUnsignedByte();
+ result = (((firstByte & 0x7f) << 8) | secondByte);
+ }
+
+ return result;
+ }
+
+ /**
+ * Read integer in BER format.
+ *
+ * Most significant bit of first byte indicates type of date in first byte: if
+ * 0, then byte contains length (up to 7f), if 1, then byte contains number of
+ * following bytes with value in network order. Value 0x80 means unlimited
+ * length, which ends with two zero bytes (0x00 0x00) sequence.
+ *
+ * If -1 is returned by this method, then caller must seek two consecutive
+ * zeroes in buffer and consume all that data from buffer, including these two
+ * zeroes, but caller should not parse these two zeroes.
+ *
+ * @return length or -1, for unlimited length
+ */
+ public long readBerLength() {
+ int firstByte = readUnsignedByte();
+
+ long result;
+ if ((firstByte & 0x80) == 0) {
+ result = firstByte & 0x7f;
+ } else {
+ int intLength = firstByte & 0x7f;
+ if (intLength != 0)
+ result = readUnsignedVarInt(intLength);
+ else
+ return -1;
+ }
+
+ return result;
+ }
+
+ /**
+ * Read integer in BER format.
+ *
+ * Most significant bit of first byte indicates type of date in first byte: if
+ * 0, then byte contains length (up to 7f), if 1, then byte contains number of
+ * following bytes with value in network order.
+ */
+ public void writeBerLength(long length) {
+ if (length < 0)
+ throw new RuntimeException("Length cannot be less than zero: " + length + ". Data: " + this + ".");
+
+ if (length < 0x80) {
+ writeByte((int)length);
+ } else {
+ if (length < 0xff) {
+ writeByte(0x81);
+ writeByte((int)length);
+ } else if (length <= 0xffFF) {
+ writeByte(0x82);
+ writeShort((int)length);
+ } else if (length <= 0xffFFff) {
+ writeByte(0x83);
+ writeByte((int)(length >> 16));
+ writeShort((int)length);
+ } else if (length <= 0xffFFffFFL) {
+ writeByte(0x84);
+ writeInt((int)length);
+ } else if (length <= 0xffFFffFFffL) {
+ writeByte(0x85);
+ writeByte((int)(length >> 32));
+ writeInt((int)length);
+ } else if (length <= 0xffFFffFFffFFL) {
+ writeByte(0x86);
+ writeShort((int)(length >> 32));
+ writeInt((int)length);
+ } else if (length <= 0xffFFffFFffFFffL) {
+ writeByte(0x87);
+ writeByte((int)(length >> (32 + 16)));
+ writeShort((int)(length >> 32));
+ writeInt((int)length);
+ } else {
+ writeByte(0x88);
+ writeInt((int)(length >> 32));
+ writeInt((int)length);
+ }
+ }
+
+ }
+
+ /**
+ * Read signed variable length integers in network order.
+ *
+ * @param len
+ * length of integer
+ */
+ public long readSignedVarInt(int len) {
+ long value = 0;
+ switch (len) {
+ case 0:
+ value = 0;
+ break;
+ case 1:
+ value = readSignedByte();
+ break;
+ case 2:
+ value = readSignedShort();
+ break;
+ case 3:
+ value = (readSignedByte() << 16) | readUnsignedShort();
+ break;
+ case 4:
+ value = readSignedInt();
+ break;
+ case 5:
+ value = (readSignedByte() << 32) | readUnsignedInt();
+ break;
+ case 6:
+ value = (readSignedShort() << 32) | readUnsignedInt();
+ break;
+ case 7:
+ value = (readSignedByte() << 32 + 24) | (readUnsignedShort() << 32) | readUnsignedInt();
+ break;
+ case 8:
+ value = readSignedLong();
+ break;
+ default:
+ throw new RuntimeException("Cannot read integers which are more than 8 bytes long. Length: " + len + ". Data: " + this + ".");
+ }
+
+ return value;
+ }
+
+ /**
+ * Read unsigned variable length integers in network order. Values, which are
+ * larger than 0x7FffFFffFFffFFff cannot be parsed by this method.
+ */
+ public long readUnsignedVarInt(int len) {
+ long value = 0;
+ switch (len) {
+ case 0:
+ value = 0;
+ break;
+ case 1:
+ value = readUnsignedByte();
+ break;
+ case 2:
+ value = readUnsignedShort();
+ break;
+ case 3:
+ value = (readUnsignedByte() << 16) | readUnsignedShort();
+ break;
+ case 4:
+ value = readUnsignedInt();
+ break;
+ case 5:
+ value = (readUnsignedByte() << 32) | readUnsignedInt();
+ break;
+ case 6:
+ value = (readUnsignedShort() << 32) | readUnsignedInt();
+ break;
+ case 7:
+ value = (readUnsignedByte() << 32 + 16) | (readUnsignedShort() << 32) | readUnsignedInt();
+ break;
+ case 8:
+ value = readSignedLong();
+ if (value < 0)
+ throw new RuntimeException(
+ "Cannot read 64 bit integers which are larger than 0x7FffFFffFFffFFff, because of lack of unsinged long type in Java. Value: " + value + ". Data: "
+ + this + ".");
+ break;
+ default:
+ throw new RuntimeException("Cannot read integers which are more than 8 bytes long. Length: " + len + ". Data: " + this + ".");
+ }
+
+ return value;
+ }
+
+ /**
+ * Read unsigned short in little endian order. Cursor is advanced by 2.
+ */
+ public int readUnsignedShortLE() {
+ if (cursor + 2 > length)
+ throw new ArrayIndexOutOfBoundsException("Cannot read 2 bytes from this buffer: " + this + ".");
+
+ int result = (((data[offset + cursor + 1] & 0xff) << 8) | (data[offset + cursor] & 0xff));
+ cursor += 2;
+ return result;
+ }
+
+ /**
+ * Read unsigned short in network order in variable length format. Cursor is
+ * advanced by 1 or 2 bytes.
+ *
+ * Most significant bit of first byte indicates length of field: 0x00 - 1
+ * byte, 0x80 - 2 bytes.
+ *
+ * @see http://msdn.microsoft.com/en-us/library/cc241612.aspx
+ */
+ public int readEncodedUnsignedShort() {
+ int firstByte = readUnsignedByte();
+
+ int result;
+ if ((firstByte & 0x80) == 0)
+ result = firstByte & 0x7f;
+ else {
+ int secondByte = readUnsignedByte();
+ result = (((firstByte & 0x7f) << 8) | secondByte);
+ }
+
+ return result;
+ }
+
+ /**
+ * Read signed short in network order in variable length format. Cursor is
+ * advanced by 1 or 2 bytes.
+ *
+ * Most significant bit of first byte indicates length of field: 0x00 - 1
+ * byte, 0x80 - 2 bytes. Second most significant bit indicates is value
+ * positive or negative.
+ *
+ * @see http://msdn.microsoft.com/en-us/library/cc241613.aspx
+ */
+ public int readEncodedSignedShort() {
+ int firstByte = readUnsignedByte();
+
+ int result;
+ if ((firstByte & 0x80) == 0)
+ result = firstByte & 0x3f;
+ else {
+ int secondByte = readUnsignedByte();
+ result = (((firstByte & 0x3f) << 8) | secondByte);
+ }
+
+ if ((firstByte & 0x40) > 0)
+ return -result;
+ else
+ return result;
+ }
+
+ /**
+ * Read signed long in little endian order. Cursor is advanced by 8 bytes.
+ */
+ public long readSignedLongLE() {
+ return (((long)readSignedIntLE()) & 0xffFFffFFL) | (((long)readSignedIntLE()) << 32);
+ }
+
+ /**
+ * Read signed long in network order. Cursor is advanced by 8 bytes.
+ */
+ public long readSignedLong() {
+ return (((long)readSignedInt()) << 32) | (((long)readSignedInt()) & 0xffFFffFFL);
+ }
+
+ /**
+ * Read string from buffer. Cursor is advanced by string length.
+ */
+ public String readString(int length, Charset charset) {
+ if (cursor + length > this.length)
+ throw new ArrayIndexOutOfBoundsException("Cannot read " + length + " bytes from this buffer: " + this + ".");
+
+ String string = new String(data, offset + cursor, length, charset);
+ cursor += length;
+ return string;
+ }
+
+ /**
+ * Read string with '\0' character at end.
+ */
+ public String readVariableString(Charset charset) {
+
+ int start = cursor;
+
+ // Find end of string
+ while (readUnsignedByte() != 0) {
+ }
+
+ String string = new String(data, offset + start, cursor - start - 1, charset);
+
+ return string;
+ }
+
+ /**
+ * Read wide string with wide '\0' character at end.
+ */
+ public String readVariableWideString(Charset charset) {
+
+ int start = cursor;
+
+ // Find end of string
+ while (readUnsignedShortLE() != 0) {
+ }
+
+ String string = new String(data, offset + start, cursor - start - 2, charset);
+
+ return string;
+ }
+
+ /**
+ * Get bytes as lightweight slice. Cursor is advanced by data length.
+ */
+ public ByteBuffer readBytes(int dataLength) {
+ if (cursor + dataLength > length)
+ throw new ArrayIndexOutOfBoundsException("Cannot read " + dataLength + " bytes from this buffer: " + this + ".");
+
+ ByteBuffer slice = slice(cursor, dataLength, false);
+ cursor += dataLength;
+ return slice;
+ }
+
+ /**
+ * Cursor is advanced by given number of bytes.
+ */
+ public void skipBytes(int numOfBytes) {
+ if (cursor + numOfBytes > length)
+ throw new ArrayIndexOutOfBoundsException("Cannot read " + numOfBytes + " bytes from this buffer: " + this + ".");
+
+ cursor += numOfBytes;
+ }
+
+ /**
+ * Write byte. Cursor is advanced by 1.
+ */
+ public void writeByte(int b) {
+ if (cursor + 1 > length)
+ throw new ArrayIndexOutOfBoundsException("Cannot write 1 byte to this buffer: " + this + ".");
+
+ data[offset + cursor] = (byte)b;
+ cursor += 1;
+ }
+
+ /**
+ * Write short in network order. Cursor is advanced by 2.
+ */
+ public void writeShort(int x) {
+ if (cursor + 2 > length)
+ throw new ArrayIndexOutOfBoundsException("Cannot write 2 bytes to this buffer: " + this + ".");
+
+ data[offset + cursor] = (byte)(x >> 8);
+ data[offset + cursor + 1] = (byte)x;
+ cursor += 2;
+ }
+
+ /**
+ * Write short in little endian order. Cursor is advanced by 2.
+ */
+ public void writeShortLE(int x) {
+ if (cursor + 2 > length)
+ throw new ArrayIndexOutOfBoundsException("Cannot write 2 bytes to this buffer: " + this + ".");
+
+ data[offset + cursor + 1] = (byte)(x >> 8);
+ data[offset + cursor] = (byte)x;
+ cursor += 2;
+ }
+
+ /**
+ * Write int in network order. Cursor is advanced by 4.
+ */
+ public void writeInt(int i) {
+ if (cursor + 4 > length)
+ throw new ArrayIndexOutOfBoundsException("Cannot write 4 bytes to this buffer: " + this + ".");
+
+ data[offset + cursor] = (byte)(i >> 24);
+ data[offset + cursor + 1] = (byte)(i >> 16);
+ data[offset + cursor + 2] = (byte)(i >> 8);
+ data[offset + cursor + 3] = (byte)i;
+ cursor += 4;
+ }
+
+ public void writeIntLE(int i) {
+ if (cursor + 4 > length)
+ throw new ArrayIndexOutOfBoundsException("Cannot write 4 bytes to this buffer: " + this + ".");
+
+ data[offset + cursor] = (byte)i;
+ data[offset + cursor + 1] = (byte)(i >> 8);
+ data[offset + cursor + 2] = (byte)(i >> 16);
+ data[offset + cursor + 3] = (byte)(i >> 24);
+ cursor += 4;
+ }
+
+ /**
+ * Write int in variable length format. Cursor is advanced by number of bytes
+ * written (1-5).
+ *
+ * Topmost bit of each byte is set to 1 to indicate that next byte has data.
+ */
+ public void writeVariableIntLE(int i) {
+ while (i != 0) {
+ // Get lower bits of number
+ int b = i & 0x7f;
+ i >>= 7;
+
+ if (i > 0)
+ // Set topmost bit of byte to indicate that next byte(s) contains
+ // remainder bits
+ b |= 0x80;
+
+ writeByte(b);
+ }
+ }
+
+ /**
+ * Write short in variable length format. Cursor is advanced by number of
+ * bytes written (1-2).
+ *
+ * Topmost bit of first byte is set to 1 to indicate that next byte has data.
+ */
+ public void writeVariableShort(int length) {
+ if (length > 0x7f | length < 0)
+ writeShort(length | 0x8000);
+ else
+ writeByte(length);
+ }
+
+ /**
+ * Prepend given data to this byte buffer.
+ */
+ public void prepend(ByteBuffer buf) {
+ prepend(buf.data, buf.offset, buf.length);
+ }
+
+ /**
+ * Prepend given data to this byte buffer.
+ */
+ public void prepend(byte[] data) {
+ prepend(data, 0, data.length);
+ }
+
+ /**
+ * Prepend given data to this byte buffer.
+ */
+ public void prepend(byte[] data, int offset, int length) {
+ if (!isSoleOwner()) {
+ throw new RuntimeException("Create full copy of this byte buffer data for modification. refCount: " + refCount + ", parentByteBuffer: "
+ + parentByteBuffer + ".");
+ }
+
+ // If there is no enough space for header to prepend
+ if (!(this.offset >= length)) {
+ throw new RuntimeException("Reserve data to have enough space for header.");
+ }
+
+ // Copy header
+ System.arraycopy(data, offset, this.data, this.offset - length, length);
+
+ // Extend byte range to include header
+ this.offset -= length;
+ this.length += length;
+ this.cursor += length;
+ }
+
+ /**
+ * Write byte representation of given string, without string terminators (zero
+ * or zeroes at end of string).
+ */
+ public void writeString(String str, Charset charset) {
+ writeBytes(str.getBytes(charset));
+ }
+
+ /**
+ * Write string of fixed size. When string is shorted, empty space is filled
+ * with zeros. When string is larger, it is truncated.
+ */
+ public void writeFixedString(int length, String str, Charset charset) {
+ byte[] bytes = str.getBytes(charset);
+ writeBytes(bytes, 0, Math.min(bytes.length, length));
+
+ for (int i = bytes.length; i < length; i++)
+ writeByte(0);
+ }
+
+ public void writeBytes(ByteBuffer buf) {
+ writeBytes(buf.data, buf.offset, buf.length);
+ }
+
+ public void writeBytes(byte[] bytes) {
+ writeBytes(bytes, 0, bytes.length);
+ }
+
+ public void writeBytes(byte[] bytes, int offset, int length) {
+ System.arraycopy(bytes, offset, this.data, this.offset + this.cursor, length);
+ cursor += length;
+ }
+
+ /**
+ * Reduce length of buffer to cursor position.
+ */
+ public void trimAtCursor() {
+ length = cursor;
+ }
+
+ /**
+ * Rewind cursor to beginning of the buffer.
+ */
+ public void rewindCursor() {
+ cursor = 0;
+ }
+
+ /**
+ * Read RGB color in LE order. Cursor is advanced by 3.
+ *
+ * @return color as int, with red in lowest octet.
+ */
+ public int readRGBColor() {
+ return readUnsignedByte() | (readUnsignedByte() << 8) | (readUnsignedByte() << 16);
+ }
+
+ public void assertThatBufferIsFullyRead() {
+ if (cursor != length)
+ throw new RuntimeException("Data in buffer is not read fully. Buf: " + this + ".");
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+
+ int end = offset + length;
+ for (int i = offset; i < end; i++)
+ result = 31 * result + data[i];
+
+ result = prime * result + length;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+
+ // Does not work in case of anonymous type(s)
+ if (getClass() != obj.getClass())
+ return false;
+
+ ByteBuffer other = (ByteBuffer)obj;
+ if (length != other.length)
+ return false;
+
+ for (int i = 0; i < length; i++)
+ if (data[offset + i] != other.data[other.offset + i])
+ return false;
+
+ return true;
+ }
+
+ /**
+ * Return length of data left after cursor.
+ */
+ public int remainderLength() {
+ if (length >= cursor)
+ return length - cursor;
+ else
+ throw new RuntimeException("Inconsistent state of buffer: cursor is after end of buffer: " + this + ".");
+ }
+
+ public Set<String> getMetadataKeys() {
+ if (metadata != null)
+ return metadata.keySet();
+ else
+ return new HashSet<String>(0);
+ }
+
+ /**
+ * Return unsigned value of byte at given position relative to cursor. Cursor
+ * is not advanced.
+ */
+ public int peekUnsignedByte(int i) {
+ return data[offset + cursor + i] & 0xff;
+ }
+
+ /**
+ * Trim few first bytes.
+ */
+ public void trimHeader(int length) {
+ this.offset += length;
+ this.length -= length;
+ rewindCursor();
+ }
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4f3611f9/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/DataSink.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/DataSink.java b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/DataSink.java
old mode 100644
new mode 100755
index e3de289..becdb36
--- a/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/DataSink.java
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/DataSink.java
@@ -18,7 +18,7 @@ package streamer;
public interface DataSink {
- void sendData(ByteBuffer buf);
+ void sendData(ByteBuffer buf);
- void sendEvent(Event event, Direction direction);
+ void sendEvent(Event event, Direction direction);
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4f3611f9/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/DataSource.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/DataSource.java b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/DataSource.java
old mode 100644
new mode 100755
index 152be2e..40064c5
--- a/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/DataSource.java
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/DataSource.java
@@ -18,43 +18,43 @@ package streamer;
public interface DataSource {
- /**
- * Get data from source.
- *
- * @param block
- * if false, then return immediately when no data is available,
- * otherwise wait for data
- * @return new data or null, when no data is available
- */
- ByteBuffer pull(boolean block);
+ /**
+ * Get data from source.
+ *
+ * @param block
+ * if false, then return immediately when no data is available,
+ * otherwise wait for data
+ * @return new data or null, when no data is available
+ */
+ ByteBuffer pull(boolean block);
- /**
- * Hold data temporary to use at next pull or push.
- *
- * @param buf
- * a data
- */
- void pushBack(ByteBuffer buf);
+ /**
+ * Hold data temporary to use at next pull or push.
+ *
+ * @param buf
+ * a data
+ */
+ void pushBack(ByteBuffer buf);
- /**
- * Hold data temporary to use at next pull. Don't return abything untill given
- * amount of data will be read from source, because data will be pushed back
- * anyway.
- *
- * @param buf
- * a data
- * @param lengthOfFullPacket
- * length of full block of data to read from source
- */
- void pushBack(ByteBuffer buf, int lengthOfFullPacket);
+ /**
+ * Hold data temporary to use at next pull. Don't return abything untill given
+ * amount of data will be read from source, because data will be pushed back
+ * anyway.
+ *
+ * @param buf
+ * a data
+ * @param lengthOfFullPacket
+ * length of full block of data to read from source
+ */
+ void pushBack(ByteBuffer buf, int lengthOfFullPacket);
- /**
- * Send event to pads.
- *
- * @param event
- * a event
- * @param direction
- * pad direction
- */
- void sendEvent(Event event, Direction direction);
+ /**
+ * Send event to pads.
+ *
+ * @param event
+ * a event
+ * @param direction
+ * pad direction
+ */
+ void sendEvent(Event event, Direction direction);
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4f3611f9/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/Direction.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/Direction.java b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/Direction.java
old mode 100644
new mode 100755
index c9dede8..92fc8fd
--- a/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/Direction.java
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/Direction.java
@@ -17,5 +17,5 @@
package streamer;
public enum Direction {
- IN, OUT
+ IN, OUT
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4f3611f9/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/Element.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/Element.java b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/Element.java
old mode 100644
new mode 100755
index c927dea..997ec38
--- a/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/Element.java
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/Element.java
@@ -19,102 +19,102 @@ package streamer;
import java.util.Set;
/**
- * Element is for processing of data. It has one or more contact pads, which can
+ * Element is basic building block for constructing data processing pipes. It has one or more contact pads, which can
* be wired with other elements using links.
*/
public interface Element {
- /**
- * Name of pad for standard input. Should be set in all elements except pure
- * sinks.
- */
- public static final String STDIN = "stdin";
+ /**
+ * Name of pad for standard input. Should be set in all elements except pure
+ * sinks.
+ */
+ public static final String STDIN = "stdin";
- /**
- * Name of pad for standard output. Should be set in all elements except pure
- * sources.
- */
- public static final String STDOUT = "stdout";
+ /**
+ * Name of pad for standard output. Should be set in all elements except pure
+ * sources.
+ */
+ public static final String STDOUT = "stdout";
- /**
- * Get link connected to given pad.
- *
- * @param padName
- * Standard pads are "stdin" and "stdout".
- */
- Link getLink(String padName);
+ /**
+ * Get link connected to given pad.
+ *
+ * @param padName
+ * Standard pads are "stdin" and "stdout".
+ */
+ Link getLink(String padName);
- /**
- * Get pads of this element.
- */
- Set<String> getPads(Direction direction);
+ /**
+ * Get pads of this element.
+ */
+ Set<String> getPads(Direction direction);
- /**
- * Connect link to given pad.
- *
- * @param padName
- * a pad name. Standard pads are "stdin" and "stdout".
- */
- void setLink(String padName, Link link, Direction direction);
+ /**
+ * Connect link to given pad.
+ *
+ * @param padName
+ * a pad name. Standard pads are "stdin" and "stdout".
+ */
+ void setLink(String padName, Link link, Direction direction);
- /**
- * Disconnect link from given pad.
- *
- * @param padName
- * Standard pads are "stdin" and "stdout".
- */
- void dropLink(String padName);
+ /**
+ * Disconnect link from given pad.
+ *
+ * @param padName
+ * Standard pads are "stdin" and "stdout".
+ */
+ void dropLink(String padName);
- /**
- * Pull data from element and handle it. Element should ask one of it input
- * pads for data, handle data and push result to it sink(s), if any.
- *
- * @param block
- * block until data will be available, or do a slight delay at least,
- * when data is not available
- */
- void poll(boolean block);
+ /**
+ * Pull data from element and handle it. Element should ask one of it input
+ * pads for data, handle data and push result to it sink(s), if any.
+ *
+ * @param block
+ * block until data will be available, or do a slight delay at least,
+ * when data is not available
+ */
+ void poll(boolean block);
- /**
- * Handle incoming data.
- *
- * @param buf
- * a data
- * @param link
- * TODO
- */
- void handleData(ByteBuffer buf, Link link);
+ /**
+ * Handle incoming data.
+ *
+ * @param buf
+ * a data
+ * @param link
+ * TODO
+ */
+ void handleData(ByteBuffer buf, Link link);
- /**
- * Handle event.
- *
- * @param event
- * an event
- * @param direction
- * if IN, then send event to input pads, when OUT, then send to
- * output pads
- */
- void handleEvent(Event event, Direction direction);
+ /**
+ * Handle event.
+ *
+ * @param event
+ * an event
+ * @param direction
+ * if IN, then send event to input pads, when OUT, then send to
+ * output pads
+ */
+ void handleEvent(Event event, Direction direction);
- /**
- * Get element ID.
- */
- String getId();
+ /**
+ * Get element ID.
+ */
+ String getId();
- /**
- * Validate element: check is all required pads are connected.
- */
- void validate();
+ /**
+ * Validate element: check is all required pads are connected.
+ */
+ void validate();
- /**
- * Drop link.
- *
- * @param link a link to drop
- */
- void dropLink(Link link);
+ /**
+ * Drop link.
+ *
+ * @param link a link to drop
+ */
+ void dropLink(Link link);
- /**
- * Drop existing link and replace it by new link.
- */
- void replaceLink(Link existingLink, Link newLink);
+ /**
+ * Drop existing link and replace it by new link.
+ */
+ void replaceLink(Link existingLink, Link newLink);
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4f3611f9/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/Event.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/Event.java b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/Event.java
old mode 100644
new mode 100755
index 5e1a389..998274c
--- a/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/Event.java
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/Event.java
@@ -17,17 +17,17 @@
package streamer;
public enum Event {
- STREAM_START,
- STREAM_CLOSE,
-
- /**
- * Upgrade socket to SSL.
- */
- SOCKET_UPGRADE_TO_SSL,
-
- /**
- * Switch links to input mode.
- */
- LINK_SWITCH_TO_PULL_MODE
+ STREAM_START,
+ STREAM_CLOSE,
+
+ /**
+ * Upgrade socket to SSL.
+ */
+ SOCKET_UPGRADE_TO_SSL,
+
+ /**
+ * Switch links to input mode.
+ */
+ LINK_SWITCH_TO_PULL_MODE
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4f3611f9/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/FakeSink.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/FakeSink.java b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/FakeSink.java
deleted file mode 100644
index 65fb29e..0000000
--- a/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/FakeSink.java
+++ /dev/null
@@ -1,69 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package streamer;
-
-public class FakeSink extends BaseElement {
-
- public FakeSink(String id) {
- super(id);
- }
-
- @Override
- public void handleData(ByteBuffer buf, Link link) {
- if (verbose)
- System.out.println("[" + this + "] INFO: Received buf #" + (packetNumber) + " " + buf + ".");
-
- if (buf == null)
- return;
-
- // Use packetNumber variable to count incoming packets
- packetNumber++;
-
- buf.unref();
- }
-
- @Override
- public String toString() {
- return "FakeSink(" + id + ")";
- }
-
- @Override
- public void handleEvent(Event event, Direction direction) {
- if (verbose)
- System.out.println("[" + this + "] INFO: Event received: " + event + ".");
-
- }
-
- /**
- * Example.
- */
- public static void main(String args[]) {
-
- Element sink = new FakeSink("sink") {
- {
- verbose = true;
- }
- };
-
- byte[] data = new byte[] { 1, 2, 3 };
- ByteBuffer buf = new ByteBuffer(data);
- sink.setLink(STDIN, new SyncLink(), Direction.IN);
- sink.getLink(STDIN).sendData(buf);
-
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4f3611f9/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/FakeSource.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/FakeSource.java b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/FakeSource.java
deleted file mode 100644
index 4cf6503..0000000
--- a/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/FakeSource.java
+++ /dev/null
@@ -1,125 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package streamer;
-
-public class FakeSource extends BaseElement {
-
- /**
- * Delay for null packets in poll method when blocking is requested, in
- * milliseconds.
- */
- protected long delay = SyncLink.STANDARD_DELAY_FOR_EMPTY_PACKET;
-
- public FakeSource(String id) {
- super(id);
- }
-
- @Override
- public void poll(boolean block) {
- if (numBuffers > 0 && packetNumber >= numBuffers) {
- // Close stream when limit of packets is reached
- sendEventToAllPads(Event.STREAM_CLOSE, Direction.OUT);
- return;
- }
-
- // Prepare new packet
- ByteBuffer buf = initializeData();
-
- // Push it to output(s)
- pushDataToAllOuts(buf);
-
- // Make slight delay when blocking input was requested (to avoid
- // consuming of 100% in parent loop)
- if (block)
- delay();
-
- }
-
- /**
- * Make slight delay. Should be used when blocking input is requested in pull
- * mode, but null packed was returned by input.
- */
- protected void delay() {
- try {
- Thread.sleep(delay);
- } catch (InterruptedException e) {
- }
- }
-
- /**
- * Initialize data.
- */
- public ByteBuffer initializeData() {
- ByteBuffer buf = new ByteBuffer(incommingBufLength);
-
- // Set first byte of package to it sequance number
- buf.data[buf.offset] = (byte) (packetNumber % 128);
-
- // Initialize rest of bytes with sequential values, which are
- // corresponding with their position in byte buffer
- for (int i = buf.offset + 1; i < buf.length; i++)
- buf.data[i] = (byte) (i % 128);
-
- buf.putMetadata(ByteBuffer.SEQUENCE_NUMBER, packetNumber);
- buf.putMetadata("src", id);
-
- return buf;
- }
-
- @Override
- public String toString() {
- return "FakeSource(" + id + ")";
- }
-
- public static void main(String args[]) {
-
- Element fakeSource = new FakeSource("source 3/10/100") {
- {
- verbose = true;
- this.incommingBufLength = 3;
- this.numBuffers = 10;
- this.delay = 100;
- }
- };
-
- Element fakeSink = new FakeSink("sink") {
- {
- this.verbose = true;
- }
- };
-
- Element fakeSink2 = new FakeSink("sink2") {
- {
- this.verbose = true;
- }
- };
-
- Link link = new SyncLink();
-
- fakeSource.setLink(STDOUT, link, Direction.OUT);
- fakeSink.setLink(STDIN, link, Direction.IN);
-
- Link link2 = new SyncLink();
-
- fakeSource.setLink("out2", link2, Direction.OUT);
- fakeSink2.setLink(STDIN, link2, Direction.IN);
-
- link.run();
-
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4f3611f9/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/InputStreamSource.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/InputStreamSource.java b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/InputStreamSource.java
old mode 100644
new mode 100755
index b05637f..0c8c97d
--- a/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/InputStreamSource.java
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/InputStreamSource.java
@@ -20,175 +20,177 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
+import streamer.debug.FakeSink;
+
/**
* Source element, which reads data from InputStream.
*/
public class InputStreamSource extends BaseElement {
- protected InputStream is;
- protected SocketWrapper socketWrapper;
-
- public InputStreamSource(String id) {
- super(id);
- }
-
- public InputStreamSource(String id, InputStream is) {
- super(id);
- this.is = is;
- }
-
- public InputStreamSource(String id, SocketWrapper socketWrapper) {
- super(id);
- this.socketWrapper = socketWrapper;
- }
-
- @Override
- public void handleEvent(Event event, Direction direction) {
- switch (event) {
- case SOCKET_UPGRADE_TO_SSL:
- socketWrapper.upgradeToSsl();
- break;
- default:
- super.handleEvent(event, direction);
+ protected InputStream is;
+ protected SocketWrapperImpl socketWrapper;
+
+ public InputStreamSource(String id) {
+ super(id);
}
- }
-
- @Override
- public void setLink(String padName, Link link, Direction direction) {
- switch (direction) {
- case OUT:
- super.setLink(padName, link, direction);
-
- if (is == null) {
- // Pause links until data stream will be ready
- link.pause();
- }
- break;
- case IN:
- throw new RuntimeException("Cannot assign link to input pad in source element. Element: " + this + ", pad: " + padName + ", link: " + link + ".");
+
+ public InputStreamSource(String id, InputStream is) {
+ super(id);
+ this.is = is;
}
- }
- public void setInputStream(InputStream is) {
- this.is = is;
+ public InputStreamSource(String id, SocketWrapperImpl socketWrapper) {
+ super(id);
+ this.socketWrapper = socketWrapper;
+ }
- // Resume links
- resumeLinks();
- }
+ @Override
+ public void handleEvent(Event event, Direction direction) {
+ switch (event) {
+ case SOCKET_UPGRADE_TO_SSL:
+ socketWrapper.upgradeToSsl();
+ break;
+ default:
+ super.handleEvent(event, direction);
+ }
+ }
- private void resumeLinks() {
- for (DataSink sink : outputPads.values())
- ((Link) sink).resume();
- }
+ @Override
+ public void setLink(String padName, Link link, Direction direction) {
+ switch (direction) {
+ case OUT:
+ super.setLink(padName, link, direction);
+
+ if (is == null) {
+ // Pause links until data stream will be ready
+ link.pause();
+ }
+ break;
+ case IN:
+ throw new RuntimeException("Cannot assign link to input pad in source element. Element: " + this + ", pad: " + padName + ", link: " + link + ".");
+ }
+ }
- /**
- * Read data from input stream.
- */
- @Override
- public void poll(boolean block) {
- try {
- if (!block && is.available() == 0) {
+ public void setInputStream(InputStream is) {
+ this.is = is;
- if (verbose)
- System.out.println("[" + this + "] INFO: No data in stream is available now, returning.");
+ // Resume links
+ resumeLinks();
+ }
- return;
- }
+ private void resumeLinks() {
+ for (DataSink sink : outputPads.values())
+ ((Link)sink).resume();
+ }
- // Create buffer of recommended size and with default offset
- ByteBuffer buf = new ByteBuffer(incommingBufLength);
+ /**
+ * Read data from input stream.
+ */
+ @Override
+ public void poll(boolean block) {
+ try {
+ if (!block && is.available() == 0) {
- if (verbose)
- System.out.println("[" + this + "] INFO: Reading data from stream.");
+ if (verbose)
+ System.out.println("[" + this + "] INFO: No data in stream is available now, returning.");
- int actualLength = is.read(buf.data, buf.offset, buf.data.length - buf.offset);
+ return;
+ }
- if (actualLength < 0) {
- if (verbose)
- System.out.println("[" + this + "] INFO: End of stream.");
+ // Create buffer of recommended size and with default offset
+ ByteBuffer buf = new ByteBuffer(incommingBufLength);
- buf.unref();
- closeStream();
- sendEventToAllPads(Event.STREAM_CLOSE, Direction.OUT);
- return;
- }
+ if (verbose)
+ System.out.println("[" + this + "] INFO: Reading data from stream.");
- if (actualLength == 0) {
- if (verbose)
- System.out.println("[" + this + "] INFO: Empty buffer is read from stream.");
+ int actualLength = is.read(buf.data, buf.offset, buf.data.length - buf.offset);
+
+ if (actualLength < 0) {
+ if (verbose)
+ System.out.println("[" + this + "] INFO: End of stream.");
+
+ buf.unref();
+ closeStream();
+ sendEventToAllPads(Event.STREAM_CLOSE, Direction.OUT);
+ return;
+ }
- buf.unref();
- return;
- }
+ if (actualLength == 0) {
+ if (verbose)
+ System.out.println("[" + this + "] INFO: Empty buffer is read from stream.");
- buf.length = actualLength;
+ buf.unref();
+ return;
+ }
- if (verbose)
- System.out.println("[" + this + "] INFO: Data read from stream: " + buf + ".");
+ buf.length = actualLength;
- pushDataToAllOuts(buf);
+ if (verbose)
+ System.out.println("[" + this + "] INFO: Data read from stream: " + buf + ".");
- } catch (IOException e) {
- System.err.println("[" + this + "] ERROR: " + e.getMessage());
- closeStream();
+ pushDataToAllOuts(buf);
+
+ } catch (IOException e) {
+ System.err.println("[" + this + "] ERROR: " + e.getMessage());
+ closeStream();
+ }
}
- }
- @Override
- protected void onClose() {
- closeStream();
- }
+ @Override
+ protected void onClose() {
+ closeStream();
+ }
- private void closeStream() {
- if (verbose)
- System.out.println("[" + this + "] INFO: Closing stream.");
+ private void closeStream() {
+ if (verbose)
+ System.out.println("[" + this + "] INFO: Closing stream.");
+
+ try {
+ is.close();
+ } catch (IOException e) {
+ }
+ try {
+ sendEventToAllPads(Event.STREAM_CLOSE, Direction.OUT);
+ } catch (Exception e) {
+ }
+ }
- try {
- is.close();
- } catch (IOException e) {
+ @Override
+ public String toString() {
+ return "InputStreamSource(" + id + ")";
}
- try {
- sendEventToAllPads(Event.STREAM_CLOSE, Direction.OUT);
- } catch (Exception e) {
+
+ /**
+ * Example.
+ */
+ public static void main(String args[]) {
+ InputStream is = new ByteArrayInputStream(new byte[] {1, 2, 3});
+
+ InputStreamSource source = new InputStreamSource("source") {
+ {
+ verbose = true;
+ }
+ };
+ Element fakeSink = new FakeSink("sink") {
+ {
+ verbose = true;
+ }
+ };
+
+ Link link = new SyncLink() {
+ {
+ verbose = true;
+ }
+ };
+
+ source.setLink(STDOUT, link, Direction.OUT);
+ fakeSink.setLink(STDIN, link, Direction.IN);
+
+ source.setInputStream(is);
+
+ link.sendEvent(Event.STREAM_START, Direction.OUT);
+ link.run();
+
}
- }
-
- @Override
- public String toString() {
- return "InputStreamSource(" + id + ")";
- }
-
- /**
- * Example.
- */
- public static void main(String args[]) {
- InputStream is = new ByteArrayInputStream(new byte[] { 1, 2, 3 });
-
- InputStreamSource source = new InputStreamSource("source") {
- {
- verbose = true;
- }
- };
- Element fakeSink = new FakeSink("sink") {
- {
- verbose = true;
- }
- };
-
- Link link = new SyncLink() {
- {
- verbose = true;
- }
- };
-
- source.setLink(STDOUT, link, Direction.OUT);
- fakeSink.setLink(STDIN, link, Direction.IN);
-
- source.setInputStream(is);
-
- link.sendEvent(Event.STREAM_START, Direction.OUT);
- link.run();
-
- }
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4f3611f9/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/Link.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/Link.java b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/Link.java
old mode 100644
new mode 100755
index bd970f0..d1f747f
--- a/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/Link.java
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/Link.java
@@ -22,45 +22,45 @@ package streamer;
*/
public interface Link extends DataSource, DataSink, Runnable {
- /**
- * Wire this link with given sink.
- *
- * @param sink
- * an Element
- * @return same sink element, for chaining
- */
- Element setSink(Element sink);
+ /**
+ * Wire this link with given sink.
+ *
+ * @param sink
+ * an Element
+ * @return same sink element, for chaining
+ */
+ Element setSink(Element sink);
- /**
- * Wire this link with given source.
- *
- * @param source
- * an Element
- * @return same source element, for chaining
- */
- Element setSource(Element source);
+ /**
+ * Wire this link with given source.
+ *
+ * @param source
+ * an Element
+ * @return same source element, for chaining
+ */
+ Element setSource(Element source);
- Element getSource();
+ Element getSource();
- Element getSink();
+ Element getSink();
- /**
- * Hold all data in cache, don't pass data to sink until resumed.
- */
- void pause();
+ /**
+ * Hold all data in cache, don't pass data to sink until resumed.
+ */
+ void pause();
- /**
- * Resume transfer.
- */
- void resume();
-
- /**
- * Change mode of operation of this link from push mode to pull mode.
- */
- void setPullMode();
-
- /**
- * Drop this link.
- */
- void drop();
+ /**
+ * Resume transfer.
+ */
+ void resume();
+
+ /**
+ * Change mode of operation of this link from push mode to pull mode.
+ */
+ void setPullMode();
+
+ /**
+ * Drop this link.
+ */
+ void drop();
}