Skip to content

Commit 27c7713

Browse files
author
Kelven Yang
committed
Console proxy refactoring - new VNC engine is plugged in
1 parent bed3f7f commit 27c7713

26 files changed

Lines changed: 1504 additions & 994 deletions

console-proxy/src/com/cloud/consoleproxy/ConsoleProxy.java

Lines changed: 442 additions & 688 deletions
Large diffs are not rendered by default.

console-proxy/src/com/cloud/consoleproxy/ConsoleProxyAjaxHandler.java

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -114,22 +114,11 @@ private void doHandle(HttpExchange t) throws Exception, IllegalArgumentException
114114
}
115115
}
116116

117-
ConsoleProxyViewer viewer = null;
117+
ConsoleProxyClient viewer = null;
118118
try {
119119
viewer = ConsoleProxy.getAjaxVncViewer(host, port, sid, tag, ticket, ajaxSessionIdStr);
120120
} catch(Exception e) {
121121

122-
/*
123-
StringWriter writer = new StringWriter();
124-
try {
125-
ConsoleProxy.processTemplate("viewer-bad-sid.ftl", null, writer);
126-
} catch (IOException ex) {
127-
s_logger.warn("Unexpected exception in processing template.", e);
128-
} catch (TemplateException ex) {
129-
s_logger.warn("Unexpected exception in processing template.", e);
130-
}
131-
StringBuffer sb = writer.getBuffer();
132-
*/
133122
s_logger.warn("Failed to create viwer due to " + e.getMessage(), e);
134123

135124
String[] content = new String[] {
@@ -236,7 +225,8 @@ private void sendResponse(HttpExchange t, String contentType, String response) t
236225
}
237226
}
238227

239-
private void handleClientEventBag(ConsoleProxyViewer viewer, String requestData) {
228+
@SuppressWarnings("deprecation")
229+
private void handleClientEventBag(ConsoleProxyClient viewer, String requestData) {
240230
if(s_logger.isTraceEnabled())
241231
s_logger.trace("Handle event bag, event bag: " + requestData);
242232

@@ -294,7 +284,7 @@ else if(start > 0)
294284
}
295285
}
296286

