changeset 599:3b8de13a9c16

packet full handling using new deflator for VNC Server is wrong
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Sun, 16 Feb 2020 18:26:03 +0900
parents 27449453ebde
children fb26a48b440d
files src/main/java/com/glavsoft/rfb/encoding/decoder/ZRLEDecoder.java src/main/java/com/glavsoft/rfb/protocol/ReceiverTask.java
diffstat 2 files changed, 46 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/src/main/java/com/glavsoft/rfb/encoding/decoder/ZRLEDecoder.java	Fri Feb 14 10:32:15 2020 +0900
+++ b/src/main/java/com/glavsoft/rfb/encoding/decoder/ZRLEDecoder.java	Sun Feb 16 18:26:03 2020 +0900
@@ -152,7 +152,7 @@
 		 * @param tileH
 		 */
 
-		public void multicastPut(TreeRFBProto rfb, boolean last, byte[] bytes, int offset, int tileW, int tileH) {
+		public void multicastPut(TreeRFBProto rfb, boolean last, byte[] bytes, int offset, int tileW, int tileH) throws TransportException {
 			if (!blocking) return;
 			int span = offset - prevoffset;
 			deflater.setInput(bytes, prevoffset, span);
@@ -162,14 +162,15 @@
 				deflater.deflate(c1, Deflater.SYNC_FLUSH);
 				if (!deflater.needsInput()) {
 					// packet full
-					flushDeflator();
+					flushDeflator(true," full ");
 					int bytesRead = (int)deflater.getBytesRead();
 					prevoffset = flushOffset+bytesRead;
 					assert(prevoffset==offset);
-					System.out.println("od prevOffset = "+prevoffset+" span = "+(prevoffset-flushOffset));
+					System.out.println("od prevOffset = "+prevoffset+" span = "+(prevoffset-flushOffset)+ " " + c1rect);
 					if (c0rect!=null) { // finish pahse 1
 						flushRectangle(c0rect,prevC1LineOffset);
 						moveNext();
+						c0rect = null;
 					}
 					flushRectangle(c1rect,c1.position()); // phase 2
 					flushMuticast(rfb, bytes);
@@ -189,10 +190,12 @@
 			} while (! deflater.needsInput());
 			prevoffset = offset;
 			if (last) {
-				flushDeflator();
+				System.out.println("last prevOffset = "+prevoffset+" span = "+(prevoffset-flushOffset)+ " " + c1rect);
+				flushDeflator(false," last");
 				if (c0rect!=null) {
 					flushRectangle(c0rect,prevC1LineOffset);
 					moveNext();
+					c0rect = null;
 				}
 				flushRectangle(c1rect,c1.position());
 				flushMuticast(rfb, bytes);
@@ -202,24 +205,32 @@
 			if (c1rect.x > rect.x) {  // phase 0
 				assert(c0rect==null);
 				if (c1rect.x + c1rect.width >= rect.x + rect.width) {  // end of phase 0
-					deflater.deflate(c1,Deflater.FULL_FLUSH);
+					boolean end = flushDeflator(false," end of phase 0 ");
+					width = 0;
 					flushRectangle(c1rect,c1.position());
+					if (end) {
+						flushMuticast(rfb,bytes);
+						return;
+					}
 					c1.position(c1.position()+16); // header space
 					prevC1Offset = c1.position();
 					c1rect = new FramebufferUpdateRectangle(rect.x,c1rect.y+tileH,0,0);
-					width = 0;
 				}
 			} else {  // phase 1
 				if (width >= rect.width) { // next line
-					deflater.deflate(c1,Deflater.FULL_FLUSH);
+					boolean end = flushDeflator(false, " phoase 1 next line ");
+					width = 0;
 					prevC1LineOffset = c1.position();
 					if (c0rect!=null) { // extend phase 1
 						c0rect.height += tileH;
 					} else { // first phase 1 case
 						c0rect = c1rect;
 					}
+					if (end) {
+						flushMuticast(rfb,bytes);
+						return;
+					}
 					c1rect = new FramebufferUpdateRectangle(rect.x, c0rect.y+c0rect.height, 0, 0);
-					width = 0;
 					prevLineOffset = offset;
 				}
 			}
@@ -232,13 +243,20 @@
 			prevC1Offset = prevC1LineOffset+16;
 		}
 
-		private void flushDeflator() {
-			c1.limit(c1.limit() + MARGIN);
+		private boolean flushDeflator(boolean extend,String what) throws TransportException {
+			System.out.println("\nflusing "+what+c1);
+			if (extend) c1.limit(c1.limit() + MARGIN-16);
 			deflater.deflate(c1, Deflater.FULL_FLUSH);
-			deflater.getBytesRead();
 			if (c1.remaining()==0) {
-				System.out.println("Multicast packet overrun.");
+				if (!extend) {
+					c1.limit(c1.capacity()-16);
+					deflater.deflate(c1, Deflater.FULL_FLUSH);
+				}
+				if (c1.remaining() == 0)
+					throw new TransportException("Multicast packet overrun", null);
+				return true;
 			}
+			return false;
 		}
 
 		private void bufdump(byte[] bytes,int beigin, int end) {
@@ -253,6 +271,7 @@
 		 * send muticast pacate if nessesally
 		 */
 		private void flushRectangle(FramebufferUpdateRectangle rect,int pos) {
+			if (rect.width==0) return;
 			c1.putShort(prevC1Offset - 16, (short) rect.x);
 			c1.putShort(prevC1Offset - 14, (short) rect.y);
 			c1.putShort(prevC1Offset - 12, (short) rect.width);
@@ -268,7 +287,7 @@
 			deflater.reset();
 			LinkedList<ByteBuffer> bufs = new LinkedList<ByteBuffer>();
 			bufs.add(c1);
-			rfb.getContext().checkFrameBufferRectanble(c1, bytes, flushOffset, prevoffset);
+			//rfb.getContext().checkFrameBufferRectanble(c1, bytes, flushOffset, prevoffset);
 			flushOffset = prevoffset;
 			if (rfb.isTreeManager() && rfb.connectionPresenter.isUseMulticast()) {
 				for (ByteBuffer buf : bufs)
@@ -284,7 +303,7 @@
 					   FramebufferUpdateRectangle rect) throws TransportException {
 		int zippedLength = (int) reader.readUInt32();
 		if (0 == zippedLength) return;
-		int length = rect.width * rect.height * renderer.getBytesPerPixel();
+		int length = rect.width * rect.height * renderer.getBytesPerPixel()+1024*32;
 		ByteBuffer buf = unzip(reader, zippedLength, length, rect.getEncodingType());
 		decode1(renderer, null, rect, buf, zippedLength, null);
 	}
@@ -301,6 +320,8 @@
 		decode1(renderer, header, rect, buf, zippedLength, rfb);
 	}
 
+	public String decoding = "";
+
 	public void decode1(Renderer renderer, ByteBuffer header, FramebufferUpdateRectangle rect, ByteBuffer buf, int zippedLength, TreeRFBProto rfbProto) throws TransportException {
 		int offset = zippedLength;
 		int maxX = rect.x + rect.width;
@@ -320,12 +341,14 @@
 			tileloop.zrleeBlocking(rfbProto, header, rect, bytes);
 		}
 		try {
+			System.out.print(decoding);
 			for (int tileY = rect.y; tileY < maxY; tileY += MAX_TILE_SIZE) {
 				int tileHeight = Math.min(maxY - tileY, MAX_TILE_SIZE);
 				if (tileloop.blocking) {
 					tileloop.c1rect.height += tileHeight;
 				}
 				for (int tileX = rect.x; tileX < maxX; tileX += MAX_TILE_SIZE) {
+					// System.out.print(" "+Integer.toHexString(0xff&bytes[offset])+(offset<bytes.length-1?Integer.toHexString(0xff&bytes[offset+1]):""));
 					int tileWidth = Math.min(maxX - tileX, MAX_TILE_SIZE);
 					int subencoding = bytes[offset++] & 0x0ff;
 					if (subencoding != 0) {
--- a/src/main/java/com/glavsoft/rfb/protocol/ReceiverTask.java	Fri Feb 14 10:32:15 2020 +0900
+++ b/src/main/java/com/glavsoft/rfb/protocol/ReceiverTask.java	Sun Feb 16 18:26:03 2020 +0900
@@ -389,15 +389,18 @@
                 int n = numberOfRectangeles;
                 while(n-- > 0 ) {
                     rect.fill(in);
-                    System.out.println("check rect No." + n + " = " + rect);
                     if (rect.getEncodingType() == EncodingType.ZRLEE) {
-                        int length = rect.width * rect.height * renderer.getBytesPerPixel();
+                        int length = rect.width * rect.height * renderer.getBytesPerPixel() + 20480;
                         int zippedLength = (int) in.readUInt32();
                         if (zippedLength > in.available()) {
                             System.out.println("overrun zippedLength=" + zippedLength + " available="+in.available());
                         }
                         try {
+                            decoder.decoding = "checking offset="+Integer.toHexString(flushOffset)+ " ";
                             ByteBuffer buf = decoder.unzip(in, zippedLength, length, rect.getEncodingType());
+                            System.out.println("check rect No." + n + " = " + rect
+                                    + " offset =" + flushOffset + " end = " + (flushOffset+buf.remaining())
+                                    + " span = " + (buf.remaining()));
                             compareBytes(buf, bytes, flushOffset, flushOffset+buf.remaining());
                             flushOffset += buf.remaining();
                         } catch (Exception e) {
@@ -408,10 +411,13 @@
                 assert(flushOffset==flushEnd);
                 in.reset();
             }
-            Decoder decoder = new ZRLEDecoder();
+            ZRLEDecoder zdecoder = new ZRLEDecoder();
+            Decoder decoder = zdecoder;
             while (numberOfRectangeles-- > 0) {
                 rect.fill(in);
                 if (rect.getEncodingType() == EncodingType.ZRLEE) {
+                    System.out.println();
+                    zdecoder.decoding = "checking offset="+Integer.toHexString(flushOffset)+ " ";
                     decoder.decode(in,new NullRenderer(context.getPixelFormat().bitsPerPixel/8, context.getFbWidth(), context.getFbHeight(), context.getPixelFormat()),rect);
                 }
             }