changeset 80:712a047908df

recompress output
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Wed, 03 Aug 2011 02:42:56 +0900
parents 5970410efee7
children 9109273b96dc
files src/myVncProxy/AcceptThread.java src/myVncProxy/MyRfbProto.java src/myVncProxy/ProxyVncCanvas.java src/myVncProxy/VncCanvas.java src/myVncProxy/VncProxyService.java
diffstat 5 files changed, 65 insertions(+), 48 deletions(-) [+]
line wrap: on
line diff
--- a/src/myVncProxy/AcceptThread.java	Fri Jul 29 19:17:31 2011 +0900
+++ b/src/myVncProxy/AcceptThread.java	Wed Aug 03 02:42:56 2011 +0900
@@ -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/MyRfbProto.java	Fri Jul 29 19:17:31 2011 +0900
+++ b/src/myVncProxy/MyRfbProto.java	Wed Aug 03 02:42:56 2011 +0900
@@ -21,6 +21,9 @@
 
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
+import java.util.zip.DataFormatException;
+import java.util.zip.Deflater;
+import java.util.zip.Inflater;
 import java.io.OutputStream;
 
 class MyRfbProto extends RfbProto {
@@ -29,6 +32,7 @@
 	 * CheckMillis is one of new msgType for RFB 3.998. 
 	 */
 	final static int SpeedCheckMillis = 4;
+	private static final int INFLATE_BUFSIZE = 1024*1024;
 	boolean printStatusFlag = false;
 	long startCheckTime;
 
@@ -54,6 +58,7 @@
 	byte[] pngBytes;
 
 	private MulticastQueue<byte[]> multicastqueue = new MulticastQueue<byte[]>();
+	private int clients = 0;
 
 	MyRfbProto(String h, int p, VncViewer v) throws IOException {
 		super(h, p, v);
@@ -104,20 +109,20 @@
 	}
 
 	// 5550を開けるが、開いてないなら+1のポートを開ける。
-	void selectPort() {
-		int i = 5550;
+	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() {
@@ -248,20 +253,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 {
@@ -293,30 +284,23 @@
 		System.out.println("numBytesRead=" + numBytesRead);
 	}
 
-	void bufResetSend(int size) throws IOException {
-		is.reset();
-		int len = size;
-		if (available() < size)
-			len = available();
-		byte buffer[] = new byte[len];
-		readFully(buffer);
-		sendData(buffer);
-	}
 
 	
 	void regiFramebufferUpdate() throws IOException {
 		is.mark(20);
-		messageType = readU8();
-		skipBytes(1);
-		rectangles = readU16();
-		rectX = readU16();
-		rectY = readU16();
-		rectW = readU16();
-		rectH = readU16();
-		encoding = readU32();
+		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 == 16)
+		if (encoding == EncodingZRLE)
 			zLen = readU32();
+		else
+			zLen = 0;
 		is.reset();
 /*
 		int dataLen;
@@ -362,8 +346,11 @@
 		case RfbProto.EncodingRRE:
 		case RfbProto.EncodingCoRRE:
 		case RfbProto.EncodingHextile:
+		case RfbProto.EncodingTight:
+			dataLen = zLen + 20;
+			is.mark(dataLen);
+			break;
 		case RfbProto.EncodingZlib:
-		case RfbProto.EncodingTight:
 		case RfbProto.EncodingZRLE:
 			dataLen = zLen + 20;
 			is.mark(dataLen);
@@ -389,6 +376,8 @@
 		multicastqueue.put(buffer);
 		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.
 /*
 		for (Socket cli : cliList) {
 			try {
@@ -527,6 +516,9 @@
 		final Client<byte[]> c = multicastqueue.newClient();
 		Runnable sender = new Runnable() {
 			public void run() {
+
+			    Deflater deflater = new Deflater();
+				Inflater inflater = new Inflater();
 				try {
 					/**
 					 *  initial connection of RFB protocol
@@ -541,18 +533,37 @@
 
 					for (;;) {
 						byte[] b = c.poll();
-						os.write(b, 0, b.length);
+						if (b[0]==RfbProto.FramebufferUpdate) {
+							int encoding = ((b[12]*256+b[13])*256+b[14])*256+b[15];
+							if (encoding==RfbProto.EncodingZlib||encoding==RfbProto.EncodingZRLE) {
+								byte inf[] = new byte[INFLATE_BUFSIZE];
+								inflater.setInput(inf, 0, b.length-24);
+								int inflen = inflater.inflate(inf);
+								if (inflen==INFLATE_BUFSIZE) throw new DataFormatException(); // too large 
+								byte[] c = new byte[INFLATE_BUFSIZE];
+								deflater.setInput(inf,0,inflen);
+								int len = deflater.deflate(c);
+								byte[] blen = castIntByte(len);
+								os.write(b,0,20);
+								os.write(blen,0,4);
+								os.write(c,0,len);
+							}
+						} else
+							os.write(b, 0, b.length);
 					}
 				} catch (IOException e) {
 					/**
 					 * if socket closed
 					 */
 					//					cliList.remove(newCli);
+				} catch (DataFormatException e) {
+				      // should print some error
 				}
 
 			}
 
 		};
