/*	XAP provider c file					*/
/*	Written by Liu Zhiguo 2003-03-12	*/
/*	Version 1.0							*/
/*	--------------------------------	*/


#include "xap_provider.h"
#include "xap_monitor.h"
#include "../../tcap/src/include/itcap.h"
#include "../../tcap/src/include/idmanage.h"


struct xap_acn_info		map_acn_buf;
struct xap_acn_info		cap_acn_buf;
struct xap_opr_info		map_opr_buf;
struct xap_opr_info		cap_opr_buf;
struct xap_opr_info		is41_opr_buf;

extern char	tcap_pabort_desc[7][64];
extern char	tcap_uabort_desc[3][32];

/** extern function **/
extern void is41_init();
#if _SUPPORT_ANSI
extern u8	map_check_map_flag(u32 did);
#endif

u8 init_is41const(void)
{
#if _SUPPORT_ANSI	
	FILE		*fp,*temp_fp;
	char		oprfile_name[32]="conf/is41_operation.conf";
	char		string[256];
	char		temp[256];
	char		*ch_ptr;
	int			ii,jj;
#endif

	is41_init();//init is41 coding

#if _SUPPORT_ANSI

	fp = fopen(oprfile_name,"r");		// read operation code file
	if (fp == NULL)
	{
		xap_send_error("XAPP can not open is41 operation code file %s!!\n",oprfile_name);
		return 0;
	}
	temp_fp = fp;
	while(!feof(temp_fp))
	{
		fgets(string,250,temp_fp);
		if (strncmp(string,"total data length=",18) == 0)	// acn total length
		{
			strcpy(temp,(strchr(string,'=')+1));
			is41_opr_buf.buf_len = atol(temp);
			if (is41_opr_buf.buf_len > XAP_OPR_NUM)
			{
				printf("XAPP is41 opration length is larger than expected");
				is41_opr_buf.buf_len = XAP_OPR_NUM;
				return 0;
			}
			break;
		}
	}
	for (ii = 0;ii < is41_opr_buf.buf_len;ii++)
	{
		temp_fp = fp;
		while (!feof(temp_fp))
		{
			fgets(string,250,temp_fp);
			if (strncmp(string,"No.",3) == 0)
			{
				ch_ptr = strchr(string,'.') + 1;
				jj = strlen(ch_ptr) - strlen(strchr(string,':'));
				strncpy(temp,ch_ptr,jj);
				temp[jj] = '\0';
				if (ii != (atol(temp)-1))	// not find data
					continue;
				ch_ptr = strchr(string,':') + 1;
				jj = strlen(ch_ptr) - strlen(strchr(string,' '));
				strncpy(temp,ch_ptr,jj);
				temp[jj] = '\0';
				is41_opr_buf.opr_code[ii] = atol(temp);
				ch_ptr = strchr(string,' ') + 1;
				jj = strlen(ch_ptr) - strlen(strchr(ch_ptr,' '));
				strncpy(temp,ch_ptr,jj);
				temp[jj] = '\0';
				is41_opr_buf.opr_class[ii] = atol(temp);
				ch_ptr = strchr(ch_ptr,' ') + 1;
				jj = strlen(ch_ptr) - strlen(strchr(string,'\t'));
				strncpy(temp,ch_ptr,jj);
				temp[jj] = '\0';
				is41_opr_buf.opr_timer[ii] = atol(temp);
				break;
			}
		}
	}
	fclose(fp);

#endif

	return 1;
}

u8 init_mappconst(void)
{
	FILE		*fp,*temp_fp;
	char		acnfile_name[32]="conf/map_acn.conf";
	char		oprfile_name[32]="conf/map_operation.conf";
	char		string[256];
	char		temp[256];
	char		*ch_ptr;
	int			ii,jj;

	fp = fopen(acnfile_name,"r");		// read acn info
	if (fp == NULL)
	{
		xap_send_error("XAPP can not open ACN file %s!!\n",acnfile_name);
		return 0;
	}
	temp_fp = fp;
	while(!feof(temp_fp))
	{
		fgets(string,250,temp_fp);
		if (strncmp(string,"total data length=",18) == 0)	// acn total length
		{
			strcpy(temp,(strchr(string,'=')+1));
			map_acn_buf.buf_len = atol(temp);
			if (map_acn_buf.buf_len > XAP_ACN_NUM)
			{
				printf("XAPP map acn length is larger than expected!!");
				map_acn_buf.buf_len = XAP_ACN_NUM;
				return 0;
			}
			break;
		}
	}
	for (ii = 0;ii < map_acn_buf.buf_len;ii++)
	{
		temp_fp = fp;
		while (!feof(temp_fp))
		{
			fgets(string,250,temp_fp);
			if (strncmp(string,"No.",3) == 0)
			{
				ch_ptr = strchr(string,'.') + 1;
				jj = strlen(ch_ptr) - strlen(strchr(string,':'));
				strncpy(temp,ch_ptr,jj);
				temp[jj] = '\0';
				if (ii != (atol(temp)-1))	// not find data
					continue;
				ch_ptr = strchr(string,':') + 1;
				jj = strlen(ch_ptr) - strlen(strchr(string,' '));
				strncpy(temp,ch_ptr,jj);
				temp[jj] = '\0';
				map_acn_buf.acn[ii] = atol(temp);
				ch_ptr = strchr(string,' ') + 1;
				jj = strlen(ch_ptr) - strlen(strchr(string,'\t'));
				strncpy(temp,ch_ptr,jj);
				temp[jj] = '\0';
				map_acn_buf.acn_ver[ii] = atol(temp);
				break;
			}
		}
	}
	fclose(fp);

	fp = fopen(oprfile_name,"r");		// read operation code file
	if (fp == NULL)
	{
		xap_send_error("XAPP can not open map operation code file %s!!\n",oprfile_name);
		return 0;
	}
	temp_fp = fp;
	while(!feof(temp_fp))
	{
		fgets(string,250,temp_fp);
		if (strncmp(string,"total data length=",18) == 0)	// acn total length
		{
			strcpy(temp,(strchr(string,'=')+1));
			map_opr_buf.buf_len = atol(temp);
			if (map_opr_buf.buf_len > XAP_OPR_NUM)
			{
				printf("XAPP map opration length is larger than expected");
				map_opr_buf.buf_len = XAP_OPR_NUM;
				return 0;
			}
			break;
		}
	}
	for (ii = 0;ii < map_opr_buf.buf_len;ii++)
	{
		temp_fp = fp;
		while (!feof(temp_fp))
		{
			fgets(string,250,temp_fp);
			if (strncmp(string,"No.",3) == 0)
			{
				ch_ptr = strchr(string,'.') + 1;
				jj = strlen(ch_ptr) - strlen(strchr(string,':'));
				strncpy(temp,ch_ptr,jj);
				temp[jj] = '\0';
				if (ii != (atol(temp)-1))	// not find data
					continue;
				ch_ptr = strchr(string,':') + 1;
				jj = strlen(ch_ptr) - strlen(strchr(string,' '));
				strncpy(temp,ch_ptr,jj);
				temp[jj] = '\0';
				map_opr_buf.opr_code[ii] = atol(temp);
				ch_ptr = strchr(string,' ') + 1;
				jj = strlen(ch_ptr) - strlen(strchr(ch_ptr,' '));
				strncpy(temp,ch_ptr,jj);
				temp[jj] = '\0';
				map_opr_buf.opr_class[ii] = atol(temp);
				ch_ptr = strchr(ch_ptr,' ') + 1;
				jj = strlen(ch_ptr) - strlen(strchr(string,'\t'));
				strncpy(temp,ch_ptr,jj);
				temp[jj] = '\0';
				map_opr_buf.opr_timer[ii] = atol(temp);
				break;
			}
		}
	}
	fclose(fp);

	return 1;
}

u8 init_cappconst(void)
{
	FILE		*fp,*temp_fp;
	char		acnfile_name[32]="conf/cap_acn.conf";
	char		oprfile_name[32]="conf/cap_operation.conf";
	char		string[256];
	char		temp[256];
	char		*ch_ptr;
	int			ii,jj;
	char		info_str[1024];

	fp = fopen(acnfile_name,"r");		// read acn info
	if (fp == NULL)
	{
		sprintf(info_str,"XAPP can not open ACN file %s!!\n",acnfile_name);
		xap_send_error(info_str);
		printf("%s",info_str);
		return 0;
	}
	temp_fp = fp;
	while(!feof(temp_fp))
	{
		fgets(string,250,temp_fp);
		if (strncmp(string,"total data length=",18) == 0)	// acn total length
		{
			strcpy(temp,(strchr(string,'=')+1));
			cap_acn_buf.buf_len = atol(temp);
			if (cap_acn_buf.buf_len > XAP_ACN_NUM)
			{
				printf("XAPP cap acn length is larger than expected!!");
				cap_acn_buf.buf_len = XAP_ACN_NUM;
				return 0;
			}
			break;
		}
	}
	for (ii = 0;ii < cap_acn_buf.buf_len;ii++)
	{
		temp_fp = fp;
		while (!feof(temp_fp))
		{
			fgets(string,250,temp_fp);
			if (strncmp(string,"No.",3) == 0)
			{
				ch_ptr = strchr(string,'.') + 1;
				jj = strlen(ch_ptr) - strlen(strchr(string,':'));
				strncpy(temp,ch_ptr,jj);
				temp[jj] = '\0';
				if (ii != (atol(temp)-1))	// not find data
					continue;
				ch_ptr = strchr(string,':') + 1;
				if(ch_ptr == NULL) continue;
				jj = strlen(ch_ptr) - strlen(strchr(string,' '));
				strncpy(temp,ch_ptr,jj);
				temp[jj] = '\0';
				cap_acn_buf.acn[ii] = atol(temp);
				ch_ptr = strchr(string,' ') + 1;
				if(ch_ptr == NULL) continue;
				jj = strlen(ch_ptr) - strlen(strchr(string,'\t'));
				strncpy(temp,ch_ptr,jj);
				temp[jj] = '\0';
				cap_acn_buf.acn_ver[ii] = atol(temp);
				break;
			}
		}
	}
	fclose(fp);

	fp = fopen(oprfile_name,"r");		// read operation code file
	if (fp == NULL)
	{
		xap_send_error("XAPP can not open operation code file %s!!\n",oprfile_name);
		return 0;
	}
	temp_fp = fp;
	while(!feof(temp_fp))
	{
		fgets(string,250,temp_fp);
		if (strncmp(string,"total data length=",18) == 0)	// acn total length
		{
			strcpy(temp,(strchr(string,'=')+1));
			cap_opr_buf.buf_len = atol(temp);
			if (cap_opr_buf.buf_len > XAP_OPR_NUM)
			{
				printf("XAPP cap opration length is larger than expected");
				cap_opr_buf.buf_len = XAP_OPR_NUM;
				return 0;
			}
			break;
		}
	}
	for (ii = 0;ii < cap_opr_buf.buf_len;ii++)
	{
		temp_fp = fp;
		while (!feof(temp_fp))
		{
			fgets(string,250,temp_fp);
			if (strncmp(string,"No.",3) == 0)
			{
				ch_ptr = strchr(string,'.') + 1;
				jj = strlen(ch_ptr) - strlen(strchr(string,':'));
				strncpy(temp,ch_ptr,jj);
				temp[jj] = '\0';
				if (ii != (atol(temp)-1))	// not find data
					continue;
				ch_ptr = strchr(string,':') + 1;
				jj = strlen(ch_ptr) - strlen(strchr(string,' '));
				strncpy(temp,ch_ptr,jj);
				temp[jj] = '\0';
				cap_opr_buf.opr_code[ii] = atol(temp);
				ch_ptr = strchr(string,' ') + 1;
				jj = strlen(ch_ptr) - strlen(strchr(ch_ptr,' '));
				strncpy(temp,ch_ptr,jj);
				temp[jj] = '\0';
				cap_opr_buf.opr_class[ii] = atol(temp);
				ch_ptr = strchr(ch_ptr,' ') + 1;
				jj = strlen(ch_ptr) - strlen(strchr(string,'\t'));
				strncpy(temp,ch_ptr,jj);
				temp[jj] = '\0';
				cap_opr_buf.opr_timer[ii] = atol(temp);
				break;
			}
		}
	}
	fclose(fp);
	return 1;
}

void xap_init(int didgrant)
{
	int		shm_id;

	/*	xap virtue machine share memory	*/
	if ((shm_id = shmget(XAP_VM_KEY,sizeof(xap_vm_struct),XAP_VM_PERM|IPC_CREAT)) == -1)
	{
		printf("can not init xap_vm share memory1\n");
		exit(0);
	}
	if ((xap_vm_ptr = (xap_vm_struct *)shmat(shm_id,(char *)0,0)) == (xap_vm_struct *) -1)
	{
		printf("can not init xap_vm share memory2\n");
		exit(0);
	}
	memset(xap_vm_ptr,0,sizeof(xap_vm_struct));
	xap_vm_ptr->debug_data.ascin_buf[0] = '\0';
	xap_vm_ptr->debug_data.ascout_buf[0] = '\0';
	/*	xap interface share memory	*/
	if ((shm_id = shmget(XAP_INTER_KEY,sizeof(xap_inter_struct),XAP_INTER_PERM|IPC_CREAT)) == -1)
	{
		printf("can not init xap_inter share memory1\n");
		exit(0);
	}
	if ((xap_inter_ptr = (xap_inter_struct *)shmat(shm_id,(char *)0,0)) == (xap_inter_struct *) -1)
	{
		printf("can not init xap_inter share memory2\n");
		exit(0);
	}
	if( didgrant <= 0 || didgrant > MAX_DIALOGUEID)
	{
		  printf( "unexpect tcap did grant number!\r\n");
		  exit(0);
	}
	(xap_vm_ptr->grantdid) = didgrant;
	memset(xap_inter_ptr,0,sizeof(xap_inter_struct));
	memset(&map_acn_buf,0,sizeof(xap_acn_info));
	memset(&map_opr_buf,0,sizeof(xap_opr_info));
	memset(&is41_opr_buf,0,sizeof(xap_opr_info));
	if (!init_mappconst())
		xap_send_error("MAP system configure data has problem");
	memset(&cap_acn_buf,0,sizeof(xap_acn_info));
	memset(&cap_opr_buf,0,sizeof(xap_opr_info));
	if (!init_cappconst())
		xap_send_error("CAP system configure data has problem");
	if (!init_is41const())
		xap_send_error("IS41 system configure data has problem");
	xap_init_m();
}

void set_mapperr(struct MapOprData_struct *opr_ptr,u8 perr_flag)	// set map provider error
{
	opr_ptr->param_flag |= 0x80;
	opr_ptr->provider_error = perr_flag;
}

void set_mapuerr(struct MapOprData_struct *opr_ptr,u8 uerr_flag)	// set map user error
{
	opr_ptr->param_flag |= 0x40;
	opr_ptr->user_error = uerr_flag;
}

u8 check_mapuerr(struct MapOprData_struct *opr_ptr,u8 *temp_result)
{
	if (opr_ptr->message_flag != MAP_RESPONSE)
		return 0;
	if ((opr_ptr->param_flag & 0x40))
	{
		*temp_result = opr_ptr->user_error;
		return 1;
	}
	return 0;
}

void get_mapuabort_reason(MapUAbort_Arg *abrt_ptr,MapDlgUAbort_struct *dlg_ptr)
{
	u32		temp_flag;

	temp_flag = 0x01;
	switch (dlg_ptr->choice_flag)
	{
		case 0:	// user specific reason
			abrt_ptr->user_reason = ProcedureError;
			break;
		case 1:	// user resource limitation
			abrt_ptr->user_reason = ResourceLimite;
			break;
		case 2:	// resource unavailable reason
			temp_flag += 0x02;
			abrt_ptr->user_reason = ResourceUnavailable;
			if (dlg_ptr->choice.resunavi == 0)	// short term resource limitation
				abrt_ptr->diag_info = ShortTermProblem;
			else
				abrt_ptr->diag_info = LongTermProblem;
			break;
		case 3:	// application procedure cancellation
			temp_flag |= 0x02;
			abrt_ptr->user_reason = ApplicationCancel;
			switch (dlg_ptr->choice.appproccancel)
			{
				case 0:
					abrt_ptr->diag_info = HandoverCancel;
					break;
				case 1:
					abrt_ptr->diag_info = RadioChannelRelease;
					break;
				case 2:
					abrt_ptr->diag_info = NetworkPathRelease;
					break;
				case 3:
					abrt_ptr->diag_info = CallRelease;
					break;
				case 4:
					abrt_ptr->diag_info = AssociateProcedureFailure;
					break;
				case 5:
					abrt_ptr->diag_info = TandemDialogueRelease;
					break;
				case 6:
					abrt_ptr->diag_info = RemoteOperationFailure;
					break;
				default:
					abrt_ptr->diag_info = RemoteOperationFailure;
					break;
			}
			break;
		default:	// unknown reason
			abrt_ptr->user_reason = ResourceLimite;
			break;
	}
	abrt_ptr->param_flag = temp_flag;
}

