Mercurial > hg > Members > you > TreeVNC
diff src/treeVnc/VncProxyService.java @ 15:578ea14c95e9
merge treeVnc
author | Yu Taninari <you@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 13 Jan 2012 13:38:38 +0900 |
parents | |
children | 20c53b836ff8 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/treeVnc/VncProxyService.java Fri Jan 13 13:38:38 2012 +0900 @@ -0,0 +1,1038 @@ +package treeVnc; + +import java.awt.*; +import java.awt.event.*; +import java.io.*; +import java.net.*; + +public class VncProxyService implements java.lang.Runnable { + + + public void treeVncProxy(String[] argv) { + VncProxyService v = new VncProxyService(); + + // v.checkArgs(argv); + + v.mainArgs = argv; + + v.init(); + v.start_threads(); + } + + String[] mainArgs; + String username; + + CreateHtmlFile hgtmlFile; + + // RfbProto rfb; + MyRfbProtoProxy rfb; + MyRfbProtoProxy testrfb; + Thread rfbThread; + Thread accThread; + Thread clientThread; + private Thread bCast; + CreateThread geth; + AcceptClient acc; + private AcceptThread acceptThread; + private TextBoxProxy getHost; + private GetBroadCastProxy getCast; + + Frame vncFrame; + Container vncContainer; + ScrollPane desktopScrollPane; + GridBagLayout gridbag; + ButtonPanel buttonPanel; + Label connStatusLabel; + ProxyVncCanvas vc; + // OptionsFrame options; + OptionsNoFrame options; + ClipboardFrame clipboard; + RecordingFrame rec; + + // Control session recording. + Object recordingSync; + String sessionFileName; + boolean recordingActive; + boolean recordingStatusChanged; + String cursorUpdatesDef; + String eightBitColorsDef; + + // Variables read from parameter values. + String socketFactory; + String host; + int port = 5900; + String passwordParam; + boolean showControls; + boolean offerRelogin; + boolean showOfflineDesktop; + int deferScreenUpdates; + int deferCursorUpdates; + int deferUpdateRequests; + int debugStatsExcludeUpdates; + int debugStatsMeasureUpdates; + + int echoPort = 9999; + private boolean changeFlag; + + String url; + + // XmlRpc client; + String wpUsername, wpPassword, blogId; + String title = "TreeVNC"; + + void checkArgs(String[] argv) { + int len = argv.length; + + for (int i = 0; i < len; i++) { + String str = argv[i]; + if (str.equals("-h") || str.equals("--host")) { + host = argv[++i]; + } else if (str.equals("-pn") || str.equals("--port")) { + port = Integer.parseInt(argv[++i]); + } else if (str.equals("-pw") || str.equals("--password")) { + passwordParam = argv[++i]; + } else if (str.equals("-w") || str.equals("--wpurl")) { + url = argv[++i]; + } else if (str.equals("-wu") || str.equals("--wpusername")) { + wpUsername = argv[++i]; + } else if (str.equals("-wp") || str.equals("--wppassword")) { + wpPassword = argv[++i]; + } else if (str.equals("-wb") || str.equals("--wpblogId")) { + blogId = argv[++i]; + } else if (str.equals("--help")) { + printHelp(); + System.exit(0); + } else if (len == 3) { + host = argv[0]; + port = Integer.parseInt(argv[1]); + passwordParam = argv[2]; + } else if (len == 2) { + host = argv[0]; + port = Integer.parseInt(argv[1]); + } else if (len == 1) { + host = argv[0]; + } + } + } + + void printHelp() { + System.out + .println("usage: java -jar VncProxyService [-h hostname] " + + "[-pn portnumber] [-pw password] [-w WordPressURL] [-wu WPUsername] " + + "[-wp WPPassword] [-wb blogId]"); + } + + // + // init() + // + + public void init() { + + readParameters(); + + options = new OptionsNoFrame(this); + recordingSync = new Object(); + + sessionFileName = null; + recordingActive = false; + recordingStatusChanged = false; + cursorUpdatesDef = null; + eightBitColorsDef = null; + + try { + connectAndAuthenticate(); + doProtocolInitialisation(); + } catch (NoRouteToHostException e) { + fatalError("Network error: no route to server: " + host, e); + } catch (UnknownHostException e) { + fatalError("Network error: server name unknown: " + host, e); + } catch (ConnectException e) { + fatalError("Network error: could not connect to server: " + host + + ":" + port, e); + } catch (IOException e) { + fatalError("Network error: faild connect or authenticate to server"); + } catch (Exception e) { + + } +/* + if(changeFlag){ + acceptThread.changeRfb(rfb); + } else {*/ + rfb.selectPort(5999); + rfbThread = new Thread(this); + acceptThread = new AcceptThread(rfb, 5999); + accThread = new Thread(acceptThread); + getCast = new GetBroadCastProxy(this); + bCast = new Thread(getCast); + //broadCast.udpTransmission(rfb.acceptPort+"-"+host+"-"+rfb.desktopName); + //} + /* + * if(url != null) { try { client = new XmlRpc(blogId, wpUsername, + * wpPassword, url ); InetAddress addr = InetAddress.getLocalHost(); + * String add = new String(addr.getHostAddress()); + * client.addDescription(rfb.desktopName); setStatusXmlRpc(client, + * title, add, rfb.acceptPort); client.editPost(); + * System.out.println("URL:\n" + client.getUrl() + "\n"); } catch + * (MalformedURLException e) { + * System.out.println("Faild create instance of class XmlRpc"); + * e.printStackTrace(); } catch (UnknownHostException e) { + * e.printStackTrace(); } } + */ + + } + + + public void changeInit() throws Exception { + VncProxyService v = new VncProxyService(); + v.changeFlag = true; + //v.checkArgs(argv); + + v.mainArgs = new String[0]; + v.host = host; + v.init(); + v.start_threads(); + + Thread.sleep(10000); + //rfb = v.rfb; + rfb.is = v.rfb.is; + rfb.os = v.rfb.os; + rfb.initData = v.rfb.initData; + + //changeConnection(); +// doProtocolInitialisation(); + + //readParameters(); + options = new OptionsNoFrame(this); + recordingSync = new Object(); + + sessionFileName = null; + recordingActive = false; + recordingStatusChanged = false; + cursorUpdatesDef = null; + eightBitColorsDef = null; + + try { + changeConnection(); + doProtocolInitialisation(); + } catch (NoRouteToHostException e) { + fatalError("Network error: no route to server: " + host, e); + } catch (UnknownHostException e) { + fatalError("Network error: server name unknown: " + host, e); + } catch (ConnectException e) { + fatalError("Network error: could not connect to server: " + host + + ":" + port, e); + } catch (IOException e) { + fatalError("Network error: faild connect or authenticate to server"); + } catch (Exception e) { + + } + + //acceptThread.changeRfb(rfb); + //vc.rfb = rfb; + //rfbThread.start(); + + } + + /* + * void setStatusXmlRpc(XmlRpc client, String title, String hostname, int + * port) { client.setTitle(title); String description = + * makeDescription(hostname, Integer.toString(port)); + * client.addDescription(description); } + */ + String makeDescription(String hostname, String port) { + String description = "<h1>" + hostname + " " + port + "<h1>\n"; + return description; + } + + public void start_threads() { + rfbThread.start(); + accThread.start(); + bCast.start(); + rfb.requestThreadStart(); + } + + // + // run() - executed by the rfbThread to deal with the RFB socket. + // + public void run() { + + try { + // connectAndAuthenticate(); + // doProtocolInitialisation(); + /* + * htmlFile = new CreateHtmlFile(rfb, host, username); + * htmlFile.createHtml(); + */ + vc = new ProxyVncCanvas(this, 0, 0); + vc.updateFramebufferSize(); + + processNormalProtocol();// main loop + + } catch (NoRouteToHostException e) { + fatalError("Network error: no route to server: " + host, e); + } catch (UnknownHostException e) { + fatalError("Network error: server name unknown: " + host, e); + } catch (ConnectException e) { + fatalError("Network error: could not connect to server: " + host + + ":" + port, e); + } catch (EOFException e) { + if (showOfflineDesktop) { + e.printStackTrace(); + System.out + .println("Network error: remote side closed connection"); + if (vc != null) { + vc.enableInput(false); + } + if (rfb != null && !rfb.closed()) + rfb.close(); + if (showControls && buttonPanel != null) { + buttonPanel.disableButtonsOnDisconnect(); + } + } else { + fatalError("Network error: remote side closed connection", e); + } + } catch (IOException e) { + String str = e.getMessage(); + if (str != null && str.length() != 0) { + fatalError("Network Error: " + str, e); + } else { + fatalError(e.toString(), e); + } + } catch (Exception e) { + String str = e.getMessage(); + if (str != null && str.length() != 0) { + fatalError("Error: " + str, e); + } else { + fatalError(e.toString(), e); + } + } + + } + + // + // Process RFB socket messages. + // If the rfbThread is being stopped, ignore any exceptions, + // otherwise rethrow the exception so it can be handled. + // + + void processNormalProtocol() throws Exception { + try { + vc.processNormalProtocol();// main loop + } catch (Exception e) { + if (rfbThread == null) { + System.out.println("Ignoring RFB socket exceptions" + + " because applet is stopping"); + } else { + throw e; + } + } + } + + // + // Connect to the RFB server and authenticate the user. + // + + void connectAndAuthenticate() throws Exception { + if (mainArgs.length == 0) + acc = new AcceptClient(host); + //acc = new AcceptClient(getHost.getAddress()); + // acc = new AcceptClient(); + else + acc = new AcceptClient(mainArgs[0]); + geth = new CreateThread(acc, echoPort); + Thread thread = new Thread(geth); + thread.start(); + + showConnectionStatus("Initializing..."); + + showConnectionStatus("Connecting to " + host + ", port " + port + "..."); + + rfb = new MyRfbProtoProxy(host, port, geth); + + showConnectionStatus("Connected to server"); + + rfb.readVersionMsg(); + showConnectionStatus("RFB server supports protocol version " + + rfb.serverMajor + "." + rfb.serverMinor); + + rfb.writeVersionMsg(); + showConnectionStatus("Using RFB protocol version " + rfb.clientMajor + + "." + rfb.clientMinor); + + int secType = rfb.negotiateSecurity(); + int authType; + if (secType == RfbProto.SecTypeTight) { + showConnectionStatus("Enabling TightVNC protocol extensions"); + rfb.setupTunneling(); + authType = rfb.negotiateAuthenticationTight(); + } else { + authType = secType; + } + + switch (authType) { + case MyRfbProtoProxy.AuthAccess: + rfb.authenticationRequestAccess(); + System.out.println("authenticateion Request right of Acces"); + break; + case RfbProto.AuthNone: + showConnectionStatus("No authentication needed"); + rfb.authenticateNone(); + break; + case RfbProto.AuthVNC: + showConnectionStatus("Performing standard VNC authentication"); + if (passwordParam != null) { + rfb.authenticateVNC(passwordParam); + } else { + String pw = askPassword(); + rfb.authenticateVNC(pw); + } + break; + default: + throw new Exception("Unknown authentication scheme " + authType); + } + } + + void changeConnection() throws Exception { + /* + acc = new AcceptClient(getHost.getAddress()); + geth = new CreateThread(acc, echoPort); + Thread thread = new Thread(geth); + thread.start(); + */ + showConnectionStatus("Initializing..."); + + showConnectionStatus("Connecting to " + host + ", port " + port + "..."); + + //rfb = null; + //rfb.is = null; + + testrfb = new MyRfbProtoProxy(host, port); + showConnectionStatus("Connected to server"); + + testrfb.readVersionMsg(); + showConnectionStatus("RFB server supports protocol version " + + testrfb.serverMajor + "." + testrfb.serverMinor); + + testrfb.writeVersionMsg(); + showConnectionStatus("Using RFB protocol version " + testrfb.clientMajor + + "." + testrfb.clientMinor); + + int secType = testrfb.negotiateSecurity(); + int authType; + if (secType == RfbProto.SecTypeTight) { + showConnectionStatus("Enabling TightVNC protocol extensions"); + testrfb.setupTunneling(); + authType = testrfb.negotiateAuthenticationTight(); + } else { + authType = secType; + } + + switch (authType) { + case MyRfbProtoProxy.AuthAccess: + testrfb.authenticationRequestAccess(); + System.out.println("authenticateion Request right of Acces"); + break; + case RfbProto.AuthNone: + showConnectionStatus("No authentication needed"); + testrfb.authenticateNone(); + break; + case RfbProto.AuthVNC: + showConnectionStatus("Performing standard VNC authentication"); + if (passwordParam != null) { + testrfb.authenticateVNC(passwordParam); + } else { + String pw = askPassword(); + testrfb.authenticateVNC(pw); + } + break; + default: + throw new Exception("Unknown authentication scheme " + authType); + } + //rfb.is = testrfb.is; + //rfb.os = testrfb.os; + //rfb = testrfb; + } + + // + // Show a message describing the connection status. + // To hide the connection status label, use (msg == null). + // + + void showConnectionStatus(String msg) { + System.out.println(msg); + } + + // + // Show an authentication panel. + // + + String askPassword() throws Exception { + /* + * showConnectionStatus(null); AuthPanel authPanel = new + * AuthPanel(this); + * + * GridBagConstraints gbc = new GridBagConstraints(); gbc.gridwidth = + * GridBagConstraints.REMAINDER; gbc.anchor = + * GridBagConstraints.NORTHWEST; gbc.weightx = 1.0; gbc.weighty = 1.0; + * gbc.ipadx = 100; gbc.ipady = 50; gridbag.setConstraints(authPanel, + * gbc); vncContainer.add(authPanel); + * + * + * authPanel.moveFocusToDefaultField(); vncContainer.remove(authPanel); + */ + showConnectionStatus("ask password..."); + String pw; + if (mainArgs.length != 0) + pw = mainArgs[2]; + else + pw = getHost.getPassword(); + return pw; + } + + // + // Do the rest of the protocol initialisation. + // + + void doProtocolInitialisation() throws IOException { + rfb.writeClientInit(); + rfb.readServerInit(); + + System.out.println("Desktop name is " + rfb.desktopName); + System.out.println("Desktop size is " + rfb.framebufferWidth + " x " + + rfb.framebufferHeight); + + setEncodings(); + + // showConnectionStatus(null); + } + + // + // Send current encoding list to the RFB server. + // + + int[] encodingsSaved; + int nEncodingsSaved; + + void setEncodings() { + setEncodings(false); + } + + void autoSelectEncodings() { + setEncodings(true); + } + + void setEncodings(boolean autoSelectOnly) { + if (options == null || rfb == null || !rfb.inNormalProtocol) + return; + + int preferredEncoding = options.preferredEncoding; + if (preferredEncoding == -1) { + long kbitsPerSecond = rfb.kbitsPerSecond(); + /* + * if (nEncodingsSaved < 1) { // Choose Tight or ZRLE encoding for + * the very first update. + * System.out.println("Using Tight/ZRLE encodings"); + * preferredEncoding = RfbProto.EncodingTight; } else if + * (kbitsPerSecond > 2000 && encodingsSaved[0] != + * RfbProto.EncodingHextile) { // Switch to Hextile if the + * connection speed is above 2Mbps. System.out.println("Throughput " + * + kbitsPerSecond + " kbit/s - changing to Hextile encoding"); + * preferredEncoding = RfbProto.EncodingHextile; } else if + * (kbitsPerSecond < 1000 && encodingsSaved[0] != + * RfbProto.EncodingTight) { // Switch to Tight/ZRLE if the + * connection speed is below 1Mbps. System.out.println("Throughput " + * + kbitsPerSecond + " kbit/s - changing to Tight/ZRLE encodings"); + * preferredEncoding = RfbProto.EncodingTight; } else { // Don't + * change the encoder. if (autoSelectOnly) return; preferredEncoding + * = encodingsSaved[0]; } + */ + } else { + // Auto encoder selection is not enabled. + if (autoSelectOnly) + return; + } + + int[] encodings = new int[20]; + int nEncodings = 0; + + encodings[nEncodings++] = preferredEncoding; + + if (options.useCopyRect) { + encodings[nEncodings++] = RfbProto.EncodingCopyRect; + } + /* + * if (preferredEncoding != RfbProto.EncodingTight) { + * encodings[nEncodings++] = RfbProto.EncodingTight; } + */ + + if (preferredEncoding != RfbProto.EncodingZRLE) { + encodings[nEncodings++] = RfbProto.EncodingZRLE; + } + /* + * if (preferredEncoding != RfbProto.EncodingHextile) { + * encodings[nEncodings++] = RfbProto.EncodingHextile; } if + * (preferredEncoding != RfbProto.EncodingZlib) { + * encodings[nEncodings++] = RfbProto.EncodingZlib; } + */ + /* + * if (preferredEncoding != RfbProto.EncodingCoRRE) { + * encodings[nEncodings++] = RfbProto.EncodingCoRRE; } if + * (preferredEncoding != RfbProto.EncodingRRE) { encodings[nEncodings++] + * = RfbProto.EncodingRRE; } + */ + /* + * if (options.compressLevel >= 0 && options.compressLevel <= 9) { + * encodings[nEncodings++] = RfbProto.EncodingCompressLevel0 + + * options.compressLevel; } if (options.jpegQuality >= 0 && + * options.jpegQuality <= 9) { encodings[nEncodings++] = + * RfbProto.EncodingQualityLevel0 + options.jpegQuality; } if + * (options.requestCursorUpdates) { encodings[nEncodings++] = + * RfbProto.EncodingXCursor; encodings[nEncodings++] = + * RfbProto.EncodingRichCursor; if (!options.ignoreCursorUpdates) + * encodings[nEncodings++] = RfbProto.EncodingPointerPos; } + */ + + encodings[nEncodings++] = RfbProto.EncodingLastRect; + encodings[nEncodings++] = RfbProto.EncodingNewFBSize; + + boolean encodingsWereChanged = false; + if (nEncodings != nEncodingsSaved) { + encodingsWereChanged = true; + } else { + for (int i = 0; i < nEncodings; i++) { + if (encodings[i] != encodingsSaved[i]) { + encodingsWereChanged = true; + break; + } + } + } + + if (encodingsWereChanged) { + try { + rfb.writeSetEncodings(encodings, nEncodings); + if (vc != null) { + vc.softCursorFree(); + } + } catch (Exception e) { + e.printStackTrace(); + } + encodingsSaved = encodings; + nEncodingsSaved = nEncodings; + } + } + + // + // setCutText() - send the given cut text to the RFB server. + // + + void setCutText(String text) { + try { + if (rfb != null && rfb.inNormalProtocol) { + rfb.writeClientCutText(text); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + // + // Order change in session recording status. To stop recording, pass + // null in place of the fname argument. + // + + void setRecordingStatus(String fname) { + synchronized (recordingSync) { + sessionFileName = fname; + recordingStatusChanged = true; + } + } + + // + // Start or stop session recording. Returns true if this method call + // causes recording of a new session. + // + + boolean checkRecordingStatus() throws IOException { + synchronized (recordingSync) { + if (recordingStatusChanged) { + recordingStatusChanged = false; + if (sessionFileName != null) { + startRecording(); + return true; + } else { + stopRecording(); + } + } + } + return false; + } + + // + // Start session recording. + // + + protected void startRecording() throws IOException { + synchronized (recordingSync) { + if (!recordingActive) { + // Save settings to restore them after recording the session. + cursorUpdatesDef = options.choices[options.cursorUpdatesIndex] + .getSelectedItem(); + eightBitColorsDef = options.choices[options.eightBitColorsIndex] + .getSelectedItem(); + // Set options to values suitable for recording. + options.choices[options.cursorUpdatesIndex].select("Disable"); + options.choices[options.cursorUpdatesIndex].setEnabled(false); + options.setEncodings(); + options.choices[options.eightBitColorsIndex].select("No"); + options.choices[options.eightBitColorsIndex].setEnabled(false); + options.setColorFormat(); + } else { + rfb.closeSession(); + } + + System.out.println("Recording the session in " + sessionFileName); + rfb.startSession(sessionFileName); + recordingActive = true; + } + } + + // + // Stop session recording. + // + + protected void stopRecording() throws IOException { + synchronized (recordingSync) { + if (recordingActive) { + // Restore options. + options.choices[options.cursorUpdatesIndex] + .select(cursorUpdatesDef); + options.choices[options.cursorUpdatesIndex].setEnabled(true); + options.setEncodings(); + options.choices[options.eightBitColorsIndex] + .select(eightBitColorsDef); + options.choices[options.eightBitColorsIndex].setEnabled(true); + options.setColorFormat(); + + rfb.closeSession(); + System.out.println("Session recording stopped."); + } + sessionFileName = null; + recordingActive = false; + } + } + + // + // readParameters() - read parameters from the html source or from the + // command line. On the command line, the arguments are just a sequence of + // param_name/param_value pairs where the names and values correspond to + // those expected in the html applet tag source. + // + + void readParameters() { + if (!(changeFlag)) { + if (mainArgs.length == 0) { + getHost = new TextBoxProxy(this); + getHost.ipRegister(); + host = getHost.getAddress(); + } else { + host = mainArgs[0]; + } + + if (mainArgs.length < 2) { + port = Integer.parseInt(getHost.getPort()); + // port = 5900; + } else { + port = Integer.parseInt(mainArgs[1]); + } + } else { + getHost = new TextBoxProxy(this); + port = 5900; + } + if(getHost==null){ + getHost = new TextBoxProxy(this); + //getHost.changeHost(); + } else { + //getHost.changeHost(); + } + + // Read "ENCPASSWORD" or "PASSWORD" parameter if specified. + // readPasswordParameters(); + + String str; + + // "Show Controls" set to "No" disables button panel. + showControls = true; + str = readParameter("Show Controls", false); + if (str != null && str.equalsIgnoreCase("No")) + showControls = false; + + // "Offer Relogin" set to "No" disables "Login again" and "Close + // window" buttons under error messages in applet mode. + offerRelogin = true; + str = readParameter("Offer Relogin", false); + if (str != null && str.equalsIgnoreCase("No")) + offerRelogin = false; + + // Do we continue showing desktop on remote disconnect? + showOfflineDesktop = false; + str = readParameter("Show Offline Desktop", false); + if (str != null && str.equalsIgnoreCase("Yes")) + showOfflineDesktop = true; + + // Fine tuning options. + deferScreenUpdates = readIntParameter("Defer screen updates", 20); + deferCursorUpdates = readIntParameter("Defer cursor updates", 10); + deferUpdateRequests = readIntParameter("Defer update requests", 0); + + // Debugging options. + debugStatsExcludeUpdates = readIntParameter("DEBUG_XU", 0); + debugStatsMeasureUpdates = readIntParameter("DEBUG_CU", 0); + + // SocketFactory. + socketFactory = readParameter("SocketFactory", false); + } + + // + // Read password parameters. If an "ENCPASSWORD" parameter is set, + // then decrypt the password into the passwordParam string. Otherwise, + // try to read the "PASSWORD" parameter directly to passwordParam. + // + + private void readPasswordParameters() { + String encPasswordParam; + // String encPasswordParam = readParameter("ENCPASSWORD", false); + if (mainArgs.length != 0) + encPasswordParam = mainArgs[2]; + else + encPasswordParam = getHost.getPassword(); + + if (encPasswordParam == null) { + // passwordParam = readParameter("PASSWORD", false); + + } else { + // ENCPASSWORD is hexascii-encoded. Decode. + byte[] pw = { 0, 0, 0, 0, 0, 0, 0, 0 }; + int len = encPasswordParam.length() / 2; + if (len > 8) + len = 8; + for (int i = 0; i < len; i++) { + String hex = encPasswordParam.substring(i * 2, i * 2 + 2); + Integer x = new Integer(Integer.parseInt(hex, 16)); + pw[i] = x.byteValue(); + } + // Decrypt the password. + byte[] key = { 23, 82, 107, 6, 35, 78, 88, 7 }; + DesCipher des = new DesCipher(key); + des.decrypt(pw, 0, pw, 0); + passwordParam = new String(pw); + + } + } + + public String readParameter(String name, boolean required) { + if(mainArgs!=null){ + for (int i = 0; i < mainArgs.length; i += 2) { + if (mainArgs[i].equalsIgnoreCase(name)) { + try { + return mainArgs[i + 1]; + } catch (Exception e) { + if (required) { + fatalError(name + " parameter not specified"); + } + return null; + } + } + } + if (required) { + fatalError(name + " parameter not specified"); + } + } + return null; + } + + int readIntParameter(String name, int defaultValue) { + String str = readParameter(name, false); + int result = defaultValue; + if (str != null) { + try { + result = Integer.parseInt(str); + } catch (NumberFormatException e) { + } + } + return result; + } + + // + // disconnect() - close connection to server. + // + + synchronized public void disconnect() { + System.out.println("Disconnecting"); + + if (vc != null) { + double sec = (System.currentTimeMillis() - vc.statStartTime) / 1000.0; + double rate = Math.round(vc.statNumUpdates / sec * 100) / 100.0; + int nRealRects = vc.statNumPixelRects; + int nPseudoRects = vc.statNumTotalRects - vc.statNumPixelRects; + System.out.println("Updates received: " + vc.statNumUpdates + " (" + + nRealRects + " rectangles + " + nPseudoRects + + " pseudo), " + rate + " updates/sec"); + int numRectsOther = nRealRects - vc.statNumRectsTight + - vc.statNumRectsZRLE - vc.statNumRectsHextile + - vc.statNumRectsRaw - vc.statNumRectsCopy; + System.out.println("Rectangles:" + " Tight=" + vc.statNumRectsTight + + "(JPEG=" + vc.statNumRectsTightJPEG + ") ZRLE=" + + vc.statNumRectsZRLE + " Hextile=" + + vc.statNumRectsHextile + " Raw=" + vc.statNumRectsRaw + + " CopyRect=" + vc.statNumRectsCopy + " other=" + + numRectsOther); + + int raw = vc.statNumBytesDecoded; + int compressed = vc.statNumBytesEncoded; + if (compressed > 0) { + double ratio = Math.round((double) raw / compressed * 1000) / 1000.0; + System.out.println("Pixel data: " + vc.statNumBytesDecoded + + " bytes, " + vc.statNumBytesEncoded + + " compressed, ratio " + ratio); + } + } + + if (rfb != null && !rfb.closed()) + rfb.close(); + // options.dispose(); + clipboard.dispose(); + if (rec != null) + rec.dispose(); + + System.exit(0); + + } + + // + // fatalError() - print out a fatal error message. + // FIXME: Do we really need two versions of the fatalError() method? + // + + synchronized public void fatalError(String str) { + System.out.println(str); + System.exit(1); + } + + synchronized public void fatalError(String str, Exception e) { + + if (rfb != null && rfb.closed()) { + // Not necessary to show error message if the error was caused + // by I/O problems after the rfb.close() method call. + System.out.println("RFB thread finished"); + return; + } + + System.out.println(str); + e.printStackTrace(); + + if (rfb != null) + rfb.close(); + + System.exit(1); + + } + + // + // Show message text and optionally "Relogin" and "Close" buttons. + // + + void showMessage(String msg) { + vncContainer.removeAll(); + + Label errLabel = new Label(msg, Label.CENTER); + errLabel.setFont(new Font("Helvetica", Font.PLAIN, 12)); + + if (offerRelogin) { + /* + * Panel gridPanel = new Panel(new GridLayout(0, 1)); Panel + * outerPanel = new Panel(new FlowLayout(FlowLayout.LEFT)); + * outerPanel.add(gridPanel); vncContainer.setLayout(new + * FlowLayout(FlowLayout.LEFT, 30, 16)); + * vncContainer.add(outerPanel); Panel textPanel = new Panel(new + * FlowLayout(FlowLayout.CENTER)); textPanel.add(errLabel); + * gridPanel.add(textPanel); gridPanel.add(new ReloginPanel(this)); + */ + } else { + /* + * vncContainer.setLayout(new FlowLayout(FlowLayout.LEFT, 30, 30)); + * vncContainer.add(errLabel); + */ + } + + } + + // + // Stop the applet. + // Main applet thread will terminate on first exception + // after seeing that rfbThread has been set to null. + // + + public void stop() { + System.out.println("Stopping applet"); + rfbThread = null; + } + + // + // This method is called before the applet is destroyed. + // + + public void destroy() { + System.out.println("Destroying applet"); + + vncContainer.removeAll(); + // options.dispose(); + clipboard.dispose(); + if (rec != null) + rec.dispose(); + if (rfb != null && !rfb.closed()) + rfb.close(); + } + + // + // Start/stop receiving mouse events. + // + + public void enableInput(boolean enable) { + vc.enableInput(enable); + } + + // + // Close application properly on window close event. + // + + public void windowClosing(WindowEvent evt) { + System.out.println("Closing window"); + if (rfb != null) + disconnect(); + + vncContainer.hide(); + + } + + // + // Ignore window events we're not interested in. + // + + public void windowActivated(WindowEvent evt) { + } + + public void windowDeactivated(WindowEvent evt) { + } + + public void windowOpened(WindowEvent evt) { + } + + public void windowClosed(WindowEvent evt) { + } + + public void windowIconified(WindowEvent evt) { + } + + public void windowDeiconified(WindowEvent evt) { + } +}