Skip to content

Commit a98c473

Browse files
committed
Remote Desktop Protocol(RDP) client that is suitable for including in the console VM.
The client renders RDP to a window created by Java. It is important for Hyper-V support, because Hyper-V provides access to the consoles of VMs that it is running over RDP.
1 parent 57ba367 commit a98c473

98 files changed

Lines changed: 16550 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
This project contains code for basic VNC and RDP clients.
18+
19+
VNC client can be invoked using following command:
20+
21+
mvn exec:java -Dexec.mainClass="common.Client" -Dexec.args="vnc 192.168.0.101 5901 password"
22+
23+
where
24+
* vnc - name of protcol;
25+
* 192.168.0.101 - IP of VNC server;
26+
* 5901 - port of VNC server screen (5900+display number);
27+
* password - VNC server password.
28+
29+
30+
RDP client can be invoked using following command:
31+
32+
mvn exec:java -Dexec.mainClass="common.Client" -Dexec.args="rdp 192.168.0.101 3389 Administrator"
33+
34+
where
35+
* rdp - name of protcol;
36+
* 192.168.0.101 - IP of RDP server;
37+
* 3389 - port of RDP server;
38+
* Administrator - user name for loging dialog.
39+
40+
41+
Limitations of VNC client:
42+
* only basic functionality work.
43+
44+
Limitations of RDP client:
45+
* it uses SSL/TLS;
46+
* NLA is not supported;
47+
* only basic functionality work.
48+
49+
50+
To configure and start RDP service properly, run rdp-config.bat on server.
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<!--
2+
Licensed to the Apache Software Foundation (ASF) under one
3+
or more contributor license agreements. See the NOTICE file
4+
distributed with this work for additional information
5+
regarding copyright ownership. The ASF licenses this file
6+
to you under the Apache License, Version 2.0 (the
7+
"License"); you may not use this file except in compliance
8+
with the License. You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing,
13+
software distributed under the License is distributed on an
14+
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
KIND, either express or implied. See the License for the
16+
specific language governing permissions and limitations
17+
under the License.
18+
-->
19+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
20+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
21+
<modelVersion>4.0.0</modelVersion>
22+
23+
<groupId>rdpclient</groupId>
24+
<artifactId>rdpclient</artifactId>
25+
<version>4.3.0-SNAPSHOT</version>
26+
<packaging>jar</packaging>
27+
28+
<name>rdpclient</name>
29+
<url>http://maven.apache.org</url>
30+
31+
<properties>
32+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
33+
</properties>
34+
35+
<dependencies>
36+
<dependency>
37+
<groupId>junit</groupId>
38+
<artifactId>junit</artifactId>
39+
<version>3.8.1</version>
40+
<scope>test</scope>
41+
</dependency>
42+
<dependency>
43+
<groupId>org.apache.tomcat.embed</groupId>
44+
<artifactId>tomcat-embed-core</artifactId>
45+
<version>7.0.30</version>
46+
<scope>test</scope>
47+
</dependency>
48+
</dependencies>
49+
</project>
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
rem Licensed to the Apache Software Foundation (ASF) under one
2+
rem or more contributor license agreements. See the NOTICE file
3+
rem distributed with this work for additional information
4+
rem regarding copyright ownership. The ASF licenses this file
5+
rem to you under the Apache License, Version 2.0 (the
6+
rem "License"); you may not use this file except in compliance
7+
rem with the License. You may obtain a copy of the License at
8+
rem
9+
rem http://www.apache.org/licenses/LICENSE-2.0
10+
rem
11+
rem Unless required by applicable law or agreed to in writing,
12+
rem software distributed under the License is distributed on an
13+
rem "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
rem KIND, either express or implied. See the License for the
15+
rem specific language governing permissions and limitations
16+
rem under the License.
17+
18+
rem
19+
rem Configure and start RDP service.
20+
rem
21+
22+
rem Turn off firewall
23+
24+
netsh advfirewall firewall set rule group="Remote Desktop" new enable=yes
25+
26+
rem Enable TS connections
27+
28+
reg add "HKLM\System\CurrentControlSet\Control\Terminal Server" /v "AllowTSConnections" /t REG_DWORD /d 1 /f
29+
reg add "HKLM\System\CurrentControlSet\Control\Terminal Server" /v "fDenyTSConnections" /t REG_DWORD /d 0 /f
30+
31+
rem Disable RDP NLA
32+
33+
reg add "HKLM\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" /v UserAuthentication /t REG_DWORD /d 0 /f
34+
35+
rem Enable TS service
36+
37+
sc config TermService start=auto
38+
39+
rem Start TS service
40+
41+
net start Termservice
42+
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
package common;
18+
19+
import java.awt.Toolkit;
20+
21+
import streamer.BaseElement;
22+
import streamer.ByteBuffer;
23+
import streamer.Element;
24+
import streamer.FakeSource;
25+
import streamer.Link;
26+
import streamer.Pipeline;
27+
import streamer.PipelineImpl;
28+
29+
public class AwtBellAdapter extends BaseElement {
30+
31+
public AwtBellAdapter(String id) {
32+
super(id);
33+
declarePads();
34+
}
35+
36+
private void declarePads() {
37+
inputPads.put(STDIN, null);
38+
}
39+
40+
@Override
41+
public void handleData(ByteBuffer buf, Link link) {
42+
if (verbose)
43+
System.out.println("[" + this + "] INFO: Data received: " + buf + ".");
44+
45+
if (buf == null)
46+
return;
47+
48+
Toolkit.getDefaultToolkit().beep();
49+
}
50+
51+
public String toString() {
52+
return "Bell(" + id + ")";
53+
}
54+
55+
/**
56+
* Example.
57+
*/
58+
public static void main(String args[]) {
59+
System.setProperty("streamer.Element.debug", "true");
60+
61+
Element source = new FakeSource("source") {
62+
{
63+
this.incommingBufLength = 0;
64+
this.delay = 1000;
65+
this.numBuffers = 3;
66+
}
67+
};
68+
69+
Element sink = new AwtBellAdapter("sink");
70+
71+
Pipeline pipeline = new PipelineImpl("test");
72+
pipeline.addAndLink(source, sink);
73+
pipeline.runMainLoop("source", STDOUT, false, false);
74+
}
75+
76+
}
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
package common;
18+
19+
import java.awt.Graphics2D;
20+
import java.awt.image.BufferedImage;
21+
import java.awt.image.WritableRaster;
22+
23+
import rdpclient.ServerBitmapUpdate;
24+
import streamer.BaseElement;
25+
import streamer.ByteBuffer;
26+
import streamer.Element;
27+
import streamer.Link;
28+
import streamer.Order;
29+
import streamer.Pipeline;
30+
import streamer.PipelineImpl;
31+
32+
public class AwtCanvasAdapter extends BaseElement {
33+
34+
protected ScreenDescription screen;
35+
36+
public AwtCanvasAdapter(String id, BufferedImageCanvas canvas, ScreenDescription screen) {
37+
super(id);
38+
this.canvas = canvas;
39+
this.screen = screen;
40+
}
41+
42+
protected BufferedImageCanvas canvas;
43+
44+
public String toString() {
45+
return "AwtRdpAdapter(" + id + ")";
46+
}
47+
48+
@Override
49+
public void handleData(ByteBuffer buf, Link link) {
50+
if (verbose)
51+
System.out.println("[" + this + "] INFO: Data received: " + buf + ".");
52+
53+
Order order = (Order) buf.getOrder();
54+
switch ((OrderType) order.type) {
55+
56+
case BITMAP_UPDATE:
57+
handleBitmap((BitmapOrder) order, buf);
58+
break;
59+
60+
case COPY_RECT:
61+
handleCopyRect((CopyRectOrder) order, buf);
62+
break;
63+
64+
default:
65+
throw new RuntimeException("Order is not implemented: " + buf + ".");
66+
// break;
67+
}
68+
69+
buf.unref();
70+
}
71+
72+
private void handleCopyRect(CopyRectOrder order, ByteBuffer buf) {
73+
// TODO Auto-generated method stub
74+
// Copy image
75+
canvas.getOfflineGraphics().copyArea(order.srcX, order.srcY, order.width, order.height, order.x - order.srcX, order.y - order.srcY);
76+
77+
// Request update of repainted area
78+
canvas.repaint(order.x, order.y, order.width, order.height);
79+
80+
}
81+
82+
private void handleBitmap(BitmapOrder order, ByteBuffer buf) {
83+
// Draw rectangle on offline buffer
84+
BufferedImage image = canvas.getOfflineImage();
85+
Graphics2D g = (Graphics2D) image.getGraphics();
86+
87+
for (BitmapRectangle rectangle : order.rectangles) {
88+
// *DEBUG*/System.out.println("["+this+"] DEBUG: Rectangle: " +
89+
// rectangle.toString());
90+
91+
int x = rectangle.x;
92+
int y = rectangle.y;
93+
int width = rectangle.width;
94+
int height = rectangle.height;
95+
int bufferWidth = rectangle.bufferWidth;
96+
int bufferHeight = rectangle.bufferHeight;
97+
98+
BufferedImage rectImage;
99+
switch (rectangle.colorDepth) {
100+
case 8: {
101+
rectImage = new BufferedImage(bufferWidth, height, BufferedImage.TYPE_BYTE_INDEXED, screen.colorMap);
102+
WritableRaster raster = rectImage.getRaster();
103+
raster.setDataElements(0, 0, bufferWidth, bufferHeight, rectangle.bitmapDataStream.toByteArray());
104+
break;
105+
}
106+
case 15: {
107+
rectImage = new BufferedImage(bufferWidth, height, BufferedImage.TYPE_USHORT_555_RGB);
108+
WritableRaster raster = rectImage.getRaster();
109+
raster.setDataElements(0, 0, bufferWidth, bufferHeight, rectangle.bitmapDataStream.toShortArray());
110+
break;
111+
}
112+
case 16: {
113+
rectImage = new BufferedImage(bufferWidth, height, BufferedImage.TYPE_USHORT_565_RGB);
114+
WritableRaster raster = rectImage.getRaster();
115+
raster.setDataElements(0, 0, bufferWidth, bufferHeight, rectangle.bitmapDataStream.toShortArray());
116+
break;
117+
}
118+
case 24:
119+
case 32: {
120+
rectImage = new BufferedImage(bufferWidth, height, BufferedImage.TYPE_INT_RGB);
121+
WritableRaster raster = rectImage.getRaster();
122+
raster.setDataElements(0, 0, bufferWidth, bufferHeight, rectangle.bitmapDataStream.toIntLEArray());
123+
break;
124+
}
125+
default:
126+
throw new RuntimeException("Unsupported color depth: " + rectangle.colorDepth + ".");
127+
}
128+
129+
g.setClip(x, y, width, height);
130+
g.drawImage(rectImage, x, y, null);
131+
132+
// Request update of repainted area
133+
canvas.repaint(x, y, width, height);
134+
}
135+
136+
}
137+
138+
/**
139+
* Example.
140+
*/
141+
public static void main(String args[]) {
142+
// System.setProperty("streamer.Link.debug", "true");
143+
// System.setProperty("streamer.Element.debug", "true");
144+
// System.setProperty("streamer.Pipeline.debug", "true");
145+
ByteBuffer packet = new ByteBuffer(new byte[] { 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x10, 0x00,
146+
0x01, 0x04, 0x0a, 0x00, 0x0c, (byte) 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 });
147+
148+
Pipeline pipeline = new PipelineImpl("test");
149+
150+
Element bitmap = new ServerBitmapUpdate("bitmap");
151+
152+
BufferedImageCanvas canvas = new BufferedImageCanvas(1024, 768);
153+
Element adapter = new AwtCanvasAdapter("test", canvas, null) {
154+
{
155+
verbose = true;
156+
}
157+
};
158+
pipeline.addAndLink(bitmap, adapter);
159+
160+
bitmap.handleData(packet, null);
161+
162+
}
163+
164+
}

0 commit comments

Comments
 (0)