/*************************************************
File name:	cdr.c
Author: 	
Version:	9:00:00 
Date:  		2002-5-7
Description:该文件实现了cdrCollector模块的主要功能，包括模块初始化，状态机，接收数据，处理
			数据，并且写到数据库里.
			
			调用snmp模块的函数
			void snmp_init(WORD nport);
			int snmp_receive(snmp_pdu *msgbuf,snmp_addr *addr);
			int snmp_send(snmp_pdu *msgbuf,snmp_addr *addr);
			
												
History:               
No. 		
Author:		  
Date:		 
Version:	   
Description:
*************************************************/

#include "cdr.h"

DWORD MAX_CDR_PTR=0x7FFFFFFF;
cdr_src CdrSet[CDR_SRC_NUM];
BYTE iCdrNum = 0;
BOOL cdr_running = 1;
int smlog_decode_flag = 0;
static MYSQL *pCdrConn;
MYSQL *pubConn;

int omcSysNo=-1;
//add 2007-8-27
void load_cdr_remoteip(cdr_src *pcdr);

//for NRTRDE
char local_mcc[8];
char local_mnc[8];

int initNRConf(void);
int getOmcSysNo(int* sysNo);
int getOmcStatus(int sysNo);
void load_cdrsrc();
BOOL load_cdrdef(cdr_def * pdef, char *define_table,BYTE cdr_ver);
static BYTE str2oid(char *str, DWORD * array, BYTE max);
static char *bcd2str(BYTE * buf, int len);
void cdr_request(cdr_src * pcdr);
void check_ptr(cdr_src * pcdr);
void alter_ptr(cdr_src * pcdr);
void cdr_receive();
int cdr_process(cdr_src * pcdr, int serial, BYTE * pmsg, WORD msglen);
int smsDecodeAll(int code_type,char *strIn, char *strOut,int length);

//WSMS
int wsms_enable_flag;
void getVlrCdr(cdr_src * pcdr, int serial, BYTE * pmsg, WORD msglen);
int wsms_check_sub(char* imsi,char* msisdn);
int initWSMSConf(void);

/*************************************************
Function:        // cdr_init
Description:     // 初始化snmp模块，打开日志文件，初始化数据库链接，初始化数据.
Calls:           // cdrlog_init; mysql_init; mysql_real_connect; cdr_start; cdrdb_init;
Called By:       // cdrmain.c:main;
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 
Others:          // 
*************************************************/
void cdr_init()
{
	char sqlstr[256];
	MYSQL_RES *res;
	MYSQL_ROW row;
	
	//printf("init cdr......\n");
	cdrlog_init();
	
	//从NR.conf获取本地mnc和本地mcc
	//initNRConf();
	//initWSMSConf();
	//从omcd.conf中获取omc sysNo
	//getOmcSysNo(&omcSysNo);
	//if(omcSysNo<0 || omcSysNo >1)
	//	printf("Fail to get the omcSysNo\n");
	
	//初始化数据库
	while ((pCdrConn = mysql_init(NULL)) == NULL) {
		printf("Fail to init mysql:%s\n", mysql_error(pCdrConn));
		sleep(2);
	}
	
	//初始化数据库连接
	while (mysql_real_connect
		   (pCdrConn, "localhost", "root", "rootaa", "CDR_DB", 0, NULL,
			0) == NULL) {
		printf("Fail to init mysql:%s\n", mysql_error(pCdrConn));
		sleep(2);
	}
	
	//初始化CdrSet内存快空间
	memset(CdrSet, 0, CDR_SRC_NUM * sizeof(cdr_src));

	//Init the OMC_PUB DB connection
	while ((pubConn = mysql_init(NULL)) == NULL) {
		printf("Fail to init mysql:%s\n", mysql_error(pubConn));
		sleep(2);
	}

	while (mysql_real_connect
		(pubConn, "localhost", "root", "rootaa", "OMC_PUB", 0, NULL, 0) == NULL) {
		printf("Fail to init mysql:%s\n", mysql_error(pubConn));
		sleep(2);
	}

	//Get the parameter SMLOG_CONTENT_DECODE_FLAG in the OMC.omcPubVarConf
	sprintf(sqlstr,
                 "SELECT pubVarValue FROM OMC_PUB.omcPubVarConf WHERE pubVarName='SMLOG_CONTENT_DECODE_FLAG'");

	if(mysql_query(pubConn, sqlstr) != 0){
	  	cdr_log("%s\n", mysql_error(pubConn));
		return;
	}
	if((res = mysql_store_result(pubConn)) == NULL){
		return;
	}
	if((row = mysql_fetch_row(res)) != NULL){
		if(strlen(row[0]) == 0)
			smlog_decode_flag=0;
		else if(strcmp(row[0],"Yes") == 0)
                        smlog_decode_flag=1;
	        else
	                smlog_decode_flag=0;
	}
	mysql_free_result(res);



#if CDR_LINK_DEBUG
	cdrdebug_init();
#endif
	cdr_start();
	cdrdb_init();
	//printf(".....finish\n");
}

/*************************************************
Function:        // initNRConf
Description:     // Get the information in file NR.conf 
Calls:           // 
Called By:       // cdr_init;
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 1:SUCCESSFUL; 0:FAIL;
Others:          // 
*************************************************/
int initNRConf(void)
{
	char fileName[512];
	unsigned char buf[4096];
	unsigned char param[32][512];
	char paramName[128];
	char paramValue[384];
	char* temp;
	FILE* fp;
	int fi;
	int i;
	//int j;
	int paramCount;
	int byteCount;
	
	paramCount=0;
	byteCount=0;
	memset(buf,0,4096);
	memset(param,0,32*512);
	sprintf(fileName,"./conf/NR.conf");
	fp=fopen(fileName,"r");
	if(fp)
	{		
		fi=fileno(fp);
		if(read(fi,buf,4096))
		{
			for(i=0;i<4096;i++)
			{
				
				if(buf[i] == 0x0A)
				{
					//printf("\n");
					if(byteCount<512 && param[paramCount][0] != 0x00 && param[paramCount][0] != 0x23)
						paramCount++;
					else
						memset(param[paramCount],0,512);	
					byteCount=0;
				}	
				else
				{	
					param[paramCount][byteCount]=buf[i];
					byteCount++;
				}
				
				//printf("%02x ",buf[i]);
			}

			
			for(i=0;i<paramCount;i++)
			{
				temp=strtok(param[i],"=");
				sprintf(paramName,"%s",temp);
				//printf("Name=%s,",temp);
				temp=strtok(NULL,"=");
				sprintf(paramValue,"%s",temp);
				//printf("Value=%s\n",temp);
						
				if(strcasecmp(paramName,"MCC") == 0)
				{
					sprintf(local_mcc,"%s",paramValue);
				}	
				else if(strcasecmp(paramName,"MNC") == 0)
				{
					sprintf(local_mnc,"%s",paramValue);
				}	
			}

		}	
		close(fi);
		fclose(fp);
	}	
	else
	{
		cdr_log("Fatal Error: The NR.conf does not exist!");
		exit(1);
	}		
	
	return 1;
}

/*************************************************
Function:        // getOmcSysNo
Description:     // Get the sysNo of the local omc system 
Calls:           // 
Called By:       // cdr_init;
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // sysNo:the sysNo of the local omc
Return:          // 1:SUCCESSFUL; 0:FAIL;
Others:          // 
*************************************************/
int getOmcSysNo(int* sysNo)
{
	char fileName[512];
	unsigned char buf[4096];
	unsigned char param[32][512];
	char paramName[128];
	char paramValue[384];
	char* temp;
	FILE* fp;
	int fi;
	int i;
	//int j;
	int paramCount;
	int byteCount;
	
	paramCount=0;
	byteCount=0;
	memset(buf,0,4096);
	memset(param,0,32*512);
	sprintf(fileName,"./conf/omcd.conf");
	fp=fopen(fileName,"r");
	if(fp)
	{
		fi=fileno(fp);
		if(read(fi,buf,4096))
		{
			for(i=0;i<4096;i++)
			{	
				if(buf[i] == 0x0A)
				{
					//printf("\n");
					if(byteCount<512 && param[paramCount][0] != 0x00 && param[paramCount][0] != 0x23)
						paramCount++;
					else
						memset(param[paramCount],0,512);	
					byteCount=0;
				}	
				else
				{	
					param[paramCount][byteCount]=buf[i];
					byteCount++;
				}
				
				//printf("%02x ",buf[i]);
			}
			
			for(i=0;i<paramCount;i++)
			{
				temp=strtok(param[i],"=");
				sprintf(paramName,"%s",temp);
				//printf("Name=%s,",temp);
				temp=strtok(NULL,"=");
				sprintf(paramValue,"%s",temp);
				//printf("Value=%s\n",temp);
				
				
				if(strcasecmp(paramName,"omcSysNo") == 0)
				{
					*sysNo=atoi(paramValue);
				}	
			}
		}	
		close(fi);
		fclose(fp);
	}	
	else
	{
		exit(1);
	}	
	return 1;
}

/*************************************************
Function:        // getOmcStatus
Description:     // Get the status of the local omc system 
Calls:           // 
Called By:       // cdr_timer;
Table Accessed:  // 
Table Updated:   // 
Input:           // sysNo:the sysNo of the local omc
Output:          // 
Return:          // the status of the omc
										0 - Offline
										1 - Init
										2 - Detect
										3 - Slave
				 						4 - Sync
										5 - Master
				   					6 - Degrade
										7 - Single
Others:          // 
*************************************************/
int getOmcStatus(int sysNo)
{
	MYSQL_RES *res;
	MYSQL_ROW row;
	char sqlstr[256];
	int status;
	char binCode[256];
	
	sprintf(sqlstr,
         "SELECT detailStat FROM OMC_PUB.sysStat WHERE sysTypeNo=0 and sysNo=%d ",sysNo);

	if(mysql_query(pubConn, sqlstr) != 0){
	  	cdr_log("%s\n", mysql_error(pubConn));
		return -1;
	}
	if((res = mysql_store_result(pubConn)) == NULL){
		return -1;
	}
	if((row = mysql_fetch_row(res)) != NULL){
		sprintf(binCode,"%s",row[0]);
		//printf("52-%c,53-%c\n",binCode[52],binCode[53]);
		status=(binCode[52]-0x30)*16+(binCode[53]-0x30);
	}
	mysql_free_result(res);
	return status;
}

