/*	MAP public function c file			*/
/*	Written by Liu Zhiguo 2002-03-25	*/
/*	Version 1.0							*/
/*	--------------------------------	*/

#include "map_includes.h"
#include "map_code.h"

// fix multiple definition====================================
int		decErr;
//

#define MAP_CODE_DEBUG 0
static int map_code_debug1 = 1;
extern void xap_watch_dog(u32 wd_site);
#if _SUPPORT_ANSI
extern u8	map_check_map_flag(u32 did);
#endif

void log_doit(int errnoflag, int priority, const char *fmt, va_list ap)
{
    int     errno_save;
    char    buf[2048];

    errno_save = errno;        //value caller might want printed 
    vsprintf(buf, fmt, ap);
    if (errnoflag)
        sprintf(buf+strlen(buf), ": %s", strerror(errno_save));
    strcat(buf, "\n");
    if (map_code_debug1) 
	{
        fflush(stdout);
        fputs(buf, stderr);
        fflush(stderr);
    }
	else
        syslog(priority, "%s", buf);
    return;
}

void mapp_log_debug(const char *fmt, ...)
{	
#if MAP_CODE_DEBUG
    va_list        ap;    

    va_start(ap, fmt);
    log_doit(0,LOG_ERR, fmt, ap);
	printf(fmt, ap);
    va_end(ap);
    return;
#endif
}

u8	bytestrtobitstr(u8 *bit_str,u8 *byte_str,u8 bit_len)
{	// byte string code to bit string code
	u8		ii;
	u8		aa,bb,cc;
	u8		str_len;
	u8		null_len;

	str_len = bit_len / 8;
	null_len = bit_len % 8;
	if (null_len != 0)
	{
		str_len += 2;
		bit_str[0] = 8 - null_len;
	}
	else
	{
		str_len += 1;
		bit_str[0] = 0;
	}
	memset(bit_str+1,0,str_len-1);
	for (ii = 0;ii < bit_len;ii ++)
	{
		aa = ii / 8;
		bb = str_len - aa - 1;
		cc = (byte_str[aa] >> (ii % 8)) & 0x01;
		bit_str[bb] |= cc << (7 - (ii % 8));
	}
	return str_len;
}

u8	bitstrtobytestr(u8 *byte_str,u8 *bit_str,u8 bit_len)
{
	u8		ii;
	u8		aa,bb,cc;
	u8		str_len;
	u8		total_len;

	str_len = bit_len - 1;
	total_len = str_len * 8 - bit_str[0];
	memset(byte_str,0,str_len);
	for (ii = 0;ii < total_len;ii ++)
	{
		aa = ii / 8 + 1;
		bb = str_len - ii / 8 - 1;
		cc = (bit_str[aa] >> (7 - (ii % 8))) & 0x01;
		byte_str[bb] |= cc << (ii % 8);
	}
	return str_len;
}

/*	transfer tele service from bit string to bcd string	*/
u8	tele_bittostr(u16 tele_data,u8 *tele_str,u8 ss_flag)
{
	u8		len=0;
	u16		temp_data;

	temp_data = tele_data;
	if ((temp_data & 0x1ff) == 0x1ff && ss_flag)	// has all tele data
	{
		tele_str[0] = TS_All;
		return 1;	// tele service list length
	}
	if ((temp_data & 0x7c) == 0x7c && ss_flag)
	{
		tele_str[len++] = TS_AllData;
		temp_data &= ~0x7c;
	}
	if ((temp_data & 0x73) == 0x73 && ss_flag)
	{
		tele_str[len++] = TS_AllEXSMS;
		temp_data &= ~0x73;
	}
	if ((temp_data & 0x03) == 0x03 && ss_flag)
	{
		tele_str[len++] = TS_AllSTS;
		temp_data &= ~0x03;
	}
	if ((temp_data & 0x01) == 0x01)
	{
		tele_str[len++] = TS_PHONY;
		temp_data &= ~0x01;
	}
	if ((temp_data & 0x02) == 0x02)
	{
		tele_str[len++] = TS_EMERCALL;
		temp_data &= ~0x02;
	}
	if ((temp_data & 0x0c) == 0x0c && ss_flag)
	{
		tele_str[len++] = TS_AllSMS;
		temp_data &= ~0x0c;
	}
	if ((temp_data & 0x04) == 0x04)
	{
		tele_str[len++] = TS_SMMTPP;
		temp_data &= ~0x04;
	}
	if ((temp_data & 0x08) == 0x08)
	{
		tele_str[len++] = TS_SMMOPP;
		temp_data &= ~0x08;
	}
	if ((temp_data & 0x70) == 0x70 && ss_flag)
	{
		tele_str[len++] = TS_AllFTS;
		temp_data &= ~0x70;
	}
	if ((temp_data & 0x10) == 0x10)
	{
		tele_str[len++] = TS_FG3AAS;
		temp_data &= ~0x10;
	}
	if ((temp_data & 0x20) == 0x20)
	{
		tele_str[len++] = TS_AFG3;
		temp_data &= ~0x20;
	}
	if ((temp_data & 0x40) == 0x40)
	{
		tele_str[len++] = TS_FG4;
		temp_data &= ~0x40;
	}
	if ((temp_data & 0x180) == 0x180 && ss_flag)
	{
		tele_str[len++] = TS_AllVGCS;
		temp_data &= ~0x180;
	}
	if ((temp_data & 0x80) == 0x80)
	{
		tele_str[len++] = TS_VGC;
		temp_data &= ~0x80;
	}
	if ((temp_data & 0x100) == 0x100)
	{
		tele_str[len++] = TS_VBSC;
		temp_data &= ~0x100;
	}
	return len;
}

