/*	TCAP c program file					*/
/*	written by Liu Zhiguo 2002-08-06	*/
/*	Version 2.0							*/
/*	--------------------------------	*/
#include "../../sccp/src/include/sccp.h"
#include "./include/tcap_public.h"
#include "./include/idmanage.h"
#include "./include/tcap_struct.h"
#include "./include/tcap_m.h"

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;

/*@ignore@*/
static struct	tcapdebug_struct	*debug_ptr;
void print_msg(u8 *ptr, u16 len);
extern int sclc_receive(SCLC_MSG * pmsg, BYTE usertype);
extern int sclc_send(SCLC_MSG * pmsg);
extern u8 get_transfer_iid(int did, u8 iid);
extern u8 transfer_iid(int did, u8 iid);
extern int xap_get_est_timer();
extern u32				tcap_dlg_h[MAX_DIALOGUEID];
extern u32				tcap_dlg_t[MAX_DIALOGUEID];

/*	protocol version	*/
static u8	Version_1[2] = {0x07,0x80};
static u8	Version_Ansi = 0x01;
void tcap_set_local_ip()
{
	char	hostname[64];
	struct	hostent		*pcn;
	struct	in_addr		*hostip_add;

	if ((gethostname(hostname,-1)) == -1)
	{
		printf("get host name fail\n");
		exit(0);
	}
	pcn = gethostbyname(hostname);
	if (pcn == NULL)
	{
		printf("get host name fail!\n");
		exit(0);
	}
	((struct in_addr *)(*pcn->h_addr_list))->s_addr = GetLocalIP();
	hostip_add = (struct in_addr *) (*pcn->h_addr_list);
	debug_ptr->local_ip = hostip_add->s_addr;
	//debug_ptr->peer_ip = debug_ptr->local_ip + 0x10000; 
	/* like : mss0=172.18.98.1-0x016212ac, mss1=172.18.99.1-0x016312ac */
}

void tcapvm_init(u_long localip, u_long peerip)		// init share memory
{
	int		shm_id;
 
	/*	init share memory	*/
	if ((shm_id = shmget(TCAP_KEY+wxc2_get_shm_offset(),sizeof(tcapbuf_struct),TCAP_PERM|IPC_CREAT)) == -1)
	{
		printf("can not init tcap share memory");
		exit(0);
	}
	if ((tcap_ptr = (tcapbuf_struct *)shmat(shm_id,(char *)0,0)) == (tcapbuf_struct *) -1)
	{
		printf("can not init tcap share memory");
		exit(0);
	}
	memset(tcap_ptr,0,sizeof(tcapbuf_struct));
	debug_ptr = (tcapdebug_struct *) &tcap_ptr->tcap_debug;
	if(localip>0)
	{
		debug_ptr->local_ip = localip;
		debug_ptr->peer_ip = peerip;
	}
	else
	{
		tcap_set_local_ip();
	}
}

void get_dlgpdu(struct dlgPDU_struct *pdu_ptr,struct dlgport_struct *port_ptr)
{
	switch (pdu_ptr->dialogue_type)
	{
		case PDU_AARQ:
			port_ptr->acn_len = pdu_ptr->pdu_union.aarq.acn_len;
			memcpy(port_ptr->acn,pdu_ptr->pdu_union.aarq.acn,port_ptr->acn_len);
			port_ptr->user_info_len = pdu_ptr->pdu_union.aarq.user_info_len;
			memcpy(port_ptr->user_info,pdu_ptr->pdu_union.aarq.user_info,port_ptr->user_info_len);
			break;
		case PDU_AARE:
			port_ptr->acn_len = pdu_ptr->pdu_union.aare.acn_len;
			memcpy(port_ptr->acn,pdu_ptr->pdu_union.aare.acn,port_ptr->acn_len);
			port_ptr->user_info_len = pdu_ptr->pdu_union.aare.user_info_len;
			memcpy(port_ptr->user_info,pdu_ptr->pdu_union.aare.user_info,port_ptr->user_info_len);
			break;
		case PDU_ABRT:
			port_ptr->acn_len = 0;
			port_ptr->user_info_len = pdu_ptr->pdu_union.abrt.user_info_len;
			memcpy(port_ptr->user_info,pdu_ptr->pdu_union.abrt.user_info,port_ptr->user_info_len);
			break;
		case PDU_ASUDT:
			port_ptr->acn_type = pdu_ptr->pdu_union.asudt.acn_type;
			port_ptr->acn_len = pdu_ptr->pdu_union.asudt.acn_len;
			memcpy(port_ptr->acn,pdu_ptr->pdu_union.asudt.acn,port_ptr->acn_len);
			port_ptr->user_info_len = pdu_ptr->pdu_union.asudt.user_info_len;
			memcpy(port_ptr->user_info,pdu_ptr->pdu_union.asudt.user_info,port_ptr->user_info_len);
			port_ptr->security_context_type = pdu_ptr->pdu_union.asudt.security_context_type;
			port_ptr->security_context_len = pdu_ptr->pdu_union.asudt.security_context_len;
			memcpy(port_ptr->security_context,pdu_ptr->pdu_union.asudt.security_context,port_ptr->security_context_len);
			port_ptr->confidential_info_len = pdu_ptr->pdu_union.asudt.confidential_info_len;
			memcpy(port_ptr->confidential_info,pdu_ptr->pdu_union.asudt.confidential_info,port_ptr->confidential_info_len);
			break;
		default:
			tcap_send_error("CSL error. Dialogue PDU type error");
			break;
	}
}

void set_dlgpdu(struct dlgPDU_struct *pdu_ptr,struct dlgport_struct *port_ptr)
{
	if (port_ptr->user_info_len > TCAP_USERINFO_LEN)
		port_ptr->user_info_len = TCAP_USERINFO_LEN;
	if (port_ptr->acn_len > TCAP_ACN_LEN)
		port_ptr->acn_len = TCAP_ACN_LEN;
	if (port_ptr->security_context_len > TCAP_SECURITY_CONTEXT_LEN)
		port_ptr->security_context_len = TCAP_SECURITY_CONTEXT_LEN;
	if (port_ptr->confidential_info_len > TCAP_CONFIDENTIAL_INFO_LEN)
		port_ptr->confidential_info_len = TCAP_CONFIDENTIAL_INFO_LEN;
	
	switch (pdu_ptr->dialogue_type)
	{
		case PDU_AARQ:
			pdu_ptr->pdu_union.aarq.acn_len = port_ptr->acn_len;
			memcpy(pdu_ptr->pdu_union.aarq.acn,port_ptr->acn,port_ptr->acn_len);
			pdu_ptr->pdu_union.aarq.user_info_len = port_ptr->user_info_len;
			memcpy(pdu_ptr->pdu_union.aarq.user_info,port_ptr->user_info,port_ptr->user_info_len);
			break;
		case PDU_AARE:
			pdu_ptr->pdu_union.aare.acn_len = port_ptr->acn_len;
			memcpy(pdu_ptr->pdu_union.aare.acn,port_ptr->acn,port_ptr->acn_len);
			pdu_ptr->pdu_union.aare.user_info_len = port_ptr->user_info_len;
			memcpy(pdu_ptr->pdu_union.aare.user_info,port_ptr->user_info,port_ptr->user_info_len);
			break;
		case PDU_ABRT:
			pdu_ptr->pdu_union.abrt.user_info_len = port_ptr->user_info_len;
			memcpy(pdu_ptr->pdu_union.abrt.user_info,port_ptr->user_info,port_ptr->user_info_len);
			break;
		case PDU_ASUDT:
			pdu_ptr->pdu_union.asudt.acn_type = port_ptr->acn_type;
			pdu_ptr->pdu_union.asudt.acn_len = port_ptr->acn_len;
			memcpy(pdu_ptr->pdu_union.asudt.acn,port_ptr->acn,port_ptr->acn_len);
			pdu_ptr->pdu_union.asudt.user_info_len = port_ptr->user_info_len;
			memcpy(pdu_ptr->pdu_union.asudt.user_info,port_ptr->user_info,port_ptr->user_info_len);
			pdu_ptr->pdu_union.asudt.security_context_type = port_ptr->security_context_type;
			pdu_ptr->pdu_union.asudt.security_context_len = port_ptr->security_context_len;
			memcpy(pdu_ptr->pdu_union.asudt.security_context,port_ptr->security_context,port_ptr->security_context_len);
			pdu_ptr->pdu_union.asudt.confidential_info_len = port_ptr->confidential_info_len;
			memcpy(pdu_ptr->pdu_union.asudt.confidential_info,port_ptr->confidential_info,port_ptr->confidential_info_len);
			break;
		default:
			memset(pdu_ptr,0,sizeof(dlgPDU_struct));
			break;
	}
}

void ism_terminate(u32 did,u8 iid)
{
	struct	tcapvm_struct		*vm_ptr;

	vm_ptr = (tcapvm_struct *) &tcap_ptr->tcapvm_data[did];
	vm_ptr->ism_data[iid].ism_state = TCAP_INIT;
}

void tcap_terminate(u32 proc)
{
	struct	tcapvm_struct		*vm_ptr;
	struct	tcapint_struct		*int_ptr;

	vm_ptr = (tcapvm_struct *) &tcap_ptr->tcapvm_data[proc];
	int_ptr = (tcapint_struct *) &tcap_ptr->tcapint_data[proc];
	memset(&vm_ptr->ism_data,0,MAX_TEMPINVOKEID*sizeof(ismvm_data));
	int_ptr->cmprecv_head = int_ptr->cmprecv_tail = 0;
	int_ptr->cmpsend_head = int_ptr->cmpsend_tail = 0;
}

void tcap_clear_fsm(u32 proc)
{
	struct	tcapvm_struct		*vm_ptr;
	struct	tcapint_struct		*int_ptr;

	vm_ptr = (tcapvm_struct *) &tcap_ptr->tcapvm_data[proc];
	int_ptr = (tcapint_struct *) &tcap_ptr->tcapint_data[proc];
	vm_ptr->peer_tid = 0;
	vm_ptr->tcap_timer = 0;
	vm_ptr->ac_mode = 0;
	vm_ptr->proto_type = 0;
	vm_ptr->sccp_class = 0;
	
	ID_ptr->current_iid[proc] = 0; //added by yingmin 2007-12-6
	
	vm_ptr->tcaprecv_head = vm_ptr->tcaprecv_tail = 0;
	int_ptr->dlgrecv_head = int_ptr->dlgrecv_tail = 0;
	int_ptr->dlgsend_head = int_ptr->dlgsend_tail = 0;
	tcap_dlg_h[proc] = 0;
	tcap_dlg_t[proc] = 0;
	debug_ptr->watch_dog[190]++;
	tcap_terminate(proc);
}

u8 tcap_from_sccp(struct SCLC_MSG *data_ptr)	//receive data from sccp
{
	char	buf[4*TCAP_BUF_LEN];
	char	*cur_time;

	if (!sclc_receive(data_ptr,0))
		return 0;
	if (debug_ptr->sccp_switch == 1 && debug_ptr->send_control == 0)
	{
		cur_time = GetAsciiTime();
		sprintf(buf,"sccp->tcap, len: %d, time: %s\r",data_ptr->msglen,cur_time);
		HexToDisplay((u8 *)buf+strlen(buf),data_ptr->msg,data_ptr->msglen);
		strcat(buf,"\r\n\r\n");
		tcap_send_ascout(buf);
	}
	debug_ptr->watch_dog[0] ++;
	return 1;
}

u8	tcap_get_sls(u32 tid)
{
	u8		ii;
	u8		sls;

	ii = (tid >> 16) & 0xff;
	if (ii % 2)		// odd
		sls = (((tid + 1)/2) * 2 + 1) % TCAP_SLS_NUM;
	else
		sls = (((tid + 1)/2) * 2) % TCAP_SLS_NUM;
	return sls;
}

void tcap_set_sccp_class(u32 did)
{
	struct	tcapvm_struct		*vm_ptr;

	if(did>=MAX_DIALOGUEID) return;

	vm_ptr = (tcapvm_struct *) &tcap_ptr->tcapvm_data[did];
	vm_ptr->sccp_class = 1;		
}

void tcap_to_sccp(struct TSL_struct *tsl_data,u8 sls,u8 flag)	// send data to sccp
{
	struct	SCLC_MSG 	sccp_data;
	char	buf[4*TCAP_BUF_LEN];
	char	*cur_time;

	if (!tsl_message_encode(&sccp_data,tsl_data,flag))	// encode the tsl message
	{
		debug_ptr->watch_dog[1] ++;
		return;
	}
	if (debug_ptr->sccp_switch == 1 && debug_ptr->send_control == 0)
	{
		cur_time = GetAsciiTime();
		sprintf(buf,"tcap->sccp, len: %d, time: %s\r",sccp_data.msglen,cur_time);
		HexToDisplay((u8 *)buf+strlen(buf),sccp_data.msg,sccp_data.msglen);
		strcat(buf,"\r\n\r\n");
		tcap_send_ascout(buf);
	}
	if((tsl_data->message_type != Begin) && (sccp_data.src_addr.SSN != 247))        //MNP calling address neednot change
	    sccp_data.src_addr.RI = RI_GT;
	if (flag == 1)
		sccp_data.sls = 0x80;
	else{
		sccp_data.sls = sls % TCAP_SLS_NUM;
		sccp_data.sequence_control = 0;
	}
	sclc_send(&sccp_data);
	debug_ptr->watch_dog[2] ++;
}

void tcap_to_sccp_class(struct TSL_struct *tsl_data,u8 sls,u8 flag, u32 proc)	// send data to sccp
{
	struct	SCLC_MSG 	sccp_data;
	char	buf[4*TCAP_BUF_LEN];
	char	*cur_time;
	struct	tcapvm_struct		*vm_ptr;

	if(proc>=MAX_DIALOGUEID) return;

	vm_ptr = (tcapvm_struct *) &tcap_ptr->tcapvm_data[proc];
	
	if (!tsl_message_encode(&sccp_data,tsl_data,flag))	// encode the tsl message
	{
		debug_ptr->watch_dog[1] ++;
		return;
	}
	if (debug_ptr->sccp_switch == 1 && debug_ptr->send_control == 0)
	{
		cur_time = GetAsciiTime();
		sprintf(buf,"tcap->sccp, len: %d, time: %s\r",sccp_data.msglen,cur_time);
		HexToDisplay((u8 *)buf+strlen(buf),sccp_data.msg,sccp_data.msglen);
		strcat(buf,"\r\n\r\n");
		tcap_send_ascout(buf);
	}
	if((tsl_data->message_type != Begin) && (sccp_data.src_addr.SSN != 247))        //MNP calling address neednot change
   	    sccp_data.src_addr.RI = RI_GT;
	if (flag == 1)
		sccp_data.sls = 0x80;
	else{
		sccp_data.sls = sls % TCAP_SLS_NUM;
		sccp_data.sequence_control = vm_ptr->sccp_class;
	}
	sclc_send(&sccp_data);
	debug_ptr->watch_dog[2] ++;
}

u8	check_resend(struct TSL_struct *tsl_ptr,u32 tid)
{
	u32		ii;

	ii = tid & 0xffff0000; 
	if (ii == (debug_ptr->local_ip & 0xffff0000))// owner data, do not need resend
		return 0;
	if(ii == (debug_ptr->peer_ip & 0xffff0000))
	{	
		ii = tid & 0x8000;
		if (ii == 0)	// resend data
			tcap_to_sccp(tsl_ptr,0x80,1);
	}
	else
	{
		tcap_send_error("local ip  chanage it back\r\n");
		tcap_set_local_ip();
	}
	return 1;
}

void tco_to_tsm(struct TSL_struct *tsl_data,u32 tid_flag)	// send data to TSM
{
	struct	tcapvm_struct		*vm_ptr;
	u8		head_flag;
	u8		tail_flag;
	u8		info_buf[1024];

	if (tid_flag >= (tcap_ptr->grantdid))
		return;
	vm_ptr = (tcapvm_struct *) &tcap_ptr->tcapvm_data[tid_flag];
	head_flag = vm_ptr->tcaprecv_head;
	tail_flag = vm_ptr->tcaprecv_tail;
	if (((head_flag + 1) % MAX_TSL_BUF) == tail_flag)	// buffer is full
	{
		if (debug_ptr->error_switch)
		{
			sprintf((char *)info_buf,"TSL error. TCO -> TSM buffer is full, dialogue id: %u",tid_flag);
			tcap_send_error((char *)info_buf);
		}
		return;
	}
		/*added by Pierre, 2006-08-19 */
	if(tsl_data->message_type == Begin ||
		tsl_data->message_type == Continue)
	{
		vm_ptr->peer_tid_len = tsl_data->peer_tid_len;
	}
	memcpy(&vm_ptr->tsl_data[head_flag],tsl_data,sizeof(TSL_struct));
	vm_ptr->tcaprecv_head = (head_flag + 1) % MAX_TSL_BUF;
}