/*************************************************
Function:        // load_cdr_remoteip
Description:     // 根据cdr配置获取该设备的IP地址
Calls:           // cdrlog_init; mysql_init; mysql_real_connect; cdr_start; cdrdb_init;
Called By:       // cdr_timer;
Table Accessed:  // OMC_PUB.sysInfo;
Table Updated:   // 
Input:           // pcdr:cdr数据源结构;
Output:          // 
Return:          // 
Others:          // 
*************************************************/
void load_cdr_remoteip(cdr_src *pcdr)
{
	char sqlstr[512];
	MYSQL_RES *res_set;
	MYSQL_ROW row;
	
	//根据cdr数据源的sysTypeNo和sysid获取在sysInfo里的实时IP地址
	sprintf(sqlstr,
			"SELECT ip FROM OMC_PUB.sysInfo WHERE sysTypeNo=%d and sysNo =%d",
			pcdr->sysTypeNo,pcdr->sysid);
	

	if (mysql_query(pCdrConn, sqlstr) != 0) {
		cdr_log("%s\n", mysql_error(pCdrConn));
		return;
	}
	if ((res_set = mysql_store_result(pCdrConn)) == NULL)
		return;

	

	while ((row = mysql_fetch_row(res_set)) != NULL) {
			pcdr->addr.remote_ip = inet_addr(row[0]);
	}
	mysql_free_result(res_set);
}
/*************************************************
Function:        // cdr_start
Description:     // 启动cdrCollector模块，初始化模块的全局数据.
Calls:           // load_cdrsrc; cdr_report; 
Called By:       // cdr.c:cdr_init;
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 
Others:          // 
*************************************************/
void cdr_start()
{
	iCdrNum = 0;
	load_cdrsrc();
	cdr_report();
	cdr_running = 1;
}

/*************************************************
Function:        // cdr_stop
Description:     // 停止cdrCollector模块的运行
Calls:           //  
Called By:       // 
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 
Others:          // 该函数没有被任何函数调用
*************************************************/
void cdr_stop()
{
	cdr_running = 0;
}


/*************************************************
Function:        // cdr_status
Description:     // 获取cdrCollector模块的运行状态
Calls:           //  
Called By:       // 
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 
Others:          // 该函数没有被任何函数调用
*************************************************/
BOOL cdr_status()
{
	return cdr_running;
}

/*************************************************
Function:        // load_cdrsrc
Description:     // 初始化全局变量CdrSet,并获取cdr数据表的字段定义
Calls:           // loac_cdrdef;
Called By:       // cdr_start; 
Table Accessed:  // CDR_DB.cdrSource; xxxCdrDefine
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 
Others:          //
*************************************************/
void load_cdrsrc()
{
	char sqlstr[1024];
	cdr_src *pcdr;
	MYSQL_RES *res_set;
	MYSQL_ROW row;
	int len;
	long l_time;
	struct tm *t;

	l_time = time(NULL);
	t = localtime(&l_time);

	//构造查询语句用来查询cdr数据源
	/*
	sprintf(sqlstr,
			"SELECT oid,bufSize,headOid,tailOid,ip,port,recordTable,defineTable,csvPath,backupMax,key_sys_id,version FROM %s.cdrSource WHERE isEnable > '0'",
			CDRDB_NAME);
	*/		
	sprintf(sqlstr,
			"SELECT oid,bufSize,headOid,tailOid,ip,port,recordTable,defineTable,csvPath,backupMax,key_sys_id,version,a.sysTypeNo FROM %s.cdrSource a  LEFT OUTER JOIN OMC_PUB.sysInfo b ON a.sysTypeNo=b.sysTypeNo and key_sys_id =sysNo where isEnable > '0'",
			CDRDB_NAME);		
	//cdr_log("%s\n",sqlstr);
	
	if (mysql_query(pCdrConn, sqlstr) != 0) {
		cdr_log("%s\n", mysql_error(pCdrConn));
		return;
	}
	if ((res_set = mysql_store_result(pCdrConn)) == NULL)
		return;

	cdr_log("search cdr source\n");
	
	//遍历查询的结果，即所有的cdr数据源
	while ((row = mysql_fetch_row(res_set)) != NULL && iCdrNum < 64) {
		pcdr = &CdrSet[iCdrNum];
		
		//获得cdr数据源的一般信息
		pcdr->request_id = pcdr->set_rid = 0;
		pcdr->get_state = ST_GET_TAIL;
		pcdr->set_state = ST_TAIL_IDLE;
		pcdr->set_fail = 0;
		pcdr->set_timeout = -1;
		pcdr->get_timeout = -1;
		pcdr->move_flag = 0;
		pcdr->maxbind = 1;
		pcdr->retry = 0;
		pcdr->instance = -1;
		//pcdr->serial =-1;
		pcdr->oid_len = str2oid(row[0], pcdr->oid, 20);
		pcdr->buf_size = atoi(row[1]);
		str2oid(row[2], pcdr->head_oid, 20);
		str2oid(row[3], pcdr->tail_oid, 20);
		
		//获得数据源的地址信息
		//pcdr->addr.remote_ip = inet_addr(row[4]);
		
		if(row[4]==NULL)
			pcdr->addr.remote_ip=0;	
		else	
			pcdr->addr.remote_ip = inet_addr(row[4]);
			
		pcdr->addr.remote_port = atoi(row[5]);
		pcdr->addr.local_port = CDR_PORT;

		strcpy(pcdr->record_table, row[6]);
		strcpy(pcdr->define_table, row[7]);
		strcpy(pcdr->csv_path, row[8]);
		len = strlen(pcdr->csv_path);
		if (pcdr->csv_path[len - 1] == '/')
			pcdr->csv_path[len - 1] = '\0';

		pcdr->backup_max = atoi(row[9]) % 365;
		pcdr->sysid = atoi(row[10]);
		pcdr->cdr_ver = atoi(row[11]);
		//add 2007-08-27
		pcdr->sysTypeNo=atoi(row[12]);
		//if(pcdr->sysTypeNo==320)
		//	printf("%s\n",row[4]);
		//printf("sysTypeNo=%ld\n",pcdr->sysTypeNo);
		
		//获得cdr数据表的字段定义
		if (load_cdrdef(&pcdr->define, pcdr->define_table,pcdr->cdr_ver)) {
			sprintf(sqlstr, "CREATE TABLE IF NOT EXISTS CDR_DB.%s_%02d %s",
					pcdr->record_table, t->tm_hour,
					pcdr->define.create_sql);
			if (mysql_query(pCdrConn, sqlstr) == 0)
				iCdrNum++;
			else
				cdr_log("%s\n", mysql_error(pCdrConn));
		}
	}
	mysql_free_result(res_set);
}

