/*	TCAP code/decode c file				*/
/*	written by Liu Zhiguo 2002-08-08	*/
/*	Version 2.0							*/
/*	--------------------------------	*/

#include "../../public/src/include/asn1.h"
#include "../../sccp/src/include/sccp.h"
#include "./include/tcap_public.h"
#include "./include/tcap_struct.h"
#include "./include/tcap_m.h"

/*@ignore@*/
/*	protocol version	*/
static u8	Version_1[2] = {0x07,0x80};

/*	Undialogue-As-ID value	*/
static u8	Undialogue_As_ID[7] = {0x00,0x11,0x86,0x05,0x01,0x02,0x01};
/*	Dialogue-As-ID value	*/
static u8	Dialogue_As_ID[7] = {0x00,0x11,0x86,0x05,0x01,0x01,0x01};

void print_msg(u8 *ptr, u16 len)
{
	int i;
	
	for (i = 0; i < len; i++)
		printf("%02X ", ptr[i]);
	
	printf("\n");
}

u8 tsl_message_decode(struct SCLC_MSG *src_ptr,struct TSL_struct *dst_ptr, u8 *err_code)// tsl decode
{
	#define	TMPBUFSIZE				512
	ASN_BUF	asn_buf;
	struct	TRUni_struct		*uni_ptr;
	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;
	int		len=0;
	u32		temp_tid=0;
	u8		temp_buf[TMPBUFSIZE];
	u8		tag_class;
	u16		tag_code;
	u8		uabort_flag;
	
	memcpy(&dst_ptr->peer_add,&src_ptr->src_addr,sizeof(SCCP_ADDR));
	memcpy(&dst_ptr->local_add,&src_ptr->dst_addr,sizeof(SCCP_ADDR));
	
	len = asn_decode(src_ptr->msg,1,&asn_buf);
	if (len == -1)
		tcap_send_error("TSL decode error. ASN.1 structure has problem");
	
	len = GetAnyTLV("1",TMPBUFSIZE,temp_buf,&tag_class,&tag_code,&asn_buf);	// check if is Unidirectional/Unidirectional_Ansi
	if (len != -1)	// message_type is Unidirectional/Unidirectional_Ansi
	{
		if (tag_class == ANSI_TAG_CLASS_CONS)
		{
			dst_ptr->message_type = Unidirectional_Ansi;
			tcap_send_info("Unidirectional_Ansi received from sccp");
		}
		else
		{
			dst_ptr->message_type = Unidirectional;
			tcap_send_info("Unidirectional received from sccp");
		}
		dst_ptr->message_flag = INDICATE;
		uni_ptr = (TRUni_struct *) &dst_ptr->tsl_prim.tr_uni;
		uni_ptr->dialogue_len = uni_ptr->components_len = 0;
		if (tag_class == ANSI_TAG_CLASS_CONS)
		{
			len = get_tlv("1.7",temp_buf,&asn_buf);
			if (len != 0)
			{
				tcap_send_error("TSL decode error. Lacks transaction id");
				*err_code = DERR_OTHER;
				return 0;
			}
		}
		if (tag_class == ANSI_TAG_CLASS_CONS)
			len = get_tlv("1.25",temp_buf,&asn_buf);	// get dialogue portion
		else
			len = get_tlv("1.11",temp_buf,&asn_buf);
		if (len != -1)
		{
			if (len <= TCAP_DLG_LEN)
			{
				uni_ptr->dialogue_len = len;
				memcpy(uni_ptr->dialogue,temp_buf,len);
			}
			else
			{
				tcap_send_error("TSL decode error. Dialogue portion is too long");
				*err_code = DERR_OTHER;
				return 0;
			}
		}
		if (tag_class == ANSI_TAG_CLASS_CONS)
			len = get_tlv("1.8",uni_ptr->components,&asn_buf);
		else
			len = get_tlv("1.12",uni_ptr->components,&asn_buf);
		if ((len == -1) || (len > TCAP_CMP_LEN))
		{
			if (len == -1)
				tcap_send_error("TSL decode error. Lacks component portion");
			else
				tcap_send_error("TSL decode error. Component portion is too long");
			*err_code = DERR_OTHER;
			return 0;
		}
		uni_ptr->components_len = len;
		sprintf((char *)temp_buf, "dialogue portion len: %02X, component portion len: %02X\r\n", uni_ptr->dialogue_len, uni_ptr->components_len);
		tcap_send_info((char *)temp_buf);
		return 1;
	}
	
	len = GetAnyTLV("2",TMPBUFSIZE,temp_buf,&tag_class,&tag_code,&asn_buf);	// check if is begin/query with permission
	if (len == -1)
		len = GetAnyTLV("3",TMPBUFSIZE,temp_buf,&tag_class,&tag_code,&asn_buf);	// check if is query without permission
	if (len != -1)	// message_type is begin/query
	{
		if (tag_class == ANSI_TAG_CLASS_CONS)
		{
			if (tag_code == 2)
			{
				dst_ptr->message_type = Query_WithPerm_Ansi;
				tcap_send_info("Query_WithPerm_Ansi received from sccp");
			}
			else
			{
				dst_ptr->message_type = Query_WithoutPerm_Ansi;
				tcap_send_info("Query_WithoutPerm_Ansi received from sccp");
			}
		}
		else
		{
			dst_ptr->message_type = Begin;
			tcap_send_info("Begin received from sccp");
		}
		dst_ptr->message_flag = INDICATE;
		begin_ptr = (TRBegin_struct *) &dst_ptr->tsl_prim.tr_begin;
		begin_ptr->dialogue_len = begin_ptr->components_len = 0;
		if (tag_class == ANSI_TAG_CLASS_CONS)
		{
			if (tag_code == 2)	// get otid
				len = get_tlv("2.7",temp_buf,&asn_buf);
			else
				len = get_tlv("3.7",temp_buf,&asn_buf);
			if (len != 4)
			{
				tcap_send_error("TSL decode error. Lacks originating transaction id");
				begin_ptr->tid_flag = 0;
				*err_code = DERR_OTHER;
				return 0;
			}
		}
		else
		{
			len = get_tlv("2.8",temp_buf,&asn_buf);	// get otid
			if ((len == -1) || (len > 4) || (len == 0))
			{
				tcap_send_error("TSL decode error. Lacks originating transaction id");
				begin_ptr->tid_flag = 0;
				*err_code = DERR_UNTID;
				return 0;
			}
		}
		
		dst_ptr->peer_tid_len = len; /* added by Pierre, 2006-08-19 */ 
	
		begin_ptr->transaction_id = bcdtou32(temp_buf,len);
		begin_ptr->tid_flag = 1;
		if (tag_class == ANSI_TAG_CLASS_CONS)
		{
			if (tag_code == 2)
				len = get_tlv("2.25",temp_buf,&asn_buf);
			else
				len = get_tlv("3.25",temp_buf,&asn_buf);
		}
		else
			len = get_tlv("2.11",temp_buf,&asn_buf);
		if (len != -1)	// has dialogue portion
		{
			if (len <= TCAP_DLG_LEN)
			{
				begin_ptr->dialogue_len = len;
				memcpy(begin_ptr->dialogue,temp_buf,len);
			}
			else
			{
				tcap_send_error("TSL decode error. Dialogue portion is too long");
				*err_code = DERR_OTHER;
				return 0;
			}
		}
		if (tag_class == ANSI_TAG_CLASS_CONS)
		{
			if (tag_code == 2)
				len = get_tlv("2.8",begin_ptr->components,&asn_buf);
			else
				len = get_tlv("3.8",begin_ptr->components,&asn_buf);
		}
		else
			len = get_tlv("2.12",begin_ptr->components,&asn_buf);
		if (((len == -1) || (len > TCAP_CMP_LEN)) && (tag_class == ANSI_TAG_CLASS_CONS))	// has components portion
		{
			if (len == -1)
				tcap_send_error("TSL decode error. Lacks component portion");
			else
				tcap_send_error("TSL decode error. Component portion is too long");
			*err_code = DERR_OTHER;
			return 0;
		}
		if (len != -1 && len <= TCAP_CMP_LEN)
			begin_ptr->components_len = len;
		sprintf((char *)temp_buf, "otid: %08X, dialogue portion len: %02X, component portion len: %02X\r\n", 
				begin_ptr->transaction_id, begin_ptr->dialogue_len, begin_ptr->components_len);
		tcap_send_info((char *)temp_buf);
		return 1;
	}
	
	len = GetAnyTLV("4",TMPBUFSIZE,temp_buf,&tag_class,&tag_code,&asn_buf);	// check if is end/response
	if (len != -1)	// message_type is end/response
	{
		if (tag_class == ANSI_TAG_CLASS_CONS)
		{
			dst_ptr->message_type = Response_Ansi;
			tcap_send_info("Response_Ansi received from sccp");
		}
		else
		{
			dst_ptr->message_type = End;
			tcap_send_info("End received from sccp");
		}
		dst_ptr->message_flag = INDICATE;
		end_ptr = (TREnd_struct *) &dst_ptr->tsl_prim.tr_end;
		end_ptr->dialogue_len = end_ptr->components_len = 0;
		if (tag_class == ANSI_TAG_CLASS_CONS)
		{
			len = get_tlv("4.7",temp_buf,&asn_buf);	// get dtid
			if (len != 4)
			{
				tcap_send_error("TSL decode error. Lacks responding transaction id");
				end_ptr->tid_flag = 0;
				*err_code = DERR_UNTID;
				return 0;
			}
		}
		else
		{
			len = get_tlv("4.9",temp_buf,&asn_buf);	// get dtid
			if ((len == -1) || (len > 4) || (len == 0))
			{
				tcap_send_error("TSL decode error. Lacks destination transaction id");
				end_ptr->tid_flag = 0;
				*err_code = DERR_UNTID;
				return 0;
			}
		}
		end_ptr->transaction_id = bcdtou32(temp_buf,len);
		end_ptr->tid_flag = 1;
		if (tag_class == ANSI_TAG_CLASS_CONS)
			len = get_tlv("4.25",temp_buf,&asn_buf);
		else
			len = get_tlv("4.11",temp_buf,&asn_buf);
		if (len != -1)	// has dialogue portion
		{
			if (len <= TCAP_DLG_LEN)
			{
				end_ptr->dialogue_len = len;
				memcpy(end_ptr->dialogue,temp_buf,len);
			}
			else
			{
				tcap_send_error("TSL decode error. Dialogue portion is too long");
				*err_code = DERR_OTHER;
				return 0;
			}
		}
		if (tag_class == ANSI_TAG_CLASS_CONS)
			len = get_tlv("4.8",end_ptr->components,&asn_buf);
		else
			len = get_tlv("4.12",end_ptr->components,&asn_buf);
		if (((len == -1) || (len > TCAP_CMP_LEN)) && (tag_class == ANSI_TAG_CLASS_CONS))	// has components portion
		{
			if (len == -1)
				tcap_send_error("TSL decode error. Lacks component portion");
			else
				tcap_send_error("TSL decode error. Component portion is too long");
			*err_code = DERR_OTHER;
			return 0;
		}
		if (len != -1 && len <= TCAP_CMP_LEN)
			end_ptr->components_len = len;
		sprintf((char *)temp_buf, "dtid: %08X, dialogue portion len: %02X, component portion len: %02X\r\n",
				end_ptr->transaction_id, end_ptr->dialogue_len, end_ptr->components_len);
		tcap_send_info((char *)temp_buf);
		return 1;
	}
	
	len = GetAnyTLV("5",TMPBUFSIZE,temp_buf,&tag_class,&tag_code,&asn_buf);	// check if is continue/conversation with permission
	if (len == -1)
		len = GetAnyTLV("6",TMPBUFSIZE,temp_buf,&tag_class,&tag_code,&asn_buf);	// check if is conversation without permission
	if (len != -1)	// message_type is continue/conversation
	{
		if (tag_class == ANSI_TAG_CLASS_CONS)
		{
			if (tag_code == 5)
			{
				dst_ptr->message_type = Conversation_WithPerm_Ansi;
				tcap_send_info("Conversation_WithPerm_Ansi received from sccp");
			}
			else
			{
				dst_ptr->message_type = Conversation_WithoutPerm_Ansi;
				tcap_send_info("Conversation_WithoutPerm_Ansi received from sccp");
			}
		}
		else
		{
			dst_ptr->message_type = Continue;
			tcap_send_info("Continue received from sccp");
		}
		dst_ptr->message_flag = INDICATE;
		con_ptr = (TRContinue_struct *) &dst_ptr->tsl_prim.tr_continue;
		con_ptr->dialogue_len = con_ptr->components_len = 0;
		if (tag_class == ANSI_TAG_CLASS_CONS)
		{
			if (tag_code == 5)
				len = get_tlv("5.7",temp_buf,&asn_buf);	// get tid
			else
				len = get_tlv("6.7",temp_buf,&asn_buf);
			if (len != 8)
			{
				tcap_send_error("TSL decode error. Lacks transaction id");
				con_ptr->ltid_flag = 0;
				con_ptr->ptid_flag = 0;
				*err_code = DERR_OTHER;
				return 0;
			}
			dst_ptr->peer_tid_len = len; /* added by Pierre , 2006-08-19 */
			
			con_ptr->peer_tid = bcdtou32(temp_buf,4);
			con_ptr->ptid_flag = 1;
			con_ptr->local_tid = bcdtou32(temp_buf + 4,4);
			con_ptr->ltid_flag = 1;
		}
		else
		{
			len = get_tlv("5.8",temp_buf,&asn_buf);	// get otid
			if ((len == -1) || (len > 4) || (len == 0))
			{
				tcap_send_error("TSL decode error. Lacks originating transaction id");
				con_ptr->ptid_flag = 0;
				*err_code = DERR_UNTID;
				return 0;
			}
			dst_ptr->peer_tid_len = len; /* added by Pierre, 2006-08-19 */ 
			con_ptr->peer_tid = bcdtou32(temp_buf,len);
			con_ptr->ptid_flag = 1;
			len = get_tlv("5.9",temp_buf,&asn_buf);	// get dtid
			if ((len == -1) || (len > 4) || (len == 0))
			{
				tcap_send_error("TSL decode error. Lacks destination transaction id");
				con_ptr->ltid_flag = 0;
				*err_code = DERR_UNTID;
				return 0;
			}
			con_ptr->local_tid = bcdtou32(temp_buf,len);
			con_ptr->ltid_flag = 1;
		}
		if (tag_class == ANSI_TAG_CLASS_CONS)
		{
			if (tag_code == 5)
				len = get_tlv("5.25",temp_buf,&asn_buf);
			else
				len = get_tlv("6.25",temp_buf,&asn_buf);
		}
		else
			len = get_tlv("5.11",temp_buf,&asn_buf);
		if (len != -1)	// has dialogue portion
		{
			if (len <= TCAP_DLG_LEN)
			{
				con_ptr->dialogue_len = len;
				memcpy(con_ptr->dialogue,temp_buf,len);
			}
			else
			{
				tcap_send_error("TSL decode error. Dialogue portion is too long");
				*err_code = DERR_OTHER;
				return 0;
			}
		}
		if (tag_class == ANSI_TAG_CLASS_CONS)
		{
			if (tag_code == 5)
				len = get_tlv("5.8",con_ptr->components,&asn_buf);
			else
				len = get_tlv("6.8",con_ptr->components,&asn_buf);
		}
		else
			len = get_tlv("5.12",con_ptr->components,&asn_buf);
		if (((len == -1) || (len > TCAP_CMP_LEN)) && (tag_class == ANSI_TAG_CLASS_CONS))	// has components portion
		{
			if (len == -1)
				tcap_send_error("TSL decode error. Lacks component portion");
			else
				tcap_send_error("TSL decode error. Component portion is too long");
			*err_code = DERR_OTHER;
			return 0;
		}
		if (len != -1 && len <= TCAP_CMP_LEN)
			con_ptr->components_len = len;
		sprintf((char *)temp_buf, "otid: %08X, dtid: %08X\r\ndialogue portion len: %02X, component portion len: %02X\r\n",
				con_ptr->peer_tid, con_ptr->local_tid, con_ptr->dialogue_len, con_ptr->components_len);
		tcap_send_info((char *)temp_buf);
		return 1;
	}
	
	len = GetAnyTLV("7",TMPBUFSIZE,temp_buf,&tag_class,&tag_code,&asn_buf);	// check if is abort
	if (len != -1)	// message_type is abort
	{
		dst_ptr->message_type = U_Abort;
		tcap_send_info("Abort received from sccp");
		dst_ptr->message_flag = INDICATE;
		uabort_ptr = (TRUAbort_struct *) &dst_ptr->tsl_prim.tr_uabort;
		uabort_ptr->dialogue_len = 0;
		uabort_ptr->uabort_info_len = 0;
		len = get_tlv("7.9",temp_buf,&asn_buf);	// get dtid
		if (len == -1 || len > 4 || len == 0)
		{
			tcap_send_error("TSL decode error. Lacks destination transaction id");
			uabort_ptr->tid_flag = 0;
			*err_code = DERR_UNTID;
			return 0;
		}
		temp_tid = bcdtou32(temp_buf,len);
		uabort_ptr->tid_flag = 1;
		uabort_ptr->transaction_id = temp_tid;
		len = get_tlv("7.11",temp_buf,&asn_buf);
		if (len != -1 && len <= TCAP_DLG_LEN)	// has dialogue portion
		{
			uabort_ptr->dialogue_len = len;
			memcpy(uabort_ptr->dialogue,temp_buf,len);
			sprintf((char *)temp_buf, "dtid: %08X, dialogue portion len: %02X\r\n",
					uabort_ptr->transaction_id, uabort_ptr->dialogue_len);
			tcap_send_info((char *)temp_buf);
			return 1;
		}
		else if (len > TCAP_DLG_LEN)
		{
			tcap_send_error("TSL decode error. Dialogue portion is too long");
			*err_code = DERR_OTHER;
			return 0;
		}
		len = get_tlv("7.10",temp_buf,&asn_buf);
		if (len != -1)	// has P_Abort_Cause
		{
			dst_ptr->message_type = P_Abort;
			pabort_ptr = (TRPAbort_struct *) &dst_ptr->tsl_prim.tr_pabort;
			pabort_ptr->tid_flag = 1;
			pabort_ptr->transaction_id = temp_tid;
			if (len != 1)
			{
				tcap_send_error("TSL decode error. P_Abort lacks abort reason");
				*err_code = DERR_OTHER;
				return 0;
			}
			pabort_ptr->abort_reason = temp_buf[0];
			sprintf((char *)temp_buf, "dtid: %08X, pabort reason: %02X\r\n",
					pabort_ptr->transaction_id, pabort_ptr->abort_reason);
			tcap_send_info((char *)temp_buf);
			return 1;
		}
	}
	
	len = GetAnyTLV("22",TMPBUFSIZE,temp_buf,&tag_class,&tag_code,&asn_buf);	// check if is ansi abort
	if (len != -1)	// message_type is ansi abort
	{
		dst_ptr->message_type = U_Abort_Ansi;
		tcap_send_info("Abort_Ansi received from sccp");
		dst_ptr->message_flag = INDICATE;
		uabort_ptr = (TRUAbort_struct *) &dst_ptr->tsl_prim.tr_uabort;
		uabort_ptr->dialogue_len = 0;
		uabort_ptr->uabort_info_len = 0;
		uabort_flag = 0;
		len = get_tlv("22.7",temp_buf,&asn_buf);	// get dtid
		if (len != 4)
		{
			tcap_send_error("TSL decode error. Lacks responding transaction id");
			uabort_ptr->tid_flag = 0;
			*err_code = DERR_UNTID;
			return 0;
		}
		temp_tid = bcdtou32(temp_buf,4);
		uabort_ptr->tid_flag = 1;
		uabort_ptr->transaction_id = temp_tid;
		len = get_tlv("22.25",temp_buf,&asn_buf);
		if (len != -1)	// has dialogue portion
		{
			uabort_flag = 1;
			if (len <= TCAP_DLG_LEN)
			{
				uabort_ptr->dialogue_len = len;
				memcpy(uabort_ptr->dialogue,temp_buf,len);
			}
			else
			{
				tcap_send_error("TSL decode error. Dialogue portion is too long");
				*err_code = DERR_OTHER;
				return 0;
			}
		}
		len = get_tlv("22.24",temp_buf,&asn_buf);
		if (len >= 0)	// has user abort info
		{
			if (len <= TCAP_UABORT_INFO_LEN)
			{
				uabort_ptr->uabort_info_len = len;
				memcpy(uabort_ptr->uabort_info,temp_buf,len);
				sprintf((char *)temp_buf, "dtid: %08X, dialogue portion len: %02X, uabort info len: %02X\r\n",
						uabort_ptr->transaction_id, uabort_ptr->dialogue_len, uabort_ptr->uabort_info_len);
				tcap_send_info((char *)temp_buf);
				return 1;
			}
			else
			{
				tcap_send_error("TSL decode error. Uabort info is too long");
				*err_code = DERR_OTHER;
				return 0;
			}
		}
		else if (uabort_flag)
		{
			*err_code = DERR_OTHER;
			tcap_send_error("TSL decode error. U_Abort lacks uabort info");
			return 0;
		}
		len = get_tlv("22.23",temp_buf,&asn_buf);
		if (len != -1)	// has P_Abort_Cause
		{
			dst_ptr->message_type = P_Abort_Ansi;
			pabort_ptr = (TRPAbort_struct *) &dst_ptr->tsl_prim.tr_pabort;
			pabort_ptr->tid_flag = 1;
			pabort_ptr->transaction_id = temp_tid;
			if (len != 1)
			{
				tcap_send_error("TSL decode error. P_Abort lacks abort reason");
				*err_code = DERR_OTHER;
				return 0;
			}
			pabort_ptr->abort_reason = temp_buf[0];
			sprintf((char *)temp_buf, "dtid: %08X, pabort reason: %02X\r\n",
					pabort_ptr->transaction_id, pabort_ptr->abort_reason);
			tcap_send_info((char *)temp_buf);
			return 1;
		}
	}
	
	tcap_send_error("TSL decode error. Can not recognize package type");
	return 0;
}

