cloudstack-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From devd...@apache.org
Subject [11/22] CLOUDSTACK-5344: Update to allow rdp console to access hyper-v vm virtual framebuffer.
Date Mon, 23 Dec 2013 09:13:05 GMT
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4f3611f9/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ClientConfirmActivePDU.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ClientConfirmActivePDU.java b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ClientConfirmActivePDU.java
new file mode 100755
index 0000000..9c0c52e
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ClientConfirmActivePDU.java
@@ -0,0 +1,1132 @@
+// 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;
+
+import common.ScreenDescription;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/cc240488.aspx
+ */
+public class ClientConfirmActivePDU extends BaseElement {
+
+    public static final String SOURCE_DESC = "MSTSC";
+
+    public static final int CAPSTYPE_BITMAP = 0x2;
+
+    protected int numberCapabilities;
+
+    protected RdpState state;
+    protected ScreenDescription screen;
+
+    protected boolean desktopResize = false;
+    protected int prefferedBitsPerPixel = 16;
+
+    public ClientConfirmActivePDU(String id, ScreenDescription screen, RdpState state) {
+        super(id);
+        this.state = state;
+        this.screen = screen;
+    }
+
+    @Override
+    public void handleData(ByteBuffer aBuf, Link link) {
+
+        // Body
+        ByteBuffer buf = new ByteBuffer(1024, true);
+        numberCapabilities = 0;
+        writeCapabilities(buf);
+        buf.trimAtCursor();
+
+        // Header
+        ByteBuffer header = createMCSHeader(buf);
+
+        // Length of source descriptor, including NULL character (LE)
+        header.writeShortLE(SOURCE_DESC.length() + 1);
+
+        // Length of combined capabilities + 4 bytes (number of capabilities and
+        // padding) (LE)
+        header.writeShortLE(buf.length + 4);
+
+        header.writeString(SOURCE_DESC, RdpConstants.CHARSET_8);
+        header.writeByte(0);
+
+        // Number of capabilities
+        header.writeShortLE(numberCapabilities);
+
+        // Padding 2 bytes
+        header.writeShortLE(0);
+
+        header.trimAtCursor();
+
+        // Prepend header to capabilities
+        buf.prepend(header);
+
+        // Trim buffer to actual length of data written
+        buf.trimAtCursor();
+
+        pushDataToPad(STDOUT, buf);
+
+        sendOtherRequredPackets();
+
+    }
+
+    private ByteBuffer createMCSHeader(ByteBuffer buf) {
+        ByteBuffer header = new ByteBuffer(100);
+        // MCS Send Data Request
+        header.writeByte(0x64);
+
+        // Initiator: 1004 (1001+3)
+        header.writeShort(3);
+
+        // Channel ID: 1003 (I/O channel)
+        header.writeShort(RdpConstants.CHANNEL_IO);
+
+        // Data priority: high (0x40), segmentation: begin (0x20) | end (0x10)
+        header.writeByte(0x70);
+
+        int length = buf.length + 26;
+
+        // User data length: (variable length field, LE)
+        header.writeVariableShort(length);
+
+        // Total length: (LE)
+        header.writeShortLE(length);
+
+        // PDU type: Confirm Active PDU (0x3), TS_PROTOCOL_VERSION (0x10) (LE)
+        header.writeShortLE(0x13);
+
+        // PDU source: 1004 (LE)
+        header.writeShortLE(1004);
+
+        // Share ID, e.g. 0x000103ea (LE)
+        header.writeIntLE((int)state.serverShareId);
+
+        // Originator ID: 1002 (LE)
+        header.writeShortLE(1002);
+        return header;
+    }
+
+    private void sendOtherRequredPackets() {
+        // Send sequence in bulk
+
+        sendSynchronizePDU();
+        sendControlPDUActionCooperate();
+        sendControlPDUActionRequestControl();
+        // sendBitmapCachePersistentListPDU();
+        sendFontListPDU();
+    }
+
+    private void sendFontListPDU() {
+        {
+            int length = 1024; // Large enough
+            ByteBuffer buf = new ByteBuffer(length, true);
+
+            /* @formatter:off */
+      buf.writeBytes(new byte[] {
+          // MCS Send Data Request
+          (byte)0x64,
+          // Initiator: 1004 (1001+3)
+          (byte)0x00, (byte)0x03, 
+          // Channel ID: 1003 (I/O channel)
+          (byte)0x03, (byte)0xeb, 
+          // Data priority: high (0x40), segmentation: begin (0x20) | end (0x10)
+          (byte)0x70, 
+          // User data length: 26 bytes (0x1a, variable length field)
+          (byte)0x80, (byte)0x1a,
+          
+          // Total length: 26 bytes (0x1a, LE)
+          (byte)0x1a, (byte)0x00, 
+          // PDU type: PDUTYPE_DATAPDU (0x7), PDU version: 1 (0x0010) (LE)
+          (byte)0x17, (byte)0x00, 
+          // PDU source: 1004 (LE)
+          (byte)0xec, (byte)0x03, 
+      });
+      // Share ID, 4 bytes  (LE)
+      buf.writeIntLE((int)state.serverShareId);
+      
+      buf.writeBytes(new byte[] {
+          // Padding 1 byte
+          (byte)0x00, 
+          // Stream ID: STREAM_LOW (1)
+          (byte)0x01, 
+          // uncompressedLength : 12 bytes (LE)
+          (byte)0x0c, (byte)0x00,
+          
+          // pduType2: PDUTYPE2_FONTLIST (39)
+          (byte)0x27, 
+          // generalCompressedType: 0
+          (byte)0x00, 
+          // generalCompressedLength: 0 (LE)
+          (byte)0x00, (byte)0x00, 
+
+          // numberEntries (should be set to zero): 0 (LE)
+          (byte)0x00, (byte)0x00,
+          // totalNumEntries (should be set to zero): 0 (LE)
+          (byte)0x00, (byte)0x00,
+          // listFlags  (should be set to 0x3): 0x0003 (LE), FONTLIST_LAST(0x2) | FONTLIST_FIRST(0x1) 
+          (byte)0x03, (byte)0x00,
+          // entrySize: 50 bytes (0x0032, LE)
+          (byte)0x32, (byte)0x00,
+      });
+      /* @formatter:on */
+
+            // Trim buffer to actual length of data written
+            buf.trimAtCursor();
+
+            pushDataToPad(STDOUT, buf);
+        }
+    }
+
+    private void sendControlPDUActionRequestControl() {
+        int length = 1024; // Large enough
+        ByteBuffer buf = new ByteBuffer(length, true);
+
+        /* @formatter:off */
+    buf.writeBytes(new byte[] {
+        // MCS Send Data Request
+        (byte)0x64, 
+        // Initiator: 1004 (1001+3)
+        (byte)0x00, (byte)0x03,
+        // Channel ID: 1003 (I/O channel)
+        (byte)0x03, (byte)0xeb, 
+        // Data priority: high (0x40), segmentation: begin (0x20) | end (0x10)
+        (byte)0x70, 
+        // User data length: 26 bytes (0x1a, variable length field)
+        (byte)0x80, (byte)0x1a,
+        
+        // Total length: 26 bytes (0x1a, LE)
+        (byte)0x1a, (byte)0x00,
+        // PDU type: PDUTYPE_DATAPDU (0x7), PDU version: 1 (0x0010) (LE)
+        (byte)0x17, (byte)0x00, 
+        // PDU source: 1004 (LE)
+        (byte)0xec, (byte)0x03,
+    });
+        // Share ID, 4 bytes  (LE)
+    buf.writeIntLE((int)state.serverShareId);
+        
+    buf.writeBytes(new byte[] {
+        // Padding 1 byte
+        (byte)0x00, 
+        // Stream ID: STREAM_LOW (1)
+        (byte)0x01, 
+        // uncompressedLength : 12 bytes (LE)
+        (byte)0x0c, (byte)0x00, 
+        // pduType2: PDUTYPE2_CONTROL (20)
+        (byte)0x14, 
+        // generalCompressedType: 0
+        (byte)0x00, 
+        // generalCompressedLength: 0 (LE)
+        (byte)0x00, (byte)0x00,
+        
+        // action: CTRLACTION_REQUEST_CONTROL (1) (LE)
+        (byte)0x01, (byte)0x00,
+        // grantId: 0 (LE)
+        (byte)0x00, (byte)0x00, 
+        // controlId: 0 (LE)
+        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+    });
+    /* @formatter:on */
+
+        // Trim buffer to actual length of data written
+        buf.trimAtCursor();
+
+        pushDataToPad(STDOUT, buf);
+    }
+
+    private void sendControlPDUActionCooperate() {
+        int length = 1024; // Large enough
+        ByteBuffer buf = new ByteBuffer(length, true);
+
+        /* @formatter:off */
+    buf.writeBytes(new byte[] {
+        // MCS Send Data Request
+        (byte)0x64, 
+        // Initiator: 1004 (1001+3)
+        (byte)0x00, (byte)0x03, 
+        // Channel ID: 1003 (I/O channel)
+        (byte)0x03, (byte)0xeb, 
+        // Data priority: high (0x40), segmentation: begin (0x20) | end (0x10)
+        (byte)0x70, 
+        // User data length: 26 bytes (0x1a, variable length field)
+        (byte)0x80, (byte)0x1a,
+        
+        // Total length: 26 bytes (0x1a, LE)
+        (byte)0x1a,(byte)0x00,
+        // PDU type: PDUTYPE_DATAPDU (0x7), PDU version: 1 (0x0010) (LE)
+        (byte)0x17, (byte)0x00, 
+        // PDU source: 1004 (LE)
+        (byte)0xec, (byte)0x03, 
+    });
+    // Share ID, 4 bytes  (LE)
+    buf.writeIntLE((int)state.serverShareId);
+    
+    buf.writeBytes(new byte[] {
+        // Padding 1 byte
+        (byte)0x00, 
+        // Stream ID: STREAM_LOW (1)
+        (byte)0x01, 
+        // uncompressedLength : 12 bytes (LE)
+        (byte)0x0c, (byte)0x00, 
+        // pduType2: PDUTYPE2_CONTROL (20)
+        (byte)0x14, 
+        // generalCompressedType: 0
+        (byte)0x00, 
+        // generalCompressedLength: 0 (LE?)
+        (byte)0x00, (byte)0x00, 
+        // action: CTRLACTION_COOPERATE (4) (LE)
+        (byte)0x04, (byte)0x00,
+        // grantId: 0 (LE)
+        (byte)0x00, (byte)0x00,
+        // controlId: 0
+        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+    });
+    /* @formatter:on */
+
+        buf.trimAtCursor();
+
+        pushDataToPad(STDOUT, buf);
+    }
+
+    private void sendSynchronizePDU() {
+
+        ByteBuffer buf = new ByteBuffer(1024, true);
+        /* @formatter:off */
+    buf.writeBytes(new byte[] {
+        // MCS send data request
+        (byte)0x64,
+        // Initiator: 1004 (1001+3)
+        (byte)0x00, (byte)0x03,
+        // Channel ID: 1003 (I/O Channel)
+        (byte)0x03, (byte)0xeb,
+        // Data priority: high (0x40), segmentation: begin (0x20) | end (0x10)
+        (byte)0x70, 
+        // Data length:  22 bytes (0x16, variable length field)
+        (byte)0x80,  (byte)0x16, 
+        
+        // RDP: total length: 22 bytes (LE)
+        (byte)0x16, (byte)0x00, 
+        
+        // PDU type: PDUTYPE_DATAPDU (0x7), TS_PROTOCOL_VERSION (0x10) (LE)
+        (byte)0x17, (byte)0x00,
+        
+        // PDU source: 1007 (LE)
+        (byte)0xec, (byte)0x03,
+    });
+    // Share ID, 4 bytes  (LE)
+    buf.writeIntLE((int)state.serverShareId);
+    
+    buf.writeBytes(new byte[] {
+        // Padding: 1 byte
+        (byte)0x00,
+        // Stream ID: STREAM_LOW (1)
+        (byte)0x01, 
+        // uncompressedLength : 8 bytes (LE)
+        (byte)0x08, (byte)0x00,
+        // pduType2 = PDUTYPE2_SYNCHRONIZE (31)
+        (byte)0x1f, 
+        // generalCompressedType: 0
+        (byte)0x00,
+        // generalCompressedLength: 0 (LE?)
+        (byte)0x00, (byte)0x00,
+        //  messageType: SYNCMSGTYPE_SYNC (1) (LE)
+        (byte)0x01, (byte)0x00, 
+        // targetUser: 0x03ea
+        (byte)0xea, (byte)0x03,
+    });
+    /* @formatter:on */
+        buf.trimAtCursor();
+        pushDataToPad(STDOUT, buf);
+    }
+
+    private void writeCapabilities(ByteBuffer buf) {
+        writeGeneralCS(buf);
+
+        writeBitmapCS(buf);
+
+        writeOrderCS(buf);
+
+        writeBitmapCache2CS(buf);
+
+        writeColorTableCacheCS(buf);
+
+        writeWindowActivationCS(buf);
+
+        writeControlCS(buf);
+
+        writePointerCS(buf);
+
+        writeShareCS(buf);
+
+        writeInputCS(buf);
+
+        writeBrushCS(buf);
+
+        writeSoundCS(buf);
+
+        writeFontCS(buf);
+
+        writeOffscreenBitmapCS(buf);
+
+        writeGlyphCacheCS(buf);
+    }
+
+    private void writeBrushCS(ByteBuffer buf) {
+        numberCapabilities++;
+        buf.writeBytes(new byte[] {
+                //
+                // Brush Capability Set (8 bytes), see
+                // http://msdn.microsoft.com/en-us/library/cc240564.aspx
+                (byte)0x0f, (byte)0x00, // capability set type: CAPSTYPE_BRUSH (15,
+                                        // LE)
+                (byte)0x08, (byte)0x00, // length of capability set: 8 bytes (LE)
+                (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, // brushSupportLevel:
+                                                                // BRUSH_DEFAULT
+                                                                // (0x0, LE)
+
+        });
+    }
+
+    private void writeInputCS(ByteBuffer buf) {
+        numberCapabilities++;
+        buf.writeBytes(new byte[] {
+                //
+                // Input Capability Set (88 bytes), see
+                // http://msdn.microsoft.com/en-us/library/cc240563.aspx
+                (byte)0x0d,
+                (byte)0x00, // capability set type: CAPSTYPE_INPUT (13, LE)
+                (byte)0x58,
+                (byte)0x00, // length of capability set: 88 bytes (LE)
+                (byte)0x35,
+                (byte)0x00, // inputFlags: 0x0035 (LE), INPUT_FLAG_FASTPATH_INPUT2
+                            // (0x20), INPUT_FLAG_VKPACKET (0x10), INPUT_FLAG_MOUSEX
+                            // (0x4), INPUT_FLAG_SCANCODES (0x1)
+                (byte)0x00,
+                (byte)0x00, // Padding 2 bytes
+                (byte)0x09,
+                (byte)0x04,
+                (byte)0x00,
+                (byte)0x00, // keyboardLayout: "US" keyboard layout (0x000409, LE)
+                (byte)0x00,
+                (byte)0x00,
+                (byte)0x00,
+                (byte)0x00, // keyboardType: unknown (LE)
+                (byte)0x00,
+                (byte)0x00,
+                (byte)0x00,
+                (byte)0x00, // keyboardSubType: unknown (LE)
+                (byte)0x00,
+                (byte)0x00,
+                (byte)0x00,
+                (byte)0x00, // keyboardFunctionKey: unknown (LE)
+                // imeFileName: "", (64 bytes, including trailing NULL characters, UCS2)
+                (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+                (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+                (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+                (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+                (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+                (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+
+        });
+    }
+
+    private void writeShareCS(ByteBuffer buf) {
+        numberCapabilities++;
+        buf.writeBytes(new byte[] {
+                //
+                // Share Capability Set (8 bytes), see
+                // http://msdn.microsoft.com/en-us/library/cc240570.aspx
+                (byte)0x09, (byte)0x00, // capability set type: CAPSTYPE_SHARE (9, LE)
+                (byte)0x08, (byte)0x00, // length of capability set: 8 bytes (LE)
+                (byte)0x00, (byte)0x00, // nodeID (must be set to 0 by client): 0 (LE)
+                (byte)0x00, (byte)0x00, // Padding 2 bytes (LE)
+
+        });
+    }
+
+    private void writePointerCS(ByteBuffer buf) {
+        numberCapabilities++;
+        buf.writeBytes(new byte[] {
+                //
+                // Pointer Capability Set (10 bytes), see
+                // http://msdn.microsoft.com/en-us/library/cc240562.aspx
+                (byte)0x08, (byte)0x00, // capability set type: CAPSTYPE_POINTER (8,
+                                        // LE)
+                (byte)0x0a, (byte)0x00, // length of capability set: 10 bytes (LE)
+                (byte)0x00, (byte)0x00, // colorPointerFlag: FALSE (LE)
+                (byte)0x00, (byte)0x00, // colorPointerCacheSize: 0 (LE)
+                (byte)0x14, (byte)0x00, // pointerCacheSize: 20 (LE)
+
+        });
+    }
+
+    private void writeControlCS(ByteBuffer buf) {
+        numberCapabilities++;
+        buf.writeBytes(new byte[] {
+                //
+                // Control Capability Set (12 bytes), see
+                // http://msdn.microsoft.com/en-us/library/cc240568.aspx
+                (byte)0x05, (byte)0x00, // capability set type: CAPSTYPE_ACTIVATION
+                                        // (7)
+                (byte)0x0c, (byte)0x00, // length of capability set: 12 bytes (LE)
+                (byte)0x00, (byte)0x00, // controlFlags (should be set to 0): 0 (LE)
+                (byte)0x00, (byte)0x00, // remoteDetachFlag (should be set to 0): 0
+                                        // (LE)
+                (byte)0x02, (byte)0x00, // controlInterest (should be set to
+                                        // CONTROLPRIORITY_NEVER):
+                                        // CONTROLPRIORITY_NEVER (2) (LE)
+                (byte)0x02, (byte)0x00, // detachInterest (should be set to
+                                        // CONTROLPRIORITY_NEVER):
+                                        // CONTROLPRIORITY_NEVER (2) (LE)
+
+        });
+    }
+
+    private void writeWindowActivationCS(ByteBuffer buf) {
+        numberCapabilities++;
+        buf.writeBytes(new byte[] {
+                //
+                // Window Activation Capability Set (12 bytes), see
+                // http://msdn.microsoft.com/en-us/library/cc240569.aspx
+                (byte)0x07, (byte)0x00, // capability set type: CAPSTYPE_ACTIVATION
+                                        // (7) (LE)
+                (byte)0x0c, (byte)0x00, // length of capability set: 12 bytes (LE)
+                (byte)0x00, (byte)0x00, // helpKeyFlag (should be set to FALSE (0)):
+                                        // FALSE (0, LE)
+                (byte)0x00, (byte)0x00, // helpKeyIndexFlag (should be set to FALSE
+                                        // (0)): FALSE (0, LE)
+                (byte)0x00, (byte)0x00, // helpExtendedKeyFlag (should be set to FALSE
+                                        // (0)): FALSE (0, LE)
+                (byte)0x00, (byte)0x00, // windowManagerKeyFlag (should be set to
+                                        // FALSE (0)): FALSE (0, LE)
+
+        });
+    }
+
+    private void writeColorTableCacheCS(ByteBuffer buf) {
+        numberCapabilities++;
+        buf.writeBytes(new byte[] {
+
+                //
+                // Color Table Cache Capability Set (8 bytes), see
+                // http://msdn.microsoft.com/en-us/library/cc241564.aspx
+                (byte)0x0a, (byte)0x00, // capability set type: CAPSTYPE_COLORCACHE
+                                        // (10) (LE)
+                (byte)0x08, (byte)0x00, // length of capability set: 8 bytes (LE)
+                (byte)0x06, (byte)0x00, // Color table cache size (must be ignored
+                                        // during capability exchange and is assumed
+                                        // to be 0x0006): 6 (LE)
+                (byte)0x00, (byte)0x00, // Padding 2 bytes
+
+        });
+    }
+
+    private void writeBitmapCache2CS(ByteBuffer buf) {
+        numberCapabilities++;
+        buf.writeBytes(new byte[] {
+                //
+                // Bitmap Cache Rev. 2 Capability Set (40 bytes), see
+                // http://msdn.microsoft.com/en-us/library/cc240560.aspx
+                (byte)0x13, (byte)0x00, // capability set type:
+                                        // CAPSTYPE_BITMAPCACHE_REV2 (19) (LE)
+                (byte)0x28, (byte)0x00, // length of capability set: 40 bytes (LE)
+                (byte)0x00, (byte)0x00, // Cache flags: 0 (LE)
+                (byte)0x00, // Padding 1 byte
+                (byte)0x00, // Number of cell caches: 0
+                (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, // Bitmap cache0
+                                                                // cell info: 0 (LE)
+                (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, // Bitmap cache1
+                                                                // cell info: 0 (LE)
+                (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, // Bitmap cache2
+                                                                // cell info: 0 (LE)
+                (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, // Bitmap cache3
+                                                                // cell info: 0 (LE)
+                (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, // Bitmap cache4
+                                                                // cell info: 0 (LE)
+                (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, // Padding 12 bytes
+                (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, // Padding
+                (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, // Padding
+        });
+    }
+
+    private void writeGeneralCS(ByteBuffer buf) {
+        numberCapabilities++;
+        buf.writeBytes(new byte[] {
+                // Capabilities, see
+                // http://msdn.microsoft.com/en-us/library/cc240486.aspx
+
+                //
+                // General capability set (24 bytes), see
+                // http://msdn.microsoft.com/en-us/library/cc240549.aspx
+                (byte)0x01, (byte)0x00, // capability set type: CAPSTYPE_GENERAL (1)
+                                        // (LE)
+                (byte)0x18, (byte)0x00, // length of capability set: 24 bytes (LE)
+                (byte)0x01, (byte)0x00, // TS_OSMAJORTYPE_WINDOWS (1) (LE)
+                (byte)0x03, (byte)0x00, // TS_OSMINORTYPE_WINDOWS_NT (3) (LE)
+                (byte)0x00, (byte)0x02, // TS_CAPS_PROTOCOLVERSION (0x0200) (LE)
+                (byte)0x00, (byte)0x00, // Padding 2 bytes
+                (byte)0x00, (byte)0x00, // generalCompressionTypes: 0 (LE)
+
+                // Extra flags: 0x040d (LE)
+                // FastPathOutput: (...............1) Advertiser supports fast-path
+                // output
+                // ShadowCompression: (..............0.) Advertiser NOT supports shadow
+                // compression
+                // LongLengthCredentials: (.............1..) Advertiser supports
+                // long-length credentials for the user name, password, or domain name
+                // SessionAutoreconnection: (............1...) Advertiser supports
+                // session auto-reconnection
+                // ImprovedEncryptionChecksum: (...........0....) Client and server NOT
+                // support improved encryption checksum
+                // Reserved1: (......00000.....)
+                // CompressedBitMapDataFlag: (.....1..........) No 8-UINT8 header is
+                // present for compressed bitmap data
+                // Reserved2: (00000...........)
+                (byte)0x0d, (byte)0x04,
+
+                (byte)0x00, (byte)0x00, // updateCapabilityFlag: 0 (LE)
+                (byte)0x00, (byte)0x00, // remoteUnshareFlag: 0 (LE)
+                (byte)0x00, (byte)0x00, // generalCompressionLevel: 0 (LE)
+                (byte)0x00, // refreshRectSupport: FALSE (0)
+                (byte)0x00, // suppressOutputSupport: FALSE (0)
+
+        });
+    }
+
+    private void writeBitmapCS(ByteBuffer buf) {
+        // Bitmap capability set (28 bytes), see
+        // http://msdn.microsoft.com/en-us/library/cc240554.aspx
+
+        numberCapabilities++;
+
+        // Capability set type: CAPSTYPE_BITMAP (2) (LE)
+        buf.writeShortLE(CAPSTYPE_BITMAP);
+
+        // Length of capability set: 28 bytes (LE)
+        buf.writeShortLE(28);
+
+        // preferredBitsPerPixel: 16 bpp (LE)
+        buf.writeShortLE(prefferedBitsPerPixel);
+
+        // receive1BitPerPixel (ignored and SHOULD be set to TRUE (0x1)): TRUE (0x1) (LE)
+        buf.writeShortLE(1);
+
+        // receive4BitsPerPixel (ignored and SHOULD be set to TRUE (0x1)): TRUE (0x1) (LE)
+        buf.writeShortLE(1);
+
+        // receive8BitsPerPixel (ignored and SHOULD be set to TRUE (0x1)): TRUE (0x1) (LE)
+        buf.writeShortLE(1);
+
+        // Desktop width and height (LE)
+        buf.writeShortLE(screen.getFramebufferWidth());
+        buf.writeShortLE(screen.getFramebufferHeight());
+
+        // Padding 2 bytes
+        buf.writeShortLE(0);
+
+        // desktopResizeFlag (LE)
+        buf.writeShortLE((desktopResize) ? 1 : 0);
+
+        buf.writeBytes(new byte[] {
+                (byte)0x01, (byte)0x00, // bitmapCompressionFlag (must be set to TRUE
+                                        // (0x1)): TRUE (0x1) (LE)
+                (byte)0x00, // highColorFlags (field is ignored and SHOULD be set to
+                            // zero): 0
+                (byte)0x01, // drawingFlags: 0x1 TODO: padding, why 0x1 ???
+                (byte)0x01, (byte)0x00, // multipleRectangleSupport: TRUE (LE)
+                (byte)0x00, (byte)0x00, // Padding 2 bytes
+
+        });
+    }
+
+    private void writeOrderCS(ByteBuffer buf) {
+        numberCapabilities++;
+        buf.writeBytes(new byte[] {
+                //
+                // Order Capability Set (88 bytes), see
+                // http://msdn.microsoft.com/en-us/library/cc240556.aspx
+                (byte)0x03,
+                (byte)0x00, // capability set type: CAPSTYPE_ORDER (3) (LE)
+                (byte)0x58,
+                (byte)0x00, // length of capability set: 88 bytes (LE)
+                // terminalDescriptor = "" (16 bytes, UCS2)
+                (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+                (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, // pad4octetsA
+                (byte)0x01, (byte)0x00, // desktopSaveXGranularity (ignored): 1 (LE)
+                (byte)0x14, (byte)0x00, // desktopSaveYGranularity (ignored): 20 (LE)
+                (byte)0x00, (byte)0x00, // pad2octetsA (ignored)
+                (byte)0x01, (byte)0x00, // maximumOrderLevel: ORD_LEVEL_1_ORDERS (1)
+                (byte)0x00, (byte)0x00, // number of fonts (ignored): 0
+                (byte)0x4a, (byte)0x00, // orderFlags = 0x004a (LE),
+                                        // SOLIDPATTERNBRUSHONLY (0x40),
+                                        // ZEROBOUNDSDELTASSUPPORT (0x8, MUST),
+                                        // NEGOTIATEORDERSUPPORT (0x2, MUST)
+                // Order support: 32 bytes (no primary drawing orders are supported, so
+                // this array MUST be initialized to all zeros, use 0x01 for TRUE).
+                (byte)0x00, // TS_NEG_DSTBLT_INDEX: FALSE
+                (byte)0x00, // TS_NEG_PATBLT_INDEX: FALSE
+                (byte)0x00, // TS_NEG_SCRBLT_INDEX: FALSE
+                (byte)0x00, // TS_NEG_MEMBLT_INDEX: FALSE
+                (byte)0x00, // TS_NEG_MEM3BLT_INDEX: FALSE
+                (byte)0x00, // TS_NEG_ATEXTOUT_INDEX: FALSE
+                (byte)0x00, // TS_NEG_AEXTTEXTOUT_INDEX: FALSE
+                (byte)0x00, // TS_NEG_DRAWNINEGRID_INDEX: FALSE
+                (byte)0x00, // TS_NEG_LINETO_INDEX: FALSE
+                (byte)0x00, // TS_NEG_MULTI_DRAWNINEGRID_INDEX: FALSE
+                (byte)0x00, // TS_NEG_OPAQUERECT_INDEX: FALSE
+                (byte)0x00, // TS_NEG_SAVEBITMAP_INDEX: FALSE
+                (byte)0x00, // TS_NEG_WTEXTOUT_INDEX: FALSE
+                (byte)0x00, // TS_NEG_MEMBLT_R2_INDEX: FALSE
+                (byte)0x00, // TS_NEG_MEM3BLT_R2_INDEX: FALSE
+                (byte)0x00, // TS_NEG_MULTIDSTBLT_INDEX: FALSE
+                (byte)0x00, // TS_NEG_MULTIPATBLT_INDEX: FALSE
+                (byte)0x00, // TS_NEG_MULTISCRBLT_INDEX: FALSE
+                (byte)0x00, // TS_NEG_MULTIOPAQUERECT_INDEX: FALSE
+                (byte)0x00, // TS_NEG_FAST_INDEX_INDEX: FALSE
+                (byte)0x00, // TS_NEG_POLYGON_SC_INDEX: FALSE
+                (byte)0x00, // TS_NEG_POLYGON_CB_INDEX: FALSE
+                (byte)0x00, // TS_NEG_POLYLINE_INDEX: TRUE
+                (byte)0x00, // Unused: 0
+                (byte)0x00, // TS_NEG_FAST_GLYPH_INDEX: FALSE
+                (byte)0x00, // TS_NEG_ELLIPSE_SC_INDEX: FALSE
+                (byte)0x00, // TS_NEG_ELLIPSE_CB_INDEX: FALSE
+                (byte)0x00, // TS_NEG_INDEX_INDEX: FALSE
+                (byte)0x00, // TS_NEG_WEXTTEXTOUT_INDEX: FALSE
+                (byte)0x00, // TS_NEG_WLONGTEXTOUT_INDEX: FALSE
+                (byte)0x00, // TS_NEG_WLONGEXTTEXTOUT_INDEX: FALSE
+                (byte)0x00, // Unused: 0
+                (byte)0x00, (byte)0x00, // Text flags (ignored): 0 (LE)
+                (byte)0x00, (byte)0x00, // Order support extra flags: 0 (LE)
+                (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, // Padding 4 bytes
+                (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, // Desktop save size
+                                                                // (ignored): 0
+                                                                // (assumed to be
+                                                                // 230400 bytes
+                                                                // (480*480,
+                                                                // 0x38400, LE))
+                (byte)0x00, (byte)0x00, // Padding 2 bytes
+                (byte)0x00, (byte)0x00, // Padding 2 bytes
+                (byte)0xe4, (byte)0x04, // Text ANSI Code Page: 1252, ANSI - Latin I
+                                        // (0x04e4, LE)
+                (byte)0x00, (byte)0x00, // Padding 2 bytes
+
+        });
+    }
+
+    private void writeSoundCS(ByteBuffer buf) {
+        numberCapabilities++;
+        buf.writeBytes(new byte[] {
+                //
+                // Sound Capability Set (8 bytes), see
+                // http://msdn.microsoft.com/en-us/library/cc240552.aspx
+                (byte)0x0c, (byte)0x00, // capability set type: CAPSTYPE_SOUND (12,
+                                        // LE)
+                (byte)0x08, (byte)0x00, // length of capability set: 8 bytes (LE)
+                (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, // soundFlags:
+                                                                // 0x0000 (LE) //
+                                                                // SOUND_FLAG_BEEPS
+                                                                // (0x1)
+
+        });
+    }
+
+    private void writeFontCS(ByteBuffer buf) {
+        numberCapabilities++;
+        buf.writeBytes(new byte[] {
+                //
+                // Font Capability Set (8 bytes), see
+                // http://msdn.microsoft.com/en-us/library/cc240571.aspx
+                (byte)0x0e, (byte)0x00, (byte)0x08, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x00,
+
+        });
+    }
+
+    private void writeOffscreenBitmapCS(ByteBuffer buf) {
+        numberCapabilities++;
+        buf.writeBytes(new byte[] {
+                //
+                // Offscreen Bitmap Cache Capability Set (12 bytes), see
+                // http://msdn.microsoft.com/en-us/library/cc240550.aspx
+                (byte)0x11, (byte)0x00, // capability set type:
+                                        // CAPSTYPE_OFFSCREENCACHE (17, LE)
+                (byte)0x0c, (byte)0x00, // length of capability set: 12 bytes (LE)
+                (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, // offscreenSupportLevel:
+                                                                // FALSE (LE)
+                (byte)0x00, (byte)0x00, // offscreenCacheSize: 0 (LE)
+                (byte)0x00, (byte)0x00, // offscreenCacheEntries: 0 (LE)
+
+        });
+    }
+
+    private void writeGlyphCacheCS(ByteBuffer buf) {
+        numberCapabilities++;
+        buf.writeBytes(new byte[] {
+                //
+                // Glyph Cache Capability Set (52 bytes), see
+                // http://msdn.microsoft.com/en-us/library/cc240565.aspx
+                (byte)0x10, (byte)0x00, // capability set type:
+                                        // CAPSTYPE_OFFSCREENCACHE (16, LE)
+                (byte)0x34, (byte)0x00, // length of capability set: 52 bytes (LE)
+                // Glyph Cache (40 bytes)
+                (byte)0xfe, (byte)0x00, // CacheEntries: 254 (LE)
+                (byte)0x04, (byte)0x00, // CacheMaximumCellSize: 4 (LE)
+                (byte)0xfe, (byte)0x00, // CacheEntries: 254 (LE)
+                (byte)0x04, (byte)0x00, // CacheMaximumCellSize: 4 (LE)
+                (byte)0xfe, (byte)0x00, // CacheEntries: 254 (LE)
+                (byte)0x08, (byte)0x00, // CacheMaximumCellSize: 4 (LE)
+                (byte)0xfe, (byte)0x00, // CacheEntries: 254 (LE)
+                (byte)0x08, (byte)0x00, // CacheMaximumCellSize: 4 (LE)
+                (byte)0xfe, (byte)0x00, // CacheEntries: 254 (LE)
+                (byte)0x10, (byte)0x00, // CacheMaximumCellSize: 4 (LE)
+                (byte)0xfe, (byte)0x00, // CacheEntries: 254 (LE)
+                (byte)0x20, (byte)0x00, // CacheMaximumCellSize: 4 (LE)
+                (byte)0xfe, (byte)0x00, // CacheEntries: 254 (LE)
+                (byte)0x40, (byte)0x00, // CacheMaximumCellSize: 4 (LE)
+                (byte)0xfe, (byte)0x00, // CacheEntries: 254 (LE)
+                (byte)0x80, (byte)0x00, // CacheMaximumCellSize: 4 (LE)
+                (byte)0xfe, (byte)0x00, // CacheEntries: 254 (LE)
+                (byte)0x00, (byte)0x01, // CacheMaximumCellSize: 4 (LE)
+                (byte)0x40, (byte)0x00, // CacheEntries: 64 (LE)
+                (byte)0x00, (byte)0x08, // CacheMaximumCellSize: 2048 (LE)
+                // FragCache
+                (byte)0x00, (byte)0x01, // CacheEntries: 256 (LE)
+                (byte)0x00, (byte)0x01, // CacheMaximumCellSize: 256 (LE)
+                //
+                (byte)0x00, (byte)0x00, // GlyphSupportLevel: GLYPH_SUPPORT_NONE (0x0,
+                                        // LE)
+                (byte)0x00, (byte)0x00, // Padding 2 bytes
+        });
+    }
+
+    /**
+     * 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");
+
+        /* @formatter:off */
+    byte[] packet = new byte[] {
+        // MCS Send Data Request
+        (byte)0x64,  
+        
+        // Initiator: 1004 (1001+3)
+        (byte)0x00, (byte)0x03, 
+        
+        // Channel ID: 1003 (I/O channel)
+        (byte)0x03, (byte)0xeb,
+        
+        // Data priority: high (0x40), segmentation: begin (0x20) | end (0x10)
+        (byte)0x70,
+        
+        // User data length: 432 bytes (0x1b0, variable length field)
+        (byte)0x81, (byte)0xb0, 
+        
+        // Total length: 432 bytes (0x1b0, LE)
+        (byte)0xb0, (byte)0x01, 
+        
+        // PDU type: Confirm Active PDU (0x3), TS_PROTOCOL_VERSION (0x10) (LE)
+        (byte)0x13, (byte)0x00, 
+        
+        // PDU source: 1004 (LE)
+        (byte)0xec, (byte)0x03, 
+        
+        // Share ID: 0x000103ea (LE)
+        (byte)0xea, (byte)0x03, (byte)0x01, (byte)0x00,
+        
+        // Originator ID: 1002 (LE)
+        (byte)0xea, (byte)0x03,
+        
+        // Length of source descriptor: 6 bytes (including NULL character) (LE) 
+        (byte)0x06, (byte)0x00, 
+        
+        // Length of combined capabilities: 410 bytes (LE)
+        (byte)0x9a, (byte)0x01,
+        
+        // Source descriptor: "MSTSC" ???
+        (byte)0x4d, (byte)0x53, (byte)0x54, (byte)0x53, (byte)0x43, (byte)0x00,
+        
+        // Number of capabilities: 15 (LE)
+        (byte)0x0f, (byte)0x00,
+        
+        // Padding 2 bytes
+        (byte)0x00, (byte)0x00,
+        
+        // Capabilities, see http://msdn.microsoft.com/en-us/library/cc240486.aspx
+        
+        //
+        // General capability set (24 bytes), see http://msdn.microsoft.com/en-us/library/cc240549.aspx
+        (byte)0x01, (byte)0x00, // capability set type: CAPSTYPE_GENERAL (1) (LE) 
+        (byte)0x18, (byte)0x00, // length of capability set: 24 bytes (LE)
+        (byte)0x01, (byte)0x00, // TS_OSMAJORTYPE_WINDOWS (1) (LE)
+        (byte)0x03, (byte)0x00, // TS_OSMINORTYPE_WINDOWS_NT (3) (LE)
+        (byte)0x00, (byte)0x02, // TS_CAPS_PROTOCOLVERSION (0x0200) (LE)
+        (byte)0x00, (byte)0x00, // Padding 2 bytes
+        (byte)0x00, (byte)0x00, // generalCompressionTypes: 0 (LE)
+        
+        // Extra flags: 0x040d (LE)
+//        FastPathOutput:             (...............1) Advertiser supports fast-path output
+//        ShadowCompression:          (..............0.) Advertiser NOT supports shadow compression
+//        LongLengthCredentials:      (.............1..) Advertiser supports long-length credentials for the user name, password, or domain name
+//        SessionAutoreconnection:    (............1...) Advertiser supports session auto-reconnection
+//        ImprovedEncryptionChecksum: (...........0....) Client and server NOT support improved encryption checksum
+//        Reserved1:                  (......00000.....)
+//        CompressedBitMapDataFlag:   (.....1..........) No 8-UINT8 header is present for compressed bitmap data
+//        Reserved2:                  (00000...........)
+        (byte)0x0d, (byte)0x04,
+        
+        (byte)0x00, (byte)0x00, // updateCapabilityFlag: 0 (LE)
+        (byte)0x00, (byte)0x00, // remoteUnshareFlag: 0 (LE)
+        (byte)0x00, (byte)0x00, // generalCompressionLevel: 0 (LE)
+        (byte)0x00, // refreshRectSupport: FALSE (0)
+        (byte)0x00, // suppressOutputSupport: FALSE (0)
+        
+        //
+        // Bitmap capability set (28 bytes), see http://msdn.microsoft.com/en-us/library/cc240554.aspx
+        (byte)0x02, (byte)0x00, // capability set type: CAPSTYPE_BITMAP (2) (LE)
+        (byte)0x1c, (byte)0x00, // length of capability set: 28 bytes (LE)
+        (byte)0x10, (byte)0x00, // preferredBitsPerPixel: 16 bpp (LE)
+        (byte)0x01, (byte)0x00, // receive1BitPerPixel (ignored and SHOULD be set to TRUE (0x1)): TRUE (0x1) (LE)
+        (byte)0x01, (byte)0x00, // receive4BitsPerPixel (ignored and SHOULD be set to TRUE (0x1)): TRUE (0x1) (LE)
+        (byte)0x01, (byte)0x00, // receive8BitsPerPixel (ignored and SHOULD be set to TRUE (0x1)): TRUE (0x1) (LE)
+        (byte)0x00, (byte)0x04, // desktopWidth = 1024 pixels (LE)
+        (byte)0x00, (byte)0x03, // desktopHeight = 768 pixels (LE)
+        (byte)0x00, (byte)0x00, // Padding 2 bytes
+        (byte)0x00, (byte)0x00, // desktopResizeFlag: FALSE (0x0) (LE)
+        (byte)0x01, (byte)0x00, // bitmapCompressionFlag (must be set to TRUE (0x1)): TRUE (0x1) (LE)
+        (byte)0x00, // highColorFlags (field is ignored and SHOULD be set to zero): 0 
+        (byte)0x01, // drawingFlags: 0x1 TODO: padding, why 0x1 ???
+        (byte)0x01, (byte)0x00, // multipleRectangleSupport: TRUE (LE) 
+        (byte)0x00, (byte)0x00, // Padding 2 bytes
+        
+        //
+        // Order Capability Set (88 bytes), see http://msdn.microsoft.com/en-us/library/cc240556.aspx
+        (byte)0x03, (byte)0x00, // capability set type: CAPSTYPE_ORDER (3) (LE)
+        (byte)0x58, (byte)0x00, // length of capability set: 88 bytes (LE)
+        // terminalDescriptor = "" (16 bytes, UCS2)
+        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, // pad4octetsA 
+        (byte)0x01, (byte)0x00, // desktopSaveXGranularity (ignored): 1 (LE)
+        (byte)0x14, (byte)0x00, // desktopSaveYGranularity (ignored): 20 (LE)
+        (byte)0x00, (byte)0x00, // pad2octetsA (ignored)
+        (byte)0x01, (byte)0x00, // maximumOrderLevel: ORD_LEVEL_1_ORDERS (1) 
+        (byte)0x00, (byte)0x00, // number of fonts (ignored): 0 
+        (byte)0x4a, (byte)0x00, // orderFlags = 0x004a (LE), SOLIDPATTERNBRUSHONLY (0x40), ZEROBOUNDSDELTASSUPPORT (0x8, MUST), NEGOTIATEORDERSUPPORT (0x2, MUST)
+        // Order support: 32 bytes (no primary drawing orders are supported, so this array MUST be initialized to all zeros, use 0x01 for TRUE).
+        (byte)0x00, // TS_NEG_DSTBLT_INDEX: FALSE 
+        (byte)0x00, // TS_NEG_PATBLT_INDEX: FALSE  
+        (byte)0x00, // TS_NEG_SCRBLT_INDEX: FALSE 
+        (byte)0x00, // TS_NEG_MEMBLT_INDEX: FALSE  
+        (byte)0x00, // TS_NEG_MEM3BLT_INDEX: FALSE 
+        (byte)0x00, // TS_NEG_ATEXTOUT_INDEX: FALSE 
+        (byte)0x00, // TS_NEG_AEXTTEXTOUT_INDEX: FALSE
+        (byte)0x00, // TS_NEG_DRAWNINEGRID_INDEX: FALSE
+        (byte)0x00, // TS_NEG_LINETO_INDEX: FALSE
+        (byte)0x00, // TS_NEG_MULTI_DRAWNINEGRID_INDEX: FALSE 
+        (byte)0x00, // TS_NEG_OPAQUERECT_INDEX: FALSE
+        (byte)0x00, // TS_NEG_SAVEBITMAP_INDEX: FALSE
+        (byte)0x00, // TS_NEG_WTEXTOUT_INDEX: FALSE
+        (byte)0x00, // TS_NEG_MEMBLT_R2_INDEX: FALSE
+        (byte)0x00, // TS_NEG_MEM3BLT_R2_INDEX: FALSE
+        (byte)0x00, // TS_NEG_MULTIDSTBLT_INDEX: FALSE
+        (byte)0x00, // TS_NEG_MULTIPATBLT_INDEX: FALSE
+        (byte)0x00, // TS_NEG_MULTISCRBLT_INDEX: FALSE
+        (byte)0x00, // TS_NEG_MULTIOPAQUERECT_INDEX: FALSE 
+        (byte)0x00, // TS_NEG_FAST_INDEX_INDEX: FALSE 
+        (byte)0x00, // TS_NEG_POLYGON_SC_INDEX: FALSE 
+        (byte)0x00, // TS_NEG_POLYGON_CB_INDEX: FALSE 
+        (byte)0x00, // TS_NEG_POLYLINE_INDEX: TRUE 
+        (byte)0x00, // Unused: 0 
+        (byte)0x00, // TS_NEG_FAST_GLYPH_INDEX: FALSE 
+        (byte)0x00, // TS_NEG_ELLIPSE_SC_INDEX: FALSE 
+        (byte)0x00, // TS_NEG_ELLIPSE_CB_INDEX: FALSE
+        (byte)0x00, // TS_NEG_INDEX_INDEX: FALSE 
+        (byte)0x00, // TS_NEG_WEXTTEXTOUT_INDEX: FALSE 
+        (byte)0x00, // TS_NEG_WLONGTEXTOUT_INDEX: FALSE 
+        (byte)0x00, // TS_NEG_WLONGEXTTEXTOUT_INDEX: FALSE
+        (byte)0x00, // Unused: 0 
+        (byte)0x00, (byte)0x00, // Text flags (ignored): 0  (LE)
+        (byte)0x00, (byte)0x00, // Order support extra flags: 0 (LE)
+        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, // Padding 4 bytes
+        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, // Desktop save size (ignored): 0 (assumed to be 230400 bytes (480*480, 0x38400, LE))  
+        (byte)0x00, (byte)0x00, // Padding 2 bytes 
+        (byte)0x00, (byte)0x00, // Padding 2 bytes
+        (byte)0xe4, (byte)0x04, // Text ANSI Code Page: 1252,  ANSI - Latin I (0x04e4, LE) 
+        (byte)0x00, (byte)0x00, // Padding 2 bytes
+        
+        //
+        // Bitmap Cache Rev. 2 Capability Set (40 bytes), see http://msdn.microsoft.com/en-us/library/cc240560.aspx
+        (byte)0x13, (byte)0x00, // capability set type: CAPSTYPE_BITMAPCACHE_REV2 (19) (LE) 
+        (byte)0x28, (byte)0x00, // length of capability set: 40 bytes (LE)
+        (byte)0x00, (byte)0x00, // Cache flags: 0 (LE) 
+        (byte)0x00, // Padding 1 byte 
+        (byte)0x00, // Number of cell caches: 0 
+        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, // Bitmap cache0 cell info: 0 (LE) 
+        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, // Bitmap cache1 cell info: 0 (LE)
+        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, // Bitmap cache2 cell info: 0 (LE)
+        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, // Bitmap cache3 cell info: 0 (LE)
+        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, // Bitmap cache4 cell info: 0 (LE)
+        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, // Padding 12 bytes 
+        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, // Padding
+        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, // Padding
+        
+        //
+        // Color Table Cache Capability Set (8 bytes), see http://msdn.microsoft.com/en-us/library/cc241564.aspx
+        (byte)0x0a, (byte)0x00, // capability set type: CAPSTYPE_COLORCACHE (10) (LE)
+        (byte)0x08, (byte)0x00, // length of capability set: 8 bytes (LE)
+        (byte)0x06, (byte)0x00, // Color table cache size (must be ignored during capability exchange and is assumed to be 0x0006): 6 (LE)
+        (byte)0x00, (byte)0x00, // Padding 2 bytes
+        
+        //
+        // Window Activation Capability Set (12 bytes), see http://msdn.microsoft.com/en-us/library/cc240569.aspx
+        (byte)0x07, (byte)0x00, // capability set type: CAPSTYPE_ACTIVATION (7) (LE) 
+        (byte)0x0c, (byte)0x00, // length of capability set: 12 bytes (LE)
+        (byte)0x00, (byte)0x00, // helpKeyFlag (should be set to FALSE (0)): FALSE (0, LE)
+        (byte)0x00, (byte)0x00, // helpKeyIndexFlag (should be set to FALSE (0)): FALSE (0, LE)
+        (byte)0x00, (byte)0x00, // helpExtendedKeyFlag (should be set to FALSE (0)): FALSE (0, LE)
+        (byte)0x00, (byte)0x00, // windowManagerKeyFlag (should be set to FALSE (0)): FALSE (0, LE)
+        
+        //
+        // Control Capability Set (12 bytes), see http://msdn.microsoft.com/en-us/library/cc240568.aspx
+        (byte)0x05, (byte)0x00, // capability set type: CAPSTYPE_ACTIVATION (7)
+        (byte)0x0c, (byte)0x00, // length of capability set: 12 bytes (LE)
+        (byte)0x00, (byte)0x00, // controlFlags (should be set to 0): 0 (LE)
+        (byte)0x00, (byte)0x00, // remoteDetachFlag (should be set to 0): 0 (LE)
+        (byte)0x02, (byte)0x00, // controlInterest (should be set to CONTROLPRIORITY_NEVER): CONTROLPRIORITY_NEVER (2) (LE)
+        (byte)0x02, (byte)0x00, // detachInterest (should be set to CONTROLPRIORITY_NEVER): CONTROLPRIORITY_NEVER (2) (LE)
+        
+        //
+        // Pointer Capability Set (10 bytes), see http://msdn.microsoft.com/en-us/library/cc240562.aspx
+        (byte)0x08, (byte)0x00, // capability set type: CAPSTYPE_POINTER (8, LE)
+        (byte)0x0a, (byte)0x00, // length of capability set: 10 bytes (LE)
+        (byte)0x00, (byte)0x00, // colorPointerFlag: FALSE (LE)
+        (byte)0x00, (byte)0x00, // colorPointerCacheSize: 0 (LE)
+        (byte)0x14, (byte)0x00, // pointerCacheSize: 20 (LE)
+        
+        //
+        // Share Capability Set (8 bytes), see http://msdn.microsoft.com/en-us/library/cc240570.aspx
+        (byte)0x09, (byte)0x00, // capability set type: CAPSTYPE_SHARE (9, LE)
+        (byte)0x08, (byte)0x00, // length of capability set: 8 bytes (LE)
+        (byte)0x00, (byte)0x00, // nodeID (must be set to 0 by client): 0 (LE)
+        (byte)0x00, (byte)0x00, // Padding 2 bytes (LE)
+        
+        //
+        // Input Capability Set (88 bytes), see http://msdn.microsoft.com/en-us/library/cc240563.aspx
+        (byte)0x0d, (byte)0x00, // capability set type:  CAPSTYPE_INPUT (13, LE)
+        (byte)0x58, (byte)0x00, // length of capability set: 88 bytes (LE)
+        (byte)0x35, (byte)0x00, // inputFlags: 0x0035  (LE),  INPUT_FLAG_FASTPATH_INPUT2 (0x20), INPUT_FLAG_VKPACKET (0x10), INPUT_FLAG_MOUSEX (0x4), INPUT_FLAG_SCANCODES (0x1)
+        (byte)0x00, (byte)0x00, // Padding 2 bytes 
+        (byte)0x09, (byte)0x04, (byte)0x00, (byte)0x00, // keyboardLayout: "US" keyboard layout (0x000409, LE) 
+        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, // keyboardType: unknown (LE) 
+        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, // keyboardSubType: unknown (LE) 
+        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, // keyboardFunctionKey: unknown (LE)
+        // imeFileName: "", (64 bytes, including trailing NULL characters, UCS2) 
+        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, 
+        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, 
+        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, 
+        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, 
+        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+        
+        //
+        // Brush Capability Set (8 bytes), see http://msdn.microsoft.com/en-us/library/cc240564.aspx
+        (byte)0x0f, (byte)0x00, // capability set type: CAPSTYPE_BRUSH (15, LE)
+        (byte)0x08, (byte)0x00, // length of capability set: 8 bytes (LE)
+        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, // brushSupportLevel: BRUSH_DEFAULT (0x0, LE)
+        
+        //
+        // Sound Capability Set (8 bytes), see http://msdn.microsoft.com/en-us/library/cc240552.aspx
+        (byte)0x0c, (byte)0x00, // capability set type: CAPSTYPE_SOUND (12, LE)
+        (byte)0x08, (byte)0x00, // length of capability set: 8 bytes (LE)
+        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, // soundFlags: 0x0000 (LE) // SOUND_FLAG_BEEPS (0x1)   
+        
+        //
+        // Font Capability Set (8 bytes), see http://msdn.microsoft.com/en-us/library/cc240571.aspx
+        (byte)0x0e, (byte)0x00, 
+        (byte)0x08, (byte)0x00, 
+        (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x00, 
+        
+        //
+        // Offscreen Bitmap Cache Capability Set (12 bytes), see http://msdn.microsoft.com/en-us/library/cc240550.aspx
+        (byte)0x11, (byte)0x00, // capability set type: CAPSTYPE_OFFSCREENCACHE (17, LE)
+        (byte)0x0c, (byte)0x00, // length of capability set: 12 bytes (LE)
+        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, // offscreenSupportLevel: FALSE (LE) 
+        (byte)0x00, (byte)0x00, // offscreenCacheSize: 0 (LE)
+        (byte)0x00, (byte)0x00, // offscreenCacheEntries: 0 (LE)
+        
+        //
+        // Glyph Cache Capability Set (52 bytes), see http://msdn.microsoft.com/en-us/library/cc240565.aspx
+        (byte)0x10, (byte)0x00, // capability set type: CAPSTYPE_OFFSCREENCACHE (16, LE)
+        (byte)0x34, (byte)0x00, // length of capability set: 52 bytes (LE)
+        // Glyph Cache (40 bytes)
+        (byte)0xfe, (byte)0x00, // CacheEntries: 254 (LE) 
+        (byte)0x04, (byte)0x00, // CacheMaximumCellSize: 4 (LE)
+        (byte)0xfe, (byte)0x00, // CacheEntries: 254 (LE)
+        (byte)0x04, (byte)0x00, // CacheMaximumCellSize: 4 (LE)
+        (byte)0xfe, (byte)0x00, // CacheEntries: 254 (LE)
+        (byte)0x08, (byte)0x00, // CacheMaximumCellSize: 4 (LE)
+        (byte)0xfe, (byte)0x00, // CacheEntries: 254 (LE)
+        (byte)0x08, (byte)0x00, // CacheMaximumCellSize: 4 (LE)
+        (byte)0xfe, (byte)0x00, // CacheEntries: 254 (LE)
+        (byte)0x10, (byte)0x00, // CacheMaximumCellSize: 4 (LE)
+        (byte)0xfe, (byte)0x00, // CacheEntries: 254 (LE)
+        (byte)0x20, (byte)0x00, // CacheMaximumCellSize: 4 (LE)
+        (byte)0xfe, (byte)0x00, // CacheEntries: 254 (LE)
+        (byte)0x40, (byte)0x00, // CacheMaximumCellSize: 4 (LE)
+        (byte)0xfe, (byte)0x00, // CacheEntries: 254 (LE)
+        (byte)0x80, (byte)0x00, // CacheMaximumCellSize: 4 (LE)
+        (byte)0xfe, (byte)0x00, // CacheEntries: 254 (LE)
+        (byte)0x00, (byte)0x01, // CacheMaximumCellSize: 4 (LE)
+        (byte)0x40, (byte)0x00, // CacheEntries: 64 (LE)
+        (byte)0x00, (byte)0x08, // CacheMaximumCellSize: 2048 (LE)
+        // FragCache
+        (byte)0x00, (byte)0x01, // CacheEntries: 256 (LE)
+        (byte)0x00, (byte)0x01, // CacheMaximumCellSize: 256 (LE)
+        // 
+        (byte)0x00, (byte)0x00, // GlyphSupportLevel: GLYPH_SUPPORT_NONE (0x0, LE)  
+        (byte)0x00, (byte)0x00, // Padding 2 bytes   
+    };
+    /* @formatter:on */
+
+        RdpState rdpState = new RdpState();
+        ScreenDescription screenDescription = new ScreenDescription();
+        screenDescription.setFramebufferSize(1024, 768);
+
+        rdpState.serverShareId = 0x000103ea;
+
+        MockSource source = new MockSource("source", ByteBuffer.convertByteArraysToByteBuffers(new byte[] {}));
+        Element confirm_active = new ClientConfirmActivePDU("confirm_active", screenDescription, rdpState);
+        Element sink = new MockSink("sink", ByteBuffer.convertByteArraysToByteBuffers(packet));
+
+        Pipeline pipeline = new PipelineImpl("test");
+        pipeline.add(source, confirm_active, sink);
+        pipeline.link("source", "confirm_active", "sink");
+        pipeline.runMainLoop("source", STDOUT, false, false);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4f3611f9/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ClientFastPathPDU.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ClientFastPathPDU.java b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ClientFastPathPDU.java
new file mode 100755
index 0000000..108429c
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ClientFastPathPDU.java
@@ -0,0 +1,55 @@
+// 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;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/cc240589.aspx
+ */
+public class ClientFastPathPDU extends BaseElement {
+
+    public ClientFastPathPDU(String id) {
+        super(id);
+    }
+
+    @Override
+    public void handleData(ByteBuffer buf, Link link) {
+        if (verbose)
+            System.out.println("[" + this + "] INFO: Data received: " + buf + ".");
+
+        if (buf.length > 32767 - 3)
+            throw new RuntimeException("Packet is too long: " + buf + ".");
+
+        ByteBuffer data = new ByteBuffer(6);
+
+        // FastPath, 1 event, no checksum, not encrypted
+        data.writeByte(0x4);
+
+        // Length of full packet, including length field, in network order.
+        // Topmost bit of first byte indicates that field has 2 bytes
+        data.writeShort((1 + 2 + buf.length) | 0x8000);
+        data.trimAtCursor();
+
+        buf.prepend(data);
+
+        pushDataToAllOuts(buf);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4f3611f9/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ClientInfoPDU.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ClientInfoPDU.java b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ClientInfoPDU.java
new file mode 100755
index 0000000..7334d7f
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ClientInfoPDU.java
@@ -0,0 +1,456 @@
+// 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;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/cc240475.aspx
+ */
+public class ClientInfoPDU extends OneTimeSwitch {
+
+    public static final int INFO_MOUSE = 0x1;
+    public static final int INFO_DISABLECTRLALTDEL = 0x2;
+    public static final int INFO_UNICODE = 0x10;
+
+    public static final int INFO_MAXIMIZESHELL = 0x20;
+    public static final int INFO_LOGONNOTIFY = 0x40;
+    public static final int INFO_ENABLEWINDOWSKEY = 0x100;
+    public static final int INFO_MOUSE_HAS_WHEEL = 0x00020000;
+    public static final int INFO_NOAUDIOPLAYBACK = 0x00080000;
+
+    public static final int PERF_DISABLE_WALLPAPER = 0x1;
+    public static final int PERF_DISABLE_FULLWINDOWDRAG = 0x2;
+    public static final int PERF_DISABLE_MENUANIMATIONS = 0x4;
+
+    protected byte[] userName = "".getBytes(RdpConstants.CHARSET_16);
+    protected byte[] password = "".getBytes(RdpConstants.CHARSET_16); // No effect
+    protected byte[] alternateShell = "".getBytes(RdpConstants.CHARSET_16);
+    protected byte[] domain = "".getBytes(RdpConstants.CHARSET_16);
+    protected byte[] workingDir = "".getBytes(RdpConstants.CHARSET_16);
+    protected byte[] clientAddress = "192.168.0.100".getBytes(RdpConstants.CHARSET_16);
+    protected byte[] clientDir = "C:\\Windows\\System32\\mstscax.dll".getBytes(RdpConstants.CHARSET_16);
+
+    protected String standardTimeZoneName = "EET, Standard Time";
+    protected String daylightTimeZoneName = "EET, Summer Time";
+    protected int standardTimeZoneBias = 0; /* in minutes */
+    protected int daylightTimeZoneBias = 60; /* in minutes */
+
+    public ClientInfoPDU(String id, String userName) {
+        super(id);
+        this.userName = userName.getBytes(RdpConstants.CHARSET_16);
+    }
+
+    @Override
+    protected void handleOneTimeData(ByteBuffer buf, Link link) {
+        if (buf == null)
+            return;
+
+        throw new RuntimeException("Unexpected packet: " + buf + ".");
+    }
+
+    @Override
+    protected void onStart() {
+        super.onStart();
+
+        // Length of packet
+        ByteBuffer buf = new ByteBuffer(1024, true);
+
+        // MCS Send Data Request PDU 
+        buf.writeByte(0x64);
+
+        // Initiator: 0x03 + 1001 = 1004
+        buf.writeShort(3);
+
+        // Channel ID: 1003
+        buf.writeShort(1003);
+
+        // Data priority: high, segmentation: begin | end (0x40 | 0x20 | 0x10 = 0x70)
+        buf.writeByte(0x70);
+
+        // User data length: (variable length field)
+        int length = 224 + userName.length + password.length + alternateShell.length + domain.length + workingDir.length + clientAddress.length + clientDir.length;
+        buf.writeShort(length | 0x8000);
+
+        // Flags: SEC_INFO_PKT (0x4000)
+        buf.writeShort(0x4000);
+
+        // TS_SECURITY_HEADER::flagsHi - ignored
+        buf.writeShort(0x0000);
+
+        // Codepage: 0 (UNKNOWN, LE) (use  0x04090409  (1033,1033) for EN_US)  
+        buf.writeIntLE(0x0000);
+
+        // Flags
+        buf.writeIntLE(INFO_MOUSE | INFO_DISABLECTRLALTDEL | INFO_UNICODE |
+                INFO_MAXIMIZESHELL | INFO_LOGONNOTIFY | INFO_ENABLEWINDOWSKEY |
+                INFO_MOUSE_HAS_WHEEL | INFO_NOAUDIOPLAYBACK);
+
+        //
+        // Lengths
+        //
+
+        // cbDomain length: 0 bytes (LE) (NOT including size of mandatory NULL terminator)
+        buf.writeShortLE(domain.length);
+
+        // cbUserName length: 16 bytes (0x10, LE) (NOT including size of mandatory NULL terminator)
+        buf.writeShortLE(userName.length);
+
+        // cbPassword length: (LE) (NOT including size of mandatory NULL terminator)
+        buf.writeShortLE(password.length);
+
+        // cbAlternateShell:  (LE) (NOT including size of mandatory NULL terminator)
+        buf.writeShortLE(alternateShell.length);
+
+        // cbWorkingDir: (LE) (NOT including size of mandatory NULL terminator)
+        buf.writeShortLE(workingDir.length);
+
+        //
+        // Values
+        //
+
+        // Domain: (UCS2), see cbDomain
+        buf.writeBytes(domain);
+        buf.writeShort(0);
+
+        // User name: (UCS2), see cbUserName
+        buf.writeBytes(userName);
+        buf.writeShort(0);
+
+        // Password: (UCS2), see cbPassword
+        buf.writeBytes(password);
+        buf.writeShort(0);
+
+        // Alternate shell: (UCS2), see cbAlternateShell
+        buf.writeBytes(alternateShell);
+        buf.writeShort(0);
+
+        // Working directory: (UCS2), see cbWorkingDir
+        buf.writeBytes(workingDir);
+        buf.writeShort(0);
+
+        // Client address family: 2 (AF_INET, LE)
+        buf.writeShortLE(2);
+
+        // cbClientAddress: ( LE) (including the size of the mandatory NULL terminator)
+        buf.writeShortLE(clientAddress.length + 2);
+
+        // Client address: (UCS2) 
+        buf.writeBytes(clientAddress);
+        buf.writeShort(0);
+
+        // cbClientDir: 64 bytes (0x40, LE) (including the size of the mandatory NULL terminator)
+        buf.writeShortLE(clientDir.length + 2);
+
+        // Client directory: (UCS2)
+        buf.writeBytes(clientDir);
+        buf.writeShort(0);
+
+        //
+        // Client time zone:
+        //
+
+        // Bias: 0 minutes (LE)
+        buf.writeIntLE(0);
+
+        // Standard name: "EET, Standard Time" (fixed string: 64 bytes, UCS2)
+        buf.writeFixedString(62, standardTimeZoneName, RdpConstants.CHARSET_16);
+        buf.writeShort(0);
+
+        // Standard date
+        buf.writeBytes(new byte[] {
+                // wYear: 0 (LE)
+                (byte)0x00, (byte)0x00,
+                // wMonth: unknown (LE)
+                (byte)0x00, (byte)0x00,
+                // wDayOfWeek: Sunday (LE)
+                (byte)0x00, (byte)0x00,
+                // wDay: unknown (LE)
+                (byte)0x00, (byte)0x00,
+                // wHour: 0 (LE)
+                (byte)0x00, (byte)0x00,
+                // wMinute: 0 (LE)
+                (byte)0x00, (byte)0x00,
+                // wSecond: 0 (LE)
+                (byte)0x00, (byte)0x00,
+                // wMilliseconds: 0
+                (byte)0x00, (byte)0x00,
+
+        });
+
+        // StandardBias: 0 minutes (LE)
+        buf.writeIntLE(standardTimeZoneBias);
+
+        // Daylight name: "EET, Summer Time" (fixed string: 64 bytes, UCS2)
+        buf.writeFixedString(62, daylightTimeZoneName, RdpConstants.CHARSET_16);
+        buf.writeShort(0);
+
+        // Daylight date
+        buf.writeBytes(new byte[] {
+                // wYear: 0 (LE)
+                (byte)0x00, (byte)0x00,
+                // wMonth: unknown (LE)
+                (byte)0x00, (byte)0x00,
+                // wDayOfWeek: Sunday (LE)
+                (byte)0x00, (byte)0x00,
+                // wDay: unknown (LE)
+                (byte)0x00, (byte)0x00,
+                // wHour: 0 (LE)
+                (byte)0x00, (byte)0x00,
+                // wMinute: 0 (LE)
+                (byte)0x00, (byte)0x00,
+                // wSecond: 0 (LE)
+                (byte)0x00, (byte)0x00,
+                // wMilliseconds: 0
+                (byte)0x00, (byte)0x00,
+
+        });
+
+        // Daylight bias: 60 minutes (LE)
+        buf.writeIntLE(daylightTimeZoneBias);
+
+        // Client session ID: 0x00000000 (LE)
+        buf.writeIntLE(0);
+
+        // Performance flags: 0x7 (LE) = PERF_DISABLE_WALLPAPER (0x1), PERF_DISABLE_FULLWINDOWDRAG (0x2), PERF_DISABLE_MENUANIMATIONS (0x4)
+        buf.writeIntLE(PERF_DISABLE_WALLPAPER | PERF_DISABLE_FULLWINDOWDRAG | PERF_DISABLE_MENUANIMATIONS);
+
+        // cbAutoReconnectCookie: 0 bytes (LE)
+        buf.writeShortLE(0);
+
+        // Trim buffer to actual length of data written
+        buf.trimAtCursor();
+
+        pushDataToOTOut(buf);
+
+        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");
+
+        /* @formatter:off */
+    byte[] packet = new byte[] {
+        
+        // TPKT
+        (byte) 0x03, (byte) 0x00,
+
+        // TPKT length: 343 bytes
+        (byte) 0x01, (byte) 0x57,
+        
+        // X224 Data PDU
+        (byte) 0x02, (byte) 0xf0, (byte) 0x80,
+        
+        
+        // MCS Send Data Request PDU 
+        (byte) 0x64, 
+        
+        // Initiator: 0x03 + 1001 = 1004
+        (byte) 0x00, (byte) 0x03,
+        
+        // Channel ID: 1003 (IO Channel)
+        (byte) 0x03, (byte) 0xeb,
+        
+        // Data priority: high, segmentation: begin | end (0x40 | 0x20 | 0x10 = 0x70)
+        (byte) 0x70, 
+        
+        // User data length: 328  (0x148) bytes, variable length field 
+        (byte) 0x81, (byte) 0x48, 
+        
+        // Flags: SEC_INFO_PKT (0x4000)
+        (byte) 0x40, (byte) 0x00, 
+
+        // TS_SECURITY_HEADER::flagsHi - ignored
+        (byte) 0x00, (byte) 0x00,
+        
+        // Codepage: 0 (UNKNOWN, LE) (use  0x04090409  (1033,1033) for EN_US)  
+        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 
+        
+        // Flags: 0xa0173 (LE), INFO_MOUSE (0x1), INFO_DISABLECTRLALTDEL (0x2), INFO_UNICODE (0x10), 
+        // INFO_MAXIMIZESHELL (0x20), INFO_LOGONNOTIFY (0x40), INFO_ENABLEWINDOWSKEY (0x100),
+        // INFO_MOUSE_HAS_WHEEL (0x00020000), INFO_NOAUDIOPLAYBACK (0x00080000), 
+        (byte) 0x73, (byte) 0x01, (byte) 0x0a, (byte) 0x00, 
+        
+        // Lengths
+        
+        // cbDomain length: 0 bytes (LE) (NOT including size of mandatory NULL terminator)
+        (byte) 0x00, (byte) 0x00, 
+        
+        // cbUserName length: 16 bytes (0x10, LE) (NOT including size of mandatory NULL terminator)
+        (byte) 0x10, (byte) 0x00,
+        
+        // cbPassword length: 0 bytes (LE) (NOT including size of mandatory NULL terminator)
+        (byte) 0x00, (byte) 0x00,
+        
+        // cbAlternateShell:  0 bytes (LE) (NOT including size of mandatory NULL terminator)
+        (byte) 0x00, (byte) 0x00, 
+        
+        // cbWorkingDir: 0 bytes (LE) (NOT including size of mandatory NULL terminator)
+        (byte) 0x00, (byte) 0x00,
+        
+        // Values
+        
+        // Domain: "" (UCS2), see cbDomain
+        (byte) 0x00, (byte) 0x00, 
+        
+        // User name: "vlisivka" (UCS2), see cbUserName
+        (byte) 0x76, (byte) 0x00, (byte) 0x6c, (byte) 0x00, (byte) 0x69, (byte) 0x00, (byte) 0x73, (byte) 0x00, 
+        (byte) 0x69, (byte) 0x00, (byte) 0x76, (byte) 0x00, (byte) 0x6b, (byte) 0x00, (byte) 0x61, (byte) 0x00, 
+        (byte) 0x00, (byte) 0x00, 
+        
+        // Password: "" (UCS2), see cbPassword
+        (byte) 0x00, (byte) 0x00, 
+        
+        // Alternate shell: "" (UCS2), see cbAlternateShell
+        (byte) 0x00, (byte) 0x00, 
+        
+        // Working directory: "" (UCS2), see cbWorkingDir
+        (byte) 0x00, (byte) 0x00, 
+        
+        // Client address family: 2 (AF_INET, LE)
+        (byte) 0x02, (byte) 0x00, 
+        
+        // cbClientAddress = 28 bytes (0x1c, LE) (including the size of the mandatory NULL terminator)
+        (byte) 0x1c, (byte) 0x00, 
+        
+        // Client address: "192.168.0.100" (UCS2) 
+        (byte) 0x31, (byte) 0x00, (byte) 0x39, (byte) 0x00, (byte) 0x32, (byte) 0x00, (byte) 0x2e, (byte) 0x00,
+        (byte) 0x31, (byte) 0x00, (byte) 0x36, (byte) 0x00, (byte) 0x38, (byte) 0x00, (byte) 0x2e, (byte) 0x00,
+        (byte) 0x30, (byte) 0x00, (byte) 0x2e, (byte) 0x00, (byte) 0x31, (byte) 0x00, (byte) 0x30, (byte) 0x00, 
+        (byte) 0x30, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+        
+        // cbClientDir: 64 bytes (0x40, LE) (including the size of the mandatory NULL terminator)
+        (byte) 0x40, (byte) 0x00,
+        
+        // Client directory: "C:\Windows\System32\mstscax.dll" (UCS2)
+        (byte) 0x43, (byte) 0x00, (byte) 0x3a, (byte) 0x00, (byte) 0x5c, (byte) 0x00, (byte) 0x57, (byte) 0x00, 
+        (byte) 0x69, (byte) 0x00, (byte) 0x6e, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0x6f, (byte) 0x00, 
+        (byte) 0x77, (byte) 0x00, (byte) 0x73, (byte) 0x00, (byte) 0x5c, (byte) 0x00, (byte) 0x53, (byte) 0x00, 
+        (byte) 0x79, (byte) 0x00, (byte) 0x73, (byte) 0x00, (byte) 0x74, (byte) 0x00, (byte) 0x65, (byte) 0x00, 
+        (byte) 0x6d, (byte) 0x00, (byte) 0x33, (byte) 0x00, (byte) 0x32, (byte) 0x00, (byte) 0x5c, (byte) 0x00, 
+        (byte) 0x6d, (byte) 0x00, (byte) 0x73, (byte) 0x00, (byte) 0x74, (byte) 0x00, (byte) 0x73, (byte) 0x00, 
+        (byte) 0x63, (byte) 0x00, (byte) 0x61, (byte) 0x00, (byte) 0x78, (byte) 0x00, (byte) 0x2e, (byte) 0x00, 
+        (byte) 0x64, (byte) 0x00, (byte) 0x6c, (byte) 0x00, (byte) 0x6c, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+        
+        //
+        // Client time zone:
+        
+        // Bias: 0 minutes (LE)
+        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+        
+        // Standard name: "EET, Standard Time" (fixed string: 64 bytes, UCS2)
+        (byte) 0x45, (byte) 0x00, (byte) 0x45, (byte) 0x00, (byte) 0x54, (byte) 0x00, (byte) 0x2c, (byte) 0x00, 
+        (byte) 0x20, (byte) 0x00, (byte) 0x53, (byte) 0x00, (byte) 0x74, (byte) 0x00, (byte) 0x61, (byte) 0x00, 
+        (byte) 0x6e, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0x61, (byte) 0x00, (byte) 0x72, (byte) 0x00, 
+        (byte) 0x64, (byte) 0x00, (byte) 0x20, (byte) 0x00, (byte) 0x54, (byte) 0x00, (byte) 0x69, (byte) 0x00, 
+        (byte) 0x6d, (byte) 0x00, (byte) 0x65, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 
+        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 
+        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 
+        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+        
+        //
+        // Standard date
+        // wYear: 0 (LE)
+        (byte) 0x00, (byte) 0x00, 
+        // wMonth: unknown (LE)
+        (byte) 0x00, (byte) 0x00, 
+        // wDayOfWeek: Sunday (LE)
+        (byte) 0x00, (byte) 0x00, 
+        // wDay: unknown (LE)
+        (byte) 0x00, (byte) 0x00, 
+        // wHour: 0 (LE)
+        (byte) 0x00, (byte) 0x00, 
+        // wMinute: 0 (LE)
+        (byte) 0x00, (byte) 0x00, 
+        // wSecond: 0 (LE)
+        (byte) 0x00, (byte) 0x00, 
+        // wMilliseconds: 0
+        (byte) 0x00, (byte) 0x00,
+        
+        // StandardBias: 0 minutes (LE)
+        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 
+        
+        // Daylight name: "EET, Summer Time" (fixed string: 64 bytes, UCS2)
+        (byte) 0x45, (byte) 0x00, (byte) 0x45, (byte) 0x00, (byte) 0x54, (byte) 0x00, (byte) 0x2c, (byte) 0x00, 
+        (byte) 0x20, (byte) 0x00, (byte) 0x53, (byte) 0x00, (byte) 0x75, (byte) 0x00, (byte) 0x6d, (byte) 0x00, 
+        (byte) 0x6d, (byte) 0x00, (byte) 0x65, (byte) 0x00, (byte) 0x72, (byte) 0x00, (byte) 0x20, (byte) 0x00, 
+        (byte) 0x54, (byte) 0x00, (byte) 0x69, (byte) 0x00, (byte) 0x6d, (byte) 0x00, (byte) 0x65, (byte) 0x00, 
+        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 
+        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 
+        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 
+        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 
+        
+        // Daylight date
+        // wYear: 0 (LE)
+        (byte) 0x00, (byte) 0x00, 
+        // wMonth: unknown (LE)
+        (byte) 0x00, (byte) 0x00,
+        // wDayOfWeek: Sunday (LE)
+        (byte) 0x00, (byte) 0x00,
+        // wDay: unknown (LE)
+        (byte) 0x00, (byte) 0x00,
+        // wHour: 0 (LE)
+        (byte) 0x00, (byte) 0x00,
+        // wMinute: 0 (LE)
+        (byte) 0x00, (byte) 0x00,
+        // wSecond: 0 (LE)
+        (byte) 0x00, (byte) 0x00,
+        // wMilliseconds: 0
+        (byte) 0x00, (byte) 0x00,
+        
+        // Daylight bias: 60 minutes (LE)
+        (byte) 0x3c, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+        
+        
+        // Client session ID: 0x00000000 (LE)
+        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 
+        
+        // Performance flags: 0x7 (LE) = PERF_DISABLE_WALLPAPER (0x1), PERF_DISABLE_FULLWINDOWDRAG (0x2), PERF_DISABLE_MENUANIMATIONS (0x4)
+        (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, 
+        
+        // cbAutoReconnectCookie: 0 bytes (LE)
+        (byte) 0x00, (byte) 0x00, 
+    };
+    /* @formatter:on */
+
+        MockSource source = new MockSource("source", ByteBuffer.convertByteArraysToByteBuffers(new byte[] {1, 2, 3}));
+        Element client_info = new ClientInfoPDU("client_info", "vlisivka");
+        Element x224 = new ClientX224DataPDU("x224");
+        Element tpkt = new ClientTpkt("tpkt");
+        Element sink = new MockSink("sink", ByteBuffer.convertByteArraysToByteBuffers(packet));
+        Element mainSink = new MockSink("mainSink", ByteBuffer.convertByteArraysToByteBuffers(new byte[] {1, 2, 3}));
+
+        Pipeline pipeline = new PipelineImpl("test");
+        pipeline.add(source, client_info, x224, tpkt, sink, mainSink);
+        pipeline.link("source", "client_info", "mainSink");
+        pipeline.link("client_info >" + OTOUT, "x224", "tpkt", "sink");
+        pipeline.runMainLoop("source", STDOUT, false, false);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4f3611f9/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ClientMCSAttachUserRequest.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ClientMCSAttachUserRequest.java b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ClientMCSAttachUserRequest.java
new file mode 100755
index 0000000..dbe8bd1
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ClientMCSAttachUserRequest.java
@@ -0,0 +1,103 @@
+// 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;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/cc240684.aspx
+ */
+public class ClientMCSAttachUserRequest extends OneTimeSwitch {
+
+    public ClientMCSAttachUserRequest(String id) {
+        super(id);
+    }
+
+    @Override
+    protected void handleOneTimeData(ByteBuffer buf, Link link) {
+        if (buf == null)
+            return;
+
+        throw new RuntimeException("Unexpected packet: " + buf + ".");
+    }
+
+    @Override
+    protected void onStart() {
+        super.onStart();
+
+        int length = 1;
+        ByteBuffer buf = new ByteBuffer(length, true);
+
+        buf.writeByte(0x28); // AttachUserRequest
+
+        pushDataToOTOut(buf);
+
+        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");
+
+        /* @formatter:off */
+    byte[] packet = new byte[] {
+
+        0x03, 0x00, 0x00, 0x08,  //  TPKT Header (length = 8 bytes)
+        0x02, (byte) 0xf0, (byte) 0x80,  //  X.224 Data TPDU
+        
+        // PER encoded (ALIGNED variant of BASIC-PER) PDU contents:
+        0x28, 
+        
+        // 0x28:
+        // 0 - --\
+        // 0 -   |
+        // 1 -   | CHOICE: From DomainMCSPDU select attachUserRequest (10) 
+        // 0 -   | of type AttachUserRequest
+        // 1 -   |
+        // 0 - --/
+        // 0 - padding
+        // 0 - padding
+
+    };
+    /* @formatter:on */
+
+        MockSource source = new MockSource("source", ByteBuffer.convertByteArraysToByteBuffers(new byte[] {1, 2, 3}));
+        Element todo = new ClientMCSAttachUserRequest("TODO");
+        Element x224 = new ClientX224DataPDU("x224");
+        Element tpkt = new ClientTpkt("tpkt");
+        Element sink = new MockSink("sink", ByteBuffer.convertByteArraysToByteBuffers(packet));
+        Element mainSink = new MockSink("mainSink", ByteBuffer.convertByteArraysToByteBuffers(new byte[] {1, 2, 3}));
+
+        Pipeline pipeline = new PipelineImpl("test");
+        pipeline.add(source, todo, x224, tpkt, sink, mainSink);
+        pipeline.link("source", "TODO", "mainSink");
+        pipeline.link("TODO >" + OTOUT, "x224", "tpkt", "sink");
+        pipeline.runMainLoop("source", STDOUT, false, false);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4f3611f9/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ClientMCSChannelJoinRequest_ServerMCSChannelConfirmPDUs.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ClientMCSChannelJoinRequest_ServerMCSChannelConfirmPDUs.java b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ClientMCSChannelJoinRequest_ServerMCSChannelConfirmPDUs.java
new file mode 100755
index 0000000..59dd233
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/rdp/ClientMCSChannelJoinRequest_ServerMCSChannelConfirmPDUs.java
@@ -0,0 +1,223 @@
+// 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;
+
+/**
+ * The MCS Channel Join Request PDUs are sent sequentially. The first PDU is
+ * sent after receiving the MCS Attach User Confirm PDU and subsequent PDUs are
+ * sent after receiving the MCS Channel Join Confirm PDU for the previous
+ * request. Sending of the MCS Channel Join Request PDUs MUST continue until all
+ * channels have been successfully joined.
+ * 
+ * @see http://msdn.microsoft.com/en-us/library/cc240686.aspx
+ */
+public class ClientMCSChannelJoinRequest_ServerMCSChannelConfirmPDUs extends OneTimeSwitch {
+
+    private static final int MCS_CHANNEL_CONFIRM_PDU = 15;
+
+    protected int[] channels;
+    protected int channelRequestsSent = 0;
+
+    protected RdpState state;
+
+    public ClientMCSChannelJoinRequest_ServerMCSChannelConfirmPDUs(String id, int[] channels, RdpState state) {
+        super(id);
+        this.channels = channels;
+        this.state = state;
+    }
+
+    @Override
+    protected void handleOneTimeData(ByteBuffer buf, Link link) {
+        if (buf == null)
+            return;
+
+        // Parse channel confirm response
+        int typeAndFlags = buf.readUnsignedByte();
+        int type = typeAndFlags >> 2;
+        // int flags = typeAndFlags & 0x3;
+
+        if (type != MCS_CHANNEL_CONFIRM_PDU)
+            throw new RuntimeException("[" + this + "] ERROR: Incorrect type of MCS AttachUserConfirm PDU. Expected value: 15, actual value: " + type + ", data: " + buf + ".");
+
+        int rtSuccess = buf.readUnsignedByte() >> 4;
+        if (rtSuccess != 0)
+            throw new RuntimeException("[" + this + "] ERROR: Cannot connect to channel: request failed. Error code: " + rtSuccess + ", channel ID: "
+                    + channels[channelRequestsSent - 1]
+                    + ", data: " + buf + ".");
+
+        // Initiator and requested fields MAY be ignored, however, the channelId
+        // field MUST be examined. If the value of the channelId field does not
+        // correspond with the value of the channelId field sent in the previous MCS
+        // Channel Join Request PDU the connection SHOULD be dropped.
+
+        // Initiator: 1007 (6+1001)
+        // int initator=buf.readUnsignedShort();
+        buf.skipBytes(2);
+
+        // Requested channel
+        // int requestedChannel=buf.readUnsignedShort();
+        buf.skipBytes(2);
+
+        // Actual channel
+        int actualChannel = buf.readUnsignedShort();
+        if (actualChannel != channels[channelRequestsSent - 1])
+            throw new RuntimeException("Unexpeceted channeld ID returned. Expected channeld ID: " + channels[channelRequestsSent - 1] + ", actual channel ID: "
+                    + actualChannel + ", data: " + buf + ".");
+
+        state.channelJoined(actualChannel);
+
+        buf.unref();
+
+        if (channelRequestsSent < channels.length)
+            sendChannelRequest(channels[channelRequestsSent++]);
+        else
+            switchOff();
+    }
+
+    @Override
+    protected void onStart() {
+        super.onStart();
+
+        sendChannelRequest(channels[channelRequestsSent++]);
+
+        // Switch off after receiving response(s)
+    }
+
+    private void sendChannelRequest(int channel) {
+        ByteBuffer buf = new ByteBuffer(5, true);
+
+        buf.writeByte(0x38); // Channel Join request
+
+        buf.writeShort(state.serverUserChannelId - 1001); // ChannelJoinRequest::initiator: 1004
+        buf.writeShort(channel);
+
+        pushDataToOTOut(buf);
+    }
+
+    /**
+     * Example.
+     * 
+     * @see http://msdn.microsoft.com/en-us/library/cc240834.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");
+
+        /* @formatter:off */
+    byte[] clientRequestPacket = new byte[] {
+        0x03, 0x00, 0x00, 0x0c,  //  TPKT Header (length = 12 bytes)
+        0x02, (byte) 0xf0, (byte) 0x80,  //  X.224 Data TPDU
+        
+        // PER encoded (ALIGNED variant of BASIC-PER) PDU contents:
+        0x38, 0x00, 0x03, 0x03, (byte) 0xef, 
+
+         // 0x38:
+         // 0 - --\
+         // 0 -   |
+         // 1 -   | CHOICE: From DomainMCSPDU select channelJoinRequest (14) 
+         // 1 -   | of type ChannelJoinRequest
+         // 1 -   |
+         // 0 - --/
+         // 0 - padding
+         // 0 - padding
+
+         // 0x00:
+         // 0 - --\
+         // 0 -   | 
+         // 0 -   | 
+         // 0 -   | 
+         // 0 -   | 
+         // 0 -   | 
+         // 0 -   | 
+         // 0 -   | 
+         //       | ChannelJoinRequest::initiator = 0x03 + 1001 = 1004
+         // 0x03: |
+         // 0 -   | 
+         // 0 -   | 
+         // 0 -   | 
+         // 0 -   | 
+         // 0 -   | 
+         // 1 -   | 
+         // 1 -   | 
+         // 0 - --/
+
+         // 0x03:
+         // 0 - --\
+         // 0 -   |
+         // 0 -   |
+         // 0 -   |
+         // 0 -   |
+         // 0 -   |
+         // 1 -   |
+         // 1 -   |
+         //       | ChannelJoinRequest::channelId = 0x03ef = 1007
+         // 0xef: |
+         // 1 -   |
+         // 1 -   |
+         // 1 -   |
+         // 0 -   |
+         // 1 -   |
+         // 1 -   |
+         // 1 -   |
+         // 1 - --/
+    };
+    
+    byte[] serverResponsePacket = new byte[] {
+        // MCS Channel Confirm
+    (byte)0x3e, 
+    
+    // result: rt-successful (0)
+    (byte)0x00, 
+    
+    // Initiator: 1007 (6+1001)
+    (byte)0x00, (byte)0x06, 
+    
+    // Requested channel
+    (byte)0x03, (byte)0xef,
+    
+    // Actual channel
+    (byte)0x03, (byte)0xef,
+    };
+    /* @formatter:on */
+
+        RdpState rdpState = new RdpState();
+        rdpState.serverUserChannelId = 1004;
+        MockSource source = new MockSource("source", ByteBuffer.convertByteArraysToByteBuffers(serverResponsePacket, new byte[] {1, 2, 3}));
+        Element todo = new ClientMCSChannelJoinRequest_ServerMCSChannelConfirmPDUs("channels", new int[] {1007}, rdpState);
+        Element x224 = new ClientX224DataPDU("x224");
+        Element tpkt = new ClientTpkt("tpkt");
+        Element sink = new MockSink("sink", ByteBuffer.convertByteArraysToByteBuffers(clientRequestPacket));
+        Element mainSink = new MockSink("mainSink", ByteBuffer.convertByteArraysToByteBuffers(new byte[] {1, 2, 3}));
+
+        Pipeline pipeline = new PipelineImpl("test");
+        pipeline.add(source, todo, x224, tpkt, sink, mainSink);
+        pipeline.link("source", "channels", "mainSink");
+        pipeline.link("channels >" + OTOUT, "x224", "tpkt", "sink");
+        pipeline.runMainLoop("source", STDOUT, false, false);
+    }
+
+}


Mime
View raw message