#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <termio.h>
#include <sys/stat.h>
#include <sys/io.h>
#include <sys/utsname.h>

#include "include/wxc2ver.h"
#include "../../plat/snmp/src/include/snmp.h"
#include "../../plat/public/src/include/license_id.h"
#include "../../plat/tcap/src/include/tcap_public.h"
#include "../../plat/radius/src/include/radius.h"
#include "../../plat/tcp/src/include/tcp_if.h"


#define MAX_FUNCTION_ID	16
#define MAX_APP_FUNC_ID	16
#define MAX_License_ID	(MAX_FUNCTION_ID+MAX_APP_FUNC_ID)

extern unsigned int wxc2_get_shm_offset();

typedef enum _WXC2_LICENSE_DIR
{
	BOTH_IN_DE_CREASABLE,
	ONLY_INCREASABLE,
	ONLY_DECREASABLE,
}WXC2_LICENSE_DIR;

typedef struct _wxc2_license_vadility
{
	char name[16];		/* name of the module or function */
	int	maxValue;		/* max value of the license, the minimum is 0 */
	int	step;			/* step of license, each modification should be X*step */
	int	dir;			/* how to modify the license, 0=can increase or decrease, 
						  1=only increase, 2=only decrease */
}wxc2_license_vadility;

wxc2_license_vadility wxc2_license_rule[MAX_License_ID]=
{
	{"MSC TRUNKS",1024,1,ONLY_INCREASABLE},
	{"HLR USERS",100000,100,ONLY_INCREASABLE},
	{"VLR USERS",100000,100,ONLY_INCREASABLE},
	{"AUC USERS",100000,100,ONLY_INCREASABLE},
	{"EIR USERS",100000,100,ONLY_INCREASABLE},
	{"PPS USERS",100000,100,ONLY_INCREASABLE},
	{"SMSC USERS",100000,100,ONLY_INCREASABLE},
	{"MNP USERS",100000,100,ONLY_INCREASABLE},
	{"SMEG USERS",100000,100,ONLY_INCREASABLE},
	{"OPPS USERS",100000,100,ONLY_INCREASABLE},
	{"PALIM USERS",100000,100,ONLY_INCREASABLE},
	{"Mesh HLR",100000,100,ONLY_INCREASABLE},
	{"RMC",100000,100,ONLY_INCREASABLE},
	{"",100000,100,ONLY_INCREASABLE},
	{"",100000,100,ONLY_INCREASABLE},
	{"",100000,100,ONLY_INCREASABLE},
	
	{"GPRS",1,1,BOTH_IN_DE_CREASABLE},
	{"USSD",1,1,BOTH_IN_DE_CREASABLE},
	{"ISUP",1,1,BOTH_IN_DE_CREASABLE},
	{"BICC",1,1,BOTH_IN_DE_CREASABLE},
	{"AIF",1,1,BOTH_IN_DE_CREASABLE},
	{"MGC",1,1,BOTH_IN_DE_CREASABLE},
	{"CAP",1,1,BOTH_IN_DE_CREASABLE},
	{"OPPS_OPR",1,1,BOTH_IN_DE_CREASABLE},
	{"OPPS_IMDM",1,1,BOTH_IN_DE_CREASABLE},
	{"ISDN",1,1,BOTH_IN_DE_CREASABLE},
	{"SIP",1,1,BOTH_IN_DE_CREASABLE},
	{"RLS",1,1,BOTH_IN_DE_CREASABLE},
	{"",1,1,BOTH_IN_DE_CREASABLE},
	{"",1,1,BOTH_IN_DE_CREASABLE},
	{"",1,1,BOTH_IN_DE_CREASABLE},
	{"",1,1,BOTH_IN_DE_CREASABLE}
};

//extern int mnpf_exit(int flag);
//extern int mnpf_timer();
//extern int mnpf_init(int capability, int sysID, u_long local_ip,u_long peer_ip,char *sn);
extern void debug_change_title1();

u32	WXC2_OID_PREFIX[]={1,3,6,1,4,1,1373,2,3,3,99};

static	BYTE app_state = 0, sub_state=0;

#define SYS_IT_INTERVAL_SEC 0

#define ES4_IT_INTERVAL_USEC (9*1000)
#define CENTOS_IT_INTERVAL_USEC (10*1000)               // actually it's 10 ms interval, but should set timer to 9 ms on ES4
#define APP_CYCLE               10

#define DEFAULT_USERS		(100000+1)

#define MAX_APP_NUM		16
#define MAX_LICENSE_TYPE	255

#define WXC2_SHM_KEY		0x90010000
#define	 WXC2_SHM_PERM		0777

#define	 MAX_DELAY_TIME		2000

char	app_name[MAX_APP_NUM][8]={
	"MSC",
	"HLR",
	"VLR",
	"AUC",
	"EIR",
	"PPS",
	"SMSC",
	"MNP",
	"SMEG"
	"OPPS",
	"PALIM",
	"MC",
	"RMC",
	"",
	"",
	"",
};


enum _SYS_LIST{
	MSC_,
	HLR_,
	VLR_,
	AUC_,
	EIR_,
	PPS_,
	SMSC_,
	MNPF_,
	SMEG_,
	OPPS_,
	PALIM_,
	MC_,
	RMC_
};

enum _WXC2_STATE{
	WXC2_STARTUP,
	WXC2_INITRAM,
	WXC2_PRIV,
	WXC2_NORMAL,
};

enum _WXC2_SYSTTYPE{
	WXC2_SYSTYPE_UNIB,
	WXC2_SYSTYPE_X40,
	WXC2_SYSTYPE_X100,
};

char	systemTypeName[3][8]={
	"NIB",
	"X40",
	"X100"};
	
/* index=MSC,HLR,PPS,AUC,EIR , from 0 */
/* old one
struct _wxc2_param
{
	int systemType;
	char segmentFaultCommand[128];
	int register_flag[MAX_APP_NUM];
	int max_users[MAX_APP_NUM];
	char serialNumber[16];
	unsigned char HDSerialNumber[256];
	char license_flag[MAX_APP_NUM];
	u_char license_date[3]; // year(0-99),month,day
	unsigned char userBcdLicense[MAX_LICENSE_TYPE][8];
	unsigned int userIntLicense[MAX_LICENSE_TYPE];
	unsigned char HDSerialNumber1[256];
}wxc2_param,tmpParam;
*/

/* new one */
struct _wxc2_param
{
	char serialNumber[16];
	int systemType;
	u_char license_date[3]; /* year(0-99),month,day */
	int register_flag[MAX_APP_NUM];
	int max_users[MAX_APP_NUM];
	unsigned char HDSerialNumber[2][256];
	unsigned char userBcdLicense[MAX_LICENSE_TYPE][8];
	unsigned int userIntLicense[MAX_LICENSE_TYPE];
}wxc2_param,tmpParam;

static int sys_timer10ms=0;
static int systemID=0,systemInited=0;
static int shutDownCommand = 0,endflag=0;
static int wxc2_main_state = WXC2_STARTUP;
static int wxc2_startup_state = VLR_;
//static int	HzFlag=0;
static u_long	wxc_localip,wxc_peerip;
static char	wxc_localip_str[32],wxc_peerip_str[32];
static int	nowModule=MSC_;
static u_char	heartbeat_no = 0x09,hb_sub_no=0x00;
static u_short	hb_no=0x0901;
static u_short plat_work_port = 4096;
static char		wxc2HDInfo[256]; /* array[0] is length */
struct timeval tmstart,tmend;
static char	serialNumber[18]="";
//static int	updateFromLowVersion=0;
u_char 	noTimeSyncFlag = 0;

struct		timeval main_now;

typedef enum _OS_VERSION
{
        OS_ES4,
        OS_CENTOS,
}OS_VERSION;
static int      Linux_OS_Release=OS_CENTOS; /* 0=ES4, 1=CentOS */

typedef struct segLog{
	u_long tmnow;
	u_char	app_state;
	u_char	sub_state;	
}segLog;
segLog *segmentLog;
/*----------------------------------------------------*/
static void wxc2SetTermSignal(struct termio *ptermio, void (*handler)(int));
static void wxc2Terminate(int sig);
static void moduleProc();
static int  GetHDInfo();
static void SaveWxc2SystemConf();
static int CheckHDLicense(unsigned char *HDSerialNumber);
static void CheckLicenseExpire();
static void UpdateWXC2License();
/*----------------------------------------------------*/
extern int iptrMainInit();
extern void iptrans_timer();

extern void debug_init();
extern void debug_rt();

extern void heartbeat_init( unsigned short sysID);
extern void heartbeat_timer();

extern void snmp_init(unsigned short port );
extern void snmp_timer();

extern int smpp_timer();
extern int smpp_init_new(u8 sysid);
extern int smpp_fsm_new();

