Mercurial > hg > Members > nobuyasu > tightVNCProxy
view src/myVncProxy/MyRfbProto.java @ 67:f695bc56eb4f
add OptionNoFrame.java. add setEncodings.
author | e085711 |
---|---|
date | Tue, 26 Jul 2011 15:51:19 +0900 |
parents | 7632606406cb |
children | bf5ac06df675 6e703f1000e7 |
line wrap: on
line source
package myVncProxy; 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.ServerSocket; import java.net.Socket; import java.util.LinkedList; import javax.imageio.ImageIO; import myVncProxy.MulticastQueue.Client; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.io.OutputStream; class MyRfbProto extends RfbProto { final static String versionMsg_3_998 = "RFB 003.998\n"; /** * CheckMillis is one of new msgType for RFB 3.998. */ final static int CheckMillis = 4; 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 ServerSocket servSock; private int acceptPort; private byte initData[]; private LinkedList<Socket> cliListTmp; private LinkedList<Socket> cliList; private LinkedList<Thread> sendThreads; boolean createBimgFlag; ExecutorService executor; byte[] pngBytes; private MulticastQueue<byte[]> multicastqueue = new MulticastQueue<byte[]>(); MyRfbProto(String h, int p, VncViewer v) throws IOException { super(h, p, v); cliList = new LinkedList<Socket>(); cliListTmp = new LinkedList<Socket>(); createBimgFlag = false; // sendThreads = new LinkedList<Thread>(); // executor = Executors.newCachedThreadPool(); // executor = Executors.newSingleThreadExecutor(); } MyRfbProto(String h, int p) throws IOException { super(h, p); cliList = new LinkedList<Socket>(); cliListTmp = new LinkedList<Socket>(); createBimgFlag = false; // sendThreads = new LinkedList<Thread>(); // executor = Executors.newCachedThreadPool(); // executor = Executors.newSingleThreadExecutor(); } // over write void writeVersionMsg() throws IOException { clientMajor = 3; if (serverMinor >= 9) { clientMinor = 9; os.write(versionMsg_3_998.getBytes()); } else if (serverMajor > 3 || serverMinor >= 8) { clientMinor = 8; os.write(versionMsg_3_8.getBytes()); } else if (serverMinor >= 9) { clientMinor = 9; os.write(versionMsg_3_998.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; } // 5550を開けるが、開いてないなら+1のポートを開ける。 void selectPort() { int i = 5550; while (true) { try { initServSock(i); break; } catch (BindException e) { i++; continue; } catch (IOException e) { } } System.out.println("accept port = " + i); } int getAcceptPort() { return acceptPort; } void setSoTimeout(int num) throws IOException { servSock.setSoTimeout(num); } 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); } void mark(int len) throws IOException { is.mark(len); } void reset() throws IOException { is.reset(); } boolean markSupported() { return is.markSupported(); } void readServerInit() throws IOException { mark(255); skipBytes(20); int nlen = readU32(); int blen = 20 + 4 + nlen; initData = new byte[blen]; reset(); mark(blen); readFully(initData); 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_998.getBytes()); } void readVersionMsg(InputStream is) 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"); } serverMajor = (b[4] - '0') * 100 + (b[5] - '0') * 10 + (b[6] - '0'); serverMinor = (b[8] - '0') * 100 + (b[9] - '0') * 10 + (b[10] - '0'); if (serverMajor < 3) { throw new IOException( "RFB server does not support protocol version 3"); } } void sendSecurityType(OutputStream os) throws IOException { // number-of-security-types os.write(1); // security-types // 1:None os.write(1); } void readSecType(InputStream is) throws IOException { byte[] b = new byte[1]; is.read(b); } 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 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 { 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 bufResetSend(int size) throws IOException { reset(); int len = size; if (available() < size) len = available(); byte buffer[] = new byte[len]; readFully(buffer); sendData(buffer); } void regiFramebufferUpdate() throws IOException { mark(20); messageType = readU8(); skipBytes(1); rectangles = readU16(); rectX = readU16(); rectY = readU16(); rectW = readU16(); rectH = readU16(); encoding = readU32(); if (encoding == 16) zLen = readU32(); reset(); /* int dataLen; switch (encoding) { case RfbProto.EncodingRaw: dataLen = rectW * rectH * 4 + 16; mark(dataLen); break; case RfbProto.EncodingCopyRect: dataLen = 16 + 4; mark(dataLen); break; case RfbProto.EncodingRRE: case RfbProto.EncodingCoRRE: case RfbProto.EncodingHextile: case RfbProto.EncodingZlib: case RfbProto.EncodingTight: case RfbProto.EncodingZRLE: dataLen = zLen + 20; mark(dataLen); break; default: dataLen = 1000000; mark(dataLen); } */ } int checkAndMark() throws IOException { int dataLen; switch (encoding) { case RfbProto.EncodingRaw: dataLen = rectW * rectH * 4 + 16; mark(dataLen); break; case RfbProto.EncodingCopyRect: dataLen = 16 + 4; mark(dataLen); break; case RfbProto.EncodingRRE: case RfbProto.EncodingCoRRE: case RfbProto.EncodingHextile: case RfbProto.EncodingZlib: case RfbProto.EncodingTight: case RfbProto.EncodingZRLE: dataLen = zLen + 20; mark(dataLen); break; default: dataLen = 1000000; mark(dataLen); } return dataLen; } void readSendData(int dataLen) throws IOException { byte buffer[] = new byte[dataLen]; readFully(buffer); multicastqueue.put(buffer); reset(); /* for (Socket cli : cliList) { try { OutputStream out = cli.getOutputStream(); executor.execute(new SendThread(out, buffer)); } catch (IOException e) { // if client socket closed cliListTmp.remove(cli); } catch (Exception e) { } } */ } void sendDataToClient() throws IOException { regiFramebufferUpdate(); 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 readPngData() throws IOException { pngBytes = new byte[is.available()]; readFully(pngBytes); } */ void printFramebufferUpdate() { System.out.println("messageType=" + messageType); System.out.println("rectangles=" + rectangles); System.out.println("encoding=" + encoding); switch (encoding) { case RfbProto.EncodingRaw: System.out.println("rectW * rectH * 4 + 16 =" + rectW * rectH * 4 + 16); break; default: } } void readCheckMillis() throws IOException { byte[] b = new byte[2]; readFully(b); } void startCheckMillis() { byte[] b = new byte[2]; b[0] = (byte) CheckMillis; b[1] = (byte) 0; startCheckTime = System.currentTimeMillis(); System.out.println("startChckTime = "+ startCheckTime); multicastqueue.put(b); } void endCheckMills() { long accTime = System.currentTimeMillis(); long time = accTime - startCheckTime; System.out.println("checkMillis: " + time); } void printStatus() { System.out.println(); } synchronized void changeStatusFlag() { printStatusFlag = true; } void printMills() { if(printStatusFlag) { changeStatusFlag(); } else { changeStatusFlag(); } } void newClient(acceptThread acceptThread, final Socket newCli, final OutputStream os, final InputStream is) throws IOException { // createBimgFlag = true; // rfb.addSockTmp(newCli); // addSock(newCli); final Client<byte[]> c = multicastqueue.newClient(); Runnable sender = new Runnable() { public void run() { try { /** * initial connection of RFB protocol */ sendRfbVersion(os); readVersionMsg(is); sendSecurityType(os); readSecType(is); sendSecResult(os); readClientInit(is); sendInitData(os); for (;;) { byte[] b = c.poll(); os.write(b, 0, b.length); } } catch (IOException e) { /** * if socket closed */ // cliList.remove(newCli); } } }; new Thread(sender).start(); } void sendCheckMillis() { Runnable stdin = new Runnable() { public void run() { int c; try { while( (c = System.in.read()) != -1 ) { switch(c) { case 's': break; default: startCheckMillis(); break; } } }catch(IOException e){ System.out.println(e); } } }; new Thread(stdin).start(); } }