/*	transfer tele service from bcd string to bit string	*/
u16	tele_strtobit(u8 *tele_str,u8 tele_len)
{
	u16		tele_data=0;
	u8		ii;

	for (ii = 0;ii < tele_len;ii ++)
	{
		switch (tele_str[ii])
		{
			case TS_All:
				tele_data |= 0x1ff;
				break;
			case TS_AllSTS:
				tele_data |= 0x03;
				break;
			case TS_PHONY:
				tele_data |= 0x01;
				break;
			case TS_EMERCALL:
				tele_data |= 0x02;
				break;
			case TS_AllSMS:
				tele_data |= 0x0c;
				break;
			case TS_SMMTPP:
				tele_data |= 0x04;
				break;
			case TS_SMMOPP:
				tele_data |= 0x08;
				break;
			case TS_AllFTS:
				tele_data |= 0x70;
				break;
			case TS_FG3AAS:
				tele_data |= 0x10;
				break;
			case TS_AFG3:
				tele_data |= 0x20;
				break;
			case TS_FG4:
				tele_data |= 0x40;
				break;
			case TS_AllData:
				tele_data |= 0x7c;
				break;
			case TS_AllEXSMS:
				tele_data |= 0x73;
				break;
			case TS_AllVGCS:
				tele_data |= 0x180;
				break;
			case TS_VGC:
				tele_data |= 0x80;
				break;
			case TS_VBSC:
				tele_data |= 0x100;
				break;
			default:
//				tele_data = 0;
				break;
		}
	}
	return tele_data;
}