/*************************************************
Function:        // load_cdrdef
Description:     // 根据系统获取cdr数据表的字段定义
Calls:           // mysql_query; mysql_store_result; mysql_fetch_row
Called By:       // load_cdrsrc; 
Table Accessed:  // xxxCdrDefine;
Table Updated:   // 
Input:           // pdef:数据表的字段定义指针; define_table:字段定义的表名; cdr_ver:版本号
Output:          // 
Return:          // 0:failed; 1:successful
Others:          //
*************************************************/
BOOL load_cdrdef(cdr_def * pdef, char *define_table,BYTE cdr_ver)
{
	char sqlstr[2048], str[64], tagstr[128] = "\0";
	int index, len, i;
	MYSQL_RES *res_set;
	MYSQL_ROW row;

	//构造sql语句，查询xxxCdrDefine表的字段信息
	sprintf(sqlstr, "SHOW FIELDS FROM %s.%s", CDRDB_NAME, define_table);
	
	if (mysql_query(pCdrConn, sqlstr) != 0) {
		cdr_log("%s\n", mysql_error(pCdrConn));
		return 0;
	}

	if ((res_set = mysql_store_result(pCdrConn)) == NULL) {
		cdr_log("%s\n", mysql_error(pCdrConn));
		return 0;
	}

	//初始化字段定义数据结构的内存空间
	memset(pdef->valid, 0, sizeof(pdef->valid));
	
	//填充pdef->valid数组的值，用来构造tag的字符串
	while ((row = mysql_fetch_row(res_set)) != NULL) {
		if (strstr(row[0], "tag") != NULL) {
			index = atoi(row[0] + 3);
			if (index >= 0 && index < 17)
				pdef->valid[index] = 1;
			else
				return 0;
		}

	}

	//构造tag的字符串，用来构造字段查询语句
	for (i = 0; i < 17; i++) {
		if (pdef->valid[i]) {
			sprintf(str, "tag%d,", i);
			strcat(tagstr, str);
		}
	}
	len = strlen(tagstr);
	tagstr[len - 1] = '\0';
	mysql_free_result(res_set);
	
	//构造sql语句，利用刚才构造的tag字符串，用来查询数据表的字段定义
	sprintf(sqlstr, "SELECT fieldName,type,optional,width,%s FROM %s.%s",
			tagstr, CDRDB_NAME, define_table);

	if (mysql_query(pCdrConn, sqlstr) != 0) {
		cdr_log("%s\n", mysql_error(pCdrConn));
		return 0;
	}

	if ((res_set = mysql_store_result(pCdrConn)) == NULL) {
		cdr_log("%s\n", mysql_error(pCdrConn));
		return 0;
	}
	
	//cdr_log("%s\n",sqlstr);
	
	//初始化数据表字段个数
	pdef->field_count = 0;

	sprintf(pdef->field_set, "(key_sys_id,instance,");
	sprintf(pdef->create_sql,
			"(key_sys_id tinyint(2) NOT NULL,instance int(4)  NOT NULL,");
	while ((row = mysql_fetch_row(res_set)) != NULL
		   && pdef->field_count < CDR_OBJ_MAX) {
		strcpy(pdef->obj[pdef->field_count].field_name, row[0]);
		pdef->obj[pdef->field_count].type = atoi(row[1]) % 256;
		pdef->obj[pdef->field_count].optional = atoi(row[2]) % 2;
		pdef->obj[pdef->field_count].width = atoi(row[3]) % 256;

		//获取每个字段的tag的值
		index = 4;
		for (i = 0; i < 17; i++) {
			if (pdef->valid[i] && row[index] != NULL)
				strcpy(pdef->obj[pdef->field_count].tag_seq[i],
					   row[index++]);
			else
				pdef->obj[pdef->field_count].tag_seq[i][0] = '\0';
		}

		//获取字段的名字连接字符串和对应的产生数据表的sql语句字符串,根据各字段的类型
		strcat(pdef->field_set, row[0]);
		strcat(pdef->field_set, ",");
		strcat(pdef->create_sql, row[0]);
		strcat(pdef->create_sql, " ");
		switch (pdef->obj[pdef->field_count].type) {
		case 0:				//string
		case 2:
		case 4:
		case 40:
		case 41:
		case 7:
			if ((pdef->obj[pdef->field_count].width) < 256)
				sprintf(str, "VARCHAR(%d)",
						pdef->obj[pdef->field_count].width);
			else
				sprintf(str, "TEXT");
			strcat(pdef->create_sql, str);
			break;
		case 1:				//integer
			sprintf(str, "int(%d)", pdef->obj[pdef->field_count].width);
			strcat(pdef->create_sql, str);
			break;
		case 5:
			strcat(pdef->create_sql, "VARCHAR(20)");
			break;
		case 3:				//timestamp
			strcat(pdef->create_sql, "DATETIME");
			break;
		case 6:
		case 8:
			sprintf(str, "int(%d)", pdef->obj[pdef->field_count].width);
			strcat(pdef->create_sql, str);
			//strcat(pdef->create_sql, "tinyint(2)");
			break;
		case 9:
		case 10:
		case 11:
		case 12:
		case 13:
		case 14:
		case 15:
		case 16:
		case 17:
		case 18:
		case 19:
		case 20:
		case 22:
		case 23:
			strcat(pdef->create_sql, "TEXT");
			break;
		case 21:
			strcat(pdef->create_sql, "VARCHAR(3)");
			break;
		}

		if (!pdef->obj[pdef->field_count].optional)
			strcat(pdef->create_sql, " NOT NULL");
		strcat(pdef->create_sql, ",");
		pdef->field_count++;
	}
	strcat(pdef->field_set, "srcCode)");
	strcat(pdef->create_sql, "srcCode TEXT,KEY instance (instance))");
	cdr_log("%s\n", pdef->create_sql);

	mysql_free_result(res_set);	
	
//**********************************************************

	//由于wxc1和wxc2的不同，数据记录表的字段也不一样
	sprintf(sqlstr, "SELECT fieldName FROM %s.%s WHERE fileOrder>0 order by fileOrder",
			CDRDB_NAME, define_table);

	if (mysql_query(pCdrConn, sqlstr) != 0) {
		cdr_log("%s\n", mysql_error(pCdrConn));
		return 0;
	}

	if ((res_set = mysql_store_result(pCdrConn)) == NULL) {
		cdr_log("%s\n", mysql_error(pCdrConn));
		return 0;
	}
	
	//新版本多了三个字段,key_sys_id,instance,srcCode
	if(cdr_ver!=1)//cdr_ver==1 for wxc1
		strcpy(pdef->field_select, "key_sys_id,instance");					
	while ((row = mysql_fetch_row(res_set)) != NULL){
		strcat(pdef->field_select, ",");				
		strcat(pdef->field_select, row[0]);		
	}		
	if(cdr_ver!=1)//cdr_ver==1 for wxc1
		strcat(pdef->field_select, ",srcCode");		
	else	
		pdef->field_select[0]=' ';
	mysql_free_result(res_set);			
//**********************************************************	
	
	return 1;
}

/*************************************************
Function:        // cdr_timer
Description:     // 定时器，包括了状态机轮询
Calls:           // gettimeofday; alter_ptr; check_ptr; cdr_request; cdrdb_timer; cdrlog_timer
Called By:       // cdrmain.c:On_Timer;
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 
Others:          //
*************************************************/
void cdr_timer()
{
	int i;
	static int m_state = 0;
	cdr_src *pcdr;

	static struct timeval tv1, tv2;
	struct timezone tz;
	long elapse;
	int omcStatus;
	gettimeofday(&tv2, &tz);
	/*
	elapse =
		(tv2.tv_sec - tv1.tv_sec) * (10 ^ 6) + tv2.tv_usec - tv1.tv_usec;
	if(elapse>21000)
		printf("timeval=%ld\n", elapse);
	*/
	tv1.tv_sec = tv2.tv_sec;
	tv1.tv_usec = tv2.tv_usec;

	//Modify by Jianhui Zheng 2008-1-16
	//get the omc sysNo
	omcStatus=getOmcStatus(omcSysNo);
	
	//Master or single
	if(omcStatus == OMC_MASTER || omcStatus == OMC_SINGLE)
	{
		//printf("omcStatus=%d\n",omcStatus);
		cdr_receive();
		for (i = 0; i < iCdrNum; i++) {
			pcdr = &CdrSet[i];
			if(pcdr->addr.remote_ip==0){
				load_cdr_remoteip(pcdr);
				continue;
			}
			
			//尾指针改变了
			if (cdr_running == 0) {
				if (pcdr->move_flag > 0)
					alter_ptr(pcdr);
				continue;
			}
	
			switch (pcdr->get_state) {
			case ST_GET_TAIL:
				//send request
				check_ptr(pcdr);	
				pcdr->get_state = ST_WAIT_TAIL;
				break;
			case ST_WAIT_TAIL:
				//send request again
				if (pcdr->get_timeout <= 0)
					check_ptr(pcdr);	
				else
					pcdr->get_timeout--;
				break;
			case ST_CDR_IDLE:
				//time out event
				if (pcdr->get_timeout <= 0)	
				{
					cdr_request(pcdr);
					pcdr->get_state = ST_WAIT_CDR;
				} else
					pcdr->get_timeout--;
				break;
			case ST_GET_CDR:
				cdr_request(pcdr);
				pcdr->get_state = ST_WAIT_CDR;
				break;
			case ST_WAIT_CDR:
				//time out event
				if (pcdr->get_timeout <= 0)	
				{
					if (pcdr->retry < 5)
						cdr_request(pcdr);
					else {
						pcdr->maxbind = 1;
						pcdr->retry = 0;
						pcdr->request_id = 0;
						pcdr->get_state = ST_GET_TAIL;
						cdr_log
							("Lost connection to CDR Server.IP=%lx(%s-%d)\n",
							 pcdr->addr.remote_ip, pcdr->record_table,
							 pcdr->sysid);
					}
				} else
					pcdr->get_timeout--;
	
				break;
			}
	
	
			switch (pcdr->set_state) {
			case ST_TAIL_IDLE:
				if (pcdr->move_flag > 0) {
					alter_ptr(pcdr);
					pcdr->set_state = ST_SET_TAIL;
				}
				break;
			case ST_SET_TAIL:
				if (pcdr->set_timeout <= 0)
					alter_ptr(pcdr);
				else
					pcdr->set_timeout--;
	
				break;
			}
	
		}
	}

	if (m_state++ >= 500) {
		cdrdb_timer();
		cdrlog_timer();
		m_state = 0;
		
		//********************************************************
		//定时更新设备的IP地址
		for (i = 0; i < iCdrNum; i++) {
			pcdr = &CdrSet[i];			
			if(pcdr->addr.remote_ip==0){
				load_cdr_remoteip(pcdr);
			}
		}		
		//********************************************************
		
	}

	gettimeofday(&tv2, &tz);
	elapse =
		(tv2.tv_sec - tv1.tv_sec) * (10 ^ 6) + tv2.tv_usec - tv1.tv_usec;
	//if(elapse>18000)
	//  printf("\tprocess time=%ld\n",elapse);
}

/*************************************************
Function:        // str2oid
Description:     // 把字符串oid转换成字节数组
Calls:           // 
Called By:       // load_cdrsrc;
Table Accessed:  // 
Table Updated:   // 
Input:           // str:oid字符串; array:转换后的字节数组; max:数组最大长度
Output:          // 
Return:          // 实际数组长度  
Others:          //
*************************************************/
BYTE str2oid(char *str, DWORD * array, BYTE max)
{
	BYTE sub = 0;
	short len, i;
	char *pvar;
	len = strlen(str);
	pvar = str;
	for (i = 0; i < len && sub < max; i++) {
		if (str[i] == '.') {
			str[i] = '\0';
			if (strlen(pvar) == 0)
				continue;
			array[sub++] = atoi(pvar);
			pvar = str + i + 1;
		}
	}
	if (strlen(pvar) == 0)
		return sub;
	array[sub++] = atoi(pvar);
	return sub;
}

