/*	HAE sync function c file	*/
/*	Written by Liu Zhiguo V1.0	*/
/*	Time: 2003-08-08			*/
/*	--------------------------	*/

#include "./include/hae_include.h"

#define	PERIOD_SYNC_TIMEOUT		64 //16
#define	READ_ITEMS_PER_CYCLE	8  //The max readed items per cylce,must<32
#define MAX_WAIT_TIMEOUT		(READ_ITEMS_PER_CYCLE*3)
#define	MAX_RAM_INIT_RETRY		4

const  u32	HLR_OID_PREFIX[11] =   {1,3,6,1,4,1,1373,2,3,3,3};
const  u32	AUC_OID_PREFIX[11] =   {1,3,6,1,4,1,1373,2,3,3,4};
const  u32	EIR_OID_PREFIX[11] =   {1,3,6,1,4,1,1373,2,3,3,8};
static u32	HLR_RAM_OID_PREFIX[13]={1,3,6,1,4,1,1373,2,3,3,3,2,7};
static u32	AUC_RAM_OID_PREFIX[13]={1,3,6,1,4,1,1373,2,3,3,4,2,7};
static u32	EIR_RAM_OID_PREFIX[13]={1,3,6,1,4,1,1373,2,3,3,8,2,7};

static u32	conf_oid[HAE_SYNC_MOD_NUM]={2,2,2};
static u32	sync_ram_oid[HAE_SYNC_MOD_NUM]={7,7,7};

static u32	ramdata_pack_num[HAE_SYNC_MOD_NUM]={0,0,0};		//The Max packets of the Module
static void	*ramshm_ptr[HAE_SYNC_MOD_NUM]={NULL,NULL,NULL};	//Restored the  pointer of the subs shm.
static u8	master_flag[HAE_SYNC_MOD_NUM]={0,0,0};			//0/1=slave/master
static u8	switch_flag[HAE_SYNC_MOD_NUM]={0,0,0};
static u8	period_flag[HAE_SYNC_MOD_NUM]={1,1,1};
static int	sent_pack_no[HAE_SYNC_MOD_NUM]={0,0,0};
static int	no_prd_sync[HAE_SYNC_MOD_NUM]={0,0,0};			// number of period sync
static u8	oid_prefix_len[HAE_SYNC_MOD_NUM]={0,0,0};
static u32	read_start[HAE_SYNC_MOD_NUM]={0,0,0};
static u32	recv_stand[HAE_SYNC_MOD_NUM]={0,0,0};
static u32	recv_flag[HAE_SYNC_MOD_NUM]={0,0,0};

static u8	hae_data_ver[HAE_SYNC_MOD_NUM][3]={{0,0,0},{0,0,0},{0,0,0}};


extern int	hlr_realsync_proc();
extern void hlr_send_psync_proc();
extern void hlr_set_mastermode(); 
extern void hlr_set_slavermode(); 
extern int hlr_recv_psync_proc(u8 oid_len, u32 * oid, u8 * sync_data, u32 data_len, snmp_addr * addr_ptr);
extern void	hlr_upgrade_subs_n_1(void *ptr, void *r_ptr, int file_size);
extern void	hlr_upgrade_subs_n_2(void *ptr, void *r_ptr, int file_size);
extern int	AucSyncNowMsgProc(BYTE OIDLen,DWORD *OID,BYTE *Pdata,u_short DataLen);
extern int	EirSyncNowMsgProc(BYTE OIDLen,DWORD *OID,BYTE *Pdata,u_short DataLen);

int get_weekday(char *wday_buf)
{
    struct tm *t,tt;
    long curr_date;

    t=&tt;
    curr_date=time((long *)0);
    t=localtime(&curr_date);
    if( t == NULL )
    {
    	assert(0 && "syscall: Locatime fail");
    	exit(0);
    }
    sprintf(wday_buf,"%02d", t->tm_wday);
    wday_buf[2]=0;
    return t->tm_wday;
}

void hae_init_sync(u8 fun_mod,u8 oid_len,u32 max_mem,u8 *data_ptr,void *shm_ptr)
{
	u8	i=0;

	oid_prefix_len[fun_mod] = oid_len;

	if((max_mem % HAE_PER_PACK_LEN))
		ramdata_pack_num[fun_mod] = max_mem/HAE_PER_PACK_LEN+1;
	else
		ramdata_pack_num[fun_mod] = max_mem/HAE_PER_PACK_LEN;
	memcpy(&hae_data_ver[fun_mod],data_ptr,3);
	for (i = 0;i < READ_ITEMS_PER_CYCLE;i ++)
		recv_stand[fun_mod] |= (0x01<<i);
	ramshm_ptr[fun_mod] = shm_ptr;
}