/*	tranfer bearer service from bit string to bcd string	*/
u8	bearer_bittostr(u32 bearer_data, u8 *bearer_str,u8 ss_flag)
{
//	u8		ii=0,jj;
	u8		len=0;
	u32		temp_data;

	temp_data = bearer_data;
	if ((temp_data & 0x7ffffff) == 0x7ffffff && ss_flag)
	{
		bearer_str[0] = BS_All;
		return 1;	// bearer service list length
	}
	if ((temp_data & 0x287f07f) == 0x287f07f && ss_flag)
	{
		bearer_str[len++] = BS_AllAS;
		temp_data &= ~0x287f07f;
	}
	if ((temp_data & 0x280007f) == 0x280007f && ss_flag)
	{
		bearer_str[len++] = BS_AllDCA;
		temp_data &= ~0x280007f;
	}
	if ((temp_data & 0x280007f) == 0x5780f80 && ss_flag)
	{
		bearer_str[len++] = BS_AllSS;
		temp_data &= ~0x5780f80;
	}
	if ((temp_data & 0x280007f) == 0x5000f80 && ss_flag)
	{
		bearer_str[len++] = BS_AllDCS;
		temp_data &= ~0x5000f80;
	}
	if ((temp_data & 0x7f) == 0x7f && ss_flag)	// all data CDA
	{
		bearer_str[len++] = BS_AllDataCDA;
		temp_data &= ~0x7f;
	}
	if ((temp_data & 0x01) == 0x01)
	{
		bearer_str[len++] = BS_CDA300;
		temp_data &= ~0x01;
	}
	if ((temp_data & 0x02) == 0x02)
	{
		bearer_str[len++] = BS_CDA1200;
		temp_data &= ~0x02;
	}
	if ((temp_data & 0x04) == 0x04)
	{
		bearer_str[len++] = BS_CDA7500;
		temp_data &= ~0x04;
	}
	if ((temp_data & 0x08) == 0x08)
	{
		bearer_str[len++] = BS_CDA2400;
		temp_data &= ~0x08;
	}
	if ((temp_data & 0x10) == 0x10)
	{
		bearer_str[len++] = BS_CDA4800;
		temp_data &= ~0x10;
	}
	if ((temp_data & 0x20) == 0x20)
	{
		bearer_str[len++] = BS_CDA9600;
		temp_data &= ~0x20;
	}
	if ((temp_data & 0x40) == 0x40)
	{
		bearer_str[len++] = BS_CDAGNRL;
		temp_data &= ~0x40;
	}
	if ((temp_data & 0x800000) == 0x800000)
	{
		bearer_str[len++] = BS_AllASDCDA;
		temp_data &= ~0x800000;
	}
	if ((temp_data & 0x2000000) == 0x2000000)
	{
		bearer_str[len++] = BS_AllASFBDCDA;
		temp_data &= ~0x2000000;
	}
	if ((temp_data & 0x7f000) == 0x7f000 && ss_flag)	// all PDA acccess CDA
	{
		bearer_str[len++] = BS_AllPACA;
		temp_data &= ~0x7f000;
	}
	if ((temp_data & 0x1000) == 0x1000)
	{
		bearer_str[len++] = BS_PACA300;
		temp_data &= ~0x1000;
	}
	if ((temp_data & 0x2000) == 0x2000)
	{
		bearer_str[len++] = BS_PACA1200;
		temp_data &= ~0x2000;
	}
	if ((temp_data & 0x4000) == 0x4000)
	{
		bearer_str[len++] = BS_PACA7500;
		temp_data &= ~0x4000;
	}
	if ((temp_data & 0x8000) == 0x8000)
	{
		bearer_str[len++] = BS_PACA2400;
		temp_data &= ~0x8000;
	}
	if ((temp_data & 0x10000) == 0x10000)
	{
		bearer_str[len++] = BS_PACA4800;
		temp_data &= ~0x10000;
	}
	if ((temp_data & 0x20000) == 0x20000)
	{
		bearer_str[len++] = BS_PACA9600;
		temp_data &= ~0x20000;
	}
	if ((temp_data & 0x40000) == 0x40000)
	{
		bearer_str[len++] = BS_PACAGNRL;
		temp_data &= ~0x40000;
	}
	if ((temp_data & 0xf80) == 0xf80 && ss_flag)	// all data CDS
	{
		bearer_str[len++] = BS_AllDataCDS;
		temp_data &= ~0xf80;
	}
	if ((temp_data & 0x80) == 0x80)
	{
		bearer_str[len++] = BS_CDS1200;
		temp_data &= ~0x80;
	}
	if ((temp_data & 0x100) == 0x100)
	{
		bearer_str[len++] = BS_CDS2400;
		temp_data &= ~0x100;
	}
	if ((temp_data & 0x200) == 0x200)
	{
		bearer_str[len++] = BS_CDS4800;
		temp_data &= ~0x200;
	}
	if ((temp_data & 0x400) == 0x400)
	{
		bearer_str[len++] = BS_CDS9600;
		temp_data &= ~0x400;
	}
	if ((temp_data & 0x800) == 0x800)
	{
		bearer_str[len++] = BS_CDSGNRL;
		temp_data &= ~0x800;
	}
	if ((temp_data & 0x1000000) == 0x1000000)
	{
		bearer_str[len++] = BS_AllASDCDS;
		temp_data &= ~0x1000000;
	}
	if ((temp_data & 0x4000000) == 0x4000000)
	{
		bearer_str[len++] = BS_AllASFBDCDS;
		temp_data &= ~0x4000000;
	}
	if ((temp_data & 0x780000) == 0x780000 && ss_flag)	// all PDA acccess CDS
	{
		bearer_str[len++] = BS_AllDPDS;
		temp_data &= ~0x780000;
	}
	if ((temp_data & 0x80000) == 0x80000)
	{
		bearer_str[len++] = BS_DPDS2400;
		temp_data &= ~0x80000;
	}
	if ((temp_data & 0x100000) == 0x100000)
	{
		bearer_str[len++] = BS_DPDS4800;
		temp_data &= ~0x100000;
	}
	if ((temp_data & 0x200000) == 0x200000)
	{
		bearer_str[len++] = BS_DPDS9600;
		temp_data &= ~0x200000;
	}
	if ((temp_data & 0x400000) == 0x400000)
	{
		bearer_str[len++] = BS_DPDSGNRL;
		temp_data &= ~0x400000;
	}
	return len;
}