extern void mtp_shm_init(WORD moduleid_systemid, DWORD local_ip, DWORD peer_ip);
extern void mtp3_proc();
extern void sccp_init(int sysid, u_long localip, u_long peerip);
extern void sccp_timer();
extern int ReadHDInfoList();
extern int CheckIfHDInfoBackup(unsigned char *license_info);
extern int SaveHDInfoList(unsigned char *new_hd_info);
extern void tcap_init(u_short maxPorts,u_long localip,u_long peerip);
extern void tcap_msgprc();
extern void tcap_fsm();

extern void xap_init(u_short maxPorts);
extern void xap_fsm();

extern void scsm_init();
extern void scsm();

extern int pps_init();
extern int pps_proc();
extern int pps_exit();

extern void DesCrypt(
unsigned char *Output /*8 bytes*/,
unsigned char *Input /*8 bytes*/,
unsigned char *DesKey/*default=NULL.While using for user licenses control,can keep the default value*/,
unsigned char DesMode/*encrpt or decrypt,refer to enum _DesMode*/);

extern void ppsRecordLog();
extern void debug_init_wxc2_ver(char *info);

//extern void gx_handle_msg_cb();

extern void m2ua_init(BYTE);
extern void mtp3_init_serial(char *Serial);
extern void sccp_init_serial_number(BYTE *Serial);
extern int cdr_init(char plane_id, char memset_flag);
extern void m2ua_timer(void);
extern void ReadMCMSParam(void);
extern int fd_main(int argc, char * argv[]);
extern int gx_fsm(long sec, int msec);

/*----------------------------------------------------*/

static u8 wxc2_version[4] = {1, 0, 1, 46};
//static char	wxc2_mini_version[4]={""};

static int wxc2_update_version(char *state_str)
{
	char ver_string[64];

	/*if(wxc2_version[3] == 0)
	{
		sprintf(ver_string, "WXC2 MSS R%d.%d.%d%s - %s", \
			wxc2_version[0], wxc2_version[1], wxc2_version[2], wxc2_mini_version,state_str);
	}
	else*/
	{
		//sprintf(ver_string, "WXC2 MSS R%d.%d.%d.%03d%s - %s", 
		sprintf(ver_string, "AGT OCS %d.%d.%d.%03d - %s", \
			wxc2_version[0], wxc2_version[1], wxc2_version[2], wxc2_version[3],state_str);
	}
	debug_init_wxc2_ver(ver_string);
	return 1;
}

static int
snmpSetWXC2(u_char oidLen, DWORD *oid,u_char *pdata, u_short dataLen)
{
	u_char ocode=0;
	DWORD oidtype=0;
//	int	ssn;
//	u_char	bufdecrypt[128]="";
//	char	buf[128];
 //16.2.1.1:configuration
	if(oidLen<14) return 0;

	oidtype = oid[11];
	if(oidtype !=2) return 0; //only configuration supported
	oidtype = oid[12];		
	if(oidtype !=1) return 0; //parameter
	oidtype = oid[13];
 
	if(oidtype !=1 && oidtype !=2) return 0; //status, license
	switch(oidtype)
	{
		case 1: /* status */
			ocode = pdata[0];
			switch(ocode)
			{
				case 1: //init
				break;
				case 2: //suspend
				break;
				case 3: //normal
				break;
				case 4: //shutdown
						shutDownCommand = 1;
				break;
				case 5: //Save subs. data	
						endflag=1;
						return dataLen;
						if(wxc2_param.register_flag[PPS_]) pps_exit(1);
						endflag =0;
				break;
				case 6:	//backup configuration file, it should work with the script,MSS generates a log file, a script do the acutal backuping...
					{
					 FILE    *fpLog;

					 fpLog = fopen("/usr/local/wxc2/log/mss_backup_conf.txt","w");
					 fprintf(fpLog,"This is a log file to backup mss conf\n");
					 fclose(fpLog);
					}
					//system("tar cf /usr/local/subsManage/conf.bk.tar conf");
					//system("chmod 666 /usr/local/subsManage/conf.bk.tar");
				break;
				case 7:
					//system("tar xf /usr/local/subsManage/conf.bk.tar");
					wxc2Terminate(128);					
				break;
				default:
						return 0;
				break;
			}
		break;
		case 2: /* license */
			UpdateWXC2License();
			break;
		break;
		}
	return dataLen;
}

static int snmpGetWXC2(u_char oidLen, DWORD *oid,u_char *pdata, u_char *vartype)
{
	DWORD oidtype=0;
	int len=0;
	int i;
	unsigned int intLicense;
	
		//16.2.1.3: license status
	if(oidLen<14) return 0;
	
	oidtype = oid[11];
	if(oidtype !=2) return 0; //only configuration supported
	oidtype = oid[12];		
	if(oidtype !=1) return 0; //parameter
	oidtype = oid[13];
	
	if (oidtype != 3) return 0; //license status
	
	switch (oidtype)
	{
		case 3: /* license status */
			len = MAX_License_ID * sizeof(int);
			for (i = 0; i < MAX_License_ID; i++)
			{
				intLicense = htonl(wxc2_param.userIntLicense[i]);
				memcpy(pdata + i * sizeof(unsigned int), (u_char *) &intLicense, sizeof(unsigned int));
			}
			break;
		default:
			break;
		}
		
		*vartype = 4;
		
	return len;
}

static 
void wxc2SetTermSignal(struct termio *ptermio, void (*handler)(int))
{
	ioctl(0,TCGETA, ptermio);
	ptermio->c_cc[VINTR] = '\x03';
	ioctl(0,TCSETA, ptermio);

	signal(SIGINT, handler);
//	signal(SIGPIPE,handler);
	signal(SIGKILL,handler);
	signal(SIGSTOP,handler);
	signal(SIGTERM,handler);
}

static
void wxc2Terminate(int sig)
{
	char exitlog[128]="../log/wxc2exit.txt";
	FILE *fpExit;
	struct tm *tp, tb; 
	long ltime;
	//char *argv[2];
	int	loop=0;
	 static  int     wxc2TermFlag=0;

        if(wxc2TermFlag) return;
        wxc2TermFlag = 1;

	endflag=1;
	printf("backup file for normal stop...\n");
	fpExit=fopen(exitlog,"w");
	if(fpExit!=NULL)
	{
	tp = &tb;
	ltime = time((long *)0);
	tp = localtime(&ltime);
	fprintf(fpExit,"WXC2 procedure exit log\n");
	fprintf(fpExit,"  Time: %s\n",asctime(tp));
	fprintf(fpExit,"Now module: %s\n",app_name[nowModule]);
	fclose(fpExit);
	}else{
		printf("fopen file failed\n");
	}

	if(wxc2_param.register_flag[PPS_]) pps_exit(1);
	
	loop = 0;
	while(loop++<MAX_DELAY_TIME)
	{
		moduleProc(); /* to send pps daily report or other CDR need*/
		if(wxc2_param.register_flag[PPS_])
		    pps_proc();
		usleep(10);
		loop++;
	}
	
	if(sig == 128) //for restore configuration
        {
                FILE    *fpLog;
                fpLog = fopen("/usr/local/wxc2/log/mss_restore_conf.txt","w");
                fprintf(fpLog,"This is a log file to restore mss conf\n");
                fclose(fpLog);
        }
	
	exit(sig);
}

static
void sysDaemonInit()
{
	int		i;
	pid_t	pid;


	if ( (pid = fork()) < 0)		 /* parent terminates */
		printf("%s: %s: fork (%d)", 
				__FILE__, __FUNCTION__, __LINE__);
	else if (pid != 0)
		exit(0);		/* parent goes bye-bye */
	
	setsid();				// become session leader 

	for (i = 0; i<3; i++)
		close(i);
}


static void
SetFSMTimer()
{
        struct itimerval        *ptv, tv;
        struct utsname          u_name;

        uname(&u_name);

        if(strstr(u_name.release,"2.6.9") == NULL)
                Linux_OS_Release = OS_CENTOS;
        ptv = (struct itimerval *) &tv;
        ptv->it_interval.tv_sec = SYS_IT_INTERVAL_SEC;
        ptv->it_value. tv_sec = SYS_IT_INTERVAL_SEC;
        if(Linux_OS_Release == OS_ES4)
        {
                ptv->it_interval.tv_usec = ES4_IT_INTERVAL_USEC;
                ptv->it_value.tv_usec = ES4_IT_INTERVAL_USEC;
        }
        else
        {
                ptv->it_interval.tv_usec = CENTOS_IT_INTERVAL_USEC;
                ptv->it_value.tv_usec = CENTOS_IT_INTERVAL_USEC;
        }
        setitimer(ITIMER_REAL, ptv, NULL);

}

