//--------------------------------------  
// USSD EAE write for ussd test
// Author: lw 2006/7/10
//--------------------------------------

#include "./include/smpp.h"

#define ISDN_LEN 9

typedef struct GameSession
{
        BYTE   LinkNo;
        BYTE   flag;
        BYTE   ussd_ref;
        BYTE   seed[4];
        BYTE   ssm_state;
        BYTE   shmsg[256];
        BYTE   us_prm;
        BYTE   input[4];
        BYTE   history[512];
        BYTE   count;
        char   msisdn[(ISDN_LEN+1)*2+2];
}
GameSession;



typedef enum _USSD_OP
{
	PSSDR = 0 ,  // MAP_Process_USS_Data request operation
	PSSRR = 1 ,  // MAP_Process_USS_Request request operation
	USSRR = 2 ,  // MAP_USS_Request Request operation
	USSNR = 3 ,  // MAP_USS_Notify Request operation
	OPENR = 4 ,  // open request operation
	RELR  = 5 ,  // Release request operation
  
	PSSDA = 6 ,  // MAP_Process_USS_Data Answer   operation
	PSSDE = 7 ,  // MAP_Process_USS_Data error   operation
	
	PSSRA = 8 ,  // MAP_Process_USS_Request Answer   operation
	PSSRE = 9 ,  // MAP_Process_USS_Request error   operation
	
	USSRA = 10 ,  // MAP_USS_Request Answer  operation
	USSRE = 11,  // MAP_USS_Request Error   operation
	
	USSNA = 12,  // MAP_USS_Notify Answer   operation
	USSNE = 13,  // MAP_USS_Notify  Error operation
	
	OPENE = 14,  // open error   operation
	RELE  = 15,  // Release error   operation
	
	PSSDS = 16,  // MAP_Process_USS_Data confirm operation
	PSSRS = 17,  // MAP_Process_USS_Request confirm operation
	USSRC = 18,  // MAP_USS_Request Confirm operation
	USSNC = 19,  // MAP_USS_Notify Confirm operation
	
	USSRS = 20,  // MAP_USS_Request response operation
	USSNS = 21,  // MAP_USS_Notify response operation
	PSSRC = 22,  // MAP_Process_USS_Request confirm operation
	OPENC = 23,  // open confirm operation
	RELC  = 24,  // Release confirm operation
} 
USSD_OP;

struct ussd_op
{
        char      *s;
        USSD_OP    v;
};

#define USSD_OP_NUM 25
#define USSD_OP_LEN 5

static const struct ussd_op op_map_name[25] = {
	{ "PSSDR" , PSSDR },  // 0  MAP_Process_USS_Data request operation 
	{ "PSSRR" , PSSRR },  // 1  MAP_Process_USS_Request request operation 
	{ "USSRR" , USSRR },  // 2  MAP_USS_Request Request operation
	{ "USSNR" , USSNR },  // 3  MAP_USS_Notify Request operation
  { "OPENR" , OPENR },  // 4  open request operation
  { "RELR " , RELR  },  // 5  Release request operation
  
  { "PSSAE" , PSSDA },  // 6  MAP_Process_USS_Data Answer    operation
  { "PSSDE" , PSSDE },  // 7  MAP_Process_USS_Data error   operation
  
  { "PSSRE" , PSSRA },  // 8  MAP_Process_USS_Request Answer   operation
  { "PSSRE" , PSSRE },  // 9  MAP_Process_USS_Request error   operation
  
  { "USSRA" , USSRA },  // 10  MAP_USS_Request Answer  operation
  { "USSRE" , USSRE },  // 11 MAP_USS_Request Error   operation
  
  { "USSNA" , USSNA },  // 12 MAP_USS_Notify Answer  operation
	{ "USSNE" , USSNE },  // 13 MAP_USS_Notify Error   operation
	
	{ "OPENE" , OPENE },  // 14 open error   operation
	{ "RELE " , RELE  },  // 15 Release error   operation
  
  { "PSSDS" , PSSDS },  // 16 MAP_Process_USS_Data confirm operation
  { "PSSRS" , PSSRS },  // 17 MAP_Process_USS_Request confirm operation
  { "USSRC" , USSRC },  // 18 MAP_USS_Request Confirm operation
  { "USSNC" , USSNC },  // 19 MAP_USS_Notify Confirm operation
  
  { "USSRS" , USSRS },  // 20 MAP_USS_Request response operation
  { "USSNS" , USSNS },  // 21 MAP_USS_Notify response operation
  { "PSSRC" , PSSRC },  // 22 MAP_Process_USS_Request confirm operation
	{ "OPENC" , OPENC },  // 23 open confirm operation
	{ "RELC " , RELC  },  // 24 Release confirm operation	
};

