/*	interface c file					*/
/*	written by Liu zhiguo 2002-08-16	*/
/*	version 2.0							*/
/*	-----------------------------		*/
#include "../../sccp/src/include/sccp.h"
#include "./include/tcap_public.h"
#include "./include/tcap_struct.h"
#include "./include/idmanage.h"
#include "./include/tcap_m.h"

/*@ignore@*/
static	u8		t10ms_flag;
static	u32		tcap_proc;

u32				tcap_dlg_h[MAX_DIALOGUEID];
u32				tcap_dlg_t[MAX_DIALOGUEID];
u32				tcap_dlg_stats[MAX_DIALOGUEID];

typedef struct id_struct
{
        u32     current_did;
        u32     count_did;
        u32     count_did_occupied;
        u32     count_did_max;
        u32     count_did_tmp;
        u8      dialogue_id[MAX_DIALOGUEID];
    	u8 		current_iid[MAX_DIALOGUEID];
        u8  	invoke_id[MAX_DIALOGUEID][MAX_INVOKEID];
}id_struct;

extern struct	id_struct	*ID_ptr;

void tcap_disp_dlg(struct CSLdlg_struct *dha_ptr,u8 disp_flag)
{
	char	temp_buf[1024],temp_data[1024];
	char	info_str[1024];
	char	*cur_time;
	struct	TCUni_struct		*uni_ptr;
	struct	TCBegin_struct		*begin_ptr;
	struct	TCContinue_struct	*con_ptr;
	struct	TCEnd_struct		*end_ptr;
	struct	TCUAbort_struct		*uabrt_ptr;
	struct	TCPAbort_struct		*pabrt_ptr;
	u8 		proto_type;
	
	if (tcap_ptr->tcap_debug.send_control == 1)
		return;
	if (tcap_ptr->tcap_debug.tcu_switch == 0 && dha_ptr->dialogue_id != tcap_ptr->tcap_debug.monitor_did)
		return;
	if (disp_flag == 1)		// send data to tc-user
		strcpy(info_str,"Dialogue tcap->tc user, time: ");
	else
		strcpy(info_str,"Dialogue tc user->tcap, time: ");
	cur_time = GetAsciiTime();
	strcat(info_str,cur_time);
	strcat(info_str,"\rType: ");
	if (dha_ptr->message_flag == REQUEST)
		sprintf(temp_buf,"\tFlag: Request\tDialogue id: %ld\r\n",dha_ptr->dialogue_id);
	else
		sprintf(temp_buf,"\tFlag: Indicate\tDialogue id: %ld\r\n",dha_ptr->dialogue_id);
	if ((dha_ptr->message_type & 0xE0) == ANSI_TAG_CLASS_CONS)
		proto_type = ANSI_TCAP;
	else
		proto_type = ITU_TCAP;
	switch (dha_ptr->message_type)
	{
		case Unidirectional:
		case Unidirectional_Ansi:
			if (dha_ptr->message_type == Unidirectional)
				strcat(info_str,"Unidirectional");
			else
				strcat(info_str,"Unidirectional_Ansi");
			strcat(info_str,temp_buf);
			uni_ptr = (TCUni_struct *) &dha_ptr->dlg_prim.tc_uni;
			if (uni_ptr->dialogue_flag == 1)
			{
				if (uni_ptr->dlg_data.acn_len > 0)
				{
					HexToDisplay(temp_buf,uni_ptr->dlg_data.acn,uni_ptr->dlg_data.acn_len);
					sprintf(temp_data,"ACN is: %s\r\n",temp_buf);
					strcat(info_str,temp_data);
				}
				if (uni_ptr->dlg_data.user_info_len > 0)
				{
					HexToDisplay(temp_buf,uni_ptr->dlg_data.user_info,uni_ptr->dlg_data.user_info_len);
					sprintf(temp_data,"User info is: %s\r\n",temp_buf);
					strcat(info_str,temp_data);
				}
				if (proto_type)
				{
					if (uni_ptr->dlg_data.security_context_len > 0)
					{
						HexToDisplay(temp_buf,uni_ptr->dlg_data.security_context,uni_ptr->dlg_data.security_context_len);
						sprintf(temp_data,"Security context is: %s\r\n",temp_buf);
						strcat(info_str,temp_data);
					}
					if (uni_ptr->dlg_data.confidential_info_len > 0)
					{
						HexToDisplay(temp_buf,uni_ptr->dlg_data.confidential_info,uni_ptr->dlg_data.confidential_info_len);
						sprintf(temp_data,"Confidential info is: %s\r\n",temp_buf);
						strcat(info_str,temp_data);
					}
				}
			}
			if (uni_ptr->component_present != 0)
				strcat(info_str,"Has component\r\n");
			strcat(info_str,"\r\n");
			break;
		case Begin:
		case Query_WithPerm_Ansi:
		case Query_WithoutPerm_Ansi:
			if (dha_ptr->message_type == Begin)
				strcat(info_str,"Begin");
			else if (dha_ptr->message_type == Query_WithPerm_Ansi)
				strcat(info_str,"Query_WithPerm_Ansi");
			else
				strcat(info_str,"Query_WithoutPerm_Ansi");
			strcat(info_str,temp_buf);
			begin_ptr = (TCBegin_struct *) &dha_ptr->dlg_prim.tc_begin;
			if (begin_ptr->dialogue_flag == 1)
			{
				if (begin_ptr->dlg_data.acn_len > 0)
				{
					HexToDisplay(temp_buf,begin_ptr->dlg_data.acn,begin_ptr->dlg_data.acn_len);
					sprintf(temp_data,"ACN is: %s\r\n",temp_buf);
					strcat(info_str,temp_data);
				}
				if (begin_ptr->dlg_data.user_info_len != 0)
				{
					HexToDisplay(temp_buf,begin_ptr->dlg_data.user_info,begin_ptr->dlg_data.user_info_len);
					sprintf(temp_data,"User info is: %s\r\n",temp_buf);
					strcat(info_str,temp_data);
				}
				if (proto_type)
				{
					if (begin_ptr->dlg_data.security_context_len > 0)
					{
						HexToDisplay(temp_buf,begin_ptr->dlg_data.security_context,begin_ptr->dlg_data.security_context_len);
						sprintf(temp_data,"Security context is: %s\r\n",temp_buf);
						strcat(info_str,temp_data);
					}
					if (begin_ptr->dlg_data.confidential_info_len > 0)
					{
						HexToDisplay(temp_buf,begin_ptr->dlg_data.confidential_info,begin_ptr->dlg_data.confidential_info_len);
						sprintf(temp_data,"Confidential info is: %s\r\n",temp_buf);
						strcat(info_str,temp_data);
					}
				}
			}
			if (begin_ptr->component_present != 0)
				strcat(info_str,"Has component\r\n");
			strcat(info_str,"\r\n");
			break;
		case Continue:
		case Conversation_WithPerm_Ansi:
		case Conversation_WithoutPerm_Ansi:
			if (dha_ptr->message_type == Continue)
				strcat(info_str,"Continue");
			else if (dha_ptr->message_type == Conversation_WithPerm_Ansi)
				strcat(info_str,"Conversation_WithPerm_Ansi");
			else
				strcat(info_str,"Conversation_WithoutPerm_Ansi");
			strcat(info_str,temp_buf);
			con_ptr = (TCContinue_struct *) &dha_ptr->dlg_prim.tc_continue;
			if (con_ptr->dialogue_flag == 1)
			{
				if (con_ptr->dlg_data.acn_len > 0)
				{
					HexToDisplay(temp_buf,con_ptr->dlg_data.acn,con_ptr->dlg_data.acn_len);
					sprintf(temp_data,"ACN is: %s\r\n",temp_buf);
					strcat(info_str,temp_data);
				}
				if (con_ptr->dlg_data.user_info_len != 0)
				{
					HexToDisplay(temp_buf,con_ptr->dlg_data.user_info,con_ptr->dlg_data.user_info_len);
					sprintf(temp_data,"User info is: %s\r\n",temp_buf);
					strcat(info_str,temp_data);
				}
				if (proto_type)
				{
					if (con_ptr->dlg_data.security_context_len > 0)
					{
						HexToDisplay(temp_buf,con_ptr->dlg_data.security_context,con_ptr->dlg_data.security_context_len);
						sprintf(temp_data,"Security context is: %s\r\n",temp_buf);
						strcat(info_str,temp_data);
					}
					if (con_ptr->dlg_data.confidential_info_len > 0)
					{
						HexToDisplay(temp_buf,con_ptr->dlg_data.confidential_info,con_ptr->dlg_data.confidential_info_len);
						sprintf(temp_data,"Confidential info is: %s\r\n",temp_buf);
						strcat(info_str,temp_data);
					}
				}
			}
			if (con_ptr->component_present != 0)
				strcat(info_str,"Has component\r\n");
			strcat(info_str,"\r\n");
			break;
		case End:
		case Response_Ansi:
			if (dha_ptr->message_type == End)
				strcat(info_str,"End");
			else
				strcat(info_str,"Response");
			strcat(info_str,temp_buf);
			end_ptr = (TCEnd_struct *) &dha_ptr->dlg_prim.tc_end;
			if (end_ptr->dialogue_flag == 1)
			{
				if (end_ptr->dlg_data.acn_len > 0)
				{
					HexToDisplay(temp_buf,end_ptr->dlg_data.acn,end_ptr->dlg_data.acn_len);
					sprintf(temp_data,"ACN is: %s\r\n",temp_buf);
					strcat(info_str,temp_data);
				}
				if (proto_type)
				{
					if (end_ptr->dlg_data.user_info_len != 0)
					{
						HexToDisplay(temp_buf,end_ptr->dlg_data.user_info,end_ptr->dlg_data.user_info_len);
						sprintf(temp_data,"User info is: %s\r\n",temp_buf);
						strcat(info_str,temp_data);
					}
					if (end_ptr->dlg_data.security_context_len > 0)
					{
						HexToDisplay(temp_buf,end_ptr->dlg_data.security_context,end_ptr->dlg_data.security_context_len);
						sprintf(temp_data,"Security context is: %s\r\n",temp_buf);
						strcat(info_str,temp_data);
					}
					if (end_ptr->dlg_data.confidential_info_len > 0)
					{
						HexToDisplay(temp_buf,end_ptr->dlg_data.confidential_info,end_ptr->dlg_data.confidential_info_len);
						sprintf(temp_data,"Confidential info is: %s\r\n",temp_buf);
						strcat(info_str,temp_data);
					}
				}
			}
			if (end_ptr->component_present != 0)
				strcat(info_str,"Has component\r\n");
			strcat(info_str,"\r\n");
			break;
		case U_Abort:
		case U_Abort_Ansi:
			if (dha_ptr->message_type == U_Abort)
				strcat(info_str,"U_Abort");
			else
				strcat(info_str,"U_Abort_Ansi");
			strcat(info_str,temp_buf);
			uabrt_ptr = (TCUAbort_struct *) &dha_ptr->dlg_prim.tc_uabort;
			if (uabrt_ptr->dialogue_flag == 1)
			{
				if (uabrt_ptr->dlg_data.acn_len != 0)
				{
					HexToDisplay(temp_buf,uabrt_ptr->dlg_data.acn,uabrt_ptr->dlg_data.acn_len);
					sprintf(temp_data,"ACN is: %s\r\n",temp_buf);
					strcat(info_str,temp_data);
				}
				if (proto_type)
				{
					if (uabrt_ptr->dlg_data.user_info_len != 0)
					{
						HexToDisplay(temp_buf,uabrt_ptr->dlg_data.user_info,uabrt_ptr->dlg_data.user_info_len);
						sprintf(temp_data,"User info is: %s\r\n",temp_buf);
						strcat(info_str,temp_data);
					}
					if (uabrt_ptr->dlg_data.security_context_len > 0)
					{
						HexToDisplay(temp_buf,uabrt_ptr->dlg_data.security_context,uabrt_ptr->dlg_data.security_context_len);
						sprintf(temp_data,"Security context is: %s\r\n",temp_buf);
						strcat(info_str,temp_data);
					}
					if (uabrt_ptr->dlg_data.confidential_info_len > 0)
					{
						HexToDisplay(temp_buf,uabrt_ptr->dlg_data.confidential_info,uabrt_ptr->dlg_data.confidential_info_len);
						sprintf(temp_data,"Confidential info is: %s\r\n",temp_buf);
						strcat(info_str,temp_data);
					}
				}
			}
			if (!proto_type)
			{
				sprintf(temp_buf,"User abort reason: %d\r\n",uabrt_ptr->uabort_reason);
				strcat(info_str,temp_buf);
			}
			else
			{
				if (uabrt_ptr->uabort_info_len != 0)
				{
					HexToDisplay(temp_buf,uabrt_ptr->uabort_info,uabrt_ptr->uabort_info_len);
					sprintf(temp_data,"User abort info is: %s\r\n",temp_buf);
					strcat(info_str,temp_data);
				}
			}
			strcat(info_str, "\r\n");
			break;
		case P_Abort:
		case P_Abort_Ansi:
			if (dha_ptr->message_type == P_Abort)
				strcat(info_str,"P_Abort");
			else
				strcat(info_str,"P_Abort_Ansi");
			strcat(info_str,temp_buf);
			pabrt_ptr = (TCPAbort_struct *) &dha_ptr->dlg_prim.tc_pabort;
			sprintf(temp_buf,"Provider abort reason: %d\r\n",pabrt_ptr->pabort_reason);
			strcat(info_str,temp_buf);
			strcat(info_str, "\r\n");
			break;
		default:
			break;
	}
	tcap_send_ascout(info_str);
}

