#include "cdr.h"

extern void cdrdb_init();
extern void cdrdb_timer();
extern void cdr_clock_init(int tc_sec);

char globalstr[8192];
char sqlstr[8192];
char nrtrdesqlstr[8192];
char mtsmssqlstr[8192];
cdr_src cdr_src_set[MAX_SRC_NUM];
int cdr_src_num=0;
cdr_sys cdr_sys_set[MAX_SYS_NUM];
int cdr_sys_num=0;

msg snmp_msg_set[MAX_SNMP_MSG_NUM];
int snmp_msg_num=0;

sql_comm_buf sql_comm_buffer;

static int sys_index;
static cdr_sys *psys=NULL;
static unsigned long prev_time=0;
static unsigned long curr_time=0;
static unsigned long time_slot=0;

static int cdr_sync_data_id=-1;
//dual mode
int omcSysNo=-1;
int getOmcSysNo(int* sysNo);
int getOmcStatus(int sysNo);

//heartbeat
DWORD PROC_HEARTBEAT_OID[12]={1,3,6,1,4,1,1373,2,4,10,6};
int PROC_HEARTBEAT_OIDLEN=11;
unsigned long heartbeat_timeout=0;
int sendHeartbeat();

//smlog content parse
int smlog_decode_flag=0;
void getConfFromDB();

//for NRTRDE
int nrtrde_flag=0;
char local_mcc[8];
char local_mnc[8];
char mcc[8];
char mnc[8];
int isRoamCDR=0;
int initNRConf(void);

//for wsms
int wsms_enable_flag;
void getVlrCdr(cdr_sys* psys,int serial,BYTE * pmsg,WORD msglen,int tagcode);
int wsms_check_sub(char* imsi,char* msisdn);
int initWSMSConf(void);
int formatSingleQuotation(char *inbuf,int inlen,char* outbuf);

//for mt sms charge
int mt_sms_charge_flag=0;
#define MT_SMS_CHARGE_TABLE "mt_sms_cdr"

void cdr_log(const char *fmt, ...);
void cdr_logmsg(BYTE* msgbuf,int len);
void load_cdr_info();
void load_sys_info();
void get_info(cdr_sys *psys);
void cdr_receive();
int get_msg(cdr_sys *psys);
void check_pointer(cdr_sys *psys,snmp_pdu *pdu);
int parse_info(snmp_pdu *pdu,DWORD *head,DWORD *tail);
void get_cdr(cdr_sys *psys);
void set_cdr_tail(cdr_sys *psys);
void reset_cdr_pointer(cdr_sys *psys);
void cdr_process(cdr_sys *psys,snmp_pdu *pdu);
void load_cdr_def(cdr_src *psrc);
void create_record_table(cdr_src *psrc,MYSQL *pCdrConn);
void send_sql_comm(char *sqlcomm);
void cdr_parse(cdr_sys *psys,int tagcode,ASN_BUF *asnbuf,int fieldIndex,char* fieldstr);

BYTE str2oid(char *str, DWORD * array, BYTE max);
char *bcd2str(BYTE* buf,int len);
int smsDecodeAll(int code_type,char* strIn,char* strOut,int length);
char* digits2str(BYTE* buf,int len);

void test()
{
	cdr_sys sys;
	snmp_pdu pdu;
	int i,pos;
	
	pdu.error_status=0;
	pdu.var_num=1;
	pdu.var[0].vartype=4;
	pdu.var[0].msglen=0;
	pos=0;
	
	pdu.var[0].msg[pos++]=0x02;
	pdu.var[0].msg[pos++]=0x04;
	pdu.var[0].msg[pos++]=0x00;
	pdu.var[0].msg[pos++]=0x00;
	pdu.var[0].msg[pos++]=0x00;
	pdu.var[0].msg[pos++]=0x01;
	
	pdu.var[0].msg[pos++]=0xA0;
	pdu.var[0].msg[pos++]=0x60;
	pdu.var[0].msg[pos++]=0x80;
	pdu.var[0].msg[pos++]=0x01;
	pdu.var[0].msg[pos++]=0x12;
	pdu.var[0].msg[pos++]=0x81;
	pdu.var[0].msg[pos++]=0x06;
	pdu.var[0].msg[pos++]=0x91;
	pdu.var[0].msg[pos++]=0x76;
	pdu.var[0].msg[pos++]=0x76;
	pdu.var[0].msg[pos++]=0x47;
	pdu.var[0].msg[pos++]=0x64;
	pdu.var[0].msg[pos++]=0x54;
	pdu.var[0].msg[pos++]=0x82;
	pdu.var[0].msg[pos++]=0x06;
	pdu.var[0].msg[pos++]=0x91;
	pdu.var[0].msg[pos++]=0x76;
	pdu.var[0].msg[pos++]=0x76;
	pdu.var[0].msg[pos++]=0x77;
	pdu.var[0].msg[pos++]=0x33;
	pdu.var[0].msg[pos++]=0x86;
	pdu.var[0].msg[pos++]=0x83;
	pdu.var[0].msg[pos++]=0x09;
	pdu.var[0].msg[pos++]=0x12;
	pdu.var[0].msg[pos++]=0x04;
	pdu.var[0].msg[pos++]=0x26;
	pdu.var[0].msg[pos++]=0x16;
	pdu.var[0].msg[pos++]=0x39;
	pdu.var[0].msg[pos++]=0x43;
	pdu.var[0].msg[pos++]=0x2D;
	pdu.var[0].msg[pos++]=0x13;
	pdu.var[0].msg[pos++]=0x00;
	pdu.var[0].msg[pos++]=0x84;
	pdu.var[0].msg[pos++]=0x01;
	pdu.var[0].msg[pos++]=0x00;
	pdu.var[0].msg[pos++]=0x85;
	pdu.var[0].msg[pos++]=0x22;
	pdu.var[0].msg[pos++]=0x4F;
	pdu.var[0].msg[pos++]=0x34;
	pdu.var[0].msg[pos++]=0x28;
	pdu.var[0].msg[pos++]=0xFD;
	pdu.var[0].msg[pos++]=0x66;
	pdu.var[0].msg[pos++]=0xD1;
	pdu.var[0].msg[pos++]=0xDF;
	pdu.var[0].msg[pos++]=0xEB;
	pdu.var[0].msg[pos++]=0x37;
	pdu.var[0].msg[pos++]=0x3B;
	pdu.var[0].msg[pos++]=0x8C;
	pdu.var[0].msg[pos++]=0x4E;
	pdu.var[0].msg[pos++]=0x83;
	pdu.var[0].msg[pos++]=0xCC;
	pdu.var[0].msg[pos++]=0xEF;
	pdu.var[0].msg[pos++]=0x75;
	pdu.var[0].msg[pos++]=0x1A;
	pdu.var[0].msg[pos++]=0xB4;
	pdu.var[0].msg[pos++]=0x0E;
	pdu.var[0].msg[pos++]=0xD7;
	pdu.var[0].msg[pos++]=0x41;
	pdu.var[0].msg[pos++]=0xE6;
	pdu.var[0].msg[pos++]=0xFB;
	pdu.var[0].msg[pos++]=0x18;
	pdu.var[0].msg[pos++]=0x64;
	pdu.var[0].msg[pos++]=0x7E;
	pdu.var[0].msg[pos++]=0xAF;
	pdu.var[0].msg[pos++]=0xD3;
	pdu.var[0].msg[pos++]=0xA0;
	pdu.var[0].msg[pos++]=0x74;
	pdu.var[0].msg[pos++]=0x18;
	pdu.var[0].msg[pos++]=0x54;
	pdu.var[0].msg[pos++]=0x76;
	pdu.var[0].msg[pos++]=0x01;
	pdu.var[0].msg[pos++]=0x86;
	pdu.var[0].msg[pos++]=0x02;
	pdu.var[0].msg[pos++]=0x38;
	pdu.var[0].msg[pos++]=0x40;
	pdu.var[0].msg[pos++]=0x87;
	pdu.var[0].msg[pos++]=0x01;
	pdu.var[0].msg[pos++]=0x01;
	pdu.var[0].msg[pos++]=0x88;
	pdu.var[0].msg[pos++]=0x04;
	pdu.var[0].msg[pos++]=0x00;
	pdu.var[0].msg[pos++]=0x9D;
	pdu.var[0].msg[pos++]=0x82;
	pdu.var[0].msg[pos++]=0x21;
	pdu.var[0].msg[pos++]=0x89;
	pdu.var[0].msg[pos++]=0x09;
	pdu.var[0].msg[pos++]=0x12;
	pdu.var[0].msg[pos++]=0x04;
	pdu.var[0].msg[pos++]=0x26;
	pdu.var[0].msg[pos++]=0x16;
	pdu.var[0].msg[pos++]=0x39;
	pdu.var[0].msg[pos++]=0x37;
	pdu.var[0].msg[pos++]=0x2D;
	pdu.var[0].msg[pos++]=0x13;
	pdu.var[0].msg[pos++]=0x00;
	pdu.var[0].msg[pos++]=0x8A;
	pdu.var[0].msg[pos++]=0x01;
	pdu.var[0].msg[pos++]=0x00;
	
	pdu.var[0].msglen=pos;
	
	sys.cdrSrcNo=7;
	sys.sysTypeNo=351;
	sys.sysNo=0;
	sys.subSysNo=0;
	
	
	for(i=0;i<cdr_src_num;i++)
	{
		printf("sysTypeNo=%d,recordTable=%s,i=%d\n",cdr_src_set[i].sysTypeNo,cdr_src_set[i].recordTable,i);
	}
	
	cdr_process(&sys,&pdu);
	exit(1);
}

void cdr_init()
{
	printf("cdrCollector is starting ......\n");
	cdr_log("cdrCollector is starting ......");
	load_cdr_info();
	load_sys_info();
	curr_time=prev_time=time(NULL);
	
	initNRConf();
	initWSMSConf();
	
	getConfFromDB();
	
	getOmcSysNo(&omcSysNo);
	if(omcSysNo<0 || omcSysNo >1)
	{
		cdr_log("[ERR][cdr_init]:Fail to get the omcSysNo\n");
		exit(-1);
	}
	
	cdrdb_init();
	cdr_sync_data_id=sync_data_register("CDR_SYNC");
	
	//test();
}