u8 tsl_message_encode(struct SCLC_MSG *sccp_ptr,struct TSL_struct *tsl_ptr,u8 flag)// tsl encode
{
	ASN_BUF	asn_buf;
	u8		temp_buf[512];
	u8		tag_class;
	u32		len = 0;
	u32		temp_tid=0;
	struct	TRUni_struct		*uni_ptr;
	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;
	
	if (flag)	// resend
	{
		memcpy(&sccp_ptr->dst_addr,&tsl_ptr->local_add,sizeof(SCCP_ADDR));
		memcpy(&sccp_ptr->src_addr,&tsl_ptr->peer_add,sizeof(SCCP_ADDR));
	}
	else
	{
		memcpy(&sccp_ptr->dst_addr,&tsl_ptr->peer_add,sizeof(SCCP_ADDR));
		memcpy(&sccp_ptr->src_addr,&tsl_ptr->local_add,sizeof(SCCP_ADDR));
	}
	asn_encode(sccp_ptr->msg,&asn_buf);
	tag_class = tsl_ptr->message_type & 0xE0;
	switch (tsl_ptr->message_type)
	{
		case Unidirectional:
		case Unidirectional_Ansi:
			if (tag_class == ANSI_TAG_CLASS_CONS)
			{
				sccp_ptr->msglen = add_tlv("1",0,temp_buf,ANSI_TAG_CLASS_CONS,&asn_buf);
				tcap_send_info("Unidirectional_Ansi sent to sccp");
			}
			else
			{
				sccp_ptr->msglen = add_tlv("1",0,temp_buf,0x60,&asn_buf);
				tcap_send_info("Unidirectional sent to sccp");
			}
			uni_ptr = (TRUni_struct *) &tsl_ptr->tsl_prim.tr_uni;
			if (tag_class == ANSI_TAG_CLASS_CONS)	// Transaction ID
				sccp_ptr->msglen = add_tlv("1.7-1",0,temp_buf,ANSI_TAG_CLASS_PRIM,&asn_buf);
			if (uni_ptr->dialogue_len != 0)	// dialogue portion
			{
				if (tag_class == ANSI_TAG_CLASS_CONS)
					sccp_ptr->msglen = add_tlv("1.25-2",uni_ptr->dialogue_len,uni_ptr->dialogue,ANSI_TAG_CLASS_CONS,&asn_buf);
				else
					sccp_ptr->msglen = add_tlv("1.11",uni_ptr->dialogue_len,uni_ptr->dialogue,0x60,&asn_buf);
			}
			if (uni_ptr->components_len != 0)	// component portion
			{
				if (tag_class == ANSI_TAG_CLASS_CONS)
					sccp_ptr->msglen = add_tlv("1.8-3",uni_ptr->components_len,uni_ptr->components,ANSI_TAG_CLASS_CONS,&asn_buf);
				else
					sccp_ptr->msglen = add_tlv("1.12",uni_ptr->components_len,uni_ptr->components,0x60,&asn_buf);
			}
			sprintf((char *)temp_buf, "dialogue portion len: %02X, component portion len: %02X\r\n", uni_ptr->dialogue_len, uni_ptr->components_len);
			tcap_send_info((char *)temp_buf);
			tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][0] ++;
			break;
		case Begin:
		case Query_WithPerm_Ansi:
		case Query_WithoutPerm_Ansi:
			if (tag_class == ANSI_TAG_CLASS_CONS)
			{
				if (tsl_ptr->message_type == Query_WithPerm_Ansi)
				{
					sccp_ptr->msglen = add_tlv("2",0,temp_buf,ANSI_TAG_CLASS_CONS,&asn_buf);
					tcap_send_info("Query_WithPerm_Ansi sent to sccp");
				}
				else
				{
					sccp_ptr->msglen = add_tlv("3",0,temp_buf,ANSI_TAG_CLASS_CONS,&asn_buf);
					tcap_send_info("Query_WithoutPerm_Ansi sent to sccp");
				}
			}
			else
			{
				sccp_ptr->msglen = add_tlv("2",0,temp_buf,0x60,&asn_buf);
				tcap_send_info("Begin sent to sccp");
			}
			begin_ptr = (TRBegin_struct *) &tsl_ptr->tsl_prim.tr_begin;
			temp_tid = (tcap_ptr->tcap_debug.local_ip & 0xffff0000) + begin_ptr->transaction_id;
			len = u32tobcd(temp_buf,temp_tid);	//encode orig TID
			if (tag_class == ANSI_TAG_CLASS_CONS)
			{
				if (tsl_ptr->message_type == Query_WithPerm_Ansi)
					sccp_ptr->msglen = add_tlv("2.7-1",len,temp_buf,ANSI_TAG_CLASS_PRIM,&asn_buf);
				else
					sccp_ptr->msglen = add_tlv("3.7-1",len,temp_buf,ANSI_TAG_CLASS_PRIM,&asn_buf);
			}
			else
				sccp_ptr->msglen = add_tlv("2.8",len,temp_buf,0x40,&asn_buf);
			if (begin_ptr->dialogue_len != 0)	// dialogue portion
			{
				if (tag_class == ANSI_TAG_CLASS_CONS)
				{
					if (tsl_ptr->message_type == Query_WithPerm_Ansi)
						sccp_ptr->msglen = add_tlv("2.25-2",begin_ptr->dialogue_len,begin_ptr->dialogue,ANSI_TAG_CLASS_CONS,&asn_buf);
					else
						sccp_ptr->msglen = add_tlv("3.25-2",begin_ptr->dialogue_len,begin_ptr->dialogue,ANSI_TAG_CLASS_CONS,&asn_buf);
				}
				else
					sccp_ptr->msglen = add_tlv("2.11",begin_ptr->dialogue_len,begin_ptr->dialogue,0x60,&asn_buf);
			}
			if (begin_ptr->components_len != 0)	// component portion
			{
				if (tag_class == ANSI_TAG_CLASS_CONS)
				{
					if (tsl_ptr->message_type == Query_WithPerm_Ansi)
						sccp_ptr->msglen = add_tlv("2.8-3",begin_ptr->components_len,begin_ptr->components,ANSI_TAG_CLASS_CONS,&asn_buf);
					else
						sccp_ptr->msglen = add_tlv("3.8-3",begin_ptr->components_len,begin_ptr->components,ANSI_TAG_CLASS_CONS,&asn_buf);
				}
				else
					sccp_ptr->msglen = add_tlv("2.12",begin_ptr->components_len,begin_ptr->components,0x60,&asn_buf);
			}
			sprintf((char *)temp_buf, "otid: %08X, dialogue portion len: %02X, component portion len: %02X\r\n", begin_ptr->transaction_id, begin_ptr->dialogue_len, begin_ptr->components_len);
			tcap_send_info((char *)temp_buf);
			tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][1] ++;
			break;
		case Continue:
		case Conversation_WithPerm_Ansi:
		case Conversation_WithoutPerm_Ansi:
			if (tag_class == ANSI_TAG_CLASS_CONS)
			{
				if (tsl_ptr->message_type == Conversation_WithPerm_Ansi)
				{
					sccp_ptr->msglen = add_tlv("5",0,temp_buf,ANSI_TAG_CLASS_CONS,&asn_buf);
					tcap_send_info("Conversation_WithPerm_Ansi sent to sccp");
				}
				else
				{
					sccp_ptr->msglen = add_tlv("6",0,temp_buf,ANSI_TAG_CLASS_CONS,&asn_buf);
					tcap_send_info("Conversation_WithoutPerm_Ansi sent to sccp");
				}
			}
			else
			{
				sccp_ptr->msglen = add_tlv("5",0,temp_buf,0x60,&asn_buf);
				tcap_send_info("Continue sent to sccp");
			}
			con_ptr = (TRContinue_struct *) &tsl_ptr->tsl_prim.tr_continue;
			if (flag)	//resend
			{
				if (tag_class == ANSI_TAG_CLASS_CONS)
				{
					u32tobcd(temp_buf,con_ptr->peer_tid);
					temp_tid = con_ptr->local_tid | 0x8000;
					u32tobcd(temp_buf + 4,temp_tid);
					if (tsl_ptr->message_type == Conversation_WithPerm_Ansi)
						sccp_ptr->msglen = add_tlv("5.7-1",8,temp_buf,ANSI_TAG_CLASS_PRIM,&asn_buf);
					else
						sccp_ptr->msglen = add_tlv("6.7-1",8,temp_buf,ANSI_TAG_CLASS_PRIM,&asn_buf);
				}
				else
				{
					memset(temp_buf,0,4);
					len = u32tobcd(temp_buf,con_ptr->peer_tid);
					len = tsl_ptr->peer_tid_len%5;  /* added by Pierre, 2006-08-19 */
					sccp_ptr->msglen = add_tlv("5.8",len,&temp_buf[4-len],0x40,&asn_buf);
					temp_tid = con_ptr->local_tid ;//| 0x8000;
					memset(temp_buf,0,4);
					len = u32tobcd(temp_buf,temp_tid);
					if(len == 0) len = 4;
					sccp_ptr->msglen = add_tlv("5.9",len,temp_buf,0x40,&asn_buf);
				}
			}
			else
			{
				if (tag_class == ANSI_TAG_CLASS_CONS)
				{
					temp_tid = (tcap_ptr->tcap_debug.local_ip & 0xffff0000) + con_ptr->local_tid;
					u32tobcd(temp_buf,temp_tid);
					u32tobcd(temp_buf + 4,con_ptr->peer_tid);
					if (tsl_ptr->message_type == Conversation_WithPerm_Ansi)
						sccp_ptr->msglen = add_tlv("5.7-1",8,temp_buf,ANSI_TAG_CLASS_PRIM,&asn_buf);
					else
						sccp_ptr->msglen = add_tlv("6.7-1",8,temp_buf,ANSI_TAG_CLASS_PRIM,&asn_buf);
				}
				else
				{
					memset(temp_buf,0,4);
					temp_tid = (tcap_ptr->tcap_debug.local_ip & 0xffff0000) + con_ptr->local_tid;
					len = u32tobcd(temp_buf,temp_tid);	//encode orig TID
					sccp_ptr->msglen = add_tlv("5.8",len,temp_buf,0x40,&asn_buf);
					memset(temp_buf,0,4);
					len = u32tobcd(temp_buf,con_ptr->peer_tid);	// encode dst TID
					len = tsl_ptr->peer_tid_len%5;  /* added by Pierre, 2006-08-19 */				
					if(len == 0) len = 4;
					sccp_ptr->msglen = add_tlv("5.9",len,&temp_buf[4-len],0x40,&asn_buf);
				}
			}
			if (con_ptr->dialogue_len != 0)	// dialogue portion
			{
				if (tag_class == ANSI_TAG_CLASS_CONS)
				{
					if (tsl_ptr->message_type == Conversation_WithPerm_Ansi)
						sccp_ptr->msglen = add_tlv("5.25-2",con_ptr->dialogue_len,con_ptr->dialogue,ANSI_TAG_CLASS_CONS,&asn_buf);
					else
						sccp_ptr->msglen = add_tlv("6.25-2",con_ptr->dialogue_len,con_ptr->dialogue,ANSI_TAG_CLASS_CONS,&asn_buf);
				}
				else
					sccp_ptr->msglen = add_tlv("5.11",con_ptr->dialogue_len,con_ptr->dialogue,0x60,&asn_buf);
			}
			if (con_ptr->components_len != 0)	// component portion
			{
				if (tag_class == ANSI_TAG_CLASS_CONS)
				{
					if (tsl_ptr->message_type == Conversation_WithPerm_Ansi)
						sccp_ptr->msglen = add_tlv("5.8-3",con_ptr->components_len,con_ptr->components,ANSI_TAG_CLASS_CONS,&asn_buf);
					else
						sccp_ptr->msglen = add_tlv("6.8-3",con_ptr->components_len,con_ptr->components,ANSI_TAG_CLASS_CONS,&asn_buf);
				}
				else
					sccp_ptr->msglen = add_tlv("5.12",con_ptr->components_len,con_ptr->components,0x60,&asn_buf);
			}
			sprintf((char *)temp_buf, "otid: %08X, dtid: %08X\r\ndialogue portion len: %02X, component portion len: %02X\r\n", con_ptr->local_tid, con_ptr->peer_tid, con_ptr->dialogue_len, con_ptr->components_len);
			tcap_send_info((char *)temp_buf);
			tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][2] ++;
			break;
		case End:
		case Response_Ansi:
			if (tag_class == ANSI_TAG_CLASS_CONS)
			{
				sccp_ptr->msglen = add_tlv("4",0,temp_buf,ANSI_TAG_CLASS_CONS,&asn_buf);
				tcap_send_info("Response_Ansi sent to sccp");
			}
			else
			{
				sccp_ptr->msglen = add_tlv("4",0,temp_buf,0x60,&asn_buf);
				tcap_send_info("End sent to sccp");
			}
			end_ptr = (TREnd_struct *) &tsl_ptr->tsl_prim.tr_end;
