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