void set_mapuabort_reason(MapDlgUAbort_struct *dlg_ptr,MapUAbort_Arg *abrt_ptr)
{
	switch (abrt_ptr->user_reason)
	{
		case ProcedureError:
			dlg_ptr->choice_flag = 0;
			break;
		case ResourceLimite:
			dlg_ptr->choice_flag = 1;
			break;
		case ResourceUnavailable:
			dlg_ptr->choice_flag = 2;
			if (abrt_ptr->diag_info == ShortTermProblem)
				dlg_ptr->choice.resunavi = 0;
			else
				dlg_ptr->choice.resunavi = 1;
			break;
		case ApplicationCancel:
			dlg_ptr->choice_flag = 3;
			switch (abrt_ptr->diag_info)
			{
				case HandoverCancel:
					dlg_ptr->choice.appproccancel = 0;
					break;
				case RadioChannelRelease:
					dlg_ptr->choice.appproccancel = 1;
					break;
				case NetworkPathRelease:
					dlg_ptr->choice.appproccancel = 2;
					break;
				case CallRelease:
					dlg_ptr->choice.appproccancel = 3;
					break;
				case AssociateProcedureFailure:
					dlg_ptr->choice.appproccancel = 4;
					break;
				case TandemDialogueRelease:
					dlg_ptr->choice.appproccancel = 5;
					break;
				case RemoteOperationFailure:
					dlg_ptr->choice.appproccancel = 6;
					break;
				default:
					dlg_ptr->choice.appproccancel = 6;
					break;
			}
			break;
		default:
			dlg_ptr->choice_flag = 1;
			break;
	}
}

u8 get_mappabort_reason(struct TCPAbort_struct *dlg_ptr,u32 did)
{
	u8		reason=0;

#if _SUPPORT_ANSI
	if (map_check_map_flag(did))//map or cap
	{
#endif
		switch (dlg_ptr->pabort_reason)
		{
			case P_Abort_UMT:
				reason = ProviderMalfunction;
				break;
			case P_Abort_UTID:
				reason = SupportingReleased;
				break;
			case P_Abort_BFTP:
				reason = ProviderMalfunction;
				break;
			case P_Abort_RL:
				reason = ResourceLimitation;
				break;
			case P_Abort_ADLG:
				reason = ProviderMalfunction;
				break;
			case P_Abort_NCDP:
				reason = VersionIncompatibility;
				break;
			default:
				reason = ProviderMalfunction;
				break;
		}
#if _SUPPORT_ANSI
	}
#endif

#if _SUPPORT_ANSI
	else//is41
	{
		switch (dlg_ptr->pabort_reason)
		{
			case P_Abort_UMT_Ansi:
				reason = ProviderMalfunction;
				break;
			case P_Abort_UTID_Ansi:
				reason = SupportingReleased;
				break;
			case P_Abort_BFTP_Ansi:
				reason = ProviderMalfunction;
				break;
			case P_Abort_RL_Ansi:
				reason = ResourceLimitation;
				break;
			default:
				reason = ProviderMalfunction;
				break;
		}
	}
#endif
	return reason;
}

u8 get_xapacn(struct psmvm_data *psm_ptr,struct dlgport_struct *dlg_ptr)
{
/* daniel */
	switch (psm_ptr->xap_flag)
	{
	case XAP_MAP_SSN:
		if (dlg_ptr->acn_len==0)
		{
			psm_ptr->acn = 0;
			psm_ptr->acn_ver = AC_Version1;
			return 1;
		}
		break;
	case XAP_CAP_SSN:
		if (dlg_ptr->acn_len==0)
		{
			psm_ptr->acn = 0;
			psm_ptr->acn_ver = 0;
			return 1;
		}
		break;
#if _SUPPORT_ANSI
	case XAP_IS41_SSN:
		psm_ptr->acn = 0;
		psm_ptr->acn_ver = 0;
		return 1;
#endif		
	default://XAP_CAP_SSN or XAP_IS41_SSN
		psm_ptr->acn = 0;
		psm_ptr->acn_ver = 0;
		return 1;
		break;
	}
/* daniel */


/* daniel 
	if (dlg_ptr->acn_len==0 && psm_ptr->xap_flag!=XAP_CAP_SSN)
	{
		psm_ptr->acn = 0;
		psm_ptr->acn_ver = AC_Version1;
		return 1;
	}
 daniel */

	if (dlg_ptr->acn_len != XAP_ACN_LEN)
	{
		xap_send_error("MAPP receive error length ACN");
		return 0;
	}
	psm_ptr->acn = dlg_ptr->acn[XAP_ACN_LEN-2];
	psm_ptr->acn_ver = dlg_ptr->acn[XAP_ACN_LEN-1];
	return 1;
}

void set_xapacn(struct dlgport_struct *dlg_ptr,struct psmvm_data *psm_ptr)
{
	if ((psm_ptr->xap_flag == XAP_MAP_SSN) ||
		(psm_ptr->xap_flag == XAP_CAP_SSN))
	{
		dlg_ptr->acn_len = XAP_ACN_LEN;
		dlg_ptr->acn[0] = Identified_Organization;
		dlg_ptr->acn[1] = ETSI;
		dlg_ptr->acn[2] = MobileDomain;
		dlg_ptr->acn[3] = GSM_Network;
		dlg_ptr->acn[4] = AC_ID;
		dlg_ptr->acn[5] = psm_ptr->acn;
		dlg_ptr->acn[6] = psm_ptr->acn_ver;
	}
	else
	{//IS41 do not has acn
		dlg_ptr->acn_len = 0;
#if _SUPPORT_ANSI
		dlg_ptr->confidential_info_len = 0;
		dlg_ptr->security_context_len = 0;
#endif
		dlg_ptr->user_info_len = 0;
	}
}

u8	get_xapacn_ver(u8 acn,u8 xap_flag)
{
	u32		ii;

	switch (xap_flag)
	{
		case XAP_MAP_SSN:
			for (ii = 0;ii < map_acn_buf.buf_len;ii ++)
			{
				if (map_acn_buf.acn[ii] == acn)
					return map_acn_buf.acn_ver[ii];
			}
			break;
#if _SUPPORT_ANSI
		case XAP_IS41_SSN:
			return 1;
#endif
		case XAP_CAP_SSN:
			//printf("buflen=%d %d\n",cap_acn_buf.buf_len,cap_acn_buf.acn[0]);
			for (ii = 0;ii < cap_acn_buf.buf_len;ii ++)
			{
				if (cap_acn_buf.acn[ii] == acn)
					return cap_acn_buf.acn_ver[ii];
			}
			break;

		default:
			break;
	}
	return 0;
}

u8 check_acname(u8 acn,u8 acn_ver,u8 xap_flag)	// check if the AC is supported
{
	u8		temp_ver;

/* daniel */
	switch (xap_flag)
	{
	case XAP_MAP_SSN:
		if (acn_ver==AC_Version1)
		{
			return 0;
		}
		break;
#if _SUPPORT_ANSI
	case XAP_IS41_SSN:
		return 0;
#endif
	case XAP_CAP_SSN:
		if (acn_ver==0)
		{
			return 0;
		}
		break;
	default:
		if (acn_ver==AC_Version1 && acn==0)
			return 0;
		break;
	}
/* daniel */

/* daniel 
	if (xap_flag!=XAP_CAP_SSN && acn_ver==AC_Version1 && acn==0)
		return 0;
 daniel */

	temp_ver = get_xapacn_ver(acn,xap_flag);
	if (temp_ver == 0 && xap_flag != XAP_CAP_SSN)
	{
		xap_send_error("XAP check unknown ACN :%d,%d",acn,acn_ver);
		return 1;
	}
	if (temp_ver >= acn_ver)
		return 0;
	else
		return 2;
}

u8 cmp_acname(psmvm_data *psm_ptr,dlgport_struct *dlg_ptr) // compare is AC is changed
{
#if _SUPPORT_ANSI
	if (psm_ptr->xap_flag == XAP_IS41_SSN)
		return 1;
#endif

	if (psm_ptr->xap_flag == XAP_MAP_SSN)
	{
		if (psm_ptr->acn_ver == AC_Version1)
			return 1;
	}
	
	else if (psm_ptr->xap_flag == XAP_CAP_SSN)
	{
		if (psm_ptr->acn_ver == 0)
		{//cap version 1
			return 1;
		}
	}
	
	if (dlg_ptr->acn_len != XAP_ACN_LEN)
		return 0;
	if (dlg_ptr->acn[XAP_ACN_LEN-1] != psm_ptr->acn_ver)
		return 0;
	if (dlg_ptr->acn[XAP_ACN_LEN-2] != psm_ptr->acn)
		return 0;
	return 1;
}

u8	map_get_acnver(SCCP_ADDR *sccp_ptr,u8 acn)
{
	int		ii;
	u8		*acn_ptr;

	if (GetACNInfo(sccp_ptr,&acn_ptr)<=0)
		return 2;	// default version is 2
	for (ii = 0;ii < map_acn_buf.buf_len;ii ++)
	{
		if (map_acn_buf.acn[ii] == acn)
			return acn_ptr[ii];
	}
	return 2;//default version is 2
}

u8	map_set_acnver(SCCP_ADDR *sccp_ptr,u8 acn,u8 acn_ver)
{	// empty, need to fill later
	return 0;
}


u8	find_oprclass(u8 opr_code,u8 xap_flag)	// check operation code and find operation class
{
	u32		ii;

	switch (xap_flag)
	{
		case XAP_MAP_SSN:
			for (ii = 0;ii < map_opr_buf.buf_len;ii++)
			{
				if (map_opr_buf.opr_code[ii] == opr_code)
					return map_opr_buf.opr_class[ii];	// return operation class
			}
			xap_send_error("MAPP find unknown operation code:%d",opr_code);
			break;
#if _SUPPORT_ANSI
		case XAP_IS41_SSN:
			for (ii = 0;ii < is41_opr_buf.buf_len;ii++)
			{
				if (is41_opr_buf.opr_code[ii] == opr_code)
					return is41_opr_buf.opr_class[ii];	// return operation class
			}
			xap_send_error("IS41 find unknown operation code:%d",opr_code);
			break;
#endif
		case XAP_CAP_SSN:
			for (ii = 0;ii < cap_opr_buf.buf_len;ii++)
			{
				if (cap_opr_buf.opr_code[ii] == opr_code)
					return cap_opr_buf.opr_class[ii];	// return operation class
			}
			xap_send_error("CAPP find unknown operation code:%d, buf_len = %d", opr_code, cap_opr_buf.buf_len);
			break;
		default:
			break;
	}

	xap_send_error("XAPP can't find operation code: xap_flag=%d", xap_flag);
	return 0;	// can not find operation
}

u32	find_oprtimer(u8 opr_code,u8 xap_flag)	// find opreation timer
{
	u32		ii;

	switch (xap_flag)
	{
		case XAP_MAP_SSN:
			for (ii = 0;ii < map_opr_buf.buf_len;ii++)
			{
				if (map_opr_buf.opr_code[ii] == opr_code)
					return map_opr_buf.opr_timer[ii];	// return operation class
			}
			break;
#if _SUPPORT_ANSI
		case XAP_IS41_SSN:
			for (ii = 0;ii < is41_opr_buf.buf_len;ii++)
			{
				if (is41_opr_buf.opr_code[ii] == opr_code)
					return is41_opr_buf.opr_timer[ii];	// return operation class
			}
			break;
#endif
		case XAP_CAP_SSN:
			for (ii = 0;ii < cap_opr_buf.buf_len;ii++)
			{
				if (cap_opr_buf.opr_code[ii] == opr_code)
					return cap_opr_buf.opr_timer[ii];	// return operation class
			}
			break;
		default:
			break;
	}

	xap_send_error("XAP find unknown operation code:%d",opr_code);
	return 0;	// can not find operation
}

u8	map_check_lnkid(u8 opr_code)
{
	switch (opr_code)
	{
		case RegPasswd:
			return 1;
			break;
		default:
			break;
	}
	return 0;
}

void set_xap_flag(u32 did,u8 ssn)
{
	int		ii;
	u8		flag=0;

	for (ii = 0;ii < xap_inter_ptr->regssn_len;ii ++)
	{
		if (xap_inter_ptr->reg_ssn[ii] == ssn)
		{
			flag = 1;
			break;
		}
	}
	if (flag == 0)
	{
		xap_send_error("Can not find SSN=%d in xap provider",ssn);
		return;
	}
	xap_vm_ptr->xap_data[did].psm_data.xap_flag = xap_inter_ptr->regssn_flag[ii];
}

u8  send_SSBeginSubActy(struct	MapOpen_Arg	*open_ptr ,  struct MapOprSrv_struct *srv_ptr)
{
	  struct MapOprData_struct data_ptr;
	  struct	MapBSA_Arg *bsa;
	  struct	TCInvoke_struct		*inv_ptr;
	  u8		  data_flow[MAX_MAPPOPR_LEN];
	  struct	xapp_vm_data		*vm_ptr;
	  struct	psmvm_data			*psm_ptr;
	  struct	CSLcmp_struct		csl_cmp;
	  	
	  u8		buf[4096];
	  int len;
	  
	  vm_ptr = (xapp_vm_data *) &xap_vm_ptr->xap_data[srv_ptr->dialogue_id];
	  psm_ptr = (psmvm_data *) &vm_ptr->psm_data;
	  bsa = (struct	MapBSA_Arg *)&srv_ptr->msg_list.bsa_arg;
	  bsa->param_flag = 0;
	  
		if (open_ptr->param_flag & 0x04)	// has peer ref
		{
				bsa->param_flag |= 0x01;
				if(open_ptr->peerref_len == 9 )
				{
				   memcpy(bsa->imsi,open_ptr->peer_reference,open_ptr->peerref_len);
				}
				else
				{
					 xap_send_error("XAPP peer reference lenght err while SS MAP V1");
	  	     return 0;
				}
		}
		
		if ((open_ptr->param_flag |= 0x10))	// has local ref
		{
				bsa->param_flag |= 0x02;
				bsa->orgenty_num_len = open_ptr->localref_len;
				memcpy(bsa->orgenty_num,open_ptr->local_reference,open_ptr->localref_len);
		}		
		
		data_ptr.port_id      = srv_ptr->port_id;
	  data_ptr.dialogue_id  = srv_ptr->dialogue_id; 
	  data_ptr.invoke_id    = srv_ptr->invoke_id;
	  data_ptr.message_type = srv_ptr->message_type;
	  data_ptr.message_flag = srv_ptr->message_flag;
	  data_ptr.param_flag = 0x1f;
	  
	  len = build_mapparam(srv_ptr,buf);
	  if (len == 0 || len > MAX_MAPPOPR_LEN)
	  {
		    return 0;
	  }
	  
	  data_ptr.param_len = len; 
	  memcpy(data_ptr.param,buf,len); 
	  data_ptr.param_flag |= 0x20;
    
    
    map_opr_stof(&data_ptr,data_flow,1);
    xap_msg_display(data_flow);
	  /*if( !map_send_oprdata(data_flow) )
	  {
	  	  return 0;
	  } 
	  
	  vm_ptr   = (xapp_vm_data *) &xap_vm_ptr->xap_data[srv_ptr->dialogue_id];
	  psm_ptr = (psmvm_data *) &vm_ptr->psm_data;
	  
	  psm_ptr->data_count += requesting_ssm(&vm_ptr->recvopr_data,SERVICE_INVOKED,1);
		vm_ptr->recvopr_flag = 0;
		*/
		
		inv_ptr = (TCInvoke_struct *) &csl_cmp.cmp_prim.tc_invoke;
		csl_cmp.message_type = Invoke;
		csl_cmp.message_flag = REQUEST;
		csl_cmp.dialogue_id  = data_ptr.dialogue_id ;
		csl_cmp.invoke_id    = data_ptr.invoke_id;
	  inv_ptr->linkedid_flag = 0;

		inv_ptr->operation_code = data_ptr.message_type;
		inv_ptr->parameter_len = 0;
		if ((data_ptr.param_flag & 0x20))	// has component portion
		{
				if (data_ptr.param_len > MAX_TCAPSEND_LEN)
				{
					xap_send_error("XAPP check the operation %d parameter is to long:%ld",data_ptr.message_type,data_ptr.param_len);
				}
				else
				{
					inv_ptr->parameter_len = data_ptr.param_len;
					memcpy(inv_ptr->parameter,data_ptr.param,data_ptr.param_len);
				}
	  }
	  if( (open_ptr->param_flag & 0x08) != 0x08 )
	  {
	  	  xap_send_error("XAPP check the Open param flag do not include local add while SS MAP V1");
	  	  return 0;
	  }
	  else
	  {
	      set_xap_flag(data_ptr.dialogue_id,open_ptr->local_add.SSN);
		    inv_ptr->operation_class = find_oprclass(data_ptr.message_type,psm_ptr->xap_flag);
		    inv_ptr->timer = find_oprtimer(data_ptr.message_type,psm_ptr->xap_flag);
		    psm_ptr->opr_class[csl_cmp.invoke_id] = inv_ptr->operation_class;
	  }
	  
		SendTcapCmp(&csl_cmp);
	  xap_cmp_display(&csl_cmp);
		return 1;

}
 