//			if (flag)
//				temp_tid = end_ptr->transaction_id | 0x8000;
//			else
				temp_tid = end_ptr->transaction_id;
			memset(temp_buf,0,4);
			len = u32tobcd(temp_buf,temp_tid);	//encode dst TID
			
			if(!flag)
				len = tsl_ptr->peer_tid_len%5;  /* added by Pierre, 2006-08-19 */
			if(len == 0) len = 4;
			
			if (tag_class == ANSI_TAG_CLASS_CONS)
				sccp_ptr->msglen = add_tlv("4.7-1",len,temp_buf,ANSI_TAG_CLASS_PRIM,&asn_buf);
			else
				sccp_ptr->msglen = add_tlv("4.9",len,&temp_buf[4-len],0x40,&asn_buf);
			if (end_ptr->dialogue_len != 0)	// dialogue portion
			{
				if (tag_class == ANSI_TAG_CLASS_CONS)
					sccp_ptr->msglen = add_tlv("4.25-2",end_ptr->dialogue_len,end_ptr->dialogue,ANSI_TAG_CLASS_CONS,&asn_buf);
				else
					sccp_ptr->msglen = add_tlv("4.11",end_ptr->dialogue_len,end_ptr->dialogue,0x60,&asn_buf);
			}
			if (end_ptr->components_len != 0)	// component portion
			{
				if (tag_class == ANSI_TAG_CLASS_CONS)
					sccp_ptr->msglen = add_tlv("4.8-3",end_ptr->components_len,end_ptr->components,ANSI_TAG_CLASS_CONS,&asn_buf);
				else
					sccp_ptr->msglen = add_tlv("4.12",end_ptr->components_len,end_ptr->components,0x60,&asn_buf);
			}
			sprintf((char *)temp_buf, "dtid: %08X, dialogue portion len: %02X, component portion len: %02X\r\n", end_ptr->transaction_id, end_ptr->dialogue_len, end_ptr->components_len);
			tcap_send_info((char *)temp_buf);
			tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][3] ++;
			break;
		case P_Abort:
		case P_Abort_Ansi:
			if (tag_class == ANSI_TAG_CLASS_CONS)
			{
				sccp_ptr->msglen = add_tlv("22",0,temp_buf,ANSI_TAG_CLASS_CONS,&asn_buf);
				tcap_send_info("P_Abort_Ansi sent to sccp");
			}
			else
			{
				sccp_ptr->msglen = add_tlv("7",0,temp_buf,0x60,&asn_buf);
				tcap_send_info("P_Abort sent to sccp");
			}
			pabort_ptr = (TRPAbort_struct *) &tsl_ptr->tsl_prim.tr_pabort;
