/* ***************************************************************************+
 * ITX package (cnrg.itx) for telephony application programming.              *
 * Copyright (c) 1999  Cornell University, Ithaca NY.                         *
 * A copy of the license is distributed with this package.  Look in the docs  *
 * directory, filename GPL.  Contact information: bergmark@cs.cornell.edu     *
 ******************************************************************************/

package cnrg.itx.signal;

import cnrg.itx.ds.*;
import cnrg.itx.datax.*;
import cnrg.itx.datax.devices.*;
import java.util.*;
import java.net.*;

/**
 * This class converts methods in <code>InvitePacket</code> into SIP packet format and vice versa.
 */
public class SIPInterface
{
	/**
	 * Converts an <code>InvitePacket</code> into a SIP request message.
	 * 
	 * @param sip the <code>InvitePacket</code>
	 * @param destHost the destination address of the recipient server
	 * @param port the destination port of the recipient server
	 * @return the SIP request message
	 * @exception SIPException
	 */
	protected static String makeSIPRequest(InvitePacket sip, String destHost, int port) throws SIPException
	{
		String SIPString = null;
		int packType = sip.getPacketID();
		int meth = sip.getMethodID();
		String SIPMethod = translatePacket(packType,meth);
		UserID otherID = sip.getDestination();
		String destUID = null;
		
		if (SIPMethod == null)
			throw new SIPException("Bad method");
		else
		{
			if (otherID != null)
				destUID = otherID.toString();
			String destValue = destHost + ":" + (new Integer(port)).toString();
			
			String destString = getDestString(destUID, destValue);
			SIPString = new String(SIPMethod + " " + destString + " " + DesktopSignaling.SIPVersion + "\r\n");
			try
			{
				SIPString = SIPString + makeSIPMessage(sip,SIPMethod,destString);
			}
			catch (SIPException se)
			{
				throw se;
			}
		}
		
		return SIPString;
	}
	
	/**
	 * Creates a SIP response message.
	 * 
	 * @param sip the <code>InvitePacket</code> from the client to respond to
	 * @param header the SIP response header
	 * @param SIPMethod the SIP method being responded to
	 * @param destHost the destinaton address of the receiving client
	 * @param port the destination port of the receiving client
	 * @return the SIP response message
	 * @exception SIPException
	 */
	protected static String makeSIPResponse(InvitePacket sip, String header, String SIPMethod, String destHost, int port) 
		throws SIPException
	{
		String SIPString = null;
		int packType = sip.getPacketID();
		int meth = sip.getMethodID();
		
		if (header == null)
			throw new SIPException("Bad status line");
		else
		{
			UserID otherID = sip.getDestination();
			String destUID = otherID.toString();
			String destValue = destHost + ":" + (new Integer(port)).toString();
			
			String destString = getDestString(destUID,destValue);
			SIPString = DesktopSignaling.SIPVersion + " " + header + "\r\n";
			SIPString = SIPString + makeSIPMessage(sip,SIPMethod,destString);
		}
		
		return SIPString;
	}
	
	/**
	 * Takes the packet type and method of an <code>InvitePacket</code> and determines the corresponding SIP method.
	 * 
	 * @param packType the packet type of the <code>InvitePacket</code>
	 * @param meth the method of the <code>InvitePacket</code>
	 * @return the SIP method
	 */
	protected static String translatePacket(int packType, int meth)
	{
		String sipString = null;
		
		switch(packType)
		{
		case SignalID.INVITE:
			switch(meth)
			{
			case SignalID.DIAL:
				sipString = new String("INVITE");
				break;
			case SignalID.HANGUP:
				sipString = new String("BYE");
				break;
			case SignalID.SENDDTMF:
				sipString = new String("SENDDTMF");
				break;
			}
			break;
		case SignalID.CONFIRM:
			sipString = new String("ACK");
			break;
		}
		return sipString;
	}
	