u32	bearer_strtobit(u8 *bearer_str,u8 bearer_len)
{
	u8		ii;
	u32		bearer_data=0;

	for (ii = 0;ii < bearer_len;ii ++)
	{
		switch (bearer_str[ii])
		{
			case BS_All:
				bearer_data |= 0x7ffffff;
				break;
			case BS_AllDataCDA:
				bearer_data |= 0x7f;
				break;
			case BS_CDA300:
				bearer_data |= 0x01;
				break;
			case BS_CDA1200:
				bearer_data |= 0x02;
				break;
			case BS_CDA7500:
				bearer_data |= 0x04;
				break;
			case BS_CDA2400:
				bearer_data |= 0x08;
				break;
			case BS_CDA4800:
				bearer_data |= 0x10;
				break;
			case BS_CDA9600:
				bearer_data |= 0x20;
				break;
			case BS_CDAGNRL:
				bearer_data |= 0x40;
				break;
			case BS_AllDataCDS:
				bearer_data |= 0xf80;
				break;
			case BS_CDS1200:
				bearer_data |= 0x80;
				break;
			case BS_CDS2400:
				bearer_data |= 0x100;
				break;
			case BS_CDS4800:
				bearer_data |= 0x200;
				break;
			case BS_CDS9600:
				bearer_data |= 0x400;
				break;
			case BS_CDSGNRL:
				bearer_data |= 0x800;
				break;
			case BS_AllPACA:
				bearer_data |= 0x7f000;
				break;
			case BS_PACA300:
				bearer_data |= 0x1000;
				break;
			case BS_PACA1200:
				bearer_data |= 0x2000;
				break;
			case BS_PACA7500:
				bearer_data |= 0x4000;
				break;
			case BS_PACA2400:
				bearer_data |= 0x8000;
				break;
			case BS_PACA4800:
				bearer_data |= 0x10000;
				break;
			case BS_PACA9600:
				bearer_data |= 0x20000;
				break;
			case BS_PACAGNRL:
				bearer_data |= 0x40000;
				break;
			case BS_AllDPDS:
				bearer_data |= 0x780000;
				break;
			case BS_DPDS2400:
				bearer_data |= 0x80000;
				break;
			case BS_DPDS4800:
				bearer_data |= 0x100000;
				break;
			case BS_DPDS9600:
				bearer_data |= 0x200000;
				break;
			case BS_DPDSGNRL:
				bearer_data |= 0x400000;
				break;
			case BS_AllASDCDA:
				bearer_data |= 0x800000;
				break;
			case BS_AllASDCDS:
				bearer_data |= 0x1000000;
				break;
			case BS_AllASFBDCDA:
				bearer_data |= 0x2000000;
				break;
			case BS_AllASFBDCDS:
				bearer_data |= 0x4000000;
				break;
			default:
				bearer_data = 0;
				break;
		}
	}
	return bearer_data;
}

void get_sccpadd(struct	SCCP_ADDRESS *add_ptr,u8 *data)
{
	u8		temp_len;

	add_ptr->ip = (data[0]<<24) + (data[1]<<16) + (data[2]<<8) + data[3];
	add_ptr->DPC = (data[4]<<24) + (data[5]<<16) + (data[6]<<8) + data[7];
	add_ptr->NetID = data[8];
	add_ptr->SSN = data[9];
	add_ptr->RI = data[10];
	add_ptr->GTI = data[11];
	add_ptr->TT = data[12];
	add_ptr->NP = data[13];
	add_ptr->ES = data[14];
	add_ptr->NAI = data[15];
	add_ptr->len = data[16];
	temp_len = (data[16] + 1) / 2;
	memcpy(add_ptr->GTAI,data+17,temp_len%ISDN_LEN);
}

void set_sccpadd(struct SCCP_ADDRESS *add_ptr,u8 *data)
{
	u8		temp_len;

	data[0] = add_ptr->ip >> 24;
	data[1] = add_ptr->ip >> 16;
	data[2] = add_ptr->ip >> 8;
	data[3] = add_ptr->ip;
	data[4] = add_ptr->DPC >> 24;
	data[5] = add_ptr->DPC >> 16;
	data[6] = add_ptr->DPC >> 8;
	data[7] = add_ptr->DPC;
	data[8] = add_ptr->NetID;
	data[9] = add_ptr->SSN;
	data[10] = add_ptr->RI;
	data[11] = add_ptr->GTI;
	data[12] = add_ptr->TT;
	data[13] = add_ptr->NP;
	data[14] = add_ptr->ES;
	data[15] = add_ptr->NAI;
	data[16] = add_ptr->len;
	temp_len = (add_ptr->len + 1) / 2;
	memcpy(data+17,add_ptr->GTAI,temp_len);
}

