/*	TCAP monitor c file					*/
/*	Written by Liu Zhiguo	2002-05-06	*/
/*	Version 1.0							*/
/*	-----------------------------------	*/
#include "../../public/src/include/pub_include.h"
#include "../../sccp/src/include/sccp.h"
#include "../../debug/src/include/debug.h"
#include "../../snmp/src/include/snmp.h"
#include "../../snmp/src/include/heartbeat.h"
#include "./include/tcap_public.h"
#include "./include/tcap_struct.h"
#include "./include/idmanage.h"


/*@ignore@*/
#define LED_GREEN			9
#define LED_YELLOW			10
#define LED_RED				11
#define	MAX_PAGE			8
#define MAX_LINE			22
#define STATE_LINE			20
#define TCAP_CSTA_INTERVAL	15	// tcap CDR interval time:15 minutes
#define TCAP_PREOBJ_LEN		11	// tcap prefix object id length
#define TCAP_HBOBJ_LEN		14	// tcap heartbeat led object id length
#define TCAP_ID_LEN			15
#define TCAP_TITLE_LEN		16
#define TCAP_LINE_LEN		17
#define TCAP_PAGE_POINT		14
#define TCAP_LINE_POINT		15
#define TCAP_VERSION_LEN	3

static struct	tcapdebug_struct	*debug_ptr;
extern u32		tcap_dlg_stats[MAX_DIALOGUEID];

static u8	tcap_1s_flag;
static u8	tcap_10s_flag;
static u8	sec_page;
static u8	*disp_ptr;
static u8	tcap_status = 1;
static u32	tcap_object_id[] = {1,3,6,1,4,1,1373,2,3,2,4};
static u32	tcap_status_id[] = {1,3,6,1,4,1,1373,1,3,2,3,1,2,TCAP_MODULE_ID + 2,1};
static u32	tcap_version_id[] = {1,3,6,1,4,1,1373,1,3,2,3,1,2,TCAP_MODULE_ID + 2,2};
static u32	tcap_ascin_id[] = {1,3,6,1,4,1,1373,1,3,2,3,1,2,TCAP_MODULE_ID + 2,3};
static u32	tcap_ascout_id[] = {1,3,6,1,4,1,1373,1,3,2,3,1,2,TCAP_MODULE_ID + 2,4};
static u32	tcap_page_title[] = {1,3,6,1,4,1,1373,1,3,2,3,1,2,TCAP_MODULE_ID + 2,5,1};
static u32	tcap_page_line[] = {1,3,6,1,4,1,1373,1,3,2,3,1,2,TCAP_MODULE_ID + 2,5,2,2};
//static u8	tcap_ver[] = {6,5,10};
static u8	tcap_ver[] = {1,0,01};
static u8	title1[] = {"Page 01\t\tTCAP module information\r\n\nStart time\r\nCurrent time\r\nInvoke timer\r\nReject timer\r\nMonitor did\r\nTcap status\r\n"};
static u8	title2[] = {"Page 02\t\tTCAP watch_dog page\r\n\t\t   00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15\r\n"};
static u8	title3[] = {"Page 03\t\tTCAP CSTA information\r\n\t\t   00\t       01\t   02\t       03\t   04\r\nSection page\r\n"};

static u8 	ascii[16] = {0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
						 0x38,0x39,0x41,0x42,0x43,0x44,0x45,0x46};
			
void HexToDisplay(u8 *to_asc, u8 *from_hex, u8 from_len)
{
	int	i, j = 0;
	
	for (i = 0; i < from_len; i++)
	{
		to_asc[j] = ascii[from_hex[i] >> 4];
		j++;
		to_asc[j] = ascii[from_hex[i] & 0x0f];
		j++;
		to_asc[j] = ' ';
		j++;
	}
	to_asc[j] = '\0';
}

