Mercurial > hg > Members > nobuyasu > tightVNCProxy
changeset 133:acd88e63854b
modify 128
author | Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 30 Aug 2011 06:49:49 +0900 |
parents | 4297c2011b71 (diff) fa2122e5c807 (current diff) |
children | c3ae65fea76a |
files | src/myVncProxy/MyRfbProto.java src/myVncProxy/ProxyVncCanvas.java src/myVncProxy/RfbProto.java src/myVncProxy/VncProxyService.java |
diffstat | 52 files changed, 838 insertions(+), 498 deletions(-) [+] |
line wrap: on
line diff
--- a/.classpath Tue Aug 02 20:15:01 2011 +0900 +++ b/.classpath Tue Aug 30 06:49:49 2011 +0900 @@ -2,5 +2,6 @@ <classpath> <classpathentry kind="src" path="src"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> + <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/> <classpathentry kind="output" path="bin"/> </classpath>
--- a/src/myVncProxy/AcceptClient.java Tue Aug 02 20:15:01 2011 +0900 +++ b/src/myVncProxy/AcceptClient.java Tue Aug 30 06:49:49 2011 +0900 @@ -6,215 +6,235 @@ import java.util.*; public class AcceptClient extends Thread { - int counter = 0 , parentnum = 0/*落ちたときの親の番号をカウントするためのもの*/; + int counter = 0, parentnum = 0/* 落ちたときの親の番号をカウントするためのもの */; LinkedList<String> ls = new LinkedList<String>(); - boolean runflag =false; - private String name; - boolean addrRegistor=true; + boolean runflag = false; + private String name; + boolean addrRegistor = true; public AcceptClient(String _name) { name = _name; } + public AcceptClient() { new CreateThread(this); } - - public synchronized void gethost(BufferedReader is,PrintStream os) { - String line,port; - int intv_time = 100; - String request; - int treebranch = 2;//treeの子ノードの数 - String leaderflag="0",sendleaderflag="0";//Socket send standardization String - + + // public synchronized void transferParentAddrerss(BufferedReader + // is,PrintStream os) { + public synchronized void transferParentAddrerss(BufferedReader is,PrintStream os) { + String line, port; + int intv_time = 100; + String request; + int treebranch = 2;// treeの子ノードの数 + String leaderflag = "0", sendleaderflag = "0"; // クライアントからのメッセージを待ち、受け取ったメッセージをそのまま返す - try { - while (true) { - line = is.readLine(); - port = is.readLine(); - - System.out.println("データーを受信しましたlin="+line+" port="+port); - //自分の IPADRESSを取得する - InetAddress addr = InetAddress.getLocalHost(); - String add = new String(addr.getHostAddress()); + try { + while (true) { + line = is.readLine(); + port = is.readLine(); + + System.out.println("データーを受信しましたlin=" + line + + " port=" + port); + // 自分の IPADRESSを取得する + InetAddress addr = InetAddress.getLocalHost(); + String add = new String(addr.getHostAddress()); + + if ("1".equals(line)) { + System.out.println("親が落ちましたmessage" + port); + String checkRepetition = is.readLine(); + os.println(ls.getLast()); + parentnum = (Integer.parseInt(port) - 1) + / treebranch; + String newparent = ls.get(parentnum); + + counter--; + runflag = true; + + sendleaderflag = decisionLeader( + Integer.parseInt(port), treebranch); + + Child report = new Child(); - if("1".equals(line)) { - System.out.println("親が落ちましたmessage" + port); - os.println(ls.getLast()); - parentnum = (Integer.parseInt(port) -1) / treebranch; - String hidenchild=ls.getLast(); - String newparent=ls.get(parentnum); - listupdate(port); - counter--; - runflag = true; - - if((counter-1)%treebranch==1) { // children in most young treenum have leaderflag 1 other 0 - sendleaderflag = "1"; - } else { - sendleaderflag = "0"; - } + report.reportLastNode(ls.getLast(), newparent, + port, String.valueOf(parentnum), + sendleaderflag, counter); + + listupdate(port); + + int g = 0; + for (String bs : ls) { + System.out.println(g + "番目" + bs); + g++; + } + + os.println(port); + // os.println(leaderflag); + + leaderflag = decisionLeader( + Integer.parseInt(checkRepetition), + treebranch); + + if (Integer.parseInt(checkRepetition) == counter + 1) { + checkRepetition = "stop"; + } else { + checkRepetition = "go"; + } + os.println(checkRepetition); + + // os.println(leaderflag); + Thread.sleep(intv_time); + is.close(); + os.close(); - Child report = new Child(); - - report.reportLastNode(hidenchild,newparent,port,String.valueOf(parentnum), - sendleaderflag,counter); - - os.println(port); - Thread.sleep(intv_time); - is.close(); - os.close(); + } else if ("2".equals(line)) { + parentnum = (Integer.parseInt(port) - 1) + / treebranch; + String newparent = ls.get(parentnum); + + outputStream(os, newparent, + String.valueOf(parentnum), + String.valueOf(counter), leaderflag); + + os.close(); + is.close(); + } else if ("3".equals(line)) { + String checkRepetition = is.readLine(); + System.out.println("落ちたのを確認しました"); + + os.println(ls.get(Integer.parseInt(port))); + os.println(port); + + if (checkRepetition.equals(ls.getLast())) { + checkRepetition = "stop"; + } else { + checkRepetition = "go"; + } + os.println(checkRepetition); - } else if("2".equals(line)) { - parentnum = (Integer.parseInt(port) -1) / treebranch; - String newparent=ls.get(parentnum); - - outputStream(os,newparent,String.valueOf(parentnum), - String.valueOf(counter),leaderflag); - - os.close(); - is.close(); - } else if("3".equals(line)) { - System.out.println("落ちたのを確認しました"); + System.out.println("num4=" + + ls.get(Integer.parseInt(port))); + line = null; + runflag = false; + is.close(); + os.close(); + } else { + if (addrRegistor == true) { + ls.add(add); + addrRegistor = false; + } + + if (line != null) { + addClientAdress(line, ls); + counter++; + } else { + break; + } - os.println(ls.get(Integer.parseInt(port))); - os.println(port); - int g = 0; - for(String bs: ls){ - System.out.println(g+"番目"+bs); - g++; + if (counter >= treebranch + 1) { + + leaderflag = decisionLeader(counter, treebranch); + parentnum = (counter - 1) / treebranch; + + request = ls.get(parentnum); + System.out.println(parentnum); + + outputStream(os, request, + String.valueOf(parentnum), + String.valueOf(counter), leaderflag); + + checkParameter(parentnum, counter, leaderflag); + } else { + // treeの親ノードに接続する人に接続する人を教える + outputStream(os, add, "0", + String.valueOf(counter), leaderflag); + } + Thread.sleep(intv_time); } - System.out.println("num4=" + ls.get(Integer.parseInt(port))); - line=null; - runflag = false; - is.close(); - os.close(); - } else { - if(addrRegistor==true){ - ls.add(add); - addrRegistor = false; - } - System.out.println(parentnum); - if(line != null) { - arg(line,ls); - counter++; - } else { - break; - } + } + + } catch (IOException e) { + System.out.println(e); + } - if(counter>=treebranch+1) { - if((counter-1)%treebranch==0) { - leaderflag = "1"; - } else { - leaderflag = "0"; - } - - parentnum = (counter - 1) / treebranch; - // request = [p-1]; - request = ls.get(parentnum); - - outputStream(os,request,String.valueOf(parentnum), - String.valueOf(counter),leaderflag); - - checkParameter(parentnum,counter,leaderflag); - } else { - //treeの親ノードに接続する人に接続する人を教える - outputStream(os,name,"0",String.valueOf(counter), - leaderflag); - } - Thread.sleep(intv_time); - } + catch (InterruptedException e) { + e.printStackTrace(); } - - } catch (IOException e) { - System.out.println(e); - } - - catch(InterruptedException e) { - e.printStackTrace(); - } - /* - try{ - echoServer.close(); - } - catch (IOException e){ - System.out.println(e); - } - */ - //} comment out while + + } - + /** * @param port - * parent value + * parent value */ void listupdate(String port) { ls.remove(Integer.parseInt(port)); - ls.add(Integer.parseInt(port),ls.getLast()); + ls.add(Integer.parseInt(port), ls.getLast()); ls.removeLast(); } - void outputStream(PrintStream os,String request,String parentnum,String treenum,String leaderflag) { + void outputStream(PrintStream os, String request, String parentnum, + String treenum, String leaderflag) { os.println(request); os.println(parentnum); os.println(treenum); os.println(leaderflag); } - - void checkParameter(int parent,int counter,String leaderflag) { - System.out.println("pの値="+parentnum); - System.out.println("iの値="+counter); - System.out.println("leaderflag="+leaderflag + "\n"); + + void checkParameter(int parent, int counter, String leaderflag) { + System.out.println("pの値=" + parentnum); + System.out.println("iの値=" + counter); + System.out.println("leaderflag=" + leaderflag + "\n"); } - - void arg(String line,LinkedList<String> ls) { - if(line != null){ + + void addClientAdress(String line, LinkedList<String> ls) { + int g = 0; + if (line != null) { ls.add(line); } - int g=0; - - for(String bs: ls){ - System.out.println(g+"番目"+bs); + for (String bs : ls) { + System.out.println(g + "番目" + bs); g++; } } - + + String decisionLeader(int counter, int treebranch) { + if ((counter - 1) % treebranch == 1) { // children in most young treenum + // have leaderflag 1 other 0 + return "0"; + } else { + return "1"; + } + } + } -/* -class sock { - void arg(String line,LinkedList<String> ls) { - if(line != null){ - ls.add(line); - } - int g=0; +class Child { - for(String bs: ls){ - System.out.println(g+"番目"+bs); - g++; - } - } -} -*/ -class Child{ - - void reportLastNode(String hiddenchild,String newparent,String newtreenum,String newpnum,String newleaderflag,int i) throws IOException{ + void reportLastNode(String hiddenchild, String newparent, + String newtreenum, String newpnum, String newleaderflag, int i) + throws IOException { try { Socket echoSocket; System.out.println(hiddenchild + "に接続します"); - echoSocket = new Socket(hiddenchild, 10001 + (i + 1));//i+1は実験中に同じマシーンを使っていたのでportを変えて対応、本番時には取り除く予定。 + echoSocket = new Socket(hiddenchild, 10001 + (i + 1));// i+1は実験中に同じマシーンを使っていたのでportを変えて対応、本番時には取り除く予定。 - DataOutputStream os = new DataOutputStream(echoSocket.getOutputStream()); + DataOutputStream os = new DataOutputStream( + echoSocket.getOutputStream()); - os.writeBytes(newparent+"\n"); - os.writeBytes(newpnum+"\n"); - os.writeBytes(newtreenum+"\n"); - os.writeBytes(newleaderflag+"\n"); - + os.writeBytes(newparent + "\n"); + os.writeBytes(newpnum + "\n"); + os.writeBytes(newtreenum + "\n"); + os.writeBytes(newleaderflag + "\n"); + os.close(); } catch (UnknownHostException e) { System.err.println("Don't know about host: localhost"); } catch (IOException e) { - System.err.println("Couldn't get I/O for the connection to: localhost"); + System.err + .println("Couldn't get I/O for the connection to: localhost"); } }
--- a/src/myVncProxy/AcceptThread.java Tue Aug 02 20:15:01 2011 +0900 +++ b/src/myVncProxy/AcceptThread.java Tue Aug 30 06:49:49 2011 +0900 @@ -1,4 +1,4 @@ -package myVncProxy; + package myVncProxy; import java.net.Socket; import java.io.IOException; import java.io.InputStream; @@ -7,13 +7,19 @@ public class AcceptThread implements Runnable { MyRfbProto rfb; byte[] imageBytes; - + int port; + AcceptThread(MyRfbProto _rfb) { rfb = _rfb; } + AcceptThread(MyRfbProto _rfb, int p) { + rfb = _rfb; + port = p; + } + public void run() { - rfb.selectPort(); + rfb.selectPort(port); while (true) { try { Socket newCli = rfb.accept();
--- a/src/myVncProxy/CreateThread.java Tue Aug 02 20:15:01 2011 +0900 +++ b/src/myVncProxy/CreateThread.java Tue Aug 30 06:49:49 2011 +0900 @@ -4,47 +4,79 @@ import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; +import java.net.BindException; import java.net.ServerSocket; import java.net.Socket; - - public class CreateThread implements Runnable { ServerSocket echoServer; AcceptClient acceptClient; + int port; + public CreateThread(AcceptClient _acc) { + acceptClient = _acc; + port = 9999; + } + + public CreateThread(AcceptClient _acc , int port) { + acceptClient = _acc; + this.port = port; + } - public CreateThread(AcceptClient _acc){ - acceptClient = _acc; + void newEchoClient(final BufferedReader is,final PrintStream os) { + Runnable echoSender = new Runnable() { + public void run() { + acceptClient.transferParentAddrerss(is,os); + } + }; + new Thread(echoSender).start(); + } + + void selectPort(int p) { + int port = p; + while (true) { + try { + initServSock(port); + break; + } catch (BindException e) { + port++; + continue; + } catch (IOException e) { + + } + } + System.out.println("accept Echo port = " + port); + } + + void initServSock(int port) throws IOException { + echoServer = new ServerSocket(port); + this.port = port; } public void run() { + selectPort(port); while (true) { - try { - echoServer = new ServerSocket(9999); - } - catch (IOException e) { +// echoServer = new ServerSocket(9999); + Socket clientSocket = echoServer.accept(); + BufferedReader is = new BufferedReader(new InputStreamReader( + clientSocket.getInputStream())); + PrintStream os = new PrintStream(clientSocket.getOutputStream()); + newEchoClient(is,os); +// acceptClient.transferParentAddrerss(is, os); + } catch (IOException e) { System.out.println(e); } +/* try { - Socket clientSocket = echoServer.accept(); - BufferedReader is = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); - PrintStream os = new PrintStream(clientSocket.getOutputStream()); - acceptClient.gethost(is,os); - } catch (IOException e){ - e.printStackTrace(); + echoServer.close(); + } catch (IOException e) { System.out.println(e); } - try { - echoServer.close(); - } - catch (IOException e){ - System.out.println(e); - } - +*/ + } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/myVncProxy/MostRecentMultiCast.java Tue Aug 30 06:49:49 2011 +0900 @@ -0,0 +1,27 @@ +package myVncProxy; + +import java.util.LinkedList; + + +public class MostRecentMultiCast<T> extends MulticastQueue<T> { + + LinkedList<Node<T>> alive; + int count = 0; + MostRecentMultiCast(int limit) { + count = limit; + this.alive = new LinkedList<Node<T>>(); + } + + @Override + public synchronized void put(T item) + { + Node<T> next = new Node<T>(item); + tail.set(next); + tail = next; + alive.addLast(next); + if (alive.size()>count) { + Node<T> old = alive.getFirst(); + old.clear(); + } + } +}
--- a/src/myVncProxy/MulticastQueue.java Tue Aug 02 20:15:01 2011 +0900 +++ b/src/myVncProxy/MulticastQueue.java Tue Aug 30 06:49:49 2011 +0900 @@ -33,21 +33,24 @@ node = tail; } - public T poll() + synchronized public T poll() { Node<T> next = null; - - try { - next = node.next(); - }catch(InterruptedException _e){ - _e.printStackTrace(); - } - node = next; - return next.item; + T item = null; + do { + try { + next = node.next(); + }catch(InterruptedException _e){ + continue; + } + item = node.getItem(); + node = next; + } while ( item == null); + return item; } } - private static class Node<T> + static class Node<T> { private T item; private Node<T> next; @@ -60,6 +63,10 @@ latch = new CountDownLatch(1); } + synchronized public T getItem() { + return item; + } + public void set(Node<T> next) { this.next = next; @@ -71,5 +78,9 @@ latch.await(); return next; } + + synchronized public void clear() { + item = null; + } } }
--- a/src/myVncProxy/MyRfbProto.java Tue Aug 02 20:15:01 2011 +0900 +++ b/src/myVncProxy/MyRfbProto.java Tue Aug 30 06:49:49 2011 +0900 @@ -1,36 +1,46 @@ package myVncProxy; +import static org.junit.Assert.*; + import java.awt.Graphics; import java.awt.Image; import java.awt.image.BufferedImage; -import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.BindException; import java.net.ServerSocket; import java.net.Socket; +import java.nio.ByteBuffer; +import java.util.Iterator; import java.util.LinkedList; import javax.imageio.ImageIO; +import org.junit.Test; + import myVncProxy.MulticastQueue.Client; import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; +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 extends RfbProto { final static String versionMsg_3_998 = "RFB 003.998\n"; /** * CheckMillis is one of new msgType for RFB 3.998. */ - final static int SpeedCheckMillis = 4; + final static byte SpeedCheckMillis = 4; + private static final int INFLATE_BUFSIZE = 1024*100; boolean printStatusFlag = false; long startCheckTime; @@ -41,51 +51,44 @@ private int rectW; private int rectH; private int encoding; - private int bytesPixel; + private int zLen; + private boolean clicomp = false; private ServerSocket servSock; private int acceptPort; private byte initData[]; private LinkedList<Socket> cliListTmp; private LinkedList<Socket> cliList; - private LinkedList<Thread> sendThreads; boolean createBimgFlag; - boolean sendFlag = true; + ExecutorService executor; - // override viewer to VncProxyService from VncViewer - VncProxyService viewer; - byte[] pngBytes; - private MulticastQueue<byte[]> multicastqueue = new MulticastQueue<byte[]>(); - + // 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(); + private CreateThread geth; + + public + MyRfbProto() throws IOException { + } + MyRfbProto(String h, int p, VncViewer v) throws IOException { super(h, p, v); - cliList = new LinkedList<Socket>(); - cliListTmp = new LinkedList<Socket>(); - createBimgFlag = false; - // sendThreads = new LinkedList<Thread>(); - // executor = Executors.newCachedThreadPool(); - // executor = Executors.newSingleThreadExecutor(); } - MyRfbProto(String h, int p, VncProxyService v) throws IOException { + MyRfbProto(String h, int p, CreateThread geth) throws IOException { super(h, p); - viewer = v; + this.geth = geth; } - + MyRfbProto(String h, int p) throws IOException { super(h, p); - cliList = new LinkedList<Socket>(); - cliListTmp = new LinkedList<Socket>(); - createBimgFlag = false; - // sendThreads = new LinkedList<Thread>(); - // executor = Executors.newCachedThreadPool(); - // executor = Executors.newSingleThreadExecutor(); } - - + // over write void writeVersionMsg() throws IOException { clientMajor = 3; @@ -114,21 +117,21 @@ acceptPort = port; } - // open port 5999 for to accept client. - void selectPort() { - int i = 5999;// i = 5550; + // 5999を開けるが、開いてないなら+1のポートを開ける。 + void selectPort(int p) { + int port = p; while (true) { try { - initServSock(i); + initServSock(port); break; } catch (BindException e) { - i++; + port++; continue; } catch (IOException e) { } } - System.out.println("accept port = " + i); + System.out.println("accept port = " + port); } int getAcceptPort() { @@ -206,7 +209,7 @@ os.write(versionMsg_3_998.getBytes()); } - void readVersionMsg(InputStream is) throws IOException { + void readVersionMsg(InputStream is, OutputStream os) throws IOException { byte[] b = new byte[12]; @@ -229,6 +232,16 @@ "RFB server does not support protocol version 3"); } + if (serverMinor == 998) { + sendPortNumber(os); + } + + } + + void sendPortNumber(OutputStream os) throws IOException { + byte[] b = new byte[4]; + b = castIntByte(geth.port); + os.write(b); } void sendSecurityType(OutputStream os) throws IOException { @@ -259,20 +272,6 @@ os.write(initData); } - void sendData(byte b[]) { - try { - multicastqueue.put(b); - - /* - * // for(Socket cli : cliList){ // try{ // - * cli.getOutputStream().write(b, 0, b.length); // - * }catch(IOException e){ // // if socket closed // - * cliList.remove(cli); // } // } - */ - // System.out.println("cliSize="+cliSize()); - } catch (Exception e) { - } - } void sendPngImage() { try { @@ -304,77 +303,50 @@ System.out.println("numBytesRead=" + numBytesRead); } - void bufResetSend(int size) throws IOException { - is.reset(); - byte buffer[] = new byte[size]; - readFully(buffer); - sendData(buffer); - } void regiFramebufferUpdate() throws IOException { - is.mark(30); - messageType = readU8(); - skipBytes(1); - rectangles = readU16(); - rectX = readU16(); - rectY = readU16(); - rectW = readU16(); - rectH = readU16(); - encoding = readU32(); + is.mark(20); + messageType = readU8(); // 0 + skipBytes(1); // 1 + rectangles = readU16(); // 2 + rectX = readU16(); // 4 + rectY = readU16(); // 6 + rectW = readU16(); // 8 + rectH = readU16(); // 10 + encoding = readU32(); // 12 +// System.out.println("encoding = "+encoding); + if (encoding == EncodingZRLE|| encoding==EncodingZRLEE||encoding==EncodingZlib) + zLen = readU32(); + else + zLen = 0; + is.reset(); + } + + int checkAndMark() throws IOException { int dataLen; switch (encoding) { case RfbProto.EncodingRaw: dataLen = rectW * rectH * 4 + 16; - break; - case RfbProto.EncodingTight: - dataLen = 4000000; +// is.mark(dataLen); break; - case RfbProto.EncodingZRLE: - int zLen = readU32(); - dataLen = zLen + 20; + case RfbProto.EncodingCopyRect: + dataLen = 16 + 4; +// is.mark(dataLen); break; case RfbProto.EncodingRRE: case RfbProto.EncodingCoRRE: case RfbProto.EncodingHextile: - dataLen = rectW * rectH * 4 + 16; + case RfbProto.EncodingTight: + dataLen = zLen + 20; +// is.mark(dataLen); break; case RfbProto.EncodingZlib: - default: - dataLen = rectW * rectH * 4 + 16; - break; - } - System.out.println("dataLen = "+dataLen); - is.reset(); - is.mark(dataLen); - - } - - - int checkAndMark() throws IOException { -/* - int dataLen; - switch (encoding) { - case RfbProto.EncodingRaw: - dataLen = rectW * rectH * 4 + 16; - is.mark(dataLen); - break; - case RfbProto.EncodingCopyRect: - dataLen = 16 + 4; - is.mark(dataLen); - break; - case RfbProto.EncodingRRE: - case RfbProto.EncodingCoRRE: - case RfbProto.EncodingHextile: - case RfbProto.EncodingZlib: - case RfbProto.EncodingTight: + case RfbProto.EncodingZRLE: + case RfbProto.EncodingZRLEE: dataLen = zLen + 20; - is.mark(dataLen); - break; - case RfbProto.EncodingZRLE: - dataLen = zLen + 20; - is.mark(dataLen); +// is.mark(dataLen); break; case RfbProto.EncodingXCursor: case RfbProto.EncodingRichCursor: @@ -382,50 +354,23 @@ int u8Array = (int)Math.floor((rectW + 7)/8) * rectH; dataLen = pixArray + u8Array; printFramebufferUpdate(); - is.mark(dataLen); +// is.mark(dataLen); break; default: dataLen = 1000000; - is.mark(dataLen); +// is.mark(dataLen); } return dataLen; -*/ - return 0; } - void readSendData(int dataLen) throws IOException { - byte buffer[] = new byte[dataLen]; - readFully(buffer); - multicastqueue.put(buffer); - is.reset(); -/* - for (Socket cli : cliList) { - try { - OutputStream out = cli.getOutputStream(); - executor.execute(new SendThread(out, buffer)); - } catch (IOException e) { - // if client socket closed - cliListTmp.remove(cli); - } catch (Exception e) { - - } - - } -*/ - } - void sendDataToClient() throws IOException { + void sendDataToClient() throws Exception { regiFramebufferUpdate(); + printFramebufferUpdate(); int dataLen = checkAndMark(); readSendData(dataLen); } - void sendDataToClient(int num) throws IOException { - bytesPixel = num; - regiFramebufferUpdate(); - int dataLen = checkAndMark(); - readSendData(dataLen); - } BufferedImage createBufferedImage(Image img) { BufferedImage bimg = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_RGB); @@ -475,28 +420,26 @@ 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); System.out.println("rectangles=" + rectangles); System.out.println("encoding=" + encoding); - System.out.println("rectX = "+ rectX +": rectY = "+rectY); - System.out.println("rectW = "+ rectW +": rectH = "+rectH); - System.out.println("rectW * rectH = " + rectW * rectH); + System.out.println("rectX = "+rectX+": rectY = "+rectY); + System.out.println("rectW = "+rectW+": rectH = "+rectH); switch (encoding) { case RfbProto.EncodingRaw: - int dataLen = rectW * rectH * 4 + 16; - System.out.println("rectW * rectH * 4 + 16 = " + (rectW * rectH * 4 + 16)); + System.out.println("rectW * rectH * 4 + 16 =" + rectW * rectH * 4 + + 16); break; default: } } + int returnMsgtype() { + return messageType; + } + void readSpeedCheck() throws IOException { byte[] b = new byte[1]; @@ -504,12 +447,14 @@ } void startSpeedCheck() { - byte[] b = new byte[2]; - b[0] = (byte) SpeedCheckMillis; - b[1] = (byte) 0; + ByteBuffer b = ByteBuffer.allocate(10); + b.put((byte)SpeedCheckMillis); + b.flip(); startCheckTime = System.currentTimeMillis(); System.out.println("startChckTime = "+ startCheckTime); - multicastqueue.put(b); + LinkedList<ByteBuffer>bufs = new LinkedList<ByteBuffer>(); + bufs.add(b); + multicastqueue.put(bufs); } void endSpeedCheck() { @@ -518,9 +463,6 @@ System.out.println("checkMillis: " + time); } - void printStatus() { - System.out.println(); - } synchronized void changeStatusFlag() { printStatusFlag = true; @@ -534,93 +476,9 @@ changeStatusFlag(); } } - void require() throws IOException { - sendFlag = false; - System.out.println("setEncodingRaw()"); - setEncodingRaw(); - writeFramebufferUpdateRequest(0, 0, - 16, 16, false); - System.out.println("setEncodingZRLE()"); - setEncodingZRLE(); - System.out.println("writeFramebufferUpdateRequest"); - writeFramebufferUpdateRequest(0, 0, - framebufferWidth, framebufferHeight, false); - } - - void setEncodingRaw() throws IOException{ - byte[] b = new byte[4 + 4]; - - b[0] = (byte) SetEncodings; - b[2] = (byte) ((1 >> 8) & 0xff); - b[3] = (byte) (1 & 0xff); - - b[4] = (byte)0; - b[5] = (byte)0; - b[6] = (byte)0; - b[7] = (byte)0; - - os.write(b); - - } - - void setEncodingZRLE() throws IOException{ - byte[] b = new byte[4 + 4]; - - b[0] = (byte) SetEncodings; - b[2] = (byte) ((1 >> 8) & 0xff); - b[3] = (byte) (1 & 0xff); - - b[4] = (byte)0; - b[5] = (byte)0; - b[6] = (byte)0; - b[7] = (byte)16; - - os.write(b); - - } - void newClient(AcceptThread acceptThread, final Socket newCli, - final OutputStream os, final InputStream is) throws IOException { - // createBimgFlag = true; - // rfb.addSockTmp(newCli); - // addSock(newCli); - final Client<byte[]> c = multicastqueue.newClient(); - require(); - Runnable sender = new Runnable() { - public void run() { - try { - /** - * initial connection of RFB protocol - */ - sendRfbVersion(os); - readVersionMsg(is); - sendSecurityType(os); - readSecType(is); - sendSecResult(os); - readClientInit(is); - sendInitData(os); - - for (;;) { - byte[] b = c.poll(); - os.write(b, 0, b.length); - } - } catch (IOException e) { - /** - * if socket closed - */ - // cliList.remove(newCli); - } - - } - - }; - new Thread(sender).start(); - - } - void speedCheckMillis() { - - Runnable stdin = new Runnable() { + Runnable stdin = new Runnable() { public void run() { int c; try { @@ -629,10 +487,7 @@ case 's': break; default: -// startSpeedCheck(); - writeFramebufferUpdateRequest(0, 0, framebufferWidth, - framebufferHeight, false); - + startSpeedCheck(); break; } } @@ -645,28 +500,397 @@ new Thread(stdin).start(); } - void requireFramebuffer() { - Runnable stdin = new Runnable() { + /** + * gzip byte arrays + * @param deflater + * @param inputs + * byte data[] + * @param inputIndex + * @param outputs + * byte data[] + * @return byte length in last byte array + * @throws IOException + */ + public int zip(Deflater deflater,LinkedList<ByteBuffer> inputs, int inputIndex, LinkedList<ByteBuffer> outputs) throws IOException { + int len = 0; + ByteBuffer c1= ByteBuffer.allocate(INFLATE_BUFSIZE); + while(inputIndex < inputs.size() ) { + ByteBuffer b1 = inputs.get(inputIndex++); + deflater.setInput(b1.array(),b1.position(),b1.remaining()); + /** + * 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 { + len1 = deflater.deflate(c1.array(),c1.position(),c1.remaining()); + if (len1>0) { + len += len1; + c1.position(c1.position()+len1); + if (c1.remaining()==0) { + c1.flip(); outputs.addLast(c1); + c1 = ByteBuffer.allocate(INFLATE_BUFSIZE); + } + } + } while (len1 >0 || !deflater.needsInput()); // &&!deflater.finished()); + } + if (c1.position()!=0) { + c1.flip(); outputs.addLast(c1); + } + deflater.reset(); + return len; + } + + /** + * gunzip byte arrays + * @param inflater + * @param inputs + * byte data[] + * @param outputs + * byte data[] + *@return number of total bytes + * @throws IOException + */ + public int unzip(Inflater inflater, LinkedList<ByteBuffer> inputs, int inputIndex, LinkedList<ByteBuffer> outputs,int bufSize) + throws DataFormatException { + int len=0; + 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) { + buf.position(buf.position()+len0); + len += len0; + if (buf.remaining()==0) { + buf.flip(); + outputs.addLast(buf); + buf = ByteBuffer.allocate(bufSize); + } + } + } while (!inflater.needsInput()); + } + if (buf.position()!=0) { + buf.flip(); + outputs.addLast(buf); + } + 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); + readFully(header.array(),0,16); + header.limit(16); + if (header.get(0)==RfbProto.FramebufferUpdate) { + int encoding = header.getInt(12); + 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); + + 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(); + return ; + } + bufs.add(header); + if (dataLen>16) { + ByteBuffer b = ByteBuffer.allocate(dataLen-16); + readFully(b.array(),0,dataLen-16); b.limit(dataLen-16); + bufs.add(b); + } + multicastqueue.put(bufs); + is.reset(); + } + is.reset(); + + // It may be compressed. We can inflate here to avoid repeating clients decompressing here, + // but it may generate too many large data. It is better to do it in each client. + // But we have do inflation for all input data, so we have to do it here. + } + + void newClient(AcceptThread acceptThread, final Socket newCli, + final OutputStream os, final InputStream is) throws IOException { + // 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 c; - try { - while ((c = System.in.read()) != -1) { - sendFlag = false; - switch (c) { - default: - System.out.println("writeFramebufferUpdateRequest()"); - writeFramebufferUpdateRequest(0, 0, - framebufferWidth, framebufferHeight, false); - break; + 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) { } - } catch (IOException e) { - e.printStackTrace(); } } }; + new Thread(timer).start(); + /** + * discard all incoming from clients + */ + final Runnable reader = new Runnable() { + public void run() { + byte b[] = new byte[4096]; + for(;;) { + try { + int c = is.read(b); + if (c<=0) throw new IOException(); + // System.out.println("client read "+c); + } catch (IOException e) { + try { + writerRunning.set(2); + os.close(); + is.close(); + } catch (IOException e1) { + } + return; + } + } + } + }; + /** + * send packets to a client + */ + Runnable sender = new Runnable() { + public void run() { + writerRunning.set(1); + try { + /** + * initial connection of RFB protocol + */ + sendRfbVersion(os); +// readVersionMsg(is); + readVersionMsg(is,os); + sendSecurityType(os); + readSecType(is); + sendSecResult(os); + readClientInit(is); + sendInitData(os); + new Thread(reader).start(); // discard incoming packet here after. + for (;;) { + LinkedList<ByteBuffer> bufs = c.poll(); + int inputIndex = 0; + ByteBuffer header = bufs.get(inputIndex); + if (header==null) continue; + if (header.get(0)==RfbProto.FramebufferUpdate) { + // System.out.println("client "+ myId); + } + 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); */ + } + } - new Thread(stdin).start(); + 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(); + } + + @Test + public void test1() { + try { + LinkedList<ByteBuffer> in = new LinkedList<ByteBuffer>(); + LinkedList<ByteBuffer> out = new LinkedList<ByteBuffer>(); + LinkedList<ByteBuffer> out2 = new LinkedList<ByteBuffer>(); +// if (false) { +// for(int i=0;i<10;i++) { +// in.add(ByteBuffer.wrap("test1".getBytes())); +// in.add(ByteBuffer.wrap("test2".getBytes())); +// in.add(ByteBuffer.wrap("test3".getBytes())); +// in.add(ByteBuffer.wrap("test44".getBytes())); +// } +// } else + { + String t = ""; + for(int i=0;i<10;i++) { + t += "test1"; + t += "test2"; + t += "test3"; + t += "test44"; + } + in.add(ByteBuffer.wrap(t.getBytes())); + } + + LinkedList<ByteBuffer> in1 = clone(in); + + Deflater deflater = new Deflater(); + zip(deflater,in,0,out); + // LinkedList<ByteBuffer> out3 = clone(out); zipped result is depend on deflator's state + unzip(inflater, out, 0,out2, INFLATE_BUFSIZE); + // inflater.reset(); + equalByteBuffers(in1, out2); + LinkedList<ByteBuffer> out4 = new LinkedList<ByteBuffer>(); + deflater = new Deflater(); + zip(deflater,out2,0,out4); + LinkedList<ByteBuffer> out5 = new LinkedList<ByteBuffer>(); + unzip(inflater,out4,0, out5, INFLATE_BUFSIZE); + int len = equalByteBuffers(in1,out5); + + System.out.println("Test Ok. "+len); + } catch (Exception e) { + assertEquals(0,1); + } + } + + private LinkedList<ByteBuffer> clone(LinkedList<ByteBuffer> in) { + LinkedList<ByteBuffer> copy = new LinkedList<ByteBuffer>(); + for(ByteBuffer b: in) { + ByteBuffer c = b.duplicate(); + copy.add(c); + } + return copy; + } + + + + public int equalByteBuffers(LinkedList<ByteBuffer> in, + LinkedList<ByteBuffer> out2) { + int len = 0; + Iterable<Byte> i = byteBufferIterator(in); + Iterator<Byte> o = byteBufferIterator(out2).iterator(); + + for(int b: i) { + len ++; + if (o.hasNext()) { + int c = o.next(); + assertEquals(b,c); + } else + assertEquals(0,1); + } + if (o.hasNext()) + assertEquals(0,1); + // System.out.println(); + return len; + } + + 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/myVncProxy/OptionsNoFrame.java Tue Aug 02 20:15:01 2011 +0900 +++ b/src/myVncProxy/OptionsNoFrame.java Tue Aug 30 06:49:49 2011 +0900 @@ -74,10 +74,16 @@ // Constructor. Set up the labels and choices from the names and values // arrays. // - +/* OptionsNoFrame(VncProxyService v) { - viewer = v; - + viewer = v; + preferredEncoding = -1; + } +*/ +// OptionsNoFrame(VncProxyService v, VncCanvas vc) { + OptionsNoFrame(VncProxyService v) { + viewer = v; + for (int i = 0; i < names.length; i++) { labels[i] = new Label(names[i]);
--- a/src/myVncProxy/ProxyVncCanvas.java Tue Aug 02 20:15:01 2011 +0900 +++ b/src/myVncProxy/ProxyVncCanvas.java Tue Aug 30 06:49:49 2011 +0900 @@ -3,12 +3,8 @@ 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; // @@ -79,6 +75,7 @@ // True if we process keyboard and mouse events. boolean inputEnabled; + private int b = 0; @@ -352,8 +349,6 @@ rfb.writeFramebufferUpdateRequest(0, 0, rfb.framebufferWidth, rfb.framebufferHeight, false); - - rfb.requireFramebuffer(); resetStats(); boolean statsRestarted = false; @@ -364,19 +359,25 @@ long count = 0; while (true) { -// System.out.println("\ncount=" + count); + // System.out.println("\ncount=" + count); + count++; /** * read Data from parents and send Data to Client. */ - //rfb.sendDataToClient(); - //rfb.sendDataToClient(bytesPixel); - rfb.regiFramebufferUpdate(); - rfb.printFramebufferUpdate(); + rfb.sendDataToClient(); + + if(rfb.returnMsgtype() == RfbProto.FramebufferUpdate ) { + boolean fullUpdateNeeded = false; + int w = rfb.framebufferWidth; + int h = rfb.framebufferHeight; + rfb.writeFramebufferUpdateRequest(0, 0, w, h, !fullUpdateNeeded); + continue; + } - long bytesRead = rfb.getNumBytesRead(); + long numBytesRead = rfb.getNumBytesRead(); // Read message type from the server. int msgType = rfb.readServerMessageType(); @@ -385,10 +386,13 @@ switch (msgType) { case MyRfbProto.SpeedCheckMillis: rfb.readSpeedCheck(); - break; case RfbProto.FramebufferUpdate: - + if(msgType == RfbProto.FramebufferUpdate){ + rfb.is.reset(); + break; + } + if (statNumUpdates == viewer.debugStatsExcludeUpdates && !statsRestarted) { resetStats(); @@ -418,12 +422,14 @@ 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; @@ -454,6 +460,7 @@ handleHextileRect(rx, ry, rw, rh); break; case RfbProto.EncodingZRLE: + case RfbProto.EncodingZRLEE: statNumRectsZRLE++; handleZRLERect(rx, ry, rw, rh); break; @@ -501,14 +508,13 @@ // 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; @@ -531,10 +537,12 @@ default: throw new Exception("Unknown RFB message type " + msgType); } + + - int bufSize = (int)(rfb.getNumBytesRead() - bytesRead); - System.out.println("bufSize = " + bufSize); - rfb.bufResetSend(bufSize); + int bufSize = (int)(rfb.getNumBytesRead() - numBytesRead); + System.out.println("bufSize="+bufSize); +// rfb.bufResetSend(bufSize);
--- a/src/myVncProxy/RfbProto.java Tue Aug 02 20:15:01 2011 +0900 +++ b/src/myVncProxy/RfbProto.java Tue Aug 30 06:49:49 2011 +0900 @@ -26,12 +26,9 @@ // 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 { @@ -79,7 +76,7 @@ // Supported encodings and pseudo-encodings final static int EncodingRaw = 0, EncodingCopyRect = 1, EncodingRRE = 2, EncodingCoRRE = 4, EncodingHextile = 5, EncodingZlib = 6, - EncodingTight = 7, EncodingZRLE = 16, + EncodingTight = 7, EncodingZRLEE = 15, EncodingZRLE = 16, EncodingCompressLevel0 = 0xFFFFFF00, EncodingQualityLevel0 = 0xFFFFFFE0, EncodingXCursor = 0xFFFFFF10, EncodingRichCursor = 0xFFFFFF11, EncodingPointerPos = 0xFFFFFF18, @@ -88,6 +85,7 @@ SigEncodingCopyRect = "COPYRECT", SigEncodingRRE = "RRE_____", SigEncodingCoRRE = "CORRE___", SigEncodingHextile = "HEXTILE_", SigEncodingZlib = "ZLIB____", SigEncodingTight = "TIGHT___", + SigEncodingZRLEE = "ZRLEE___", SigEncodingZRLE = "ZRLE____", SigEncodingCompressLevel0 = "COMPRLVL", SigEncodingQualityLevel0 = "JPEGQLVL", @@ -180,7 +178,6 @@ // // Constructor. Make TCP connection to RFB server. // - RfbProto(String h, int p, VncViewer v) throws IOException { viewer = v; host = h; @@ -224,6 +221,10 @@ timeWaitedIn100us = 5; timedKbits = 0; } + + public RfbProto() { + + } @@ -292,7 +293,7 @@ protocolTightVNC = false; initCapabilities(); } - + // // Negotiate the authentication scheme. // @@ -468,7 +469,9 @@ 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, @@ -723,6 +726,7 @@ if (updateRectEncoding == EncodingZlib || updateRectEncoding == EncodingZRLE + || updateRectEncoding == EncodingZRLEE || updateRectEncoding == EncodingTight) wereZlibUpdates = true; @@ -955,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. @@ -1370,6 +1376,7 @@ final int readU8() throws IOException { int r = is.readUnsignedByte(); numBytesRead++; + return r; }
--- a/src/myVncProxy/VncCanvas.java Tue Aug 02 20:15:01 2011 +0900 +++ b/src/myVncProxy/VncCanvas.java Tue Aug 30 06:49:49 2011 +0900 @@ -26,11 +26,8 @@ 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; @@ -478,6 +475,7 @@ handleHextileRect(rx, ry, rw, rh); break; case RfbProto.EncodingZRLE: + case RfbProto.EncodingZRLEE: statNumRectsZRLE++; handleZRLERect(rx, ry, rw, rh); break; @@ -740,6 +738,7 @@ // These colors should be kept between handleHextileSubrect() calls. private Color hextile_bg, hextile_fg; + boolean noZRLEdecode = false; void handleHextileRect(int x, int y, int w, int h) throws IOException { @@ -887,8 +886,8 @@ // void handleZRLERect(int x, int y, int w, int h) throws Exception { - - if (zrleInStream == null) + if (noZRLEdecode) return; + if (zrleInStream == null || rfb.updateRectEncoding==RfbProto.EncodingZRLEE) zrleInStream = new ZlibInStream(); // System.out.println("zrleInStream.end="+zrleInStream.inflater.off);
--- a/src/myVncProxy/VncProxyService.java Tue Aug 02 20:15:01 2011 +0900 +++ b/src/myVncProxy/VncProxyService.java Tue Aug 30 06:49:49 2011 +0900 @@ -64,6 +64,9 @@ int debugStatsExcludeUpdates; int debugStatsMeasureUpdates; + int echoPort = 9999; + + void checkArgs(String[] argv){ if(argv.length > 3){ @@ -106,7 +109,7 @@ }catch(Exception e){} rfbThread = new Thread(this); - accThread = new Thread(new AcceptThread(rfb)); + accThread = new Thread(new AcceptThread(rfb, 5999)); } @@ -199,7 +202,7 @@ void connectAndAuthenticate() throws Exception { acc = new AcceptClient(mainArgs[0]); - geth = new CreateThread(acc); + geth = new CreateThread(acc , echoPort); Thread thread = new Thread(geth); thread.start(); @@ -208,10 +211,10 @@ showConnectionStatus("Connecting to " + host + ", port " + port + "..."); -// rfb = new RfbProto(host, port, this); + // rfb = new RfbProto(host, port, this); // rfb = new MyRfbProto(host, port); - rfb = new MyRfbProto(host, port, this); - + rfb = new MyRfbProto(host, port, geth); + showConnectionStatus("Connected to server"); rfb.readVersionMsg(); @@ -324,8 +327,6 @@ 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"); @@ -348,7 +349,6 @@ return; preferredEncoding = encodingsSaved[0]; } -*/ } else { // Auto encoder selection is not enabled. if (autoSelectOnly) @@ -360,30 +360,29 @@ 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