void wxc2StartLog(int flag)
{
	FILE *fpLog=NULL;
	char logFile[]="../log/wxc2_startup.log";
	time_t *p,tnow;

	p=&tnow;
	*p = time(NULL);
	fpLog = fopen(logFile,"a+");
	if(fpLog !=NULL)
	{
		if(!flag)
			fprintf(fpLog,"wxc2main startup --->%s ",ctime(p));
		else
			fprintf(fpLog,"wxc2main shutdown --->%s ",ctime(p));
		fclose(fpLog);
	}
}

int wxc2_system(char *command)
{
	int pid, status;
	char *argv[3];

	pid = fork();
	if(pid == -1)
		return -1;
	if(pid == 0)
	{
		argv[0] = "wxc2d";
		argv[1] = "restart";
		argv[2] = 0;
		execvp("/usr/local/wxc2/bin/wxc2d",argv);
		exit(127); 
	}
	do{
		if(waitpid(pid,&status,0) == -1){
			if(errno != EINTR)
			return -1;
		}else{
			return status;
		}			
	}while(1);
}

#if 0
static void SysGuard(int sig)
{
	struct timeval tm;
	char fname[64]={"../log/logout.txt"};
	FILE *fp;
	struct tm *tp, tb; 
	long ltime;
	
	tp = &tb;
	ltime = time((long *)0);
	tp = localtime(&ltime);
	sprintf(fname,"../log/wxc2_logout.log");

	fp = fopen(fname,"w");

	if(fp != NULL)
	{
		gettimeofday(&tm,NULL);
		fprintf(fp,"====================================\n");
		fprintf(fp,"system restart for segementation fault!\n");
		fprintf(fp,"log time	:  %s\n",ctime(&tm.tv_sec));
		fprintf(fp,"Now module: %d\n",segmentLog->sub_state);
		fclose(fp);
	}

	printf("wxc2 exit for SEGMENT FAULT!\n");

	pps_exit(0);

	ppsRecordLog();
	exit(1);
}
#endif

static void sysTimer_IRQ()
{
	gettimeofday(&main_now,NULL);
	sys_timer10ms = 1;
}

static void
SigactionSystem()
{
	struct sigaction action;//,actsegv;

	action.sa_handler = sysTimer_IRQ;
	sigemptyset(&action.sa_mask);
	action.sa_flags = SA_RESTART;
	if(sigaction(SIGALRM, &action, NULL)<0)
	{
		printf("sigactin sigalarm failed\n");
	}

/*	if(!wxc2_param.segmentFaultAction)
	 {
		actsegv.sa_handler = SysGuard;
		sigemptyset(&actsegv.sa_mask);
		actsegv.sa_flags = SA_RESTART;
		sigaction(SIGSEGV,&actsegv,NULL);
	}
*/
}

static void CheckLicenseExpire()
{
	struct tm *tp, tb; 
	long ltime;
	int	 error_flag = 0;
	/* max license is 2099-12-31 */	
	tp = &tb;
	ltime = time((long *)0);
	tp = localtime(&ltime);

	//printf("Check license date..."); may cause system crash
	
	if((tp->tm_year+1900)>wxc2_param.license_date[0]+2000)
	{
		error_flag = 1;
	}
	else if((tp->tm_year+1900)==wxc2_param.license_date[0]+2000)
	{
		if((tp->tm_mon+1)>wxc2_param.license_date[1])
		{
			error_flag = 1;
		}
		else if((tp->tm_mon+1)==wxc2_param.license_date[1])
		{
			if(tp->tm_mday>wxc2_param.license_date[2])
			{
				error_flag = 1;
			}
		}
	}
					
	if(error_flag)
	{
		printf("Failed!\n");
		/*printf("License is expired (20%02d-%02d-%02d),today:(%04d-%02d-%02d)\n",
			wxc2_param.license_date[0],
			wxc2_param.license_date[1],
			wxc2_param.license_date[2],
			tp->tm_year+1900,
			tp->tm_mon+1,
			tp->tm_mday);*/
		exit(4);
	}
	//printf("pass!\n"); may cause system crash
}

static int CheckHDLicense(unsigned char *HDSerailNumber)
{
#if 0// old CheckHDLicense
	int length;
	length = wxc2HDInfo[0];

	printf("Check HD License...\n");
	if (memcmp(&wxc2HDInfo[1],HDSerailNumber,length) !=0)
	{
		char ascii_buf[256];
		BcdToAscii(ascii_buf,&wxc2HDInfo[1],length*2);
		printf("Check HD license...FAILED!\n");
		//printf("Activation request code: %s\n", ascii_buf);
		printf("Please send ./log/Activation_request_code.txt to get the license\n");
		return 0;
	}
	printf("Check HD License...PASS!\n");
	return 1;
#endif
	int length;
	length = wxc2HDInfo[0];

	printf("Check HD License...\n");

	ReadHDInfoList();
	
	if (memcmp(&wxc2HDInfo[1],HDSerailNumber,length) !=0)
	{
		if(CheckIfHDInfoBackup(HDSerailNumber) == 0)
		{
			char ascii_buf[256];
			BcdToAscii(ascii_buf, (BYTE *)&wxc2HDInfo[1],length*2);
			printf("Check HD license...FAILED!\n");
			//printf("Activation request code: %s\n", ascii_buf);
			printf("Please send ../log/Activation_request_code.txt to get the license\n");
			return 0;
		}
	}

	SaveHDInfoList((unsigned char *)wxc2HDInfo);
	
	printf("Check HD License...PASS!\n");
	return 1;
}