//			if (flag)
//				temp_tid = pabort_ptr->transaction_id | 0x8000;
//			else
				temp_tid = pabort_ptr->transaction_id;
			memset(temp_buf,0,4);
			len = u32tobcd(temp_buf,temp_tid);	//encode dst TID

			if(!flag)
				len = tsl_ptr->peer_tid_len%5;  /* added by Pierre, 2006-08-19 */
			if(len == 0) len = 4;
				
			if (tag_class == ANSI_TAG_CLASS_CONS)
				sccp_ptr->msglen = add_tlv("22.7-1",len,temp_buf,ANSI_TAG_CLASS_PRIM,&asn_buf);
			else
				sccp_ptr->msglen = add_tlv("7.9",len,temp_buf,0x40,&asn_buf);
			temp_buf[0] = pabort_ptr->abort_reason;
			len = 1;
			if (tag_class == ANSI_TAG_CLASS_CONS)
				sccp_ptr->msglen = add_tlv("22.23-2",len,temp_buf,ANSI_TAG_CLASS_PRIM,&asn_buf);
			else
				sccp_ptr->msglen = add_tlv("7.10",len,temp_buf,0x40,&asn_buf);
			tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][4] ++;
			switch (pabort_ptr->abort_reason)
			{
				case P_Abort_UMT:
					tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][48] ++;
					break;
				case P_Abort_ITP:
					tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][49] ++;
					break;
				case P_Abort_BFTP:
					tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][50] ++;
					break;
				case P_Abort_UTID:
					tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][51] ++;
					break;
				case P_Abort_RL:
					tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][52] ++;
					break;
				default:
					break;
			}
			sprintf((char *)temp_buf, "dtid: %08X, pabort reason: %02X\r\n", pabort_ptr->transaction_id, pabort_ptr->abort_reason);
			tcap_send_info((char *)temp_buf);
			break;
		case U_Abort:
		case U_Abort_Ansi:
			if (tag_class == ANSI_TAG_CLASS_CONS)
			{
				sccp_ptr->msglen = add_tlv("22",0,temp_buf,ANSI_TAG_CLASS_CONS,&asn_buf);
				tcap_send_info("mU_Abort_Ansi sent to sccp");
			}
			else
			{
				sccp_ptr->msglen = add_tlv("7",0,temp_buf,0x60,&asn_buf);
				tcap_send_info("U_Abort sent to sccp");
			}
			uabort_ptr = (TRUAbort_struct *) &tsl_ptr->tsl_prim.tr_uabort;
//			if (flag)
//				temp_tid = uabort_ptr->transaction_id | 0x8000;
//			else
				temp_tid = uabort_ptr->transaction_id;
			memset(temp_buf,0,4);
			len = u32tobcd(temp_buf,temp_tid);	//encode dst TID
			if(!flag)		
				len = tsl_ptr->peer_tid_len%5;  /* added by Pierre, 2006-08-19 */
			if(len == 0) len = 4;
			
			if (tag_class == ANSI_TAG_CLASS_CONS)
				sccp_ptr->msglen = add_tlv("22.7-1",len,temp_buf,ANSI_TAG_CLASS_PRIM,&asn_buf);
			else
				sccp_ptr->msglen = add_tlv("7.9",len,temp_buf,0x40,&asn_buf);
			if (uabort_ptr->dialogue_len != 0)	// dialogue portion
			{
				if (tag_class == ANSI_TAG_CLASS_CONS)
					sccp_ptr->msglen = add_tlv("22.25-2",uabort_ptr->dialogue_len,uabort_ptr->dialogue,ANSI_TAG_CLASS_CONS,&asn_buf);
				else
					sccp_ptr->msglen = add_tlv("7.11",uabort_ptr->dialogue_len,uabort_ptr->dialogue,0x60,&asn_buf);
			}
			if (tag_class == ANSI_TAG_CLASS_CONS)
			{
				sccp_ptr->msglen = add_tlv("22.24-3",uabort_ptr->uabort_info_len,uabort_ptr->uabort_info,ANSI_TAG_CLASS_PRIM,&asn_buf);
				sprintf((char *)temp_buf, "dtid: %08X, dialogue portion len: %02X, uabort info len: %02X\r\n", uabort_ptr->transaction_id, uabort_ptr->dialogue_len, uabort_ptr->uabort_info_len);
			}
			else
				sprintf((char *)temp_buf, "dtid: %08X, dialogue portion len: %02X\r\n", uabort_ptr->transaction_id, uabort_ptr->dialogue_len);
			tcap_send_info((char *)temp_buf);
			tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][4] ++;
			break;
		default:	//unknown message type
			tcap_send_error("TSL encode error. Can not recognize package type");
			return 0;
			break;
	}
	return 1;
}

int extract_acn(u8 *acn,u8 *data,int data_len)
{
	ASN_BUF	asn_buf;
	int		len;
	u8		temp_buf[TCAP_BUF_LEN];

	len = asn_decode(data,1,&asn_buf);
	if (len != data_len)	// data length is wrong
	{
		tcap_send_error("CSL dialogue decode error. ACN structure is error");
		return 0;
	}
	len = get_tlv("6",temp_buf,&asn_buf);	// get Object_Identifier
	if (len == -1 || len > TCAP_ACN_LEN)
	{
		tcap_send_error("CSL dialogue decode error. dialogue portion lack ACN");
		return 0;
	}
	memcpy(acn,temp_buf,len);
	return len;
}

u8 extract_result(u8 *result,u8 *data,int data_len)
{
	ASN_BUF	asn_buf;
	int		len;
	u8		temp_buf[TCAP_BUF_LEN];

	len = asn_decode(data,1,&asn_buf);
	if (len != data_len)
	{
		tcap_send_error("CSL dialogue decode error. Result structure is error");
		return 0;
	}
	len = get_tlv("2",temp_buf,&asn_buf);	// get Integer
	if (len != 1)
	{
		tcap_send_error("CSL dialogue decode error. Result structure is error");
		return 0;
	}
	*result = temp_buf[0];
	return 1;
}

u8 extract_diag(u8 *result,u8 *data,int data_len)	// extract diagnostic
{
	ASN_BUF	asn_buf;
	int		len;
	u8		temp_buf[TCAP_BUF_LEN];
	u8		result_type;

	len = asn_decode(data,1,&asn_buf);
	if (len != data_len)
	{
		tcap_send_error("CSL dialogue decode error. ASN.1 structure is error");
		return 0;
	}
	len = get_tlv("1",temp_buf,&asn_buf);	// check dialogue service user
	if (len != -1)
	{
		result_type = Dialogue_Service_User;
		len = get_tlv("1.2",temp_buf,&asn_buf);
		if (len == 0)
			*result = 0;
		else
			*result = temp_buf[0];
		return result_type;
	}
	len = get_tlv("2",temp_buf,&asn_buf);	// check dialogue service provider
	if (len != -1)
	{
		result_type = Dialogue_Service_Provider;
		len = get_tlv("2.2",temp_buf,&asn_buf);
		if (len == 0)
			*result = 0;
		else
			*result = temp_buf[0];
		return result_type;
	}
	tcap_send_error("CSL dialogue decode error. Can not recognize diagnostic service type");
	return 0;
}