u8 map_com_ftos(struct MapComSrv_struct *map_com,u8 *data_flow)
{	// common service data flow to structure
	u32		aa;
	u32		len;
	u8		ii;
	u8		delimiter_flag = 0;
	struct	MapOpen_Arg		*open_arg;
	struct	MapOpen_Res		*open_res;
	struct	MapClose_Arg	*close_ptr;
	struct	MapUAbort_Arg	*uabrt_ptr;
	struct	MapPAbort_Arg	*pabrt_ptr;

	len = (data_flow[0] << 8) + data_flow[1];
	if (len < 9)	// data flow is too short
		return 0;
	if ((data_flow[2] != MAP_FLAG)	&&
	    (data_flow[2] != IS41_FLAG)	)
		return 0;
	map_com->map_flag = data_flow[2];
	map_com->port_id = (data_flow[3] << 8) + data_flow[4];
	map_com->dialogue_id = (data_flow[6] << 8) + data_flow[7];
	map_com->message_type = data_flow[9];
	map_com->message_flag = data_flow[10];
	switch (map_com->message_type)
	{
		case MAP_OPEN:
			if (map_com->message_flag == MAP_REQUEST || map_com->message_flag == MAP_INDICATE)
			{
				open_arg = (MapOpen_Arg *) &map_com->dlg_list.open_arg;
				open_arg->acn_data.acn = data_flow[11];
				open_arg->acn_data.acn_ver = data_flow[12];
				get_sccpadd(&open_arg->peer_add,data_flow+13);
				get_sccpadd(&open_arg->local_add,data_flow+41);
				open_arg->param_flag = 0x0b;
				aa = 70;
				for (ii = 0;ii < 3;ii ++)
				{
					if (data_flow[aa] == 0x00)
						break;
					else if (data_flow[aa] == 0x01)	// peer reference
					{
						len = data_flow[aa+1];
						if (len > ISDN_LEN)
							return 0;
						open_arg->peerref_len = len;
						memcpy(open_arg->peer_reference,&data_flow[aa+2],len);
						aa += len + 2;
						open_arg->param_flag |= 0x04;
					}
					else if (data_flow[aa] == 0x02)	// local reference
					{
						len = data_flow[aa+1];
						if (len > ISDN_LEN)
							return 0;
						open_arg->localref_len = len;
						memcpy(open_arg->local_reference,&data_flow[aa+2],len);
						aa+= len + 2;
						open_arg->param_flag |= 0x10;
					}
					else if (data_flow[aa] == 0x03)	// specific info
					{
						len = data_flow[aa+1];
						if (len >= MAX_SPCINFO_LEN)
							return 0;
						open_arg->specific_info.info_len = len;
						memcpy(open_arg->specific_info.info_data,&data_flow[aa+2],len);
						open_arg->param_flag |= 0x20;
						aa += 2 + len;
					}
					else if (data_flow[aa] == 0x10)
					{
						delimiter_flag = 1;
						aa += 2;
						xap_watch_dog(66);
					}
				}
			}
			else if (map_com->message_flag == MAP_RESPONSE || map_com->message_flag == MAP_CONFIRM)
			{
				open_res = (MapOpen_Res *) &map_com->dlg_list.open_res;
				open_res->result = data_flow[11];
				open_res->param_flag = 0x08;
				aa = 13;
				for (ii = 0;ii < 4;ii ++)
				{
					if (data_flow[aa] == 0x00)
						break;
					else if (data_flow[aa] == 0x01)	// acn
					{
						open_res->acn_data.acn = data_flow[aa+2];
						open_res->acn_data.acn_ver = data_flow[aa+3];
						aa += 4;
						open_res->param_flag |= 0x01;
					}
					else if (data_flow[aa] == 0x02)	// specific info
					{
						len = data_flow[aa+1];
						if (len >= MAX_SPCINFO_LEN)
							return 0;
						open_res->specific_info.info_len = len;
						memcpy(open_res->specific_info.info_data,&data_flow[aa+2],len);
						open_res->param_flag |= 0x02;
						aa += 2 + len;
					}
					else if (data_flow[aa] == 0x03)	// refuse reason
					{
						open_res->refuse_reason = data_flow[aa+2];
						open_res->param_flag |= 0x10;
						aa += 3;
					}
					else if (data_flow[aa] == 0x04)	// provider error
					{
						open_res->provider_error = data_flow[aa+2];
						open_res->param_flag |= 0x20;
						aa += 3;
					}
					else if (data_flow[aa] == 0x10)
					{
						delimiter_flag = 1;
						aa += 2;
						xap_watch_dog(69);
					}
				}
			}
			else
				return 0;
			break;
		case MAP_CLOSE:
			close_ptr = (MapClose_Arg *) &map_com->dlg_list.close_arg;
			close_ptr->release_method = data_flow[11];
			close_ptr->param_flag = 0x01;
			if (data_flow[13] == 0x01)
			{
				len = data_flow[14];
				if (len >= MAX_SPCINFO_LEN)
					return 0;
				close_ptr->specific_info.info_len = len;
				memcpy(close_ptr->specific_info.info_data,&data_flow[15],len);
				close_ptr->param_flag |= 0x02;
			}
			break;
		case MAP_U_ABORT:
			uabrt_ptr = (MapUAbort_Arg *) &map_com->dlg_list.uabort_arg;
			uabrt_ptr->user_reason = data_flow[11];
			uabrt_ptr->param_flag = 0x01;
			aa = 13;
			for (ii = 0;ii < 2;ii ++)
			{
				if (data_flow[aa] == 0)
					break;
				else if (data_flow[aa] == 0x01)	// diagnostic flag
				{
					uabrt_ptr->diag_info = data_flow[aa+2];
					uabrt_ptr->param_flag |= 0x02;
					aa += 3;
				}
				else if (data_flow[aa] == 0x02)	// specific info
				{
					len = data_flow[aa+1];
					if (len >= MAX_SPCINFO_LEN)
						return 0;
					uabrt_ptr->specific_info.info_len = len;
					memcpy(uabrt_ptr->specific_info.info_data,&data_flow[aa+2],len);
					uabrt_ptr->param_flag |= 0x04;
					aa += 2 + len;
				}
			}
			break;
		case MAP_P_ABORT:
			pabrt_ptr = (MapPAbort_Arg *) &map_com->dlg_list.pabort_arg;
			pabrt_ptr->provider_reason = data_flow[11];
			pabrt_ptr->source = data_flow[12];
			pabrt_ptr->param_flag = 0x03;
			break;
		case MAP_NOTICE:
			map_com->dlg_list.notice_arg.problem = data_flow[11];
			map_com->dlg_list.notice_arg.param_flag = 0x01;
			break;
		case MAP_DELIMITER:
		case MAP_LINK:
			break;
		default:
			return 0;
			break;
	}
	if (delimiter_flag == 1)
	{
		xap_watch_dog(67);
		return 2;
	}
	else
		return 1;
}