void cdr_timer()
{
	int index;
	int omcStatus;
	static unsigned long update_sys_timeout=0;

	curr_time=time(NULL);
	if(curr_time < prev_time)
	{
		cdr_log("[ERR][cdr_timer]: The system time may be changed! curr_time=%d, prev_time=%d", curr_time, prev_time);
		prev_time=curr_time;
		
		cdr_clock_init(0);
		return;
	}
	time_slot=curr_time-prev_time;
	if(time_slot > 30)
	{
		/* Fixed for Norfolk EMS CDR lost issue by simon
		 * Store second number when time to be changed
		 * --begin
		 */
		cdr_log("[ERR][cdr_timer]: The previous timer consume too much time or the system time my be changed! prev_time=%d, time_slot=%d", prev_time, time_slot);
		/* --end
		 *
		 */
		cdr_clock_init(time_slot);
	}
	
	if(time(NULL) - heartbeat_timeout > 5)
	{
		heartbeat_timeout=time(NULL);
		sendHeartbeat();
	}
	
	cdrdb_timer();
	
	send_sql_comm(NULL);
	
	
	omcStatus=getOmcStatus(omcSysNo);
	
	if(omcStatus == OMC_MASTER || omcStatus == OMC_SINGLE)
	{
		update_sys_timeout+=time_slot;
		if(update_sys_timeout > 60)
		{
			update_sys_timeout=0;
			load_sys_info();
		}
		
		for(index=0;index<MAX_SNMP_MSG_NUM;index++)
		{
			snmp_msg_set[index].timeout-=time_slot;
			if(snmp_msg_set[index].use && snmp_msg_set[index].timeout <= 0)
			{
				snmp_msg_set[index].use=0;
				snmp_msg_num--;
				cdr_log("[WARN][get_msg]:SNMP msg[%d] has been discarded because timeout, request id=%ld",index,snmp_msg_set[index].pdu.request_id);
//printf("msg %ld has been discard\n",snmp_msg_set[index].pdu.request_id);
			}
		}
		
		//receive snmp msg
		if(snmp_msg_num < MAX_SNMP_MSG_NUM)
			cdr_receive();
		
		for(sys_index=0;sys_index<cdr_sys_num;sys_index++)
		{
			psys=&cdr_sys_set[sys_index];
			
			//check timeout
			if(psys->timeout > 0)
				psys->timeout-=time_slot;
			
			if(psys->timeout > 0)
				continue;
			switch(psys->state)
			{
			case STATE_IDLE:
				psys->state=STATE_INFO_GET;
				break;
			case STATE_INFO_GET:
				psys->state=STATE_INFO_RESPONSE;
				psys->retry=0;
				get_info(psys);
				break;
			case STATE_INFO_RESPONSE:
				if((index=get_msg(psys)) != -1)
				{
					snmp_msg_set[index].use=0;
					snmp_msg_num--;
					check_pointer(psys,&snmp_msg_set[index].pdu);
				}
				else
				{
					if(psys->retry++ > MAX_RETRY)
					{
						cdr_log("[ERR][cdr_receive]:GET_INFO_RESPONSE timeout, request id=%ld, %d-%d-%d",psys->requestId,psys->sysTypeNo,psys->sysNo,psys->subSysNo);
						psys->state=STATE_IDLE;
						psys->timeout=MAX_IDLE_TIMEOUT;
					}
				}
				break;
			case STATE_CDR_GET:
				psys->state=STATE_CDR_RESPONSE;
				psys->retry=0;
				get_cdr(psys);
				break;
			case STATE_CDR_RESPONSE:
				if((index=get_msg(psys)) != -1)
				{
					//get a cdr response
					cdr_process(psys,&snmp_msg_set[index].pdu);
					
					snmp_msg_set[index].use=0;
					snmp_msg_num--;
					
					if(psys->error >= 256)
					{
						psys->error=0;
						psys->state=STATE_RESET_SET;
						psys->retry=0;
						break;
					}
					
					if(psys->isVarTooBig)
					{
						psys->isVarTooBig=0;
						psys->tail=psys->tmptail;
						psys->prepareSetTail=0;
					}
					
					if(psys->prepareSetTail)
					{
						psys->prepareSetTail=0;
						psys->state=STATE_TAIL_SET;
						psys->retry=0;
					}
					else
					{
						psys->state=STATE_CDR_GET;
					}
					
				}
				else
				{
					if(psys->retry++ > MAX_RETRY)
					{
						cdr_log("[ERR][cdr_receive]:GET_CDR_RESPONSE timeout, request id=%ld, %d-%d-%d",psys->requestId,psys->sysTypeNo,psys->sysNo,psys->subSysNo);
						psys->state=STATE_IDLE;
						psys->timeout=MAX_IDLE_TIMEOUT;
					}
				}
				break;
			case STATE_TAIL_SET:
				psys->state=STATE_TAIL_RESPONSE;
				psys->retry=0;
				set_cdr_tail(psys);
				//set tail
				break;
			case STATE_TAIL_RESPONSE:
				if((index=get_msg(psys)) != -1)
				{
					snmp_msg_set[index].use=0;
					snmp_msg_num--;
					psys->state=STATE_IDLE;
					psys->timeout=INSTANT_TIMEOUT;
				}
				else
				{
					if(psys->retry++ > MAX_RETRY)
					{
						cdr_log("[ERR][cdr_receive]:STATE_TAIL_RESPONSE timeout, request id=%ld, %d-%d-%d",psys->requestId,psys->sysTypeNo,psys->sysNo,psys->subSysNo);
						psys->state=STATE_IDLE;
						psys->timeout=MAX_IDLE_TIMEOUT;
					}
				}
				break;
			case STATE_RESET_SET:
				psys->state=STATE_RESET_RESPONSE;
				psys->retry=0;
				reset_cdr_pointer(psys);
				break;
			case STATE_RESET_RESPONSE:
				if((index=get_msg(psys)) != -1)
				{
					snmp_msg_set[index].use=0;
					snmp_msg_num--;
					psys->state=STATE_IDLE;
					psys->timeout=INSTANT_TIMEOUT;
				}
				else
				{
					if(psys->retry++ > MAX_RETRY)
					{
						cdr_log("[ERR][cdr_receive]:STATE_RESET_RESPONSE timeout, request id=%ld, %d-%d-%d",psys->requestId,psys->sysTypeNo,psys->sysNo,psys->subSysNo);
						psys->state=STATE_IDLE;
						psys->timeout=MAX_IDLE_TIMEOUT;
					}
				}
				break;
			}
		}
	}
	
	prev_time=curr_time;
}

void set_cdr_tail(cdr_sys *psys)
{
	snmp_pdu request_msg;
	cdr_src *psrc;
	
	psrc=&cdr_src_set[psys->cdrSrcNo];
	request_msg.pdu_type=PDU_SET;
	
	memcpy(request_msg.var[0].oid,psrc->tailOid,4*psrc->tailOidLen);
	request_msg.var[0].oidlen=psrc->tailOidLen;
	
	sprintf(request_msg.community,"public");
	request_msg.var_num=1;
	request_msg.request_id=0;
	
	request_msg.var[0].vartype=2;						//Integer
	request_msg.var[0].msglen=4;
	request_msg.var[0].msg[0]=psys->tail >> 24;
	request_msg.var[0].msg[1]=(psys->tail >> 16) & 0xFF;
	request_msg.var[0].msg[2]=(psys->tail >> 8) & 0xFF;
	request_msg.var[0].msg[3]=psys->tail & 0xFF;
	
	psys->requestId=snmp_send(&request_msg,&psys->addr);
//printf("send msg1 %ld\n",psys->requestId);
#if CDR_DEBUG
	cdr_log("Set tail requst, request id=%ld, %d-%d-%d",psys->requestId,psys->sysTypeNo,psys->sysNo,psys->subSysNo);
#endif
	if(psys->requestId == 0)
	{
		cdr_log("[ERR][set_cdr_tail]:Send snmp request to set cdr tail pointer fail, %d-%d-%d",psys->sysTypeNo,psys->sysNo,psys->subSysNo);
	}
}

void reset_cdr_pointer(cdr_sys *psys)
{
	snmp_pdu request_msg;
	cdr_src *psrc;
	
	psrc=&cdr_src_set[psys->cdrSrcNo];
	request_msg.pdu_type=PDU_SET;
	
	memcpy(request_msg.var[0].oid,psrc->headOid,4*psrc->headOidLen);
	request_msg.var[0].oidlen=psrc->headOidLen;
	
	memcpy(request_msg.var[1].oid,psrc->tailOid,4*psrc->tailOidLen);
	request_msg.var[1].oidlen=psrc->tailOidLen;
	
	sprintf(request_msg.community,"public");
	request_msg.var_num=2;
	request_msg.request_id=0;
	
	request_msg.var[0].vartype=2;						//Integer
	request_msg.var[0].msglen=4;
	request_msg.var[0].msg[0]=0;
	request_msg.var[0].msg[1]=0;
	request_msg.var[0].msg[2]=0;
	request_msg.var[0].msg[3]=0;
	
	request_msg.var[1].vartype=2;						//Integer
	request_msg.var[1].msglen=4;
	request_msg.var[1].msg[0]=0;
	request_msg.var[1].msg[1]=0;
	request_msg.var[1].msg[2]=0;
	request_msg.var[1].msg[3]=0;
	
	psys->requestId=snmp_send(&request_msg,&psys->addr);
//printf("send msg2 %ld\n",psys->requestId);
#if CDR_DEBUG
	cdr_log("Reset pointer requst, request id=%ld, %d-%d-%d",psys->requestId,psys->sysTypeNo,psys->sysNo,psys->subSysNo);
#endif
	if(psys->requestId == 0)
	{
		cdr_log("[ERR][reset_cdr_pointer]:Send snmp request to reset cdr pointer fail, %d-%d-%d",psys->sysTypeNo,psys->sysNo,psys->subSysNo);
	}
}