typedef enum US_STATE
{
	 US_IDLE=0,
	 US_OPENR,
	 US_OPENC,
	 US_OPENE,
	 US_PSSRR,
	 US_PSSRA,
	 US_PSSRE,
	 US_PSSRC,
	 US_PSSRS,
	 US_USSRR,
	 US_USSRC,
	 US_USSRS,
	 US_USSNR,
	 US_USSNC,
	 US_USSNS,
	 US_RELER,
	 US_RELEC,
	 US_RELES,
	 US_RELEE,
}
US_STATE;

#define MAX_GAME_SESSION 255

typedef struct GuessGame
{
	     BYTE   wxc2_hlr_number[8];
	     char   service_number[8];
	     BYTE   link_enable;
       BYTE   link;	     
}GuessGame;

GuessGame gg;


struct GameSession ssm_data[MAX_GAME_SESSION];

#define SD_PKT_NUM	10
#define STORE_MSG_ITEM	60

typedef struct	SMPP_MSG_STORE_STRUCT
{
	BYTE	short_message[SMPP_MSG_LEN];
	BYTE	message_id[65];
} SMPP_MSG_STORE_STRUCT;


#define MAX_GAME_LINK 1

static struct itimerval itimer,old_itimer;
static int		timer_counter[MAX_GAME_LINK];
static int		stateFlag[MAX_GAME_LINK];
static int		msg_count[MAX_GAME_LINK];
static int		msg_pointer[MAX_GAME_LINK];
static SMPP_MSG_STORE_STRUCT	store_msg_buf[MAX_GAME_LINK][STORE_MSG_ITEM];

static void On_Timer();
static void SetTimer();
static void smpp_test_init();
static int  smpp_onDataRecv(BYTE linkNo, SMPP_MSG *pData, WORD dataLen);
static int  smpp_onLinkStateChange(BYTE linkNo, BYTE linkstate);

BYTE hae_isdn_ston(BYTE *normal_isdn,BYTE *str_isdn)
{
	BYTE		ii;
	BYTE		len;

	len = strlen(str_isdn);
	if (len > ISDN_LEN*2-2)
		return 0;
	if ((len % 2) == 1)		// odd number
	{
		AsciiToBcd(normal_isdn+1,str_isdn,len-1);
		ii = len/2 + 1;
		normal_isdn[ii] = (str_isdn[len-1] - '0') << 4;
		normal_isdn[ii] |= 0x0E;
	}
	else
	{
		AsciiToBcd(normal_isdn+1,str_isdn,len);
		ii = len/2;
	}
	memset(normal_isdn+ii+1,0xEE,ISDN_LEN-ii-1);
	normal_isdn[0] = 0x91;	// default value
	return 1;
}


void hae_isdn_ntos(BYTE *str_isdn,BYTE *normal_isdn)
{
	BYTE		len = 0;
	BYTE		ii,jj;

	for (ii = 1;ii < ISDN_LEN;ii ++)
	{
		jj = (normal_isdn[ii] >> 4) & 0x0f;
		if (jj > 0x0c)
			break;
		str_isdn[len++] = jj + '0';
		jj = normal_isdn[ii] & 0x0f;
		if (jj > 0x0c)
			break;
		str_isdn[len++] = jj + '0';
	}
	str_isdn[len] = '\0';
}

int register_link()
{
	BYTE	        ret;
	
	strcpy( gg.service_number , "86755001");
	
	if( gg.link == MAX_SMPP_LINK+1 )
	{
		ret = smpp_registerLink(SMPP_CLIENT, BIND_TRX, gg.service_number, TRANSACTION);
		if ((ret&0x80) == 0x80) 
		{
			 gg.link = ret&0x7f;
			 printf("Get link for GuessGame EAE .link:%d",  gg.link);
			 smpp_attach_link(gg.link, smpp_onDataRecv, smpp_onLinkStateChange);
			 return 1;
		}
  }
  else
  {
  	  smpp_attach_link(gg.link, smpp_onDataRecv, smpp_onLinkStateChange);
	    return 1;
  }
	return 0;
}