u8 extract_dp(struct dlgPDU_struct *pdu_ptr,u8 *databuf,int datalen,u8 proto_type)	// extract dialogue portion
{
	ASN_BUF	asn_buf;
	int		len;
	int		result;
	u8		id_value_flag = 0;
	struct	AARQ_struct			*aarq_ptr;
	struct	AARE_struct			*aare_ptr;
	struct	ABRT_struct			*abrt_ptr;
	struct	ASUDT_struct		*asudt_ptr;
	u8		asn_data[TCAP_BUF_LEN];
	u8		temp_data[TCAP_BUF_LEN];
	
	memset(pdu_ptr,0,sizeof(dlgPDU_struct));
	if (!proto_type)
		len = asn_decode(databuf,1,&asn_buf);
	else
		len = asn_decode(databuf,5,&asn_buf);
	if (len == -1)	// asn1 decode error
	{
		tcap_send_error("CSL dialogue decode error. ASN.1 structure has error");
		return 0;
	}
	
	if (proto_type)
	{
		result = 0;
		asudt_ptr = (ASUDT_struct *) &pdu_ptr->pdu_union.asudt;
		len = get_tlv("26",temp_data,&asn_buf);	// get protocol version
		if (len == 1)
		{
			asudt_ptr->version = temp_data[0];
			result = 1;
		}
		len = get_tlv("28",temp_data,&asn_buf);	// get object identifier ACN
		if (len != -1)
			asudt_ptr->acn_type = TYPE_OID;
		else
		{
			len = get_tlv("27",temp_data,&asn_buf);	// get integer ACN
			if (len != -1)
				asudt_ptr->acn_type = TYPE_INT;
		}
		if (len > 0)
		{
			asudt_ptr->acn_len = len;
			memcpy(asudt_ptr->acn,temp_data,len);
			result = 1;
		}
		len = get_tlv("29",temp_data,&asn_buf);	// get user information
		if (len != -1)
		{
			asudt_ptr->user_info_len = len;
			memcpy(asudt_ptr->user_info,temp_data,len);
			result = 1;
		}
		len = get_tlv("1",temp_data,&asn_buf);	// get object id security context
		if (len != -1)
			asudt_ptr->security_context_type = TYPE_OID;
		else
		{
			len = get_tlv("0",temp_data,&asn_buf);	// get integer security context
			if (len != -1)
				asudt_ptr->security_context_type = TYPE_INT;
		}
		if (len != -1)
		{
			asudt_ptr->security_context_len = len;
			memcpy(asudt_ptr->security_context,temp_data,len);
			result = 1;
		}
		len = get_tlv("2",temp_data,&asn_buf);	// get confidentiality information
		if (len != -1)
		{
			asudt_ptr->confidential_info_len = len;
			memcpy(asudt_ptr->confidential_info,temp_data,len);
			result = 1;
		}
		if (result)
		{
			pdu_ptr->dialogue_type = PDU_ASUDT;
			return 1;
		}
		else
			return 0;
	}
	else
	{
		len = get_tlv("8",temp_data,&asn_buf);	// get External
		if (len == -1)
		{
			tcap_send_error("CSL dialogue decode error. Lack External structure");
			return 0;
		}
		len = get_tlv("8.6",temp_data,&asn_buf);	// get Object_Identifier
		if (len == -1)	// dialogue-as-ID portion
		{
			tcap_send_error("CSL dialogue decode error. Lack Object identifier");
			return 0;
		}
		if (memcmp(Undialogue_As_ID,temp_data,len) == 0)	// undialogue as id value
			id_value_flag = 2;
		else if (memcmp(Dialogue_As_ID,temp_data,len) == 0)	// dialogue as id value
			id_value_flag = 1;
		else	// unknwn data
		{
			tcap_send_error("CSL dialogue decode error. Dialogue-as-ID value error");
			return 0;
		}
		len = get_tlv("8.0",asn_data,&asn_buf);	// get Single ASN.1 type
		if (len == -1)
		{
			tcap_send_error("CSL dialogue decode error. Lack single ASN.1 structure");
			return 0;
		}
		len = asn_decode(asn_data,1,&asn_buf);
		if (len == -1)
		{
			tcap_send_error("CSL dialogue decode error. ASN.1 structure is error");
			return 0;
		}
		len = get_tlv("0",temp_data,&asn_buf);	// get AARQ dialogue
		if (len != -1)	// has AARQ
		{
			pdu_ptr->dialogue_type = PDU_AARQ;
			aarq_ptr = (AARQ_struct *) &pdu_ptr->pdu_union.aarq;
			memcpy(aarq_ptr->version,Version_1,2);
			len = get_tlv("0.0",temp_data,&asn_buf);	// get protocol version
			if (len != 2)	// lack protocol version or version is error
			{
				temp_data[0] = 0x07;
				temp_data[1] = 0x80;
				tcap_send_error("CSL dialogue decode error. AARQ lack protocol version");
				//return 0;
			}
			memcpy(aarq_ptr->version,temp_data,2);
			len = get_tlv("0.1",temp_data,&asn_buf);	// get ACN
			if (len == -1 || len > TCAP_ACN_LEN)
			{
				tcap_send_error("CSL dialogue decode error. AARQ lack ACN");
				return 0;
			}
			aarq_ptr->acn_len = extract_acn(aarq_ptr->acn,temp_data,len);
			len = get_tlv("0.30",temp_data,&asn_buf);	// get user info
			if (len != -1 && len <= TCAP_USERINFO_LEN)	// has user information
			{
				aarq_ptr->user_info_len = len;
				memcpy(aarq_ptr->user_info,temp_data,len);
			}
			return 1;
		}
		len = get_tlv("1",temp_data,&asn_buf);	// get AARE dialogue
		if (len != -1)	// has AARE
		{
			pdu_ptr->dialogue_type = PDU_AARE;
			aare_ptr = (AARE_struct *) &pdu_ptr->pdu_union.aare;
			memcpy(aare_ptr->version,Version_1,2);
			len = get_tlv("1.0",temp_data,&asn_buf);	// get protocol version
			if (len != 2)	// lack protocol version or version is error
			{
				temp_data[0] = 0x07;
				temp_data[1] = 0x80;
				tcap_send_error("CSL dialogue decode error. AARE lack protocol version");
				//return 0;
			}
			memcpy(aare_ptr->version,temp_data,2);
			len = get_tlv("1.1",temp_data,&asn_buf);	// get ACN
			if (len == -1)
			{
				tcap_send_error("CSL dialogue decode error. AARE lack ACN");
				return 0;
			}
			aare_ptr->acn_len = extract_acn(aare_ptr->acn,temp_data,len);
			len = get_tlv("1.2",temp_data,&asn_buf);	// get result
			if (len == -1)	// has no result
			{
				tcap_send_error("CSL dialogue decode error. AARE lack result");
				return 0;
			}
			if (!extract_result(&aare_ptr->result,temp_data,len))
				return 0;
			len = get_tlv("1.3",temp_data,&asn_buf);	// get source diagnostic
			if (len == -1)
			{
				tcap_send_error("CSL dialogue decode error. AARE lack source diagnostic");
				return 0;
			}
			result = extract_diag(&aare_ptr->diagnostic_type,temp_data,len);
			if (result == 0)
				return 0;
			else
				aare_ptr->diagnostic_flag = result;
			len = get_tlv("1.30",temp_data,&asn_buf);	// get user info
			if (len != -1 && len <= TCAP_USERINFO_LEN)	// has user information
			{
				aare_ptr->user_info_len = len;
				memcpy(aare_ptr->user_info,temp_data,len);
			}
			return 1;
		}
		len = get_tlv("4",temp_data,&asn_buf);	// get ABRT dialogue
		if (len != -1)	// has ABRT
		{
			pdu_ptr->dialogue_type = PDU_ABRT;
			abrt_ptr = (ABRT_struct *) &pdu_ptr->pdu_union.abrt;
			len = get_tlv("4.0",temp_data,&asn_buf);	// get reason
			if (len != 1)	// lack reason
			{
				tcap_send_error("CSL dialogue decode error. ABRT lack reason");
				return 0;
			}
			abrt_ptr->abort_source = temp_data[0];
			len = get_tlv("4.30",temp_data,&asn_buf);	// get user info
			if (len != -1 && len <= TCAP_USERINFO_LEN)	// has user information
			{
				abrt_ptr->user_info_len = len;
				memcpy(abrt_ptr->user_info,temp_data,len);
			}
			return 1;
		}
		tcap_send_error("CSL dialogue decode error. Can not recognize dialogue type");
		return 0;
	}
}

u8 build_dp(u8 *content,struct dlgPDU_struct *dlg_ptr,u8 un_flag,u8 proto_type)	// build dialogue portion
{
	ASN_BUF	asn_buf;
	u8		temp_data[TCAP_BUF_LEN];
	u32		len = 0,len1 = 0;
	struct	AARQ_struct			*aarq_ptr;
	struct	AARE_struct			*aare_ptr;
	struct	ABRT_struct			*abrt_ptr;
	struct	ASUDT_struct		*asudt_ptr;
	
	if (proto_type)
		asn_encode(content,&asn_buf);
	else
		asn_encode(temp_data,&asn_buf);
	switch (dlg_ptr->dialogue_type)	// encode the content of dialogue portion
	{
		case PDU_AARQ:
			aarq_ptr = (AARQ_struct *) &dlg_ptr->pdu_union.aarq;
			len1 = add_tlv("0",0,temp_data,0x60,&asn_buf);
			len1 = add_tlv("0.0",2,aarq_ptr->version,0x80,&asn_buf);
			if (aarq_ptr->acn_len != 0)
			{
				len1 = add_tlv("0.1",0,aarq_ptr->acn,0x0a0,&asn_buf);
				len1 = add_tlv("0.1.6",aarq_ptr->acn_len,aarq_ptr->acn,0x00,&asn_buf);
			}
			if (aarq_ptr->user_info_len != 0)
				len1 = add_tlv("0.30",aarq_ptr->user_info_len,aarq_ptr->user_info,0x0a0,&asn_buf);
			break;
		case PDU_AARE:
			aare_ptr = (AARE_struct *) &dlg_ptr->pdu_union.aare;
			len1 = add_tlv("1",0,temp_data,0x60,&asn_buf);
			len1 = add_tlv("1.0",2,aare_ptr->version,0x80,&asn_buf);
			if (aare_ptr->acn_len != 0)	// encode acn portion
			{
				len1 = add_tlv("1.1",0,aare_ptr->acn,0x0a0,&asn_buf);
				len1 = add_tlv("1.1.6",aare_ptr->acn_len,aare_ptr->acn,0x00,&asn_buf);
			}
			len1 = add_tlv("1.2",0,&aare_ptr->result,0x0a0,&asn_buf);// encode result
			len1 = add_tlv("1.2.2",1,&aare_ptr->result,0x00,&asn_buf);
			len1 = add_tlv("1.3",0,&aare_ptr->diagnostic_flag,0x0a0,&asn_buf);	// encode diagnostic
			if (aare_ptr->diagnostic_flag == Dialogue_Service_Provider)
			{
				len1 = add_tlv("1.3.2",0,&aare_ptr->diagnostic_flag,0x0a0,&asn_buf);
				len1 = add_tlv("1.3.2.2",1,&aare_ptr->diagnostic_type,0x00,&asn_buf);
			}
			else
			{
				len1 = add_tlv("1.3.1",0,&aare_ptr->diagnostic_flag,0x0a0,&asn_buf);
				len1 = add_tlv("1.3.1.2",1,&aare_ptr->diagnostic_type,0x00,&asn_buf);
			}
			if (aare_ptr->user_info_len != 0)
				len1 = add_tlv("1.30",aare_ptr->user_info_len,aare_ptr->user_info,0x0a0,&asn_buf);
			break;
		case PDU_ABRT:
			abrt_ptr = (ABRT_struct *) &dlg_ptr->pdu_union.abrt;
			len1 = add_tlv("4",0,temp_data,0x60,&asn_buf);
			len1 = add_tlv("4.0",1,&abrt_ptr->abort_source,0x80,&asn_buf);
			if (abrt_ptr->user_info_len != 0)
				len1 = add_tlv("4.30",abrt_ptr->user_info_len,abrt_ptr->user_info,0x0a0,&asn_buf);
			break;
		case PDU_ASUDT:
			asudt_ptr = (ASUDT_struct *) &dlg_ptr->pdu_union.asudt;
			len1 = add_tlv("26-1",1,&asudt_ptr->version,ANSI_TAG_CLASS_PRIM,&asn_buf);
			if (asudt_ptr->acn_len > 0)
			{
				if (asudt_ptr->acn_type == TYPE_OID)	// object id acn
					len1 = add_tlv("28-2",asudt_ptr->acn_len,asudt_ptr->acn,ANSI_TAG_CLASS_PRIM,&asn_buf);
				else
					len1 = add_tlv("27-2",asudt_ptr->acn_len,asudt_ptr->acn,ANSI_TAG_CLASS_PRIM,&asn_buf); 
			}
			if (asudt_ptr->user_info_len > 0)
				len1 = add_tlv("29-3",asudt_ptr->user_info_len,asudt_ptr->user_info,ANSI_TAG_CLASS_PRIM,&asn_buf); 
			if (asudt_ptr->security_context_len > 0)
			{
				if (asudt_ptr->security_context_type == TYPE_OID)	// object id security context
					len1 = add_tlv("1-4",asudt_ptr->security_context_len,asudt_ptr->security_context,0x80,&asn_buf);
				else
					len1 = add_tlv("0-4",asudt_ptr->security_context_len,asudt_ptr->security_context,0x80,&asn_buf);
			}
			if (asudt_ptr->confidential_info_len > 0)
				len1 = add_tlv("2-5",asudt_ptr->confidential_info_len,asudt_ptr->confidential_info,0xA0,&asn_buf); 
			return len1;
			break;
		default:
			tcap_send_error("CSL dialogue encode error. Can not recognize dialogue type");
			return 0;
			break;
	}
	asn_encode(content,&asn_buf);
	len = add_tlv("8",0,temp_data,0x20,&asn_buf);
	if (un_flag == 1)	// unidirectional dialogue
		len = add_tlv("8.6-1",7,Undialogue_As_ID,0x00,&asn_buf);
	else
		len = add_tlv("8.6-1",7,Dialogue_As_ID,0x00,&asn_buf);
	len = add_tlv("8.0-2",len1,temp_data,0x0a0,&asn_buf);
	return len;
}