void get_info(cdr_sys *psys)
{
	snmp_pdu request_msg;
	cdr_src *psrc;
	
	psrc=&cdr_src_set[psys->cdrSrcNo];
	request_msg.pdu_type=PDU_GET;
	//fill the get head var
	memcpy(request_msg.var[0].oid,psrc->headOid,4*psrc->headOidLen);
	request_msg.var[0].oidlen=psrc->headOidLen;
	
	//fill the get tail var
	memcpy(request_msg.var[1].oid,psrc->tailOid,4*psrc->tailOidLen);
	request_msg.var[1].oidlen=psrc->tailOidLen;
	
	sprintf(request_msg.community,"public");
	request_msg.var_num=2;
	request_msg.request_id=0;
	
	psys->requestId=snmp_send(&request_msg,&psys->addr);
//printf("send msg3 %ld\n",psys->requestId);
	if(psys->requestId == 0)
	{
		cdr_log("[ERR][get_info]:Send snmp request to get info fail, %d-%d-%d",psys->sysTypeNo,psys->sysNo,psys->subSysNo);
	}
#if CDR_DEBUG
	cdr_log("send info requst, request id=%ld",psys->requestId);
#endif
}

void get_cdr(cdr_sys *psys)
{
	snmp_pdu request_msg;
	cdr_src *psrc;
	DWORD chasePtr;
	int var_num=0;
	
	psrc=&cdr_src_set[psys->cdrSrcNo];
	request_msg.pdu_type=PDU_GET;
	request_msg.request_id=0;
	sprintf(request_msg.community,"public");
	
	if(psys->head < psys->tail)
		chasePtr=MAX_CDR_PTR;
	else
		chasePtr=psys->head;
	
	psys->tmptail=psys->tail;
	do
	{
		if(var_num >= psys->maxVarNum)
			break;
		memcpy(request_msg.var[var_num].oid,psrc->dataOid,4*psrc->dataOidLen);
		request_msg.var[var_num].oid[psrc->dataOidLen]=psys->tail;
		request_msg.var[var_num].oidlen=psrc->dataOidLen+1;
#if CDR_DEBUG
		cdr_log("Encode var to get cdr %ld[%08X], %d-%d-%d",psys->tail,psys->tail,psys->sysTypeNo,psys->sysNo,psys->subSysNo);
#endif
		psys->tail++;
		if(psys->tail > MAX_CDR_PTR)
			psys->tail=0;
		var_num++;
	}while(psys->tail < chasePtr);
	
	request_msg.var_num=var_num;
	psys->requestId=snmp_send(&request_msg,&psys->addr);
//printf("send msg4 %ld\n",psys->requestId);
#if CDR_DEBUG
	cdr_log("send data request, request id=%ld",psys->requestId);
#endif
	if(psys->requestId == 0)
	{
		cdr_log("[ERR][get_cdr]:Send snmp request to get cdr fail, %d-%d-%d",psys->sysTypeNo,psys->sysNo,psys->subSysNo);
	}
	
	if(psys->tail == chasePtr)
	{
		psys->prepareSetTail=1;
		//cdr_log("[INFO][get_cdr]:Finish to get cdr, start to set tail, %d-%d-%d",psys->sysTypeNo,psys->sysNo,psys->subSysNo);
		return;
	}
}

void load_cdr_def(cdr_src *psrc)
{
	MYSQL_RES *res_set;
	MYSQL_ROW row;
	MYSQL *pCdrConn;
	int tagvalue;
	cdr_def *pdef;
	char tagstr[256];
	char tmpstr[128];
	int i,pos;
	
	pCdrConn=mysql_conn(HOST_NAME,CDRDB_NAME);
	if(pCdrConn == NULL)
	{
		cdr_log("[ERR][load_cdr_def]:mysql_conn CDR_DB\n");
		exit(-1);
	}
	
	sprintf(sqlstr,"SHOW FIELDS FROM %s.%s LIKE 'tag%%'",CDRDB_NAME,psrc->defineTable);
	res_set=mysql_getres(pCdrConn,sqlstr);
	if(res_set == NULL)
	{
		cdr_log("[ERR %d][load_cdr_def]:%s\n",mysql_errno(pCdrConn),sqlstr);
		exit(-1);
	}
	
	pdef=&psrc->define;
	while((row = mysql_fetch_row(res_set))) 
	{
		tagvalue=atoi((char*)(row[0]+strlen("tag")));
		if(tagvalue >= MAX_TAG_VALUE)
		{
			cdr_log("[ERR][load_cdr_def]:The tag value define in %s is out of range[%d >= %d]",psrc->defineTable,tagvalue,MAX_TAG_VALUE);
			exit(-1);
		}
		pdef->tags[tagvalue]=1;
	}
	mysql_free_result(res_set);
	
//	memset(tagstr,0,strlen(tagstr));
	memset(tagstr,0,256);
	for(i=0;i<MAX_TAG_VALUE;i++)
	{
		if(pdef->tags[i])
		{
			sprintf(tmpstr,",tag%d",i);
			strcat(tagstr,tmpstr);
		}
	}
	
	sprintf(sqlstr,"SELECT fieldName,type,optional,width%s FROM %s.%s",tagstr,CDRDB_NAME,psrc->defineTable);
	res_set=mysql_getres(pCdrConn,sqlstr);
	if(res_set == NULL)
	{
		cdr_log("[ERR %d][load_cdr_def]:%s\n",mysql_errno(pCdrConn),sqlstr);
		exit(-1);
	}
	
	pdef->fieldCount=0;
	memset(pdef->allFieldList,0,strlen(pdef->allFieldList));
	strcat(pdef->allFieldList,"key_sys_id,instance,srcCode");
	while((row = mysql_fetch_row(res_set)))
	{
		sprintf(pdef->fields[pdef->fieldCount].fieldName,"%s",row[0]);
		sprintf(tmpstr,",%s",row[0]);
		strcat(pdef->allFieldList,tmpstr);
		pdef->fields[pdef->fieldCount].type=atoi(row[1]);
		pdef->fields[pdef->fieldCount].optional=atoi(row[2]);
		pdef->fields[pdef->fieldCount].width=atoi(row[3]);
		pos=4;
		for(i=0;i<MAX_TAG_VALUE;i++)
		{
			if(pdef->tags[i])
			{
				if(strlen(row[pos]) > 0)
				{
					pdef->fields[pdef->fieldCount].tagFlag[i]=1;
					sprintf(pdef->fields[pdef->fieldCount].tags[i],"%s",row[pos]);
				}
				else
				{
					pdef->fields[pdef->fieldCount].tagFlag[i]=0;
				}
				//cdr_log("%s,tags[%d]=%s,flag=%d",row[0],i,row[pos],pdef->fields[pdef->fieldCount].tagFlag[i]);
				pos++;
			}
		}
		
		pdef->fieldCount++;
		if(pdef->fieldCount >= MAX_FLD_NUM)
		{
			cdr_log("[ERR][load_cdr_def]:The field count define in %s is out of range [%d >= %d]",psrc->defineTable,pdef->fieldCount,MAX_FLD_NUM);
			exit(-1);
		}
	}
	mysql_free_result(res_set);
	
	sprintf(sqlstr,"SELECT fieldName FROM %s.%s WHERE fileOrder>0 ORDER BY fileOrder",CDRDB_NAME,psrc->defineTable);
	res_set=mysql_getres(pCdrConn,sqlstr);
	if(res_set == NULL)
	{
		cdr_log("[ERR %d][load_cdr_def]:%s\n",mysql_errno(pCdrConn),sqlstr);
		exit(-1);
	}
	
	memset(pdef->outFieldList,0,strlen(pdef->outFieldList));
	while((row = mysql_fetch_row(res_set)))
	{
		sprintf(tmpstr,",%s",row[0]);
		strcat(pdef->outFieldList,tmpstr);
	}
	mysql_free_result(res_set);
	
	create_record_table(psrc,pCdrConn);
	
	mysql_close(pCdrConn);
}

void create_record_table(cdr_src *psrc,MYSQL *pCdrConn)
{
	char createsql[8192];
	char createfieldlist[8192];
	char tmpstr[256];
	cdr_def *pdef;
	int hour;
	int index;
	
	pdef=&psrc->define;
	//memset(createfieldlist,0,strlen(createfieldlist));
	memset(createfieldlist,0,8192);
	memset(tmpstr,0,256);
	sprintf(tmpstr,"key_sys_id tinyint(2) DEFAULT '0' NOT NULL,instance int(4) DEFAULT '0' NOT NULL,");
	strcat(createfieldlist,tmpstr);
	for(index=0;index<pdef->fieldCount;index++)
	{
		sprintf(tmpstr,"%s ",pdef->fields[index].fieldName);
		strcat(createfieldlist,tmpstr);
		switch(pdef->fields[index].type) 
		{
		//string
		case 0:				
		case 2:
		case 4:
		case 24:
		case 26:
		case 40:
		case 41:
		case 7:
			if((pdef->fields[index].width) < 255)
				sprintf(tmpstr,"VARCHAR(%d)",pdef->fields[index].width);
			else
				sprintf(tmpstr,"TEXT");
			strcat(createfieldlist,tmpstr);
			break;
		//integer
		case 1:
		//unsigned integer
		case 25:
		case 6:
		case 8:
			sprintf(tmpstr,"int(%d)",pdef->fields[index].width);
			strcat(createfieldlist,tmpstr);
			break;
		case 5:
			strcat(createfieldlist,"VARCHAR(20)");
			break;
		//timestamp
		case 3:
			strcat(createfieldlist,"DATETIME DEFAULT '0000-00-00 00:00:00'");
			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(createfieldlist,"TEXT");
			break;
		case 21:
			strcat(createfieldlist,"VARCHAR(3)");
			break;
		}
		if(!pdef->fields[index].optional)
			strcat(createfieldlist, " NOT NULL");
		strcat(createfieldlist,",");
	}
	strcat(createfieldlist,"srcCode TEXT,PRIMARY KEY (key_sys_id, instance, releaseTime));");
	
	
	for(hour=0;hour<24;hour++)
	{
		//memset(createsql,0,strlen(createsql));
		memset(createsql,0,8192);
		sprintf(tmpstr,"CREATE TABLE IF NOT EXISTS %s.%s_%02d (",CDRDB_NAME,psrc->recordTable,hour);
		strcat(createsql,tmpstr);
		strcat(createsql,createfieldlist);
		if(mysql_getnores(pCdrConn,createsql) != 0)
		{
			cdr_log("[ERR][create_record_table]:Fail to create table '%s.%s_%02d'\n%s",CDRDB_NAME,psrc->recordTable,hour,createsql);
			exit(-1);
		}
	}
	
}

