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