int hae_set_master_flag(u8 fun_mod,u8 MasterFlag)
{
	master_flag[fun_mod] = MasterFlag;
	return 1;
}

int hae_get_master_flag(u8 fun_mod)
{
	return master_flag[fun_mod];  
}

int hae_inspect_master(u8 fun_mod)
{
	snmp_pdu    snmp_buf;
	snmp_addr   snmp_add;
  int         i;
  int         recv_count=0;

	switch(fun_mod)
	{
		case HLR_SYNC_MOD:
   			snmp_add.local_port = HLR_SYNC_UDPPORT;
   			for(i = 0;i < 10; i ++)  //add here becase if mss-0 and mss-1 start 
	      {
	          if( snmp_receive(&snmp_buf,&snmp_add) && snmp_buf.var[0].oid[12] == 9  )
		            recv_count++;	    
	      }
			break;
		case AUC_SYNC_MOD:
   			snmp_add.local_port = AUC_SYNC_UDPPORT;
   			if( snmp_receive(&snmp_buf,&snmp_add) )
   			{
   				recv_count = 3;
   			}
			break;
		case EIR_SYNC_MOD:
   			snmp_add.local_port = EIR_SYNC_UDPPORT;
   			if( snmp_receive(&snmp_buf,&snmp_add) )
   			{
   				recv_count = 3;
   			}
			break;
  		default:
			return 0;
	}
	return (recv_count >= 3) ?  1 : 0;
}

int hae_set_period_flag(u8 fun_mod, u8 flag)
{
	if(fun_mod < HAE_SYNC_MOD_NUM)
	{
		period_flag[fun_mod] = flag & 0x01;
		return 1;
	}
	return 0;
}

/*	+++++++++++++++++++++++++++++++++++++++++++++++++++++++	*/
/*	Receive	real time sync and periodic sync				*/
/*	Real time sync proc must be implemented by application	*/
/*	+++++++++++++++++++++++++++++++++++++++++++++++++++++++	*/
void hae_sync_msg_proc(u8 fun_mod)	// hae sync message process
{
	int			periodic_flag[HAE_SYNC_MOD_NUM]={0,0,0};
	void		*ptr;
	int			i;
	int			instance=0,data_type;
	snmp_pdu	snmp_buf;
	snmp_addr	snmp_add;
	var_list	*varptr=NULL;
	u32			master_ip = hae_get_localip();

	switch(fun_mod)
	{
		case HLR_SYNC_MOD:
   			snmp_add.local_port = HLR_SYNC_UDPPORT;
			break;
		case AUC_SYNC_MOD:
   			snmp_add.local_port = AUC_SYNC_UDPPORT;
			break;
		case EIR_SYNC_MOD:
   			snmp_add.local_port = EIR_SYNC_UDPPORT;
			break;
  		default:
			return;
	}
	for(i = 0;i < ramdata_pack_num[fun_mod];i ++)
	{
		if (!snmp_receive(&snmp_buf,&snmp_add))
			break;
		varptr = &snmp_buf.var[0];
		data_type = varptr->oid[12];
		switch(data_type)
		{
			case 2:
				switch(varptr->oid[10])
				{
				case 3://real sync message for HLR
					hlr_realsync_proc(varptr->oidlen,varptr->oid,varptr->msg,varptr->msglen,&snmp_add);
					break;
				case 4://Auc real sync message
					#ifdef _MODIFY_AUC   
					AucSyncNowMsgProc(varptr->oidlen,varptr->oid,varptr->msg,varptr->msglen);
					#endif
					break;
				case 8://Eir real sync message
					#ifdef _MODIFY_EIR      
					EirSyncNowMsgProc(varptr->oidlen,varptr->oid,varptr->msg,varptr->msglen);
					#endif
					break;
				}
				break;
/*			case 3: //real sync message for AUC/EIR
				switch(fun_mod)
				{
					case AUC_SYNC_MOD: //Auc real sync message	
						#ifdef _MODIFY_AUC   
						AucSyncNowMsgProc(varptr->oidlen,varptr->oid,varptr->msg,varptr->msglen);
						#endif
						break;
					case EIR_SYNC_MOD: //Eir real sync message	  
						#ifdef _MODIFY_EIR      
						EirSyncNowMsgProc(varptr->oidlen,varptr->oid,varptr->msg,varptr->msglen);
						#endif
						break;
				}
				break;
			case 6: //real sync message for HLR
				hlr_realsync_proc(varptr->oidlen,varptr->oid,varptr->msg,varptr->msglen,&snmp_add);
				break;*/
			case 7 ://periodic sync message AUC EIR		
				if( fun_mod != HLR_SYNC_MOD )
				{
					  /*
					  master_ip = snmp_add.remote_ip; 
				    periodic_flag[fun_mod] = 1;
					  instance = varptr->oid[13];
				    if(instance >= ramdata_pack_num[fun_mod]) 
					    continue;
				    if (varptr->msglen != HAE_PER_PACK_LEN)
					    continue;
				
				    ptr = (void *) ramshm_ptr[fun_mod];
				    memcpy(ptr+instance*HAE_PER_PACK_LEN,varptr->msg,HAE_PER_PACK_LEN);
				    */ 
		    }
		    break;
		  case 9: //periodic sync message HLR
				if( fun_mod == HLR_SYNC_MOD )
				{
					  master_ip = snmp_add.remote_ip; 
				    periodic_flag[fun_mod] = 1;
				    //printf( "hlr recv periodic sync\n");
				    hlr_recv_psync_proc(varptr->oidlen,varptr->oid,varptr->msg,varptr->msglen,&snmp_add);
				}
				break;
		}
	}
	
	if (periodic_flag[fun_mod])
	{
		if (master_flag[fun_mod] && master_ip < hae_get_localip())
		{
			master_flag[fun_mod] = 0;
			if( fun_mod == HLR_SYNC_MOD )
			{
				//printf( "hlr set to slaver\n");
				hlr_set_slavermode();
			}
		}
		no_prd_sync[fun_mod] = 0;
	}
	else if(no_prd_sync[fun_mod]++ > PERIOD_SYNC_TIMEOUT)
	{
		master_flag[fun_mod] = 1;
		if( fun_mod == HLR_SYNC_MOD )
		{
			  //printf( "hlr set to master\n");
				hlr_set_mastermode();
		}
	}
}

