changeset 157:7cea8789387b

thread base command listening loop
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Fri, 13 Jun 2014 23:12:28 +0900
parents 93d903877c6b
children 7ffb3fc44105
files src/main/java/com/glavsoft/rfb/protocol/ProtocolContext.java src/main/java/jp/ac/u_ryukyu/treevnc/CreateConnectionParam.java src/main/java/jp/ac/u_ryukyu/treevnc/MyRfbProto.java src/main/java/jp/ac/u_ryukyu/treevnc/TreeVncCommand.java src/main/java/jp/ac/u_ryukyu/treevnc/TreeVncCommandCannelListener.java src/main/java/jp/ac/u_ryukyu/treevnc/TreeVncCommandChannelListener.java src/main/java/jp/ac/u_ryukyu/treevnc/server/VncProxyService.java src/viewer_swing/java/com/glavsoft/viewer/TreeViewer.java src/viewer_swing/java/com/glavsoft/viewer/Viewer.java
diffstat 9 files changed, 273 insertions(+), 230 deletions(-) [+]
line wrap: on
line diff
--- a/src/main/java/com/glavsoft/rfb/protocol/ProtocolContext.java	Fri Jun 13 19:18:47 2014 +0900
+++ b/src/main/java/com/glavsoft/rfb/protocol/ProtocolContext.java	Fri Jun 13 23:12:28 2014 +0900
@@ -91,6 +91,7 @@
 	public static final int CONNECT_TO_AS_LEADER = 224;
     public static final int	LOST_PARENT = 225;
     public static final int NOT_FOUND_PARENT = 226;
+    public static final int NEW_NODE = 227;
     
 	
 }
--- a/src/main/java/jp/ac/u_ryukyu/treevnc/CreateConnectionParam.java	Fri Jun 13 19:18:47 2014 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/treevnc/CreateConnectionParam.java	Fri Jun 13 23:12:28 2014 +0900
@@ -13,7 +13,7 @@
 	private int portNumber = ConnectionParams.DEFAULT_VNC_ROOT;
 	private MyRfbProto rfb;
     private String myHostName;
-    private Thread accThread;
+    public TreeVncCommandChannelListener acceptThread;
 	
 	public CreateConnectionParam(MyRfbProto rfb) {
 		this.rfb = rfb;
@@ -44,8 +44,8 @@
 	
 	public void runTreeVncCommandListener() {
 		rfb.selectPort(ConnectionParams.DEFAULT_VNC_ROOT);
-		TreeVncCommandCannelListener acceptThread = new TreeVncCommandCannelListener(rfb, rfb.getAcceptPort());
-		accThread = new Thread(acceptThread, "tree-vnc-command-listener");
+		acceptThread = new TreeVncCommandChannelListener(rfb, rfb.getAcceptPort());
+		Thread accThread = new Thread(acceptThread, "tree-vnc-command-listener");
 		accThread.start();
 	}
 
@@ -69,7 +69,7 @@
 	    return myHostName;
 	}
 
-    public  Thread getAcceptThread() {
-        return accThread;
+    public  TreeVncCommandChannelListener getAcceptThread() {
+        return acceptThread;
     }
 }
--- a/src/main/java/jp/ac/u_ryukyu/treevnc/MyRfbProto.java	Fri Jun 13 19:18:47 2014 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/treevnc/MyRfbProto.java	Fri Jun 13 23:12:28 2014 +0900
@@ -21,7 +21,6 @@
 import com.glavsoft.rfb.encoding.EncodingType;
 import com.glavsoft.rfb.protocol.Protocol;
 import com.glavsoft.rfb.protocol.ProtocolContext;
-import com.glavsoft.rfb.protocol.state.HandshakeState;
 import com.glavsoft.transport.Reader;
 import com.glavsoft.transport.Writer;
 import com.glavsoft.viewer.ViewerInterface;
@@ -32,7 +31,6 @@
 	final static int CheckDelay = 11;
 	protected final static int FramebufferUpdate = 0;
 	protected ProtocolContext context;