+		clients++;
 		new Thread(sender).start();
 
 	}
--- a/src/myVncProxy/ProxyVncCanvas.java	Fri Jul 29 19:17:31 2011 +0900
+++ b/src/myVncProxy/ProxyVncCanvas.java	Wed Aug 03 02:42:56 2011 +0900
@@ -371,7 +371,7 @@
 			 */
 			rfb.sendDataToClient();
 			
-			int bufSize = (int)rfb.getNumBytesRead();
+			long numBytesRead = rfb.getNumBytesRead();
 			
 			// Read message type from the server. 
 			int msgType = rfb.readServerMessageType();
@@ -529,7 +529,7 @@
 				throw new Exception("Unknown RFB message type " + msgType);
 			}
 
-			bufSize = (int)rfb.getNumBytesRead() - bufSize;
+			int bufSize = (int)(rfb.getNumBytesRead() - numBytesRead);
 //			System.out.println("bufSize="+bufSize);
 //			rfb.bufResetSend(bufSize);
 
--- a/src/myVncProxy/VncCanvas.java	Fri Jul 29 19:17:31 2011 +0900
+++ b/src/myVncProxy/VncCanvas.java	Wed Aug 03 02:42:56 2011 +0900
@@ -740,6 +740,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,7 +888,7 @@
 	//
 
 	void handleZRLERect(int x, int y, int w, int h) throws Exception {
-
+		if (noZRLEdecode) return;
 		if (zrleInStream == null)
 			zrleInStream = new ZlibInStream();
 //		System.out.println("zrleInStream.end="+zrleInStream.inflater.off);			
--- a/src/myVncProxy/VncProxyService.java	Fri Jul 29 19:17:31 2011 +0900
+++ b/src/myVncProxy/VncProxyService.java	Wed Aug 03 02:42:56 2011 +0900
@@ -106,7 +106,7 @@
 		}catch(Exception e){}
 
 		rfbThread = new Thread(this);
-		accThread = new Thread(new AcceptThread(rfb)); 
+		accThread = new Thread(new AcceptThread(rfb, 5999)); 
 
 	}
 	
@@ -353,7 +353,7 @@
 		int[] encodings = new int[20];
 		int nEncodings = 0;
 
-/*		
+
 		encodings[nEncodings++] = preferredEncoding;
 		if (options.useCopyRect) {
 			encodings[nEncodings++] = RfbProto.EncodingCopyRect;
@@ -367,11 +367,10 @@
 		if (preferredEncoding != RfbProto.EncodingHextile) {
 			encodings[nEncodings++] = RfbProto.EncodingHextile;
 		}
-*/
 		if (preferredEncoding != RfbProto.EncodingZlib) {
 			encodings[nEncodings++] = RfbProto.EncodingZlib;
 		}
-/*
+		/*
 		if (preferredEncoding != RfbProto.EncodingCoRRE) {
 			encodings[nEncodings++] = RfbProto.EncodingCoRRE;
 		}