/*************************************************
Function:        // cdr_request
Description:     // 向CDR数据源发送get请求，以获得多个CDR数据
Calls:           // 
Called By:       // cdr_timer;
Table Accessed:  // 
Table Updated:   // 
Input:           // pcdr:cdr数据源指针
Output:          // 
Return:          // 
Others:          //
*************************************************/
void cdr_request(cdr_src * pcdr)
{
	int i;
	int maxbind;
	snmp_pdu request_msg;
	
	if (pcdr->request_id == 0)
		pcdr->retry = 0;
	else
		pcdr->retry++;
		
	//填充snmp数据包	
	request_msg.pdu_type = PDU_GET;
	if(pcdr->head>=pcdr->instance)
		maxbind=pcdr->head-pcdr->instance;
	else
		maxbind=(unsigned long)(pcdr->head+MAX_CDR_PTR)-pcdr->instance;
	if(maxbind>19)
		maxbind=19;
	
	//because the snmp moudle build msg from back to front,so cdrCollector need adapt it
	for (i = maxbind-1; i >=0; i--) {
		memcpy(request_msg.var[i].oid, pcdr->oid, 4 * pcdr->oid_len);
		request_msg.var[i].oid[pcdr->oid_len] =
			(pcdr->instance + (maxbind-1-i)) & MAX_CDR_PTR;
		request_msg.var[i].oidlen = pcdr->oid_len + 1;		
	}
	
	
	/*
	for (i = 0; i < pcdr->maxbind && i < 20; i++) {
		memcpy(request_msg.var[i].oid, pcdr->oid, 4 * pcdr->oid_len);
		request_msg.var[i].oid[pcdr->oid_len] =
			(pcdr->instance + i) & MAX_CDR_PTR;
		request_msg.var[i].oidlen = pcdr->oid_len + 1;
	}
	*/
	
	memcpy(request_msg.var[maxbind].oid, pcdr->head_oid,
		   4 * pcdr->oid_len);
	request_msg.var[maxbind].oid[pcdr->oid_len] = 0;
	request_msg.var[maxbind].oidlen = pcdr->oid_len + 1;

	//填充公共体名字
	sprintf(request_msg.community, "public");
	request_msg.var_num = maxbind + 1;
	request_msg.request_id = pcdr->request_id;
	
	//向系统发送snmp数据包
	pcdr->request_id = snmp_send(&request_msg, &pcdr->addr);

	pcdr->get_timeout = CDR_T_getcdr;
	//cdr_log("request cdr.host=%x,port =%d,request id=%ld\n",pcdr->addr.remote_ip,pcdr->addr.remote_port,pcdr->request_id);
}

/*************************************************
Function:        // check_ptr
Description:     // 获得头指针和尾指针，再向系统发送get请求，以获得数据
Calls:           // 
Called By:       // cdr_timer;
Table Accessed:  // 
Table Updated:   // 
Input:           // pcdr:cdr数据源指针
Output:          // 
Return:          // 
Others:          //
*************************************************/
void check_ptr(cdr_src * pcdr)
{
	snmp_pdu request_msg;
	request_msg.pdu_type = PDU_GET;

	memcpy(request_msg.var[0].oid, pcdr->tail_oid, 4 * pcdr->oid_len);
	request_msg.var[0].oid[pcdr->oid_len] = 0;
	request_msg.var[0].oidlen = pcdr->oid_len + 1;

	memcpy(request_msg.var[1].oid, pcdr->head_oid, 4 * pcdr->oid_len);
	request_msg.var[1].oid[pcdr->oid_len] = 0;
	request_msg.var[1].oidlen = pcdr->oid_len + 1;

	sprintf(request_msg.community, "public");
	request_msg.var_num = 2;
	request_msg.request_id = pcdr->request_id;

	pcdr->request_id = snmp_send(&request_msg, &pcdr->addr);
	//cdr_log("request tail.host=%lx,port =%d,request id=%ld\n",pcdr->addr.remote_ip,pcdr->addr.remote_port,pcdr->request_id);

	pcdr->get_timeout = CDR_T_gettail;
}

/*************************************************
Function:        // alter_ptr
Description:     // 向指定的CDR数据源发送set-request请求，修改头尾指针
Calls:           // 
Called By:       // cdr_timer;
Table Accessed:  // 
Table Updated:   // 
Input:           // pcdr:cdr数据源指针
Output:          // 
Return:          // 
Others:          //
*************************************************/
void alter_ptr(cdr_src * pcdr)
{
	snmp_pdu request_msg;
	unsigned long tail = pcdr->instance & MAX_CDR_PTR;

	request_msg.pdu_type = PDU_SET;

	memcpy(request_msg.var[0].oid, pcdr->tail_oid, 4 * pcdr->oid_len);
	request_msg.var[0].oid[pcdr->oid_len] = 0;
	request_msg.var[0].oidlen = pcdr->oid_len + 1;
	request_msg.var_num = 1;

	request_msg.var[0].msglen = 4;
	//encode_integer(request_msg.var[0].msg ,pcdr->instance);
	request_msg.var[0].msg[0] = tail >> 24;
	request_msg.var[0].msg[1] = (tail >> 16) & 0xFF;
	request_msg.var[0].msg[2] = (tail >> 8) & 0xFF;
	request_msg.var[0].msg[3] = tail & 0xFF;
	request_msg.var[0].vartype=2;
	sprintf(request_msg.community, "public");
	request_msg.request_id = pcdr->set_rid;
	
	
//Test Code
/*
{
int i;	
printf("alter_ptr\n");
for(i=0;i<request_msg.var[0].oidlen;i++)
	printf("%d.",request_msg.var[0].oid[i]);
printf("\ndata=%d %d %d %d ",request_msg.var[0].msg[0],request_msg.var[0].msg[1],request_msg.var[0].msg[2],request_msg.var[0].msg[3]);	
}
*/
	pcdr->set_rid = snmp_send(&request_msg, &pcdr->addr);

//Test Code
/*	
{
	printf("set_rid=%ld\n",pcdr->set_rid);
	printf("local_ip=%ld,remote_ip=%ld,local_port=%d,remote_port=%d\n",pcdr->addr.local_ip,pcdr->addr.remote_ip,pcdr->addr.local_port,pcdr->addr.remote_port);
	printf("myip=%ld\n",inet_addr("172.54.247.231"));
}	
*/
	//cdr_log("set tail,instance=%d\n",pcdr->instance);
	pcdr->set_timeout = CDR_T_settail;

	pcdr->set_fail++;

}

/*************************************************
Function:        // move_head
Description:     // 设置MSS缓冲区的头指针和尾指针和instance的位置一样
Calls:           // 
Called By:       // cdr_receive;
Table Accessed:  // 
Table Updated:   // 
Input:           // pcdr:cdr数据源指针
Output:          // 
Return:          // 
Others:          //
*************************************************/
void move_head(cdr_src * pcdr)
{
	snmp_pdu request_msg;
	unsigned long head, tail;
	request_msg.pdu_type = PDU_SET;

	tail = pcdr->instance & MAX_CDR_PTR;
	pcdr->instance = tail;
	head = (pcdr->instance) & MAX_CDR_PTR;
	memcpy(request_msg.var[0].oid, pcdr->tail_oid, 4 * pcdr->oid_len);
	request_msg.var[0].oid[pcdr->oid_len] = 0;
	request_msg.var[0].oidlen = pcdr->oid_len + 1;
	request_msg.var[0].vartype = 2;						//Integer
	request_msg.var[0].msglen = 4;
	request_msg.var[0].msg[0] = tail >> 24;
	request_msg.var[0].msg[1] = (tail >> 16) & 0xFF;
	request_msg.var[0].msg[2] = (tail >> 8) & 0xFF;
	request_msg.var[0].msg[3] = tail & 0xFF;


	memcpy(request_msg.var[1].oid, pcdr->head_oid, 4 * pcdr->oid_len);
	request_msg.var[1].oid[pcdr->oid_len] = 0;
	request_msg.var[1].oidlen = pcdr->oid_len + 1;
	request_msg.var[1].vartype = 2;
	request_msg.var[1].msglen = 4;
	request_msg.var[1].msg[0] = head >> 24;
	request_msg.var[1].msg[1] = (head >> 16) & 0xFF;
	request_msg.var[1].msg[2] = (head >> 8) & 0xFF;
	request_msg.var[1].msg[3] = head & 0xFF;

	request_msg.var_num = 2;
	request_msg.request_id = 0;

	sprintf(request_msg.community, "public");
	pcdr->set_rid = snmp_send(&request_msg, &pcdr->addr);
	#if	CDR_DEBUG
	cdr_log("move head,head=tail=%d(%s-%d)\n", tail, pcdr->record_table,
			pcdr->sysid);
	#endif

}

/*************************************************
Function:        // instance_cmp
Description:     // 比较两个指针的大小
Calls:           // 
Called By:       // cdr_receive;
Table Accessed:  // 
Table Updated:   // 
Input:           // 两个指针
Output:          // 
Return:          // 0:equal; else:相差
Others:          //
*************************************************/
/*
int instance_cmp(unsigned long a, unsigned long b)
{
	if (a == b)
		return 0;
	if (a > b) {
		if (a - b < 0x8000000)
			return a - b;
		else
			return a - (0x10000000 + b);

	} else						//b>a
	{
		if (b - a < 0x8000000)
			return a - b;
		else
			return 0x10000000 - b + a;

	}
}
*/
long instance_cmp(unsigned long a, unsigned long b)
{
	unsigned long halfOfMaxCDRPtr=(unsigned long)(MAX_CDR_PTR+1)/2;
	
	if (a == b)
		return 0;
	if (a > b) {
		if (a - b <halfOfMaxCDRPtr)
			return a - b;
		else
			return a - ((MAX_CDR_PTR+1) + b);

	} else						//b>a
	{
		
		if (b - a < halfOfMaxCDRPtr ){
			return a - b;
		}else
			return (MAX_CDR_PTR+1) - b + a;

	}
}