void tcap_disp_cmp(struct CSLcmp_struct *cha_ptr,u8 disp_flag)
{
	int		ii=0;
	char	temp_buf[1024];
	char	info_str[1024];
	char	*cur_time;
	u8		proto_type;
	struct	TCInvoke_struct		*invoke_ptr;
	struct	TCResult_struct		*result_ptr;
	struct	TCUError_struct		*uerror_ptr;
	struct	TCReject_struct		*reject_ptr;

	if (tcap_ptr->tcap_debug.send_control == 1)
		return;
	if (tcap_ptr->tcap_debug.tcu_switch == 0 && cha_ptr->dialogue_id != tcap_ptr->tcap_debug.monitor_did)
		return;
	if (disp_flag == 1)		// send data to tc-user
		strcpy(info_str,"Component tcap->tc user, time: ");
	else
		strcpy(info_str,"Component tc user->tcap, time: ");
	cur_time = GetAsciiTime();
	strcat(info_str,cur_time);
	strcat(info_str,"\rType: ");
	if (cha_ptr->message_flag == REQUEST)
		sprintf(temp_buf,"\tFlag: Request\tDialogue id: %ld, Invoke id: %d\r\n",cha_ptr->dialogue_id,cha_ptr->invoke_id);
	else
		sprintf(temp_buf,"\tFlag: Indicate\tDialogue id: %ld, Invoke id: %d\r\n",cha_ptr->dialogue_id,cha_ptr->invoke_id);
	if ((cha_ptr->message_type & 0xE0) == ANSI_TAG_CLASS_CONS)
		proto_type = ANSI_TCAP;
	else
		proto_type = ITU_TCAP;
	switch (cha_ptr->message_type)
	{
		case Invoke:
		case Invoke_L_Ansi:
		case Invoke_NL_Ansi:
			if (cha_ptr->message_type == Invoke)
				strcat(info_str,"Invoke");
			else if (cha_ptr->message_type == Invoke_L_Ansi)
				strcat(info_str,"Invoke_L_Ansi");
			else
				strcat(info_str,"Invoke_NL_Ansi");
			strcat(info_str,temp_buf);
			invoke_ptr = (TCInvoke_struct *) &cha_ptr->cmp_prim.tc_invoke;
			ii = invoke_ptr->parameter_len;
			if (cha_ptr->message_type == Invoke)
				sprintf(temp_buf,"Operation code: %d\tParameter len: %d\r\n",invoke_ptr->operation_code,ii);
			else
				sprintf(temp_buf,"Operation family: %d\tOperation code: %d\tParameter len: %d\r\n",invoke_ptr->operation_family,invoke_ptr->operation_code,ii);
			strcat(info_str,temp_buf);
			if (ii != 0)
			{
				strcat(info_str,"Parameter: ");
				HexToDisplay(temp_buf,invoke_ptr->parameter,ii);
				strcat(info_str,temp_buf);
				strcat(info_str,"\r\n");
			}
			strcat(info_str, "\r\n");
			break;
		case Result_L:
		case Result_NL:
		case Result_L_Ansi:
		case Result_NL_Ansi:
			if (cha_ptr->message_type == Result_L)
				strcat(info_str,"Result_L");
			else if (cha_ptr->message_type == Result_NL)
				strcat(info_str,"Result_NL");
			else if (cha_ptr->message_type == Result_L_Ansi)
				strcat(info_str,"Result_L_Ansi");
			else
				strcat(info_str,"Result_NL_Ansi");
			strcat(info_str,temp_buf);
			result_ptr = (TCResult_struct *) &cha_ptr->cmp_prim.tc_result;
			ii = result_ptr->parameter_len;
			if (ii != 0)
			{
				if ((cha_ptr->message_type == Result_L_Ansi) ||
					(cha_ptr->message_type == Result_NL_Ansi))
					sprintf(temp_buf,"Operation family: %d\tOperation code: %d\tParameter len: %d\r\n",result_ptr->operation_family,result_ptr->operation_code,ii);
				else
					sprintf(temp_buf,"Operation code: %d\tParameter len: %d\r\n",result_ptr->operation_code,ii);
				strcat(info_str,temp_buf);
				strcat(info_str,"Parameter: ");
				HexToDisplay(temp_buf,result_ptr->parameter,ii);
				strcat(info_str,temp_buf);
				strcat(info_str,"\r\n");
			}
			strcat(info_str, "\r\n");
			break;
		case U_Error:
		case U_Error_Ansi:
			if (cha_ptr->message_type == U_Error)
				strcat(info_str,"U_Error");
			else
				strcat(info_str,"U_Error_Ansi");
			strcat(info_str,temp_buf);
			uerror_ptr = (TCUError_struct *) &cha_ptr->cmp_prim.tc_uerror;
			ii = uerror_ptr->parameter_len;
			sprintf(temp_buf,"Error code: %d\tParameter len: %d\r\n",uerror_ptr->error_code,ii);
			strcat(info_str,temp_buf);
			if (ii != 0)
			{
				strcat(info_str,"Parameter: ");
				HexToDisplay(temp_buf,uerror_ptr->parameter,ii);
				strcat(info_str,temp_buf);
				strcat(info_str,"\r\n");
			}
			strcat(info_str, "\r\n");
			break;
		case U_Reject:
		case L_Reject:
		case R_Reject:
		case U_Reject_Ansi:
		case L_Reject_Ansi:
		case R_Reject_Ansi:
			switch (cha_ptr->message_type)
			{
				case U_Reject:
					strcat(info_str,"U_Reject");
					break;
				case L_Reject:
					strcat(info_str,"L_Reject");
					break;
				case R_Reject:
					strcat(info_str,"R_Reject");
					break;
				case U_Reject_Ansi:
					strcat(info_str,"U_Reject_Ansi");
					break;
				case L_Reject_Ansi:
					strcat(info_str,"L_Reject_Ansi");
					break;
				case R_Reject_Ansi:
					strcat(info_str,"R_Reject_Ansi");
					break;
			}
			strcat(info_str,temp_buf);
			reject_ptr = (TCReject_struct *) &cha_ptr->cmp_prim.tc_reject;
			sprintf(temp_buf,"Problem type: %d\tProblem code: %d",reject_ptr->problem_type,reject_ptr->problem_code);
			strcat(info_str,temp_buf);
			if (proto_type)
			{
				ii = reject_ptr->parameter_len;
				if (ii != 0)
				{
					sprintf(temp_buf,"\tParameter len: %d\r\n",ii);
					strcat(info_str,temp_buf);
					strcat(info_str,"Parameter: ");
					HexToDisplay(temp_buf,reject_ptr->parameter,ii);
					strcat(info_str,temp_buf);
				}
			}
			strcat(info_str,"\r\n\r\n");
			break;
		default:
			if (cha_ptr->message_type == L_Cancel)
				strcat(info_str,"Local cancel");
			else if (cha_ptr->message_type == U_Cancel)
				strcat(info_str,"User cancel");
			strcat(info_str,temp_buf);
			strcat(info_str,"\r\n");
			break;
	}
	tcap_send_ascout(info_str);
}