void load_cdr_info()
{
	MYSQL_RES *res_set;
	MYSQL_ROW row;
	MYSQL *pCdrConn;
	cdr_src *psrc=NULL;
	
	pCdrConn=mysql_conn(HOST_NAME,CDRDB_NAME);
	if(pCdrConn == NULL)
	{
		cdr_log("[ERR][load_cdr_info]:mysql_conn CDR_DB\n");
		exit(-1);
	}
	
	sprintf(sqlstr,"SELECT oid,bufSize,headOid,tailOid,port,recordTable,defineTable,csvPath,backupMax,version,sysTypeNo FROM %s.cdrSource where isEnable > 0 group by defineTable",CDRDB_NAME);
	res_set=mysql_getres(pCdrConn,sqlstr);
	if(res_set == NULL)
	{
		cdr_log("[ERR %d][load_cdr_info]:%s\n",mysql_errno(pCdrConn),sqlstr);
		exit(-1);
	}
	
	cdr_src_num=0;
	cdr_sys_num=0;
	memset(cdr_src_set,0,sizeof(cdr_src_set));
	memset(cdr_sys_set,0,sizeof(cdr_sys_set));
	memset(snmp_msg_set,0,sizeof(snmp_msg_set));
	memset(&sql_comm_buffer,0,sizeof(sql_comm_buffer));
	while((row = mysql_fetch_row(res_set))) 
	{
		psrc=&cdr_src_set[cdr_src_num];
		sprintf(psrc->dataPotOid,"%s",row[0]);
		psrc->bufferSize=atoi(row[1]);
		sprintf(psrc->headPotOid,"%s",row[2]);
		sprintf(psrc->tailPotOid,"%s",row[3]);
		sprintf(psrc->recordTable,"%s",row[5]);
		
		psrc->headOidLen=str2oid(row[2],psrc->headOid,20);
		psrc->tailOidLen=str2oid(row[3],psrc->tailOid,20);
		psrc->dataOidLen=str2oid(row[0],psrc->dataOid,20);
		
		sprintf(psrc->defineTable,"%s",row[6]);
		sprintf(psrc->csvPath,"%s",row[7]);
		psrc->version=atoi(row[9]);
		psrc->port=atoi(row[4]);
		psrc->sysTypeNo=atoi(row[10]);
		
		load_cdr_def(psrc);
		
		cdr_log("[INFO][load_cdr_info]:CDR SOURCE[%d], sysTypeNo=%d, dataOid[%d]=%s, headOid[%d]=%s, tailOid[%d]=%s, recordTable=%s, defineTable=%s, csvPath=%s, version=%d",
			cdr_src_num,psrc->sysTypeNo,psrc->dataOidLen,psrc->dataPotOid,psrc->headOidLen,psrc->headPotOid,psrc->tailOidLen,psrc->tailPotOid,psrc->recordTable,psrc->defineTable,psrc->csvPath,psrc->version);
		cdr_src_num++;
		if(cdr_src_num >= MAX_SRC_NUM)
		{
			cdr_log("[ERR][load_cdr_info]:There are too mang CDR SOURCE");
			break;
		}
	}
	
	mysql_free_result(res_set);
	mysql_close(pCdrConn);
}

void load_sys_info()
{
	MYSQL_RES *res_set;
	MYSQL_ROW row;
	MYSQL *pCdrConn;
	int sysTypeNo,sysNo,subSysNo;
	int i;
	
	pCdrConn=mysql_conn(HOST_NAME,CDRDB_NAME);
	if(pCdrConn == NULL)
	{
		cdr_log("[ERR][load_sys_info]:mysql_conn CDR_DB\n");
		exit(-1);
	}
	
	sprintf(sqlstr,"SELECT sysTypeNo,sysNo,subSysNo,ip FROM OMC_PUB.sysInfo");
	res_set=mysql_getres(pCdrConn,sqlstr);
	if(res_set == NULL)
	{
		cdr_log("[ERR %d][load_sys_info]:%s\n",mysql_errno(pCdrConn),sqlstr);
		exit(-1);
	}
	
	while((row = mysql_fetch_row(res_set))) 
	{
		sysTypeNo=atoi(row[0]);
		sysNo=atoi(row[1]);
		subSysNo=atoi(row[2]);
		
		for(i=0;i<cdr_sys_num;i++)
		{
			if(cdr_sys_set[i].sysTypeNo == sysTypeNo && cdr_sys_set[i].sysNo == sysNo && cdr_sys_set[i].subSysNo == subSysNo)
				break;
		}
		
		if(i == cdr_sys_num)
		{
			if(cdr_sys_num >= MAX_SYS_NUM)
			{
				cdr_log("[ERR][load_sys_info]: There are too many system");
				break;
			}
			for(i=0;i<cdr_src_num;i++)
			{
				if(sysTypeNo == cdr_src_set[i].sysTypeNo)
				{
					cdr_sys_set[cdr_sys_num].sysTypeNo=sysTypeNo;
					cdr_sys_set[cdr_sys_num].cdrSrcNo=i;
					cdr_sys_set[cdr_sys_num].sysNo=sysNo;
					cdr_sys_set[cdr_sys_num].subSysNo=subSysNo;
					sprintf(cdr_sys_set[cdr_sys_num].ip,"%s",row[3]);
					cdr_sys_set[cdr_sys_num].addr.remote_ip=inet_addr(row[3]);
					cdr_sys_set[cdr_sys_num].addr.local_port=CDR_PORT;
					cdr_sys_set[cdr_sys_num].addr.remote_port=cdr_src_set[i].port;
					cdr_sys_set[cdr_sys_num].maxVarNum=MAX_BIND_VAR_NUM;
					cdr_log("[INFO][load_sys_info]:Connect to system, sysTypeNo=%d, sysNo=%d, subSysNo=%d, ip=%s",sysTypeNo,sysNo,subSysNo,row[3]);
					cdr_sys_num++;
				}
			}
		}
	}
	
	mysql_free_result(res_set);
	mysql_close(pCdrConn);
}

void cdr_receive()
{
	snmp_pdu cdrmsg;
	snmp_addr addr;

	addr.local_port=CDR_PORT;
	int index=0;
	
	while(1)
	{
		if(snmp_msg_num >= MAX_SNMP_MSG_NUM)
			return;
		memset(&cdrmsg,0,sizeof(snmp_pdu));
		if(snmp_receive(&cdrmsg,&addr) == 0)
			return;
		if(cdrmsg.pdu_type != PDU_RSP)
			continue;
			
		while(index < MAX_SNMP_MSG_NUM)
		{
			if(snmp_msg_set[index].use == 0)
				break;
			index++;
		}
		
		if(index == MAX_SNMP_MSG_NUM)
		{
			cdr_log("[WARN][cdr_receive]:The receive buffer is full");
			return;
		}
		memset(&snmp_msg_set[index].pdu,0,sizeof(snmp_pdu));
		memcpy(&snmp_msg_set[index].pdu,&cdrmsg,sizeof(snmp_pdu));
//printf("receive msg request id=%ld\n",snmp_msg_set[index].pdu.request_id);
		snmp_msg_set[index].use=1;
		snmp_msg_set[index].timeout=MAX_MSG_TIMEOUT;
		snmp_msg_num++;
		
		int i;
		char stroid[64];
		char strtmp[24];
		sprintf(stroid," ");
		for(i=0;i<cdrmsg.var[0].oidlen;i++)
		{
			sprintf(strtmp,"%ld.",cdrmsg.var[0].oid[i]);
			strcat(stroid,strtmp);
		}
#if CDR_DEBUG
		cdr_log("Receive msg, store in %d, request id=%ld,curr num=%ld,oid=%s",index,cdrmsg.request_id,snmp_msg_num,stroid);
#endif
	}
}

