/*************************************************
File name:	wsms.c
Author: 	JianHui Zheng
Version:	9:00:00 
Date:  		2008-03-04
Description:The application file about Welcome short message function.This module is nested
            into the omcMain module.It provides two functions:wsms_init,wsms_timer
            for omcMain to call.
			
			When receive a VLR CDR,if the diagnostics=2,then the cdrCollector insert
			the information into OMC_PUB.wsmsRoamer.
			wsms get the record from OMC_PUB.wsmsRoamer,then send the welcome short
			message and AD short message to the subscriber according to the hpmn 
			server configuration.
			
			The wsms support 100 hpmn servers configuration,every hpmn server
			support 1 welcome short message and 8 AD short messages.
			
			Note:(1)The VLR CDR must include the diagnostics field.
			     (2)You must config smpp links on EMS first.
				 (3)You can set smpp link service number in the welcomeSMS.conf file 
			
												
History:               
No. 		
Author:		  
Date:		 
Version:	   
Description:
*************************************************/
#include "wsms.h"

/***************************/
/**  Variable Declarion  ***/
/***************************/
/* The DB connection with the OMC_PUB */
MYSQL *pubConn;

/* The current count of hpmn servers */
int wsms_serv_count;

/* 1-enable the wsms function, 0-disable the wsms function */
int wsms_enable_flag;

/* The service number of the smpp link */
char wsms_service_number[16];

/* The day time to keep the roamer record */
int wsms_keep_day_time;

/* The smpp link no */
unsigned char smpp_link_no;

/* The smpp link status */
int smpp_link_status;

/* The struct objects of the hpmn servers */
HpmnServer servers[HPMN_MAX];

/* The default hpmn server index */
int def_hpmn_server_index;

/* For writing the log file */
char message[2048];

/***************************/
/**  Function Declarion  ***/
/***************************/
int initDBConnection(void);
void logMessage(const char *fmt,...);
void wsms_update(void);
int durTime(char* start,char* end);
int initWSMSConf(void);
int initSMPPLink(void);
void makeDefConf(void);
int wsms_smppOnDataRecv(BYTE linkNo, SMPP_MSG *pMsg, WORD dataLen);
int wsms_smppOnLinkStateChange(BYTE linkNo, BYTE state);
void wsms_send(HpmnServer *wsmsServer,char* msisdn);
int smsEncodeAll(int type,unsigned char* out,unsigned char* in,int len);
void wsms_del_overdue_sub(void);
void wsms_get_record(void);
int wsms_send_normal_sms();
void wsms_send_sm_by_content(char *content,char* msisdn);
/***************************/
/****      functions    ****/
/***************************/
/*************************************************
Function:        // initDBConnection
Description:     // Init the connection with DB OMC_PUB
Calls:           // 
Called By:       // wsms_init
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 
Others:          // 
*************************************************/
int initDBConnection(void)
{
	//init the OMC_PUB DB connection
	sprintf(message,"Init the OMC_PUB database connection\n");
	logMessage(message);
	
	pubConn=mysql_conn("localhost","OMC_PUB");
	if(pubConn == NULL)
		printf("[ERR][InitDBConnection]:mysql_conn OMC_PUB");
		
	return 1;
}

/*************************************************
Function:        // logMessage
Description:     // Write the log message to the log file
Calls:           // 
Called By:       // 
Table Accessed:  // 
Table Updated:   // 
Input:           // fmt: the message write to the log file
Output:          // 
Return:          // 
Others:          // 
*************************************************/
void logMessage(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/wsms%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);
	}
}