u8 RecvTcapDlg(struct CSLdlg_struct *dha_ptr,u32 dlg_flag)	// receive the dialogue portion
{
	struct	tcapint_struct		*int_ptr;
	u8		ii;
	
	if (dlg_flag >= (tcap_ptr->grantdid))
		return 0;
	int_ptr = (tcapint_struct *) &tcap_ptr->tcapint_data[dlg_flag];
	ii = int_ptr->dlgrecv_tail;
	if (ii == int_ptr->dlgrecv_head)
		return 0;
	memcpy(dha_ptr,&int_ptr->dlg_recv[ii],sizeof(CSLdlg_struct));
	int_ptr->dlgrecv_tail = (ii + 1) % MAX_TSL_BUF;
	tcap_disp_dlg(dha_ptr,1);
	return 1;
}

u8 RecvTcapCmp(struct CSLcmp_struct *cha_ptr,u32 dlg_flag)	// receive the component portion
{
	struct	tcapint_struct		*int_ptr;
	u8		ii;
	struct	tcapdebug_struct	*debug_ptr = (tcapdebug_struct *) &tcap_ptr->tcap_debug;
	
	if (dlg_flag >= (tcap_ptr->grantdid))
	{
		debug_ptr->watch_dog[247]++;
		return 0;
	}
	int_ptr = (tcapint_struct *) &tcap_ptr->tcapint_data[dlg_flag];
	ii = int_ptr->cmprecv_tail;
	if (ii == int_ptr->cmprecv_head)
		return 0;
	memcpy(cha_ptr,&int_ptr->cmp_recv[ii],sizeof(CSLcmp_struct));
	int_ptr->cmprecv_tail = (ii + 1) % MAX_CSL_BUF;
	tcap_disp_cmp(cha_ptr,1);
	debug_ptr->watch_dog[246]++;
	return 1;
}

