/* ***************************************************************************+
 * ITX package (cnrg.itx) for telephony application programming.              *
 * Copyright (c) 1999  Cornell University, Ithaca NY                          *
 *                                                                            *
 * This program is free software; you can redistribute it and/or modify       *
 * it under the terms of the GNU General Public Liense as published by        *
 * the Free Software Foundation, either version 2 of the License, or (at      * 
 * your option) any later version.                                            *
 *                                                                            *
 * The ITX package is distributed in the hope that it will be useful, but     *
 * WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY *
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License   *
 * for more details.                                                          * 
 *                                                                            *
 * A copy of the license is distributed with this package.  Look in the docs  *
 * directory, filename GPL.                                                   *
 *                                                                            * 
 * Contact information:                                                       *
 * Donna Bergmark                                                             *
 * 484 Rhodes Hall                                                            *
 * Cornell University                                                         *
 * Ithaca, NY 14853-3801                                                      *
 * bergmark@cs.cornell.edu                                                    *
 ******************************************************************************/

package cnrg.itx.signal;

import java.net.*;
import java.io.*;

import cnrg.itx.signal.SignalEvent.*;

/**
 * This class represents a backgroud thread that periodically opens socket connections to an
 * application that is participating in a call; to find out if the application is still alive.
 */
class KeepAlive extends Thread
{
	/** Handle to DesktopSignaling **/
	private DesktopSignaling myDS = null;
	/** Handle to the SignalConnection **/
	private SignalConnection mySC = null;
	/** If a socket connection fails thrice the application hangs up the peer **/
	private int count = 0;
	/** To run or not to run **/
	private boolean flag = true;
	/**Keep alive time period; every 15 secs **/
	private static int KEEPALIVE = 15000;	
	
	/** Constructor
	 * 
	 * @param ds the handle to DesktopSignaling
	 * @param sc the handle to present SignalConnection
	 */
	public KeepAlive(DesktopSignaling ds, SignalConnection sc){
		myDS = ds;
		mySC = sc;	
	}
	
	/**
	 * Method called when the thread is started.
	 * 
	 * @param   None.
	 * @return  void
	 */
	public void run(){
		boolean alive = false;
		System.out.println("Keep Alive Thread running...\n");
		try{
			this.sleep(15000);
		}
		catch(InterruptedException ie){
			ie.printStackTrace();
		}

		while(flag){
			alive = checkPeer();
			if (!alive){
				count++;
				System.out.println("Count: "+ count);
			}
			else{
				count = 0;				
				System.out.println("Count: "+ count);
			}
			
			if(count == 3){
				System.out.println("Count: "+ count + "Client is assumed dead.\n");
				alive = false;
			}
			else//assume peer is alive for 3 tries
				alive = true;

			if (alive){
				try{
					this.sleep(KEEPALIVE);
				}
				catch(InterruptedException ie){
					ie.printStackTrace();
				}
			}
			else{
				System.out.println("Peer is not alive.  Closing data connection and hanging up.\n");
				myDS.handlePeerNotAlive(mySC);
				cleanup();
			}
		}
		System.out.println("Keep Alive Thread is now exiting.\n");
	}
	
	/**
	 * This method kills the thread by setting flag to false
	 * 
	 * @param   None.
	 * @return  void
	 */
	public void cleanup(){
		flag = false;
	}
	
	/**
	 * This method sets the wait time for the keep alive thread
	 * 
	 * @param   t is the integer value of waiting period in milli seconds
	 * @return  void
	 */
	public void setKeepAliveTime(int t){
		KEEPALIVE = t;
	}
	
	/**
	 * This method connects to the peer by opening a socket
	 * 
	 * @param   None.
	 * @return  TRUE if the socket was created, FALSE otherwise.
	 */
	private boolean checkPeer(){
		String ip = mySC.getIP();
		int p = mySC.getPort();		
		InetAddress add = null;
		
		try{
			add = InetAddress.getByName(ip);
		}
		catch(UnknownHostException uhe){
			uhe.printStackTrace();
		}
		
		try{
			Socket s = new Socket(add, p);
			s.close();
			return true;
		}
		catch(IOException ioe){
			System.out.println("Peer not responding...");
			return false;
		}
	}

}