void tcap_send_ascout(char *asc_str)
{
	if (debug_ptr->send_control == 1)
		return;
	if ((strlen(asc_str) + strlen((char *)debug_ptr->ascout_buf)) > TCAP_ASCOUT_LEN/2)	// buffer is full
	{
		debug_ptr->send_control = 1;
//		strcat(debug_ptr->ascout_buf,"\r\n--\r\n");
//		strcpy(debug_ptr->ascout_buf,asc_str);
	}
	else
		strcat((char *)debug_ptr->ascout_buf,asc_str);
}

void tcap_send_error(char *err_str)
{
	char info_str[1024];

	if (debug_ptr->error_switch == 0 || debug_ptr->send_control == 1)
		return;
	sprintf(info_str,"\33[31m%s\33[0m\n\r\n\r",err_str);
	tcap_send_ascout(info_str);
}

void tcap_send_info(char *info)
{
	char info_str[1024];

	if (debug_ptr->sccp_switch == 0 || debug_ptr->send_control == 1)
		return;
	sprintf(info_str,"%s\n\r",info);
	tcap_send_ascout(info_str);
}

u8	tcap_disp_line(u8 page,u8 line)
{
	u8		line_len=0;
	u32		ii;

	disp_ptr = tcap_ver;
	switch (page)
	{
		case 1:	// page 1
			switch (line)
			{
				case 0:
					disp_ptr = debug_ptr->start_time;
					line_len = 6;
					break;
				case 1:
					disp_ptr = debug_ptr->current_time;
					line_len = 6;
					break;
				case 2:		// invoke time
					disp_ptr = &debug_ptr->default_invtime;
					line_len = 1;
					break;
				case 3:		// reject time
					disp_ptr = &debug_ptr->default_rejtime;
					line_len = 1;
					break;
				case 4:		// monitor dialogue id
					disp_ptr = (u8 *) &debug_ptr->monitor_did;
					line_len = 4;
					break;
				case 5:		// heartbeat status
					disp_ptr = debug_ptr->hb_status;
					line_len = TCAP_HB_LEN;
					break;
				case 6:
					line_len = 8;
					disp_ptr = (u8 *)&debug_ptr->local_ip;
					break;
				default:
					line_len = 0;
					break;
			}
			break;
		case 2:	// page 2
			if (line < 16)
			{
				disp_ptr = debug_ptr->watch_dog + line * 16;
				line_len = 16;
			}
			break;
		case 3:	// page 3
			if (line == 0)
			{
				disp_ptr = &sec_page;
				line_len = 1;
			}
			else if (line < TCAP_UTILIZE_LEN/5+1)
			{
				ii = sec_page % (TCAP_UTILIZE_COUNT-1);
				disp_ptr = (u8 *)&debug_ptr->tc_utilize[ii][(line-1)*5];
				line_len = 20;
			}
			break;
		case 4:	// tcap state
			if (line < STATE_LINE)
			{
				ii = (sec_page * STATE_LINE + line) % (tcap_ptr->grantdid);
				disp_ptr = (u8 *) &tcap_ptr->tcapvm_data[ii].peer_tid;
				line_len = 20;
			}
			else if (line == STATE_LINE+1)
			{
				disp_ptr = &sec_page;
				line_len = 1;
			}
			break;
		case 5:	// ism state
			if (line < MAX_TEMPINVOKEID)
			{
				ii = sec_page % (tcap_ptr->grantdid);
				disp_ptr = (u8 *) &tcap_ptr->tcapvm_data[ii].ism_data[line].used_flag;
				line_len = 20;
			}
			else if (line == MAX_TEMPINVOKEID+1)
			{
				disp_ptr = &sec_page;
				line_len = 1;
			}
			break;
		default:
			line_len = 0;
			break;
	}
	return line_len;
}

void tcap_disp_page(u8 page)
{
	u8		line;
	u8		line_len;

	tcap_page_line[TCAP_PAGE_POINT] = page + 5;
	for (line = 0;line < MAX_LINE;line ++)
	{
		line_len = tcap_disp_line(page,line);
		tcap_page_line[TCAP_LINE_POINT] = line + 2;
		debug_set_response(TCAP_LINE_LEN,tcap_page_line,disp_ptr,line_len);
	}
}