void send_pabort_sccp(u8 tid_len,u32 tid,u8 reason,SCCP_ADDR *local_add,SCCP_ADDR *peer_add,u8 proto_type)
{
	struct	TSL_struct			tsl_data;
	struct	TRPAbort_struct		*pabort_ptr;
	u8		sls;

	if (tid == 0)
		return;
	if (proto_type == ANSI_TCAP)
		tsl_data.message_type = P_Abort_Ansi;
	else
		tsl_data.message_type = P_Abort;
	tsl_data.message_flag = REQUEST;
	memcpy(&tsl_data.local_add,local_add,sizeof(SCCP_ADDR));
	memcpy(&tsl_data.peer_add,peer_add,sizeof(SCCP_ADDR));
	pabort_ptr = (TRPAbort_struct *) &tsl_data.tsl_prim.tr_pabort;
	pabort_ptr->transaction_id = tid;
	pabort_ptr->abort_reason = reason;
	sls = tcap_get_sls(tid);
	tsl_data.peer_tid_len = tid_len;
	tcap_to_sccp(&tsl_data,sls,0);
}

void send_pabort_tsm(u32 tid,u8 reason,u8 proto_type)
{
	struct	TSL_struct			tsl_data;
	struct	TRPAbort_struct		*pabort_ptr;
	
	if (proto_type == ANSI_TCAP)
		tsl_data.message_type = P_Abort_Ansi;
	else
		tsl_data.message_type = P_Abort;
	tsl_data.message_flag = INDICATE;
	pabort_ptr = (TRPAbort_struct *) &tsl_data.tsl_prim.tr_pabort;
	pabort_ptr->transaction_id = tid;
	pabort_ptr->abort_reason = reason;
	
	tco_to_tsm(&tsl_data,tid);
}

void send_pabort_tcu(u32 did,u8 reason,u8 data_flag,u8 proto_type)
{
	struct	tcapint_struct		*int_ptr;
	struct	CSLdlg_struct		*csl_ptr;

	int_ptr = (tcapint_struct *) &tcap_ptr->tcapint_data[did];
	csl_ptr = (CSLdlg_struct *) &int_ptr->dlg_recv[data_flag];
	if (proto_type)
		csl_ptr->message_type = P_Abort_Ansi;
	else
		csl_ptr->message_type = P_Abort;
	csl_ptr->message_flag = INDICATE;
	csl_ptr->dialogue_id = did;
	csl_ptr->dlg_prim.tc_pabort.pabort_reason = reason;
	int_ptr->dlgrecv_head = (data_flag + 1) % MAX_TSL_BUF;
}

void send_uabort_sccp(u32 proc,struct dlgPDU_struct *pdu_ptr,u8 proto_type,u8 uabort_info_len, u8 *uabort_info)
{
	struct	tcapvm_struct		*vm_ptr;
	struct	TSL_struct			tsl_data;
	struct	TRUAbort_struct		*uabort_ptr;
	u8		sls;

	vm_ptr = (tcapvm_struct *) &tcap_ptr->tcapvm_data[proc];
	if (vm_ptr->peer_tid == 0)
		return;
	if (!proto_type)
		tsl_data.message_type = U_Abort;
	else
		tsl_data.message_type = U_Abort_Ansi;
	tsl_data.message_flag = REQUEST;
	memcpy(&tsl_data.local_add,&vm_ptr->local_add,sizeof(SCCP_ADDR));
	memcpy(&tsl_data.peer_add,&vm_ptr->peer_add,sizeof(SCCP_ADDR));
	uabort_ptr = (TRUAbort_struct *) &tsl_data.tsl_prim.tr_uabort;
	uabort_ptr->transaction_id = vm_ptr->peer_tid;
	uabort_ptr->dialogue_len = 0;
	uabort_ptr->dialogue_len = build_dp(uabort_ptr->dialogue,pdu_ptr,0,proto_type);
	if (proto_type)
	{
		uabort_ptr->uabort_info_len = uabort_info_len;
		memcpy(uabort_ptr->uabort_info,uabort_info,uabort_info_len);
	}
	sls = tcap_get_sls(vm_ptr->peer_tid);
	tsl_data.peer_tid_len = vm_ptr->peer_tid_len; //modified by Pierre, 06-08-19
	tcap_to_sccp(&tsl_data,sls,0);
}

u8 check_csldata(u32 proc)
{
	struct	tcapint_struct		*int_ptr;
	//char	info_str[1024];
	
	int_ptr = (tcapint_struct *) &tcap_ptr->tcapint_data[proc];
	if (int_ptr->dlgrecv_head == int_ptr->dlgrecv_tail)	// dlg recv buffer is empty
	{
		if (int_ptr->cmprecv_head == int_ptr->cmprecv_tail)
			return 1;
		//debug_ptr->watch_dog[159]++;
		//printf("check_csldata, cmprecv: %d, did: %d\n", int_ptr->cmp_recv[int_ptr->cmprecv_tail].message_type, proc);
		//sprintf(info_str, "check_csldata, cmprecv: %d, did: %ld\n", int_ptr->cmp_recv[int_ptr->cmprecv_tail].message_type, proc);
		//tcap_send_error(info_str);
	}
	else
	{
		;
		//debug_ptr->watch_dog[158]++;
		//printf("check_csldata, dlgrecv: %d, did: %d\n", int_ptr->dlg_recv[int_ptr->dlgrecv_tail].message_type, proc);
		//sprintf(info_str, "check_csldata, dlgrecv: %d, did: %ld\n", int_ptr->dlg_recv[int_ptr->dlgrecv_tail].message_type, proc);
		//tcap_send_error(info_str);
	}
	
	return 0;
}

void tco_program(void)	// transaction coordinator
{
	struct	SCLC_MSG			sccp_data;
	struct	TSL_struct			tsl_data;
	struct	TRBegin_struct		*begin_ptr;
	struct	TRContinue_struct	*con_ptr;
	struct	TREnd_struct		*end_ptr;
	struct	TRUAbort_struct		*uabort_ptr;
	struct	TRPAbort_struct		*pabort_ptr;
	struct	TRNotice_struct		*notice_ptr;
	u8		decode_result;
	u8		decode_error;
	u8		proto_type, pabort_cause;
	u32		temp_tid = 0;
	u32		ii;
	char	info_str[1024];

	if (tcap_from_sccp(&sccp_data))	// get data from sccp buffer
	{
		memset(&tsl_data,0,sizeof(TSL_struct));
		decode_result = tsl_message_decode(&sccp_data,&tsl_data,&decode_error);
		if ((tsl_data.message_type & 0xE0) == ANSI_TAG_CLASS_CONS)
			proto_type = ANSI_TCAP;
		else
			proto_type = ITU_TCAP;
		switch (tsl_data.message_type)
		{
			case Unidirectional:
			case Unidirectional_Ansi:
				debug_ptr->tc_utilize[TCAP_UTILIZE_COUNT-1][5] ++;
				debug_ptr->watch_dog[32] ++;
				if (decode_result == 1)
				{
					debug_ptr->watch_dog[33] ++;
					temp_tid = assign_did();
					if (temp_tid != 0)
					{
						debug_ptr->watch_dog[222] ++;
						tco_to_tsm(&tsl_data,temp_tid);
					}
				}
				break;
			case Begin:
			case Query_WithPerm_Ansi:
			case Query_WithoutPerm_Ansi:
				debug_ptr->tc_utilize[TCAP_UTILIZE_COUNT-1][6] ++;
				debug_ptr->watch_dog[34] ++;
				begin_ptr = (TRBegin_struct *) &tsl_data.tsl_prim.tr_begin;
				if (decode_result == 0)	// message format is wrong
				{
					debug_ptr->tc_utilize[TCAP_UTILIZE_COUNT-1][75] ++;
					debug_ptr->watch_dog[35] ++;
					if (begin_ptr->tid_flag == 1)	// ptid derivable
					{
						debug_ptr->watch_dog[36] ++;
						if (proto_type)
							pabort_cause = P_Abort_ITP_Ansi;
						else
							pabort_cause = P_Abort_ITP;
						send_pabort_sccp(tsl_data.peer_tid_len, //modified by Pierre, 06-08-19 */
						                 begin_ptr->transaction_id,pabort_cause,&tsl_data.local_add,&tsl_data.peer_add,proto_type);
					}
					return;
				}
				temp_tid = assign_did();
				if (temp_tid == 0)	// can not assign a dialogue id
				{
					tcap_send_alarm(5,1);
					debug_ptr->tc_utilize[TCAP_UTILIZE_COUNT-1][72] ++;
					debug_ptr->tc_utilize[TCAP_UTILIZE_COUNT-1][24]++;
					tcap_send_error("TSL error. Can not assign transaction id");
					debug_ptr->watch_dog[37] ++;
					if (proto_type)
						pabort_cause = P_Abort_RL_Ansi;
					else
						pabort_cause = P_Abort_RL;
					send_pabort_sccp(tsl_data.peer_tid_len,//modified by Pierre, 06-08-19 
					                 begin_ptr->transaction_id,pabort_cause,&tsl_data.local_add,&tsl_data.peer_add,proto_type);
					return;
				}
				debug_ptr->watch_dog[221] ++;
				debug_ptr->tc_utilize[TCAP_UTILIZE_COUNT-1][20]++;
				tco_to_tsm(&tsl_data,temp_tid);
				break;
			case Continue:
			case Conversation_WithPerm_Ansi:
			case Conversation_WithoutPerm_Ansi:
				debug_ptr->tc_utilize[TCAP_UTILIZE_COUNT-1][7] ++;
				debug_ptr->watch_dog[38] ++;
				con_ptr = (TRContinue_struct *) &tsl_data.tsl_prim.tr_continue;
				if (decode_result == 0)	// message format is wrong
				{
					debug_ptr->tc_utilize[TCAP_UTILIZE_COUNT-1][75] ++;
					debug_ptr->watch_dog[39] ++;
					if (con_ptr->ptid_flag == 1)	// ptid derivable
					{
						if (con_ptr->ltid_flag == 0)	// DTID not assigned
						{
							debug_ptr->watch_dog[40] ++;
							if (proto_type)
								pabort_cause = P_Abort_ITP_Ansi;
							else
								pabort_cause = P_Abort_ITP;
							send_pabort_sccp(tsl_data.peer_tid_len, //modified by Pierre, 06-08-19
							                 con_ptr->peer_tid,pabort_cause,&tsl_data.local_add,&tsl_data.peer_add,proto_type);
						}
						else
						{
							ii = con_ptr->local_tid;
							if (check_resend(&tsl_data,ii))
								return;
							ii = ii & 0x7fff;
							if (!check_did(ii))
							{
								debug_ptr->watch_dog[40] ++;
								if (proto_type)
									pabort_cause = P_Abort_ITP_Ansi;
								else
									pabort_cause = P_Abort_ITP;
								send_pabort_sccp(tsl_data.peer_tid_len, //modified by Pierre, 06-08-19
								                 con_ptr->peer_tid,pabort_cause,&tsl_data.local_add,&tsl_data.peer_add,proto_type);
							}
							else
							{
								debug_ptr->watch_dog[41] ++;
								if (decode_error == DERR_UNTID || decode_error == DERR_OTHER)
								{
									if (proto_type)
										pabort_cause = P_Abort_ITP_Ansi;
									else
										pabort_cause = P_Abort_ITP;
								}
								else
								{
									if (proto_type)
										pabort_cause = P_Abort_BFTP_Ansi;
									else
										pabort_cause = P_Abort_BFTP;
								}
								send_pabort_sccp(tsl_data.peer_tid_len, //modified by Pierre, 06-08-19
								                 con_ptr->peer_tid,pabort_cause,&tsl_data.local_add,&tsl_data.peer_add,proto_type);
								send_pabort_tsm(ii,pabort_cause,proto_type);
							}
						}
					}
					return;
				}
				ii = con_ptr->local_tid;
				if (check_resend(&tsl_data,ii))
					return;
				con_ptr->local_tid = ii & 0x7fff;
				if (!check_did(con_ptr->local_tid))	// DTID not assigned
				{
					debug_ptr->tc_utilize[TCAP_UTILIZE_COUNT-1][72] ++;
					sprintf(info_str, "TSL error. Can not check out transaction id, did: %u, type: %d, continue", temp_tid, tsl_data.message_type);
					tcap_send_error(info_str);
					debug_ptr->watch_dog[230]++;
					//tcap_send_error("TSL error. Can not check out transaction id");
					debug_ptr->watch_dog[42] ++;
					if (con_ptr->peer_tid != 0)	// ptid derivable
					{
						debug_ptr->watch_dog[43] ++;
						if (proto_type)
							pabort_cause = P_Abort_UTID_Ansi;
						else
							pabort_cause = P_Abort_UTID;
						send_pabort_sccp(tsl_data.peer_tid_len, //modified by Pierre, 06-08-19
						                 con_ptr->peer_tid,pabort_cause,&tsl_data.local_add,&tsl_data.peer_add,proto_type);
					}
					return;
				}
				tco_to_tsm(&tsl_data,con_ptr->local_tid);
				break;
			case End:
			case Response_Ansi:
				debug_ptr->tc_utilize[TCAP_UTILIZE_COUNT-1][8] ++;
				debug_ptr->watch_dog[44] ++;
				end_ptr = (TREnd_struct *) &tsl_data.tsl_prim.tr_end;
				if (check_resend(&tsl_data,end_ptr->transaction_id))
					return;
				end_ptr->transaction_id &= 0x7fff;
				temp_tid = end_ptr->transaction_id;
				if (decode_result == 0)
				{
					debug_ptr->tc_utilize[TCAP_UTILIZE_COUNT-1][75] ++;
					debug_ptr->watch_dog[45] ++;
					if (end_ptr->tid_flag == 0 || !check_did(temp_tid))
						debug_ptr->watch_dog[46] ++;
					else
					{
						if (proto_type)
							pabort_cause = P_Abort_BFTP_Ansi;
						else
							pabort_cause = P_Abort_BFTP;
						send_pabort_tsm(temp_tid,pabort_cause,proto_type);
					}
					return;
				}
				if (!check_did(temp_tid))
				{
					debug_ptr->tc_utilize[TCAP_UTILIZE_COUNT-1][72] ++;
					sprintf(info_str, "TSL error. Can not check out transaction id, did: %u, type: %d, end", temp_tid, tsl_data.message_type);
					tcap_send_error(info_str);
					//printf("TSL error. Can not check out transaction id, did: %ld, type: %d, end\n", temp_tid, tsl_data.message_type);
					debug_ptr->watch_dog[229]++;
					//tcap_send_error("TSL error. Can not check out transaction id");
					return;
				}
				tco_to_tsm(&tsl_data,temp_tid);
				break;
			case U_Abort:
			case U_Abort_Ansi:
				debug_ptr->tc_utilize[TCAP_UTILIZE_COUNT-1][9] ++;
				debug_ptr->watch_dog[47] ++;
				uabort_ptr = (TRUAbort_struct *) &tsl_data.tsl_prim.tr_uabort;
				if (check_resend(&tsl_data,uabort_ptr->transaction_id))
					return;
				uabort_ptr->transaction_id &= 0x7fff;
				temp_tid = uabort_ptr->transaction_id;
				if (decode_result == 0)
				{
					debug_ptr->tc_utilize[TCAP_UTILIZE_COUNT-1][75] ++;
					debug_ptr->watch_dog[48] ++;
					if (uabort_ptr->tid_flag == 0 || !check_did(temp_tid))
					{
						debug_ptr->watch_dog[49] ++;
						if (proto_type)
							pabort_cause = P_Abort_BFTP_Ansi;
						else
							pabort_cause = P_Abort_BFTP;
						send_pabort_tsm(temp_tid,pabort_cause,proto_type);
					}
					return;
				}
				if (!check_did(temp_tid))
				{
					debug_ptr->tc_utilize[TCAP_UTILIZE_COUNT-1][72] ++;
					sprintf(info_str, "TSL error. Can not check out transaction id, did: %u, type: %d, uabort", temp_tid, tsl_data.message_type);
					tcap_send_error(info_str);
					debug_ptr->watch_dog[228]++;
					//tcap_send_error("TSL error. Can not check out transaction id");
					return;
				}
				if (debug_ptr->error_switch)
				{
					if (!proto_type)
						sprintf(info_str,"TSL warning. Receive U_Abort from other machine. Tid= %u",temp_tid);
					else
						sprintf(info_str,"TSL warning. Receive U_Abort_Ansi from other machine. Tid= %u",temp_tid);
					tcap_send_error(info_str);
				}
				tco_to_tsm(&tsl_data,temp_tid);
				break;
			case P_Abort:
			case P_Abort_Ansi:
				debug_ptr->tc_utilize[TCAP_UTILIZE_COUNT-1][9] ++;
				debug_ptr->watch_dog[50] ++;
				pabort_ptr = (TRPAbort_struct *) &tsl_data.tsl_prim.tr_pabort;
				if (check_resend(&tsl_data,pabort_ptr->transaction_id))
					return;
				pabort_ptr->transaction_id &= 0x7fff;
				temp_tid = pabort_ptr->transaction_id;
				if (decode_result == 0)
				{
					debug_ptr->tc_utilize[TCAP_UTILIZE_COUNT-1][75] ++;
					debug_ptr->watch_dog[51] ++;
					if (pabort_ptr->tid_flag == 0 || !check_did(temp_tid))
						debug_ptr->watch_dog[52] ++;
					else
					{
						if (proto_type)
							pabort_cause = P_Abort_BFTP_Ansi;
						else
							pabort_cause = P_Abort_BFTP;
						send_pabort_tsm(temp_tid,pabort_cause,proto_type);
					}
					return;
				}
				if (!check_did(temp_tid))
				{
					debug_ptr->tc_utilize[TCAP_UTILIZE_COUNT-1][72] ++;
					sprintf(info_str, "TSL error. Can not check out transaction id, did: %u, type: %d, pabort", temp_tid, tsl_data.message_type);
					tcap_send_error(info_str);
					debug_ptr->watch_dog[227]++;
					//tcap_send_error("TSL error. Can not check out transaction id");
					return;
				}
				tco_to_tsm(&tsl_data,temp_tid);
				debug_ptr->tc_utilize[TCAP_UTILIZE_COUNT-1][73] ++;
				if (!proto_type)
				{
					switch (pabort_ptr->abort_reason)
					{
						case P_Abort_UMT:
							debug_ptr->tc_utilize[TCAP_UTILIZE_COUNT-1][25] ++;
							break;
						case P_Abort_ITP:
							debug_ptr->tc_utilize[TCAP_UTILIZE_COUNT-1][26] ++;
							break;
						case P_Abort_BFTP:
							debug_ptr->tc_utilize[TCAP_UTILIZE_COUNT-1][27] ++;
							break;
						case P_Abort_UTID:
							debug_ptr->tc_utilize[TCAP_UTILIZE_COUNT-1][28] ++;
							break;
						case P_Abort_RL:
							debug_ptr->tc_utilize[TCAP_UTILIZE_COUNT-1][29] ++;
							break;
						default:
							break;
					}
				}
				else
				{
					switch (pabort_ptr->abort_reason)
					{
						case P_Abort_UMT_Ansi:
							debug_ptr->tc_utilize[TCAP_UTILIZE_COUNT-1][25] ++;
							break;
						case P_Abort_ITP_Ansi:
							debug_ptr->tc_utilize[TCAP_UTILIZE_COUNT-1][26] ++;
							break;
						case P_Abort_BFTP_Ansi:
							debug_ptr->tc_utilize[TCAP_UTILIZE_COUNT-1][27] ++;
							break;
						case P_Abort_UTID_Ansi:
							debug_ptr->tc_utilize[TCAP_UTILIZE_COUNT-1][28] ++;
							break;
						case P_Abort_RL_Ansi:
							debug_ptr->tc_utilize[TCAP_UTILIZE_COUNT-1][29] ++;
							break;
						default:
							break;
					}
				}
				if (debug_ptr->error_switch)
				{
					if (!proto_type)
						sprintf(info_str,"TSL warning. Receive P_Abort from other machine. Tid= %u",temp_tid);
					else
						sprintf(info_str,"TSL warning. Receive P_Abort_Ansi from other machine. Tid= %u",temp_tid);
					tcap_send_error(info_str);
				}
				break;
			case Notice:
				debug_ptr->watch_dog[53] ++;
				notice_ptr = (TRNotice_struct *) &tsl_data.tsl_prim.tr_notice;
				temp_tid = notice_ptr->transaction_id;
				if (!check_did(temp_tid))
				{
					sprintf(info_str, "TSL error. Can not check out transaction id, did: %u, type: %d, notice", temp_tid, tsl_data.message_type);
					tcap_send_error(info_str);
					debug_ptr->watch_dog[226]++;
					//tcap_send_error("TSL error. Can not check out transaction id");
					return;
				}
				tco_to_tsm(&tsl_data,temp_tid);
				tcap_send_error("TSL error. Receive Notice from lower layer");
				break;
			default:
				debug_ptr->watch_dog[54] ++;
				break;
		}
	}
}