void check_pointer(cdr_sys *psys,snmp_pdu *pdu)
{
	int ret;
	DWORD getHead,getTail;
	cdr_src *psrc;
	
	ret=parse_info(pdu,&getHead,&getTail);
	if(!ret)
	{
		//cdr_log("[ERR][check_pointer]:Parse info of head and tail pointer fail, sysTypeNo=%d, sysNo=%d, subSysNo=%d",psys->sysTypeNo,psys->sysNo,psys->subSysNo);
		psys->state=STATE_IDLE;
		psys->timeout=MAX_IDLE_TIMEOUT;
		return;
	}
	psrc=&cdr_src_set[psys->cdrSrcNo];
	//check the head and tail pointer
	//cdr_log("[INFO][check_pointer]:Get head=%ld[%08X], tail=%ld[%08X], current, head=%ld[%08X], tail=%ld[%08X], %d-%d-%d",getHead,getHead,getTail,getTail,psys->head,psys->head,psys->tail,psys->tail,psys->sysTypeNo,psys->sysNo,psys->subSysNo);
	
	if(getHead == getTail)
	{
		psys->head=getHead;
		psys->tail=getTail;
		psys->state=STATE_IDLE;
		psys->timeout=MAX_IDLE_TIMEOUT;
		return;
	}
	else if(getHead > getTail)
	{
		psys->head=getHead;
		if(getHead - getTail > psrc->bufferSize)
			psys->tail=getHead - psrc->bufferSize;
		else
			psys->tail=getTail;
		psys->state=STATE_CDR_GET;
		psys->retry=0;
		psys->timeout=INSTANT_TIMEOUT;
		//cdr_log("[INFO][check_pointer]:Get the info first, start to chase to get CDR, head=%ld[%08X], tail=%ld[%08X], %d-%d-%d",psys->head,psys->head,psys->tail,psys->tail,psys->sysTypeNo,psys->sysNo,psys->subSysNo);
		return;
	}
	else
	{
		if(getHead >= psrc->bufferSize)
		{
			psys->tail=getHead - psrc->bufferSize;
			psys->head=getHead;
			//cdr_log("[INFO][check_pointer]:Get the info first, the head pointer get the max value already, head=%ld[%08X], tail=%ld[%08X], %d-%d-%d",psys->head,psys->head,psys->tail,psys->tail,psys->sysTypeNo,psys->sysNo,psys->subSysNo);
		}
		else
		{
			//psys->tail=MAX_CDR_PTR -(psrc->bufferSize - getHead);
			//psys->head=getHead;
			psys->head=getHead;
			psys->tail=0;
			if(psys->head == psys->tail)
			{
				psys->prepareSetTail=0;
				psys->state=STATE_TAIL_SET;
				psys->retry=0;
				cdr_log("[INFO][check_pointer]:No more cdr, set the tail, head=%ld[%08X], tail=%ld[%08X], %d-%d-%d",psys->head,psys->head,psys->tail,psys->tail,psys->sysTypeNo,psys->sysNo,psys->subSysNo);
				return;
			}
			cdr_log("[INFO][check_pointer]:Get the info first, the head pointer get the max value already and some cdr may miss, head=%ld[%08X], tail=%ld[%08X], %d-%d-%d",psys->head,psys->head,psys->tail,psys->tail,psys->sysTypeNo,psys->sysNo,psys->subSysNo);
		}
		psys->state=STATE_CDR_GET;
		psys->retry=0;
		psys->timeout=INSTANT_TIMEOUT;
		return;
	}
	
	psys->state=STATE_IDLE;
	psys->timeout=MAX_IDLE_TIMEOUT;
}

int parse_info(snmp_pdu *pdu,DWORD *head,DWORD *tail)
{
	if(pdu->var_num != 2)
		return 0;
		
	//parse head
	*head=decode_integer(pdu->var[0].msg,pdu->var[0].msglen);
	*tail=decode_integer(pdu->var[1].msg,pdu->var[1].msglen);
		
	return 1;
}

int get_msg(cdr_sys *psys)
{
	int index;
	int i;
	int use_count=0;
	char tmpstr[64];
	
	for(index=0;index<MAX_SNMP_MSG_NUM;index++)
	{
		if(use_count >= snmp_msg_num)
		{
			if(psys->retry >= MAX_RETRY)
			{
				cdr_log("[Err][get_msg]:Get msg fail,request_id=%ld,retry=%d\n",psys->requestId,psys->retry);
				cdr_log("Current msg set\n");
				globalstr[0]=0;
				for(i=0;i<MAX_SNMP_MSG_NUM;i++)
				{
					if(snmp_msg_set[index].use == 1)
					{
						sprintf(tmpstr,"[%d-%ld-%d] ",index,snmp_msg_set[index].pdu.request_id,snmp_msg_set[index].timeout);
						strcat(globalstr,tmpstr);
					}
				}
				cdr_log("%s",globalstr);
			}
			return -1;
		}
		if(snmp_msg_set[index].use == 1)
		{
			if(snmp_msg_set[index].pdu.request_id == psys->requestId)
			{
#if CDR_DEBUG
				cdr_log("Get msg,%d,request_id=%ld,curr num=%d",index,psys->requestId,snmp_msg_num-1);
#endif
//				cdr_log("Get msg[%d],request_id=%ld,curr num=%d,timeout=%d",index,psys->requestId,snmp_msg_num-1,snmp_msg_set[index].timeout);
				return index;
			}
			use_count++;
		}
	}
	
	if(psys->retry >= MAX_RETRY)
	{
		cdr_log("[Err][get_msg]:Get msg fail,request_id=%ld,retry=%d\n",psys->requestId,psys->retry);
		cdr_log("Current msg set\n");
		globalstr[0]=0;
		for(i=0;i<MAX_SNMP_MSG_NUM;i++)
		{
			if(snmp_msg_set[index].use == 1)
			{
				sprintf(tmpstr,"[%d-%ld-%d] ",index,snmp_msg_set[index].pdu.request_id,snmp_msg_set[index].timeout);
				strcat(globalstr,tmpstr);
			}
		}
#if CDR_DEBUG
		cdr_log("%s",globalstr);
#endif
	}
	
	return -1;
}