int extract_component(struct CSLcmp_struct *cmp_ptr,u8 *data_buf,u32 proc,int *section_len)	// extract component portion
{
	ASN_BUF	asn_buf;
	int		len,len1=0,len2=0;
	u8		temp_buf[TCAP_BUF_LEN],temp_buf1[TCAP_BUF_LEN];
	u8		tag1;
	char	tlv1[32];
	struct	TCInvoke_struct		*invoke_ptr;
	struct	TCResult_struct		*result_ptr;
	struct	TCUError_struct		*uerror_ptr;
	struct	TCReject_struct		*reject_ptr;
	int		result;
	u8		tag_class;
	u16		tag_code;

	cmp_ptr->dialogue_id = proc;
	cmp_ptr->invoke_id = 0xff;
	cmp_ptr->message_flag = INDICATE;
	result = asn_decode_v2(data_buf,1,section_len,&asn_buf);
	if (*section_len == -1)
	{
		tcap_send_error("CSL component decode length error. ASN.1 structure is error");
		return 0;	// 0 indicate that the syntax is error
	}
	if (result == -1)
		tcap_send_error("CSL component decode error. ASN.1 structure is error");
	
	len1 = GetAnyTLV("1",TCAP_BUF_LEN,temp_buf1,&tag_class,&tag_code,&asn_buf);	// get invoke
	if (len1 == -1)
	{
		len1 = GetAnyTLV("9",TCAP_BUF_LEN,temp_buf1,&tag_class,&tag_code,&asn_buf);	// get Invoke_L_Ansi
		if (len1 == -1)
			len1 = GetAnyTLV("13",TCAP_BUF_LEN,temp_buf1,&tag_class,&tag_code,&asn_buf);	// get Invoke_NL_Ansi
	}
	if (len1 != -1)	// has invoke
	{
		tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][15] ++;
		if (tag_code == 1)
			cmp_ptr->message_type = Invoke;
		else if (tag_code == 9)
			cmp_ptr->message_type = Invoke_L_Ansi;
		else
			cmp_ptr->message_type = Invoke_NL_Ansi;
		invoke_ptr = (TCInvoke_struct *) &cmp_ptr->cmp_prim.tc_invoke;
		if (tag_class != ANSI_TAG_CLASS_CONS)
		{
			len = get_tlv("1.2-1",temp_buf,&asn_buf);	// get invoke id
			if (len != 1)	// has no invoke id
			{
				tcap_send_error("CSL component decode error. Invoke primitive lack invoke id");
				return 0;
			}
			len2 += 3;
			cmp_ptr->invoke_id = temp_buf[0];
			tag1 = 2;
			len = get_tlv("1.0",temp_buf,&asn_buf);	// get linked id
			if (len != -1)
			{
				if (len != 1)
				{
					tcap_send_error("CSL component decode error. Invoke primitive has error linked id");
					return 0;
				}
				//invoke_ptr->linkedid_flag = 1;
				invoke_ptr->linked_id = temp_buf[0];
				tag1 ++;
				len2 += 3;
			}
			sprintf(tlv1,"1.2-%d\n",tag1);
			len = get_tlv(tlv1,temp_buf,&asn_buf);	// get operation code
			if (len != 1)	// has no operation code
			{
				len = get_tlv("1.6",temp_buf,&asn_buf);
				if (len != 1)
				{
					tcap_send_error("CSL component decode error. Invoke primitive lack operation code");
					return 0;
				}
			}
			invoke_ptr->operation_code = temp_buf[0];
			len2 += 3;
		}
		else
		{
			if (tag_code == 9)
				len = get_tlv("9.15",temp_buf,&asn_buf);	// get invoke id
			else
				len = get_tlv("13.15",temp_buf,&asn_buf);
			if (len == -1)	// has no invoke id
			{	// Mandatory when Correlation ID present or if reply expected
				tcap_send_error("CSL component decode error. Ansi Invoke primitive lack invoke id");
				return 0;
			}
			else
			{
				len2 += 3;
				cmp_ptr->invoke_id = temp_buf[0];
				if (len == 2)
				{
					//invoke_ptr->linkedid_flag = 1;
					invoke_ptr->linked_id = temp_buf[1];
					len2++;
				}
			}
			if (tag_code == 9)
			{
				len = get_tlv("9.17",temp_buf,&asn_buf);	// get private operation code
				if (len != -1)
					invoke_ptr->operation_domain = TYPE_PRIVATE;
				else
				{
					len = get_tlv("9.16",temp_buf,&asn_buf);	// get national operation code
					if (len != -1)
						invoke_ptr->operation_domain = TYPE_NATIONAL;
				}
			}
			else
			{
				len = get_tlv("13.17",temp_buf,&asn_buf);	// get private operation code
				if (len != -1)
					invoke_ptr->operation_domain = TYPE_PRIVATE;
				else
				{
					len = get_tlv("13.16",temp_buf,&asn_buf);	// get national operation code
					if (len != -1)
						invoke_ptr->operation_domain = TYPE_NATIONAL;
				}
			}
			if (len == -1)
			{
				tcap_send_error("CSL component decode error. Ansi Invoke primitive lack operation code");
				return 0;
			}
			invoke_ptr->operation_family = temp_buf[0];
			invoke_ptr->operation_code = temp_buf[1];
			len2 += 4;
		}
		if (len1 > len2)
		{
			invoke_ptr->parameter_len = len1 - len2;
			memcpy(invoke_ptr->parameter,temp_buf1+len2,len1-len2);
		}
		else
			invoke_ptr->parameter_len = 0;
		return 1;
	}
	
	len = GetAnyTLV("2",TCAP_BUF_LEN,temp_buf1,&tag_class,&tag_code,&asn_buf);	// get return result
	if (len == -1)
	{
		len = GetAnyTLV("7",TCAP_BUF_LEN,temp_buf1,&tag_class,&tag_code,&asn_buf);	// get return result not last
		if (len == -1)
		{
			len = GetAnyTLV("10",TCAP_BUF_LEN,temp_buf1,&tag_class,&tag_code,&asn_buf);	// get Result_L_Ansi
			if (len == -1)
				len = GetAnyTLV("14",TCAP_BUF_LEN,temp_buf1,&tag_class,&tag_code,&asn_buf);	// get Result_NL_Ansi
		}
	}
	if (len != -1)	// has return result
	{
		tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][16] ++;
		if (tag_code == 2)
			cmp_ptr->message_type = Result_L;
		else if (tag_code == 7)
			cmp_ptr->message_type = Result_NL;
		else if (tag_code == 10)
			cmp_ptr->message_type = Result_L_Ansi;
		else
			cmp_ptr->message_type = Result_NL_Ansi;
		result_ptr = (TCResult_struct *) &cmp_ptr->cmp_prim.tc_result;
		if (tag_class != ANSI_TAG_CLASS_CONS)
		{
			len = get_tlv("2.2",temp_buf,&asn_buf);	// get invoke id
			if (len != 1)	// has no invoke id
			{
				tcap_send_error("CSL component decode error. Result last primitive lack invoke id");
				return 0;
			}
			cmp_ptr->invoke_id = temp_buf[0];
			len1 = get_tlv("2.16",temp_buf,&asn_buf);	// get SEQUENCE
			if (len1 != -1)
			{
				len = get_tlv("2.16.2",temp_buf,&asn_buf);	// operation code, just one byte
				if (len != 1)
				{
					len = get_tlv("2.16.6",temp_buf,&asn_buf);
					if (len != 1)
					{
						tcap_send_error("CSL component decode error. Result primitive lack operation code");
						return 0;
					}
				}
				result_ptr->operation_flag = 1;
				result_ptr->operation_code = temp_buf[0];
				if (len1 <= 3)
				{
					result_ptr->parameter_len = 0;
					tcap_send_error("CSL component decode error. Result primitive lack parameter");
					return 0;
				}
				len = len1 - 3;
				result_ptr->parameter_len = len;
				memcpy(result_ptr->parameter,temp_buf+3,len);
			}
			return 1;
		}
		else
		{
			if (tag_code == 10)
				len1 = get_tlv("10.15",temp_buf,&asn_buf);	// get invoke id
			else
				len1 = get_tlv("14.15",temp_buf,&asn_buf);
			if (len1 != 1)	// has no invoke id
			{
				tcap_send_error("CSL component decode error. Ansi return result primitive lack invoke id");
				return 0;
			}
			else
			{
				cmp_ptr->invoke_id = temp_buf[0];
				len2 += 3;
			}
			if (len > len2)
			{
				result_ptr->parameter_len = len - len2;
				memcpy(result_ptr->parameter,temp_buf1+len2,len-len2);
			}
			return 1;
		}
	}
	
	len1 = GetAnyTLV("3",TCAP_BUF_LEN,temp_buf1,&tag_class,&tag_code,&asn_buf);	// get return error
	if (len1 == -1)
		len1 = GetAnyTLV("11",TCAP_BUF_LEN,temp_buf1,&tag_class,&tag_code,&asn_buf);	// get Error_Ansi
	if (len1 != -1)	// has return error
	{
		tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][17] ++;
		if (tag_code == 3)
			cmp_ptr->message_type = Error;
		else
			cmp_ptr->message_type = Error_Ansi;
		uerror_ptr = (TCUError_struct *) &cmp_ptr->cmp_prim.tc_uerror;
		if (tag_class != ANSI_TAG_CLASS_CONS)
		{
			len = get_tlv("3.2-1",temp_buf,&asn_buf);	// get invoke id
			if (len != 1)	// has no invoke id
			{
				tcap_send_error("CSL component decode error. Error primitive lack invoke id");
				return 0;
			}
			cmp_ptr->invoke_id = temp_buf[0];
			len2 = 3;
			len = get_tlv("3.2-2",temp_buf,&asn_buf);	// get error code
			if (len == 1)	// success
				uerror_ptr->error_type = Local_Error_Code;
			else
			{
				len = get_tlv("3.6",temp_buf,&asn_buf);
				if (len != 1)
				{
					tcap_send_error("CSL component decode error. Error primitive lack error code");
					return 0;
				}
				uerror_ptr->error_type = Global_Error_Code;
			}
			uerror_ptr->error_code = temp_buf[0];
			len2 = 3;
			if (len1 > len2)
			{
				uerror_ptr->parameter_len = len1 - len2;
				memcpy(uerror_ptr->parameter,temp_buf1+len2,len1-len2);
			}
			else
				uerror_ptr->parameter_len = 0;
			return 1;
		}
		else
		{
			len = get_tlv("11.15",temp_buf,&asn_buf);	// get invoke id
			if (len != 1)	// has no invoke id
			{
				tcap_send_error("CSL component decode error. Ansi return error primitive lack invoke id");
				return 0;
			}
			else
			{
				cmp_ptr->invoke_id = temp_buf[0];
				len2 += 3;
			}
			len = get_tlv("11.20",temp_buf,&asn_buf);	// get private error code
			if (len != -1)
				uerror_ptr->error_type = TYPE_PRIVATE;
			else
			{
				len = get_tlv("11.19",temp_buf,&asn_buf);	// get national error code
				if (len != -1)
					uerror_ptr->error_type = TYPE_NATIONAL;
			}
			if (len != 1)
			{
				tcap_send_error("CSL component decode error. Ansi Error primitive lack error code");
				return 0;
			}
			else
			{
				uerror_ptr->error_code = temp_buf[0];
				len2 += 3;
			}
			if (len1 > len2)
			{
				uerror_ptr->parameter_len = len1 - len2;
				memcpy(uerror_ptr->parameter,temp_buf1+len2,len1-len2);
			}
			else
				uerror_ptr->parameter_len = 0;
			return 1;
		}
	}
	
	len1 = GetAnyTLV("4",TCAP_BUF_LEN,temp_buf1,&tag_class,&tag_code,&asn_buf);	// get reject
	if (len1 == -1)
		len1 = GetAnyTLV("12",TCAP_BUF_LEN,temp_buf1,&tag_class,&tag_code,&asn_buf);	// get Reject_Ansi
	if (len1 != -1)	// has reject
	{
		tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][18] ++;
		tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][74] ++;
		if (tag_code == 4)
			cmp_ptr->message_type = Reject;
		else
			cmp_ptr->message_type = Reject_Ansi;
		reject_ptr = (TCReject_struct *) &cmp_ptr->cmp_prim.tc_reject;
		if (tag_class != ANSI_TAG_CLASS_CONS)
		{
			len = get_tlv("4.2-1",temp_buf,&asn_buf);	// get invoke id
			if (len != 1)	// has no invoke id
			{
				len = get_tlv("4.5",temp_buf,&asn_buf);	// get Invoke_ID_NULL
				if (len != 1)
				{
					tcap_send_error("CSL component decode error. Reject primitive lack invoke id");
					return 0;
				}
				temp_buf[0] = 0xff;
			}
			cmp_ptr->invoke_id = temp_buf[0];
			len = get_tlv("4.0",temp_buf,&asn_buf);	// get general problem
			if (len == 1)
			{
				reject_ptr->problem_type = General_Problem;
				reject_ptr->problem_code = temp_buf[0];
				switch (temp_buf[0])
				{
					case General_Problem_UC:
						tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][30] ++;
						break;
					case General_Problem_MC:
						tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][31] ++;
						break;
					case General_Problem_BSC:
						tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][32] ++;
						break;
					default:
						break;
				}
				return 1;
			}
			len = get_tlv("4.1",temp_buf,&asn_buf);	// get invoke problem
			if (len == 1)
			{
				reject_ptr->problem_type = Invoke_Problem;
				reject_ptr->problem_code = temp_buf[0];
				switch (temp_buf[0])
				{
					case Invoke_Problem_ULID:
						tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][33] ++;
						break;
					case Invoke_Problem_DIID:
						tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][38] ++;
						break;
					case Invoke_Problem_UO:
						tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][39] ++;
						break;
					case Invoke_Problem_MP:
						tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][40] ++;
						break;
					case Invoke_Problem_IR:
						tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][41] ++;
						break;
					case Invoke_Problem_LRU:
						tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][42] ++;
						break;
					case Invoke_Problem_ULO:
						tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][43] ++;
						break;
					default:
						break;
				}
				return 1;
			}
			len = get_tlv("4.2-2",temp_buf,&asn_buf);	// get return result problem
			if (len == 1)
			{
				reject_ptr->problem_type = Return_Result;
				reject_ptr->problem_code = temp_buf[0];
				switch (temp_buf[0])
				{
					case Return_Result_UIID:
						tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][34] ++;
						break;
					case Return_Result_RRU:
						tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][35] ++;
						break;
					case Return_Result_MP:
						tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][46] ++;
						break;
					default:
						break;
				}
				return 1;
			}
			len = get_tlv("4.3",temp_buf,&asn_buf);	// get return error problem
			if (len == 1)
			{
				reject_ptr->problem_type = Return_Error;
				reject_ptr->problem_code = temp_buf[0];
				switch (temp_buf[0])
				{
					case Return_Error_UIID:
						tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][36] ++;
						break;
					case Return_Error_REU:
						tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][37] ++;
						break;
					case Return_Error_URE:
						tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][44] ++;
						break;
					case Return_Error_UEE:
						tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][45] ++;
						break;
					case Return_Error_MP:
						tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][47] ++;
						break;
					default:
						break;
				}
				return 1;
			}
			tcap_send_error("CSL component decode error. Reject primitive lack problem type");
			return 0;
		}
		else
		{
			len = get_tlv("12.15",temp_buf,&asn_buf);	// get invoke id
			if (len != 1)	// has no invoke id
			{
				tcap_send_error("CSL component decode error. Ansi Reject primitive lack invoke id");
				return 0;
			}
			else
			{
				cmp_ptr->invoke_id = temp_buf[0];
				len2 += 3;
			}
			len = get_tlv("12.21",temp_buf,&asn_buf);	// get problem code
			if (len != 2)
			{
				tcap_send_error("CSL component decode error. Ansi reject primitive lack problem code");
				return 0;
			}
			else
			{	
				reject_ptr->problem_type = temp_buf[0];
				reject_ptr->problem_code = temp_buf[1];
				len2 += 4;
			}
			if (len1 > len2)
			{
				reject_ptr->parameter_len = len1 - len2;
				memcpy(reject_ptr->parameter,temp_buf1+len2,len1-len2);
			}
			else
				reject_ptr->parameter_len = 0;
			switch (temp_buf[0])
			{
				case General_Problem_Ansi:
					switch (temp_buf[1])
					{
						case General_Problem_UC_Ansi:
							tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][30] ++;
							break;
						case General_Problem_MC_Ansi:
							tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][31] ++;
							break;
						case General_Problem_BSC_Ansi:
							tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][32] ++;
							break;
						default:
							break;
					}
					return 1;
					break;
				case Invoke_Problem_Ansi:
					switch (temp_buf[1])
					{
						case Invoke_Problem_ULID_Ansi:
							tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][33] ++;
							break;
						case Invoke_Problem_DIID_Ansi:
							tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][38] ++;
							break;
						case Invoke_Problem_UO_Ansi:
							tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][39] ++;
							break;
						case Invoke_Problem_MP_Ansi:
							tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][40] ++;
							break;
						default:
							break;
					}
					return 1;
					break;
				case Return_Result_Ansi:
					switch (temp_buf[1])
					{
						case Return_Result_UIID_Ansi:
							tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][34] ++;
							break;
						case Return_Result_RRU_Ansi:
							tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][35] ++;
							break;
						case Return_Result_MP_Ansi:
							tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][46] ++;
							break;
						default:
							break;
					}
					return 1;
					break;
				case Return_Error_Ansi:
					switch (temp_buf[1])
					{
						case Return_Error_UIID_Ansi:
							tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][36] ++;
							break;
						case Return_Error_REU_Ansi:
							tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][37] ++;
							break;
						case Return_Error_URE_Ansi:
							tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][44] ++;
							break;
						case Return_Error_UEE_Ansi:
							tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][45] ++;
							break;
						case Return_Error_MP_Ansi:
							tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][47] ++;
							break;
						default:
							break;
					}
					return 1;
					break;
				case Transaction_Ansi:
					return 1;
					break;
			}
			tcap_send_error("CSL component decode error. Ansi Reject primitive lack problem type");
			return 0;
		}
	}
	
	tcap_send_error("CSL component decode error. Can not recognize message type");
	return 0;
}

