#include "../../public/src/include/includes.h"
#include "../../debug/src/include/debug.h"
#include "./include/mtp3.h"
#include "./include/mtpstm.h"
#include "./include/mtpdef.h"
#include "./include/mtpfunc.h"
#include "./include/mtp3lite.h"


/*@ignore@*/
#define PROG_NAME	"iptrans"

/* by simon at 23/9/26 */
extern mtp3_dpc_index mtp3SortRoutine;
extern _mtp3_input mtp3ObjInput;
extern _mtp3_state mtp3ObjState;
extern _mtp3_IPMng MTP3IPMng;

extern iprt1			mtp3_iprt;
struct tm			mtp3_tm;
struct tm			*mtp3_time = &mtp3_tm;
iptrans_shm			*IPTRANS_shm_ptr;
static int			iptrans_shm_id;
tup_shm				*T_shm_ptr;
isup_shm			*I_shm_ptr;
bicc_shm			*B_shm_ptr;
sccp_shm			*S_shm_ptr;
primitive_to_isup	*I_primitive;
primitive_to_bicc	*B_primitive;
primitive_to_sccp	*S_primitive;
primitive_to_tup	*T_primitive;

primitive_to_isup	I_primitive_init;
primitive_to_bicc	B_primitive_init;
primitive_to_sccp	S_primitive_init;
primitive_to_tup	T_primitive_init;
tup_shm				tup_shm_ptr_init;
isup_shm			isup_shm_ptr_init;
bicc_shm			bicc_shm_ptr_init;
sccp_shm			sccp_shm_ptr_init;

BOOL				mtp3DebugFull=0;
mtp3_routing_result	routingResult;
void scan_conf_right_or_not(BYTE nw);
void rsrt_proc(BYTE netw,BYTE dst);
void mtp3lite_reset(void);
void otherMTP3_managed_link_unavailable(BYTE chl);

int mtp3lite_InitServerSocket();
extern int	mtp3lite_listen_fd;
extern ull Str2Ull(char *pStr);
extern void	send_to_mtp2(long dest_ip);
extern void	send_to_mtp2_new_struct(long dest_ip);//link,len_high,len_low,sio...
extern void MTP3_send_isup_count(BYTE nw,BYTE type);
extern void get_routes_from_other_plat();
extern void deactive_m3ua_lk(BYTE link);

void send_ip_to_mtp2();

void mtp3_init_dynamic_opc()
{
	memset((BYTE *)&mtp3_opc, 0, sizeof(mtp3_dynamic_opc));
}

int mtp3_create_opc(BYTE nw, DWORD opc)
{
	BYTE	i, pclen, num;
	DWORD	para_opc;

	if ((nw > 3) || (opc == 0))
		return -1;

	pclen = pc_length(nw);
	if (pclen == MTP3_24BIT_PC)
		para_opc = mtp3_para->nw[nw].opc24;
	else
		para_opc = mtp3_para->nw[nw].opc14;
	if (opc == para_opc)
		return 0;

	num = mtp3_opc.opc_num[nw];
	for (i = 0; i < num; i++)
	{
		if (mtp3_opc.opc[nw][i] == opc)
			return 0;
	}

	if (num >= MTP3_MAX_DYNAMIC_OPC_PER_NW)
		return -1;

	mtp3_opc.opc[nw][num] = opc;
	mtp3_opc.opc_num[nw]++;

	return 0;
}

int mtp3_delete_opc(BYTE nw, DWORD opc)
{
	BYTE	i, pclen, num, num_mv;
	DWORD	para_opc;

	if ((nw > 3) || (opc == 0))
		return -1;

	pclen = pc_length(nw);
	if (pclen == MTP3_24BIT_PC)
		para_opc = mtp3_para->nw[nw].opc24;
	else
		para_opc = mtp3_para->nw[nw].opc14;
	if (opc == para_opc)
		return 0;

	num = mtp3_opc.opc_num[nw];
	if (num == 0)
		return -1;

	for (i = 0; i < num; i++)
	{
		if (mtp3_opc.opc[nw][i] == opc)
		{
			num_mv = num - i - 1;
			memcpy((BYTE *) &mtp3_opc.opc[nw][i], (BYTE *) &mtp3_opc.opc[nw][i+1], num_mv * sizeof(DWORD));
			mtp3_opc.opc_num[nw]--;
			return 0;
		}
	}

	return -1;
}

BYTE mtp3_check_dpc_equal_to_opc(BYTE nw, DWORD dpc)
{
	BYTE	i, pclen, num;
	DWORD	para_opc;

	if ((nw > 3) || (dpc == 0))
		return -1;

	pclen = pc_length(nw);
	if (pclen == MTP3_24BIT_PC)
		para_opc = mtp3_para->nw[nw].opc24;
	else
		para_opc = mtp3_para->nw[nw].opc14;
	if (dpc == para_opc)
		return 1;

	num = mtp3_opc.opc_num[nw];
	for (i = 0; i < num; i++)
	{
		if (mtp3_opc.opc[nw][i] == dpc)
			return 1;
	}

	return 0;
}

BYTE MTP3_LINK_TYPE(BYTE Link)
{
	return (mtp3_para->lk[Link].e1_lk_type >> 1) & 0x07;
}

void MTP3_Enable_SubSystem(BYTE SubSystem)
{
	SubSystem &= 15;

	if (SubSystem < 8)
		mtp3_heartbeat.SubState[0] |= (1 << SubSystem);
	else
		mtp3_heartbeat.SubState[1] |= (1 << (SubSystem & 7));
}

void MTP3_Disable_SubSystem(BYTE SubSystem)
{
	SubSystem &= 15;

	if (SubSystem < 8)
		mtp3_heartbeat.SubState[0] |= (~(1 << SubSystem));
	else
		mtp3_heartbeat.SubState[1] |= (~(1 << (SubSystem & 7)));

}

void scan_lk_state_quickly(BYTE lk)
{
	if (mtp3ObjState.lk_configured[lk] != PARA_CONFIGURED)
	{
		lk = lk+1;
		return;
	}
	if (mtp3ObjState.link_l3_state[lk] != AVAILABLE)
	{
		current_measure->lk_measure1[lk][3]++;//Duration of SL unavailability(for any reason
	}
	else if (mtp3ObjState.link_l3_state[lk] == UNAVAILABLE)
		current_measure->lk_measure1[lk][6]++;//Duration of SL unavailability due to link fai
	if (mtp3ObjState.link_l3_state[lk] == INHIBITED)
	{
		if (link_locally_inhibited[lk] == TRUE)
		{
			current_measure->lk_measure1[lk][4]++;//Duration of SL inhibition due to local  management actions
		}
		else
			current_measure->lk_measure1[lk][5]++;//Duration of SL inhibition due to remote  management actions
	}

	if (mtp3_para->lk[lk].e1_to_mtp3 == mtp3_localip)
	{//this mtp3 is the normal mtp3 of this link
		if (mtp3ObjState.lk_AMTP3_ok[lk] & 15)//Alternative MTP3 available
		{
//			mtp3ObjState.lk_mtp3[lk] = mtp3_para->lk[lk].e1_to_alterMTP3;
			//do nothing, waiting for alternative unavailable
		}
		else if (mtp3ObjState.lk_NMTP3_ok[lk] >> 4)//if Alternative MTP3 not avilable and normal mtp3 is activated
		{
			mtp3_debug(MTP3DB_EVENT,"link %d host MTP3 change from backup to normal",lk);
			mtp3ObjState.lk_NMTP3_ok[lk] &= 0x0f;
			if (mtp3ObjState.lk_mtp3[lk] == mtp3_para->lk[lk].e1_to_alterMTP3)
			{
				mtp3ObjState.lk_mtp3[lk] = mtp3_para->lk[lk].e1_to_mtp3;
				if (mtp3ObjState.link_l3_state[lk] == AVAILABLE)
					otherMTP3_managed_link_unavailable(lk);
			}
			mtp3ObjState.lk_mtp3[lk] = mtp3_para->lk[lk].e1_to_mtp3;
		}
		else//other case normal is always the host
			mtp3ObjState.lk_mtp3[lk] = mtp3_para->lk[lk].e1_to_mtp3;
	}
	else if (mtp3_para->lk[lk].e1_to_alterMTP3 == mtp3_localip)
	{//this mtp3 is the alternative mtp3 of this link
		if (mtp3ObjState.lk_mtp3[lk] == mtp3_localip)//it is the current host
		{
			if ((mtp3ObjState.lk_AMTP3_ok[lk]>>4)==2)//only the deactivate command can make it abandon host
			{
				mtp3_debug(MTP3DB_EVENT,"link %d host MTP3 change back to normal",lk);
				mtp3ObjState.lk_AMTP3_ok[lk] &= 0x0f;
				mtp3ObjState.lk_mtp3[lk] = mtp3_para->lk[lk].e1_to_mtp3;

/* disable the link */
				mtp3_debug(MTP3DB_EVENT,"link %d L2 out of service (changing back to normal MTP3)",lk);
				mtp3ObjInput.lsac_input_from_l2[lk] = LSAC_L2_OUT_OF_SERVICE;
				mtp3ObjInput.sltc_input[lk] = SLTC_STOP;
				sltc_proc(lk);

	/* send stop command to mtp2 */
				if (MTP3_LINK_TYPE(lk) == LKTYPE_SIGTRAN)//m2ua link
				{
					send_command_to_mtp2(lk,MTP2_DEACTIVE_LINK);
					send_command_to_mtp2(lk,MTP3_M2UA_DISABLE);
				}
				else
					send_command_to_mtp2(lk,MTP2_STOP_L2);
				mtp3_send_alarm(MTP3_LINK_COMPONENT+lk,MTP3ALARM_LINK_CB_TO_NMTP3);
			}
		}
		else
		{
			if (mtp3ObjState.lk_NMTP3_ok[lk] & 15)
			{//normal ok
				mtp3ObjState.lk_mtp3[lk] = mtp3_para->lk[lk].e1_to_mtp3;
			}

			else if ((mtp3ObjState.lk_AMTP3_ok[lk]>>4)==1)//if normal MTP3 not avilable and alternative mtp3 is activated
			{
				mtp3_debug(MTP3DB_EVENT,"link %d host MTP3 change to alternative",lk);
				mtp3ObjState.lk_AMTP3_ok[lk] &= 0x0f;
				mtp3ObjState.lk_mtp3[lk] = mtp3_para->lk[lk].e1_to_alterMTP3;

			}
		}
	}

	else
	{
		if (mtp3ObjState.lk_AMTP3_ok[lk] & 15)
			mtp3ObjState.lk_mtp3[lk] = mtp3_para->lk[lk].e1_to_alterMTP3;

		else if (mtp3ObjState.lk_NMTP3_ok[lk] & 15)
			mtp3ObjState.lk_mtp3[lk] = mtp3_para->lk[lk].e1_to_mtp3;
	}


	if (mtp3ObjState.lk_mtp3[lk]==mtp3_localip)
	{
		mtp3_heartbeat.masterMTP3[lk/8] |= (1<<(lk&7));
	}
	else
		mtp3_heartbeat.masterMTP3[lk/8] &= (~(1<<(lk&7)));

	lk = lk+1;

	if (lk==255)
	{
		set_status(MTP3_COMPONENT_ID,MTP3_HB_LEN,(BYTE*)&mtp3_heartbeat.version);
	}
}