/*************************************************
Function:        // durTime
Description:     // Judge the current time whether during the given date
Calls:           // 
Called By:       // wsms_update
Table Accessed:  // 
Table Updated:   // 
Input:           // start: the start date, "20081010" for exam. end: the end date
Output:          // 
Return:          // 1-during the given date, 0-not during the given date
Others:          // 
*************************************************/
int durTime(char* start,char* end)
{
	char tempstr[16];
	struct tm* local;
	time_t t;
	int start_year,start_mon,start_day;
	int end_year,end_mon,end_day;
	long lnow,lstart,lend;
	
	if(strlen(start) != 8 || strlen(end) != 8)
		return 0;
	
	tempstr[0]=start[0];
	tempstr[1]=start[1];
	tempstr[2]=start[2];
	tempstr[3]=start[3];
	tempstr[4]='\0';
	start_year=atoi(tempstr)-1900;

	tempstr[0]=start[4];
	tempstr[1]=start[5];
	tempstr[2]='\0';
	start_mon=atoi(tempstr)-1;

	tempstr[0]=start[6];
	tempstr[1]=start[7];
	tempstr[2]='\0';
	start_day=atoi(tempstr);

	
	tempstr[0]=end[0];
	tempstr[1]=end[1];
	tempstr[2]=end[2];
	tempstr[3]=end[3];
	tempstr[4]='\0';
	end_year=atoi(tempstr)-1900;

	tempstr[0]=end[4];
	tempstr[1]=end[5];
	tempstr[2]='\0';
	end_mon=atoi(tempstr)-1;

	tempstr[0]=end[6];
	tempstr[1]=end[7];
	tempstr[2]='\0';
	end_day=atoi(tempstr);
	
	t=time(NULL);
	local=localtime(&t);
	
	lnow=365*local->tm_year + 31*local->tm_mon + local->tm_mday;
	//printf("n_year=%d,n_mon=%d,n_day=%d\n",local->tm_year,local->tm_mon,local->tm_mday);
	//printf("s_year=%d,s_mon=%d,s_day=%d\n",start_year,start_mon,start_day);
	//printf("e_year=%d,e_mon=%d,e_day=%d\n",end_year,end_mon,end_day);
	lstart=start_year*365 + 31*start_mon + start_day;
	lend=end_year*365 + 31*end_mon + end_day;
	//printf("now=%ld,start=%ld,end=%ld\n",lnow,lstart,lend);
	if(lnow>=lstart && lnow<=lend)
		return 1;
	else
		return 0;	
}

/*************************************************
Function:        // wsms_update
Description:     // Update the hpmn server information
Calls:           // durTime
Called By:       // wsms_timer
Table Accessed:  // OMC_PUB.wsmsServConf, OMC_PUB.wsmsMsgConf
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 
Others:          // 
*************************************************/
void wsms_update()
{
	char sqlstr[256];
	MYSQL_RES *res;
	MYSQL_ROW row;
	char start[32];
	char end[32];
	int i;

	sprintf(message,"Update the hpmn server information\n");
	logMessage(message);
	
	sprintf(sqlstr,"select mcc,mnc,flag,smsEncode,welcomeMsg from wsmsServConf");
	
	res=mysql_getres(pubConn,sqlstr);
	if(res == NULL)
	{
		logMessage("[ERR %d][wsms_update]:%s",mysql_errno(pubConn),sqlstr);
		return;
	}
	
	wsms_serv_count=0;
	def_hpmn_server_index=-1;
	while((row = mysql_fetch_row(res)) != NULL)
	{
		sprintf(servers[wsms_serv_count].mcc,"%s",row[0]);
		sprintf(servers[wsms_serv_count].mnc,"%s",row[1]);
		servers[wsms_serv_count].flag=atoi(row[2]);
		servers[wsms_serv_count].smsEncode=atoi(row[3]);
		sprintf((char*)servers[wsms_serv_count].wlContent,"%s",row[4]);
		if(strcmp(servers[wsms_serv_count].mcc,"***")==0 && strcmp(servers[wsms_serv_count].mnc,"**")==0)
			def_hpmn_server_index=wsms_serv_count;
		wsms_serv_count++;
	}
	sprintf(message,"Hpmn server count=%d\n",wsms_serv_count);
        logMessage(message);
	mysql_free_result(res);

	sprintf(sqlstr,"select mcc,mnc,content,validStart,validEnd from wsmsMsgConf");
	
	res=mysql_getres(pubConn,sqlstr);
	if(res == NULL)
	{
		logMessage("[ERR %d][wsms_update]:%s",mysql_errno(pubConn),sqlstr);
		return;
	}
	
	for(i=0;i<wsms_serv_count;i++)
	{
		servers[i].adCount=0;
	}
	
	while((row = mysql_fetch_row(res)) != NULL)
	{
		for(i=0;i<wsms_serv_count;i++)
		{
			if(strcmp(servers[i].mcc,row[0])==0 && strcmp(servers[i].mnc,row[1])==0)
			{
				sprintf((char*)servers[i].adContent[servers[i].adCount],"%s",row[2]);
				sprintf(start,"%s",row[3]);
				sprintf(end,"%s",row[4]);
				servers[i].adValid[servers[i].adCount++]=durTime(start,end);			
				//break;
			}
		}
		//printf("mcc=%s,mnc=%s,flag=%d,smsEncode=%d\n",row[0],row[1],atoi(row[2]),atoi(row[3]));
	}
	mysql_free_result(res);
	/*
	//test
	printf("------------------------\n");
	{	
		int j=0;
		for(i=0;i<wsms_serv_count;i++)
		{
			printf("mcc=%s,mnc=%s,flag=%d,smsEncode=%d,adCount=%d\n",
				servers[i].mcc,servers[i].mnc,servers[i].flag,servers[i].smsEncode,servers[i].adCount);
				
			printf("wlContent=%s\n",servers[i].wlContent);
			for(j=0;j<servers[i].adCount;j++)
			{
				printf("%d-%d-%s\n",j,servers[i].adValid[j],servers[i].adContent[j]);
			}	
		}
	}	
	*/
}