#if 1//def Kylin_and_2204_lic
static int GetHDInfo()
{
	FILE *fpConf=NULL;
	int i,j=0,k;
	char ethmac[64]="",meminfo[64]="",hwinfo[128]="",*start,*offset,*offset_0,buf[8192]="",tmp[2048]="";//,cpuinfo[64]=""
	char ascii_buf[128] = {0};
	unsigned char TmpStr[64] = {0}, act_req_code[128] = {0}, act_req_code_des[128] = {0};
	int ret, offset_len;

	printf("Get HD info ...\n");

	memset(ethmac, 0, 64);
	sprintf(buf,"ip a > ../log/hwinfo");
	ret = system(buf);
	fpConf = fopen("../log/hwinfo","r");
	if (fpConf == NULL) {
		printf("Log directory may be missing!\n");
		return 0;
	}
	ret = fread(buf,2048,1,fpConf);
	start = buf;
	for (;;) {
		offset = strstr(start,"ether ");
		if (offset == NULL) {
			offset = strstr(start,"HWaddr ");
			offset_len = 7;
		} else {
			offset_len = 6;
		}
		if (offset != NULL) {
			strncpy(tmp, start, offset-start);
			tmp[offset-start] = 0;
			if (strstr(tmp, "docker") != NULL) {
				start = offset + offset_len;
				continue;
			}
			offset += offset_len;
			for(i=0,j=0;i<64;i++) {
				if ((*(offset+i)=='\n') ||
					(*(offset+i)==' ')) {
					ethmac[j] = 0;
					break;
				} else if (*(offset+i)==':') {
					continue;
				} else {
					ethmac[j] = tolower(*(offset+i));
					j++;
				}
			}
			ethmac[j] = 0;
		}
		fclose(fpConf);
		remove("../log/hwinfo");
		break;
	}

	int uuid_or_cpuid=0; //0=CPUID, 1=UUID
	memset(meminfo, 0, 64);
	sprintf(buf,"dmidecode | grep UUID > ../log/hwinfo");
	ret = system(buf);
	fpConf = fopen("../log/hwinfo","r");
	if(fpConf != NULL) {
		ret = fread(buf,2048,1,fpConf);
		offset_0=offset = strstr(buf,"UUID: ");
		if (offset != NULL) {
			uuid_or_cpuid = 1;
			for(i=6,j=0;i<64;i++) {
				if (*(offset+i)=='\n') {
					meminfo[j] = 0;
					break;
				} else if (isdigit(*(offset+i))) {
					meminfo[j] = *(offset+i);
					j++;
				}
			}
		}
		fclose(fpConf);
		remove("../log/hwinfo");
	}

	if( uuid_or_cpuid == 0) {//UUID not found
		// CPUID
		memset(meminfo, 0, 64);
		sprintf(buf,"dmidecode -t 4 | grep ID >../log/hwinfo");
		ret = system(buf);
		fpConf = fopen("../log/hwinfo","r");
		if(fpConf != NULL) {
			ret = fread(buf,2048,1,fpConf);
			offset_0=offset = strstr(buf,"ID: ");
			if (offset != NULL) {
				for(i=4,j=0;i<64;i++) {
					if (*(offset+i)=='\n') {
						meminfo[j] = 0;
						break;
					} else if (isdigit(*(offset+i))) {
						meminfo[j] = *(offset+i);
						j++;
					}
				}
				offset = strstr(offset_0+4,"ID: ");
				if (offset != NULL) {
					for(i=4;i<64;i++) {
						if (*(offset+i)=='\n') {
							meminfo[j] = 0;
							break;
						} else if (isdigit(*(offset+i))) {
							meminfo[j] = *(offset+i);
							j++;
						}
					}
				}
			}
			fclose(fpConf);
			remove("../log/hwinfo");
		}
	}

	strcpy(hwinfo, "");
	strcat(hwinfo, ethmac);
	i = j = strlen(ethmac);
	hwinfo[i++] = ethmac[0];
	hwinfo[i++] = ethmac[1];
	hwinfo[i++] = ethmac[2];
	hwinfo[i++] = ethmac[3];
	hwinfo[i] = 0;
	strcat(hwinfo, meminfo);
	j = strlen(meminfo);
	i += j;
	hwinfo[i++] = ethmac[4];
	hwinfo[i++] = ethmac[5];
	hwinfo[i++] = ethmac[6];
	hwinfo[i++] = ethmac[7];
	hwinfo[i] = 0;
	//strcat(hwinfo, cpuinfo);
	//j = strlen(cpuinfo);
	//i += j;
	hwinfo[i++] = ethmac[8];
	hwinfo[i++] = ethmac[9];
	hwinfo[i++] = ethmac[10];
	hwinfo[i++] = ethmac[11];
	hwinfo[i] = 0;

	j = strlen(hwinfo);
	if (j == 0) {
		printf("Missing Activation Request Info!\n");
		return 0;
	}

	k = (j + 7) / 8;
	memset(hwinfo + j, '0', 128 - j);

	memset(act_req_code, 0, 128);
	for (i = 0; i < k; i++) {
		memset(TmpStr, 0, 64);
		DesCrypt(TmpStr, (unsigned char *)hwinfo + 8 * i, NULL, 0);
		memcpy(act_req_code + 8 * i, TmpStr, 8);
	}
	memset(ascii_buf, 0, 128);
	BcdToAscii(ascii_buf, act_req_code, k * 16);
	
	fpConf = fopen("../log/Activation_request_code.txt","w");
	if (fpConf != NULL) {
		fprintf(fpConf, "%s\n", ascii_buf);
		fclose(fpConf);
	} else {
		printf("Missing Activation_request_code file!\n");
		return 0;
	}

	memset(act_req_code_des, 0, 128);
	for (i = 0; i < k; i++) {
		memset(TmpStr, 0, 64);
		DesCrypt(TmpStr, act_req_code + 8 * i, NULL, 0);
		memcpy(act_req_code_des + 8 * i, TmpStr, 8);
	}
	wxc2HDInfo[0] = k*8;
	memcpy(&wxc2HDInfo[1],act_req_code_des,k*8);
	printf("Get HD info... OK!\n");
	return 1;
}
#else
static int GetHDInfo()
{
	FILE *fpConf=NULL;
	int i,j=0,k;
	char ethmac[64]="",meminfo[64]="",cpuinfo[64]="",hwinfo[128]="",*offset,*offset_0, buf[8192];
	char	ascii_buf[128] = {0};
	unsigned char TmpStr[64] = {0}, act_req_code[128] = {0}, act_req_code_des[128] = {0};
	int lic_mem_cpu = 0;// 0, new lic; 1, old lic;
	//struct stat fileinfo;
	
	// Ethernet Hardware Address
	printf("Get HD info ...\n\n");
	 
	memset(ethmac, 0, 64);
	sprintf(buf,"ip a >../log/ethlog.txt");
	system(buf);
	fpConf = fopen("../log/ethlog.txt","r");
	if(fpConf != NULL)
	{
		fread(buf,2048,1,fpConf);
		offset = strstr(buf,"ether ");
		if (offset == NULL)
		{
			offset = strstr(buf,"HWaddr ");
			if (offset != NULL)
			{
				offset += 7;
			}
		} else {
			offset += 6;
		}
		if (offset != NULL)
		{
			//offset += 7;
			for(i=0,j=0;i<64;i++)
			{
				if ((*(offset+i)=='\n') ||
					(*(offset+i)==' '))
				{
					ethmac[j] = 0;
					break;
				}
				else if (*(offset+i)==':')
					continue;
				else
				{
					ethmac[j] = *(offset+i);
					//printf("ethmac[%d] = %c\n", j, ethmac[j]);
					j++;
				}
			}
			ethmac[j] = 0;
		}
		fclose(fpConf);
		remove("../log/ethlog.txt");
	}
	else
	{
	 	printf("Log directory may be missing!\n");
	 	return 0;
	}

	if(lic_mem_cpu)
	{
		// Memory
		memset(meminfo, 0, 64);
		sprintf(buf,"cat /proc/meminfo >../log/memlog.txt");
		system(buf);
		fpConf = fopen("../log/memlog.txt","r");
		if(fpConf != NULL)
		{
			fread(buf,2048,1,fpConf);
			offset = strstr(buf,"MemTotal:");
			if (offset != NULL)
			{
				for(i=0,j=0;i<64;i++)
				{
					if ((*(offset+i)=='\n') ||(*(offset+i)=='k'))
					{
						meminfo[j] = 0;
						break;
					}
					else if (isdigit(*(offset+i)))
					{
						meminfo[j] = *(offset+i);
						//printf("meminfo[%d] = %c\n", j, meminfo[j]);
						j++;
					}
				}
				meminfo[j] = 0;
			}
			fclose(fpConf);
			remove("../log/memlog.txt");
			
		}
		else
		{
		 	printf("Log directory may be missing!\n");
		 	return 0;
		}
	}
	else
	{
		int uuid_or_cpuid=0; //0=CPUID, 1=UUID
	  	memset(meminfo, 0, 64);
	   	sprintf(buf,"sudo dmidecode | grep UUID >../log/cpuIDlog.txt");
	   	system(buf);
	   	fpConf = fopen("../log/cpuIDlog.txt","r");

  		if(fpConf != NULL)
	   	{
	   		fread(buf,2048,1,fpConf);
			offset_0=offset = strstr(buf,"UUID: ");
	   		if (offset != NULL)
	   		{
	   			uuid_or_cpuid = 1;
	   			for(i=6,j=0;i<64;i++)
	   			{
	   				if (*(offset+i)=='\n')
	   				{
	   					meminfo[j] = 0;
	   					break;
	   				}
	   				else if (isdigit(*(offset+i)))
	   				{
	   					meminfo[j] = *(offset+i);
	   					printf("cpuinfo[%d] = %c\n", j, meminfo[j]);
	   					j++;
	   				}
	   			}
	   		}
			fclose(fpConf);
			remove("../log/cpuIDlog.txt");
			
		}	

		if(uuid_or_cpuid == 0)//UUID not found
		{
		   	sprintf(buf,"sudo dmidecode -t 4 | grep ID >../log/cpuIDlog.txt");
		   	system(buf);
		   	fpConf = fopen("../log/cpuIDlog.txt","r");
			if(fpConf != NULL)
		   	{
		   		fread(buf,2048,1,fpConf);
				offset_0=offset = strstr(buf,"ID: ");
		   		if (offset != NULL)
		   		{
		   			for(i=4,j=0;i<64;i++)
		   			{
		   				if (*(offset+i)=='\n')
		   				{
		   					meminfo[j] = 0;
		   					break;
		   				}
		   				else if (isdigit(*(offset+i)))
		   				{
		   					meminfo[j] = *(offset+i);
		   					printf("cpuinfo[%d] = %c\n", j, meminfo[j]);
		   					j++;
		   				}
		   			}
		   		}
				offset = strstr(offset_0+4,"ID: ");
		   		if (offset != NULL)
		   		{
		   			for(i=4;i<64;i++)
		   			{
		   				if (*(offset+i)=='\n')
		   				{
		   					meminfo[j] = 0;
		   					break;
		   				}
		   				else if (isdigit(*(offset+i)))
		   				{
		   					meminfo[j] = *(offset+i);
		   					printf("cpuinfo[%d] = %c\n", j, meminfo[j]);
		   					j++;
		   				}
		   			}
		   		}
				fclose(fpConf);
				remove("../log/cpuIDlog.txt");
				
			}	
		}
	}

if(lic_mem_cpu)
{
	// CPUInfo
	memset(cpuinfo, 0, 64);
	sprintf(buf,"cat /proc/cpuinfo >../log/cpuModlog.txt");
	system(buf);
	fpConf = fopen("../log/cpuModlog.txt","r");
	if(fpConf != NULL)
	{
		fread(buf,2048,1,fpConf);
		offset = strstr(buf,"cpu family");
		if (offset != NULL)
		{
			for(i=0,j=0;i<64;i++)
			{
				if (*(offset+i)=='\n')
				{
					cpuinfo[j] = 0;
					break;
				}
				else if (isdigit(*(offset+i)))
				{
					cpuinfo[j] = *(offset+i);
					//printf("cpuinfo[%d] = %c\n", j, cpuinfo[j]);
					j++;
				}
			}
		}
		offset = strstr(buf,"model");
		if (offset != NULL)
		{
			for(i=0;i<64;i++)
			{
				if (*(offset+i)=='\n')
				{
					cpuinfo[j] = 0;
					break;
				}
				else if (isdigit(*(offset+i)))
				{
					cpuinfo[j] = *(offset+i);
					//printf("cpuinfo[%d] = %c\n", j, cpuinfo[j]);
					j++;
				}
			}
		}
		offset = strstr(buf,"cache size");
		//offset = strstr(buf,"cpu MHz");
		//offset = strstr(buf,"bogomips");
		if (offset != NULL)
		{
			for(i=0;i<64;i++)
			{
				if (*(offset+i)=='\n')
				{
					cpuinfo[j] = 0;
					break;
				}
				else if (*(offset+i) == 'K')
				{
					//continue;
					break;
				}
				else if (isdigit(*(offset+i)))
				{
					cpuinfo[j] = *(offset+i);
					//printf("cpuinfo[%d] = %c\n", j, cpuinfo[j]);
					j++;
				}
			}
			cpuinfo[j] = 0;
		}
		fclose(fpConf);
		remove("../log/cpuModlog.txt");
		
	}
	else
	{
	 	printf("Log directory may be missing!\n");
	 	return 0;
	}
}

	strcpy(hwinfo, "");
	strcat(hwinfo, ethmac);
	i = j = strlen(ethmac);
	hwinfo[i++] = ethmac[0];
	hwinfo[i++] = ethmac[1];
	hwinfo[i++] = ethmac[2];
	hwinfo[i++] = ethmac[3];
	hwinfo[i] = 0;
	strcat(hwinfo, meminfo);
	j = strlen(meminfo);
	i += j;
	hwinfo[i++] = ethmac[4];
	hwinfo[i++] = ethmac[5];
	hwinfo[i++] = ethmac[6];
	hwinfo[i++] = ethmac[7];
	hwinfo[i] = 0;
	if (lic_mem_cpu)
	{
	strcat(hwinfo, cpuinfo);
	j = strlen(cpuinfo);
	i += j;
	}
	hwinfo[i++] = ethmac[8];
	hwinfo[i++] = ethmac[9];
	hwinfo[i++] = ethmac[10];
	hwinfo[i++] = ethmac[11];
	hwinfo[i] = 0;
	
	j = strlen(hwinfo);
	if (j == 0)
	{
		printf("Missing Activation Request Info!\n");
		return 0;
	}
	
	k = (j + 7) / 8;
	//printf("hwinfo: %s, len: %d, segment: %d\n", hwinfo, j, k);
	memset(hwinfo + j, '0', 128 - j);
	
	memset(act_req_code, 0, 128);
	for (i = 0; i < k; i++)
	{
		memset(TmpStr, 0, 64);
		DesCrypt(TmpStr, (unsigned char *)hwinfo + 8 * i, NULL, 0);
		memcpy(act_req_code + 8 * i, TmpStr, 8);
	}
	memset(ascii_buf, 0, 128);
	BcdToAscii(ascii_buf, act_req_code, k * 16);
	
	fpConf = fopen("../log/Activation_request_code.txt","w");
	if (fpConf != NULL)
	{
		fprintf(fpConf, "%s\n", ascii_buf);
		fclose(fpConf);
	}
	else
	{
		printf("Missing Activation_request_code file!\n");
		return 0;
	}
	
	memset(act_req_code_des, 0, 128);
	for (i = 0; i < k; i++)
	{
		memset(TmpStr, 0, 64);
		DesCrypt(TmpStr, act_req_code + 8 * i, NULL, 0);
		memcpy(act_req_code_des + 8 * i, TmpStr, 8);
	}
	//memset(ascii_buf, 0, 128);
	//BcdToAscii(ascii_buf, act_req_code_des, k * 16);
	//printf("Activation request code DES: %s\n", ascii_buf);
	wxc2HDInfo[0] = k*8;
	memcpy(&wxc2HDInfo[1],act_req_code_des,k*8);
	printf("Get HD info... OK!\n");
	return 1;
}
#endif