-	protected final static String versionMsg_3_856 = "RFB 003.856\n";
 	private int clients = 0;
 	public MulticastQueue<LinkedList<ByteBuffer>> multicastqueue = new MulticastQueue<LinkedList<ByteBuffer>>();
 	private RequestScreenThread rThread;
@@ -41,48 +39,25 @@
 	private boolean cuiVersion;
 	private long counter = 0; // packet serial number
     TreeVncProtocol treeProtocol;
-	public TreeVncCommand treeVncCommand;
     public ServerSocket servSock;
     private boolean permitChangeScreen = true;
     private static final int INFLATE_BUFSIZE = 1024 * 100;
 
     private Inflater inflater = new Inflater();
     private Deflater deflater = new Deflater();
-    private VncProxyService viewer;
+    VncProxyService viewer;
 
 
 	public MyRfbProto() {
 		rThread = new RequestScreenThread(this);
-	    treeVncCommand = new TreeVncCommand(null,this,null);
 	}
 	
 	public void setVncProxy(VncProxyService viewer) {
 	    this.viewer = viewer;
-	    treeVncCommand.setViewer(viewer);
 	}
 
 	abstract public boolean isRoot() ;
 	
-	public boolean initialConnection(final Writer os, final Reader is, Socket connection)
-			throws IOException, TransportException {
-		/**
-		 * initial connection of RFB protocol
-		 */
-		sendRfbVersion(os);
-		byte[] b;
-		if ((b = readVersionMsg(is, os))!=null) {
-			String myHostAddress = connection.getLocalAddress().getHostAddress();
-            treeVncCommand.treeVncCommand(b,is,os,myHostAddress);
-			return true;
-		}
-		sendSecurityType(os);
-		readSecType(is);
-		sendSecResult(os);
-		readClientInit(is);
-		sendInitData(os);
-		return false;
-	}
-	
 	/**
 	 * handle new client accept 
 	 *     it also handle TreeVNC Command
@@ -93,25 +68,8 @@
 	 * @throws IOException
 	 * @throws TransportException
 	 */