/*	+++++++++++++++++++++++++++++++++++++++++++++++++++++++	*/
/*	Called by every applicatoin								*/
/*	Receive sync message(real and periodic), and			*/
/*	send periodic sync message if it acts as master server	*/
/*	+++++++++++++++++++++++++++++++++++++++++++++++++++++++	*/
void hae_syncdata_proc(u8 fun_mod)
{
	void		*ptr;
	snmp_pdu	snmp_buf;
	snmp_addr	snmp_add;
	var_list	*varlist = NULL;
  
  //printf("psync proc\r\n");
	hae_sync_msg_proc(fun_mod);		//receive sync message
  if(!master_flag[fun_mod])
		return;
	if((switch_flag[fun_mod]++) & 0x01)
		return;
	if(!period_flag[fun_mod])
		return;
	//send periodic sync message
	snmp_buf.pdu_type = 0x07; //trap
	snmp_buf.var_num = 0x01;
	varlist = snmp_buf.var;
	varlist->oidlen = oid_prefix_len[fun_mod]+2+1;
	varlist->vartype = 0x04;
	switch(fun_mod)
	{
		case HLR_SYNC_MOD:
		    snmp_add.remote_port = HLR_SYNC_UDPPORT;
			snmp_add.local_port = HLR_SYNC_UDPPORT;
			memcpy(&varlist->oid,HLR_OID_PREFIX,oid_prefix_len[fun_mod]*sizeof(u32));
			break;
		case AUC_SYNC_MOD:
		    snmp_add.remote_port = AUC_SYNC_UDPPORT;
			snmp_add.local_port  = AUC_SYNC_UDPPORT;
			memcpy(&varlist->oid,AUC_OID_PREFIX,oid_prefix_len[fun_mod]*sizeof(u32));
			break;
		case EIR_SYNC_MOD:
		  snmp_add.remote_port = EIR_SYNC_UDPPORT;
			snmp_add.local_port  = EIR_SYNC_UDPPORT;
			memcpy(&varlist->oid,EIR_OID_PREFIX,oid_prefix_len[fun_mod]*sizeof(u32));
			break;
	}
	if( fun_mod == HLR_SYNC_MOD )
	{
		hlr_send_psync_proc();
		//printf( "hlr send periodic sync\n");
		return ;
	}

	snmp_add.remote_ip = hae_get_peerip();
	snmp_add.local_ip = hae_get_localip();
	snmp_add.broadcast = 0x00;
	varlist->oid[oid_prefix_len[fun_mod]] = conf_oid[fun_mod]; //configuration
	varlist->oid[oid_prefix_len[fun_mod]+1] = sync_ram_oid[fun_mod]; //sync ram
	varlist->oid[13] = sent_pack_no[fun_mod]; //account_db
	varlist->msglen  = HAE_PER_PACK_LEN;//single packet,unit:KB
	ptr = (void *)ramshm_ptr[fun_mod];
	memcpy(varlist->msg,ptr+sent_pack_no[fun_mod]*HAE_PER_PACK_LEN,HAE_PER_PACK_LEN);
	snmp_send(&snmp_buf,&snmp_add);
	sent_pack_no[fun_mod] ++;
	sent_pack_no[fun_mod] %= ramdata_pack_num[fun_mod];
}