297-
private void handleClientEvent(ConsoleProxyViewer viewer, int event, Map<String, String> queryMap) {
287+
private void handleClientEvent(ConsoleProxyClient viewer, int event, Map<String, String> queryMap) {
298288
int code = 0;
299289
int x = 0, y = 0;
300290
int modifiers = 0;
@@ -347,7 +337,7 @@ private void handleClientEvent(ConsoleProxyViewer viewer, int event, Map<String,
347337
if(s_logger.isTraceEnabled())
348338
s_logger.trace("Handle client mouse move event. x: " + x + ", y: " + y);
349339
}
350-
viewer.sendClientMouseEvent(event, x, y, code, modifiers);
340+
viewer.sendClientMouseEvent(InputEventType.fromEventCode(event), x, y, code, modifiers);
351341
break;
352342

353343
case 4: // key press
@@ -371,15 +361,15 @@ private void handleClientEvent(ConsoleProxyViewer viewer, int event, Map<String,
371361

372362
if(s_logger.isDebugEnabled())
373363
s_logger.debug("Handle client keyboard event. event: " + event + ", code: " + code + ", modifier: " + modifiers);
374-
viewer.sendClientRawKeyboardEvent(event, code, modifiers);
364+
viewer.sendClientRawKeyboardEvent(InputEventType.fromEventCode(event), code, modifiers);
375365
break;
376366

377367
default :
378368
break;
379369
}
380370
}
381371

382-
private void handleClientKickoff(HttpExchange t, ConsoleProxyViewer viewer) throws IOException {
372+
private void handleClientKickoff(HttpExchange t, ConsoleProxyClient viewer) throws IOException {
383373
String response = viewer.onAjaxClientKickoff();
384374
t.sendResponseHeaders(200, response.length());
385375
OutputStream os = t.getResponseBody();
@@ -390,7 +380,7 @@ private void handleClientKickoff(HttpExchange t, ConsoleProxyViewer viewer) thro
390380
}
391381
}
392382

393-
private void handleClientStart(HttpExchange t, ConsoleProxyViewer viewer, String title, String guest) throws IOException {
383+
private void handleClientStart(HttpExchange t, ConsoleProxyClient viewer, String title, String guest) throws IOException {
394384
List<String> languages = t.getRequestHeaders().get("Accept-Language");
395385
String response = viewer.onAjaxClientStart(title, languages, guest);
396386

@@ -408,7 +398,7 @@ private void handleClientStart(HttpExchange t, ConsoleProxyViewer viewer, String
408398
}
409399
}
410400

411-
private void handleClientUpdate(HttpExchange t, ConsoleProxyViewer viewer) throws IOException {
401+
private void handleClientUpdate(HttpExchange t, ConsoleProxyClient viewer) throws IOException {
412402
String response = viewer.onAjaxClientUpdate();
413403

414404
Headers hds = t.getResponseHeaders();

console-proxy/src/com/cloud/consoleproxy/ConsoleProxyAjaxImageHandler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ private void doHandle(HttpExchange t) throws Exception, IllegalArgumentException
9191
throw new IllegalArgumentException(e);
9292
}
9393

94-
ConsoleProxyViewer viewer = ConsoleProxy.getVncViewer(host, port, sid, tag, ticket);
94+
ConsoleProxyClient viewer = ConsoleProxy.getVncViewer(host, port, sid, tag, ticket);
9595
byte[] img = viewer.getAjaxImageCache().getImage(key);
9696
if(img != null) {
9797
Headers hds = t.getResponseHeaders();
Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,56 @@
11
package com.cloud.consoleproxy;
22

3+
import java.awt.Image;
4+
import java.util.List;
5+
36
/**
47
* @author Kelven Yang
58
* ConsoleProxyClient defines an standard interface that a console client should implement,
69
* example of such console clients could be a VNC client or a RDP client
710
*
811
* ConsoleProxyClient maintains a session towards the target host, it glues the session
9-
* to a AJAX frontend viewer
12+
* to a AJAX front-end viewer
1013
*/
1114
public interface ConsoleProxyClient {
1215
int getClientId();
1316

17+
//
18+
// Quick status
19+
//
20+
boolean isHostConnected();
21+
boolean isFrontEndAlive();
22+
23+
//
24+
// AJAX viewer
25+
//
26+
long getAjaxSessionId();
27+
AjaxFIFOImageCache getAjaxImageCache();
28+
Image getClientScaledImage(int width, int height); // client thumbnail support
29+
30+
String onAjaxClientStart(String title, List<String> languages, String guest);
31+
String onAjaxClientUpdate();
32+
String onAjaxClientKickoff();
33+
34+
//
35+
// Input handling
36+
//
37+
void sendClientRawKeyboardEvent(InputEventType event, int code, int modifiers);
38+
void sendClientMouseEvent(InputEventType event, int x, int y, int code, int modifiers);
39+
40+
//
41+
// Info/Stats
42+
//
1443
long getClientCreateTime();
1544
long getClientLastFrontEndActivityTime();
16-
1745
String getClientHostAddress();
1846
int getClientHostPort();
1947
String getClientHostPassword();
2048
String getClientTag();
2149

50+
//
51+
// Setup/house-keeping
52+
//
2253
void initClient(String clientHostAddress, int clientHostPort,
23-
String clientHostPassword, String clientTag);
54+
String clientHostPassword, String clientTag, String ticket);
2455
void closeClient();
2556
}

console-proxy/src/com/cloud/consoleproxy/ConsoleProxyClientBase.java

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.cloud.consoleproxy;
22

3+
import java.awt.Image;
34
import java.awt.Rectangle;
45
import java.util.List;
56

@@ -8,7 +9,6 @@
89
import com.cloud.console.TileInfo;
910
import com.cloud.console.TileTracker;
1011
import com.cloud.consoleproxy.vnc.FrameBufferCanvas;
11-
import com.cloud.consoleproxy.vnc.FrameBufferEventListener;
1212

1313
/**
1414
*
@@ -20,7 +20,7 @@
2020
* It mainly implements the features needed by front-end AJAX viewer
2121
*
2222
*/
23-
public abstract class ConsoleProxyClientBase implements ConsoleProxyClient, FrameBufferEventListener {
23+
public abstract class ConsoleProxyClientBase implements ConsoleProxyClient, ConsoleProxyClientListener {
2424
private static final Logger s_logger = Logger.getLogger(ConsoleProxyClientBase.class);
2525

2626
private static int s_nextClientId = 0;
@@ -37,6 +37,7 @@ public abstract class ConsoleProxyClientBase implements ConsoleProxyClient, Fram
3737
protected int port;
3838
protected String passwordParam;
3939
protected String tag = "";
40+
protected String ticket = "";
4041
protected long createTime = System.currentTimeMillis();
4142
protected long lastFrontEndActivityTime = System.currentTimeMillis();
4243

@@ -45,6 +46,8 @@ public abstract class ConsoleProxyClientBase implements ConsoleProxyClient, Fram
4546
protected int resizedFramebufferHeight;
4647

4748
public ConsoleProxyClientBase() {
49+
tracker = new TileTracker();
50+
tracker.initTracking(64, 64, 800, 600);
4851
}
4952

5053
//
@@ -55,6 +58,30 @@ public int getClientId() {
5558
return clientId;
5659
}
5760

61+
public abstract boolean isHostConnected();
62+
public abstract boolean isFrontEndAlive();
63+
64+
@Override
65+
public long getAjaxSessionId() {
66+
return this.ajaxSessionId;
67+
}
68+
69+
@Override
70+
public AjaxFIFOImageCache getAjaxImageCache() {
71+
return ajaxImageCache;
72+
}
73+
74+
public Image getClientScaledImage(int width, int height) {
75+
FrameBufferCanvas canvas = getFrameBufferCavas();
76+
if(canvas != null)
77+
return canvas.getFrameBufferScaledImage(width, height);
78+
79+
return null;
80+
}
81+
82+
public abstract void sendClientRawKeyboardEvent(InputEventType event, int code, int modifiers);
83+
public abstract void sendClientMouseEvent(InputEventType event, int x, int y, int code, int modifiers);
84+
5885
@Override
5986
public long getClientCreateTime() {
6087
return createTime;
@@ -87,8 +114,8 @@ public String getClientTag() {
87114

88115
@Override
89116
public abstract void initClient(String clientHostAddress, int clientHostPort,
90-
String clientHostPassword, String clientTag);
91-
117+
String clientHostPassword, String clientTag, String ticket);
118+
92119
@Override
93120
public abstract void closeClient();
94121

@@ -170,6 +197,7 @@ private String prepareAjaxSession(boolean init) {
170197
return sb.toString();
171198
}
172199

200+
@Override
173201
public String onAjaxClientKickoff() {
174202
return "onKickoff();";
175203
}
@@ -193,8 +221,11 @@ private String onAjaxClientConnectFailed() {
193221
"Unable to start console session as connection is refused by the machine you are accessing" +
194222
"</p></div></body></html>";
195223
}
196-
224+
225+
@Override
197226
public String onAjaxClientStart(String title, List<String> languages, String guest) {
227+
updateFrontEndActivityTime();
228+
198229
if(!waitForViewerReady())
199230
return onAjaxClientConnectFailed();
200231

@@ -317,8 +348,10 @@ private String getAjaxViewerPageContent(String tileSequence, String imgUrl, Stri
317348
public String onAjaxClientDisconnected() {
318349
return "onDisconnect();";
319350
}
320-
351+
352+
@Override
321353
public String onAjaxClientUpdate() {
354+
updateFrontEndActivityTime();
322355
if(!waitForViewerReady())
323356
return onAjaxClientDisconnected();
324357

@@ -386,14 +419,6 @@ private synchronized static int getNextClientId() {
386419
return ++s_nextClientId;
387420
}
388421

389-
public long getAjaxSessionId() {
390-
return this.ajaxSessionId;
391-
}
392-
393-
public AjaxFIFOImageCache getAjaxImageCache() {
394-
return ajaxImageCache;
395-
}
396-
397422
private void signalTileDirtyEvent() {
398423
synchronized(tileDirtyEvent) {
399424
dirtyFlag = true;

console-proxy/src/com/cloud/consoleproxy/ConsoleProxyClientHandler.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@
2828
import com.cloud.console.Logger;
2929
import com.cloud.console.RfbProto;
3030

31-
public class ConsoleProxyClientHandler extends Thread {
31+
public class ConsoleProxyClientHandler extends Thread {
32+
/*
3233
private static final Logger s_logger = Logger.getLogger(ConsoleProxyClientHandler.class);
3334
3435
Socket clientSocket = null;
@@ -274,5 +275,6 @@ void handleClientSession(ConsoleProxyViewer viewer, String srcinfo) throws Excep
274275
} finally {
275276
viewer.lastUsedTime = System.currentTimeMillis();
276277
}
277-
}
278+
}
279+
*/
278280
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.cloud.consoleproxy;
2+
3+
public interface ConsoleProxyClientListener {
4+
void onFramebufferSizeChange(int w, int h);
5+
void onFramebufferUpdate(int x, int y, int w, int h);
6+
7+
void onClientConnected();
8+
void onClientClose();
9+
}

console-proxy/src/com/cloud/consoleproxy/ConsoleProxyClientStatsCollector.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.cloud.consoleproxy;
22

3+
import java.io.OutputStreamWriter;
34
import java.util.ArrayList;
45
import java.util.Enumeration;
56
import java.util.Hashtable;
@@ -28,6 +29,11 @@ public String getStatsReport() {
2829
Gson gson = new GsonBuilder().setPrettyPrinting().create();
2930
return gson.toJson(this);
3031
}
32+
33+
public void getStatsReport(OutputStreamWriter os) {
34+
Gson gson = new GsonBuilder().setPrettyPrinting().create();
35+
gson.toJson(this, os);
36+
}
3137

3238
private void setConnections(Hashtable<String, ConsoleProxyClient> connMap) {
3339

console-proxy/src/com/cloud/consoleproxy/ConsoleProxyCmdHandler.java

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@
2323
import java.io.OutputStreamWriter;
2424

2525
import com.cloud.console.Logger;
26-
import com.google.gson.Gson;
27-
import com.google.gson.GsonBuilder;
2826
import com.sun.net.httpserver.Headers;
2927
import com.sun.net.httpserver.HttpExchange;
3028
import com.sun.net.httpserver.HttpHandler;
@@ -60,15 +58,14 @@ public void doHandle(HttpExchange t) throws Exception {
6058
int i = path.indexOf("/", 1);
6159
String cmd = path.substring(i + 1);
6260
s_logger.info("Get CMD request for " + cmd);
63-
if (cmd.equals("getstatus")) {
64-
ConsoleProxyStatus status = new ConsoleProxyStatus();
65-
status.setConnections(ConsoleProxy.connectionMap);
61+
if (cmd.equals("getstatus")) {
62+
ConsoleProxyClientStatsCollector statsCollector = ConsoleProxy.getStatsCollector();
63+
6664
Headers hds = t.getResponseHeaders();
6765
hds.set("Content-Type", "text/plain");
6866
t.sendResponseHeaders(200, 0);
69-
OutputStreamWriter os = new OutputStreamWriter(t.getResponseBody());
70-
Gson gson = new GsonBuilder().setPrettyPrinting().create();
71-
gson.toJson(status, os);
67+
OutputStreamWriter os = new OutputStreamWriter(t.getResponseBody());
68+
statsCollector.getStatsReport(os);
7269
os.close();
7370
}
7471
}

console-proxy/src/com/cloud/consoleproxy/ConsoleProxyGCThread.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ public void run() {
8181
s_logger.debug("Report load change : " + loadInfo);
8282
}
8383

84-
try { Thread.sleep(30000); } catch (InterruptedException ex) {}
84+
try { Thread.sleep(1000); } catch (InterruptedException ex) {}
8585
}
8686
}
8787
}

0 commit comments

Comments
 (0)