void MTP3_activate(DWORD ip)
{
	int	chl;

	for (chl=0; chl<256; chl++)
	{
		if ( mtp3_para->lk[chl].e1_to_mtp3 == ip )
		{
			if ((mtp3_para->lk[chl].e1_to_alterMTP3 != 0) && (mtp3_para->lk[chl].e1_to_alterMTP3 != 0xffffffff))
			{
				mtp3ObjState.lk_NMTP3_ok[chl] = 0x11;// activated and set ok
			 	mtp3ObjInput.lsac_input_from_mgmt[chl] = LSAC_MGMT_ACTIVATE_LINK;
				mtp3_debug(MTP3DB_EVENT,"Upper layer active link %d normal MTP3",chl);
			}
		}
		else if ( mtp3_para->lk[chl].e1_to_alterMTP3 == ip )
		{
			mtp3ObjState.lk_AMTP3_ok[chl] = 0x11;// activated and set ok
		 	mtp3ObjInput.lsac_input_from_mgmt[chl] = LSAC_MGMT_ACTIVATE_LINK;
			mtp3_debug(MTP3DB_EVENT,"Upper layer active link %d alternative MTP3",chl);
			mtp3_alterip = ip;//take over altermtp3
		}
	}
}

void MTP3_deactivate(DWORD ip)
{
	int	chl;

	for (chl=0; chl<256; chl++)
	{
/*		if ( mtp3_para->lk[chl].e1_to_mtp3 == ip )
		{
			if ((mtp3_para->lk[chl].e1_to_alterMTP3 != 0) && (mtp3_para->lk[chl].e1_to_alterMTP3 != 0xffffffff))
			{
				mtp3ObjState.lk_NMTP3_ok[chl] = 0x20;//deactive and set not ok
			 	mtp3ObjInput.lsac_input_from_mgmt[chl] = LSAC_MGMT_DEACTIVATE_LINK;
				mtp3_debug(MTP3DB_EVENT,"Upper layer deactive link %d normal MTP3",chl);
			}
		}
*/
		if ( mtp3_para->lk[chl].e1_to_alterMTP3 == ip )
		{
			mtp3ObjState.lk_AMTP3_ok[chl] = 0x20;//deactive and set not ok
		 	mtp3ObjInput.lsac_input_from_mgmt[chl] = LSAC_MGMT_DEACTIVATE_LINK;
			mtp3_debug(MTP3DB_EVENT,"Upper layer deactive link %d alternative MTP3",chl);
			deactive_m3ua_lk(chl);
			if ((MTP3_LINK_TYPE(chl) == LKTYPE_M3UA) && 	// M3UA
				(mtp3_para->lk[chl].e1_lk_type & 0x01))
				scan_lk_state_quickly(chl);
			mtp3_alterip = 0;//take over altermtp3
		}
//			mtp3_heartbeat.link_state[chl/8] = mtp3_heartbeat.link_state[chl/8] & (~(1<<(chl&7)));
	}
}

BYTE *check_MTP3LinkType()
{
	return mtp3ObjState.link_type;
}

BYTE *check_MTP3LinkL2State()
{
	return mtp3ObjState.link_l2_state;
}

int mtp3_get_time()
{
	long	curr_time;
	curr_time = time((long *)0);
	mtp3_time = localtime(&curr_time);
	return 1;
}

void mtp3_set_csta_p()
{
	BYTE	csta_p;
	long	timestamp;

	csta_p = (mtp3_time->tm_hour*4+(mtp3_time->tm_min/15))%96;
	if (mtp3_csta_p != csta_p)
	{/* clear csta_p buffer */
		timestamp = time((long *)0);
		memset(&mtp3_measure.measure[csta_p],0,sizeof(struct measure_of_mtp3));
		mtp3_measure.measure[csta_p].time_stamp = timestamp;
	}
	mtp3_csta_p = csta_p;
	current_measure = &mtp3_measure.measure[mtp3_csta_p];
}

void mtp_lgetlocalip()
{
	struct hostent *host;
	struct in_addr	*hostip_addr;
	char name[100];

	gethostname(name,24);
	if ( (host=gethostbyname(name)) == NULL )
	{
		printf("MTP3 Get Host Name Failed!\n");
		exit(0);
	}
	hostip_addr = (struct in_addr*) (*host->h_addr_list);
	mtp3_localip = hostip_addr->s_addr;
//	return (unsigned char)host->h_addr_list[0][2];
}

void *
mtp3_ShmInit(int shm_id, char *prog_name, key_t key, int size, int shmflg)
{
void       *retp;
//char       *func_name = "ShmInit";

    shm_id = shmget(key, size, shmflg);

    retp = shmat(shm_id, (char *)0, 0);

    return retp;
}

/*******************************/

void tup_shm_init()
{
	T_shm_ptr = &tup_shm_ptr_init;
	T_shm_ptr->TM_Buf.RSub = 0;
	T_shm_ptr->TM_Buf.WSub = 0;
	T_shm_ptr->MT_Buf.RSub = 0;
	T_shm_ptr->MT_Buf.WSub = 0;

	T_primitive = &T_primitive_init;
	T_primitive->WSub = 0;
	T_primitive->RSub = 0;
}

void isup_shm_init()
{
	I_shm_ptr = &isup_shm_ptr_init;
	I_shm_ptr->IM_Buf.RSub = 0;
	I_shm_ptr->IM_Buf.WSub = 0;
	I_shm_ptr->MI_Buf.RSub = 0;
	I_shm_ptr->MI_Buf.WSub = 0;

	I_primitive = &I_primitive_init;
	I_primitive->WSub = 0;
	I_primitive->RSub = 0;
}

void bicc_shm_init()
{
	B_shm_ptr = &bicc_shm_ptr_init;
	B_shm_ptr->IM_Buf.RSub = 0;
	B_shm_ptr->IM_Buf.WSub = 0;
	B_shm_ptr->MI_Buf.RSub = 0;
	B_shm_ptr->MI_Buf.WSub = 0;

	B_primitive = &B_primitive_init;
	B_primitive->WSub = 0;
	B_primitive->RSub = 0;
}

void sccp_shm_init()
{
	S_shm_ptr = &sccp_shm_ptr_init;
	S_shm_ptr->SM_Buf.RSub = 0;
	S_shm_ptr->SM_Buf.WSub = 0;
	S_shm_ptr->MS_Buf.RSub = 0;
	S_shm_ptr->MS_Buf.WSub = 0;

	S_primitive = &S_primitive_init;
	S_primitive->WSub = 0;
	S_primitive->RSub = 0;
}

void iptransInit_mtp3()
{
	/*
	 * Get shared memory block,
	 * IPTRANS_SHM_KEY to be defined in iptrans.h
	 */
	IPTRANS_shm_ptr = (iptrans_shm *) mtp3_ShmInit(iptrans_shm_id, PROG_NAME,IPTRANS_SHM_KEY, sizeof(iptrans_shm), IPTRANS_SHM_PERM|IPC_CREAT);
//	memset(IPTRANS_shm_ptr, 0, sizeof(iptrans_shm));
}

void init_mtp3para()
{
	int	i,j;
	mtp3_para = &mtp3_para_init;
	for (i=0; i<256; i++)
	{
		mtp3_para->lk[i].e1_to_linkset = 128;
		mtp3_para->lk[i].e1_to_slc = 16;
		for (j=0; j<4; j++)
		{
			mtp3_para->nw[j].normal_ls[i] = 128;
			mtp3_para->nw[j].alternative_ls[i] = 128;
		}
	}
}


int mtp3_set_flag_ip(BYTE link, DWORD mtp3_ip)
{
	int i;


	for(i = 0; i <= MAX_MTP3_NUM; i++)
	{
		if(MTP3IPMng.mtp3_flag_ip[i] == mtp3_ip)
			return 2;

	}
	for(i = 0; i <= MAX_MTP3_NUM; i++)
	{
		if(MTP3IPMng.mtp3_flag_ip[i] == 0)
		{
			MTP3IPMng.mtp3_flag_new[i] = 1;
			MTP3IPMng.mtp3_flag_ip[i] = mtp3_ip;
			return 1;
		}
	}
	return 0;
}