int cmp_data_ver(u8 fun_mod,u8 *src_ptr)
{
	if(!memcmp(hae_data_ver[fun_mod],src_ptr,3))
		return 1;
	return 0;
}

/* The procedure is called back when peer data comes in SNMP GET RESP */
int hae_load_from_peer_resp(u8 fun_mod,snmp_pdu *pdu,snmp_addr *addr)
{
   //static int  LastInstance[HAE_SYNC_MOD_NUM]={0,0,0};
	int		instance=0,tmp_val=0;
	void	*ptr;

   /*
	if(LastInstance[fun_mod] && (LastInstance[fun_mod]+1) != (instance)){
		return 0;
	}
	LastInstance[fun_mod]=instance;
   */
	if (pdu->var[0].oid[12] != 7)	// do not ram data
		return 0;
	instance = pdu->var[0].oid[13]; //for init
	if (instance >= ramdata_pack_num[fun_mod])
		return 0;
	if (pdu->var[0].msglen != HAE_PER_PACK_LEN)
		return 0;
	tmp_val = instance - read_start[fun_mod];
	if (0 <= tmp_val && READ_ITEMS_PER_CYCLE > tmp_val)
		recv_flag[fun_mod] |= (0x01 << tmp_val);
	else
		return 0;
	ptr = (void *)ramshm_ptr[fun_mod];
	memcpy(ptr+instance*HAE_PER_PACK_LEN,pdu->var[0].msg,HAE_PER_PACK_LEN);
	if (0 == instance)
	{//check data version
		if (!cmp_data_ver(fun_mod,(u8 *)ptr))
		{
			memset((u8 *)ptr,0,HAE_PER_PACK_LEN);
			return 0;	// load fail
		}
	}
	return 1;
}

/* Use SNMP GET to load user data from peer server, and wait response */
int hae_load_from_peer(u8 fun_mod)
{//calling during init procedure
	snmp_pdu		snmp_buf;
	snmp_addr		snmp_add;
	var_list		*varlist = NULL;
	static int		read_pack_no[HAE_SYNC_MOD_NUM]={0,0,0};
	static int		read_state[HAE_SYNC_MOD_NUM]={0,0,0};
	static int		try_times[HAE_SYNC_MOD_NUM]={0,0,0};
	static int		reread_times[HAE_SYNC_MOD_NUM]={0,0,0};
	static u8		max_read_item[HAE_SYNC_MOD_NUM]={0,0,0};
//	int		retval = _LOADING_DATA;
	int				i=0,oid_len=0;

	switch(read_state[fun_mod])
	{
		case 0: //send request
			if (read_pack_no[fun_mod] >= ramdata_pack_num[fun_mod])
			{  //init over
				read_state[fun_mod] = 0;
				try_times[fun_mod] = 0;
				reread_times[fun_mod] = 0;
				read_pack_no[fun_mod] = 0;
				return 2;	// load success
			}
			snmp_buf.pdu_type = 0;		// snmp get
			snmp_buf.var_num = 0x01;
//			snmp_add.remote_ip = PeerIp[fun_mod];
			snmp_add.remote_ip = hae_get_peerip();
			snmp_add.remote_port = HAE_AGENT_UDPPORT;
			snmp_add.local_ip = hae_get_localip();
			snmp_add.local_port = HAE_AGENT_UDPPORT;
			snmp_add.broadcast = 0x00;
			varlist = &snmp_buf.var[0];
			switch(fun_mod)
			{
				case HLR_SYNC_MOD:
					oid_len = sizeof(HLR_RAM_OID_PREFIX)/sizeof(u32);
					memcpy(&varlist->oid,HLR_RAM_OID_PREFIX,oid_len*4);
					break;
				case AUC_SYNC_MOD:
					oid_len=sizeof(AUC_RAM_OID_PREFIX)/sizeof(u32);
					memcpy(&varlist->oid,AUC_RAM_OID_PREFIX,oid_len*4);
					break;
				case EIR_SYNC_MOD:
					oid_len=sizeof(EIR_RAM_OID_PREFIX)/sizeof(u32);
					memcpy(&varlist->oid,EIR_RAM_OID_PREFIX,oid_len*4);
					break;
			}
			varlist->oidlen = oid_len+1;
			varlist->vartype = 0x04;
			varlist->msglen  = 0;
			if (ramdata_pack_num[fun_mod] >= (read_pack_no[fun_mod]+READ_ITEMS_PER_CYCLE))
				max_read_item[fun_mod] = READ_ITEMS_PER_CYCLE;
			else
				max_read_item[fun_mod] = ramdata_pack_num[fun_mod]-read_pack_no[fun_mod];
			read_start[fun_mod] = read_pack_no[fun_mod];
			for (i = 0;i < max_read_item[fun_mod];i ++)
			{
				recv_stand[fun_mod] |= (0x01<<i);
				varlist->oid[oid_len] = read_pack_no[fun_mod] + i;
				snmp_send(&snmp_buf,&snmp_add);
			}
			read_state[fun_mod] = 1;
			try_times[fun_mod] = 0;
			recv_flag[fun_mod] = 0;
			break;
		case 1: //wait response
			if(recv_flag[fun_mod] == recv_stand[fun_mod])
			{
				try_times[fun_mod] = 0;
				read_state[fun_mod] = 0;
				reread_times[fun_mod] = 0;
				recv_flag[fun_mod] = 0;
				recv_stand[fun_mod] = 0;
				read_pack_no[fun_mod] += max_read_item[fun_mod];
			}
			else if (try_times[fun_mod]++ >= MAX_WAIT_TIMEOUT*5)
			{
				read_state[fun_mod] = 0;
				try_times[fun_mod] = 0;
//				recv_flag[fun_mod] = 0;
//				recv_stand[fun_mod] = 0;
				if(reread_times[fun_mod]++ >= MAX_RAM_INIT_RETRY)
				{
					reread_times[fun_mod] = 0;
					read_pack_no[fun_mod] = 0;
					printf("Load data form peer timeout\n");
					return 0;
				}
			}
			break;
		default:
			read_state[fun_mod] = 0;
			break;
	}
	return 1;	// load data
}