u8 SendTcapDlg(struct CSLdlg_struct *dha_ptr)	// send the dialogue portion
{
	struct	tcapint_struct		*int_ptr;
	u32		dlg_flag;
	u8		ii;
	char	info_str[1024];
	struct	tcapdebug_struct	*debug_ptr = (tcapdebug_struct *) &tcap_ptr->tcap_debug;
	
	dlg_flag = dha_ptr->dialogue_id;
	if (dlg_flag >= (tcap_ptr->grantdid))
	{
		debug_ptr->watch_dog[194]++;
		return 0;
	}
	
	int_ptr = (tcapint_struct *) &tcap_ptr->tcapint_data[dlg_flag];
	ii = int_ptr->dlgsend_head;
	
	if (tcap_dlg_h[dlg_flag] != int_ptr->dlgsend_head)
	{
		debug_ptr->watch_dog[192] ++;
		//printf("h: %d-%d\n", tcap_dlg_h[dlg_flag], int_ptr->dlgsend_head);
	}
	
	if (((ii + 1) % MAX_TSL_BUF) == int_ptr->dlgsend_tail)	// buffer is full
	{
		tcap_send_error("TCAP error. TCU to TCAP buffer is full");
		debug_ptr->watch_dog[193]++;
		return 0;
	}
	memcpy(&int_ptr->dlg_send[ii],dha_ptr,sizeof(CSLdlg_struct));
	int_ptr->dlgsend_head = (ii + 1) % MAX_TSL_BUF;
	
	tcap_dlg_h[dlg_flag] = int_ptr->dlgsend_head;
	
	switch (dha_ptr->message_type)
	{
		case U_Abort:
		case U_Abort_Ansi:
			if (tcap_ptr->tcap_debug.error_switch)
			{
				if (dha_ptr->message_type == U_Abort)
					sprintf(info_str,"CSL warning. Receive U_Abort from TC-user. Did: %ld",dlg_flag);
				else
					sprintf(info_str,"CSL warning. Receive U_Abort_Ansi from TC-user. Did: %ld",dlg_flag);
				tcap_send_error(info_str);
			}
			break;
		case P_Abort:
		case P_Abort_Ansi:
			if (tcap_ptr->tcap_debug.error_switch)
			{
				if (dha_ptr->message_type == P_Abort)
					sprintf(info_str,"CSL warning. Receive P_Abort from TC-user. Did: %ld",dlg_flag);
				else
					sprintf(info_str,"CSL warning. Receive P_Abort_Ansi from TC-user. Did: %ld",dlg_flag);
				tcap_send_error(info_str);
			}
			break;
		default:
			break;
	}
	tcap_disp_dlg(dha_ptr,2);
	if (dha_ptr->message_type == Begin)
	{
		if (ID_ptr->dialogue_id[dlg_flag] == 0)
			debug_ptr->watch_dog[183]++;
		if (++tcap_dlg_stats[dlg_flag] > 1)
			debug_ptr->watch_dog[182]++;
		debug_ptr->watch_dog[196]++;
	}
	debug_ptr->watch_dog[195]++;
	
	return 1;
}

