view src/main/java/jp/ac/u_ryukyu/treevnc/server/AcceptClient.java @ 136:81b558b38b9f

reconnection
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Sun, 08 Jun 2014 19:23:50 +0900
parents ada4d850a820
children c3761c896607
line wrap: on
line source

package jp.ac.u_ryukyu.treevnc.server;

import java.net.UnknownHostException;
import java.io.*;
import java.net.*;
import java.util.*;

import jp.ac.u_ryukyu.treevnc.MyRfbProto;
import jp.ac.u_ryukyu.treevnc.client.TreeVncProtocol;

public class AcceptClient {
	private LinkedList<TreeVNCNode> nodeList = new LinkedList<TreeVNCNode>();
	boolean runflag = false;
	private final int treebranch = 2;
	//  private final int intv_time = 100;    avoid too frequent reconnection
    private MyRfbProto rfb;

	public AcceptClient(MyRfbProto rfb) {
	    this.rfb = rfb;
	    TreeVNCNode me = new TreeVNCNode( rfb.getMyAddress(), rfb.getAcceptPort());
	    me.setTreeNum(0);
        nodeList.add(me);
	}
	
//
//	private boolean checkAddress(String line) {
//		String test[] = line.split("\\.");
//		int a = Integer.parseInt(test[0]);
//		int b = Integer.parseInt(test[1]);
//		if ((192 == a && b == 168) || (172 == a && (b > 15 || b < 32))
//				|| 10 == a) {
//			return true;
//		} else {
//			return false;
//		}
//	}

	/**
	 * a parent is lost, remove from the list and move last one into here
	 * @param nodeNum
	 *            parent value
	 */
	private void moveLastNodeToLostNodePosition(int nodeNum) {
		nodeList.remove(nodeNum);
		TreeVNCNode node = nodeList.removeLast();
		node.setTreeNum(nodeNum);
		nodeList.add(nodeNum, node) ; 
	}

	private void checkParameter(int parent, int counter, int leaderflag2) {
		System.out.println("number p =" + parent);
		System.out.println("number i =" + counter);
		System.out.println("leaderflag=" + leaderflag2 + "\n");
	}

	String getMyAddress() {
		InetAddress addr = null;
		try {
			addr = InetAddress.getLocalHost();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}
		return addr.getHostAddress();
	}

	private TreeVNCNode getParentNode(int nodeNum) {
		int parentnum = (nodeNum - 1) / treebranch;
        return  nodeList.get(parentnum);
	}
	
	/**
	 * A parent is lost, move last node which has no child to the position 
	 * @param hostname
	 * @param port
	 */
    public void fixLostParent(String hostname, int port) {
        TreeVNCNode lostParentNode = lookup(nodeList,hostname,port);
        if (lostParentNode == null ) return;   // some thing wrong
        int treeNumber = lostParentNode.getTreeNum();
        TreeVNCNode newparent = getParentNode(treeNumber);
        moveLastNodeToLostNodePosition(treeNumber);
        if(nodeList.size() > treeNumber +1)
            lostNodeConnection(newparent);
        // if lostParentNode is the last one, we don't need reconnection
        // Thread.sleep(intv_time);
    }

    /**
     * send reconnect to all children
     * @param newparent
     */
    private void lostNodeConnection(TreeVNCNode newparent) {
        for(int i=1; i < treebranch; i++ ) {
            if (newparent.getTreeNum() + i <=nodeList.size() ) {
                TreeVNCNode n = nodeList.get(newparent.getTreeNum()+i) ;
                TreeVncProtocol vc = new TreeVncProtocol(n.getHostname(),n.getPort());
                try {
                    vc.connectTo(newparent.getHostname(), newparent.getPort(), isLeader(newparent));
                } catch (IOException e) {
                    // log
                }
            }
        }
    }

    private int isLeader(TreeVNCNode n) {
        return ( n.getTreeNum() % treebranch == 1) ? 1 : 0;
    }

    private TreeVNCNode lookup(LinkedList<TreeVNCNode> list, String hostname, int port) {
	    for (TreeVNCNode r : list) {
	        if (r.getHostname().equals(hostname) && r.getPort() == port )
	                return r;
	    }
	    return null;
    }

	/**
	 * Determine tree topology and send CONNECT_TO command
	 * @param hostname
	 * @param port
	 */
	public void replyCreateTree(String hostname, int port) {
        TreeVNCNode node = new TreeVNCNode(hostname,port);
        node.setTreeNum(nodeList.size());
        nodeList.add(node);
	    TreeVncProtocol treeProtocol = new TreeVncProtocol(hostname,port);
	    try {
	        if (nodeList.size() >= treebranch + 1) {
	            TreeVNCNode parent = getParentNode(node.getTreeNum());
	            checkParameter(parent.getTreeNum(), nodeList.size(), isLeader(node));
	            treeProtocol.connectTo(parent.getHostname(),parent.getPort(),isLeader(node));
	        } else {
	            // connect to me
	            treeProtocol.connectTo(rfb.getMyAddress(),rfb.getAcceptPort(),isLeader(node));
	        }
	    } catch (IOException e) {
	        // log
	    }
	}

	public LinkedList<TreeVNCNode> getList() {
		return nodeList;
	}

	public void setList(LinkedList<TreeVNCNode> _ls) {
		nodeList = _ls;
	}

	public int getTreeBranch() {
		return treebranch;
	}

}