Mercurial > hg > Members > nobuyasu > tightVNCProxy
annotate src/myVncProxy/VncProxyService.java @ 185:950ffe24f72e
update
author | Yu Taninari <you@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 07 Nov 2011 12:47:57 +0900 |
parents | 134deb9f8148 |
children | e7cc8bcf261d |
rev | line source |
---|---|
24 | 1 package myVncProxy; |
180 | 2 |
13 | 3 import java.awt.*; |
4 import java.awt.event.*; | |
5 import java.io.*; | |
6 import java.net.*; | |
7 | |
8 public class VncProxyService implements java.lang.Runnable { | |
184 | 9 |
13 | 10 |
11 public static void main(String[] argv) { | |
12 VncProxyService v = new VncProxyService(); | |
30 | 13 |
180 | 14 // v.checkArgs(argv); |
15 | |
13 | 16 v.mainArgs = argv; |
17 | |
18 v.init(); | |
50 | 19 v.start_threads(); |
13 | 20 } |
180 | 21 |
13 | 22 String[] mainArgs; |
31 | 23 String username; |
180 | 24 |
25 CreateHtmlFile hgtmlFile; | |
13 | 26 |
27 // RfbProto rfb; | |
28 MyRfbProto rfb; | |
184 | 29 MyRfbProto testrfb; |
13 | 30 Thread rfbThread; |
27 | 31 Thread accThread; |
63
4864a7d1df00
add CreateThread.java modify acceptClient.java and VncProxyService.java
Yu Taninari <e085734@ie.u-ryukyu.ac.jp>
parents:
51
diff
changeset
|
32 Thread clientThread; |
180 | 33 CreateThread geth; |
34 AcceptClient acc; | |
184 | 35 private AcceptThread acceptThread; |
180 | 36 private TextBox getHost; |
13 | 37 |
38 Frame vncFrame; | |
39 Container vncContainer; | |
40 ScrollPane desktopScrollPane; | |
41 GridBagLayout gridbag; | |
42 ButtonPanel buttonPanel; | |
43 Label connStatusLabel; | |
44 ProxyVncCanvas vc; | |
180 | 45 // OptionsFrame options; |
67 | 46 OptionsNoFrame options; |
13 | 47 ClipboardFrame clipboard; |
48 RecordingFrame rec; | |
49 | |
50 // Control session recording. | |
51 Object recordingSync; | |
52 String sessionFileName; | |
53 boolean recordingActive; | |
54 boolean recordingStatusChanged; | |
55 String cursorUpdatesDef; | |
56 String eightBitColorsDef; | |
57 | |
58 // Variables read from parameter values. | |
59 String socketFactory; | |
60 String host; | |
144 | 61 int port = 5900; |
13 | 62 String passwordParam; |
63 boolean showControls; | |
64 boolean offerRelogin; | |
65 boolean showOfflineDesktop; | |
66 int deferScreenUpdates; | |
67 int deferCursorUpdates; | |
68 int deferUpdateRequests; | |
69 int debugStatsExcludeUpdates; | |
70 int debugStatsMeasureUpdates; | |
71 | |
130 | 72 int echoPort = 9999; |
184 | 73 private boolean changeFlag; |
144 | 74 |
75 String url; | |
130 | 76 |
180 | 77 // XmlRpc client; |
144 | 78 String wpUsername, wpPassword, blogId; |
79 String title = "TreeVNC"; | |
180 | 80 |
81 void checkArgs(String[] argv) { | |
144 | 82 int len = argv.length; |
83 | |
180 | 84 for (int i = 0; i < len; i++) { |
144 | 85 String str = argv[i]; |
180 | 86 if (str.equals("-h") || str.equals("--host")) { |
144 | 87 host = argv[++i]; |
180 | 88 } else if (str.equals("-pn") || str.equals("--port")) { |
144 | 89 port = Integer.parseInt(argv[++i]); |
180 | 90 } else if (str.equals("-pw") || str.equals("--password")) { |
144 | 91 passwordParam = argv[++i]; |
180 | 92 } else if (str.equals("-w") || str.equals("--wpurl")) { |
144 | 93 url = argv[++i]; |
180 | 94 } else if (str.equals("-wu") || str.equals("--wpusername")) { |
144 | 95 wpUsername = argv[++i]; |
180 | 96 } else if (str.equals("-wp") || str.equals("--wppassword")) { |
144 | 97 wpPassword = argv[++i]; |
180 | 98 } else if (str.equals("-wb") || str.equals("--wpblogId")) { |
144 | 99 blogId = argv[++i]; |
100 } else if (str.equals("--help")) { | |
101 printHelp(); | |
102 System.exit(0); | |
103 } else if (len == 3) { | |
104 host = argv[0]; | |
105 port = Integer.parseInt(argv[1]); | |
106 passwordParam = argv[2]; | |
180 | 107 } else if (len == 2) { |
176 | 108 host = argv[0]; |
109 port = Integer.parseInt(argv[1]); | |
180 | 110 } else if (len == 1) { |
111 host = argv[0]; | |
144 | 112 } |
30 | 113 } |
180 | 114 } |
115 | |
144 | 116 void printHelp() { |
180 | 117 System.out |
118 .println("usage: java -jar VncProxyService [-h hostname] " | |
119 + "[-pn portnumber] [-pw password] [-w WordPressURL] [-wu WPUsername] " | |
120 + "[-wp WPPassword] [-wb blogId]"); | |
30 | 121 } |
180 | 122 |
13 | 123 // |
124 // init() | |
125 // | |
126 | |
127 public void init() { | |
184 | 128 |
13 | 129 readParameters(); |
180 | 130 |
67 | 131 options = new OptionsNoFrame(this); |
13 | 132 recordingSync = new Object(); |
133 | |
134 sessionFileName = null; | |
135 recordingActive = false; | |
136 recordingStatusChanged = false; | |
137 cursorUpdatesDef = null; | |
138 eightBitColorsDef = null; | |
139 | |
180 | 140 try { |
25 | 141 connectAndAuthenticate(); |
145 | 142 doProtocolInitialisation(); |
180 | 143 } catch (NoRouteToHostException e) { |
25 | 144 fatalError("Network error: no route to server: " + host, e); |
145 } catch (UnknownHostException e) { | |
146 fatalError("Network error: server name unknown: " + host, e); | |
147 } catch (ConnectException e) { | |
148 fatalError("Network error: could not connect to server: " + host | |
149 + ":" + port, e); | |
180 | 150 } catch (IOException e) { |
151 fatalError("Network error: faild connect or authenticate to server"); | |
152 } catch (Exception e) { | |
153 | |
154 } | |
184 | 155 /* |
156 if(changeFlag){ | |
157 acceptThread.changeRfb(rfb); | |
158 } else {*/ | |
159 rfb.selectPort(5999); | |
160 rfbThread = new Thread(this); | |
161 acceptThread = new AcceptThread(rfb, 5999); | |
162 accThread = new Thread(acceptThread); | |
163 //} | |
180 | 164 /* |
165 * if(url != null) { try { client = new XmlRpc(blogId, wpUsername, | |
166 * wpPassword, url ); InetAddress addr = InetAddress.getLocalHost(); | |
167 * String add = new String(addr.getHostAddress()); | |
168 * client.addDescription(rfb.desktopName); setStatusXmlRpc(client, | |
169 * title, add, rfb.acceptPort); client.editPost(); | |
170 * System.out.println("URL:\n" + client.getUrl() + "\n"); } catch | |
171 * (MalformedURLException e) { | |
172 * System.out.println("Faild create instance of class XmlRpc"); | |
173 * e.printStackTrace(); } catch (UnknownHostException e) { | |
174 * e.printStackTrace(); } } | |
175 */ | |
176 | |
144 | 177 } |
184 | 178 |
179 | |
180 public void changeInit() throws Exception { | |
181 VncProxyService v = new VncProxyService(); | |
182 v.changeFlag = true; | |
183 // v.checkArgs(argv); | |
184 | |
185 v.mainArgs = new String[0]; | |
186 v.host = host; | |
187 v.init(); | |
188 v.start_threads(); | |
189 | |
190 //Thread.sleep(10000); | |
191 rfb.is = v.rfb.is; | |
192 //rfb.os = v.rfb.os; | |
193 //rfb.initData = v.rfb.initData; | |
194 | |
195 // changeConnection(); | |
196 // doProtocolInitialisation(); | |
197 /* | |
198 //readParameters(); | |
199 options = new OptionsNoFrame(this); | |
200 recordingSync = new Object(); | |
201 | |
202 sessionFileName = null; | |
203 recordingActive = false; | |
204 recordingStatusChanged = false; | |
205 cursorUpdatesDef = null; | |
206 eightBitColorsDef = null; | |
207 | |
208 try { | |
209 changeConnection(); | |
210 doProtocolInitialisation(); | |
211 } catch (NoRouteToHostException e) { | |
212 fatalError("Network error: no route to server: " + host, e); | |
213 } catch (UnknownHostException e) { | |
214 fatalError("Network error: server name unknown: " + host, e); | |
215 } catch (ConnectException e) { | |
216 fatalError("Network error: could not connect to server: " + host | |
217 + ":" + port, e); | |
218 } catch (IOException e) { | |
219 fatalError("Network error: faild connect or authenticate to server"); | |
220 } catch (Exception e) { | |
221 | |
222 } | |
223 | |
224 //acceptThread.changeRfb(rfb); | |
225 //vc.rfb = rfb; | |
226 //rfbThread.start(); | |
227 */ | |
228 } | |
180 | 229 |
230 /* | |
231 * void setStatusXmlRpc(XmlRpc client, String title, String hostname, int | |
232 * port) { client.setTitle(title); String description = | |
233 * makeDescription(hostname, Integer.toString(port)); | |
234 * client.addDescription(description); } | |
235 */ | |
144 | 236 String makeDescription(String hostname, String port) { |
237 String description = "<h1>" + hostname + " " + port + "<h1>\n"; | |
238 return description; | |
50 | 239 } |
184 | 240 |
180 | 241 public void start_threads() { |
13 | 242 rfbThread.start(); |
27 | 243 accThread.start(); |
162 | 244 rfb.requestThreadStart(); |
13 | 245 } |
246 | |
247 // | |
248 // run() - executed by the rfbThread to deal with the RFB socket. | |
249 // | |
250 public void run() { | |
251 | |
252 try { | |
180 | 253 // connectAndAuthenticate(); |
254 // doProtocolInitialisation(); | |
255 /* | |
256 * htmlFile = new CreateHtmlFile(rfb, host, username); | |
257 * htmlFile.createHtml(); | |
258 */ | |
13 | 259 vc = new ProxyVncCanvas(this, 0, 0); |
25 | 260 vc.updateFramebufferSize(); |
180 | 261 |
13 | 262 processNormalProtocol();// main loop |
263 | |
264 } catch (NoRouteToHostException e) { | |
265 fatalError("Network error: no route to server: " + host, e); | |
266 } catch (UnknownHostException e) { | |
267 fatalError("Network error: server name unknown: " + host, e); | |
268 } catch (ConnectException e) { | |
269 fatalError("Network error: could not connect to server: " + host | |
270 + ":" + port, e); | |
271 } catch (EOFException e) { | |
272 if (showOfflineDesktop) { | |
273 e.printStackTrace(); | |
274 System.out | |
275 .println("Network error: remote side closed connection"); | |
276 if (vc != null) { | |
277 vc.enableInput(false); | |
278 } | |
279 if (rfb != null && !rfb.closed()) | |
280 rfb.close(); | |
281 if (showControls && buttonPanel != null) { | |
282 buttonPanel.disableButtonsOnDisconnect(); | |
283 } | |
284 } else { | |
285 fatalError("Network error: remote side closed connection", e); | |
286 } | |
287 } catch (IOException e) { | |
288 String str = e.getMessage(); | |
289 if (str != null && str.length() != 0) { | |
290 fatalError("Network Error: " + str, e); | |
291 } else { | |
292 fatalError(e.toString(), e); | |
293 } | |
180 | 294 } catch (Exception e) { |
13 | 295 String str = e.getMessage(); |
296 if (str != null && str.length() != 0) { | |
297 fatalError("Error: " + str, e); | |
298 } else { | |
299 fatalError(e.toString(), e); | |
300 } | |
301 } | |
302 | |
303 } | |
304 | |
305 // | |
306 // Process RFB socket messages. | |
307 // If the rfbThread is being stopped, ignore any exceptions, | |
308 // otherwise rethrow the exception so it can be handled. | |
309 // | |
310 | |
311 void processNormalProtocol() throws Exception { | |
312 try { | |
313 vc.processNormalProtocol();// main loop | |
314 } catch (Exception e) { | |
315 if (rfbThread == null) { | |
316 System.out.println("Ignoring RFB socket exceptions" | |
317 + " because applet is stopping"); | |
318 } else { | |
319 throw e; | |
320 } | |
321 } | |
322 } | |
323 | |
324 // | |
325 // Connect to the RFB server and authenticate the user. | |
326 // | |
327 | |
328 void connectAndAuthenticate() throws Exception { | |
180 | 329 if (mainArgs.length == 0) |
184 | 330 acc = new AcceptClient(host); |
331 //acc = new AcceptClient(getHost.getAddress()); | |
180 | 332 // acc = new AcceptClient(); |
170 | 333 else |
180 | 334 acc = new AcceptClient(mainArgs[0]); |
335 geth = new CreateThread(acc, echoPort); | |
336 Thread thread = new Thread(geth); | |
337 thread.start(); | |
48 | 338 |
13 | 339 showConnectionStatus("Initializing..."); |
340 | |
341 showConnectionStatus("Connecting to " + host + ", port " + port + "..."); | |
342 | |
130 | 343 rfb = new MyRfbProto(host, port, geth); |
344 | |
13 | 345 showConnectionStatus("Connected to server"); |
346 | |
347 rfb.readVersionMsg(); | |
348 showConnectionStatus("RFB server supports protocol version " | |
349 + rfb.serverMajor + "." + rfb.serverMinor); | |
350 | |
351 rfb.writeVersionMsg(); | |
352 showConnectionStatus("Using RFB protocol version " + rfb.clientMajor | |
353 + "." + rfb.clientMinor); | |
354 | |
355 int secType = rfb.negotiateSecurity(); | |
356 int authType; | |
357 if (secType == RfbProto.SecTypeTight) { | |
358 showConnectionStatus("Enabling TightVNC protocol extensions"); | |
359 rfb.setupTunneling(); | |
360 authType = rfb.negotiateAuthenticationTight(); | |
361 } else { | |
362 authType = secType; | |
363 } | |
364 | |
365 switch (authType) { | |
166
3c055da4d050
add authenticate AuthAccess
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
162
diff
changeset
|
366 case MyRfbProto.AuthAccess: |
3c055da4d050
add authenticate AuthAccess
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
162
diff
changeset
|
367 rfb.authenticationRequestAccess(); |
3c055da4d050
add authenticate AuthAccess
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
162
diff
changeset
|
368 System.out.println("authenticateion Request right of Acces"); |
3c055da4d050
add authenticate AuthAccess
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
162
diff
changeset
|
369 break; |
13 | 370 case RfbProto.AuthNone: |
371 showConnectionStatus("No authentication needed"); | |
372 rfb.authenticateNone(); | |
373 break; | |
374 case RfbProto.AuthVNC: | |
375 showConnectionStatus("Performing standard VNC authentication"); | |
376 if (passwordParam != null) { | |
377 rfb.authenticateVNC(passwordParam); | |
378 } else { | |
379 String pw = askPassword(); | |
380 rfb.authenticateVNC(pw); | |
381 } | |
382 break; | |
383 default: | |
384 throw new Exception("Unknown authentication scheme " + authType); | |
385 } | |
386 } | |
184 | 387 |
388 void changeConnection() throws Exception { | |
389 /* | |
390 acc = new AcceptClient(getHost.getAddress()); | |
391 geth = new CreateThread(acc, echoPort); | |
392 Thread thread = new Thread(geth); | |
393 thread.start(); | |
394 */ | |
395 showConnectionStatus("Initializing..."); | |
396 | |
397 showConnectionStatus("Connecting to " + host + ", port " + port + "..."); | |
398 | |
399 //rfb = null; | |
400 //rfb.is = null; | |
401 | |
402 testrfb = new MyRfbProto(host, port); | |
403 showConnectionStatus("Connected to server"); | |
404 | |
405 testrfb.readVersionMsg(); | |
406 showConnectionStatus("RFB server supports protocol version " | |
407 + testrfb.serverMajor + "." + testrfb.serverMinor); | |
408 | |
409 testrfb.writeVersionMsg(); | |
410 showConnectionStatus("Using RFB protocol version " + testrfb.clientMajor | |
411 + "." + testrfb.clientMinor); | |
412 | |
413 int secType = testrfb.negotiateSecurity(); | |
414 int authType; | |
415 if (secType == RfbProto.SecTypeTight) { | |
416 showConnectionStatus("Enabling TightVNC protocol extensions"); | |
417 testrfb.setupTunneling(); | |
418 authType = testrfb.negotiateAuthenticationTight(); | |
419 } else { | |
420 authType = secType; | |
421 } | |
422 | |
423 switch (authType) { | |
424 case MyRfbProto.AuthAccess: | |
425 testrfb.authenticationRequestAccess(); | |
426 System.out.println("authenticateion Request right of Acces"); | |
427 break; | |
428 case RfbProto.AuthNone: | |
429 showConnectionStatus("No authentication needed"); | |
430 testrfb.authenticateNone(); | |
431 break; | |
432 case RfbProto.AuthVNC: | |
433 showConnectionStatus("Performing standard VNC authentication"); | |
434 if (passwordParam != null) { | |
435 testrfb.authenticateVNC(passwordParam); | |
436 } else { | |
437 String pw = askPassword(); | |
438 testrfb.authenticateVNC(pw); | |
439 } | |
440 break; | |
441 default: | |
442 throw new Exception("Unknown authentication scheme " + authType); | |
443 } | |
444 rfb.is = testrfb.is; | |
445 rfb.os = testrfb.os; | |
446 //rfb = testrfb; | |
447 } | |
13 | 448 |
449 // | |
450 // Show a message describing the connection status. | |
451 // To hide the connection status label, use (msg == null). | |
452 // | |
453 | |
454 void showConnectionStatus(String msg) { | |
455 System.out.println(msg); | |
456 } | |
457 | |
458 // | |
459 // Show an authentication panel. | |
460 // | |
461 | |
462 String askPassword() throws Exception { | |
463 /* | |
180 | 464 * showConnectionStatus(null); AuthPanel authPanel = new |
465 * AuthPanel(this); | |
13 | 466 * |
467 * GridBagConstraints gbc = new GridBagConstraints(); gbc.gridwidth = | |
468 * GridBagConstraints.REMAINDER; gbc.anchor = | |
469 * GridBagConstraints.NORTHWEST; gbc.weightx = 1.0; gbc.weighty = 1.0; | |
470 * gbc.ipadx = 100; gbc.ipady = 50; gridbag.setConstraints(authPanel, | |
471 * gbc); vncContainer.add(authPanel); | |
180 | 472 * |
473 * | |
474 * authPanel.moveFocusToDefaultField(); vncContainer.remove(authPanel); | |
13 | 475 */ |
30 | 476 showConnectionStatus("ask password..."); |
170 | 477 String pw; |
180 | 478 if (mainArgs.length != 0) |
170 | 479 pw = mainArgs[2]; |
480 else | |
481 pw = getHost.getPassword(); | |
13 | 482 return pw; |
483 } | |
484 | |
485 // | |
486 // Do the rest of the protocol initialisation. | |
487 // | |
488 | |
489 void doProtocolInitialisation() throws IOException { | |
490 rfb.writeClientInit(); | |
491 rfb.readServerInit(); | |
492 | |
493 System.out.println("Desktop name is " + rfb.desktopName); | |
494 System.out.println("Desktop size is " + rfb.framebufferWidth + " x " | |
495 + rfb.framebufferHeight); | |
496 | |
497 setEncodings(); | |
498 | |
180 | 499 // showConnectionStatus(null); |
13 | 500 } |
501 | |
502 // | |
503 // Send current encoding list to the RFB server. | |
504 // | |
505 | |
506 int[] encodingsSaved; | |
507 int nEncodingsSaved; | |
508 | |
509 void setEncodings() { | |
510 setEncodings(false); | |
511 } | |
512 | |
513 void autoSelectEncodings() { | |
514 setEncodings(true); | |
515 } | |
516 | |
517 void setEncodings(boolean autoSelectOnly) { | |
518 if (options == null || rfb == null || !rfb.inNormalProtocol) | |
519 return; | |
520 | |
521 int preferredEncoding = options.preferredEncoding; | |
522 if (preferredEncoding == -1) { | |
523 long kbitsPerSecond = rfb.kbitsPerSecond(); | |
180 | 524 /* |
525 * if (nEncodingsSaved < 1) { // Choose Tight or ZRLE encoding for | |
526 * the very first update. | |
527 * System.out.println("Using Tight/ZRLE encodings"); | |
528 * preferredEncoding = RfbProto.EncodingTight; } else if | |
529 * (kbitsPerSecond > 2000 && encodingsSaved[0] != | |
530 * RfbProto.EncodingHextile) { // Switch to Hextile if the | |
531 * connection speed is above 2Mbps. System.out.println("Throughput " | |
532 * + kbitsPerSecond + " kbit/s - changing to Hextile encoding"); | |
533 * preferredEncoding = RfbProto.EncodingHextile; } else if | |
534 * (kbitsPerSecond < 1000 && encodingsSaved[0] != | |
535 * RfbProto.EncodingTight) { // Switch to Tight/ZRLE if the | |
536 * connection speed is below 1Mbps. System.out.println("Throughput " | |
537 * + kbitsPerSecond + " kbit/s - changing to Tight/ZRLE encodings"); | |
538 * preferredEncoding = RfbProto.EncodingTight; } else { // Don't | |
539 * change the encoder. if (autoSelectOnly) return; preferredEncoding | |
540 * = encodingsSaved[0]; } | |
541 */ | |
13 | 542 } else { |
543 // Auto encoder selection is not enabled. | |
544 if (autoSelectOnly) | |
545 return; | |
546 } | |
547 | |
548 int[] encodings = new int[20]; | |
549 int nEncodings = 0; | |
550 | |
551 encodings[nEncodings++] = preferredEncoding; | |
130 | 552 |
13 | 553 if (options.useCopyRect) { |
554 encodings[nEncodings++] = RfbProto.EncodingCopyRect; | |
555 } | |
180 | 556 /* |
557 * if (preferredEncoding != RfbProto.EncodingTight) { | |
558 * encodings[nEncodings++] = RfbProto.EncodingTight; } | |
559 */ | |
151 | 560 |
13 | 561 if (preferredEncoding != RfbProto.EncodingZRLE) { |
562 encodings[nEncodings++] = RfbProto.EncodingZRLE; | |
563 } | |
180 | 564 /* |
565 * if (preferredEncoding != RfbProto.EncodingHextile) { | |
566 * encodings[nEncodings++] = RfbProto.EncodingHextile; } if | |
567 * (preferredEncoding != RfbProto.EncodingZlib) { | |
568 * encodings[nEncodings++] = RfbProto.EncodingZlib; } | |
569 */ | |
570 /* | |
571 * if (preferredEncoding != RfbProto.EncodingCoRRE) { | |
572 * encodings[nEncodings++] = RfbProto.EncodingCoRRE; } if | |
573 * (preferredEncoding != RfbProto.EncodingRRE) { encodings[nEncodings++] | |
574 * = RfbProto.EncodingRRE; } | |
575 */ | |
576 /* | |
577 * if (options.compressLevel >= 0 && options.compressLevel <= 9) { | |
578 * encodings[nEncodings++] = RfbProto.EncodingCompressLevel0 + | |
579 * options.compressLevel; } if (options.jpegQuality >= 0 && | |
580 * options.jpegQuality <= 9) { encodings[nEncodings++] = | |
581 * RfbProto.EncodingQualityLevel0 + options.jpegQuality; } if | |
582 * (options.requestCursorUpdates) { encodings[nEncodings++] = | |
583 * RfbProto.EncodingXCursor; encodings[nEncodings++] = | |
584 * RfbProto.EncodingRichCursor; if (!options.ignoreCursorUpdates) | |
585 * encodings[nEncodings++] = RfbProto.EncodingPointerPos; } | |
586 */ | |
587 | |
13 | 588 encodings[nEncodings++] = RfbProto.EncodingLastRect; |
589 encodings[nEncodings++] = RfbProto.EncodingNewFBSize; | |
590 | |
591 boolean encodingsWereChanged = false; | |
592 if (nEncodings != nEncodingsSaved) { | |
593 encodingsWereChanged = true; | |
594 } else { | |
595 for (int i = 0; i < nEncodings; i++) { | |
596 if (encodings[i] != encodingsSaved[i]) { | |
597 encodingsWereChanged = true; | |
598 break; | |
599 } | |
600 } | |
601 } | |
602 | |
603 if (encodingsWereChanged) { | |
604 try { | |
180 | 605 rfb.writeSetEncodings(encodings, nEncodings); |
13 | 606 if (vc != null) { |
607 vc.softCursorFree(); | |
608 } | |
609 } catch (Exception e) { | |
610 e.printStackTrace(); | |
611 } | |
612 encodingsSaved = encodings; | |
613 nEncodingsSaved = nEncodings; | |
614 } | |
615 } | |
616 | |
617 // | |
618 // setCutText() - send the given cut text to the RFB server. | |
619 // | |
620 | |
621 void setCutText(String text) { | |
622 try { | |
623 if (rfb != null && rfb.inNormalProtocol) { | |
624 rfb.writeClientCutText(text); | |
625 } | |
626 } catch (Exception e) { | |
627 e.printStackTrace(); | |
628 } | |
629 } | |
630 | |
631 // | |
632 // Order change in session recording status. To stop recording, pass | |
633 // null in place of the fname argument. | |
634 // | |
635 | |
636 void setRecordingStatus(String fname) { | |
637 synchronized (recordingSync) { | |
638 sessionFileName = fname; | |
639 recordingStatusChanged = true; | |
640 } | |
641 } | |
642 | |
643 // | |
644 // Start or stop session recording. Returns true if this method call | |
645 // causes recording of a new session. | |
646 // | |
647 | |
648 boolean checkRecordingStatus() throws IOException { | |
649 synchronized (recordingSync) { | |
650 if (recordingStatusChanged) { | |
651 recordingStatusChanged = false; | |
652 if (sessionFileName != null) { | |
653 startRecording(); | |
654 return true; | |
655 } else { | |
656 stopRecording(); | |
657 } | |
658 } | |
659 } | |
660 return false; | |
661 } | |
662 | |
663 // | |
664 // Start session recording. | |
665 // | |
666 | |
667 protected void startRecording() throws IOException { | |
668 synchronized (recordingSync) { | |
669 if (!recordingActive) { | |
670 // Save settings to restore them after recording the session. | |
671 cursorUpdatesDef = options.choices[options.cursorUpdatesIndex] | |
672 .getSelectedItem(); | |
673 eightBitColorsDef = options.choices[options.eightBitColorsIndex] | |
674 .getSelectedItem(); | |
675 // Set options to values suitable for recording. | |
676 options.choices[options.cursorUpdatesIndex].select("Disable"); | |
677 options.choices[options.cursorUpdatesIndex].setEnabled(false); | |
678 options.setEncodings(); | |
679 options.choices[options.eightBitColorsIndex].select("No"); | |
680 options.choices[options.eightBitColorsIndex].setEnabled(false); | |
681 options.setColorFormat(); | |
682 } else { | |
683 rfb.closeSession(); | |
684 } | |
685 | |
686 System.out.println("Recording the session in " + sessionFileName); | |
687 rfb.startSession(sessionFileName); | |
688 recordingActive = true; | |
689 } | |
690 } | |
691 | |
692 // | |
693 // Stop session recording. | |
694 // | |
695 | |
696 protected void stopRecording() throws IOException { | |
697 synchronized (recordingSync) { | |
698 if (recordingActive) { | |
699 // Restore options. | |
700 options.choices[options.cursorUpdatesIndex] | |
701 .select(cursorUpdatesDef); | |
702 options.choices[options.cursorUpdatesIndex].setEnabled(true); | |
703 options.setEncodings(); | |
704 options.choices[options.eightBitColorsIndex] | |
705 .select(eightBitColorsDef); | |
706 options.choices[options.eightBitColorsIndex].setEnabled(true); | |
707 options.setColorFormat(); | |
708 | |
709 rfb.closeSession(); | |
710 System.out.println("Session recording stopped."); | |
711 } | |
712 sessionFileName = null; | |
713 recordingActive = false; | |
714 } | |
715 } | |
716 | |
717 // | |
718 // readParameters() - read parameters from the html source or from the | |
719 // command line. On the command line, the arguments are just a sequence of | |
720 // param_name/param_value pairs where the names and values correspond to | |
721 // those expected in the html applet tag source. | |
722 // | |
184 | 723 |
13 | 724 void readParameters() { |
184 | 725 if (!(changeFlag)) { |
726 if (mainArgs.length == 0) { | |
727 getHost = new TextBox(this); | |
728 getHost.ipRegister(); | |
729 host = getHost.getAddress(); | |
730 } else { | |
731 host = mainArgs[0]; | |
732 } | |
733 | |
734 if (mainArgs.length < 2) { | |
735 port = Integer.parseInt(getHost.getPort()); | |
736 // port = 5900; | |
737 } else { | |
738 port = Integer.parseInt(mainArgs[1]); | |
739 } | |
170 | 740 } else { |
184 | 741 getHost = new TextBox(this); |
742 port = 5900; | |
170 | 743 } |
184 | 744 |
185 | 745 //getHost.changeHost(); |
13 | 746 |
747 // Read "ENCPASSWORD" or "PASSWORD" parameter if specified. | |
180 | 748 // readPasswordParameters(); |
13 | 749 |
750 String str; | |
751 | |
752 // "Show Controls" set to "No" disables button panel. | |
753 showControls = true; | |
754 str = readParameter("Show Controls", false); | |
755 if (str != null && str.equalsIgnoreCase("No")) | |
756 showControls = false; | |
757 | |
758 // "Offer Relogin" set to "No" disables "Login again" and "Close | |
759 // window" buttons under error messages in applet mode. | |
760 offerRelogin = true; | |
761 str = readParameter("Offer Relogin", false); | |
762 if (str != null && str.equalsIgnoreCase("No")) | |
763 offerRelogin = false; | |
764 | |
765 // Do we continue showing desktop on remote disconnect? | |
766 showOfflineDesktop = false; | |
767 str = readParameter("Show Offline Desktop", false); | |
768 if (str != null && str.equalsIgnoreCase("Yes")) | |
769 showOfflineDesktop = true; | |
770 | |
771 // Fine tuning options. | |
772 deferScreenUpdates = readIntParameter("Defer screen updates", 20); | |
773 deferCursorUpdates = readIntParameter("Defer cursor updates", 10); | |
774 deferUpdateRequests = readIntParameter("Defer update requests", 0); | |
775 | |
776 // Debugging options. | |
777 debugStatsExcludeUpdates = readIntParameter("DEBUG_XU", 0); | |
778 debugStatsMeasureUpdates = readIntParameter("DEBUG_CU", 0); | |
779 | |
780 // SocketFactory. | |
781 socketFactory = readParameter("SocketFactory", false); | |
782 } | |
783 | |
784 // | |
785 // Read password parameters. If an "ENCPASSWORD" parameter is set, | |
786 // then decrypt the password into the passwordParam string. Otherwise, | |
787 // try to read the "PASSWORD" parameter directly to passwordParam. | |
788 // | |
789 | |
790 private void readPasswordParameters() { | |
170 | 791 String encPasswordParam; |
13 | 792 // String encPasswordParam = readParameter("ENCPASSWORD", false); |
180 | 793 if (mainArgs.length != 0) |
170 | 794 encPasswordParam = mainArgs[2]; |
795 else | |
796 encPasswordParam = getHost.getPassword(); | |
13 | 797 |
798 if (encPasswordParam == null) { | |
799 // passwordParam = readParameter("PASSWORD", false); | |
800 | |
801 } else { | |
802 // ENCPASSWORD is hexascii-encoded. Decode. | |
803 byte[] pw = { 0, 0, 0, 0, 0, 0, 0, 0 }; | |
804 int len = encPasswordParam.length() / 2; | |
805 if (len > 8) | |
806 len = 8; | |
807 for (int i = 0; i < len; i++) { | |
808 String hex = encPasswordParam.substring(i * 2, i * 2 + 2); | |
809 Integer x = new Integer(Integer.parseInt(hex, 16)); | |
810 pw[i] = x.byteValue(); | |
811 } | |
812 // Decrypt the password. | |
813 byte[] key = { 23, 82, 107, 6, 35, 78, 88, 7 }; | |
814 DesCipher des = new DesCipher(key); | |
815 des.decrypt(pw, 0, pw, 0); | |
816 passwordParam = new String(pw); | |
817 | |
818 } | |
819 } | |
820 | |
821 public String readParameter(String name, boolean required) { | |
184 | 822 if(mainArgs!=null){ |
823 for (int i = 0; i < mainArgs.length; i += 2) { | |
824 if (mainArgs[i].equalsIgnoreCase(name)) { | |
825 try { | |
826 return mainArgs[i + 1]; | |
827 } catch (Exception e) { | |
828 if (required) { | |
829 fatalError(name + " parameter not specified"); | |
830 } | |
831 return null; | |
13 | 832 } |
833 } | |
834 } | |
184 | 835 if (required) { |
836 fatalError(name + " parameter not specified"); | |
837 } | |
13 | 838 } |
839 return null; | |
840 } | |
841 | |
842 int readIntParameter(String name, int defaultValue) { | |
843 String str = readParameter(name, false); | |
844 int result = defaultValue; | |
845 if (str != null) { | |
846 try { | |
847 result = Integer.parseInt(str); | |
848 } catch (NumberFormatException e) { | |
849 } | |
850 } | |
851 return result; | |
852 } | |
853 | |
854 // | |
855 // disconnect() - close connection to server. | |
856 // | |
857 | |
858 synchronized public void disconnect() { | |
859 System.out.println("Disconnecting"); | |
860 | |
861 if (vc != null) { | |
862 double sec = (System.currentTimeMillis() - vc.statStartTime) / 1000.0; | |
863 double rate = Math.round(vc.statNumUpdates / sec * 100) / 100.0; | |
864 int nRealRects = vc.statNumPixelRects; | |
865 int nPseudoRects = vc.statNumTotalRects - vc.statNumPixelRects; | |
866 System.out.println("Updates received: " + vc.statNumUpdates + " (" | |
867 + nRealRects + " rectangles + " + nPseudoRects | |
868 + " pseudo), " + rate + " updates/sec"); | |
869 int numRectsOther = nRealRects - vc.statNumRectsTight | |
870 - vc.statNumRectsZRLE - vc.statNumRectsHextile | |
871 - vc.statNumRectsRaw - vc.statNumRectsCopy; | |
872 System.out.println("Rectangles:" + " Tight=" + vc.statNumRectsTight | |
873 + "(JPEG=" + vc.statNumRectsTightJPEG + ") ZRLE=" | |
874 + vc.statNumRectsZRLE + " Hextile=" | |
875 + vc.statNumRectsHextile + " Raw=" + vc.statNumRectsRaw | |
876 + " CopyRect=" + vc.statNumRectsCopy + " other=" | |
877 + numRectsOther); | |
878 | |
879 int raw = vc.statNumBytesDecoded; | |
880 int compressed = vc.statNumBytesEncoded; | |
881 if (compressed > 0) { | |
882 double ratio = Math.round((double) raw / compressed * 1000) / 1000.0; | |
883 System.out.println("Pixel data: " + vc.statNumBytesDecoded | |
884 + " bytes, " + vc.statNumBytesEncoded | |
885 + " compressed, ratio " + ratio); | |
886 } | |
887 } | |
888 | |
889 if (rfb != null && !rfb.closed()) | |
890 rfb.close(); | |
180 | 891 // options.dispose(); |
13 | 892 clipboard.dispose(); |
893 if (rec != null) | |
894 rec.dispose(); | |
895 | |
896 System.exit(0); | |
897 | |
898 } | |
899 | |
900 // | |
901 // fatalError() - print out a fatal error message. | |
902 // FIXME: Do we really need two versions of the fatalError() method? | |
903 // | |
904 | |
905 synchronized public void fatalError(String str) { | |
906 System.out.println(str); | |
907 System.exit(1); | |
908 } | |
909 | |
910 synchronized public void fatalError(String str, Exception e) { | |
911 | |
912 if (rfb != null && rfb.closed()) { | |
913 // Not necessary to show error message if the error was caused | |
914 // by I/O problems after the rfb.close() method call. | |
915 System.out.println("RFB thread finished"); | |
916 return; | |
917 } | |
918 | |
919 System.out.println(str); | |
920 e.printStackTrace(); | |
921 | |
922 if (rfb != null) | |
923 rfb.close(); | |
924 | |
925 System.exit(1); | |
926 | |
927 } | |
928 | |
929 // | |
930 // Show message text and optionally "Relogin" and "Close" buttons. | |
931 // | |
932 | |
933 void showMessage(String msg) { | |
934 vncContainer.removeAll(); | |
935 | |
936 Label errLabel = new Label(msg, Label.CENTER); | |
937 errLabel.setFont(new Font("Helvetica", Font.PLAIN, 12)); | |
938 | |
939 if (offerRelogin) { | |
940 /* | |
941 * Panel gridPanel = new Panel(new GridLayout(0, 1)); Panel | |
942 * outerPanel = new Panel(new FlowLayout(FlowLayout.LEFT)); | |
943 * outerPanel.add(gridPanel); vncContainer.setLayout(new | |
944 * FlowLayout(FlowLayout.LEFT, 30, 16)); | |
945 * vncContainer.add(outerPanel); Panel textPanel = new Panel(new | |
946 * FlowLayout(FlowLayout.CENTER)); textPanel.add(errLabel); | |
947 * gridPanel.add(textPanel); gridPanel.add(new ReloginPanel(this)); | |
948 */ | |
949 } else { | |
950 /* | |
951 * vncContainer.setLayout(new FlowLayout(FlowLayout.LEFT, 30, 30)); | |
952 * vncContainer.add(errLabel); | |
953 */ | |
954 } | |
955 | |
956 } | |
957 | |
958 // | |
959 // Stop the applet. | |
960 // Main applet thread will terminate on first exception | |
961 // after seeing that rfbThread has been set to null. | |
962 // | |
963 | |
964 public void stop() { | |
965 System.out.println("Stopping applet"); | |
966 rfbThread = null; | |
967 } | |
968 | |
969 // | |
970 // This method is called before the applet is destroyed. | |
971 // | |
972 | |
973 public void destroy() { | |
974 System.out.println("Destroying applet"); | |
975 | |
976 vncContainer.removeAll(); | |
180 | 977 // options.dispose(); |
13 | 978 clipboard.dispose(); |
979 if (rec != null) | |
980 rec.dispose(); | |
981 if (rfb != null && !rfb.closed()) | |
982 rfb.close(); | |
983 } | |
984 | |
985 // | |
986 // Start/stop receiving mouse events. | |
987 // | |
988 | |
989 public void enableInput(boolean enable) { | |
990 vc.enableInput(enable); | |
991 } | |
992 | |
993 // | |
994 // Close application properly on window close event. | |
995 // | |
996 | |
997 public void windowClosing(WindowEvent evt) { | |
998 System.out.println("Closing window"); | |
999 if (rfb != null) | |
1000 disconnect(); | |
1001 | |
1002 vncContainer.hide(); | |
1003 | |
1004 } | |
1005 | |
1006 // | |
1007 // Ignore window events we're not interested in. | |
1008 // | |
1009 | |
1010 public void windowActivated(WindowEvent evt) { | |
1011 } | |
1012 | |
1013 public void windowDeactivated(WindowEvent evt) { | |
1014 } | |
1015 | |
1016 public void windowOpened(WindowEvent evt) { | |
1017 } | |
1018 | |
1019 public void windowClosed(WindowEvent evt) { | |
1020 } | |
1021 | |
1022 public void windowIconified(WindowEvent evt) { | |
1023 } | |
1024 | |
1025 public void windowDeiconified(WindowEvent evt) { | |
1026 } | |
1027 } |