void mtp3_set_link_manager(BYTE link)
{
	if (mtp3_para->lk[link].e1_to_mtp3 == mtp3_localip)
	{
		if (mtp3_para->lk[link].e1_to_alterMTP3 != 0 && mtp3_para->lk[link].e1_to_alterMTP3 != 0xffffffff)
		{
			mtp3ObjState.lk_mtp3[link] = mtp3_para->lk[link].e1_to_alterMTP3;
			mtp3ObjState.lk_AMTP3_ok[link] = 1;
//			MTP3IPMng.mtp3_flag_new[0] = 1;
//			MTP3IPMng.mtp3_flag_ip[0] = mtp3_para->lk[link].e1_to_alterMTP3;
			mtp3_set_flag_ip(link, mtp3_localip);
			if(mtp3_set_flag_ip(link, mtp3_para->lk[link].e1_to_alterMTP3)<=0)
			{
				printf("\r\n mtp3 set flag ip error! link=%d, e1_to_alterMTP3=%ld\r\n", link, mtp3_para->lk[link].e1_to_alterMTP3 );
			}
		}
		else
		{
			mtp3ObjState.lk_mtp3[link] = mtp3_para->lk[link].e1_to_mtp3;
			mtp3ObjState.lk_AMTP3_ok[link] = 0;
		}
	}
	else if (mtp3_para->lk[link].e1_to_alterMTP3 == mtp3_localip)
	{
		if (mtp3_para->lk[link].e1_to_mtp3 != 0 && mtp3_para->lk[link].e1_to_mtp3 != 0xffffffff)
		{
			mtp3ObjState.lk_mtp3[link] = mtp3_para->lk[link].e1_to_mtp3;
			mtp3ObjState.lk_NMTP3_ok[link] = 1;
//			MTP3IPMng.mtp3_flag_new[1] = 1;
//			MTP3IPMng.mtp3_flag_ip[1] = mtp3_para->lk[0].e1_to_mtp3;
			if(mtp3_set_flag_ip(link, mtp3_para->lk[link].e1_to_mtp3)<=0)
			{
				printf("\r\n mtp3 set flag ip error! link=%d, e1_to_mtp3=%ld\r\n", link, mtp3_para->lk[link].e1_to_mtp3 );
			}
		}
/*		else
		{
			mtp3ObjState.lk_mtp3[link] = mtp3_para->lk[link].e1_to_alterMTP3;
			mtp3ObjState.lk_NMTP3_ok[link] = 0;
		}*/
	}
	else
	{
		mtp3ObjState.lk_NMTP3_ok[link] = 0;
		mtp3ObjState.lk_AMTP3_ok[link] = 0;
		mtp3ObjState.lk_mtp3[link] = mtp3_para->lk[link].e1_to_mtp3;
	}
}

static void i_sys()
{
	int		i;
	BYTE	version[3] = MTP3_VERSION;

	memset(&mtp3_heartbeat,0,sizeof(heartbeat_compoent_of_mtp3));
	memset(&mtp3SortRoutine,0,sizeof(mtp3_dpc_index));

	for (i=0; i<32; i++)
	{
		mtp2_flag_new[i] = IDLE;
		mtp2_flag_old[i] = IDLE;
	}
	for (i=0; i<MAX_MTP3_NUM; i++)
	{
		MTP3IPMng.mtp3_flag_new[i] = IDLE;
		MTP3IPMng.mtp3_flag_old[i] = IDLE;
		MTP3IPMng.mtp3_flag_ip[i] = 0;
		MTP3IPMng.LinkIP[i] = 0;
		MTP3IPMng.LinkIPSubSta[i][0] = 0xff;
		MTP3IPMng.LinkIPSubSta[i][1] = 0xff;
	}
	MTP3IPMng.LinkIPNum = 0;

	for (i=0; i<128; i++)
	{
		mtp3.ls[i].links_available = 0;
		mtp3.ls[i].links_available_t = 0;
		mtp3.ls[i].adjacentsp_restarting = 0;
		mtp3.ls[i].influ_dstnum_asNLS = 0;
		mtp3.ls[i].influ_dstnum_asALS = 0;
		mtp3.ls[i].linksNum_configured = 0;
		mtp3.ls[i].adjacent_sp_place = 0xffff;
		taprc_loop[i] = 0;
		mtp3ObjInput.taprc_input[i] = 0;
//		linknum_in_ls[i] = 0;
		mtp3_t21_flag[i] = TIMER_STOP;
		sending_phase_finished[i] = IDLE;
	}

	for ( i=0; i<2048; i++ )
	{
		ls_sls[i] = 255;
		ls_slc[i] = 255;
		sls_to_link[i] = 255;
	}
	own_sp_restarting = 0;
	srm_nw = 0;
	active_ls_num = 0;
	current_active_ls_num = 0;
	rv_TRA_num = 0;
	tprc_nw = 0;
	mtp3ObjInput.tprc_input = IDLE;
	mtp3ObjState.tprc_state = 0;
	for (i=0; i<=255; i++ )
	{
		mtp3ObjState.lk_configured[i] = PARA_NOT_CONFIGURED;
		mtp3ObjState.lk_command[i] = 1;/* default: enable */
		nld_cause_lkd[i] = 0;
		local_change_over[i] = 0;
		mtp2_buf_full[i] = 0;
		mtp3ObjState.tlac_state[i] = 0;
		init_lsac_state[i] = IDLE;
		init_tlac_state[i] = IDLE;
	 	mtp3ObjInput.tsrc_input_from_stm[i] = IDLE;
	 	mtp3ObjInput.tsrc_input_from_tlac[i] = IDLE;
		mtp3ObjInput.tsrc_input_from_tcoc[i] = IDLE;
		mtp3ObjInput.tsrc_input_from_tcbc[i] = IDLE;
 		mtp3ObjState.tsrc_state[i] = 0;
	 	mtp3ObjInput.tcoc_input_from_stm[i] = IDLE;
	 	mtp3ObjInput.tcoc_input_from_hmdt[i] = IDLE;
		mtp3ObjInput.tcoc_input_from_tsrc[i] = IDLE;
 		mtp3ObjState.tcoc_state[i] = 0;
	 	mtp3ObjInput.tcbc_input[i] = IDLE;
		mtp3ObjInput.tcbc_input_from_tsrc[i] = IDLE;
 		mtp3ObjState.tcbc_state[i] = 0;
	 	mtp3ObjInput.lsac_input_from_l2[i] = IDLE;
 		mtp3ObjInput.lsac_input_from_sltc[i] = IDLE;
	 	mtp3ObjInput.lsac_input_from_stm[i] = IDLE;
	 	mtp3ObjInput.lsac_input_from_mgmt[i] = LSAC_MGMT_ACTIVATE_LINK;
		mtp3ObjInput.lsac_input_from_tcoc[i] = IDLE;
 		mtp3ObjState.lsac_state[i] = 0;
	 	mtp3ObjInput.tlac_input_from_slm[i] = IDLE;
 		mtp3ObjInput.tlac_input_from_mgmt[i] = IDLE;
	 	mtp3ObjInput.tlac_input_from_stm[i] = IDLE;
 		mtp3ObjInput.tlac_input_from_hmdt[i] = IDLE;
		mtp3ObjInput.tlac_input_from_Tctl[i] = IDLE;
		mtp3ObjInput.sltc_input[i] = IDLE;
		mtp3ObjState.sltc_state[i] = 0;
		link_available[i] = IDLE;
		changeover_possible[i] = IDLE;
		retrieval_required[i] = IDLE;
		remote_bsnt_retrieved[i] = IDLE;
		changeback_in_progress[i] = IDLE;
		changeover_in_progress[i] = IDLE;
		changeback_required[i] = IDLE;
		changeover_required[i] = IDLE;
		emergency_changeover_order[i] = IDLE;
		changeover_order[i] = IDLE;
	 	changeover_completed[i] = IDLE;
		failed[i] = IDLE;
		blocked_by[i] = IDLE;
		local_blocked[i] = IDLE;
		remote_blocked[i] = IDLE;
		first_failure[i] = IDLE;
		changeover_select[i] = IDLE;
		changeback_select[i] = IDLE;
		co_msg_can_exchange[i] = IDLE;
		cb_msg_can_exchange[i] = IDLE;
		local_bsnt_retrievable[i] = IDLE;
		tcbc_route_change[i] = IDLE;
		command3[i] = IDLE;
		controlled_rerouting_in_progress[i] = IDLE;
		transfer_prohibited[i] = IDLE;
		link_remotely_inhibited[i] = IDLE;
		link_locally_inhibited[i] = IDLE;
		link_inhibited[i] = IDLE;
		local_inhibit_in_progress[i] = IDLE;
		uninhibit_in_progress[i] = IDLE;
		management_req[i] = IDLE;
		t12_expired_2nd_time[i] = IDLE;
		t13_expired_2nd_time[i] = IDLE;

/* mark */
		mtp3.nw[0].routine[i] = 0x8a;
		mtp3.nw[1].routine[i] = 0x8a;
		mtp3.nw[2].routine[i] = 0x8a;
		mtp3.nw[3].routine[i] = 0x8a;

		mtp3ObjState.link_l3_state[i] = UNAVAILABLE;
		mtp3ObjState.link_l2_state[i] = UNAVAILABLE;
		mtp3ObjState.link_l1_state[i] = UNAVAILABLE;

		mtp3_set_link_manager(i);

/*		if (mtp3ObjState.lk_AMTP3_ok[i])
			mtp3ObjState.lk_mtp3[i] = mtp3_para->lk[i].e1_to_alterMTP3;
		else if (mtp3ObjState.lk_NMTP3_ok[i])
			mtp3ObjState.lk_mtp3[i] = mtp3_para->lk[i].e1_to_MTP3;
		else
			mtp3ObjState.lk_mtp3[i] = 0;*/

		wx5[i] = i*5;
		debug_link[i] = MTP3_MSGLOG_OFF;
	}

	mtp3_heartbeat.state = 0;
	mtp3_heartbeat.SubState[0] = 0xff;//all subs system available
	mtp3_heartbeat.SubState[1] = 0xff;//all subs system available
	memcpy(mtp3_heartbeat.version,version,3);
}