/*************************************************
Function:        // initWSMSConf
Description:     // Init the global parameter from welcomeSMS.conf file
Calls:           // makeDefConf
Called By:       // wsms_init
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 
Others:          // 
*************************************************/
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);
				}	
				else if(strcasecmp(paramName,"keep_day_time") == 0)
				{
					wsms_keep_day_time=atoi(paramValue);
				}
				else if(strcasecmp(paramName,"service_number") == 0)
				{
					sprintf(wsms_service_number,"%s",paramValue);
				}	
			}
			//printf("enable_flag=%d,keep_day_time=%d,service_number=%s\n",wsms_enable_flag,wsms_keep_day_time,wsms_service_number);

		}	
		sprintf(message,"Load conf file,wsms_enable_flag=%d,wsms_keep_day_time=%d,wsms_service_number=%s\n",wsms_enable_flag,wsms_keep_day_time,wsms_service_number);
		logMessage(message);
		close(fi);
		fclose(fp);
	}	
	else
	{
		logMessage("The welcomeSMS.conf does not exist!\n");
		makeDefConf();
	}		
	
	return 1;
}

/*************************************************
Function:        // makeDefConf
Description:     // Generate the default welcomeSMS.conf file
Calls:           // 
Called By:       // initWSMSConf
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // welcomeSMS.conf
Return:          // 
Others:          // 
*************************************************/
void makeDefConf()
{
	FILE* fp;
	char fileName[32];
	
	system("touch ./conf/welcomeSMS.conf");
	system("chmod 644 ./conf/welcomeSMS.conf");
	
	sprintf(fileName,"./conf/welcomeSMS.conf");
	fp=fopen(fileName,"w");
	if(fp!=NULL)
	{
		fputs("#WelcomeSMS conf file\n\n",fp);
		fputs("#1-enable 0-disable\n",fp);
		fputs("flag=0\n\n",fp);
		fputs("#The day time to keep roamer record\n",fp);
		fputs("keep_day_time=7\n\n",fp);
		fputs("#The service number of the smpp link\n",fp);
		fputs("service_number=98765\n\n",fp);
		fflush(fp);
		fclose(fp);
	}	


	logMessage("Make the default log file\n");
	wsms_enable_flag=0;
	wsms_keep_day_time=7;
	sprintf(wsms_service_number,"98765");
}

/*************************************************
Function:        // initSMPPLink
Description:     // Init the smpp link
Calls:           // smpp_registerLink, smpp_attach_link
Called By:       // wsms_init
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 
Others:          // 
*************************************************/
int initSMPPLink()
{
	smpp_loadParam();
	smpp_link_no=smpp_registerLink(SMPP_CLIENT,BIND_TX,wsms_service_number,0);
	
	if((smpp_link_no & 0x80)==0x80)
	{
		smpp_link_no=smpp_link_no & 0x7f;
		smpp_attach_link(smpp_link_no,wsms_smppOnDataRecv,wsms_smppOnLinkStateChange);
	}
	sprintf(message,"init smpp link,smpp_link_no=%d\n",smpp_link_no);
	smpp_link_status=0;
	logMessage(message);
	return 1;
}

/*************************************************
Function:        // wsms_smppOnDataRecv
Description:     // The call-back function when receive data from SMSC
Calls:           // 
Called By:       // initSMPPLink
Table Accessed:  // 
Table Updated:   // 
Input:           // linkNo:the link no; pMsg:the data received; dataLen:the length of received data
Output:          // 
Return:          // 
Others:          // 
*************************************************/
int wsms_smppOnDataRecv(BYTE linkNo, SMPP_MSG *pMsg, WORD dataLen)
{ 
	int sequence_number = 100;
	SMPP_MSG	smpp_msg;

	memset(&smpp_msg, 0, sizeof(SMPP_MSG));
	//printf("DataRecv\n");
	switch (pMsg->message_type)
	{

		case 0x0C:	// SUBMIT SM RESP
			break;
		case 0x0B:	// SUBMIT SM 
			smpp_msg.message_type	= 0x0c;
			smpp_msg.pdu.submit_sm_resp.head.command_status	= htonl(ESME_ROK);
			smpp_msg.pdu.submit_sm_resp.head.sequence_number = pMsg->pdu.submit_sm.head.sequence_number;
			smpp_msg.pdu.submit_sm_resp.head.command_length  = 16 + strlen((char*)smpp_msg.pdu.submit_sm_resp.message_id);
			strcpy((char*)smpp_msg.pdu.submit_sm_resp.message_id,"0");
			smpp_send(linkNo, &smpp_msg, dataLen);		
			break;
		case 0x10: // deliver_sm_resp
			break;
		case 0x0F: // deliver_sm
			smpp_msg.message_type	= 0x10;
			smpp_msg.pdu.deliver_sm_resp.head.command_status	= htonl(ESME_ROK);
			smpp_msg.pdu.deliver_sm_resp.head.sequence_number	= pMsg->pdu.deliver_sm.head.sequence_number;
			smpp_msg.pdu.deliver_sm_resp.message_id = '0';
			smpp_msg.pdu.deliver_sm_resp.head.command_length = 17;
			smpp_send(linkNo, &smpp_msg, dataLen);
			break;
		default:
			break;	
  }
	return sequence_number;
}