void cdr_process(cdr_sys *psys,snmp_pdu *pdu)
{
	DWORD serial;
	int pos,errpos,tagcode,len;
	BYTE temp;
	ASN_BUF asnbuf;
	int index,i;
	BYTE tempbyte[256];
	char tmpstr[1024];
	char fieldstr[1024];
	char tmptime[256];
	cdr_src *psrc;
	cdr_def *pdef;
	long ltime;
	struct tm *t;
	char *pstr,*tmp;
	//check the var wether too big
	if(pdu->error_status != 0)
	{
		if(pdu->error_status == 1)
		{
			cdr_log("[WARN][cdr_process]:The var num is too big, curr num=%d, change var num=%d, %d-%d-%d",psys->maxVarNum,psys->maxVarNum-1,psys->sysTypeNo,psys->sysNo,psys->subSysNo);
			psys->isVarTooBig=1;
			psys->maxVarNum--;
			return;
		}
		else
		{	
			cdr_log("[ERR][cdr_process]:Receive error snmp response, error_status=%d, %d-%d-%d",pdu->error_status,psys->sysTypeNo,psys->sysNo,psys->subSysNo);
			return;
		}
	}
	
	psrc=&cdr_src_set[psys->cdrSrcNo];
	pdef=&psrc->define;
	ltime=time(NULL);
	t=localtime(&ltime);
#if CDR_DEBUG
	cdr_log("pdu var num=%d ", pdu->var_num);
#endif
	for(index=0;index<pdu->var_num;index++)
	{
		isRoamCDR=0;
		memset(mcc,0,sizeof(mcc));
		memset(mnc,0,sizeof(mnc));
		
		if(pdu->var[index].vartype != NosuchInstance && pdu->var[index].msglen != 0)
		{
			if(AsnDecode(pdu->var[index].msg,pdu->var[index].msglen,1,&errpos,&asnbuf) < 0 && errpos < 6) 
			{
				cdr_log("[ERR][cdr_process]:Fail to process snmp msg1, %d-%d-%d",psys->sysTypeNo,psys->sysNo,psys->subSysNo);
				cdr_logmsg(pdu->var[index].msg,pdu->var[index].msglen);
				return;
			}
#if CDR_DEBUG
			cdr_log("pdu[%d] var length=%d\n", index, pdu->var[index].msglen);
#endif
			//get serial
			pos=get_int_v2("2",(int*)&serial,&asnbuf)+2;
			serial=serial & MAX_CDR_PTR;
#if CDR_DEBUG
			cdr_log("serial=%ld\n", serial);
#endif
			//get tag
			if(gettagcode(pdu->var[index].msg+pos,(unsigned int*)&tagcode,&temp) < 1)
			{
				cdr_log("[ERR][cdr_process]:Get tagcode fail, %d-%d-%d",psys->sysTypeNo,psys->sysNo,psys->subSysNo);
				return;
			}
			memset(&asnbuf,0,sizeof(ASN_BUF));
			if(AsnDecode(pdu->var[index].msg+pos,pdu->var[index].msglen-pos,1,&errpos,&asnbuf) < 0 && errpos < 6) 
			{
				cdr_log("[ERR][cdr_process]:Fail to process snmp msg2, %d-%d-%d",psys->sysTypeNo,psys->sysNo,psys->subSysNo);
				cdr_logmsg(pdu->var[index].msg+pos,pdu->var[index].msglen-pos);
				return;
			}
			
			if(tagcode >= MAX_TAG_VALUE || pdef->tags[tagcode] == 0)
			{
				cdr_log("[ERR][cdr_process]:Invalid tagcode=%d, %d-%d-%d",tagcode,psys->sysTypeNo,psys->sysNo,psys->subSysNo);
				cdr_logmsg(pdu->var[index].msg+pos,pdu->var[index].msglen-pos);
				return;
			}

		
			//If this cdr is VLR cdr
			if(psys->sysTypeNo == 325 && wsms_enable_flag)
				getVlrCdr(psys,serial,pdu->var[index].msg+pos,pdu->var[index].msglen-pos,tagcode);
			
			sqlstr[0]=0;
			//sprintf(tmpstr,"REPLACE INTO %s.%s_%02d(%s) VALUES(",CDRDB_NAME,psrc->recordTable,t->tm_hour,pdef->allFieldList);
			sprintf(tmpstr,"VALUES(");		
			strcat(sqlstr,tmpstr);
			sprintf(tmpstr,"'%d','%ld','%s'",psys->sysNo,serial,bcd2str(pdu->var[index].msg+pos,pdu->var[index].msglen-pos));
			strcat(sqlstr,tmpstr);
#if CDR_DEBUG
			cdr_log("sqlstr1=%s ", sqlstr);
#endif
			if(psys->sysTypeNo == 320)
			{
				if(nrtrde_flag)
				{
					memset(nrtrdesqlstr,0,sizeof(nrtrdesqlstr));
					sprintf(tmpstr,"REPLACE INTO %s.cdrFromMSCSend(%s,mcc,mnc) VALUES(",CDRDB_NAME,pdef->allFieldList);
					strcat(nrtrdesqlstr,tmpstr);
					sprintf(tmpstr,"'%d','%ld','%s'",psys->sysNo,serial,bcd2str(pdu->var[index].msg+pos,pdu->var[index].msglen-pos));
					strcat(nrtrdesqlstr,tmpstr);
				}
				if(mt_sms_charge_flag)
				{
					memset(mtsmssqlstr,0,sizeof(mtsmssqlstr));
					sprintf(tmpstr,"REPLACE INTO OMC_PUB.%s(%s) VALUES(",MT_SMS_CHARGE_TABLE,pdef->allFieldList);
					strcat(mtsmssqlstr,tmpstr);
					sprintf(tmpstr,"'%d','%ld','%s'",psys->sysNo,serial,bcd2str(pdu->var[index].msg+pos,pdu->var[index].msglen-pos));
					strcat(mtsmssqlstr,tmpstr);
				}
			}

			for(i=0;i<pdef->fieldCount;i++)
			{
			//	cdr_log("tagcode=%d\n", tagcode);
				if(pdef->fields[i].tagFlag[tagcode])
				{
				//	cdr_log("tag=%s ", pdef->fields[i].tagFlag[tagcode]);
					memset(tempbyte,0,sizeof(tempbyte));
					len=get_tlv(pdef->fields[i].tags[tagcode],tempbyte,&asnbuf);
				//	cdr_log("len=%d\n", len);
					if(len == -1)
					{
						sprintf(tmpstr,",NULL");
					}
					else
					{
						cdr_parse(psys,tagcode,&asnbuf,i,fieldstr);
						sprintf(tmpstr,"%s",fieldstr);
#if CDR_DEBUG
						cdr_log("fieldstr=%s ", fieldstr);
#endif
						if(!strcmp(pdef->fields[i].fieldName,"releaseTime"))
							sprintf(tmptime,"%s",fieldstr);
#if CDR_DEBUG
						cdr_log("fieldname=%s,tag=%s,len=%d,%d-%d-%d",pdef->fields[i].fieldName,pdef->fields[i].tags[tagcode],len,psys->sysTypeNo,psys->sysNo,psys->subSysNo);
						cdr_logmsg(tempbyte,len);
#endif
					}
				}
				else
				{
					sprintf(tmpstr,",NULL");
				}
				strcat(sqlstr,tmpstr);
				if(psys->sysTypeNo==320 && mt_sms_charge_flag)
				{
					strcat(mtsmssqlstr,tmpstr);
				}
				if(psys->sysTypeNo==320 && nrtrde_flag)
				{
					strcat(nrtrdesqlstr,tmpstr);
				}
			}
			strcat(sqlstr,");");
#if CDR_DEBUG
			cdr_log("sqlstr2=%s ", sqlstr);
			cdr_log("[tmptime]%s",tmptime);
#endif
			if (strlen(tmptime) != 0)
			{
				pstr=strstr(tmptime," ");
				cdr_log("[pstr]%s",pstr);
				tmp=&pstr[1];
				pstr=strtok(tmp,":");
				cdr_log("[time]%s",pstr);
			}
			if (pstr == NULL)
			//if(strlen(pstr)==0)
				sprintf(tmpstr,"REPLACE INTO %s.%s_%02d(%s) ",CDRDB_NAME,psrc->recordTable,t->tm_hour,pdef->allFieldList);
			else
				sprintf(tmpstr,"REPLACE INTO %s.%s_%s(%s) ",CDRDB_NAME,psrc->recordTable,pstr,pdef->allFieldList);
			strcat(tmpstr,sqlstr);
			sprintf(sqlstr,"%s",tmpstr);
#if CDR_DEBUG
			cdr_log("[SQL]%s",sqlstr);
#endif
			if(psys->sysTypeNo==320 && nrtrde_flag && isRoamCDR)
			{
				sprintf(tmpstr,",'%s','%s');",mcc,mnc);
				strcat(nrtrdesqlstr,tmpstr);
				send_sql_comm(nrtrdesqlstr);
			}
			if(psys->sysTypeNo==320 && mt_sms_charge_flag)
			{
				strcat(mtsmssqlstr,");");
				send_sql_comm(mtsmssqlstr);
			}
			// removed by simon, at 2023-11-14
			//printf("%s\n",sqlstr);
			
			send_sql_comm(sqlstr);
				
			psys->processNum++;
			if(psys->processNum >= MAX_PROCESS_CDR_NUM)
			{
				cdr_log("[INFO][cdr_process]:Set the tail to %ld to save, %d-%d-%d",psys->tail,psys->sysTypeNo,psys->sysNo,psys->subSysNo);
				psys->processNum=0;
				psys->prepareSetTail=1;
			}
#if CDR_DEBUG
			cdr_log("Get cdr, serial=%d[%08X], %d-%d-%d",serial,serial,psys->sysTypeNo,psys->sysNo,psys->subSysNo);
			cdr_logmsg(pdu->var[index].msg,pdu->var[index].msglen);
			cdr_log("Insert cdr,%s",sqlstr);
#endif
			
		}
		else
		{
			psys->error++;
			cdr_log("[WARN][cdr_process]:No such instance or zero var, %ld -> %ld, %d-%d-%d",psys->tail,psys->head,psys->sysTypeNo,psys->sysNo,psys->subSysNo);
		}
				
		
	}

#if CDR_DEBUG
	cdr_log("[INFO][cdr_process]:process cdr, var num=%d",pdu->var_num);
#endif
}