u8  recv_SSBeginSubActy(u32 did , struct CSLcmp_struct *csl_cmp ,struct	MapOpen_Arg	*open_ptr )
{
	  struct	MapBSA_Arg *bsa;
	  struct  MapOprSrv_struct  srv_ptr; 
	  struct	xapp_vm_data		*vm_ptr;
	  struct	psmvm_data			*psm_ptr;
	  //u8		  data_flow[MAX_MAPPOPR_LEN]; 
	  struct	TCInvoke_struct		*inv_ptr;
	  struct MapOprData_struct data_ptr;
	  
	  
	  vm_ptr = (xapp_vm_data *) &xap_vm_ptr->xap_data[did];
	  psm_ptr = (psmvm_data *) &vm_ptr->psm_data;
	  if( !RecvTcapCmp(csl_cmp,did) )
	  {
	  	  return 0;
	  }
	  xap_cmp_display(csl_cmp);
	  
	  if( csl_cmp->message_type != Invoke || csl_cmp->cmp_prim.tc_invoke.operation_code != BeginSubAct )
	  {
	  	  return 2;
	  }
	 
	  //performing_ssm(&csl_cmp,SERVICE_INVOCATION_RECEIVED,0);
		inv_ptr = (TCInvoke_struct *) &csl_cmp->cmp_prim.tc_invoke;
		data_ptr.port_id      = psm_ptr->port_id; 
		data_ptr.dialogue_id  = csl_cmp->dialogue_id;
		data_ptr.invoke_id    = csl_cmp->invoke_id;
		data_ptr.message_type = inv_ptr->operation_code;
		data_ptr.message_flag = MAP_INDICATE;
		data_ptr.param_flag = 0x1f;
		data_ptr.param_len = 0;
		
		if (inv_ptr->parameter_len != 0)
		{
				data_ptr.param_len = inv_ptr->parameter_len;
				memcpy(data_ptr.param,inv_ptr->parameter,inv_ptr->parameter_len);
				data_ptr.param_flag |= 0x20;
		}		
				
		if( !(data_ptr.param_flag & 0x20))	// has not parameter
			  return -1;
			  
    extract_mapparam(&srv_ptr, data_ptr.message_type, 
                     data_ptr.message_flag,data_ptr.param_len,data_ptr.param);
		
		bsa = (struct	MapBSA_Arg *)&srv_ptr.msg_list.bsa_arg;
		if( bsa->param_flag != 0x03 )
		{
			 return -1;
		}
		
		open_ptr->param_flag |= 0x04;
		open_ptr->localref_len = IMSI_LEN + 1  ;
		memcpy(open_ptr->local_reference,bsa->imsi,open_ptr->localref_len); 

		open_ptr->param_flag |= 0x10;
		open_ptr->peerref_len = bsa->orgenty_num_len ;
		memcpy(open_ptr->peer_reference,bsa->orgenty_num,open_ptr->peerref_len);		
		
		return 1;
	 
}

u8 xap_store_open(u8 ssn,u32 did)
{
	int		ii,jj;
	u8		flag=0;

	for (ii = 0;ii < xap_inter_ptr->regssn_len;ii ++)
	{
		if (xap_inter_ptr->reg_ssn[ii] == ssn)
		{
			flag = 1;
			break;
		}
	}
	if (flag == 0)
	{
		xap_send_error("Can not find SSN=%d in xap provider",ssn);
		return 0;
	}
	jj = xap_inter_ptr->open_head[ii];
	if (((jj + 1) % XAP_OPEN_LEN) == xap_inter_ptr->open_tail[ii])
	{
		xap_send_error("XAP provider open buffer of ssn: %d has full, did: %d", ssn, did);
		return 0;
	}
	xap_inter_ptr->open_did[ii][jj] = did;
	xap_inter_ptr->open_head[ii] = (jj + 1) % XAP_OPEN_LEN;
	return 1;
}

int xapp_send_comdata(struct MapComSrv_struct *com_ptr)
{
	struct	xapp_vm_data		*vm_ptr;
	u32		temp_did;
	u8		ssn;
	
	temp_did = com_ptr->dialogue_id;
	if (temp_did >= (xap_vm_ptr->grantdid))
		return 0;
	if (com_ptr->message_type == MAP_OPEN && com_ptr->message_flag == MAP_INDICATE)
	{	// store data in open did buffer
		xap_watch_dog(3);
		ssn = com_ptr->dlg_list.open_arg.local_add.SSN;
		if (!xap_store_open(ssn,temp_did))
			return 0;
	}
	vm_ptr = (xapp_vm_data *) &xap_vm_ptr->xap_data[temp_did];
	if (vm_ptr->sendcom_flag == 1)
		return 0;
	memcpy(&vm_ptr->sendcom_data,com_ptr,sizeof(MapComSrv_struct));
	vm_ptr->sendcom_flag = 1;
	xap_watch_dog(5);
	return 1;
}

void xapp_send_openrefuse(u32 pid,u32 did,u8 reason)
{
	struct	MapComSrv_struct	map_com;
	struct	MapOpen_Res			*mapo_ptr;
	struct	xapp_vm_data		*vm_ptr;
	struct	psmvm_data			*psm_ptr;

	if (did >= (xap_vm_ptr->grantdid))
		return;
	vm_ptr = (xapp_vm_data *) &xap_vm_ptr->xap_data[did];
	psm_ptr = (psmvm_data *) &vm_ptr->psm_data;
	map_com.message_type = MAP_OPEN;
	map_com.message_flag = MAP_CONFIRM;
	map_com.port_id = pid;
	map_com.dialogue_id = did;
	mapo_ptr = (MapOpen_Res *) &map_com.dlg_list.open_res;
	mapo_ptr->result = OpenResultRefuse;
	mapo_ptr->refuse_reason = reason;
	mapo_ptr->param_flag = 0x18;
	if (reason == ACNotSupported)
	{
		mapo_ptr->acn_data.acn = psm_ptr->acn;
		mapo_ptr->acn_data.acn_ver = psm_ptr->acn_ver;
		mapo_ptr->param_flag |= 0x01;
	}
	xapp_send_comdata(&map_com);
}

void xapp_send_pabort(u32 pid,u32 did,u8 reason,u8 source)
{
	struct	MapComSrv_struct	map_com;
	struct	MapPAbort_Arg		*mappa_ptr;

	map_com.message_type = MAP_P_ABORT;
	map_com.message_flag = MAP_INDICATE;
	map_com.port_id = pid;
	map_com.dialogue_id = did;
	mappa_ptr = (MapPAbort_Arg *) &map_com.dlg_list.pabort_arg;
	mappa_ptr->provider_reason = reason;
	mappa_ptr->source = source;
	mappa_ptr->param_flag = 0x03;
	xapp_send_comdata(&map_com);
}

void xapp_send_notice(u32 pid,u32 did,u8 reason)
{
	struct	MapComSrv_struct	map_com;

	map_com.message_type = MAP_NOTICE;
	map_com.message_flag = MAP_INDICATE;
	map_com.port_id = pid;
	map_com.dialogue_id = did;
	map_com.dlg_list.notice_arg.problem = reason;
	map_com.dlg_list.notice_arg.param_flag = 0x01;
	xapp_send_comdata(&map_com);
}

void xapp_send_ureject(u32 did,u8 iid,u8 err_type,u8 err_code,u8 xap_flag)
{
	struct	CSLcmp_struct		csl_cmp;

#if _SUPPORT_ANSI
	if ((xap_flag == XAP_MAP_SSN) ||
		(xap_flag == XAP_CAP_SSN))
#endif
		csl_cmp.message_type = U_Reject;
#if _SUPPORT_ANSI
	else
		csl_cmp.message_type = U_Reject_Ansi;
#endif
	csl_cmp.message_flag = REQUEST;
	csl_cmp.dialogue_id = did;
	csl_cmp.invoke_id = iid;
	csl_cmp.cmp_prim.tc_reject.problem_type = err_type;
	csl_cmp.cmp_prim.tc_reject.problem_code = err_code;
	SendTcapCmp(&csl_cmp);
	xap_cmp_display(&csl_cmp);
}

void xapp_send_uabort(u32 did,u8 reason,u8 dlg_flag,struct dlgport_struct *dlg_ptr,u8 xap_flag)
{
	struct	TCUAbort_struct		*uabort_ptr;
	struct	CSLdlg_struct		csl_data;

	uabort_ptr = (TCUAbort_struct *) &csl_data.dlg_prim.tc_uabort;
#if _SUPPORT_ANSI
	if ((xap_flag == XAP_MAP_SSN) ||
		(xap_flag == XAP_CAP_SSN))
#endif
	{
		csl_data.message_type = U_Abort;
		uabort_ptr->dialogue_flag = dlg_flag;
	}
#if _SUPPORT_ANSI
	else
	{
		csl_data.message_type = U_Abort_Ansi;
		uabort_ptr->dialogue_flag = 0;
	}
#endif
	csl_data.message_flag = REQUEST;
	csl_data.dialogue_id = did;
	
	uabort_ptr->uabort_reason = reason;
	if (dlg_flag)
		memcpy(&uabort_ptr->dlg_data,dlg_ptr,sizeof(dlgport_struct));
	else
		uabort_ptr->dlg_data.user_info_len = 0;
#if _SUPPORT_ANSI
	uabort_ptr->uabort_info_len = 0;
	uabort_ptr->dlg_data.security_context_len = 0;
	uabort_ptr->dlg_data.confidential_info_len = 0;
#endif
	SendTcapDlg(&csl_data);
	xap_dlg_display(&csl_data);
}

u8 performing_ssm(void *data_ptr,u8 flag,u8 level)
{	// fail, return 0;success, return 1; partial data, return 2
	struct	CSLcmp_struct		*cmp_ptr=NULL;
	struct	MapOprData_struct	*opr_ptr=NULL;
	struct	xapp_vm_data		*vm_ptr;
	struct	psmvm_data			*psm_ptr;
	struct	TCInvoke_struct		*inv_ptr;
	struct	CSLcmp_struct		csl_cmp;
	struct	TCResult_struct		*result_ptr;
	u32		temp_did;
	u8		temp_iid;
	u32		temp_class;
	u8		temp_result;
	u8		default_len;
	int		param_len,param_site;
//char	info_str[1024];

	if (level == 1)
		default_len = MAX_TCAPSEND_LEN_1;
	else
		default_len = MAX_TCAPSEND_LEN;
	if (flag == SERVICE_INVOCATION_RECEIVED)
	{
		cmp_ptr = (CSLcmp_struct *) data_ptr;
		temp_did = cmp_ptr->dialogue_id;
		temp_iid = cmp_ptr->invoke_id;
	}
	else
	{
		opr_ptr = (MapOprData_struct *) data_ptr;
		temp_did = opr_ptr->dialogue_id;
		temp_iid = opr_ptr->invoke_id;
	}
	if (temp_did >= (xap_vm_ptr->grantdid))
		return 0;
	vm_ptr = (xapp_vm_data *) &xap_vm_ptr->xap_data[temp_did];
	psm_ptr = (psmvm_data *) &vm_ptr->psm_data;
	switch (psm_ptr->opr_state[temp_iid])
	{
		case SSM_IDLE:
			if (flag != SERVICE_INVOCATION_RECEIVED)
			{
				vm_ptr->recvopr_flag = 0;
				xap_watch_dog(46);
				xap_watch_dog(50);
				return 0;
			}
			temp_class = psm_ptr->opr_class[temp_iid];
			inv_ptr = (TCInvoke_struct *) &cmp_ptr->cmp_prim.tc_invoke;
			vm_ptr->sendopr_data.port_id = psm_ptr->port_id;
			vm_ptr->sendopr_data.dialogue_id = temp_did;
			vm_ptr->sendopr_data.invoke_id = temp_iid;
			vm_ptr->sendopr_data.message_type = inv_ptr->operation_code;
			vm_ptr->sendopr_data.message_flag = MAP_INDICATE;
			vm_ptr->sendopr_data.param_flag = 0x1f;
			vm_ptr->sendopr_data.param_len = 0;
			if (inv_ptr->parameter_len != 0)
			{
				vm_ptr->sendopr_data.param_len = inv_ptr->parameter_len;
				memcpy(vm_ptr->sendopr_data.param,inv_ptr->parameter,inv_ptr->parameter_len);
				vm_ptr->sendopr_data.param_flag |= 0x20;
			}
			if (inv_ptr->linkedid_flag)
			{
				vm_ptr->sendopr_data.param_flag |= 0x100;
				vm_ptr->sendopr_data.linked_id = inv_ptr->linked_id;
			}
			vm_ptr->sendopr_flag = 1;
			xap_watch_dog(10);
			xap_watch_dog(12);
			if (temp_class != OPERATION_CLASS4)
				psm_ptr->opr_state[temp_iid] = SSM_WFRESPONSE;
			break;
		case SSM_WFRESPONSE:	// wait for response
			if (flag == RESPONSE_ISSUED)
			{
				csl_cmp.message_flag = REQUEST;
				csl_cmp.dialogue_id = temp_did;
				csl_cmp.invoke_id = temp_iid;
				if (check_mapuerr(opr_ptr,&temp_result))	// find the user error
				{
					if (temp_result == ResLimit)
					{
#if _SUPPORT_ANSI
						if ((psm_ptr->xap_flag == XAP_MAP_SSN) ||
							(psm_ptr->xap_flag == XAP_CAP_SSN))
#endif
							csl_cmp.message_type = U_Reject;
#if _SUPPORT_ANSI
						else
							csl_cmp.message_type = U_Reject_Ansi;
#endif
						csl_cmp.cmp_prim.tc_reject.problem_type = Invoke_Problem;
						csl_cmp.cmp_prim.tc_reject.problem_code = Invoke_Problem_IR;
					}
					else
					{
#if _SUPPORT_ANSI
						if ((psm_ptr->xap_flag == XAP_MAP_SSN) ||
							(psm_ptr->xap_flag == XAP_CAP_SSN))
#endif
							csl_cmp.message_type = U_Error;
#if _SUPPORT_ANSI
						else
							csl_cmp.message_type = U_Error_Ansi;
#endif
						csl_cmp.cmp_prim.tc_uerror.error_type = Local_Error_Code;
						csl_cmp.cmp_prim.tc_uerror.error_code = temp_result;
#if _SUPPORT_ANSI
						if ((psm_ptr->xap_flag == XAP_MAP_SSN) ||
							(psm_ptr->xap_flag == XAP_CAP_SSN))
#endif
							csl_cmp.cmp_prim.tc_uerror.parameter_len = 0;
#if _SUPPORT_ANSI
						else
						{
							param_len = vm_ptr->recvopr_data.param_len;
							csl_cmp.cmp_prim.tc_uerror.parameter_len = param_len;
							memcpy(csl_cmp.cmp_prim.tc_uerror.parameter,vm_ptr->recvopr_data.param,param_len);							
						}
#endif
						xap_send_error("XAP ==> TCAP User Error. Operation Code=%d, Error Code=%d", psm_ptr->opr_code[temp_iid], Local_Error_Code);
					}
					vm_ptr->recvopr_flag = 0;
					xap_watch_dog(46);
					xap_watch_dog(51);
					psm_ptr->opr_state[temp_iid] = SSM_IDLE;
				}
				else
				{	/*	+++ the linked request operation is not support +++	*/
					result_ptr = (TCResult_struct *) &csl_cmp.cmp_prim.tc_result;
#if _SUPPORT_ANSI
					if (psm_ptr->xap_flag == XAP_IS41_SSN)
					{
						result_ptr->operation_domain = XAPP_PRIVATE_TCAP;
						result_ptr->operation_family = XAPP_OPER_FAMILY;
					}
#endif
					result_ptr->operation_code = psm_ptr->opr_code[temp_iid];
					result_ptr->parameter_len = 0;
					if (vm_ptr->recvopr_flag==2)	// send partial data
					{
						param_site = vm_ptr->recvopr_site;
						if (param_site+default_len >= vm_ptr->recvopr_data.param_len)	// send result last
						{
#if _SUPPORT_ANSI
							if ((psm_ptr->xap_flag == XAP_MAP_SSN) ||
								(psm_ptr->xap_flag == XAP_CAP_SSN))
#endif
								csl_cmp.message_type = Result_L;
#if _SUPPORT_ANSI
							else
								csl_cmp.message_type = Result_L_Ansi;
#endif
							result_ptr->parameter_len = vm_ptr->recvopr_data.param_len-param_site;
							memcpy(result_ptr->parameter,vm_ptr->recvopr_data.param+param_site,result_ptr->parameter_len);
							result_ptr->operation_flag = 1;
							vm_ptr->recvopr_site = 0;
							vm_ptr->recvopr_flag = 0;	// clear the recvopr flag
							xap_watch_dog(46);
							xap_watch_dog(52);
						}
						else	// send result not last
						{
#if _SUPPORT_ANSI
							if ((psm_ptr->xap_flag == XAP_MAP_SSN) ||
								(psm_ptr->xap_flag == XAP_CAP_SSN))
#endif
								csl_cmp.message_type = Result_NL;
#if _SUPPORT_ANSI
							else
								csl_cmp.message_type = Result_NL_Ansi;
#endif
							result_ptr->parameter_len = default_len;
							memcpy(result_ptr->parameter,vm_ptr->recvopr_data.param+param_site,default_len);
							result_ptr->operation_flag = 1;
							vm_ptr->recvopr_site += default_len;
						}
					}
					else
					{
						param_len = vm_ptr->recvopr_data.param_len;
						if (param_len <= default_len)	// can send in one packet
						{
#if _SUPPORT_ANSI
							if ((psm_ptr->xap_flag == XAP_MAP_SSN) ||
								(psm_ptr->xap_flag == XAP_CAP_SSN))
#endif
								csl_cmp.message_type = Result_L;
#if _SUPPORT_ANSI
							else
								csl_cmp.message_type = Result_L_Ansi;
#endif
							result_ptr->parameter_len = param_len;
							memcpy(result_ptr->parameter,vm_ptr->recvopr_data.param,param_len);
							if (param_len == 0)
								result_ptr->operation_flag = 0;
							else
								result_ptr->operation_flag = 1;
							vm_ptr->recvopr_flag = 0;
							xap_watch_dog(46);
							xap_watch_dog(53);
							psm_ptr->opr_state[temp_iid] = SSM_IDLE;
						}
						else	// long data,need split it
						{
#if _SUPPORT_ANSI
							if ((psm_ptr->xap_flag == XAP_MAP_SSN) ||
								(psm_ptr->xap_flag == XAP_CAP_SSN))
#endif
								csl_cmp.message_type = Result_NL;
#if _SUPPORT_ANSI
							else
								csl_cmp.message_type = Result_NL_Ansi;
#endif
							result_ptr->parameter_len = default_len;
							memcpy(result_ptr->parameter,vm_ptr->recvopr_data.param,default_len);
							result_ptr->operation_flag = 1;
							vm_ptr->recvopr_site = default_len;
							vm_ptr->recvopr_flag = 2;
						}
					}
				}
				SendTcapCmp(&csl_cmp);
				xap_cmp_display(&csl_cmp);
			}
			else if (flag == GUARD_TIMER)
				psm_ptr->opr_state[temp_iid] = SSM_IDLE;
			else if (flag == TERMINATED)
				psm_ptr->opr_state[temp_iid] = SSM_IDLE;
			break;
		default:
			psm_ptr->opr_state[temp_iid] = SSM_IDLE;
			break;
	}
	return 1;
}