void smpp_test_init(int flag)
{
	int  i;
	
	FILE *fp;
	char line[32];
	char test_file[] = "./conf/guess_number_test.conf";
	
  gg.link_enable = 0;
  gg.link = MAX_SMPP_LINK+1;
	for (i=0; i<MAX_GAME_LINK; i++)
	{
		memset(store_msg_buf[i], 0, sizeof(SMPP_MSG_STORE_STRUCT)*STORE_MSG_ITEM);
		msg_pointer[i]	= 0;
	}
	strcpy(gg.wxc2_hlr_number, "86755001");
	register_link();
	
	if( flag )
	{
			fp = fopen( test_file , "r");
			if( fp == NULL )
			{
				  printf("Open %s file fail!\n", test_file );
			}
			
			
			 while ( !feof ( fp ) )
		   {
		        if( fgets ( line, 256, fp ) == NULL )
		        {
		            break;
		        }
		        
		        for( i = 16 ; i > 6 ; i -- )
		        {
		        	 if( line[i] == ' ' || line[i] == '\t' || line[i] == '\r' || line[i] == '\n')
		        	 {
		        	 	  continue;
		        	 }
		        	 else if( isdigit( line[i] ) )
		        	 {
		        	 	  break;
		        	 }
		        }
		        if( i < 16 && i > 6 )
		        {
		        	 line[i+1] = '\0';
		        } 
		        line[16] = '\0';
		        for( i = 0 ; i <  MAX_GAME_SESSION ; i ++ )
		    	  {
		
		    	  	 	 if( !ssm_data[i].flag )
		    	  	 	 {
		    	  	 	    ssm_data[i].flag = 1;
		    	  	 	    ssm_data[i].ssm_state =6;
		    	  	 	    printf("read msisdn :%s\n",line);
		    	  	 	    strcpy ( ssm_data[i].msisdn, line );
		                //hae_isdn_ston ( temp_isdn, temp_msisdn ); 
		                //memcpy( ssm_data[i].msisdn ,  temp_isdn , ISDN_LEN);   
		                break;
		             }
		    	 }
		   }
	}
}

extern int iptrMainInit();


int main(int argc,char *argv[])
{
	int i;
	char ret;

	heartbeat_init(0xFFFF);
	debug_init();
	iptrMainInit();
	snmp_init(SMPP_PORT);
	mtp_shm_init();
	sccp_init();

	smpp_init_new();
	while ((ret = getopt(argc,argv,"n")) != -1)
	{
		switch (ret)
		{
			case 'n':
				printf("\n\n\nNetwork initial ussd to ms\n\n\n");
				smpp_test_init(1);
				break;
			default:
				smpp_test_init(0);
				break;
		}
	}
	
  
	for (i=0; i<MAX_GAME_LINK; i++)
	{
		stateFlag[i]	= FALSE;
		timer_counter[i]= 0;
		msg_count[i]	= 0;
	}

	opterr = 0;
	


	SetTimer();
	while(1)
	{
		usleep(50);
	}
	return 1;
}

void GameFsm();

static int call_flag = 0;

void On_Timer()
{
	int i;
	

	for (i=0; i<MAX_GAME_LINK; i++)
	{	// 2 msgs per second
		if (timer_counter[i]==25)
			timer_counter[i]=0;
		if ((timer_counter[i]%25)==0)
		{
			if( (call_flag++)%2 == 0 )
			{ 
			   GameFsm();
			}
		}
		timer_counter[i]++;

		if (msg_count[i] == SD_PKT_NUM)
		{
			smpp_close(i);
		}
	}

	iptrans_timer();
	debug_rt();
	snmp_timer();
	mtp3_proc();
	heartbeat_timer();
	sccp_timer();
	smpp_fsm_new();
}

void SetTimer()
{
	struct sigaction	act;
	act.sa_handler=On_Timer;
	sigemptyset(&act.sa_mask);
	act.sa_flags=0;
	if(sigaction(SIGALRM,&act,NULL)<0)
	{
		perror("Produce Sigaction");
		exit(1);
	}
	
	itimer.it_interval.tv_sec=0;
	itimer.it_interval.tv_usec=20*1000;
	itimer.it_value.tv_sec=0;
	itimer.it_value.tv_usec=20*1000;

	if (setitimer(ITIMER_REAL,&itimer,&old_itimer) !=0 )
	{
		printf("Setting Timer  error! \n");
		exit(1);
	}
}

void SendMsgToSMPP(int sid , BYTE* msg , BYTE ussd_op);