/*************************************************
Function:        // cdr_receive
Description:     // 接受数据包，并解析数据
Calls:           // snmp_receive; instance_cmp;
Called By:       // cdr_timer;
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 
Others:          //
*************************************************/
void cdr_receive()
{
	BYTE loop = 50, i, j;
	DWORD tail, cdrlen = 0;
	long rest;
	DWORD serial;
	int pos, errpos;
	snmp_pdu cdrmsg;
	snmp_addr addr;
	cdr_src *pcdr;
	ASN_BUF asnbuf;


	addr.local_port = CDR_PORT;

	while (loop-- > 0) {
		
		if (snmp_receive(&cdrmsg, &addr) == 0)
			return;
		if (cdrmsg.pdu_type != PDU_RSP)
			continue;

		for (i = 0; i < iCdrNum; i++) {
			pcdr = &CdrSet[i];
			cdrlen = 0;
		
			//oid长度不对
			if (cdrmsg.var[0].oidlen - 1 != pcdr->oid_len)
				continue;
		
			//get response
			if (cdrmsg.request_id == pcdr->request_id)	
			{
				//回复的数据单元应该至少带有一个或以上参数
				//最后一个参数是头指针参数
				//第一个参数可能是尾指针参数，或者是数据参数
				//数据参数可能有多个
				pcdr->request_id = 0;
				//if (cdrmsg.var_num < 2)
				//	break;

				/***************************************/
				//head get response--------------------->
				/***************************************/
				//最后一个 var是CDR头指针参数
				if (memcmp
					(cdrmsg.var[cdrmsg.var_num - 1].oid, pcdr->head_oid,
					 4 * pcdr->oid_len) != 0)
					break;
					
				//头指针参数的数据长度是4个字节
				if (cdrmsg.var[cdrmsg.var_num - 1].msglen > 4)
					break;

				//更新数据源头指针的位置
				pcdr->head =
					decode_integer(cdrmsg.var[cdrmsg.var_num - 1].msg,
								   cdrmsg.var[cdrmsg.var_num - 1].msglen);

				//头指针到达缓冲区的最大值
				if (pcdr->head > MAX_CDR_PTR) {
					move_head(pcdr);
					pcdr->move_flag = 0;
					pcdr->get_timeout = CDR_T_idle * 2;
					pcdr->get_state = ST_CDR_IDLE;
					cdr_log("Alarm:phead(=%d) is too large(%s-%d)\n",
							pcdr->head, pcdr->record_table, pcdr->sysid);
					break;
				}
				
				//尾指针和头指针相等，说明CRD已经全部取完
				if (pcdr->head == pcdr->instance) {
					pcdr->get_timeout = CDR_T_idle * 2;
					pcdr->get_state = ST_CDR_IDLE;
					break;
				}

				/***************************************/
				//cdr data get response----------------->
				/***************************************/
				//CDR数据response参数
				if (memcmp(cdrmsg.var[0].oid, pcdr->oid, 4 * pcdr->oid_len) == 0)
				{
					//because the snmp moudle build msg from back to front,so cdrCollector need adapt it
					for (j = cdrmsg.var_num - 1-1; j >=0; j--) {
						
						//再次判断此var是不是CDR数据response参数
						if (memcmp(cdrmsg.var[j].oid, pcdr->oid,4 * pcdr->oid_len) != 0)
							break;

						if (cdrmsg.var[j].vartype == 0x04 && cdrmsg.var[j].msglen > 0) 
						{
							cdrlen += (cdrmsg.var[j].msglen+cdrmsg.var[j].oidlen+2);
							pcdr->recv++;

							//头指针比数据指针小
							if (instance_cmp
								(pcdr->head,
								 cdrmsg.var[j].oid[pcdr->oid_len]) <= 0) {
								cdrlen = 0;	//to avoid maxbind increase
								break;
							}
							//decode serial number
							if (AsnDecode
								(cdrmsg.var[j].msg, cdrmsg.var[j].msglen,
								 1, &errpos, &asnbuf) < 0 && errpos < 6) {
								cdr_log
									("fail to decode cdr message.(%s-%d)\n",
									 pcdr->record_table, pcdr->sysid);
								cdr_logmsg(cdrmsg.var[j].msg,
										   cdrmsg.var[j].msglen);
								cdrlen = 0;	//to avoid maxbind increase
								break;
							}

							pos = get_int_v2("2", &serial, &asnbuf) + 2;	//serial

							if (serial > MAX_CDR_PTR) {
								cdr_log
									("Alarm:sequence(%d) exceed limit(MAX_CDR_PTR).(%s-%d)\n",
									 serial, pcdr->record_table,
									 pcdr->sysid);
								serial = serial & MAX_CDR_PTR;
							}
							//no cdr left
							if (serial == pcdr->head)	
								break;
							else if (serial == pcdr->instance)
							//获得一条CDR数据，数据源的当前指针加1	
								pcdr->instance = (serial + 1) & MAX_CDR_PTR;
							else if (instance_cmp(serial, pcdr->head) >= 0) {
								cdr_log
									("Alarm:Invaid sequence.phead=%ld < receive sequence=%d(%s-%d)\n",
									 pcdr->head, serial,
									 pcdr->record_table, pcdr->sysid);
								//to avoid maxbind increase	 
								cdrlen = 0;	
								pcdr->instance =
									(pcdr->instance + 1) & MAX_CDR_PTR;
								continue;
							} else if ((rest = instance_cmp(serial, pcdr->instance)) < 0)	//old cdr
							{
								cdr_log
									("Alarm:old cdr.expected sequence=%ld,receive sequence=%d(%s-%d)\n",
									 pcdr->instance, serial,
									 pcdr->record_table, pcdr->sysid);
								//to avoid maxbind increase	 
								cdrlen = 0;	
								pcdr->instance =
									(pcdr->instance + 1) & MAX_CDR_PTR;
							} else {
								pcdr->loss += rest;
								cdr_log
									("Alarm:cdr lost.expected sequence=%ld,receive sequence=%d,loss=%d(%s-%d)\n",
									 pcdr->instance, serial, rest,
									 pcdr->record_table, pcdr->sysid);
								pcdr->instance = (serial + 1) & MAX_CDR_PTR;
							}
							
							//把cdr数据保存在数据库中
							if (cdr_process
								(pcdr, serial, cdrmsg.var[j].msg + pos,
								 cdrmsg.var[j].msglen - pos)) {
								pcdr->recd++;
								//设此标志，就会去重新设置MSS的尾指针
								pcdr->move_flag = 1;
							}
						} 
						else 
						{
							cdrlen = 0;	//to avoid maxbind increase
							break;
						}
					}

					rest = instance_cmp(pcdr->head, pcdr->instance);

					if (rest < 0) {
						move_head(pcdr);
						pcdr->move_flag = 0;
						pcdr->get_timeout = CDR_T_idle * 2;
						pcdr->get_state = ST_CDR_IDLE;

						cdr_log
							("Alarm:Pointer crashed,ptail=%ld,phead=%ld(%s-%d)\n",
							 pcdr->instance, pcdr->head,
							 pcdr->record_table, pcdr->sysid);
					} else if (rest == 0) {
						pcdr->get_timeout = CDR_T_idle * 2;
						pcdr->get_state = ST_CDR_IDLE;
					} else if (rest < pcdr->maxbind)	//send next request after 5s
					{
						pcdr->get_timeout = CDR_T_idle;
						pcdr->get_state = ST_CDR_IDLE;
					} else if (rest <= 50) {
						pcdr->get_state = ST_GET_CDR;
					} else {
						cdr_request(pcdr);
						pcdr->get_state = ST_WAIT_CDR;
					}

				}

				/***************************************/
				//tail get response--------------------->
				/***************************************/
				else if (memcmp
						 (cdrmsg.var[0].oid, pcdr->tail_oid,
						  4 * pcdr->oid_len) == 0)
					//tail_get-response
				{
					if (cdrmsg.var_num != 2)
						break;

					if (cdrmsg.var[0].msglen > 4)
						break;

					tail =
						decode_integer(cdrmsg.var[0].msg,
									   cdrmsg.var[0].msglen);

					if (tail > MAX_CDR_PTR)	
					{
						if (pcdr->instance >= 0) {
							//#if CDR_DEBUG
							cdr_log
								("CDR Server(IP:%lX) Restart.Set sequence=%d(%s-%d),tail=%d\n",
								 pcdr->addr.remote_ip, pcdr->instance,
								 pcdr->record_table, pcdr->sysid,tail);
							//#endif
							move_head(pcdr);
						} else {
							//#if CDR_DEBUG
							cdr_log
								("CDR Server(IP:%lX) Startup.Set sequence=0(%s-%d),tail=%d\n",
								 pcdr->addr.remote_ip, pcdr->record_table,
								 pcdr->sysid,tail);
							//#endif
					
							pcdr->instance = 0;
							alter_ptr(pcdr);
						}
						return;
					} else {
						//MSS已经正常运行，EMS刚启动，则收到的第一条尾指针response就把尾指针赋给当前指针
						if (pcdr->instance == -1)
							pcdr->instance = tail;
						pcdr->get_state = ST_GET_CDR;
						//#if CDR_DEBUG
						cdr_log
							("Establish connection to CDR Server(IP:%lX %s-%d)\n",
							 pcdr->addr.remote_ip, pcdr->record_table,
							 pcdr->sysid);
						cdr_log("tail:%d(%s-%d)\n", pcdr->instance,
								pcdr->record_table, pcdr->sysid);
						//#endif
					}

				}
				/***************************************/
				//unknown response--------------------->
				/***************************************/
				//else
				//	break;

			}
			//set response
			//设置尾指针参数的response 
			else if (cdrmsg.request_id == pcdr->set_rid)
			{
				pcdr->set_rid = 0;
				if (memcmp
					(cdrmsg.var[0].oid, pcdr->tail_oid,
					 4 * pcdr->oid_len) != 0)
					break;

				pcdr->set_fail = 0;
				pcdr->move_flag = 0;
				pcdr->set_timeout = -1;
				pcdr->set_state = ST_TAIL_IDLE;
			}

			/*
			if (pcdr->maxbind > 1 && (cdrlen > 1200 || cdrmsg.error_status == 1))	//too big
				pcdr->maxbind--;
			else if (cdrlen > 0 && cdrlen < 800 && pcdr->maxbind < 20)
				pcdr->maxbind++;
			*/
		}
	}
}