/*************************************************
Function:        // wsms_smppOnLinkStateChange
Description:     // The call-back function when the smpp link state change
Calls:           // 
Called By:       // initSMPPLink
Table Accessed:  // 
Table Updated:   // 
Input:           // linkNo:the link no; state:the state of the smpp link
Output:          // 
Return:          // 
Others:          // 
*************************************************/
int wsms_smppOnLinkStateChange(BYTE linkNo, BYTE state)
{
	sprintf(message,"smpp link %d state change to %d\n",linkNo,state);
	logMessage(message);
	//printf("\nsmpp_tx link %d state change to %d\n", linkNo, state);
	if(state==0)
	{
		smpp_link_status=0;
/*
		smpp_link_no=smpp_registerLink(SMPP_CLIENT,BIND_TX,wsms_service_number,0);
		if((smpp_link_no & 0x80)==0x80)
		{
			smpp_link_no=smpp_link_no & 0x7f;
			smpp_attach_link(smpp_link_no,wsms_smppOnDataRecv,wsms_smppOnLinkStateChange);
		}
		else
		{
			smpp_link_no=0;
		}	
*/
		//printf("smpp_link_no=%d\n",smpp_link_no);
	}
	else
	{
		smpp_link_status=1;
		//wsms_send(&servers[0],"86755810008");
	}
	return linkNo;
}

/*************************************************
Function:        // wsms_send
Description:     // The call-back function when the smpp link state change
Calls:           // smsEncodeAll, smpp_send;
Called By:       // wsms_get_record
Table Accessed:  // 
Table Updated:   // 
Input:           // wsmsServer: the hpmn server; msisdn: the msisdn of the roamer 
Output:          // 
Return:          // 
Others:          // 
*************************************************/
void wsms_send(HpmnServer *wsmsServer,char* msisdn)
{
	SMPP_MSG sm_msg;
	unsigned char data[512];
	int i;
	int dataLen;
	
	sprintf(message,"Send smpp message to msisdn=%s\n",msisdn);
	logMessage(message);	
	//printf("send smpp message\n");
	memset(&sm_msg,0,sizeof(SMPP_MSG));
	sm_msg.message_type = 0x0B;		//PDU_SUBMIT_SM
	sm_msg.optional_param_flag1 = 0x00;
	sm_msg.optional_param_flag2 = 0x00;
	memset(sm_msg.pdu.submit_sm.service_type,0,6);
	sm_msg.pdu.submit_sm.source_addr_ton = 0x00;
	//Unknown, 1=international, 2=National
	sm_msg.pdu.submit_sm.source_addr_npi = 0x01;	//ISDN
	memcpy(sm_msg.pdu.submit_sm.source_addr, wsms_service_number,sizeof(wsms_service_number));
	sm_msg.pdu.submit_sm.dest_addr_ton = 0x01;	//National
	sm_msg.pdu.submit_sm.dest_addr_npi = 0x01;	//ISDN
	memcpy(sm_msg.pdu.submit_sm.destination_addr, msisdn,strlen(msisdn));
	sm_msg.pdu.submit_sm.esm_class = 0x00;
	sm_msg.pdu.submit_sm.protocol_id = 0x00;
	sm_msg.pdu.submit_sm.priority_flag = 0x03;
	memset(sm_msg.pdu.submit_sm.schedule_delivery_time, 0,1);
	memset(sm_msg.pdu.submit_sm.validity_period, 0,1);
	sm_msg.pdu.submit_sm.registered_delivery = 0x11;
	sm_msg.pdu.submit_sm.replace_if_present_flag = 0x01;
	sm_msg.pdu.submit_sm.sm_default_msg_id = 0x01;
	//7-bit
	if(wsmsServer->smsEncode == 0)
	{
		sm_msg.pdu.submit_sm.data_coding = 0x00;
	}
	//8-bit
	else if(wsmsServer->smsEncode == 1)	
	{
		sm_msg.pdu.submit_sm.data_coding = 0x04;
	}
	//16-bit
	else if(wsmsServer->smsEncode == 2)
	{
		sm_msg.pdu.submit_sm.data_coding = 0x08;
	}
	memset(data,0,512);
	memset(sm_msg.pdu.submit_sm.short_message,0,254);
		
	//int smsEncodeAll(int type,char* out,char* in,int len)
	//printf("in=%s\n",wsmsServer->wlContent);
	dataLen=smsEncodeAll(wsmsServer->smsEncode,data,wsmsServer->wlContent,strlen((char*)wsmsServer->wlContent));
	//printf("out \n");
	//for(i=0;i<dataLen;i++)
	//	printf("%02x ",data[i]);

	sm_msg.pdu.submit_sm.sm_length = dataLen%255;
	memcpy(sm_msg.pdu.submit_sm.short_message,data,dataLen>=254?254:(dataLen%255));	
	smpp_send(smpp_link_no,&sm_msg,0);

	for(i=0;i<wsmsServer->adCount;i++)
	{
		if(wsmsServer->adValid[i])
		{	
			memset(data,0,512);
			memset(sm_msg.pdu.submit_sm.short_message,0,254);
			dataLen=smsEncodeAll(wsmsServer->smsEncode,data,wsmsServer->adContent[i],strlen((char*)wsmsServer->adContent[i]));
			sm_msg.pdu.submit_sm.sm_length = dataLen%255;
			
			memcpy(sm_msg.pdu.submit_sm.short_message,data,dataLen>=254?254:(dataLen%255));
			smpp_send(smpp_link_no,&sm_msg,0);
		}	
	}
	
}