int tcap_snmp_set(u8 oid_len,u32 *oid,u8 *data_buf,u16 data_len)
{
	u8		ii;

	ii = TCAP_PREOBJ_LEN;
	if (oid_len < ii+2)
		return -1;
	switch (oid[ii])
	{
		case 2:	// set timer
			switch (oid[ii+1])
			{
				case 1:		// set invoke timer
					if (data_len == 1)	// only one octet
					{
						debug_ptr->default_invtime = data_buf[0];
						return 1;
					}
					break;
				case 2:		// set reject timer
					if (data_len == 1)
					{
						debug_ptr->default_rejtime = data_buf[0];
						return 1;
					}
					break;
				case 3:		// set monitor switch
					switch (oid[ii+2])
					{
						case 1:		// monitor SCCP
							if (data_len == 1)
							{
								debug_ptr->sccp_switch = data_buf[0];
								return 1;
							}
							break;
						case 2:		// monitor tcu
							if (data_len == 1)
							{
								debug_ptr->tcu_switch = data_buf[0];
								return 1;
							}
							break;
						case 3:		// monitor error
							if (data_len == 1)
							{
								debug_ptr->error_switch = data_buf[0];
								return 1;
							}
							break;
						case 4:		// monitor dialogue id
							if (data_len <= 4)
							{
								debug_ptr->monitor_did = bcdtou32(data_buf,data_len);
								return data_len;
							}
							break;
						default:
							break;
					}
					break;
				default:
					break;
			}
			break;
		default:
			break;
	}
	return -1;	// set fail
}

int tcap_snmp_get(u8 oid_len,u32 *oid,u8 *data_buf,u8 *data_type)
{
	u8		ii,jj,kk;
	int		data_len=-1;

	ii = TCAP_PREOBJ_LEN;
	if (oid_len <= ii+1)
		return -1;
	switch (oid[ii])	// judge object id
	{
		case 3:		// measure
			if (oid_len != ii + 2)	// reach instance, get total measure data
				return -1;			// not support
			if (oid[ii+1] > TCAP_UTILIZE_COUNT-2)
				return -1;
			if (oid[ii+1] == debug_ptr->current_csta)
				return -1;
			jj = oid[ii+1];
			if (debug_ptr->csta_time[jj] == 0)
				return 0;
			u32tobyte(data_buf,debug_ptr->csta_time[jj]);
			data_len = 4;
			for (kk = 0;kk < TCAP_UTILIZE_LEN;kk ++)
				u32tobyte(data_buf+(kk+1)*4,debug_ptr->tc_utilize[jj][kk]);
			data_len += TCAP_UTILIZE_LEN * 4;
			*data_type = 4;
			break;
		case 2:		// configure
			switch (oid[ii+1])
			{
				case 1:		// invoke timer
					data_len = 1;
					data_buf[0] = debug_ptr->default_invtime;
					*data_type = 2;
					break;
				case 2:		// reject timer
					data_len = 1;
					data_buf[0] = debug_ptr->default_rejtime;
					*data_type = 2;
					break;
				case 3:		// monitro switch
					switch (oid[ii+2])
					{
						case 1:		// sccp switch
							data_buf[0] = debug_ptr->sccp_switch;
							data_len = 1;
							*data_type = 2;
							break;
						case 2:		// tcu switch
							data_buf[0] = debug_ptr->tcu_switch;
							data_len = 1;
							*data_type = 2;
							break;
						case 3:		// error switch
							data_buf[0] = debug_ptr->error_switch;
							data_len = 1;
							*data_type = 2;
							break;
						case 4:		// dialogue id switch
							u32tobyte(data_buf,debug_ptr->monitor_did);
							data_len = 4;
							*data_type = 4;
							break;
						default:
							break;
					}
					break;
				default:
					break;
			}
			break;
		case 1:	// status
			switch (oid[ii+1])
			{
				case 1:		// get version
					data_len = TCAP_VERSION_LEN;
					memcpy(data_buf,tcap_ver,data_len);
					*data_type = 4;
					break;
				case 2:		// get tcap status
					data_len = TCAP_HB_LEN;
					memcpy(data_buf,debug_ptr->hb_status,data_len);
					*data_type = 4;
					break;
				default:
					break;
			}
			break;
		default:	// can not recognize object id
			break;
	}
	return data_len;	// get fail
}

