// Version 0.9a
// 27 January 2007
// Changelog:
//	0.9a: converted msgCode from int to string
// 	0.9: added setMsgCodeAndLabel function

#include "Receiver.h"

// set the listening port
void Receiver::setRecieverPort(int portNum)
{
	serverPort = portNum;
}

// receive the message
void Receiver::getMsg(string msg)
{
	try
	{
		// uncomment to print the message
// 		cout << msg << "\n";

		//set the data field
		setCallID(msg.c_str());
		setFromIP(msg.c_str());
		setToIP(msg.c_str());
		setMsgType(msg.c_str());

	}
	catch (SocketException& e)
	{
		cout << "Exception was caught:" << e.description() << "\nExiting.\n";
	}
}

// set methods follow. these are private ones to be used in getMsg()

// sets string msgType to one of the types in char* type[setOfType]
// or UNKNOWN if not found in array
void Receiver::setMsgType(const char* packet)
{
	int i = 0;
	char* ptr = strstr(packet, "");
	while(*ptr != '\n')
	{
		i++;
		ptr++;
	}

	char* line = new char[i+1];
	char* cptr = line;

	ptr = strstr(packet, ""); // reset pointer location
	while(*ptr != '\n')
	{
		*cptr = *ptr;
		ptr++;
		cptr++;
	}
	
	*cptr = '\0';

	bool found = false;
	bool hasCode = false;
	const int setOfTypes = 11;
	char* type[setOfTypes] = {
		// supported message types
		// some message types, such as INVITE, should never
		// been seen by the receiver, but they are included
		// for completeness
		"100 Trying", "180 Ringing",		// 2
		"200 OK",				// 1
		"408 Request Timeout", "480 Temporarily Unavailable",	// 2
		"603 Decline", "606 Not Acceptable",	// 2
		"ACK", "BYE", "INVITE", "CANCEL"	// 4
	};
	// change this variable whenever then lenght of type[] is changed
// 	int typesWithCodes = 6; // use number of types minus one

	// try to find known type identifiers
        for(int i = 0; i < setOfTypes; i++)
	{
		if(strstr(line, type[i]) != NULL)
		{
			// future TODO: fix case sensitivity
			// SIP RFC says messages are case insensitive.
			// however, the current implementation is fully
			// compatible with KPhone
			msgType = type[i]; // found a known type
			found = true;
			setMsgCodeAndLabel(i);
		}

		if(found)
			break;
	}

	if(!found)
		msgType = "UNKNOWN";
}

// splits a message type (e.g., 100 Trying) into a
// code (e.g., 100) and label (e.g., Trying) part.
// if the code is not recognized, it will be set to int "-111"
// if the label is not recognized, it will be set to string "NA"
// while a switch is harder to maintain, it is easier to read, and more
// importantly, is more reliable thandoing even more type conversions
// and additional parsing
void Receiver::setMsgCodeAndLabel(int i)
{
// 	"100 Trying", "180 Ringing",		// 0,1
// 	"200 OK",				// 2
// 	"408 Request Timeout", "480 Temporarily Unavailable",	// 3,4
// 	"603 Decline", "606 Not Acceptable",	// 5,6
// 	"ACK", "BYE", "INVITE", "CANCEL"	// 7,8,9,10
	msgCode = "-111";
	msgLabel = "NA";

	switch(i)
	{
		case 0:
			msgCode = "100"; msgLabel = "Trying";
			break;
		case 1:
			msgCode = "180"; msgLabel = "Ringing";
			break;
		case 2:
			msgCode = "200"; msgLabel = "OK";
			break;
		case 3:
			msgCode = "408"; msgLabel = "Request Timeout";
			break;
		case 4:
			msgCode = "480"; msgLabel = "Temporarily Unavailable";
			break;
		case 5:
			msgCode = "603"; msgLabel = "Decline";
			break;
		case 6:
			msgCode = "606"; msgLabel = "Not Acceptable";
			break;
		case 7:
			msgLabel = "ACK";
			break;
		case 8:
			msgLabel = "BYE";
			break;
		case 9:
			msgLabel = "INVITE";
			break;
		case 10:
			msgLabel = "CANCEL";
			break;
	}
}

void Receiver::setCallID(const char* packet)
{
	char* ptr = NULL; 
	
	//find the Call-ID: first
	ptr = strstr(packet, "Call-ID:");

	while(*ptr != '\n') 
		ptr++;

	int count=0;
	while(*ptr != ':')
	{	
		ptr--;
		count++;
	}
	ptr += 2;
	
	char* temp = new char[count];
	char* cptr = temp;
	
	while(*ptr != '\n')
	{
		*cptr = *ptr;
		ptr++;
		cptr++;
	}
	
	*cptr = '\0';

	callID = temp;
}

void Receiver::setFromIP(const char* packet)
{
	char* ptr = NULL; 
	
	//find the To: first
	ptr = strstr(packet, "From:");

	while(*ptr != '>') 
		ptr++;

	int count = 0;
	while(*ptr != '@')
	{
		ptr--;
		count++;
	}
	ptr++;

	char* host = new char[count];
	char* hptr = host;
	
	while(*ptr != '>')
	{
		*hptr = *ptr;
		ptr++;
		hptr++;
	}

	*hptr = '\0';

	fromIP = host;
}

void Receiver::setToIP(const char* packet)
{
	char* ptr = NULL; 

	//find the To: first
	ptr = strstr(packet, "To:");

	while(*ptr != '\n') 
		ptr++;

	int count = 0;
	while(*ptr != '@')
	{	
		ptr--;
		count++;
	}
	ptr++;

	char* host = new char[count];
	char* hptr = host;
	
	while(*ptr != '>')
	{
		*hptr = *ptr;
		ptr++;
		hptr++;
	}

	*hptr = '\0';
	char* temp = host;

	toIP = temp;
}