/*************************************************
Function:        // smsEncodeAll
Description:     // Encode the short message content
Calls:           // 
Called By:       // wsms_send
Table Accessed:  // 
Table Updated:   // 
Input:           // type: 0-7 bit,1-8 bit,2-16 bit; out: 
                    out: the encoded data
                    in: the original data
                    len: the length of the original data
Output:          // 
Return:          // the length of the encoded data
Others:          // 
*************************************************/
int smsEncodeAll(int type,unsigned char* out,unsigned char* in_tmp,int len)
{
	int length,lentmp;
	int i,j,index=0,tt,end;
	unsigned char mask;
	char tempstr[1024];	

	unsigned char in[4096];

	memcpy(in,in_tmp,len);

	if(type<0 || type>2)
		return 0;

	for(i=0;i<len;i++)
    	{
            switch(in[i])
            {
                    case '@':
                            in[i] = 0x00;
                            break;
                    case '$':
                            in[i] = 0x02;
                            break;
                    case '_':
                            in[i] = 0x11;
                            break;
                    case '[':
                            in[i] = 0x28;
                            break;
                    case ']':
                            in[i] = 0x29;
                            break;
                    case '/':
                            in[i] = 0x2F;
                            break;
                    case '`':
                            in[i] = 0x27;
                            break;
                    case '{':
                            in[i] = 0x28;
                            break;
                    case '}':
                            in[i] = 0x92;
                            break;
                    case 0x82:
                            in[i] = 0x05;
                            break;
                    case 0x85:
                            in[i] = 0x7F;
                            break;
                    case 0x8A:
                            in[i] = 0x04;
                            break;
                    case 0x8D:
                            in[i] = 0x07;
                            break;
                    case 0x95:
                            in[i] = 0x08;
                            break;
                    case 0x97:
                            in[i] = 0x06;
                            break;
                    case 0x9D:
                            in[i] = 0x03;
                            break;
                    default:
                            break;
            }
    	}
	if(type == 0)
	{
		
        lentmp=len;
        index=0;
        do
        {
        	end=index==0?lentmp:8;
			memcpy(&out[index*7],&in[index*8],end);
			tt=index++*7;
			for(i=0;i<end;i++)
			{
				j=i%7+1;
				mask=(unsigned char)((2<<(j-1))-1)&0xff;
				out[tt] |= (out[tt+1]&mask)<<(8-j);
				out[tt+1]>>=j;
				tt++;
			}
			lentmp-=8;
		}while(lentmp>0);
		

		length=len-len/8;
		
	}
	else if(type == 1)
	{
		memcpy(out,in,len);
		length=len;
	}	
	else if(type == 2)
	{
		unsigned int ii;
		for(i=0;i<len/2;i++)
		{
			tempstr[0]=in[i*2];
			tempstr[1]=in[i*2+1];
			tempstr[2]='\0';
			sscanf(tempstr,"%02x",&ii);
			out[i]=(unsigned char)ii;
		}
		length=len/2;
		//printf("In data\n");
		/*
		for(i=0;i<len;i++)
		{
			
			if(in[i]>=0x41 && in[i]<=0x46)
			{	
				in[i]=in[i]-0x37;
			}
			else if(in[i]>=0x61 && in[i]<=0x66)
			{
				in[i]=in[i]-0x57;
			}
			else
			{
				in[i]=in[i]-0x30;
			}			
			printf("%02x ",in[i]);
		}
		
		j=0;
		tt=0;
		for(i=0;i<len;i++)
		{
			if(i%2==0)
				out[j]+=in[i]*16;
			else
				out[j]+=in[i];	
			printf("out[%d]=%02x\n",j,out[j]);
			tt++;
			if(tt==2)
			{
				
				tt=0;
				j++;
			}	
		}
		length=j;
		*/
	}	
			
	return length;
}