void init_m(void)
{
	u8		page,ii;
	char	info_str[1024];
	char	temp_str[256];
	char	*cur_time;
	u32		str_len;

	debug_ptr = (tcapdebug_struct *) &tcap_ptr->tcap_debug;
	tcap_1s_flag = 0;
	tcap_10s_flag = 0;
	sec_page = 0;
	GetCurrentTime(debug_ptr->start_time);
	debug_ptr->ascin_buf[0] = '\0';
	debug_ptr->ascout_buf[0] = '\0';
	debug_set_response(TCAP_ID_LEN,tcap_status_id,&tcap_status,1);	// set status id
	sprintf(info_str,"V%d.%d.%02d",tcap_ver[0],tcap_ver[1],tcap_ver[2]);
	debug_set_response(TCAP_ID_LEN,tcap_version_id,(BYTE *)info_str,strlen(info_str));	// set module description
	debug_set_response(TCAP_ID_LEN,tcap_ascin_id,debug_ptr->ascin_buf,TCAP_ASCIN_LEN);
	debug_set_response(TCAP_ID_LEN,tcap_ascout_id,debug_ptr->ascout_buf,TCAP_ASCOUT_LEN);
	for (page = 1;page < MAX_PAGE;page ++)
	{
		switch (page)
		{
			case 1:
				sprintf(info_str,"Version:R%dV%dT%d\t%s",tcap_ver[0],tcap_ver[1],tcap_ver[2],title1);
				str_len = strlen(info_str);
				break;
			case 2:
				sprintf(info_str,"Version:R%dV%dT%d\t%s",tcap_ver[0],tcap_ver[1],tcap_ver[2],title2);
				for (ii = 0;ii < 16;ii ++)
				{
					sprintf(temp_str,"watch_dog%d\r\n",ii*16);
					strcat(info_str,temp_str);
				}
				str_len = strlen(info_str);
				break;
			case 3:
				sprintf(info_str,"Version:R%dV%dT%d\t%s",tcap_ver[0],tcap_ver[1],tcap_ver[2],title3);
				for (ii = 0;ii < TCAP_UTILIZE_LEN/5;ii ++)
				{
					sprintf(temp_str,"Data%d--%d\r\n",ii*5,ii*5+4);
					strcat(info_str,temp_str);
				}
				str_len = strlen(info_str);
				break;
			case 4:
				sprintf(info_str,"Version:R%dV%dT%d\tTCAP state\r\n\n",tcap_ver[0],tcap_ver[1],tcap_ver[2]);
				for (ii = 0;ii < STATE_LINE;ii ++)
				{
					sprintf(temp_str,"TCAP %d\r\n",ii);
					strcat(info_str,temp_str);
				}
				strcat(info_str,"\nCurrent_page\r\n");
				str_len = strlen(info_str);
				break;
			case 5:
				sprintf(info_str,"Version:R%dV%dT%d\tISM state\r\n\n",tcap_ver[0],tcap_ver[1],tcap_ver[2]);
				for (ii = 0;ii < MAX_TEMPINVOKEID;ii ++)
				{
					sprintf(temp_str,"ISM %d\r\n",ii);
					strcat(info_str,temp_str);
				}
				strcat(info_str,"\nCurrent_page\r\n");
				str_len = strlen(info_str);
				break;
			default:
				strcpy(info_str, (char *)title1);
				str_len = 0;
				break;
		}
		tcap_page_title[TCAP_PAGE_POINT] = page + 5;
		debug_set_response(TCAP_TITLE_LEN,tcap_page_title, (BYTE *)info_str,str_len);
		tcap_disp_page(page);
	}
	
// 	init snmp portion
//	heartbeat_init(TCAP_SYSTEM_ID);	// register tcap heartbeat
	inquire_setmsg(TCAP_PREOBJ_LEN,tcap_object_id,tcap_snmp_set);
	inquire_getmsg(TCAP_PREOBJ_LEN,tcap_object_id,tcap_snmp_get);
	debug_ptr->default_invtime = INVOKE_TIMER;
	debug_ptr->default_rejtime = REJECT_TIMER;

	cur_time = GetAsciiTime();
	sprintf(info_str,"TCAP init process completed. Init time is:%s\r",cur_time);
	tcap_send_ascout(info_str);
//	init_paralport();	// init parallel port
//	write_paralport(TCAP_LED_CODE,1);
}