void cdr_parse(cdr_sys *psys,int tagcode,ASN_BUF *asnbuf,int fieldIndex,char* fieldstr)
{
	cdr_def *pdef;
	cdr_src *psrc;
	int len;
	char tmpstr[1024];
	BYTE tempbyte[1024];
	int tempint,tmpint1,tmpint2;
	int index;
	char tag_seq[24];
	char tag_seq1[24];
	
	//for smlog
	int smlog_smdcs_decode_type=0;		//1-7bit, 2-8bit, 3-unicode
	int smlog_smdcs_value;
	
	psrc=&cdr_src_set[psys->cdrSrcNo];
	pdef=&cdr_src_set[psys->cdrSrcNo].define;
	memset(fieldstr,0,256);
	memset(tempbyte,0,256);
#if CDR_DEBUG
	cdr_log("field %d type = %d\n", fieldIndex,pdef->fields[fieldIndex].type);
#endif
	switch(pdef->fields[fieldIndex].type)
	{
	//string
	case 0:
		if((len = get_tlv(pdef->fields[fieldIndex].tags[tagcode],(u_char*)tmpstr,asnbuf)) > 0) 
		{
			tmpstr[len]='\0';
			sprintf(fieldstr,",'%s'",tmpstr);
		} 
		else
			sprintf(fieldstr,",NULL");
		break;
	//integer
	case 1:
		if((get_int_v2(pdef->fields[fieldIndex].tags[tagcode],&tempint,asnbuf)) >= 0)
			sprintf(fieldstr,",%d",tempint);
		else
			sprintf(fieldstr,",NULL");
		break;
	//BCD
	case 2:
		if((len = get_tlv(pdef->fields[fieldIndex].tags[tagcode],tempbyte,asnbuf)) > 0)
			sprintf(fieldstr,",'%s'",bcd2str(tempbyte,len));	
		else
			sprintf(fieldstr, ",NULL");	
		break;
	//timestamp
	case 3:
		if((len = get_tlv(pdef->fields[fieldIndex].tags[tagcode],tempbyte,asnbuf)) > 0) 
			sprintf(fieldstr,",'%02x-%02x-%02x %02x:%02x:%02x'",tempbyte[0],tempbyte[1],tempbyte[2],tempbyte[3],tempbyte[4],tempbyte[5]); 
		else
			sprintf(fieldstr,",NULL");
		break;
	//MSISDN
	case 4:
		if((len = get_tlv(pdef->fields[fieldIndex].tags[tagcode],tempbyte,asnbuf)) > 0)
		{
			//opps need cc
			if(psrc->sysTypeNo == 375)
				sprintf(fieldstr,",'%s'",digits2str(tempbyte,len * 2));
			else
				sprintf(fieldstr,",'%s'",digits2str(tempbyte + 1,(len - 1) * 2));
		}
		else
			sprintf(fieldstr,",NULL");
		break;
	//trunkgroup
	case 5:
		sprintf(tag_seq,"%s.0",pdef->fields[fieldIndex].tags[tagcode]);	//integer
		if((tempint = get_int(tag_seq,asnbuf)) >= 0)
			sprintf(fieldstr,",%d",tempint);
		else
		{
			sprintf(tag_seq,"%s.1",pdef->fields[fieldIndex].tags[tagcode]);
			if((len = get_tlv(tag_seq,(u_char*)tmpstr,asnbuf)) > 0)
			{
				tmpstr[len] = '\0';
				sprintf(fieldstr,",'%s'",tmpstr);
			}
			else
				sprintf(fieldstr,",NULL");
		}
		break;
	//BasicServiceCode
	case 6:
		sprintf(tag_seq,"%s.2",pdef->fields[fieldIndex].tags[tagcode]);	//integer
		if((len = get_tlv(tag_seq,tempbyte,asnbuf)) < 0) 
		{
			sprintf(tag_seq,"%s.3",pdef->fields[fieldIndex].tags[tagcode]);
			len = get_tlv(tag_seq,tempbyte,asnbuf);
		}
		if(len > 0)
			sprintf(fieldstr,",%d",tempbyte[0]);
		else
			sprintf(fieldstr,",NULL");
		break;
	//recordingEntity
	case 7:
		if((len = get_tlv(pdef->fields[fieldIndex].tags[tagcode],tempbyte,asnbuf)) > 0)
			sprintf(fieldstr,",'%s'",bcd2str(tempbyte + 1, len - 1));
		else
			sprintf(fieldstr,",NULL");
		break;
	//Diagnostics
	case 8:
		for(index=0;index<5;index++)
		{
			sprintf(tag_seq,"%s.%d",pdef->fields[fieldIndex].tags[tagcode],index);	//integer
			if((tempint = get_int(tag_seq,asnbuf)) >= 0)
			{
				sprintf(fieldstr,",%d",tempint);
				break;
			}
			if(index == 4)
				sprintf(fieldstr,",NULL");
		}
		break;
	//LocationAreaAndCell
	case 9:	
		sprintf(tag_seq,"%s.0",pdef->fields[fieldIndex].tags[tagcode]);
		sprintf(tag_seq1,"%s.1",pdef->fields[fieldIndex].tags[tagcode]);
		if(get_int_v2(tag_seq,&tmpint1,asnbuf) >= 0 && get_int_v2(tag_seq1,&tmpint2,asnbuf) >= 0)
			sprintf(fieldstr,",'%05d %05d'",tmpint1,tmpint2);		
		else
			sprintf(fieldstr, ",NULL");
		break;
	//SEQUENCE OF LocationChange
	case 10:
	//SEQUENCE OF ChangeOfService
	case 11:
	//SEQUENCE OF SuppServiceUsed
	case 12:
	//AOCParameters
	case 13:
	//SEQUENCE OF AOCParmChange
	case 14:
		break;
	//ChangeOfClassmark
	case 15:
		if((len = get_tlv(pdef->fields[fieldIndex].tags[tagcode],tempbyte,asnbuf)) > 0)
			sprintf(fieldstr,",'[%02x][%02x][%02x]'",tempbyte[0],tempbyte[1],tempbyte[2]);
		else
			sprintf(fieldstr,",NULL");
		break;
	//ChangeOfRadioChannel
	case 16:
	//AdditionalChgInfo
	case 17:
	//ManagementExtensions
	case 18:
	//SEQUENCE OF HSCSDParmsChange
	case 19:
	//SEQUENCE OF ChannelCoding
	case 20:
	//LevelOfCAMELService(bit string)
	case 21:
	//SEQUENCE OF CAMELInformation
	case 22:
		break;
	//SmRslf
	case 23:
		for(index=0;index<5;index++)
		{
			sprintf(tag_seq,"%s.%d",pdef->fields[fieldIndex].tags[tagcode],index);
			if((get_int_v2(tag_seq,&tempint,asnbuf)) >= 0)
			{
				sprintf(fieldstr,",'%02d %02d'",index+7,tempint);
				break;			
			}
			if(index == 4)
				sprintf(fieldstr,",NULL");						
		}
		break;
	//imei
	case 24:
		if((len = get_tlv(pdef->fields[fieldIndex].tags[tagcode],tempbyte,asnbuf)) > 0)
			sprintf(fieldstr,",'%s'",digits2str(tempbyte,len * 2));
		else
			sprintf(fieldstr,",NULL");
		break;
	//unsigned integer
	case 25:
		len=get_int_v2(pdef->fields[fieldIndex].tags[tagcode],&tempint,asnbuf);
		if(len > 0)
		{
			switch(len)
			{
			case 1:
				sprintf(fieldstr,",%u",0x000000ff & tempint);
				break;
			case 2:
				sprintf(fieldstr,",%u",0x0000ffff & tempint);
				break;
			case 3:
				sprintf(fieldstr,",%u",0x00ffffff & tempint);
				break;
			case 4:
				sprintf(fieldstr,",%u",tempint);
				break;
			}
		}
		else if(len == 0)
			sprintf(fieldstr,",0");
		else
			sprintf(fieldstr,",NULL");
		break;
	
	//decode smcontent
	case 26:
		if(smlog_decode_flag)
		{
			char formatstring[256];
			char mes[256];
			//Get the smdcs tlv
			
			memset(formatstring,0,256);
			memset(mes,0,256);
			
			if((len = get_tlv("0.4",tempbyte,asnbuf)) != 1)
			{
				cdr_log("[ERR]:smdcs != 1 byte");
				if((len = get_tlv(pdef->fields[fieldIndex].tags[tagcode],tempbyte,asnbuf)) > 0)
					sprintf(fieldstr,",'%s'",bcd2str(tempbyte,len));	
				else
					sprintf(fieldstr, ",NULL");
				break;
			}
			
			smlog_smdcs_value=tempbyte[0];

			if((len = get_tlv(pdef->fields[fieldIndex].tags[tagcode],tempbyte,asnbuf)) > 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");
					memset(tmpstr,0,256);
					if(smsDecodeAll(smlog_smdcs_decode_type,(char*)tempbyte,tmpstr,len)>0)
					{	
						int mpos=0,pos=0;			
						memset(mes,0,256);
						for(pos=0;pos<256;pos++)
						{
							if(isprint(tmpstr[pos]))
							{
								mes[mpos]=tmpstr[pos];
								mpos++;
							}
						}

						formatSingleQuotation(mes,strlen(mes),formatstring);
						sprintf(fieldstr,",'%s'",formatstring);
					}
					else
						sprintf(fieldstr,",'decode error'");		
				}
				else if(smlog_smdcs_decode_type == 3)
				{
					//printf("unicode to unicode\n");
					sprintf(mes,"%s",bcd2str(tempbyte,len));
					formatSingleQuotation(mes,strlen(mes),formatstring);
					sprintf(fieldstr,",'%s'",formatstring);
				}
				else
				{
					if((len = get_tlv(pdef->fields[fieldIndex].tags[tagcode],tempbyte,asnbuf)) > 0)
						sprintf(fieldstr,",'%s'",bcd2str(tempbyte,len));	
					else
						sprintf(fieldstr, ",NULL");
				}
			}
			else
				sprintf(fieldstr,",NULL");
		}
		else
		{
			if((len = get_tlv(pdef->fields[fieldIndex].tags[tagcode],tempbyte,asnbuf)) > 0)
				sprintf(fieldstr,",'%s'",bcd2str(tempbyte,len));	
			else
				sprintf(fieldstr, ",NULL");
		}
		break;
	//IMSI
	case 40:
		if((len = get_tlv(pdef->fields[fieldIndex].tags[tagcode],tempbyte,asnbuf)) > 0)
		{
			sprintf(fieldstr,",'%s'",digits2str(tempbyte,len * 2));
			if(psys->sysTypeNo == 320 && nrtrde_flag)
			{
				sprintf(tmpstr,"%s",digits2str(tempbyte,len * 2));
				//compare the local_mcc and local_mnc with mcc mnc
				for(index=0;index<3;index++)
				{
					mcc[index]=tmpstr[index];
				}
				mcc[3]='\0';
					
				for(index=3;index<5;index++)
				{
					mnc[index-3]=tmpstr[index];
				}
				mnc[2]='\0';
				if(strcmp(mcc,local_mcc) != 0 || strcmp(mnc,local_mnc) != 0)
				{
					isRoamCDR=1;
				}
			}
		}
		else
		{	
			sprintf(fieldstr,",NULL");
		}
		break;
	//RoutingNumber
	case 41:
		sprintf(tag_seq,"%s.1",pdef->fields[fieldIndex].tags[tagcode]);	//RoamingNumber
		if((len = get_tlv(tag_seq,tempbyte,asnbuf)) > 0)
			sprintf(fieldstr,",'RM:%s'",digits2str(tempbyte + 1, (len - 1) * 2));
		else
		{
			sprintf(tag_seq,"%s.2",pdef->fields[fieldIndex].tags[tagcode]);	//ForwardToNumber 
			if((len = get_tlv(tag_seq,tempbyte,asnbuf)) > 0)
				sprintf(fieldstr,",'FW:%s'",digits2str(tempbyte + 1, (len - 1) * 2));
			else
				sprintf(fieldstr,",NULL");
		}
		break;
	
	}
}

void send_sql_comm(char *sqlcomm)
{
	MYSQL *pCdrConn;
	static unsigned long do_time=0;
	int index;
	int doit=0;
	
	static struct timeval tv1, tv2;
	struct timezone tz;
	long elapse;
	int pre_num;
	
	do_time+=time_slot;
	
	if(sqlcomm == NULL)
	{
		if(do_time > 5 && sql_comm_buffer.commNum > 0)
		{
			do_time=0;
			doit=1;
		}
	}
	else
	{
		sprintf(sql_comm_buffer.sqlstr[sql_comm_buffer.commNum],"%s",sqlcomm);
		sql_comm_buffer.commNum++;
			
		if(sql_comm_buffer.commNum == MAX_SQL_COMM_NUM)
		{
			doit=1;
		}
	}
	
	if(doit)
	{
		do_time=0;
		gettimeofday(&tv1,&tz);
		pre_num=sql_comm_buffer.commNum;
		
		pCdrConn=mysql_conn(HOST_NAME,CDRDB_NAME);
		if(pCdrConn == NULL)
		{
			cdr_log("[ERR][send_sql_comm]:mysql_conn CDR_DB\n");
			return;
		}
		
		for(index=0;index<sql_comm_buffer.commNum;index++)
		{
			if(mysql_getnores(pCdrConn,sql_comm_buffer.sqlstr[index]) != 0)
			{
				cdr_log("[ERR][send_sql_comm]:Excute fail, %s",sql_comm_buffer.sqlstr[index]);
			}
			sync_data_write(cdr_sync_data_id,sql_comm_buffer.sqlstr[index],strlen(sql_comm_buffer.sqlstr[index]));
		}
		sql_comm_buffer.commNum=0;
		mysql_close(pCdrConn);
		
		gettimeofday(&tv2,&tz);
		elapse=(tv2.tv_sec - tv1.tv_sec) * (10 ^ 6) + tv2.tv_usec - tv1.tv_usec;
		cdr_log("[INFO][send_sql_comm]:Excute %d SQL commands, consume time=%ld",pre_num,elapse);
	}
}