-	public void newClient(TreeVncCommandCannelListener acceptThread, final Socket newCli,final Writer os, final Reader is) { 
+	public void newClient(final Socket newCli,final Writer os, final Reader is) { 
 
-		try {
-            if (initialConnection(os, is, newCli)) {
-                // TreeVNC command is processed
-                newCli.close();
-                return; 
-            }
-        } catch (Exception e) {
-            try {
-                System.out.println("new client faild :" + e.getMessage());
-                newCli.close();
-                return;
-            } catch (IOException e1) {
-                System.out.println("new client close faild");
-                return;
-            }
-        }
-			
 		final int myId = clients;
 		final MulticastQueue.Client<LinkedList<ByteBuffer>> c = multicastqueue.newClient();
 		final AtomicInteger writerRunning = new AtomicInteger();
@@ -271,6 +229,7 @@
 		new Thread(sender, "writer-to-lower-node").start();
 
 	}
+
 	
 
     public boolean permitChangeScreen() {
@@ -286,77 +245,6 @@
 		rThread.reStart();
 	}
 	
-	private void sendRfbVersion(Writer writer) throws IOException, TransportException {
-		writer.write(versionMsg_3_856.getBytes());
-	}
-	
-	private 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 extention 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;
-	}
-	
-	
-	private void readSecType(Reader reader) throws TransportException {
-		byte[] b = new byte[1];
-		reader.read(b);
-	}
-	
-	private 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();
-		 */
-	}
-	
-	private void sendSecResult(Writer os) throws TransportException {
-	       ByteBuffer b = ByteBuffer.allocate(4);
-	        b.order(ByteOrder.BIG_ENDIAN);
-	        b.putInt(0);
-	        os.write(b.array());
-	}
-
-	private 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, 102, 105, 114, 101, 102, 108, 121};
-	private void sendInitData(Writer os) throws TransportException {
-		// In case of "-d" we have no context 
-		if (context != null){
-			os.write(context.getInitData());			
-		} else {
-			// Send dummy data
-			os.write(initData);
-		}
-	}
 	
     public void setProtocolContext(Protocol workingProtocol) {
         context = workingProtocol;
@@ -406,7 +294,6 @@
 	
 	public void setEcho(TreeVncProtocol _echo) {
 		treeProtocol = _echo;
-		treeVncCommand.setVncProtocol(_echo);
 	}
 	
 	public void setViewer(ViewerInterface v) {
--- a/src/main/java/jp/ac/u_ryukyu/treevnc/TreeVncCommand.java	Fri Jun 13 19:18:47 2014 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/treevnc/TreeVncCommand.java	Fri Jun 13 23:12:28 2014 +0900
@@ -1,65 +1,44 @@
 package jp.ac.u_ryukyu.treevnc;
 
 import java.io.IOException;
+import java.net.Socket;
 import java.net.SocketException;
 import java.net.UnknownHostException;
-import java.nio.ByteBuffer;
 
-import com.glavsoft.exceptions.TransportException;
 import com.glavsoft.rfb.protocol.ProtocolContext;
 import com.glavsoft.transport.Reader;
 import com.glavsoft.transport.Writer;
 
-import jp.ac.u_ryukyu.treevnc.client.TreeVncProtocol;
-import jp.ac.u_ryukyu.treevnc.server.VncProxyService;
-
 public class TreeVncCommand {
-    public VncProxyService viewer;
     MyRfbProto rfb;
-    private TreeVncProtocol treeProtocol;
+    int port;
+    String hostname;
+    String myHostName;
+    Writer os;
+    Reader is;
+    private int command;
+    private Socket connection;
 
-    public TreeVncCommand(VncProxyService viewer,MyRfbProto rfb, TreeVncProtocol treeProtocol) {
-        this.viewer = viewer;
+    public TreeVncCommand(MyRfbProto rfb,String myHostName, int command, int port, String hostname) {
         this.rfb = rfb;
-        this.treeProtocol = treeProtocol;
+        this.myHostName = myHostName;
+        this.hostname = hostname;
+        this.port = port;
+        this.command = command;
     }
 
-    /**
-     * handle TreeVNC Command
-     * @param b   byte [] command
-     * @param is
-     * @param os
-     * @param myHostName 
-     * @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)
-     */
-    void treeVncCommand(byte[] b, Reader is, Writer os, String myHostName) throws TransportException, IOException {
-    	ByteBuffer buf = ByteBuffer.wrap(b);
-        int command = 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;
-            }
-             byte namebuf[] = new byte[length-4];
-             try {
-                is.readBytes(namebuf);
-            } catch (TransportException e) {
-                return;
-            }
-             hostname = new String(namebuf);
-        }
-    	switch (command) {
+    public TreeVncCommand(MyRfbProto rfb, String myHostAddress, int newNode,
+            Writer os, Reader is, Socket connection) {
+        this.rfb = rfb;
+        this.myHostName = myHostAddress; 
+        command = newNode;
+        this.os = os;
+        this.is = is;
+        this.connection = connection;
+    }
+
+    public void handleTreeVncCommand()  {
+        switch (command) {
     	case ProtocolContext.FIND_ROOT_REPLY :
     		handleFindRootReply(port,hostname,myHostName);
     		break;
@@ -78,14 +57,13 @@
         case ProtocolContext.LOST_PARENT :
             handleLostParent(port,hostname);
             break;
+        case ProtocolContext.NEW_NODE :
+            rfb.newClient(connection, os, is);
     	    default:
     	        System.out.println("unknown treeVNC command" + command);
     	}
     }
 
-
-
-
  /**
      * new clients ask root to where to connect
      * tell him his parent
@@ -94,7 +72,7 @@
      * @param myHostName 
      */
     void handleWhereToConnect(int port, String hostname, String myHostName) {
-        viewer.decideWhereToConnect(hostname,port,myHostName);
+        rfb.viewer.decideWhereToConnect(hostname,port,myHostName);
     }
 
     /**
@@ -106,12 +84,15 @@
      * @throws SocketException 
      * @throws UnknownHostException 
      */
-    void handleConnectTo(int port, String hostname, String myHostName, boolean leader) 
-    		throws UnknownHostException, SocketException, IOException {
+    void handleConnectTo(int port, String hostname, String myHostName, boolean leader) {
         if (rfb.isRoot()) {
             return; // we don't have parent
         }
-        treeProtocol.connectToParenet(port, hostname, myHostName, leader);
+        try {
+            rfb.treeProtocol.connectToParenet(port, hostname, myHostName, leader);
+        } catch (IOException e) {
+            System.out.println(e.getMessage());
+        }
     }
 
     /**
@@ -131,15 +112,8 @@
      * @param hostname
      */
     private void handleLostParent(int port, String hostname) {
-        viewer.fixLostParent(hostname,port);
+        rfb.viewer.fixLostParent(hostname,port);
     }
 
-	public void setVncProtocol(TreeVncProtocol _echo) {
-		this.treeProtocol = _echo;
-	}
-
-	public void setViewer(VncProxyService v) {
-		this.viewer = v;
-	}
 
 }
\ No newline at end of file
--- a/src/main/java/jp/ac/u_ryukyu/treevnc/TreeVncCommandCannelListener.java	Fri Jun 13 19:18:47 2014 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-package jp.ac.u_ryukyu.treevnc;
-import java.net.Socket;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import com.glavsoft.transport.Reader;
-import com.glavsoft.transport.Writer;
-
-public class TreeVncCommandCannelListener implements Runnable {
-        public MyRfbProto rfb = null;
-        byte[] imageBytes;
-        int port;
-        
-        public TreeVncCommandCannelListener(MyRfbProto _rfb, int p) {
-            rfb = _rfb;
-            port = p;
-        }
-       
-	public void changeRfb(MyRfbProto _rfb) {
-		rfb = _rfb;
-	}
-
-	public void run() {
-		while (true) {
-			try {
-				Socket newCli = rfb.accept();
-				OutputStream os = newCli.getOutputStream();
-				InputStream is = newCli.getInputStream();
-				rfb.newClient(this, newCli, new Writer(os), new Reader(is));
-			} catch (Exception e) {
-			    System.out.println("failed to connect incoming client" + e.getMessage());
-			}
-		}
-	}
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/jp/ac/u_ryukyu/treevnc/TreeVncCommandChannelListener.java	Fri Jun 13 23:12:28 2014 +0900
@@ -0,0 +1,211 @@
+package jp.ac.u_ryukyu.treevnc;
+import java.net.Socket;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.concurrent.LinkedBlockingDeque;
+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.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;
+    LinkedBlockingDeque<TreeVncCommand> cmdQueue = new LinkedBlockingDeque<TreeVncCommand>();
+    protected final static String versionMsg_3_856 = "RFB 003.856\n";
+    
+    public TreeVncCommandChannelListener(MyRfbProto _rfb, int p) {
+        rfb = _rfb;
+        port = p;
+    }
+
+    public void changeRfb(MyRfbProto _rfb) {
+        rfb = _rfb;
+    }
+   
+    public void commandMainLoop() {
+        while(true) {
+            TreeVncCommand cmd = cmdQueue.poll();
+            cmd.handleTreeVncCommand();
+        }
+    }
+
+    public void run() {
+        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)  {
+                // 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, ProtocolContext.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);
+        int command = 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 extention 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, 102, 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);
+        }
+    }
+}
--- a/src/main/java/jp/ac/u_ryukyu/treevnc/server/VncProxyService.java	Fri Jun 13 19:18:47 2014 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/treevnc/server/VncProxyService.java	Fri Jun 13 23:12:28 2014 +0900
@@ -6,7 +6,7 @@
 import java.util.LinkedList;
 import java.util.logging.Logger;
 
-import jp.ac.u_ryukyu.treevnc.TreeVncCommandCannelListener;
+import jp.ac.u_ryukyu.treevnc.TreeVncCommandChannelListener;
 import com.glavsoft.core.SettingsChangedEvent;
 import com.glavsoft.rfb.IChangeSettingsListener;
 import com.glavsoft.rfb.IRfbSessionListener;
@@ -27,7 +27,7 @@
 	public static Logger logger = Logger.getLogger("com.glavsoft");
 	private boolean forceReconnection;
 	private String reconnectionReason;
-	private TreeVncCommandCannelListener acceptThread;
+	private TreeVncCommandChannelListener acceptThread;
 	private TreeRootFinderListener getCast;
 	private TreeManagement clients;
 	static VncProxyService currentVps;
@@ -103,7 +103,7 @@
 	 */
 	public void createConnectionAndStart() {
 		myRfb.selectPort(ConnectionParams.DEFAULT_VNC_ROOT);
-		acceptThread = new TreeVncCommandCannelListener(myRfb, myRfb.getAcceptPort());
+		acceptThread = new TreeVncCommandChannelListener(myRfb, myRfb.getAcceptPort());
 		Thread thread = new Thread(acceptThread, "TreeVNC-accept");
 		thread.start();
 		if(firstTime) {
@@ -172,8 +172,6 @@
 		orderRecconection(hostName);
 	}
 
-	
-
 	@Override
 	public void settingsChanged(SettingsChangedEvent event) {
 
@@ -199,4 +197,8 @@
     public void fixLostParent(String hostname, int port) {
         clients.fixLostParent(hostname,port);
     }
+
+    public  TreeVncCommandChannelListener getAcceptThread() {
+        return this.acceptThread;
+    }
 }
--- a/src/viewer_swing/java/com/glavsoft/viewer/TreeViewer.java	Fri Jun 13 19:18:47 2014 +0900
+++ b/src/viewer_swing/java/com/glavsoft/viewer/TreeViewer.java	Fri Jun 13 23:12:28 2014 +0900
@@ -23,6 +23,12 @@
 	        vps.setNoConnection(noConnection);
 	        vps.proxyStart(args,width,height);
 	        if (!permitChangeScreen ) vps.getRfb().setPermitChangeScreen(false);
+	        Thread root = new Thread(new Runnable() {
+                @Override
+                public void run() {
+                    vps.getAcceptThread().commandMainLoop();             
+                }
+	        },"root-command-loop");
 	    }
 	    ViewerInterface v;
 	    if (viewer) {
--- a/src/viewer_swing/java/com/glavsoft/viewer/Viewer.java	Fri Jun 13 19:18:47 2014 +0900
+++ b/src/viewer_swing/java/com/glavsoft/viewer/Viewer.java	Fri Jun 13 23:12:28 2014 +0900
@@ -292,19 +292,16 @@
 		try {
             cp.findTreeVncRoot();
         } catch (InterruptedException e) {
+            System.out.println("cannot find TreeVNC Root "+e.getMessage());
+            return;
         }
 		isTreeVNC = true;
 		myRfb =  rfb;
         settings.setViewOnly(true); // too avoid unnecessary upward traffic
         cp.createConnectionParam(this);
         rfb.setViewer(this);
-        // SwingUtilities.invokeLater(this);
-        try {
-            Thread thr = cp.getAcceptThread();
-            thr.join();
-        } catch (InterruptedException e) {
-        }
-	}
+        cp.getAcceptThread().commandMainLoop();
+ 	}
 	
 	/**
 	 * start view with specific TreeVNC root
@@ -320,7 +317,7 @@
 		rfb.setViewer(this);
 		myRfb =  rfb;
         settings.setViewOnly(true); // too avoid unnecessary upward traffic
-        SwingUtilities.invokeLater(this);
+        cp.getAcceptThread().commandMainLoop();
 	}