extern void clrcount_did_max(void);
void tcap_monitor(void)
{
	u32		ii,jj;
	u8		*time_ptr;
	u16		used_id;
	char	info_str[1024],temp_info[1024];

	debug_ptr->send_control = 0;
	if (strlen((char *)debug_ptr->ascin_buf) > 0)	// has command
	{
		if (strcmp((char *)debug_ptr->ascin_buf+1,"clear") == 0)
		{
			memset(debug_ptr->watch_dog,0,256);
			memset(tcap_dlg_stats, 0, sizeof(u32) * MAX_DIALOGUEID);
			clrcount_did_max();
		}
		else if (strncmp((char *)debug_ptr->ascin_buf+1,"go to ",6) == 0)	// change section page
		{
			ii = atol((char *)debug_ptr->ascin_buf+7);
			sec_page = ii;
		}
		else if (strncmp((char *)debug_ptr->ascin_buf+1,"log port ",9) == 0)	// monitor the did
		{
			ii = atol((char *)debug_ptr->ascin_buf+10);
			if (ii >= (tcap_ptr->grantdid))
				tcap_send_ascout("The appointed dialogue id is not expected\r\n");
			else
				debug_ptr->monitor_did = ii;
		}
		else if (strcmp((char *)debug_ptr->ascin_buf+1,"list para") == 0)// display parameter
		{
			tcap_send_ascout("The TCAP system parameters are:\r\n");
			sprintf(info_str,"Invoke timer:%d s\r\nReject timer:%d s\r\n",debug_ptr->default_invtime,debug_ptr->default_rejtime);
			tcap_send_ascout(info_str);
		}
		else if (strcmp((char *)debug_ptr->ascin_buf+1,"log none") == 0)// close all switch
		{
			debug_ptr->error_switch = 0;
			debug_ptr->sccp_switch = 0;
			debug_ptr->tcu_switch = 0;
		}
		else if (strcmp((char *)debug_ptr->ascin_buf+1,"log error on") == 0)
		{
			debug_ptr->error_switch = 1;
		}
		else if (strcmp((char *)debug_ptr->ascin_buf+1,"log error off") == 0)
		{
			debug_ptr->error_switch = 0;
		}
		else if (strcmp((char *)debug_ptr->ascin_buf+1,"log all") == 0)
		{
			debug_ptr->error_switch = 1;
			debug_ptr->sccp_switch = 1;
			debug_ptr->tcu_switch = 1;
		}
		else if (strcmp((char *)debug_ptr->ascin_buf+1,"log sccp") == 0)
		{
			debug_ptr->sccp_switch = 1;
			tcap_send_ascout("tcap monitoring sccp message switch open\n\r");
		}
		else if (strcmp((char *)debug_ptr->ascin_buf+1,"log tcu") == 0)
		{
			debug_ptr->tcu_switch = 1;
		}
		else if (strncmp((char *)debug_ptr->ascin_buf+1,"help",6) == 0)	// display help message
		{
			sprintf(temp_info,"%d-%02d-%02d %02d:%02d:%02d",debug_ptr->start_time[0]+2000,debug_ptr->start_time[1],debug_ptr->start_time[2],debug_ptr->start_time[3],debug_ptr->start_time[4],debug_ptr->start_time[5]);
			sprintf(info_str,"TCAP module R%dV%d_%02d, start time: %s\r\n\n",tcap_ver[0],tcap_ver[1],tcap_ver[2],temp_info);
			tcap_send_ascout(info_str);
			tcap_send_ascout("Command list:\r\n");
			tcap_send_ascout("log all   --------- Turn on all log items\r\n");
			tcap_send_ascout("log none  --------- Turn off all log items\r\n");
			tcap_send_ascout("log error on/off --------- Turn on/off error log item\r\n");
			tcap_send_ascout("log tcu   --------- Turn on TCAP<->TCUser log item\r\n");
			tcap_send_ascout("log sccp  --------- Turn on TCAP<->SCCP log item\r\n");
			tcap_send_ascout("log port [did] ---- Monitor the specified dialogue id\r\n");
			tcap_send_ascout("list para --------- Display TCAP system parameters\r\n");
		}
		debug_ptr->ascin_buf[0] = '\0';
	}
/*	for (page_n = 1;page_n < MAX_PAGE;page_n ++)
		tcap_disp_page(page_n);*/
	if (++tcap_1s_flag > 24)
		tcap_1s_flag = 0;
	if (tcap_1s_flag == 0)
	{
		GetCurrentTime(debug_ptr->current_time);
		time_ptr = debug_ptr->current_time;
		jj = (time_ptr[3]*60+time_ptr[4])/TCAP_CSTA_INTERVAL;
		for (ii = 0;ii < TCAP_UTILIZE_LEN;ii ++)
		{
			if ((time_ptr[4] % TCAP_CSTA_INTERVAL)==0 && time_ptr[5]==0)	// clear CDR
			{
				debug_ptr->tc_utilize[jj][ii] = 0;
				debug_ptr->csta_time[jj] = time(NULL);
				debug_ptr->current_csta = jj;
			}
			debug_ptr->tc_utilize[jj][ii] += debug_ptr->tc_utilize[TCAP_UTILIZE_COUNT-1][ii];
			debug_ptr->tc_utilize[TCAP_UTILIZE_COUNT-1][ii] = 0;
		}
		used_id = chkcount_did_occupied();
		debug_ptr->tc_utilize[jj][21] += used_id;
		if (debug_ptr->tc_utilize[jj][23] < used_id)
			debug_ptr->tc_utilize[jj][23] = used_id;
		if (++tcap_10s_flag > 9)
			tcap_10s_flag = 0;
		if (tcap_10s_flag == 0)		// 10s timer, set tcap status
		{
			set_led(TCAP_LED_CODE,LED_GREEN);
			memcpy(debug_ptr->hb_status,tcap_ver,TCAP_VERSION_LEN);
			debug_ptr->hb_status[TCAP_VERSION_LEN] = tcap_status;
			debug_ptr->hb_status[TCAP_VERSION_LEN+1] = used_id >> 8;
			debug_ptr->hb_status[TCAP_VERSION_LEN+2] = used_id;
			used_id = chkcount_did_max();
			debug_ptr->hb_status[TCAP_VERSION_LEN+3] = used_id >> 8;
			debug_ptr->hb_status[TCAP_VERSION_LEN+4] = used_id;
			set_status(TCAP_MODULE_ID,TCAP_HB_LEN,debug_ptr->hb_status);
			//clrcount_did_max();
		}
	}
}

void tcap_send_alarm(u8 alarm_code,u8 alarm_level)
{
	if (alarm_level == 1)	// mini alarm
		set_led(TCAP_LED_CODE,LED_YELLOW);
	else if (alarm_level == 2)	// critical alarm
		set_led(TCAP_LED_CODE,LED_RED);
	set_alarm(TCAP_MODULE_ID,alarm_code);
}
/*@end@*/
