cloudstack-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From devd...@apache.org
Subject [06/22] CLOUDSTACK-5344: Update to allow rdp console to access hyper-v vm virtual framebuffer.
Date Mon, 23 Dec 2013 09:13:00 GMT
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();
 }


Mime
View raw message