/*************************************************
Function:        // wsms_del_overdue_sub
Description:     // Delete the overdue roamer records in the OMC_PUB.wsmsRoamer
Calls:           // 
Called By:       // wsms_timer
Table Accessed:  // OMC_PUB.wsmsRoamer
Table Updated:   // OMC_PUB.wsmsRoamer
Input:           // 
Output:          // 
Return:          // 
Others:          // 
*************************************************/
void wsms_del_overdue_sub()
{
	char sqlstr[128];	
	char timestr[32];
	time_t t;
	struct tm *local;
	struct tm *result;
	struct tm over_tm;
	time_t over_t;
	
	t=time(NULL);
	local=localtime(&t);
	//printf("local %d-%d-%d\n",local->tm_year,local->tm_mon,local->tm_mday);
	
	over_tm.tm_sec=0;
	over_tm.tm_min=0;
	over_tm.tm_hour=0;
	over_tm.tm_mday=local->tm_mday;
	over_tm.tm_mon=local->tm_mon;
	over_tm.tm_year=local->tm_year;
	//printf("over %d-%d-%d\n",over_tm.tm_year,over_tm.tm_mon,over_tm.tm_mday);
	//printf("wsms_keep_day_time=%d\n",wsms_keep_day_time);
	over_t=mktime(&over_tm)-wsms_keep_day_time*24*60*60;
	result=localtime(&over_t);
	//printf("result %d-%d-%d\n",result->tm_year,result->tm_mon,result->tm_mday);
	sprintf(timestr,"%04d-%02d-%02d 00:00:00",result->tm_year+1900,result->tm_mon+1,result->tm_mday);
	//printf("timestr=%s\n",timestr);
	sprintf(sqlstr,"DELETE FROM OMC_PUB.wsmsRoamer where logTime<'%s'",timestr);
	
	if(mysql_getnores(pubConn,sqlstr) != 0)
	{
		logMessage("[ERR %d][wsms_del_overdue_sub]:%s",mysql_errno(pubConn),sqlstr);
		return;
	}
	
	sprintf(message,"Delete the overdue roamer record log in before %s\n",timestr);
	logMessage(message);
	
	sprintf(sqlstr,"DELETE FROM OMC_PUB.sendSMSList where issue_time<'%s' and send_time != '0000-00-00 00:00:00'",timestr);
	
	if(mysql_getnores(pubConn,sqlstr) != 0)
	{
		logMessage("[ERR %d][wsms_del_overdue_sub]:%s",mysql_errno(pubConn),sqlstr);
		return;
	}
	return;
}