void map_com_stof(struct MapComSrv_struct *com_ptr,u8 *data_flow,u8 delimiter_flag)
{	// transfer common structure to data flow
	u32		ii;
	u32		len;
	struct	MapOpen_Arg		*open_arg;
	struct	MapOpen_Res		*open_res;
	struct	MapClose_Arg	*close_arg;
	struct	MapUAbort_Arg	*uabrt_arg;

#if _SUPPORT_ANSI
	if (map_check_map_flag(com_ptr->dialogue_id))
#endif
		data_flow[2] = MAP_FLAG;
#if _SUPPORT_ANSI
	else
		data_flow[2] = IS41_FLAG;
#endif
	data_flow[3] = com_ptr->port_id >> 8;
	data_flow[4] = com_ptr->port_id;
	data_flow[6] = com_ptr->dialogue_id >> 8;
	data_flow[7] = com_ptr->dialogue_id;
	data_flow[9] = com_ptr->message_type;
	data_flow[10] = com_ptr->message_flag;
	ii = 11;
	switch (com_ptr->message_type)
	{
		case MAP_OPEN:
			if (com_ptr->message_flag == MAP_INDICATE || com_ptr->message_flag == MAP_REQUEST)
			{
				open_arg = (MapOpen_Arg *) &com_ptr->dlg_list.open_arg;
				data_flow[ii++] = open_arg->acn_data.acn;
				data_flow[ii++] = open_arg->acn_data.acn_ver;
				set_sccpadd(&open_arg->peer_add,data_flow+ii);
				ii += 28;
				set_sccpadd(&open_arg->local_add,data_flow+ii);
				ii += 28;
				data_flow[ii++] = 1;	// optional point
				if ((open_arg->param_flag & 0x04))	// has peer reference address
				{
					data_flow[ii++] = 0x01;
					len = open_arg->peerref_len;
					data_flow[ii++] = len;
					memcpy(data_flow+ii,open_arg->peer_reference,len);
					ii += len;
				}
				if ((open_arg->param_flag & 0x10))	// has local reference address
				{
					data_flow[ii++] = 0x02;
					len = open_arg->localref_len;
					data_flow[ii++] = len;
					memcpy(data_flow+ii,open_arg->local_reference,len);
					ii += len;
				}
				if ((open_arg->param_flag & 0x20))
				{
					data_flow[ii++] = 0x03;
					len = open_arg->specific_info.info_len;
					data_flow[ii++] = len;
					memcpy(data_flow+ii,open_arg->specific_info.info_data,len);
					ii += len;
				}
				if (delimiter_flag == 1)
				{
					data_flow[ii++] = 0x10;
					data_flow[ii++] = 0x00;
					xap_watch_dog(63);
				}
				data_flow[ii++] = 0x00;
			}
			else if (com_ptr->message_flag == MAP_RESPONSE || com_ptr->message_flag == MAP_CONFIRM)
			{
				open_res = (MapOpen_Res *) &com_ptr->dlg_list.open_res;
				data_flow[ii++] = open_res->result;
				data_flow[ii++] = 0x01;	// optional point
				if ((open_res->param_flag & 0x01))	// has ACN
				{
					data_flow[ii++] = 0x01;
					data_flow[ii++] = 2;
					data_flow[ii++] = open_res->acn_data.acn;
					data_flow[ii++] = open_res->acn_data.acn_ver;
				}
				if ((open_res->param_flag & 0x02))	// has specific info
				{
					data_flow[ii++] = 0x02;
					len = open_res->specific_info.info_len;
					data_flow[ii++] = len;
					memcpy(data_flow+ii,open_res->specific_info.info_data,len);
					ii += len;
				}
				if ((open_res->param_flag & 0x10))	// has refuse reason
				{
					data_flow[ii++] = 0x03;
					data_flow[ii++] = 1;
					data_flow[ii++] = open_res->refuse_reason;
				}
				if ((open_res->param_flag & 0x20))	// has provider error
				{
					data_flow[ii++] = 0x04;
					data_flow[ii++] = 1;
					data_flow[ii++] = open_res->provider_error;
				}
				if (delimiter_flag == 1)
				{
					data_flow[ii++] = 0x10;
					data_flow[ii++] = 0x00;
				}
				data_flow[ii++] = 0x00;
			}
			break;
		case MAP_CLOSE:
			close_arg = (MapClose_Arg *) &com_ptr->dlg_list.close_arg;
			data_flow[ii++] = close_arg->release_method;
			data_flow[ii++] = 0x01;	// optional point
			if ((close_arg->param_flag & 0x02))	// has specific info
			{
				data_flow[ii++] = 0x01;
				len = close_arg->specific_info.info_len;
				data_flow[ii++] = len;
				memcpy(data_flow+ii,close_arg->specific_info.info_data,len);
				ii += len;
			}
			data_flow[ii++] = 0x00;
			break;
		case MAP_U_ABORT:
			uabrt_arg = (MapUAbort_Arg *) &com_ptr->dlg_list.uabort_arg;
			data_flow[ii++] = uabrt_arg->user_reason;
			data_flow[ii++] = 0x01;	// optional point
			if ((uabrt_arg->param_flag & 0x02))
			{
				data_flow[ii++] = 0x01;
				data_flow[ii++] = 1;
				data_flow[ii++] = uabrt_arg->diag_info;
			}
			if ((uabrt_arg->param_flag & 0x04))	// has specific info
			{
				data_flow[ii++] = 0x02;
				len = uabrt_arg->specific_info.info_len;
				data_flow[ii++] = len;
				memcpy(data_flow+ii,uabrt_arg->specific_info.info_data,len);
				ii += len;
			}
			data_flow[ii++] = 0x00;
			break;
		case MAP_P_ABORT:
			data_flow[ii++] = com_ptr->dlg_list.pabort_arg.provider_reason;
			data_flow[ii++] = com_ptr->dlg_list.pabort_arg.source;
			break;
		case MAP_NOTICE:
			data_flow[ii++] = com_ptr->dlg_list.notice_arg.problem;
			break;
		default:
			break;
	}
	ii -= 2;
	data_flow[0] = ii >> 8;
	data_flow[1] = ii;
}