u8 requesting_ssm(void *data_ptr,u8 flag,u8 level)
{
	struct	CSLcmp_struct		*cmp_ptr=NULL;
	struct	MapOprData_struct	*opr_ptr=NULL;
	struct	xapp_vm_data		*vm_ptr;
	struct	psmvm_data			*psm_ptr;
	struct	CSLcmp_struct		csl_cmp;
	struct	TCInvoke_struct		*inv_ptr;
	struct	TCResult_struct		*result_ptr;
	struct	TCReject_struct		*rej_ptr;
	u32		temp_did;
	u8		temp_iid;
	int		param_len;
	u8		default_len;
	u8		result=0;

  
		
	if (flag == SERVICE_INVOKED)
	{
		opr_ptr = (MapOprData_struct *) data_ptr;
		temp_did = opr_ptr->dialogue_id;
		temp_iid = opr_ptr->invoke_id;
	}
	else
	{
		cmp_ptr = (CSLcmp_struct *) data_ptr;
		temp_did = cmp_ptr->dialogue_id;
		temp_iid = cmp_ptr->invoke_id;
	}
	
	if (temp_did >= (xap_vm_ptr->grantdid))
	{
		xap_send_error("requesting_ssm: temp_did >= grantdid\r\n");
		return 0;
    }
	vm_ptr = (xapp_vm_data *) &xap_vm_ptr->xap_data[temp_did];
	psm_ptr = (psmvm_data *) &vm_ptr->psm_data;

  if( psm_ptr->acn_ver == 1 )
    default_len = MAX_TCAPSEND_LEN_1;
	else if (level == 1)
		default_len = MAX_TCAPSEND_LEN_1;
	else
		default_len = MAX_TCAPSEND_LEN;
		
	switch (psm_ptr->opr_state[temp_iid])
	{
		case SSM_IDLE:
			if (flag != SERVICE_INVOKED)
			{
				xap_send_error("requesting_ssm: flag != INVOKED");
				return 0;
			}
			inv_ptr = (TCInvoke_struct *) &csl_cmp.cmp_prim.tc_invoke;
#if _SUPPORT_ANSI
			if ((psm_ptr->xap_flag == XAP_MAP_SSN) ||
				(psm_ptr->xap_flag == XAP_CAP_SSN))
#endif
				csl_cmp.message_type = Invoke;
#if _SUPPORT_ANSI
			else
				csl_cmp.message_type = Invoke_L_Ansi;
#endif
			csl_cmp.message_flag = REQUEST;
			csl_cmp.dialogue_id = temp_did;
			csl_cmp.invoke_id = temp_iid;
			if ((opr_ptr->param_flag & 0x100))	// has linked_id
			{
				inv_ptr->linkedid_flag = 1;
				inv_ptr->linked_id = opr_ptr->linked_id;
			}
			else
				inv_ptr->linkedid_flag = 0;
#if _SUPPORT_ANSI
			if (psm_ptr->xap_flag == XAP_IS41_SSN)
			{
				inv_ptr->operation_domain = XAPP_PRIVATE_TCAP;//0=national,1=private
				inv_ptr->operation_family = XAPP_OPER_FAMILY;
			}
#endif
			inv_ptr->operation_code = opr_ptr->message_type;
			inv_ptr->parameter_len = 0;
			if ((opr_ptr->param_flag & 0x20))	// has component portion
			{
				if (opr_ptr->param_len > default_len)
				{
					xap_send_error("XAPP check the operation %d parameter is too long:%ld",opr_ptr->message_type,opr_ptr->param_len);
				}
				else
				{
					inv_ptr->parameter_len = opr_ptr->param_len;
					memcpy(inv_ptr->parameter,opr_ptr->param,opr_ptr->param_len);
				}
			}
			inv_ptr->operation_class = find_oprclass(opr_ptr->message_type,psm_ptr->xap_flag);
			inv_ptr->timer = find_oprtimer(opr_ptr->message_type,psm_ptr->xap_flag);
			psm_ptr->opr_class[temp_iid] = inv_ptr->operation_class;
			if (inv_ptr->operation_class != OPERATION_CLASS4)
			{
				psm_ptr->opr_state[temp_iid] = SSM_WFCONFIRM;
				psm_ptr->opr_code[temp_iid] = opr_ptr->message_type;
			}
			SendTcapCmp(&csl_cmp);
			xap_cmp_display(&csl_cmp);
			vm_ptr->recvopr_flag = 0;
			xap_watch_dog(46);
			xap_watch_dog(54);
			break;
		case SSM_WFCONFIRM:
			switch (flag)
			{
				case RESULT_RECEIVED:
					result_ptr = (TCResult_struct *) &cmp_ptr->cmp_prim.tc_result;
					param_len = result_ptr->parameter_len;
					if (vm_ptr->sendopr_flag == 2)	//	has exist partial data
					{
						if (vm_ptr->sendopr_data.invoke_id == temp_iid)
						{
							if (param_len+vm_ptr->sendopr_data.param_flag > MAX_MAPPOPR_LEN)
							{
								xap_send_error("XAPP received result last data is too long");
								xapp_send_ureject(temp_did,temp_iid,Return_Result,Return_Result_MP,psm_ptr->xap_flag);
								psm_ptr->opr_state[temp_iid] = SSM_IDLE;
								return 0;
							}
							memcpy(vm_ptr->sendopr_data.param+vm_ptr->sendopr_data.param_len,result_ptr->parameter,param_len);
							vm_ptr->sendopr_data.param_len += param_len;
							vm_ptr->sendopr_data.param_flag |= 0x20;
							vm_ptr->sendopr_flag = 1;
							xap_watch_dog(10);
							xap_watch_dog(13);
						}
						else
						{
							xap_send_error("XAPP received result last with wrong iid");
							xapp_send_ureject(temp_did,temp_iid,Return_Result,Return_Result_RRU,psm_ptr->xap_flag);
							psm_ptr->opr_state[temp_iid] = SSM_IDLE;
							return 0;
						}
					}
					else
					{
						vm_ptr->sendopr_data.port_id = psm_ptr->port_id;
						vm_ptr->sendopr_data.dialogue_id = temp_did;
						vm_ptr->sendopr_data.invoke_id = temp_iid;
						vm_ptr->sendopr_data.message_type = psm_ptr->opr_code[temp_iid];
						vm_ptr->sendopr_data.message_flag = MAP_CONFIRM;
						vm_ptr->sendopr_data.param_flag = 0x1f;
						memcpy(vm_ptr->sendopr_data.param,result_ptr->parameter,param_len);
						vm_ptr->sendopr_data.param_len = param_len;
						if (param_len != 0)
							vm_ptr->sendopr_data.param_flag |= 0x20;
						vm_ptr->sendopr_flag = 1;
						xap_watch_dog(10);
						xap_watch_dog(14);
					}
					psm_ptr->opr_state[temp_iid] = SSM_IDLE;
					break;
				case PARTIAL_RESULT_RECEIVED:
					result_ptr = (TCResult_struct *) &cmp_ptr->cmp_prim.tc_result;
					param_len = result_ptr->parameter_len;
					if (vm_ptr->sendopr_flag == 0)	//	has not exist partial data
					{
						vm_ptr->sendopr_data.port_id = psm_ptr->port_id;
						vm_ptr->sendopr_data.dialogue_id = temp_did;
						vm_ptr->sendopr_data.invoke_id = temp_iid;
						vm_ptr->sendopr_data.message_type = psm_ptr->opr_code[temp_iid];
						vm_ptr->sendopr_data.message_flag = MAP_CONFIRM;
						vm_ptr->sendopr_data.param_flag = 0x1f;
						memcpy(vm_ptr->sendopr_data.param,result_ptr->parameter,param_len);
						vm_ptr->sendopr_data.param_len = param_len;
						if (param_len != 0)
							vm_ptr->sendopr_data.param_flag |= 0x20;
						vm_ptr->sendopr_flag = 2;
					}
					else 
					{
						if (vm_ptr->sendopr_data.invoke_id == temp_iid)
						{
							memcpy(vm_ptr->sendopr_data.param+vm_ptr->sendopr_data.param_len,result_ptr->parameter,param_len);
							vm_ptr->sendopr_data.param_len += param_len;
							vm_ptr->sendopr_flag = 2;
						}
						else	// the buffer is used by other invoke id
						{	
							xap_send_error("receive partial result with wrong iid");
							xapp_send_ureject(temp_did,temp_iid,Return_Result,Return_Result_RRU,psm_ptr->xap_flag);
							psm_ptr->opr_state[temp_iid] = SSM_IDLE;
							return 0;
						}
					}
					break;
				case NEGATIVE_RESULT_RECEIVED:
					vm_ptr->sendopr_data.message_type = psm_ptr->opr_code[temp_iid];
					vm_ptr->sendopr_data.message_flag = MAP_CONFIRM;
					vm_ptr->sendopr_data.port_id = psm_ptr->port_id;
					vm_ptr->sendopr_data.dialogue_id = temp_did;
					vm_ptr->sendopr_data.invoke_id = temp_iid;
					vm_ptr->sendopr_data.param_flag = 0x1f;
					set_mapuerr(&vm_ptr->sendopr_data,cmp_ptr->cmp_prim.tc_uerror.error_code);	// set user error
					xap_send_error("XAPP <== TCAP User Error. did=%d, iid=%d, oCode=0x%02X, errCode=%d", temp_did, temp_iid, vm_ptr->sendopr_data.message_type, cmp_ptr->cmp_prim.tc_uerror.error_code);
					vm_ptr->sendopr_flag = 1;
					xap_watch_dog(10);
					xap_watch_dog(15);
					psm_ptr->opr_state[temp_iid] = SSM_IDLE;
					break;
				case LINKED_REQUEST_RECEIVED:
					break;
				case LINKED_SERVICE_INVOKED:
					break;
				case USER_REJECT_RECEIVED:
					rej_ptr = (TCReject_struct *) &cmp_ptr->cmp_prim.tc_reject;
					vm_ptr->sendopr_data.message_type = psm_ptr->opr_code[temp_iid];
					vm_ptr->sendopr_data.message_flag = MAP_CONFIRM;
					vm_ptr->sendopr_data.port_id = psm_ptr->port_id;
					vm_ptr->sendopr_data.dialogue_id = temp_did;
					vm_ptr->sendopr_data.invoke_id = temp_iid;
					vm_ptr->sendopr_data.param_flag = 0x1f;
					if (rej_ptr->problem_code == Invoke_Problem_DIID)
						result = DupInvokeId;
					else if (rej_ptr->problem_code == Invoke_Problem_UO)
						result = SrvNotSupport;
					else
						result = MistypeParam;
					set_mapperr(&vm_ptr->sendopr_data,result);	// set provider error
					xap_send_error("XAPP <== TCAP User Reject. did=%d, iid=%d, oCode=0x%02X, Problem=%d", temp_did, temp_iid, vm_ptr->sendopr_data.message_type, rej_ptr->problem_code);
					vm_ptr->sendopr_flag = 1;
					xap_watch_dog(10);
					psm_ptr->opr_state[temp_iid] = SSM_IDLE;
					break;
				case PROVIDER_REJECT_RECEIVED:
					vm_ptr->sendopr_data.message_type = psm_ptr->opr_code[temp_iid];
					vm_ptr->sendopr_data.message_flag = MAP_CONFIRM;
					vm_ptr->sendopr_data.port_id = psm_ptr->port_id;
					vm_ptr->sendopr_data.dialogue_id = temp_did;
					vm_ptr->sendopr_data.invoke_id = temp_iid;
					vm_ptr->sendopr_data.param_flag = 0x1f;
					set_mapperr(&vm_ptr->sendopr_data,UnexpResFromPeer);	// set provider error
					xap_send_error("XAPP <== TCAP Provider Reject. did=%d, iid=%d, oCode=0x%02X", temp_did, temp_iid, vm_ptr->sendopr_data.message_type);
					vm_ptr->sendopr_flag = 1;
					xap_watch_dog(10);
					psm_ptr->opr_state[temp_iid] = SSM_IDLE;
					break;
				case TIMER_EXPIRY:
					switch (psm_ptr->opr_class[temp_iid])
					{
						case OPERATION_CLASS1:
						case OPERATION_CLASS3:
							vm_ptr->sendopr_data.message_type = psm_ptr->opr_code[temp_iid];
							vm_ptr->sendopr_data.message_flag = MAP_CONFIRM;
							vm_ptr->sendopr_data.port_id = psm_ptr->port_id;
							vm_ptr->sendopr_data.dialogue_id = temp_did;
							vm_ptr->sendopr_data.invoke_id = temp_iid;
							vm_ptr->sendopr_data.param_flag = 0x1f;
							set_mapperr(&vm_ptr->sendopr_data,UnexpResFromPeer);	// set provider error
							xap_send_error("XAPP <== TCAP Timer Expired. did=%d, iid=%d, oCode=0x%02X, Class=%d", temp_did, temp_iid, vm_ptr->sendopr_data.message_type, psm_ptr->opr_class[temp_iid]);
							vm_ptr->sendopr_flag = 1;
							xap_watch_dog(10);
							break;
						default:
							break;
					}
					psm_ptr->opr_state[temp_iid] = SSM_IDLE;
					break;
				case TERMINATED:
					psm_ptr->opr_state[temp_iid] = SSM_IDLE;
					break;
				default:
					break;
			}
			break;
		default:
			psm_ptr->opr_state[temp_iid] = SSM_IDLE;
			break;
	}
	return 1;
}