/*************************************************
Function:        // wsms_get_record
Description:     // Get the roamer record from OMC_PUB.wsmsRoamer to prepare send message
Calls:           // wsms_send
Called By:       // 
Table Accessed:  // OMC_PUB.wsmsRoamer
Table Updated:   // OMC_PUB.wsmsRoamer
Input:           // 
Output:          // 
Return:          // 
Others:          // 
*************************************************/
void wsms_get_record()
{
	char sqlstr[256];
	char updatestr[256];
	MYSQL_RES *res;
	MYSQL_ROW row;
	char parse_mcc[8];
	char parse_mnc[8];
	char imsi[32];
	char msisdn[32];
	HpmnServer *wsmsServer;
	int isExist=0;
	int i;
	
	sprintf(sqlstr,"SELECT imsi,msisdn FROM OMC_PUB.wsmsRoamer WHERE flag=0");
	
	
	if(!smpp_link_status)
		return;
	sprintf(sqlstr,"SELECT imsi,msisdn FROM OMC_PUB.wsmsRoamer WHERE flag=0");
	
	res=mysql_getres(pubConn,sqlstr);
	if(res == NULL)
	{
		logMessage("[ERR %d][wsms_get_record]:%s",mysql_errno(pubConn),sqlstr);
		return;
	}

	while((row = mysql_fetch_row(res)) != NULL)
	{
		isExist=0;
		sprintf(imsi,"%s",row[0]);
		sprintf(msisdn,"%s",row[1]);
		if(strlen(imsi)>5)
		{
			for(i=0;i<3;i++)
			{
				parse_mcc[i]=imsi[i];
			}
			parse_mcc[i]='\0';
			
			for(i=3;i<5;i++)
			{
				parse_mnc[i-3]=imsi[i];
			}
			parse_mnc[i-3]='\0';

			for(i=0;i<wsms_serv_count;i++)
			{
				if(strcmp(servers[i].mcc,parse_mcc)==0 && strcmp(servers[i].mnc,parse_mnc)==0)
				{
					wsmsServer=&servers[i];
					isExist=1;
					break;
				}		
			}
			//send the message and set the flag=1
			if(isExist)
			{
				if(wsmsServer->flag)
				{	
					sprintf(message,"The sub imsi=%s log in the network,now prepare to send smpp message\n",imsi);
					logMessage(message);
					wsms_send(wsmsServer,msisdn);
					sprintf(updatestr,"UPDATE OMC_PUB.wsmsRoamer SET flag=1 WHERE imsi='%s'",imsi);
					
					if(mysql_getnores(pubConn, updatestr) != 0)
					{
						logMessage("[ERR %d][wsms_get_record]:%s",mysql_errno(pubConn),updatestr);
					}
				}		
			}
			//delete the record
			else
			{
				if(def_hpmn_server_index != -1)
				{
					sprintf(message,"The sub imsi=%s log in the network,but not config,now prepare to send default smpp message\n",imsi);
					logMessage(message);
					wsms_send(&servers[def_hpmn_server_index],msisdn);
					sprintf(updatestr,"UPDATE OMC_PUB.wsmsRoamer SET flag=1 WHERE imsi='%s'",imsi);
					
					if(mysql_getnores(pubConn, updatestr) != 0)
					{
						logMessage("[ERR %d][wsms_get_record]:%s",mysql_errno(pubConn),updatestr);
					}	
				}
				else
				{		
					sprintf(message,"The sub imsi=%s log in the network,but not config,delete it\n",imsi);
					logMessage(message);
					sprintf(updatestr,"DELETE FROM OMC_PUB.wsmsRoamer WHERE imsi='%s'",imsi);
					
					if(mysql_getnores(pubConn, updatestr) != 0)
					{
						logMessage("[ERR %d][wsms_get_record]:%s",mysql_errno(pubConn),updatestr);
					}	
				}	
			}
		}			
	}
	mysql_free_result(res);
}

/*************************************************
Function:        // wsms_init
Description:     // The init function of the wsms
Calls:           // initDBConnection, initWSMSConf, initSMPPLink, wsms_update
Called By:       // omcMain
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 
Others:          // 
*************************************************/
int wsms_init(void)
{	
	logMessage("Init WSMS module...\n");
	initDBConnection();
	initWSMSConf();
	initSMPPLink();
	//printf("wsms_enable_flag=%d,wsms_keey_day_time=%d,wsms_service_number=%s\n",wsms_enable_flag,wsms_keep_day_time,wsms_service_number);
	wsms_update();
	return 0;
}

/*************************************************
Function:        // wsms_timer
Description:     // The timer function of the wsms
Calls:           // wsms_update, wsms_get_record, wsms_del_overdue_sub
Called By:       // omcMain
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 
Others:          // 
*************************************************/
void wsms_timer()
{
	static int wsms_update_time=0;
	static int wsms_get_record_time=0;
	static int wsms_check_link_time=0;
	static long wsms_del_record_time=0;
	
	if(!wsms_enable_flag)
		return;
	
	//5 minutes
	if(wsms_update_time++ > 15000)
	{
		wsms_update_time=0;
		wsms_update();
	}
	
	if(wsms_check_link_time++ > 3000)
	{
		wsms_check_link_time=0;
		if(smpp_link_status == 0)
		{
			initSMPPLink();
		}
	}
	
	//5 seconds
	if(wsms_get_record_time++ > 250)
	{
		wsms_get_record_time=0;
		wsms_get_record();
	
#if CDR_ALARM_FLAG == 1
		wsms_send_normal_sms();
#endif
	}

	//1 hour
	if(wsms_del_record_time++ > 180000)
	{
		wsms_del_record_time=0;
		wsms_del_overdue_sub();
	}
}