/*************************************************
Function:        // digits2str
Description:     // 把字节数组转换成16进制字符串
Calls:           // 
Called By:       // cdr_process
Table Accessed:  // 
Table Updated:   // 
Input:           // buf:字节数组; len:长度
Output:          // 
Return:          // 
Others:          //
*************************************************/
static char *digits2str(BYTE * buf, int len)
{
	int i;
	static char dig[512]="", temp[5];
	char *pchr;
	dig[0] = '\0';
	for (i = 0; i < len / 2; i++) {
		sprintf(temp, "%X%X", buf[i] & 0xf, (buf[i] & 0xf0) >> 4);
		strcat(dig, temp);
	}

	if ((pchr = strchr(dig, 'F')) != NULL)
		pchr[0] = '\0';
	if ((pchr = strchr(dig, 'E')) != NULL)
		pchr[0] = '\0';

	return dig;
}

/*************************************************
Function:        // bcd2str
Description:     // 把BCD码字节数组转换成16进制字符串
Calls:           // 
Called By:       // cdr_process
Table Accessed:  // 
Table Updated:   // 
Input:           // buf:字节数组; len:长度
Output:          // 
Return:          // 
Others:          //
*************************************************/
char *bcd2str(BYTE * buf, int len)
{
	int i;
	static char str[1024] = "\0";
	for (i = 0; i < len; i++)
		sprintf(str + 2 * i, "%02X", buf[i]);
	return str;
}

BYTE *str2bcd(char *str, int len)
{
	int i;
	char ch;
	int in;
	static BYTE bcdbuf[1024];
	for (i = 0; i < len/2; i++){
		ch=str[2*i];
		
		if ((ch >= '0') && (ch <= '9'))
			ch -= '0';
		else if ((ch >= 'A') && (ch <= 'F'))
			ch -= 'A' - 10;
		else if ((ch >= 'a') && (ch <= 'f'))
			ch -= 'a' - 10;
		else
			ch = 0;
		
		in=(ch<<4)&0xf0;
		
		
		ch=str[2*i+1];
		if ((ch >= '0') && (ch <= '9'))
			ch -= '0';
		else if ((ch >= 'A') && (ch <= 'F'))
			ch -= 'A' - 10;
		else if ((ch >= 'a') && (ch <= 'f'))
			ch -= 'a' - 10;
		else
			ch = 0;
		in=in|(ch&0x0f);
		
		bcdbuf[i]=(unsigned char*)in;
		
	}
	return bcdbuf;
}