u8 assemble_param(u8 *data_buf,u8 *string,u8 str_len,u8 opr_code,u8 opr_family,u8 opr_domain,u8 proto_type)
{
	ASN_BUF		asn_buf;
	int			len = 0;
	u8			temp_buf[8];
	
	asn_encode(data_buf,&asn_buf);
	if (!proto_type)
		len = add_tlv("2",1,&opr_code,0x00,&asn_buf);
	else
	{
		temp_buf[0] = opr_family;
		temp_buf[1] = opr_code;
		if (opr_domain)
			len = add_tlv("17",2,temp_buf,ANSI_TAG_CLASS_PRIM,&asn_buf);
		else
			len = add_tlv("16",2,temp_buf,ANSI_TAG_CLASS_PRIM,&asn_buf);
	}
	if (str_len != 0)
	{
		memcpy(data_buf+len,string,str_len);
		len += str_len;
	}
	return len;
}

int assemble_component(u8 *string,struct CSLcmp_struct *cha_ptr)	// assemble component portion
{
	ASN_BUF	asn_buf;
	u8		temp_data[TCAP_BUF_LEN],temp_str[TCAP_BUF_LEN];
	u32		len = 0,temp_len;
	struct	TCInvoke_struct		*invoke_ptr;
	struct	TCResult_struct		*result_ptr;
	struct	TCUError_struct		*uerror_ptr;
	struct	TCReject_struct		*reject_ptr;
	u8		proto_type;
	
	if ((cha_ptr->message_type & 0xE0) == ANSI_TAG_CLASS_CONS)
		proto_type = ANSI_TCAP;
	else
		proto_type = ITU_TCAP;
	switch (cha_ptr->message_type)
	{
		case Invoke:
		case Invoke_L_Ansi:
		case Invoke_NL_Ansi:
			tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][10] ++;
			invoke_ptr = (TCInvoke_struct *) &cha_ptr->cmp_prim.tc_invoke;
			asn_encode(temp_data,&asn_buf);
			if (!proto_type)
			{
				temp_len = add_tlv("2-1",1,&cha_ptr->invoke_id,0x00,&asn_buf);
				if (invoke_ptr->linkedid_flag ==1)	// has linked id
					temp_len = add_tlv("0-2",1,&invoke_ptr->linked_id,0x80,&asn_buf);
				len = assemble_param(string,invoke_ptr->parameter,invoke_ptr->parameter_len,
						invoke_ptr->operation_code,invoke_ptr->operation_family,invoke_ptr->operation_domain,proto_type);
				memcpy(temp_data+temp_len,string,len);
				temp_len += len;
				asn_encode(string,&asn_buf);
				len = add_tlv("1",temp_len,temp_data,0x0a0,&asn_buf);
			}
			else
			{
				temp_len = add_tlv("15",1,&cha_ptr->invoke_id,ANSI_TAG_CLASS_PRIM,&asn_buf);
				len = assemble_param(string,invoke_ptr->parameter,invoke_ptr->parameter_len,
						invoke_ptr->operation_code,invoke_ptr->operation_family,invoke_ptr->operation_domain,proto_type);
				memcpy(temp_data+temp_len,string,len);
				temp_len += len;
				asn_encode(string,&asn_buf);
				if (cha_ptr->message_type == Invoke_L_Ansi)
					len = add_tlv("9",temp_len,temp_data,ANSI_TAG_CLASS_CONS,&asn_buf);
				else
					len = add_tlv("13",temp_len,temp_data,ANSI_TAG_CLASS_CONS,&asn_buf);
			}
			break;
		case Result_L:
		case Result_NL:
		case Result_L_Ansi:
		case Result_NL_Ansi:
			tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][11] ++;
			result_ptr = (TCResult_struct *) &cha_ptr->cmp_prim.tc_result;
			asn_encode(temp_data,&asn_buf);
			if (!proto_type)
			{
				temp_len = add_tlv("2",1,&cha_ptr->invoke_id,0x00,&asn_buf);
				if (result_ptr->parameter_len > 0)
				{
					len = assemble_param(temp_str,result_ptr->parameter,result_ptr->parameter_len,
							result_ptr->operation_code,result_ptr->operation_family,result_ptr->operation_domain,proto_type);
					asn_encode(string,&asn_buf);
					len = add_tlv("16",len,temp_str,0x20,&asn_buf);
				}
				memcpy(temp_data+temp_len,string,len);
				temp_len += len;
				asn_encode(string,&asn_buf);
				if (cha_ptr->message_type == Result_L)
					len = add_tlv("2",temp_len,temp_data,0x0a0,&asn_buf);	// add result last
				else
					len = add_tlv("7",temp_len,temp_data,0x0a0,&asn_buf);	// add result not last
			}
			else
			{
				temp_len = add_tlv("15",1,&cha_ptr->invoke_id,ANSI_TAG_CLASS_PRIM,&asn_buf);
				memcpy(temp_data+temp_len,result_ptr->parameter,result_ptr->parameter_len);
				temp_len += result_ptr->parameter_len;
				asn_encode(string,&asn_buf);
				if (cha_ptr->message_type == Result_L_Ansi)
					len = add_tlv("10",temp_len,temp_data,ANSI_TAG_CLASS_CONS,&asn_buf);
				else
					len = add_tlv("14",temp_len,temp_data,ANSI_TAG_CLASS_CONS,&asn_buf);
			}
			break;
		case Error:
		case Error_Ansi:
			tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][12] ++;
			uerror_ptr = (TCUError_struct *) &cha_ptr->cmp_prim.tc_uerror;
			asn_encode(temp_data,&asn_buf);
			if (!proto_type)
			{
				temp_len = add_tlv("2",1,&cha_ptr->invoke_id,0x00,&asn_buf);
				asn_encode(string,&asn_buf);
				if (uerror_ptr->error_type == Local_Error_Code)
					len = add_tlv("2",1,&uerror_ptr->error_code,0x00,&asn_buf);
				else
					len = add_tlv("6",1,&uerror_ptr->error_code,0x00,&asn_buf);
				if (uerror_ptr->parameter_len != 0)
				{
					memcpy(string+len,uerror_ptr->parameter,uerror_ptr->parameter_len);
					len += uerror_ptr->parameter_len;
				}
				memcpy(temp_data+temp_len,string,len);
				temp_len += len;
				asn_encode(string,&asn_buf);
				len = add_tlv("3",temp_len,temp_data,0x0a0,&asn_buf);	// add result error
			}
			else
			{
				temp_len = add_tlv("15",1,&cha_ptr->invoke_id,ANSI_TAG_CLASS_PRIM,&asn_buf);
				if (uerror_ptr->error_type)
					temp_len = add_tlv("20",1,&uerror_ptr->error_code,ANSI_TAG_CLASS_PRIM,&asn_buf);
				else
					temp_len = add_tlv("19",1,&uerror_ptr->error_code,ANSI_TAG_CLASS_PRIM,&asn_buf);
				memcpy(temp_data+temp_len,uerror_ptr->parameter,uerror_ptr->parameter_len);
				temp_len += uerror_ptr->parameter_len;
				asn_encode(string,&asn_buf);
				len = add_tlv("11",temp_len,temp_data,ANSI_TAG_CLASS_CONS,&asn_buf);
			}
			break;
		case Reject:
		case Reject_Ansi:
			tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][13] ++;
			reject_ptr = (TCReject_struct *) &cha_ptr->cmp_prim.tc_reject;
			if (!proto_type)
				asn_encode(string,&asn_buf);
			else
				asn_encode(temp_data,&asn_buf);
			if (!proto_type)
			{
				len = add_tlv("4",0,temp_data,0x0a0,&asn_buf);	// add result reject
				if (cha_ptr->invoke_id != 0xff)
					len = add_tlv("4.2-1",1,&cha_ptr->invoke_id,0x00,&asn_buf);
				else
					len = add_null("4.5-1",0x00,&asn_buf);
				switch (reject_ptr->problem_type)
				{
					case General_Problem:
						len = add_tlv("4.0-2",1,&reject_ptr->problem_code,0x80,&asn_buf);
						switch (reject_ptr->problem_code)
						{
							case General_Problem_UC:
								tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][53] ++;
								break;
							case General_Problem_MC:
								tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][54] ++;
								break;
							case General_Problem_BSC:
								tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][55] ++;
								break;
							default:
								break;
						}
						break;
					case Invoke_Problem:
						len = add_tlv("4.1-2",1,&reject_ptr->problem_code,0x80,&asn_buf);
						switch (reject_ptr->problem_code)
						{
							case Invoke_Problem_DIID:
								tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][61] ++;
								break;
							case Invoke_Problem_UO:
								tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][62] ++;
								break;
							case Invoke_Problem_MP:
								tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][63] ++;
								break;
							case Invoke_Problem_IR:
								tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][64] ++;
								break;
							case Invoke_Problem_ULID:
								tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][56] ++;
								break;
							case Invoke_Problem_LRU:
								tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][65] ++;
								break;
							case Invoke_Problem_ULO:
								tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][66] ++;
								break;
							default:
								break;
						}
						break;
					case Return_Result:
						len = add_tlv("4.2-2",1,&reject_ptr->problem_code,0x80,&asn_buf);
						switch (reject_ptr->problem_code)
						{
							case Return_Result_UIID:
								tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][57] ++;
								break;
							case Return_Result_RRU:
								tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][58] ++;
								break;
							case Return_Result_MP:
								tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][69] ++;
								break;
							default:
								break;
						}
						break;
					default:
						len = add_tlv("4.3-2",1,&reject_ptr->problem_code,0x80,&asn_buf);
						switch (reject_ptr->problem_code)
						{
							case Return_Error_UIID:
								tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][59] ++;
								break;
							case Return_Error_REU:
								tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][60] ++;
								break;
							case Return_Error_URE:
								tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][67] ++;
								break;
							case Return_Error_UEE:
								tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][68] ++;
								break;
							case Return_Error_MP:
								tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][70] ++;
								break;
							default:
								break;
						}
						break;
				}
			}
			else
			{
				temp_len = add_tlv("15",1,&cha_ptr->invoke_id,ANSI_TAG_CLASS_PRIM,&asn_buf);
				temp_str[0] = reject_ptr->problem_type;
				temp_str[1] = reject_ptr->problem_code;
				temp_len = add_tlv("21",2,temp_str,ANSI_TAG_CLASS_PRIM,&asn_buf);
				memcpy(temp_data+temp_len,reject_ptr->parameter,reject_ptr->parameter_len);
				temp_len += reject_ptr->parameter_len;
				asn_encode(string,&asn_buf);
				len = add_tlv("12",temp_len,temp_data,ANSI_TAG_CLASS_CONS,&asn_buf);
				switch (reject_ptr->problem_type)
				{
					case General_Problem_Ansi:
						switch (reject_ptr->problem_code)
						{
							case General_Problem_UC_Ansi:
								tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][53] ++;
								break;
							case General_Problem_MC_Ansi:
								tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][54] ++;
								break;
							case General_Problem_BSC_Ansi:
								tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][55] ++;
								break;
							default:
								break;
						}
						break;
					case Invoke_Problem_Ansi:
						switch (reject_ptr->problem_code)
						{
							case Invoke_Problem_DIID_Ansi:
								tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][61] ++;
								break;
							case Invoke_Problem_UO_Ansi:
								tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][62] ++;
								break;
							case Invoke_Problem_MP_Ansi:
								tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][63] ++;
								break;
							case Invoke_Problem_ULID_Ansi:
								tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][56] ++;
								break;
							default:
								break;
						}
						break;
					case Return_Result_Ansi:
						switch (reject_ptr->problem_code)
						{
							case Return_Result_UIID_Ansi:
								tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][57] ++;
								break;
							case Return_Result_RRU_Ansi:
								tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][58] ++;
								break;
							case Return_Result_MP_Ansi:
								tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][69] ++;
								break;
							default:
								break;
						}
						break;
					default:
						switch (reject_ptr->problem_code)
						{
							case Return_Error_UIID_Ansi:
								tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][59] ++;
								break;
							case Return_Error_REU_Ansi:
								tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][60] ++;
								break;
							case Return_Error_URE_Ansi:
								tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][67] ++;
								break;
							case Return_Error_UEE_Ansi:
								tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][68] ++;
								break;
							case Return_Error_MP_Ansi:
								tcap_ptr->tcap_debug.tc_utilize[TCAP_UTILIZE_COUNT-1][70] ++;
								break;
							default:
								break;
						}
						break;
				}
			}
			break;
		default:
			tcap_send_error("CSL component encode error. Can not recognize component type");
			return 0;
			break;
	}
	return len;
}
/*@end@*/