static void SaveWxc2SystemConf()
{
	FILE *fpConf=NULL;
	char filename[]="./conf/system.ini";
	
	fpConf = fopen(filename,"w");
	if(fpConf==NULL){
		return;
	}
 	fwrite(&wxc2_param,sizeof(wxc2_param),1,fpConf);
 	fclose(fpConf);
}

static void UpdateWXC2License()
{
	FILE *fpConf=NULL;
	FILE *fpFIB=NULL;
	char buf[512],output[256];
	u_char data[8];
	int i,len,newLicense,dif;
 
	char filename[]="/usr/local/subsManage/system.ini";
	struct stat fileinfo;
	
	memset(&tmpParam,0,sizeof(tmpParam));
	
	fpFIB = fopen("/usr/local/subsManage/fib.txt","w");
	
	fpConf = fopen(filename,"r");
	if(fpConf==NULL){
		fprintf(fpFIB,"Cann't open config file:system.ini\n");
		fclose(fpFIB);
		return;
	}
	
	stat(filename,&fileinfo);
	if(fileinfo.st_size < sizeof(wxc2_param))
	{
		fprintf(fpFIB,"Error file length: %d, should be: %lu\n",
			(int)fileinfo.st_size, sizeof(wxc2_param));
		fclose(fpFIB);
		fclose(fpConf);
		remove(filename);
		return;
	}
		
	fread(&tmpParam,sizeof(wxc2_param),1,fpConf);
	fclose(fpConf);

	rename(filename,"/usr/local/subsManage/system.ini.OLD");
	
	if(tmpParam.systemType != wxc2_param.systemType)
	{
		fprintf(fpFIB,"Wrong FIB file: system type (%s) is not the same as the current one (%s)\n",
			systemTypeName[tmpParam.systemType],
			systemTypeName[wxc2_param.systemType]);
		fclose(fpFIB);
		return;
	}
	if(memcmp(tmpParam.serialNumber,wxc2_param.serialNumber,8))
	{
		fprintf(fpFIB,"Wrong FIB file: serial number is not correct.\n");
		fclose(fpFIB);		
		return;
	}
/*
	if(!systemID)
	{
		if(!CheckHDLicense(tmpParam.HDSerialNumber[0]))
		{
			fprintf(fpFIB,"Wrong FIB file: Hardware codeis not correct.\n");
			fclose(fpFIB);
			return;		
		}
	}
	else
	{
		if(!CheckHDLicense(tmpParam.HDSerialNumber[1]))
		{
			fprintf(fpFIB,"Wrong FIB file: Hardware codeis not correct.\n");
			fclose(fpFIB);
			return;		
		}
	}
*/	
	for(i=0;i<MAX_APP_NUM;i++)
	{
		if(tmpParam.register_flag[i] && (!wxc2_param.register_flag[i]))
		{
			fprintf(fpFIB,"Wrong FIB file: system %s can't be opened when update license\n",
					app_name[i]);
			fclose(fpFIB);
			return;
		}		
	}
		
	for (i = 0; i < LIC_MAX_ID; i++)
	{
		if ((i < MAX_APP_FUNC_ID) && (wxc2_param.register_flag[i] == 0))
		{	// application, not registered
			tmpParam.userIntLicense[i] = 0;
			//printf("tmp LICENSE[%d]:%d\n",i, tmpParam.userIntLicense[i]);
			continue;
		}
		DesCrypt(data,tmpParam.userBcdLicense[i],NULL,1);
		tmpParam.userIntLicense[i] = (data[6] * 256 + data[7]) * wxc2_license_rule[i].step;
		if (tmpParam.userIntLicense[i] < 0)
		{
			fprintf(fpFIB,"Wrong license value: %s license should be greater than 0\n",
				wxc2_license_rule[i].name);
			fclose(fpFIB);
			return;
		}
		//printf("tmp LICENSE[%d]:%d\n",i, tmpParam.userIntLicense[i]);
	}
	
	for(i=0;i<MAX_License_ID;i++)
	{
		newLicense = tmpParam.userIntLicense[i];
		if (newLicense > wxc2_license_rule[i].maxValue)
		{
			fprintf(fpFIB,"Wrong license value: %s license can't be greater than maxValue %d\n",
				wxc2_license_rule[i].name, wxc2_license_rule[i].maxValue);
			fclose(fpFIB);
			return;
		}
		if (wxc2_license_rule[i].dir == ONLY_INCREASABLE)
		{
			if (newLicense < wxc2_param.userIntLicense[i])
			{
				fprintf(fpFIB,"Wrong license value: %s license can't be less than before,old=%d,now=%d\n",
				wxc2_license_rule[i].name,wxc2_param.userIntLicense[i],newLicense);
				fclose(fpFIB);
				return;
			}
		}
		else if (wxc2_license_rule[i].dir == ONLY_DECREASABLE)
		{
			if (newLicense > wxc2_param.userIntLicense[i])
			{
				fprintf(fpFIB,"Wrong license value: %s license can't be greater than before\n",
					wxc2_license_rule[i].name);
				fclose(fpFIB);
				return;
			}
		}
		
		if (newLicense >= wxc2_param.userIntLicense[i])
			dif = newLicense - wxc2_param.userIntLicense[i];
		else
			dif = wxc2_param.userIntLicense[i] - newLicense;
			
		if (dif > 0)
		{	// if dif equals 0, means no change at all
			if (dif % wxc2_license_rule[i].step)
			{
				fprintf(fpFIB,"Wrong license value: %s license should change by step %d\n",
					wxc2_license_rule[i].name, wxc2_license_rule[i].step);
				fclose(fpFIB);
				return;
			}
		}
	}
		
	
	if(tmpParam.license_date[0] == 0 &&
		tmpParam.license_date[1] == 0 &&
		tmpParam.license_date[2] == 0)
	{
		tmpParam.license_date[0] = 99;
		tmpParam.license_date[1] = 12;
		tmpParam.license_date[2] = 31;
	}
	memcpy(&wxc2_param,&tmpParam,sizeof(wxc2_param));
	rename("./conf/system.ini","./conf/system.ini.OLD");
	SaveWxc2SystemConf();
	
	/* set FIB file */
	fprintf(fpFIB,"[ system info ]\n");
	fprintf(fpFIB,"software version=R9.0\n");
	switch(wxc2_param.systemType)
	{
		case 0:
		fprintf(fpFIB,"system type=NIB\n");
		break;
		case 1:
		fprintf(fpFIB,"system type=X40\n");
		break;
		case 2:
		fprintf(fpFIB,"system type=X100\n");
		break;
	}
	fprintf(fpFIB,"\n");
	
	fprintf(fpFIB,"[ deployment info ]\n");
	fprintf(fpFIB,"serial number=%s\n",serialNumber);
	
	len = wxc2_param.HDSerialNumber[0][255];	
	for(i=0;i<len/16;i++)
	{
		DesCrypt((unsigned char *)&output[i*8],
			(unsigned char *)&wxc2_param.HDSerialNumber[0][i*8],
			NULL,1);
	}
	output[len] = 0;
	BcdToAscii(buf, (BYTE *)output,len);
	buf[len] = 0;	
	fprintf(fpFIB,"HDID0=%s\n",buf);
	
	if(wxc2_param.systemType==WXC2_SYSTYPE_UNIB)
	{
		fprintf(fpFIB,"HDID1=NULL\n");
	}
	else	
	{
		len = wxc2_param.HDSerialNumber[1][255];	
		for(i=0;i<len/16;i++)
		{
			DesCrypt((unsigned char *)&output[i*8],
				(unsigned char *)&wxc2_param.HDSerialNumber[1][i*8],
				NULL,1);
		}
		output[len] = 0;
		BcdToAscii(buf, (BYTE *)output,len);
		buf[len] = 0;			
		fprintf(fpFIB,"HDID1=%s\n",buf);		
	}
	
	if(wxc2_param.license_date[0] == 99)
	{
		fprintf(fpFIB,"expire on=000000\n");
	}
	else
	{
		fprintf(fpFIB,"expire on=%02d%02d%02d\n",
			wxc2_param.license_date[0],
			wxc2_param.license_date[1],
			wxc2_param.license_date[2]);
	}	
	fprintf(fpFIB,"\n");
	
	fprintf(fpFIB,"[ application flag ]\n");
	for(i=0;i<8;i++)
	{
		if(wxc2_param.register_flag[i])
			fprintf(fpFIB,"%s=ON\n",app_name[i]);
		else
			fprintf(fpFIB,"%s=OFF\n",app_name[i]);
	}
	
	fprintf(fpFIB,"\n");
	

	fprintf(fpFIB,"[ license ]\n");
	for(i=0;i<MAX_License_ID;i++)
	{
		fprintf(fpFIB,"%s=%d\n",wxc2_license_rule[i].name,wxc2_param.userIntLicense[i]);
	}
	fprintf(fpFIB,"\n");
	fprintf(fpFIB,"\n");
	fclose(fpFIB);
}