void wsms_send_sm_by_content(char *content,char* msisdn)
{
	SMPP_MSG sm_msg;
	unsigned char data[512];
	int dataLen;
	int ret;

	if(smpp_link_status == 0)
	{
		logMessage("wsms_send_sm_by_content,but smpp_link_status=0");
		return;
	}
	
	sprintf(message,"Send smpp message to msisdn=%s\n",msisdn);
	logMessage(message);	
	//printf("send smpp message\n");
	memset(&sm_msg,0,sizeof(SMPP_MSG));
	sm_msg.message_type = 0x0B;		//PDU_SUBMIT_SM
	sm_msg.optional_param_flag1 = 0x00;
	sm_msg.optional_param_flag2 = 0x00;
	memset(sm_msg.pdu.submit_sm.service_type,0,6);
	sm_msg.pdu.submit_sm.source_addr_ton = 0x00;
	//Unknown, 1=international, 2=National
	sm_msg.pdu.submit_sm.source_addr_npi = 0x01;	//ISDN
	memcpy(sm_msg.pdu.submit_sm.source_addr, wsms_service_number,sizeof(wsms_service_number));
	sm_msg.pdu.submit_sm.dest_addr_ton = 0x01;	//National
	sm_msg.pdu.submit_sm.dest_addr_npi = 0x01;	//ISDN
	memcpy(sm_msg.pdu.submit_sm.destination_addr, msisdn,strlen(msisdn));
	sm_msg.pdu.submit_sm.esm_class = 0x00;
	sm_msg.pdu.submit_sm.protocol_id = 0x00;
	sm_msg.pdu.submit_sm.priority_flag = 0x03;
	memset(sm_msg.pdu.submit_sm.schedule_delivery_time, 0,1);
	memset(sm_msg.pdu.submit_sm.validity_period, 0,1);
	sm_msg.pdu.submit_sm.registered_delivery = 0x11;
	sm_msg.pdu.submit_sm.replace_if_present_flag = 0x01;
	sm_msg.pdu.submit_sm.sm_default_msg_id = 0x01;

	sm_msg.pdu.submit_sm.data_coding = 0x04;
	
	
	memset(data,0,512);
	memset(sm_msg.pdu.submit_sm.short_message,0,254);
		
	//int smsEncodeAll(int type,char* out,char* in,int len)
	//printf("in=%s\n",wsmsServer->wlContent);
	dataLen=smsEncodeAll(1,data,(unsigned char*)content,strlen((char*)content));
	//printf("out \n");
	//for(i=0;i<dataLen;i++)
	//	printf("%02x ",data[i]);

	sm_msg.pdu.submit_sm.sm_length = dataLen%255;
	memcpy(sm_msg.pdu.submit_sm.short_message,data,dataLen>=254?254:(dataLen%255));	
	ret=smpp_send(smpp_link_no,&sm_msg,0);
	logMessage("send result=%d",ret);
}

int wsms_send_normal_sms()
{
	char sqlstr[256];
	MYSQL_RES *res;
	MYSQL_ROW row;
	MYSQL *dbConn;
	logMessage("wsms_send_normal_sms");	
	dbConn=mysql_conn("localhost","OMC_PUB");
	if(dbConn == NULL)
		logMessage("[ERR][wsms_send_normal_sms]:mysql_conn OMC_PUB\n");
		
	sprintf(sqlstr,"select instance,receiver,content from OMC_PUB.sendSMSList where send_time ='0000-00-00 00:00:00' limit 0,1");
	res=mysql_getres(dbConn,sqlstr);	
	if(res == NULL)
	{
		logMessage("[ERR %d][wsms_send_normal_sms]:%s\n",mysql_errno(dbConn),sqlstr);
		mysql_close(dbConn);
		return 0;
	}
	
	row = mysql_fetch_row(res);
	if(row == NULL)
	{
		mysql_free_result(res);
		mysql_close(dbConn);
		return 0;
	}
	
	wsms_send_sm_by_content(row[2],row[1]);
	
	sprintf(sqlstr,"update OMC_PUB.sendSMSList set send_time=FROM_UNIXTIME(%ld) where instance='%s';",time(NULL),row[0]);
	mysql_free_result(res);
	
	if(mysql_getnores(dbConn,sqlstr) != 0)
	{
		logMessage("[ERR %d][wsms_send_normal_sms]:%s\n",mysql_errno(dbConn),sqlstr);
	}
	
	mysql_close(dbConn);
	return 1;
}