void cdr_logmsg(BYTE* msgbuf,int len)
{
	char logFile[64];
	FILE *fp;
	time_t l_time;
	int i;
	struct tm *t;
	char buf[8192];
		
	l_time=time(NULL);
	t=localtime(&l_time);
	sprintf(logFile,"/usr/local/omc/log/cdrlog_%04d%02d%02d.log",t->tm_year+1900,t->tm_mon+1,t->tm_mday);
	fp=fopen(logFile,"a");
	if(fp!=NULL)
	{
		for (i = 0; i < len; i++)
			sprintf(buf + 3 * i, "%02X ", msgbuf[i]);
		
		strcat(buf, "\n");
		fputs(buf,fp);
		fflush(fp);
		fclose(fp);
	}
}

void cdr_log(const char *fmt, ...)
{
	char logFile[64];
	FILE *fp;
	time_t l_time;
	va_list ap;
	char buf[8192];
	struct tm *t;
	char timestr[64];
	
	l_time=time(NULL);
	t=localtime(&l_time);
	sprintf(logFile,"/usr/local/omc/log/cdrlog_%04d%02d%02d.log",t->tm_year+1900,t->tm_mon+1,t->tm_mday);
	fp=fopen(logFile,"a");
	if(fp!=NULL)
	{
		va_start(ap,fmt);
		vsprintf(buf,fmt,ap);
		sprintf(timestr,"%02d:%02d:%02d: ",t->tm_hour,t->tm_min,t->tm_sec);
		fputs(timestr,fp);
		fputs(buf,fp);
		fputs("\n",fp);
		fflush(fp);
		va_end(ap);
		fclose(fp);
	}
}

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;
}

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;
}

/* 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;
}

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;
}

// Extra function
int sendHeartbeat()
{
	snmp_pdu pdu;
	snmp_addr addr;
	char proc_name[16];
	
	memset(proc_name,0,16);
	sprintf(proc_name,"cdrCollector");
	
	//pdu
	memset(&pdu,0,sizeof(snmp_pdu));
	pdu.pdu_type=7;
	pdu.request_id=0;
	sprintf(pdu.community,"public");
	pdu.var_num=1;
	pdu.error_status=0;
	pdu.error_index=0;
	
	//Addr
	addr.local_port = 4957;
	//addr.remote_ip = inet_addr("127.0.0.1");
	addr.remote_ip = GetLocalIP();
	addr.broadcast = 0;
	addr.remote_port = 4957;
	
	//Varlist
	memcpy(pdu.var[0].oid,PROC_HEARTBEAT_OID,PROC_HEARTBEAT_OIDLEN*sizeof(DWORD));

	pdu.var[0].oidlen=PROC_HEARTBEAT_OIDLEN;
	pdu.var[0].vartype=0x04;
	pdu.var[0].msglen=16;
	memcpy(pdu.var[0].msg,proc_name,16);
	
	if(snmp_send(&pdu, &addr) <= 0)
	{
		cdr_log("[ERR][sendHeart]:Send heartbeat fail");
		return 0;
	}
	return 1;
}

int getOmcStatus(int sysNo)
{
	MYSQL_RES *res;
	MYSQL_ROW row;
	char sqlstr[256];
	int status;
	char binCode[256];
	MYSQL *pubConn;
	
	pubConn=mysql_conn(HOST_NAME,"OMC_PUB");
	if(pubConn == NULL)
	{
		cdr_log("[ERR][load_cdr_info]:mysql_conn OMC_PUB\n");
		exit(-1);
	}
	
	sprintf(sqlstr,"SELECT detailStat FROM OMC_PUB.sysStat WHERE sysTypeNo=0 and sysNo=%d ",sysNo);

	res=mysql_getres(pubConn,sqlstr);
	if(res == NULL)
	{
		mysql_close(pubConn);
		cdr_log("[ERR %d][getOmcStatus]:%s\n",mysql_errno(pubConn),sqlstr);
		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);
	}
	else
	{
		mysql_free_result(res);
		mysql_close(pubConn);
		cdr_log("[ERR %d][getOmcStatus]:Find no row, %s\n",mysql_errno(pubConn),sqlstr);
		return -1;
	}
	mysql_free_result(res);
	mysql_close(pubConn);
	return status;
}

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((char*)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
	{
		exitLog("cdrCollector:getOmcSysNo, Can not open the omcd.conf");
		exit(1);
	}	
	return 1;
}

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((char*)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);
				}	
				else if(strcasecmp(paramName,"Flag") == 0)
				{
					nrtrde_flag=atoi(paramValue);
				}	
				
			}

		}	
		close(fi);
		fclose(fp);
	}	
	else
	{
		cdr_log("Fatal Error: The NR.conf does not exist!");
		exitLog("cdrCollector:initNRConf,The NR.conf does not exist");
		exit(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((char *)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 getVlrCdr(cdr_sys * psys,int serial,BYTE * pmsg,WORD msglen,int tagcode)
{
	ASN_BUF asn_buf;
	
	BYTE tempbyte[256];
	char tag_seq[20];
	int errpos;
	int i,j;
	int len;
	int tempint;
	char msisdn[64]="\0";
	char imsi[64]="\0";
	int diagnostics=-1;
	int recordExtensions=-1;
	
	cdr_src *psrc;
	cdr_def *pdef;
	
	psrc=&cdr_src_set[psys->cdrSrcNo];
	pdef=&cdr_src_set[psys->cdrSrcNo].define;

	if(AsnDecode(pmsg,msglen,1,&errpos,&asn_buf) < 0 && errpos < msglen) 
	{
		cdr_log("[ERR][getVlrCdr]:Wrong encoding of CDR Message.ip=%lX(%s-%d)\n",psys->addr.remote_ip,psrc->recordTable,psys->sysNo);
		return;
	}
	
	for(i=0;i<pdef->fieldCount;i++) 
	{
		if(strlen(pdef->fields[i].tags[tagcode]) == 0)
			continue;	

		switch(pdef->fields[i].type) 
		{
			case 2:
			//recordExtensions
			if(strcmp(pdef->fields[i].fieldName,"recordExtensions") == 0)
			{
				if((len = get_tlv(pdef->fields[i].tags[tagcode],tempbyte,&asn_buf)) > 0)
					recordExtensions=atoi(bcd2str(tempbyte,len));
				else
					recordExtensions=-1;
			}
			//servedMSISDN
			case 4:
				if(strcmp(pdef->fields[i].fieldName,"servedMSISDN") == 0)
				{	
					if((len = get_tlv(pdef->fields[i].tags[tagcode],tempbyte,&asn_buf)) > 0)
						sprintf(msisdn,"%s",digits2str(tempbyte + 1, (len - 1) * 2));
					else
						return;
				}
				break;
			//diagnostics	
			case 8:
				if(strcmp(pdef->fields[i].fieldName,"diagnostics") == 0)
				{
					for(j=0;j<5;j++) 
					{
						sprintf(tag_seq,"%s.%d",pdef->fields[i].tags[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->fields[i].tags[tagcode],tempbyte,&asn_buf)) > 0)
					sprintf(imsi,"%s", digits2str(tempbyte, len * 2));
				else
					return;
				break;		
		}
	}
	if(recordExtensions !=-1 && strcmp(msisdn,"\0") != 0 && strcmp(imsi,"\0") != 0)
	{
		if(recordExtensions == 1)
			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;
	MYSQL *pubConn;

	//Init the OMC_PUB DB connection
	pubConn=mysql_conn("localhost","OMC_PUB");
	if(pubConn == NULL)
	{
		cdr_log("[ERR][wsms_check_sub]:mysql_conn OMC_PUB\n");
		exit(-1);
	}
	
	sprintf(sqlstr,"SELECT imsi,logTime FROM OMC_PUB.wsmsRoamer WHERE imsi='%s'",imsi);

	res=mysql_getres(pubConn,sqlstr);
	if(res == NULL)
	{
		cdr_log("[ERR %d][wsms_check_sub]:%s\n",mysql_errno(pubConn),sqlstr);
		mysql_close(pubConn);
		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_getnores(pubConn, sqlstr) != 0) 
		{
			cdr_log("[ERR %d][wsms_check_sub]:%s\n",mysql_errno(pubConn),sqlstr);
			mysql_close(pubConn);
			return 1;
		}
		mysql_close(pubConn);
		return 0;
	}	
	//if the sub exist return 1
	else if(count>=1)
	{	
		mysql_close(pubConn);
		return 1;
	}
	mysql_close(pubConn);
	return 1;
}

void getConfFromDB()
{
	MYSQL_RES *res;
	MYSQL_ROW row;
	MYSQL *pubConn;

	//Init the OMC_PUB DB connection
	pubConn=mysql_conn("localhost","OMC_PUB");
	if(pubConn == NULL)
	{
		cdr_log("[ERR][getConfFromDB]:mysql_conn OMC_PUB\n");
		exit(-1);
	}
	
	//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'");
	res=mysql_getres(pubConn,sqlstr);
	if(res == NULL)
	{
		cdr_log("[ERR %d][getConfFromDB]:%s\n",mysql_errno(pubConn),sqlstr);
		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);
	
	//Get the parameter mt_sms_charge_flag in the OMC.omcPubVarConf
	sprintf(sqlstr,"SELECT pubVarValue FROM OMC_PUB.omcPubVarConf WHERE pubVarName='MTSMSCharge'");	
	res=mysql_getres(pubConn,sqlstr);
	if(res == NULL)
	{
		cdr_log("[ERR %d][cdr_init]:%s\n",mysql_errno(pubConn),sqlstr);
		return;
	}
	if((row = mysql_fetch_row(res)) != NULL)
	{
		if(strlen(row[0]) == 0)
			mt_sms_charge_flag=0;
		else if(atol(row[0]) > 0)
			mt_sms_charge_flag=1;
	  else
			mt_sms_charge_flag=0;
	}
	mysql_free_result(res);
	mysql_close(pubConn);
}

int formatSingleQuotation(char *inbuf,int inlen,char* outbuf)
{
        int i;
        int pos=0;

        for(i=0;i<inlen;i++)
        {
                if(inbuf[i] == '\'')
                {
                        outbuf[pos]='\'';
                        pos++;
                }
                outbuf[pos]=inbuf[i];
                pos++;
                if(pos == 255)
                        return 255;
        }

        return pos;
}