u8	process_components(struct CSLcmp_struct *cmp_ptr,u32 proc)
{
	struct	xapp_vm_data		*vm_ptr;
	struct	psmvm_data			*psm_ptr;
	struct	TCInvoke_struct		*inv_ptr;
	struct	TCReject_struct		*rej_ptr;
	u32		temp_did;
	u8		temp_iid;
	u8		result_flag;

	temp_did = cmp_ptr->dialogue_id;
	temp_iid = cmp_ptr->invoke_id;
	vm_ptr = (xapp_vm_data *) &xap_vm_ptr->xap_data[temp_did];
	psm_ptr = (psmvm_data *) &vm_ptr->psm_data;
	switch (cmp_ptr->message_type)
	{
		case Invoke:
#if _SUPPORT_ANSI
		case Invoke_L_Ansi:
#endif
			inv_ptr = (TCInvoke_struct *) &cmp_ptr->cmp_prim.tc_invoke;
			if (inv_ptr->linkedid_flag == 0)
			{
				result_flag = find_oprclass(inv_ptr->operation_code,psm_ptr->xap_flag);
				if (result_flag == 0)	// can not find operation code
				{
					xap_send_error("process_components: can not find operation code");
					xapp_send_ureject(temp_did,temp_iid,Invoke_Problem,Invoke_Problem_UO,psm_ptr->xap_flag);
				}
				else
				{
					psm_ptr->opr_class[temp_iid] = result_flag;	// store operation class
					psm_ptr->opr_code[temp_iid] = inv_ptr->operation_code;
					performing_ssm(cmp_ptr,SERVICE_INVOCATION_RECEIVED,0);
				}
			}
			else
			{
				if (!check_iid(temp_did,inv_ptr->linked_id))
				{
					if (psm_ptr->opr_state[inv_ptr->linked_id] != SSM_IDLE)
					{
						xap_send_error("receive Invoke with wrong link id");
						xapp_send_notice(psm_ptr->port_id,temp_did,AbnormalEventReceived);
						xapp_send_ureject(temp_did,inv_ptr->linked_id,Invoke_Problem,Invoke_Problem_ULID,psm_ptr->xap_flag);
					}
				}
				else
				{
					if (psm_ptr->opr_class[inv_ptr->linked_id] == OPERATION_CLASS4)
						requesting_ssm(cmp_ptr,LINKED_REQUEST_RECEIVED,0);
					else
					{
						requesting_ssm(cmp_ptr,LINKED_SERVICE_INVOKED,0);
						result_flag = find_oprclass(inv_ptr->operation_code,psm_ptr->xap_flag);
						if (result_flag == 0)	// can not find operation code
						{
							xap_send_error("process_components: can not find operation code 2");
							xapp_send_ureject(temp_did,temp_iid,Invoke_Problem,Invoke_Problem_UO,psm_ptr->xap_flag);
						}
						else
						{
							psm_ptr->opr_class[temp_iid] = result_flag;	// store operation class
							psm_ptr->opr_code[temp_iid] = inv_ptr->operation_code;
							performing_ssm(cmp_ptr,SERVICE_INVOCATION_RECEIVED,0);
						}
					}
				}
			}
			break;
		case Result_L:
#if _SUPPORT_ANSI
		case Result_L_Ansi:
#endif
			if (!check_iid(temp_did,temp_iid))
			{
				xap_send_error("received Result_L without correspond Invoke id");
				xapp_send_notice(psm_ptr->port_id,temp_did,AbnormalEventReceived);
				xapp_send_ureject(temp_did,temp_iid,Return_Result,Return_Result_UIID,psm_ptr->xap_flag);
			}
			else
				requesting_ssm(cmp_ptr,RESULT_RECEIVED,0);
			break;
		case Result_NL:
#if _SUPPORT_ANSI
		case Result_NL_Ansi:
#endif
			if (!check_iid(temp_did,temp_iid))
			{
				xap_send_error("received Result_NL without correspond Invoke id");
				xapp_send_notice(psm_ptr->port_id,temp_did,AbnormalEventReceived);
				xapp_send_ureject(temp_did,temp_iid,Return_Result,Return_Result_UIID,psm_ptr->xap_flag);
			}
			else
				requesting_ssm(cmp_ptr,PARTIAL_RESULT_RECEIVED,0);
			break;
		case U_Error:
#if _SUPPORT_ANSI
		case U_Error_Ansi:
#endif
			if (!check_iid(temp_did,temp_iid))
			{
				xap_send_error("received U_Error without correspond Invoke id");
				xapp_send_notice(psm_ptr->port_id,temp_did,AbnormalEventReceived);
				xapp_send_ureject(temp_did,temp_iid,Return_Error,Return_Error_UIID,psm_ptr->xap_flag);
			}
			else
				requesting_ssm(cmp_ptr,NEGATIVE_RESULT_RECEIVED,0);
			break;
		case U_Reject:
#if _SUPPORT_ANSI
		case U_Reject_Ansi:
#endif
			rej_ptr = (TCReject_struct *) &cmp_ptr->cmp_prim.tc_reject;
			if (rej_ptr->problem_type == Invoke_Problem)
			{
				if (!check_iid(temp_did,temp_iid))
					xapp_send_notice(psm_ptr->port_id,temp_did,AbnormalEventReceived);
				else
					requesting_ssm(cmp_ptr,USER_REJECT_RECEIVED,0);
			}
			else
				xapp_send_notice(psm_ptr->port_id,temp_did,ResponseRejected);
			break;
		case R_Reject:
#if _SUPPORT_ANSI
		case R_Reject_Ansi:
#endif
			rej_ptr = (TCReject_struct *) &cmp_ptr->cmp_prim.tc_reject;
			if (rej_ptr->problem_type == Invoke_Problem)
			{
				if (!check_iid(temp_did,temp_iid))
					xapp_send_notice(psm_ptr->port_id,temp_did,AbnormalEventReceived);
				else
					requesting_ssm(cmp_ptr,PROVIDER_REJECT_RECEIVED,0);	// there is not identify with protocol
			}
			else
				xapp_send_notice(psm_ptr->port_id,temp_did,AbnormalEventDetect);
			break;
		case L_Reject:
#if _SUPPORT_ANSI
		case L_Reject_Ansi:
#endif
			rej_ptr = (TCReject_struct *) &cmp_ptr->cmp_prim.tc_reject;
			if (rej_ptr->problem_type == Invoke_Problem)
			{
				if (!check_iid(temp_did,temp_iid))
					xapp_send_notice(psm_ptr->port_id,temp_did,MessageNotDelivered);
				else
					requesting_ssm(cmp_ptr,PROVIDER_REJECT_RECEIVED,0);
			}
			else
				xapp_send_notice(psm_ptr->port_id,temp_did,AbnormalEventDetect);
			break;
		default:
			break;
	}
	if (cmp_ptr->last_flag == 1)
		return 1;
	return 0;
}

int include_dialogue(u32 proc)
{
	struct	xapp_vm_data		*vm_ptr;
	struct	psmvm_data			*psm_ptr;
	
	vm_ptr = (xapp_vm_data *) &xap_vm_ptr->xap_data[proc];
	psm_ptr = (psmvm_data *) &vm_ptr->psm_data;
	
	switch (psm_ptr->xap_flag)
	{
	case XAP_MAP_SSN:
		if (psm_ptr->acn_ver>AC_Version1)
			return 1;//map version 2 and map version 3 include dialogue portion
		break;
	case XAP_CAP_SSN:
		if (psm_ptr->acn_ver>0)
			return 1;
		break;
#if _SUPPORT_ANSI
	case XAP_IS41_SSN:
		return 1;//is41 do not has dialogue portion
#endif
	default:
		break;
	}
	
	return 0;
}


int	wfur_program(u32 proc)	// wait for user requests
{
	struct	xapp_vm_data		*vm_ptr;
	struct	psmvm_data			*psm_ptr;
	struct	MapOpen_Arg			*open_ptr;
	struct	MapDlg_struct		map_dlg;
	struct	MapDlgOpen_struct	*dlg_open;
	struct	TCBegin_struct		*begin_ptr;
	struct	CSLdlg_struct		csl_data;
	struct	dlgport_struct		tcap_dlg;
	u8      ss_mapv1_flag=0;

	vm_ptr = (xapp_vm_data *) &xap_vm_ptr->xap_data[proc];
	psm_ptr = (psmvm_data *) &vm_ptr->psm_data;
	if (vm_ptr->recvopr_flag != 0 && !(psm_ptr->acn_ver == 1  && psm_ptr->acn == AC_networkFunctionalSs))	// has components
	{
		psm_ptr->data_count += requesting_ssm(&vm_ptr->recvopr_data,SERVICE_INVOKED,0);
		vm_ptr->recvopr_flag = 0;
	} 
	else
	{

		if (psm_ptr->delimiter_flag == 1)
		{
			if (vm_ptr->recvcom_data.message_type != MAP_OPEN)	// reqeust open a dialogue
			{
				xap_watch_dog(62);
				return -1;
			}
			
			open_ptr = (MapOpen_Arg *) &vm_ptr->recvcom_data.dlg_list.open_arg;
			begin_ptr = (TCBegin_struct *) &csl_data.dlg_prim.tc_begin;

#if _SUPPORT_ANSI
			if (psm_ptr->xap_flag == XAP_IS41_SSN)
				csl_data.message_type = Query_WithPerm_Ansi;
			else
#endif
				csl_data.message_type = Begin;
			begin_ptr->dialogue_flag = include_dialogue(proc);

			csl_data.message_flag = REQUEST;
			csl_data.dialogue_id = proc;
			
			memcpy(&begin_ptr->peer_add,&open_ptr->peer_add,sizeof(SCCP_ADDR));
			memcpy(&begin_ptr->local_add,&open_ptr->local_add,sizeof(SCCP_ADDR));
			
			if( psm_ptr->acn_ver == 1  && psm_ptr->acn == AC_networkFunctionalSs )
			{
				if ((open_ptr->param_flag & 0x14) == 0x14 )	// has reference
			  {		  	      
	           begin_ptr->dlg_data.user_info_len = 0;    
	           ss_mapv1_flag = 1;			 	     
			  }
			}
			else if ((open_ptr->param_flag & 0x14))	// has reference
			{
				map_dlg.dlg_type = MAPDLG_OPEN;
				dlg_open = (MapDlgOpen_struct *) &map_dlg.map_dlg.map_open;
				dlg_open->param_flag = 0;
				if ((open_ptr->param_flag & 0x04) )
			    {
			     if( open_ptr->peerref_len <= ISDN_LEN+1 )	// has peer ref
			     {
					dlg_open->param_flag |= 0x01;
					dlg_open->peer_ref[0] = open_ptr->peerref_len;
					memcpy(dlg_open->peer_ref+1,open_ptr->peer_reference,open_ptr->peerref_len);
				 }
				 else
				 {
				    xap_send_error("dlg open peerref is too long :%d \r\n" , open_ptr->peerref_len );		 
				 }
				}
				if ((open_ptr->param_flag |= 0x10) )
				{
				  if( open_ptr->localref_len <= ISDN_LEN+1)	// has local ref
		 	      {
					dlg_open->param_flag |= 0x02;
					dlg_open->local_ref[0] = open_ptr->localref_len;
					memcpy(dlg_open->local_ref+1,open_ptr->local_reference,open_ptr->localref_len);
				  }
				  else
				  {
					xap_send_error("dlg open localref is too long :%d \r\n" , open_ptr->localref_len );	  
				  }
				}
				
				begin_ptr->dlg_data.user_info_len = build_mapdlg(&map_dlg,begin_ptr->dlg_data.user_info);
			}
			else
				begin_ptr->dlg_data.user_info_len = 0;
				
#if _SUPPORT_ANSI
			begin_ptr->dlg_data.security_context_len = 0;
			begin_ptr->dlg_data.confidential_info_len = 0;
#endif
			/*	++++ not support the specific information +++	*/
			if( ss_mapv1_flag )
			{
				  struct MapOprSrv_struct srv_ptr;
			  	  
			  	srv_ptr.port_id      = psm_ptr->port_id;
	        srv_ptr.dialogue_id  = proc;
	        srv_ptr.invoke_id    = map_get_invokeid(proc);
	        srv_ptr.message_type = BeginSubAct;
	        srv_ptr.message_flag = MAP_REQUEST; 
	         
	        begin_ptr->dlg_data.user_info_len = 0;
				  send_SSBeginSubActy( open_ptr ,  &srv_ptr);
				  psm_ptr->data_count++;
				  if (vm_ptr->recvopr_flag != 0 && (psm_ptr->acn_ver == 1  && psm_ptr->acn == AC_networkFunctionalSs))	// has components
	        {
		            psm_ptr->data_count += requesting_ssm(&vm_ptr->recvopr_data,SERVICE_INVOKED,0);
		            vm_ptr->recvopr_flag = 0;
	        } 
			}
			begin_ptr->component_present = psm_ptr->data_count; 
			psm_ptr->data_count = 0;
			
			if( psm_ptr->acn_ver == 1 && psm_ptr->xap_flag != XAP_CAP_SSN)
				  psm_ptr->acn = 0;
				  
			set_xapacn(&begin_ptr->dlg_data,psm_ptr);
			
			SendTcapDlg(&csl_data);	
			xap_watch_dog(4);
			xap_dlg_display(&csl_data);
			
			psm_ptr->delimiter_flag = 0;
//			psm_ptr->msg_type = 0;
//			psm_ptr->msg_flag = 0;
//			vm_ptr->recvcom_flag = 0;
			return 1;
		}
		else if (psm_ptr->msg_type == MAP_U_ABORT && psm_ptr->msg_flag == MAP_REQUEST)
		{
			tcap_dlg.acn_len = 0;
			map_dlg.dlg_type = MAPDLG_UABORT;
			set_mapuabort_reason(&map_dlg.map_dlg.map_uabort,&vm_ptr->recvcom_data.dlg_list.uabort_arg);
			tcap_dlg.user_info_len = build_mapdlg(&map_dlg,tcap_dlg.user_info);
#if _SUPPORT_ANSI
			tcap_dlg.security_context_len = 0;
			tcap_dlg.confidential_info_len = 0;
#endif
			xapp_send_uabort(proc,UABORT_SPEC,1,&tcap_dlg,psm_ptr->xap_flag);
			psm_ptr->msg_type = 0;
			psm_ptr->msg_flag = 0;
			vm_ptr->recvcom_flag = 0;
			xap_watch_dog(26);
			xap_watch_dog(30);
			return -1;
		}
	}
	return 0;
}

