Mercurial > hg > Members > you > TreeVNC
changeset 16:92f984b47b7a
merge
author | Yu Taninari <you@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 13 Jan 2012 13:41:30 +0900 |
parents | 578ea14c95e9 (current diff) 87eb194e4b2c (diff) |
children | 23b3df33b4c5 |
files | src/treeVnc/TreeVnc.java |
diffstat | 12 files changed, 8277 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/myVncProxy/CuiMyVncClient.java Fri Jan 13 13:41:30 2012 +0900 @@ -0,0 +1,1074 @@ +package myVncProxy; + +import java.awt.*; +import java.awt.event.*; +import java.io.*; +import java.net.*; +import java.nio.ByteBuffer; +import java.util.Random; + +import myVncProxy.AcceptThread; +import myVncProxy.OptionsNoFrame; + + +public class CuiMyVncClient implements InterfaceForViewer { + + + String[] mainArgs; + String username; + + // RfbProto rfb; + MyRfbProto rfb; + Thread rfbThread; + Thread accThread; + Thread clientThread; + + Frame vncFrame; + Container vncContainer; + ScrollPane desktopScrollPane; + GridBagLayout gridbag; + ButtonPanel buttonPanel; + Label connStatusLabel; + CuiVncCanvas 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; + String passwordParam; + boolean showControls; + boolean offerRelogin; + boolean showOfflineDesktop; + int deferScreenUpdates; + int deferCursorUpdates; + int deferUpdateRequests; + int debugStatsExcludeUpdates; + int debugStatsMeasureUpdates; + + private static final long serialVersionUID = 1L; + boolean inAnApplet = true; + boolean inSeparateFrame = false; + Socket clientSocket = null; + String parent, treenum; + private String leaderflag; + boolean runflag = false; + boolean first = true; + + EchoClient echoValue; + int echoPort; + String pHost; + + public static void main(String[] argv) { + CuiMyVncClient v = new CuiMyVncClient(); + v.echoValue = null; + v.runClient(argv, v); + + } + + private void runClient(String[] argv, CuiMyVncClient v) { + mainArgs = argv; + + if (mainArgs.length > 0) + pHost = mainArgs[0]; + else + pHost = "cls080.ie.u-ryukyu.ac.jp"; + if (mainArgs.length > 1) + port = Integer.parseInt(mainArgs[1]); + else + port = 5999; + + v.init(); + v.start_threads(); + + } + + + void checkArgs(String[] argv) { + if (argv.length > 3) { + username = argv[3]; + } else if (argv.length < 2) { + System.out.println("Please enter argv"); + System.out.println("hostname(IPaddress) port password"); + System.exit(0); + } else { + username = argv[0]; + } + } + + // + // init() + // + + public void init() { + + Random rnd = new Random(); + long ran = rnd.nextInt(5000); + try { + Thread.sleep(ran); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + readParameters(); + //readParameters(value); + + options = new OptionsNoFrame(this); + recordingSync = new Object(); + + sessionFileName = null; + recordingActive = false; + recordingStatusChanged = false; + cursorUpdatesDef = null; + eightBitColorsDef = null; + + /* + * try { connectAndAuthenticate(); } 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 (Exception e) { } + */ + rfbThread = new Thread(this); + + } + + // + // run() - executed by the rfbThread to deal with the RFB socket. + // + + public void start_threads() { + rfbThread.start(); + } + + public void run() { + + try { + if (first) { + connectAndAuthenticate(); + accThread = new Thread(new AcceptThread(rfb, 5999)); + accThread.start(); + first = false; + }else { + reConnectAndAuthenticate(); + } + doProtocolInitialisation(); + + vc = new CuiVncCanvas(this, 0, 0); + vc.updateFramebufferSize(); + + } catch (IOException e) { + + System.out.println("Socket error"); + // parent no find + Random rnd = new Random(); + long ran = rnd.nextInt(5000) + 5000; + System.out.println(ran); + // 親がいない場合の処理はここに書く!!!! + /** + * this while reconnection + */ + + int counter = 0; + + /* + vncFrame.setVisible(false); + vncFrame.dispose(); +*/ + while (true) { + /** + * if my last node case reconnectoion stop + */ + + echoValue = new EchoClient(echoValue, this); + try { + Thread.sleep(ran); + } catch (InterruptedException e1) { + e1.printStackTrace(); + } + + if (counter >= 3) { + echoValue.openport(); + echoValue.notfoundParent(); + } + + echoValue.openport(); + // runflag = echo.losthost(); + if (echoValue.losthost()) { + break; + } + counter++; + } + // System.exit(0); + }catch (Exception e) { + System.out.println(e); + System.exit(0); + } + try{ + + 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 (leaderflag != null) { + while (true) { + echoValue = new EchoClient(echoValue, this); + echoValue.openport(); + // runflag = echo.losthost(); + if (echoValue.losthost()) { + break; + } + } + } else { + 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 { + showConnectionStatus("Initializing..."); + + showConnectionStatus("Connecting to " + host + ", port " + port + "..."); + + // rfb = new RfbProto(host, port, this); + rfb = new MyRfbProto(pHost, port, this); + + 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); + + + if (rfb.serverMinor == 855) { + /* + * if connect to proxy, userEchoPortFlag is true. + * if connect to client, userEchoPortFlag is false. + */ + boolean useEchoPortFlag = rfb.readProxyFlag(); + + if (useEchoPortFlag) { + byte[] b = new byte[4]; + b = rfb.readEchoPort(); + echoPort = castByteInt(b); + + InetAddress addr = InetAddress.getByName(pHost); + String h = new String(addr.getHostAddress()); + + getParentName(); + if (!(h.equals(host))) { + rfb.changeParent(host, port); + rfb.readVersionMsg(); + rfb.writeVersionMsg(); + boolean flag = rfb.readProxyFlag(); + } + } + } + + 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 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 reConnectAndAuthenticate() throws Exception { + showConnectionStatus("Initializing..."); + + showConnectionStatus("Connecting to " + host + ", port " + port + "..."); + + rfb.changeParent(host, port); + + 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); + + if (rfb.serverMinor == 855) { + boolean useEchoPortFlag = rfb.readProxyFlag(); + if (useEchoPortFlag) { + byte[] b = new byte[4]; + b = rfb.readEchoPort(); + echoPort = castByteInt(b); + + InetAddress addr = InetAddress.getByName(pHost); + String h = new String(addr.getHostAddress()); + + getParentName(); + if (!(h.equals(host))) { + rfb.changeParent(host, port); + rfb.readVersionMsg(); + rfb.writeVersionMsg(); + boolean flag = rfb.readProxyFlag(); + } + } + } + + 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 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); + } + } + + // + // 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 = mainArgs[2]; + 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() { + /* + * host = readParameter("HOST", !inAnApplet); + * + * if (host == null) { host = getCodeBase().getHost(); if + * (host.equals("")) { fatalError("HOST parameter not specified"); } } + * + * port = readIntParameter("PORT", 5550); + */ + + // Read "ENCPASSWORD" or "PASSWORD" parameter if specified. + // readPasswordParameters(); + + String str; + if (inAnApplet) { + str = readParameter("Open New Window", false); + if (str != null && str.equalsIgnoreCase("Yes")) + inSeparateFrame = true; + } + + // "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 = readParameter("ENCPASSWORD", false); + + 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) { + 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) { + } + + public void setClientSocket(Socket sock) { + clientSocket = sock; + } + + public void start() { + + } + public void close() { + rfb.close(); + } + public void getParentName() { + if (echoValue == null) { + + if (clientSocket == null) { + String pHost; + if (mainArgs.length > 0) + pHost = mainArgs[0]; + else + pHost = "cls080.ie.u-ryukyu.ac.jp"; +// echo = new EchoClient(pHost, this); + echoValue = new EchoClient(pHost, this, echoPort); + echoValue.openport(); + + echoValue = echoValue.requestHostName("1"); + } else { + echoValue = new EchoClient(); + echoValue = echoValue.Interruption(clientSocket); + } + } + + // proxyからの返信で接続先を決定する + host = echoValue.responseLine; + parent = echoValue.parent; + if (echoValue.treenum != null) { + treenum = echoValue.treenum; + } else { + treenum = echoValue.treenum; + } + if (echoValue.leaderflag != null) { + leaderflag = echoValue.leaderflag; + } else { + leaderflag = echoValue.leaderflag; + } + System.out.println("Parent =" + parent); + System.out.println("mynumber =" + treenum); + System.out.println("connect host =" + host); + System.out.println("leaderflag(boolean) = " + leaderflag); + +// port = 5999; + + } + public void setEchoValue(EchoClient value) { + this.echoValue = value; + } + + + int castByteInt(byte[] b) { + ByteBuffer bb = ByteBuffer.wrap(b); + int echoValue = bb.getInt(); + return echoValue; + } + public Image getScreenImage() { + return vc.rawPixelsImage; + } + + public void writeScreenData(byte[] b, String imageFormat) { + try{ + vc.drawBufferedImage(b); + }catch(IOException e){ + e.printStackTrace(); + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/myVncProxy/CuiVncCanvas.java Fri Jan 13 13:41:30 2012 +0900 @@ -0,0 +1,1955 @@ +package myVncProxy; +import java.awt.*; +import java.awt.event.*; +import java.awt.image.*; +import java.io.*; +import java.lang.*; +import java.nio.ByteBuffer; +import java.util.zip.*; + +import java.net.Socket; + +import javax.imageio.ImageIO; + +// +//VncCanvas is a subclass of Canvas which draws a VNC desktop on it. +// + +class CuiVncCanvas extends Canvas implements KeyListener, MouseListener, + MouseMotionListener { + + CuiMyVncClient viewer; + MyRfbProto rfb; + ColorModel cm8, cm24; + Color[] colors; + int bytesPixel; + + int maxWidth = 0, maxHeight = 0; + int scalingFactor; + int scaledWidth, scaledHeight; + +// Image memImage; + BufferedImage memImage; + Graphics memGraphics; + + Image rawPixelsImage; +// BufferedImage rawPixelsImage; + BufferedImage bimg; + + MemoryImageSource pixelsSource; + byte[] pixels8; + int[] pixels24; + + // Update statistics. + long statStartTime; // time on first framebufferUpdateRequest + int statNumUpdates; // counter for FramebufferUpdate messages + int statNumTotalRects; // rectangles in FramebufferUpdate messages + int statNumPixelRects; // the same, but excluding pseudo-rectangles + int statNumRectsTight; // Tight-encoded rectangles (including JPEG) + int statNumRectsTightJPEG; // JPEG-compressed Tight-encoded rectangles + int statNumRectsZRLE; // ZRLE-encoded rectangles + int statNumRectsHextile; // Hextile-encoded rectangles + int statNumRectsRaw; // Raw-encoded rectangles + int statNumRectsCopy; // CopyRect rectangles + int statNumBytesEncoded; // number of bytes in updates, as received + int statNumBytesDecoded; // number of bytes, as if Raw encoding was used + + // ZRLE encoder's data. + byte[] zrleBuf; + int zrleBufLen = 0; + byte[] zrleTilePixels8; + int[] zrleTilePixels24; + ZlibInStream zrleInStream; + boolean zrleRecWarningShown = false; + + // Zlib encoder's data. + byte[] zlibBuf; + int zlibBufLen = 0; + Inflater zlibInflater; + + // Tight encoder's data. + final static int tightZlibBufferSize = 512; + Inflater[] tightInflaters; + + // Since JPEG images are loaded asynchronously, we have to remember + // their position in the framebuffer. Also, this jpegRect object is + // used for synchronization between the rfbThread and a JVM's thread + // which decodes and loads JPEG images. + Rectangle jpegRect; + + // True if we process keyboard and mouse events. + boolean inputEnabled; + private int b = 0; + + + + // + // The constructors. + // + + public CuiVncCanvas(CuiMyVncClient v, int maxWidth_, int maxHeight_) + throws IOException { + + viewer = v; + maxWidth = maxWidth_; + maxHeight = maxHeight_; + + rfb = viewer.rfb; + + tightInflaters = new Inflater[4]; + + cm8 = new DirectColorModel(8, 7, (7 << 3), (3 << 6)); + cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF); + + colors = new Color[256]; + for (int i = 0; i < 256; i++) + colors[i] = new Color(cm8.getRGB(i)); + +// setPixelFormat(); + + inputEnabled = false; + // Keyboard listener is enabled even in view-only mode, to catch + // 'r' or 'R' key presses used to request screen update. + addKeyListener(this); + } + + public CuiVncCanvas(CuiMyVncClient v) throws IOException { + this(v, 0, 0); + } + + // + // Callback methods to determine geometry of our Component. + // + + public Dimension getPreferredSize() { + return new Dimension(scaledWidth, scaledHeight); + } + + public Dimension getMinimumSize() { + return new Dimension(scaledWidth, scaledHeight); + } + + public Dimension getMaximumSize() { + return new Dimension(scaledWidth, scaledHeight); + } + + // + // All painting is performed here. + // + + public void update(Graphics g) { + paint(g); + } + + public void paint(Graphics g) { + synchronized (memImage) { + if (rfb.framebufferWidth == scaledWidth) { + g.drawImage(memImage, 0, 0, null); + } else { + paintScaledFrameBuffer(g); + } + } + if (showSoftCursor) { + int x0 = cursorX - hotX, y0 = cursorY - hotY; + Rectangle r = new Rectangle(x0, y0, cursorWidth, cursorHeight); + if (r.intersects(g.getClipBounds())) { + g.drawImage(softCursor, x0, y0, null); + } + } + } + + public void paintScaledFrameBuffer(Graphics g) { + g.drawImage(memImage, 0, 0, scaledWidth, scaledHeight, null); + } + + // + // Override the ImageObserver interface method to handle drawing of + // JPEG-encoded data. + // + + public boolean imageUpdate(Image img, int infoflags, int x, int y, + int width, int height) { + if ((infoflags & (ALLBITS | ABORT)) == 0) { + return true; // We need more image data. + } else { + // If the whole image is available, draw it now. + if ((infoflags & ALLBITS) != 0) { + if (jpegRect != null) { + synchronized (jpegRect) { + memGraphics + .drawImage(img, jpegRect.x, jpegRect.y, null); + scheduleRepaint(jpegRect.x, jpegRect.y, jpegRect.width, + jpegRect.height); + jpegRect.notify(); + } + } + } + return false; // All image data was processed. + } + } + + // + // Start/stop receiving mouse events. Keyboard events are received + // even in view-only mode, because we want to map the 'r' key to the + // screen refreshing function. + // + + public synchronized void enableInput(boolean enable) { + if (enable && !inputEnabled) { + inputEnabled = true; + addMouseListener(this); + addMouseMotionListener(this); + if (viewer.showControls) { + viewer.buttonPanel.enableRemoteAccessControls(true); + } + createSoftCursor(); // scaled cursor + } else if (!enable && inputEnabled) { + inputEnabled = false; + removeMouseListener(this); + removeMouseMotionListener(this); + if (viewer.showControls) { + viewer.buttonPanel.enableRemoteAccessControls(false); + } + createSoftCursor(); // non-scaled cursor + } + } + + public void setPixelFormat() throws IOException { +/* + if (viewer.options.eightBitColors) { + rfb.writeSetPixelFormat(8, 8, false, true, 7, 7, 3, 0, 3, 6); + bytesPixel = 1; + } else { + rfb.writeSetPixelFormat(32, 24, false, true, 255, 255, 255, 16, 8, + 0); + bytesPixel = 4; + } +*/ + updateFramebufferSize(); + } + + void updateFramebufferSize() { + + // Useful shortcuts. + int fbWidth = rfb.framebufferWidth; + int fbHeight = rfb.framebufferHeight; + + // Calculate scaling factor for auto scaling. + if (maxWidth > 0 && maxHeight > 0) { + int f1 = maxWidth * 100 / fbWidth; + int f2 = maxHeight * 100 / fbHeight; + scalingFactor = Math.min(f1, f2); + if (scalingFactor > 100) + scalingFactor = 100; + System.out.println("Scaling desktop at " + scalingFactor + "%"); + } + + // Update scaled framebuffer geometry. + scaledWidth = (fbWidth * scalingFactor + 50) / 100; + scaledHeight = (fbHeight * scalingFactor + 50) / 100; + + // Create new off-screen image either if it does not exist, or if + // its geometry should be changed. It's not necessary to replace + // existing image if only pixel format should be changed. +/* + if (memImage == null) { + memImage = viewer.vncContainer.createImage(fbWidth, fbHeight); + memGraphics = memImage.getGraphics(); + } else if (memImage.getWidth(null) != fbWidth + || memImage.getHeight(null) != fbHeight) { + synchronized (memImage) { + memImage = viewer.vncContainer.createImage(fbWidth, fbHeight); + memGraphics = memImage.getGraphics(); + } + } +*/ + memImage = new BufferedImage(rfb.framebufferWidth, rfb.framebufferHeight, BufferedImage.TYPE_INT_RGB ); + memGraphics = memImage.getGraphics(); + + // Images with raw pixels should be re-allocated on every change + // of geometry or pixel format. + if (bytesPixel == 1) { + + pixels24 = null; + pixels8 = new byte[fbWidth * fbHeight]; + + pixelsSource = new MemoryImageSource(fbWidth, fbHeight, cm8, + pixels8, 0, fbWidth); + + zrleTilePixels24 = null; + zrleTilePixels8 = new byte[64 * 64]; + + } else { + + pixels8 = null; + pixels24 = new int[fbWidth * fbHeight]; + + pixelsSource = new MemoryImageSource(fbWidth, fbHeight, cm24, + pixels24, 0, fbWidth); + + zrleTilePixels8 = null; + zrleTilePixels24 = new int[64 * 64]; + + } + pixelsSource.setAnimated(true); + rawPixelsImage = Toolkit.getDefaultToolkit().createImage(pixelsSource); +// rawPixelsImage = (BufferedImage) Toolkit.getDefaultToolkit().createImage(pixelsSource); + + } + + void resizeDesktopFrame() { + setSize(scaledWidth, scaledHeight); + + // FIXME: Find a better way to determine correct size of a + // ScrollPane. -- const + Insets insets = viewer.desktopScrollPane.getInsets(); + viewer.desktopScrollPane.setSize( + scaledWidth + 2 * Math.min(insets.left, insets.right), + scaledHeight + 2 * Math.min(insets.top, insets.bottom)); + + viewer.vncFrame.pack(); + + // Try to limit the frame size to the screen size. + + Dimension screenSize = viewer.vncFrame.getToolkit().getScreenSize(); + Dimension frameSize = viewer.vncFrame.getSize(); + Dimension newSize = frameSize; + + // Reduce Screen Size by 30 pixels in each direction; + // This is a (poor) attempt to account for + // 1) Menu bar on Macintosh (should really also account for + // Dock on OSX). Usually 22px on top of screen. + // 2) Taxkbar on Windows (usually about 28 px on bottom) + // 3) Other obstructions. + + screenSize.height -= 30; + screenSize.width -= 30; + + boolean needToResizeFrame = false; + if (frameSize.height > screenSize.height) { + newSize.height = screenSize.height; + needToResizeFrame = true; + } + if (frameSize.width > screenSize.width) { + newSize.width = screenSize.width; + needToResizeFrame = true; + } + if (needToResizeFrame) { + viewer.vncFrame.setSize(newSize); + } + + viewer.desktopScrollPane.doLayout(); + } + + // + // processNormalProtocol() - executed by the rfbThread to deal with the + // RFB socket. + // + + public void processNormalProtocol() throws Exception { + + // Start/stop session recording if necessary. + viewer.checkRecordingStatus(); + + rfb.writeFramebufferUpdateRequest(0, 0, rfb.framebufferWidth, + rfb.framebufferHeight, false); + + resetStats(); + boolean statsRestarted = false; + + // + // main dispatch loop + // + + long count = 0; + while (true) { +// System.out.println("\ncount=" + count); + + count++; + + /** + * read Data from parents and send Data to Client. + */ + rfb.sendDataToClient(); + + long numBytesRead = rfb.getNumBytesRead(); + + // Read message type from the server. + int msgType = rfb.readServerMessageType(); + + // Process the message depending on its type. + switch (msgType) { + case MyRfbProto.SpeedCheckMillis: + rfb.readSpeedCheck(); + + break; + case MyRfbProto.WriteJpegData: + byte[] b = rfb.readJpegData(); + drawBufferedImage(b); + break; + case RfbProto.FramebufferUpdate: + + if (statNumUpdates == viewer.debugStatsExcludeUpdates + && !statsRestarted) { + resetStats(); + statsRestarted = true; + } else if (statNumUpdates == viewer.debugStatsMeasureUpdates + && statsRestarted) { + viewer.disconnect(); + } + + rfb.readFramebufferUpdate(); + statNumUpdates++; + + boolean cursorPosReceived = false; + + for (int i = 0; i < rfb.updateNRects; i++) { + + rfb.readFramebufferUpdateRectHdr(); + statNumTotalRects++; + int rx = rfb.updateRectX, ry = rfb.updateRectY; + int rw = rfb.updateRectW, rh = rfb.updateRectH; + + if (rfb.updateRectEncoding == rfb.EncodingLastRect) + break; + + if (rfb.updateRectEncoding == rfb.EncodingNewFBSize) { + rfb.setFramebufferSize(rw, rh); + updateFramebufferSize(); + break; + } + + if (rfb.updateRectEncoding == rfb.EncodingXCursor + || rfb.updateRectEncoding == rfb.EncodingRichCursor) { + handleCursorShapeUpdate(rfb.updateRectEncoding, rx, ry, + rw, rh); + continue; + } + + if (rfb.updateRectEncoding == rfb.EncodingPointerPos) { + softCursorMove(rx, ry); + cursorPosReceived = true; + continue; + } + + long numBytesReadBefore = rfb.getNumBytesRead(); + + rfb.startTiming(); + + switch (rfb.updateRectEncoding) { + case RfbProto.EncodingRaw: + statNumRectsRaw++; + handleRawRect(rx, ry, rw, rh); + break; + case RfbProto.EncodingCopyRect: + statNumRectsCopy++; + handleCopyRect(rx, ry, rw, rh); + break; + case RfbProto.EncodingRRE: + handleRRERect(rx, ry, rw, rh); + break; + case RfbProto.EncodingCoRRE: + handleCoRRERect(rx, ry, rw, rh); + break; + case RfbProto.EncodingHextile: + statNumRectsHextile++; + handleHextileRect(rx, ry, rw, rh); + break; + case RfbProto.EncodingZRLE: + statNumRectsZRLE++; + handleZRLERect(rx, ry, rw, rh); + break; + case RfbProto.EncodingZRLEE: + statNumRectsZRLE++; + handleZRLERect(rx, ry, rw, rh); + break; + case RfbProto.EncodingZlib: + handleZlibRect(rx, ry, rw, rh); + break; + case RfbProto.EncodingTight: + statNumRectsTight++; + handleTightRect(rx, ry, rw, rh); + break; + default: + throw new Exception("Unknown RFB rectangle encoding " + + rfb.updateRectEncoding); + } + + rfb.stopTiming(); + + long kbitsPerSecond = rfb.kbitsPerSecond(); +// System.out.println("kbitsPerSecond = " + kbitsPerSecond); + + statNumPixelRects++; + statNumBytesDecoded += rw * rh * bytesPixel; + statNumBytesEncoded += (int) (rfb.getNumBytesRead() - numBytesReadBefore); + } + + boolean fullUpdateNeeded = false; + + // Start/stop session recording if necessary. Request full + // update if a new session file was opened. + if (viewer.checkRecordingStatus()) + fullUpdateNeeded = true; + + // Defer framebuffer update request if necessary. But wake up + // immediately on keyboard or mouse event. Also, don't sleep + // if there is some data to receive, or if the last update + // included a PointerPos message. + if (viewer.deferUpdateRequests > 0 && rfb.available() == 0 + && !cursorPosReceived) { + synchronized (rfb) { + try { + rfb.wait(viewer.deferUpdateRequests); + } catch (InterruptedException e) { + } + } + } + + viewer.autoSelectEncodings(); + + // Before requesting framebuffer update, check if the pixel + // format should be changed. +/* + if (viewer.options.eightBitColors != (bytesPixel == 1)) { + // Pixel format should be changed. + setPixelFormat(); + fullUpdateNeeded = true; + } +*/ + // Request framebuffer update if needed. + int w = rfb.framebufferWidth; + int h = rfb.framebufferHeight; + rfb.writeFramebufferUpdateRequest(0, 0, w, h, !fullUpdateNeeded); + + break; + + case RfbProto.SetColourMapEntries: + throw new Exception("Can't handle SetColourMapEntries message"); + + case RfbProto.Bell: + Toolkit.getDefaultToolkit().beep(); + break; + + case RfbProto.ServerCutText: + String s = rfb.readServerCutText(); + viewer.clipboard.setCutText(s); + break; + + default: + throw new Exception("Unknown RFB message type " + msgType); + } + + int bufSize = (int)(rfb.getNumBytesRead() - numBytesRead); +// System.out.println("bufSize="+bufSize); +// rfb.bufResetSend(bufSize); + + + + if(rfb.createBimgFlag){ +// bimg = createBufferedImage(rawPixelsImage); + bimg = createBufferedImage(memImage); + //bimg(BufferedImage) -> rfb.pngBytes(byte[]) + rfb.createPngBytes(bimg); + rfb.sendPngImage(); + rfb.createBimgFlag = false; + } + + +/* + boolean result = false; + try{ + result = ImageIO.write(bimg, "png", new File("sample.png")); + }catch(Exception e){ + e.printStackTrace(); + result = false; + } +*/ + } + } + + // + // Handle a raw rectangle. The second form with paint==false is used + // by the Hextile decoder for raw-encoded tiles. + // + + void handleRawRect(int x, int y, int w, int h) throws IOException { + handleRawRect(x, y, w, h, true); + } + + void handleRawRect(int x, int y, int w, int h, boolean paint) + throws IOException { + + if (bytesPixel == 1) { + for (int dy = y; dy < y + h; dy++) { + rfb.readFully(pixels8, dy * rfb.framebufferWidth + x, w); + if (rfb.rec != null) { + rfb.rec.write(pixels8, dy * rfb.framebufferWidth + x, w); + } + } + } else { + byte[] buf = new byte[w * 4]; + int i, offset; + for (int dy = y; dy < y + h; dy++) { + rfb.readFully(buf); + if (rfb.rec != null) { + rfb.rec.write(buf); + } + + offset = dy * rfb.framebufferWidth + x; + for (i = 0; i < w; i++) { + pixels24[offset + i] = (buf[i * 4 + 2] & 0xFF) << 16 | + (buf[i * 4 + 1] & 0xFF) << 8 | + (buf[i * 4] & 0xFF); + } + + } + } + + handleUpdatedPixels(x, y, w, h); +// if (paint) scheduleRepaint(x, y, w, h); + + } + + // + // Handle a CopyRect rectangle. + // + + void handleCopyRect(int x, int y, int w, int h) throws IOException { + + rfb.readCopyRect(); + memGraphics.copyArea(rfb.copyRectSrcX, rfb.copyRectSrcY, w, h, x + - rfb.copyRectSrcX, y - rfb.copyRectSrcY); + + scheduleRepaint(x, y, w, h); + } + + // + // Handle an RRE-encoded rectangle. + // + + void handleRRERect(int x, int y, int w, int h) throws IOException { + + int nSubrects = rfb.readU32(); + + byte[] bg_buf = new byte[bytesPixel]; + rfb.readFully(bg_buf); + Color pixel; + if (bytesPixel == 1) { + pixel = colors[bg_buf[0] & 0xFF]; + } else { + pixel = new Color(bg_buf[2] & 0xFF, bg_buf[1] & 0xFF, + bg_buf[0] & 0xFF); + } + memGraphics.setColor(pixel); + memGraphics.fillRect(x, y, w, h); + + byte[] buf = new byte[nSubrects * (bytesPixel + 8)]; + rfb.readFully(buf); + DataInputStream ds = new DataInputStream(new ByteArrayInputStream(buf)); + + if (rfb.rec != null) { + rfb.rec.writeIntBE(nSubrects); + rfb.rec.write(bg_buf); + rfb.rec.write(buf); + } + + int sx, sy, sw, sh; + + for (int j = 0; j < nSubrects; j++) { + if (bytesPixel == 1) { + pixel = colors[ds.readUnsignedByte()]; + } else { + ds.skip(4); + pixel = new Color(buf[j * 12 + 2] & 0xFF, + buf[j * 12 + 1] & 0xFF, buf[j * 12] & 0xFF); + } + sx = x + ds.readUnsignedShort(); + sy = y + ds.readUnsignedShort(); + sw = ds.readUnsignedShort(); + sh = ds.readUnsignedShort(); + + memGraphics.setColor(pixel); + memGraphics.fillRect(sx, sy, sw, sh); + } + + scheduleRepaint(x, y, w, h); + } + + // + // Handle a CoRRE-encoded rectangle. + // + + void handleCoRRERect(int x, int y, int w, int h) throws IOException { + int nSubrects = rfb.readU32(); + + byte[] bg_buf = new byte[bytesPixel]; + rfb.readFully(bg_buf); + Color pixel; + if (bytesPixel == 1) { + pixel = colors[bg_buf[0] & 0xFF]; + } else { + pixel = new Color(bg_buf[2] & 0xFF, bg_buf[1] & 0xFF, + bg_buf[0] & 0xFF); + } + memGraphics.setColor(pixel); + memGraphics.fillRect(x, y, w, h); + + byte[] buf = new byte[nSubrects * (bytesPixel + 4)]; + rfb.readFully(buf); + + if (rfb.rec != null) { + rfb.rec.writeIntBE(nSubrects); + rfb.rec.write(bg_buf); + rfb.rec.write(buf); + } + + int sx, sy, sw, sh; + int i = 0; + + for (int j = 0; j < nSubrects; j++) { + if (bytesPixel == 1) { + pixel = colors[buf[i++] & 0xFF]; + } else { + pixel = new Color(buf[i + 2] & 0xFF, buf[i + 1] & 0xFF, + buf[i] & 0xFF); + i += 4; + } + sx = x + (buf[i++] & 0xFF); + sy = y + (buf[i++] & 0xFF); + sw = buf[i++] & 0xFF; + sh = buf[i++] & 0xFF; + + memGraphics.setColor(pixel); + memGraphics.fillRect(sx, sy, sw, sh); + } + + scheduleRepaint(x, y, w, h); + } + + // + // Handle a Hextile-encoded rectangle. + // + + // These colors should be kept between handleHextileSubrect() calls. + private Color hextile_bg, hextile_fg; + + void handleHextileRect(int x, int y, int w, int h) throws IOException { + + hextile_bg = new Color(0); + hextile_fg = new Color(0); + + for (int ty = y; ty < y + h; ty += 16) { + int th = 16; + if (y + h - ty < 16) + th = y + h - ty; + + for (int tx = x; tx < x + w; tx += 16) { + int tw = 16; + if (x + w - tx < 16) + tw = x + w - tx; + + handleHextileSubrect(tx, ty, tw, th); + } + + // Finished with a row of tiles, now let's show it. + scheduleRepaint(x, y, w, h); + } + } + + // + // Handle one tile in the Hextile-encoded data. + // + + void handleHextileSubrect(int tx, int ty, int tw, int th) + throws IOException { + + int subencoding = rfb.readU8(); + if (rfb.rec != null) { + rfb.rec.writeByte(subencoding); + } + + // Is it a raw-encoded sub-rectangle? + if ((subencoding & rfb.HextileRaw) != 0) { + handleRawRect(tx, ty, tw, th, false); + return; + } + + // Read and draw the background if specified. + byte[] cbuf = new byte[bytesPixel]; + if ((subencoding & rfb.HextileBackgroundSpecified) != 0) { + rfb.readFully(cbuf); + if (bytesPixel == 1) { + hextile_bg = colors[cbuf[0] & 0xFF]; + } else { + hextile_bg = new Color(cbuf[2] & 0xFF, cbuf[1] & 0xFF, + cbuf[0] & 0xFF); + } + if (rfb.rec != null) { + rfb.rec.write(cbuf); + } + } + memGraphics.setColor(hextile_bg); + memGraphics.fillRect(tx, ty, tw, th); + + // Read the foreground color if specified. + if ((subencoding & rfb.HextileForegroundSpecified) != 0) { + rfb.readFully(cbuf); + if (bytesPixel == 1) { + hextile_fg = colors[cbuf[0] & 0xFF]; + } else { + hextile_fg = new Color(cbuf[2] & 0xFF, cbuf[1] & 0xFF, + cbuf[0] & 0xFF); + } + if (rfb.rec != null) { + rfb.rec.write(cbuf); + } + } + + // Done with this tile if there is no sub-rectangles. + if ((subencoding & rfb.HextileAnySubrects) == 0) + return; + + int nSubrects = rfb.readU8(); + int bufsize = nSubrects * 2; + if ((subencoding & rfb.HextileSubrectsColoured) != 0) { + bufsize += nSubrects * bytesPixel; + } + byte[] buf = new byte[bufsize]; + rfb.readFully(buf); + if (rfb.rec != null) { + rfb.rec.writeByte(nSubrects); + rfb.rec.write(buf); + } + + int b1, b2, sx, sy, sw, sh; + int i = 0; + + if ((subencoding & rfb.HextileSubrectsColoured) == 0) { + + // Sub-rectangles are all of the same color. + memGraphics.setColor(hextile_fg); + for (int j = 0; j < nSubrects; j++) { + b1 = buf[i++] & 0xFF; + b2 = buf[i++] & 0xFF; + sx = tx + (b1 >> 4); + sy = ty + (b1 & 0xf); + sw = (b2 >> 4) + 1; + sh = (b2 & 0xf) + 1; + memGraphics.fillRect(sx, sy, sw, sh); + } + } else if (bytesPixel == 1) { + + // BGR233 (8-bit color) version for colored sub-rectangles. + for (int j = 0; j < nSubrects; j++) { + hextile_fg = colors[buf[i++] & 0xFF]; + b1 = buf[i++] & 0xFF; + b2 = buf[i++] & 0xFF; + sx = tx + (b1 >> 4); + sy = ty + (b1 & 0xf); + sw = (b2 >> 4) + 1; + sh = (b2 & 0xf) + 1; + memGraphics.setColor(hextile_fg); + memGraphics.fillRect(sx, sy, sw, sh); + } + + } else { + + // Full-color (24-bit) version for colored sub-rectangles. + for (int j = 0; j < nSubrects; j++) { + hextile_fg = new Color(buf[i + 2] & 0xFF, buf[i + 1] & 0xFF, + buf[i] & 0xFF); + i += 4; + b1 = buf[i++] & 0xFF; + b2 = buf[i++] & 0xFF; + sx = tx + (b1 >> 4); + sy = ty + (b1 & 0xf); + sw = (b2 >> 4) + 1; + sh = (b2 & 0xf) + 1; + memGraphics.setColor(hextile_fg); + memGraphics.fillRect(sx, sy, sw, sh); + } + + } + } + + // + // Handle a ZRLE-encoded rectangle. + // + // FIXME: Currently, session recording is not fully supported for ZRLE. + // + + void handleZRLERect(int x, int y, int w, int h) throws Exception { + if (rfb.updateRectEncoding==RfbProto.EncodingZRLEE) zrleInStream = null; + + if (zrleInStream == null) + zrleInStream = new ZlibInStream(); + + int nBytes = rfb.readU32(); + if (nBytes > 64 * 1024 * 1024) + throw new Exception("ZRLE decoder: illegal compressed data size"); + + if (zrleBuf == null || zrleBufLen < nBytes) { + zrleBufLen = nBytes + 4096; + zrleBuf = new byte[zrleBufLen]; + } + + // FIXME: Do not wait for all the data before decompression. + rfb.readFully(zrleBuf, 0, nBytes); + + if (rfb.rec != null) { + if (rfb.recordFromBeginning) { + rfb.rec.writeIntBE(nBytes); + rfb.rec.write(zrleBuf, 0, nBytes); + } else if (!zrleRecWarningShown) { + System.out.println("Warning: ZRLE session can be recorded" + + " only from the beginning"); + System.out.println("Warning: Recorded file may be corrupted"); + zrleRecWarningShown = true; + } + + } + + zrleInStream.setUnderlying(new MemInStream(zrleBuf, 0, nBytes), nBytes); + + for (int ty = y; ty < y + h; ty += 64) { + + int th = Math.min(y + h - ty, 64); + + for (int tx = x; tx < x + w; tx += 64) { + + int tw = Math.min(x + w - tx, 64); + + int mode = zrleInStream.readU8(); + boolean rle = (mode & 128) != 0; + int palSize = mode & 127; + int[] palette = new int[128]; + + readZrlePalette(palette, palSize); + + if (palSize == 1) { + int pix = palette[0]; + Color c = (bytesPixel == 1) ? colors[pix] : new Color( + 0xFF000000 | pix); + memGraphics.setColor(c); + memGraphics.fillRect(tx, ty, tw, th); + continue; + } + + if (!rle) { + if (palSize == 0) { + readZrleRawPixels(tw, th); + } else { + readZrlePackedPixels(tw, th, palette, palSize); + } + } else { + if (palSize == 0) { + readZrlePlainRLEPixels(tw, th); + } else { + readZrlePackedRLEPixels(tw, th, palette); + } + } + handleUpdatedZrleTile(tx, ty, tw, th); + } + } + + zrleInStream.reset(); + + scheduleRepaint(x, y, w, h); + } + + int readPixel(InStream is) throws Exception { + int pix; + + if (bytesPixel == 1) { + + pix = is.readU8(); + } else { + int p1 = is.readU8(); + int p2 = is.readU8(); + int p3 = is.readU8(); + pix = (p3 & 0xFF) << 16 | (p2 & 0xFF) << 8 | (p1 & 0xFF); + } + return pix; + } + + void readPixels(InStream is, int[] dst, int count) throws Exception { + int pix; + if (bytesPixel == 1) { + byte[] buf = new byte[count]; + is.readBytes(buf, 0, count); + for (int i = 0; i < count; i++) { + dst[i] = (int) buf[i] & 0xFF; + } + } else { + byte[] buf = new byte[count * 3]; + is.readBytes(buf, 0, count * 3); + for (int i = 0; i < count; i++) { + dst[i] = ((buf[i * 3 + 2] & 0xFF) << 16 + | (buf[i * 3 + 1] & 0xFF) << 8 | (buf[i * 3] & 0xFF)); + } + } + } + + void readZrlePalette(int[] palette, int palSize) throws Exception { + readPixels(zrleInStream, palette, palSize); + } + + void readZrleRawPixels(int tw, int th) throws Exception { + if (bytesPixel == 1) { + zrleInStream.readBytes(zrleTilePixels8, 0, tw * th); + } else { + readPixels(zrleInStream, zrleTilePixels24, tw * th); // / + } + } + + void readZrlePackedPixels(int tw, int th, int[] palette, int palSize) + throws Exception { + + int bppp = ((palSize > 16) ? 8 : ((palSize > 4) ? 4 + : ((palSize > 2) ? 2 : 1))); + int ptr = 0; + + for (int i = 0; i < th; i++) { + int eol = ptr + tw; + int b = 0; + int nbits = 0; + + while (ptr < eol) { + if (nbits == 0) { + b = zrleInStream.readU8(); + nbits = 8; + } + nbits -= bppp; + int index = (b >> nbits) & ((1 << bppp) - 1) & 127; + if (bytesPixel == 1) { + zrleTilePixels8[ptr++] = (byte) palette[index]; + } else { + zrleTilePixels24[ptr++] = palette[index]; + } + } + } + } + + void readZrlePlainRLEPixels(int tw, int th) throws Exception { + int ptr = 0; + int end = ptr + tw * th; + while (ptr < end) { + int pix = readPixel(zrleInStream); + int len = 1; + int b; + do { + b = zrleInStream.readU8(); + len += b; + } while (b == 255); + + if (!(len <= end - ptr)) + throw new Exception("ZRLE decoder: assertion failed" + + " (len <= end-ptr)"); + + if (bytesPixel == 1) { + while (len-- > 0) + zrleTilePixels8[ptr++] = (byte) pix; + } else { + while (len-- > 0) + zrleTilePixels24[ptr++] = pix; + } + } + } + + void readZrlePackedRLEPixels(int tw, int th, int[] palette) + throws Exception { + + int ptr = 0; + int end = ptr + tw * th; + while (ptr < end) { + int index = zrleInStream.readU8(); + int len = 1; + if ((index & 128) != 0) { + int b; + do { + b = zrleInStream.readU8(); + len += b; + } while (b == 255); + + if (!(len <= end - ptr)) + throw new Exception("ZRLE decoder: assertion failed" + + " (len <= end - ptr)"); + } + + index &= 127; + int pix = palette[index]; + + if (bytesPixel == 1) { + while (len-- > 0) + zrleTilePixels8[ptr++] = (byte) pix; + } else { + while (len-- > 0) + zrleTilePixels24[ptr++] = pix; + } + } + } + + // + // Copy pixels from zrleTilePixels8 or zrleTilePixels24, then update. + // + + void handleUpdatedZrleTile(int x, int y, int w, int h) { + Object src, dst; + if (bytesPixel == 1) { + src = zrleTilePixels8; + dst = pixels8; + } else { + src = zrleTilePixels24; + dst = pixels24; + } + int offsetSrc = 0; + int offsetDst = (y * rfb.framebufferWidth + x); + for (int j = 0; j < h; j++) { + System.arraycopy(src, offsetSrc, dst, offsetDst, w); + offsetSrc += w; + offsetDst += rfb.framebufferWidth; + } + handleUpdatedPixels(x, y, w, h); + } + + // + // Handle a Zlib-encoded rectangle. + // + + void handleZlibRect(int x, int y, int w, int h) throws Exception { + + int nBytes = rfb.readU32(); + + if (zlibBuf == null || zlibBufLen < nBytes) { + zlibBufLen = nBytes * 2; + zlibBuf = new byte[zlibBufLen]; + } + + rfb.readFully(zlibBuf, 0, nBytes); + + if (rfb.rec != null && rfb.recordFromBeginning) { + rfb.rec.writeIntBE(nBytes); + rfb.rec.write(zlibBuf, 0, nBytes); + } + + if (zlibInflater == null) { + zlibInflater = new Inflater(); + } + zlibInflater.setInput(zlibBuf, 0, nBytes); + + if (bytesPixel == 1) { + for (int dy = y; dy < y + h; dy++) { + zlibInflater.inflate(pixels8, dy * rfb.framebufferWidth + x, w); + if (rfb.rec != null && !rfb.recordFromBeginning) + rfb.rec.write(pixels8, dy * rfb.framebufferWidth + x, w); + } + } else { + byte[] buf = new byte[w * 4]; + int i, offset; + for (int dy = y; dy < y + h; dy++) { + zlibInflater.inflate(buf); + offset = dy * rfb.framebufferWidth + x; + for (i = 0; i < w; i++) { + pixels24[offset + i] = (buf[i * 4 + 2] & 0xFF) << 16 + | (buf[i * 4 + 1] & 0xFF) << 8 + | (buf[i * 4] & 0xFF); + } + if (rfb.rec != null && !rfb.recordFromBeginning) + rfb.rec.write(buf); + } + } + + handleUpdatedPixels(x, y, w, h); + scheduleRepaint(x, y, w, h); + } + + // + // Handle a Tight-encoded rectangle. + // + + void handleTightRect(int x, int y, int w, int h) throws Exception { + + int comp_ctl = rfb.readU8(); + if (rfb.rec != null) { + if (rfb.recordFromBeginning || comp_ctl == (rfb.TightFill << 4) + || comp_ctl == (rfb.TightJpeg << 4)) { + // Send data exactly as received. + rfb.rec.writeByte(comp_ctl); + } else { + // Tell the decoder to flush each of the four zlib streams. + rfb.rec.writeByte(comp_ctl | 0x0F); + } + } + + // Flush zlib streams if we are told by the server to do so. + for (int stream_id = 0; stream_id < 4; stream_id++) { + if ((comp_ctl & 1) != 0 && tightInflaters[stream_id] != null) { + tightInflaters[stream_id] = null; + } + comp_ctl >>= 1; + } + + // Check correctness of subencoding value. + if (comp_ctl > rfb.TightMaxSubencoding) { + throw new Exception("Incorrect tight subencoding: " + comp_ctl); + } + + // Handle solid-color rectangles. + if (comp_ctl == rfb.TightFill) { + + if (bytesPixel == 1) { + int idx = rfb.readU8(); + memGraphics.setColor(colors[idx]); + if (rfb.rec != null) { + rfb.rec.writeByte(idx); + } + } else { + byte[] buf = new byte[3]; + rfb.readFully(buf); + if (rfb.rec != null) { + rfb.rec.write(buf); + } + Color bg = new Color(0xFF000000 | (buf[0] & 0xFF) << 16 + | (buf[1] & 0xFF) << 8 | (buf[2] & 0xFF)); + memGraphics.setColor(bg); + } + memGraphics.fillRect(x, y, w, h); + scheduleRepaint(x, y, w, h); + return; + + } + + if (comp_ctl == rfb.TightJpeg) { + + statNumRectsTightJPEG++; + + // Read JPEG data. + byte[] jpegData = new byte[rfb.readCompactLen()]; + rfb.readFully(jpegData); + if (rfb.rec != null) { + if (!rfb.recordFromBeginning) { + rfb.recordCompactLen(jpegData.length); + } + rfb.rec.write(jpegData); + } + + // Create an Image object from the JPEG data. + Image jpegImage = Toolkit.getDefaultToolkit().createImage(jpegData); + + // Remember the rectangle where the image should be drawn. + jpegRect = new Rectangle(x, y, w, h); + + // Let the imageUpdate() method do the actual drawing, here just + // wait until the image is fully loaded and drawn. + synchronized (jpegRect) { + Toolkit.getDefaultToolkit().prepareImage(jpegImage, -1, -1, + this); + try { + // Wait no longer than three seconds. + jpegRect.wait(3000); + } catch (InterruptedException e) { + throw new Exception("Interrupted while decoding JPEG image"); + } + } + + // Done, jpegRect is not needed any more. + jpegRect = null; + return; + + } + + // Read filter id and parameters. + int numColors = 0, rowSize = w; + byte[] palette8 = new byte[2]; + int[] palette24 = new int[256]; + boolean useGradient = false; + if ((comp_ctl & rfb.TightExplicitFilter) != 0) { + int filter_id = rfb.readU8(); + if (rfb.rec != null) { + rfb.rec.writeByte(filter_id); + } + if (filter_id == rfb.TightFilterPalette) { + numColors = rfb.readU8() + 1; + if (rfb.rec != null) { + rfb.rec.writeByte(numColors - 1); + } + if (bytesPixel == 1) { + if (numColors != 2) { + throw new Exception("Incorrect tight palette size: " + + numColors); + } + rfb.readFully(palette8); + if (rfb.rec != null) { + rfb.rec.write(palette8); + } + } else { + byte[] buf = new byte[numColors * 3]; + rfb.readFully(buf); + if (rfb.rec != null) { + rfb.rec.write(buf); + } + for (int i = 0; i < numColors; i++) { + palette24[i] = ((buf[i * 3] & 0xFF) << 16 + | (buf[i * 3 + 1] & 0xFF) << 8 | (buf[i * 3 + 2] & 0xFF)); + } + } + if (numColors == 2) + rowSize = (w + 7) / 8; + } else if (filter_id == rfb.TightFilterGradient) { + useGradient = true; + } else if (filter_id != rfb.TightFilterCopy) { + throw new Exception("Incorrect tight filter id: " + filter_id); + } + } + if (numColors == 0 && bytesPixel == 4) + rowSize *= 3; + + // Read, optionally uncompress and decode data. + int dataSize = h * rowSize; + if (dataSize < rfb.TightMinToCompress) { + // Data size is small - not compressed with zlib. + if (numColors != 0) { + // Indexed colors. + byte[] indexedData = new byte[dataSize]; + rfb.readFully(indexedData); + if (rfb.rec != null) { + rfb.rec.write(indexedData); + } + if (numColors == 2) { + // Two colors. + if (bytesPixel == 1) { + decodeMonoData(x, y, w, h, indexedData, palette8); + } else { + decodeMonoData(x, y, w, h, indexedData, palette24); + } + } else { + // 3..255 colors (assuming bytesPixel == 4). + int i = 0; + for (int dy = y; dy < y + h; dy++) { + for (int dx = x; dx < x + w; dx++) { + pixels24[dy * rfb.framebufferWidth + dx] = palette24[indexedData[i++] & 0xFF]; + } + } + } + } else if (useGradient) { + // "Gradient"-processed data + byte[] buf = new byte[w * h * 3]; + rfb.readFully(buf); + if (rfb.rec != null) { + rfb.rec.write(buf); + } + decodeGradientData(x, y, w, h, buf); + } else { + // Raw truecolor data. + if (bytesPixel == 1) { + for (int dy = y; dy < y + h; dy++) { + rfb.readFully(pixels8, dy * rfb.framebufferWidth + x, w); + if (rfb.rec != null) { + rfb.rec.write(pixels8, dy * rfb.framebufferWidth + + x, w); + } + } + } else { + byte[] buf = new byte[w * 3]; + int i, offset; + for (int dy = y; dy < y + h; dy++) { + rfb.readFully(buf); + if (rfb.rec != null) { + rfb.rec.write(buf); + } + offset = dy * rfb.framebufferWidth + x; + for (i = 0; i < w; i++) { + pixels24[offset + i] = (buf[i * 3] & 0xFF) << 16 + | (buf[i * 3 + 1] & 0xFF) << 8 + | (buf[i * 3 + 2] & 0xFF); + } + } + } + } + } else { + // Data was compressed with zlib. + int zlibDataLen = rfb.readCompactLen(); + byte[] zlibData = new byte[zlibDataLen]; + rfb.readFully(zlibData); + if (rfb.rec != null && rfb.recordFromBeginning) { + rfb.rec.write(zlibData); + } + int stream_id = comp_ctl & 0x03; + if (tightInflaters[stream_id] == null) { + tightInflaters[stream_id] = new Inflater(); + } + Inflater myInflater = tightInflaters[stream_id]; + myInflater.setInput(zlibData); + byte[] buf = new byte[dataSize]; + myInflater.inflate(buf); + if (rfb.rec != null && !rfb.recordFromBeginning) { + rfb.recordCompressedData(buf); + } + + if (numColors != 0) { + // Indexed colors. + if (numColors == 2) { + // Two colors. + if (bytesPixel == 1) { + decodeMonoData(x, y, w, h, buf, palette8); + } else { + decodeMonoData(x, y, w, h, buf, palette24); + } + } else { + // More than two colors (assuming bytesPixel == 4). + int i = 0; + for (int dy = y; dy < y + h; dy++) { + for (int dx = x; dx < x + w; dx++) { + pixels24[dy * rfb.framebufferWidth + dx] = palette24[buf[i++] & 0xFF]; + } + } + } + } else if (useGradient) { + // Compressed "Gradient"-filtered data (assuming bytesPixel == + // 4). + decodeGradientData(x, y, w, h, buf); + } else { + // Compressed truecolor data. + if (bytesPixel == 1) { + int destOffset = y * rfb.framebufferWidth + x; + for (int dy = 0; dy < h; dy++) { + System.arraycopy(buf, dy * w, pixels8, destOffset, w); + destOffset += rfb.framebufferWidth; + } + } else { + int srcOffset = 0; + int destOffset, i; + for (int dy = 0; dy < h; dy++) { + myInflater.inflate(buf); + destOffset = (y + dy) * rfb.framebufferWidth + x; + for (i = 0; i < w; i++) { + pixels24[destOffset + i] = (buf[srcOffset] & 0xFF) << 16 + | (buf[srcOffset + 1] & 0xFF) << 8 + | (buf[srcOffset + 2] & 0xFF); + srcOffset += 3; + } + } + } + } + } + + handleUpdatedPixels(x, y, w, h); + scheduleRepaint(x, y, w, h); + } + + // + // Decode 1bpp-encoded bi-color rectangle (8-bit and 24-bit versions). + // + + void decodeMonoData(int x, int y, int w, int h, byte[] src, byte[] palette) { + + int dx, dy, n; + int i = y * rfb.framebufferWidth + x; + int rowBytes = (w + 7) / 8; + byte b; + + for (dy = 0; dy < h; dy++) { + for (dx = 0; dx < w / 8; dx++) { + b = src[dy * rowBytes + dx]; + for (n = 7; n >= 0; n--) + pixels8[i++] = palette[b >> n & 1]; + } + for (n = 7; n >= 8 - w % 8; n--) { + pixels8[i++] = palette[src[dy * rowBytes + dx] >> n & 1]; + } + i += (rfb.framebufferWidth - w); + } + } + + void decodeMonoData(int x, int y, int w, int h, byte[] src, int[] palette) { + + int dx, dy, n; + int i = y * rfb.framebufferWidth + x; + int rowBytes = (w + 7) / 8; + byte b; + + for (dy = 0; dy < h; dy++) { + for (dx = 0; dx < w / 8; dx++) { + b = src[dy * rowBytes + dx]; + for (n = 7; n >= 0; n--) + pixels24[i++] = palette[b >> n & 1]; + } + for (n = 7; n >= 8 - w % 8; n--) { + pixels24[i++] = palette[src[dy * rowBytes + dx] >> n & 1]; + } + i += (rfb.framebufferWidth - w); + } + } + + // + // Decode data processed with the "Gradient" filter. + // + + void decodeGradientData(int x, int y, int w, int h, byte[] buf) { + + int dx, dy, c; + byte[] prevRow = new byte[w * 3]; + byte[] thisRow = new byte[w * 3]; + byte[] pix = new byte[3]; + int[] est = new int[3]; + + int offset = y * rfb.framebufferWidth + x; + + for (dy = 0; dy < h; dy++) { + + /* First pixel in a row */ + for (c = 0; c < 3; c++) { + pix[c] = (byte) (prevRow[c] + buf[dy * w * 3 + c]); + thisRow[c] = pix[c]; + } + pixels24[offset++] = (pix[0] & 0xFF) << 16 | (pix[1] & 0xFF) << 8 + | (pix[2] & 0xFF); + + /* Remaining pixels of a row */ + for (dx = 1; dx < w; dx++) { + for (c = 0; c < 3; c++) { + est[c] = ((prevRow[dx * 3 + c] & 0xFF) + (pix[c] & 0xFF) - (prevRow[(dx - 1) + * 3 + c] & 0xFF)); + if (est[c] > 0xFF) { + est[c] = 0xFF; + } else if (est[c] < 0x00) { + est[c] = 0x00; + } + pix[c] = (byte) (est[c] + buf[(dy * w + dx) * 3 + c]); + thisRow[dx * 3 + c] = pix[c]; + } + pixels24[offset++] = (pix[0] & 0xFF) << 16 + | (pix[1] & 0xFF) << 8 | (pix[2] & 0xFF); + } + + System.arraycopy(thisRow, 0, prevRow, 0, w * 3); + offset += (rfb.framebufferWidth - w); + } + } + + // + // Display newly updated area of pixels. + // + + void handleUpdatedPixels(int x, int y, int w, int h) { + + // Draw updated pixels of the off-screen image. + + pixelsSource.newPixels(x, y, w, h); + memGraphics.setClip(x, y, w, h); + memGraphics.drawImage(rawPixelsImage, 0, 0, null); + memGraphics.setClip(0, 0, rfb.framebufferWidth, rfb.framebufferHeight); + + } + + // + // Tell JVM to repaint specified desktop area. + // + + void scheduleRepaint(int x, int y, int w, int h) { + // Request repaint, deferred if necessary. + if (rfb.framebufferWidth == scaledWidth) { + repaint(viewer.deferScreenUpdates, x, y, w, h); + } else { + int sx = x * scalingFactor / 100; + int sy = y * scalingFactor / 100; + int sw = ((x + w) * scalingFactor + 49) / 100 - sx + 1; + int sh = ((y + h) * scalingFactor + 49) / 100 - sy + 1; + repaint(viewer.deferScreenUpdates, sx, sy, sw, sh); + } + } + + // + // Handle events. + // + + public void keyPressed(KeyEvent evt) { + processLocalKeyEvent(evt); + } + + public void keyReleased(KeyEvent evt) { + processLocalKeyEvent(evt); + } + + public void keyTyped(KeyEvent evt) { + evt.consume(); + } + + public void mousePressed(MouseEvent evt) { + processLocalMouseEvent(evt, false); + } + + public void mouseReleased(MouseEvent evt) { + processLocalMouseEvent(evt, false); + } + + public void mouseMoved(MouseEvent evt) { + processLocalMouseEvent(evt, true); + } + + public void mouseDragged(MouseEvent evt) { + processLocalMouseEvent(evt, true); + } + + public void processLocalKeyEvent(KeyEvent evt) { + if (viewer.rfb != null && rfb.inNormalProtocol) { + if (!inputEnabled) { + if ((evt.getKeyChar() == 'r' || evt.getKeyChar() == 'R') + && evt.getID() == KeyEvent.KEY_PRESSED) { + // Request screen update. + try { + rfb.writeFramebufferUpdateRequest(0, 0, + rfb.framebufferWidth, rfb.framebufferHeight, + false); + } catch (IOException e) { + e.printStackTrace(); + } + } + } else { + // Input enabled. + synchronized (rfb) { + try { + rfb.writeKeyEvent(evt); + } catch (Exception e) { + e.printStackTrace(); + } + rfb.notify(); + } + } + } + // Don't ever pass keyboard events to AWT for default processing. + // Otherwise, pressing Tab would switch focus to ButtonPanel etc. + evt.consume(); + } + + public void processLocalMouseEvent(MouseEvent evt, boolean moved) { + if (viewer.rfb != null && rfb.inNormalProtocol) { + if (moved) { + softCursorMove(evt.getX(), evt.getY()); + } + if (rfb.framebufferWidth != scaledWidth) { + int sx = (evt.getX() * 100 + scalingFactor / 2) / scalingFactor; + int sy = (evt.getY() * 100 + scalingFactor / 2) / scalingFactor; + evt.translatePoint(sx - evt.getX(), sy - evt.getY()); + } + synchronized (rfb) { + try { + rfb.writePointerEvent(evt); + } catch (Exception e) { + e.printStackTrace(); + } + rfb.notify(); + } + } + } + + // + // Ignored events. + // + + public void mouseClicked(MouseEvent evt) { + } + + public void mouseEntered(MouseEvent evt) { + } + + public void mouseExited(MouseEvent evt) { + } + + // + // Reset update statistics. + // + + void resetStats() { + statStartTime = System.currentTimeMillis(); + statNumUpdates = 0; + statNumTotalRects = 0; + statNumPixelRects = 0; + statNumRectsTight = 0; + statNumRectsTightJPEG = 0; + statNumRectsZRLE = 0; + statNumRectsHextile = 0; + statNumRectsRaw = 0; + statNumRectsCopy = 0; + statNumBytesEncoded = 0; + statNumBytesDecoded = 0; + } + + // //////////////////////////////////////////////////////////////// + // + // Handle cursor shape updates (XCursor and RichCursor encodings). + // + + boolean showSoftCursor = false; + + MemoryImageSource softCursorSource; + Image softCursor; + + int cursorX = 0, cursorY = 0; + int cursorWidth, cursorHeight; + int origCursorWidth, origCursorHeight; + int hotX, hotY; + int origHotX, origHotY; + + // + // Handle cursor shape update (XCursor and RichCursor encodings). + // + + synchronized void handleCursorShapeUpdate(int encodingType, int xhot, + int yhot, int width, int height) throws IOException { + + softCursorFree(); + + if (width * height == 0) + return; + + // Ignore cursor shape data if requested by user. + if (viewer.options.ignoreCursorUpdates) { + int bytesPerRow = (width + 7) / 8; + int bytesMaskData = bytesPerRow * height; + + if (encodingType == rfb.EncodingXCursor) { + rfb.skipBytes(6 + bytesMaskData * 2); + } else { + // rfb.EncodingRichCursor + rfb.skipBytes(width * height * bytesPixel + bytesMaskData); + } + return; + } + + // Decode cursor pixel data. + softCursorSource = decodeCursorShape(encodingType, width, height); + + // Set original (non-scaled) cursor dimensions. + origCursorWidth = width; + origCursorHeight = height; + origHotX = xhot; + origHotY = yhot; + + // Create off-screen cursor image. + createSoftCursor(); + + // Show the cursor. + showSoftCursor = true; + repaint(viewer.deferCursorUpdates, cursorX - hotX, cursorY - hotY, + cursorWidth, cursorHeight); + } + + // + // decodeCursorShape(). Decode cursor pixel data and return + // corresponding MemoryImageSource instance. + // + + synchronized MemoryImageSource decodeCursorShape(int encodingType, + int width, int height) throws IOException { + + int bytesPerRow = (width + 7) / 8; + int bytesMaskData = bytesPerRow * height; + + int[] softCursorPixels = new int[width * height]; + + if (encodingType == rfb.EncodingXCursor) { + + // Read foreground and background colors of the cursor. + byte[] rgb = new byte[6]; + rfb.readFully(rgb); + int[] colors = { + (0xFF000000 | (rgb[3] & 0xFF) << 16 | (rgb[4] & 0xFF) << 8 | (rgb[5] & 0xFF)), + (0xFF000000 | (rgb[0] & 0xFF) << 16 | (rgb[1] & 0xFF) << 8 | (rgb[2] & 0xFF)) }; + + // Read pixel and mask data. + byte[] pixBuf = new byte[bytesMaskData]; + rfb.readFully(pixBuf); + byte[] maskBuf = new byte[bytesMaskData]; + rfb.readFully(maskBuf); + + // Decode pixel data into softCursorPixels[]. + byte pixByte, maskByte; + int x, y, n, result; + int i = 0; + for (y = 0; y < height; y++) { + for (x = 0; x < width / 8; x++) { + pixByte = pixBuf[y * bytesPerRow + x]; + maskByte = maskBuf[y * bytesPerRow + x]; + for (n = 7; n >= 0; n--) { + if ((maskByte >> n & 1) != 0) { + result = colors[pixByte >> n & 1]; + } else { + result = 0; // Transparent pixel + } + softCursorPixels[i++] = result; + } + } + for (n = 7; n >= 8 - width % 8; n--) { + if ((maskBuf[y * bytesPerRow + x] >> n & 1) != 0) { + result = colors[pixBuf[y * bytesPerRow + x] >> n & 1]; + } else { + result = 0; // Transparent pixel + } + softCursorPixels[i++] = result; + } + } + + } else { + // encodingType == rfb.EncodingRichCursor + + // Read pixel and mask data. + byte[] pixBuf = new byte[width * height * bytesPixel]; + rfb.readFully(pixBuf); + byte[] maskBuf = new byte[bytesMaskData]; + rfb.readFully(maskBuf); + + // Decode pixel data into softCursorPixels[]. + byte pixByte, maskByte; + int x, y, n, result; + int i = 0; + for (y = 0; y < height; y++) { + for (x = 0; x < width / 8; x++) { + maskByte = maskBuf[y * bytesPerRow + x]; + for (n = 7; n >= 0; n--) { + if ((maskByte >> n & 1) != 0) { + if (bytesPixel == 1) { + result = cm8.getRGB(pixBuf[i]); + } else { + result = 0xFF000000 + | (pixBuf[i * 4 + 2] & 0xFF) << 16 + | (pixBuf[i * 4 + 1] & 0xFF) << 8 + | (pixBuf[i * 4] & 0xFF); + } + } else { + result = 0; // Transparent pixel + } + softCursorPixels[i++] = result; + } + } + for (n = 7; n >= 8 - width % 8; n--) { + if ((maskBuf[y * bytesPerRow + x] >> n & 1) != 0) { + if (bytesPixel == 1) { + result = cm8.getRGB(pixBuf[i]); + } else { + result = 0xFF000000 + | (pixBuf[i * 4 + 2] & 0xFF) << 16 + | (pixBuf[i * 4 + 1] & 0xFF) << 8 + | (pixBuf[i * 4] & 0xFF); + } + } else { + result = 0; // Transparent pixel + } + softCursorPixels[i++] = result; + } + } + + } + + return new MemoryImageSource(width, height, softCursorPixels, 0, width); + } + + // + // createSoftCursor(). Assign softCursor new Image (scaled if necessary). + // Uses softCursorSource as a source for new cursor image. + // + + synchronized void createSoftCursor() { + + if (softCursorSource == null) + return; + + int scaleCursor = viewer.options.scaleCursor; + if (scaleCursor == 0 || !inputEnabled) + scaleCursor = 100; + + // Save original cursor coordinates. + int x = cursorX - hotX; + int y = cursorY - hotY; + int w = cursorWidth; + int h = cursorHeight; + + cursorWidth = (origCursorWidth * scaleCursor + 50) / 100; + cursorHeight = (origCursorHeight * scaleCursor + 50) / 100; + hotX = (origHotX * scaleCursor + 50) / 100; + hotY = (origHotY * scaleCursor + 50) / 100; + softCursor = Toolkit.getDefaultToolkit().createImage(softCursorSource); + + if (scaleCursor != 100) { + softCursor = softCursor.getScaledInstance(cursorWidth, + cursorHeight, Image.SCALE_SMOOTH); + } + + if (showSoftCursor) { + // Compute screen area to update. + x = Math.min(x, cursorX - hotX); + y = Math.min(y, cursorY - hotY); + w = Math.max(w, cursorWidth); + h = Math.max(h, cursorHeight); + + repaint(viewer.deferCursorUpdates, x, y, w, h); + } + } + + // + // softCursorMove(). Moves soft cursor into a particular location. + // + + synchronized void softCursorMove(int x, int y) { + int oldX = cursorX; + int oldY = cursorY; + cursorX = x; + cursorY = y; + if (showSoftCursor) { + repaint(viewer.deferCursorUpdates, oldX - hotX, oldY - hotY, + cursorWidth, cursorHeight); + repaint(viewer.deferCursorUpdates, cursorX - hotX, cursorY - hotY, + cursorWidth, cursorHeight); + } + } + + // + // softCursorFree(). Remove soft cursor, dispose resources. + // + + synchronized void softCursorFree() { + if (showSoftCursor) { + showSoftCursor = false; + softCursor = null; + softCursorSource = null; + + repaint(viewer.deferCursorUpdates, cursorX - hotX, cursorY - hotY, + cursorWidth, cursorHeight); + } + } + + BufferedImage createBufferedImage(Image img){ + BufferedImage bimg = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_RGB ); + + Graphics g = bimg.getGraphics(); + g.drawImage(img, 0, 0, null); + g.dispose(); + return bimg; + } + + byte[] getBytes(BufferedImage img)throws IOException { + byte[] b = getImageBytes(img, "raw"); + return b; + } + + byte[] getImageBytes(BufferedImage image, String imageFormat) throws IOException { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + BufferedOutputStream os = new BufferedOutputStream(bos); + image.flush(); + ImageIO.write(image, imageFormat, os); + os.flush(); + os.close(); + return bos.toByteArray(); + } + + void drawBufferedImage(byte[] b) throws IOException{ + BufferedImage bimg = ImageIO.read(new ByteArrayInputStream(b)); +// ImageIO.write(bimg, "jpeg", new File("sample.jpeg")); + memGraphics.setClip(0,0, rfb.framebufferWidth, rfb.framebufferHeight ); + memGraphics.drawImage( bimg, 0,0, null); + scheduleRepaint(0, 0, rfb.framebufferWidth, rfb.framebufferHeight ); + } + + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/myVncProxy/EchoClient.java Fri Jan 13 13:41:30 2012 +0900 @@ -0,0 +1,288 @@ +package myVncProxy; + +import java.io.*; +import java.net.*; + +import myVncProxy.MulticastQueue.Client; + + + +public class EchoClient { + private String name; + private BufferedReader is = null; + private DataOutputStream os = null; + private Socket echoSocket = null; + private boolean runflag = false; + private WaitReply waitReply; + private Socket clientSocket = null; +// MyVncClient client; + private InterfaceForViewer client; + private int echoPort = 9999; + private IpV6 ipV6; + private MyVncClient checkMove; + private VncViewer vncV; + String responseLine; + String parent;// 親の番号 + String treenum;// 自分の番号 + String leaderflag;// リーダフラグ + //boolean passflag; + + + // WaitReplyに自分自身を渡している + public EchoClient() { + } + + + public EchoClient(EchoClient echo) { + this.name = echo.name; + this.leaderflag= echo.leaderflag; + this.parent = echo.parent; + this.treenum = echo.treenum; + this.client = echo.client; + this.waitReply = echo.waitReply; + checkMove = (MyVncClient)echo.client; + } + // VncViewerから引数をもらってきてproxy役を認識する + public EchoClient(String name,MyVncClient client) { + this.client = client; + this.name = name; + } + + public EchoClient(String name,MyVncClient client, int echoPort) { + this.client = client; + this.name = name; + this.echoPort = echoPort; + } + + + + public EchoClient(EchoClient echo,MyVncClient client) { + this.client = client; + this.name = echo.name; + leaderflag = echo.leaderflag; + parent = echo.parent; + treenum = echo.treenum; + waitReply = echo.waitReply; + } + + public EchoClient(String name,CuiMyVncClient client) { + this.client = client; + this.name = name; + } + + public EchoClient(String name,CuiMyVncClient client, int echoPort) { + this.client = client; + this.name = name; + this.echoPort = echoPort; + } + + public EchoClient(EchoClient echo,CuiMyVncClient client) { + this.client = client; + this.name = echo.name; + leaderflag = echo.leaderflag; + parent = echo.parent; + treenum = echo.treenum; + } + + // void hostn(String args){ + void openport() { + try { + if (name != null) { + echoSocket = new Socket(name, echoPort); + } else { + echoSocket = new Socket("133.13.48.18", echoPort); + } + os = new DataOutputStream(echoSocket.getOutputStream()); + is = new BufferedReader(new InputStreamReader(echoSocket.getInputStream())); + } catch (UnknownHostException e) { + System.err.println("Don't know about host: localhost"); + } catch (IOException e) { + System.out.println(name + " Connection Faild"); + System.exit(0); + } + } + + /** + * @param args + * select connect port + * @return + */ + EchoClient requestHostName(String args) { + // サーバーにメッセージを送る + if (echoSocket != null && os != null && is != null) { + try { + + InetAddress addr = InetAddress.getLocalHost(); + String add = new String(addr.getHostAddress()); + //add = getIpV6(); + + os.writeBytes(add + "\n"); + os.writeBytes(args + "\n"); + getProxyData(is); + + streamClose(); + } catch (UnknownHostException e) { + System.err.println("Trying to connect to unknown host: " + e); + } catch (IOException e) { + System.err.println("IOException: " + e); + } + waitReply = new WaitReply(treenum,client); + waitReply.start(); + } + return this; + } + + + /** + * Call at lost host + */ + boolean losthost() { + if (echoSocket != null && os != null && is != null) { + try { + if(runflag){ + return true; + } + sendDataProxy(); + String checkRepetition = getProxyData2(is); + if(checkRepetition.equals("stop")){ + return true; + } + //if(!(checkRepetition.equals("skip")) || "1".equals(leaderflag)) { + if(!(waitReply.checkPath())) { + Thread.sleep(1000); + reConnectionMain(echoSocket); + streamClose(); + } + //Thread.sleep(1000); + /* + if(!(checkMove.vncFrame.isShowing())&&"skip".equals(checkRepetition)) { + openport(); + notfoundParent(); + } + */ + } catch (UnknownHostException e) { + System.err.println("Trying to connect to unknown host: " + e); + } catch (IOException e) { + return false; + } catch (InterruptedException e) { + e.printStackTrace(); + + } catch (NullPointerException e) { + openport(); + System.out.println("notFoundParents"); + notfoundParent(); + } + } + return true; + } + + boolean notfoundParent() { + if (echoSocket != null && os != null && is != null) { + runflag = true; + try { + sendDataProxy("2", parent,null); + getProxyData(is); + reConnectionMain(echoSocket); + streamClose(); + } catch (UnknownHostException e) { + System.err.println("Trying to connect to unknown host: " + e); + } catch (IOException e) { + System.err.println("IOException: " + e); + } + } + return true; + } + + + EchoClient Interruption(Socket _clientSocket) { + clientSocket = _clientSocket; + BufferedReader lostis = null;//あとで修正する + + + try { + lostis = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); + getProxyData(lostis); + clientSocket.close();// WaitReplyのacceptを終了させる + } catch (IOException e) { + System.out.println(e); + } + return this; + } + + void getProxyData(BufferedReader is) throws IOException { + if ((responseLine = is.readLine()) != null) { + System.out.println("Server: " + responseLine); + } + if ((parent = is.readLine()) != null) { + System.out.println("parent: " + parent); + } + if ((treenum = is.readLine()) != null) { + System.out.println("treenum: " + treenum); + } + if ((leaderflag = is.readLine()) != null) { + System.out.println("leaderflag: " + leaderflag); + } + } + + String getProxyData2(BufferedReader is) throws IOException { + String checkRepetition; + if ((responseLine = is.readLine()) != null) { + System.out.println("Server: " + responseLine); + } + if ((parent = is.readLine()) != null) { + System.out.println("parent: " + parent); + } + if ((checkRepetition = is.readLine()) != null) { + System.out.println("checkRepetition: " + checkRepetition); + } + return checkRepetition; + } + + void reConnectionMain(Socket echoSocket) { + client.close(); + client.setClientSocket(echoSocket); + client.init(); + client.setEchoValue(this); + client.getParentName(); + client.start_threads(); + client.start(); + } + + void streamClose() throws IOException { + os.close(); + is.close(); + echoSocket.close(); + } + + void sendDataProxy() { + if ("1".equals(leaderflag)) { + sendDataProxy("1",parent,treenum); + } else { + sendDataProxy("3",parent,treenum); + } + } + + void sendDataProxy(String type,String num,String treenum) { + try { + if(treenum!=null) { + os.writeBytes(type + "\n"); + os.writeBytes(num + "\n"); + os.writeBytes(treenum + "\n"); + } else { + os.writeBytes(type + "\n"); + os.writeBytes(num + "\n"); + } + + } catch (UnknownHostException e) { + System.err.println("Trying to connect to unknown host: " + e); + } catch (IOException e) { + System.err.println("IOException: " + e); + } + } + + String getIpV6() { + ipV6 = new IpV6(); + ipV6.getInterface(); + return ipV6.getV6(); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/myVncProxy/EchoClient.java.orig Fri Jan 13 13:41:30 2012 +0900 @@ -0,0 +1,369 @@ +package myVncClient; + +import java.io.*; +import java.net.*; + +import myVncClient.MulticastQueue.Client; + + +public class EchoClient { + private String name; + private BufferedReader is = null; + private DataOutputStream os = null; + private Socket echoSocket = null; + private boolean runflag = false; + private WaitReply waitReply; + private Socket clientSocket = null; +// MyVncClient client; + private InterfaceForViewer client; + private int echoPort = 9999; + MyVncClient checkMove; + VncViewer vncV; + String responseLine; + String parent;// 親の番号 + String treenum;// 自分の番号 + String leaderflag;// リーダフラグ + boolean passflag; + + + // WaitReplyに自分自身を渡している + public EchoClient() { + } + + // VncViewerから引数をもらってきてproxy役を認識する + public EchoClient(String name,MyVncClient client) { + this.client = client; + this.name = name; + } + + public EchoClient(String name,MyVncClient client, int echoPort) { + this.client = client; + this.name = name; + this.echoPort = echoPort; + } + + + + public EchoClient(EchoClient echo,MyVncClient client) { + this.client = client; + this.name = echo.name; + leaderflag = echo.leaderflag; + parent = echo.parent; + treenum = echo.treenum; + waitReply = echo.waitReply; + } + + public EchoClient(String name,CuiMyVncClient client) { + this.client = client; + this.name = name; + } + + public EchoClient(String name,CuiMyVncClient client, int echoPort) { + this.client = client; + this.name = name; + this.echoPort = echoPort; + } + + public EchoClient(EchoClient echo,CuiMyVncClient client) { + this.client = client; + this.name = echo.name; + leaderflag = echo.leaderflag; + parent = echo.parent; + treenum = echo.treenum; + } + + // void hostn(String args){ + void openport() { + // ソケットや入出力用のストリームの宣言 + /* + Random rnd = new Random(); + long ran = rnd.nextInt(1000) + 1000; +*/ + // ポート9999番に接続 + try { + if (name != null) { + echoSocket = new Socket(name, echoPort); + } else { + echoSocket = new Socket("133.13.48.18", echoPort); + } + os = new DataOutputStream(echoSocket.getOutputStream()); + is = new BufferedReader(new InputStreamReader(echoSocket.getInputStream())); + } catch (UnknownHostException e) { + System.err.println("Don't know about host: localhost"); + } catch (IOException e) { + System.out.println(name + " への接続に失敗しました"); + System.exit(0); + } + } + + /** + * @param args + * select connect port + * @return + */ + EchoClient hostn(String args) { + // サーバーにメッセージを送る + if (echoSocket != null && os != null && is != null) { + try { + // ip情報を取得する + InetAddress addr = InetAddress.getLocalHost(); + // System.out.println(addr.getHostAddress()); + String add = new String(addr.getHostAddress()); + + // メッセージを送ります + os.writeBytes(add + "\n"); + os.writeBytes(args + "\n"); + + if ((responseLine = is.readLine()) != null) { + System.out.println("Server: " + responseLine); + } + if ((parent = is.readLine()) != null) { + System.out.println("parent: " + parent); + } + if ((treenum = is.readLine()) != null) { + System.out.println("treenum: " + treenum); + } + if ((leaderflag = is.readLine()) != null) { + System.out.println("leaderflag: " + leaderflag); + } + + // 開いたソケットなどをクローズ + os.close(); + is.close(); + echoSocket.close(); + } catch (UnknownHostException e) { + System.err.println("Trying to connect to unknown host: " + e); + } catch (IOException e) { + System.err.println("IOException: " + e); + + } + + waitReply = new WaitReply(treenum,client); + waitReply.start(); + + } + return this; + } + + + /** + * Call at lost host + */ + boolean losthost() { + String checkRepetition; + if (echoSocket != null && os != null && is != null) { + try { + if(runflag){ + return true; + } + // echoSocketの情報を呼び出す + if ("1".equals(leaderflag)) { + senddataProxy("1",parent,treenum); + } else { + senddataProxy("3",parent,treenum); + } + + if ((responseLine = is.readLine()) != null) { + System.out.println("Server: " + responseLine); + } + if ((parent = is.readLine()) != null) { + System.out.println("parent: " + parent); + } + if ((checkRepetition = is.readLine()) != null) { + System.out.println("checkRepetition: " + checkRepetition); + } + if(checkRepetition.equals("stop")){ + return true; + } + + /** + * if ((value.treenum = is.readLine()) != null) { + * System.out.println("treenum: " + value.treenum); } + */ + +<<<<<<< local + if(!(checkRepetition.equals("skip")) || "1".equals(leaderflag)) { +======= + if(!(checkRepetition.equals("skip"))) { +>>>>>>> other + Thread.sleep(1000); + client.init(); + client.setEchoValue(this); + client.getParentName(); + client.start_threads(); + client.start(); + // MyVncClient.main(this); + + // 開いたソケットなどをクローズ + os.close(); + is.close(); + echoSocket.close(); + //runflag = true; + } +<<<<<<< local + /* + Thread.sleep(1000); + if(checkRepetition.equals("skip") &&!(waitReply.passflag)) { + openport(); + notfoundParent(); + }*/ + +======= + +>>>>>>> other + } catch (UnknownHostException e) { + System.err.println("Trying to connect to unknown host: " + e); + } catch (IOException e) { + + return false; + + /* + while (true) { + + try { + Thread.sleep(1000); + System.out.println("once connection proxy"); + } catch (InterruptedException e1) { + e1.printStackTrace(); + } + + openport(); + losthost(); + System.out.println("faild in this area"); + System.err.println("IOException: " + e); + + if(runflag == true){ + break; + } + } + */ + } + catch (InterruptedException e) { + e.printStackTrace(); + } + + } + return true; + } + + boolean notfoundParent() { + if (echoSocket != null && os != null && is != null) { + runflag = true; + try { + senddataProxy("2", parent,null); + + if ((responseLine = is.readLine()) != null) { + System.out.println("Server: " + responseLine); + } + if ((parent = is.readLine()) != null) { + System.out.println("parent: " + parent); + } + if ((treenum = is.readLine()) != null) { + System.out.println("treenum: " + treenum); + } + if ((leaderflag = is.readLine()) != null) { + System.out.println("leaderflag: " + leaderflag); + } + client.init(); + client.setEchoValue(this); + client.getParentName(); + client.start_threads(); + client.start(); + os.close(); + is.close(); + echoSocket.close(); + } catch (UnknownHostException e) { + System.err.println("Trying to connect to unknown host: " + e); + } catch (IOException e) { + System.err.println("IOException: " + e); + } + } + return true; + } +/* + void lostchild() { + + // ßSystem.out.println(name); + if (echoSocket != null && os != null && is != null) { + try { + + // echoSocketなどの情報を呼び出す(追加) + + // 自分の番号を報告 + os.writeBytes("4\n"); + os.writeBytes(treenum + "\n"); + + os.close(); + is.close(); + echoSocket.close(); + + } catch (UnknownHostException e) { + System.err.println("Trying to connect to unknown host: " + e); + } catch (IOException e) { + System.err.println("IOException: " + e); + } + } + } +*/ + EchoClient Interruption(Socket _clientSocket) { + clientSocket = _clientSocket; + BufferedReader lostis = null;//あとで修正する + + + try { + lostis = new BufferedReader(new InputStreamReader( + clientSocket.getInputStream())); + // while (true){ + // line = lostis.readLine(); + // System.out.println(line); + + try { + if ((responseLine = lostis.readLine()) != null) { + System.out.println("newServer: " + responseLine); + } + if ((parent = lostis.readLine()) != null) { + System.out.println("newtparent: " + parent); + } + if ((treenum = lostis.readLine()) != null) { + System.out.println("newtreenum: " + treenum); + } + if ((leaderflag = lostis.readLine()) != null) { + System.out.println("newreaderflag: " + leaderflag); + } + + } catch (UnknownHostException e) { + System.err.println("Trying to connect to unknown host: " + e); + } catch (IOException e) { + System.err.println("IOException: " + e); + } + + // } + } catch (IOException e) { + System.out.println(e); + } + try { + clientSocket.close();// WaitReplyのacceptを終了させる + } catch (IOException e) { + System.out.println(e); + } + return this; + } + + void senddataProxy(String type,String num,String treenum) { + try { + if(treenum!=null) { + os.writeBytes(type + "\n"); + os.writeBytes(num + "\n"); + os.writeBytes(treenum + "\n"); + } else { + os.writeBytes(type + "\n"); + os.writeBytes(num + "\n"); + } + + } catch (UnknownHostException e) { + System.err.println("Trying to connect to unknown host: " + e); + } catch (IOException e) { + System.err.println("IOException: " + e); + } + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/myVncProxy/EchoClient.java~ Fri Jan 13 13:41:30 2012 +0900 @@ -0,0 +1,369 @@ +package myVncClient; + +import java.io.*; +import java.net.*; + +import myVncClient.MulticastQueue.Client; + + +public class EchoClient { + private String name; + private BufferedReader is = null; + private DataOutputStream os = null; + private Socket echoSocket = null; + private boolean runflag = false; + private WaitReply waitReply; + private Socket clientSocket = null; +// MyVncClient client; + private InterfaceForViewer client; + private int echoPort = 9999; + MyVncClient checkMove; + VncViewer vncV; + String responseLine; + String parent;// 親の番号 + String treenum;// 自分の番号 + String leaderflag;// リーダフラグ + boolean passflag; + + + // WaitReplyに自分自身を渡している + public EchoClient() { + } + + // VncViewerから引数をもらってきてproxy役を認識する + public EchoClient(String name,MyVncClient client) { + this.client = client; + this.name = name; + } + + public EchoClient(String name,MyVncClient client, int echoPort) { + this.client = client; + this.name = name; + this.echoPort = echoPort; + } + + + + public EchoClient(EchoClient echo,MyVncClient client) { + this.client = client; + this.name = echo.name; + leaderflag = echo.leaderflag; + parent = echo.parent; + treenum = echo.treenum; + waitReply = echo.waitReply; + } + + public EchoClient(String name,CuiMyVncClient client) { + this.client = client; + this.name = name; + } + + public EchoClient(String name,CuiMyVncClient client, int echoPort) { + this.client = client; + this.name = name; + this.echoPort = echoPort; + } + + public EchoClient(EchoClient echo,CuiMyVncClient client) { + this.client = client; + this.name = echo.name; + leaderflag = echo.leaderflag; + parent = echo.parent; + treenum = echo.treenum; + } + + // void hostn(String args){ + void openport() { + // ソケットや入出力用のストリームの宣言 + /* + Random rnd = new Random(); + long ran = rnd.nextInt(1000) + 1000; +*/ + // ポート9999番に接続 + try { + if (name != null) { + echoSocket = new Socket(name, echoPort); + } else { + echoSocket = new Socket("133.13.48.18", echoPort); + } + os = new DataOutputStream(echoSocket.getOutputStream()); + is = new BufferedReader(new InputStreamReader(echoSocket.getInputStream())); + } catch (UnknownHostException e) { + System.err.println("Don't know about host: localhost"); + } catch (IOException e) { + System.out.println(name + " への接続に失敗しました"); + System.exit(0); + } + } + + /** + * @param args + * select connect port + * @return + */ + EchoClient hostn(String args) { + // サーバーにメッセージを送る + if (echoSocket != null && os != null && is != null) { + try { + // ip情報を取得する + InetAddress addr = InetAddress.getLocalHost(); + // System.out.println(addr.getHostAddress()); + String add = new String(addr.getHostAddress()); + + // メッセージを送ります + os.writeBytes(add + "\n"); + os.writeBytes(args + "\n"); + + if ((responseLine = is.readLine()) != null) { + System.out.println("Server: " + responseLine); + } + if ((parent = is.readLine()) != null) { + System.out.println("parent: " + parent); + } + if ((treenum = is.readLine()) != null) { + System.out.println("treenum: " + treenum); + } + if ((leaderflag = is.readLine()) != null) { + System.out.println("leaderflag: " + leaderflag); + } + + // 開いたソケットなどをクローズ + os.close(); + is.close(); + echoSocket.close(); + } catch (UnknownHostException e) { + System.err.println("Trying to connect to unknown host: " + e); + } catch (IOException e) { + System.err.println("IOException: " + e); + + } + + waitReply = new WaitReply(treenum,client); + waitReply.start(); + + } + return this; + } + + + /** + * Call at lost host + */ + boolean losthost() { + String checkRepetition; + if (echoSocket != null && os != null && is != null) { + try { + if(runflag){ + return true; + } + // echoSocketの情報を呼び出す + if ("1".equals(leaderflag)) { + senddataProxy("1",parent,treenum); + } else { + senddataProxy("3",parent,treenum); + } + + if ((responseLine = is.readLine()) != null) { + System.out.println("Server: " + responseLine); + } + if ((parent = is.readLine()) != null) { + System.out.println("parent: " + parent); + } + if ((checkRepetition = is.readLine()) != null) { + System.out.println("checkRepetition: " + checkRepetition); + } + if(checkRepetition.equals("stop")){ + return true; + } + + /** + * if ((value.treenum = is.readLine()) != null) { + * System.out.println("treenum: " + value.treenum); } + */ + +<<<<<<< local + if(!(checkRepetition.equals("skip")) || "1".equals(leaderflag)) { +======= + if(!(checkRepetition.equals("skip"))) { +>>>>>>> other + Thread.sleep(1000); + client.init(); + client.setEchoValue(this); + client.getParentName(); + client.start_threads(); + client.start(); + // MyVncClient.main(this); + + // 開いたソケットなどをクローズ + os.close(); + is.close(); + echoSocket.close(); + //runflag = true; + } +<<<<<<< local + /* + Thread.sleep(1000); + if(checkRepetition.equals("skip") &&!(waitReply.passflag)) { + openport(); + notfoundParent(); + }*/ + +======= + +>>>>>>> other + } catch (UnknownHostException e) { + System.err.println("Trying to connect to unknown host: " + e); + } catch (IOException e) { + + return false; + + /* + while (true) { + + try { + Thread.sleep(1000); + System.out.println("once connection proxy"); + } catch (InterruptedException e1) { + e1.printStackTrace(); + } + + openport(); + losthost(); + System.out.println("faild in this area"); + System.err.println("IOException: " + e); + + if(runflag == true){ + break; + } + } + */ + } + catch (InterruptedException e) { + e.printStackTrace(); + } + + } + return true; + } + + boolean notfoundParent() { + if (echoSocket != null && os != null && is != null) { + runflag = true; + try { + senddataProxy("2", parent,null); + + if ((responseLine = is.readLine()) != null) { + System.out.println("Server: " + responseLine); + } + if ((parent = is.readLine()) != null) { + System.out.println("parent: " + parent); + } + if ((treenum = is.readLine()) != null) { + System.out.println("treenum: " + treenum); + } + if ((leaderflag = is.readLine()) != null) { + System.out.println("leaderflag: " + leaderflag); + } + client.init(); + client.setEchoValue(this); + client.getParentName(); + client.start_threads(); + client.start(); + os.close(); + is.close(); + echoSocket.close(); + } catch (UnknownHostException e) { + System.err.println("Trying to connect to unknown host: " + e); + } catch (IOException e) { + System.err.println("IOException: " + e); + } + } + return true; + } +/* + void lostchild() { + + // ßSystem.out.println(name); + if (echoSocket != null && os != null && is != null) { + try { + + // echoSocketなどの情報を呼び出す(追加) + + // 自分の番号を報告 + os.writeBytes("4\n"); + os.writeBytes(treenum + "\n"); + + os.close(); + is.close(); + echoSocket.close(); + + } catch (UnknownHostException e) { + System.err.println("Trying to connect to unknown host: " + e); + } catch (IOException e) { + System.err.println("IOException: " + e); + } + } + } +*/ + EchoClient Interruption(Socket _clientSocket) { + clientSocket = _clientSocket; + BufferedReader lostis = null;//あとで修正する + + + try { + lostis = new BufferedReader(new InputStreamReader( + clientSocket.getInputStream())); + // while (true){ + // line = lostis.readLine(); + // System.out.println(line); + + try { + if ((responseLine = lostis.readLine()) != null) { + System.out.println("newServer: " + responseLine); + } + if ((parent = lostis.readLine()) != null) { + System.out.println("newtparent: " + parent); + } + if ((treenum = lostis.readLine()) != null) { + System.out.println("newtreenum: " + treenum); + } + if ((leaderflag = lostis.readLine()) != null) { + System.out.println("newreaderflag: " + leaderflag); + } + + } catch (UnknownHostException e) { + System.err.println("Trying to connect to unknown host: " + e); + } catch (IOException e) { + System.err.println("IOException: " + e); + } + + // } + } catch (IOException e) { + System.out.println(e); + } + try { + clientSocket.close();// WaitReplyのacceptを終了させる + } catch (IOException e) { + System.out.println(e); + } + return this; + } + + void senddataProxy(String type,String num,String treenum) { + try { + if(treenum!=null) { + os.writeBytes(type + "\n"); + os.writeBytes(num + "\n"); + os.writeBytes(treenum + "\n"); + } else { + os.writeBytes(type + "\n"); + os.writeBytes(num + "\n"); + } + + } catch (UnknownHostException e) { + System.err.println("Trying to connect to unknown host: " + e); + } catch (IOException e) { + System.err.println("IOException: " + e); + } + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/myVncProxy/InterfaceForViewer.java Fri Jan 13 13:41:30 2012 +0900 @@ -0,0 +1,31 @@ +package myVncProxy; + +import java.awt.Image; +import java.net.Socket; + +public interface InterfaceForViewer extends java.lang.Runnable{ + + public void init(); + public void start_threads(); + public void start(); + + public void setEchoValue(EchoClient value); + public String readParameter(String name, boolean required); + + public void getParentName(); + // synchronized + public void disconnect(); + public void fatalError(String str); + public void fatalError(String str, Exception e); + + + public void destroy(); + + public void enableInput(boolean enable); + + + public void setClientSocket(Socket sock); + public void close(); + public Image getScreenImage(); + public void writeScreenData(byte[] b, String imageFormat); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/myVncProxy/IpV6.java Fri Jan 13 13:41:30 2012 +0900 @@ -0,0 +1,78 @@ +package myVncProxy; + +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashMap; +import java.net.Inet6Address; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class IpV6 { + private HashMap<NetworkInterface, ArrayList<InetAddress>> interfaceMap; + + public IpV6() { + interfaceMap = new HashMap<NetworkInterface, ArrayList<InetAddress>>(); + } + + public void getInterface() { + interfaceMap.clear(); + try { + Enumeration<NetworkInterface> iList = NetworkInterface + .getNetworkInterfaces(); + if (iList == null) { + System.out.println("notfound interface"); + } else { + while (iList.hasMoreElements()) { + NetworkInterface iface = iList.nextElement(); + Enumeration<InetAddress> addrList = iface + .getInetAddresses(); + if (!addrList.hasMoreElements()) + continue; + ArrayList<InetAddress> iaddress = new ArrayList<InetAddress>(); + while (addrList.hasMoreElements()) + iaddress.add(addrList.nextElement()); + interfaceMap.put(iface, iaddress); + } + } + } catch (SocketException se) { + System.out.println("Error getting network interfaces: " + + se.getMessage()); + } + } + + public boolean match(String name) { + Pattern pattern = Pattern.compile("lo.*"); + Matcher matcher = pattern.matcher(name); + return matcher.matches(); + } + + public String getV6() { + boolean flag = false; + String name = null; + for (NetworkInterface n : interfaceMap.keySet()) { + if (!(match(n.getName()))) { + for (InetAddress a : interfaceMap.get(n)) { + if (a instanceof Inet6Address && !(flag)) { + System.out.println(a.getHostAddress()); + flag = true; + name = a.getHostAddress(); + } + } + } + } + return name; + } + + public HashMap<NetworkInterface, ArrayList<InetAddress>> getInetfaceMap() { + return interfaceMap; + } + + public void setInterfaceMap( + HashMap<NetworkInterface, ArrayList<InetAddress>> interfaceMap) { + this.interfaceMap = interfaceMap; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/myVncProxy/MyVncClient.java Fri Jan 13 13:41:30 2012 +0900 @@ -0,0 +1,1256 @@ +package myVncProxy; + +import java.awt.*; +import java.awt.event.*; +import java.awt.image.BufferedImage; +import java.io.*; +import java.net.*; +import java.util.Random; + +import java.nio.ByteBuffer; + +public class MyVncClient extends VncViewer implements InterfaceForViewer, + java.lang.Runnable, WindowListener { + + /** + * + */ + private static final long serialVersionUID = 1L; + private boolean inAnApplet = true; + private boolean inSeparateFrame = false; + private Socket clientSocket = null; + private String parent, treenum; + private String leaderflag; + private boolean runflag = false; + private boolean first = true; + + private EchoClient echoValue; + private int echoPort; + private String pHost; + //private TextBox getHost; + private GetBroadCast getBcast; + private Thread runBcast; + private BroadCast bCast; + + // + // main() is called when run as a java program from the command line. + // It simply runs the applet inside a newly-created frame. + // + + public void treeVncClient(String[] argv) { + MyVncClient v = new MyVncClient(); + v.echoValue = null; + v.runClient(argv); + } + + private void runClient(String[] argv) { + mainArgs = argv; + System.out.println(mainArgs.length); + inAnApplet = false; + inSeparateFrame = true; + if(mainArgs.length == 0) { + bCast = new BroadCast("who"); + bCast.createSocket(); + bCast.sendData(); + getBcast = new GetBroadCast(); + runBcast = new Thread(getBcast); + runBcast.start(); + } + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + if(mainArgs.length == 0) + getBcast.setStopFlag(true); + + if (mainArgs.length > 0) + pHost = mainArgs[0]; + else { + pHost = getBcast.text.getAddress(); + } + + + //pHost = "cls080.ie.u-ryukyu.ac.jp"; + if (mainArgs.length > 1) + port = Integer.parseInt(mainArgs[1]); + else { + port = Integer.parseInt(getBcast.text.getPort()); + getBcast.socketClose(); +// port = 5999; + } + init(); + start_threads(); + start(); + } + + // + // init() + // + + public void init() { + + readParameters(); + + refApplet = this; + + if (inSeparateFrame) { + vncFrame = new Frame("TightVNC"); + if (!inAnApplet) { + vncFrame.add("Center", this); + } + vncContainer = vncFrame; + } else { + vncContainer = this; + } + + recordingSync = new Object(); + + options = new OptionsFrame(this); + clipboard = new ClipboardFrame(this); + if (RecordingFrame.checkSecurity()) + rec = new RecordingFrame(this); + + sessionFileName = null; + recordingActive = false; + recordingStatusChanged = false; + cursorUpdatesDef = null; + eightBitColorsDef = null; + + if (inSeparateFrame) + vncFrame.addWindowListener(this); + + rfbThread = new Thread(this); + } + + public void update(Graphics g) { + } + + // + // run() - executed by the rfbThread to deal with the RFB socket. + // + + public void start_threads() { + rfbThread.start(); + } + + public void run() { + + gridbag = new GridBagLayout(); + vncContainer.setLayout(gridbag); + + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridwidth = GridBagConstraints.REMAINDER; + gbc.anchor = GridBagConstraints.NORTHWEST; + + if (showControls) { + buttonPanel = new ButtonPanel(this); + gridbag.setConstraints(buttonPanel, gbc); + vncContainer.add(buttonPanel); + } + + try { + + if (first) { + connectAndAuthenticate(); + accThread = new Thread(new AcceptThread(rfb, 5999)); + accThread.start(); + first = false; + } else { + System.out.println("reConnectAndAuthenticate() "); + reConnectAndAuthenticate(); + //accThread = new Thread(new AcceptThread(rfb, 5999)); + //accThread.start(); + } + + doProtocolInitialisation(); + + createCanvas(0, 0); + + // rfb.readPngData(); + // vc.drawFirstImage(); + + } catch (IOException e) { + try { + rfb.sock.close(); + + } catch (IOException e2) { + e2.printStackTrace(); + } + System.out.println("Socket error"); + // parent no find + Random rnd = new Random(); + long ran = rnd.nextInt(3000) + 3000; + System.out.println(ran); + // 親がいない場合の処理はここに書く!!!! + /** + * this while reconnection + */ + + int counter = 0; + vncFrame.setVisible(false); + vncFrame.dispose(); + + while (true) { + /** + * if my last node case reconnectoion stop + */ + + echoValue = new EchoClient(echoValue, this); + // echoValue = new EchoClient(echoValue); + + try { + Thread.sleep(ran); + } catch (InterruptedException e1) { + e1.printStackTrace(); + } + + if (counter >= 3) { + echoValue.openport(); + echoValue.notfoundParent(); + } + + echoValue.openport(); + /* + if(echoValue.notfoundParent()) { + break; + } + */ + // runflag = echo.losthost(); + + + if (echoValue.losthost()) { + break; + } + + counter++; + } + + // System.exit(0); + } catch (Exception e) { + System.out.println(e); + System.exit(0); + } + + gbc.weightx = 1.0; + gbc.weighty = 1.0; + + if (inSeparateFrame) { + + // Create a panel which itself is resizeable and can hold + // non-resizeable VncCanvas component at the top left corner. + Panel canvasPanel = new Panel(); + canvasPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); + canvasPanel.add(vc); + + // Create a ScrollPane which will hold a panel with VncCanvas + // inside. + desktopScrollPane = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED); + gbc.fill = GridBagConstraints.BOTH; + gridbag.setConstraints(desktopScrollPane, gbc); + desktopScrollPane.add(canvasPanel); + + // Finally, add our ScrollPane to the Frame window. + vncFrame.add(desktopScrollPane); + vncFrame.setTitle(rfb.desktopName); + vncFrame.pack(); + vc.resizeDesktopFrame(); + + } else { + + // Just add the VncCanvas component to the Applet. + gridbag.setConstraints(vc, gbc); + add(vc); + validate(); + + } + + try { + if (showControls) + buttonPanel.enableButtons(); + + moveFocusToDesktop(); + + 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) { + + vncFrame.setVisible(false); + vncFrame.dispose(); + // num4 + if (leaderflag != null) { + while (true) { + // echoValue = new EchoClient(echoValue, this); + echoValue = new EchoClient(echoValue); + echoValue.openport(); + // runflag = echo.losthost(); + if (echoValue.losthost()) { + break; + } + } + } else { + + if (showOfflineDesktop) { + e.printStackTrace(); + System.out + .println("Network error: remote side closed connection"); + if (vc != null) { + vc.enableInput(false); + } + if (inSeparateFrame) { + vncFrame.setTitle(rfb.desktopName + " [disconnected]"); + } + if (rfb != null && !rfb.closed()) + rfb.close(); + if (showControls && buttonPanel != null) { + buttonPanel.disableButtonsOnDisconnect(); + if (inSeparateFrame) { + vncFrame.pack(); + } else { + validate(); + } + } + } 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); + } + } + + } + + // + // Create a VncCanvas instance. + // + + void createCanvas(int maxWidth, int maxHeight) throws IOException { + // Determine if Java 2D API is available and use a special + // version of VncCanvas if it is present. + vc = null; + try { + // This throws ClassNotFoundException if there is no Java 2D API. + Class cl = Class.forName("java.awt.Graphics2D"); + // If we could load Graphics2D class, then we can use VncCanvas2D. + cl = Class.forName("VncCanvas2"); + Class[] argClasses = { this.getClass(), Integer.TYPE, Integer.TYPE }; + java.lang.reflect.Constructor cstr = cl.getConstructor(argClasses); + Object[] argObjects = { this, new Integer(maxWidth), + new Integer(maxHeight) }; + vc = (VncCanvas) cstr.newInstance(argObjects); + } catch (Exception e) { + System.out.println("Warning: Java 2D API is not available"); + } + + // If we failed to create VncCanvas2D, use old VncCanvas. + if (vc == null) + vc = new VncCanvas(this, maxWidth, maxHeight); + } + + // + // 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 { + + showConnectionStatus("Initializing..."); + if (inSeparateFrame) { + vncFrame.pack(); + vncFrame.setVisible(true); + } else { + validate(); + } + + showConnectionStatus("Connecting to " + host + ", port " + port + "..."); + + rfb = new MyRfbProto(pHost, port, this); + 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); + + if (rfb.serverMinor == 855) { + /* + * if connect to proxy, userEchoPortFlag is true. + * if connect to client, userEchoPortFlag is false. + */ + boolean useEchoPortFlag = rfb.readProxyFlag(); + if (useEchoPortFlag) { + byte[] b = new byte[4]; + b = rfb.readEchoPort(); + echoPort = castByteInt(b); + + + InetAddress addr = InetAddress.getByName(pHost); + String h = new String(addr.getHostAddress()); + + getParentName(); + if (!(h.equals(host))) { + rfb.changeParent(host, port); + rfb.readVersionMsg(); + rfb.writeVersionMsg(); + boolean flag = rfb.readProxyFlag(); + } + } + } + + 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 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 reConnectAndAuthenticate() throws Exception { + + showConnectionStatus("Initializing..."); + + if (inSeparateFrame) { + vncFrame.pack(); + vncFrame.setVisible(true); + } else { + validate(); + } + + showConnectionStatus("Connecting to " + host + ", port " + port + "..."); + + rfb.changeParent(host, port); + + 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); + + if (rfb.serverMinor == 855) { + boolean useEchoPortFlag = rfb.readProxyFlag(); + if (useEchoPortFlag) { + byte[] b = new byte[4]; + b = rfb.readEchoPort(); + echoPort = castByteInt(b); + + InetAddress addr = InetAddress.getByName(pHost); + String h = new String(addr.getHostAddress()); + + getParentName(); + if (!(h.equals(host))) { + rfb.changeParent(host, port); + rfb.readVersionMsg(); + rfb.writeVersionMsg(); + boolean flag = rfb.readProxyFlag(); + } + } + } + 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 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); + } + } + + // + // Show a message describing the connection status. + // To hide the connection status label, use (msg == null). + // + + void showConnectionStatus(String msg) { + if (msg == null) { + if (vncContainer.isAncestorOf(connStatusLabel)) { + vncContainer.remove(connStatusLabel); + } + return; + } + + System.out.println(msg); + + if (connStatusLabel == null) { + connStatusLabel = new Label("Status: " + msg); + connStatusLabel.setFont(new Font("Helvetica", Font.PLAIN, 12)); + } else { + connStatusLabel.setText("Status: " + msg); + } + + if (!vncContainer.isAncestorOf(connStatusLabel)) { + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridwidth = GridBagConstraints.REMAINDER; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.anchor = GridBagConstraints.NORTHWEST; + gbc.weightx = 1.0; + gbc.weighty = 1.0; + gbc.insets = new Insets(20, 30, 20, 30); + gridbag.setConstraints(connStatusLabel, gbc); + vncContainer.add(connStatusLabel); + } + + if (inSeparateFrame) { + vncFrame.pack(); + } else { + validate(); + } + } + + // + // 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); + + if (inSeparateFrame) { + vncFrame.pack(); + } else { + validate(); + } + + authPanel.moveFocusToDefaultField(); + String pw = authPanel.getPassword(); + vncContainer.remove(authPanel); + 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() { + /* + * host = readParameter("HOST", !inAnApplet); + * + * if (host == null) { host = getCodeBase().getHost(); if + * (host.equals("")) { fatalError("HOST parameter not specified"); } } + * + * port = readIntParameter("PORT", 5550); + */ + + // Read "ENCPASSWORD" or "PASSWORD" parameter if specified. + readPasswordParameters(); + + String str; + if (inAnApplet) { + str = readParameter("Open New Window", false); + if (str != null && str.equalsIgnoreCase("Yes")) + inSeparateFrame = true; + } + + // "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 = readParameter("ENCPASSWORD", false); + 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 (inAnApplet) { + String s = getParameter(name); + if ((s == null) && required) { + fatalError(name + " parameter not specified"); + } + return s; + } + /* + * 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; + } + + // + // moveFocusToDesktop() - move keyboard focus either to VncCanvas. + // + + void moveFocusToDesktop() { + if (vncContainer != null) { + if (vc != null && vncContainer.isAncestorOf(vc)) + vc.requestFocus(); + } + } + + // + // 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(); + + if (inAnApplet) { + showMessage("Disconnected"); + } else { + 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); + + if (inAnApplet) { + // vncContainer null, applet not inited, + // can not present the error to the user. + Thread.currentThread().stop(); + } else { + 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(); + + if (inAnApplet) { + showMessage(str); + } else { + 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); + + } + + if (inSeparateFrame) { + vncFrame.pack(); + } else { + validate(); + } + } + + // + // 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(); + if (inSeparateFrame) + vncFrame.dispose(); + } + + // + // 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(); + + if (!inAnApplet) { + System.exit(0); + } + } + + // + // 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) { + } + + public void getParentName() { + if (echoValue == null) { + + if (clientSocket == null) { + + // echo = new EchoClient(pHost, this); + echoValue = new EchoClient(pHost, this, echoPort); + echoValue.openport(); + + echoValue = echoValue.requestHostName("1"); + } else { + echoValue = new EchoClient(); + echoValue = echoValue.Interruption(clientSocket); + } + } + // proxyからの返信で接続先を決定する + host = echoValue.responseLine; + parent = echoValue.parent; + if (echoValue.treenum != null) { + treenum = echoValue.treenum; + } else { + treenum = echoValue.treenum; + } + if (echoValue.leaderflag != null) { + leaderflag = echoValue.leaderflag; + } else { + leaderflag = echoValue.leaderflag; + } + System.out.println("Parent =" + parent); + System.out.println("mynumber =" + treenum); + System.out.println("connect host =" + host); + System.out.println("leaderflag(boolean) = " + leaderflag); + + } + + public void setEchoValue(EchoClient value) { + this.echoValue = value; + } + + int castByteInt(byte[] b) { + ByteBuffer bb = ByteBuffer.wrap(b); + int value = bb.getInt(); + return value; + } + + public void setClientSocket(Socket sock) { + clientSocket = sock; + } + + public void close() { + rfb.close(); + vncFrame.setVisible(false); + vncFrame.dispose(); + } + + @Override + public Image getScreenImage() { +// return vc.memImage; + return vc.rawPixelsImage; + } + + public void writeScreenData(byte[] b, String imageFormat) { + try{ + vc.drawBufferedImage(b); + }catch(IOException e){ + e.printStackTrace(); + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/myVncProxy/MyVncClient.java.orig Fri Jan 13 13:41:30 2012 +0900 @@ -0,0 +1,1220 @@ +package myVncClient; + +import java.awt.*; +import java.awt.event.*; +import java.awt.image.BufferedImage; +import java.io.*; +import java.net.*; +import java.util.Random; + +import java.nio.ByteBuffer; + +public class MyVncClient extends VncViewer implements InterfaceForViewer, + java.lang.Runnable, WindowListener { + + /** + * + */ + private static final long serialVersionUID = 1L; + boolean inAnApplet = true; + boolean inSeparateFrame = false; + Socket clientSocket = null; + String parent, treenum; + private String leaderflag; + boolean runflag = false; + boolean first = true; + + EchoClient echoValue; + int echoPort; + String pHost; + + // + // main() is called when run as a java program from the command line. + // It simply runs the applet inside a newly-created frame. + // + + public static void main(String[] argv) { + MyVncClient v = new MyVncClient(); + v.echoValue = null; + v.runClient(argv); + } + + private void runClient(String[] argv) { + mainArgs = argv; + inAnApplet = false; + inSeparateFrame = true; + + if (mainArgs.length > 0) + pHost = mainArgs[0]; + else + pHost = "cls080.ie.u-ryukyu.ac.jp"; + if (mainArgs.length > 1) + port = Integer.parseInt(mainArgs[1]); + else + port = 5999; + + init(); + start_threads(); + start(); + } + + // + // init() + // + + public void init() { + + readParameters(); + + refApplet = this; + + if (inSeparateFrame) { + vncFrame = new Frame("TightVNC"); + if (!inAnApplet) { + vncFrame.add("Center", this); + } + vncContainer = vncFrame; + } else { + vncContainer = this; + } + + recordingSync = new Object(); + + options = new OptionsFrame(this); + clipboard = new ClipboardFrame(this); + if (RecordingFrame.checkSecurity()) + rec = new RecordingFrame(this); + + sessionFileName = null; + recordingActive = false; + recordingStatusChanged = false; + cursorUpdatesDef = null; + eightBitColorsDef = null; + + if (inSeparateFrame) + vncFrame.addWindowListener(this); + + rfbThread = new Thread(this); + } + + public void update(Graphics g) { + } + + // + // run() - executed by the rfbThread to deal with the RFB socket. + // + + public void start_threads() { + rfbThread.start(); + } + + public void run() { + + gridbag = new GridBagLayout(); + vncContainer.setLayout(gridbag); + + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridwidth = GridBagConstraints.REMAINDER; + gbc.anchor = GridBagConstraints.NORTHWEST; + + if (showControls) { + buttonPanel = new ButtonPanel(this); + gridbag.setConstraints(buttonPanel, gbc); + vncContainer.add(buttonPanel); + } + + try { + + if (first) { + connectAndAuthenticate(); + accThread = new Thread(new AcceptThread(rfb, 5999)); + accThread.start(); + first = false; + } else { + System.out.println("reConnectAndAuthenticate() "); + reConnectAndAuthenticate(); + accThread = new Thread(new AcceptThread(rfb, 5999)); + accThread.start(); + } + + doProtocolInitialisation(); + + createCanvas(0, 0); + + // rfb.readPngData(); + // vc.drawFirstImage(); + + } catch (IOException e) { + try { + rfb.sock.close(); + + } catch (IOException e2) { + e2.printStackTrace(); + } + System.out.println("Socket error"); + // parent no find + Random rnd = new Random(); + long ran = rnd.nextInt(5000) + 5000; + System.out.println(ran); + // 親がいない場合の処理はここに書く!!!! + /** + * this while reconnection + */ + + int counter = 0; + vncFrame.setVisible(false); + vncFrame.dispose(); + + while (true) { + /** + * if my last node case reconnectoion stop + */ + + echoValue = new EchoClient(echoValue, this); + // echoValue = new EchoClient(echoValue); + + try { + Thread.sleep(ran); + } catch (InterruptedException e1) { + e1.printStackTrace(); + } + + if (counter >= 4) { + echoValue.openport(); + echoValue.notfoundParent(); + } + + echoValue.openport(); + // runflag = echo.losthost(); + if (echoValue.losthost()) { + break; + } + counter++; + } + + // System.exit(0); + } catch (Exception e) { + System.out.println(e); + System.exit(0); + } + + gbc.weightx = 1.0; + gbc.weighty = 1.0; + + if (inSeparateFrame) { + + // Create a panel which itself is resizeable and can hold + // non-resizeable VncCanvas component at the top left corner. + Panel canvasPanel = new Panel(); + canvasPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); + canvasPanel.add(vc); + + // Create a ScrollPane which will hold a panel with VncCanvas + // inside. + desktopScrollPane = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED); + gbc.fill = GridBagConstraints.BOTH; + gridbag.setConstraints(desktopScrollPane, gbc); + desktopScrollPane.add(canvasPanel); + + // Finally, add our ScrollPane to the Frame window. + vncFrame.add(desktopScrollPane); + vncFrame.setTitle(rfb.desktopName); + vncFrame.pack(); + vc.resizeDesktopFrame(); + + } else { + + // Just add the VncCanvas component to the Applet. + gridbag.setConstraints(vc, gbc); + add(vc); + validate(); + + } + + try { + if (showControls) + buttonPanel.enableButtons(); + + moveFocusToDesktop(); + + 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) { + + vncFrame.setVisible(false); + vncFrame.dispose(); + // num4 + if (leaderflag != null) { + while (true) { + // echoValue = new EchoClient(echoValue, this); + echoValue = new EchoClient(echoValue); + echoValue.openport(); + // runflag = echo.losthost(); + if (echoValue.losthost()) { + break; + } + } + } else { + + if (showOfflineDesktop) { + e.printStackTrace(); + System.out + .println("Network error: remote side closed connection"); + if (vc != null) { + vc.enableInput(false); + } + if (inSeparateFrame) { + vncFrame.setTitle(rfb.desktopName + " [disconnected]"); + } + if (rfb != null && !rfb.closed()) + rfb.close(); + if (showControls && buttonPanel != null) { + buttonPanel.disableButtonsOnDisconnect(); + if (inSeparateFrame) { + vncFrame.pack(); + } else { + validate(); + } + } + } 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); + } + } + + } + + // + // Create a VncCanvas instance. + // + + void createCanvas(int maxWidth, int maxHeight) throws IOException { + // Determine if Java 2D API is available and use a special + // version of VncCanvas if it is present. + vc = null; + try { + // This throws ClassNotFoundException if there is no Java 2D API. + Class cl = Class.forName("java.awt.Graphics2D"); + // If we could load Graphics2D class, then we can use VncCanvas2D. + cl = Class.forName("VncCanvas2"); + Class[] argClasses = { this.getClass(), Integer.TYPE, Integer.TYPE }; + java.lang.reflect.Constructor cstr = cl.getConstructor(argClasses); + Object[] argObjects = { this, new Integer(maxWidth), + new Integer(maxHeight) }; + vc = (VncCanvas) cstr.newInstance(argObjects); + } catch (Exception e) { + System.out.println("Warning: Java 2D API is not available"); + } + + // If we failed to create VncCanvas2D, use old VncCanvas. + if (vc == null) + vc = new VncCanvas(this, maxWidth, maxHeight); + } + + // + // 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 { + + showConnectionStatus("Initializing..."); + if (inSeparateFrame) { + vncFrame.pack(); + vncFrame.setVisible(true); + } else { + validate(); + } + + showConnectionStatus("Connecting to " + host + ", port " + port + "..."); + + rfb = new MyRfbProto(pHost, port, this); + 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); + + if (rfb.serverMinor == 855) { + /* + * if connect to proxy, userEchoPortFlag is true. + * if connect to client, userEchoPortFlag is false. + */ + boolean useEchoPortFlag = rfb.readProxyFlag(); + if (useEchoPortFlag) { + byte[] b = new byte[4]; + b = rfb.readEchoPort(); + echoPort = castByteInt(b); + + InetAddress addr = InetAddress.getByName(pHost); + String h = new String(addr.getHostAddress()); + + getParentName(); + if (!(h.equals(host))) { + rfb.changeParent(host, port); + rfb.readVersionMsg(); + rfb.writeVersionMsg(); + boolean flag = rfb.readProxyFlag(); + } + } + } + + 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 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 reConnectAndAuthenticate() throws Exception { + + showConnectionStatus("Initializing..."); + + if (inSeparateFrame) { + vncFrame.pack(); + vncFrame.setVisible(true); + } else { + validate(); + } + + showConnectionStatus("Connecting to " + host + ", port " + port + "..."); + + rfb.changeParent(host, port); + + 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); + + if (rfb.serverMinor == 855) { + boolean useEchoPortFlag = rfb.readProxyFlag(); + if (useEchoPortFlag) { + byte[] b = new byte[4]; + b = rfb.readEchoPort(); + echoPort = castByteInt(b); + + InetAddress addr = InetAddress.getByName(pHost); + String h = new String(addr.getHostAddress()); + + getParentName(); + if (!(h.equals(host))) { + rfb.changeParent(host, port); + rfb.readVersionMsg(); + rfb.writeVersionMsg(); + boolean flag = rfb.readProxyFlag(); + } + } + } + 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 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); + } + } + + // + // Show a message describing the connection status. + // To hide the connection status label, use (msg == null). + // + + void showConnectionStatus(String msg) { + if (msg == null) { + if (vncContainer.isAncestorOf(connStatusLabel)) { + vncContainer.remove(connStatusLabel); + } + return; + } + + System.out.println(msg); + + if (connStatusLabel == null) { + connStatusLabel = new Label("Status: " + msg); + connStatusLabel.setFont(new Font("Helvetica", Font.PLAIN, 12)); + } else { + connStatusLabel.setText("Status: " + msg); + } + + if (!vncContainer.isAncestorOf(connStatusLabel)) { + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridwidth = GridBagConstraints.REMAINDER; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.anchor = GridBagConstraints.NORTHWEST; + gbc.weightx = 1.0; + gbc.weighty = 1.0; + gbc.insets = new Insets(20, 30, 20, 30); + gridbag.setConstraints(connStatusLabel, gbc); + vncContainer.add(connStatusLabel); + } + + if (inSeparateFrame) { + vncFrame.pack(); + } else { + validate(); + } + } + + // + // 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); + + if (inSeparateFrame) { + vncFrame.pack(); + } else { + validate(); + } + + authPanel.moveFocusToDefaultField(); + String pw = authPanel.getPassword(); + vncContainer.remove(authPanel); + 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() { + /* + * host = readParameter("HOST", !inAnApplet); + * + * if (host == null) { host = getCodeBase().getHost(); if + * (host.equals("")) { fatalError("HOST parameter not specified"); } } + * + * port = readIntParameter("PORT", 5550); + */ + + // Read "ENCPASSWORD" or "PASSWORD" parameter if specified. + readPasswordParameters(); + + String str; + if (inAnApplet) { + str = readParameter("Open New Window", false); + if (str != null && str.equalsIgnoreCase("Yes")) + inSeparateFrame = true; + } + + // "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 = readParameter("ENCPASSWORD", false); + 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 (inAnApplet) { + String s = getParameter(name); + if ((s == null) && required) { + fatalError(name + " parameter not specified"); + } + return s; + } + /* + * 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; + } + + // + // moveFocusToDesktop() - move keyboard focus either to VncCanvas. + // + + void moveFocusToDesktop() { + if (vncContainer != null) { + if (vc != null && vncContainer.isAncestorOf(vc)) + vc.requestFocus(); + } + } + + // + // 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(); + + if (inAnApplet) { + showMessage("Disconnected"); + } else { + 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); + + if (inAnApplet) { + // vncContainer null, applet not inited, + // can not present the error to the user. + Thread.currentThread().stop(); + } else { + 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(); + + if (inAnApplet) { + showMessage(str); + } else { + 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); + + } + + if (inSeparateFrame) { + vncFrame.pack(); + } else { + validate(); + } + } + + // + // 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(); + if (inSeparateFrame) + vncFrame.dispose(); + } + + // + // 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(); + + if (!inAnApplet) { + System.exit(0); + } + } + + // + // 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) { + } + + public void getParentName() { + if (echoValue == null) { + + if (clientSocket == null) { + + // echo = new EchoClient(pHost, this); + echoValue = new EchoClient(pHost, this, echoPort); + echoValue.openport(); + + echoValue = echoValue.requestHostName("1"); + } else { + echoValue = new EchoClient(); + echoValue = echoValue.Interruption(clientSocket); + } + } + // proxyからの返信で接続先を決定する + host = echoValue.responseLine; + parent = echoValue.parent; + if (echoValue.treenum != null) { + treenum = echoValue.treenum; + } else { + treenum = echoValue.treenum; + } + if (echoValue.leaderflag != null) { + leaderflag = echoValue.leaderflag; + } else { + leaderflag = echoValue.leaderflag; + } + System.out.println("Parent =" + parent); + System.out.println("mynumber =" + treenum); + System.out.println("connect host =" + host); + System.out.println("leaderflag(boolean) = " + leaderflag); + + } + + public void setEchoValue(EchoClient value) { + this.echoValue = value; + } + + int castByteInt(byte[] b) { + ByteBuffer bb = ByteBuffer.wrap(b); + int value = bb.getInt(); + return value; + } + + public void setClientSocket(Socket sock) { + clientSocket = sock; + } + + public void close() { + rfb.close(); + vncFrame.setVisible(false); + vncFrame.dispose(); + } + + @Override + public Image getScreenImage() { +// return vc.memImage; + return vc.rawPixelsImage; + } + + public void writeScreenData(byte[] b, String imageFormat) { + try{ + vc.drawBufferedImage(b); + }catch(IOException e){ + e.printStackTrace(); + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/myVncProxy/MyVncClient.java~ Fri Jan 13 13:41:30 2012 +0900 @@ -0,0 +1,1240 @@ +package myVncClient; + +import java.awt.*; +import java.awt.event.*; +import java.awt.image.BufferedImage; +import java.io.*; +import java.net.*; +import java.util.Random; + +import java.nio.ByteBuffer; + +public class MyVncClient extends VncViewer implements InterfaceForViewer, + java.lang.Runnable, WindowListener { + + /** + * + */ + private static final long serialVersionUID = 1L; + boolean inAnApplet = true; + boolean inSeparateFrame = false; + Socket clientSocket = null; + String parent, treenum; + private String leaderflag; + boolean runflag = false; + boolean first = true; + + EchoClient echoValue; + int echoPort; + String pHost; + TextBox getHost; + + // + // main() is called when run as a java program from the command line. + // It simply runs the applet inside a newly-created frame. + // + + public static void main(String[] argv) { + MyVncClient v = new MyVncClient(); + v.echoValue = null; + v.runClient(argv); + } + + private void runClient(String[] argv) { + mainArgs = argv; + inAnApplet = false; + inSeparateFrame = true; + getHost = new TextBox(); + + if (mainArgs.length > 0) + pHost = mainArgs[0]; + else { + getHost.ipRegister(); + pHost = getHost.getAddress(); + } + + + //pHost = "cls080.ie.u-ryukyu.ac.jp"; + if (mainArgs.length > 1) + port = Integer.parseInt(mainArgs[1]); + else +<<<<<<< local + port = 5999; + +======= + port = Integer.parseInt(getHost.getPort()); + //port = 5999; + +>>>>>>> other + init(); + start_threads(); + start(); + } + + // + // init() + // + + public void init() { + + readParameters(); + + refApplet = this; + + if (inSeparateFrame) { + vncFrame = new Frame("TightVNC"); + if (!inAnApplet) { + vncFrame.add("Center", this); + } + vncContainer = vncFrame; + } else { + vncContainer = this; + } + + recordingSync = new Object(); + + options = new OptionsFrame(this); + clipboard = new ClipboardFrame(this); + if (RecordingFrame.checkSecurity()) + rec = new RecordingFrame(this); + + sessionFileName = null; + recordingActive = false; + recordingStatusChanged = false; + cursorUpdatesDef = null; + eightBitColorsDef = null; + + if (inSeparateFrame) + vncFrame.addWindowListener(this); + + rfbThread = new Thread(this); + } + + public void update(Graphics g) { + } + + // + // run() - executed by the rfbThread to deal with the RFB socket. + // + + public void start_threads() { + rfbThread.start(); + } + + public void run() { + + gridbag = new GridBagLayout(); + vncContainer.setLayout(gridbag); + + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridwidth = GridBagConstraints.REMAINDER; + gbc.anchor = GridBagConstraints.NORTHWEST; + + if (showControls) { + buttonPanel = new ButtonPanel(this); + gridbag.setConstraints(buttonPanel, gbc); + vncContainer.add(buttonPanel); + } + + try { + + if (first) { + connectAndAuthenticate(); + accThread = new Thread(new AcceptThread(rfb, 5999)); + accThread.start(); + first = false; + } else { + System.out.println("reConnectAndAuthenticate() "); + reConnectAndAuthenticate(); + //accThread = new Thread(new AcceptThread(rfb, 5999)); + //accThread.start(); + } + + doProtocolInitialisation(); + + createCanvas(0, 0); + + // rfb.readPngData(); + // vc.drawFirstImage(); + + } catch (IOException e) { + try { + rfb.sock.close(); + + } catch (IOException e2) { + e2.printStackTrace(); + } + System.out.println("Socket error"); + // parent no find + Random rnd = new Random(); + long ran = rnd.nextInt(3000) + 3000; + System.out.println(ran); + // 親がいない場合の処理はここに書く!!!! + /** + * this while reconnection + */ + + int counter = 0; + vncFrame.setVisible(false); + vncFrame.dispose(); + + while (true) { + /** + * if my last node case reconnectoion stop + */ + + echoValue = new EchoClient(echoValue, this); + // echoValue = new EchoClient(echoValue); + + try { + Thread.sleep(ran); + } catch (InterruptedException e1) { + e1.printStackTrace(); + } + + if (counter >= 6) { + echoValue.openport(); + echoValue.notfoundParent(); + } + + echoValue.openport(); + // runflag = echo.losthost(); + if (echoValue.losthost()) { + break; + } + counter++; + } + + // System.exit(0); + } catch (Exception e) { + System.out.println(e); + System.exit(0); + } + + gbc.weightx = 1.0; + gbc.weighty = 1.0; + + if (inSeparateFrame) { + + // Create a panel which itself is resizeable and can hold + // non-resizeable VncCanvas component at the top left corner. + Panel canvasPanel = new Panel(); + canvasPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); + canvasPanel.add(vc); + + // Create a ScrollPane which will hold a panel with VncCanvas + // inside. + desktopScrollPane = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED); + gbc.fill = GridBagConstraints.BOTH; + gridbag.setConstraints(desktopScrollPane, gbc); + desktopScrollPane.add(canvasPanel); + + // Finally, add our ScrollPane to the Frame window. + vncFrame.add(desktopScrollPane); + vncFrame.setTitle(rfb.desktopName); + vncFrame.pack(); + vc.resizeDesktopFrame(); + + } else { + + // Just add the VncCanvas component to the Applet. + gridbag.setConstraints(vc, gbc); + add(vc); + validate(); + + } + + try { + if (showControls) + buttonPanel.enableButtons(); + + moveFocusToDesktop(); + + 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) { + + vncFrame.setVisible(false); + vncFrame.dispose(); + // num4 + if (leaderflag != null) { + while (true) { + // echoValue = new EchoClient(echoValue, this); + echoValue = new EchoClient(echoValue); + echoValue.openport(); + // runflag = echo.losthost(); + if (echoValue.losthost()) { + break; + } + } + } else { + + if (showOfflineDesktop) { + e.printStackTrace(); + System.out + .println("Network error: remote side closed connection"); + if (vc != null) { + vc.enableInput(false); + } + if (inSeparateFrame) { + vncFrame.setTitle(rfb.desktopName + " [disconnected]"); + } + if (rfb != null && !rfb.closed()) + rfb.close(); + if (showControls && buttonPanel != null) { + buttonPanel.disableButtonsOnDisconnect(); + if (inSeparateFrame) { + vncFrame.pack(); + } else { + validate(); + } + } + } 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); + } + } + + } + + // + // Create a VncCanvas instance. + // + + void createCanvas(int maxWidth, int maxHeight) throws IOException { + // Determine if Java 2D API is available and use a special + // version of VncCanvas if it is present. + vc = null; + try { + // This throws ClassNotFoundException if there is no Java 2D API. + Class cl = Class.forName("java.awt.Graphics2D"); + // If we could load Graphics2D class, then we can use VncCanvas2D. + cl = Class.forName("VncCanvas2"); + Class[] argClasses = { this.getClass(), Integer.TYPE, Integer.TYPE }; + java.lang.reflect.Constructor cstr = cl.getConstructor(argClasses); + Object[] argObjects = { this, new Integer(maxWidth), + new Integer(maxHeight) }; + vc = (VncCanvas) cstr.newInstance(argObjects); + } catch (Exception e) { + System.out.println("Warning: Java 2D API is not available"); + } + + // If we failed to create VncCanvas2D, use old VncCanvas. + if (vc == null) + vc = new VncCanvas(this, maxWidth, maxHeight); + } + + // + // 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 { + + showConnectionStatus("Initializing..."); + if (inSeparateFrame) { + vncFrame.pack(); + vncFrame.setVisible(true); + } else { + validate(); + } + + showConnectionStatus("Connecting to " + host + ", port " + port + "..."); + + rfb = new MyRfbProto(pHost, port, this); + 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); + + if (rfb.serverMinor == 855) { + /* + * if connect to proxy, userEchoPortFlag is true. + * if connect to client, userEchoPortFlag is false. + */ + boolean useEchoPortFlag = rfb.readProxyFlag(); + if (useEchoPortFlag) { + byte[] b = new byte[4]; + b = rfb.readEchoPort(); + echoPort = castByteInt(b); + +<<<<<<< local + InetAddress addr = InetAddress.getByName(pHost); + String h = new String(addr.getHostAddress()); +======= + if(rfb.serverMinor == 855) { + byte[] b = new byte[4]; + b = rfb.readEchoPort(); + echoPort = castByteInt(b); +>>>>>>> other + + getParentName(); + if (!(h.equals(host))) { + rfb.changeParent(host, port); + rfb.readVersionMsg(); + rfb.writeVersionMsg(); + boolean flag = rfb.readProxyFlag(); + } + } + } + + 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 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 reConnectAndAuthenticate() throws Exception { + + showConnectionStatus("Initializing..."); + + if (inSeparateFrame) { + vncFrame.pack(); + vncFrame.setVisible(true); + } else { + validate(); + } + + showConnectionStatus("Connecting to " + host + ", port " + port + "..."); + + rfb.changeParent(host, port); + + 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); + + if (rfb.serverMinor == 855) { + boolean useEchoPortFlag = rfb.readProxyFlag(); + if (useEchoPortFlag) { + byte[] b = new byte[4]; + b = rfb.readEchoPort(); + echoPort = castByteInt(b); + + InetAddress addr = InetAddress.getByName(pHost); + String h = new String(addr.getHostAddress()); + + getParentName(); + if (!(h.equals(host))) { + rfb.changeParent(host, port); + rfb.readVersionMsg(); + rfb.writeVersionMsg(); + boolean flag = rfb.readProxyFlag(); + } + } + } + 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 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); + } + } + + // + // Show a message describing the connection status. + // To hide the connection status label, use (msg == null). + // + + void showConnectionStatus(String msg) { + if (msg == null) { + if (vncContainer.isAncestorOf(connStatusLabel)) { + vncContainer.remove(connStatusLabel); + } + return; + } + + System.out.println(msg); + + if (connStatusLabel == null) { + connStatusLabel = new Label("Status: " + msg); + connStatusLabel.setFont(new Font("Helvetica", Font.PLAIN, 12)); + } else { + connStatusLabel.setText("Status: " + msg); + } + + if (!vncContainer.isAncestorOf(connStatusLabel)) { + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridwidth = GridBagConstraints.REMAINDER; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.anchor = GridBagConstraints.NORTHWEST; + gbc.weightx = 1.0; + gbc.weighty = 1.0; + gbc.insets = new Insets(20, 30, 20, 30); + gridbag.setConstraints(connStatusLabel, gbc); + vncContainer.add(connStatusLabel); + } + + if (inSeparateFrame) { + vncFrame.pack(); + } else { + validate(); + } + } + + // + // 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); + + if (inSeparateFrame) { + vncFrame.pack(); + } else { + validate(); + } + + authPanel.moveFocusToDefaultField(); + String pw = authPanel.getPassword(); + vncContainer.remove(authPanel); + 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() { + /* + * host = readParameter("HOST", !inAnApplet); + * + * if (host == null) { host = getCodeBase().getHost(); if + * (host.equals("")) { fatalError("HOST parameter not specified"); } } + * + * port = readIntParameter("PORT", 5550); + */ + + // Read "ENCPASSWORD" or "PASSWORD" parameter if specified. + readPasswordParameters(); + + String str; + if (inAnApplet) { + str = readParameter("Open New Window", false); + if (str != null && str.equalsIgnoreCase("Yes")) + inSeparateFrame = true; + } + + // "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 = readParameter("ENCPASSWORD", false); + 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 (inAnApplet) { + String s = getParameter(name); + if ((s == null) && required) { + fatalError(name + " parameter not specified"); + } + return s; + } + /* + * 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; + } + + // + // moveFocusToDesktop() - move keyboard focus either to VncCanvas. + // + + void moveFocusToDesktop() { + if (vncContainer != null) { + if (vc != null && vncContainer.isAncestorOf(vc)) + vc.requestFocus(); + } + } + + // + // 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(); + + if (inAnApplet) { + showMessage("Disconnected"); + } else { + 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); + + if (inAnApplet) { + // vncContainer null, applet not inited, + // can not present the error to the user. + Thread.currentThread().stop(); + } else { + 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(); + + if (inAnApplet) { + showMessage(str); + } else { + 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); + + } + + if (inSeparateFrame) { + vncFrame.pack(); + } else { + validate(); + } + } + + // + // 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(); + if (inSeparateFrame) + vncFrame.dispose(); + } + + // + // 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(); + + if (!inAnApplet) { + System.exit(0); + } + } + + // + // 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) { + } + + public void getParentName() { + if (echoValue == null) { + + if (clientSocket == null) { + + // echo = new EchoClient(pHost, this); + echoValue = new EchoClient(pHost, this, echoPort); + echoValue.openport(); + + echoValue = echoValue.requestHostName("1"); + } else { + echoValue = new EchoClient(); + echoValue = echoValue.Interruption(clientSocket); + } + } + // proxyからの返信で接続先を決定する + host = echoValue.responseLine; + parent = echoValue.parent; + if (echoValue.treenum != null) { + treenum = echoValue.treenum; + } else { + treenum = echoValue.treenum; + } + if (echoValue.leaderflag != null) { + leaderflag = echoValue.leaderflag; + } else { + leaderflag = echoValue.leaderflag; + } + System.out.println("Parent =" + parent); + System.out.println("mynumber =" + treenum); + System.out.println("connect host =" + host); + System.out.println("leaderflag(boolean) = " + leaderflag); + + } + + public void setEchoValue(EchoClient value) { + this.echoValue = value; + } + + int castByteInt(byte[] b) { + ByteBuffer bb = ByteBuffer.wrap(b); + int value = bb.getInt(); + return value; + } + + public void setClientSocket(Socket sock) { + clientSocket = sock; + } + + public void close() { + rfb.close(); + vncFrame.setVisible(false); + vncFrame.dispose(); + } + + @Override + public Image getScreenImage() { +// return vc.memImage; + return vc.rawPixelsImage; + } + + public void writeScreenData(byte[] b, String imageFormat) { + try{ + vc.drawBufferedImage(b); + }catch(IOException e){ + e.printStackTrace(); + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/myVncProxy/OptionNoFrame.java Fri Jan 13 13:41:30 2012 +0900 @@ -0,0 +1,333 @@ +package myVncProxy; + +import java.awt.*; +import java.awt.event.*; + +class OptionsNoFrame{ + + static String[] names = { + "Encoding", + "Compression level", + "JPEG image quality", + "Cursor shape updates", + "Use CopyRect", + "Restricted colors", + "Mouse buttons 2 and 3", + "View only", + "Scale remote cursor", + "Share desktop", + }; + + static String[][] values = { + { "Auto", "Raw", "RRE", "CoRRE", "Hextile", "Zlib", "Tight", "ZRLE" }, + { "Default", "1", "2", "3", "4", "5", "6", "7", "8", "9" }, + { "JPEG off", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }, + { "Enable", "Ignore", "Disable" }, + { "Yes", "No" }, + { "Yes", "No" }, + { "Normal", "Reversed" }, + { "Yes", "No" }, + { "No", "50%", "75%", "125%", "150%" }, + { "Yes", "No" }, + }; + + final int + encodingIndex = 0, + compressLevelIndex = 1, + jpegQualityIndex = 2, + cursorUpdatesIndex = 3, + useCopyRectIndex = 4, + eightBitColorsIndex = 5, + mouseButtonIndex = 6, + viewOnlyIndex = 7, + scaleCursorIndex = 8, + shareDesktopIndex = 9; + + Label[] labels = new Label[names.length]; + Choice[] choices = new Choice[names.length]; + Button closeButton; + CuiMyVncClient viewer; + + + // + // The actual data which other classes look at: + // + + int preferredEncoding; + int compressLevel; + int jpegQuality; + boolean useCopyRect; + boolean requestCursorUpdates; + boolean ignoreCursorUpdates; + + boolean eightBitColors; + + boolean reverseMouseButtons2And3; + boolean shareDesktop; + boolean viewOnly; + int scaleCursor; + + boolean autoScale; + int scalingFactor; + + // + // Constructor. Set up the labels and choices from the names and values + // arrays. + // + + OptionsNoFrame(CuiMyVncClient v) { + + viewer = v; +/* + for (int i = 0; i < names.length; i++) { + labels[i] = new Label(names[i]); + + choices[i] = new Choice(); + + + for (int j = 0; j < values[i]. length; j++) { + choices[i].addItem(values[i][j]); + } + } + + // Set up defaults + + choices[encodingIndex].select("Auto"); + choices[compressLevelIndex].select("Default"); + choices[jpegQualityIndex].select("6"); + choices[cursorUpdatesIndex].select("Enable"); + choices[useCopyRectIndex].select("Yes"); + choices[eightBitColorsIndex].select("No"); + choices[mouseButtonIndex].select("Normal"); + choices[viewOnlyIndex].select("No"); + choices[scaleCursorIndex].select("No"); + choices[shareDesktopIndex].select("Yes"); + + // But let them be overridden by parameters + + for (int i = 0; i < names.length; i++) { + String s = viewer.readParameter(names[i], false); + if (s != null) { + for (int j = 0; j < values[i].length; j++) { + if (s.equalsIgnoreCase(values[i][j])) { + choices[i].select(j); + } + } + } + } + + // FIXME: Provide some sort of GUI for "Scaling Factor". + + autoScale = false; + scalingFactor = 100; + String s = viewer.readParameter("Scaling Factor", false); + if (s != null) { + if (s.equalsIgnoreCase("Auto")) { + autoScale = true; + } else { + // Remove the '%' char at the end of string if present. + if (s.charAt(s.length() - 1) == '%') { + s = s.substring(0, s.length() - 1); + } + // Convert to an integer. + try { + scalingFactor = Integer.parseInt(s); + } + catch (NumberFormatException e) { + scalingFactor = 100; + } + // Make sure scalingFactor is in the range of [1..1000]. + if (scalingFactor < 1) { + scalingFactor = 1; + } else if (scalingFactor > 1000) { + scalingFactor = 1000; + } + } + } +*/ + + // Make the booleans and encodings array correspond to the state of the GUI + +// setEncodings(); +// setColorFormat(); +// setOtherOptions(); + + } + + + // + // Disable the shareDesktop option + // + + void disableShareDesktop() { + labels[shareDesktopIndex].setEnabled(false); + choices[shareDesktopIndex].setEnabled(false); + } + + // + // setEncodings looks at the encoding, compression level, JPEG + // quality level, cursor shape updates and copyRect choices and sets + // corresponding variables properly. Then it calls the VncViewer's + // setEncodings method to send a SetEncodings message to the RFB + // server. + // + + void setEncodings() { +// useCopyRect = choices[useCopyRectIndex].getSelectedItem().equals("Yes"); + + preferredEncoding = RfbProto.EncodingRaw; + boolean enableCompressLevel = false; + + if (choices[encodingIndex].getSelectedItem().equals("RRE")) { + preferredEncoding = RfbProto.EncodingRRE; + } else if (choices[encodingIndex].getSelectedItem().equals("CoRRE")) { + preferredEncoding = RfbProto.EncodingCoRRE; + } else if (choices[encodingIndex].getSelectedItem().equals("Hextile")) { + preferredEncoding = RfbProto.EncodingHextile; + } else if (choices[encodingIndex].getSelectedItem().equals("ZRLE")) { + preferredEncoding = RfbProto.EncodingZRLE; + } else if (choices[encodingIndex].getSelectedItem().equals("Zlib")) { + preferredEncoding = RfbProto.EncodingZlib; + enableCompressLevel = true; + } else if (choices[encodingIndex].getSelectedItem().equals("Tight")) { + preferredEncoding = RfbProto.EncodingTight; + enableCompressLevel = true; + } else if (choices[encodingIndex].getSelectedItem().equals("Auto")) { + preferredEncoding = -1; + } + + // Handle compression level setting. + + try { + compressLevel = + Integer.parseInt(choices[compressLevelIndex].getSelectedItem()); + } + catch (NumberFormatException e) { + compressLevel = -1; + } + if (compressLevel < 1 || compressLevel > 9) { + compressLevel = -1; + } + labels[compressLevelIndex].setEnabled(enableCompressLevel); + choices[compressLevelIndex].setEnabled(enableCompressLevel); + + // Handle JPEG quality setting. + + try { + jpegQuality = + Integer.parseInt(choices[jpegQualityIndex].getSelectedItem()); + } + catch (NumberFormatException e) { + jpegQuality = -1; + } + if (jpegQuality < 0 || jpegQuality > 9) { + jpegQuality = -1; + } + + // Request cursor shape updates if necessary. + + requestCursorUpdates = + !choices[cursorUpdatesIndex].getSelectedItem().equals("Disable"); + + if (requestCursorUpdates) { + ignoreCursorUpdates = + choices[cursorUpdatesIndex].getSelectedItem().equals("Ignore"); + } + + viewer.setEncodings(); + } + + // + // setColorFormat sets eightBitColors variable depending on the GUI + // setting, causing switches between 8-bit and 24-bit colors mode if + // necessary. + // + + void setColorFormat() { + + eightBitColors = + choices[eightBitColorsIndex].getSelectedItem().equals("Yes"); + + boolean enableJPEG = !eightBitColors; + + labels[jpegQualityIndex].setEnabled(enableJPEG); + choices[jpegQualityIndex].setEnabled(enableJPEG); + } + + // + // setOtherOptions looks at the "other" choices (ones that do not + // cause sending any protocol messages) and sets the boolean flags + // appropriately. + // + + void setOtherOptions() { + + reverseMouseButtons2And3 + = choices[mouseButtonIndex].getSelectedItem().equals("Reversed"); + + viewOnly + = choices[viewOnlyIndex].getSelectedItem().equals("Yes"); + if (viewer.vc != null) + viewer.vc.enableInput(!viewOnly); + + shareDesktop + = choices[shareDesktopIndex].getSelectedItem().equals("Yes"); + + String scaleString = choices[scaleCursorIndex].getSelectedItem(); + if (scaleString.endsWith("%")) + scaleString = scaleString.substring(0, scaleString.length() - 1); + try { + scaleCursor = Integer.parseInt(scaleString); + } + catch (NumberFormatException e) { + scaleCursor = 0; + } + if (scaleCursor < 10 || scaleCursor > 500) { + scaleCursor = 0; + } + if (requestCursorUpdates && !ignoreCursorUpdates && !viewOnly) { + labels[scaleCursorIndex].setEnabled(true); + choices[scaleCursorIndex].setEnabled(true); + } else { + labels[scaleCursorIndex].setEnabled(false); + choices[scaleCursorIndex].setEnabled(false); + } + if (viewer.vc != null) + viewer.vc.createSoftCursor(); // update cursor scaling + } + + + // + // Respond to actions on Choice controls + // + + public void itemStateChanged(ItemEvent evt) { + Object source = evt.getSource(); + + if (source == choices[encodingIndex] || + source == choices[compressLevelIndex] || + source == choices[jpegQualityIndex] || + source == choices[cursorUpdatesIndex] || + source == choices[useCopyRectIndex]) { + + setEncodings(); + + if (source == choices[cursorUpdatesIndex]) { + setOtherOptions(); // update scaleCursor state + } + + } else if (source == choices[eightBitColorsIndex]) { + + setColorFormat(); + + } else if (source == choices[mouseButtonIndex] || + source == choices[shareDesktopIndex] || + source == choices[viewOnlyIndex] || + source == choices[scaleCursorIndex]) { + + setOtherOptions(); + + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/myVncProxy/WaitReply.java Fri Jan 13 13:41:30 2012 +0900 @@ -0,0 +1,64 @@ +package myVncProxy; + +import java.net.*; +import java.io.*; + +public class WaitReply extends Thread { + // MyVncClient client; + InterfaceForViewer client; + private String treenum; + boolean passflag; + + + /* + * public WaitReply(String treenum,MyVncClient client) { this.client = + * client; this.treenum = treenum; } + */ + + public WaitReply(String treenum, InterfaceForViewer client) { + this.client = client; + this.treenum = treenum; + } + + public boolean checkPath() { + return passflag; + } + + public void run() { + Socket clientSocket = null; + ServerSocket echoServer = null; + // boolean mainFlag; + + while (true) { + try { + echoServer = new ServerSocket(10001 + Integer.parseInt(treenum)); + } catch (IOException e) { + System.out.println(e); + } + try { + clientSocket = echoServer.accept(); + if (clientSocket != null) { + client.close(); + passflag = true; + // client.clientSocket = clientSocket; + client.setClientSocket(clientSocket); + client.init(); + client.setEchoValue(null); + client.getParentName(); + client.start_threads(); + client.start(); + // MyVncClient.main(clientSocket); + // echo.Interruption(clientSocket); + echoServer.close(); + } + + } catch (IOException e) { + System.out.println(e); + } + /* + * try { Thread.sleep(100); } catch (InterruptedException e) { + * e.printStackTrace(); } + */ + } + } +} \ No newline at end of file