int MTP3_LinkIP_List(DWORD IP,BYTE mode)
{//mode=0:query ip, mode=1:add ip, mode=2:del ip
	int	i;

	if (IP==0 || IP==0xffffffff)
		return -1;

	for (i=0;i<MTP3IPMng.LinkIPNum;i++)
	{
		if (MTP3IPMng.LinkIP[i] == IP)
		{
			if (mode==2)
			{
				if ((i<MAX_MTP3_NUM-1) && (i>1))
					memcpy(&MTP3IPMng.LinkIP[i],&MTP3IPMng.LinkIP[i+1],MTP3IPMng.LinkIPNum-i-1);
				MTP3IPMng.LinkIPNum--;
			}
			return i;
		}
	}

	if (MTP3IPMng.LinkIPNum >= MAX_MTP3_NUM)
		return 0;

	if (mode==1)
	{
		MTP3IPMng.LinkIP[MTP3IPMng.LinkIPNum] = IP;
		MTP3IPMng.LinkIPNum = (MTP3IPMng.LinkIPNum + 1) & (MAX_MTP3_NUM-1);
		return MTP3IPMng.LinkIPNum-1;
	}

	return -1;
}

/*	slc0	slc1	slc3	slc5
sls	 0		 1		 2		 3
sls	 4		 5		 6		 7
sls	 8		 9		 10		 11
sls	 12		 13		 14		 15		*/


void update_sls_to_link_table(int ls)
{
	int		i=0,j;
	BYTE	sls=0;
	int		lknum;
	int		place;
	int		lsx16;
	int		link;

	lsx16 = ls*16;
	lknum = mtp3.ls[ls].linksNum_configured;
//	lknum = linknum_in_ls[ls];
	if (lknum > 0)
	{
		for (sls=0; sls<16; sls++)
		{
			place = sls % lknum;
			j=0;
			for (i=0; i<16; i++)
			{
				link = ls_slc[lsx16+i];
				if (mtp3ObjState.lk_configured[link] == PARA_CONFIGURED)
				{
					if (j == place)
					{
						sls_to_link[lsx16+sls] = link;
						break;
					}
					else
						j++;
				}
			}
		}
	}
	else
	{
		for (sls=0; sls<16; sls++)
		{
			sls_to_link[lsx16+sls] = 0xFF;
		}
	}
}

int update_ls_slc_table(int link)
{
	WORD	ls;
	int		lsx16;
	BYTE	slc;
	int		temp;
	int		idiv4;
	int		idiv8;

	idiv4 = link/4;
	idiv8 = link/8;
	temp = 3<<((link%4)*2);
	ls = mtp3_para->lk[link].e1_to_linkset;
	if (ls < 128)
	{
		lsx16 = ls << 4;
		slc = mtp3_para->lk[link].e1_to_slc;
		if ( (slc < 16)								&&
			 (mtp3_para->lk[link].e1_lk_type & 1)	&&//enabled
			 (mtp3ObjState.lk_configured[ls_slc[lsx16+slc]] != PARA_CONFIGURED))
		{
			mtp3ObjState.lk_configured[link] = PARA_CONFIGURED;
			mtp3ObjState.link_l3_state[link] = UNAVAILABLE;
			mtp3.ls[ls].linksNum_configured++;
			ls_slc[lsx16+slc] = link;
//			linknum_in_ls[ls]++;
			mtp3_heartbeat.link_state[idiv4] = mtp3_heartbeat.link_state[idiv4] & (~temp);
			return 1;
		}
		else
		{
			mtp3ObjState.lk_configured[link] = PARA_NOT_CONFIGURED;
			mtp3ObjState.link_l3_state[link] = UNAVAILABLE;
			mtp3_heartbeat.link_state[idiv4] = mtp3_heartbeat.link_state[idiv4] | temp;
		}
	}
	else
		mtp3_heartbeat.link_state[idiv4] = mtp3_heartbeat.link_state[idiv4] | temp;

	return 0;
}

void update_influence_table(BYTE nw_no)
{
	nw_para	*routine;
	int		lsno;
	BYTE	dst_num;
	int		i;
	ls_info	*ls;
	BOOL	added=0;

	routine = &mtp3_para->nw[nw_no];
	for ( i=0; i<256; i++ )
	{
		if (routine->dpc[i] == 0)
			continue;
		lsno = routine->normal_ls[i];
		if ( (lsno < 128)								&&
			 ((mtp3_para->ls_pro[lsno] & 3) == nw_no)	)
		{
			added = 1;
			Mtp3AddSortRec(nw_no,routine->dpc[i],i, routine->opc[i]);
			ls = &mtp3.ls[lsno];
			dst_num = ls->influ_dstnum_asNLS;
			if ( dst_num < MAX_LS_DPC )
			{
				ls->influ_dstplace_intable_asNLS[dst_num] = i;
				ls->influ_dstnum_asNLS ++;
			}
		}

		lsno = routine->alternative_ls[i];
		if ( (lsno < 128)								&&
			 (routine->normal_ls[i] < 128)				&&
			 ((mtp3_para->ls_pro[lsno] & 3) == nw_no)	)
		{
			if (!added)
				Mtp3AddSortRec(nw_no,routine->dpc[i],i, routine->opc[i]);
			ls = &mtp3.ls[lsno];
			dst_num = ls->influ_dstnum_asALS;
			if ( dst_num < MAX_LS_DPC )
			{
				ls->influ_dstplace_intable_asALS[dst_num] = i;
				ls->influ_dstnum_asALS ++;
			}
		}

		added = 0;
	}
}

void update_ls_adjacent_sp_place(BYTE ls)/*linkset adjacent sp's place in sp table */
{
	BYTE	lsnw;/* network that linkset belong to */
	long	pc, opc;
	int		j;

	pc = mtp3_para->ls_op_pc[ls];
	opc = mtp3_para->ls_opc[ls];
	if ( pc != 0)
	{
		for (j=0; j<256; j++)
		{
			lsnw = (mtp3_para->ls_pro[ls]) & 3;
			if (mtp3_para->nw[lsnw].dpc[j] == pc && mtp3_para->nw[lsnw].opc[j] == opc )
			{
				mtp3.ls[ls].adjacent_sp_place = j;
				return;
			}
		}
	}
}

void update_active_ls_num()
{
	int		i;

	for (i=0; i<128; i++)
	{
		if (mtp3.ls[i].linksNum_configured > 0)
//		if ( linknum_in_ls[i] > 0 )
		{
			active_ls_num ++;
		}
		else
		{
			mtp3_heartbeat.linkset_state[i/4] = mtp3_heartbeat.linkset_state[i/4] | (3<<((i%4)*2));
		}
	}
}

void update_timer(int	link)
{
	lk_timer	*lt;

//	mtp3_para->lt[i].t1 = 5;/* 800ms */
//	mtp3_para->lt[i].t2 = 8;/* 1280ms */
//	mtp3_para->lt[i].t3 = 5;/* 800ms */
//	mtp3_para->lt[i].t4 = 5;/* 800ms */
//	mtp3_para->lt[i].t5 = 5;/* 800ms */
//	mtp3_para->lt[i].t7 = 10;/* 1600ms */
//	mtp3_para->lt[i].t8 = 6;/* 960ms */
//	mtp3_para->lt[i].t12 = 7;/* 1120ms */
//	mtp3_para->lt[i].t13 = 7;/* 1120ms */
//	mtp3_para->lt[i].t14 = 15;/* 2400ms */


	lt = &mtp3_para->lt[link];
	if ( (lt->t1 > 7) || (lt->t1 < 4) )
		lt->t1 = 5;
	if ( (lt->t2 > 7) || (lt->t2 < 5) )
		lt->t2 = 6;
	if ( (lt->t3 > 7) || (lt->t3 < 4) )
		lt->t3 = 5;
	if ( (lt->t4 > 7) || (lt->t4 < 4) )
		lt->t4 = 5;
	if ( (lt->t5 > 7) || (lt->t5 < 4) )
		lt->t5 = 5;
	if ( (lt->t7 > 12) || (lt->t7 < 6) )
		lt->t7 = 10;
	if ( (lt->t8 > 7) || (lt->t8 < 5) )
		lt->t8 = 6;
	if ( (lt->t12 > 10) || (lt->t12 < 5) )
		lt->t12 = 7;
	if ( (lt->t13 > 10) || (lt->t13 < 5) )
		lt->t13 = 7;
	if ( (lt->t14 > 19) || (lt->t14 < 12) )
		lt->t14 = 15;
}

void init_mtp3table()
{
	int	i;

	for (i=0; i<256; i++)
	{
		if (update_ls_slc_table(i));
		MTP3_LinkIP_List(mtp3_para->lk[i].e1_to_mtp3,1);//addip
		MTP3_LinkIP_List(mtp3_para->lk[i].e1_to_alterMTP3,1);//addip
	}
	for (i=0; i<128; i++)
	{
		update_sls_to_link_table(i);
	}
	for (i=0; i<4; i++)
	{
		update_influence_table(i);
	}
	for (i=0; i<128; i++)
	{
		update_ls_adjacent_sp_place(i);
	}
	update_active_ls_num();
	for (i=0; i<256; i++)
	{
		update_timer(i);
	}
	mtp3_para->mtp3_t10 = 63;/* 40 SECOND, unit=640ms,for dpc */
	mtp3_para->mtp3_t18 = 20;
	mtp3_para->mtp3_t19 = 4;
	mtp3_para->mtp3_t20 = 4;
	mtp3_para->mtp3_t21 = 375;/* 30 SECOND,unit=80ms, for linkset */
	mtp3ObjInput.tprc_input = TPRC_SP_RESTART_INDICATION;
	own_sp_restarting = 1;
	tprc_mgmt_signalling_point_restart_indication();
	mtp3_get_time();
	mtp3_set_csta_p();
	set_status(MTP3_COMPONENT_ID,MTP3_HB_LEN,(BYTE*)&mtp3_heartbeat.version);
	get_routes_from_other_plat();
	mtp3_debug(MTP3DB_CMD,"MTP3 INIT COMPLETE(%08lx)",mtp3_localip);
}