int smpp_onDataRecv(BYTE linkNo, SMPP_MSG *pMsg, WORD dataLen)
{
	int sequence_number=100;
	SMPP_MSG	smpp_msg;
	int i;
	//BYTE  temp_isdn[ISDN_LEN+1];
	//BYTE  temp_msisdn[65];
	struct GameSession *ssm_ptr;
	char  temp_str[256];

	switch (pMsg->message_type)
	{

	case 0x0C:	/* SUBMIT SM RESP */
		printf("[TEST PROGRAM]Link %d received SUBMIT SM RESP.\n", linkNo);
		break;
	case 0x0F:	/* DELIVER SM */
		printf("[TEST PROGRAM]Link %d received DELIVER SM. op:%d \n", linkNo , pMsg->pdu.deliver_sm.ussd_service_op);
    switch( pMsg->pdu.deliver_sm.ussd_service_op )
    {
    	 case PSSRR:
    	 	    smpp_send_ascout("\33[32mGuess Game Recv PSSRR\33[0m\n");
    	 	    if( pMsg->pdu.deliver_sm.user_message_reference >=  MAX_GAME_SESSION )
    	      {
    	      	   smpp_send_ascout("\33[32mThe session id is too large!\33[0m\n");
    	      	   return -1;
    	      }
    	 	    for( i = 0 ; i <  MAX_GAME_SESSION ; i ++ )
    	      {
    	  	     if( pMsg->pdu.deliver_sm.user_message_reference == ssm_data[i].ussd_ref )
    	  	     {
    	  	 	       if( ssm_data[i].flag == 1)
    	  	 	       {
	                    smpp_send_ascout("\33[32mThe session id is in used!\33[0m\n");
    	  	 	   	      return -1;
    	  	 	       }
    	  	 	   }
    	  	 	}    
    	  	 	for( i = 0 ; i <  MAX_GAME_SESSION ; i ++ )
    	      {
    	  	 	       if( ssm_data[i].flag == 0)
    	  	 	       {
	                    break;
    	  	 	       }
    	  	 	}  
    	  	  ssm_data[i].flag = 1;
    	  	 	ssm_data[i].ssm_state =1;
    	  	 	ssm_data[i].ussd_ref = pMsg->pdu.deliver_sm.user_message_reference;
    	  	 	strcpy ( ssm_data[i].msisdn, pMsg->pdu.deliver_sm.source_addr );
    	 	    break;
    	 case USSRC:
    	 	    for( i = 0 ; i <  MAX_GAME_SESSION ; i ++ )
    	      {
    	  	     if( strcmp( pMsg->pdu.deliver_sm.source_addr ,ssm_data[i].msisdn ) == 0 )
    	  	     {
    	  	 	       break;
    	  	 	   }
    	  	 	}
    	  	 	if( i == MAX_GAME_SESSION )
    	  	 	{
    	  	 		 printf( "unkown USSRC msisdn :%s \n",pMsg->pdu.deliver_sm.source_addr );
    	  	 		 SendMsgToSMPP(  pMsg->pdu.deliver_sm.user_message_reference ,ssm_ptr->shmsg , RELR );
    	  	 		 ssm_ptr->us_prm = US_RELER;
    	  	 		 return -1;
    	  	 	}
    	 	    ssm_ptr = &ssm_data[i];
    	 	    ssm_ptr->us_prm = US_USSRC;
    	 	    smpp_send_ascout("\33[32mGuess Game Recv USSRC\33[0m\n");
    	 	    sprintf(temp_str, "\33[32mGame Fsm state :% d sid : %d\33[0m\n" , ssm_ptr->ssm_state , pMsg->pdu.deliver_sm.user_message_reference);
			      smpp_send_ascout(temp_str); 
    	 	    if( pMsg->pdu.deliver_sm.sm_length == 4 )
    	 	    {
    	 	        memcpy( &ssm_ptr->input , &pMsg->pdu.deliver_sm.short_message  ,4);
    	 	        ssm_ptr->input[0] -= '0'; 
    	 	        ssm_ptr->input[1] -= '0';
    	 	        ssm_ptr->input[2] -= '0';
    	 	        ssm_ptr->input[3] -= '0';
    	 	    }
    	 	    strcpy( ssm_ptr->shmsg , pMsg->pdu.deliver_sm.short_message  );
    	 	    ssm_ptr->shmsg[pMsg->pdu.deliver_sm.sm_length]  = '\0';
    	 	    break;
    	 case USSNC:
    	 	    for( i = 0 ; i <  MAX_GAME_SESSION ; i ++ )
    	      {
    	  	     if( strcmp( pMsg->pdu.deliver_sm.source_addr ,ssm_data[i].msisdn ) == 0 )
    	  	     {
    	  	 	       break;
    	  	 	   }
    	  	 	}
    	  	 	if( i == MAX_GAME_SESSION )
    	  	 	{
    	  	 		 printf( "unkown USSRC msisdn :%s \n",pMsg->pdu.deliver_sm.source_addr );
    	  	 		 if( pMsg->pdu.deliver_sm.user_message_reference < MAX_GAME_SESSION )
    	  	 		 {
    	  	 		     ssm_ptr = &ssm_data[i];
    	  	 		     strcpy(  ssm_ptr->shmsg , " incorrect user msg reference " );
    	  	 		     SendMsgToSMPP(  pMsg->pdu.deliver_sm.user_message_reference ,ssm_ptr->shmsg , RELR );
    	  	 		 }
    	  	 		 return -1;
    	  	 	}
    	 	    ssm_ptr = &ssm_data[i];
    	 	    ssm_ptr->us_prm = US_USSNC;
    	 	    smpp_send_ascout("\33[32mGuess Game Recv USSNC\33[0m\n");
    	 	    break;
    	 case RELR:
    	 	     for( i = 0 ; i <  MAX_GAME_SESSION ; i ++ )
    	      {
    	  	     if( strcmp( pMsg->pdu.deliver_sm.source_addr ,ssm_data[i].msisdn ) == 0 )
    	  	     {
    	  	 	       break;
    	  	 	   }
    	  	 	}
    	  	 	if( i == MAX_GAME_SESSION )
    	  	 	{
    	  	 		 
    	  	 		 //sprintf( ssm_ptr->shmsg ,"unkown RELR msisdn :%s \n",pMsg->pdu.deliver_sm.source_addr );
    	  	 		 //SendMsgToSMPP(  pMsg->pdu.deliver_sm.user_message_reference ,ssm_ptr->shmsg , RELR );
    	  	 		 return -1;
    	  	 	}
    	 	    ssm_ptr = &ssm_data[i];
    	 	    ssm_ptr->us_prm = US_RELEC;
    	 	    smpp_send_ascout("\33[32mGuess Game Recv RELR\33[0m\n");
    	 	    break;
    	 case RELC:
    	 	    for( i = 0 ; i <  MAX_GAME_SESSION ; i ++ )
    	      {
    	  	     if( strcmp( pMsg->pdu.deliver_sm.source_addr ,ssm_data[i].msisdn ) == 0 )
    	  	     {
    	  	 	       break;
    	  	 	   }
    	  	 	}
    	  	 	if( i == MAX_GAME_SESSION )
    	  	 	{
    	  	 		 printf( "unkown RELC msisdn :%s \n",pMsg->pdu.deliver_sm.source_addr );
    	  	 		 SendMsgToSMPP(  pMsg->pdu.deliver_sm.user_message_reference ,ssm_ptr->shmsg , RELR );
    	  	 		 return -1;
    	  	 	}
    	 	    ssm_ptr = &ssm_data[i];
    	 	    ssm_ptr->us_prm = US_RELES;
    	 	    smpp_send_ascout("\33[32mGuess Game Recv RELR\33[0m\n");
    	 	    break;
    	 default:
    	 	    break;
    }
		
		/* fill with DELIVER SM RESP structure. */
		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				    = 0x0;
		smpp_send(linkNo, &smpp_msg, dataLen);
		smpp_send_ascout("Send deliver_sm_resp\n");
		call_flag = 0;
		break;
  }
	return sequence_number;
}