/* The procedure is called when peer server request loading data */
int hae_peerdata_resp(u8 fun_mod,u8 oidLen,u32 *oid,u8 *pdata,u8 *vartype)
{	// Response the Peer's reading request
	u32		instance;
	void	*ptr;

   //instance = oid[13];
	instance = oid[oidLen-1];
	*vartype = 0x04;
	if (instance >= ramdata_pack_num[fun_mod])
		return 0;
	ptr = (void *)ramshm_ptr[fun_mod];
	memcpy(pdata,ptr+instance*HAE_PER_PACK_LEN,HAE_PER_PACK_LEN);
	return HAE_PER_PACK_LEN;
}

int hae_load_from_local(u8 fun_mod,char *file_name)
{
	int		i;
	FILE	*fp=NULL;
	void	*r_ptr;
	void	*ptr=(void *)ramshm_ptr[fun_mod];
	struct stat	fileinfo;
	
	
	if((fp = fopen(file_name, "r")) == NULL)
		return 0;
	if(fun_mod == HLR_SYNC_MOD)
	{
		stat(file_name, &fileinfo);
		r_ptr = malloc(fileinfo.st_size);
		if( r_ptr == NULL )
		{
		    assert(0 && "syscall: malloc fail");
    	    exit(0);
		}
		fread(r_ptr, fileinfo.st_size, 1, fp);
//		if((hae_data_ver[HLR_SYNC_MOD][0] == ((u8 *)r_ptr)[0]) &&(hae_data_ver[HLR_SYNC_MOD][1] == ((u8 *)r_ptr)[1]))
//		{
//			if(fileinfo.st_size <= ramdata_pack_num[HLR_SYNC_MOD]*HAE_PER_PACK_LEN)
//				memcpy(ptr, r_ptr, fileinfo.st_size);
//			else
//				memcpy(ptr, r_ptr, ramdata_pack_num[HLR_SYNC_MOD]*HAE_PER_PACK_LEN);
//		}
//		if((hae_data_ver[HLR_SYNC_MOD][0] == ((u8 *)r_ptr)[0]) &&(hae_data_ver[HLR_SYNC_MOD][1] == ((u8 *)r_ptr)[1]))
//		if(hae_data_ver[HLR_SYNC_MOD][1] == ((u8 *)r_ptr)[1])
//		{
			if(fileinfo.st_size <= ramdata_pack_num[HLR_SYNC_MOD]*HAE_PER_PACK_LEN)
				memcpy(ptr+1024, r_ptr+1024, fileinfo.st_size-1024);
			else
				memcpy(ptr+1024, r_ptr+1024, ramdata_pack_num[HLR_SYNC_MOD]*HAE_PER_PACK_LEN-1024);
//		}
//		else if(hae_data_ver[HLR_SYNC_MOD][0] == ((u8 *)r_ptr)[0])
//		{
//			switch(hae_data_ver[HLR_SYNC_MOD][1] - ((u8 *)r_ptr)[1])
//			{
//				case 1:
//					hlr_upgrade_subs_n_1(ptr, r_ptr, fileinfo.st_size);
//					break;
//				case 2:
//					hlr_upgrade_subs_n_2(ptr, r_ptr, fileinfo.st_size);
//					break;
//				default:
//					printf("Failed to upgrade subscriber data\n");
//					break;
//			}
//		}
		free(r_ptr);
	}
	else
	{
		for (i = 0;i < ramdata_pack_num[fun_mod];i ++)
		{
			fread(ptr+i*HAE_PER_PACK_LEN,HAE_PER_PACK_LEN,1,fp);
	//		if(i == 0)
	//		{//check data version
	//			if(!cmp_data_ver(fun_mod,(u8 *)ptr))
	//			{
	//				memset((u8 *)ptr,0,HAE_PER_PACK_LEN);
	//				fclose(fp);
	//				return 0;
	//			}
	//		}
		}
	}
	fclose(fp);
	return 2;		// load success
}

