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