view src/main/java/jp/ac/u_ryukyu/treevnc/server/GetBroadCastProxy.java @ 81:f93d0286c2ab

root find multicast send port number now.
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Wed, 30 Apr 2014 17:11:15 +0900
parents 2951dd85e9fc
children cc72fdbb7c72
line wrap: on
line source

package jp.ac.u_ryukyu.treevnc.server;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.UnknownHostException;

//import TextBoxProxy;

public class GetBroadCastProxy implements Runnable {
	public static final String McastAddr = "224.0.0.1";
	static final int BufSize = 1024;
	private ByteArrayInputStream inputStream;
	private boolean stopFlag = false;
	private VncProxyService vps;
	public static String MULTICAST_FIND_TREEVNC_ROOT = "TREEVNC-who:";
	private MulticastSocket soc;
    private String bCast;

	public GetBroadCastProxy(VncProxyService _vps,String desktopName,String host){
	    String myaddress = getMyAddress();
	    // getMyAddress is not always connectable eg. in private segment.
		vps = _vps;
		bCast = vps.getRfb().getAcceptPort()+":"+host+":"
				+desktopName+":"+myaddress+":";
	}
	
	/**
	 * To find TreeVNC root, a client sends me a multicast, reply our address to him.
	 *  It contains a port to receive, so multiple TREEVNC clients can run on a PC. 
	 */
	private void replyToRootSearchMulticast() {
		byte[] buf = new byte[BufSize];
		byte[] reply = new byte[BufSize];
		try {
			InetAddress mAddr = InetAddress.getByName(McastAddr);
			soc = new MulticastSocket(Port);
			DatagramPacket recvPacket = new DatagramPacket(buf, BufSize);
			soc.joinGroup(mAddr);
			while (!stopFlag) {
				soc.receive(recvPacket);
				String address = getAddress(recvPacket.getSocketAddress());
				inputStream = new ByteArrayInputStream(recvPacket.getData());
				inputStream.read(reply);
				int i = 0;
				for(byte b : MULTICAST_FIND_TREEVNC_ROOT.getBytes()) {
				    if (b != reply[i]) return;
				    i++;
				}
				int port = parse_code(reply,i);
				replyToClient(address,port,bCast);
				if(stopFlag) break;
			}
		} catch (Exception e) {
			
		}
	}
	
	public int parse_code( byte[] bs,int offset )
	{
	    int intval = 0;
	    for( int i = offset; i < bs.length ; i++ )
	        intval = intval * 10 + ( bs[ i ] - '0' );
	    return intval;
	}
	

    /**
     * To find me (TreeVNC root) ,a client send a broadcast with port number.
     * Send  the parameter to connect to him.
     * The client's GetDataClient will receive this message.
     * 
     * @param addr
     * @param port
     * @param str 
     */
	private void replyToClient(String addr, int port_,String str_) {
	    final String address = addr;
	    final int port = port_;
	    final String str = str_;
		Runnable sender = new Runnable() {
			public void run() {

			        try {
			            Thread.sleep(1000);
			            Socket socket = new Socket(address, port);  // This is a TCP stream to reply
			            PrintStream os = new PrintStream(socket.getOutputStream());
			            os.println(str);
			            os.print(Integer.toString(port));
			            os.close();
			            socket.close();
			        } catch (IOException e) {
			            System.out.println("Connection faild");
			        } catch (InterruptedException e) {
			            System.out.println("Connection faild");
			        }
			}
		};
		new Thread(sender).start();
	}

	private String getAddress(SocketAddress addr) {
		String str = addr.toString();
		str = str.substring(1,str.indexOf(":"));
		return str;
	}
	
	public void run() {
		replyToRootSearchMulticast();
	}

	public void setStopFlag(boolean stopFlag) {
		this.stopFlag = stopFlag;
	}

	public boolean isStopFlag() {
		return stopFlag;
	}
	
	/**
	 *  getLocalHost() returns hostname's address. It may not connectable, but
	 *  it gives readable hostname. Do not use it to connect.
	 * @return
	 */
	String getMyAddress () {
		InetAddress addr = null;
		try {
			addr = InetAddress.getLocalHost();
		} catch (UnknownHostException e) {
			return "localhost";
		}
		return addr.getHostAddress();
	}
}