void hae_tftp_read_req(u16 portno,char *filename)
{
	int			filename_len;
	char		readmode[20] = "octetoblksizeo1024";
	_msg_list	ipmsg;

	filename_len = strlen(filename);
	ipmsg.msgSrcPort = portno;
	ipmsg.msgSrcIP   = hae_get_localip();
	ipmsg.msgDstPort = 69; //TFTP_PORT;
	ipmsg.msgDstIP   = hae_get_primomcip();
	ipmsg.msgBroadcast  = 0x00;
	ipmsg.msgContent[0] = 0;
	ipmsg.msgContent[1] = 1; //read request
	memcpy(ipmsg.msgContent+2,filename,filename_len);
	memcpy(ipmsg.msgContent+filename_len+3,readmode,18);
	ipmsg.msgContent[filename_len+2] = 0;
	ipmsg.msgContent[filename_len+8] = 0;
	ipmsg.msgContent[filename_len+16] = 0;
	ipmsg.msgContent[filename_len+21] = 0;
	ipmsg.msgLength = filename_len+22;
	iptrPutMessage(ipmsg);
}

int hae_tftp_read_data(u8 fun_mod,u16 portno,u8 *databuf)
{
	static int	readblocknum[HAE_SYNC_MOD_NUM] = {0};
	static int	proc_len[HAE_SYNC_MOD_NUM] = {0};
	static int	try_timer[HAE_SYNC_MOD_NUM] = {0};
	static int	try_times[HAE_SYNC_MOD_NUM] = {0};
	static int	tftp_read_port = 69;	// TFTP port for OMC response
	int			ackblocknum;
	int			retval=0;
	_msg_list	ipmsg,ipack;

	if (iptrGetMessage(&ipmsg,portno))
	{
		try_timer[fun_mod] = 0;
		try_times[fun_mod] = 0;
		switch (ipmsg.msgContent[1])
		{
			case 3:	// response
				ackblocknum = ipmsg.msgContent[2]*256+ipmsg.msgContent[3];
				proc_len[fun_mod] += ipmsg.msgLength - 4;
				if(ackblocknum == readblocknum[fun_mod]+1)
					readblocknum[fun_mod] = ackblocknum;
				else if(ackblocknum == 0)
				{
					if(readblocknum[fun_mod] == 0xffff)
						readblocknum[fun_mod] = 0;
				}
				memcpy(databuf,ipmsg.msgContent,ipmsg.msgLength); //length
				retval = ipmsg.msgLength;
				// read next package
				ipack.msgLength = 4;
				ipack.msgContent[0] = 0x00;
				ipack.msgContent[1] = 0x04;
				ipack.msgContent[2] = ackblocknum >> 8;
				ipack.msgContent[3] = ackblocknum;
				ipack.msgSrcIP = hae_get_localip();
				ipack.msgSrcPort = TFTP_SRVC_PORT;
				ipack.msgDstPort = ipmsg.msgSrcPort;
				ipack.msgDstIP = hae_get_primomcip();
				iptrPutMessage(ipack);
				tftp_read_port = ipmsg.msgSrcPort;
				break;
			case 6:	// the first package response
				proc_len[fun_mod] = 0;
				readblocknum[fun_mod] = 0;
				ipack.msgLength = 4;
				ipack.msgContent[0] = 0x00;
				ipack.msgContent[1] = 0x04;
				ipack.msgContent[2] = readblocknum[fun_mod]>>8;
				ipack.msgContent[3] = readblocknum[fun_mod];
				ipack.msgSrcIP = hae_get_localip();
				ipack.msgSrcPort = TFTP_SRVC_PORT;
				ipack.msgDstPort = ipmsg.msgSrcPort;
				ipack.msgDstIP = hae_get_primomcip();
				iptrPutMessage(ipack);
				tftp_read_port = ipmsg.msgSrcPort;
				break;
			default:
				printf("Error!\n");
				break;
		}
	}
	else	// do not receive response package
	{
		if (try_timer[fun_mod]++ > MAX_RAM_INIT_RETRY)
		{
			try_timer[fun_mod] = 0;
			if (try_times[fun_mod]++ > MAX_RAM_INIT_RETRY)
				return -1;
			if (tftp_read_port == 69)	// the request package is not response
				return -1;
			// resend the unreceived package
			ipack.msgLength = 4;
			ipack.msgContent[0] = 0x00;
			ipack.msgContent[1] = 0x04;
			ipack.msgContent[2] = readblocknum[fun_mod]>>8;
			ipack.msgContent[3] = readblocknum[fun_mod];
			ipack.msgSrcIP = hae_get_localip();
			ipack.msgSrcPort = TFTP_SRVC_PORT;
			ipack.msgDstPort = tftp_read_port;
			ipack.msgDstIP = hae_get_primomcip();
			iptrPutMessage(ipack);
		}
	}
	return retval;
}