u8 SendTcapCmp(struct CSLcmp_struct *cha_ptr)	// send the component portion
{
	struct	tcapint_struct		*int_ptr;
	u32		dlg_flag;
	u8		inv_flag;
	u8		ii,jj,kk;
	struct	tcapdebug_struct	*debug_ptr = (tcapdebug_struct *) &tcap_ptr->tcap_debug;

	dlg_flag = cha_ptr->dialogue_id;
	inv_flag = cha_ptr->invoke_id;
	if (dlg_flag >= (tcap_ptr->grantdid))
	{
		debug_ptr->watch_dog[253]++;
		return 0;
	}

//add by daniel on 2006-06-19, to release invoke id propery, if the component is not invoke, then the iid will be released
    if ((cha_ptr->message_type != Invoke ) &&
            (cha_ptr->message_type != Result_NL))
    {
        free_iid(dlg_flag,inv_flag);
		//tcap_send_ascout("sendTcapCmp free_iid\r\n");
	}
//add by daniel on 2006-06-19, to release invoke id propery, if the component is not invoke, then the iid will be released

		
	int_ptr = (tcapint_struct *) &tcap_ptr->tcapint_data[dlg_flag];
	tcap_disp_cmp(cha_ptr,2);
	if (cha_ptr->message_type == U_Cancel)
	{
		ii = int_ptr->cmpsend_tail;
		while (ii != int_ptr->cmpsend_head)	// search any INV component for this DID and TID
		{
			if (int_ptr->cmp_send[ii].invoke_id == inv_flag)	// has data which is not sent out
			{
				jj = ii;
				kk = (ii + 1) % MAX_CSL_BUF;
				while (kk != int_ptr->cmpsend_head)
				{
					memcpy(&int_ptr->cmp_send[jj],&int_ptr->cmp_send[kk],sizeof(CSLcmp_struct));
					jj = (jj + 1) % MAX_CSL_BUF;
					kk = (kk + 1) % MAX_CSL_BUF;
				}
				if (int_ptr->cmpsend_head == 0)
					int_ptr->cmpsend_head = MAX_CSL_BUF - 1;
				else
					int_ptr->cmpsend_head -= 1;
				if (int_ptr->cmpsend_head == ii)
				{
					write_ism(cha_ptr);
					debug_ptr->watch_dog[238]++;
					debug_ptr->watch_dog[255]++;
					return 1;
				}
			}
			ii = (ii + 1) % MAX_CSL_BUF;
			debug_ptr->watch_dog[235]++;
		}
		write_ism(cha_ptr);
		debug_ptr->watch_dog[240]++;
		debug_ptr->watch_dog[255]++;
		return 1;
	}
	ii = int_ptr->cmpsend_head;
	if (((ii + 1) % MAX_CSL_BUF) == int_ptr->cmpsend_tail)	// buffer full
	{
		tcap_send_alarm(3,1);
		tcap_send_error("CSL warning. ISM buffer is full");
		debug_ptr->watch_dog[254]++;
		return 0;
	}
	memcpy(&int_ptr->cmp_send[ii],cha_ptr,sizeof(CSLcmp_struct));
	int_ptr->cmpsend_head = (ii + 1) % MAX_CSL_BUF;
	if ((cha_ptr->message_type == U_Reject) || 
		(cha_ptr->message_type == U_Reject_Ansi) || 
		(cha_ptr->message_type == Invoke) ||
		(cha_ptr->message_type == Invoke_L_Ansi) ||
		(cha_ptr->message_type == Invoke_NL_Ansi))
	{
		debug_ptr->watch_dog[239]++;
		write_ism(cha_ptr);
	}
	else
	{
		debug_ptr->watch_dog[237]++;
		if (cha_ptr->message_type != Result_L)
		{
			debug_ptr->watch_dog[236]++;
//			printf("tcap: %d\n", cha_ptr->message_type);
		}
	}
	debug_ptr->watch_dog[255]++;
	return 1;
}