int get_from_cha(u8 *content,u32 proc,u8 *temp,u8 data_count,u8 level)	// build component primitive
{
	struct	tcapint_struct		*int_ptr;
	int		len = 0;
	int		ii,jj,aa;
	u8		default_len,send_count=0;
	u8		temp_buf[TCAP_BUF_LEN];

	int_ptr = (tcapint_struct *) &tcap_ptr->tcapint_data[proc];
	*temp = 0;
	if (level == 1)
		default_len = TCAP_PARAM_LEN_1;
	else
		default_len = TCAP_PARAM_LEN;
	for (ii = 0;ii < data_count;ii ++)
	{
		jj = int_ptr->cmpsend_tail;
		if (jj == int_ptr->cmpsend_head)
			break;
		int_ptr->cmp_send[jj].invoke_id = get_transfer_iid(proc, int_ptr->cmp_send[jj].invoke_id); //2010-11-04 for dup iid
		
		aa = assemble_component(temp_buf,&int_ptr->cmp_send[jj]);
		if ((len+aa) > default_len)	// components data is too long
		{
			tcap_send_error("CSL warning.components length is larger than expected");
			*temp = send_count;
			debug_ptr->watch_dog[250]++;
			break;
		}
		else
		{
			memcpy(content+len,temp_buf,aa);
			int_ptr->cmpsend_tail = (jj + 1) % MAX_CSL_BUF;
			len += aa;
			send_count ++;
			debug_ptr->watch_dog[251]++;
		}
	}
	return len;
}

void send_cancel_tcu(u32 proc,u8 invid)
{
	struct	tcapint_struct		*int_ptr;
	struct	CSLcmp_struct		*cmp_ptr;
	u8		ii;
	u8		info_buf[1024];

	int_ptr = (tcapint_struct *) &tcap_ptr->tcapint_data[proc];
	ii = int_ptr->cmprecv_head;
	if ((ii + 1) % MAX_CSL_BUF == int_ptr->cmprecv_tail)	// buffer is full
	{
		if (debug_ptr->error_switch)
		{
			sprintf((char *)info_buf,"ISM error. component buffer is full:%u",proc);
			tcap_send_error((char *)info_buf);
		}
		return;
	}
	cmp_ptr = (CSLcmp_struct *) &int_ptr->cmp_recv[ii];
	cmp_ptr->message_type = L_Cancel;
	cmp_ptr->message_flag = INDICATE;
	cmp_ptr->dialogue_id = proc;
	cmp_ptr->invoke_id = invid;
	int_ptr->cmprecv_head = (ii + 1) % MAX_CSL_BUF;
	debug_ptr->watch_dog[156]++;
}

void send_reject_tcu(u32 proc,u8 invid,u8 err_type,u8 err_code,u8 proto_type)
{
	struct	tcapint_struct		*int_ptr;
	struct	CSLcmp_struct		*cmp_ptr;
	struct	TCReject_struct		*reject_ptr;
	u8		ii;
	u8		flag=0;

	int_ptr = (tcapint_struct *) &tcap_ptr->tcapint_data[proc];
	ii = int_ptr->cmprecv_tail;
	while(ii != int_ptr->cmprecv_head)
	{
		if (int_ptr->cmp_recv[ii].invoke_id == invid)	// find exist data
		{
			flag = 1;
			break;
		}
		ii = (ii + 1) % MAX_CSL_BUF;
	}
	if (flag == 0)
	{
		ii = int_ptr->cmprecv_head;
		int_ptr->cmprecv_head = (ii + 1) % MAX_CSL_BUF;
	}
	cmp_ptr = (CSLcmp_struct *) &int_ptr->cmp_recv[ii];
	if (proto_type)
		cmp_ptr->message_type = L_Reject_Ansi;
	else
		cmp_ptr->message_type = L_Reject;
	cmp_ptr->message_flag = INDICATE;
	cmp_ptr->dialogue_id = proc;
	cmp_ptr->invoke_id = invid;
	cmp_ptr->last_flag = 1;
	reject_ptr = (TCReject_struct *) &cmp_ptr->cmp_prim.tc_reject;
	reject_ptr->problem_type = err_type;
	reject_ptr->problem_code = err_code;	// badly structured component
}

u8 find_tempiid(u32 did,u8 iid,u8 flag)
{
	struct	tcapvm_struct	*vm_ptr;
	struct	ismvm_data		*ism_ptr;
	u8		ii;

	vm_ptr = (tcapvm_struct *) &tcap_ptr->tcapvm_data[did];
	if (flag == 1)		//apply for new iid
	{
		for (ii = 0;ii < MAX_TEMPINVOKEID;ii ++)
		{
			ism_ptr = (ismvm_data *) &vm_ptr->ism_data[ii];
			if (ism_ptr->used_flag == 0)	// empty temp iid
			{
				ism_ptr->used_flag = 1;
				ism_ptr->linked_iid = iid;
				return ii;
			}
		}
	}
	else			//search assigned iid
	{
		for (ii = 0;ii < MAX_TEMPINVOKEID;ii ++)
		{
			ism_ptr = (ismvm_data *) &vm_ptr->ism_data[ii];
			if ((ism_ptr->used_flag==1)&&(ism_ptr->linked_iid==iid))
				return ii;
		}
	}
	tcap_send_error("CSL warning.Can not assign a temp invoke id");
	return 0xff;
}

u8 write_ism(CSLcmp_struct *cmp_ptr)
{
	struct	tcapvm_struct	*vm_ptr;
	struct	ismvm_data		*ism_ptr;
	u8		iid,temp_iid;
	u32		did;

	did = cmp_ptr->dialogue_id;
	iid = cmp_ptr->invoke_id;
	vm_ptr = (tcapvm_struct *) &tcap_ptr->tcapvm_data[did];
	
	if (((cmp_ptr->message_type == Invoke) ||
		(cmp_ptr->message_type == Invoke_L_Ansi) ||
		(cmp_ptr->message_type == Invoke_NL_Ansi)) &&
		(cmp_ptr->message_flag == REQUEST))
		temp_iid = find_tempiid(did,iid,1);
	else
		temp_iid = find_tempiid(did,iid,0);
	if (temp_iid == 0xff)	// can not find temp iid
	{
		debug_ptr->watch_dog[252]++;
		return 0;
	}
	ism_ptr = (ismvm_data *) &vm_ptr->ism_data[temp_iid];
	ism_ptr->ism_msgtype = cmp_ptr->message_type;
	ism_ptr->ism_msgflag = cmp_ptr->message_flag;
	if (((cmp_ptr->message_type == Invoke) ||
		(cmp_ptr->message_type == Invoke_L_Ansi) ||
		(cmp_ptr->message_type == Invoke_NL_Ansi)) &&
		(cmp_ptr->message_flag == REQUEST))
	{
		ism_ptr->ism_msgclass = cmp_ptr->cmp_prim.tc_invoke.operation_class;
		ism_ptr->ism_oper_domain = cmp_ptr->cmp_prim.tc_invoke.operation_domain;
		ism_ptr->ism_oper_family = cmp_ptr->cmp_prim.tc_invoke.operation_family;
		ism_ptr->ism_oper_code = cmp_ptr->cmp_prim.tc_invoke.operation_code;
		if (cmp_ptr->cmp_prim.tc_invoke.timer != 0)	// has invoke time
			ism_ptr->ism_timer = cmp_ptr->cmp_prim.tc_invoke.timer*ISM_TIMERHZ;
		else
			ism_ptr->ism_timer = debug_ptr->default_invtime*ISM_TIMERHZ;
	}
	else if ((cmp_ptr->message_type == U_Cancel) && (cmp_ptr->message_flag == REQUEST))
	{
		debug_ptr->watch_dog[157]++;
		ism_ptr->ism_state = TCAP_INIT;
	}
	else if (((cmp_ptr->message_type == U_Reject) ||
			(cmp_ptr->message_type == U_Reject_Ansi)) &&
			(cmp_ptr->message_flag == REQUEST))
	{
		if ((cmp_ptr->cmp_prim.tc_reject.problem_type != Invoke_Problem) &&
			(cmp_ptr->cmp_prim.tc_reject.problem_type != Invoke_Problem_Ansi))
			ism_ptr->ism_state = TCAP_INIT;
	}
	return 1;
}