void reset_mtp3()
{
//	init_mtp3para();

	mtp3lite_reset();
	i_sys();
	init_mtp3table();
	if(mtp3_alterip != 0)//take over altermtp3
	{
		MTP3_activate(mtp3_alterip);
	}
}

void mtp3_reload_data()
{
	mtp3_readpara_from_disk();
//	recover_para();
	i_sys();
	init_mtp3table();
}

void mtp_shm_init(WORD moduleid_systemid)
{
	printf("mtp3 start init\n");
	mtp_lgetlocalip();
	sccp_shm_init();
	tup_shm_init();
	isup_shm_init();
	bicc_shm_init();
	iptransInit_mtp3();
	init_mtp3para();
	mtp_debug_set();
	mtp_snmp_init();
	mtp3_reload_data();
	mtp3lite_init();
	mtp3_init_dynamic_opc();
	mtp2_module = moduleid_systemid>>8;
	mtp2_systemid = moduleid_systemid & 0xff;
	printf("mtp3 complete init\n");
}

void mtp3_init_serial(char *Serial)
{
	mtp3_para->MTP3SerialNum = Str2Ull(Serial);
}

int	sccp_get_SPstate(mtp_primitive *ptr)
{
	BYTE	RSub;

	RSub = S_primitive->RSub;
	if (RSub != S_primitive->WSub)
	{
		memcpy(ptr,&S_primitive->primitive[RSub],sizeof (struct mtp_primitive));
		S_primitive->RSub = (RSub+1) & 0x0f;
		return 1;
	}
	return 0;
}

int	isup_get_SPstate(mtp_primitive *ptr)
{
	BYTE	RSub;

	RSub = I_primitive->RSub;
	if (RSub != I_primitive->WSub)
	{
		memcpy(ptr,&I_primitive->primitive[RSub],sizeof (struct mtp_primitive));
		I_primitive->RSub = (RSub+1) & 0x0f;
		return 1;
	}
	return 0;
}

int	bicc_get_SPstate(mtp_primitive *ptr)
{
	BYTE	RSub;

	RSub = B_primitive->RSub;
	if (RSub != B_primitive->WSub)
	{
		memcpy(ptr,&B_primitive->primitive[RSub],sizeof (struct mtp_primitive));
		B_primitive->RSub = (RSub+1) & 0x0f;
		return 1;
	}
	return 0;
}

int	tup_get_SPstate(mtp_primitive *ptr)
{
	BYTE	RSub;

	RSub = I_primitive->RSub;
	if (RSub != I_primitive->WSub)
	{
		memcpy(ptr,&I_primitive->primitive[RSub],sizeof (struct mtp_primitive));
		I_primitive->RSub = (RSub+1) & 0x0f;
		return 1;
	}
	return 0;
}

int tup_GetMsg(up_message *msgptr)
{
	BYTE    RSub;

	RSub = T_shm_ptr->MT_Buf.RSub;
	if (RSub != T_shm_ptr->MT_Buf.WSub)
	{
		memcpy(msgptr,&T_shm_ptr->MT_Buf.msgNum[RSub],sizeof(up_message));

		T_shm_ptr->MT_Buf.RSub++;
		return 1;
	}
	return 0;
}

int isup_GetMsg(up_message *msgptr)
{
	BYTE    RSub;

	RSub = I_shm_ptr->MI_Buf.RSub;
	if (RSub != I_shm_ptr->MI_Buf.WSub)
	{
		memcpy(msgptr,&I_shm_ptr->MI_Buf.msgNum[RSub],sizeof(up_message));

		I_shm_ptr->MI_Buf.RSub++;
		return 1;
	}
	return 0;
}

int bicc_GetMsg(up_message_2 *msgptr)
{
	BYTE    RSub;

	RSub = B_shm_ptr->MI_Buf.RSub;
	if (RSub != B_shm_ptr->MI_Buf.WSub)
	{
		memcpy(msgptr,&B_shm_ptr->MI_Buf.msgNum[RSub],sizeof(up_message_2));

		B_shm_ptr->MI_Buf.RSub++;
		return 1;
	}
	return 0;
}

int sccp_GetMsg(up_message *msgptr)
{
	BYTE    RSub;

	RSub = S_shm_ptr->MS_Buf.RSub;
	if (RSub != S_shm_ptr->MS_Buf.WSub)
	{
		memcpy(msgptr,&S_shm_ptr->MS_Buf.msgNum[RSub],sizeof(up_message));
		S_shm_ptr->MS_Buf.RSub++;
		return 1;
	}
	return 0;
}

int	mtp3_perform_routing(up_message *msgptr,BYTE WriteSub)
{
	BYTE	sls;
	int		returnValue;
	BYTE	sio;

	sio = msgptr->sio;
	if (msgptr->dest_ip != 0xffffffff)
		return 256;
	else
	{
		sls = msgptr->cic[0] & 0x0f;
		returnValue = check_outbound_route((msgptr->sio>>6)&3,msgptr->dpc,sls, msgptr->opc);//??-
		if (returnValue >= 0)
		{
			switch (sio & 7)
			{
				case 3:
					routingResult.sccpMsgOutLink[WriteSub] = returnValue;
					break;
				case 4:
					routingResult.tupMsgOutLink[WriteSub] = returnValue;
					break;
				case 5:
					routingResult.isupMsgOutLink[WriteSub] = returnValue;
					break;
				case 13:
					routingResult.biccMsgOutLink[WriteSub] = returnValue;
					break;
			}
		}
		else
		{
			mtp3_debug(MTP3DB_ERROR,"USER==>MTP3,SIO=%x,DPC=%lx,len=%d",msgptr->sio,msgptr->dpc,msgptr->len);
			mtp3_showbuf(MTP3DB_ERROR,msgptr->msgList,msgptr->len);
			switch (returnValue)
			{
				case -1:
					mtp3_debug(MTP3DB_ERROR,"Routing Failed,Reason:linkset unavailable");
					break;
				case -2:
					mtp3_debug(MTP3DB_ERROR,"Routing Failed,Reason:linkset not configured");
					break;
				case -3:
					mtp3_debug(MTP3DB_ERROR,"Routing Failed,Reason:dpc(dpc->linkset) not configured");
					break;
				default:
					break;
			}
		}
		return returnValue;
	}
}

int	mtp3_perform_routing_2(up_message_2 *msgptr,BYTE WriteSub)
{
	BYTE	sls;
	int		returnValue;
	BYTE	sio;

	sio = msgptr->sio;
	if (msgptr->dest_ip != 0xffffffff)
		return 256;
	else
	{
		sls = msgptr->cic[0] & 0x0f;
		returnValue = check_outbound_route((msgptr->sio>>6)&3,msgptr->dpc,sls, msgptr->opc);//??-
		if (returnValue >= 0)
		{
			switch (sio & 15)
			{
				case 3:
					routingResult.sccpMsgOutLink[WriteSub] = returnValue;
					break;
				case 4:
					routingResult.tupMsgOutLink[WriteSub] = returnValue;
					break;
				case 5:
					routingResult.isupMsgOutLink[WriteSub] = returnValue;
					break;
				case 13:
					routingResult.biccMsgOutLink[WriteSub] = returnValue;
					break;
			}
		}
		else
		{
			mtp3_debug(MTP3DB_ERROR,"USER==>MTP3,SIO=%x,DPC=%lx,len=%d",msgptr->sio,msgptr->dpc,msgptr->len);
			mtp3_showbuf(MTP3DB_ERROR,msgptr->msgList,msgptr->len);
			switch (returnValue)
			{
				case -1:
					mtp3_debug(MTP3DB_ERROR,"Routing Failed,Reason:linkset unavailable");
					break;
				case -2:
					mtp3_debug(MTP3DB_ERROR,"Routing Failed,Reason:linkset not configured");
					break;
				case -3:
					mtp3_debug(MTP3DB_ERROR,"Routing Failed,Reason:dpc(dpc->linkset) not configured");
					break;
				default:
					break;
			}
		}
		return returnValue;
	}
}

int sccp_to_mtp3(up_message *msgptr)
{
	BYTE	ReadSub;
	BYTE	WriteSub;
	BYTE	nw;
	int		rtResult;

	nw = ((msgptr->sio) >> 6) & 3;

//	current_measure->tf_measure1[0][wx5[nw]+2]+=msgptr->len;/* octets */
	current_measure->tf_measure2[0][wx5[nw]+2]++;/* MSUs */

	ReadSub = S_shm_ptr->SM_Buf.RSub;
	WriteSub = S_shm_ptr->SM_Buf.WSub;
	if(msgptr->dest_ip == 0 &&  msgptr->dpc == 0)
	{
		mtp3_debug(MTP3DB_ERROR,"receive message from SCCP,sio=%x,dpc=%lx",msgptr->sio,msgptr->dpc);
		mtp3_showbuf(MTP3DB_ERROR,msgptr->msgList,msgptr->len);
		mtp3_debug(MTP3DB_ERROR,"perform routing:Route Failure,Reason:dst ip=0, dpc=0 ");
		return -4;
	}
	if ( (WriteSub+1) == ReadSub)// buffer overflow
	{
		mtp3.nw[nw].flow.UtoM_throwed[2]++;
		mtp3_debug(MTP3DB_ERROR,"receive message from UP,sio=%x,dpc=%lx",msgptr->sio,msgptr->dpc);
		mtp3_showbuf(MTP3DB_ERROR,msgptr->msgList,msgptr->len);
		mtp3_debug(MTP3DB_ERROR,"perform routing:Route Failure,Reason:buffer overflow");
		return -4;
	}
	rtResult = mtp3_perform_routing(msgptr,WriteSub);
	if (rtResult >= 0)
	{
		memcpy(&S_shm_ptr->SM_Buf.msgNum[WriteSub],msgptr,sizeof(struct up_message));
		S_shm_ptr->SM_Buf.WSub++;
		mtp3.nw[nw].flow.UtoM[2]++;
	}
	else
	{
//		current_measure->tf_measure1[5][wx5[nw]+2]+=len;/* octets */
		current_measure->tf_measure2[5][wx5[nw]+2]++;/* MSUs */
	}
	return rtResult;
}

