Return-Path: X-Original-To: apmail-cloudstack-commits-archive@www.apache.org Delivered-To: apmail-cloudstack-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id C621410D5E for ; Fri, 3 Jan 2014 10:19:19 +0000 (UTC) Received: (qmail 93774 invoked by uid 500); 3 Jan 2014 10:18:36 -0000 Delivered-To: apmail-cloudstack-commits-archive@cloudstack.apache.org Received: (qmail 92839 invoked by uid 500); 3 Jan 2014 10:18:12 -0000 Mailing-List: contact commits-help@cloudstack.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cloudstack.apache.org Delivered-To: mailing list commits@cloudstack.apache.org Received: (qmail 92033 invoked by uid 99); 3 Jan 2014 10:17:36 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 03 Jan 2014 10:17:36 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 7A246915773; Fri, 3 Jan 2014 10:17:35 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: hugo@apache.org To: commits@cloudstack.apache.org Date: Fri, 03 Jan 2014 10:17:46 -0000 Message-Id: In-Reply-To: <4fd5128ac77a4b5cb6cd11b25f626a08@git.apache.org> References: <4fd5128ac77a4b5cb6cd11b25f626a08@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [13/50] [abbrv] CLOUDSTACK-5344: Updated to allow rdp console to access hyper-v vm virtual framebuffer. http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/debug/AssertingByteBuffer.java ---------------------------------------------------------------------- diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/debug/AssertingByteBuffer.java b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/debug/AssertingByteBuffer.java new file mode 100755 index 0000000..15449c3 --- /dev/null +++ b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/debug/AssertingByteBuffer.java @@ -0,0 +1,109 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package streamer.debug; + +import java.nio.charset.Charset; + +import streamer.ByteBuffer; + +/** + * Assert that writes to this buffer are matching expected data. + */ +public class AssertingByteBuffer extends ByteBuffer { + + public AssertingByteBuffer(byte[] expectedData) { + super(expectedData); + } + + private void assertEquals(int expected, int actual) { + if (expected != actual) + throw new RuntimeException("Expected value does not match actual value. Expected value: " + expected + ", actual value: " + actual + ", buf: " + this + "."); + } + + @Override + public void writeByte(int b) { + if (b < 0) + throw new RuntimeException(); + //*DEBUG*/System.out.println("WriteByte: "+b+", cursor:"+cursor+"."); + assertEquals(readUnsignedByte(), b & 0xff); + } + + @Override + public void writeShort(int x) { + //*DEBUG*/System.out.println("WriteShort: "+x+", cursor:"+cursor+"."); + assertEquals(readUnsignedShort(), x & 0xFFff); + } + + @Override + public void writeShortLE(int x) { + //*DEBUG*/System.out.println("WriteShortLE: "+x+", cursor:"+cursor+"."); + assertEquals(readUnsignedShortLE(), x & 0xFFff); + } + + @Override + public void writeInt(int i) { + //*DEBUG*/System.out.println("WriteInt: "+i+", cursor:"+cursor+"."); + assertEquals(readSignedInt(), i); + } + + @Override + public void writeIntLE(int i) { + //*DEBUG*/System.out.println("WriteIntLE: "+i+", cursor:"+cursor+"."); + assertEquals(readSignedIntLE(), i); + } + + @Override + public void writeVariableIntLE(int i) { + //*DEBUG*/System.out.println("WriteVariableIntLE: "+i+", cursor:"+cursor+"."); + assertEquals(readVariableSignedIntLE(), i); + } + + @Override + public void writeString(String actual, Charset charset) { + //*DEBUG*/System.out.println("WriteString: "+actual+", cursor:"+cursor+"."); + String expected = readString(actual.length(), charset); + if (!actual.equals(expected)) + throw new RuntimeException("Expected value does not match actual value. Expected value: " + expected + ", actual value: " + actual + "."); + } + + @Override + public void writeBytes(ByteBuffer actual) { + //*DEBUG*/System.out.println("WriteString: "+actual+", cursor:"+cursor+"."); + ByteBuffer expected = readBytes(actual.length); + if (!actual.equals(expected)) + throw new RuntimeException("Expected value does not match actual value. Expected value: " + expected + ", actual value: " + actual + "."); + } + + @Override + public void writeBytes(byte[] actualData) { + ByteBuffer actual = new ByteBuffer(actualData); + //*DEBUG*/System.out.println("WriteString: "+actual+", cursor:"+cursor+"."); + ByteBuffer expected = readBytes(actual.length); + if (!actual.equals(expected)) + throw new RuntimeException("Expected value does not match actual value. Expected value: " + expected + ", actual value: " + actual + "."); + } + + @Override + public void writeBytes(byte[] actualData, int offset, int length) { + ByteBuffer actual = new ByteBuffer(actualData, offset, length); + //*DEBUG*/System.out.println("WriteString: "+actual+", cursor:"+cursor+"."); + ByteBuffer expected = readBytes(actual.length); + if (!actual.equals(expected)) + throw new RuntimeException("Expected value does not match actual value. Expected value: " + expected + ", actual value: " + actual + "."); + } + +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/debug/Dumper.java ---------------------------------------------------------------------- diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/debug/Dumper.java b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/debug/Dumper.java new file mode 100755 index 0000000..c884cfb --- /dev/null +++ b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/debug/Dumper.java @@ -0,0 +1,28 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package streamer.debug; + +import streamer.ByteBuffer; + +public interface Dumper { + + /** + * Parse and dump content of buffer. + */ + void dump(ByteBuffer buf); + +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/debug/FakeSink.java ---------------------------------------------------------------------- diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/debug/FakeSink.java b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/debug/FakeSink.java new file mode 100755 index 0000000..9315488 --- /dev/null +++ b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/debug/FakeSink.java @@ -0,0 +1,77 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package streamer.debug; + +import streamer.BaseElement; +import streamer.ByteBuffer; +import streamer.Direction; +import streamer.Element; +import streamer.Event; +import streamer.Link; +import streamer.SyncLink; + +public class FakeSink extends BaseElement { + + public FakeSink(String id) { + super(id); + } + + @Override + public void handleData(ByteBuffer buf, Link link) { + if (verbose) + System.out.println("[" + this + "] INFO: Received buf #" + (packetNumber) + " " + buf + "."); + + if (buf == null) + return; + + // Use packetNumber variable to count incoming packets + packetNumber++; + + buf.unref(); + } + + @Override + public String toString() { + return "FakeSink(" + id + ")"; + } + + @Override + public void handleEvent(Event event, Direction direction) { + if (verbose) + System.out.println("[" + this + "] INFO: Event received: " + event + "."); + + } + + /** + * Example. + */ + public static void main(String args[]) { + + Element sink = new FakeSink("sink") { + { + verbose = true; + } + }; + + byte[] data = new byte[] {1, 2, 3}; + ByteBuffer buf = new ByteBuffer(data); + sink.setLink(STDIN, new SyncLink(), Direction.IN); + sink.getLink(STDIN).sendData(buf); + + } + +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/debug/FakeSource.java ---------------------------------------------------------------------- diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/debug/FakeSource.java b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/debug/FakeSource.java new file mode 100755 index 0000000..7f0c554 --- /dev/null +++ b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/debug/FakeSource.java @@ -0,0 +1,138 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package streamer.debug; + +import streamer.BaseElement; +import streamer.ByteBuffer; +import streamer.Direction; +import streamer.Element; +import streamer.Event; +import streamer.Link; +import streamer.SyncLink; + +public class FakeSource extends BaseElement { + + /** + * Delay for null packets in poll method when blocking is requested, in + * milliseconds. + */ + protected long delay = SyncLink.STANDARD_DELAY_FOR_EMPTY_PACKET; + + public FakeSource(String id) { + super(id); + } + + @Override + public void poll(boolean block) { + if (numBuffers > 0 && packetNumber >= numBuffers) { + // Close stream when limit of packets is reached + sendEventToAllPads(Event.STREAM_CLOSE, Direction.OUT); + return; + } + + // Prepare new packet + ByteBuffer buf = initializeData(); + + // Push it to output(s) + if (buf != null) + pushDataToAllOuts(buf); + + // Make slight delay when blocking input was requested (to avoid + // consuming of 100% in parent loop) + if (block) + delay(); + + } + + /** + * Make slight delay. Should be used when blocking input is requested in pull + * mode, but null packed was returned by input. + */ + protected void delay() { + try { + Thread.sleep(delay); + } catch (InterruptedException e) { + } + } + + /** + * Initialize data. + */ + public ByteBuffer initializeData() { + ByteBuffer buf = new ByteBuffer(incommingBufLength); + + // Set first byte of package to it sequance number + buf.data[buf.offset] = (byte)(packetNumber % 128); + + // Initialize rest of bytes with sequential values, which are + // corresponding with their position in byte buffer + for (int i = buf.offset + 1; i < buf.length; i++) + buf.data[i] = (byte)(i % 128); + + buf.putMetadata(ByteBuffer.SEQUENCE_NUMBER, packetNumber); + buf.putMetadata("src", id); + + return buf; + } + + @Override + public String toString() { + return "FakeSource(" + id + ")"; + } + + /** + * Example. + */ + public static void main(String args[]) { + + Element fakeSource = new FakeSource("source 3/10/100") { + { + verbose = true; + incommingBufLength = 3; + numBuffers = 10; + delay = 100; + } + }; + + Element fakeSink = new FakeSink("sink") { + { + verbose = true; + } + }; + + Element fakeSink2 = new FakeSink("sink2") { + { + verbose = true; + } + }; + + Link link = new SyncLink(); + + fakeSource.setLink(STDOUT, link, Direction.OUT); + fakeSink.setLink(STDIN, link, Direction.IN); + + Link link2 = new SyncLink(); + + fakeSource.setLink("out2", link2, Direction.OUT); + fakeSink2.setLink(STDIN, link2, Direction.IN); + + link.sendEvent(Event.STREAM_START, Direction.IN); + link.run(); + + } + +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/debug/MockServer.java ---------------------------------------------------------------------- diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/debug/MockServer.java b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/debug/MockServer.java new file mode 100755 index 0000000..348a006 --- /dev/null +++ b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/debug/MockServer.java @@ -0,0 +1,203 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package streamer.debug; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.Arrays; + +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; + +public class MockServer implements Runnable { + + private boolean shutdown = false; + private ServerSocket serverSocket; + private Packet[] packets; + private Throwable exception; + private boolean shutdowned; + + /** + * Set to true to enable debugging messages. + */ + protected boolean verbose = System.getProperty("rdpclient.MockServer.debug", "false").equals("true"); + + public MockServer(Packet packets[]) { + this.packets = packets; + } + + public void start() throws IOException { + serverSocket = new ServerSocket(0); + + shutdown = false; + exception = null; + shutdowned = false; + + Thread thread = new Thread(this); + thread.setDaemon(true); + thread.start(); + } + + @Override + public void run() { + + try { + Socket socket = serverSocket.accept(); + + if (verbose) + System.out.println("[" + this + "] INFO: Clien connected: " + socket.getRemoteSocketAddress() + "."); + + InputStream is = socket.getInputStream(); + OutputStream os = socket.getOutputStream(); + + try { + for (int i = 0; i < packets.length && !shutdown; i++) { + + Packet packet = packets[i]; + switch (packet.type) { + case CLIENT: { + // Read client data and compare it with mock data + // (unless "ignore" option is set) + byte actualData[] = new byte[packet.data.length]; + int actualDataLength = is.read(actualData); + + if (verbose) + System.out.println("[" + this + "] INFO: Data is read: {" + Arrays.toString(Arrays.copyOf(actualData, actualDataLength)) + "}."); + + if (!packet.ignore) { + // Compare actual data with expected data + if (actualDataLength != packet.data.length) { + throw new AssertionError("Actual length of client request for packet #" + (i + 1) + " (\"" + packet.id + "\")" + + " does not match length of expected client request. Actual length: " + actualDataLength + ", expected legnth: " + packet.data.length + + "."); + } + + for (int j = 0; j < packet.data.length; j++) { + + if (packet.data[j] != actualData[j]) { + throw new AssertionError("Actual byte #" + (j + 1) + " of client request for packet #" + (i + 1) + " (\"" + packet.id + "\")" + + " does not match corresponding byte of expected client request. Actual byte: " + actualData[j] + ", expected byte: " + packet.data[j] + + "."); + } + } + } + break; + } + case SERVER: { + // Send mock data to client + os.write(packet.data); + + if (verbose) + System.out.println("[" + this + "] INFO: Data is written: {" + Arrays.toString(packet.data) + "}."); + + break; + } + case UPGRADE_TO_SSL: { + // Attach SSL context to socket + + final SSLSocketFactory sslSocketFactory = (SSLSocketFactory)SSLSocketFactory.getDefault(); + SSLSocket sslSocket = (SSLSocket)sslSocketFactory.createSocket(socket, null, serverSocket.getLocalPort(), true); + sslSocket.setEnabledCipherSuites(sslSocket.getSupportedCipherSuites()); + sslSocket.setUseClientMode(false); + sslSocket.startHandshake(); + is = sslSocket.getInputStream(); + os = sslSocket.getOutputStream(); + + break; + } + default: + throw new RuntimeException("Unknown packet type: " + packet.type); + } + + } + } finally { + try { + is.close(); + } catch (Throwable e) { + } + try { + os.close(); + } catch (Throwable e) { + } + try { + socket.close(); + } catch (Throwable e) { + } + try { + serverSocket.close(); + } catch (Throwable e) { + } + } + } catch (Throwable e) { + System.err.println("Error in mock server: " + e.getMessage()); + e.printStackTrace(System.err); + exception = e; + } + shutdowned = true; + if (verbose) + System.out.println("[" + this + "] INFO: Mock server shutdowned."); + + } + + public void shutdown() { + shutdown = true; + } + + public InetSocketAddress getAddress() { + return (InetSocketAddress)serverSocket.getLocalSocketAddress(); + } + + public Throwable getException() { + return exception; + } + + public static class Packet { + public static enum PacketType { + SERVER, CLIENT, UPGRADE_TO_SSL; + } + + public String id = ""; + + public Packet() { + } + + public Packet(String id) { + this.id = id; + } + + public PacketType type; + + public boolean ignore = false; + + public byte data[]; + } + + public boolean isShutdowned() { + return shutdowned; + } + + public void waitUntilShutdowned(long timeToWaitMiliseconds) throws InterruptedException { + long deadline = System.currentTimeMillis() + timeToWaitMiliseconds; + while (!shutdowned && System.currentTimeMillis() < deadline) { + Thread.sleep(10); + } + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/debug/MockSink.java ---------------------------------------------------------------------- diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/debug/MockSink.java b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/debug/MockSink.java new file mode 100755 index 0000000..fe038a9 --- /dev/null +++ b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/debug/MockSink.java @@ -0,0 +1,154 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package streamer.debug; + +import java.util.Arrays; +import java.util.Set; + +import streamer.BaseElement; +import streamer.ByteBuffer; +import streamer.Direction; +import streamer.Element; +import streamer.Link; +import streamer.SyncLink; + +/** + * Compare incoming packets with expected packets. + */ +public class MockSink extends BaseElement { + + protected ByteBuffer bufs[]; + protected Dumper dumper; + + public MockSink(String id) { + super(id); + } + + public MockSink(String id, ByteBuffer bufs[]) { + super(id); + this.bufs = bufs; + } + + public MockSink(String id, ByteBuffer bufs[], Dumper dumper) { + super(id); + this.bufs = bufs; + this.dumper = dumper; + } + + @Override + public void handleData(ByteBuffer buf, Link link) { + if (verbose) + System.out.println("[" + this + "] INFO: Received buf #" + (packetNumber) + " " + buf + "."); + + if (buf == null) + return; + + if (packetNumber >= bufs.length) + throw new AssertionError("[" + this + "] Incoming buffer #" + packetNumber + " is not expected. Number of expected buffers: " + bufs.length + + ", unexpected buffer: " + buf + "."); + + // Compare incoming buffer with expected buffer + ByteBuffer expectedBuf = bufs[packetNumber]; + if (!Arrays.equals(expectedBuf.toByteArray(), buf.toByteArray())) { + dump(buf, expectedBuf); + throw new AssertionError("[" + this + "] Incoming buffer #" + packetNumber + " is not equal to expected buffer.\n Actual bufer: " + buf + + ",\n expected buffer: " + expectedBuf + "."); + } + + // If expected buffer has metadata, then compare it too + Set metadataKeys = expectedBuf.getMetadataKeys(); + if (metadataKeys.size() > 0) { + for (String key : metadataKeys) { + Object expectedValue = expectedBuf.getMetadata(key); + Object actualValue = buf.getMetadata(key); + if (actualValue == null) + throw new AssertionError("[" + this + "] Incoming buffer #" + packetNumber + " is not equal to expected buffer in metadata for key \"" + key + + "\".\n Actual metadata value: " + actualValue + ",\n expected value: \"" + expectedValue + "\"."); + + if (!expectedValue.equals(actualValue)) + throw new AssertionError("[" + this + "] Incoming buffer #" + packetNumber + " is not equal to expected buffer in metadata for key \"" + key + + "\".\n Actual metadata value: \"" + actualValue + "\",\n expected value: \"" + expectedValue + "\"."); + } + } + + if (verbose) + System.out.println("[" + this + "] INFO: buffers are equal."); + + // Use packetNumber variable to count incoming packets + packetNumber++; + + buf.unref(); + } + + private void dump(ByteBuffer actualData, ByteBuffer expectedData) { + if (dumper != null) { + System.out.println("[" + this + "] INFO: Actual data:"); + dumper.dump(actualData); + System.out.println("[" + this + "] INFO: Expected data:"); + dumper.dump(expectedData); + } + } + + @Override + protected void onClose() { + super.onClose(); + + if (packetNumber != bufs.length) + throw new AssertionError("[" + this + "] Number of expected buffers: " + bufs.length + ", number of actual buffers: " + packetNumber + "."); + } + + @Override + public String toString() { + return "MockSink(" + id + ")"; + } + + /** + * Example. + */ + public static void main(String args[]) { + + Element mockSource = new MockSource("source") { + { + bufs = new ByteBuffer[] {new ByteBuffer(new byte[] {1, 1, 2, 3, 4, 5}), new ByteBuffer(new byte[] {2, 1, 2, 3, 4}), + new ByteBuffer(new byte[] {3, 1, 2, 3}), new ByteBuffer(new byte[] {4, 1, 2}), new ByteBuffer(new byte[] {5, 1})}; + verbose = true; + delay = 100; + numBuffers = bufs.length; + } + }; + + Element mockSink = new MockSink("sink") { + { + bufs = new ByteBuffer[] {new ByteBuffer(new byte[] {1, 1, 2, 3, 4, 5}), new ByteBuffer(new byte[] {2, 1, 2, 3, 4}), + new ByteBuffer(new byte[] {3, 1, 2, 3}), new ByteBuffer(new byte[] {4, 1, 2}), new ByteBuffer(new byte[] {5, 1})}; + verbose = true; + } + }; + + Link link = new SyncLink() { + { + verbose = true; + } + }; + + mockSource.setLink(STDOUT, link, Direction.OUT); + mockSink.setLink(STDIN, link, Direction.IN); + + link.run(); + } + +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/debug/MockSource.java ---------------------------------------------------------------------- diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/debug/MockSource.java b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/debug/MockSource.java new file mode 100755 index 0000000..a77f1d4 --- /dev/null +++ b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/debug/MockSource.java @@ -0,0 +1,95 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package streamer.debug; + +import streamer.ByteBuffer; +import streamer.Direction; +import streamer.Element; +import streamer.Event; +import streamer.Link; +import streamer.SyncLink; + +public class MockSource extends FakeSource { + + protected ByteBuffer bufs[] = null; + + public MockSource(String id) { + super(id); + } + + public MockSource(String id, ByteBuffer bufs[]) { + super(id); + this.bufs = bufs; + } + + /** + * Initialize data. + */ + @Override + public ByteBuffer initializeData() { + if (packetNumber >= bufs.length) { + sendEventToAllPads(Event.STREAM_CLOSE, Direction.OUT); + return null; + } + + ByteBuffer buf = bufs[packetNumber]; + + buf.putMetadata(ByteBuffer.SEQUENCE_NUMBER, packetNumber); + return buf; + } + + @Override + public void handleEvent(Event event, Direction direction) { + if (verbose) + System.out.println("[" + this + "] INFO: Event received: " + event + "."); + + } + + @Override + public String toString() { + return "MockSource(" + id + ")"; + } + + /** + * Example. + */ + public static void main(String args[]) { + + Element mockSource = new MockSource("source") { + { + bufs = new ByteBuffer[] {new ByteBuffer(new byte[] {1, 1, 2, 3, 4, 5}), new ByteBuffer(new byte[] {2, 1, 2, 3, 4}), + new ByteBuffer(new byte[] {3, 1, 2, 3}), new ByteBuffer(new byte[] {4, 1, 2}), new ByteBuffer(new byte[] {5, 1})}; + verbose = true; + delay = 100; + // this.numBuffers = this.bufs.length; + } + }; + + Element fakeSink = new FakeSink("sink") { + { + verbose = true; + } + }; + + Link link = new SyncLink(); + + mockSource.setLink(STDOUT, link, Direction.OUT); + fakeSink.setLink(STDIN, link, Direction.IN); + + link.run(); + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/ssl/SSLState.java ---------------------------------------------------------------------- diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/ssl/SSLState.java b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/ssl/SSLState.java new file mode 100755 index 0000000..f405088 --- /dev/null +++ b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/ssl/SSLState.java @@ -0,0 +1,26 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package streamer.ssl; + +public class SSLState { + + /** + * Server public certificate in ASN.1 BER format. + */ + public byte[] serverCertificateSubjectPublicKeyInfo; + +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/ssl/TrustAllX509TrustManager.java ---------------------------------------------------------------------- diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/ssl/TrustAllX509TrustManager.java b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/ssl/TrustAllX509TrustManager.java new file mode 100755 index 0000000..4d9eac2 --- /dev/null +++ b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/ssl/TrustAllX509TrustManager.java @@ -0,0 +1,52 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package streamer.ssl; + +import java.security.cert.X509Certificate; + +import javax.net.ssl.X509TrustManager; + +public class TrustAllX509TrustManager implements X509TrustManager { + private SSLState sslState; + + public TrustAllX509TrustManager(SSLState sslState) { + this.sslState = sslState; + } + + @Override + public void checkClientTrusted(final X509Certificate[] chain, final String authType) { + // TODO: ask user to confirm self-signed certificates + // Trust all (insecure) + } + + @Override + public void checkServerTrusted(final X509Certificate[] chain, final String authType) { + // TODO: ask user to confirm self-signed certificates + // Trust all (insecure) + + // Store public certificates to use for NTLMSSP negotiation + if (sslState != null) + sslState.serverCertificateSubjectPublicKeyInfo = chain[0].getPublicKey().getEncoded(); + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + // TODO: use system CA certificates here + return null; + } + +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/ssl/UpgradeSocketToSSL.java ---------------------------------------------------------------------- diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/ssl/UpgradeSocketToSSL.java b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/ssl/UpgradeSocketToSSL.java new file mode 100755 index 0000000..9d7c708 --- /dev/null +++ b/services/console-proxy-rdp/rdpconsole/src/main/java/streamer/ssl/UpgradeSocketToSSL.java @@ -0,0 +1,44 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package streamer.ssl; + +import streamer.ByteBuffer; +import streamer.Direction; +import streamer.Event; +import streamer.Link; +import streamer.OneTimeSwitch; + +public class UpgradeSocketToSSL extends OneTimeSwitch { + + public UpgradeSocketToSSL(String id) { + super(id); + } + + @Override + protected void onStart() { + + sendEventToAllPads(Event.SOCKET_UPGRADE_TO_SSL, Direction.IN); + switchOff(); + } + + @Override + protected void handleOneTimeData(ByteBuffer buf, Link link) { + throw new RuntimeException("Unexpected data: " + buf + "."); + + } + +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/AwtKeyboardEventToVncAdapter.java ---------------------------------------------------------------------- diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/AwtKeyboardEventToVncAdapter.java b/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/AwtKeyboardEventToVncAdapter.java deleted file mode 100644 index a804e26..0000000 --- a/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/AwtKeyboardEventToVncAdapter.java +++ /dev/null @@ -1,368 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -package vncclient; - -import java.awt.event.KeyEvent; - -import streamer.BaseElement; -import streamer.ByteBuffer; -import streamer.Link; -import common.KeyOrder; - -public class AwtKeyboardEventToVncAdapter extends BaseElement { - - protected boolean sh = false; - protected boolean caps = false; - protected boolean num = false; - - public AwtKeyboardEventToVncAdapter(String id) { - super(id); - } - - @Override - public void handleData(ByteBuffer buf, Link link) { - if (verbose) - System.out.println("[" + this + "] INFO: Data received: " + buf + "."); - - KeyOrder order = (KeyOrder)buf.getOrder(); - buf.unref(); - - ByteBuffer outBuf = new ByteBuffer(8); - outBuf.writeByte(RfbConstants.CLIENT_KEYBOARD_EVENT); - - outBuf.writeByte((order.pressed) ? RfbConstants.KEY_DOWN : RfbConstants.KEY_UP); - outBuf.writeShort(0); // padding - outBuf.writeInt(map_en_us(order)); - - pushDataToAllOuts(outBuf); - } - - /** - * Return key scan code (in lower byte) and extended flags (in second byte). - */ - private int map_en_us(KeyOrder order) { - - switch (order.event.getKeyCode()) { - // Functional keys - case KeyEvent.VK_ESCAPE: - return 0xff1b; - case KeyEvent.VK_F1: - return 0xffbe; - case KeyEvent.VK_F2: - return 0xffbf; - case KeyEvent.VK_F3: - return 0xffc0; - case KeyEvent.VK_F4: - return 0xffc1; - case KeyEvent.VK_F5: - return 0xffc2; - case KeyEvent.VK_F6: - return 0xffc3; - case KeyEvent.VK_F7: - return 0xffc4; - case KeyEvent.VK_F8: - return 0xffc5; - case KeyEvent.VK_F9: - return 0xffc6; - case KeyEvent.VK_F10: - return 0xffc7; - case KeyEvent.VK_F11: - return 0xffc8; - case KeyEvent.VK_F12: - return 0xffc9; - - // Row #1 - case KeyEvent.VK_BACK_QUOTE: - return (sh) ? '~' : '`'; - case KeyEvent.VK_1: - return (sh) ? '!' : '1'; - case KeyEvent.VK_2: - return (sh) ? '@' : '2'; - case KeyEvent.VK_3: - return (sh) ? '#' : '3'; - case KeyEvent.VK_4: - return (sh) ? '$' : '4'; - case KeyEvent.VK_5: - return (sh) ? '%' : '5'; - case KeyEvent.VK_6: - return (sh) ? '^' : '6'; - case KeyEvent.VK_7: - return (sh) ? '&' : '7'; - case KeyEvent.VK_8: - return (sh) ? '*' : '8'; - case KeyEvent.VK_9: - return (sh) ? '(' : '9'; - case KeyEvent.VK_0: - return (sh) ? ')' : '0'; - case KeyEvent.VK_MINUS: - return (sh) ? '_' : '-'; - case KeyEvent.VK_EQUALS: - return (sh) ? '+' : '='; - case KeyEvent.VK_BACK_SPACE: - return 0xff08; - - // Row #2 - case KeyEvent.VK_TAB: - return 0xff09; - case KeyEvent.VK_Q: - return (sh ^ caps) ? 'Q' : 'q'; - case KeyEvent.VK_W: - return (sh ^ caps) ? 'W' : 'w'; - case KeyEvent.VK_E: - return (sh ^ caps) ? 'E' : 'e'; - case KeyEvent.VK_R: - return (sh ^ caps) ? 'R' : 'r'; - case KeyEvent.VK_T: - return (sh ^ caps) ? 'T' : 't'; - case KeyEvent.VK_Y: - return (sh ^ caps) ? 'Y' : 'y'; - case KeyEvent.VK_U: - return (sh ^ caps) ? 'U' : 'u'; - case KeyEvent.VK_I: - return (sh ^ caps) ? 'I' : 'i'; - case KeyEvent.VK_O: - return (sh ^ caps) ? 'O' : 'o'; - case KeyEvent.VK_P: - return (sh ^ caps) ? 'P' : 'p'; - case KeyEvent.VK_OPEN_BRACKET: - return (sh) ? '{' : '['; - case KeyEvent.VK_CLOSE_BRACKET: - return (sh) ? '{' : ']'; - case KeyEvent.VK_ENTER: - switch (order.event.getKeyLocation()) { - default: - case KeyEvent.KEY_LOCATION_STANDARD: - return 0xff0d; - case KeyEvent.KEY_LOCATION_NUMPAD: - return 0xff8d; - } - - // Row #3 - case KeyEvent.VK_CAPS_LOCK: - if (order.pressed) - caps = !caps; - return 0xFFE5; - case KeyEvent.VK_A: - return (sh ^ caps) ? 'A' : 'a'; - case KeyEvent.VK_S: - return (sh ^ caps) ? 'S' : 's'; - case KeyEvent.VK_D: - return (sh ^ caps) ? 'D' : 'd'; - case KeyEvent.VK_F: - return (sh ^ caps) ? 'F' : 'f'; - case KeyEvent.VK_G: - return (sh ^ caps) ? 'G' : 'g'; - case KeyEvent.VK_H: - return (sh ^ caps) ? 'H' : 'h'; - case KeyEvent.VK_J: - return (sh ^ caps) ? 'J' : 'j'; - case KeyEvent.VK_K: - return (sh ^ caps) ? 'K' : 'k'; - case KeyEvent.VK_L: - return (sh ^ caps) ? 'L' : 'l'; - case KeyEvent.VK_SEMICOLON: - return (sh) ? ':' : ';'; - case KeyEvent.VK_QUOTE: - return (sh) ? '"' : '\''; - - // Row #4 - case KeyEvent.VK_SHIFT: - sh = !sh; - switch (order.event.getKeyLocation()) { - default: - case KeyEvent.KEY_LOCATION_LEFT: - return 0xffe1; - case KeyEvent.KEY_LOCATION_RIGHT: - return 0xffe2; - } - case KeyEvent.VK_BACK_SLASH: - return (sh) ? '|' : '\\'; - case KeyEvent.VK_Z: - return (sh ^ caps) ? 'Z' : 'z'; - case KeyEvent.VK_X: - return (sh ^ caps) ? 'X' : 'x'; - case KeyEvent.VK_C: - return (sh ^ caps) ? 'C' : 'c'; - case KeyEvent.VK_V: - return (sh ^ caps) ? 'V' : 'v'; - case KeyEvent.VK_B: - return (sh ^ caps) ? 'B' : 'b'; - case KeyEvent.VK_N: - return (sh ^ caps) ? 'N' : 'n'; - case KeyEvent.VK_M: - return (sh ^ caps) ? 'M' : 'M'; - case KeyEvent.VK_COMMA: - return (sh) ? '<' : ','; - case KeyEvent.VK_PERIOD: - return (sh) ? '>' : '.'; - case KeyEvent.VK_SLASH: - return (sh) ? '?' : '/'; - - // - // Bottom row - case KeyEvent.VK_CONTROL: - switch (order.event.getKeyLocation()) { - default: - case KeyEvent.KEY_LOCATION_LEFT: - return 0xFFE3; - case KeyEvent.KEY_LOCATION_RIGHT: - return 0xFFE4; - } - case KeyEvent.VK_WINDOWS: - switch (order.event.getKeyLocation()) { - default: - case KeyEvent.KEY_LOCATION_LEFT: - return 0xFFED; // HyperL - case KeyEvent.KEY_LOCATION_RIGHT: - return 0xFFEE; // HyperR - } - case KeyEvent.VK_META: - switch (order.event.getKeyLocation()) { - default: - case KeyEvent.KEY_LOCATION_LEFT: - return 0xFFE7; // MetaL - case KeyEvent.KEY_LOCATION_RIGHT: - return 0xFFE8; // MetaR - } - - case KeyEvent.VK_ALT: - switch (order.event.getKeyLocation()) { - default: - case KeyEvent.KEY_LOCATION_LEFT: - return 0xFFE9; - case KeyEvent.KEY_LOCATION_RIGHT: - return 0xFFEA; - } - case KeyEvent.VK_ALT_GRAPH: - return 0xfe03; - - case KeyEvent.VK_SPACE: - return ' '; - - case KeyEvent.VK_CONTEXT_MENU: - return 0xff67; - - // - // Special keys - case KeyEvent.VK_PRINTSCREEN: - return (sh) ? 0xFF15/* SysRq */: 0xFF61 /* Print */; - case KeyEvent.VK_SCROLL_LOCK: - return 0xFF14; - case KeyEvent.VK_PAUSE: - return (sh) ? 0xFF6B/* Break */: 0xFF13/* Pause */; - - // Text navigation keys - case KeyEvent.VK_INSERT: - return 0xff63; - case KeyEvent.VK_DELETE: - return 0xffff; - case KeyEvent.VK_HOME: - return 0xff50; - case KeyEvent.VK_END: - return 0xff57; - case KeyEvent.VK_PAGE_UP: - return 0xff55; - case KeyEvent.VK_PAGE_DOWN: - return 0xff56; - - // Cursor keys - case KeyEvent.VK_LEFT: - switch (order.event.getKeyLocation()) { - default: - case KeyEvent.KEY_LOCATION_LEFT: - return 0xff51; - case KeyEvent.KEY_LOCATION_NUMPAD: - return 0xFF96; - } - case KeyEvent.VK_UP: - switch (order.event.getKeyLocation()) { - default: - case KeyEvent.KEY_LOCATION_LEFT: - return 0xff52; - case KeyEvent.KEY_LOCATION_NUMPAD: - return 0xFF97; - } - case KeyEvent.VK_RIGHT: - switch (order.event.getKeyLocation()) { - default: - case KeyEvent.KEY_LOCATION_LEFT: - return 0xff53; - case KeyEvent.KEY_LOCATION_NUMPAD: - return 0xFF98; - } - case KeyEvent.VK_DOWN: - switch (order.event.getKeyLocation()) { - default: - case KeyEvent.KEY_LOCATION_LEFT: - return 0xff54; - case KeyEvent.KEY_LOCATION_NUMPAD: - return 0xFF99; - } - - // Keypad - case KeyEvent.VK_NUM_LOCK: - if (order.pressed) - num = !num; - return 0xFF6F; - case KeyEvent.VK_DIVIDE: - return 0xFFAF; - case KeyEvent.VK_MULTIPLY: - return 0xFFAA; - case KeyEvent.VK_SUBTRACT: - return 0xFFAD; - case KeyEvent.VK_ADD: - return 0xFFAB; - - case KeyEvent.VK_KP_LEFT: - return 0xFF96; - case KeyEvent.VK_KP_UP: - return 0xFF97; - case KeyEvent.VK_KP_RIGHT: - return 0xFF98; - case KeyEvent.VK_KP_DOWN: - return 0xFF99; - - case KeyEvent.VK_NUMPAD0: - return 0xFFB0; - case KeyEvent.VK_NUMPAD1: - return 0xFFB1; - case KeyEvent.VK_NUMPAD2: - return 0xFFB2; - case KeyEvent.VK_NUMPAD3: - return 0xFFB3; - case KeyEvent.VK_NUMPAD4: - return 0xFFB4; - case KeyEvent.VK_NUMPAD5: - return 0xFFB5; - case KeyEvent.VK_NUMPAD6: - return 0xFFB6; - case KeyEvent.VK_NUMPAD7: - return 0xFFB7; - case KeyEvent.VK_NUMPAD8: - return 0xFFB8; - case KeyEvent.VK_NUMPAD9: - return 0xFFB9; - case KeyEvent.VK_DECIMAL: - return 0xFFAE; - - default: - System.err.println("Key is not mapped: " + order + "."); - return ' '; // Space - } - } - -} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/AwtMouseEventToVncAdapter.java ---------------------------------------------------------------------- diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/AwtMouseEventToVncAdapter.java b/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/AwtMouseEventToVncAdapter.java deleted file mode 100644 index 8af0195..0000000 --- a/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/AwtMouseEventToVncAdapter.java +++ /dev/null @@ -1,71 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -package vncclient; - -import java.awt.event.InputEvent; - -import streamer.BaseElement; -import streamer.ByteBuffer; -import streamer.Link; -import common.MouseOrder; - -public class AwtMouseEventToVncAdapter extends BaseElement { - - public AwtMouseEventToVncAdapter(String id) { - super(id); - } - - @Override - public void handleData(ByteBuffer buf, Link link) { - if (verbose) - System.out.println("[" + this + "] INFO: Data received: " + buf + "."); - - // Get mouse event - MouseOrder order = (MouseOrder)buf.getOrder(); - - ByteBuffer outBuf = new ByteBuffer(6); - - outBuf.writeByte(RfbConstants.CLIENT_POINTER_EVENT); - - int buttonMask = mapAwtModifiersToVncButtonMask(order.event.getModifiersEx()); - outBuf.writeByte(buttonMask); - outBuf.writeShort(order.event.getX()); - outBuf.writeShort(order.event.getY()); - - pushDataToAllOuts(outBuf); - } - - /** - * Current state of buttons 1 to 8 are represented by bits 0 to 7 of - * button-mask respectively, 0 meaning up, 1 meaning down (pressed). On a - * conventional mouse, buttons 1, 2 and 3 correspond to the left, middle and - * right buttons on the mouse. On a wheel mouse, each step of the wheel - * upwards is represented by a press and release of button 4, and each step - * downwards is represented by a press and release of button 5. - * - * @param modifiers - * extended modifiers from AWT mouse event - * @return VNC mouse button mask - */ - public static int mapAwtModifiersToVncButtonMask(int modifiers) { - int mask = - (((modifiers & InputEvent.BUTTON1_DOWN_MASK) != 0) ? 0x1 : 0) | (((modifiers & InputEvent.BUTTON2_DOWN_MASK) != 0) ? 0x2 : 0) | - (((modifiers & InputEvent.BUTTON3_DOWN_MASK) != 0) ? 0x4 : 0); - return mask; - } - -} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/EncodingsMessage.java ---------------------------------------------------------------------- diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/EncodingsMessage.java b/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/EncodingsMessage.java deleted file mode 100644 index 81540d6..0000000 --- a/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/EncodingsMessage.java +++ /dev/null @@ -1,63 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -package vncclient; - -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/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/FrameBufferUpdateRequest.java ---------------------------------------------------------------------- diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/FrameBufferUpdateRequest.java b/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/FrameBufferUpdateRequest.java deleted file mode 100644 index 0081827..0000000 --- a/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/FrameBufferUpdateRequest.java +++ /dev/null @@ -1,126 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -package vncclient; - -import streamer.BaseElement; -import streamer.ByteBuffer; -import streamer.Element; -import streamer.Link; -import streamer.MockSink; -import streamer.MockSource; -import streamer.Pipeline; -import streamer.PipelineImpl; -import common.ScreenDescription; - -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/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/RGB888LE32PixelFormatRequest.java ---------------------------------------------------------------------- diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/RGB888LE32PixelFormatRequest.java b/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/RGB888LE32PixelFormatRequest.java deleted file mode 100644 index 32de903..0000000 --- a/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/RGB888LE32PixelFormatRequest.java +++ /dev/null @@ -1,89 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -package vncclient; - -import streamer.BaseElement; -import streamer.ByteBuffer; -import streamer.Link; -import common.ScreenDescription; - -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/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/RfbConstants.java ---------------------------------------------------------------------- diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/RfbConstants.java b/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/RfbConstants.java deleted file mode 100644 index 7359cd3..0000000 --- a/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/RfbConstants.java +++ /dev/null @@ -1,85 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -package vncclient; - -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/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/Vnc33Authentication.java ---------------------------------------------------------------------- diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/Vnc33Authentication.java b/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/Vnc33Authentication.java deleted file mode 100644 index de1036c..0000000 --- a/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/Vnc33Authentication.java +++ /dev/null @@ -1,292 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -package vncclient; - -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.FakeSink; -import streamer.Link; -import streamer.MockSink; -import streamer.MockSource; -import streamer.OneTimeSwitch; -import streamer.Pipeline; -import streamer.PipelineImpl; - -public class Vnc33Authentication extends OneTimeSwitch { - - /** - * Password to use when authentication is required. - */ - protected String password = null; - - /** - * Authentication stage: - *
    - *
  • 0 - challenge received, response must be sent - *
  • 1 - authentication result received. - *
- */ - protected int stage = 0; - - public Vnc33Authentication(String id) { - super(id); - } - - public Vnc33Authentication(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(); - - } - - @Override - 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 Vnc33Authentication auth = new Vnc33Authentication("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/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/Vnc33Hello.java ---------------------------------------------------------------------- diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/Vnc33Hello.java b/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/Vnc33Hello.java deleted file mode 100644 index 63d0caa..0000000 --- a/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/Vnc33Hello.java +++ /dev/null @@ -1,116 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -package vncclient; - -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 Vnc33Hello extends OneTimeSwitch { - - public Vnc33Hello(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(); - - } - - @Override - 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); - - Vnc33Hello hello = new Vnc33Hello("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/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/VncClient.java ---------------------------------------------------------------------- diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/VncClient.java b/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/VncClient.java old mode 100644 new mode 100755 index c035b52..1c76656 --- a/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/VncClient.java +++ b/services/console-proxy-rdp/rdpconsole/src/main/java/vncclient/VncClient.java @@ -18,13 +18,23 @@ package vncclient; import streamer.PipelineImpl; import streamer.Queue; -import common.AwtBellAdapter; -import common.AwtCanvasAdapter; -import common.AwtClipboardAdapter; +import vncclient.adapter.AwtVncKeyboardAdapter; +import vncclient.adapter.AwtVncMouseAdapter; +import vncclient.vnc.EncodingsMessage; +import vncclient.vnc.FrameBufferUpdateRequest; +import vncclient.vnc.RGB888LE32PixelFormatRequest; +import vncclient.vnc.RfbConstants; +import vncclient.vnc.VncInitializer; +import vncclient.vnc.VncMessageHandler; +import vncclient.vnc.Vnc33Authentication; +import vncclient.vnc.Vnc33Hello; import common.AwtKeyEventSource; import common.AwtMouseEventSource; import common.BufferedImageCanvas; import common.ScreenDescription; +import common.adapter.AwtBellAdapter; +import common.adapter.AwtCanvasAdapter; +import common.adapter.AwtClipboardAdapter; public class VncClient extends PipelineImpl { @@ -44,41 +54,41 @@ public class VncClient extends PipelineImpl { canvas.addKeyListener(keyEventSource); add( - // Handshake + // Handshake - // RFB protocol version exchanger - new Vnc33Hello("hello"), - // Authenticator - new Vnc33Authentication("auth", password), - // Initializer - new VncInitializer("init", true, screen), + // RFB protocol version exchanger + new Vnc33Hello("hello"), + // Authenticator + new Vnc33Authentication("auth", password), + // Initializer + new VncInitializer("init", true, screen), - new EncodingsMessage("encodings", RfbConstants.SUPPORTED_ENCODINGS_ARRAY), + new EncodingsMessage("encodings", RfbConstants.SUPPORTED_ENCODINGS_ARRAY), - new RGB888LE32PixelFormatRequest("pixel_format", screen), + new RGB888LE32PixelFormatRequest("pixel_format", screen), - // Main + // Main - // Packet receiver - new VncMessageHandler("message_handler", screen), + // Packet receiver + new VncMessageHandler("message_handler", screen), - new AwtBellAdapter("bell"), + new AwtBellAdapter("bell"), - new AwtClipboardAdapter("clipboard"), + new AwtClipboardAdapter("clipboard"), - new AwtCanvasAdapter("pixels", canvas, screen), + new AwtCanvasAdapter("pixels", canvas, screen), - new Queue("queue"), + new Queue("queue"), - new FrameBufferUpdateRequest("fbur", screen), + new FrameBufferUpdateRequest("fbur", screen), - new AwtKeyboardEventToVncAdapter("keyboard_adapter"), + new AwtVncKeyboardAdapter("keyboard_adapter"), - new AwtMouseEventToVncAdapter("mouse_adapter"), + new AwtVncMouseAdapter("mouse_adapter"), - mouseEventSource, keyEventSource + mouseEventSource, keyEventSource - ); + ); // Link handshake elements link("IN", "hello", "auth", "init", "message_handler");