void send_to_cha(u32 proc,u8 *content,u8 data_len)	// analyse the component primitive
{
	struct	tcapvm_struct		*vm_ptr;
	struct	tcapint_struct		*int_ptr;
	struct	CSLcmp_struct		*cmp_ptr;
	struct	ismvm_data			*state_ptr=NULL;
	struct	TCInvoke_struct		*invoke_ptr;
	struct	TCReject_struct		*reject_ptr;
	u8		ii;
	u8		temp_invid;
	u8		flag;
	u8		proto_type;
	int		len = 0;
	int		sec_len;
	int		result;
	char	info_str[1024];
	u8		problem_type,problem_code;
	
	vm_ptr = (tcapvm_struct *) &tcap_ptr->tcapvm_data[proc];
	int_ptr = (tcapint_struct *) &tcap_ptr->tcapint_data[proc];
	while (len < data_len)
	{
		ii = int_ptr->cmprecv_head;
		if (((ii + 1) % MAX_CSL_BUF) == int_ptr->cmprecv_tail)
		{
			if (debug_ptr->error_switch)
			{
				sprintf(info_str,"ISM error. Component buffer is full: %u",proc);
				tcap_send_error(info_str);
			}
			int_ptr->cmp_recv[ii].last_flag = 1;
			return;
		}
		cmp_ptr = (CSLcmp_struct *) &int_ptr->cmp_recv[ii];
		memset(cmp_ptr,0,sizeof(CSLcmp_struct));
		result = extract_component(cmp_ptr,content+len,proc,&sec_len);
		if (sec_len == -1)	// structure length is error
		{
			debug_ptr->watch_dog[249]++;
			return;
		}
		if (result != 0)	// syntax is right
		{
			debug_ptr->watch_dog[248]++;
			len += sec_len;
		}
		if (len == data_len)	// this component is the last one
			cmp_ptr->last_flag = 1;
		temp_invid = cmp_ptr->invoke_id;
		if ((cmp_ptr->message_type & 0xE0) == ANSI_TAG_CLASS_CONS)
			proto_type = ANSI_TCAP;
		else
			proto_type = ITU_TCAP;
		switch (cmp_ptr->message_type)
		{
			case Invoke:
			case Invoke_L_Ansi:
			case Invoke_NL_Ansi:
				if (result == 0)	// syntax error
				{
					if (!proto_type)
					{
						problem_type = General_Problem;
						problem_code = General_Problem_MC;
					}
					else
					{
						problem_type = General_Problem_Ansi;
						problem_code = General_Problem_MC_Ansi;
					}
					send_reject_tcu(proc,temp_invid,problem_type,problem_code,proto_type);
					return;
				}
				if (!store_iid(proc,temp_invid))
				{
				       cmp_ptr->invoke_id = transfer_iid(proc, temp_invid);
				       tcap_send_error("Duplicate invoke id, transfer it!");
				       /*
					tcap_send_error("CSL error. Duplicate invoke id");
					if (!proto_type)
					{
						problem_type = Invoke_Problem;
						problem_code = Invoke_Problem_DIID;
					}
					else
					{
						problem_type = Invoke_Problem_Ansi;
						problem_code = Invoke_Problem_DIID_Ansi;
					}
					send_reject_tcu(proc,temp_invid,problem_type,problem_code,proto_type);
					return;
					*/
				}
				invoke_ptr = (TCInvoke_struct *) &cmp_ptr->cmp_prim.tc_invoke;
				if (invoke_ptr->linkedid_flag == 1)	// linked other operation
				{
					flag = find_tempiid(proc,invoke_ptr->linked_id,0);
					if (flag != 0xff)	// find temp invoke id
						state_ptr = (ismvm_data *) &vm_ptr->ism_data[flag];
					if ((flag == 0xff)||(state_ptr->ism_state!=SENT_STATE1&&state_ptr->ism_state!=SENT_STATE2&&state_ptr->ism_state!=SENT_STATE3&&state_ptr->ism_state!=SENT_STATE4))// the linked ISM is not in sent state
					{
						tcap_send_error("CSL error. Linked ID is not in use");
						if (!proto_type)
						{
							problem_type = Invoke_Problem;
							problem_code = Invoke_Problem_ULID;
						}
						else
						{
							problem_type = Invoke_Problem_Ansi;
							problem_code = Invoke_Problem_ULID_Ansi;
						}
						send_reject_tcu(proc,temp_invid,problem_type,problem_code,proto_type);
					}
					else
						int_ptr->cmprecv_head = (ii + 1) % MAX_CSL_BUF;
				}
				else
					int_ptr->cmprecv_head = (ii + 1) % MAX_CSL_BUF;		
				break;
			case Result_NL:
			case Result_L:
			case Error:
			case Result_NL_Ansi:
			case Result_L_Ansi:
			case Error_Ansi:
				if (result == 0)
				{
					if (check_iid(proc,temp_invid))	// invoke id can search
					{
						flag = find_tempiid(proc,temp_invid,0);
						if (flag != 0xff)
							ism_terminate(proc,flag);
						if (!proto_type)
						{
							problem_type = General_Problem;
							problem_code = General_Problem_MC;
						}
						else
						{
							problem_type = General_Problem_Ansi;
							problem_code = General_Problem_MC_Ansi;
						}
						send_reject_tcu(proc,temp_invid,problem_type,problem_code,proto_type);
					}
					return;
				}
				flag = find_tempiid(proc,temp_invid,0);
				if (flag != 0xff)
					state_ptr = (ismvm_data *) &vm_ptr->ism_data[flag];
				if ((flag == 0xff)||(state_ptr->ism_state == TCAP_IDLE))	// invoke id is not active
				{
					if ((cmp_ptr->message_type == Result_NL) ||
						(cmp_ptr->message_type == Result_L) ||
						(cmp_ptr->message_type == Result_NL_Ansi) ||
						(cmp_ptr->message_type == Result_L_Ansi))
					{
						if (!proto_type)
						{
							problem_type = Return_Result;
							problem_code = Return_Result_RRU;
							tcap_send_error("CSL error. Return Result is not expected");
						}
						else
						{
							problem_type = Return_Result_Ansi;
							problem_code = Return_Result_RRU_Ansi;
							tcap_send_error("CSL error. Return Result Ansi is not expected");
						}
					}
					else
					{
						if (!proto_type)
						{
							problem_type = Return_Error;
							problem_code = Return_Error_UEE;
							tcap_send_error("CSL error. Return Error is not expected");
						}
						else
						{
							problem_type = Return_Error_Ansi;
							problem_code = Return_Error_UEE_Ansi;
							tcap_send_error("CSL error. Return Error Ansi is not expected");
						}
					}
					send_reject_tcu(proc,temp_invid,problem_type,problem_code,proto_type);
					return;
				}
				if (((cmp_ptr->message_type == Error) ||
				 	(cmp_ptr->message_type == Error_Ansi)) &&
				 	 (debug_ptr->error_switch))
				{
					if (cmp_ptr->message_type == Error)
						sprintf(info_str,"CSL warning. Return Error received from other machine. Did is %u, Iid is %d",proc,temp_invid);
					else
						sprintf(info_str,"CSL warning. Return Error Ansi received from other machine. Did is %u, Iid is %d",proc,temp_invid);
					tcap_send_error(info_str);
				}
				if (proto_type)
				{
					if ((cmp_ptr->message_type == Result_NL_Ansi) ||
						(cmp_ptr->message_type == Result_L_Ansi))
					{
						cmp_ptr->cmp_prim.tc_result.operation_flag = 1;
						cmp_ptr->cmp_prim.tc_result.operation_domain = state_ptr->ism_oper_domain;
						cmp_ptr->cmp_prim.tc_result.operation_family = state_ptr->ism_oper_family;
						cmp_ptr->cmp_prim.tc_result.operation_code = state_ptr->ism_oper_code;
					}
				}
				if (!write_ism(cmp_ptr))
					debug_ptr->watch_dog[230] ++;
				int_ptr->cmprecv_head = (ii + 1) % MAX_CSL_BUF;		
				break;
			case Reject:
			case Reject_Ansi:
				reject_ptr = (TCReject_struct *) &cmp_ptr->cmp_prim.tc_reject;
				if (result == 0)	// syntax error
				{
					if (!proto_type)
					{
						problem_type = General_Problem;
						problem_code = General_Problem_MC;
					}
					else
					{
						problem_type = General_Problem_Ansi;
						problem_code = General_Problem_MC_Ansi;
					}
					send_reject_tcu(proc,temp_invid,problem_type,problem_code,proto_type);
					return;
				}
				if ((reject_ptr->problem_type == Invoke_Problem) ||
					(reject_ptr->problem_type == Invoke_Problem_Ansi)) // invoke problem type
				{
					flag = find_tempiid(proc,temp_invid,0);
					if (flag != 0xff)
						state_ptr = (ismvm_data *) &vm_ptr->ism_data[flag];
					if ((flag == 0xff)||(state_ptr->ism_state == TCAP_IDLE))	// the ism is not active
					{
						if (proto_type)
							cmp_ptr->message_type = R_Reject_Ansi;
						else
							cmp_ptr->message_type = R_Reject;
					}
					else
					{
						ism_terminate(proc,flag);
						if ((reject_ptr->problem_code == Invoke_Problem_ULID) ||
							(reject_ptr->problem_code == Invoke_Problem_ULID_Ansi))
						{
							if (proto_type)
								cmp_ptr->message_type = R_Reject_Ansi;
							else
								cmp_ptr->message_type = R_Reject;
						}
						else
						{
							if (proto_type)
								cmp_ptr->message_type = U_Reject_Ansi;
							else
								cmp_ptr->message_type = U_Reject;
						}
					}
				}
				else
				{
					if ((reject_ptr->problem_type == General_Problem) ||
						(reject_ptr->problem_type == General_Problem_Ansi))
					{
						if (proto_type)
							cmp_ptr->message_type = R_Reject_Ansi;
						else
							cmp_ptr->message_type = R_Reject;
					}
					else if ((reject_ptr->problem_type == Return_Result) ||
							(reject_ptr->problem_type == Return_Result_Ansi))
					{
						if ((reject_ptr->problem_code == Return_Result_MP) ||
							(reject_ptr->problem_code == Return_Result_MP_Ansi))
						{
							if (proto_type)
								cmp_ptr->message_type = U_Reject_Ansi;
							else
								cmp_ptr->message_type = U_Reject;
						}
						else
						{
							if (proto_type)
								cmp_ptr->message_type = R_Reject_Ansi;
							else
								cmp_ptr->message_type = R_Reject;
						}
					}
					else
					{
						if ((reject_ptr->problem_code == Return_Error_UIID) ||
							(reject_ptr->problem_code == Return_Error_UIID_Ansi) ||
							 (reject_ptr->problem_code == Return_Error_REU) ||
							 (reject_ptr->problem_code == Return_Error_REU_Ansi))
						{
							if (proto_type)
								cmp_ptr->message_type = R_Reject_Ansi;
							else
								cmp_ptr->message_type = R_Reject;
						}
						else
						{
							if (proto_type)
								cmp_ptr->message_type = U_Reject_Ansi;
							else
								cmp_ptr->message_type = U_Reject;
						}
					}
				}
				if (debug_ptr->error_switch)
				{
					if (!proto_type)
						sprintf(info_str,"CSL warning. Reject Received from other machine. Did is %u, Iid is %d",proc,temp_invid);
					else
						sprintf(info_str,"CSL warning. Reject Ansi Received from other machine. Did is %u, Iid is %d",proc,temp_invid);
					tcap_send_error(info_str);
				}
				int_ptr->cmprecv_head = (ii + 1) % MAX_CSL_BUF;
				break;
			default:
				if (result == 0)
				{
					if (!proto_type)
					{
						problem_type = General_Problem;
						problem_code = General_Problem_MC;
					}
					else
					{
						problem_type = General_Problem_Ansi;
						problem_code = General_Problem_MC_Ansi;
					}
					send_reject_tcu(proc,temp_invid,problem_type,problem_code,proto_type);
					return;
				}
				if (check_iid(proc,temp_invid))	// invoke id can search
				{
					flag = find_tempiid(proc,temp_invid,0);
					if (flag != 0xff)
						ism_terminate(proc,flag);
				}
				if (!proto_type)
				{
					problem_type = General_Problem;
					problem_code = General_Problem_UC;
				}
				else
				{
					problem_type = General_Problem_Ansi;
					problem_code = General_Problem_UC_Ansi;
				}
				send_reject_tcu(proc,temp_invid,problem_type,problem_code,proto_type);
				break;
		}
	}
}

void tcap_uni_request(u32 proc,u8 data_flag)
{
	struct	tcapvm_struct		*vm_ptr;
	struct	tcapint_struct		*int_ptr;
	struct	CSLdlg_struct		*csl_ptr;
	struct	TCUni_struct		*tcuni_ptr;
	struct	TSL_struct			tsl_data;
	struct	TRUni_struct		*truni_ptr;
	struct	dlgPDU_struct		pdu_data;
	u8		ii,proto_type;
	u8		temp=0;
	u8		cmp_level,sls;

	vm_ptr = (tcapvm_struct *) &tcap_ptr->tcapvm_data[proc];
	int_ptr = (tcapint_struct *) &tcap_ptr->tcapint_data[proc];
	csl_ptr = (CSLdlg_struct *) &int_ptr->dlg_send[data_flag];
	tcuni_ptr = (TCUni_struct *) &csl_ptr->dlg_prim.tc_uni;
	tsl_data.message_type = csl_ptr->message_type;
	tsl_data.message_flag = REQUEST;
	if ((csl_ptr->message_type & 0xE0) == ANSI_TAG_CLASS_CONS)
		proto_type = ANSI_TCAP;
	else
		proto_type = ITU_TCAP;
	memcpy(&tsl_data.local_add,&tcuni_ptr->local_add,sizeof(SCCP_ADDR));
	memcpy(&tsl_data.peer_add,&tcuni_ptr->peer_add,sizeof(SCCP_ADDR));
	truni_ptr = (TRUni_struct *) &tsl_data.tsl_prim.tr_uni;
	truni_ptr->dialogue_len = truni_ptr->components_len = 0;
	if (tcuni_ptr->dialogue_flag == 1)	// has dialogue portion
	{
		if (!proto_type)
		{
			pdu_data.dialogue_type = PDU_AUDT;
			memcpy(pdu_data.pdu_union.aarq.version,Version_1,2);
		}
		else
		{
			pdu_data.dialogue_type = PDU_ASUDT;
			pdu_data.pdu_union.asudt.version = Version_Ansi;
		}
		set_dlgpdu(&pdu_data,&tcuni_ptr->dlg_data);
		truni_ptr->dialogue_len = build_dp(truni_ptr->dialogue,&pdu_data,1,proto_type);
		cmp_level = 0;
	}
	else
		cmp_level = 1;
	ii = tcuni_ptr->component_present;
	if (ii != 0)
		truni_ptr->components_len = get_from_cha(truni_ptr->components,proc,&temp,ii,cmp_level);
	if (temp == 0)	// components is not too long
	{
		vm_ptr->proto_type = proto_type;
		sls = proc % TCAP_SLS_NUM;
		tcap_to_sccp(&tsl_data,sls,0);
	}
	else
		tcap_send_error("CSL error. Component is too long");
}

u8 tcap_uni_indicate(u32 proc,u8 data_flag)
{
	struct	tcapvm_struct		*vm_ptr;
	struct	TSL_struct			*tsl_ptr;
	struct	TRUni_struct		*truni_ptr;
	struct	tcapint_struct		*int_ptr;
	struct	CSLdlg_struct		*csl_ptr;
	struct	TCUni_struct		*tcuni_ptr;
	struct	dlgPDU_struct		pdu_data;
	u8		ii, proto_type;

	vm_ptr = (tcapvm_struct *) &tcap_ptr->tcapvm_data[proc];
	tsl_ptr = (TSL_struct *) &vm_ptr->tsl_data[data_flag];
	truni_ptr = (TRUni_struct *) &tsl_ptr->tsl_prim.tr_uni;
	int_ptr = (tcapint_struct *) &tcap_ptr->tcapint_data[proc];
	ii = int_ptr->dlgrecv_head;
	csl_ptr = (CSLdlg_struct *) &int_ptr->dlg_recv[ii];
	csl_ptr->message_type = tsl_ptr->message_type;
	csl_ptr->message_flag = INDICATE;
	csl_ptr->dialogue_id = proc;
	if ((tsl_ptr->message_type & 0xE0) == ANSI_TAG_CLASS_CONS)
		proto_type = ANSI_TCAP;
	else
		proto_type = ITU_TCAP;
	tcuni_ptr = (TCUni_struct *) &csl_ptr->dlg_prim.tc_uni;
	memcpy(&tcuni_ptr->local_add,&tsl_ptr->local_add,sizeof(SCCP_ADDR));
	memcpy(&tcuni_ptr->peer_add,&tsl_ptr->peer_add,sizeof(SCCP_ADDR));
	if (truni_ptr->dialogue_len != 0)
	{
		if ((!proto_type && !extract_dp(&pdu_data,truni_ptr->dialogue,truni_ptr->dialogue_len,proto_type)) ||
			(!proto_type && (pdu_data.dialogue_type != PDU_AUDT)))
		{
			tcap_send_error("CSL error. Unidirectional primitive has error PDU type");
			return 0;
		}
		if ((proto_type && (pdu_data.pdu_union.asudt.version != 0) &&
			(pdu_data.pdu_union.asudt.version != Version_Ansi)) ||
			(!proto_type && (memcmp(pdu_data.pdu_union.aarq.version,Version_1,2) != 0)))
		{
			tcap_send_error("CSL error. Unidirectional primitive has error protocol version");
			return 0;
		}
		tcuni_ptr->dialogue_flag = 1;
		get_dlgpdu(&pdu_data,&tcuni_ptr->dlg_data);
	}
	if (truni_ptr->components_len > 0)
	{
		send_to_cha(proc,truni_ptr->components,truni_ptr->components_len);
		tcuni_ptr->component_present = 1;
	}
	else
		tcuni_ptr->component_present = 0;
	vm_ptr->proto_type = proto_type;
	int_ptr->dlgrecv_head = (ii + 1) % MAX_TSL_BUF;
	return 1;
}

