/* ***************************************************************************+
 * 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 cnrg.itx.signal.SignalEvent.*;
import cnrg.itx.datax.*;

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

/** This class represents a thread that handles each request that arrives at the DesktopSignalingServer.
 *  The thread reads and decodes the SigPacket and calls the appropriate method in DesktopSignaling
 *  to complete handling the request.
 */
class SigPacketHandler extends Thread
{
	/** Communication Socket **/
	private Socket mSocket = null;
	/** Request Number of current request **/
	private int mRequestNumber = -1;
	/** InputStream to read the SigPacket **/
	private ObjectInputStream myIn = null;
	/** SigPacket received from peer **/
	private SigPacket mySP = null;
	/** DesktopSignaling handle **/
	private DesktopSignaling myDS = null;
	/** To run or not to run **/
	private boolean flag = true;

	/** Default Constructor
	 * 
	 * @param sock the socket for communication
	 * @param rN the request number
	 * @param ds the DesktopSignaling handle
	 */
	public SigPacketHandler(Socket sock, int rN, DesktopSignaling ds)
	{
		mSocket = sock;
		mRequestNumber = rN;
		myDS = ds;
		
		System.out.println("New request #" + mRequestNumber + " on local port " + sock.getLocalPort() + 
						   " connected to port " + sock.getPort());
		try {
			myIn  = new ObjectInputStream(mSocket.getInputStream());			
		} 
		catch(IOException ioe) {			
			System.out.println("Socket created and then closed by peer.");
			flag = false;
		}
	}

	/**
	 * Method called when the thread is started.
	 * 
	 * @param   None.
	 * @return  void
	 */
	public void run(){
		if (flag){
			readPacket();
			if (flag){
				try{
					handlePacket();
				}
				catch(SigPacketHandlerException sphe){
					System.out.println("Error handling SigPacket, request ignored.");
					sphe.printStackTrace();
				}
			}
		}
		System.out.println("SigPacketHandler Thread exiting for request number: " + mRequestNumber);
	}
			
	/**
	 * Reads the SigPacket object from the ObjectInputStream.
	 * 
	 * @param   None.
	 * @return  void
	 */
	private void readPacket(){
		try{
			mySP = (SigPacket) myIn.readObject();
		}
		catch (OptionalDataException ode){
			flag = false;
			ode.printStackTrace();
		}
		catch (ClassNotFoundException cnfe){
			flag = false;
			cnfe.printStackTrace();
		}
		catch (IOException ioe){
			flag = false;
			ioe.printStackTrace();
		}
	}
		
	/**
	 * This method decodes a SignalPacket and calls the required method in DesktopSignaling.
	 * The thread passes the socket handle to DesktopSignaling for further communication.
	 * 
	 * @param None
	 * @return void
	 * @exception SigPacketHandlerException
	 * 
	 * @see cnrg.itx.signal.SigPacketHandlerException
	 */
	private void handlePacket() throws SigPacketHandlerException{
		if (mySP == null){
			throw new SigPacketHandlerException("Received a null object.  Dropping object...  Dropped\n");
		}

		if(mySP.isInvitePacket()){
			switch(mySP.getMethodID()){
				case SignalID.DIAL:
					InviteSignalEvent ise = new InviteSignalEvent((InvitePacket)mySP);
					ise.setDesktopSignaling(myDS);
					try{
						myDS.handleDialInvite(ise, mSocket);
					}
					catch (DesktopSignalingException dse){
						dse.printStackTrace();
					}
					catch (DataException de){
						de.printStackTrace();
					}
					break;
				case SignalID.HANGUP:
					HangupSignalEvent hse = new HangupSignalEvent((InvitePacket)mySP);
					hse.setDesktopSignaling(myDS);
					myDS.handleHangupInvite(hse, mSocket);
					break;
				case SignalID.SENDDTMF:
					DTMFSignalEvent dse = new DTMFSignalEvent((InvitePacket)mySP, (String) mySP.getCustomObject());
					dse.setDesktopSignaling(myDS);
					myDS.handleSendDTMFInvite(dse, mSocket);
					break;
				case SignalID.ALIVEQUERY:
					AliveSignalEvent ase = new AliveSignalEvent((InvitePacket)mySP);
					ase.setDesktopSignaling(myDS);
					myDS.handleAliveInvite(ase, mSocket);
					break;
			}
		}
		else
			throw new SigPacketHandlerException("Received an unknown SigPacket.  Dropping packet...\nDropped.\n");
	}	

}
