Mercurial > hg > Members > nobuyasu > tightVNCClient
changeset 69:1f05b73b15df
modify MyVncClient.java and CuiMyVNcClient.java
author | e085711 |
---|---|
date | Sun, 07 Aug 2011 04:22:07 +0900 |
parents | 4e31d8494360 |
children | affdcbdc90ea |
files | src/myVncClient/CuiMyVncClient.java src/myVncClient/InterfaceForViewer.java src/myVncClient/MyRfbProto.java src/myVncClient/MyVncClient.java src/myVncClient/RfbProto.java |
diffstat | 5 files changed, 340 insertions(+), 141 deletions(-) [+] |
line wrap: on
line diff
--- a/src/myVncClient/CuiMyVncClient.java Sat Aug 06 23:34:37 2011 +0900 +++ b/src/myVncClient/CuiMyVncClient.java Sun Aug 07 04:22:07 2011 +0900 @@ -9,7 +9,7 @@ import myVncClient.AcceptThread; import myVncClient.OptionsNoFrame; -public class CuiMyVncClient implements InterfaceForViewer, java.lang.Runnable { +public class CuiMyVncClient implements InterfaceForViewer { public static void main(String[] argv) { CuiMyVncClient v = new CuiMyVncClient(); @@ -75,6 +75,7 @@ String parent, treenum; private String leaderflag; boolean runflag = false; + boolean first = true; EchoClient echo; @@ -95,7 +96,13 @@ // public void init(EchoClient value) { - + Random rnd = new Random(); + long ran = rnd.nextInt(5000); + try { + Thread.sleep(ran); + } catch (InterruptedException e1) { + e1.printStackTrace(); + } // readParameters(); readParameters(value); @@ -133,7 +140,12 @@ public void run() { try { - connectAndAuthenticate(); + if (first) { + connectAndAuthenticate(); + first = false; + }else { + reConnectAndAuthenticate(); + } accThread = new Thread(new AcceptThread(rfb, 5999)); accThread.start(); doProtocolInitialisation(); @@ -153,10 +165,11 @@ */ int counter = 0; - // window を消してnullを突っ込んでGCで削除させる。 + /* - * vncFrame.setVisible(false); vncFrame = null; - */ + vncFrame.setVisible(false); + vncFrame.dispose(); +*/ while (true) { /** * if my last node case reconnectoion stop @@ -177,19 +190,18 @@ echo.openport(); // runflag = echo.losthost(); if (echo.losthost()) { - break; + return; } counter++; } // System.exit(0); - } catch (Exception e) { + }catch (Exception e) { System.out.println(e); System.exit(0); } - - try { - + try{ + processNormalProtocol();// main loop } catch (NoRouteToHostException e) { @@ -316,6 +328,54 @@ } } + + + 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); + + 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).
--- a/src/myVncClient/InterfaceForViewer.java Sat Aug 06 23:34:37 2011 +0900 +++ b/src/myVncClient/InterfaceForViewer.java Sun Aug 07 04:22:07 2011 +0900 @@ -3,7 +3,7 @@ import java.awt.Graphics; import java.net.Socket; -public interface InterfaceForViewer { +public interface InterfaceForViewer extends java.lang.Runnable{ public void init(EchoClient value); public void start_threads();
--- a/src/myVncClient/MyRfbProto.java Sat Aug 06 23:34:37 2011 +0900 +++ b/src/myVncClient/MyRfbProto.java Sun Aug 07 04:22:07 2011 +0900 @@ -1,5 +1,6 @@ package myVncClient; + import java.awt.Graphics; import java.awt.Image; import java.awt.image.BufferedImage; @@ -15,23 +16,25 @@ import java.net.BindException; import java.net.ServerSocket; import java.net.Socket; +import java.net.UnknownHostException; import java.nio.ByteBuffer; import java.util.Iterator; import java.util.LinkedList; import javax.imageio.ImageIO; - import myVncClient.MulticastQueue.Client; import java.util.concurrent.ExecutorService; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; import java.util.zip.DataFormatException; import java.util.zip.Deflater; import java.util.zip.Inflater; import java.io.OutputStream; public -class MyRfbProto<ByteBuffersIterator> extends RfbProto { +class MyRfbProto extends RfbProto { final static String versionMsg_3_998 = "RFB 003.998\n"; /** * CheckMillis is one of new msgType for RFB 3.998. @@ -49,7 +52,7 @@ private int rectH; private int encoding; private int zLen; - private boolean clicomp; + private boolean clicomp = false; private ServerSocket servSock; private int acceptPort; @@ -62,12 +65,16 @@ byte[] pngBytes; - // private MulticastQueue<LinkedList<ByteBuffer>> multicastqueue = new MostRecentMultiCast<LinkedList<ByteBuffer>>(10); private MulticastQueue<LinkedList<ByteBuffer>> multicastqueue = new MulticastQueue<LinkedList<ByteBuffer>>(); private int clients = 0; private Inflater inflater = new Inflater(); + private Deflater deflater = new Deflater(); + public + MyRfbProto() throws IOException { + } + MyRfbProto(String h, int p, VncViewer v) throws IOException { super(h, p, v); cliList = new LinkedList<Socket>(); @@ -87,8 +94,20 @@ // executor = Executors.newCachedThreadPool(); // executor = Executors.newSingleThreadExecutor(); } - - + void changeParent(String h, int p) throws IOException { + host = h; + port = p; + + sock = new Socket(host, port); + is = new DataInputStream(new BufferedInputStream(sock.getInputStream(), + 16384)); + os = sock.getOutputStream(); + + timing = false; + timeWaitedIn100us = 5; + timedKbits = 0; + } + // over write void writeVersionMsg() throws IOException { clientMajor = 3; @@ -117,7 +136,7 @@ acceptPort = port; } - + // 5550を開けるが、開いてないなら+1のポートを開ける。 void selectPort(int p) { int port = p; while (true) { @@ -305,40 +324,13 @@ rectW = readU16(); // 8 rectH = readU16(); // 10 encoding = readU32(); // 12 -// System.out.println("encoding = "+encoding); - if (encoding == EncodingZRLE) + // System.out.println("encoding = "+encoding); + if (encoding == EncodingZRLE|| encoding==EncodingZRLEE||encoding==EncodingZlib) zLen = readU32(); else zLen = 0; is.reset(); -/* - int dataLen; - switch (encoding) { - case RfbProto.EncodingRaw: - dataLen = rectW * rectH * 4 + 16; - mark(dataLen); - break; - case RfbProto.EncodingCopyRect: - dataLen = 16 + 4; - mark(dataLen); - break; - case RfbProto.EncodingRRE: - case RfbProto.EncodingCoRRE: - case RfbProto.EncodingHextile: - - case RfbProto.EncodingZlib: - case RfbProto.EncodingTight: - case RfbProto.EncodingZRLE: - dataLen = zLen + 20; - mark(dataLen); - break; - default: - dataLen = 1000000; - mark(dataLen); - } - -*/ - + } int checkAndMark() throws IOException { @@ -361,6 +353,7 @@ break; case RfbProto.EncodingZlib: case RfbProto.EncodingZRLE: + case RfbProto.EncodingZRLEE: dataLen = zLen + 20; is.mark(dataLen); break; @@ -435,12 +428,7 @@ BufferedImage bimg = ImageIO.read(new ByteArrayInputStream(pngBytes)); return bimg; } -/* - void readPngData() throws IOException { - pngBytes = new byte[is.available()]; - readFully(pngBytes); - } -*/ + void printFramebufferUpdate() { System.out.println("messageType=" + messageType); @@ -479,9 +467,6 @@ System.out.println("checkMillis: " + time); } - void printStatus() { - System.out.println(); - } synchronized void changeStatusFlag() { printStatusFlag = true; @@ -536,9 +521,16 @@ while(inputIndex < inputs.size() ) { ByteBuffer b1 = inputs.get(inputIndex++); deflater.setInput(b1.array(),b1.position(),b1.remaining()); - if (inputIndex==inputs.size()) deflater.finish(); + /** + * If we finish() stream and reset() it, Deflater start new gzip stream, this makes continuous zlib reader unhappy. + * if we remove finish(), Deflater.deflate() never flushes its output. The original zlib deflate has flush flag. I'm pretty + * sure this a kind of bug of Java library. + */ + if (inputIndex==inputs.size()) + deflater.finish(); + int len1 = 0; do { - int len1 = deflater.deflate(c1.array(),c1.position(),c1.remaining()); + len1 = deflater.deflate(c1.array(),c1.position(),c1.remaining()); if (len1>0) { len += len1; c1.position(c1.position()+len1); @@ -547,7 +539,7 @@ c1 = ByteBuffer.allocate(INFLATE_BUFSIZE); } } - } while (!deflater.needsInput()&&!deflater.finished()); + } while (len1 >0 || !deflater.needsInput()); // &&!deflater.finished()); } if (c1.position()!=0) { c1.flip(); outputs.addLast(c1); @@ -566,13 +558,15 @@ *@return number of total bytes * @throws IOException */ - public int unzip(Inflater inflater, LinkedList<ByteBuffer> inputs, int inputIndex, LinkedList<ByteBuffer> outputs) + public int unzip(Inflater inflater, LinkedList<ByteBuffer> inputs, int inputIndex, LinkedList<ByteBuffer> outputs,int bufSize) throws DataFormatException { int len=0; - ByteBuffer buf = ByteBuffer.allocate(INFLATE_BUFSIZE); + ByteBuffer buf = ByteBuffer.allocate(bufSize); while (inputIndex < inputs.size()) { ByteBuffer input = inputs.get(inputIndex++); inflater.setInput(input.array(),input.position(),input.limit()); +// if (inputIndex==inputs.size()) if inflater/deflater has symmetry, we need this +// inflater.end(); but this won't work do { int len0 = inflater.inflate(buf.array(),buf.position(),buf.remaining()); if (len0>0) { @@ -581,7 +575,7 @@ if (buf.remaining()==0) { buf.flip(); outputs.addLast(buf); - buf = ByteBuffer.allocate(INFLATE_BUFSIZE); + buf = ByteBuffer.allocate(bufSize); } } } while (!inflater.needsInput()); @@ -593,6 +587,20 @@ return len; } + /** + * send data to clients + * @param dataLen + * @throws IOException + * @throws DataFormatException + * + * Zlibed packet is compressed in context dependent way, that is, it have to send from the beginning. But this is + * impossible. So we have to compress it again for each clients. Separate deflater for each clients is necessary. + * + * Java's deflater does not support flush. This means to get the result, we have to finish the compression. Reseting + * start new compression, but it is not accepted well in zlib continuous reading. So we need new Encoding ZRLEE + * which reset decoder for each packet. ZRLEE can be invisible from user, but it have to be implemented in the clients. + * ZRLEE compression is not context dependent, so no recompression is necessary. + */ void readSendData(int dataLen) throws IOException, DataFormatException { LinkedList<ByteBuffer>bufs = new LinkedList<ByteBuffer>(); ByteBuffer header = ByteBuffer.allocate(16); @@ -600,23 +608,24 @@ header.limit(16); if (header.get(0)==RfbProto.FramebufferUpdate) { int encoding = header.getInt(12); - if (encoding==RfbProto.EncodingZlib||encoding==RfbProto.EncodingZRLE) { + if (encoding==RfbProto.EncodingZRLE||encoding==RfbProto.EncodingZlib) { // ZRLEE is already recompressed ByteBuffer len = ByteBuffer.allocate(4); readFully(len.array(),0,4); len.limit(4); ByteBuffer inputData = ByteBuffer.allocate(dataLen-20); readFully(inputData.array(),0,inputData.capacity()); inputData.limit(dataLen-20); LinkedList<ByteBuffer>inputs = new LinkedList<ByteBuffer>(); inputs.add(inputData); - if (clicomp) { - unzip(inflater, inputs, 0, bufs); - } else { - Deflater nDeflater = new Deflater(); - LinkedList<ByteBuffer> out = new LinkedList<ByteBuffer>(); - unzip(inflater, inputs, 0 , out); - int len2 = zip(nDeflater, out, 0, bufs); - ByteBuffer blen = ByteBuffer.allocate(4); blen.putInt(len2); blen.flip(); - bufs.addFirst(blen); - } + + header.putInt(12, RfbProto.EncodingZRLEE); // means recompress every time + // using new Deflecter every time is incompatible with the protocol, clients have to be modified. + Deflater nDeflater = deflater; // new Deflater(); + LinkedList<ByteBuffer> out = new LinkedList<ByteBuffer>(); + unzip(inflater, inputs, 0 , out, INFLATE_BUFSIZE); + // dump32(inputs); + int len2 = zip(nDeflater, out, 0, bufs); + ByteBuffer blen = ByteBuffer.allocate(4); blen.putInt(len2); blen.flip(); + bufs.addFirst(blen); + bufs.addFirst(header); multicastqueue.put(bufs); is.reset(); @@ -642,8 +651,48 @@ // createBimgFlag = true; // rfb.addSockTmp(newCli); // addSock(newCli); + final int myId = clients; final Client <LinkedList<ByteBuffer>> c = multicastqueue.newClient(); - + final AtomicInteger writerRunning = new AtomicInteger(); + writerRunning.set(1); + /** + * Timeout thread. If a client is suspended, it has top of queue indefinitely, which caused memory + * overflow. After the timeout, we poll the queue and discard it. Start long wait if writer is running. + */ + final Runnable timer = new Runnable() { + public void run() { + int count = 0; + for(;;) { + long timeout = 30000/8; + try { + synchronized(this) { + int state,flag; + writerRunning.set(0); + wait(timeout); + flag = 0; + while((state=writerRunning.get())==0) { + c.poll(); // discard, should be timeout + count++; + if (flag==0) { + System.out.println("Discarding "+myId + " count="+ count); flag = 1; + } + wait(10); // if this is too short, writer cannot take the poll, if this is too long, memory will overflow... + } + if (flag==1) System.out.println("Resuming "+myId + " count="+count); + if (state!=1) { + System.out.println("Client died "+myId); + break; + } + } + } catch (InterruptedException e) { + } + } + } + }; + new Thread(timer).start(); + /** + * discard all incoming from clients + */ final Runnable reader = new Runnable() { public void run() { byte b[] = new byte[4096]; @@ -651,9 +700,10 @@ try { int c = is.read(b); if (c<=0) throw new IOException(); - System.out.println("client read "+c); + // System.out.println("client read "+c); } catch (IOException e) { try { + writerRunning.set(2); os.close(); is.close(); } catch (IOException e1) { @@ -663,12 +713,12 @@ } } }; + /** + * send packets to a client + */ Runnable sender = new Runnable() { - - public void run() { - - Deflater deflater = new Deflater(); + writerRunning.set(1); try { /** * initial connection of RFB protocol @@ -680,65 +730,93 @@ sendSecResult(os); readClientInit(is); sendInitData(os); - new Thread(reader).start(); + new Thread(reader).start(); // discard incoming packet here after. for (;;) { LinkedList<ByteBuffer> bufs = c.poll(); int inputIndex = 0; - ByteBuffer header = bufs.get(inputIndex++); + ByteBuffer header = bufs.get(inputIndex); if (header==null) continue; if (header.get(0)==RfbProto.FramebufferUpdate) { - System.out.println("client "+ clients); - int encoding = header.getInt(12); - if (encoding==RfbProto.EncodingZlib||encoding==RfbProto.EncodingZRLE) { - LinkedList<ByteBuffer> outs; - if (clicomp) { - outs = new LinkedList<ByteBuffer>(); - int len2 = zip(deflater, bufs, inputIndex, outs); - ByteBuffer blen = ByteBuffer.allocate(4); blen.putInt(len2); blen.flip(); - outs.addFirst(blen); - outs.addFirst(header); - inputIndex = 0; - } else { - outs = bufs; - inputIndex = 0; - } - while(inputIndex < outs.size()) { - ByteBuffer out= outs.get(inputIndex++); - os.write(out.array(),out.position(),out.limit()); - } - } - if (encoding==RfbProto.EncodingRaw) { - LinkedList<ByteBuffer> outs = bufs; - inputIndex = 0; - while( inputIndex < outs.size()){ - ByteBuffer out = outs.get(inputIndex++); - os.write(out.array(), out.position(), out.limit()); - } - } - os.flush(); - continue; + // System.out.println("client "+ myId); } - os.write(header.array(),header.position(),header.limit()); - while(inputIndex < bufs.size()) { - ByteBuffer b = bufs.get(inputIndex++); - os.write(b.array(), b.position(), b.limit()); - } - os.flush(); + writeToClient(os, bufs, inputIndex); + writerRunning.set(1); // yes my client is awaking. } } catch (IOException e) { try { + writerRunning.set(2); os.close(); } catch (IOException e1) { } /* if socket closed cliList.remove(newCli); */ } } + + public void writeToClient(final OutputStream os, + LinkedList<ByteBuffer> bufs, int inputIndex) + throws IOException { + while(inputIndex < bufs.size()) { + ByteBuffer b = bufs.get(inputIndex++); + os.write(b.array(), b.position(), b.limit()); + } + os.flush(); + } }; clients++; new Thread(sender).start(); } + + public void dump32(LinkedList<ByteBuffer>bufs) { + int len =0; + for(ByteBuffer b: bufs) len += b.remaining(); + ByteBuffer top = bufs.getFirst(); + ByteBuffer end = bufs.getLast(); + System.err.println("length: "+len); + System.err.print("head 0: "); + for(int i = 0; i<16 && i < top.remaining(); i++) { + System.err.print(" "+ top.get(i)); + } + System.err.print("tail 0: "); + for(int i = 0; i<16 && i < end.remaining(); i++) { + System.err.print(" "+end.get(i)); + } + System.err.println(); + } + + private Iterable<Byte> byteBufferIterator(final LinkedList<ByteBuffer> in) { + return new Iterable<Byte>() { + public Iterator<Byte> iterator() { + return new Iterator<Byte>() { + int bytes = 0; + int buffers = 0; + public boolean hasNext() { + for(;;) { + if (buffers>=in.size()) return false; + ByteBuffer b = in.get(buffers); + if (! (bytes<b.remaining())) { + buffers ++; bytes=0; + } else return true; + } + } + public Byte next() { + ByteBuffer bf =in.get(buffers); + byte b = bf.get(bytes++); + if (bf.remaining()<=bytes) { + buffers++; + bytes = 0; + } + // System.out.print(b); + return b; + } + public void remove() { + } + }; + } + }; + } + }
--- a/src/myVncClient/MyVncClient.java Sat Aug 06 23:34:37 2011 +0900 +++ b/src/myVncClient/MyVncClient.java Sun Aug 07 04:22:07 2011 +0900 @@ -10,7 +10,7 @@ WindowListener { /** - * + * e */ private static final long serialVersionUID = 1L; boolean inAnApplet = true; @@ -19,7 +19,7 @@ String parent, treenum; private String leaderflag; boolean runflag = false; - + boolean first = true; // // main() is called when run as a java program from the command line. // It simply runs the applet inside a newly-created frame. @@ -107,7 +107,12 @@ try { - connectAndAuthenticate(); + if (first) { + connectAndAuthenticate(); + first = false; + }else { + reConnectAndAuthenticate(); + } accThread = new Thread(new AcceptThread(rfb, 5999)); accThread.start(); @@ -130,10 +135,9 @@ */ int counter = 0; - // window を消してnullを突っ込んでGCで削除させる。 - /* - * vncFrame.setVisible(false); vncFrame = null; - */ + vncFrame.setVisible(false); + vncFrame.dispose(); + while (true) { /** * if my last node case reconnectoion stop @@ -158,7 +162,7 @@ } counter++; } - + // System.exit(0); } catch (Exception e) { System.out.println(e); @@ -375,6 +379,51 @@ } } + 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); + + 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).
--- a/src/myVncClient/RfbProto.java Sat Aug 06 23:34:37 2011 +0900 +++ b/src/myVncClient/RfbProto.java Sun Aug 07 04:22:07 2011 +0900 @@ -26,18 +26,16 @@ // import java.io.*; -import java.awt.*; import java.awt.event.*; import java.net.Socket; -import java.net.ServerSocket; import java.util.zip.*; -import java.nio.*; class RfbProto { final static String versionMsg_3_3 = "RFB 003.003\n", versionMsg_3_7 = "RFB 003.007\n", versionMsg_3_8 = "RFB 003.008\n"; + // Vendor signatures: standard VNC/RealVNC, TridiaVNC, and TightVNC final static String StandardVendor = "STDV", TridiaVncVendor = "TRDV", TightVncVendor = "TGHT"; @@ -77,8 +75,8 @@ // Supported encodings and pseudo-encodings final static int EncodingRaw = 0, EncodingCopyRect = 1, EncodingRRE = 2, - EncodingCoRRE = 4, EncodingHextile = 5, EncodingZlib = 6, - EncodingTight = 7, EncodingZRLE = 16, + EncodingCoRRE = 4, EncodingHextile = 5, EncodingZlib = 6, + EncodingTight = 7, EncodingZRLEE = 15, EncodingZRLE = 16, EncodingCompressLevel0 = 0xFFFFFF00, EncodingQualityLevel0 = 0xFFFFFFE0, EncodingXCursor = 0xFFFFFF10, EncodingRichCursor = 0xFFFFFF11, EncodingPointerPos = 0xFFFFFF18, @@ -87,6 +85,7 @@ SigEncodingCopyRect = "COPYRECT", SigEncodingRRE = "RRE_____", SigEncodingCoRRE = "CORRE___", SigEncodingHextile = "HEXTILE_", SigEncodingZlib = "ZLIB____", SigEncodingTight = "TIGHT___", + SigEncodingZRLEE = "ZRLEE___", SigEncodingZRLE = "ZRLE____", SigEncodingCompressLevel0 = "COMPRLVL", SigEncodingQualityLevel0 = "JPEGQLVL", @@ -176,9 +175,6 @@ // private boolean closed; protected boolean closed; - public RfbProto(){ - } - // // Constructor. Make TCP connection to RFB server. // @@ -226,7 +222,11 @@ timedKbits = 0; } - + public RfbProto() { + + } + + synchronized void close() { try { @@ -469,13 +469,16 @@ encodingCaps.add(EncodingHextile, StandardVendor, SigEncodingHextile, "Standard Hextile encoding"); encodingCaps.add(EncodingZRLE, StandardVendor, SigEncodingZRLE, - "Standard ZRLE encoding"); + "Standard ZRLE encoding"); + encodingCaps.add(EncodingZRLEE, StandardVendor, SigEncodingZRLEE, + "Standard ZRLE(E) encoding"); encodingCaps.add(EncodingZlib, TridiaVncVendor, SigEncodingZlib, "Zlib encoding"); encodingCaps.add(EncodingTight, TightVncVendor, SigEncodingTight, "Tight encoding"); // Supported pseudo-encoding types + encodingCaps.add(EncodingCompressLevel0, TightVncVendor, SigEncodingCompressLevel0, "Compression level"); encodingCaps.add(EncodingQualityLevel0, TightVncVendor, @@ -490,6 +493,7 @@ "LastRect protocol extension"); encodingCaps.add(EncodingNewFBSize, TightVncVendor, SigEncodingNewFBSize, "Framebuffer size change"); + } // @@ -562,9 +566,13 @@ void writeClientInit() throws IOException { /* if (viewer.options.shareDesktop) { +*/ + + /** + * shared flag + */ os.write(1); -*/ - os.write(0); +// os.write(0); // viewer.options.disableShareDesktop(); } @@ -692,6 +700,8 @@ void readFramebufferUpdate() throws IOException { skipBytes(1); updateNRects = readU16(); + // System.out.println(updateNRects); + // If the session is being recorded: if (rec != null) { rec.writeByte(FramebufferUpdate); @@ -716,6 +726,7 @@ if (updateRectEncoding == EncodingZlib || updateRectEncoding == EncodingZRLE + || updateRectEncoding == EncodingZRLEE || updateRectEncoding == EncodingTight) wereZlibUpdates = true; @@ -948,6 +959,8 @@ final static int META_MASK = InputEvent.META_MASK; final static int ALT_MASK = InputEvent.ALT_MASK; + + // // Write a pointer event message. We may need to send modifier key events // around it to set the correct modifier state. @@ -1205,7 +1218,7 @@ if (!down) writeModifierKeyEvents(0); - //os.write(eventBuf, 0, eventBufLen); + os.write(eventBuf, 0, eventBufLen); } // @@ -1378,5 +1391,4 @@ numBytesRead += 4; return r; } - }