int	wfcbi_program(u32 proc)	// wait for check begin indicate
{
	struct	xapp_vm_data		*vm_ptr;
	struct	psmvm_data			*psm_ptr;
	struct	CSLdlg_struct		*tcap_ptr;
	struct	TCBegin_struct		*begin_ptr;
	struct	dlgport_struct		*dlg_ptr;
	struct	MapDlg_struct		*map_dlg;
	struct	MapDlgOpen_struct	*dlg_open;
	struct	CSLcmp_struct		csl_cmp;
	struct	MapComSrv_struct	map_com;
	struct	MapOpen_Arg			*open_ptr;
	struct	dlgport_struct		tcap_dlg;
	u8		result;
	u32		temp_flag=0;
	u8    mapv1_ss_flag=0;

	vm_ptr = (xapp_vm_data *) &xap_vm_ptr->xap_data[proc];
	psm_ptr = (psmvm_data *) &vm_ptr->psm_data;
	tcap_ptr = (CSLdlg_struct *) &vm_ptr->tcap_data;
	begin_ptr = (TCBegin_struct *) &tcap_ptr->dlg_prim.tc_begin;
	dlg_ptr = (dlgport_struct *) &begin_ptr->dlg_data;
	map_dlg = (MapDlg_struct *) &vm_ptr->map_dlg;
	switch (psm_ptr->sub_state1)
	{
		case 0:
      if (begin_ptr->dialogue_flag == 0)
                dlg_ptr->acn_len = 0;
			result = get_xapacn(psm_ptr,dlg_ptr);
			if( psm_ptr->acn == 0 && psm_ptr->acn_ver == AC_Version1 && begin_ptr->component_present == 0)
			{
				map_dlg->dlg_type = MAPDLG_PABORT;
				map_dlg->map_dlg.map_pabort.reason = abnormaldial;	// abnormal dialogue
				tcap_dlg.acn_len = 0;
				tcap_dlg.user_info_len = build_mapdlg(map_dlg,tcap_dlg.user_info);
#if _SUPPORT_ANSI
				tcap_dlg.security_context_len = 0;
				tcap_dlg.confidential_info_len = 0;
#endif
				xap_send_error("wait for check begin indicate: MAP V1 operation must send TC_Begin with component!\n", psm_ptr->xap_flag, psm_ptr->acn_ver);
				xapp_send_uabort(proc,UABORT_SPEC,1,&tcap_dlg,psm_ptr->xap_flag);
				return -1;
			}
			
			if (result == 0)
			{
				map_dlg->dlg_type = MAPDLG_PABORT;
				map_dlg->map_dlg.map_pabort.reason = abnormaldial;	// abnormal dialogue
				tcap_dlg.acn_len = 0;
				tcap_dlg.user_info_len = build_mapdlg(map_dlg,tcap_dlg.user_info);
#if _SUPPORT_ANSI
				tcap_dlg.security_context_len = 0;
				tcap_dlg.confidential_info_len = 0;
#endif
				xap_send_error("wait for check begin indicate: ACN not Supported. xap_flag=%d Version=%d", psm_ptr->xap_flag, psm_ptr->acn_ver);
				xapp_send_uabort(proc,UABORT_SPEC,1,&tcap_dlg,psm_ptr->xap_flag);
				return -1;
			}
			else
			{
				if (dlg_ptr->user_info_len != 0)	// include user information
				{
					if ((!extract_mapdlg(map_dlg,dlg_ptr)) || (map_dlg->dlg_type != MAPDLG_OPEN))
					{
						map_dlg->dlg_type = MAPDLG_PABORT;
						map_dlg->map_dlg.map_pabort.reason = abnormaldial;	// abnormal dialogue
						tcap_dlg.acn_len = 0;
						tcap_dlg.user_info_len = build_mapdlg(map_dlg,tcap_dlg.user_info);
						
#if _SUPPORT_ANSI
						tcap_dlg.security_context_len = 0;
						tcap_dlg.confidential_info_len = 0;
#endif
						xap_send_error("wait for check begin indicate: abnormal dialogue");
						xapp_send_uabort(proc,UABORT_SPEC,1,&tcap_dlg,psm_ptr->xap_flag);
						return -1;
					}
					else
						psm_ptr->sub_state1 = 2;
				}
				else
				{
					if (psm_ptr->acn == AC_networkFunctionalSs || psm_ptr->acn == AC_networkUnstructuredSs)
					{
						map_dlg->dlg_type = MAPDLG_PABORT;
						map_dlg->map_dlg.map_pabort.reason = abnormaldial;	// abnormal dialogue
						tcap_dlg.acn_len = 0;
						tcap_dlg.user_info_len = build_mapdlg(map_dlg,tcap_dlg.user_info);
#if _SUPPORT_ANSI
						tcap_dlg.security_context_len = 0;
						tcap_dlg.confidential_info_len = 0;
#endif
						xap_send_error("wait for check begin indicate: User information can't be absent in dialogue for AC_networkFunctionalSs");
						xapp_send_uabort(proc,UABORT_SPEC,1,&tcap_dlg,psm_ptr->xap_flag);
						return -1;
					}
					else 
					  psm_ptr->sub_state1 = 2;
				}
			}
			break;
		case 1:	// wait for init data
			if (vm_ptr->sendopr_flag == 0)	// can receive operation data
			{
				if (RecvTcapCmp(&csl_cmp,proc))
				{/*	+++ do not derive the version 1 of AC +++	*/
					xap_send_error("wait for check begin indicate: AC not include 2");
					xap_cmp_display(&csl_cmp);
					xapp_send_uabort(proc,UABORT_NULL,0,&tcap_dlg,psm_ptr->xap_flag);
					return -1;
				}
			}
			break;
		case 2:	// wait for load check result1
			open_ptr = (MapOpen_Arg *) &map_com.dlg_list.open_arg;
			if( psm_ptr->acn_ver == AC_Version1 && begin_ptr->component_present > 0 ) //check if map v1 SS
			{
					result = recv_SSBeginSubActy( proc , &csl_cmp, open_ptr );
			    switch( result )
			    {
				    case 1:
				  	   mapv1_ss_flag = 1; //map v1 ss
				  	   break;
				    case 2:
				    	 mapv1_ss_flag  = 2; // map v1 not ss
				    	 break;
				  default:
				  	   map_dlg->dlg_type = MAPDLG_PABORT;
				       map_dlg->map_dlg.map_pabort.reason = invalidPDU;	// abnormal dialogue
				       tcap_dlg.acn_len = 0;
				       tcap_dlg.user_info_len = build_mapdlg(map_dlg,tcap_dlg.user_info);
#if _SUPPORT_ANSI
				       tcap_dlg.security_context_len = 0;
				       tcap_dlg.confidential_info_len = 0;
#endif
				       xap_send_error("MAP V1 SS wait for beginSubActivity fail xap_flag=%d Version=%d", psm_ptr->xap_flag, psm_ptr->acn_ver);
				       xapp_send_uabort(proc,UABORT_SPEC,1,&tcap_dlg,psm_ptr->xap_flag);
				       return -1;
				  	   break;
		      }
		  }

			result = check_acname(psm_ptr->acn,psm_ptr->acn_ver,psm_ptr->xap_flag);
			if (result==0)	// AC is supported
			{
				map_com.message_type = MAP_OPEN;
				map_com.message_flag = MAP_INDICATE;
				map_com.port_id = 0;	// need deside by map user
				map_com.dialogue_id = proc;
				open_ptr = (MapOpen_Arg *) &map_com.dlg_list.open_arg;
				open_ptr->acn_data.acn = psm_ptr->acn;
				open_ptr->acn_data.acn_ver = psm_ptr->acn_ver;
				temp_flag = 0x01;
				memcpy(&open_ptr->peer_add,&begin_ptr->peer_add,sizeof(SCCP_ADDR));
				temp_flag |= 0x02;
				memcpy(&open_ptr->local_add,&begin_ptr->local_add,sizeof(SCCP_ADDR));
				temp_flag |= 0x08;
				if( mapv1_ss_flag == 1 ) 
				{
					  temp_flag |= 0x14;
			  }	
				else if (vm_ptr->map_dlg.dlg_type == MAPDLG_OPEN)	// has dlg open
				{
					dlg_open = (MapDlgOpen_struct *) &map_dlg->map_dlg.map_open;
					if (dlg_open->param_flag & 0x01)	// has peer reference
					{
						open_ptr->peerref_len = dlg_open->peer_ref[0];
						memcpy(open_ptr->peer_reference,dlg_open->peer_ref+1,dlg_open->peer_ref[0]);
						temp_flag |= 0x04;
					}
					if (dlg_open->param_flag & 0x02)	// has local reference
					{
						open_ptr->localref_len = dlg_open->local_ref[0];
						memcpy(open_ptr->local_reference,dlg_open->local_ref+1,dlg_open->local_ref[0]);
						temp_flag |= 0x10;
					}
				}
				
				open_ptr->param_flag = temp_flag;
				map_com.component_present = begin_ptr->component_present;
				if (xapp_send_comdata(&map_com))
				{
					if (begin_ptr->component_present == 1)
					{
						psm_ptr->sub_state1 = 4;
						if(mapv1_ss_flag == 2)
						{
							 if (process_components(&csl_cmp,proc))
						       psm_ptr->sub_state1 = 5;
						}
					}
					else
						psm_ptr->sub_state1 = 5;
//					psm_ptr->sub_state1 = 3;
				}
				else
				{
					xap_send_error("wait for check begin indicate: xapp_send_comdata fail");
					xapp_send_uabort(proc,UABORT_NULL,0,&tcap_dlg,psm_ptr->xap_flag);
					return -1;
				}
			}
			else
			{
				tcap_dlg.acn_len = dlg_ptr->acn_len;
				memcpy(tcap_dlg.acn,dlg_ptr->acn,dlg_ptr->acn_len);
				if (result == 2)	// acn version not support
					tcap_dlg.acn[dlg_ptr->acn_len-1] = get_xapacn_ver(dlg_ptr->acn[dlg_ptr->acn_len-2],psm_ptr->xap_flag);
				tcap_dlg.user_info_len = 0;
#if _SUPPORT_ANSI
				tcap_dlg.security_context_len = 0;
				tcap_dlg.confidential_info_len = 0;
#endif
				xap_send_error("wait for check begin indicate: ACN not Supported. AC=%d Version=%d", psm_ptr->acn, psm_ptr->acn_ver);
				xapp_send_uabort(proc,UABORT_ACNNS,1,&tcap_dlg,psm_ptr->xap_flag);
				return -1;
			}
			break;
//		case 3:	// wait the link response from map user
//			if (psm_ptr->msg_type == MAP_LINK)
//			{
//				psm_ptr->port_id = vm_ptr->recvcom_data.port_id;
//				psm_ptr->msg_type = 0;
//				psm_ptr->msg_flag = 0;
//				vm_ptr->recvcom_flag = 0;
//				if (begin_ptr->component_present == 1)
//					psm_ptr->sub_state1 = 4;
//				else
//					psm_ptr->sub_state1 = 5;
//			}
//			else if (psm_ptr->msg_type == MAP_CLOSE)
//			{
//				xapp_send_uabort(proc,UABORT_NULL,0,&tcap_dlg,psm_ptr->xap_flag);
//				return -1;
//			}
//			break;
		case 4:	// process component
			if (vm_ptr->sendopr_flag != 1 && vm_ptr->sendcom_flag == 0)
			{
				if (RecvTcapCmp(&csl_cmp,proc))
				{
					xap_cmp_display(&csl_cmp);
					if (process_components(&csl_cmp,proc))
						psm_ptr->sub_state1 = 5;
				}
			}
			break;
		case 5:	// send delimiter primitive
			if (vm_ptr->sendcom_flag == 0)
			{
				map_com.message_type = MAP_DELIMITER;
				map_com.message_flag = MAP_INDICATE;
				map_com.port_id = psm_ptr->port_id;
				map_com.dialogue_id = proc;
				xapp_send_comdata(&map_com);
				return 1;
			}
			break;
		default:
			psm_ptr->sub_state1 = 0;
			break;
	}
	return 0;
}

int dlginit_program(u32 proc)	// dialogue initiated
{
	struct	xapp_vm_data		*vm_ptr;
	struct	psmvm_data			*psm_ptr;
	struct	CSLdlg_struct		*tcap_ptr;
	struct	TCContinue_struct	*tccon_ptr;
	struct	dlgport_struct		*port_ptr;
	struct	TCEnd_struct		*tcend_ptr;
	struct	TCUAbort_struct		*tcua_ptr;
	struct	MapComSrv_struct	map_com;
	struct	MapUAbort_Arg		*mapua_ptr;
	struct	MapOpen_Res			*mapo_ptr;
	struct	CSLdlg_struct		csl_dlg;
	struct	CSLcmp_struct		csl_cmp;
	struct	MapDlg_struct		map_dlg;
	struct	dlgport_struct		tcap_dlg;
	u8		result;

	vm_ptr = (xapp_vm_data *) &xap_vm_ptr->xap_data[proc];
	psm_ptr = (psmvm_data *) &vm_ptr->psm_data;
	tcap_ptr = (CSLdlg_struct *) &vm_ptr->tcap_data;
	switch (psm_ptr->sub_state1)
	{
		case 0:
			if (vm_ptr->sendcom_flag == 0 && RecvTcapDlg(tcap_ptr,proc))
			{
				xap_dlg_display(tcap_ptr);
				switch (tcap_ptr->message_type)
				{
					case Continue:
#if _SUPPORT_ANSI
					case Conversation_WithPerm_Ansi:
#endif
						tccon_ptr = (TCContinue_struct *) &tcap_ptr->dlg_prim.tc_continue;
						port_ptr = (dlgport_struct *) &tccon_ptr->dlg_data;
						if (!cmp_acname(psm_ptr,port_ptr))	// AC changed
						{
							xap_send_error("XAPP <== TCAP TC-Continue(Unexpected Dlg, AC Changed), did=%d", proc);
							xapp_send_pabort(psm_ptr->port_id,proc,AbnormalMAPDialogue,MAPProblem);
							map_dlg.dlg_type = MAPDLG_PABORT;
							map_dlg.map_dlg.map_pabort.reason = abnormaldial;	// abnormal dialogue
							tcap_dlg.acn_len = 0;
							tcap_dlg.user_info_len = build_mapdlg(&map_dlg,tcap_dlg.user_info);
#if _SUPPORT_ANSI
							tcap_dlg.security_context_len = 0;
							tcap_dlg.confidential_info_len = 0;
#endif
							xapp_send_uabort(proc,UABORT_SPEC,1,&tcap_dlg,psm_ptr->xap_flag);
							psm_ptr->sub_state1 = 5;
						}
						else
						{
							map_com.message_type = MAP_OPEN;
							map_com.message_flag = MAP_CONFIRM;
							map_com.port_id = psm_ptr->port_id;
							map_com.dialogue_id = proc;
							mapo_ptr = (MapOpen_Res *) &map_com.dlg_list.open_res;
							if (tccon_ptr->dialogue_flag == 1 && port_ptr->acn_len != 0)	// has acn
							{
								mapo_ptr->acn_data.acn = psm_ptr->acn;
								mapo_ptr->acn_data.acn_ver = psm_ptr->acn_ver;
								mapo_ptr->param_flag = 0x01;	// indicate thata has acn
							}
							else
								mapo_ptr->param_flag = 0;
							mapo_ptr->result = OpenResultAccept;
							mapo_ptr->param_flag += 0x08;
							xapp_send_comdata(&map_com);
							if (tccon_ptr->component_present == 1)
								psm_ptr->sub_state1 = 1;
							else
								return 1;
						}
						break;
					case End:
#if _SUPPORT_ANSI
					case Response_Ansi:
#endif
						tcend_ptr = (TCEnd_struct *) &tcap_ptr->dlg_prim.tc_end;
						port_ptr = (dlgport_struct *) &tcend_ptr->dlg_data;
						if (!cmp_acname(psm_ptr,port_ptr))	// AC changed
						{
							xap_send_error("XAPP <== TCAP TC-End(Unexpected Dlg, AC Changed), did=%d", proc);
							xapp_send_pabort(psm_ptr->port_id,proc,AbnormalMAPDialogue,MAPProblem);
							psm_ptr->sub_state1 = 5;
						}
						else
						{
							map_com.message_type = MAP_OPEN;
							map_com.message_flag = MAP_CONFIRM;
							map_com.port_id = psm_ptr->port_id;
							map_com.dialogue_id = proc;
							mapo_ptr = (MapOpen_Res *) &map_com.dlg_list.open_res;
							if (tcend_ptr->dialogue_flag == 1 && port_ptr->acn_len != 0)	// has acn
							{
								mapo_ptr->acn_data.acn = psm_ptr->acn;
								mapo_ptr->acn_data.acn_ver = psm_ptr->acn_ver;
								mapo_ptr->param_flag = 0x01;	// indicate thata has acn
							}
							else
								mapo_ptr->param_flag = 0;
							mapo_ptr->result = OpenResultAccept;
							mapo_ptr->param_flag += 0x08;
							xapp_send_comdata(&map_com);
							if (tcend_ptr->component_present == 1)
								psm_ptr->sub_state1 = 3;
							else
								psm_ptr->sub_state1 = 4;
						}
						break;
					case U_Abort:
#if _SUPPORT_ANSI
					case U_Abort_Ansi:
#endif
						tcua_ptr = (TCUAbort_struct *) &tcap_ptr->dlg_prim.tc_uabort;
						port_ptr = (dlgport_struct *) &tcua_ptr->dlg_data;
						xap_send_error("XAPP <== TCAP U_Abort did=%d Reason=%s", proc, tcap_uabort_desc[tcua_ptr->uabort_reason % 3]);
						if (tcua_ptr->uabort_reason == UABORT_SPEC)
						{
							if (!extract_mapdlg(&map_dlg,port_ptr))
							{
								xapp_send_openrefuse(psm_ptr->port_id,proc,PotentialVerIncompat);
								psm_ptr->sub_state1 = 5;
							}
							else
							{
								if (map_dlg.dlg_type == MAPDLG_UABORT)
								{
									map_com.message_type = MAP_U_ABORT;
									map_com.message_flag = MAP_INDICATE;
									map_com.port_id = psm_ptr->port_id;
									map_com.dialogue_id = proc;
									mapua_ptr = (MapUAbort_Arg *) &map_com.dlg_list.uabort_arg;
									get_mapuabort_reason(mapua_ptr,&map_dlg.map_dlg.map_uabort);
									xapp_send_comdata(&map_com);
									psm_ptr->sub_state1 = 5;
								}
								else if (map_dlg.dlg_type == MAPDLG_PABORT)
								{
									xapp_send_pabort(psm_ptr->port_id,proc,AbnormalMAPDialogue,MAPProblem);
									psm_ptr->sub_state1 = 5;
								}
								else if (map_dlg.dlg_type == MAPDLG_REFUSE)
								{
									switch (map_dlg.map_dlg.map_refuse.reason)
									{
										case 0:	// noReasonGiven
											result = NoReasonGiven;
											break;
										case 1:	// invalidDstRef
											result = InvalidDesReference;
											break;
										case 2:	// invalidOrgRef
											result = InvalidOrgReference;
											break;
										default:
											result = NoReasonGiven;
											break;
									}
									xapp_send_openrefuse(psm_ptr->port_id,proc,result);
									psm_ptr->sub_state1 = 5;
								}
								else
								{
									xapp_send_openrefuse(psm_ptr->port_id,proc,PotentialVerIncompat);
									psm_ptr->sub_state1 = 5;
								}
							}
						}
						else if (tcua_ptr->uabort_reason == UABORT_ACNNS)
						{
							get_xapacn(psm_ptr,&tcua_ptr->dlg_data);
							xapp_send_openrefuse(psm_ptr->port_id,proc,ACNotSupported);
							psm_ptr->sub_state1 = 5;
						}
						else
						{
                         	xapp_send_openrefuse(psm_ptr->port_id, proc, NoReasonGiven);
                        	psm_ptr->sub_state1 = 5;
						}
						break;
					case P_Abort:
#if _SUPPORT_ANSI
					case P_Abort_Ansi:
#endif
						xap_send_error("XAPP <== TCAP P_Abort did=%d Reason=%s", proc, tcap_pabort_desc[tcap_ptr->dlg_prim.tc_pabort.pabort_reason & 7]);
						if (tcap_ptr->dlg_prim.tc_pabort.pabort_reason == P_Abort_ITP)	// incorrect transaction portion
						{
							xapp_send_openrefuse(psm_ptr->port_id,proc,PotentialVerIncompat);
							psm_ptr->sub_state1 = 5;
						}
						else
						{
							result = get_mappabort_reason(&tcap_ptr->dlg_prim.tc_pabort,proc);
							xapp_send_pabort(psm_ptr->port_id,proc,result,TCProblem);
							psm_ptr->sub_state1 = 5;
						}
						break;
					case Notice:
						xap_send_error("XAPP <== TCAP Notice did=%d", proc);
						xapp_send_openrefuse(psm_ptr->port_id,proc,RemoteNodeNotReachable);
						psm_ptr->sub_state1 = 5;
						break;
					default:
						break;
				}
			}
			else
			{
				if (psm_ptr->msg_type == MAP_U_ABORT && psm_ptr->msg_flag == MAP_REQUEST)
				{
					map_dlg.dlg_type = MAPDLG_PABORT;
					set_mapuabort_reason(&map_dlg.map_dlg.map_uabort,&vm_ptr->recvcom_data.dlg_list.uabort_arg);
					tcap_dlg.acn_len = 0;
					tcap_dlg.user_info_len = build_mapdlg(&map_dlg,tcap_dlg.user_info);
#if _SUPPORT_ANSI
					tcap_dlg.security_context_len = 0;
					tcap_dlg.confidential_info_len = 0;
#endif
					xapp_send_uabort(proc,UABORT_SPEC,1,&tcap_dlg,psm_ptr->xap_flag);
					psm_ptr->msg_type = 0;
					psm_ptr->msg_flag = 0;
					vm_ptr->recvcom_flag = 0;
					xap_watch_dog(26);
					xap_watch_dog(31);
					psm_ptr->sub_state1 = 5;
				}
				else if (psm_ptr->msg_type == MAP_CLOSE && psm_ptr->msg_flag == MAP_REQUEST)
				{
#if _SUPPORT_ANSI
					if ((psm_ptr->xap_flag == XAP_MAP_SSN) ||
						(psm_ptr->xap_flag == XAP_CAP_SSN))
#endif
						csl_dlg.message_type = End;
#if _SUPPORT_ANSI
					else
						csl_dlg.message_type = Response_Ansi;
#endif
					csl_dlg.message_flag = REQUEST;
					csl_dlg.dialogue_id = proc;
					tcend_ptr = (TCEnd_struct *) &csl_dlg.dlg_prim.tc_end;
					tcend_ptr->dialogue_flag = 0;
					tcend_ptr->termination = PRE_END;
					SendTcapDlg(&csl_dlg);
					xap_dlg_display(&csl_dlg);
					psm_ptr->msg_type = 0;
					psm_ptr->msg_flag = 0;
					vm_ptr->recvcom_flag = 0;
					xap_watch_dog(26);
					xap_watch_dog(32);
					psm_ptr->sub_state1 = 5;
				}
				else
				{
					if (vm_ptr->sendcom_flag == 0 && RecvTcapCmp(&csl_cmp,proc))
					{
						xap_cmp_display(&csl_cmp);
						if (csl_cmp.message_type == L_Cancel)
						{
							xap_send_error("L_Cancel did=%d", proc);
							xapp_send_openrefuse(psm_ptr->port_id,proc,RemoteNodeNotReachable);
						}
					}
				}
			}
			break;
		case 1:	// continue process component
			if (vm_ptr->sendopr_flag != 1 && vm_ptr->sendcom_flag == 0)
			{
				if (RecvTcapCmp(&csl_cmp,proc))
				{
					xap_cmp_display(&csl_cmp);
					if (process_components(&csl_cmp,proc))
						psm_ptr->sub_state1 = 2;
				}
			}
			break;
		case 2:	// write delimiter
			if (vm_ptr->sendcom_flag == 0)
			{
				map_com.message_type = MAP_DELIMITER;
				map_com.message_flag = MAP_INDICATE;
				map_com.port_id = psm_ptr->port_id;
				map_com.dialogue_id = proc;
				xapp_send_comdata(&map_com);
				return 1;
			}
			break;
		case 3:	// end process component
			if (vm_ptr->sendopr_flag != 1 && vm_ptr->sendcom_flag == 0)
			{
				if (RecvTcapCmp(&csl_cmp,proc))
				{
					xap_cmp_display(&csl_cmp);
					if (process_components(&csl_cmp,proc))
						psm_ptr->sub_state1 = 4;
				}
			}
			break;
		case 4:	// write end indicate
			if (vm_ptr->sendcom_flag == 0)
			{
				map_com.message_type = MAP_CLOSE;
				map_com.message_flag = MAP_INDICATE;
				map_com.port_id = psm_ptr->port_id;
				map_com.dialogue_id = proc;
				map_com.dlg_list.close_arg.param_flag = 0;
				xapp_send_comdata(&map_com);
				psm_ptr->sub_state1 = 5;
			}
			break;
		case 5:	// terminate PSM&RSM
//			performing_ssm(&csl_cmp,TIMER_EXPIRY);
//			requesting_ssm(&csl_cmp,TIMER_EXPIRY);
			return -1;
			break;
		default:
			psm_ptr->sub_state1 = 0;
			break;
	}
	return 0;
}