u8 tcap_begin_request(u32 proc)
{
	struct	tcapvm_struct		*vm_ptr;
	struct	tcapint_struct		*int_ptr;
	struct	CSLdlg_struct		*csl_ptr;
	struct	TCBegin_struct		*tcbegin_ptr;
	struct	TSL_struct			tsl_data;
	struct	TRBegin_struct		*trbegin_ptr;
	struct	dlgPDU_struct		pdu_data;
	u8		data_flag;
	u8		cmp_level;
	u8		ii,proto_type,pabort_cause;
	u8		temp=0,sls;
	
	vm_ptr = (tcapvm_struct *) &tcap_ptr->tcapvm_data[proc];
	int_ptr = (tcapint_struct *) &tcap_ptr->tcapint_data[proc];
	data_flag = int_ptr->dlgsend_tail;
	tcap_dlg_t[proc] = int_ptr->dlgsend_tail;
	int_ptr->dlgsend_tail = (data_flag + 1) % MAX_TSL_BUF;
	tcap_dlg_t[proc] = int_ptr->dlgsend_tail;
	csl_ptr = (CSLdlg_struct *) &int_ptr->dlg_send[data_flag];
	tcbegin_ptr = (TCBegin_struct *) &csl_ptr->dlg_prim.tc_begin;
	memcpy(&vm_ptr->local_add,&tcbegin_ptr->local_add,sizeof(SCCP_ADDR));
	tsl_data.message_type = csl_ptr->message_type;
	tsl_data.message_flag = REQUEST;
	if ((csl_ptr->message_type & 0xE0) == ANSI_TAG_CLASS_CONS)
		proto_type = ANSI_TCAP;
	else
		proto_type = ITU_TCAP;
	memcpy(&tsl_data.local_add,&tcbegin_ptr->local_add,sizeof(SCCP_ADDR));
	memcpy(&tsl_data.peer_add,&tcbegin_ptr->peer_add,sizeof(SCCP_ADDR));
	trbegin_ptr = (TRBegin_struct *) &tsl_data.tsl_prim.tr_begin;
	trbegin_ptr->transaction_id = proc;
	trbegin_ptr->dialogue_len = trbegin_ptr->components_len = 0;
	if (tcbegin_ptr->dialogue_flag == 1)	// has dialogue portion
	{
		if (!proto_type)
		{
			vm_ptr->ac_mode = 1;	// set AC mode
			pdu_data.dialogue_type = PDU_AARQ;
			memcpy(pdu_data.pdu_union.aarq.version,Version_1,2);
		}
		else
		{
			vm_ptr->ac_mode = 0;
			pdu_data.dialogue_type = PDU_ASUDT;
			pdu_data.pdu_union.asudt.version = Version_Ansi;
		}
		set_dlgpdu(&pdu_data,&tcbegin_ptr->dlg_data);
		trbegin_ptr->dialogue_len = build_dp(trbegin_ptr->dialogue,&pdu_data,0,proto_type);
	}
	else
		cmp_level = 1;
	ii = tcbegin_ptr->component_present;
	if (ii != 0)
		trbegin_ptr->components_len = get_from_cha(trbegin_ptr->components,proc,&temp,ii,cmp_level);
	if (temp != 0)	// components is too long
	{
		tcap_send_error("CSL error. Component is too long");
		if (proto_type)
			pabort_cause = P_Abort_RL_Ansi;
		else
			pabort_cause = P_Abort_RL;
		send_pabort_tcu(proc,pabort_cause,int_ptr->dlgrecv_head,proto_type);
		debug_ptr->watch_dog[187] ++;
		return 0;
	}
	vm_ptr->proto_type = proto_type;
	debug_ptr->tc_utilize[TCAP_UTILIZE_COUNT-1][20]++;
	if (tcbegin_ptr->peer_add.ip != 0)	// has set the SLS by uplayer
	{
			sls = tcbegin_ptr->peer_add.ip % TCAP_SLS_NUM;
			debug_ptr->watch_dog[188] ++;
	}
	else
		sls = proc % TCAP_SLS_NUM;
	tcap_to_sccp(&tsl_data,sls,0);
	debug_ptr->watch_dog[189] ++;
	return 1;
}

u8 tcap_begin_indicate(u32 proc,u8 data_flag)
{
	struct	tcapvm_struct		*vm_ptr;
	struct	TSL_struct			*tsl_ptr;
	struct	TRBegin_struct		*trbegin_ptr;
	struct	tcapint_struct		*int_ptr;
	struct	CSLdlg_struct		*csl_ptr;
	struct	TCBegin_struct		*tcbegin_ptr;
	struct	dlgPDU_struct		pdu_data;
	u8		ii,proto_type;
	u8		acn_len=0;
	u8		acn[TCAP_ACN_LEN];
	
	vm_ptr = (tcapvm_struct *) &tcap_ptr->tcapvm_data[proc];
	tsl_ptr = (TSL_struct *) &vm_ptr->tsl_data[data_flag];
	trbegin_ptr = (TRBegin_struct *) &tsl_ptr->tsl_prim.tr_begin;
	memcpy(&vm_ptr->peer_add,&tsl_ptr->peer_add,sizeof(SCCP_ADDR));
	memcpy(&vm_ptr->local_add,&tsl_ptr->local_add,sizeof(SCCP_ADDR));
	vm_ptr->peer_tid = trbegin_ptr->transaction_id;
	int_ptr = (tcapint_struct *) &tcap_ptr->tcapint_data[proc];
	ii = int_ptr->dlgrecv_head;
	csl_ptr = (CSLdlg_struct *) &int_ptr->dlg_recv[ii];
	csl_ptr->message_type = tsl_ptr->message_type;
	csl_ptr->message_flag = INDICATE;
	csl_ptr->dialogue_id = proc;
	if ((tsl_ptr->message_type & 0xE0) == ANSI_TAG_CLASS_CONS)
		proto_type = ANSI_TCAP;
	else
		proto_type = ITU_TCAP;
	tcbegin_ptr = (TCBegin_struct *) &csl_ptr->dlg_prim.tc_begin;
	memcpy(&tcbegin_ptr->local_add,&vm_ptr->local_add,sizeof(SCCP_ADDR));
	memcpy(&tcbegin_ptr->peer_add,&vm_ptr->peer_add,sizeof(SCCP_ADDR));
	if (trbegin_ptr->dialogue_len != 0)	// has dialogue portion
	{
		if (!proto_type)
		{
			if (!extract_dp(&pdu_data,trbegin_ptr->dialogue,trbegin_ptr->dialogue_len,proto_type) || pdu_data.dialogue_type != PDU_AARQ)
			{
				tcap_send_error("CSL error. Begin primitive has error dialogue portion");
				pdu_data.dialogue_type = PDU_ABRT;	// build ABORT apdu
				pdu_data.pdu_union.abrt.abort_source = ABRTDlg_Service_Provider;
				pdu_data.pdu_union.abrt.user_info_len = 0;
				send_uabort_sccp(proc,&pdu_data,ITU_TCAP,0,NULL);
				return 0;
			}
			if (memcmp(pdu_data.pdu_union.aarq.version,Version_1,2) != 0)	// protocol is error
			{
				tcap_send_error("CSL error. Begin primitive has error protocol version");
				acn_len = pdu_data.pdu_union.aarq.acn_len;
				memcpy(acn,pdu_data.pdu_union.aarq.acn,acn_len);
				pdu_data.dialogue_type = PDU_AARE;
				pdu_data.pdu_union.aare.acn_len = acn_len;
				memcpy(pdu_data.pdu_union.aare.acn,acn,acn_len);
				pdu_data.pdu_union.aare.result = Reject_permanent;
				pdu_data.pdu_union.aare.diagnostic_flag = Dialogue_Service_Provider;
				pdu_data.pdu_union.aare.diagnostic_type = DSP_NCDP;
				pdu_data.pdu_union.aare.user_info_len = 0;
				send_uabort_sccp(proc,&pdu_data,ITU_TCAP,0,NULL);
				return 0;
			}
		}
		else
		{
			extract_dp(&pdu_data,trbegin_ptr->dialogue,trbegin_ptr->dialogue_len,proto_type);
			if ((pdu_data.pdu_union.asudt.version != 0) &&
				(pdu_data.pdu_union.asudt.version != Version_Ansi))
			{
				tcap_send_error("CSL error. Ansi Query has error protocol version");
				return 0;
			}
		}
		vm_ptr->ac_mode = 1;
		tcbegin_ptr->dialogue_flag = 1;
		get_dlgpdu(&pdu_data,&tcbegin_ptr->dlg_data);
	}
	else
	{
		tcbegin_ptr->dialogue_flag = 0;
		vm_ptr->ac_mode = 0;
	}
	if (trbegin_ptr->components_len != 0)	// has components
	{
		send_to_cha(proc,trbegin_ptr->components,trbegin_ptr->components_len);
		tcbegin_ptr->component_present = 1;
	}
	else
		tcbegin_ptr->component_present = 0;
	vm_ptr->proto_type = proto_type;
	int_ptr->dlgrecv_head = (ii + 1) % MAX_TSL_BUF;
	return 1;
}

void tcap_con_request(u32 proc)
{
	struct	tcapvm_struct		*vm_ptr;
	struct	tcapint_struct		*int_ptr;
	struct	CSLdlg_struct		*csl_ptr;
	struct	TCContinue_struct	*tccon_ptr;
	struct	TSL_struct			tsl_data;
	struct	TRContinue_struct	*trcon_ptr;
	struct	dlgPDU_struct		pdu_data;
	u8		ii,proto_type;
	u8		cmp_level;
	u8		temp=0;
	u8		data_flag,sls;
	
	vm_ptr = (tcapvm_struct *) &tcap_ptr->tcapvm_data[proc];
	int_ptr = (tcapint_struct *) &tcap_ptr->tcapint_data[proc];
	data_flag = int_ptr->dlgsend_tail;
	tcap_dlg_t[proc] = int_ptr->dlgsend_tail;
	csl_ptr = (CSLdlg_struct *) &int_ptr->dlg_send[data_flag];
	tccon_ptr = (TCContinue_struct *) &csl_ptr->dlg_prim.tc_continue;
	tsl_data.message_type = csl_ptr->message_type;
	tsl_data.message_flag = REQUEST;
	if ((csl_ptr->message_type & 0xE0) == ANSI_TAG_CLASS_CONS)
		proto_type = ANSI_TCAP;
	else
		proto_type = ITU_TCAP;
	memcpy(&tsl_data.local_add,&vm_ptr->local_add,sizeof(SCCP_ADDR));
	memcpy(&tsl_data.peer_add,&vm_ptr->peer_add,sizeof(SCCP_ADDR));
	trcon_ptr = (TRContinue_struct *) &tsl_data.tsl_prim.tr_continue;
	trcon_ptr->local_tid = proc;
	trcon_ptr->peer_tid = vm_ptr->peer_tid;
	trcon_ptr->dialogue_len = trcon_ptr->components_len = 0;
	if (tccon_ptr->dialogue_flag == 1)	// has dialogue portion
	{
		if (!proto_type)
		{
			pdu_data.dialogue_type = PDU_AARE;
			memcpy(pdu_data.pdu_union.aarq.version,Version_1,2);
			pdu_data.pdu_union.aare.result = Accepted;
			pdu_data.pdu_union.aare.diagnostic_flag = Dialogue_Service_User;
			pdu_data.pdu_union.aare.diagnostic_type = DSU_N;
		}
		else
		{
			pdu_data.dialogue_type = PDU_ASUDT;
			pdu_data.pdu_union.asudt.version = Version_Ansi;
		}
		set_dlgpdu(&pdu_data,&tccon_ptr->dlg_data);
		trcon_ptr->dialogue_len = build_dp(trcon_ptr->dialogue,&pdu_data,0,proto_type);
		cmp_level = 0;
	}
	else
		cmp_level = 1;
	ii = tccon_ptr->component_present;
	if (ii != 0)
		trcon_ptr->components_len = get_from_cha(trcon_ptr->components,proc,&temp,ii,cmp_level);
	if (temp != 0)	// components is too long
	{
		tccon_ptr->component_present -= temp;
		tccon_ptr->dialogue_flag = 0;
		tcap_send_error("CSL error. component is too long");
	}
	else
	{
		if (data_flag != tcap_dlg_t[proc])
		{
			data_flag = tcap_dlg_t[proc];
			debug_ptr->watch_dog[186] ++;
		}
		int_ptr->dlgsend_tail = (data_flag + 1) % MAX_TSL_BUF;
		tcap_dlg_t[proc] = int_ptr->dlgsend_tail;
	}
	sls = tcap_get_sls(vm_ptr->peer_tid);
	tsl_data.peer_tid_len = vm_ptr->peer_tid_len; //modified by Pierre, 06-08-19
	tcap_to_sccp_class(&tsl_data,sls,0,proc);
}

u8 tcap_con_indicate(u32 proc,u8 data_flag,u8 state_flag)
{
	struct	tcapvm_struct		*vm_ptr;
	struct	TSL_struct			*tsl_ptr;
	struct	TRContinue_struct	*trcon_ptr;
	struct	tcapint_struct		*int_ptr;
	struct	CSLdlg_struct		*csl_ptr;
	struct	TCContinue_struct	*tccon_ptr;
	struct	dlgPDU_struct		pdu_data;
	u8		ii,proto_type,pabort_cause;

	vm_ptr = (tcapvm_struct *) &tcap_ptr->tcapvm_data[proc];
	tsl_ptr = (TSL_struct *) &vm_ptr->tsl_data[data_flag];
	trcon_ptr = (TRContinue_struct *) &tsl_ptr->tsl_prim.tr_continue;
	if (state_flag == TCAP_IS)
	{
		memcpy(&vm_ptr->peer_add,&tsl_ptr->peer_add,sizeof(SCCP_ADDR));
		vm_ptr->peer_tid = trcon_ptr->peer_tid;
	}
	if ((tsl_ptr->message_type & 0xE0) == ANSI_TAG_CLASS_CONS)
		proto_type = ANSI_TCAP;
	else
		proto_type = ITU_TCAP;
	int_ptr = (tcapint_struct *) &tcap_ptr->tcapint_data[proc];
	ii = int_ptr->dlgrecv_head;
	if (((ii+1) %MAX_TSL_BUF) == int_ptr->dlgrecv_tail)	// buffer is full
	{
		tcap_send_error("TCAP error. TCAP to TCU buffer is full");
		if (proto_type)
			pabort_cause = P_Abort_RL_Ansi;
		else
			pabort_cause = P_Abort_RL;
		send_pabort_tcu(proc,pabort_cause,int_ptr->dlgrecv_tail,proto_type);
		send_pabort_sccp(vm_ptr->peer_tid_len, //modified by Pierre, 06-08-19
		                 vm_ptr->peer_tid,pabort_cause,&vm_ptr->local_add,&vm_ptr->peer_add,proto_type);
		return 0;
	}
	csl_ptr = (CSLdlg_struct *) &int_ptr->dlg_recv[ii];
	csl_ptr->message_type = tsl_ptr->message_type;
	csl_ptr->message_flag = INDICATE;
	csl_ptr->dialogue_id = proc;
	tccon_ptr = (TCContinue_struct *) &csl_ptr->dlg_prim.tc_continue;
	if (trcon_ptr->dialogue_len != 0)
	{
		if (!proto_type)
		{
			if (state_flag == TCAP_ACTIVE || vm_ptr->ac_mode == 0)
			{
				tcap_send_error("CSL error. Continue primitive has dialogue portion, but do not need it");
				pdu_data.dialogue_type = PDU_ABRT;
				pdu_data.pdu_union.abrt.abort_source = ABRTDlg_Service_Provider;
				pdu_data.pdu_union.abrt.user_info_len = 0;
				send_uabort_sccp(proc,&pdu_data,ITU_TCAP,0,NULL);
				send_pabort_tcu(proc,P_Abort_ADLG,ii,proto_type);
				return 0;
			}
			if (!extract_dp(&pdu_data,trcon_ptr->dialogue,trcon_ptr->dialogue_len,proto_type) || pdu_data.dialogue_type != PDU_AARE)
			{
				tcap_send_error("CSL error. Continue primitive has error dialogue portion");
				pdu_data.dialogue_type = PDU_ABRT;
				pdu_data.pdu_union.abrt.abort_source = ABRTDlg_Service_Provider;
				pdu_data.pdu_union.abrt.user_info_len = 0;
				send_uabort_sccp(proc,&pdu_data,ITU_TCAP,0,NULL);
				send_pabort_tcu(proc,P_Abort_ADLG,ii,proto_type);
				return 0;
			}
		}
		else
		{
			extract_dp(&pdu_data,trcon_ptr->dialogue,trcon_ptr->dialogue_len,proto_type);
			if ((pdu_data.pdu_union.asudt.version != 0) &&
				(pdu_data.pdu_union.asudt.version != Version_Ansi))
			{
				tcap_send_error("CSL error. Ansi Conversation has error protocol version");
				return 0;
			}
		}
		tccon_ptr->dialogue_flag = 1;
		get_dlgpdu(&pdu_data,&tccon_ptr->dlg_data);
		if (trcon_ptr->components_len != 0)
		{
			send_to_cha(proc,trcon_ptr->components,trcon_ptr->components_len);
			tccon_ptr->component_present = 1;
		}
		else
			tccon_ptr->component_present = 0;
		int_ptr->dlgrecv_head = (ii + 1) % MAX_TSL_BUF;
		return 1;
	}
	else
	{
		tccon_ptr->dialogue_flag = 0;
		if (!proto_type)
		{
			if (state_flag == TCAP_ACTIVE || vm_ptr->ac_mode == 0)
			{
				if (trcon_ptr->components_len != 0)
				{
					send_to_cha(proc,trcon_ptr->components,trcon_ptr->components_len);
					tccon_ptr->component_present = 1;
				}
				else
					tccon_ptr->component_present = 0;
				int_ptr->dlgrecv_head = (ii + 1) % MAX_TSL_BUF;
				return 1;
			}
			else
			{
				tcap_send_error("CSL error. Continue primitive has not dialogue portion, but need it");
				pdu_data.dialogue_type = PDU_ABRT;
				pdu_data.pdu_union.abrt.abort_source = ABRTDlg_Service_Provider;
				pdu_data.pdu_union.abrt.user_info_len = 0;
				send_uabort_sccp(proc,&pdu_data,ITU_TCAP,0,NULL);
				send_pabort_tcu(proc,P_Abort_ADLG,ii,proto_type);
				return 0;
			}
		}
		else
		{
			if (trcon_ptr->components_len != 0)
			{
				send_to_cha(proc,trcon_ptr->components,trcon_ptr->components_len);
				tccon_ptr->component_present = 1;
			}
			else
				tccon_ptr->component_present = 0;
			int_ptr->dlgrecv_head = (ii + 1) % MAX_TSL_BUF;
			return 1;
		}
	}
}

