cloudstack-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From devd...@apache.org
Subject [02/22] CLOUDSTACK-5344: Update to allow rdp console to access hyper-v vm virtual framebuffer.
Date Mon, 23 Dec 2013 09:12:56 GMT
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4f3611f9/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/vnc/EncodingsMessage.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/vnc/EncodingsMessage.java b/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/vnc/EncodingsMessage.java
new file mode 100755
index 0000000..5dfa831
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/vnc/EncodingsMessage.java
@@ -0,0 +1,63 @@
+// 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 vncclient.vnc;
+
+import streamer.BaseElement;
+import streamer.ByteBuffer;
+import streamer.Link;
+
+public class EncodingsMessage extends BaseElement {
+
+    protected final int[] encodings;
+
+    public EncodingsMessage(String id, int[] encodings) {
+        super(id);
+        this.encodings = encodings;
+        declarePads();
+    }
+
+    protected void declarePads() {
+        inputPads.put(STDIN, null);
+        outputPads.put(STDOUT, null);
+    }
+
+    @Override
+    public void handleData(ByteBuffer buf, Link link) {
+        if (buf == null)
+            return;
+
+        if (verbose)
+            System.out.println("[" + this + "] INFO: Data received: " + buf + ".");
+        buf.unref();
+
+        ByteBuffer outBuf = new ByteBuffer(4 + encodings.length * 4);
+
+        outBuf.writeByte(RfbConstants.CLIENT_SET_ENCODINGS);
+
+        outBuf.writeByte(0);// padding
+
+        outBuf.writeShort(encodings.length);
+
+        for (int i = 0; i < encodings.length; i++) {
+            outBuf.writeInt(encodings[i]);
+        }
+
+        pushDataToAllOuts(outBuf);
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4f3611f9/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/vnc/FrameBufferUpdateRequest.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/vnc/FrameBufferUpdateRequest.java b/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/vnc/FrameBufferUpdateRequest.java
new file mode 100755
index 0000000..446aa54
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/vnc/FrameBufferUpdateRequest.java
@@ -0,0 +1,127 @@
+// 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 vncclient.vnc;
+
+import common.ScreenDescription;
+
+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 FrameBufferUpdateRequest extends BaseElement {
+    // TODO: use object with fields instead of raw values in map
+    public static final String INCREMENTAL_UPDATE = "incremental";
+    public static final String TARGET_X = "x";
+    public static final String TARGET_Y = "y";
+    public static final String WIDTH = "width";
+    public static final String HEIGHT = "height";
+
+    protected ScreenDescription screen;
+
+    public FrameBufferUpdateRequest(String id, ScreenDescription screen) {
+        super(id);
+        this.screen = screen;
+    }
+
+    @Override
+    public void handleData(ByteBuffer buf, Link link) {
+        if (buf == null)
+            return;
+
+        if (verbose)
+            System.out.println("[" + this + "] INFO: Data received: " + buf + ".");
+
+        Boolean incremental = (Boolean)buf.getMetadata(INCREMENTAL_UPDATE);
+        Integer x = (Integer)buf.getMetadata(TARGET_X);
+        Integer y = (Integer)buf.getMetadata(TARGET_Y);
+        Integer width = (Integer)buf.getMetadata(WIDTH);
+        Integer height = (Integer)buf.getMetadata(HEIGHT);
+        buf.unref();
+
+        // Set default values when parameters are not set
+        if (incremental == null)
+            incremental = false;
+
+        if (x == null)
+            x = 0;
+        if (y == null)
+            y = 0;
+
+        if (width == null)
+            width = screen.getFramebufferWidth();
+        if (height == null)
+            height = screen.getFramebufferHeight();
+
+        ByteBuffer outBuf = new ByteBuffer(10);
+
+        outBuf.writeByte(RfbConstants.CLIENT_FRAMEBUFFER_UPDATE_REQUEST);
+        outBuf.writeByte((incremental) ? RfbConstants.FRAMEBUFFER_INCREMENTAL_UPDATE_REQUEST : RfbConstants.FRAMEBUFFER_FULL_UPDATE_REQUEST);
+        outBuf.writeShort(x);
+        outBuf.writeShort(y);
+        outBuf.writeShort(width);
+        outBuf.writeShort(height);
+
+        if (verbose) {
+            outBuf.putMetadata("sender", this);
+            outBuf.putMetadata("dimensions", width + "x" + height + "@" + x + "x" + y);
+        }
+
+        pushDataToAllOuts(outBuf);
+    }
+
+    public static void main(String args[]) {
+        System.setProperty("streamer.Element.debug", "true");
+
+        ScreenDescription screen = new ScreenDescription();
+        screen.setFramebufferSize(120, 80);
+        Element adapter = new FrameBufferUpdateRequest("renderer", screen);
+
+        Element sink = new MockSink("sink", ByteBuffer.convertByteArraysToByteBuffers(new byte[] {
+                // Request
+                RfbConstants.CLIENT_FRAMEBUFFER_UPDATE_REQUEST,
+                // Full update (redraw area)
+                RfbConstants.FRAMEBUFFER_FULL_UPDATE_REQUEST,
+                // X
+                0, 1,
+                // Y
+                0, 2,
+                // Width
+                0, 3,
+                // Height
+                0, 4}));
+
+        ByteBuffer buf = new ByteBuffer(new byte[0]);
+        buf.putMetadata(TARGET_X, 1);
+        buf.putMetadata(TARGET_Y, 2);
+        buf.putMetadata(WIDTH, 3);
+        buf.putMetadata(HEIGHT, 4);
+
+        Element source = new MockSource("source", new ByteBuffer[] {buf});
+
+        Pipeline pipeline = new PipelineImpl("test");
+
+        pipeline.addAndLink(source, adapter, 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/vncclient/vnc/RGB888LE32PixelFormatRequest.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/vnc/RGB888LE32PixelFormatRequest.java b/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/vnc/RGB888LE32PixelFormatRequest.java
new file mode 100755
index 0000000..d534f82
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/vnc/RGB888LE32PixelFormatRequest.java
@@ -0,0 +1,90 @@
+// 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 vncclient.vnc;
+
+import common.ScreenDescription;
+
+import streamer.BaseElement;
+import streamer.ByteBuffer;
+import streamer.Link;
+
+public class RGB888LE32PixelFormatRequest extends BaseElement {
+    protected int bitsPerPixel = 32;
+    protected int depth = 24;
+    protected int bigEndianFlag = RfbConstants.LITTLE_ENDIAN;
+    protected int trueColourFlag = RfbConstants.TRUE_COLOR;
+    protected int redMax = 255;
+    protected int greenMax = 255;
+    protected int blueMax = 255;
+    protected int redShift = 0;
+    protected int greenShift = 8;
+    protected int blueShift = 16;
+
+    protected ScreenDescription screen;
+
+    public RGB888LE32PixelFormatRequest(String id, ScreenDescription screen) {
+        super(id);
+        this.screen = screen;
+    }
+
+    protected void declarePads() {
+        inputPads.put(STDIN, null);
+        outputPads.put(STDOUT, null);
+    }
+
+    @Override
+    public void handleData(ByteBuffer buf, Link link) {
+        if (buf == null)
+            return;
+
+        if (verbose)
+            System.out.println("[" + this + "] INFO: Data received: " + buf + ".");
+        buf.unref();
+
+        ByteBuffer outBuf = new ByteBuffer(20);
+
+        outBuf.writeByte(RfbConstants.CLIENT_SET_PIXEL_FORMAT);
+
+        // Padding
+        outBuf.writeByte(0);
+        outBuf.writeByte(0);
+        outBuf.writeByte(0);
+
+        // Send pixel format
+        outBuf.writeByte(bitsPerPixel);
+        outBuf.writeByte(depth);
+        outBuf.writeByte(bigEndianFlag);
+        outBuf.writeByte(trueColourFlag);
+        outBuf.writeShort(redMax);
+        outBuf.writeShort(greenMax);
+        outBuf.writeShort(blueMax);
+        outBuf.writeByte(redShift);
+        outBuf.writeByte(greenShift);
+        outBuf.writeByte(blueShift);
+
+        // Padding
+        outBuf.writeByte(0);
+        outBuf.writeByte(0);
+        outBuf.writeByte(0);
+
+        screen.setPixelFormat(bitsPerPixel, depth, bigEndianFlag != RfbConstants.LITTLE_ENDIAN, trueColourFlag == RfbConstants.TRUE_COLOR, redMax, greenMax,
+                blueMax, redShift, greenShift, blueShift);
+
+        pushDataToAllOuts(outBuf);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4f3611f9/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/vnc/RfbConstants.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/vnc/RfbConstants.java b/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/vnc/RfbConstants.java
new file mode 100755
index 0000000..a3895d4
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/vnc/RfbConstants.java
@@ -0,0 +1,85 @@
+// 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 vncclient.vnc;
+
+import java.nio.charset.Charset;
+
+public interface RfbConstants {
+
+    public static final String RFB_PROTOCOL_VERSION_MAJOR = "RFB 003.";
+    public static final String VNC_PROTOCOL_VERSION_MINOR = "003";
+    public static final String RFB_PROTOCOL_VERSION = RFB_PROTOCOL_VERSION_MAJOR + VNC_PROTOCOL_VERSION_MINOR;
+
+    /**
+     * Server message types.
+     */
+    final static int SERVER_FRAMEBUFFER_UPDATE = 0, SERVER_SET_COLOURMAP_ENTRIES = 1, SERVER_BELL = 2, SERVER_CUT_TEXT = 3;
+
+    /**
+     * Client message types.
+     */
+    public static final int CLIENT_SET_PIXEL_FORMAT = 0, CLIENT_FIX_COLOURMAP_ENTRIES = 1, CLIENT_SET_ENCODINGS = 2, CLIENT_FRAMEBUFFER_UPDATE_REQUEST = 3,
+            CLIENT_KEYBOARD_EVENT = 4, CLIENT_POINTER_EVENT = 5, CLIENT_CUT_TEXT = 6;
+
+    /**
+     * Server authorization type
+     */
+    public final static int CONNECTION_FAILED = 0, NO_AUTH = 1, VNC_AUTH = 2;
+
+    /**
+     * Server authorization reply.
+     */
+    public final static int VNC_AUTH_OK = 0, VNC_AUTH_FAILED = 1, VNC_AUTH_TOO_MANY = 2;
+
+    /**
+     * Encodings.
+     */
+    public final static int ENCODING_RAW = 0, ENCODING_COPY_RECT = 1, ENCODING_RRE = 2, ENCODING_CO_RRE = 4, ENCODING_HEXTILE = 5, ENCODING_ZRLE = 16;
+
+    /**
+     * Pseudo-encodings.
+     */
+    public final static int ENCODING_CURSOR = -239 /*0xFFFFFF11*/, ENCODING_DESKTOP_SIZE = -223 /*0xFFFFFF21*/;
+
+    /**
+     * Encodings, which we support.
+     */
+    public final static int[] SUPPORTED_ENCODINGS_ARRAY = {ENCODING_RAW, ENCODING_COPY_RECT, ENCODING_DESKTOP_SIZE};
+
+    /**
+     * Frame buffer update request type: update of whole screen or partial update.
+     */
+    public static final int FRAMEBUFFER_FULL_UPDATE_REQUEST = 0, FRAMEBUFFER_INCREMENTAL_UPDATE_REQUEST = 1;
+
+    public static final int KEY_UP = 0, KEY_DOWN = 1;
+
+    public static final int LITTLE_ENDIAN = 0, BIG_ENDIAN = 1;
+
+    public static final int EXCLUSIVE_ACCESS = 0, SHARED_ACCESS = 1;
+
+    public static final int PALETTE = 0, TRUE_COLOR = 1;
+
+    /**
+     * Default 8 bit charset to use when communicating with server.
+     */
+    public static final Charset US_ASCII_CHARSET = Charset.availableCharsets().get("US-ASCII");
+
+    /**
+     * Default 16 bit charset to use when communicating with server.
+     */
+    public static final Charset UCS2_CHARSET = Charset.availableCharsets().get("UTF-16LE");
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4f3611f9/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/vnc/VncInitializer.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/vnc/VncInitializer.java b/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/vnc/VncInitializer.java
new file mode 100755
index 0000000..b3bd176
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/vnc/VncInitializer.java
@@ -0,0 +1,245 @@
+// 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 vncclient.vnc;
+
+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;
+
+import common.ScreenDescription;
+
+public class VncInitializer extends OneTimeSwitch {
+
+    // Pad names
+    public static final String CLIENT_SUPPORTED_ENCODINGS_ADAPTER_PAD = "encodings";
+    public static final String CLIENT_PIXEL_FORMAT_ADAPTER_PAD = "pixel_format";
+
+    protected byte sharedFlag = RfbConstants.EXCLUSIVE_ACCESS;
+
+    /**
+     * Properties of remote screen .
+     */
+    protected ScreenDescription screen;
+
+    public VncInitializer(String id, boolean shared, ScreenDescription screen) {
+        super(id);
+
+        setSharedFlag(shared);
+        this.screen = screen;
+
+        declarePads();
+    }
+
+    @Override
+    protected void declarePads() {
+        super.declarePads();
+        outputPads.put(CLIENT_SUPPORTED_ENCODINGS_ADAPTER_PAD, null);
+        outputPads.put(CLIENT_PIXEL_FORMAT_ADAPTER_PAD, null);
+    }
+
+    public ScreenDescription getScreen() {
+        return screen;
+    }
+
+    public void setScreen(ScreenDescription screen) {
+        this.screen = screen;
+    }
+
+    public void setSharedFlag(boolean shared) {
+        if (shared)
+            sharedFlag = RfbConstants.SHARED_ACCESS;
+        else
+            sharedFlag = RfbConstants.EXCLUSIVE_ACCESS;
+    }
+
+    @Override
+    protected void handleOneTimeData(ByteBuffer buf, Link link) {
+        if (verbose)
+            System.out.println("[" + this + "] INFO: Data received: " + buf + ".");
+
+        // Server initialization message is at least 24 bytes long + length of
+        // desktop name
+        if (!cap(buf, 24, UNLIMITED, link, false))
+            return;
+
+        // Read server initialization message
+        // Read frame buffer size
+        int framebufferWidth = buf.readUnsignedShort();
+        int framebufferHeight = buf.readUnsignedShort();
+
+        // Read pixel format
+        int bitsPerPixel = buf.readUnsignedByte();
+        int depth = buf.readUnsignedByte();
+
+        int bigEndianFlag = buf.readUnsignedByte();
+        int trueColorFlag = buf.readUnsignedByte();
+
+        int redMax = buf.readUnsignedShort();
+        int greenMax = buf.readUnsignedShort();
+        int blueMax = buf.readUnsignedShort();
+
+        int redShift = buf.readUnsignedByte();
+        int greenShift = buf.readUnsignedByte();
+        int blueShift = buf.readUnsignedByte();
+
+        // Skip padding
+        buf.skipBytes(3);
+
+        // Read desktop name
+        int length = buf.readSignedInt();
+
+        // Consume exactly $length bytes, push back any extra bytes
+        if (!cap(buf, length, length, link, true))
+            return;
+
+        String desktopName = buf.readString(length, RfbConstants.US_ASCII_CHARSET);
+        buf.unref();
+        if (verbose)
+            System.out.println("[" + this + "] INFO: Desktop name: \"" + desktopName + "\", bpp: " + bitsPerPixel + ", depth: " + depth + ", screen size: "
+                    + framebufferWidth + "x" + framebufferHeight + ".");
+
+        // Set screen properties
+        screen.setFramebufferSize(framebufferWidth, framebufferHeight);
+        screen.setPixelFormat(bitsPerPixel, depth, bigEndianFlag != RfbConstants.LITTLE_ENDIAN, trueColorFlag == RfbConstants.TRUE_COLOR, redMax, greenMax, blueMax, redShift,
+                greenShift, blueShift);
+        screen.setDesktopName(desktopName);
+
+        // If sever screen has different parameters than ours, then change it
+        if (!screen.isRGB888_32_LE()) {
+            // Send client pixel format
+            sendClientPixelFormat();
+        }
+
+        // Send encodings supported by client
+        sendSupportedEncodings();
+
+        switchOff();
+
+    }
+
+    @Override
+    protected void onStart() {
+        ByteBuffer buf = new ByteBuffer(new byte[] {sharedFlag});
+        pushDataToOTOut(buf);
+    }
+
+    private void sendClientPixelFormat() {
+        pushDataToPad(CLIENT_PIXEL_FORMAT_ADAPTER_PAD, new ByteBuffer(0));
+    }
+
+    private void sendSupportedEncodings() {
+        pushDataToPad(CLIENT_SUPPORTED_ENCODINGS_ADAPTER_PAD, new ByteBuffer(0));
+    }
+
+    public String toString() {
+        return "VncInit(" + id + ")";
+    }
+
+    /**
+     * 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");
+
+        final String desktopName = "test";
+
+        Element source = new MockSource("source") {
+            {
+                bufs = ByteBuffer.convertByteArraysToByteBuffers(
+                        // Send screen description
+                        new byte[] {
+                                // Framebuffer width (short)
+                                0, (byte)200,
+                                // Framebuffer height (short)
+                                0, 100,
+                                // Bits per pixel
+                                32,
+                                // Depth,
+                                24,
+                                // Endianness flag
+                                RfbConstants.LITTLE_ENDIAN,
+                                // Truecolor flag
+                                RfbConstants.TRUE_COLOR,
+                                // Red max (short)
+                                0, (byte)255,
+                                // Green max (short)
+                                0, (byte)255,
+                                // Blue max (short)
+                                0, (byte)255,
+                                // Red shift
+                                16,
+                                // Green shift
+                                8,
+                                // Blue shift
+                                0,
+                                // Padding
+                                0, 0, 0,
+                                // Desktop name length (int)
+                                0, 0, 0, 4,
+                                // Desktop name ("test", 4 bytes)
+                                't', 'e', 's', 't',
+
+                                // Tail
+                                1, 2, 3
+
+                        },
+                        // Tail packet
+                        new byte[] {4, 5, 6});
+            }
+        };
+
+        ScreenDescription screen = new ScreenDescription();
+        final VncInitializer init = new VncInitializer("init", true, screen);
+        Element initSink = new MockSink("initSink") {
+            {
+                // Expect shared flag
+                bufs = ByteBuffer.convertByteArraysToByteBuffers(new byte[] {RfbConstants.SHARED_ACCESS});
+            }
+        };
+        Element mainSink = new MockSink("mainSink") {
+            {
+                // Expect two tail packets
+                bufs = ByteBuffer.convertByteArraysToByteBuffers(new byte[] {1, 2, 3}, new byte[] {4, 5, 6});
+            }
+        };
+        ByteBuffer[] emptyBuf = ByteBuffer.convertByteArraysToByteBuffers(new byte[] {});
+        Element encodingsSink = new MockSink("encodings", emptyBuf);
+        Element pixelFormatSink = new MockSink("pixel_format", emptyBuf);
+
+        Pipeline pipeline = new PipelineImpl("test");
+        pipeline.addAndLink(source, init, mainSink);
+        pipeline.add(encodingsSink, pixelFormatSink, initSink);
+        pipeline.link("init >otout", "initSink");
+        pipeline.link("init >" + CLIENT_SUPPORTED_ENCODINGS_ADAPTER_PAD, "encodings");
+        pipeline.link("init >" + CLIENT_PIXEL_FORMAT_ADAPTER_PAD, "pixel_format");
+
+        pipeline.runMainLoop("source", STDOUT, false, false);
+
+        if (!screen.isRGB888_32_LE())
+            System.err.println("Screen description was read incorrectly: " + screen + ".");
+        if (!desktopName.equals(screen.getDesktopName()))
+            System.err.println("Screen desktop name was read incorrectly: \"" + screen.getDesktopName() + "\".");
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4f3611f9/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/vnc/VncMessageHandler.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/vnc/VncMessageHandler.java b/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/vnc/VncMessageHandler.java
new file mode 100755
index 0000000..845ed3a
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/vnc/VncMessageHandler.java
@@ -0,0 +1,419 @@
+// 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 vncclient.vnc;
+
+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.BitmapOrder;
+import common.BitmapRectangle;
+import common.CopyRectOrder;
+import common.ScreenDescription;
+import common.adapter.AwtClipboardAdapter;
+
+public class VncMessageHandler extends BaseElement {
+    protected ScreenDescription screen = null;
+
+    // Pad names
+    public static final String SERVER_BELL_ADAPTER_PAD = "bell";
+    public static final String SERVER_CLIPBOARD_ADAPTER_PAD = "clipboard";
+    public static final String PIXEL_ADAPTER_PAD = "pixels";
+    public static final String FRAME_BUFFER_UPDATE_REQUEST_ADAPTER_PAD = "fbur";
+
+    // Keys for metadata
+    public static final String TARGET_X = "x";
+    public static final String TARGET_Y = "y";
+    public static final String WIDTH = "width";
+    public static final String HEIGHT = "height";
+    public static final String SOURCE_X = "srcX";
+    public static final String SOURCE_Y = "srcY";
+    public static final String PIXEL_FORMAT = "pixel_format";
+
+    private static final String NUM_OF_PROCESSED_RECTANGLES = "rects";
+    private static final String SAVED_CURSOR_POSITION = "cursor";
+
+    // Pixel format: RGB888 LE 32
+    public static final String RGB888LE32 = "RGB888LE32";
+
+    public VncMessageHandler(String id, ScreenDescription screen) {
+        super(id);
+        this.screen = screen;
+        declarePads();
+    }
+
+    private void declarePads() {
+        outputPads.put(SERVER_BELL_ADAPTER_PAD, null);
+        outputPads.put(SERVER_BELL_ADAPTER_PAD, null);
+        outputPads.put(SERVER_CLIPBOARD_ADAPTER_PAD, null);
+        outputPads.put(PIXEL_ADAPTER_PAD, null);
+        outputPads.put(FRAME_BUFFER_UPDATE_REQUEST_ADAPTER_PAD, null);
+
+        inputPads.put("stdin", null);
+    }
+
+    @Override
+    public void handleData(ByteBuffer buf, Link link) {
+        if (buf == null)
+            return;
+
+        try {
+            if (verbose)
+                System.out.println("[" + this + "] INFO: Data received: " + buf + ".");
+
+            if (!cap(buf, 1, UNLIMITED, link, false))
+                return;
+
+            // Read server message type
+            int messageType = buf.readUnsignedByte();
+
+            // Invoke packet handler by packet type.
+            switch (messageType) {
+
+            case RfbConstants.SERVER_FRAMEBUFFER_UPDATE: {
+                // Handle frame buffer update
+                if (!handleFBU(buf, link))
+                    return;
+
+                // Frame buffer update is received and fully processed, send request for
+                // another frame buffer update to server.
+                sendFBUR();
+
+                break;
+            }
+
+            case RfbConstants.SERVER_BELL: {
+                if (!handleBell(buf, link))
+                    return;
+                break;
+            }
+
+            case RfbConstants.SERVER_CUT_TEXT: {
+                if (!handleClipboard(buf, link))
+                    return;
+                break;
+            }
+
+            default:
+                // TODO: allow to extend functionality
+                throw new RuntimeException("Unknown server packet type: " + messageType + ".");
+            }
+
+            // Cut tail, if any
+            cap(buf, 0, 0, link, true);
+        } finally {
+
+            // Return processed buffer back to pool
+            buf.unref();
+        }
+    }
+
+    private boolean handleClipboard(ByteBuffer buf, Link link) {
+        if (!cap(buf, 3 + 4, UNLIMITED, link, true))
+            return false;
+
+        // Skip padding
+        buf.skipBytes(3);
+
+        // Read text length
+        int length = buf.readSignedInt();
+
+        // We need full string to parse it
+        if (!cap(buf, length, UNLIMITED, link, true))
+            return false;
+
+        String content = buf.readString(length, RfbConstants.US_ASCII_CHARSET);
+
+        // Send content in metadata
+        ByteBuffer outBuf = new ByteBuffer(0);
+        outBuf.putMetadata(AwtClipboardAdapter.CLIPBOARD_CONTENT, content);
+
+        pushDataToPad(SERVER_CLIPBOARD_ADAPTER_PAD, outBuf);
+
+        return true;
+    }
+
+    private boolean handleBell(ByteBuffer buf, Link link) {
+        // Send empty packet to bell adapter to produce bell
+        pushDataToPad(SERVER_BELL_ADAPTER_PAD, new ByteBuffer(0));
+
+        return true;
+    }
+
+    // FIXME: this method is too complex
+    private boolean handleFBU(ByteBuffer buf, Link link) {
+
+        // We need at least 3 bytes here, 1 - padding, 2 - number of rectangles
+        if (!cap(buf, 3, UNLIMITED, link, true))
+            return false;
+
+        buf.skipBytes(1);// Skip padding
+
+        // Read number of rectangles
+        int numberOfRectangles = buf.readUnsignedShort();
+
+        if (verbose)
+            System.out.println("[" + this + "] INFO: Frame buffer update. Number of rectangles: " + numberOfRectangles + ".");
+
+        // Each rectangle must have header at least, header length is 12 bytes.
+        if (!cap(buf, 12 * numberOfRectangles, UNLIMITED, link, true))
+            return false;
+
+        // For all rectangles
+
+        // Restore saved point, to avoid flickering and performance problems when
+        // frame buffer update is split between few incoming packets.
+        int numberOfProcessedRectangles = (buf.getMetadata(NUM_OF_PROCESSED_RECTANGLES) != null) ? (Integer)buf.getMetadata(NUM_OF_PROCESSED_RECTANGLES) : 0;
+        if (buf.getMetadata(SAVED_CURSOR_POSITION) != null)
+            buf.cursor = (Integer)buf.getMetadata(SAVED_CURSOR_POSITION);
+
+        if (verbose && numberOfProcessedRectangles > 0)
+            System.out.println("[" + this + "] INFO: Restarting from saved point. Number of already processed rectangles: " + numberOfRectangles + ", cursor: "
+                    + buf.cursor + ".");
+
+        // For all new rectangles
+        for (int i = numberOfProcessedRectangles; i < numberOfRectangles; i++) {
+
+            // We need coordinates of rectangle (2x4 bytes) and encoding type (4
+            // bytes)
+            if (!cap(buf, 12, UNLIMITED, link, true))
+                return false;
+
+            // Read coordinates of rectangle
+            int x = buf.readUnsignedShort();
+            int y = buf.readUnsignedShort();
+            int width = buf.readUnsignedShort();
+            int height = buf.readUnsignedShort();
+
+            // Read rectangle encoding
+            int encodingType = buf.readSignedInt();
+
+            // Process rectangle
+            switch (encodingType) {
+
+            case RfbConstants.ENCODING_RAW: {
+                if (!handleRawRectangle(buf, link, x, y, width, height))
+                    return false;
+                break;
+            }
+
+            case RfbConstants.ENCODING_COPY_RECT: {
+                if (!handleCopyRect(buf, link, x, y, width, height))
+                    return false;
+                break;
+            }
+
+            case RfbConstants.ENCODING_DESKTOP_SIZE: {
+                if (!handleScreenSizeChangeRect(buf, link, x, y, width, height))
+                    return false;
+                break;
+            }
+
+            default:
+                // TODO: allow to extend functionality
+                throw new RuntimeException("Unsupported ecnoding: " + encodingType + ".");
+            }
+
+            // Update information about processed rectangles to avoid handling of same
+            // rectangle multiple times.
+            // TODO: push back partial rectangle only instead
+            buf.putMetadata(NUM_OF_PROCESSED_RECTANGLES, ++numberOfProcessedRectangles);
+            buf.putMetadata(SAVED_CURSOR_POSITION, buf.cursor);
+        }
+
+        return true;
+    }
+
+    private boolean handleScreenSizeChangeRect(ByteBuffer buf, Link link, int x, int y, int width, int height) {
+        // Remote screen size is changed
+        if (verbose)
+            System.out.println("[" + this + "] INFO: Screen size rect. Width: " + width + ", height: " + height + ".");
+
+        screen.setFramebufferSize(width, height);
+
+        return true;
+    }
+
+    private boolean handleCopyRect(ByteBuffer buf, Link link, int x, int y, int width, int height) {
+        // Copy rectangle from one part of screen to another.
+        // Areas may overlap. Antialiasing may cause visible artifacts.
+
+        // We need 4 bytes with coordinates of source rectangle
+        if (!cap(buf, 4, UNLIMITED, link, true))
+            return false;
+
+        CopyRectOrder order = new CopyRectOrder();
+
+        order.srcX = buf.readUnsignedShort();
+        order.srcY = buf.readUnsignedShort();
+        order.x = x;
+        order.y = y;
+        order.width = width;
+        order.height = height;
+
+        if (verbose)
+            System.out.println("[" + this + "] INFO: Copy rect. X: " + x + ", y: " + y + ", width: " + width + ", height: " + height + ", srcX: " + order.srcX
+                    + ", srcY: " + order.srcY + ".");
+
+        pushDataToPad(PIXEL_ADAPTER_PAD, new ByteBuffer(order));
+
+        return true;
+    }
+
+    private boolean handleRawRectangle(ByteBuffer buf, Link link, int x, int y, int width, int height) {
+        // Raw rectangle is just array of pixels to draw on screen.
+        int rectDataLength = width * height * screen.getBytesPerPixel();
+
+        // We need at least rectDataLength bytes. Extra bytes may contain other
+        // rectangles.
+        if (!cap(buf, rectDataLength, UNLIMITED, link, true))
+            return false;
+
+        if (verbose)
+            System.out.println("[" + this + "] INFO: Raw rect. X: " + x + ", y: " + y + ", width: " + width + ", height: " + height + ", data length: "
+                    + rectDataLength + ".");
+
+        BitmapRectangle rectangle = new BitmapRectangle();
+        rectangle.x = x;
+        rectangle.y = y;
+        rectangle.width = width;
+        rectangle.height = height;
+        rectangle.bufferWidth = width;
+        rectangle.bufferHeight = height;
+        rectangle.bitmapDataStream = buf.readBytes(rectDataLength);
+        rectangle.colorDepth = screen.getColorDeph();
+
+        BitmapOrder order = new BitmapOrder();
+        order.rectangles = new BitmapRectangle[] {rectangle};
+
+        pushDataToPad(PIXEL_ADAPTER_PAD, new ByteBuffer(order));
+        return true;
+    }
+
+    public void onStart() {
+        // Send Frame Buffer Update request
+        sendFBUR();
+    }
+
+    private void sendFBUR() {
+        ByteBuffer buf = new ByteBuffer(0);
+        buf.putMetadata("incremental", true);
+        pushDataToPad(FRAME_BUFFER_UPDATE_REQUEST_ADAPTER_PAD, buf);
+    }
+
+    public String toString() {
+        return "VNCMessageHandler(" + id + ")";
+    }
+
+    /**
+     * 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");
+
+        Element source = new MockSource("source") {
+            {
+                // Split messages at random boundaries to check "pushback" logic
+                bufs = ByteBuffer.convertByteArraysToByteBuffers(new byte[] {
+                        // Message type: server bell
+                        RfbConstants.SERVER_BELL,
+
+                        // Message type: clipboard text
+                        RfbConstants.SERVER_CUT_TEXT,
+                        // Padding
+                        0, 0, 0,
+                        // Length (test)
+                        0, 0, 0, 4,
+
+                }, new byte[] {
+                        // Clipboard text
+                        't', 'e', 's', 't',
+
+                        // Message type: frame buffer update
+                        RfbConstants.SERVER_FRAMEBUFFER_UPDATE,
+                        // Padding
+                        0,
+                        // Number of rectangles
+                        0, 3,},
+
+                        new byte[] {
+
+                                // x, y, width, height: 0x0@4x4
+                                0, 0, 0, 0, 0, 4, 0, 4,
+                                // Encoding: desktop size
+                                (byte)((RfbConstants.ENCODING_DESKTOP_SIZE >> 24) & 0xff), (byte)((RfbConstants.ENCODING_DESKTOP_SIZE >> 16) & 0xff),
+                                (byte)((RfbConstants.ENCODING_DESKTOP_SIZE >> 8) & 0xff), (byte)((RfbConstants.ENCODING_DESKTOP_SIZE >> 0) & 0xff),},
+
+                        new byte[] {
+
+                                // x, y, width, height: 0x0@4x4
+                                0, 0, 0, 0, 0, 4, 0, 4,
+                                // Encoding: raw rect
+                                (byte)((RfbConstants.ENCODING_RAW >> 24) & 0xff), (byte)((RfbConstants.ENCODING_RAW >> 16) & 0xff),
+                                (byte)((RfbConstants.ENCODING_RAW >> 8) & 0xff), (byte)((RfbConstants.ENCODING_RAW >> 0) & 0xff),
+                                // Raw pixel data 4x4x1 bpp
+                                1, 2, 3, 4, 5, 6, 7, 8, 9, 10,}, new byte[] {11, 12, 13, 14, 15, 16,
+
+                                // x, y, width, height: 0x0@2x2
+                                0, 0, 0, 0, 0, 2, 0, 2,
+                                // Encoding: copy rect
+                                (byte)((RfbConstants.ENCODING_COPY_RECT >> 24) & 0xff), (byte)((RfbConstants.ENCODING_COPY_RECT >> 16) & 0xff),
+                                (byte)((RfbConstants.ENCODING_COPY_RECT >> 8) & 0xff), (byte)((RfbConstants.ENCODING_COPY_RECT >> 0) & 0xff),
+                                // srcX, srcY: 2x2
+                                0, 2, 0, 2,});
+            }
+        };
+
+        ScreenDescription screen = new ScreenDescription() {
+            {
+                this.bytesPerPixel = 1;
+            }
+        };
+
+        final Element handler = new VncMessageHandler("handler", screen);
+
+        ByteBuffer[] emptyBuf = ByteBuffer.convertByteArraysToByteBuffers(new byte[] {});
+        Element fburSink = new MockSink("fbur", ByteBuffer.convertByteArraysToByteBuffers(new byte[] {}, new byte[] {}));
+        Element bellSink = new MockSink("bell", emptyBuf);
+        Element clipboardSink = new MockSink("clipboard", emptyBuf);
+        Element desktopSizeChangeSink = new MockSink("desktop_size", emptyBuf);
+        Element pixelsSink = new MockSink("pixels",
+                ByteBuffer.convertByteArraysToByteBuffers(new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,}));
+        Element copyRectSink = new MockSink("copy_rect", emptyBuf);
+
+        Pipeline pipeline = new PipelineImpl("test");
+        pipeline.addAndLink(source, handler);
+        pipeline.add(fburSink, bellSink, clipboardSink, desktopSizeChangeSink, pixelsSink, copyRectSink);
+
+        pipeline.link("handler >" + FRAME_BUFFER_UPDATE_REQUEST_ADAPTER_PAD, "fbur");
+        pipeline.link("handler >" + SERVER_BELL_ADAPTER_PAD, "bell");
+        pipeline.link("handler >" + SERVER_CLIPBOARD_ADAPTER_PAD, "clipboard");
+        pipeline.link("handler >" + PIXEL_ADAPTER_PAD, "pixels");
+
+        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/vncclient/vnc/Vnc_3_3_Authentication.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/vnc/Vnc_3_3_Authentication.java b/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/vnc/Vnc_3_3_Authentication.java
new file mode 100755
index 0000000..93423da
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/vnc/Vnc_3_3_Authentication.java
@@ -0,0 +1,291 @@
+// 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 vncclient.vnc;
+
+import java.security.spec.KeySpec;
+
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.DESKeySpec;
+
+import streamer.ByteBuffer;
+import streamer.Element;
+import streamer.Link;
+import streamer.OneTimeSwitch;
+import streamer.Pipeline;
+import streamer.PipelineImpl;
+import streamer.debug.FakeSink;
+import streamer.debug.MockSink;
+import streamer.debug.MockSource;
+
+public class Vnc_3_3_Authentication extends OneTimeSwitch {
+
+    /**
+     * Password to use when authentication is required.
+     */
+    protected String password = null;
+
+    /**
+     * Authentication stage:
+     * <ul>
+     * <li>0 - challenge received, response must be sent
+     * <li>1 - authentication result received.
+     * </ul>
+     */
+    protected int stage = 0;
+
+    public Vnc_3_3_Authentication(String id) {
+        super(id);
+    }
+
+    public Vnc_3_3_Authentication(String id, String password) {
+        super(id);
+        this.password = password;
+    }
+
+    @Override
+    protected void handleOneTimeData(ByteBuffer buf, Link link) {
+        if (verbose)
+            System.out.println("[" + this + "] INFO: Data received: " + buf + ".");
+
+        switch (stage) {
+        case 0: // Read security with optional challenge and response
+            stage0(buf, link);
+
+            break;
+        case 1: // Read authentication response
+            stage1(buf, link);
+            break;
+        }
+
+    }
+
+    /**
+     * Read security type. If connection type is @see
+     * RfbConstants.CONNECTION_FAILED, then throw exception. If connection type is @see
+     * RfbConstants.NO_AUTH, then switch off this element. If connection type is @see
+     * RfbConstants.VNC_AUTH, then read challenge, send encoded password, and read
+     * authentication response.
+     */
+    private void stage0(ByteBuffer buf, Link link) {
+        // At least 4 bytes are necessary
+        if (!cap(buf, 4, UNLIMITED, link, true))
+            return;
+
+        // Read security type
+        int authType = buf.readSignedInt();
+
+        switch (authType) {
+        case RfbConstants.CONNECTION_FAILED: {
+            // Server forbids to connect. Read reason and throw exception
+
+            int length = buf.readSignedInt();
+            String reason = new String(buf.data, buf.offset, length, RfbConstants.US_ASCII_CHARSET);
+
+            throw new RuntimeException("Authentication to VNC server is failed. Reason: " + reason);
+        }
+
+        case RfbConstants.NO_AUTH: {
+            // Client can connect without authorization. Nothing to do.
+            // Switch off this element from circuit
+            switchOff();
+            break;
+        }
+
+        case RfbConstants.VNC_AUTH: {
+            // Read challenge and generate response
+            responseToChallenge(buf, link);
+            break;
+        }
+
+        default:
+            throw new RuntimeException("Unsupported VNC protocol authorization scheme, scheme code: " + authType + ".");
+        }
+
+    }
+
+    private void responseToChallenge(ByteBuffer buf, Link link) {
+        // Challenge is exactly 16 bytes long
+        if (!cap(buf, 16, 16, link, true))
+            return;
+
+        ByteBuffer challenge = buf.slice(buf.cursor, 16, true);
+        buf.unref();
+
+        // Encode challenge with password
+        ByteBuffer response;
+        try {
+            response = encodePassword(challenge, password);
+            challenge.unref();
+        } catch (Exception e) {
+            throw new RuntimeException("Cannot encrypt client password to send to server: " + e.getMessage());
+        }
+
+        if (verbose) {
+            response.putMetadata("sender", this);
+        }
+
+        // Send encoded challenge
+        nextStage();
+        pushDataToOTOut(response);
+
+    }
+
+    private void nextStage() {
+        stage++;
+
+        if (verbose)
+            System.out.println("[" + this + "] INFO: Next stage: " + stage + ".");
+    }
+
+    /**
+     * Encode password using DES encryption with given challenge.
+     * 
+     * @param challenge
+     *          a random set of bytes.
+     * @param password
+     *          a password
+     * @return DES hash of password and challenge
+     */
+    public ByteBuffer encodePassword(ByteBuffer challenge, String password) {
+        if (challenge.length != 16)
+            throw new RuntimeException("Challenge must be exactly 16 bytes long.");
+
+        // VNC password consist of up to eight ASCII characters.
+        byte[] key = {0, 0, 0, 0, 0, 0, 0, 0}; // Padding
+        byte[] passwordAsciiBytes = password.getBytes(RfbConstants.US_ASCII_CHARSET);
+        System.arraycopy(passwordAsciiBytes, 0, key, 0, Math.min(password.length(), 8));
+
+        // Flip bytes (reverse bits) in key
+        for (int i = 0; i < key.length; i++) {
+            key[i] = flipByte(key[i]);
+        }
+
+        try {
+            KeySpec desKeySpec = new DESKeySpec(key);
+            SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES");
+            SecretKey secretKey = secretKeyFactory.generateSecret(desKeySpec);
+            Cipher cipher = Cipher.getInstance("DES/ECB/NoPadding");
+            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
+
+            ByteBuffer buf = new ByteBuffer(cipher.doFinal(challenge.data, challenge.offset, challenge.length));
+
+            return buf;
+        } catch (Exception e) {
+            throw new RuntimeException("Cannot encode password.", e);
+        }
+    }
+
+    /**
+     * Reverse bits in byte, so least significant bit will be most significant
+     * bit. E.g. 01001100 will become 00110010.
+     * 
+     * See also: http://www.vidarholen.net/contents/junk/vnc.html ,
+     * http://bytecrafter .blogspot.com/2010/09/des-encryption-as-used-in-vnc.html
+     * 
+     * @param b
+     *          a byte
+     * @return byte in reverse order
+     */
+    private static byte flipByte(byte b) {
+        int b1_8 = (b & 0x1) << 7;
+        int b2_7 = (b & 0x2) << 5;
+        int b3_6 = (b & 0x4) << 3;
+        int b4_5 = (b & 0x8) << 1;
+        int b5_4 = (b & 0x10) >>> 1;
+        int b6_3 = (b & 0x20) >>> 3;
+        int b7_2 = (b & 0x40) >>> 5;
+        int b8_1 = (b & 0x80) >>> 7;
+        byte c = (byte)(b1_8 | b2_7 | b3_6 | b4_5 | b5_4 | b6_3 | b7_2 | b8_1);
+        return c;
+    }
+
+    /**
+     * Read authentication result, send nothing.
+     */
+    private void stage1(ByteBuffer buf, Link link) {
+        // Read authentication response
+        if (!cap(buf, 4, 4, link, false))
+            return;
+
+        int authResult = buf.readSignedInt();
+
+        switch (authResult) {
+        case RfbConstants.VNC_AUTH_OK: {
+            // Nothing to do
+            if (verbose)
+                System.out.println("[" + this + "] INFO: Authentication successfull.");
+            break;
+        }
+
+        case RfbConstants.VNC_AUTH_TOO_MANY:
+            throw new RuntimeException("Connection to VNC server failed: too many wrong attempts.");
+
+        case RfbConstants.VNC_AUTH_FAILED:
+            throw new RuntimeException("Connection to VNC server failed: wrong password.");
+
+        default:
+            throw new RuntimeException("Connection to VNC server failed, reason code: " + authResult);
+        }
+
+        switchOff();
+
+    }
+
+    public String toString() {
+        return "VNC3.3 Authentication(" + id + ")";
+    }
+
+    /**
+     * 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");
+
+        final String password = "test";
+
+        Element source = new MockSource("source") {
+            {
+                bufs = ByteBuffer.convertByteArraysToByteBuffers(
+                        // Request authentication and send 16 byte challenge
+                        new byte[] {0, 0, 0, RfbConstants.VNC_AUTH, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
+                        // Respond to challenge with AUTH_OK
+                        new byte[] {0, 0, 0, RfbConstants.VNC_AUTH_OK});
+            }
+        };
+
+        Element mainSink = new FakeSink("mainSink");
+        final Vnc_3_3_Authentication auth = new Vnc_3_3_Authentication("auth", password);
+        Element initSink = new MockSink("initSink") {
+            {
+                // Expect encoded password
+                bufs = new ByteBuffer[] {auth.encodePassword(new ByteBuffer(new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}), password)};
+            }
+        };
+
+        Pipeline pipeline = new PipelineImpl("test");
+        pipeline.addAndLink(source, auth, mainSink);
+        pipeline.add(initSink);
+        pipeline.link("auth >otout", "initSink");
+
+        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/vncclient/vnc/Vnc_3_3_Hello.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/vnc/Vnc_3_3_Hello.java b/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/vnc/Vnc_3_3_Hello.java
new file mode 100755
index 0000000..3afff83
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/vnc/Vnc_3_3_Hello.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 vncclient.vnc;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+
+import streamer.ByteBuffer;
+import streamer.InputStreamSource;
+import streamer.Link;
+import streamer.OneTimeSwitch;
+import streamer.OutputStreamSink;
+import streamer.Pipeline;
+import streamer.PipelineImpl;
+
+/**
+ * VNC server sends hello packet with RFB protocol version, e.g.
+ * "RFB 003.007\n". We need to send response packet with supported protocol
+ * version, e.g. "RFB 003.003\n".
+ */
+public class Vnc_3_3_Hello extends OneTimeSwitch {
+
+    public Vnc_3_3_Hello(String id) {
+        super(id);
+    }
+
+    @Override
+    protected void handleOneTimeData(ByteBuffer buf, Link link) {
+        if (verbose)
+            System.out.println("[" + this + "] INFO: Data received: " + buf + ".");
+
+        // Initial packet is exactly 12 bytes long
+        if (!cap(buf, 12, 12, link, false))
+            return;
+
+        // Read protocol version
+        String rfbProtocol = new String(buf.data, buf.offset, buf.length, RfbConstants.US_ASCII_CHARSET);
+        buf.unref();
+
+        // Server should use RFB protocol 3.x
+        if (!rfbProtocol.contains(RfbConstants.RFB_PROTOCOL_VERSION_MAJOR))
+            throw new RuntimeException("Cannot handshake with VNC server. Unsupported protocol version: \"" + rfbProtocol + "\".");
+
+        // Send response: we support RFB 3.3 only
+        String ourProtocolString = RfbConstants.RFB_PROTOCOL_VERSION + "\n";
+
+        ByteBuffer outBuf = new ByteBuffer(ourProtocolString.getBytes(RfbConstants.US_ASCII_CHARSET));
+
+        if (verbose) {
+            outBuf.putMetadata("sender", this);
+            outBuf.putMetadata("version", RfbConstants.RFB_PROTOCOL_VERSION);
+        }
+
+        pushDataToOTOut(outBuf);
+
+        // Switch off this element from circuit
+        switchOff();
+
+    }
+
+    public String toString() {
+        return "Vnc3.3 Hello(" + id + ")";
+    }
+
+    /**
+     * 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");
+
+        InputStream is = new ByteArrayInputStream("RFB 003.007\ntest".getBytes(RfbConstants.US_ASCII_CHARSET));
+        ByteArrayOutputStream initOS = new ByteArrayOutputStream();
+        ByteArrayOutputStream mainOS = new ByteArrayOutputStream();
+        InputStreamSource inputStreamSource = new InputStreamSource("source", is);
+        OutputStreamSink outputStreamSink = new OutputStreamSink("mainSink", mainOS);
+
+        Vnc_3_3_Hello hello = new Vnc_3_3_Hello("hello");
+
+        Pipeline pipeline = new PipelineImpl("test");
+
+        pipeline.addAndLink(inputStreamSource, hello, outputStreamSink);
+        pipeline.add(new OutputStreamSink("initSink", initOS));
+
+        pipeline.link("hello >" + OneTimeSwitch.OTOUT, "initSink");
+
+        pipeline.runMainLoop("source", STDOUT, false, false);
+
+        String initOut = new String(initOS.toByteArray(), RfbConstants.US_ASCII_CHARSET);
+        String mainOut = new String(mainOS.toByteArray(), RfbConstants.US_ASCII_CHARSET);
+
+        if (!"RFB 003.003\n".equals(initOut))
+            System.err.println("Unexpected value for hello response: \"" + initOut + "\".");
+
+        if (!"test".equals(mainOut))
+            System.err.println("Unexpected value for main data: \"" + mainOut + "\".");
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4f3611f9/services/console-proxy-rdp/rdpconsole/src/main/resources/jaas_ntlm_config.txt
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/resources/jaas_ntlm_config.txt b/services/console-proxy-rdp/rdpconsole/src/main/resources/jaas_ntlm_config.txt
new file mode 100755
index 0000000..4137609
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/resources/jaas_ntlm_config.txt
@@ -0,0 +1,21 @@
+// 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.
+
+MyConfig { com.sun.security.auth.module.Krb5LoginModule required
+  useTicketCache=true
+  doNotPrompt=false;
+};

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4f3611f9/services/console-proxy-rdp/rdpconsole/src/test/doc/README.txt
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/test/doc/README.txt b/services/console-proxy-rdp/rdpconsole/src/test/doc/README.txt
old mode 100644
new mode 100755
index dd41683..704f5f5
--- a/services/console-proxy-rdp/rdpconsole/src/test/doc/README.txt
+++ b/services/console-proxy-rdp/rdpconsole/src/test/doc/README.txt
@@ -30,3 +30,5 @@ fingerprints.
 
 File rdp-key.pem contains private key in PEM format for use with
 Wireshark.
+
+As alternative, mimikatz can be used to extract RDP private key.

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4f3611f9/services/console-proxy-rdp/rdpconsole/src/test/doc/dev-rdp-config.bat
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/test/doc/dev-rdp-config.bat b/services/console-proxy-rdp/rdpconsole/src/test/doc/dev-rdp-config.bat
old mode 100644
new mode 100755
index 14a7bbd..4e19157
--- a/services/console-proxy-rdp/rdpconsole/src/test/doc/dev-rdp-config.bat
+++ b/services/console-proxy-rdp/rdpconsole/src/test/doc/dev-rdp-config.bat
@@ -111,6 +111,19 @@ rem Start TS service
 
 net start Termservice
 
+rem Enable logs
+
+wevtutil sl Microsoft-Windows-TerminalServices-RemoteConnectionManager/Admin /enabled:true /quiet:true
+wevtutil sl Microsoft-Windows-TerminalServices-RemoteConnectionManager/Analytic /enabled:true /quiet:true
+wevtutil sl Microsoft-Windows-TerminalServices-RemoteConnectionManager/Debug /enabled:true /quiet:true
+wevtutil sl Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational /enabled:true /quiet:true
+wevtutil sl Microsoft-Windows-TerminalServices-SessionBroker-Client/Admin /enabled:true /quiet:true
+wevtutil sl Microsoft-Windows-TerminalServices-SessionBroker-Client/Analytic /enabled:true /quiet:true
+wevtutil sl Microsoft-Windows-TerminalServices-SessionBroker-Client/Debug /enabled:true /quiet:true
+wevtutil sl Microsoft-Windows-TerminalServices-SessionBroker-Client/Operational /enabled:true /quiet:true
+wevtutil sl Microsoft-Windows-NTLM/Operational /enabled:true /quiet:true
+
+
 
 rem For Network Monitor Decrypt Expert.
 


Mime
View raw message