int tup_to_mtp3(up_message *msgptr)
{
	BYTE	ReadSub;
	BYTE	WriteSub;
	BYTE	nw;
	int		rtResult;

	nw = ((msgptr->sio) >> 6) & 3;
	ReadSub = T_shm_ptr->TM_Buf.RSub;
	WriteSub = T_shm_ptr->TM_Buf.WSub;

//	current_measure->tf_measure1[0][wx5[nw]+3]+=msgptr->len;/* octets */
	current_measure->tf_measure2[0][wx5[nw]+3]++;/* MSUs */
	if(msgptr->dest_ip == 0 &&  msgptr->dpc == 0)
	{
		mtp3_debug(MTP3DB_ERROR,"receive message from TUP,sio=%x,dpc=%lx",msgptr->sio,msgptr->dpc);
		mtp3_showbuf(MTP3DB_ERROR,msgptr->msgList,msgptr->len);
		mtp3_debug(MTP3DB_ERROR,"perform routing:Route Failure,Reason:dst ip=0, dpc=0 ");
		return -4;
	}
	if ( (WriteSub+1) == ReadSub)// buffer overflow
	{
		mtp3.nw[nw].flow.UtoM_throwed[3]++;
		mtp3_debug(MTP3DB_ERROR,"receive message from UP,sio=%x,dpc=%lx",msgptr->sio,msgptr->dpc);
		mtp3_showbuf(MTP3DB_ERROR,msgptr->msgList,msgptr->len);
		mtp3_debug(MTP3DB_ERROR,"perform routing:Route Failure,Reason:buffer overflow");
		return -4;
	}
	rtResult = mtp3_perform_routing(msgptr,WriteSub);
	if (rtResult >= 0)
	{
		memcpy(&T_shm_ptr->TM_Buf.msgNum[WriteSub],msgptr,sizeof(struct up_message));
		T_shm_ptr->TM_Buf.WSub++;
		mtp3.nw[nw].flow.UtoM[3]++;
	}
	else
	{
//		current_measure->tf_measure1[5][wx5[nw]+3]+=len;/* octets */
		current_measure->tf_measure2[5][wx5[nw]+3]++;/* MSUs */
	}
	return rtResult;
}

int isup_to_mtp3(up_message *msgptr)
{
	BYTE	ReadSub;
	BYTE	WriteSub;
	BYTE	nw;
	int		rtResult;

	nw = ((msgptr->sio) >> 6) & 3;

//	current_measure->tf_measure1[0][wx5[nw]+4]+=msgptr->len;/* octets */
	current_measure->tf_measure2[0][wx5[nw]+4]++;/* MSUs */
	if(msgptr->dest_ip == 0 &&  msgptr->dpc == 0)
	{
		mtp3_debug(MTP3DB_ERROR,"receive message from ISUP,sio=%x,dpc=%lx",msgptr->sio,msgptr->dpc);
		mtp3_showbuf(MTP3DB_ERROR,msgptr->msgList,msgptr->len);
		mtp3_debug(MTP3DB_ERROR,"perform routing:Route Failure,Reason:dst ip=0, dpc=0 ");
		return -4;
	}
	ReadSub = I_shm_ptr->IM_Buf.RSub;
	WriteSub = I_shm_ptr->IM_Buf.WSub;
	if ( (WriteSub+1) == ReadSub)// buffer overflow
	{
		mtp3.nw[nw].flow.UtoM_throwed[4]++;
		mtp3_debug(MTP3DB_ERROR,"receive message from UP,sio=%x,dpc=%lx",msgptr->sio,msgptr->dpc);
		mtp3_showbuf(MTP3DB_ERROR,msgptr->msgList,msgptr->len);
		mtp3_debug(MTP3DB_ERROR,"perform routing:Route Failure,Reason:buffer overflow");
		return -4;
	}
	rtResult = mtp3_perform_routing(msgptr,WriteSub);
	if (rtResult >= 0)
	{
		memcpy(&I_shm_ptr->IM_Buf.msgNum[WriteSub],msgptr,sizeof(struct up_message));
		I_shm_ptr->IM_Buf.WSub++;
		mtp3.nw[nw].flow.UtoM[4]++;
	}
	else
	{
//		current_measure->tf_measure1[5][wx5[nw]+4]+=len;/* octets */
		current_measure->tf_measure2[5][wx5[nw]+4]++;/* MSUs */
	}
	return rtResult;
}

int bicc_to_mtp3(up_message_2 *msgptr)
{
	BYTE	ReadSub;
	BYTE	WriteSub;
	BYTE	nw;
	int		rtResult;

	nw = ((msgptr->sio) >> 6) & 3;

//	current_measure->tf_measure1[0][wx5[nw]+4]+=msgptr->len;/* octets */
	current_measure->tf_measure2[0][wx5[nw]+4]++;/* MSUs */

	ReadSub = B_shm_ptr->IM_Buf.RSub;
	WriteSub = B_shm_ptr->IM_Buf.WSub;
	if(msgptr->dest_ip == 0 &&  msgptr->dpc == 0)
	{
		mtp3_debug(MTP3DB_ERROR,"receive message from BICC,sio=%x,dpc=%lx",msgptr->sio,msgptr->dpc);
		mtp3_showbuf(MTP3DB_ERROR,msgptr->msgList,msgptr->len);
		mtp3_debug(MTP3DB_ERROR,"perform routing:Route Failure,Reason:dst ip=0, dpc=0 ");
		return -4;
	}
	if ( (WriteSub+1) == ReadSub)// buffer overflow
	{
		mtp3.nw[nw].flow.UtoM_throwed[4]++;
		mtp3_debug(MTP3DB_ERROR,"receive message from UP,sio=%x,dpc=%lx",msgptr->sio,msgptr->dpc);
		mtp3_showbuf(MTP3DB_ERROR,msgptr->msgList,msgptr->len);
		mtp3_debug(MTP3DB_ERROR,"perform routing:Route Failure,Reason:buffer overflow");
		return -4;
	}
	rtResult = mtp3_perform_routing_2(msgptr,WriteSub);
	if (rtResult >= 0)
	{
		memcpy(&B_shm_ptr->IM_Buf.msgNum[WriteSub],msgptr,sizeof(struct up_message_2));
		B_shm_ptr->IM_Buf.WSub++;
		mtp3.nw[nw].flow.UtoM[4]++;
	}
	else
	{
//		current_measure->tf_measure1[5][wx5[nw]+4]+=len;/* octets */
		current_measure->tf_measure2[5][wx5[nw]+4]++;/* MSUs */
	}
	return rtResult;
}