int hae_load_from_omc(u8 fun_mod)
{
	static int	tftp_state[HAE_SYNC_MOD_NUM] = {0};
	void	*ptr;
	int		blocknum = 0,length = 0;
	char	filename[18] = {0};
	u8		databuf[1024] = {0};
	u8		wday = 0,tmp_buf[3] = {0};

	switch(tftp_state[fun_mod])
	{
		case 0:
			wday = (get_weekday(tmp_buf)+7-1) % 7;
			switch(fun_mod)
			{
				case HLR_SYNC_MOD:
					sprintf(filename,"hlr_backup%02d.dat",wday);
					break;
				case AUC_SYNC_MOD:
					sprintf(filename,"auc_backup%02d.dat",wday);
					break;
				case EIR_SYNC_MOD:
					sprintf(filename,"eir_backup%02d.dat",wday);
					break;
			}
			hae_tftp_read_req(TFTP_SRVC_PORT,filename);
			tftp_state[fun_mod] = 1;
			break;
		case 1:
			length = hae_tftp_read_data(fun_mod,TFTP_SRVC_PORT,databuf);
			if (length == -1)
			{
				printf("read from omc timeout\n");
				return 0;		// load fail
			}
			else if(length >= 4)
			{
				blocknum = databuf[2] * 256 + databuf[3];
//				if(blocknum>=ramdata_pack_num[fun_mod])
//					continue;
				ptr = (void *)ramshm_ptr[fun_mod];
				memcpy(ptr+(blocknum-1)*HAE_PER_PACK_LEN,databuf+4,length-4);  //length is variable
//				if (blocknum == 1)
//				{//check data version
//					if(!cmp_data_ver(fun_mod,(u8 *)ptr))
//					{
//						memset((u8 *)ptr,0,HAE_PER_PACK_LEN);
//						return 0;
//					}
//				}
				if (blocknum == ramdata_pack_num[fun_mod])
					return 2;		// load succcess
			}
			break;
		default:
			break;
	}
	return 1;		// just load data
}

int hae_tftp_write_req(int portno,char *filename)
{
	int			retval=1,filename_len;
	char		writemode[20]="octetoblksizeo1024";
	_msg_list	ipmsg;

	filename_len = strlen(filename);

	ipmsg.msgSrcPort = portno;
	ipmsg.msgSrcIP   = hae_get_localip();
	ipmsg.msgDstPort = 69; //TFTP_PORT;
	ipmsg.msgDstIP   = hae_get_primomcip();
	ipmsg.msgBroadcast  = 0x00;
	ipmsg.msgContent[0] = 0;
	ipmsg.msgContent[1] = 2; //write request
	memcpy(&ipmsg.msgContent[2],filename,filename_len);
	memcpy(&ipmsg.msgContent[filename_len+3],writemode,18);
	ipmsg.msgContent[filename_len+2] = 0;
	ipmsg.msgContent[filename_len+8] = 0;
	ipmsg.msgContent[filename_len+16] = 0;
	ipmsg.msgContent[filename_len+21] = 0;
	ipmsg.msgLength = filename_len+22;
	iptrPutMessage(ipmsg);
	return retval;
}