int smpp_onLinkStateChange(BYTE linkNo, BYTE linkstate)
{
	printf("[TEST PROGRAM]link %d state change to %d\n",linkNo, linkstate);
	if (linkstate == 1)
		gg.link_enable	= 1;
	else
		gg.link_enable	= 0;

	return linkNo;
}

int RandomNum(BYTE *seed)
{
	  int count , i , j;
	  i = j = count = 0 ;
    while( count < 4 )
    {
    	  j = 1 +(int)(10.0*rand()/(RAND_MAX+1.0));
    	  if( j >= 10 )
    	  {
    	  	continue;
    	  }
    	  for( i = count ; i > 0 ; i-- )
    	  {
    	  	 if( j == seed[i] )
    	  	 {
    	  	 	  break;
    	  	 }
    	  }
    	  if( !count || j !=  seed[i])
    	  {
    	  	 seed[count] = j;
    	  	 count++;
    	  }
    }
    return (count == 4 ? 1 : 0);
}


int CheckInput(BYTE *input)
{
    int input_index ,index;
    
    for( input_index = 0 ; input_index < 4 ; input_index++ )
    {
        for( index = 0 ; index < 4 ; index++ )
        {
            if( index != input_index && input[input_index] == input[index] )
            {
                return 0;
            }
        }
    } 
    return 1;
}

int GuessNumber(BYTE* input,BYTE* seed)
{
    BYTE seed_index , input_index ;
    BYTE rt_a       , rt_b        ;
    
    rt_a = rt_b = 0;
    for( input_index = 0 ; input_index < 4 ; input_index++ )
    {
        for( seed_index = 0 ; seed_index < 4 ; seed_index++ )
        {
            if( input[(int)input_index] == seed[(int)seed_index] )
            {
                if( input_index == seed_index )
                {
                    rt_a++;
                }
                else 
                {
                    rt_b++;
                }
            }
        }
    } 
    return (rt_a << 4) + rt_b;
}