u8 tcap_end_request(u32 proc)
{
	struct	tcapvm_struct		*vm_ptr;
	struct	tcapint_struct		*int_ptr;
	struct	CSLdlg_struct		*csl_ptr;
	struct	TCEnd_struct		*tcend_ptr;
	struct	TSL_struct			tsl_data;
	struct	TSL_struct			temp_tsl;
	struct	TRContinue_struct	*trcon_ptr;
	struct	TREnd_struct		*trend_ptr;
	struct	dlgPDU_struct		pdu_data;
	u8		ii,proto_type;
	u8		cmp_level;
	u8		temp=0;
	u8		data_flag,sls;
	
	vm_ptr = (tcapvm_struct *) &tcap_ptr->tcapvm_data[proc];
	int_ptr = (tcapint_struct *) &tcap_ptr->tcapint_data[proc];
	data_flag = int_ptr->dlgsend_tail;
	tcap_dlg_t[proc] = int_ptr->dlgsend_tail;
	csl_ptr = (CSLdlg_struct *) &int_ptr->dlg_send[data_flag];
	tcend_ptr = (TCEnd_struct *) &csl_ptr->dlg_prim.tc_end;
	if (tcend_ptr->termination == PRE_END)
	{
		if (data_flag != tcap_dlg_t[proc])
		{
			data_flag = tcap_dlg_t[proc];
			debug_ptr->watch_dog[185] ++;
		}
		int_ptr->dlgsend_tail = (data_flag + 1) % MAX_TSL_BUF;
		tcap_dlg_t[proc] = int_ptr->dlgsend_tail;
		return 1;
	}
	tsl_data.message_type = csl_ptr->message_type;
	tsl_data.message_flag = REQUEST;
	if ((csl_ptr->message_type & 0xE0) == ANSI_TAG_CLASS_CONS)
		proto_type = ANSI_TCAP;
	else
		proto_type = ITU_TCAP;
	memcpy(&tsl_data.local_add,&vm_ptr->local_add,sizeof(SCCP_ADDR));
	memcpy(&tsl_data.peer_add,&vm_ptr->peer_add,sizeof(SCCP_ADDR));
	trend_ptr = (TREnd_struct *) &tsl_data.tsl_prim.tr_end;
	trend_ptr->transaction_id = vm_ptr->peer_tid;
	trend_ptr->dialogue_len = trend_ptr->components_len = 0;
	if (tcend_ptr->dialogue_flag == 1)	// has dialogue portion
	{
		if (!proto_type)
		{
			pdu_data.dialogue_type = PDU_AARE;
			memcpy(pdu_data.pdu_union.aarq.version,Version_1,2);
			pdu_data.pdu_union.aare.result = Accepted;
			pdu_data.pdu_union.aare.diagnostic_flag = Dialogue_Service_User;
			pdu_data.pdu_union.aare.diagnostic_type = DSU_N;
		}
		else
		{
			pdu_data.dialogue_type = PDU_ASUDT;
			pdu_data.pdu_union.asudt.version = Version_Ansi;
		}
		set_dlgpdu(&pdu_data,&tcend_ptr->dlg_data);
		trend_ptr->dialogue_len = build_dp(trend_ptr->dialogue,&pdu_data,0,proto_type);
		cmp_level = 0;
	}
	else
		cmp_level = 1;
	ii = tcend_ptr->component_present;
	if (ii != 0)
		trend_ptr->components_len = get_from_cha(trend_ptr->components,proc,&temp,ii,cmp_level);
	if (temp != 0)	// components is too long
	{
		tcap_send_error("CSL error. component is too long");
		if (!proto_type)
			temp_tsl.message_type = Continue;
		else
			temp_tsl.message_type = Conversation_WithPerm_Ansi;
		temp_tsl.message_flag = REQUEST;
		memcpy(&temp_tsl.local_add,&vm_ptr->local_add,sizeof(SCCP_ADDR));
		memcpy(&temp_tsl.peer_add,&vm_ptr->peer_add,sizeof(SCCP_ADDR));
		trcon_ptr = (TRContinue_struct *) &temp_tsl.tsl_prim.tr_continue;
		trcon_ptr->local_tid = proc;
		trcon_ptr->peer_tid = vm_ptr->peer_tid;
		trcon_ptr->dialogue_len = trend_ptr->dialogue_len;
		memcpy(trcon_ptr->dialogue,trend_ptr->dialogue,trend_ptr->dialogue_len);
		trcon_ptr->components_len = trend_ptr->components_len;
		memcpy(trcon_ptr->components,trend_ptr->components,trend_ptr->components_len);
		tcend_ptr->dialogue_flag = 0;
		tcend_ptr->component_present -= temp;
		sls = tcap_get_sls(vm_ptr->peer_tid);
		tsl_data.peer_tid_len = vm_ptr->peer_tid_len;
		tcap_to_sccp_class(&temp_tsl,sls,0,proc);
		return 0;
	}
	else
	{
		sls = tcap_get_sls(vm_ptr->peer_tid);
		tsl_data.peer_tid_len = vm_ptr->peer_tid_len;
		tcap_to_sccp_class(&tsl_data,sls,0,proc);
		if (data_flag != tcap_dlg_t[proc])
		{
			data_flag = tcap_dlg_t[proc];
			debug_ptr->watch_dog[184] ++;
		}
		int_ptr->dlgsend_tail = (data_flag + 1) % MAX_TSL_BUF;
		tcap_dlg_t[proc] = int_ptr->dlgsend_tail;
		return 1;
	}
}

void tcap_end_indicate(u32 proc,u8 data_flag,u8 state_flag)
{
	struct	tcapvm_struct		*vm_ptr;
	struct	TSL_struct			*tsl_ptr;
	struct	TREnd_struct		*trend_ptr;
	struct	tcapint_struct		*int_ptr;
	struct	CSLdlg_struct		*csl_ptr;
	struct	TCEnd_struct		*tcend_ptr;
	struct	dlgPDU_struct		pdu_data;
	u8		ii,proto_type,pabort_cause;

	vm_ptr = (tcapvm_struct *) &tcap_ptr->tcapvm_data[proc];
	tsl_ptr = (TSL_struct *) &vm_ptr->tsl_data[data_flag];
	trend_ptr = (TREnd_struct *) &tsl_ptr->tsl_prim.tr_end;
	int_ptr = (tcapint_struct *) &tcap_ptr->tcapint_data[proc];
	if ((tsl_ptr->message_type & 0xE0) == ANSI_TAG_CLASS_CONS)
		proto_type = ANSI_TCAP;
	else
		proto_type = ITU_TCAP;
	ii = int_ptr->dlgrecv_head;
	if (((ii+1) % MAX_TSL_BUF) == int_ptr->dlgrecv_tail)	// buffer is full
	{
		tcap_send_error("TCAP error. TCAP to TCU buffer is full");
		if (proto_type)
			pabort_cause = P_Abort_RL_Ansi;
		else
			pabort_cause = P_Abort_RL;
		send_pabort_tcu(proc,pabort_cause,int_ptr->dlgrecv_tail,proto_type);
		return;
	}
	csl_ptr = (CSLdlg_struct *) &int_ptr->dlg_recv[ii];
	csl_ptr->message_type = tsl_ptr->message_type;
	csl_ptr->message_flag = INDICATE;
	csl_ptr->dialogue_id = proc;
	tcend_ptr = (TCEnd_struct *) &csl_ptr->dlg_prim.tc_end;
	if (trend_ptr->dialogue_len != 0)
	{
		if (!proto_type)
		{
			if (vm_ptr->ac_mode == 0)
			{
				tcap_send_error("CSL error. End primitive has dialogue portion, but do not need it");
				send_pabort_tcu(proc,P_Abort_ADLG,ii,proto_type);
				return;
			}
			if (!extract_dp(&pdu_data,trend_ptr->dialogue,trend_ptr->dialogue_len,proto_type) || pdu_data.dialogue_type != PDU_AARE)
			{
				tcap_send_error("CSL error. End primitive has error dialogue portion");
				send_pabort_tcu(proc,P_Abort_ADLG,ii,proto_type);
				return;
			}
		}
		else
		{
			extract_dp(&pdu_data,trend_ptr->dialogue,trend_ptr->dialogue_len,proto_type);
			if ((pdu_data.pdu_union.asudt.version != 0) &&
				(pdu_data.pdu_union.asudt.version != Version_Ansi))
			{
				tcap_send_error("CSL error. Ansi Response has error protocol version");
				return;
			}
		}
		tcend_ptr->dialogue_flag = 1;
		get_dlgpdu(&pdu_data,&tcend_ptr->dlg_data);
		if (trend_ptr->components_len != 0)
		{
			send_to_cha(proc,trend_ptr->components,trend_ptr->components_len);
			tcend_ptr->component_present = 1;
		}
		else
			tcend_ptr->component_present = 0;
		int_ptr->dlgrecv_head = (ii + 1) % MAX_TSL_BUF;
		return;
	}
	else
	{
		tcend_ptr->dialogue_flag = 0;
		if (!proto_type)
		{
			if (state_flag == TCAP_ACTIVE || vm_ptr->ac_mode == 0)
			{
				if (trend_ptr->components_len != 0)
				{
					send_to_cha(proc,trend_ptr->components,trend_ptr->components_len);
					tcend_ptr->component_present = 1;
				}
				else
					tcend_ptr->component_present = 0;
				int_ptr->dlgrecv_head = (ii + 1) % MAX_TSL_BUF;
				return;
			}
			else
			{
				tcap_send_error("CSL error. End primitive has not dialogue portion, but need it");
				send_pabort_tcu(proc,P_Abort_ADLG,ii,proto_type);
				return;
			}
		}
		else
		{
			if (trend_ptr->components_len != 0)
			{
				send_to_cha(proc,trend_ptr->components,trend_ptr->components_len);
				tcend_ptr->component_present = 1;
			}
			else
				tcend_ptr->component_present = 0;
			int_ptr->dlgrecv_head = (ii + 1) % MAX_TSL_BUF;
			return;
		}
	}
}

void tcap_uabort_request(u32 proc)
{
	struct	tcapvm_struct		*vm_ptr;
	struct	tcapint_struct		*int_ptr;
	struct	CSLdlg_struct		*csl_ptr;
	struct	TCUAbort_struct		*tcuabort_ptr;
	struct	dlgPDU_struct		pdu_data;
	u8		data_flag;
	u8		proto_type;

	vm_ptr = (tcapvm_struct *) &tcap_ptr->tcapvm_data[proc];
	int_ptr = (tcapint_struct *) &tcap_ptr->tcapint_data[proc];
	data_flag = int_ptr->dlgsend_tail;
	tcap_dlg_t[proc] = int_ptr->dlgsend_tail;
	int_ptr->dlgsend_tail = (data_flag + 1) % MAX_TSL_BUF;
	tcap_dlg_t[proc] = int_ptr->dlgsend_tail;
	csl_ptr = (CSLdlg_struct *) &int_ptr->dlg_send[data_flag];
	tcuabort_ptr = (TCUAbort_struct *) &csl_ptr->dlg_prim.tc_uabort;
	if ((csl_ptr->message_type & 0xE0) == ANSI_TAG_CLASS_CONS)
		proto_type = ANSI_TCAP;
	else
		proto_type = ITU_TCAP;
	if (!proto_type)
	{
		if (vm_ptr->ac_mode == 1)
		{
			if (tcuabort_ptr->uabort_reason == UABORT_ACNNS)
			{
				pdu_data.dialogue_type = PDU_AARE;
				memcpy(pdu_data.pdu_union.aare.version,Version_1,2);
				set_dlgpdu(&pdu_data,&tcuabort_ptr->dlg_data);
				pdu_data.pdu_union.aare.result = Reject_permanent;
				pdu_data.pdu_union.aare.diagnostic_flag = Dialogue_Service_User;
				pdu_data.pdu_union.aare.diagnostic_type = DSU_ACNNS;
				send_uabort_sccp(proc,&pdu_data,ITU_TCAP,0,NULL);
			}
			else if (tcuabort_ptr->dlg_data.user_info_len != 0)
			{
				pdu_data.dialogue_type = PDU_ABRT;
				pdu_data.pdu_union.abrt.abort_source = ABRTDlg_Service_User;
				set_dlgpdu(&pdu_data,&tcuabort_ptr->dlg_data);
				send_uabort_sccp(proc,&pdu_data,ITU_TCAP,0,NULL);
			}
			else
				send_pabort_sccp(vm_ptr->peer_tid_len,
				                 vm_ptr->peer_tid,P_Abort_NCDP,&vm_ptr->local_add,&vm_ptr->peer_add,proto_type);
		}
		else
			send_pabort_sccp(vm_ptr->peer_tid_len,
			                 vm_ptr->peer_tid,P_Abort_NCDP,&vm_ptr->local_add,&vm_ptr->peer_add,proto_type);
	}
	else
	{
		pdu_data.dialogue_type = PDU_ASUDT;
		pdu_data.pdu_union.asudt.version = Version_Ansi;
		set_dlgpdu(&pdu_data,&tcuabort_ptr->dlg_data);
		send_uabort_sccp(proc,&pdu_data,proto_type,tcuabort_ptr->uabort_info_len,tcuabort_ptr->uabort_info);
	}
}

void tcap_uabort_indicate(u32 proc,u8 data_flag)
{
	struct	tcapvm_struct		*vm_ptr;
	struct	TSL_struct			*tsl_ptr;
	struct	TRUAbort_struct		*truabort_ptr;
	struct	tcapint_struct		*int_ptr;
	struct	CSLdlg_struct		*csl_ptr;
	struct	TCUAbort_struct		*tcuabort_ptr;
	struct	dlgPDU_struct		pdu_data;
	u8		ii,proto_type,pabort_cause;

	vm_ptr = (tcapvm_struct *) &tcap_ptr->tcapvm_data[proc];
	tsl_ptr = (TSL_struct *) &vm_ptr->tsl_data[data_flag];
	truabort_ptr = (TRUAbort_struct *) &tsl_ptr->tsl_prim.tr_uabort;
	int_ptr = (tcapint_struct *) &tcap_ptr->tcapint_data[proc];
	if ((tsl_ptr->message_type & 0xE0) == ANSI_TAG_CLASS_CONS)
		proto_type = ANSI_TCAP;
	else
		proto_type = ITU_TCAP;
	ii = int_ptr->dlgrecv_head;
	if (((ii+1) %MAX_TSL_BUF) == int_ptr->dlgrecv_tail)	// buffer is full
	{
		tcap_send_error("TCAP error. TCAP to TCU buffer is full");
		if (proto_type)
			pabort_cause = P_Abort_RL_Ansi;
		else
			pabort_cause = P_Abort_RL;
		send_pabort_tcu(proc,pabort_cause,int_ptr->dlgrecv_tail,proto_type);
		return;
	}
	csl_ptr = (CSLdlg_struct *) &int_ptr->dlg_recv[ii];
	csl_ptr->message_type = tsl_ptr->message_type;
	csl_ptr->message_flag = INDICATE;
	csl_ptr->dialogue_id = proc;
	tcuabort_ptr = (TCUAbort_struct *) &csl_ptr->dlg_prim.tc_uabort;
	if (truabort_ptr->dialogue_len != 0)
	{
		if (!proto_type)
		{
			if (vm_ptr->ac_mode == 0)
			{
				tcap_send_error("CSL error. U_Abort primitive has dialogue portion, but do not need it");
				send_pabort_tcu(proc,P_Abort_ADLG,ii,proto_type);
				return;
			}
			if (!extract_dp(&pdu_data,truabort_ptr->dialogue,truabort_ptr->dialogue_len,proto_type))
			{
				tcap_send_error("CSL error. U_Abort primitive has error dialogue portion");
				send_pabort_tcu(proc,P_Abort_ADLG,ii,proto_type);
				return;
			}
		}
		else
		{
			extract_dp(&pdu_data,truabort_ptr->dialogue,truabort_ptr->dialogue_len,proto_type);
			if ((pdu_data.pdu_union.asudt.version != 0) &&
				(pdu_data.pdu_union.asudt.version != Version_Ansi))
			{
				tcap_send_error("CSL error. Ansi Uabort has error protocol version");
				return;
			}
		}
		tcuabort_ptr->dialogue_flag = 1;
		get_dlgpdu(&pdu_data,&tcuabort_ptr->dlg_data);
		if (!proto_type)
		{
			if (pdu_data.dialogue_type == PDU_AARE)
				tcuabort_ptr->uabort_reason = UABORT_ACNNS;
			else if (pdu_data.dialogue_type == PDU_ABRT)
			{
				if (pdu_data.pdu_union.abrt.abort_source == ABRTDlg_Service_User)
					tcuabort_ptr->uabort_reason = UABORT_NULL;
				else
				{
					send_pabort_tcu(proc,P_Abort_ADLG,ii,proto_type);
					return;
				}
			}
			else
			{
				tcap_send_error("CSL error. U_Abort primitive has error dialogue portion");
				send_pabort_tcu(proc,P_Abort_ADLG,ii,proto_type);
				return;
			}
		}
	}
	else
	{
		if (!proto_type)
		{
			if (vm_ptr->ac_mode == 1)
			{
				tcap_send_error("CSL error. U_Abort primitive has not dialogue portion, but need it");
				send_pabort_tcu(proc,P_Abort_ADLG,ii,proto_type);
				return;
			}
			tcuabort_ptr->uabort_reason = UABORT_SPEC;
		}
		tcuabort_ptr->dialogue_flag = 0;
	}
	if (proto_type)
	{
		tcuabort_ptr->uabort_info_len = truabort_ptr->uabort_info_len;
		memcpy(tcuabort_ptr->uabort_info, truabort_ptr->uabort_info, truabort_ptr->uabort_info_len);
	}
	int_ptr->dlgrecv_head = (ii + 1) % MAX_TSL_BUF;
}