void scan_lk_state()
{
	static BYTE lk=0;

	if (mtp3ObjState.lk_configured[lk] != PARA_CONFIGURED)
	{
		lk = lk+1;
		return;
	}
	if (mtp3ObjState.link_l3_state[lk] != AVAILABLE)
	{
		current_measure->lk_measure1[lk][3]++;//Duration of SL unavailability(for any reason
	}
	else if (mtp3ObjState.link_l3_state[lk] == UNAVAILABLE)
		current_measure->lk_measure1[lk][6]++;//Duration of SL unavailability due to link fai
	if (mtp3ObjState.link_l3_state[lk] == INHIBITED)
	{
		if (link_locally_inhibited[lk] == TRUE)
		{
			current_measure->lk_measure1[lk][4]++;//Duration of SL inhibition due to local  management actions
		}
		else
			current_measure->lk_measure1[lk][5]++;//Duration of SL inhibition due to remote  management actions
	}

	if (mtp3_para->lk[lk].e1_to_mtp3 == mtp3_localip)
	{//this mtp3 is the normal mtp3 of this link
		if (mtp3ObjState.lk_AMTP3_ok[lk] & 15)//Alternative MTP3 available
		{
//			mtp3ObjState.lk_mtp3[lk] = mtp3_para->lk[lk].e1_to_alterMTP3;
			//do nothing, waiting for alternative unavailable
		}
		else if (mtp3ObjState.lk_NMTP3_ok[lk] >> 4)//if Alternative MTP3 not avilable and normal mtp3 is activated
		{
			mtp3_debug(MTP3DB_EVENT,"link %d host MTP3 change from backup to normal",lk);
			mtp3ObjState.lk_NMTP3_ok[lk] &= 0x0f;
			if (mtp3ObjState.lk_mtp3[lk] == mtp3_para->lk[lk].e1_to_alterMTP3)
			{
				mtp3ObjState.lk_mtp3[lk] = mtp3_para->lk[lk].e1_to_mtp3;
				if (mtp3ObjState.link_l3_state[lk] == AVAILABLE)
					otherMTP3_managed_link_unavailable(lk);
			}
			mtp3ObjState.lk_mtp3[lk] = mtp3_para->lk[lk].e1_to_mtp3;
		}
		else//other case normal is always the host
			mtp3ObjState.lk_mtp3[lk] = mtp3_para->lk[lk].e1_to_mtp3;
	}
	else if (mtp3_para->lk[lk].e1_to_alterMTP3 == mtp3_localip)
	{//this mtp3 is the alternative mtp3 of this link
		if (mtp3ObjState.lk_mtp3[lk] == mtp3_localip)//it is the current host
		{
			if ((mtp3ObjState.lk_AMTP3_ok[lk]>>4)==2)//only the deactivate command can make it abandon host
			{
				mtp3_debug(MTP3DB_EVENT,"link %d host MTP3 change back to normal",lk);
				mtp3ObjState.lk_AMTP3_ok[lk] &= 0x0f;
				mtp3ObjState.lk_mtp3[lk] = mtp3_para->lk[lk].e1_to_mtp3;

/* disable the link */
				mtp3_debug(MTP3DB_EVENT,"link %d L2 out of service (changing back to normal MTP3)",lk);
				mtp3ObjInput.lsac_input_from_l2[lk] = LSAC_L2_OUT_OF_SERVICE;
				mtp3ObjInput.sltc_input[lk] = SLTC_STOP;
				sltc_proc(lk);

	/* send stop command to mtp2 */
				if (MTP3_LINK_TYPE(lk) == LKTYPE_SIGTRAN)//m2ua link
				{
					send_command_to_mtp2(lk,MTP2_DEACTIVE_LINK);
					send_command_to_mtp2(lk,MTP3_M2UA_DISABLE);
				}
				else
					send_command_to_mtp2(lk,MTP2_STOP_L2);
				mtp3_send_alarm(MTP3_LINK_COMPONENT+lk,MTP3ALARM_LINK_CB_TO_NMTP3);
			}
		}
		else
		{
			if (mtp3ObjState.lk_NMTP3_ok[lk] & 15)
			{//normal ok
				mtp3ObjState.lk_mtp3[lk] = mtp3_para->lk[lk].e1_to_mtp3;
			}

			else if ((mtp3ObjState.lk_AMTP3_ok[lk]>>4)==1)//if normal MTP3 not avilable and alternative mtp3 is activated
			{
				mtp3_debug(MTP3DB_EVENT,"link %d host MTP3 change to alternative",lk);
				mtp3ObjState.lk_AMTP3_ok[lk] &= 0x0f;
				mtp3ObjState.lk_mtp3[lk] = mtp3_para->lk[lk].e1_to_alterMTP3;

			}
		}
	}

	else
	{
		if (mtp3ObjState.lk_AMTP3_ok[lk] & 15)
			mtp3ObjState.lk_mtp3[lk] = mtp3_para->lk[lk].e1_to_alterMTP3;

		else if (mtp3ObjState.lk_NMTP3_ok[lk] & 15)
			mtp3ObjState.lk_mtp3[lk] = mtp3_para->lk[lk].e1_to_mtp3;
	}


	if (mtp3ObjState.lk_mtp3[lk]==mtp3_localip)
	{
		mtp3_heartbeat.masterMTP3[lk/8] |= (1<<(lk&7));
	}
	else
		mtp3_heartbeat.masterMTP3[lk/8] &= (~(1<<(lk&7)));

	lk = lk+1;

	if (lk==255)
	{
		set_status(MTP3_COMPONENT_ID,MTP3_HB_LEN,(BYTE*)&mtp3_heartbeat.version);
	}
}


void scan_ls_state()
{
	BYTE	nw;
	WORD 	adsp_place;
	static	BYTE ls=0;

	adsp_place = mtp3.ls[ls].adjacent_sp_place;
	if (adsp_place > 255)
	{
		ls = (ls + 1) & 0x7f;
		return;
	}
	nw = ( mtp3_para->ls_pro[ls] ) & 3;
	if (mtp3.ls[ls].adjacentsp_acessible != TRUE)
	{
		current_measure->ls_measure[ls][6]++;/* duration_of_adjacent_sp_inaccessible */;
	}
	if ( (mtp3.ls[ls].links_available == 0)	&&
		 (mtp3.ls[ls].linksNum_configured)	)
//		 (linknum_in_ls[ls] > 0)			)
	{
		current_measure->ls_measure[ls][0]++;/* duration_of_unavailability */
	}
	ls = (ls + 1) & 0x7f;
}

void scan_mtp2_activity()// check mtp2 exist or not
{
	int		i,j;
	int		tmp;
	int		chl;
	static  BYTE mtp_t20s=0;

	mtp_t20s++;
	if (mtp_t20s == 3)
	{
		mtp_t20s = 0;
		for (i=0; i<32; i++)
		{
			if ( (mtp2_flag_old[i] != mtp2_flag_new[i])	&&
				 (mtp2_flag_new[i] == IDLE)				)
			{
				tmp = i << 3;
				for (j=0; j<8; j++)
				{
					chl = tmp+j;
					if (mtp3ObjState.lk_mtp3[chl] == mtp3_localip)
					{
						mtp3ObjInput.lsac_input_from_l2[chl] = LSAC_L2_OUT_OF_SERVICE;
						mtp3ObjState.link_l2_state[chl] = MTP2_STATE_IDLE;
						nld_cause_lkd[chl] ++;/* internet cable disconnect cause lk disconnect */
						mtp3ObjInput.sltc_input[chl] = SLTC_STOP;
						sltc_proc(chl);
					}
				}
			}
			mtp2_flag_old[i] = mtp2_flag_new[i];
			mtp2_flag_new[i] = IDLE;
		}
	}
}

int sys_mtp3_table(DWORD ip);
void scan_mtp3_activity()// check other mtp3 can use or not
{
	int	chl;
	static BYTE mtp3ip=0;
/*	WORD		lsno;
	ls_info		*ls=NULL;*/

	mtp3ip=(mtp3ip+1) % 127;

	if (mtp3ip >= MAX_MTP3_NUM)
		return;

	if ( (MTP3IPMng.mtp3_flag_old[mtp3ip] != MTP3IPMng.mtp3_flag_new[mtp3ip])	&&
		 (MTP3IPMng.mtp3_flag_new[mtp3ip] == IDLE)					&&
		 (MTP3IPMng.mtp3_flag_ip[mtp3ip] != mtp3_localip)				)
	{
		for (chl=0; chl<256; chl++)
		{
			if ( (mtp3ObjState.lk_mtp3[chl] == MTP3IPMng.mtp3_flag_ip[mtp3ip])	&&
				 (mtp3ObjState.link_l3_state[chl] == AVAILABLE)		)
			{
/*				lsno = mtp3_para->lk[chl].e1_to_linkset;
				ls = &mtp3.ls[lsno];
				ls->links_available--;*/
				mtp3_debug(MTP3DB_EVENT,"link %d MTP3 %08lx timeout",chl,mtp3ObjState.lk_mtp3[chl]);
				mtp3ObjInput.tsrc_input_from_tlac[chl] = TSRC_TLAC_LINK_UNAVAILABLE;
				tsrc_proc(chl);
				hmrt_tcoc_update_routing_tables(chl);
				mtp3ObjState.tlac_state[chl] = TLAC_UNAVAILABLE_STATE;
			}

			if (mtp3_para->lk[chl].e1_to_mtp3 == MTP3IPMng.mtp3_flag_ip[mtp3ip])
				mtp3ObjState.lk_NMTP3_ok[chl] = 0;
			else if (mtp3_para->lk[chl].e1_to_alterMTP3 == MTP3IPMng.mtp3_flag_ip[mtp3ip])
				mtp3ObjState.lk_AMTP3_ok[chl] = 0;

		}
	}
	MTP3IPMng.mtp3_flag_old[mtp3ip] = MTP3IPMng.mtp3_flag_new[mtp3ip];
	MTP3IPMng.mtp3_flag_new[mtp3ip] = IDLE;
}

void mtp3_proc()
{
	up_message getmsg;
	up_message_2 getmsg_2;
	up_message *msgptr = (up_message*)&getmsg;
	up_message_2 *msgptr_2 = (up_message_2*)&getmsg_2;
	BYTE	i;
	BYTE	temp;
//	BYTE	ib_b;
//	unsigned short	addr;
	static BYTE sltc_loop=0;
	static BYTE dst_loop=0;
	static BYTE	mtp_t1s=0;
	static BYTE	mtp_t10s=0;
	static BYTE	mtp_10ms_tick=0;
	static BYTE	mtp_100ms_tick=0;

//	addr = 0x378;
//	ib_b = inb(addr);
//	outb(ib_b | 2,addr);

	mtp3DebugFull = 0;

	for (i = 0; i<128; i++)
	{
		GetMtp2Msg(SS7_PORT);// get mtp2 message by port 4950
		GetMtp2Msg(M2UA_PORT);// get m2ua message
		GetM3uaMsg(M2UA_PORT);// get m3ua message
		get_isup(msgptr);// check isup buffer message
		get_bicc(msgptr_2);// check bicc buffer message
		get_tup(msgptr);// check tup buffer message
		get_sccp(msgptr);// check sccp buffer message
	}

	mtp3lite_timer();
	m3ua_timer();
/* Q.704 state machine */
	for (i=0; i<16; i++)
	{
		temp = dst_loop + i;
		if (MTP3_LINK_TYPE(temp) == LKTYPE_MTP3_LITE ||MTP3_LINK_TYPE(temp) == LKTYPE_M3UA)
			continue;
		lsac_proc(temp);
		tlac_proc(temp);
		tsrc_proc(temp);
		tcoc_proc(temp);
		tcbc_proc(temp);
		rtpc_proc(srm_nw,temp);
		rtac_proc(srm_nw,temp);
		rsrt_proc(srm_nw,temp);
		mtp3Timer_proc(temp);
		taprc_proc(temp);
	}
	dst_loop = dst_loop + 16;
	if (dst_loop == 0)
		srm_nw = (srm_nw + 1) & 3;
	if (MTP3_LINK_TYPE(sltc_loop) != LKTYPE_MTP3_LITE && MTP3_LINK_TYPE(sltc_loop) != LKTYPE_M3UA)
		sltc_proc(sltc_loop);
	sltc_loop++;
/* Q.704 state machine */

	for (i=0;i<4;i++)
	{
		scan_conf_right_or_not(i);
	}

	switch (mtp_10ms_tick)/* every 160ms loop one times */
	{
		case 0:/* 10ms */
			break;
		case 1:/* 20ms */
			break;
		case 2:/* 30ms */
			scan_lk_state();
			break;
		case 3:/* 40ms */
			break;
		case 4:/* 50ms */
			break;
		case 5:/* 60ms */
			break;
		case 6:/* 70ms */
			scan_lk_state();
			break;
		case 7:/* 80ms */
			scan_ls_state();
			break;
		case 8:/* 90ms */
			break;
		case 9:/* 100ms */
			mtp_m_rt();
			break;
		case 10:/* 110ms */
			scan_lk_state();
			break;
		case 11:/* 120ms */
			break;
		case 12:/* 130ms */
			break;
		case 13:/* 140ms */
			scan_mtp3_activity();
			break;
		case 14:/* 150ms */
			scan_lk_state();
			break;
		case 15:/* 160ms */
			scan_ls_state();
			break;
		default:
			break;
	}
    mtp_10ms_tick = ((mtp_10ms_tick+1) & 15);

	if (mtp_100ms_tick == 9)
	{
		mtp_100ms_tick = 0;
		mtp_t1s++;
		if (mtp_t1s == 10)/* 1 second */
		{
			mtp_t1s = 0;
			tprc_proc();
			mtp_t10s++;
			send_ip_to_mtp2();
			send_ip_to_mtp2();
			if (mtp_t10s == 10)/* 10 second */
			{
				mtp3_heartbeat.state = 1;
				set_status(MTP3_COMPONENT_ID,MTP3_HB_LEN,(BYTE*)&mtp3_heartbeat.version);
				mtp3_get_time();// get current time
				mtp3_set_csta_p();// set csta portion
				scan_mtp2_activity();
				mtp_t10s = 0;

				if (mtp3lite_listen_fd <= 0)
					mtp3lite_InitServerSocket();
			}
		}
	}
	mtp_100ms_tick ++;

//	outb(ib_b & 0xfd,addr);
}

