cloudstack-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From devd...@apache.org
Subject [05/21] CLOUDSTACK-5344: Updated to allow rdp console to access hyper-v vm virtual framebuffer.
Date Thu, 02 Jan 2014 07:53:07 GMT
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ServerMCSAttachUserConfirmPDU.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ServerMCSAttachUserConfirmPDU.java b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ServerMCSAttachUserConfirmPDU.java
new file mode 100755
index 0000000..cbefcb9
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ServerMCSAttachUserConfirmPDU.java
@@ -0,0 +1,116 @@
+// 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 rdpclient.rdp;
+
+import streamer.ByteBuffer;
+import streamer.Element;
+import streamer.Link;
+import streamer.OneTimeSwitch;
+import streamer.Pipeline;
+import streamer.PipelineImpl;
+import streamer.debug.MockSink;
+import streamer.debug.MockSource;
+
+/**
+ * Server response to MCS Attach User request.
+ *
+ * Once the User Channel ID has been extracted, the client MUST send an MCS
+ * Channel Join Request PDU for the user channel.
+ *
+ * @see http://msdn.microsoft.com/en-us/library/cc240685.aspx
+ */
+public class ServerMCSAttachUserConfirmPDU extends OneTimeSwitch {
+
+    public static final int MCS_ATTACH_USER_CONFIRM_PDU = 0xb;
+
+    public static final int INITIATOR_PRESENT = 0x2;
+
+    protected RdpState state;
+
+    public ServerMCSAttachUserConfirmPDU(String id, RdpState state) {
+        super(id);
+        this.state = state;
+    }
+
+    @Override
+    protected void handleOneTimeData(ByteBuffer buf, Link link) {
+        if (verbose)
+            System.out.println("[" + this + "] INFO: Data received: " + buf + ".");
+
+        int typeAndFlags = buf.readUnsignedByte();
+        int type = typeAndFlags >> 2;
+        int flags = typeAndFlags & 0x3;
+
+        if (type != MCS_ATTACH_USER_CONFIRM_PDU)
+            throw new RuntimeException("[" + this + "] ERROR: Incorrect type of MCS AttachUserConfirm PDU. Expected value: 11, actual value: " + type + ", data: " + buf + ".");
+
+        if (flags != INITIATOR_PRESENT)
+            throw new RuntimeException("Initator field is not present in MCS AttachUserConfirm PDU. Data: " + buf + ".");
+
+        int rtSuccess = buf.readUnsignedByte() >> 4;
+        if (rtSuccess != 0)
+            throw new RuntimeException("[" + this + "] ERROR: Cannot attach user: request failed. Error code: " + rtSuccess + ", data: " + buf + ".");
+
+        // If the initiator field is present, the client stores the value of the
+        // initiator in the User Channel ID store , because the initiator specifies
+        // the User Channel ID.
+        state.serverUserChannelId = buf.readUnsignedShort() + 1001;
+
+        buf.unref();
+
+        // Next: client MCS Channel Join Request PDU (s)
+        switchOff();
+    }
+
+    /**
+     * Example.
+     */
+    /**
+     * Example.
+     *
+     * @see http://msdn.microsoft.com/en-us/library/cc240842.aspx
+     * @see http://msdn.microsoft.com/en-us/library/cc240500.aspx
+     */
+    public static void main(String args[]) {
+        // System.setProperty("streamer.Link.debug", "true");
+        System.setProperty("streamer.Element.debug", "true");
+        // System.setProperty("streamer.Pipeline.debug", "true");
+
+        byte[] packet = new byte[] {(byte)0x2E, // MCS user confirm (001011..,
+                // 0xb), InitiatorPresent: 1
+                // (......01, 0x1)
+                (byte)0x00, // RT successfull (0000...., 0x0)
+                // Initiator: 1001+3 = 1004
+                (byte)0x00, (byte)0x03,};
+
+        RdpState rdpState = new RdpState();
+        MockSource source = new MockSource("source", ByteBuffer.convertByteArraysToByteBuffers(packet, new byte[] {1, 2, 3}));
+        Element atachUserConfirm = new ServerMCSAttachUserConfirmPDU("attach_user_confirm", rdpState);
+        Element sink = new MockSink("sink");
+        Element mainSink = new MockSink("mainSink", ByteBuffer.convertByteArraysToByteBuffers(new byte[] {1, 2, 3}));
+
+        Pipeline pipeline = new PipelineImpl("test");
+        pipeline.add(source, atachUserConfirm, sink, mainSink);
+        pipeline.link("source", "attach_user_confirm", "mainSink");
+        pipeline.link("attach_user_confirm >" + OTOUT, "sink");
+        pipeline.runMainLoop("source", STDOUT, false, false);
+
+        if (rdpState.serverUserChannelId != 1004)
+            System.err.println("Incorrect user channel ID. Expected value: 1004, actual value: " + rdpState.serverUserChannelId + ".");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ServerMCSChannelJoinConfirmPDU.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ServerMCSChannelJoinConfirmPDU.java b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ServerMCSChannelJoinConfirmPDU.java
new file mode 100755
index 0000000..d3a5954
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ServerMCSChannelJoinConfirmPDU.java
@@ -0,0 +1,89 @@
+// 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 rdpclient.rdp;
+
+import streamer.ByteBuffer;
+import streamer.Link;
+import streamer.OneTimeSwitch;
+
+public class ServerMCSChannelJoinConfirmPDU extends OneTimeSwitch {
+
+    protected int channel;
+
+    public ServerMCSChannelJoinConfirmPDU(String id, int channel) {
+        super(id);
+        this.channel = channel;
+    }
+
+    @Override
+    protected void handleOneTimeData(ByteBuffer buf, Link link) {
+        if (buf == null)
+            return;
+
+        if (verbose)
+            System.out.println("[" + this + "] INFO: Data received: " + buf + ".");
+
+        // Ignore packet
+        buf.unref();
+        switchOff();
+    }
+
+}
+
+/*
+ * 03 00 00 0F 02 F0 80 3E 00 00 03 03 EC 03 EC
+
+  Frame: Number = 22, Captured Frame Length = 72, MediaType = DecryptedPayloadHeader
++ DecryptedPayloadHeader: FrameCount = 1, ErrorStatus = SUCCESS
+  TLSSSLData: Transport Layer Security (TLS) Payload Data
++ TLS: TLS Rec Layer-1 SSL Application Data
+  ISOTS: TPKTCount = 1
+- TPKT: version: 3, Length: 15
+    version: 3 (0x3)
+    Reserved: 0 (0x0)
+    PacketLength: 15 (0xF)
+- X224: Data
+    Length: 2 (0x2)
+    Type: Data
+    EOT: 128 (0x80)
+- T125: Channel Join Confirm, ChannelId = 1004, Result = rt-successful
+  - MCSHeader: Type=Channel Join Confirm
+   - Type: Channel Join Confirm
+    - RootIndex: 15
+       Value: (001111..) 0xf
+  - MCSChannelJoinConfirm: ChannelId = 1004, Result = rt-successful
+     ChannelIdPresent: 1 (0x1)
+   - Result: rt-successful
+    - Result: rt-successful
+     - RootIndex: 0
+        Value: (0000....) 0x0
+   - Initiator: 0x3ec
+    - UserID: 0x3ec
+     - ChannelId: 1004
+      - Align: No Padding
+         Padding5: (00000...) 0x0
+        Value: 3 (0x3)
+   - Requested: 0x3ec
+    - ChannelId: 1004
+       Align: No Padding
+       Value: 1004 (0x3EC)
+   - ChannelId: 0x3ec
+    - ChannelId: 1004
+       Align: No Padding
+       Value: 1004 (0x3EC)
+
+ */

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ServerMCSConnectResponse.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ServerMCSConnectResponse.java b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ServerMCSConnectResponse.java
new file mode 100755
index 0000000..a62ae8b
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ServerMCSConnectResponse.java
@@ -0,0 +1,283 @@
+// 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 rdpclient.rdp;
+
+import streamer.ByteBuffer;
+import streamer.Link;
+import streamer.OneTimeSwitch;
+
+/**
+ * Once the basic server settings data blocks have been processed successfully, the client MUST send the MCS Attach User Request PDU to the server.
+ *
+ * @see http://msdn.microsoft.com/en-us/library/cc240682.aspx
+ */
+public class ServerMCSConnectResponse extends OneTimeSwitch {
+
+    public ServerMCSConnectResponse(String id) {
+        super(id);
+    }
+
+    @Override
+    protected void handleOneTimeData(ByteBuffer buf, Link link) {
+        if (buf == null)
+            return;
+
+        if (verbose)
+            System.out.println("[" + this + "] INFO: Data received: " + buf + ".");
+
+        // Ignore packet
+        buf.unref();
+        switchOff();
+    }
+
+}
+
+/*
+ * @formatter:off
+ * 03 00 00 64 02 F0 80 7F 66 5A 0A 01 00 02 01 00 30 1A 02 01 22 02 01 03 02 01 00 02 01 01 02 01 00 02 01 01 02 03 00 FF F8 02 01 02 04 36 00 05 00 14 7C 00 01 2A 14 76 0A 01 01 00 01 C0 00 4D 63 44 6E 20 01 0C 0C 00 04 00 08 00 01 00 00 00 03 0C 08 00 EB 03 00 00 02 0C 0C 00 00 00 00 00 00 00 00 00
+
+  Frame: Number = 12, Captured Frame Length = 157, MediaType = DecryptedPayloadHeader
++ DecryptedPayloadHeader: FrameCount = 1, ErrorStatus = SUCCESS
+  TLSSSLData: Transport Layer Security (TLS) Payload Data
++ TLS: TLS Rec Layer-1 SSL Application Data
+  ISOTS: TPKTCount = 1
+- TPKT: version: 3, Length: 100
+    version: 3 (0x3)
+    Reserved: 0 (0x0)
+    PacketLength: 100 (0x64)
+- X224: Data
+    Length: 2 (0x2)
+    Type: Data
+    EOT: 128 (0x80)
+- T125: MCSConnect Response
+  - MCSConnectResponse: Result = rt-successful
+   - ConnectResponseHeader:
+    - AsnId: Application Constructed Tag (102)
+     - HighTag:
+        Class:     (01......) Application (1)
+        Type:      (..1.....) Constructed
+        TagNumber: (...11111)
+        TagValueEnd: 102 (0x66)
+    - AsnLen: Length = 90, LengthOfLength = 0
+       Length: 90 bytes, LengthOfLength = 0
+   - Result: rt-successful
+    - Value: 0
+     - AsnIntegerHeader:
+      - AsnId: Enumerated type (Universal 10)
+       - LowTag:
+          Class:    (00......) Universal (0)
+          Type:     (..0.....) Primitive
+          TagValue: (...01010) 10
+      - AsnLen: Length = 1, LengthOfLength = 0
+         Length: 1 bytes, LengthOfLength = 0
+       AsnInt: 0 (0x0)
+   - CalledConnectId: 0
+    - AsnIntegerHeader:
+     - AsnId: Integer type (Universal 2)
+      - LowTag:
+         Class:    (00......) Universal (0)
+         Type:     (..0.....) Primitive
+         TagValue: (...00010) 2
+     - AsnLen: Length = 1, LengthOfLength = 0
+        Length: 1 bytes, LengthOfLength = 0
+      AsnInt: 0 (0x0)
+   - DomainParameters: Length = 26, LengthOfLength = 0
+    - DomainParametersHeader: 0x1
+     - AsnId: Sequence and SequenceOf types (Universal 16)
+      - LowTag:
+         Class:    (00......) Universal (0)
+         Type:     (..1.....) Constructed
+         TagValue: (...10000) 16
+     - AsnLen: Length = 26, LengthOfLength = 0
+        Length: 26 bytes, LengthOfLength = 0
+    - ChannelIds: 34
+     - AsnIntegerHeader:
+      - AsnId: Integer type (Universal 2)
+       - LowTag:
+          Class:    (00......) Universal (0)
+          Type:     (..0.....) Primitive
+          TagValue: (...00010) 2
+      - AsnLen: Length = 1, LengthOfLength = 0
+         Length: 1 bytes, LengthOfLength = 0
+       AsnInt: 34 (0x22)
+    - UserIDs: 3
+     - AsnIntegerHeader:
+      - AsnId: Integer type (Universal 2)
+       - LowTag:
+          Class:    (00......) Universal (0)
+          Type:     (..0.....) Primitive
+          TagValue: (...00010) 2
+      - AsnLen: Length = 1, LengthOfLength = 0
+         Length: 1 bytes, LengthOfLength = 0
+       AsnInt: 3 (0x3)
+    - TokenIds: 0
+     - AsnIntegerHeader:
+      - AsnId: Integer type (Universal 2)
+       - LowTag:
+          Class:    (00......) Universal (0)
+          Type:     (..0.....) Primitive
+          TagValue: (...00010) 2
+      - AsnLen: Length = 1, LengthOfLength = 0
+         Length: 1 bytes, LengthOfLength = 0
+       AsnInt: 0 (0x0)
+    - NumPriorities: 1
+     - AsnIntegerHeader:
+      - AsnId: Integer type (Universal 2)
+       - LowTag:
+          Class:    (00......) Universal (0)
+          Type:     (..0.....) Primitive
+          TagValue: (...00010) 2
+      - AsnLen: Length = 1, LengthOfLength = 0
+         Length: 1 bytes, LengthOfLength = 0
+       AsnInt: 1 (0x1)
+    - MinThroughput: 0
+     - AsnIntegerHeader:
+      - AsnId: Integer type (Universal 2)
+       - LowTag:
+          Class:    (00......) Universal (0)
+          Type:     (..0.....) Primitive
+          TagValue: (...00010) 2
+      - AsnLen: Length = 1, LengthOfLength = 0
+         Length: 1 bytes, LengthOfLength = 0
+       AsnInt: 0 (0x0)
+    - Height: 1
+     - AsnIntegerHeader:
+      - AsnId: Integer type (Universal 2)
+       - LowTag:
+          Class:    (00......) Universal (0)
+          Type:     (..0.....) Primitive
+          TagValue: (...00010) 2
+      - AsnLen: Length = 1, LengthOfLength = 0
+         Length: 1 bytes, LengthOfLength = 0
+       AsnInt: 1 (0x1)
+    - MCSPDUsize: 65528
+     - AsnIntegerHeader:
+      - AsnId: Integer type (Universal 2)
+       - LowTag:
+          Class:    (00......) Universal (0)
+          Type:     (..0.....) Primitive
+          TagValue: (...00010) 2
+      - AsnLen: Length = 3, LengthOfLength = 0
+         Length: 3 bytes, LengthOfLength = 0
+       AsnInt: 65528 (0xFFF8)
+    - protocolVersion: 2
+     - AsnIntegerHeader:
+      - AsnId: Integer type (Universal 2)
+       - LowTag:
+          Class:    (00......) Universal (0)
+          Type:     (..0.....) Primitive
+          TagValue: (...00010) 2
+      - AsnLen: Length = 1, LengthOfLength = 0
+         Length: 1 bytes, LengthOfLength = 0
+       AsnInt: 2 (0x2)
+   - UserData: Identifier = Generic Conference Contro (0.0.20.124.0.1)
+    - UserDataHeader:
+     - AsnId: OctetString type (Universal 4)
+      - LowTag:
+         Class:    (00......) Universal (0)
+         Type:     (..0.....) Primitive
+         TagValue: (...00100) 4
+     - AsnLen: Length = 54, LengthOfLength = 0
+        Length: 54 bytes, LengthOfLength = 0
+    - AsnBerObjectIdentifier: Generic Conference Control (0.0.20.124.0.1)
+     - AsnObjectIdentifierHeader:
+      - AsnId: Reserved for use by the encoding rules (Universal 0)
+       - LowTag:
+          Class:    (00......) Universal (0)
+          Type:     (..0.....) Primitive
+          TagValue: (...00000) 0
+      - AsnLen: Length = 5, LengthOfLength = 0
+         Length: 5 bytes, LengthOfLength = 0
+       First: 0 (0x0)
+       Final: 20 (0x14)
+       Final: 124 (0x7C)
+       Final: 0 (0x0)
+       Final: 1 (0x1)
+    - ConnectPDULength: 42
+       Align: No Padding
+       Length: 42
+    - ConnectGCCPDU: conferenceCreateResponse
+       ExtensionBit: 0 (0x0)
+     - ChoiceValue: conferenceCreateResponse
+        Value: (001.....) 0x1
+     - conferenceCreateResponse:
+        ExtensionBit: 0 (0x0)
+        userDataPresent: 1 (0x1)
+      - nodeID: 0x79f3
+       - UserID: 31219
+        - Align: No Padding
+           Padding2: (00......) 0x0
+          Value: 30218 (0x760A)
+      - tag: 1 (0x1)
+       - Length: 1
+          Align: No Padding
+          Length: 1
+         Value: 1 (0x1)
+      - result: success
+         ExtensionBit: 0 (0x0)
+       - RootIndex: 0
+          Value: (000.....) 0x0
+      - userData:
+       - Size: 1
+        - Align: No Padding
+           Padding4: (0000....) 0x0
+          Length: 1
+       - UserData: 0x4d63446e
+          valuePresent: 1 (0x1)
+        - key: h221NonStandard
+         - ChoiceValue: h221NonStandard
+            Value: (1.......) 0x1
+         - h221NonStandard:
+          - H221NonStandardIdentifier: length: 4
+           - ConstrainedLength: 4
+              Value: (00000000) 0x0
+           - Align: No Padding
+              Padding6: (000000..) 0x0
+             Value: Binary Large Object (4 Bytes)
+        - ServerMcsConnectResponsePdu:
+         - RDPGCCUserDataResponseLength: 32
+            Align: No Padding
+            Length: 32
+         - TsUd: SC_CORE
+          - TsUdHeader: Type = SC_CORE, Length = 12
+             Type: SC_CORE
+             Length: 12 (0xC)
+          - TsUdScCore:
+             Version: RDP 5.0, 5.1, 5.2, 6.0, 6.1, and 7.0
+             ClientRequestedProtocols: TLS 1.0
+         - TsUd: SC_NET
+          - TsUdHeader: Type = SC_NET, Length = 8
+             Type: SC_NET
+             Length: 8 (0x8)
+          - TsUdScNet:
+             MCSChannelID: 1003 (0x3EB)
+             ChannelCount: 0 (0x0)
+             Pad: 0 Bytes
+         - TsUd: SC_SECURITY
+          - TsUdHeader: Type = SC_SECURITY, Length = 12
+             Type: SC_SECURITY
+             Length: 12 (0xC)
+          - TsUdSCSec1:
+           - EncryptionMethod:
+              Support40Bit:  (...............................0) Not Support
+              Support128Bit: (..............................0.) Not Support 128-bit
+              Reserved1:     (.............................0..)
+              Support56Bit:  (............................0...) Not Support 56-bit
+              SupportFIPS:   (...........................0....) Not Support FIPS Compliant
+              Reserved2:     (000000000000000000000000000.....)
+             EncryptionLevel: TS_ENCRYPTION_NONE
+ */

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ServerMCSPDU.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ServerMCSPDU.java b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ServerMCSPDU.java
new file mode 100755
index 0000000..d28d0a0
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ServerMCSPDU.java
@@ -0,0 +1,149 @@
+// 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 rdpclient.rdp;
+
+import streamer.BaseElement;
+import streamer.ByteBuffer;
+import streamer.Element;
+import streamer.Link;
+import streamer.Pipeline;
+import streamer.PipelineImpl;
+import streamer.debug.MockSink;
+import streamer.debug.MockSource;
+
+public class ServerMCSPDU extends BaseElement {
+
+    public ServerMCSPDU(String id) {
+        super(id);
+    }
+
+    @Override
+    public void handleData(ByteBuffer buf, Link link) {
+        if (verbose)
+            System.out.println("[" + this + "] INFO: Data received: " + buf + ".");
+
+        byte headerByte = buf.readSignedByte();
+        int type = headerByte >> 2;
+
+        switch (type) {
+        // Expected type: send data indication: 26 (0x1a, top 6 bits, or 0x68)
+        case 0x1a: {
+            // int userId = buf.readUnsignedShort() + 1001; // User ID: 1002 (1001+1)
+            buf.skipBytes(2); // Ignore user ID
+
+            int channelId = buf.readUnsignedShort(); // Channel ID: 1003
+
+            int flags = buf.readSignedByte();
+            if ((flags & 0x30) != 0x30)
+                throw new RuntimeException("Fragmented MCS packets are not supported.");
+
+            int payloadLength = buf.readVariableUnsignedShort();
+
+            ByteBuffer data = buf.readBytes(payloadLength);
+
+            buf.unref();
+
+            pushDataToPad("channel_" + channelId, data);
+            break;
+        }
+
+        case 0x8: {
+            // Disconnection sequence.
+            buf.unref();
+            break;
+        }
+
+        default:
+            throw new RuntimeException("Unsupported MCS packet type: " + type + "(" + headerByte + "), data: " + buf + ".");
+        }
+
+    }
+
+    /**
+     * Example.
+     *
+     */
+    public static void main(String args[]) {
+        // System.setProperty("streamer.Link.debug", "true");
+        // System.setProperty("streamer.Element.debug", "true");
+        // System.setProperty("streamer.Pipeline.debug", "true");
+
+        byte[] packet = new byte[] {
+                // TPKT
+                (byte)0x03, (byte)0x00, // TPKT Header: TPKT version = 3
+                (byte)0x00, (byte)0x1B, // TPKT length: 27 bytes
+
+                // X224
+                (byte)0x02, // X224 Length: 2 bytes
+                (byte)0xF0, // X224 Type: Data
+                (byte)0x80, // X224 EOT
+
+                // MCS
+                // Type: send data indication: 26 (0x1a, top 6 bits)
+                (byte)0x68, // ??
+
+                (byte)0x00, (byte)0x01, // User ID: 1002 (1001+1)
+                (byte)0x03, (byte)0xEB, // Channel ID: 1003
+                (byte)0x70, // Data priority: high, segmentation: begin|end
+                (byte)0x0D, // Payload length: 13 bytes
+
+                // Deactivate all PDU
+                (byte)0x0D, (byte)0x00, // Length: 13 bytes (LE)
+
+                // - PDUType: 22 (0x16, LE)
+                // Type: (............0110) TS_PDUTYPE_DEACTIVATEALLPDU
+                // ProtocolVersion: (000000000001....) 1
+                (byte)0x16, (byte)0x00,
+
+                (byte)0xEA, (byte)0x03, // PDU source: 1002 (LE)
+                (byte)0xEA, (byte)0x03, (byte)0x01, (byte)0x00, // ShareID = 66538
+
+                (byte)0x01, (byte)0x00, // Length if source descriptor: 1 (LE)
+                (byte)0x00, // Source descriptor (should be set to 0): 0
+        };
+
+        MockSource source = new MockSource("source", ByteBuffer.convertByteArraysToByteBuffers(packet));
+        Element mcs = new ServerMCSPDU("mcs") {
+            {
+                verbose = true;
+            }
+        };
+        Element tpkt = new ServerTpkt("tpkt");
+        Element x224 = new ServerX224DataPdu("x224");
+        Element sink = new MockSink("sink", ByteBuffer.convertByteArraysToByteBuffers(new byte[] {
+                // Deactivate all PDU
+                (byte)0x0D, (byte)0x00, // Length: 13 bytes (LE)
+
+                // - PDUType: 22 (0x16, LE)
+                // Type: (............0110) TS_PDUTYPE_DEACTIVATEALLPDU
+                // ProtocolVersion: (000000000001....) 1
+                (byte)0x16, (byte)0x00,
+
+                (byte)0xEA, (byte)0x03, // PDU source: 1002 (LE)
+                (byte)0xEA, (byte)0x03, (byte)0x01, (byte)0x00, // ShareID = 66538
+
+                (byte)0x01, (byte)0x00, // Length if source descriptor: 1 (LE)
+                (byte)0x00, // Source descriptor (should be set to 0): 0
+        }));
+
+        Pipeline pipeline = new PipelineImpl("test");
+        pipeline.add(source, tpkt, x224, mcs, sink);
+        pipeline.link("source", "tpkt", "x224", "mcs >channel_1003", "sink");
+        pipeline.runMainLoop("source", STDOUT, false, false);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ServerPaletteUpdate.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ServerPaletteUpdate.java b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ServerPaletteUpdate.java
new file mode 100755
index 0000000..606bd89
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ServerPaletteUpdate.java
@@ -0,0 +1,77 @@
+// 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 rdpclient.rdp;
+
+import java.awt.image.IndexColorModel;
+
+import streamer.BaseElement;
+import streamer.ByteBuffer;
+import streamer.Link;
+import common.ScreenDescription;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/cc240623.aspx
+ */
+public class ServerPaletteUpdate extends BaseElement {
+
+    public static final int UPDATETYPE_PALETTE = 0x0002;
+    protected ScreenDescription screen;
+
+    public ServerPaletteUpdate(String id, ScreenDescription screen) {
+        super(id);
+        this.screen = screen;
+    }
+
+    @Override
+    public void handleData(ByteBuffer buf, Link link) {
+
+        if (verbose)
+            System.out.println("[" + this + "] INFO: Data received: " + buf + ".");
+
+        // (2 bytes): A 16-bit, unsigned integer. The update type. This field MUST
+        // be set to UPDATETYPE_PALETTE (0x0002).
+        int updateType = buf.readUnsignedShortLE();
+        if (updateType != UPDATETYPE_PALETTE)
+            throw new RuntimeException("Unexpected update type. Expected type: UPDATETYPE_PALETTE (0x0002), actual value: " + updateType + ", data: " + buf + ".");
+
+        // pad2Octets (2 bytes): A 16-bit, unsigned integer. Padding. Values in this
+        // field MUST be ignored.
+        buf.skipBytes(2);
+
+        // (4 bytes): A 32-bit, unsigned integer. The number of RGB triplets in the
+        // paletteData field. This field MUST be set to 256 (the number of entries
+        // in an 8 bpp palette).
+        int numberColors = (int)buf.readUnsignedIntLE();
+        if (numberColors != 256)
+            throw new RuntimeException("Unexpected value for number of color field in server Palette Update packet. Expected value: 256 colors, actual value: "
+                    + numberColors + ", data: " + buf + ".");
+
+        // (variable): An array of palette entries in RGB triplet format packed on
+        // byte boundaries. The number of triplet entries is given by the
+        // numberColors field.
+        ByteBuffer paletteEntries = buf.readBytes(numberColors * 3);
+
+        // In the case of a Palette Update, the client MUST update the global
+        // palette on all drawing surfaces
+        screen.colorMap = new IndexColorModel(8, numberColors, paletteEntries.data, paletteEntries.offset, false);
+
+        /* DEBUG */buf.assertThatBufferIsFullyRead();
+
+        buf.unref();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ServerSynchronizePDU.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ServerSynchronizePDU.java b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ServerSynchronizePDU.java
new file mode 100755
index 0000000..f464a4a
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ServerSynchronizePDU.java
@@ -0,0 +1,115 @@
+// 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 rdpclient.rdp;
+
+import streamer.ByteBuffer;
+import streamer.Link;
+import streamer.OneTimeSwitch;
+
+public class ServerSynchronizePDU extends OneTimeSwitch {
+
+    public ServerSynchronizePDU(String id) {
+        super(id);
+    }
+
+    @Override
+    protected void handleOneTimeData(ByteBuffer buf, Link link) {
+        if (buf == null)
+            return;
+
+        if (verbose)
+            System.out.println("[" + this + "] INFO: Data received: " + buf + ".");
+
+        // Ignore packet
+        buf.unref();
+        switchOff();
+    }
+
+}
+
+/* @formatter:off */
+/*
+
+ * 03 00 00 24 02 F0 80 68 00 01 03 EB 70 16 16 00 17 00 EA 03 EA 03 01 00 08 00 16 00 1F 00 00 00 01 00 86 A4
+
+  Frame: Number = 36, Captured Frame Length = 93, MediaType = DecryptedPayloadHeader
++ DecryptedPayloadHeader: FrameCount = 1, ErrorStatus = SUCCESS
+  TLSSSLData: Transport Layer Security (TLS) Payload Data
++ TLS: TLS Rec Layer-1 SSL Application Data
+  ISOTS: TPKTCount = 1
+- TPKT: version: 3, Length: 36
+    version: 3 (0x3)
+    Reserved: 0 (0x0)
+    PacketLength: 36 (0x24)
+- X224: Data
+    Length: 2 (0x2)
+    Type: Data
+    EOT: 128 (0x80)
+- T125: Data Packet
+  - MCSHeader: Type=Send Data Indication, UserID=1002, ChannelID=1003
+   - Type: Send Data Indication
+    - RootIndex: 26
+       Value: (011010..) 0x1a
+   - UserID: 0x3ea
+    - UserID: 0x3ea
+     - ChannelId: 1002
+      - Align: No Padding
+         Padding2: (00......) 0x0
+        Value: 1 (0x1)
+   - Channel: 0x3eb
+    - ChannelId: 1003
+       Align: No Padding
+       Value: 1003 (0x3EB)
+   - DataPriority: high
+    - DataPriority: high
+     - RootIndex: 1
+        Value: (01......) 0x1
+   - Segmentation: Begin End
+      Begin: (1.......) Begin
+      End:   (.1......) End
+   - Length: 22
+    - Align: No Padding
+       Padding4: (0000....) 0x0
+      Length: 22
+    RDP: RDPBCGR
+- RDPBCGR: SynchronizePDU
+  - SlowPathPacket: SynchronizePDU
+   - SlowPath: Type = TS_PDUTYPE_DATAPDU
+    - TsShareControlHeader: Type = TS_PDUTYPE_DATAPDU
+       TotalLength: 22 (0x16)
+     - PDUType: 23 (0x17)
+        Type:            (............0111) TS_PDUTYPE_DATAPDU
+        ProtocolVersion: (000000000001....) 1
+       PDUSource: 1002 (0x3EA)
+    - SlowPathIoPacket: 0x0
+     - ShareDataHeader: TS_PDUTYPE2_SYNCHRONIZE
+        ShareID: 66538 (0x103EA)
+        Pad1: 8 (0x8)
+        StreamID: STREAM_UNDEFINED
+        UncompressedLength: 22 (0x16)
+        PDUType2: TS_PDUTYPE2_SYNCHRONIZE
+      - CompressedType: Not Compressed
+         MPPC:       (....0000) MPPC 8K
+         Reserved:   (...0....)
+         Compressed: (..0.....) Not Compressed
+         Front:      (.0......) Not At Front
+         Flush:      (0.......) Not Flushed
+        CompressedLength: 0 (0x0)
+     - TsSynchronizePDU: 0x1
+        MessageType: 0x1, MUST be set to SYNCMSGTYPE_SYNC (1)
+        TargetUser: 42118 (0xA486)
+ */

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ServerTpkt.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ServerTpkt.java b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ServerTpkt.java
new file mode 100755
index 0000000..d9662d2
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ServerTpkt.java
@@ -0,0 +1,70 @@
+// 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 rdpclient.rdp;
+
+import streamer.BaseElement;
+import streamer.ByteBuffer;
+import streamer.Link;
+
+public class ServerTpkt extends BaseElement {
+
+    /**
+     * TPKT protocol version (first byte).
+     */
+    public static final int PROTOCOL_TPKT = 3;
+
+    public ServerTpkt(String id) {
+        super(id);
+    }
+
+    @Override
+    public void handleData(ByteBuffer buf, Link link) {
+        if (buf == null)
+            return;
+
+        if (verbose)
+            System.out.println("[" + this + "] INFO: Data received: " + buf + ".");
+
+        // We need at least 4 bytes to get packet length
+        if (!cap(buf, 4, UNLIMITED, link, false))
+            return;
+
+        int version = buf.readUnsignedByte();
+        if (version != PROTOCOL_TPKT)
+            throw new RuntimeException("Unexpected data in TPKT header. Expected TPKT version: 0x03,  actual value: " + buf + ".");
+
+        buf.skipBytes(1); // Reserved byte
+
+        // Length of whole packet, including header
+        int length = buf.readUnsignedShort();
+        if (!cap(buf, length, length, link, false))
+            return;
+
+        int payloadLength = length - buf.cursor;
+
+        // Extract payload
+        ByteBuffer outBuf = buf.slice(buf.cursor, payloadLength, true);
+        buf.unref();
+
+        if (verbose) {
+            outBuf.putMetadata("source", this);
+        }
+
+        pushDataToAllOuts(outBuf);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ServerX224ConnectionConfirmPDU.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ServerX224ConnectionConfirmPDU.java b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ServerX224ConnectionConfirmPDU.java
new file mode 100755
index 0000000..5a8dfaf
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ServerX224ConnectionConfirmPDU.java
@@ -0,0 +1,234 @@
+// 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 rdpclient.rdp;
+
+import streamer.ByteBuffer;
+import streamer.Element;
+import streamer.Link;
+import streamer.OneTimeSwitch;
+import streamer.Pipeline;
+import streamer.PipelineImpl;
+import streamer.debug.MockSink;
+import streamer.debug.MockSource;
+
+/**
+ * Once the External Security Protocol handshake has run to completion, the
+ * client MUST continue with the connection sequence by sending the MCS Connect
+ * Initial PDU to the server over the newly established secure channel.
+ *
+ *
+ * @see http://msdn.microsoft.com/en-us/library/cc240663.aspx
+ */
+public class ServerX224ConnectionConfirmPDU extends OneTimeSwitch {
+
+    public static final int X224_TPDU_CONNECTION_REQUEST = 0xe0;
+    public static final int X224_TPDU_CONNECTION_CONFIRM = 0xd0;
+    public static final int X224_TPDU_DISCONNECTION_REQUEST = 0x80;
+    public static final int X224_TPDU_DISCONNECTION_CONFIRM = 0xc0;
+    public static final int X224_TPDU_EXPEDITED_DATA = 0x10;
+    public static final int X224_TPDU_DATA_ACKNOWLEDGE = 0x61;
+    public static final int X224_TPDU_EXPEDITET_ACKNOWLEDGE = 0x40;
+    public static final int X224_TPDU_REJECT = 0x51;
+    public static final int X224_TPDU_ERROR = 0x70;
+    public static final int X224_TPDU_PROTOCOL_IDENTIFIER = 0x01;
+
+    /**
+     * The server requires that the client support Enhanced RDP Security with
+     * either TLS 1.0, 1.1 or 1.2 or CredSSP. If only CredSSP was requested then
+     * the server only supports TLS.
+     */
+    public static final int SSL_REQUIRED_BY_SERVER = 0x00000001;
+
+    /**
+     * The server is configured to only use Standard RDP Security mechanisms and
+     * does not support any External Security Protocols.
+     */
+    public static final int SSL_NOT_ALLOWED_BY_SERVER = 0x00000002;
+
+    /**
+     * The server does not possess a valid authentication certificate and cannot
+     * initialize the External Security Protocol Provider.
+     */
+    public static final int SSL_CERT_NOT_ON_SERVER = 0x00000003;
+
+    /**
+     * The list of requested security protocols is not consistent with the current
+     * security protocol in effect. This error is only possible when the Direct
+     * Approach is used and an External Security Protocolis already being used.
+     */
+    public static final int INCONSISTENT_FLAGS = 0x00000004;
+
+    /**
+     * The server requires that the client support Enhanced RDP Security with
+     * CredSSP.
+     */
+    public static final int HYBRID_REQUIRED_BY_SERVER = 0x00000005;
+
+    /**
+     * The server requires that the client support Enhanced RDP Security with TLS
+     * 1.0, 1.1 or 1.2 and certificate-based client authentication.
+     */
+    public static final int SSL_WITH_USER_AUTH_REQUIRED_BY_SERVER = 0x00000006;
+
+    public ServerX224ConnectionConfirmPDU(String id) {
+        super(id);
+    }
+
+    @Override
+    protected void handleOneTimeData(ByteBuffer buf, Link link) {
+        if (buf == null)
+            return;
+
+        if (verbose)
+            System.out.println("[" + this + "] INFO: Data received: " + buf + ".");
+
+        int x224Length = buf.readVariableSignedIntLE();
+
+        int x224Type = buf.readUnsignedByte();
+        if (x224Type != X224_TPDU_CONNECTION_CONFIRM)
+            throw new RuntimeException("Unexpected type of packet. Expected type: " + X224_TPDU_CONNECTION_CONFIRM + " (CONNECTION CONFIRM), actual type: "
+                    + x224Type + ", length: " + x224Length + ", buf: " + buf + ".");
+
+        // Ignore destination reference, because client side has only one node
+        buf.skipBytes(2);
+
+        // Source reference
+        // int srcRef = buf.readUnsignedShort();
+        buf.skipBytes(2);
+
+        // Ignore class and options
+        buf.skipBytes(1);
+
+        // RDP_NEG_RSP::type (TYPE_RDP_NEG_RSP)
+        int negType = buf.readUnsignedByte();
+
+        // RDP_NEG_RSP::flags (0)
+        buf.skipBytes(1); // Ignore: always 0
+
+        // RDP_NEG_RSP::length (always 8 bytes)
+        int length = buf.readUnsignedShortLE();
+
+        if (length != 8)
+            throw new RuntimeException("Unexpected length of buffer. Expected value: 8, actual value: " + length + ", RDP NEG buf: " + buf + ".");
+
+        // RDP_NEG_RSP: Selected protocols (PROTOCOL_SSL)
+        int protocol = buf.readSignedIntLE();
+
+        if (negType != RdpConstants.RDP_NEG_REQ_TYPE_NEG_RSP) {
+            // Parse error code, see
+            // http://msdn.microsoft.com/en-us/library/cc240507.aspx
+            int errorCode = protocol;
+            String message = "Unknown error.";
+            switch (errorCode) {
+            case SSL_REQUIRED_BY_SERVER:
+                message = "The server requires that the client support Enhanced RDP Security with either TLS 1.0, 1.1 or 1.2 or CredSSP. If only CredSSP was requested then the server only supports TLS.";
+                break;
+
+            case SSL_NOT_ALLOWED_BY_SERVER:
+                message = "The server is configured to only use Standard RDP Security mechanisms and does not support any External Security Protocols.";
+                break;
+
+            case SSL_CERT_NOT_ON_SERVER:
+                message = "The server does not possess a valid authentication certificate and cannot initialize the External Security Protocol Provider.";
+                break;
+
+            case INCONSISTENT_FLAGS:
+                message = "The list of requested security protocols is not consistent with the current security protocol in effect. This error is only possible when the Direct Approach is used and an External Security Protocolis already being used.";
+                break;
+
+            case HYBRID_REQUIRED_BY_SERVER:
+                message = "The server requires that the client support Enhanced RDP Security with CredSSP.";
+                break;
+
+            case SSL_WITH_USER_AUTH_REQUIRED_BY_SERVER:
+                message = "The server requires that the client support Enhanced RDP Security  with TLS 1.0, 1.1 or 1.2 and certificate-based client authentication.";
+                break;
+
+            }
+            throw new RuntimeException("Connection failure: " + message);
+        }
+
+        if (protocol != RdpConstants.RDP_NEG_REQ_PROTOCOL_SSL && protocol != RdpConstants.RDP_NEG_REQ_PROTOCOL_HYBRID)
+            throw new RuntimeException("Unexpected protocol type (nor SSL, nor HYBRID (SSL+CredSSP)): " + protocol + ", RDP NEG buf: " + buf + ".");
+
+        if (verbose)
+            System.out.println("[" + this + "] INFO: RDP Negotiation response. Type: " + negType + ", protocol: " + protocol + ".");
+
+        // Next: upgrade socket to SSL, send ConnectInitial packet
+        switchOff();
+    }
+
+    /**
+     * Example.
+     *
+     */
+    public static void main(String args[]) {
+        // System.setProperty("streamer.Link.debug", "true");
+        System.setProperty("streamer.Element.debug", "true");
+        // System.setProperty("streamer.Pipeline.debug", "true");
+
+//    byte[] packet = new byte[] {
+//
+//        0x03, // -> TPKT Header: TPKT version = 3
+//        0x00, // TPKT Header: Reserved = 0
+//        0x00, 0x13, // TPKT Header: Packet length - (total = 19 bytes)
+//        0x0e, // X.224: Length indicator (14 bytes)
+//        (byte) 0xd0, // X.224: Type (high nibble) = 0xd = CC TPDU; credit
+//                     // (low nibble) = 0
+//        0x00, 0x00, // X.224: Destination reference = 0
+//        0x12, 0x34, // X.224: Source reference = 0x1234 (bogus value)
+//        0x00, // X.224: Class and options = 0
+//
+//        0x02, // RDP_NEG_RSP::type (TYPE_RDP_NEG_RSP)
+//        0x00, // RDP_NEG_RSP::flags (0)
+//        0x08, 0x00, // RDP_NEG_RSP::length (8 bytes)
+//        0x01, 0x00, 0x00, 0x00 // RDP_NEG_RSP: Selected protocols (PROTOCOL_SSL)
+//    };
+
+        // Connection failure
+        // 03 00 00 13 0e d0 00 00 12 34 00 03 00 08 00 05 00 00 00
+        byte[] packet = new byte[] {
+
+                0x03, // -> TPKT Header: TPKT version = 3
+                0x00, // TPKT Header: Reserved = 0
+                0x00, 0x13, // TPKT Header: Packet length - (total = 19 bytes)
+                0x0e, // X.224: Length indicator (14 bytes)
+                (byte)0xd0, // X.224: Type (high nibble) = 0xd = CC TPDU; credit
+                // (low nibble) = 0
+                0x00, 0x00, // X.224: Destination reference = 0
+                0x12, 0x34, // X.224: Source reference = 0x1234 (bogus value)
+                0x00, // X.224: Class and options = 0
+                (byte)0x03, // Failure
+                (byte)0x00, // RDP_NEG_RSP::flags (0)
+                (byte)0x08, (byte)0x00, // RDP_NEG_RSP::length (8 bytes)
+                (byte)0x05, (byte)0x00, (byte)0x00, (byte)0x00, // Code:  HYBRID_REQUIRED_BY_SERVER
+
+        };
+
+        MockSource source = new MockSource("source", ByteBuffer.convertByteArraysToByteBuffers(packet));
+        Element cc = new ServerX224ConnectionConfirmPDU("cc");
+        Element tpkt = new ServerTpkt("tpkt");
+        Element sink = new MockSink("sink", new ByteBuffer[] {});
+        Element mainSink = new MockSink("mainSink", new ByteBuffer[] {});
+
+        Pipeline pipeline = new PipelineImpl("test");
+        pipeline.add(source, tpkt, cc, sink, mainSink);
+        pipeline.link("source", "tpkt", "cc", "mainSink");
+        pipeline.link("cc >" + OTOUT, "sink");
+        pipeline.runMainLoop("source", STDOUT, false, false);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ServerX224DataPdu.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ServerX224DataPdu.java b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ServerX224DataPdu.java
new file mode 100755
index 0000000..2c0087e
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ServerX224DataPdu.java
@@ -0,0 +1,64 @@
+// 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 rdpclient.rdp;
+
+import streamer.BaseElement;
+import streamer.ByteBuffer;
+import streamer.Link;
+
+public class ServerX224DataPdu extends BaseElement {
+
+    public static final int X224_TPDU_LAST_DATA_UNIT = 0x80;
+    public static final int X224_TPDU_DATA = 0xF0;
+
+    public ServerX224DataPdu(String id) {
+        super(id);
+    }
+
+    @Override
+    public void handleData(ByteBuffer buf, Link link) {
+        if (buf == null)
+            return;
+
+        if (verbose)
+            System.out.println("[" + this + "] INFO: Data received: " + buf + ".");
+
+        int headerLength = buf.readVariableSignedIntLE();
+
+        if (headerLength != 2)
+            throw new RuntimeException("Unexpected X224 Data PDU header length. Expected header length: 2 , actual header length: " + headerLength + ".");
+
+        // Read X224 type and options
+        int type = buf.readUnsignedByte(); // High nibble: type, low nibble:
+
+        if ((type & 0xf0) != X224_TPDU_DATA)
+            throw new RuntimeException("[" + this + "] ERROR: Unexepcted X224 packet type. Expected packet type: " + X224_TPDU_DATA
+                    + " (X224_TPDU_DATA), actual packet type: " + type + ", buf: " + buf + ".");
+
+        int options = buf.readUnsignedByte();
+
+        if ((options & X224_TPDU_LAST_DATA_UNIT) != X224_TPDU_LAST_DATA_UNIT)
+            throw new RuntimeException("Unexepcted X224 packet options. Expected options: " + X224_TPDU_LAST_DATA_UNIT
+                    + " (X224_TPDU_LAST_DATA_UNIT), actual packet options: " + options + ", buf: " + buf + ".");
+
+        ByteBuffer payload = buf.readBytes(buf.length - buf.cursor);
+
+        buf.unref();
+
+        pushDataToAllOuts(payload);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/AssertingByteBuffer.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/AssertingByteBuffer.java b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/AssertingByteBuffer.java
deleted file mode 100644
index fe9cc50..0000000
--- a/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/AssertingByteBuffer.java
+++ /dev/null
@@ -1,107 +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;
-
-import java.nio.charset.Charset;
-
-/**
- * Assert that writes to this buffer are matching expected data.
- */
-public class AssertingByteBuffer extends ByteBuffer {
-
-    public AssertingByteBuffer(byte[] expectedData) {
-        super(expectedData);
-    }
-
-    private void assertEquals(int expected, int actual) {
-        if (expected != actual)
-            throw new RuntimeException("Expected value does not match actual value. Expected value: " + expected + ", actual value: " + actual + ", buf: " + this + ".");
-    }
-
-    @Override
-    public void writeByte(int b) {
-        if (b < 0)
-            throw new RuntimeException();
-        //*DEBUG*/System.out.println("WriteByte: "+b+", cursor:"+cursor+".");
-        assertEquals(readUnsignedByte(), b & 0xff);
-    }
-
-    @Override
-    public void writeShort(int x) {
-        //*DEBUG*/System.out.println("WriteShort: "+x+", cursor:"+cursor+".");
-        assertEquals(readUnsignedShort(), x & 0xFFff);
-    }
-
-    @Override
-    public void writeShortLE(int x) {
-        //*DEBUG*/System.out.println("WriteShortLE: "+x+", cursor:"+cursor+".");
-        assertEquals(readUnsignedShortLE(), x & 0xFFff);
-    }
-
-    @Override
-    public void writeInt(int i) {
-        //*DEBUG*/System.out.println("WriteInt: "+i+", cursor:"+cursor+".");
-        assertEquals(readSignedInt(), i);
-    }
-
-    @Override
-    public void writeIntLE(int i) {
-        //*DEBUG*/System.out.println("WriteIntLE: "+i+", cursor:"+cursor+".");
-        assertEquals(readSignedIntLE(), i);
-    }
-
-    @Override
-    public void writeVariableIntLE(int i) {
-        //*DEBUG*/System.out.println("WriteVariableIntLE: "+i+", cursor:"+cursor+".");
-        assertEquals(readVariableSignedIntLE(), i);
-    }
-
-    @Override
-    public void writeString(String actual, Charset charset) {
-        //*DEBUG*/System.out.println("WriteString: "+actual+", cursor:"+cursor+".");
-        String expected = readString(actual.length(), charset);
-        if (!actual.equals(expected))
-            throw new RuntimeException("Expected value does not match actual value. Expected value: " + expected + ", actual value: " + actual + ".");
-    }
-
-    @Override
-    public void writeBytes(ByteBuffer actual) {
-        //*DEBUG*/System.out.println("WriteString: "+actual+", cursor:"+cursor+".");
-        ByteBuffer expected = readBytes(actual.length);
-        if (!actual.equals(expected))
-            throw new RuntimeException("Expected value does not match actual value. Expected value: " + expected + ", actual value: " + actual + ".");
-    }
-
-    @Override
-    public void writeBytes(byte[] actualData) {
-        ByteBuffer actual = new ByteBuffer(actualData);
-        //*DEBUG*/System.out.println("WriteString: "+actual+", cursor:"+cursor+".");
-        ByteBuffer expected = readBytes(actual.length);
-        if (!actual.equals(expected))
-            throw new RuntimeException("Expected value does not match actual value. Expected value: " + expected + ", actual value: " + actual + ".");
-    }
-
-    @Override
-    public void writeBytes(byte[] actualData, int offset, int length) {
-        ByteBuffer actual = new ByteBuffer(actualData, offset, length);
-        //*DEBUG*/System.out.println("WriteString: "+actual+", cursor:"+cursor+".");
-        ByteBuffer expected = readBytes(actual.length);
-        if (!actual.equals(expected))
-            throw new RuntimeException("Expected value does not match actual value. Expected value: " + expected + ", actual value: " + actual + ".");
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/BaseElement.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/BaseElement.java b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/BaseElement.java
old mode 100644
new mode 100755
index dd2b541..1ca68ce
--- a/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/BaseElement.java
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/BaseElement.java
@@ -21,6 +21,9 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
 
+import streamer.debug.FakeSink;
+import streamer.debug.FakeSource;
+
 public class BaseElement implements Element {
 
     protected String id;
@@ -78,11 +81,11 @@ public class BaseElement implements Element {
     @Override
     public Set<String> getPads(Direction direction) {
         switch (direction) {
-            case IN:
-                return inputPads.keySet();
+        case IN:
+            return inputPads.keySet();
 
-            case OUT:
-                return outputPads.keySet();
+        case OUT:
+            return outputPads.keySet();
         }
         return null;
     }
@@ -103,24 +106,24 @@ public class BaseElement implements Element {
     @Override
     public void setLink(String padName, Link link, Direction direction) {
         switch (direction) {
-            case IN:
-                if (inputPads.get(padName) != null)
-                    throw new RuntimeException("Cannot link more than one wire to same pad. Element: " + this + ", pad: " + padName + ":" + direction + ", new link: " +
-                        link + ", existing link: " + inputPads.get(padName) + ".");
-                inputPads.put(padName, link);
-                link.setSink(this);
+        case IN:
+            if (inputPads.get(padName) != null)
+                throw new RuntimeException("Cannot link more than one wire to same pad. Element: " + this + ", pad: " + padName + ":" + direction + ", new link: "
+                        + link + ", existing link: " + inputPads.get(padName) + ".");
+            inputPads.put(padName, link);
+            link.setSink(this);
 
-                break;
+            break;
 
-            case OUT:
-                if (outputPads.get(padName) != null)
-                    throw new RuntimeException("Cannot link more than one wire to same pad. Element: " + this + ", pad: " + padName + ":" + direction + ", new link: " +
-                        link + ", existing link: " + outputPads.get(padName) + ".");
+        case OUT:
+            if (outputPads.get(padName) != null)
+                throw new RuntimeException("Cannot link more than one wire to same pad. Element: " + this + ", pad: " + padName + ":" + direction + ", new link: "
+                        + link + ", existing link: " + outputPads.get(padName) + ".");
 
-                outputPads.put(padName, link);
-                link.setSource(this);
+            outputPads.put(padName, link);
+            link.setSource(this);
 
-                break;
+            break;
         }
     }
 
@@ -162,9 +165,6 @@ public class BaseElement implements Element {
      */
     @Override
     public void handleData(ByteBuffer buf, Link link) {
-        if (buf == null)
-            return;
-
         if (verbose)
             System.out.println("[" + this + "] INFO: Data received: " + buf + ".");
 
@@ -177,7 +177,8 @@ public class BaseElement implements Element {
     protected final void pushDataToAllOuts(ByteBuffer buf) {
 
         if (buf == null)
-            return;
+            throw new NullPointerException();
+        //return;
 
         if (outputPads.size() == 0)
             throw new RuntimeException("Number of outgoing connection is zero. Cannot send data to output. Data: " + buf + ".");
@@ -218,18 +219,19 @@ public class BaseElement implements Element {
      * By default, do nothing with incoming event and retransmit event to all
      * pads.
      */
+    @SuppressWarnings("incomplete-switch")
     @Override
     public void handleEvent(Event event, Direction direction) {
         if (verbose)
             System.out.println("[" + this + "] INFO: Event " + event + ":" + direction + " is received.");
 
         switch (event) {
-            case STREAM_CLOSE:
-                onClose();
-                break;
-            case STREAM_START:
-                onStart();
-                break;
+        case STREAM_CLOSE:
+            onClose();
+            break;
+        case STREAM_START:
+            onStart();
+            break;
         }
 
         sendEventToAllPads(event, direction);
@@ -261,18 +263,18 @@ public class BaseElement implements Element {
             System.out.println("[" + this + "] INFO: Sending event " + event + ":" + direction + ".");
 
         switch (direction) {
-            case IN:
-                // Send event to all pads with IN direction
-                for (DataSource in : inputPads.values()) {
-                    in.sendEvent(event, direction);
-                }
-                break;
-            case OUT:
-                // Send event to all pads with OUT direction
-                for (DataSink out : outputPads.values()) {
-                    out.sendEvent(event, direction);
-                }
-                break;
+        case IN:
+            // Send event to all pads with IN direction
+            for (DataSource in : inputPads.values()) {
+                in.sendEvent(event, direction);
+            }
+            break;
+        case OUT:
+            // Send event to all pads with OUT direction
+            for (DataSink out : outputPads.values()) {
+                out.sendEvent(event, direction);
+            }
+            break;
         }
     }
 
@@ -290,7 +292,7 @@ public class BaseElement implements Element {
      *          source link, to push unnecessary data back
      * @param fromCursor
      *          if true, then position will be included into calculation
-     * @return true,
+     * @return true, if buffer is long enough, false otherwise
      */
     public boolean cap(ByteBuffer buf, int minLength, int maxLength, Link link, boolean fromCursor) {
 
@@ -384,16 +386,16 @@ public class BaseElement implements Element {
     public static void main(String args[]) {
         Element source = new FakeSource("source") {
             {
-                this.verbose = true;
-                this.numBuffers = 10;
-                this.incommingBufLength = 3;
-                this.delay = 100;
+                verbose = true;
+                numBuffers = 10;
+                incommingBufLength = 3;
+                delay = 100;
             }
         };
 
         Element sink = new FakeSink("sink") {
             {
-                this.verbose = true;
+                verbose = true;
             }
         };
 
@@ -411,7 +413,9 @@ public class BaseElement implements Element {
         // Links between t3-t4-sink will operate in push mode.
         // Link between t2-t3 will run main loop (pull from source and push to
         // sink).
-        pipeline.getLink("t3", STDOUT).run();
+        Link link = pipeline.getLink("t3", STDOUT);
+        link.sendEvent(Event.STREAM_START, Direction.IN);
+        link.run();
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/BufferPool.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/BufferPool.java b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/BufferPool.java
old mode 100644
new mode 100755

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/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 8543a5a..3a718ba
--- 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,7 +19,9 @@ 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.
@@ -45,9 +47,9 @@ public class ByteBuffer {
      */
     public ByteBuffer(int minLength) {
         // Get buffer of acceptable size from buffer pool
-        this.data = BufferPool.allocateNewBuffer(minLength);
-        this.offset = 0;
-        this.length = minLength;
+        data = BufferPool.allocateNewBuffer(minLength);
+        offset = 0;
+        length = minLength;
     }
 
     public ByteBuffer(byte data[]) {
@@ -55,8 +57,8 @@ public class ByteBuffer {
             throw new NullPointerException("Data must be non-null.");
 
         this.data = data;
-        this.offset = 0;
-        this.length = data.length;
+        offset = 0;
+        length = data.length;
     }
 
     public ByteBuffer(byte[] data, int offset, int length) {
@@ -74,9 +76,9 @@ public class ByteBuffer {
      */
     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;
+        data = BufferPool.allocateNewBuffer(128 + minLength);
+        offset = 128; // 100 bytes should be enough for headers
+        length = minLength;
     }
 
     /**
@@ -96,7 +98,7 @@ public class ByteBuffer {
 
     @Override
     public String toString() {
-        return toString(100);
+        return toString(length);
     }
 
     /**
@@ -106,8 +108,8 @@ public class ByteBuffer {
      *          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 "ByteRange(){offset=" + offset + ", length=" + length + ", cursor=" + cursor + ", data=" + ((data == null) ? "null" : toHexString(maxLength))
+                + ((metadata == null || metadata.size() == 0) ? "" : ", metadata=" + metadata) + "}";
     }
 
     /**
@@ -143,13 +145,68 @@ public class ByteBuffer {
             if (i > 0)
                 builder.append(" ");
             int b = data[offset + i] & 0xff;
-            builder.append(((b < 16) ? "0" : "") + Integer.toString(b, 16));
+            builder.append(String.format("%02x", b));
         }
         return builder.toString();
     }
 
-    public void dump() {
-        System.out.println(toString(length));
+    /**
+     * 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) {
@@ -190,12 +247,12 @@ public class ByteBuffer {
         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 + ".");
+            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)
+        if (copyMetadata && metadata != null)
             slice.metadata = new HashMap<String, Object>(metadata);
 
         return slice;
@@ -251,8 +308,8 @@ public class ByteBuffer {
 
     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) + ".");
+            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];
 
@@ -267,8 +324,8 @@ public class ByteBuffer {
      */
     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) + ".");
+            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];
 
@@ -279,12 +336,13 @@ public class ByteBuffer {
     }
 
     /**
-     * Return array of int's in little endian order, but use only 3 bytes per int (3RGB).
+     * 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) + ".");
+            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];
 
@@ -315,8 +373,8 @@ public class ByteBuffer {
         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));
+        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;
     }
@@ -328,8 +386,8 @@ public class ByteBuffer {
         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));
+        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;
     }
@@ -341,9 +399,21 @@ public class ByteBuffer {
         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) + (data[offset +
-                cursor] & 0xff));
+        long result = (((long)(data[offset + cursor + 3] & 0xff) << 24) + ((long)(data[offset + cursor + 2] & 0xff) << 16)
+                + ((long)(data[offset + cursor + 1] & 0xff) << 8) + (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) + (data[offset + cursor + 3] & 0xff));
         cursor += 4;
         return result;
     }
@@ -379,19 +449,19 @@ public class ByteBuffer {
         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;
+        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;
@@ -446,6 +516,18 @@ public class ByteBuffer {
     }
 
     /**
+     * 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.
      *
@@ -456,9 +538,9 @@ public class ByteBuffer {
         int firstByte = readUnsignedByte();
 
         int result;
-        if ((firstByte & 0x80) == 0)
+        if ((firstByte & 0x80) == 0) {
             result = firstByte & 0x7f;
-        else {
+        } else {
             int secondByte = readUnsignedByte();
             result = (((firstByte & 0x7f) << 8) | secondByte);
         }
@@ -467,6 +549,174 @@ public class ByteBuffer {
     }
 
     /**
+     * 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() {
@@ -536,6 +786,13 @@ public class ByteBuffer {
     }
 
     /**
+     * Read signed long in network order. Cursor is advanced by 8 bytes.
+     */
+    public long readSignedLong() {
+        return (((long)readSignedInt()) << 32) | ((readSignedInt()) & 0xffFFffFFL);
+    }
+
+    /**
      * Read string from buffer. Cursor is advanced by string length.
      */
     public String readString(int length, Charset charset) {
@@ -548,6 +805,38 @@ public class ByteBuffer {
     }
 
     /**
+     * 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) {
@@ -682,8 +971,8 @@ public class ByteBuffer {
      */
     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 +
-                ".");
+            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
@@ -697,9 +986,13 @@ public class ByteBuffer {
         // Extend byte range to include header
         this.offset -= length;
         this.length += length;
-        this.cursor += length;
+        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));
     }
@@ -725,44 +1018,10 @@ public class ByteBuffer {
     }
 
     public void writeBytes(byte[] bytes, int offset, int length) {
-        System.arraycopy(bytes, offset, this.data, this.offset + this.cursor, length);
+        System.arraycopy(bytes, offset, data, this.offset + 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.
      */
@@ -771,7 +1030,7 @@ public class ByteBuffer {
     }
 
     /**
-     * Rewind cursor to beginning of buffer.
+     * Rewind cursor to beginning of the buffer.
      */
     public void rewindCursor() {
         cursor = 0;
@@ -808,8 +1067,11 @@ public class ByteBuffer {
     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;
 
@@ -824,4 +1086,38 @@ public class ByteBuffer {
         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) {
+        offset += length;
+        this.length -= length;
+        rewindCursor();
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/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

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/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

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/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


Mime
View raw message