void tcap_pabort_indicate(u32 proc,u8 data_flag)
{
	struct	tcapvm_struct		*vm_ptr;
	struct	TSL_struct			*tsl_ptr;
	struct	TRPAbort_struct		*trpabort_ptr;
	struct	tcapint_struct		*int_ptr;
	struct	CSLdlg_struct		*csl_ptr;
	struct	TCPAbort_struct		*tcpabort_ptr;
	u8		ii,proto_type,pabort_cause;

	vm_ptr = (tcapvm_struct *) &tcap_ptr->tcapvm_data[proc];
	tsl_ptr = (TSL_struct *) &vm_ptr->tsl_data[data_flag];
	trpabort_ptr = (TRPAbort_struct *) &tsl_ptr->tsl_prim.tr_pabort;
	int_ptr = (tcapint_struct *) &tcap_ptr->tcapint_data[proc];
	if ((tsl_ptr->message_type & 0xE0) == ANSI_TAG_CLASS_CONS)
		proto_type = ANSI_TCAP;
	else
		proto_type = ITU_TCAP;
	ii = int_ptr->dlgrecv_head;
	if (((ii+1) %MAX_TSL_BUF) == int_ptr->dlgrecv_tail)	// buffer is full
	{
		tcap_send_error("TCAP error. TCAP to TCU buffer is full");
		if (proto_type)
			pabort_cause = P_Abort_RL_Ansi;
		else
			pabort_cause = P_Abort_RL;
		send_pabort_tcu(proc,pabort_cause,int_ptr->dlgrecv_tail,proto_type);
	}
	else
	{
		csl_ptr = (CSLdlg_struct *) &int_ptr->dlg_recv[ii];
		csl_ptr->message_type = tsl_ptr->message_type;
		csl_ptr->message_flag = INDICATE;
		csl_ptr->dialogue_id = proc;
		tcpabort_ptr = (TCPAbort_struct *) &csl_ptr->dlg_prim.tc_pabort;
		tcpabort_ptr->pabort_reason = trpabort_ptr->abort_reason;
		int_ptr->dlgrecv_head = (ii + 1) % MAX_TSL_BUF;
	}
}

void tcap_notice_indicate(u32 proc,u8 data_flag,u8 proto_type)
{
	struct	tcapvm_struct		*vm_ptr;
	struct	TSL_struct			*tsl_ptr;
	struct	TRNotice_struct		*trnotice_ptr;
	struct	tcapint_struct		*int_ptr;
	struct	CSLdlg_struct		*csl_ptr;
	struct	TCNotice_struct		*tcnotice_ptr;
	u8		ii,pabort_reason;

	vm_ptr = (tcapvm_struct *) &tcap_ptr->tcapvm_data[proc];
	tsl_ptr = (TSL_struct *) &vm_ptr->tsl_data[data_flag];
	trnotice_ptr = (TRNotice_struct *) &tsl_ptr->tsl_prim.tr_notice;
	int_ptr = (tcapint_struct *) &tcap_ptr->tcapint_data[proc];
	ii = int_ptr->dlgrecv_head;
	if (((ii+1) %MAX_TSL_BUF) == int_ptr->dlgrecv_tail)	// buffer is full
	{
		tcap_send_error("TCAP error. TCAP to TCU buffer is full");
		if (!proto_type)
			pabort_reason = P_Abort_RL;
		else
			pabort_reason = P_Abort_RL_Ansi;
		send_pabort_tcu(proc,pabort_reason,int_ptr->dlgrecv_tail,proto_type);
	}
	else
	{
		csl_ptr = (CSLdlg_struct *) &int_ptr->dlg_recv[ii];
		csl_ptr->message_type = Notice;
		csl_ptr->message_flag = INDICATE;
		csl_ptr->dialogue_id = proc;
		tcnotice_ptr = (TCNotice_struct *) &csl_ptr->dlg_prim.tc_notice;
		tcnotice_ptr->report_reason = trnotice_ptr->report_cause;
		int_ptr->dlgrecv_head = (ii + 1) % MAX_TSL_BUF;
	}
}

void tsm_program(u32 proc)
{
	struct	tcapvm_struct		*vm_ptr;
	struct	TSL_struct			*tsl_ptr;
	struct	tcapint_struct		*int_ptr;
	struct	CSLdlg_struct		*csl_ptr;
	u8		ii,pabort_cause,proto_type;
	u8		info[128];
	//char 	info_str[1024];
	
	vm_ptr = (tcapvm_struct *) &tcap_ptr->tcapvm_data[proc];
	int_ptr = (tcapint_struct *) &tcap_ptr->tcapint_data[proc];
	proto_type = vm_ptr->proto_type;
	
	switch (vm_ptr->tcap_state)
	{
		case TCAP_INIT:
			tcap_clear_fsm(proc);
			free_did(proc);
			debug_ptr->watch_dog[217] ++;
			vm_ptr->tcap_state = TCAP_IDLE;
			break;
		case TCAP_IDLE:
			if (vm_ptr->tcaprecv_head != vm_ptr->tcaprecv_tail)
			{
				ii = vm_ptr->tcaprecv_tail;
				tsl_ptr = (TSL_struct *) &vm_ptr->tsl_data[ii];
				vm_ptr->tcaprecv_tail = (ii + 1) % MAX_TSL_BUF;
				switch (tsl_ptr->message_type)
				{
					case Begin:
					case Query_WithPerm_Ansi:
					case Query_WithoutPerm_Ansi:
						if (tcap_begin_indicate(proc,ii))
							vm_ptr->tcap_state = TCAP_IR;
						else
						{
							debug_ptr->watch_dog[212] ++;
							vm_ptr->tcap_state = TCAP_SUSPEND;
						}
						vm_ptr->tcap_timer = 0;
						break;
					case Unidirectional:
					case Unidirectional_Ansi:
						if (tcap_uni_indicate(proc,ii))
						{
							debug_ptr->watch_dog[211] ++;
							vm_ptr->tcap_state = TCAP_SUSPEND;
						}
						else
						{
							debug_ptr->watch_dog[210] ++;
							vm_ptr->tcap_state = TCAP_SUSPEND;
						}
						vm_ptr->tcap_timer = 0;
						break;
					default:
						sprintf((char *)info, "TSL error. Improper message Received from lower layer in idle state, did: %u, type: %d", proc, tsl_ptr->message_type);
						tcap_send_error((char *)info);
						//printf("TSL error. Improper message Received from lower layer in idle state, did: %ld, type: %d", proc, tsl_ptr->message_type);
						debug_ptr->watch_dog[225]++;
						debug_ptr->watch_dog[73] ++;
						vm_ptr->tcap_timer = 0;
						vm_ptr->tcap_state = TCAP_SUSPEND;
						break;
				}
			}
			else
			{
				if (int_ptr->dlgsend_head != int_ptr->dlgsend_tail)
				{
					ii = int_ptr->dlgsend_tail;
					csl_ptr = (CSLdlg_struct *) &int_ptr->dlg_send[ii];
					switch (csl_ptr->message_type)
					{
						case Begin:
						case Query_WithPerm_Ansi:
						case Query_WithoutPerm_Ansi:
							debug_ptr->watch_dog[71] ++;
							if (tcap_begin_request(proc))
								vm_ptr->tcap_state = TCAP_IS;
							else
							{
								debug_ptr->watch_dog[209] ++;
								vm_ptr->tcap_state = TCAP_SUSPEND;
							}
							vm_ptr->tcap_timer = 0;
							break;
						case Unidirectional:
						case Unidirectional_Ansi:
							tcap_uni_request(proc,ii);
							vm_ptr->tcap_timer = 0;
							debug_ptr->watch_dog[208] ++;
							vm_ptr->tcap_state = TCAP_SUSPEND;
							break;
						default:
							sprintf((char *)info, "TSL error. Improper message Received from tc user in idle state, did: %u, type: %d", proc, csl_ptr->message_type);
							tcap_send_error((char *)info);
							//printf("TSL error. Improper message Received from tc user in idle state, did: %ld, type: %d\n", proc, csl_ptr->message_type);
							debug_ptr->watch_dog[224]++;
							debug_ptr->watch_dog[73] ++;
							vm_ptr->tcap_timer = 0;
							vm_ptr->tcap_state = TCAP_SUSPEND;
							break;
					}
				}
			}
			if (check_did(proc))
			{
				if ((vm_ptr->tcap_timer++) >= IDLE_TIMER*TCAP_TIMERHZ)
				{
					vm_ptr->tcap_timer = 0;
					debug_ptr->watch_dog[216] ++;
					vm_ptr->tcap_state = TCAP_INIT;
				}
			}
			break;
		case TCAP_IR:
			if (int_ptr->dlgsend_head != int_ptr->dlgsend_tail)
			{
				ii = int_ptr->dlgsend_tail;
				csl_ptr = (CSLdlg_struct *) &int_ptr->dlg_send[ii];
				switch (csl_ptr->message_type)
				{
					case Continue:
					case Conversation_WithPerm_Ansi:
					case Conversation_WithoutPerm_Ansi:
						debug_ptr->watch_dog[74] ++;
						tcap_con_request(proc);
						vm_ptr->tcap_timer = 0;
						vm_ptr->tcap_state = TCAP_ACTIVE;
						break;
					case End:
					case Response_Ansi:
						debug_ptr->watch_dog[75] ++;
						vm_ptr->tcap_timer = 0;
						if (tcap_end_request(proc))
						{
							debug_ptr->watch_dog[207] ++;
							vm_ptr->tcap_state = TCAP_SUSPEND;
						}
						else
							vm_ptr->tcap_state = TCAP_ACTIVE;
						break;
					case U_Abort:
					case U_Abort_Ansi:
						debug_ptr->watch_dog[78] ++;
						tcap_uabort_request(proc);
						vm_ptr->tcap_timer = 0;
						vm_ptr->tcap_state = TCAP_SUSPEND;
						break;
					default:
						break;
				}
			}
			if ((vm_ptr->tcap_timer++) >= (xap_get_est_timer()+60)*TCAP_TIMERHZ)
			{
				sprintf((char *)info, "TSL error. timer expired in TCAP_IR state, did: %u", proc);
				tcap_send_error((char *)info);
				if (proto_type)
					pabort_cause = P_Abort_RL_Ansi;
				else
					pabort_cause = P_Abort_RL;
				send_pabort_sccp(vm_ptr->peer_tid_len,
				                 vm_ptr->peer_tid,pabort_cause,&vm_ptr->local_add,&vm_ptr->peer_add,proto_type);
				send_pabort_tcu(proc,pabort_cause,int_ptr->dlgrecv_head,proto_type);
				vm_ptr->tcap_timer = 0;
				debug_ptr->watch_dog[206] ++;
				vm_ptr->tcap_state = TCAP_SUSPEND;
			}
			break;
		case TCAP_IS:
			if (vm_ptr->tcaprecv_head != vm_ptr->tcaprecv_tail)
			{
				ii = vm_ptr->tcaprecv_tail;
				tsl_ptr = (TSL_struct *) &vm_ptr->tsl_data[ii];
				vm_ptr->tcaprecv_tail = (ii + 1) % MAX_TSL_BUF;
				switch (tsl_ptr->message_type)
				{
					case Continue:
					case Conversation_WithPerm_Ansi:
					case Conversation_WithoutPerm_Ansi:
						debug_ptr->watch_dog[80] ++;
						vm_ptr->tcap_timer = 0;
						if (tcap_con_indicate(proc,ii,TCAP_IS))
							vm_ptr->tcap_state = TCAP_ACTIVE;
						else
						{
							debug_ptr->watch_dog[205] ++;
							vm_ptr->tcap_state = TCAP_SUSPEND;
						}
						break;
					case End:
					case Response_Ansi:
						debug_ptr->watch_dog[81] ++;
						tcap_end_indicate(proc,ii,TCAP_IS);
						vm_ptr->tcap_timer = 0;
						vm_ptr->tcap_state = TCAP_SUSPEND;
						break;
					case U_Abort:
					case U_Abort_Ansi:
						debug_ptr->watch_dog[82] ++;
						tcap_uabort_indicate(proc,ii);
						vm_ptr->tcap_timer = 0;
						vm_ptr->tcap_state = TCAP_SUSPEND;
						break;
					case P_Abort:
					case P_Abort_Ansi:
						debug_ptr->watch_dog[83] ++;
						tcap_pabort_indicate(proc,ii);
						vm_ptr->tcap_timer = 0;
						vm_ptr->tcap_state = TCAP_SUSPEND;
						break;
					case Notice:
						tcap_notice_indicate(proc,ii,proto_type);
						vm_ptr->tcap_timer = 0;
						vm_ptr->tcap_state = TCAP_SUSPEND;
						debug_ptr->watch_dog[204] ++;
						break;
					default:
						break;
				}
			}
			else
			{
				if (int_ptr->dlgsend_head != int_ptr->dlgsend_tail)
				{
					ii = int_ptr->dlgsend_tail;
					csl_ptr = (CSLdlg_struct *) &int_ptr->dlg_send[ii];
					switch (csl_ptr->message_type)
					{
						case End:
						case Response_Ansi:
							debug_ptr->watch_dog[75] ++;
							vm_ptr->tcap_timer = 0;
							if (tcap_end_request(proc))
							{
								debug_ptr->watch_dog[203] ++;
								vm_ptr->tcap_state = TCAP_SUSPEND;
							}
							else
								vm_ptr->tcap_state = TCAP_ACTIVE;
							break;
						case U_Abort:
						case U_Abort_Ansi:
							tcap_uabort_request(proc);
							vm_ptr->tcap_timer = 0;
							vm_ptr->tcap_state = TCAP_SUSPEND;
							debug_ptr->watch_dog[202] ++;
							break;
						default:
							break;
					}
				}
			}
			if ((vm_ptr->tcap_timer++) >= (xap_get_est_timer()+60)*TCAP_TIMERHZ)
			{
				sprintf((char *)info, "TSL error. timer expired in TCAP_IS state, did: %u", proc);
				tcap_send_error((char *)info);
				if (proto_type)
					pabort_cause = P_Abort_RL_Ansi;
				else
					pabort_cause = P_Abort_RL;
//				send_pabort_sccp(vm_ptr->peer_tid_len,vm_ptr->peer_tid,pabort_cause,&vm_ptr->local_add,&vm_ptr->peer_add,proto_type);
				send_pabort_tcu(proc,pabort_cause,int_ptr->dlgrecv_head,proto_type);
				vm_ptr->tcap_timer = 0;
				vm_ptr->tcap_state = TCAP_SUSPEND;
				debug_ptr->watch_dog[201] ++;
			}
			break;
		case TCAP_ACTIVE:
			if (vm_ptr->tcaprecv_head != vm_ptr->tcaprecv_tail)
			{
				ii = vm_ptr->tcaprecv_tail;
				tsl_ptr = (TSL_struct *) &vm_ptr->tsl_data[ii];
				vm_ptr->tcaprecv_tail = (ii + 1) % MAX_TSL_BUF;
				switch (tsl_ptr->message_type)
				{
					case Continue:
					case Conversation_WithPerm_Ansi:
					case Conversation_WithoutPerm_Ansi:
						debug_ptr->watch_dog[84] ++;
						if (!tcap_con_indicate(proc,ii,TCAP_ACTIVE))
						{
							debug_ptr->watch_dog[200] ++;
							vm_ptr->tcap_state = TCAP_SUSPEND;
						}
						vm_ptr->tcap_timer = 0;
						break;
					case End:
					case Response_Ansi:
						debug_ptr->watch_dog[86] ++;
						tcap_end_indicate(proc,ii,TCAP_ACTIVE);
						vm_ptr->tcap_state = TCAP_SUSPEND;
						vm_ptr->tcap_timer = 0;
						break;
					case U_Abort:
					case U_Abort_Ansi:
						debug_ptr->watch_dog[88] ++;
						tcap_uabort_indicate(proc,ii);
						vm_ptr->tcap_state = TCAP_SUSPEND;
						vm_ptr->tcap_timer = 0;
						break;
					case P_Abort:
					case P_Abort_Ansi:
						debug_ptr->watch_dog[90] ++;
						tcap_pabort_indicate(proc,ii);
						vm_ptr->tcap_state = TCAP_SUSPEND;
						vm_ptr->tcap_timer = 0;
						break;
					case Notice:
						tcap_notice_indicate(proc,ii,proto_type);
						vm_ptr->tcap_state = TCAP_SUSPEND;
						vm_ptr->tcap_timer = 0;
						debug_ptr->watch_dog[199] ++;
						break;
					default:
						break;
				}
			}
			else
			{
				if (int_ptr->dlgsend_head != int_ptr->dlgsend_tail)
				{
					ii = int_ptr->dlgsend_tail;
					csl_ptr = (CSLdlg_struct *) &int_ptr->dlg_send[ii];
					switch (csl_ptr->message_type)
					{
						case Continue:
						case Conversation_WithPerm_Ansi:
						case Conversation_WithoutPerm_Ansi:
							debug_ptr->watch_dog[85] ++;
							vm_ptr->tcap_timer = 0;
							tcap_con_request(proc);
							break;
						case End:
						case Response_Ansi:
							debug_ptr->watch_dog[87] ++;
							vm_ptr->tcap_timer = 0;
							if (tcap_end_request(proc))
							{
								debug_ptr->watch_dog[198] ++;
								vm_ptr->tcap_state = TCAP_SUSPEND;
							}
							break;
						case U_Abort:
						case U_Abort_Ansi:
							debug_ptr->watch_dog[89] ++;
							tcap_uabort_request(proc);
							vm_ptr->tcap_timer = 0;
							vm_ptr->tcap_state = TCAP_SUSPEND;
							break;
						default:
							break;
					}
				}
			}
			if ((vm_ptr->tcap_timer++) >= (xap_get_est_timer()+60)*TCAP_TIMERHZ)
			{
				sprintf((char *)info, "TSL error. timer expired in TCAP_ACTIVE state, did: %u", proc);
				tcap_send_error((char *)info);
				if (proto_type)
					pabort_cause = P_Abort_RL_Ansi;
				else
					pabort_cause = P_Abort_RL;
				send_pabort_sccp(vm_ptr->peer_tid_len,
				                 vm_ptr->peer_tid,pabort_cause,&vm_ptr->local_add,&vm_ptr->peer_add,proto_type);
				send_pabort_tcu(proc,pabort_cause,int_ptr->dlgrecv_head,proto_type);
				vm_ptr->tcap_timer = 0;
				vm_ptr->tcap_state = TCAP_SUSPEND;
				debug_ptr->watch_dog[197] ++;
			}
			break;
		case TCAP_SUSPEND:
			if (check_csldata(proc))
				vm_ptr->tcap_state = TCAP_INIT;
			else if ((vm_ptr->tcap_timer++) >= SUSPEND_TIMER*TCAP_TIMERHZ)

				vm_ptr->tcap_state = TCAP_INIT;

			/*
			if ((vm_ptr->tcap_timer++) >= 10 )
			{
				if (!check_csldata(proc))
				{
					sprintf(info_str, "TCAP_SUSPEND error. did: %ld", proc);
					tcap_send_error(info_str);
				}
				vm_ptr->tcap_state = TCAP_INIT;
				debug_ptr->watch_dog[215] ++;
			}*/
			break;
		default:
			vm_ptr->tcap_state = TCAP_INIT;
			debug_ptr->watch_dog[214] ++;
			break;
	}
}

