Mercurial > hg > Members > riono > TreeVNC_ja_comment
view src/main/java/jp/ac/u_ryukyu/treevnc/server/MyRfbProtoProxy.java @ 103:84f254d8bde4
remove isinstaceof
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 23 May 2014 02:20:05 +0900 |
parents | 1f7ee648e1f6 |
children | 804b1ce07aa0 |
line wrap: on
line source
package jp.ac.u_ryukyu.treevnc.server; //import static org.junit.Assert.*; //import org.junit.Test; import java.io.IOException; import java.net.BindException; import java.net.ServerSocket; import java.net.Socket; import java.nio.ByteBuffer; import java.util.LinkedList; import com.glavsoft.exceptions.TransportException; import com.glavsoft.rfb.encoding.EncodingType; import com.glavsoft.transport.Reader; import com.glavsoft.transport.Writer; import java.util.concurrent.ExecutorService; import java.util.zip.DataFormatException; import java.util.zip.Deflater; import java.util.zip.Inflater; import jp.ac.u_ryukyu.treevnc.MyRfbProto; public class MyRfbProtoProxy extends MyRfbProto { /** * CheckMillis is one of new msgType for RFB 3.855 and 3.856. */ 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 ServerSocket servSock; protected int acceptPort; private LinkedList<Socket> cliListTmp; private LinkedList<Socket> cliList; boolean createBimgFlag; boolean proxyFlag = true; ExecutorService executor; byte[] pngBytes; private Inflater inflater = new Inflater(); private Deflater deflater = new Deflater(); public RequestScreenThread rThread; private Thread requestThread; private int rangeX = 256; // screenRange XPosition private int rangeY = 256; // screenRange YPosition // private int rangeWidth = 512; // screenRange Width private int rangeHeight = 256; // screenRange Height public MyRfbProtoProxy() { rThread = new RequestScreenThread(this); requestThread = new Thread(rThread); } @Override public boolean isRoot() { return true; } public void setStream(Writer _writer) { // os = _writer; } void initServSock(int port) throws IOException { servSock = new ServerSocket(port); acceptPort = port; } /* * default port number is 5999. */ public int selectPort(int p) { if (servSock != null) return 0; int port = p; while (true) { try { initServSock(port); break; } catch (BindException e) { port++; continue; } catch (IOException e) { } } System.out.println("accept port = " + port); return port; } public int getAcceptPort() { return acceptPort; } void setSoTimeout(int num) throws IOException { servSock.setSoTimeout(num); } public Socket accept() throws IOException { return servSock.accept(); } public void socketClose() throws IOException { servSock.close(); } void addSock(Socket sock) { cliList.add(sock); } void addSockTmp(Socket sock) { System.out.println("connected " + sock.getInetAddress()); cliListTmp.add(sock); } synchronized void changeStatusFlag() { printStatusFlag = true; } void printMills() { if (printStatusFlag) { changeStatusFlag(); } else { changeStatusFlag(); } } 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 = multicastqueue.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 = multicastqueue.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 = multicastqueue.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 = multicastqueue.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 * @param is * @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. * @throws TransportException */ public void readSendData(int dataLen, Reader is) throws TransportException { LinkedList<ByteBuffer> bufs = new LinkedList<ByteBuffer>(); ByteBuffer header = multicastqueue.allocate(16); is.readBytes(header.array(), 0, 16); header.limit(16); if (header.get(0) == FramebufferUpdate) { int encoding = header.getInt(12); if (encoding == EncodingType.ZRLE.getId() || encoding == EncodingType.ZLIB.getId()) { // ZRLEE is // already // recompressed ByteBuffer len = multicastqueue.allocate(4); is.readBytes(len.array(), 0, 4); len.limit(4); ByteBuffer inputData = multicastqueue.allocate(dataLen - 20); is.readBytes(inputData.array(), 0, inputData.capacity()); // System.out.println(dataLen); inputData.limit(dataLen - 20); LinkedList<ByteBuffer> inputs = new LinkedList<ByteBuffer>(); inputs.add(inputData); header.putInt(12, EncodingType.ZRLEE.getId()); // 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>(); //List<ByteBuffer> out = java.util.Collections.synchronizedList(new LinkedList<ByteBuffer>()); int len2 = 0; try { unzip(inflater, inputs, 0, out, INFLATE_BUFSIZE); len2 = zip(nDeflater, out, 0, bufs); out = null; multicastqueue.heapAvailable(); } catch (DataFormatException e) { throw new TransportException(e); } catch (IOException e) { throw new TransportException(e); } ByteBuffer blen = multicastqueue.allocate(4); blen.putInt(len2); blen.flip(); bufs.addFirst(blen); bufs.addFirst(header); addSerialNumber(bufs); multicastqueue.put(bufs); return; } bufs.add(header); if (dataLen > 16) { ByteBuffer b = multicastqueue.allocate(dataLen - 16); is.readBytes(b.array(), 0, dataLen - 16); b.limit(dataLen - 16); 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 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); } } */ /* * 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; } */ void sendRfbVersion(Writer writer) throws IOException, TransportException { // os.write(versionMsg_3_8.getBytes()); writer.write(versionMsg_3_856.getBytes()); } int readVersionMsg(Reader reader, Writer writer) throws IOException, TransportException { byte[] b = new byte[12]; reader.readBytes(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("this 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(writer); if (proxyFlag) sendPortNumber(writer); } return rfbMinor; } void sendProxyFlag(Writer writer) throws TransportException { if (proxyFlag) writer.writeInt(1); else writer.writeInt(0); } void sendPortNumber(Writer writer) throws TransportException { byte[] b = new byte[4]; // b = castIntByte(getHost.getPort()); b = castIntByte(9999); writer.write(b); } void sendSecurityType(Writer os) throws TransportException { // number-of-security-types os.writeInt(1); // security-types // 1:None os.writeInt(1); /* * os.write(4); os.write(30); os.write(31); os.write(32); os.write(35); * os.flush(); */ } void readSecType(Reader reader) throws TransportException { byte[] b = new byte[1]; reader.read(b); } void readSecType(Reader is, Writer os) throws TransportException { byte[] b = new byte[1]; is.readBytes(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.readBytes(c); System.out.println(new String(c)); } void sendSecResult(Writer os) throws TransportException { byte[] b = castIntByte(0); os.write(b); } 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; } void readClientInit(Reader in) throws TransportException { byte[] b = new byte[0]; in.readBytes(b); } @Override public boolean getReadyReconnect() { return readyReconnect; } @SuppressWarnings("unused") private void testScreenSize(LinkedList<ByteBuffer> list, ByteBuffer header) { int block = (64*64*3)+1; // size of one-block. int skip; // skip-byte int xBlock = (header.getShort(8)-header.getShort(4))/64; //xBlockNum int yBlock = (header.getShort(10)-header.getShort(6))/64; // yBlockNum; int outOfRangeT = (rangeY - header.getShort(6))/64 > 0 ? (rangeY - header.getShort(6))/64 : 0; int outOfRangeB = (header.getShort(6) + header.getShort(10))-(rangeY + rangeHeight)/64 > 0 ? (header.getShort(6) + header.getShort(10))-(rangeY + rangeHeight)/64 : 0; int outOfRangeL = (rangeX - header.getShort(4))/64 > 0 ? (rangeY - header.getShort(4))/64 : 0; int outOfRangeR = (header.getShort(4) + header.getShort(8))-(rangeY + rangeHeight)/64 > 0 ? (header.getShort(4) + header.getShort(8))-(rangeY + rangeHeight)/64 : 0; ByteBuffer input = list.getFirst(); if((header.getShort(8)-header.getShort(4)%64)!=0) ++xBlock; if((header.getShort(10)-header.getShort(6)%64)!=0) ++yBlock; for(int i=0; i<yBlock; i++) { for(int g=0; g<xBlock; g++) { if(outOfRangeT < i && i < yBlock - outOfRangeB) { input.get(block); } } } if((rangeX-header.getShort(4))%64==0) skip = 4*block*(header.getShort(8)/64); else skip = (4*block*(header.getShort(8)/64))+1; } @SuppressWarnings("unused") private void createHeader(ByteBuffer buf) { buf.putShort(4, (short)256); buf.putShort(6, (short)256); buf.putShort(8, (short)512); buf.putShort(10, (short)256); } @Override public void stopReceiverTask() { super.stopReceiverTask(); inflater = new Inflater(); } }