Mercurial > hg > Members > riono > TreeVNC_ja_comment
view src/main/java/jp/ac/u_ryukyu/treevnc/TreeVncCommandChannelListener.java @ 164:86289e56263c
Send initData in server change
author | oc |
---|---|
date | Wed, 18 Jun 2014 21:16:28 +0900 |
parents | e997deb54314 |
children | 8ab1f6905db4 |
line wrap: on
line source
package jp.ac.u_ryukyu.treevnc; import java.net.Socket; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import com.glavsoft.exceptions.TransportException; import com.glavsoft.rfb.protocol.ProtocolContext; import com.glavsoft.rfb.protocol.ProtocolContext.TreeCommand; import com.glavsoft.rfb.protocol.state.HandshakeState; import com.glavsoft.transport.Reader; import com.glavsoft.transport.Writer; public class TreeVncCommandChannelListener implements Runnable { public MyRfbProto rfb = null; byte[] imageBytes; int port; LinkedBlockingQueue<TreeVncCommand> cmdQueue = new LinkedBlockingQueue<TreeVncCommand>(); private Thread acceptThread; protected final static String versionMsg_3_856 = "RFB 003.856\n"; public TreeVncCommandChannelListener(MyRfbProto _rfb, int p) { rfb = _rfb; port = p; } public void commandMainLoop() { acceptThread = new Thread(new Runnable() { @Override public void run() { TreeVncCommand cmd = null; do { try { cmd = cmdQueue.poll(0, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { continue; } if (cmd!=null) { cmd.handleTreeVncCommand(); } } while (cmd == null || cmd.getCommand() != TreeCommand.QUIT_LOOP); } },"root-command-loop"); acceptThread.start(); } public void run() { commandMainLoop(); while (true) { try { final Socket newCli = rfb.accept(); final OutputStream os = newCli.getOutputStream(); final InputStream is = newCli.getInputStream(); new Thread(new Runnable() { public void run() { TreeVncCommand cmd = newClientHandler(newCli,new Writer(os), new Reader(is)); if (cmd!=null) cmdQueue.add(cmd); } },"accepting").start(); } catch (Exception e) { System.out.println("failed to connect incoming client" + e.getMessage()); } } } public TreeVncCommand newClientHandler (final Socket newCli, final Writer os, final Reader is) { TreeVncCommand cmd = null; try { cmd = initialConnection(rfb, os, is, newCli); if (cmd!=null && cmd.getCommand()!=TreeCommand.NEW_NODE) { // TreeVNC command is processed newCli.close(); return cmd; } } catch (Exception e) { try { System.out.println("new client faild :" + e.getMessage()); newCli.close(); return null; } catch (IOException e1) { System.out.println("new client close faild"); return null; } } return cmd; } public TreeVncCommand initialConnection(MyRfbProto myRfbProto, final Writer os, final Reader is, Socket connection) throws IOException, TransportException { /** * initial connection of RFB protocol */ String myHostAddress = connection.getLocalAddress().getHostAddress(); sendRfbVersion(os); byte[] b; if ((b = readVersionMsg(is, os))!=null) { TreeVncCommand cmd = treeVncCommand(b,is,os,myHostAddress); if (cmd!=null) return cmd; } sendSecurityType(os); readSecType(is); sendSecResult(os); readClientInit(is); sendInitData(os); return new TreeVncCommand(rfb, myHostAddress, TreeCommand.NEW_NODE, os,is,connection); } /** * handle TreeVNC Command * @param b byte [] command * @param is * @param os * @param myHostName * @return * @throws TransportException * @throws IOException * * TreeVNC Command is sent as a possible replied version message. 12 bytes is already read. * Command 4 byte (including padding) * lenght 4 byte * port 4 byte * rest of data ( add padding if it is shorter than 12 byte) */ TreeVncCommand treeVncCommand(byte[] b, Reader is, Writer os, String myHostName) throws TransportException, IOException { ByteBuffer buf = ByteBuffer.wrap(b); TreeCommand command = TreeCommand.create(buf.get()&0xff); // make it unsigned buf.position(buf.position()+3); int length = buf.getInt(); int port = buf.getInt(); String hostname = null; if (length>4) { if (length>1024) { System.out.println("Too long TreeVncCommand "); return null; } byte namebuf[] = new byte[length-4]; try { is.readBytes(namebuf); } catch (TransportException e) { return null; } hostname = new String(namebuf); } return new TreeVncCommand(rfb, myHostName, command, port, hostname); } void sendRfbVersion(Writer writer) throws IOException, TransportException { writer.write(versionMsg_3_856.getBytes()); } byte[] readVersionMsg(Reader reader, Writer writer) throws IOException, TransportException { byte[] b = new byte[HandshakeState.PROTOCOL_STRING_LENGTH ]; reader.readBytes(b); if ((b[0]&0xff)>=220) return b; // TreeVNC extension command. 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"); } return null; } void readSecType(Reader reader) throws TransportException { byte[] b = new byte[1]; reader.read(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 sendSecResult(Writer os) throws TransportException { ByteBuffer b = ByteBuffer.allocate(4); b.order(ByteOrder.BIG_ENDIAN); b.putInt(0); os.write(b.array()); } void readClientInit(Reader in) throws TransportException { byte[] b = new byte[0]; in.readBytes(b); } byte initData[] = {7, -128, 4, 56, 32, 24, 0, 1, 0, -1, 0, -1, 0, -1, 16, 8, 0, 0, 0, 0, 0, 0, 0, 7, 103, 105, 114, 101, 102, 108, 121}; void sendInitData(Writer os) throws TransportException { // In case of "-d" we have no context ProtocolContext context = rfb.context; if (context != null){ os.write(context.getInitData()); } else { // Send dummy data os.write(initData); } } public void waitForShutdown() { if (acceptThread!=null) try { acceptThread.join(); } catch (InterruptedException e) { } } }