	/**
	 * Converts the destination ID into proper SIP format.
	 * 
	 * @param destUID the destination ID of the recipient
	 * @param destValue the host address and port number of the recipient
	 * @return the SIP format of the destination ID
	 */
	private static String getDestString(String destUID, String destValue)
	{
		String destString = null;
		
		if (destUID.indexOf("@") != -1)
			destString = makeSIPURL(destUID);
		else 
		{
			if (destUID.length() >= DesktopSignaling.globalPhoneValue)
			{
				try
				{
					new Integer(destUID);
				}
				catch (NumberFormatException nfe)
				{
					destString = makeSIPURL(destUID + "@" + destValue);
					return destString;
				}
				destString = makeSIPURL("+" + destUID + "@" + destValue);
			}
			else
				destString = makeSIPURL(destUID + "@" + destValue);
		}
		
		return destString;
	}
	
	/**
	 * Creates a SIP URL.
	 * 
	 * @param userHost the host address of the sender or recipient
	 * @return the resulting SIP URL
	 */
	private static String makeSIPURL(String userHost)
	{
		String urlString = new String("sip:" + userHost);
		return urlString;
	}
	
	/**
	 * Creates the main body of a SIP message.
	 * 
	 * @param sip the <code>InvitePacket</code> to be given to the recipient
	 * @param SIPMethod the method involved with the SIP message
	 * @param destString the SIP format of the destination ID
	 * @return the SIP message
	 * @exception SIPException
	 */
	private static String makeSIPMessage(InvitePacket sip, String SIPMethod, String destString) throws SIPException
	{
		String SIPString = new String();
		Location myLoc = sip.getSenderLoc();
		String myUID = sip.getSenderID().toString();
		String fromString = makeSIPURL(myUID);
		String myHost = myLoc.getIP();
		String myValue = myLoc.getValue();
		String id = null;
		Long seq = null;
		String desc = null;
		PropertiesCollection prop = null;
		String propAsString = null;
		Long connSeqNumber = null;
		String connSeqAsString = null;
		Object customObject = null;
		String objAsString = null;
		int length = 0;
	
		SIPString = SIPString + "Via: " + DesktopSignaling.SIPVersion + DesktopSignaling.SIPTransport + " " + myValue + "\r\n";
		SIPString = SIPString + "From: " + fromString;
		if (myUID.toString().indexOf("@") == -1)
			SIPString = SIPString + "@" + myValue;
		SIPString = SIPString + "\r\n";
		SIPString = SIPString + "To: " + destString + "\r\n";
		if ((id = sip.getCallID()) == null)
			throw new SIPException("InvitePacket missing CallID");
		SIPString = SIPString + "Call-ID: " + id + "\r\n";
		if ((seq = sip.getCSeq()) == null)
			throw new SIPException("InvitePacket missing CSeq");
		SIPString = SIPString + "CSeq: " + seq.toString() + " " + SIPMethod + "\r\n";
		if ((desc = sip.getDescription()) != null)
			SIPString = SIPString + "User Agent: " + desc + "\r\n";
		if ((prop = sip.getPropertiesCollection()) != null)
		{
			propAsString = prop.toString();
			byte[] propAsBytes = propAsString.getBytes();
			length = (new Integer(propAsBytes.length)).intValue();
		}
		if ((connSeqNumber = sip.getSeqNumber()) != null)
		{
			connSeqAsString = "ConnSeqNumber: " + connSeqNumber.toString() + "\r\n";
			byte[] connSeqAsBytes = connSeqAsString.getBytes();
			length = length + (new Integer(connSeqAsBytes.length)).intValue();
		}
		if ((customObject = sip.getCustomObject()) != null)
		{
			objAsString = "CustomObject: " + customObject.toString() + "\r\n";
			byte[] objAsBytes = objAsString.getBytes();
			length = length + (new Integer(objAsBytes.length)).intValue();
		}
		if (length > 0)
		{
			SIPString = SIPString + "Content Type: " + DesktopSignaling.SIPContentType + "\r\n";
			SIPString = SIPString + "Content Length: " + (new Integer(length)).toString() + "\r\n";
		}
		SIPString = SIPString + "\r\n";
		if (connSeqAsString != null)
			SIPString = SIPString + connSeqAsString;
		if (objAsString != null)
			SIPString = SIPString + objAsString;
		if (propAsString != null)
			SIPString = SIPString + propAsString;
		
		return SIPString;
	}
	