void tcap_fsm(void)		// TCAP state machine
{
	register u32	proc;
	struct	tcapdebug_struct *debug_ptr = (tcapdebug_struct *) &tcap_ptr->tcap_debug;
	
//	write_paralport(TCAP_LED_CODE,1);
	t10ms_flag ++;
	if (t10ms_flag >= 2)	// 20ms circle
	{
		t10ms_flag = 0;
		tcap_monitor();
	}
	for (proc = 0;proc < 64;proc++)
		tco_program();
	for (proc = 0;proc < (tcap_ptr->grantdid)/2;proc ++)
	{
		ism_program(tcap_proc);
		tsm_program(tcap_proc);
		if (tcap_proc != 0)
		{
			if (check_did(tcap_proc) || !xapp_check_did(tcap_proc))
				ID_ptr->count_did_tmp++;
		}
		if (tcap_proc == (tcap_ptr->grantdid - 1))
		{
			if ((ID_ptr->count_did_occupied = ID_ptr->count_did_tmp) > ID_ptr->count_did_max)
				ID_ptr->count_did_max = ID_ptr->count_did_occupied;
			ID_ptr->count_did_tmp = 0;
			memcpy(&debug_ptr->watch_dog[160], (BYTE *) &ID_ptr->count_did, sizeof(u32));
			memcpy(&debug_ptr->watch_dog[164], (BYTE *) &ID_ptr->count_did_occupied, sizeof(u32));
			memcpy(&debug_ptr->watch_dog[168], (BYTE *) &ID_ptr->count_did_max, sizeof(u32));
		}
		tcap_proc = (tcap_proc + 1) % (tcap_ptr->grantdid);
	}
//	write_paralport(TCAP_LED_CODE,0);
}

int itcap_reg_ssn(u8 ssn)
{
	return register_ssn(ssn,0);
}

int tcap_get_grantdid()
{
	return ((tcap_ptr->grantdid>MAX_DIALOGUEID) \
	        ? MAX_DIALOGUEID: tcap_ptr->grantdid);
}

void tcap_init(int didgrant,DWORD localip,DWORD peerip)	// init TCAP system
{
	printf("Tcap init start!\n");
	if( didgrant <= 0 || didgrant > MAX_DIALOGUEID)
	{
		  printf( "unexpect tcap did grant number!\r\n");
		  exit(0);
	}
	init_id(didgrant);
	tcapvm_init(localip,peerip);
	tcap_ptr->grantdid = didgrant;
	init_m();
	t10ms_flag = 0;
	tcap_proc = 0;
	
	memset(tcap_dlg_h, 0, sizeof(u32) * MAX_DIALOGUEID);
	memset(tcap_dlg_t, 0, sizeof(u32) * MAX_DIALOGUEID);
	memset(tcap_dlg_stats, 0, sizeof(u32) * MAX_DIALOGUEID);
	
	printf("Tcap init complete!\n");
}
/*@end@*/