void SendMsgToSMPP(int sid , BYTE* msg , BYTE ussd_op)
{
	   SMPP_MSG         pMsg;
	   int              data_len;
	   PDU_SUBMIT_SM   *submit_sm;
	   struct GameSession *ssm_ptr;
	   char             temp_str[256];
	   
	   if( sid >= MAX_GAME_SESSION )
	   {
	      ssm_ptr = &ssm_data[sid - MAX_GAME_SESSION]; 
	   }
	   else
	   {
	   	  ssm_ptr = &ssm_data[sid]; 
	   } 
	   memset( &pMsg , 0 , sizeof(SMPP_MSG));
	   
	   submit_sm = &pMsg.pdu.submit_sm; 
	   pMsg.message_type	= 0x0B;
	   pMsg.optional_param_flag1 =  0x08000001;
	   if( sid < MAX_GAME_SESSION )
	     submit_sm->user_message_reference = ssm_ptr->ussd_ref;
	   else
	   	 submit_sm->user_message_reference = 0xFFFF;
	   submit_sm->ussd_service_op        = ussd_op;
	   strcpy( submit_sm->service_type , "USSD" );
	   strcpy( submit_sm->destination_addr , ssm_ptr->msisdn   );
	   strcpy( submit_sm->source_addr      , gg.service_number );
	   //hae_isdn_ntos( submit_sm->destination_addr , ssm_ptr->msisdn ); 
	   sprintf(temp_str, "\33[32mGuessGame send smpp msg: ussd_op :%s  ssm_ptr->msisdn :%s user_refer : %d\33[0m\n" 
	           , op_map_name[submit_sm->ussd_service_op].s ,ssm_ptr->msisdn , submit_sm->user_message_reference);
		 smpp_send_ascout(temp_str);   
     submit_sm->sm_length =  strlen( msg );
     strcpy( submit_sm->short_message , msg );
     smpp_send( gg.link , &pMsg , data_len );
}