void ism_program(u32 proc)	// invocation state machine
{
	register u8		inv_proc,total_iid;
	struct	tcapvm_struct	*vm_ptr;
	struct	ismvm_data		*shm_ptr;
	char	info_str[1024];
	u8		proto_type,problem_type,problem_code;

	vm_ptr = (tcapvm_struct *) &tcap_ptr->tcapvm_data[proc];
    /*
    total_iid = (vm_ptr->total_iid+1) ;
    if(total_iid> MAX_TEMPINVOKEID)
    */
        total_iid = MAX_TEMPINVOKEID ;

	proto_type = vm_ptr->proto_type;
	for (inv_proc = 0;inv_proc < total_iid;inv_proc++)
	{
		shm_ptr = (ismvm_data *) &vm_ptr->ism_data[inv_proc];
		switch (shm_ptr->ism_state)
		{
			case TCAP_INIT:
                free_iid(proc,shm_ptr->linked_iid); //add by daniel on 2006-6-15
                                                    //this problem(call will drop after 4600s)  was found in OMT
                                                    //it is because of the invoke id occupation do not release after assigned

				//tcap_send_ascout("tcap init free linked_did\r\n");
				memset(shm_ptr,0,sizeof(ismvm_data));
				shm_ptr->ism_state = TCAP_IDLE;
				break;
			case TCAP_IDLE:
				if ((shm_ptr->ism_msgtype == Invoke) ||
					(shm_ptr->ism_msgtype == Invoke_L_Ansi) ||
					(shm_ptr->ism_msgtype == Invoke_NL_Ansi))
				{
					shm_ptr->ism_msgtype = 0;
					switch (shm_ptr->ism_msgclass)
					{
						case OPERATION_CLASS1:
							shm_ptr->ism_state = SENT_STATE1;
							break;
						case OPERATION_CLASS2:
							shm_ptr->ism_state = SENT_STATE2;
							break;
						case OPERATION_CLASS3:
							shm_ptr->ism_state = SENT_STATE3;
							break;
						case OPERATION_CLASS4:
							shm_ptr->ism_state = SENT_STATE4;
							break;
						default:
							shm_ptr->ism_state = SENT_STATE4;
							break;
					}
				}
				break;
			case SENT_STATE1:
				if ((shm_ptr->ism_timer--) == 0)	// invocation timer expiry
				{
					if (debug_ptr->error_switch)
					{
						sprintf(info_str,"ISM warning. Invoke timer expired 1. Did: %u, Iid: %d",proc,shm_ptr->linked_iid);
						tcap_send_error(info_str);
					}
					send_cancel_tcu(proc,shm_ptr->linked_iid);
					shm_ptr->ism_state = TCAP_INIT;
					debug_ptr->tc_utilize[TCAP_UTILIZE_COUNT-1][71] ++;
					debug_ptr->watch_dog[234]++;
				}
				switch (shm_ptr->ism_msgtype)
				{
					case Result_L:
					case Result_L_Ansi:
					case Error:
					case Error_Ansi:
						shm_ptr->ism_timer = 0;
						shm_ptr->ism_state = WAIT_REJECT_STATE;
						shm_ptr->ism_msgtype = 0;
						break;
					case Result_NL:
					case Result_NL_Ansi:
					case Invoke_NL_Ansi:
						shm_ptr->ism_msgtype = 0;
						break;
					default:
						break;
				}
				break;
			case SENT_STATE2:
				if ((shm_ptr->ism_timer--) == 0)	// invocation timer expiry
				{
					if (debug_ptr->error_switch)
					{
					//	sprintf(info_str,"ISM warning. Invoke timer expired 2. Did: %ld, Iid: %d",proc,shm_ptr->linked_iid);
					//	tcap_send_error(info_str);
					}
					send_cancel_tcu(proc,shm_ptr->linked_iid);
					shm_ptr->ism_state = TCAP_INIT;
					debug_ptr->watch_dog[233]++;
				}
				switch (shm_ptr->ism_msgtype)
				{
					case Error:
					case Error_Ansi:
						shm_ptr->ism_timer = 0;
						shm_ptr->ism_state = WAIT_REJECT_STATE;
						shm_ptr->ism_msgtype = 0;
						break;
					case Result_L:
					case Result_NL:
					case Result_L_Ansi:
					case Result_NL_Ansi:
						if (proto_type)
						{
							problem_type = Return_Result_Ansi;
							problem_code = Return_Result_RRU_Ansi;
							if (debug_ptr->error_switch)
							{
								sprintf(info_str,"ISM warning. Return_Result_Ansi not expected 1. Did: %u, Iid: %d",proc,shm_ptr->linked_iid);
								tcap_send_error(info_str);
							}
						}
						else
						{
							problem_type = Return_Result;
							problem_code = Return_Result_RRU;
							if (debug_ptr->error_switch)
							{
								sprintf(info_str,"ISM warning. Return_Result not expected 1. Did: %u, Iid: %d",proc,shm_ptr->linked_iid);
								tcap_send_error(info_str);
							}
						}
						send_reject_tcu(proc,shm_ptr->linked_iid,problem_type,problem_code,proto_type);
						shm_ptr->ism_state = TCAP_INIT;
						break;
					default:
						break;
				}
				break;
			case SENT_STATE3:
				if ((shm_ptr->ism_timer--) == 0)	// invocation timer expiry
				{
					if (debug_ptr->error_switch)
					{
					//	sprintf(info_str,"ISM warning. Invoke timer expire. Did: %ld, Iid: %d",proc,shm_ptr->linked_iid);
					//	tcap_send_error(info_str);
					}
					send_cancel_tcu(proc,shm_ptr->linked_iid);
					shm_ptr->ism_state = TCAP_INIT;
					debug_ptr->watch_dog[232]++;
				}
				switch (shm_ptr->ism_msgtype)
				{
					case Result_L:
					case Result_L_Ansi:
						shm_ptr->ism_timer = 0;
						shm_ptr->ism_state = WAIT_REJECT_STATE;
						shm_ptr->ism_msgtype = 0;
						break;
					case Result_NL:
					case Result_NL_Ansi:
						shm_ptr->ism_msgtype = 0;
						break;
					case Error:
					case Error_Ansi:
						if (proto_type)
						{
							problem_type = Return_Error_Ansi;
							problem_code = Return_Error_REU_Ansi;
							if (debug_ptr->error_switch)
							{
								sprintf(info_str,"ISM warning. Return_Error_Ansi not expected 1. Did: %u, Iid: %d",proc,shm_ptr->linked_iid);
								tcap_send_error(info_str);
							}
						}
						else
						{
							problem_type = Return_Error;
							problem_code = Return_Error_REU;
							if (debug_ptr->error_switch)
							{
								sprintf(info_str,"ISM warning. Return_Error not expected 1. Did: %u, Iid: %d",proc,shm_ptr->linked_iid);
								tcap_send_error(info_str);
							}
						}
						send_reject_tcu(proc,shm_ptr->linked_iid,problem_type,problem_code,proto_type);
						shm_ptr->ism_state = TCAP_INIT;
						break;
					default:
						break;
				}
				break;
			case SENT_STATE4:
				if ((shm_ptr->ism_timer--) == 0)	// invocation timer expiry
				{
					if (debug_ptr->error_switch)
					{
					//	sprintf(info_str,"ISM warning. Invoke timer expired 4. Did: %ld, Iid: %d",proc,shm_ptr->linked_iid);
					//	tcap_send_error(info_str);
					}
					send_cancel_tcu(proc,shm_ptr->linked_iid);
					shm_ptr->ism_state = TCAP_INIT;
					debug_ptr->watch_dog[231]++;
				}
				switch (shm_ptr->ism_msgtype)
				{
					case Result_NL:
					case Result_L:
					case Result_NL_Ansi:
					case Result_L_Ansi:
						if (proto_type)
						{
							problem_type = Return_Result_Ansi;
							problem_code = Return_Result_RRU_Ansi;
							if (debug_ptr->error_switch)
							{
								sprintf(info_str,"ISM warning. Return_Result_Ansi not expected 2. Did: %u, Iid: %d",proc,shm_ptr->linked_iid);
								tcap_send_error(info_str);
							}
						}
						else
						{
							problem_type = Return_Result;
							problem_code = Return_Result_RRU;
							if (debug_ptr->error_switch)
							{
								sprintf(info_str,"ISM warning. Return_Result not expected 2. Did: %u, Iid: %d",proc,shm_ptr->linked_iid);
								tcap_send_error(info_str);
							}
						}
						send_reject_tcu(proc,shm_ptr->linked_iid,problem_type,problem_code,proto_type);
						shm_ptr->ism_state = TCAP_INIT;
						break;
					case Error:
					case Error_Ansi:
						if (proto_type)
						{
							problem_type = Return_Error_Ansi;
							problem_code = Return_Error_REU_Ansi;
							if (debug_ptr->error_switch)
							{
								sprintf(info_str,"ISM warning. Return_Error_Ansi not expected 2. Did: %u, Iid: %d",proc,shm_ptr->linked_iid);
								tcap_send_error(info_str);
							}
						}
						else
						{
							problem_type = Return_Error;
							problem_code = Return_Error_REU;
							if (debug_ptr->error_switch)
							{
								sprintf(info_str,"ISM warning. Return_Error not expected 2. Did: %u, Iid: %d",proc,shm_ptr->linked_iid);
								tcap_send_error(info_str);
							}
						}
						send_reject_tcu(proc,shm_ptr->linked_iid,problem_type,problem_code,proto_type);
						shm_ptr->ism_state = TCAP_INIT;
						break;
					default:
						break;
				}
				break;
			case WAIT_REJECT_STATE:
				if ((shm_ptr->ism_timer++) >= debug_ptr->default_rejtime * ISM_TIMERHZ)
					shm_ptr->ism_state = TCAP_INIT;
				break;
			default:
				shm_ptr->ism_state = TCAP_INIT;
				break;
		}
	}
}

void tcap_change_local_ssn(u32 proc,u8 src_ssn,u8 dst_ssn)
{
	struct	tcapvm_struct		*vm_ptr;

	if (proc >= (tcap_ptr->grantdid))
		return;
	
	vm_ptr = (tcapvm_struct *) &tcap_ptr->tcapvm_data[proc];
	if (src_ssn == vm_ptr->local_add.SSN)
		vm_ptr->local_add.SSN = dst_ssn;
}

void tcap_change_local_tt(u32 proc,u8 src_ssn,u8 tt) //change local tt for ANSI network
{
	struct	tcapvm_struct		*vm_ptr;

	if (proc >= (tcap_ptr->grantdid))
		return;
	
	vm_ptr = (tcapvm_struct *) &tcap_ptr->tcapvm_data[proc];
	if (src_ssn == vm_ptr->local_add.SSN)
		vm_ptr->local_add.TT = tt;
}

extern int GetMSISDNOfSSN ( BYTE ssn, BYTE * msisdn );
u8 tcap_change_local_gtt(u32 proc, u8 uSSN)
{
	struct	tcapvm_struct		*vm_ptr;
	u8  aGTT[ISDN_LEN];

	if (proc >= (tcap_ptr->grantdid))
		return 0;
	
	vm_ptr = (tcapvm_struct *) &tcap_ptr->tcapvm_data[proc];
	if (uSSN != vm_ptr->local_add.SSN)
		return 0;

        if( GetMSISDNOfSSN ( uSSN, aGTT )  )
        {
        	u8  aISDN[ISDN_LEN];
        	
            GttToIsdn ( aISDN, aGTT );
            vm_ptr->local_add.len = IsdnToGtai( vm_ptr->local_add.GTAI ,aISDN );
            return vm_ptr->local_add.len;
        }
        return 0;
 }
 
/*@end@*/