unsigned int crc32(unsigned char *data, int length)
{
	unsigned char  i;
	unsigned int crc = 0xffffffff;        // Initial value
	while(length--)
	{
		crc ^= *data++;                // crc ^= *data; data++;
		for (i = 0; i < 8; ++i)
		{
			if (crc & 1)
				crc = (crc >> 1) ^ 0xEDB88320;// 0xEDB88320= reverse 0x04C11DB7
			else
				crc = (crc >> 1);
		}
	}
	return ~crc;
}

static int check_license_file_validity(struct _wxc2_param *param_ptr)
{
	unsigned int check_sum = 0;
	unsigned int licensed_check_sum = 0;
	char           license_date[128], e_license_date[128];

	if(param_ptr == NULL)
	{
		goto invalid_license;
	}

	check_sum = crc32((unsigned char *)param_ptr, sizeof(struct _wxc2_param)-4);	
	memcpy(&licensed_check_sum, &param_ptr->userIntLicense[MAX_LICENSE_TYPE-1], 4);

	if(check_sum != licensed_check_sum)
		goto invalid_license;

	if(1)
	{
		char year[5], month[3], day[3];
		memcpy(e_license_date, &param_ptr->userIntLicense[250], 8); 
		DesCrypt(license_date,e_license_date, NULL,1);
		memcpy(year, license_date, 4);
		year[4] = 0;
		memcpy(month, &license_date[4], 2);
		month[2] = 0;
		memcpy(day, &license_date[6], 2);
		day[2] = 0;

		param_ptr->license_date[0] = atoi(year) - 2000;
		param_ptr->license_date[1] = atoi(month);
		param_ptr->license_date[2] = atoi(day);		
	}

	return 1;
	
invalid_license:
	printf("invalid license\r\n");
	exit(110);

	return 0;	
}

static 
void ReadSystemConf()
{
	FILE *fpConf=NULL;
	int i,flag=0;
 // char hostname[128];
	char filename[]="./conf/system.ini";
	struct stat fileinfo;
	u_char data[8];
	
	fpConf = fopen(filename,"r");
	if(fpConf==NULL){
		printf("Cann't open config file\n");
		printf("Please check directory and conf file\n");
		printf("Failed to continue!\n");
		exit(1);
	}
	stat(filename,&fileinfo);
	/*
	if(fileinfo.st_size != sizeof(wxc2_param))
	{
		// don't set license when initialized
		//updateFromLowVersion = 1;
	}
	*/
	fread(&wxc2_param,sizeof(wxc2_param),1,fpConf);
	fclose(fpConf);

    // add descrypt and crc check=========================
	char buf[128];
	AsciiToBcd(buf,wxc2_param.serialNumber,16);
	DesCrypt((unsigned char *)serialNumber,buf,NULL,1);
	check_license_file_validity(&wxc2_param);
    // ===================================================

	/*
	if(updateFromLowVersion)
	{
		memcpy(wxc2_param.HDSerialNumber[1],wxc2_param.HDSerialNumber,256);
	}
	*/
	
	for(i=0;i<MAX_APP_NUM;i++){
		if(wxc2_param.register_flag[i])
			flag = 1;
	}

	if(flag==0) 
	{
		printf("Error config file for no application enabled!\n");
		exit(1);
	}
	
	if(wxc2_param.systemType == WXC2_SYSTYPE_UNIB)
	{
		plat_work_port = (MAX_DIALOGUEID/4);
		printf("system info: UNIB\n");
	}
	else if(wxc2_param.systemType == WXC2_SYSTYPE_X40)
	{
		plat_work_port = (MAX_DIALOGUEID/2);
		printf("system info: X40\n");
	}
	else
	{
		plat_work_port = MAX_DIALOGUEID;
		printf("system info: X100\n");
	}
	/* 
	if(!gethostname(hostname,128)){
		if(strstr(hostname,"-0")!=NULL){
		 systemID = 0;
		}else if(strstr(hostname,"-1")!=NULL){
		 systemID = 1;
		}
	}
	*/
	/*	
	for(i=0;i<MAX_APP_NUM;i++){
		printf("APP[%d]:\n",i);
		printf("  register: %d\n",wxc2_param.register_flag[i]);
		printf("  max user: %d\n",wxc2_param.max_users[i]);
	}
	*/
	for (i = 0; i < MAX_License_ID; i++)
	{
		if ((i < MAX_APP_FUNC_ID) && (wxc2_param.register_flag[i] == 0))
		{	// application, not registered
			wxc2_param.userIntLicense[i] = 0;
		//	printf("LICENSE[%d]:%d\n",i, wxc2_param.userIntLicense[i]);
			continue;
		}
		DesCrypt(data,wxc2_param.userBcdLicense[i],NULL,1);
		wxc2_param.userIntLicense[i] = (data[6] * 256 + data[7]) * wxc2_license_rule[i].step;
		//printf("LICENSE[%d]:%d\n",i, wxc2_param.userIntLicense[i]);
	}
	wxc2_param.register_flag[PPS_] = 1;	
}

