changeset 109:3f73ebf918bd

add time out to avoid memory overlow caused by suspended clients.
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Fri, 05 Aug 2011 12:08:17 +0900
parents 4199efcc4260
children 6f95e5efa799
files src/myVncProxy/MulticastQueue.java src/myVncProxy/MyRfbProto.java
diffstat 2 files changed, 37 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/src/myVncProxy/MulticastQueue.java	Fri Aug 05 10:57:05 2011 +0900
+++ b/src/myVncProxy/MulticastQueue.java	Fri Aug 05 12:08:17 2011 +0900
@@ -36,12 +36,12 @@
 		public T poll()
 		{
 			Node<T> next = null;
-			T item;
+			T item = null;
 			do {
 				try {
 					next = node.next();
 				}catch(InterruptedException _e){
-					_e.printStackTrace();
+					continue;
 				}
 				item = node.getItem();
 				node = next;
--- a/src/myVncProxy/MyRfbProto.java	Fri Aug 05 10:57:05 2011 +0900
+++ b/src/myVncProxy/MyRfbProto.java	Fri Aug 05 12:08:17 2011 +0900
@@ -26,6 +26,7 @@
 import myVncProxy.MulticastQueue.Client;
 
 import java.util.concurrent.ExecutorService;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.zip.DataFormatException;
 import java.util.zip.Deflater;
 import java.util.zip.Inflater;
@@ -575,6 +576,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);
@@ -626,7 +641,25 @@
 		// rfb.addSockTmp(newCli);
 		//		addSock(newCli);
 		final Client <LinkedList<ByteBuffer>> c = multicastqueue.newClient();
-
+		final AtomicBoolean writerRunning = new AtomicBoolean();
+		final Runnable timer = new Runnable() {
+			public void run() {
+				for(;;) {
+					long timeout = 30000;
+					try {
+						synchronized(this) {
+							wait(timeout);
+							while (!writerRunning.get()) {
+								c.poll(); // discard, should be timeout
+								wait(10);
+							}
+						}
+					} catch (InterruptedException e) {
+					}
+				}
+			}
+		};
+		new Thread(timer).start();
 		final Runnable reader = new Runnable() {
 			public void run() {
 				byte b[] = new byte[4096];
@@ -664,12 +697,11 @@
 					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 "+ myId);
 						}
-						os.write(header.array(),header.position(),header.limit());
 						writeToClient(os, bufs, inputIndex);
 					}
 				} catch (IOException e) {