int dlgpend_program(u32 proc)	// dialogue pending
{
	struct	xapp_vm_data		*vm_ptr;
	struct	psmvm_data			*psm_ptr;
	struct	MapOpen_Res			*open_ptr;
	struct	MapDlg_struct		map_dlg;
	struct	dlgport_struct		tcap_dlg;
	struct	CSLdlg_struct		csl_dlg;
	struct	TCEnd_struct		*tcend_ptr;

	vm_ptr = (xapp_vm_data *) &xap_vm_ptr->xap_data[proc];
	psm_ptr = (psmvm_data *) &vm_ptr->psm_data;
	switch (psm_ptr->sub_state1)
	{
		case 0:
			if (psm_ptr->msg_type == MAP_OPEN && psm_ptr->msg_flag == MAP_RESPONSE)
			{
				psm_ptr->port_id = vm_ptr->recvcom_data.port_id;
				open_ptr = (MapOpen_Res *) &vm_ptr->recvcom_data.dlg_list.open_res;
				if (open_ptr->result == OpenResultAccept)
				{/*	+++ do not know how to judge if user info include +++	*/
					psm_ptr->msg_type = 0;
					psm_ptr->msg_flag = 0;
					vm_ptr->recvcom_flag = 0;
					xap_watch_dog(26);
					xap_watch_dog(33);
					return 1;
				}
				else
				{
					xap_send_error("dialogue pending: Negative OPEN_RESPONSE");
					map_dlg.dlg_type = MAPDLG_REFUSE;
					map_dlg.map_dlg.map_refuse.reason = 0;	// no reason given
					tcap_dlg.acn_len = 0;
					tcap_dlg.user_info_len = build_mapdlg(&map_dlg,tcap_dlg.user_info);
#if _SUPPORT_ANSI
					tcap_dlg.security_context_len = 0;
					tcap_dlg.confidential_info_len = 0;
#endif
					xapp_send_uabort(proc,UABORT_SPEC,1,&tcap_dlg,psm_ptr->xap_flag);
					psm_ptr->sub_state1 = 1;
					psm_ptr->msg_type = 0;
					psm_ptr->msg_flag = 0;
					vm_ptr->recvcom_flag = 0;
					xap_watch_dog(26);
					xap_watch_dog(34);
				}
			}
			else if (psm_ptr->msg_type == MAP_U_ABORT && psm_ptr->msg_flag == MAP_REQUEST)
			{
				map_dlg.dlg_type = MAPDLG_UABORT;
				set_mapuabort_reason(&map_dlg.map_dlg.map_uabort,&vm_ptr->recvcom_data.dlg_list.uabort_arg);
				tcap_dlg.acn_len = 0;
				tcap_dlg.user_info_len = build_mapdlg(&map_dlg,tcap_dlg.user_info);
#if _SUPPORT_ANSI
				tcap_dlg.security_context_len = 0;
				tcap_dlg.confidential_info_len = 0;
#endif
				xapp_send_uabort(proc,UABORT_SPEC,1,&tcap_dlg,psm_ptr->xap_flag);
				psm_ptr->msg_type = 0;
				psm_ptr->msg_flag = 0;
				vm_ptr->recvcom_flag = 0;
				xap_watch_dog(26);
				xap_watch_dog(35);
				psm_ptr->sub_state1 = 1;
			}
			else if (psm_ptr->msg_type == MAP_CLOSE && psm_ptr->msg_flag == MAP_REQUEST)
			{
#if _SUPPORT_ANSI
				if ((psm_ptr->xap_flag == XAP_MAP_SSN) ||
					(psm_ptr->xap_flag == XAP_CAP_SSN))
#endif
					csl_dlg.message_type = End;
#if _SUPPORT_ANSI
				else
					csl_dlg.message_type = Response_Ansi;
#endif
				csl_dlg.message_flag = REQUEST;
				csl_dlg.dialogue_id = proc;
				tcend_ptr = (TCEnd_struct *) &csl_dlg.dlg_prim.tc_end;
				tcend_ptr->dialogue_flag = 0;
				tcend_ptr->termination = PRE_END;
				SendTcapDlg(&csl_dlg);
				xap_dlg_display(&csl_dlg);
				psm_ptr->msg_type = 0;
				psm_ptr->msg_flag = 0;
				vm_ptr->recvcom_flag = 0;
				xap_watch_dog(26);
				xap_watch_dog(36);
				psm_ptr->sub_state1 = 1;
			}
			else if (psm_ptr->msg_type == MAP_LINK)
			{
				psm_ptr->port_id = vm_ptr->recvcom_data.port_id;
				psm_ptr->msg_type = 0;
				psm_ptr->msg_flag = 0;
				vm_ptr->recvcom_flag = 0;
				xap_watch_dog(26);
				xap_watch_dog(37);
			}
			break;
		case 1:
//			performing_ssm(&csl_cmp,TIMER_EXPIRY);
//			requesting_ssm(&csl_cmp,TIMER_EXPIRY);
			return -1;
			break;
		default:
			psm_ptr->sub_state1 = 0;
			break;
	}
	return 0;
}

int dlgaccp_program(u32 proc)	//dialogue accept program
{
	struct	xapp_vm_data		*vm_ptr;
	struct	psmvm_data			*psm_ptr;
	struct	CSLdlg_struct		csl_dlg;
	struct	MapDlg_struct		map_dlg;
	struct	MapClose_Arg		*mapcls_ptr;
	struct	TCEnd_struct		*tcend_ptr;
	struct	dlgport_struct		tcap_dlg;

	vm_ptr = (xapp_vm_data *) &xap_vm_ptr->xap_data[proc];
	psm_ptr = (psmvm_data *) &vm_ptr->psm_data;
	switch (psm_ptr->sub_state1)
	{
		case 0:
			if (vm_ptr->recvopr_flag != 0)
			{
				if (vm_ptr->recvopr_data.message_flag == MAP_REQUEST)
				{
					psm_ptr->data_count += requesting_ssm(&vm_ptr->recvopr_data,SERVICE_INVOKED,1);
					vm_ptr->recvopr_flag = 0;
				}
				else if (vm_ptr->recvopr_data.message_flag == MAP_RESPONSE)
					psm_ptr->data_count += performing_ssm(&vm_ptr->recvopr_data,RESPONSE_ISSUED,0);
			}
			else
			{
				if (psm_ptr->delimiter_flag == 1)
				{
					csl_dlg.dlg_prim.tc_continue.dialogue_flag = include_dialogue(proc);

#if _SUPPORT_ANSI
					if (psm_ptr->xap_flag == XAP_IS41_SSN)
						csl_dlg.message_type = Conversation_WithPerm_Ansi;//ANSI-Continue
					else
#endif
						csl_dlg.message_type = Continue;
					

					csl_dlg.message_flag = REQUEST;
					csl_dlg.dialogue_id = proc;
					set_xapacn(&csl_dlg.dlg_prim.tc_continue.dlg_data,psm_ptr);
					csl_dlg.dlg_prim.tc_continue.dlg_data.user_info_len = 0;
#if _SUPPORT_ANSI
					csl_dlg.dlg_prim.tc_continue.dlg_data.security_context_len = 0;
					csl_dlg.dlg_prim.tc_continue.dlg_data.confidential_info_len = 0;
#endif
					csl_dlg.dlg_prim.tc_continue.component_present = psm_ptr->data_count;
					psm_ptr->data_count = 0;
					SendTcapDlg(&csl_dlg);
					xap_dlg_display(&csl_dlg);
					psm_ptr->delimiter_flag = 0;
//					psm_ptr->msg_type = 0;
//					psm_ptr->msg_flag = 0;
//					vm_ptr->recvcom_flag = 0;
					return 1;
				}
				else if (psm_ptr->msg_type == MAP_CLOSE && psm_ptr->msg_flag == MAP_REQUEST)
				{
					mapcls_ptr = (MapClose_Arg *) &vm_ptr->recvcom_data.dlg_list.close_arg;
					tcend_ptr = (TCEnd_struct *) &csl_dlg.dlg_prim.tc_end;
					
					tcend_ptr->dialogue_flag = include_dialogue(proc);
#if _SUPPORT_ANSI
					if (psm_ptr->xap_flag == XAP_IS41_SSN)
						csl_dlg.message_type = Response_Ansi;//ANSI-End
					else
#endif
						csl_dlg.message_type = End;
					
					csl_dlg.message_flag = REQUEST;
					csl_dlg.dialogue_id = proc;
			
					set_xapacn(&tcend_ptr->dlg_data,psm_ptr);
					tcend_ptr->dlg_data.user_info_len = 0;
#ifdef _SUPPORT_ANSI
					tcend_ptr->dlg_data.security_context_len = 0;
					tcend_ptr->dlg_data.confidential_info_len = 0;
#endif
					if (mapcls_ptr->release_method == NormalRelease)
					{
						tcend_ptr->termination = BASIC_END;
						tcend_ptr->component_present = psm_ptr->data_count;
					}
					else
						tcend_ptr->termination = PRE_END;
					psm_ptr->data_count = 0;
					SendTcapDlg(&csl_dlg);
					xap_dlg_display(&csl_dlg);
					psm_ptr->msg_type = 0;
					psm_ptr->msg_flag = 0;
					vm_ptr->recvcom_flag = 0;
					xap_watch_dog(26);
					xap_watch_dog(38);
					psm_ptr->sub_state1 = 1;
				}
				else if (psm_ptr->msg_type == MAP_U_ABORT && psm_ptr->msg_flag == MAP_REQUEST)
				{
					map_dlg.dlg_type = MAPDLG_UABORT;
					set_mapuabort_reason(&map_dlg.map_dlg.map_uabort,&vm_ptr->recvcom_data.dlg_list.uabort_arg);
					tcap_dlg.acn_len = 0;
					tcap_dlg.user_info_len = build_mapdlg(&map_dlg,tcap_dlg.user_info);
#if _SUPPORT_ANSI
					tcap_dlg.security_context_len = 0;
					tcap_dlg.confidential_info_len = 0;
#endif
					xapp_send_uabort(proc,UABORT_SPEC,1,&tcap_dlg,psm_ptr->xap_flag);
					psm_ptr->msg_type = 0;
					psm_ptr->msg_flag = 0;
					vm_ptr->recvcom_flag = 0;
					xap_watch_dog(26);
					xap_watch_dog(39);
					psm_ptr->sub_state1 = 1;
				}
			}
			break;
		case 1:
//			performing_ssm(&csl_cmp,TIMER_EXPIRY);
//			requesting_ssm(&csl_cmp,TIMER_EXPIRY);
			return -1;
			break;
		default:
			psm_ptr->sub_state1 = 0;
			break;
	}
	return 0;
}