int wxc2_read_sysparam(void)
{
	FILE	*fp;
	int		ii;
	char	*ch_ptr,*buf_ptr;
	char	*temp_ptr;
	char	hostname[64];
	char	temp_info[64],info_str[1024];
	struct	hostent		*pcn;
	struct	in_addr		temp_addr;

	char	sysconf[]="./conf/wxc2_sys.conf";

	if ((gethostname(hostname,63)) == -1)
	{
		printf("Can not get hostname\n");
		return 0;
	}
	pcn = gethostbyname(hostname);
	if (pcn == NULL)
	{
		printf("Get host ip address fail. Please check your ethernet configure\n");
		return 0;
	}
	fp = fopen(sysconf,"r");			// read system configure
	if (fp == NULL)
	{
		printf("can not open file %s!!\n",sysconf);
		return 0;
	}
	ch_ptr = strchr(hostname,'.');
	if (ch_ptr != NULL)
		ch_ptr[0] = '\0';	// delete the suffix of host name

	while (!feof(fp))
	{
		info_str[0] = '\n';
		fgets(info_str,250,fp);
		if (info_str[0] == '#' || info_str[0] == '\n')
			continue;
		buf_ptr = info_str;
		
		if(!strncasecmp(info_str,"heartbeat no=",13))
		{
			heartbeat_no = atoi(&info_str[13]);
			continue;
		}
		if(!strncasecmp(info_str,"heartbeat sub no=",17))
		{
			hb_sub_no = atoi(&info_str[17]);
			continue;
		}
		if(!strncasecmp(info_str,"noTimeSync=",11))
		{
			noTimeSyncFlag = atoi(&info_str[11]);
			continue;
		}
		if(!strncasecmp(info_str,"mca enable",10))
		{
			wxc2_param.register_flag[RMC_] = 1;
			continue;
		}
		/*
		if(!strncasecmp(info_str,"local ip=",9))
                {
                        wxc_localip = inet_addr(&info_str[9]);
                        continue;
                }
                if(!strncasecmp(info_str,"peer ip=",8))
                {
                        wxc_peerip = inet_addr(&info_str[8]);
                        continue;
                }
                if(!strncasecmp(info_str,"system id=",10))
                {
                        systemID = atoi(&info_str[10]);
                        continue;
                }
		*/
		
		for (ii = 0;ii < 2;ii ++)
		{
			ch_ptr = strsep(&(buf_ptr),"=;");
			if (ch_ptr == NULL)
			{
				printf("This field lacks infomation:%s\n",buf_ptr);
				return 0;
			}
			if (ii == 0)
			{
				if (strlen(ch_ptr) != strlen(hostname))
				{
					printf("Please check host name in file:%s\t%s\n",ch_ptr,hostname);
					return 0;
				}
				temp_ptr = strchr(hostname,'-');
				if (temp_ptr != NULL) {
					if (strncmp(ch_ptr, hostname, strlen(hostname) - strlen(temp_ptr)) != 0) {
						printf("The host name is unexpected!\n");
						return 0;
					}
				} else {
					if (strncmp(ch_ptr, hostname, strlen(hostname)) != 0) {
						printf("The host name is unexpected!\n");
						return 0;
					}
				}
				strcpy(temp_info,ch_ptr);
			}
			else
			{
				if (memcmp(hostname,temp_info,strlen(temp_info)) == 0)	// owner ip address
				{
					//if (strcmp(inet_ntoa(*(struct in_addr *)(*pcn->h_addr_list)),ch_ptr) != 0)
					//{
					//	printf("Error ip address\n");
					//	return 0;
					//}
					systemID = temp_info[strlen(temp_info)-1] - '0';
					if (systemID > 5)
					{
						printf("Error system id\n");
						return 0;
					}
					wxc_localip = inet_addr(ch_ptr); //((struct in_addr *)(*pcn->h_addr_list))->s_addr;
					strcpy(wxc_localip_str, ch_ptr);
				}
				else
				{
					if (!inet_aton(ch_ptr,&temp_addr))
					{
						printf("Can not get peer ip address\n");
						return 0;
					}
					wxc_peerip = temp_addr.s_addr;
					strcpy(wxc_peerip_str, ch_ptr);
				}
			} //for
		}//while
		
	}
	hb_no = heartbeat_no;
        hb_no <<=8;
        if(hb_sub_no)
        	hb_no |= hb_sub_no;
        else
        	hb_no |= systemID;
	fclose(fp);
	return 1;
}

static void 
wxc2HBinit()
{
//	hb_no = heartbeat_no;
//	hb_no <<=8;
//	hb_no |= systemID;
	
	heartbeat_init(hb_no);
}

void LogModuleStartState( int nType , char *Module , int nResult )
{
	char sType[32];
	char sResult[32];
	char sModule[32];
	
	if( strlen(Module) > 10 )
	{
		printf("LogModuleStartState:too long module name!\n");
		return;
	}
	strcpy(sModule, Module );
	TxtColor(BRIGHT,WHITE,BLACK,sModule);
	if( nType )
	{
		strcpy(sType , "Application");
	}
	else
	{
		strcpy(sType , "Platform");
	}
	
	if( nResult )
	{
		strcpy(sResult , " OK ");
		TxtColor(BRIGHT,GREEN,BLACK,sResult);
	}
	else
	{
		strcpy(sResult , "Fail");
		TxtColor(BRIGHT,RED,BLACK,sResult);
	}
	printf("Initialing %s %s Module: \t\t\t\t[ %s ]\n",sType,sModule,sResult);
}

static 
void moduleInit()
{
	int ret = 0;
	printf("\n\n[R9 Platform Init]\n\n");
	
	debug_init();
	LogModuleStartState( 0, "DEBUG" , 1);
	
	ret = iptrMainInit();
	LogModuleStartState( 0, "IPTR" , ret);
		
	snmp_init(4957);
	LogModuleStartState( 0, "SNMP" , ret);
	snmp_init_serial_number(serialNumber);
	if(noTimeSyncFlag == 1)
		snmp_set_timenosync();
	
       if( !wxc2_param.register_flag[RMC_])
       {
	
	    m2ua_init(systemID);
	    LogModuleStartState( 0, "M2UA" , ret);
	
//	mtp_shm_init(0x900|systemID);
	mtp_shm_init(hb_no, wxc_localip, wxc_peerip);
	LogModuleStartState( 0, "MTP3" , 1);
	mtp3_init_serial(serialNumber);
	
	sccp_init(systemID, wxc_localip, wxc_peerip);
	LogModuleStartState( 0, "SCCP" , 1);
	sccp_init_serial_number((BYTE *)serialNumber);
	
	ret = smpp_init_new(systemID);
	LogModuleStartState( 0, "SMPP" , ret);
	
	tcap_init(plat_work_port,wxc_localip,wxc_peerip);
	LogModuleStartState( 0, "TCAP" , 1);
	
	xap_init(plat_work_port); 
	LogModuleStartState( 0, "XAPP" , 1);
	
         radius_init();
         LogModuleStartState( 0, "RADIUS" , 1);	    
         
         tcp_init();
         LogModuleStartState( 0, "TCP" , 1);	    
	}
    	
	if (wxc2_param.register_flag[PPS_])
	{
		scsm_init();
		LogModuleStartState( 0, "SCF" , 1);
	}

	wxc2HBinit();
	LogModuleStartState( 0, "HB" , 1);

      cdr_init(systemID, 0);


	printf("\n\n[R9 Platform Init completed]\n\n");
	inquire_setmsg(11,WXC2_OID_PREFIX, (setcall)snmpSetWXC2);
	inquire_getmsg(11,WXC2_OID_PREFIX, (getcall)snmpGetWXC2);
}