void GameFsm()
{
     int rt;
     int i;
     char temp_str[1024];
     struct GameSession *ssm_ptr;
     
     if( !gg.link_enable && !register_link() )
     {
     	    smpp_send_ascout("Try to connect to WXC2 HLR fail\n");
     	    printf("Try to connect to WXC2 HLR fail\n");
  	      return;
     }
     //sprintf(debugBuf,);
	   //smpp_send_ascout("The session id is in used!\n");
     
     for( i = 0 ;i < MAX_GAME_SESSION ; i++)
     {
     	   ssm_ptr = &ssm_data[i];
     	   if( ssm_ptr->flag == 0 )
     	   {
     	   	 continue;
     	   }
     	   if( ssm_ptr->us_prm == US_RELES )
     	   {
     	   	   ssm_ptr->ssm_state = 7;
     	   }
     	   else if( ssm_ptr->us_prm == US_RELEC )
     	   {
     	   	  strcpy( ssm_ptr->shmsg , "Release ack!\n");
     	   	  SendMsgToSMPP( i ,ssm_ptr->shmsg , RELC );
     	   	  ssm_ptr->ssm_state = 7;
     	   }
		     switch( ssm_ptr->ssm_state )
		     {
		     	    case 0:
		     	    	   continue;
		          case 1:		  
		          	   sprintf(temp_str, "\33[32mGame Fsm state :% d sid : %d\33[0m\n" , ssm_ptr->ssm_state , i);
		          	   smpp_send_ascout(temp_str);        	   
		               if( !RandomNum( ssm_ptr->seed ) )
		               {
		                   //"Create random number fail"
		                   return;
		               }     
		               //sid = pMsg->pdu.deliver_sm.user_message_reference ;
		               //if( sid > MAX_GAME_SESSION )
		               //{
		               //    //"Game EAE do no support so much session .sid :%d",sid
		               //    return;
		               //} 
		               sprintf( ssm_ptr->shmsg ," WellCome to WXC2 Online Guess Number Game System!\n Please input you guess nubmer:\n");
		               SendMsgToSMPP( i ,ssm_ptr->shmsg , USSRR );
		               sprintf(temp_str , "\n\n\33[32mSend Game Info :\n%s\33[0m\n\n" , ssm_ptr->shmsg );
		               smpp_send_ascout(temp_str);
		               ssm_ptr->ssm_state = 2;
		               break;
		          case 2:
		               switch( ssm_ptr->us_prm )
		               {
		               	   case US_IDLE:
		               	        break;
		                   case US_RELER:
		                        break;
		                   case US_USSRC:
		                   	    sprintf(temp_str, "\33[32mGame Fsm state :% d sid : %d\33[0m\n" , ssm_ptr->ssm_state , i);
		          	            smpp_send_ascout(temp_str);     
		                   	    if( strlen(ssm_ptr->shmsg) != 4 )
							          	   {
							          	   	   sprintf(temp_str, "\33[32mThe input string length is not 4. input again.\33[0m\n");
		          	                 smpp_send_ascout(temp_str);
		          	                 strcpy ( ssm_ptr->shmsg   , "The input string length is not 4. input again."); 
		                             SendMsgToSMPP( i ,ssm_ptr->shmsg , USSRR );
		                             sprintf(temp_str , "\n\n\33[32mSend Game Info :\n%s\33[0m\n\n" , ssm_ptr->shmsg );
		                             smpp_send_ascout(temp_str);
		                             ssm_ptr->shmsg[0] = '\0';
		                             ssm_ptr->us_prm  = US_IDLE;
							                   return;
							          	   }  
		                        if( !CheckInput( ssm_ptr->input ) )
		                        {
		                           sprintf( ssm_ptr->shmsg ,"Input is Error! Please input four difference numbers.\n");
		                           SendMsgToSMPP(  i ,ssm_ptr->shmsg , USSRR );
		                        }
		                        rt = GuessNumber( ssm_ptr->input , ssm_ptr->seed ) & 0xFF ;
		                        ssm_ptr->count ++;
		                        if( ssm_ptr->count >= 8 )
		                        {
		                            sprintf ( ssm_ptr->shmsg ,"Game Over!\n");
		                            sprintf ( temp_str , "NO%d:%d%d%d%d ",ssm_ptr->count , ssm_ptr->input[0],ssm_ptr->input[1],ssm_ptr->input[2],ssm_ptr->input[3]);
		                            strcat ( ssm_ptr->history , temp_str );
		                            sprintf ( temp_str         , "->%dA%dB\n" , rt>>4 , rt&0x0F);
		                            strcat  ( ssm_ptr->history , temp_str );
		                            //strcat  ( ssm_ptr->shmsg , ssm_ptr->history );
		                            SendMsgToSMPP( i ,ssm_ptr->shmsg , USSNR );
		                            sprintf(temp_str , "\n\n\33[32mSend Game Info :\n%s\33[0m\n\n" , ssm_ptr->shmsg );
		                            smpp_send_ascout(temp_str);
		                            ssm_ptr->ssm_state = 3;
		                            ssm_ptr->us_prm  = US_IDLE;
		                            return ;
		                        }
		                        sprintf( temp_str , "NO%d:%d%d%d%d ",ssm_ptr->count , ssm_ptr->input[0],ssm_ptr->input[1],ssm_ptr->input[2],ssm_ptr->input[3]);
		                        if( rt != 0x40 )
		                        {
		                            strcat ( ssm_ptr->history , temp_str );
		                            sprintf( temp_str         , "->%dA%dB\n" , rt>>4 , rt&0x0F);
		                            strcat ( ssm_ptr->history , temp_str );
		                            strcpy ( ssm_ptr->shmsg   , ssm_ptr->history ); 
		                            SendMsgToSMPP( i ,ssm_ptr->shmsg , USSRR );
		                            sprintf(temp_str , "\n\n\33[32mSend Game Info :\n%s\33[0m\n\n" , ssm_ptr->shmsg );
		                            smpp_send_ascout(temp_str);
		                            ssm_ptr->us_prm  = US_IDLE;
		                        }
		                        else
		                        {
		                            strcat ( ssm_ptr->history , temp_str );
		                            sprintf( temp_str         , "->%dA%dB\n" , rt>>4 , rt&0x0F);
		                            strcat ( ssm_ptr->history , temp_str );
		                            strcpy ( ssm_ptr->shmsg   , ssm_ptr->history ); 
		                            SendMsgToSMPP( i ,ssm_ptr->shmsg , USSNR );
		                            sprintf(temp_str , "\n\n\33[32mSend Game Info :\n%s\33[0m\n\n" , ssm_ptr->shmsg );
		                            smpp_send_ascout(temp_str);
		                            ssm_ptr->ssm_state = 3;
		                            ssm_ptr->us_prm  = US_IDLE;
		                        }
		                        break;     
		               }
		               break;
              case 3:
              	   if( ssm_ptr->us_prm == US_USSNC )
              	   {
              	       switch( ssm_ptr->count )
		                   {
		                     case 1:
		                        sprintf ( ssm_ptr->shmsg ," So Luck!\n");
		                        break;
		                     case 2:
		                        sprintf ( ssm_ptr->shmsg ," Luck\n");
		                        break;
		                     case 3:
		                        sprintf ( ssm_ptr->shmsg ," Perfect\n");
		                        break;
		                     case 4:
		                        sprintf ( ssm_ptr->shmsg ," Very Good\n");
		                        break;
		                     case 5:
		                        sprintf ( ssm_ptr->shmsg ," Good\n");
		                        break;
		                     case 6:
		                     case 7:
		                     case 8:
		                        sprintf ( ssm_ptr->shmsg ," Correct\n");
		                        break;
		                     default:
		                     	  strcpy ( ssm_ptr->shmsg   , ssm_ptr->history ); 
		                     	  SendMsgToSMPP( i ,ssm_ptr->shmsg , USSNR );
		                        sprintf(temp_str , "\n\n\33[32mSend Game Info :\n%s\33[0m\n\n" , ssm_ptr->shmsg );
		                        smpp_send_ascout(temp_str);
		                        ssm_ptr->ssm_state = 4;
		                     	  return;
		                     	  break;
		                  }
		                  SendMsgToSMPP( i ,ssm_ptr->shmsg , USSNR );
		                  sprintf(temp_str , "\n\n\33[32mSend Game Info :\n%s\33[0m\n\n" , ssm_ptr->shmsg );
		                  smpp_send_ascout(temp_str);
		                  ssm_ptr->ssm_state = 4;
		               }
		          case 4:
		          	   if( ssm_ptr->us_prm == US_USSNC )
              	   {
			          	   sprintf(temp_str, "\33[32mGame Fsm state :% d sid : %d\33[0m\n" , ssm_ptr->ssm_state , i);
			          	   smpp_send_ascout(temp_str); 
			               sprintf( ssm_ptr->shmsg ," Guess Number\n1 . Restart game \n 2 . exit\n");
			               SendMsgToSMPP( i ,ssm_ptr->shmsg , USSRR );
			               ssm_ptr->ssm_state = 5;  
			               ssm_ptr->count =0;
			               sprintf(temp_str , "\n\n\33[32mSend Game Info :\n%s\33[0m\n\n" , ssm_ptr->shmsg );
			               smpp_send_ascout(temp_str);
			             }
		               break;
		          case 5:
		          	   if( ssm_ptr->us_prm == US_USSRC )
              	   {
			                if( ssm_ptr->shmsg[0] == '1' )
			                {
			                	 if( !RandomNum( ssm_ptr->seed ) )
		                     {
		                          //"Create random number fail"
		                          return;
		                     }   
		                     sprintf( ssm_ptr->shmsg ," Game Restart.input four difference numbers: \n");
			                   SendMsgToSMPP( i ,ssm_ptr->shmsg , USSRR );
			                   ssm_ptr->history[0]= '\0';
			                   ssm_ptr->ssm_state = 2;
			                }  
			                else if( ssm_ptr->shmsg[0] == '2' )
			                {
			                	 sprintf( ssm_ptr->shmsg ," Game Exit.GoodBye! Wellcome to use WXC2 system!\n");
			                   SendMsgToSMPP( i ,ssm_ptr->shmsg , USSNR );
			                   memset( ssm_ptr , 0 , sizeof(GameSession ));
			                   
			                } 
			                else
			                {
			                	 sprintf( ssm_ptr->shmsg ," Unexpeced menu selection!\n");
			                   SendMsgToSMPP( i ,ssm_ptr->shmsg , USSNR );
			                   ssm_ptr->ssm_state = 7;
			                }
			                sprintf(temp_str , "\n\n\33[32mSend Game Info :\n%s\33[0m\n\n" , ssm_ptr->shmsg );
			                smpp_send_ascout(temp_str);
			             }
		          	   break;
		         case 6:
		         	     if( gg.link_enable )
		         	     {
			         	     sprintf(temp_str, "\33[32mGame Fsm state :% d sid : %d\33[0m\n" , ssm_ptr->ssm_state , i);
			          	   smpp_send_ascout(temp_str);        	   
			               if( !RandomNum( ssm_ptr->seed ) )
			               {
			                   //"Create random number fail"
			                   return;
			               }     
			               sprintf( ssm_ptr->shmsg ," WellCome to WXC2 Online Guess Number Game System!\n Please input you guess nubmer:\n");
			               SendMsgToSMPP( i+MAX_GAME_SESSION ,ssm_ptr->shmsg , USSRR );
			               sprintf(temp_str , "\n\n\33[32mSend Game Info :\n%s\33[0m\n\n" , ssm_ptr->shmsg );
			               smpp_send_ascout(temp_str);
		                 ssm_ptr->ssm_state = 2;
		                 sprintf(temp_str, "\33[32mGame Fsm change to state :% d sid : %d\33[0m\n" , ssm_ptr->ssm_state , i);
			          	   smpp_send_ascout(temp_str); 
		         	     }
		         	     break;
		          case 7:  //release
		          	   if( ssm_ptr->us_prm == US_USSNC )
              	   {
              	   	   strcpy( ssm_ptr->shmsg , "session is closed");
              	   	   SendMsgToSMPP( i ,ssm_ptr->shmsg , RELR );
              	   }
		               sprintf(temp_str, "\33[32mRecv Release command ! sid: %d ussd_ref: %d\33[0m\n" , i ,ssm_ptr->ussd_ref);
			          	 smpp_send_ascout(temp_str); 
		          	   memset( ssm_ptr , 0 , sizeof(GameSession ));         	   
		          	   break;
		     }
     }
}