	/**
	 * Creates a <code>SigPacket</code> from a SIP message.
	 * 
	 * @param message the SIP message
	 * @return the <code>SigPacket</code>
	 * @exception SIPException
	 */
	protected static SigPacket makeSigPacket(String message) throws SIPException
	{
		InvitePacket infoPacket;
		UserID source = null;
		Location sourceLoc = null;
		String desc = null;
		int[] methPack = new int[2];
		int result = -1;
		String rejectReason = null;
		UserID destination = null;
		Long connSeqNumber = null;
		String callID = null;
		Long cSeq = null;
		String customObject = null;
		PropertiesCollection pc = null;
		String requestLine;
		String newMessage = message;
		String sipMethod;
		String hostName;
		int firstPlace;
		int endPlace;
		
		endPlace = newMessage.indexOf("\r\n");
		if (endPlace == -1)
			throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " Request-Line missing CRLF");
		requestLine = newMessage.substring(0,endPlace);
		newMessage = newMessage.substring(endPlace+2);
		endPlace = requestLine.indexOf(DesktopSignaling.SIPVersion);
		if (endPlace == -1)
			throw new SIPException((new Integer(ErrorResponse.BADSIPVERSION)).toString());
		if (endPlace != 0)
		{
			try
			{
				methPack = readRequestLine(requestLine);
			}
			catch (SIPException se)
			{
				throw se;
			}
		}
		else
		{
			try
			{
				methPack[0] = SignalID.DIAL;
				methPack[1] = SignalID.RESULT;
				result = readStatusLine(requestLine,rejectReason);
			}
			catch (SIPException se)
			{
				throw se;
			}
		}
		firstPlace = newMessage.indexOf("Via:");
		if (firstPlace != -1)
		{
			firstPlace = newMessage.indexOf(" ",firstPlace+5);
			if (firstPlace != -1)
			{
				endPlace = newMessage.indexOf("\r\n",firstPlace);
				if (endPlace == -1)
					throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " Header missing CRLF");
				sourceLoc = new Location(Location.INTERNET_TYPE,newMessage.substring(firstPlace+1,endPlace),"");
			}
		}
		firstPlace = newMessage.indexOf("From: ");
		if (firstPlace != -1)
		{
			firstPlace = newMessage.indexOf("sip:", firstPlace);
			if (firstPlace == -1)
				throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " From field missing sip:");
			endPlace = newMessage.indexOf("\r\n",firstPlace);
			if (endPlace == -1)
				throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " Header missing CRLF");
			requestLine = newMessage.substring(firstPlace+4,endPlace);
			endPlace = requestLine.indexOf(":");
			if (endPlace == -1)
				source = new UserID(requestLine);
			else
			{
				endPlace = requestLine.indexOf("@");
				if (endPlace == -1)
					throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " From field missing @");
				source = new UserID(requestLine.substring(0,endPlace));
			}
		}
		firstPlace = newMessage.indexOf("To: ");
		if (firstPlace != -1)
		{
			firstPlace = newMessage.indexOf("sip:", firstPlace);
			if (firstPlace == -1)
				throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " To field missing sip:");
			endPlace = newMessage.indexOf("\r\n",firstPlace);
			if (endPlace == -1)
				throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " Header missing CRLF");
			int beginning;
			if ((beginning = newMessage.indexOf("+",firstPlace)) != -1)
				requestLine = newMessage.substring(beginning,endPlace);
			else
				requestLine = newMessage.substring(firstPlace+4,endPlace);
			endPlace = requestLine.indexOf(":");
			if (endPlace == -1)
				destination = new UserID(requestLine);
			else
			{
				endPlace = requestLine.indexOf("@");
				if (endPlace != -1)
					destination = new UserID(requestLine.substring(0,endPlace));
			}
		}
		firstPlace = newMessage.indexOf("Call-ID: ");
		if (firstPlace != -1)
		{
			firstPlace = newMessage.indexOf(" ", firstPlace) + 1;
			endPlace = newMessage.indexOf("\r\n",firstPlace);
			if (endPlace == -1)
				throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " Header missing CRLF");
				callID = newMessage.substring(firstPlace,endPlace);
		}
		firstPlace = newMessage.indexOf("CSeq: ");
		if (firstPlace != -1)
		{
			firstPlace = newMessage.indexOf(" ", firstPlace) + 1;
			endPlace = newMessage.indexOf(" ",firstPlace);
			if (endPlace == -1)
				throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " Sequence header missing space");
			try
			{
				cSeq = new Long(newMessage.substring(firstPlace,endPlace));
			}
			catch (NumberFormatException nfe)
			{
				throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " CSeq: " + nfe);
			}
		}
		firstPlace = newMessage.indexOf("User Agent: ");
		if (firstPlace != -1)
		{
			firstPlace = newMessage.indexOf(" ", firstPlace+5) + 1;
			endPlace = newMessage.indexOf("\r\n",firstPlace);
			if (endPlace == -1)
				throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " Header missing CRLF");
			desc = new String(newMessage.substring(firstPlace,endPlace));
		}
		firstPlace = newMessage.indexOf("ConnSeqNumber: ");
		if (firstPlace != -1)
		{
			firstPlace = newMessage.indexOf(" ", firstPlace) + 1;
			endPlace = newMessage.indexOf("\r\n",firstPlace);
			if (endPlace == -1)
				throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " Header missing CRLF");
			try
			{
				connSeqNumber = new Long(newMessage.substring(firstPlace,endPlace));
			}
			catch (NumberFormatException nfe)
			{
				throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " ConnSeqNumber: " + nfe);
			}
		}
		firstPlace = newMessage.indexOf("CustomObject: ");
		if (firstPlace != -1)
		{
			firstPlace = newMessage.indexOf(" ", firstPlace) + 1;
			endPlace = newMessage.indexOf("\r\n",firstPlace);
			if (endPlace == -1)
				throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " Header missing CRLF");
			customObject = newMessage.substring(firstPlace,endPlace);
		}
		firstPlace = newMessage.indexOf("\r\n\r\n");
		try
		{
			pc = getProperties(newMessage.substring(firstPlace+4));
		}
		catch (SIPException se)
		{
			throw se;
		}
		infoPacket = new InvitePacket(source,sourceLoc,desc,methPack[0]);
		infoPacket.setPropertiesCollection(pc);
		if (destination != null)
			infoPacket.setDestination(destination);
		infoPacket.setSeqNumber(connSeqNumber);
		infoPacket.setCallID(callID);
		infoPacket.setCSeq(cSeq);
		infoPacket.setPacketType(methPack[1]);
		infoPacket.setCustomObject(customObject);
		if (infoPacket.isConfirmPacket())
			infoPacket.confirm();
		if (infoPacket.isResultPacket())
		{
			switch(result)
			{
			case SignalID.ACCEPT:
				infoPacket.accept();
				break;
			case SignalID.BUSY:
				infoPacket.busy();
				break;
			case SignalID.ALIVEQUERY:
				infoPacket.setMethodType(SignalID.ALIVEQUERY);
				break;
			default:
				infoPacket.reject(rejectReason);
			}
		}
		return infoPacket;
	}
	
	/**
	 * Interprets the SIP message body and determines the <code>PropertiesCollection</code>.
	 * 
	 * @param message the SIP message body with <code>PropertiesCollection</code> information
	 * @return the <code>PropertiesCollection</code> of the sender
	 */
	private static PropertiesCollection getProperties(String message) throws SIPException
	{
		int firstPlace;
		int endPlace;
		PropertiesCollection pc = new PropertiesCollection();
		
		firstPlace = message.indexOf("NetworkProperty");
		if (firstPlace != -1)
		{
			InetAddress ip;
			int port;
			double version;
			int ps;
			int seq;
			firstPlace = message.indexOf("IP: ",firstPlace);
			if (firstPlace != -1)
			{
				firstPlace = message.indexOf("/",firstPlace) + 1;
				endPlace = message.indexOf("\r\n",firstPlace);
				if (endPlace == -1)
					throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " IP missing \r\n");
				try
				{
					ip = InetAddress.getByName(message.substring(firstPlace,endPlace));
				}
				catch (UnknownHostException uhe)
				{
					throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " NetworkProperty IP: " + uhe);
				}
			}
			else
				throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " NetworkProperty missing IP Address");
			firstPlace = message.indexOf("Port: ",firstPlace);
			if (firstPlace != -1)
			{
				firstPlace = message.indexOf(" ",firstPlace) + 1;
				endPlace = message.indexOf("\r\n",firstPlace);
				if (endPlace == -1)
					throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " Message missing CRLF");
				try
				{
					port = (new Integer(message.substring(firstPlace,endPlace))).intValue();
				}
				catch (NumberFormatException nfe)
				{
					throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " NetworkProperty Port: " + nfe);
				}
			}
			else
				throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " NetworkProperty missing Port Number");
			firstPlace = message.indexOf("Version: ",firstPlace);
			if (firstPlace != -1)
			{
				firstPlace = message.indexOf(" ",firstPlace) + 1;
				endPlace = message.indexOf("\r\n",firstPlace);
				if (endPlace == -1)
					throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " Message missing CRLF");
				try
				{
					version = (new Double(message.substring(firstPlace,endPlace))).doubleValue();
				}
				catch (NumberFormatException nfe)
				{
					throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " NetworkProperty Version: " + nfe);
				}
			}
			else
				throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " NetworkProperty missing Version");
			firstPlace = message.indexOf("Packet Size: ",firstPlace);
			if (firstPlace != -1)
			{
				firstPlace = message.indexOf(" ",firstPlace+7) + 1;
				endPlace = message.indexOf("\r\n",firstPlace);
				if (endPlace == -1)
					throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " Message missing CRLF");
				try
				{
					ps = (new Integer(message.substring(firstPlace,endPlace))).intValue();
				}
				catch (NumberFormatException nfe)
				{
					throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " NetworkProperty Packet Size: " + nfe);
				}
			}
			else
				throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " NetworkProperty missing Packet Size");
			firstPlace = message.indexOf("ISeq: ",firstPlace);
			if (firstPlace != -1)
			{
				firstPlace = message.indexOf(" ",firstPlace) + 1;
				endPlace = message.indexOf("\r\n",firstPlace);
				if (endPlace == -1)
					throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " Message missing CRLF");
				try
				{
					seq = (new Integer(message.substring(firstPlace,endPlace))).intValue();
				}
				catch (NumberFormatException nfe)
				{
					throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " NetworkProperty ISeq: " + nfe);
				}
			}
			else
				throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " NetworkProperty missing Sequence Number");
			NetworkProperty np = new NetworkProperty(port,ip,ps,version,seq);
			pc.addProperty(np);
		}
		firstPlace = message.indexOf("AudioProperty");
		if (firstPlace != -1)
		{
			int format;
			int rate;
			int bits;
			
			firstPlace = message.indexOf("Format: ",firstPlace);
			if (firstPlace != -1)
			{
				firstPlace = message.indexOf(" ",firstPlace) + 1;
				endPlace = message.indexOf("\r\n",firstPlace);
				if (endPlace == -1)
					throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " Message missing CRLF");
				try
				{
					format = (new Integer(message.substring(firstPlace,endPlace))).intValue();
				}
				catch (NumberFormatException nfe)
				{
					throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " AudioProperty Format: " + nfe);
				}
			}
			else
				throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " AudioProperty missing Sample Format");
			firstPlace = message.indexOf("Rate: ",firstPlace);
			if (firstPlace != -1)
			{
				firstPlace = message.indexOf(" ",firstPlace) + 1;
				endPlace = message.indexOf("\r\n",firstPlace);
				if (endPlace == -1)
					throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " Message missing CRLF");
				try
				{
					rate = (new Integer(message.substring(firstPlace,endPlace))).intValue();
				}
				catch (NumberFormatException nfe)
				{
					throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " AudioProperty Rate: " + nfe);
				}
			}
			else
				throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " AudioProperty missing Sample Rate");
			firstPlace = message.indexOf("Bits: ",firstPlace);
			if (firstPlace != -1)
			{
				firstPlace = message.indexOf(" ",firstPlace) + 1;
				endPlace = message.indexOf("\r\n",firstPlace);
				if (endPlace == -1)
					throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " Message missing CRLF");
				try
				{
					bits = (new Integer(message.substring(firstPlace,endPlace))).intValue();
				}
				catch (NumberFormatException nfe)
				{
					throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " AudioProperty Bits: " + nfe);
				}
			}
			else
				throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " AudioProperty missing Bits Per Sample");
			AudioProperty ap = new AudioProperty(rate,bits,format);
			pc.addProperty(ap);
		}
		return pc;
				
	}
	
	/**
	 * Determines the packet type and method of the SigPacket based on the request header.
	 * 
	 * @param sipRequestLine the request header
	 * @return array of two integers; first - the method, second - the packet type
	 */
	private static int[] readRequestLine(String sipRequestLine) throws SIPException
	{
		int[] methPack = new int[2];
		
		int endPlace = sipRequestLine.indexOf(" ");
		if (endPlace == -1)
			throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " Request-Line missing space");
		String sipMethod = sipRequestLine.substring(0,endPlace);
		try
		{
			methPack = getMethPackType(sipMethod);
		}
		catch (SIPException se)
		{
			throw se;
		}
		return methPack;
	}
	
	/**
	 * Determines the result type based on the SIP response header.
	 * 
	 * @param sipStatusLine the SIP response header
	 * @param reason <code>String</code> that is written to in order to give a reason for the response
	 * @return the result type
	 * @exception SIPException
	 */
	private static int readStatusLine(String sipStatusLine, String reason) throws SIPException
	{
		int result = -1;
		int responseID;
		
		int firstPlace = sipStatusLine.indexOf(" ");
		if (firstPlace == -1)
			throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " Status-Line missing space");
		int endPlace = sipStatusLine.indexOf(" ",firstPlace+1);
		if (endPlace != -1)
		{
			try
			{
				result = (new Integer(sipStatusLine.substring(firstPlace+1,endPlace))).intValue();
			}
			catch (NumberFormatException nfe)
			{
				throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " Status-Line: " + nfe);
			}	
		}
		else
		{
			try
			{
				result = (new Integer(sipStatusLine.substring(firstPlace+1))).intValue();
			}
			catch (NumberFormatException nfe)
			{
				throw new SIPException((new Integer(ErrorResponse.BADREQUEST)).toString() + " Status-Line: " + nfe);
			}	
		}
		switch (result)
		{
		case InfoResponse.OK:
			responseID = SignalID.ACCEPT;
			break;
		case ErrorResponse.BUSYHERE:
			responseID = SignalID.BUSY;
			break;
		default:
			responseID = SignalID.REJECT;
			firstPlace = endPlace + 1;
			reason = sipStatusLine.substring(firstPlace);
		}
		
		return responseID;
	}
	
	/**
	 * Returns the method and packet corresponding to the SIP method.
	 * 
	 * @param sipMethod the SIP method
	 * @return array of two integers; first - the method, second - the packet type
	 * @exception SIPException
	 */
	private static int[] getMethPackType(String sipMethod) throws SIPException
	{
		int[] intArray = new int[2];
		
		if (sipMethod.equals("INVITE"))
		{
			intArray[0] = SignalID.DIAL;
			intArray[1] = SignalID.INVITE;
			return intArray;
		}
		if (sipMethod.equals("ACK"))
		{
			intArray[0] = SignalID.DIAL;
			intArray[1] = SignalID.CONFIRM;
			return intArray;
		}
		if (sipMethod.equals("BYE"))
		{
			intArray[0] = SignalID.HANGUP;
			intArray[1] = SignalID.INVITE;
			return intArray;
		}
		if (sipMethod.equals("SENDDTMF"))
		{
			intArray[0] = SignalID.SENDDTMF;
			intArray[1] = SignalID.INVITE;
			return intArray;
		}
		throw new SIPException((new Integer(ErrorResponse.BADMETHOD)).toString());
	}
}