static void moduleProc()
{
	//static int wait_sccp_normal_count = 0;
	//static BYTE t20ms = 0;
	
	segmentLog->tmnow = time(NULL);
	
	segmentLog->sub_state = 0;
	sub_state = 0;
	iptrans_timer();

	segmentLog->sub_state ++;
	sub_state ++;
	snmp_timer();
	
	segmentLog->sub_state ++;
	sub_state ++;
	heartbeat_timer();


	segmentLog->sub_state ++;
	sub_state ++;
	debug_rt();
	
	if (wxc2_main_state == WXC2_NORMAL)
       //if(wait_sccp_normal_count++>30)/*wait for 30secs */
	{
		//wait_sccp_normal_count=6001;
			
		segmentLog->sub_state ++;
		sub_state ++;
		m2ua_timer();

		
		segmentLog->sub_state ++;
		sub_state ++;
		mtp3_proc();

		
		segmentLog->sub_state ++;
		sub_state ++;
		sccp_timer();
		
		segmentLog->sub_state ++;
		sub_state ++;
		tcap_fsm();
	
		segmentLog->sub_state ++;
		sub_state ++;
		smpp_fsm_new();
	
		segmentLog->sub_state ++;
		sub_state ++;
		xap_fsm();	
			
		segmentLog->sub_state ++;
		sub_state ++;
		radius_timer();
			
		segmentLog->sub_state ++;
		sub_state ++;
		tcp_timer();
	}
			
	if (wxc2_param.register_flag[PPS_])
	{
		segmentLog->sub_state ++;
		sub_state ++;		
		scsm();
	}

}

void RecordLogInfo()
{
	int shm_id;
	FILE *fpTmp=NULL;

	shm_id = shmget(WXC2_SHM_KEY+wxc2_get_shm_offset(),1024,WXC2_SHM_PERM | IPC_CREAT);
	if(shm_id == -1)
		return;
	segmentLog = (segLog *)shmat(shm_id,(char *)0,0);
	if(segmentLog == (void *) -1)
	{
		printf("get shm failed\n");
		exit(127);
	}	
	fpTmp = fopen("../log/wxc2_log.txt","w");
	if(fpTmp == NULL)	return ;	
	fprintf(fpTmp,"time: %ld\n",segmentLog->tmnow);
	fprintf(fpTmp,"app_state: %d\n",segmentLog->app_state);
	fprintf(fpTmp,"sub_state: %d\n",segmentLog->sub_state);
	fclose(fpTmp);
}

int	wxc2_get_license(int functionID)
{
	if (functionID >= MAX_License_ID)
		return -1;

	return wxc2_param.userIntLicense[functionID];
}

u_long wxc2_get_localip(char *ip_str)
{
	if(ip_str != NULL)
		strcpy(ip_str,wxc_localip_str);
	return wxc_localip;
}

u_long wxc2_get_peerip(char *ip_str)
{
	if(ip_str != NULL)
		strcpy(ip_str,wxc_peerip_str);
	return wxc_peerip;
}


#define WXC2_STARTUP_COMPLETED	1

int wxc2_startup(u8 no_sync)
{
	struct termio prev_termio;
		
	switch(wxc2_startup_state)
	{
		case 0:
			if(wxc2_param.register_flag[PPS_])
			{         			    
				if(pps_init((wxc2_param.max_users[PPS_])%DEFAULT_USERS,
					systemID,wxc_localip,wxc_peerip,serialNumber,no_sync))
				{
					LogModuleStartState( 1 , "PPS" , 1);					
					wxc2SetTermSignal(&prev_termio,wxc2Terminate);		
					printf("wxc2 initram ...\n");

					systemInited = 1;
					wxc2HBinit();
			
					wxc2_update_version("Normal");
					debug_change_title1();
					return WXC2_STARTUP_COMPLETED;
				}		
			}
			else
			{
				wxc2_startup_state = 0;
				
				wxc2SetTermSignal(&prev_termio,wxc2Terminate);		
						
				systemInited = 1;
				outb(0x05,0x37a);
				wxc2HBinit();
			
				wxc2_update_version("Normal");
				debug_change_title1();
				return WXC2_STARTUP_COMPLETED;
			}
		break;
		default:
			wxc2_startup_state = 0;
			break;
	}
	return 0;
}

void wxc2_normal_running()
{
    static int license_check_timer=0;

    if(license_check_timer++ == 360000) /* every hour */
    {
        license_check_timer = 0;
        //CheckLicenseExpire();
    }
    switch (app_state)
    {
        case 0:
            app_state = 0;
            segmentLog->app_state = app_state;
            segmentLog->sub_state =50;
            sub_state =50;
            if (wxc2_param.register_flag[PPS_])
            {
                pps_proc();
            }
        break;
        default:
            app_state = 0;
        break;
    }
}

int isWxc2mainNormal()
{
	if(wxc2_main_state == WXC2_NORMAL)
		return TRUE;
	return FALSE;
}

int main(int argc, char **argv)
{
	int retval, err_flag=0, daemon_flag=0, no_sync=0;
	char buf[32]="";
	struct itimerval tv;
	char checkPidFile[32]="./pidofwxc2.txt";
	char checkPidCommand[128]="pidof agtocs 2>./pidofwxc2.txt 1>&2";
	FILE *fpPid=NULL;
	//BYTE in;
	
	system(checkPidCommand);
	fpPid = fopen(checkPidFile,"r");
	if(fpPid !=NULL)
	{	
		int len,i;
		char record[32];
		memset(record,0,32);
		fread(record,32,1,fpPid);
		len = strlen(record);
		if(len>2)
		for(i=0;i<len;i++)
		{		
			if(record[i] == ' ' && i!=len-1)
			{
				printf("agtocs (pid=%s) is running, stop it first!\n",record);
				fclose(fpPid);
				//remove(checkPidFile);
				exit(0);
			}
		}
		fclose(fpPid);
	}
	remove(checkPidFile);
	
	/* Find out what is the system clock granularity. */
	tv.it_interval.tv_sec = 0;
	tv.it_interval.tv_usec = 1;
	tv.it_value.tv_sec = 0;
	tv.it_value.tv_usec = 0;
	setitimer (ITIMER_REAL, &tv, 0);
	setitimer (ITIMER_REAL, 0, &tv);
	printf ("System clock granularity: %ld microseconds.\n", tv.it_interval.tv_usec);
	wxc2StartLog(0);

	while ((retval = getopt(argc, argv, "dtc")) != -1)
	{
		switch (retval) {
			case 'd':
				daemon_flag = 1;
				break;
			case 't':
				no_sync = 1;
				break;
			case 'c':
				no_sync = 1;
				break;
			case '?':
				err_flag = 1;
				break;
		}
	}
	if (err_flag) {
		printf("Usage: %s [-d] \n", argv[0]);
		printf("	-d with daemon mode\n");
		exit(1);
	}
	if(!wxc2_read_sysparam()){
		printf("Error config file ./conf/wxc2_sys.conf!\n");
		exit(1);
	}

	if(!GetHDInfo())
	{
		printf("Get HD Info...FAILED!\n");
		exit(1);
	}

	ReadSystemConf();
	ReadMCMSParam(); /* MCMS parameters, bind ip, shm key shift  */
	RecordLogInfo();

	
	if(!systemID)
	{
		if(!CheckHDLicense(wxc2_param.HDSerialNumber[0]))
			exit(1);
	}
	else
	{
		if(!CheckHDLicense(wxc2_param.HDSerialNumber[1]))
			exit(1);
	}

	CheckLicenseExpire();

		
	AsciiToBcd((BYTE *)buf,wxc2_param.serialNumber,16); 
	DesCrypt((unsigned char *)serialNumber, (unsigned char *)buf,NULL,1);
	
	if(daemon_flag)
		sysDaemonInit();

	moduleInit();
	
	wxc2_update_version("Init...");

	SigactionSystem();
	SetFSMTimer();

	fd_main(argc, argv);	
	
	wxc2_main_state = WXC2_STARTUP;
	wxc2_startup_state = 0;

	sys_timer10ms = 1;
	while(1)
	{
		if(sys_timer10ms)
		{
			 sys_timer10ms = 0;
			moduleProc();

			
			switch(wxc2_main_state)
			{
				case WXC2_STARTUP:
	 				if(wxc2_startup(no_sync) == WXC2_STARTUP_COMPLETED)
						wxc2_main_state = WXC2_NORMAL;
					break;
				case WXC2_NORMAL:	
					wxc2_normal_running();
					break;
				default:
					wxc2_main_state = WXC2_STARTUP;
					break;
			}

			segmentLog->sub_state =20;
			segmentLog->app_state = 20;

			//gx_handle_msg_cb();
			gx_fsm(main_now.tv_sec, main_now.tv_usec%1000);


		}	
		if (sys_timer10ms == 0)
		{
			if(Linux_OS_Release == OS_ES4)
				usleep(1);
			else
				usleep(1000);

		}
	}
	return 1;
}