/*************************************************
Function:        // cdr_process
Description:     // 解析接收到的数据，并把数据存入数据库
Calls:           // 
Called By:       // pcdr:CDR数据源指针; serial; pmsg; msglen
Table Accessed:  // 
Table Updated:   // 
Input:           // buf:字节数组; len:长度; serial:序列号; pmsg:消息指针; msglen:消息长度
Output:          // 
Return:          // 1:successful; 0:failed
Others:          //
*************************************************/
int cdr_process(cdr_src * pcdr, int serial, BYTE * pmsg, WORD msglen)
{
	int i, j,k, len, tagcode;
	BYTE temp;
	ASN_BUF asn_buf;
	cdr_def *pdef;
	char sqlbuf[2048] = "\0", sqlstr[2048] =
		"\0", tempstr[256], str[256], sqlstr2[1024];
	
	int tempint, errpos;
	BYTE tempbyte[256];
	char tag_seq[20], tb_name[50];
	long ltime;
	struct tm *t;
	ltime = time(NULL);
	t = localtime(&ltime);
	
	//for smlog
	int isSMLOG=0;
	unsigned char smlog_smdcs_value=0;
	int smlog_smdcs_decode_type=0;		//1-7bit, 2-8bit, 3-unicode
	
	//for NRTRDE
	char roam_sqlstr[2048] = "\0";	
	int isMSC;
	int isRoamCDR;
	//char cdr_imsi[64];
	char roam_field_set[2048];
	char mcc[8];
	char mnc[8];
	int index;
	
	//根据当前的时间确定CDR数据表名
	sprintf(tb_name, "%s_%02d", pcdr->record_table, t->tm_hour);

	//解析数据
	if (AsnDecode(pmsg, msglen, 1, &errpos, &asn_buf) < 0
		&& errpos < msglen) {
		cdr_log("Wrong encoding of CDR Message.ip=%lX(%s-%d)\n",
				pcdr->addr.remote_ip, pcdr->record_table, pcdr->sysid);
		cdr_logmsg(pmsg, msglen);
		return 0;
	}

	if (gettagcode(pmsg, &tagcode, &temp) < 1)
		return 0;

	if (tagcode < 0 || tagcode >= CDR_TYPE_NUM)
		return 0;

	//获得该CDR数据源的表格定义结构
	pdef = &pcdr->define;
	if (!pdef->valid[tagcode]) {
		cdr_log("CDR type(type=%d) is Not defined.ip=%lX(%s-%d)\n",
				tagcode, pcdr->addr.remote_ip, pcdr->record_table,
				pcdr->sysid);
		return 0;
	}
	
	isMSC=0;
	isRoamCDR=0;
	//If this cdr is MSC cdr
	if(strcmp(pcdr->define_table,"mscCdrDefine") ==0)
	{
		isMSC=1;
	}	
	
	//If this cdr is VLR cdr
	if(strcmp(pcdr->define_table,"vlrCdrDefine") == 0 && wsms_enable_flag)
	{
		//int cdr_process(cdr_src * pcdr, int serial, BYTE * pmsg, WORD msglen)
		getVlrCdr(pcdr, serial, pmsg, msglen);
	}	

	for (i = 0; i < pdef->field_count; i++) {
		if (strlen(pdef->obj[i].tag_seq[tagcode]) == 0) {
			strcat(sqlbuf, "NULL,");
			continue;
		}
		
		
		
		//If this cdr is smlog cdr
		if(strcmp(pcdr->define_table,"smlogCdrDefine") == 0)
		{
			//printf("This is a smlogcdr\n");
			//Get the smcontent tlv
			if(strcmp(pdef->obj[i].field_name,"smcontent") == 0)	
			   isSMLOG=1;
			//Get the smdcs tlv
			if(strcmp(pdef->obj[i].field_name,"smdcs") == 0)
			   if ((len = get_tlv(pdef->obj[i].tag_seq[tagcode], tempbyte, &asn_buf)) > 0)
			 	smlog_smdcs_value=atoi(bcd2str(tempbyte,len));
		}

		switch (pdef->obj[i].type) {
		case 0:				//string
			if ((len =
				 get_tlv(pdef->obj[i].tag_seq[tagcode], tempstr,
						 &asn_buf)) > 0) {
				tempstr[len] = '\0';
				sprintf(str, "'%s',", tempstr);
			} else
				sprintf(str, "NULL,");
			break;
		case 1:				//integer
			if ((get_int_v2
				 (pdef->obj[i].tag_seq[tagcode], &tempint, &asn_buf)) >= 0)
				sprintf(str, "%d,", tempint);
			else
				sprintf(str, "NULL,");
			break;
		case 2:				//BCD 
			
			
			//The system need to decode the content of smlog cdr
			if(isSMLOG == 1 && smlog_decode_flag == 1)
			{
				if ((len = get_tlv(pdef->obj[i].tag_seq[tagcode], tempbyte, &asn_buf)) > 0)
				{	
					//Get the decode type,1-7bit, 2-8bit, 3-unicode
					smlog_smdcs_decode_type=((smlog_smdcs_value & 0x0C)>>2)+1;
					//printf("decode type=%d\n",smlog_smdcs_decode_type);	
					if(smlog_smdcs_decode_type==1 || smlog_smdcs_decode_type==2)
					{	
						//printf("BCD ---> 7bit or 8bit\n");
						if(smsDecodeAll(smlog_smdcs_decode_type,tempbyte,tempstr,len)>0)
						{	
							sprintf(str, "'%s',",tempstr);
						}
						else
							sprintf(str, "decode error,");		
					}
					else if(smlog_smdcs_decode_type == 3)
					{
						//printf("unicode to unicode\n");
						sprintf(str,"'%s',",bcd2str(tempbyte, len));
					}	
				}
				else
					sprintf(str, "NULL,");
				isSMLOG=0;
  			}
			//The system no need to decode the content of smlog cdr
			else
			{	
				if ((len =
				 	get_tlv(pdef->obj[i].tag_seq[tagcode], tempbyte,
							 &asn_buf)) > 0)
					sprintf(str, "'%s',", bcd2str(tempbyte, len));
					
					
				else
					sprintf(str, "NULL,");
			}
			break;
			
			
			
			/*
			if ((len =
				 get_tlv(pdef->obj[i].tag_seq[tagcode], tempbyte,
						 &asn_buf)) > 0)
				sprintf(str, "'%s',", bcd2str(tempbyte, len));
			else
				sprintf(str, "NULL,");
			break;
			*/
		case 3:				//timestamp
			if ((len =
				 get_tlv(pdef->obj[i].tag_seq[tagcode], tempbyte,
						 &asn_buf)) > 0) {
				sprintf(str, "'%02x-%02x-%02x %02x:%02x:%02x',",
						tempbyte[0], tempbyte[1], tempbyte[2], tempbyte[3],
						tempbyte[4], tempbyte[5]);

				if (strstr(pdef->obj[i].field_name, "releaseTime"))
					sprintf(tb_name, "%s_%02X", pcdr->record_table,
							tempbyte[3]);
			} else
				sprintf(str, "NULL,");
			break;
		case 4:				//MSISDN
			if ((len =
				 get_tlv(pdef->obj[i].tag_seq[tagcode], tempbyte,
						 &asn_buf)) > 0)
				sprintf(str, "'%s',",
						digits2str(tempbyte + 1, (len - 1) * 2));
			else
				sprintf(str, "NULL,");
			break;
		// Zed msc sms cdr use ascii calling number ---
		case 42: // CallingNumber
			if ((len =
					 get_tlv(pdef->obj[i].tag_seq[tagcode], tempbyte,
							 &asn_buf)) > 0)
				if (tempbyte[0] == 0xAA)
					snprintf(str, sizeof(str), "'%.*s',", (len - 1), tempbyte + 1);
				else
					sprintf(str, "'%s',",
							digits2str(tempbyte + 1, (len - 1) * 2));
			else
				sprintf(str, "NULL,");
			break;
		// ---end 	
		case 40:				//IMSI
			if ((len =
				 get_tlv(pdef->obj[i].tag_seq[tagcode], tempbyte,
						 &asn_buf)) > 0)
			{			 
				sprintf(str, "'%s',", digits2str(tempbyte, len * 2));
				
				if(isMSC)
				{
					//compare the local_mcc and local_mnc with mcc mnc
					for(index=1;index<4;index++)
					{
						mcc[index-1]=str[index];
					}
					mcc[index-1]='\0';
					
					for(index=4;index<6;index++)
					{
						mnc[index-4]=str[index];
					}
					mnc[index-4]='\0';
						
					if(strcmp(mcc,local_mcc) != 0 || strcmp(mnc,local_mnc) != 0)
					{
						isRoamCDR=1;
					}	
				}	
				
			}
			else
			{	
				sprintf(str, "NULL,");
			}
			break;
		case 41:				//RoutingNumber
			sprintf(tag_seq, "%s.1", pdef->obj[i].tag_seq[tagcode]);	//RoamingNumber
			if ((len = get_tlv(tag_seq, tempbyte, &asn_buf)) > 0)
				sprintf(str, "'RM:%s',",
						digits2str(tempbyte + 1, (len - 1) * 2));
			else {
				sprintf(tag_seq, "%s.2", pdef->obj[i].tag_seq[tagcode]);	//ForwardToNumber 
				if ((len = get_tlv(tag_seq, tempbyte, &asn_buf)) > 0)
					sprintf(str, "'FW:%s',",
							digits2str(tempbyte + 1, (len - 1) * 2));
				else
					sprintf(str, "NULL,");
			}
			break;
		case 5:				//trunkgroup
			sprintf(tag_seq, "%s.0", pdef->obj[i].tag_seq[tagcode]);	//integer
			if ((tempint = get_int(tag_seq, &asn_buf)) >= 0)
				sprintf(str, "%d,", tempint);
			else {
				sprintf(tag_seq, "%s.1", pdef->obj[i].tag_seq[tagcode]);
				if ((len = get_tlv(tag_seq, tempstr, &asn_buf)) > 0) {
					tempstr[len] = '\0';
					sprintf(str, "'%s',", tempstr);
				} else
					sprintf(str, "NULL,");
			}
			break;
		case 6:				//BasicServiceCode
			sprintf(tag_seq, "%s.2", pdef->obj[i].tag_seq[tagcode]);	//integer
			if ((len = get_tlv(tag_seq, tempbyte, &asn_buf)) < 0) {
				sprintf(tag_seq, "%s.3", pdef->obj[i].tag_seq[tagcode]);
				len = get_tlv(tag_seq, tempbyte, &asn_buf);
			}
			if (len > 0)
				sprintf(str, "%d,", tempbyte[0]);
			else
				sprintf(str, "NULL,");
			break;
		case 7:				//recordingEntity
			if ((len =
				 get_tlv(pdef->obj[i].tag_seq[tagcode], tempbyte,
						 &asn_buf)) > 0)
				sprintf(str, "'%s',", bcd2str(tempbyte + 1, len - 1));
			else
				sprintf(str, "NULL,");
			break;
		case 8:				//Diagnostics
			for (j = 0; j < 5; j++) {
				sprintf(tag_seq, "%s.%d", pdef->obj[i].tag_seq[tagcode], j);	//integer
				//cdr_log("j=%d,tag_seq = %s\n",j,tag_seq);
				if ((tempint = get_int(tag_seq, &asn_buf)) >= 0) {
					sprintf(str, "%d,", tempint);
					break;
				}
				if (j == 4)
					sprintf(str, "NULL,");
			}
			break;
		case 9:				  //LocationAreaAndCell
			{
				char tmpstr[22];
				int tmpint1=0,tmpint2=0;
				if(pdef->obj[i].tag_seq[tagcode]==NULL){
					sprintf(str, "NULL,");						
					break;
				}				
				sprintf(tmpstr,"%s.%d",pdef->obj[i].tag_seq[tagcode],0);
				if ((get_int_v2(tmpstr, &tmpint1, &asn_buf)) >= 0){
					;
				}else
					sprintf(str, "NULL,");					
				sprintf(tmpstr,"%s.%d",pdef->obj[i].tag_seq[tagcode],1);
				if ((get_int_v2(tmpstr, &tmpint2, &asn_buf)) >= 0){
					sprintf(str,"'%05d %05d',",tmpint1,tmpint2);
				}else
					sprintf(str, "NULL,");				
			break;	
			}
		case 10:				//SEQUENCE OF LocationChange
			break;
		case 11:				//SEQUENCE OF ChangeOfService
			break;
		case 12:				//SEQUENCE OF  SuppServiceUsed
			break;
		case 13:				//AOCParameters
			break;
		case 14:				//SEQUENCE OF AOCParmChange
			break;
		case 15:				//ChangeOfClassmark
			if ((len =
				 get_tlv(pdef->obj[i].tag_seq[tagcode], tempbyte,
						 &asn_buf)) > 0) {
				sprintf(str, "'[%02x][%02x][%02x]',",	tempbyte[0], tempbyte[1], tempbyte[2]);
			} else
				sprintf(str, "NULL,");			
			break;
		case 16:				//ChangeOfRadioChannel
			break;
		case 17:				//AdditionalChgInfo
			break;
		case 18:				//ManagementExtensions
			break;
		case 19:				//SEQUENCE OF HSCSDParmsChange
			break;
		case 20:				//SEQUENCE OF ChannelCoding
			break;
		case 21:				//LevelOfCAMELService(bit string)
			break;
		case 22:				//SEQUENCE OF CAMELInformation
			break;
		case 23:				//SmRslf 
			if(pdef->obj[i].tag_seq[tagcode]==NULL){
				sprintf(str, "NULL,");						
				break;
			}
			for(k=0;k<5;k++){
				char tmpstr[22]="";
				sprintf(tmpstr,"%s.%d",pdef->obj[i].tag_seq[tagcode],k);
				if ((get_int_v2(tmpstr, &tempint, &asn_buf)) >= 0){
					sprintf(str, "'%02d %02d',",k+7,tempint);
					break;			
				}
				if (k == 4)
					sprintf(str, "NULL,");						
			}
			break;
		}
		strcat(sqlbuf, str);
	}
	len = strlen(sqlstr);
	sqlbuf[len - 1] = '\0';
	

	//把记录插如表格
	sprintf(sqlstr, "REPLACE INTO %s.%s %s VALUES(%d,%d,%s'%s')",
			CDRDB_NAME, tb_name, pdef->field_set, pcdr->sysid, serial,
			sqlbuf, bcd2str(pmsg, msglen));
	
	//cdr_log("%s\n",sqlstr);
	if(isRoamCDR && isMSC)
	{	
		if(sqlbuf[0] == 0x31 || sqlbuf[0] == 0x30 || sqlbuf[0] == 0x36 || sqlbuf[0] == 0x37)
		{	
			sprintf(roam_field_set,"(mcc,mnc,%s",&(pdef->field_set[1]));
			
			sprintf(roam_sqlstr, "REPLACE INTO %s.cdrFromMSCSend %s VALUES('%s','%s',%d,%d,%s'%s')",
				CDRDB_NAME, roam_field_set, mcc, mnc, pcdr->sysid, serial, sqlbuf, bcd2str(pmsg, msglen));

			mysql_query(pCdrConn, roam_sqlstr);
			
		}	
	}
	if (mysql_query(pCdrConn, sqlstr) != 0) {
		switch (mysql_errno(pCdrConn)) {
		//没有此表格，创建一个新表
		case 1146:				
			sprintf(sqlstr2, "CREATE TABLE IF NOT EXISTS %s.%s %s",
					CDRDB_NAME, tb_name, pdef->create_sql);
			cdr_log("%s\n", sqlstr2);
			if (mysql_query(pCdrConn, sqlstr2) == 0)
				mysql_query(pCdrConn, sqlstr);
			else {
				cdr_log("Fail to create table:%s\n",
						mysql_error(pCdrConn));
				return 0;
			}
			break;
		default:
			cdr_log("Fail to insert cdr:%s--", mysql_error(pCdrConn));
			#if CDR_DEBUG
			cdr_log("%s\n", sqlstr);
			#endif
			return 0;
		}
	}
	return 1;
}

