Mercurial > hg > Members > you > BroadCastTreeVNC
view src/treeVnc/MyRfbProtoProxy.java @ 6:01cdbc95142f default tip
update build.xml
author | Yu Taninari <you@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 30 Apr 2012 16:04:44 +0900 |
parents | 970d5ac80256 |
children |
line wrap: on
line source
package treeVnc; import static org.junit.Assert.*; import java.awt.Graphics; import java.awt.Image; import java.awt.image.BufferedImage; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.BindException; import java.net.DatagramPacket; import java.net.InetAddress; import java.net.MulticastSocket; 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.atomic.AtomicInteger; import java.util.zip.DataFormatException; import java.util.zip.Deflater; import java.util.zip.Inflater; import java.io.OutputStream; public class MyRfbProtoProxy extends RfbProto implements MyRfbProto { int test = 0; final static String versionMsg_3_855 = "RFB 003.855\n"; /** * CheckMillis is one of new msgType for RFB 3.855. */ final static byte SpeedCheckMillis = 4; // Secyrity type of OS X final static int SecTypeReqAccess = 32; // Supported authentication types final static int AuthAccess = 32; private static final int INFLATE_BUFSIZE = 1024 * 100; boolean printStatusFlag = false; long startCheckTime; private int messageType; private int rectangles; private int rectX; private int rectY; private int rectW; private int rectH; private int encoding; private int zLen; private boolean clicomp = false; private ServerSocket servSock; protected int acceptPort; // private byte initData[]; byte initData[]; private LinkedList<Socket> cliListTmp; private LinkedList<Socket> cliList; boolean createBimgFlag; boolean proxyFlag = true; ExecutorService executor; 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(); private CreateThread geth; // private Thread requestThread; private RequestScreenThread rThread; private Thread requestThread; public MyRfbProtoProxy() throws IOException { } MyRfbProtoProxy(String h, int p, VncViewer v) throws IOException { super(h, p, v); rThread = new RequestScreenThread(this); requestThread = new Thread(rThread); // requestThread = new Thread(new RequestScreenThread(this)); } MyRfbProtoProxy(String h, int p, CreateThread geth) throws IOException { super(h, p); this.geth = geth; proxyFlag = true; rThread = new RequestScreenThread(this); requestThread = new Thread(rThread); // requestThread = new Thread(new RequestScreenThread(this)); } MyRfbProtoProxy(String h, int p) throws IOException { super(h, p); rThread = new RequestScreenThread(this); requestThread = new Thread(rThread); // requestThread = new Thread(new RequestScreenThread(this)); } // over write void writeVersionMsg() throws IOException { clientMajor = 3; if (serverMinor == 855) { clientMinor = 855; os.write(versionMsg_3_855.getBytes()); } else if (serverMajor > 3 || serverMinor >= 8) { clientMinor = 8; os.write(versionMsg_3_8.getBytes()); } else if (serverMinor >= 7) { clientMinor = 7; os.write(versionMsg_3_7.getBytes()); } else { clientMinor = 3; os.write(versionMsg_3_3.getBytes()); } protocolTightVNC = false; initCapabilities(); } void initServSock(int port) throws IOException { servSock = new ServerSocket(port); acceptPort = port; } void authenticationRequestAccess() throws IOException { byte[] headBuf = new byte[2]; is.read(headBuf); if (headBuf[1] == 2) { byte[] b = new byte[258]; is.read(b); byte[] outBuf = new byte[256]; os.write(outBuf); os.flush(); } else if (headBuf[1] == 23) { byte[] b = new byte[130]; is.read(b); byte[] outBuf = new byte[192]; os.write(outBuf); os.flush(); } int result = readU32(); if (result != 0) { System.out.println("faild authentication "); throw new IOException(); } } /* * default port number is 5999. */ public void selectPort(int p) { if (servSock != null) return; int port = p; while (true) { try { initServSock(port); break; } catch (BindException e) { port++; continue; } catch (IOException e) { } } System.out.println("accept port = " + port); } int getAcceptPort() { return acceptPort; } void setSoTimeout(int num) throws IOException { servSock.setSoTimeout(num); } public Socket accept() throws IOException { return servSock.accept(); } void addSock(Socket sock) { cliList.add(sock); } void addSockTmp(Socket sock) { System.out.println("connected " + sock.getInetAddress()); cliListTmp.add(sock); } boolean markSupported() { return is.markSupported(); } void readServerInit() throws IOException { is.mark(255); skipBytes(20); int nlen = readU32(); int blen = 20 + 4 + nlen; initData = new byte[blen]; is.reset(); is.mark(blen); readFully(initData); is.reset(); framebufferWidth = readU16(); framebufferHeight = readU16(); bitsPerPixel = readU8(); depth = readU8(); bigEndian = (readU8() != 0); trueColour = (readU8() != 0); redMax = readU16(); greenMax = readU16(); blueMax = readU16(); redShift = readU8(); greenShift = readU8(); blueShift = readU8(); byte[] pad = new byte[3]; readFully(pad); int nameLength = readU32(); byte[] name = new byte[nameLength]; readFully(name); desktopName = new String(name); // Read interaction capabilities (TightVNC protocol extensions) if (protocolTightVNC) { int nServerMessageTypes = readU16(); int nClientMessageTypes = readU16(); int nEncodingTypes = readU16(); readU16(); readCapabilityList(serverMsgCaps, nServerMessageTypes); readCapabilityList(clientMsgCaps, nClientMessageTypes); readCapabilityList(encodingCaps, nEncodingTypes); } inNormalProtocol = true; } void sendRfbVersion(OutputStream os) throws IOException { // os.write(versionMsg_3_8.getBytes()); os.write(versionMsg_3_855.getBytes()); } int readVersionMsg(InputStream is, OutputStream os) throws IOException { byte[] b = new byte[12]; is.read(b); if ((b[0] != 'R') || (b[1] != 'F') || (b[2] != 'B') || (b[3] != ' ') || (b[4] < '0') || (b[4] > '9') || (b[5] < '0') || (b[5] > '9') || (b[6] < '0') || (b[6] > '9') || (b[7] != '.') || (b[8] < '0') || (b[8] > '9') || (b[9] < '0') || (b[9] > '9') || (b[10] < '0') || (b[10] > '9') || (b[11] != '\n')) { throw new IOException("Host " + host + " port " + port + " is not an RFB server"); } int rfbMajor = (b[4] - '0') * 100 + (b[5] - '0') * 10 + (b[6] - '0'); int rfbMinor = (b[8] - '0') * 100 + (b[9] - '0') * 10 + (b[10] - '0'); if (rfbMajor < 3) { throw new IOException( "RFB server does not support protocol version 3"); } if (rfbMinor == 855) { sendProxyFlag(os); if (proxyFlag) sendPortNumber(os); } return rfbMinor; } void sendProxyFlag(OutputStream os) throws IOException { if (proxyFlag) os.write(1); else os.write(0); } boolean readProxyFlag() throws IOException { int flag = readU8(); if (flag == 1) return true; else return false; } void sendPortNumber(OutputStream os) throws IOException { byte[] b = new byte[4]; b = castIntByte(geth.port); os.write(b); } void sendSecurityType(OutputStream os) throws IOException { // number-of-security-types os.write(1); // security-types // 1:None os.write(1); /* * os.write(4); os.write(30); os.write(31); os.write(32); os.write(35); * os.flush(); */ } void readSecType(InputStream is) throws IOException { byte[] b = new byte[1]; is.read(b); } void readSecType(InputStream is, OutputStream os) throws IOException { byte[] b = new byte[1]; is.read(b); int count = 260; int[] data = { 0, 2, 0, -128, -1, -1, -1, -1, -1, -1, -1, -1, -55, 15, -38, -94, 33, 104, -62, 52, -60, -58, 98, -117, -128, -36, 28, -47, 41, 2, 78, 8, -118, 103, -52, 116, 2, 11, -66, -90, 59, 19, -101, 34, 81, 74, 8, 121, -114, 52, 4, -35, -17, -107, 25, -77, -51, 58, 67, 27, 48, 43, 10, 109, -14, 95, 20, 55, 79, -31, 53, 109, 109, 81, -62, 69, -28, -123, -75, 118, 98, 94, 126, -58, -12, 76, 66, -23, -90, 55, -19, 107, 11, -1, 92, -74, -12, 6, -73, -19, -18, 56, 107, -5, 90, -119, -97, -91, -82, -97, 36, 17, 124, 75, 31, -26, 73, 40, 102, 81, -20, -26, 83, -127, -1, -1, -1, -1, -1, -1, -1, -1, -111, 73, -29, 30, 57, -67, -75, -77, -49, -50, -99, -76, -80, -80, 14, 65, 57, -105, -103, -54, -102, 3, 39, -44, 39, 35, 118, -84, -64, 37, -117, -21, 89, -31, -68, 70, 5, 122, -92, -119, 9, 121, 63, -112, -60, 122, -46, -69, -36, 92, -103, -92, 74, 92, -73, 87, 120, -8, 116, -47, 111, 20, -41, 110, 122, -3, -94, 14, 42, -51, -59, 48, -54, -125, 117, 60, 77, -52, -31, 98, 32, -2, -102, -15, -29, 58, -14, -106, -116, -32, -86, 50, -32, -16, -3, -123, 87, 88, -118, 10, 120, -107, -37, 125, -110, 59, 87, 93, -24, 124, -99, 18, 78, -13, -49, -34, -24, -27, 1, 114, -67, -98, -56, -3, 85, -67, -126, 77 }; for (int i = 0; i < count; i++) { os.write((byte) data[i]); os.flush(); } byte[] c = new byte[256]; is.read(c); System.out.println(new String(c)); } void sendSecResult(OutputStream os) throws IOException { byte[] b = castIntByte(0); os.write(b); } void readClientInit(InputStream in) throws IOException { byte[] b = new byte[0]; in.read(b); } void sendInitData(OutputStream os) throws IOException { os.write(initData); } void sendPngImage() { try { for (Socket cli : cliListTmp) { try { sendPngData(cli); addSock(cli); } catch (IOException e) { // if socket closed cliListTmp.remove(cli); } } // System.out.println("cliSize="+cliSize()); } catch (Exception e) { } cliListTmp.clear(); } // boolean ready() throws IOException { // BufferedReader br = new BufferedReader(new InputStreamReader(is)); // return br.ready(); // } int cliSize() { return cliList.size(); } void printNumBytesRead() { System.out.println("numBytesRead=" + numBytesRead); } void regiFramebufferUpdate() throws IOException { is.mark(20); messageType = readU8(); // 0 skipBytes(1); // 1 rectangles = readU16(); // 2 rectX = readU16(); // 4 rectY = readU16(); // 6 rectW = readU16(); // 8 rectH = readU16(); // 10 /* * readU16(); // 2 readU16(); // 4 readU16(); // 6 readU16(); // 8 * readU16(); // 10 */ encoding = readU32(); // 12 // System.out.println("encoding = "+encoding); if (encoding == EncodingZRLE || encoding == EncodingZRLEE || encoding == EncodingZlib) zLen = readU32(); else zLen = 0; // System.out.println(zLen); is.reset(); } 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.EncodingTight: dataLen = zLen + 20; // is.mark(dataLen); break; case RfbProto.EncodingZlib: case RfbProto.EncodingZRLE: case RfbProto.EncodingZRLEE: dataLen = zLen + 20; // is.mark(dataLen); break; case RfbProto.EncodingXCursor: case RfbProto.EncodingRichCursor: int pixArray = rectW * rectH * 4; int u8Array = (int) Math.floor((rectW + 7) / 8) * rectH; dataLen = pixArray + u8Array; printFramebufferUpdate(); // is.mark(dataLen); break; default: dataLen = 1000000; // is.mark(dataLen); } return dataLen; } void sendDataToClient() throws Exception { regiFramebufferUpdate(); // printFramebufferUpdate(); int dataLen = checkAndMark(); readSendData(dataLen); } BufferedImage createBufferedImage(Image img) { BufferedImage bimg = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_RGB); Graphics g = bimg.getGraphics(); g.drawImage(img, 0, 0, null); g.dispose(); return bimg; } void createPngBytes(BufferedImage bimg) throws IOException { pngBytes = getImageBytes(bimg, "png"); } byte[] getBytes(BufferedImage img) throws IOException { byte[] b = getImageBytes(img, "png"); return b; } byte[] getImageBytes(BufferedImage image, String imageFormat) throws IOException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); BufferedOutputStream os = new BufferedOutputStream(bos); image.flush(); ImageIO.write(image, imageFormat, os); os.flush(); os.close(); return bos.toByteArray(); } void sendPngData(Socket sock) throws IOException { byte[] dataLength = castIntByte(pngBytes.length); sock.getOutputStream().write(dataLength); sock.getOutputStream().write(pngBytes); } byte[] castIntByte(int len) { byte[] b = new byte[4]; b[0] = (byte) ((len >>> 24) & 0xFF); b[1] = (byte) ((len >>> 16) & 0xFF); b[2] = (byte) ((len >>> 8) & 0xFF); b[3] = (byte) ((len >>> 0) & 0xFF); return b; } BufferedImage createBimg() throws IOException { BufferedImage bimg = ImageIO.read(new ByteArrayInputStream(pngBytes)); return bimg; } 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("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); switch (encoding) { case RfbProto.EncodingRaw: 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]; readFully(b); } void startSpeedCheck() { ByteBuffer b = ByteBuffer.allocate(10); b.put((byte) SpeedCheckMillis); b.flip(); startCheckTime = System.currentTimeMillis(); System.out.println("startChckTime = " + startCheckTime); LinkedList<ByteBuffer> bufs = new LinkedList<ByteBuffer>(); bufs.add(b); multicastqueue.put(bufs); } void endSpeedCheck() { long accTime = System.currentTimeMillis(); long time = accTime - startCheckTime; System.out.println("checkMillis: " + time); } synchronized void changeStatusFlag() { printStatusFlag = true; } void printMills() { if (printStatusFlag) { changeStatusFlag(); } else { changeStatusFlag(); } } void speedCheckMillis() { Runnable stdin = new Runnable() { public void run() { int c; try { while ((c = System.in.read()) != -1) { switch (c) { case 's': break; default: startSpeedCheck(); break; } } } catch (IOException e) { System.out.println(e); } } }; new Thread(stdin).start(); } void requestThreadStart() { requestThread.start(); } public synchronized void requestThreadNotify() { rThread.reStart(); } /** * 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; } float maxMag = 1; /** * 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 sendDataCheckDelay() { LinkedList<ByteBuffer> bufs = new LinkedList<ByteBuffer>(); ByteBuffer b = ByteBuffer.allocate(1); b.put((byte) CheckDelay); b.position(0); bufs.add(b); multicastqueue.put(bufs); } 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); startTiming(); /* * if(inputData.capacity()>64000) { * System.out.println("rectW = "+rectW+": rectH = "+rectH); * System.out.println("--------------------------------"); } */ // System.out.println("DataLength"+inputData.capacity()); // System.out.println("rectW*rextdH"+rectW*rectH); readFully(inputData.array(), 0, inputData.capacity()); // System.out.println(dataLen); inputData.limit(dataLen - 20); stopTiming(); 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); // System.out.println(out.peek().get(INFLATE_BUFSIZE)); /* * System.out.println((((102400 * (out.size() - 1) + * out.getLast() .limit())) - (rectW * rectH * 3)) + ":" + rectH * + ":" + rectW + ":" + out.size()); */ // sumCheck(out); //if((((102400 * (out.size() - 1) + out.getLast() .limit())) - (rectW * rectH * 3))==1){ if(dataLen>64000){ splitData(out, header); } else { // dump32(inputs); nDeflater = new Deflater(); 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(); } /* * System.out.println("ZRLE = "+dataLen); * System.out.println("ZRLEE = "+(len2+20)); float mag = * (float)dataLen / (float)(len2 + 20); * System.out.println("ZRLE / ZRLEE = "+ mag); if(mag > maxMag) * maxMag = mag; System.out.println("maxMag = "+maxMag); */ return; } bufs.add(header); if (dataLen > 16) { ByteBuffer b = ByteBuffer.allocate(dataLen - 16); startTiming(); readFully(b.array(), 0, dataLen - 16); b.limit(dataLen - 16); stopTiming(); bufs.add(b); } multicastqueue.put(bufs); // is.reset(); return; } 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. } public 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 MulticastQueue.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 = 50000 / 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]; 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 { requestThreadNotify(); // rThread.checkDelay(); /** * initial connection of RFB protocol */ sendRfbVersion(os); // readVersionMsg(is); int rfbMinor = readVersionMsg(is, os); sendSecurityType(os); readSecType(is); sendSecResult(os); readClientInit(is); sendInitData(os); new Thread(reader).start(); // discard incoming packet here // after. // writeFramebufferUpdateRequest(0,0, framebufferWidth, // framebufferHeight, false ); int i = 0; for (;;) { LinkedList<ByteBuffer> bufs = c.poll(); int inputIndex = 0; ByteBuffer header = bufs.get(inputIndex); if (header == null) continue; else if (header.get(0) == RfbProto.CheckDelay) { writeToClient(os, bufs, inputIndex); continue; } else if (header.get(0) == RfbProto.FramebufferUpdate) { // System.out.println("client "+ myId); } /* * if(i%20==0){ sendDataCheckDelay(); } i++; */ 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); */ } } void broadCastCommunication(byte[] buf, int len) { String mcastAddr = "224.0.0.1"; int port = 8192; try { InetAddress mAddr = InetAddress.getByName(mcastAddr); MulticastSocket soc = new MulticastSocket(); DatagramPacket sendPacket = null; soc.setTimeToLive(100); // System.out.println("Multicast = " + mcastAddr); // while(buf != null) { // int len = System.in.read(buf); sendPacket = new DatagramPacket(buf, len, mAddr, port); soc.send(sendPacket); // } soc.close(); } catch (IOException e) { e.printStackTrace(); } } public void writeToClient(final OutputStream os, LinkedList<ByteBuffer> bufs, int inputIndex) throws IOException { while (inputIndex < bufs.size()) { ByteBuffer b = bufs.get(inputIndex++); // broadCastCommunication(b.array(),b.limit()-b.position()); 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() { } }; } }; } private LinkedList<ByteBuffer> splitBuffer(LinkedList<ByteBuffer> input) { LinkedList<ByteBuffer> output = new LinkedList<ByteBuffer>(); // int high = rectH / 4; // System.out.println(INFLATE_BUFSIZE * (input.size() - 1)+ // input.getLast().limit()); int dataLen = rectW * 64 * 3 * 2; int temp = 0; int count = rectH / 128; if(rectW%64==0) dataLen+=(rectW/64)*2; else dataLen+=(((rectW/64)+1)*2); for (int i = 0; i < count; i++) { int tempDataLen = dataLen - temp; while (tempDataLen > INFLATE_BUFSIZE) { output.addLast(input.poll()); tempDataLen -= INFLATE_BUFSIZE; } if (tempDataLen == INFLATE_BUFSIZE) { output.addLast(input.poll()); output.addLast(null); temp = INFLATE_BUFSIZE; } else { // System.out.println("THROWIO"); ByteBuffer tempBuf = input.poll(); // System.out.println(tempBuf.remaining()); ByteBuffer buf1 = ByteBuffer.allocate(INFLATE_BUFSIZE); ByteBuffer buf2 = ByteBuffer.allocate(INFLATE_BUFSIZE); tempBuf.get(buf1.array(), 0, tempDataLen); tempBuf.get(buf2.array(), 0, tempBuf.remaining()); buf1.limit(tempDataLen); buf2.limit(INFLATE_BUFSIZE - tempDataLen); buf2.position(0); output.addLast(buf1); output.addLast(null); output.addLast(buf2); temp = INFLATE_BUFSIZE - tempDataLen; } } while (input.size() != 0) { output.addLast(input.poll()); } return output; } private void splitData(LinkedList<ByteBuffer> input, ByteBuffer header) throws IOException, DataFormatException { int sum2=0; LinkedList<ByteBuffer> buf = splitBuffer(input); for (int i = 0 ; i < (rectH/128)+1 ; i++) { int sum=0; LinkedList<ByteBuffer> tempBuf = new LinkedList<ByteBuffer>(); while (buf.peek() != null) { tempBuf.addLast(buf.poll()); sum2+=tempBuf.getLast().limit(); } //Deflater nDeflater = deflater; Deflater nDeflater = new Deflater(); LinkedList<ByteBuffer> bufs = new LinkedList<ByteBuffer>(); for(ByteBuffer b : tempBuf) { sum += b.limit(); } int len2 = zip(nDeflater, tempBuf, 0, bufs); ByteBuffer blen = ByteBuffer.allocate(4); blen.putInt(len2); blen.flip(); bufs.addFirst(blen); createHeader(header,i); System.out.println(sum - (header.getShort(10)*header.getShort(8))*3); System.out.println("sum2="+sum2); bufs.addFirst(header); // broadcastqueue.put(bufs); multicastqueue.put(bufs); //System.out.println("pass"); if(buf.size()!=0) buf.remove(); } //System.out.println("throw"); } private void createHeader(ByteBuffer header,int count) { int rH = Math.min(128, rectH-(128*count)); int rY = rectY + (128*count); header.putShort(10, (short)rH); header.putShort(6 , (short)rY); } private void sumCheck(LinkedList<ByteBuffer> out) { int g = out.size(); int sum = 0; for (int m = 0; m < g; m++) { if (out.get(m) != null) { if (out.get(m).limit() == 102400) sum = sum + 102400; else { sum = sum + out.get(m).limit(); } } } System.out.println(sum); } private void testRoutine() { 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 inflater = new Inflater(); 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. " ); } catch (Exception e) { assertEquals(0, 1); } } }