int dlgestab_program(u32 proc)		// dialogue established
{
	struct	xapp_vm_data		*vm_ptr;
	struct	psmvm_data			*psm_ptr;
	struct	MapDlg_struct		map_dlg;
	struct	CSLdlg_struct		csl_dlg;
	struct	CSLdlg_struct		*csl_ptr;
	struct	TCUAbort_struct		*tcua_ptr;
	struct	TCEnd_struct		*tcend_ptr;
	struct	CSLcmp_struct		csl_cmp;
	struct	MapComSrv_struct	map_com;
	struct	dlgport_struct		tcap_dlg;
	u8		result;

	vm_ptr = (xapp_vm_data *) &xap_vm_ptr->xap_data[proc];
	psm_ptr = (psmvm_data *) &vm_ptr->psm_data;
	switch (psm_ptr->sub_state1)
	{
		case 0:
			if (vm_ptr->sendcom_flag == 0 && RecvTcapDlg(&csl_dlg,proc))
			{
				switch (csl_dlg.message_type)
				{
					case Continue:
#if _SUPPORT_ANSI
					case Conversation_WithPerm_Ansi:
#endif
						if (csl_dlg.dlg_prim.tc_continue.component_present == 1)
						{
							psm_ptr->suspend_timer = 0;
							psm_ptr->sub_state1 = 1;
						}
						break;
					case End:
#if _SUPPORT_ANSI
					case Response_Ansi:
#endif
						if (csl_dlg.dlg_prim.tc_end.component_present == 1)
							psm_ptr->sub_state1 = 2;
						else
							psm_ptr->sub_state1 = 3;
						break;
					case U_Abort:
#if _SUPPORT_ANSI
					case U_Abort_Ansi:
#endif
						tcua_ptr = (TCUAbort_struct *) &csl_dlg.dlg_prim.tc_uabort;
						xap_send_error("XAPP <== TCAP U_Abort did=%d Reason=%s", proc, tcap_uabort_desc[tcua_ptr->uabort_reason%3]);
						if (extract_mapdlg(&map_dlg,&tcua_ptr->dlg_data))	// analyse user info
						{
							map_com.message_flag = MAP_INDICATE;
							map_com.port_id = psm_ptr->port_id;
							map_com.dialogue_id = proc;
							if (map_dlg.dlg_type == MAPDLG_UABORT)
							{
								map_com.message_type = MAP_U_ABORT;
								get_mapuabort_reason(&map_com.dlg_list.uabort_arg,&map_dlg.map_dlg.map_uabort);
								xapp_send_comdata(&map_com);
							}
							else if (map_dlg.dlg_type == MAPDLG_PABORT)
								xapp_send_pabort(psm_ptr->port_id,proc,AbnormalMAPDialogue,TCProblem);
						}
						psm_ptr->sub_state1 = 4;
						break;
					case P_Abort:
#if _SUPPORT_ANSI
					case P_Abort_Ansi:
#endif
						xap_send_error("XAPP <== TCAP P_Abort did=%d Reason=%s", proc, tcap_pabort_desc[csl_dlg.dlg_prim.tc_pabort.pabort_reason & 7]);
						result = get_mappabort_reason(&csl_dlg.dlg_prim.tc_pabort,proc);
						xapp_send_pabort(psm_ptr->port_id,proc,result,TCProblem);
						psm_ptr->sub_state1 = 4;
						break;
					case Notice:
						xap_send_error("XAPP <== TCAP Notice did=%d", proc);
						xapp_send_notice(psm_ptr->port_id,proc,csl_dlg.dlg_prim.tc_notice.report_reason);
						break;
					default:
						break;
				}
			}
			else
			{
				if (vm_ptr->sendcom_flag == 0 && vm_ptr->sendopr_flag != 1 && RecvTcapCmp(&csl_cmp,proc))
				{
					xap_cmp_display(&csl_cmp);
					if (csl_cmp.message_type == L_Cancel)
						requesting_ssm(&csl_cmp,TIMER_EXPIRY,0);
				}
			}
			if (vm_ptr->recvopr_flag != 0)
			{
				if (vm_ptr->recvopr_data.message_flag == MAP_REQUEST)
				{
					psm_ptr->data_count += requesting_ssm(&vm_ptr->recvopr_data,SERVICE_INVOKED,1);
					vm_ptr->recvopr_flag = 0;
				}
				else if (vm_ptr->recvopr_data.message_flag == MAP_RESPONSE)
					psm_ptr->data_count += performing_ssm(&vm_ptr->recvopr_data,RESPONSE_ISSUED,1);
			}
			else
			{
				if (vm_ptr->tcap_data.message_type != 0)
				{
					if (SendTcapDlg(&vm_ptr->tcap_data))
					{
						xap_dlg_display(&vm_ptr->tcap_data);
						if (vm_ptr->recvcom_flag == 1)
							xap_watch_dog(41);
						vm_ptr->recvcom_flag = 0;
						psm_ptr->suspend_timer = 0;
#if _SUPPORT_ANSI
						if (vm_ptr->tcap_data.message_type == End || vm_ptr->tcap_data.message_type == U_Abort	||
							vm_ptr->tcap_data.message_type == Response_Ansi || vm_ptr->tcap_data.message_type == U_Abort_Ansi)
#else
						if (vm_ptr->tcap_data.message_type == End || vm_ptr->tcap_data.message_type == U_Abort)
#endif
							psm_ptr->sub_state1 = 4;
						vm_ptr->tcap_data.message_type = 0;
					}
				}
				else
				{
					csl_ptr = (CSLdlg_struct *) &vm_ptr->tcap_data;
					csl_ptr->message_flag = REQUEST;
					csl_ptr->dialogue_id = proc;
					if (psm_ptr->delimiter_flag == 1)
					{
#if _SUPPORT_ANSI
						if ((psm_ptr->xap_flag == XAP_MAP_SSN) ||
							(psm_ptr->xap_flag == XAP_CAP_SSN))
#endif
							csl_ptr->message_type = Continue;
#if _SUPPORT_ANSI
						else
							csl_ptr->message_type = Conversation_WithPerm_Ansi;
#endif
						csl_ptr->dlg_prim.tc_continue.dialogue_flag = 0;
						csl_ptr->dlg_prim.tc_continue.component_present = psm_ptr->data_count;
						psm_ptr->data_count = 0;
						psm_ptr->delimiter_flag = 0;
//						psm_ptr->msg_type = 0;
//						psm_ptr->msg_flag = 0;
					}
					else if (psm_ptr->msg_type == MAP_CLOSE)
					{
#if _SUPPORT_ANSI
						if ((psm_ptr->xap_flag == XAP_MAP_SSN) ||
							(psm_ptr->xap_flag == XAP_CAP_SSN))
#endif
							csl_ptr->message_type = End;
#if _SUPPORT_ANSI
						else
							csl_ptr->message_type = Response_Ansi;
#endif
						tcend_ptr = (TCEnd_struct *) &csl_ptr->dlg_prim.tc_end;
						tcend_ptr->dialogue_flag = 0;
						if (vm_ptr->recvcom_data.dlg_list.close_arg.release_method == NormalRelease)
						{
							tcend_ptr->termination = BASIC_END;
							tcend_ptr->component_present = psm_ptr->data_count;
						}
						else
							tcend_ptr->termination = PRE_END;
						psm_ptr->data_count = 0;
						psm_ptr->msg_type = 0;
						psm_ptr->msg_flag = 0;
					}
					else if (psm_ptr->msg_type == MAP_U_ABORT)
					{
						map_dlg.dlg_type = MAPDLG_UABORT;
						set_mapuabort_reason(&map_dlg.map_dlg.map_uabort,&vm_ptr->recvcom_data.dlg_list.uabort_arg);
						tcap_dlg.acn_len = 0;
						tcap_dlg.user_info_len = build_mapdlg(&map_dlg,tcap_dlg.user_info);
#if _SUPPORT_ANSI
						tcap_dlg.security_context_len = 0;
						tcap_dlg.confidential_info_len = 0;
#endif
						xapp_send_uabort(proc,UABORT_SPEC,1,&tcap_dlg,psm_ptr->xap_flag);
						psm_ptr->msg_type = 0;
						psm_ptr->msg_flag = 0;
						
						vm_ptr->recvcom_flag = 0;
                        psm_ptr->suspend_timer = 0;

                        psm_ptr->sub_state1 = 4;
                        vm_ptr->tcap_data.message_type = 0;
					}
				}
			}
			break;
		case 1:	// receive continue component
			if (vm_ptr->sendopr_flag != 1 && vm_ptr->sendcom_flag == 0)
			{
				if (RecvTcapCmp(&csl_cmp,proc))
				{
					xap_cmp_display(&csl_cmp);
					if (process_components(&csl_cmp,proc))
					{
						map_com.message_type = MAP_DELIMITER;
						map_com.message_flag = MAP_INDICATE;
						map_com.port_id = psm_ptr->port_id;
						map_com.dialogue_id = proc;
						xapp_send_comdata(&map_com);
						psm_ptr->sub_state1 = 0;
					}
				}
			}
			break;
		case 2:
			if (vm_ptr->sendopr_flag != 1 && vm_ptr->sendcom_flag == 0)
			{
				if (RecvTcapCmp(&csl_cmp,proc))
				{
					xap_cmp_display(&csl_cmp);
					if (process_components(&csl_cmp,proc))
						psm_ptr->sub_state1 = 3;
				}
			}
		case 3:		// send end indicate
			if (vm_ptr->sendcom_flag == 0)
			{
				map_com.message_type = MAP_CLOSE;
				map_com.message_flag = MAP_INDICATE;
				map_com.port_id = psm_ptr->port_id;
				map_com.dialogue_id = proc;
				map_com.dlg_list.close_arg.param_flag = 0;
				xapp_send_comdata(&map_com);
				psm_ptr->sub_state1 = 4;
			}
			break;
		case 4:
//			performing_ssm(&csl_cmp,TIMER_EXPIRY);
//			requesting_ssm(&csl_cmp,TIMER_EXPIRY);
			return 1;
			break;
		default:
			psm_ptr->sub_state1 = 0;
			break;
	}
	return 0;
}

void xap_fsm()		//called per 10ms
{
	register u32			proc;
	struct	xapp_vm_data	*vm_ptr;
	struct	psmvm_data		*psm_ptr;
	struct	MapOpen_Arg		*open_ptr;
	struct	dlgport_struct	tcap_dlg;
	int		result;

/* daniel changed on 2005-4-29 */
	xap_vm_ptr->debug_data.watch_dog[0] = 0;
/* daniel changed on 2005-4-29 */

	xap_monitor();
	for (proc = 1;proc < (xap_vm_ptr->grantdid);proc ++)
	{
		vm_ptr = (xapp_vm_data *) &xap_vm_ptr->xap_data[proc];
		psm_ptr = (psmvm_data *) &vm_ptr->psm_data;
		
/* daniel changed on 2005-4-29 */
		if (psm_ptr->psm_state > XAP_IDLE)
		{
			xap_vm_ptr->debug_data.watch_dog[0]++;
		}
/* daniel changed on 2005-4-29 */
		
		switch (psm_ptr->psm_state)
		{
			case XAP_INIT:
				memset(vm_ptr,0,sizeof(xapp_vm_data));
				psm_ptr->psm_state = XAP_IDLE;
				break;
			case XAP_IDLE:			//idle; (USER)==>MAP-OPEN
				if (psm_ptr->msg_type == MAP_OPEN && psm_ptr->msg_flag == MAP_REQUEST)
				{
					open_ptr = (MapOpen_Arg *) &vm_ptr->recvcom_data.dlg_list.open_arg;
					psm_ptr->acn = open_ptr->acn_data.acn;	// store acn data
					psm_ptr->acn_ver = open_ptr->acn_data.acn_ver;
					psm_ptr->port_id = vm_ptr->recvcom_data.port_id;
					psm_ptr->msg_type = 0;
					psm_ptr->msg_flag = 0;
					vm_ptr->recvcom_flag = 0;
					xap_watch_dog(26);
					xap_watch_dog(40);
					psm_ptr->psm_state = XAP_WFUR;
					xap_watch_dog(1);
				}
				else if (psm_ptr->msg_type == 0)
				{
					if (vm_ptr->sendcom_flag == 0)	// can send common data
					{
						if (RecvTcapDlg(&vm_ptr->tcap_data,proc))
						{
							if (vm_ptr->tcap_data.message_type == Begin)
							{
								xap_watch_dog(2);
								set_xap_flag(proc,vm_ptr->tcap_data.dlg_prim.tc_begin.local_add.SSN);// mark itu
								psm_ptr->psm_state = XAP_WFCBI;
							}
#if _SUPPORT_ANSI
							else if (vm_ptr->tcap_data.message_type == Query_WithPerm_Ansi)
							{
								xap_watch_dog(2);
								psm_ptr->xap_flag = XAP_IS41_SSN;// mark ansi
								psm_ptr->psm_state = XAP_WFCBI;
							}
#endif
						}
					}
				}
				else
				{
					psm_ptr->suspend_timer = 0;
					psm_ptr->psm_state = XAP_DLG_SUSPEND;
				}
				break;
			case XAP_WFUR:	// wait for user requests: (USER)==>Request primitiv/MAP_DELIMITER
				result = wfur_program(proc);
				if (result == 1)
				{
					psm_ptr->sub_state1 = 0;
					psm_ptr->suspend_timer = 0;
					psm_ptr->psm_state = XAP_DLG_INITIATED;
				}
				else if (result == -1)
				{
					psm_ptr->suspend_timer = 0;
					psm_ptr->psm_state = XAP_DLG_SUSPEND;
				}
				if ((psm_ptr->suspend_timer++) >= DLGPEND_TIME * XAPP_TIMERHZ)	// timer is expire
				{
					xap_send_error("wait for user requests: timer expired");
					psm_ptr->psm_state = XAP_DLG_HALT;
				}
				break;
			case XAP_WFCBI:	// wait for check begin indicate
				result = wfcbi_program(proc);
				if (result == 1)	// return dialogue pending
				{
					psm_ptr->suspend_timer = 0;
					psm_ptr->psm_state = XAP_DLG_PENDING;
					psm_ptr->sub_state1 = 0;
				}
				else if (result == -1)
				{
					psm_ptr->suspend_timer = 0;
					psm_ptr->psm_state = XAP_DLG_SUSPEND;
				}
				if ((psm_ptr->suspend_timer++) >= DLGPEND_TIME * XAPP_TIMERHZ)	// timer is expire
				{
					xap_send_error("wait for check begin indicate: timer expired");
					psm_ptr->psm_state = XAP_DLG_HALT;
				}
				break;
			case XAP_DLG_INITIATED:		//Continue<==(TCAP)
				result = dlginit_program(proc);
				if (result == 1)
				{
					vm_ptr->tcap_data.message_type = 0;
					psm_ptr->sub_state1 = 0;
					psm_ptr->suspend_timer = 0;
					psm_ptr->psm_state = XAP_DLG_ESTABLISHED;
				}
				else if (result == -1)
				{
					psm_ptr->suspend_timer = 0;
					psm_ptr->psm_state = XAP_DLG_SUSPEND;
				}
				if ((psm_ptr->suspend_timer++) >= DLGPEND_TIME * XAPP_TIMERHZ)	// timer is expire
				{
					xap_send_error("DLG_INITIATED: timer expired");
					psm_ptr->psm_state = XAP_DLG_HALT;
				}
				break;
			case XAP_DLG_PENDING:
				result = dlgpend_program(proc);
				if (result == 1)
				{
					psm_ptr->sub_state1 = 0;
					psm_ptr->suspend_timer = 0;
					psm_ptr->psm_state = XAP_DLG_ACCEPTED;
				}
				else if (result == -1)
				{
					psm_ptr->suspend_timer = 0;
					psm_ptr->psm_state = XAP_DLG_SUSPEND;
				}
				if ((psm_ptr->suspend_timer++) >= DLGPEND_TIME * XAPP_TIMERHZ)	// timer is expire
				{
					xap_send_error("DLG_PENDING: timer expired");
					psm_ptr->psm_state = XAP_DLG_HALT;
				}
				break;
			case XAP_DLG_ACCEPTED:
				result = dlgaccp_program(proc);
				if (result == 1)
				{
					vm_ptr->tcap_data.message_type = 0;
					psm_ptr->sub_state1 = 0;
					psm_ptr->suspend_timer = 0;
					psm_ptr->psm_state = XAP_DLG_ESTABLISHED;
				}
				else if (result == -1)
				{
					psm_ptr->suspend_timer = 0;
					psm_ptr->psm_state = XAP_DLG_SUSPEND;
				}
				if ((psm_ptr->suspend_timer++) >= DLGPEND_TIME * XAPP_TIMERHZ)	// timer is expire
				{
					xap_send_error("DLG_ACCEPTED: timer expired");
					psm_ptr->psm_state = XAP_DLG_HALT;
				}
				break;
			case XAP_DLG_ESTABLISHED:
				if (dlgestab_program(proc))
				{
					psm_ptr->suspend_timer = 0;
					psm_ptr->psm_state = XAP_DLG_SUSPEND;
				}
				if ((psm_ptr->suspend_timer++) >= DLGPEND_TIME * XAPP_TIMERHZ)	// timer is expire
				{
					xap_send_error("DLG_ESTABLISHED: timer expired");
					psm_ptr->psm_state = XAP_DLG_HALT;
				}
				break;
			case XAP_DLG_SUSPEND:
				if (vm_ptr->sendcom_flag == 0 && vm_ptr->sendopr_flag == 0)
					psm_ptr->psm_state = XAP_INIT;
				if ((psm_ptr->suspend_timer++) >= SUSPEND_TIME * XAPP_TIMERHZ/2)	// timer is expire
				{
					psm_ptr->psm_state = XAP_INIT;
				}
				if(xap_vm_ptr->debug_data.monitor_did == proc)		/* clear monitor flag, port0 never used */
					 xap_vm_ptr->debug_data.monitor_did = 0;
				break;
			case XAP_DLG_HALT:
				xapp_send_pabort(psm_ptr->port_id,proc,AbnormalMAPDialogue,MAPProblem);
				xapp_send_uabort(proc,UABORT_NULL,0,&tcap_dlg,psm_ptr->xap_flag);
				psm_ptr->psm_state = XAP_DLG_SUSPEND;
				break;
			default:
				psm_ptr->psm_state = XAP_INIT;
				break;
		}
	}
}