/* Decode the content of the SMLOG CDR */
int smsDecodeAll(int code_type,char* strIn,char* strOut,int length)
{
	int i,n,j;
	int len;
	unsigned char mid1,mid2,cur;
	unsigned char strHex[512];
	if(code_type>1 && code_type<4)
	{
		memcpy(strOut,strIn,length);
		return length;
	}
	else if(code_type>=4)
	{
		return 0;
	}

	n=0;j=0;
	len=length;
	if(len>140)
		len=140;
	memcpy(strHex,strIn,len);

	for(i=0;i<=len;i++)
	{
		if(i>0)
		{
			mid1=strHex[i];
			mid2=strHex[i-1];
			cur=((mid1<<n)&0x7f) | (mid2>>(8-n));
		}
		else
		{
			mid1=strHex[i]&0x7f;
			cur=mid1;
		}
		strOut[j++]=cur;
		n=(n+1)%8;
		if(n==0)
			i--;
	}
		
	for(i=0;j<j;i++)
	{
		switch(strOut[i])
		{
			case 0x02:
				strOut[i]='$';
				break;
			case 0x00:
				strOut[i]='@';
				break;
			case 0x11:
				strOut[i]='-';
				break;
			case 0x2F:
				strOut[i]='/';
				break;
			default:
				break;	
		}
	}

	strOut[length*8/7]=0;
	return length*8/7;
}


/*****************************************************************/
/*****************************  WSMS  ****************************/
/*****************************************************************/ 
void getVlrCdr(cdr_src * pcdr, int serial, BYTE * pmsg, WORD msglen)
{
	ASN_BUF asn_buf;
	BYTE temp;
	cdr_def *pdef;
	BYTE tempbyte[256];
	char tag_seq[20];
	int errpos;
	int tagcode;
	int i,j;
	int len;
	int tempint;
	char msisdn[64]="\0";
	char imsi[64]="\0";
	int diagnostics=-1;

	//printf("table=%s\n",pcdr->define_table);
	if (AsnDecode(pmsg, msglen, 1, &errpos, &asn_buf) < 0 && errpos < msglen) 
	{
		cdr_log("Wrong encoding of CDR Message.ip=%lX(%s-%d)\n",
				pcdr->addr.remote_ip, pcdr->record_table, pcdr->sysid);
		
		return;
	}
	if (gettagcode(pmsg, &tagcode, &temp) < 1)
		return;
	if (tagcode < 0 || tagcode >= CDR_TYPE_NUM)
		return;	
	
	pdef = &pcdr->define;
	if (!pdef->valid[tagcode]) 
	{
		cdr_log("CDR type(type=%d) is Not defined.ip=%lX(%s-%d)\n",
				tagcode, pcdr->addr.remote_ip, pcdr->record_table,
				pcdr->sysid);
		return;
	}
	for (i = 0; i < pdef->field_count; i++) 
	{
		if (strlen(pdef->obj[i].tag_seq[tagcode]) == 0) 
		{
			continue;
		}
		//printf("field_name=%s\n",pdef->obj[i].field_name);
		
		
		switch (pdef->obj[i].type) 
		{
			//servedMSISDN
			case 4:
				if ((len = get_tlv(pdef->obj[i].tag_seq[tagcode], tempbyte, &asn_buf)) > 0)
				{
					if(strcmp(pdef->obj[i].field_name,"servedMSISDN") == 0)
						sprintf(msisdn, "%s", digits2str(tempbyte + 1, (len - 1) * 2));
				}
				else
					return;
				break;
				
			//diagnostics	
			case 8:
				if(strcmp(pdef->obj[i].field_name,"diagnostics") == 0)
				{	
					for (j = 0; j < 5; j++) 
					{
						sprintf(tag_seq, "%s.%d", pdef->obj[i].tag_seq[tagcode], j);	//integer
						if ((tempint = get_int(tag_seq, &asn_buf)) >= 0) 
						{
							diagnostics=tempint;
							break;
						}
						if (j == 4)
							;
					}
				}	
				break;
			
			//servedIMSI		
			case 40:	
				if ((len = get_tlv(pdef->obj[i].tag_seq[tagcode], tempbyte, &asn_buf)) > 0)
				{			 
					sprintf(imsi, "%s", digits2str(tempbyte, len * 2));
				}
				else
				{	
					return;
				}
				break;		
		}
	}
	if(diagnostics !=-1 && strcmp(msisdn,"\0") != 0 && strcmp(imsi,"\0") != 0)
	{
		if(diagnostics == 2)
			wsms_check_sub(imsi,msisdn);		
	}
}
                         
int wsms_check_sub(char* imsi,char* msisdn)
{
	MYSQL_RES *res;
	MYSQL_ROW row;
	char sqlstr[128];	
	int count=0;
	
	sprintf(sqlstr,
                 "SELECT imsi,logTime FROM OMC_PUB.wsmsRoamer WHERE imsi='%s'",imsi);

	if(mysql_query(pubConn, sqlstr) != 0){
	  	cdr_log("%s\n", mysql_error(pubConn));
		return 1;
	}
	if((res = mysql_store_result(pubConn)) == NULL){
		return 1;
	}

	count=0;
	while((row = mysql_fetch_row(res)) != NULL)
	{
		count++;
	}
	mysql_free_result(res);
	
	//if the sub not exist,insert record into table ,return 0
	if(count==0)
	{
		sprintf(sqlstr,"REPLACE INTO OMC_PUB.wsmsRoamer (imsi,msisdn,flag,logTime)VALUES(%s,%s,0,FROM_UNIXTIME(%ld))",
				imsi,msisdn,time(NULL));
		if (mysql_query(pubConn, sqlstr) != 0) 
		{
			cdr_log("MySql errno:%d",mysql_errno(pubConn));
		}
		return 0;
	}	
	//if the sub exist return 1
	else if(count>=1)
	{	
		return 1;
	}
	return 1;
}
int initWSMSConf(void)
{
	char fileName[512];
	unsigned char buf[4096];
	unsigned char param[32][512];
	char paramName[128];
	char paramValue[384];
	char* temp;
	FILE* fp;
	int fi;
	int i;
	//int j;
	int paramCount;
	int byteCount;
	
	paramCount=0;
	byteCount=0;
	memset(buf,0,4096);
	memset(param,0,32*512);
	sprintf(fileName,"./conf/welcomeSMS.conf");
	fp=fopen(fileName,"r");
	if(fp)
	{		
		fi=fileno(fp);
		if(read(fi,buf,4096))
		{
			for(i=0;i<4096;i++)
			{
				
				if(buf[i] == 0x0A)
				{
					//printf("\n");
					if(byteCount<512 && param[paramCount][0] != 0x00 && param[paramCount][0] != 0x23)
						paramCount++;
					else
						memset(param[paramCount],0,512);	
					byteCount=0;
				}	
				else
				{	
					param[paramCount][byteCount]=buf[i];
					byteCount++;
				}
				
				//printf("%02x ",buf[i]);
			}

			
			for(i=0;i<paramCount;i++)
			{
				temp=strtok(param[i],"=");
				sprintf(paramName,"%s",temp);
				//printf("Name=%s,",temp);
				temp=strtok(NULL,"=");
				sprintf(paramValue,"%s",temp);
				//printf("Value=%s\n",temp);

				if(strcasecmp(paramName,"flag") == 0)
				{
					wsms_enable_flag=atoi(paramValue);
				}	
			}

		}	
		close(fi);
		fclose(fp);
	}	
	else
	{
		cdr_log("Fatal Error: The welcomeSMS.conf does not exist!");
		wsms_enable_flag=0;
	}		
	
	return 1;
}


void converseFile()
{
	int i;
	FILE *cdrFile;
	char tb_name[128];
	char csv_path[128];
	char inputBuf[8192];
	char *tmpInputBuf;
	char *sysId=NULL;
	char *instanceNo = NULL;
	cdr_src *pcdr;
	
	BYTE srcCodeByte[4096];
	
	for(i=0;i<CDR_SRC_NUM;i++){
		pcdr=&CdrSet[i];
		if(pcdr->sysTypeNo==320)
			break;
	}
	
	cdrFile =fopen(totalCdrFileName, "r");
	while(fgets(inputBuf, 8192, cdrFile) !=
		NULL) {
	
		if (inputBuf[0] == '#') {
			continue;
		}
		i = strlen(inputBuf);
		if (inputBuf[i - 1] == '\n')
			inputBuf[i - 1] = '\0';
		
		
		tmpInputBuf=inputBuf;
		sysId=strsep(&(tmpInputBuf), " \t");
		pcdr->sysid=atoi(sysId);
		instanceNo=strsep(&(tmpInputBuf), " \t");
		while ((strsep(&(tmpInputBuf), "\t"))){
			if(!strstr(tmpInputBuf,"\t"))
				break;
		}
		
		//printf("instanceNo=%s\n",instanceNo);
		//printf("tmpInputBuf=%s\n",tmpInputBuf); 
		//printf("tmpInputBuf=%s\n",bcd2str(str2bcd(tmpInputBuf,strlen(tmpInputBuf)),strlen(tmpInputBuf)/2));
		cdr_process(pcdr,atoi(instanceNo),str2bcd(tmpInputBuf,strlen(tmpInputBuf)),strlen(tmpInputBuf)/2);
		//break;
	}
	
	fclose(cdrFile);	
	sprintf(tb_name,"%s_%02d",pcdr->record_table,cdrHour);
	//printf("tb_name=%s\n",tb_name);
	if(pcdr->cdr_ver==1)
		create_dat_for_wxc1(tb_name, "/tmp/afterConverseCdrFiles",1,pcdr->define.field_select);
	else
		create_csv(tb_name, "/tmp/afterConverseCdrFiles",1,pcdr->define.field_select);
	clear_table(tb_name);
	return;
}