u8 map_opr_ftos(struct MapOprData_struct *opr_ptr,u8 *data_flow)
{	// transfer opration data flow to structure
	u32		aa;
	u32		total_len,len;
	u8		ii;
	u8		delimiter_flag = 0;
	
	total_len = (data_flow[0] << 8) + data_flow[1];
	if (total_len < 10)
		return 0;
	if ((data_flow[2] != MAP_FLAG) &&
		(data_flow[2] != IS41_FLAG) )
		return 0;
	opr_ptr->map_flag = data_flow[2];
	opr_ptr->port_id = (data_flow[3] << 8) + data_flow[4];
	opr_ptr->dialogue_id = (data_flow[6] << 8) + data_flow[7];
	opr_ptr->message_type = data_flow[9];
	opr_ptr->message_flag = data_flow[10];
	opr_ptr->invoke_id = data_flow[11];
	opr_ptr->param_flag = 0x1f;
	opr_ptr->param_len = 0;
	aa = 13;
	for (ii = 0;ii < 3;ii ++)
	{
		if(aa>=total_len+2)
			break;

		if (data_flow[aa] == 0x00)
			break;
		else if (data_flow[aa] == 0x01)	// parameter
		{
			len = (data_flow[aa+1] << 8) + data_flow[aa+2];
			if (len > MAX_MAPPOPR_LEN)
				return 0;
			opr_ptr->param_len = len;
			memcpy(opr_ptr->param,&data_flow[aa+3],len);
			aa += len + 3;
			opr_ptr->param_flag |= 0x20;
		}
		else if (data_flow[aa] == 0x02)	// user error
		{
			opr_ptr->user_error = data_flow[aa+2];
			opr_ptr->param_flag |= 0x40;
			aa += 3;
		}
		else if (data_flow[aa] == 0x03)	// provider error
		{
			opr_ptr->provider_error = data_flow[aa+2];
			opr_ptr->param_flag |= 0x80;
			aa += 3;
		}
		else if (data_flow[aa] == 0x04)	// linked id
		{
			opr_ptr->linked_id = data_flow[aa+2];
			opr_ptr->param_flag |= 0x100;
			aa += 3;
		}
		else if (data_flow[aa] == 0x10)
		{
			delimiter_flag = 1;
			aa += 2;
			ii = 3;
			xap_watch_dog(70);
			break;
		}
	}
	if (delimiter_flag == 1)
		return 2;
	else
		return 1;
}