int hae_tftp_write_data(u8 fun_mod)
{
	int			retval = 0;
	static int	blocknum[HAE_SYNC_MOD_NUM]={1,1,1};
	static int	ackblocknum[HAE_SYNC_MOD_NUM]={0,0,0};
	static int	try_times[HAE_SYNC_MOD_NUM]={0,0,0};
	static int	resend_times[HAE_SYNC_MOD_NUM]={0,0,0};
	_msg_list	ipmsg,ipsend;
	void		*ptr = (void *)ramshm_ptr[fun_mod];


	if(iptrGetMessage(&ipmsg,TFTP_SRVC_PORT))
	{
		if(ipmsg.msgContent[1] == 4)
		{
			ackblocknum[fun_mod] = ipmsg.msgContent[2]*256+ipmsg.msgContent[3];
		 //printf("ack:%d, real:%d\n",ackblocknum[fun_mod],blocknum[fun_mod]);
			if (ackblocknum[fun_mod] == blocknum[fun_mod])
			{
				if (blocknum[fun_mod]++ >= ramdata_pack_num[fun_mod])
				{
					blocknum[fun_mod] = 0;
					ackblocknum[fun_mod] = 0;
					try_times[fun_mod] = 0;
					resend_times[fun_mod] = 0;
					return 1;
				}
			}
		}
		else if (ipmsg.msgContent[1] == 5)
			return -2;
		else if (ipmsg.msgContent[1] == 6)
			blocknum[fun_mod] = 1;

		ipsend.msgSrcIP = hae_get_localip();
		ipsend.msgSrcPort = TFTP_SRVC_PORT;
		ipsend.msgDstPort = ipmsg.msgSrcPort;
		ipsend.msgDstIP = ipmsg.msgSrcIP;
		ipsend.msgLength = 4 + 1024;
		ipsend.msgContent[0] = 0x00;
		ipsend.msgContent[1] = 0x03;
		ipsend.msgContent[2] = blocknum[fun_mod]>>8;
		ipsend.msgContent[3] = blocknum[fun_mod];
		memcpy(&ipsend.msgContent[4],ptr+(blocknum[fun_mod]-1)*HAE_PER_PACK_LEN,HAE_PER_PACK_LEN);
		iptrPutMessage(ipsend);
		resend_times[fun_mod] = 0;
	}
	else if(try_times[fun_mod]++ > MAX_WAIT_TIMEOUT)
	{
		
		try_times[fun_mod]=0;
		
		if(resend_times[fun_mod]++ >= MAX_RAM_INIT_RETRY)
		{
			resend_times[fun_mod] = 0;
			blocknum[fun_mod] = 0;
			ackblocknum[fun_mod] = 0;
			retval = -1;
		}
		else if( blocknum[fun_mod] )
		{
			ipsend.msgSrcIP = hae_get_localip();
			ipsend.msgSrcPort = TFTP_SRVC_PORT;
			ipsend.msgDstPort = ipmsg.msgSrcPort;
			ipsend.msgDstIP = ipmsg.msgSrcIP;
			ipsend.msgLength = 4 + 1024;
			ipsend.msgContent[0] = 0x00;
			ipsend.msgContent[1] = 0x03;
			ipsend.msgContent[2] = blocknum[fun_mod]>>8;
			ipsend.msgContent[3] = blocknum[fun_mod];
			memcpy(&ipsend.msgContent[4],ptr+(blocknum[fun_mod]-1)*HAE_PER_PACK_LEN,HAE_PER_PACK_LEN);
			iptrPutMessage(ipsend);
		}
	}
	return retval;
}

int hae_back_to_omc(u8 fun_mod)
{
	int			retval = 0;
	static int	back_state[HAE_SYNC_MOD_NUM]={0};
   	char		filename[32];
	u8			tmp_buf[3]={0};

	switch(fun_mod)
	{
		case HLR_SYNC_MOD:
			sprintf(filename,"hlr_backup%02d.dat",get_weekday(tmp_buf));
			break;
		case AUC_SYNC_MOD:
			sprintf(filename,"auc_backup%02d.dat",get_weekday(tmp_buf));
			break;
		case EIR_SYNC_MOD:
			sprintf(filename,"eir_backup%02d.dat",get_weekday(tmp_buf));
			break;
	}
	switch(back_state[fun_mod])
	{
		case 0:
			if(hae_tftp_write_req(TFTP_SRVC_PORT,filename))
				back_state[fun_mod] = 1;
		 	break;
		case 1:
			if((retval = hae_tftp_write_data(fun_mod)))
				back_state[fun_mod] = 0;
			break;
		default:
			break;
	}
	return retval;
}


int hae_get_syncpercent( u8 fun_mod , u8 oidLen, u32 *oid )
{
	 int	instance=0;	 
	 int    last_instance = ramdata_pack_num[fun_mod] - ramdata_pack_num[fun_mod]%READ_ITEMS_PER_CYCLE;
	 
	 if ( oidLen != 13 && oid[12] != 7)	// do not ram data
		return -1;
	 
	 instance = oid[oidLen-1];
	 
	 if (instance >= ramdata_pack_num[fun_mod] || !last_instance)
		 return -1;
		 
	 instance = (instance*10000/last_instance) ;
	 instance = (instance > 9999) ? 0 : instance;
	 
	 return instance;
}