//These functions is added by Roy Jiang for supporting SCCP dual server redirect
int sccp_redirect(up_message *msgptr)
{
//	BYTE 	len;
	WORD	len;//long message
	BYTE	sio;
	long	route_mark;/* dpc opc sls */
	BYTE	sls;
	long	dpc;
	long	opc;
	BYTE	pclen;
	int		outlink=0;
	long	dest_ip;
	BYTE	*pContent;
	BYTE	nw;

	assert (msgptr->dest_ip != 0xffffffff);
	sio = msgptr->sio & 0xcf;
	dpc = msgptr->dpc;
	opc = msgptr->opc;
	sls = msgptr->cic[0] & 0x0f;
	nw = (sio >> 6) & 3;
	pclen = pc_length(nw);
	len = msgptr->len;
	dest_ip = msgptr->dest_ip;
	outlink = msgptr->link;

	pContent = &mtp3_iprt.io_msg.msgContent[0];
	len = msgptr->len;
	if (pclen == MTP3_24BIT_PC)
	{
		mtp3_iprt.io_msg.msgLength = len + 10 + 1;
		pContent[0] = outlink;
		pContent[1] = (len+8)>>8;
		pContent[2] = (len+8)&0xff;
		pContent[3] = sio;
		memcpy(&pContent[4],&dpc,3);
		memcpy(&pContent[7],&opc,3);
		memcpy(&pContent[10],&msgptr->cic[0],1);
		memcpy(&pContent[11],&msgptr->msgList,len);
	}
	else
	{
		route_mark = (msgptr->cic[0] << 28)+(opc << 14)+dpc;
		pContent[0] = outlink;
		pContent[1] = (len+5)>>8;
		pContent[2] = (len+5)&0xff;
		pContent[3] = sio;
		memcpy(&pContent[4],&route_mark,4);
		memcpy(&pContent[8],&msgptr->msgList,len);
	}
	len = (pContent[1]<<8) +pContent[2];
	if (len < 5 || len >272)
	{
		mtp3ObjState.MTP3WatchDog[10]++;
		mtp3_debug(MTP3DB_ERROR,"[SCCP]USER==>MTP3,LI over range and discarded! LI=%04d,Link=%d",len,outlink);
		mtp3_showbuf(MTP3DB_ERROR,&pContent[0],len + 3);
		S_shm_ptr->SM_Buf.RSub ++;
		mtp3.nw[nw].flow.MtoI_throwed[2]++;
		return 0;
	}

	mtp3.nw[nw].flow.MtoI[2]++;

	mtp3_iprt.io_msg.msgLength = pContent[2]+2+1;
	iptrans_msg_flow(pContent,pclen,MTP_MSG_OTHER_SERVER,dest_ip);
//	send_to_mtp2(dest_ip);
	send_to_mtp2_new_struct(dest_ip);
	return 1;
}

int isup_redirect(up_message *msgptr)
{
	int 	outlink=0;
	WORD  	len;
	BYTE	sio;
	long	route_mark;
	long	dpc;
	BYTE	sls;
	BYTE	pclen;
	BYTE	nw;
	DWORD	dest_ip;
//	BYTE	rSub;
	BYTE	*pContent;

	assert (msgptr->dest_ip != 0xffffffff);
	sio = msgptr->sio & 0xcf;
	dpc = msgptr->dpc;
	sls = msgptr->cic[0] & 0x0f;
	nw = (sio >> 6) & 3;
	pclen = pc_length(nw);
	len = msgptr->len;
	outlink = msgptr->link;
	dest_ip = msgptr->dest_ip;

	pContent = &mtp3_iprt.io_msg.msgContent[0];
	if (pclen == MTP3_24BIT_PC)
	{
		pContent[0] = outlink;
		pContent[1] = (len + 10)>>8;
		pContent[2] = (len + 10)&0xff;
		pContent[3] = sio;
		memcpy(&pContent[4],&dpc,3);
		memcpy(&pContent[7],&msgptr->opc,3);//keep the UP filled opc
		pContent[10] = msgptr->cic[0] & 0x0f;
		memcpy(&pContent[11],&msgptr->cic[0],2);
		memcpy(&pContent[13],&msgptr->msgList,len);
		MTP3_send_isup_count(nw,pContent[13]);
	}
	else
	{
		route_mark = (msgptr->cic[0] << 28)+(msgptr->opc << 14)+dpc;//keep the UP filled opc
		pContent[0] = outlink;
		pContent[1] = (len+7)>>8;
		pContent[2] = (len+7)&0xff;
		pContent[3] = sio;
		memcpy(&pContent[4],&route_mark,4);
		memcpy(&pContent[8],&msgptr->cic,2);
		memcpy(&pContent[10],&msgptr->msgList,len);
		MTP3_send_isup_count(nw,pContent[10]);
	}

	len = (pContent[1]<<8) + pContent[2];
	if (len < 5 || len > 272)
	{
		mtp3ObjState.MTP3WatchDog[14]++;
		mtp3_debug(MTP3DB_ERROR,"[ISUP]USER==>MTP3,LI over range and discarded! LI=%04d,Link=%d",len,outlink);
		mtp3_showbuf(MTP3DB_ERROR,&pContent[0],len + 3);
		I_shm_ptr->IM_Buf.RSub ++;
		mtp3.nw[nw].flow.MtoI_throwed[4]++;
		return 0;
	}

	mtp3.nw[nw].flow.MtoI[4]++;

	mtp3_iprt.io_msg.msgLength = pContent[2]+2+1;
	iptrans_msg_flow(pContent,pclen,MTP_MSG_OTHER_SERVER,dest_ip);
//	send_to_mtp2(dest_ip);
	send_to_mtp2_new_struct(dest_ip);
	return 1;
}

int bicc_redirect(up_message_2 *msgptr)
{
	int 	outlink=0;
	WORD 	len;
	BYTE	sio;
	long	route_mark;
	long	dpc;
	BYTE	sls;
	BYTE	pclen;
	BYTE	*pContent;
	BYTE	nw;
	DWORD	dest_ip;
//	BYTE	rSub;

	assert(msgptr->dest_ip != 0xffffffff);
	sio = msgptr->sio;
	dpc = msgptr->dpc;
	sls = msgptr->cic[0] & 0x0f;
	nw = (sio >> 6) & 3;
	pclen = pc_length(nw);
	len = msgptr->len;
	dest_ip = msgptr->dest_ip;
	outlink = msgptr->link;

	pContent = &mtp3_iprt.io_msg.msgContent[0];
	if (pclen == MTP3_24BIT_PC)
	{
		pContent[0] = outlink;
		pContent[1] = (len + 12)>>8;
		pContent[2] = (len + 12)&0xff;
		pContent[3] = sio;
		memcpy(&pContent[4],&dpc,3);
		memcpy(&pContent[7],&msgptr->opc,3);//keep the UP filled opc
		pContent[10] = msgptr->cic[0] & 0x0f;
		memcpy(&pContent[11],&msgptr->cic[0],4);
		memcpy(&pContent[15],&msgptr->msgList,len);
	}
	else
	{
		route_mark = (msgptr->cic[0] << 28)+(msgptr->opc << 14)+dpc;//keep the UP filled opc
		pContent[0] = outlink;
		pContent[1] = (len+9)>>8;
		pContent[2] = (len+9)&0xff;
		pContent[3] = sio;
		memcpy(&pContent[4],&route_mark,4);
		memcpy(&pContent[8],&msgptr->cic,4);
		memcpy(&pContent[12],&msgptr->msgList,len);
	}
	mtp3.nw[nw].flow.MtoI[4]++;
	mtp3_iprt.io_msg.msgLength = pContent[2]+2+1;
	iptrans_msg_flow(pContent,pclen,MTP_MSG_OTHER_SERVER,dest_ip);
//	send_to_mtp2(dest_ip);
	send_to_mtp2_new_struct(dest_ip);
	return 1;
}
/*@end@*/