void map_opr_stof(struct MapOprData_struct *opr_ptr,u8 *data_flow,u8 delimiter_flag)
{	// transfer opration structure to data flow
	u32		ii;
	u32		len;

#if _SUPPORT_ANSI
	if (map_check_map_flag(opr_ptr->dialogue_id))
#endif
		data_flow[2] = MAP_FLAG;
#if _SUPPORT_ANSI
	else
		data_flow[2] = IS41_FLAG;
#endif
	data_flow[3] = opr_ptr->port_id >> 8;
	data_flow[4] = opr_ptr->port_id;
	data_flow[6] = opr_ptr->dialogue_id >> 8;
	data_flow[7] = opr_ptr->dialogue_id;
	data_flow[9] = opr_ptr->message_type;
	data_flow[10] = opr_ptr->message_flag;
	data_flow[11] = opr_ptr->invoke_id;
	data_flow[12] = 1;
	ii = 13;
	if ((opr_ptr->param_flag & 0x20))	// has component
	{
		data_flow[ii++] = 0x01;
		len = opr_ptr->param_len;
		data_flow[ii++] = len >> 8;
		data_flow[ii++] = len;
		memcpy(data_flow+ii,opr_ptr->param,len);
		ii += len;
	}
	if ((opr_ptr->param_flag & 0x40))	// has user error
	{
		data_flow[ii++] = 0x02;
		data_flow[ii++] = 1;
		data_flow[ii++] = opr_ptr->user_error;
	}
	if ((opr_ptr->param_flag & 0x80))	// has provider error
	{
		data_flow[ii++] = 0x03;
		data_flow[ii++] = 1;
		data_flow[ii++] = opr_ptr->provider_error;
	}
	if ((opr_ptr->param_flag & 0x100))	// has linked id
	{
		data_flow[ii++] = 0x04;
		data_flow[ii++] = 1;
		data_flow[ii++] = opr_ptr->linked_id;
	}
	if (delimiter_flag == 1)
	{
		data_flow[ii++] = 0x10;
		data_flow[ii++] = 0x00;
	}
	data_flow[ii++] = 0;
	ii -= 2;
	data_flow[0] = ii >> 8;
	data_flow[1] = ii;
}

char *is41_sequenceTag(char *tag,int sequence)
{
	static char	sTag[32];

	sprintf(sTag,"%s-%d",tag,sequence);
	return sTag;
}

int	decode_Is41Parameter(char *tag,int len,BYTE *value,ASN_BUF *asn_buf)
{
	int		decodeLen;
	u8		temp_buf[256];

	decodeLen = GetTLV(tag,len,temp_buf,0x80,asn_buf);
	if ((decodeLen <= len) && (decodeLen > 0))
	{
		memcpy(value,temp_buf,decodeLen);
		return decodeLen;
	}
	return 0;
}
