/* 
** CDMA 2000 project, SMPP module
**
** File name: smpp_fsm.c
** Written by Li Long at 2004-11-25
** CVS $Id: smpp_fsm.c,v0.1 2004/11/25 17:03:14 lilong Exp $
**
*/

#include "./include/smpp.h"
#include "./include/smpp_ext.h"

// fix multiple definition====================================
extern int     smpp_msg_buf_len[MAX_SMPP_LINK];
//

static int	smpp_timerCount = 0;
//static int flag=-1;

/* Timer variable definitions. */
static BYTE	session_init_flag[MAX_SMPP_LINK];
static WORD	session_init_timer[MAX_SMPP_LINK];
static BYTE	enquire_link_flag[MAX_SMPP_LINK];
static WORD	enquire_link_timer[MAX_SMPP_LINK];
static BYTE	inactivity_flag[MAX_SMPP_LINK];
static WORD inactivity_timer[MAX_SMPP_LINK];
static BYTE	response_flag[MAX_SMPP_LINK];
static WORD	response_timer[MAX_SMPP_LINK];
static BYTE init_tcp_client_timeout[MAX_SMPP_LINK]={0};
static WORD suspend_timer = 0;

void smpp_stateInit()
{
	int i;

	for (i=0; i<MAX_SMPP_LINK; i++)
	{
		session_init_flag[i]		= 0;
		enquire_link_flag[i]		= 0;
		inactivity_flag[i]			= 0;
		response_flag[i]			= 0;
		session_init_timer[i]		= 0;
		enquire_link_timer[i]		= 0;
		inactivity_timer[i]			= 0;
		response_timer[i]			= 0;
		smpp_state[i]				= 0;
		smpp_msg_buf_len[i] = 0;
		if (i<MAX_SMPP_LINK/4)
		{
			smpp_hearbeat_status[i] = 0;
		}

		memset(exterEvent[i], 0, CMD_BUF_SIZE);
		memset(interEvent[i], 0, CMD_BUF_SIZE);
		inter_head[i]		= 0;
		inter_tail[i]		= 0;
		exter_head[i]		= 0;
		exter_tail[i]		= 0;
	}
}

void smpp_fsm_new()
{
	int		link;
	char	debugBuf[256];
	BYTE	temp_status;
	BYTE	platform_heartbeat_len;

	if(smpp_timerCount++>1000)//1000*10ms=10s
	{
		smpp_checkParam();
		smpp_timerCount = 0;
	}	

	smpp_rvMsgOverTCP();
//	smpp_rvMsgOverSCCP(SMPP_PPS_USERTYPE);
	smpp_rvMsgOverSCCP(SMPP_SMSC_USERTYPE);
	smpp_debugTimer();
	for(link=0; link<MAX_SMPP_LINK; link++)
	{
		if ((smpp_param[link].link_enable&0x01) == 0)	continue;
//		printf("link %d tcp client flag =%d, Mysock.Sockets[%d] = %d\n",
//			link, smpp_TCPClientFlag[link],
//			link, Mysock.Sockets[link]);
		if ((smpp_TCPClientFlag[link] == TRUE) && (Mysock.Sockets[link] == 0) && (init_tcp_client_timeout[link] == 0) ) {
//			printf("link %d start TCP connect.\n", link);
			smpp_tcp_connect(link);
			init_tcp_client_timeout[link] = 200;
			continue;
		}
		if (init_tcp_client_timeout[link] > 0) init_tcp_client_timeout[link]--;

		/* Session init timer */
		if (TRUE == session_init_flag[link])
		{
			session_init_timer[link]++;
			if (session_init_timer[link] > 100*smpp_param[link].session_init_timer)
			{
				session_init_timer[link]	= 0;
				inter_head[link]	= (inter_head[link]+1)&0x7;
				interEvent[link][inter_head[link]]	= SessionInitTimeout;
				#ifdef SMPP_DEBUG
				if ((smppDebug.debug_switch == 1) || (smppDebug.link_switch[link] == 1))
				{
					sprintf(debugBuf, "link %d session_init_timer TIMEOUT.\n", link);
					smpp_send_ascout(debugBuf);
				}
				#endif
			}
		}
		/* Enquire link timer */
		if (TRUE == enquire_link_flag[link])
		{
			enquire_link_timer[link]++;
			if (enquire_link_timer[link] > 100*smpp_param[link].enquire_link_timer)
			{
				enquire_link_timer[link]	= 0;
				inter_head[link]	= (inter_head[link]+1)&0x7;
				interEvent[link][inter_head[link]]	= EnquireLinkTimeout;
				#ifdef SMPP_DEBUG
				if ((smppDebug.debug_switch == 1) || (smppDebug.link_switch[link] == 1))
				{
					sprintf(debugBuf, "link %d T1 (Enquire link timer) TIMEOUT.\n", link);
					smpp_send_ascout(debugBuf);
				}
				#endif
			}
		}
		/* Inactivity timer */
		if (TRUE == inactivity_flag[link])
		{
			inactivity_timer[link]++;
			if (inactivity_timer[link] > 100*smpp_param[link].inactivity_timer)
			{
				inactivity_timer[link]	= 0;
				inter_head[link]	= (inter_head[link]+1)&0x7;
				interEvent[link][inter_head[link]]	= InactivityTimeout;
				#ifdef SMPP_DEBUG
				if ((smppDebug.debug_switch == 1) || (smppDebug.link_switch[link] == 1))
				{
					sprintf(debugBuf, "link %d T2 (Inactivity timer) TIMEOUT.\n", link);
					smpp_send_ascout(debugBuf);
				}
				#endif
			}
		}
	}

	for(link=0; link<MAX_SMPP_LINK; link++)
	{
		if (linkAttachFlag[link] == FALSE) continue;
		if ( (Mysock.Sockets[link] <= 0) && (SMPP_TCP == smpp_param[link].link_type) )
			continue;
		switch(smpp_state[link])
		{
		case INIT:
			smpp_state[link] = IDLE;
			temp_status = IDLE;
			temp_status = temp_status<<((link%4)*2);
			smpp_hearbeat_status[link/4]	|= temp_status;
			/*
			if (exterEvent[link][exter_tail[link]] > 0)
			{
				if (TRUE == linkUseFlag[link])
					smpp_state[link] = IDLE;
			}
			*/
			break;
		case IDLE:
			//IDLE state:: external event start.
			switch (exterEvent[link][exter_tail[link]]) {
			case Setup:
				switch (smpp_param[link].server_type) {
				case SMPP_SERVER:
					switch (smpp_param[link].session_type) {
					case BIND_RX:
						smpp_state[link] = WAITING;
						smpp_PrimitiveSend(link, Outbind);
						session_init_flag[link]	= TRUE;
						//flag = 2;
						//smpp_state[link] = WAITING;//ch:if smpp_PrimitiveSend failed,that would be error
						temp_status = WAITING;//ch:if smpp_PrimitiveSend failed,that would be error
						temp_status = temp_status<<((link%4)*2);
						smpp_hearbeat_status[link/4]	|= temp_status;
						break;
					/*
					case BIND_TRX:
						smpp_PrimitiveSend(link, BindTransceiver);
						session_init_flag[link]	= TRUE;
						flag = 1;
						smpp_state[link] = WAITING;
						temp_status = WAITING;
						temp_status = temp_status<<((link%4)*2);
						smpp_hearbeat_status[link/4]	|= temp_status;
						break;
					*/
					default:
						break;
					}
					break;
				case SMPP_CLIENT:
					switch (smpp_param[link].session_type) {
					case BIND_TX:
						smpp_state[link] = WAITING;
						smpp_PrimitiveSend(link, BindTransmitter);
						session_init_flag[link]	= TRUE;
						//flag = 1;
						//smpp_state[link] = WAITING;
						temp_status = WAITING;
						temp_status = temp_status<<((link%4)*2);
						smpp_hearbeat_status[link/4]	|= temp_status;
						break;
					/*
					case BIND_RX:
						smpp_PrimitiveSend(link, BindReceiver);
						session_init_flag[link]	= TRUE;
						flag = 0;
						smpp_state[link] = WAITING;
						temp_status = WAITING;
						temp_status = temp_status<<((link%4)*2);
						smpp_hearbeat_status[link/4]	|= temp_status;
						break;
					*/
					case BIND_TRX:
						smpp_state[link] = WAITING;
						smpp_PrimitiveSend(link, BindTransceiver);
						session_init_flag[link]	= TRUE;
						//flag = 1;
						//smpp_state[link] = WAITING;
						temp_status = WAITING;
						temp_status = temp_status<<((link%4)*2);
						smpp_hearbeat_status[link/4]	|= temp_status;
						break;
					default:
						break;
					}
					break;
				default:
					break;
				}
				break;
			default:
				break;
			}
			exterEvent[link][exter_tail[link]]	= 0;
			exter_tail[link]	= (exter_tail[link]+1)&0x7;
			//IDLE state:: external event end.
			//IDLE state:: internal event start.
			switch (interEvent[link][inter_tail[link]]) {
			case Outbind:
				smpp_state[link] = WAITING;
				smpp_PrimitiveSend(link, BindReceiver);
				session_init_flag[link]	= TRUE;
				//flag = 0;
				//smpp_state[link] = WAITING;
				temp_status = WAITING;
				temp_status = temp_status<<((link%4)*2);
				smpp_hearbeat_status[link/4]	|= temp_status;
				break;
			case BindTransmitter:
				smpp_state[link] = ESTABLISHED;
				smpp_PrimitiveSend(link, BindTransmitterResp);
				enquire_link_flag[link]	= TRUE;
				//smpp_state[link] = ESTABLISHED;
				temp_status = ESTABLISHED;
				temp_status = temp_status<<((link%4)*2);
				smpp_hearbeat_status[link/4]	|= temp_status;
				platform_heartbeat_len = (MAX_SMPP_LINK%4)?(MAX_SMPP_LINK/4+1):(MAX_SMPP_LINK/4);
				set_status(SMPP_HEARTBEAT_COMPONENT_ID, platform_heartbeat_len, smpp_hearbeat_status);
				if(callBackFunc[link].link_proc!= NULL)				
					callBackFunc[link].link_proc(link,TRUE);
				interEvent[link][inter_tail[link]]	= 0;
				inter_tail[link]	= (inter_tail[link]+1)&0x7;
				return;

				break;
			case BindTransceiver:
				smpp_state[link]	= ESTABLISHED;
				smpp_PrimitiveSend(link, BindTransceiverResp);
				enquire_link_flag[link]	= TRUE;
				//smpp_state[link]	= ESTABLISHED;
				temp_status = ESTABLISHED;
				temp_status = temp_status<<((link%4)*2);
				smpp_hearbeat_status[link/4]	|= temp_status;
				platform_heartbeat_len = (MAX_SMPP_LINK%4)?(MAX_SMPP_LINK/4+1):(MAX_SMPP_LINK/4);
				set_status(SMPP_HEARTBEAT_COMPONENT_ID, platform_heartbeat_len, smpp_hearbeat_status);
				if(callBackFunc[link].link_proc!= NULL)				
					callBackFunc[link].link_proc(link,TRUE);
				interEvent[link][inter_tail[link]]	= 0;
				inter_tail[link]	= (inter_tail[link]+1)&0x7;
				return;

				break;//fixed 2008-1-11
			case BindReceiver:
				smpp_state[link] = ESTABLISHED;
				smpp_PrimitiveSend(link, BindReceiverResp);
				session_init_flag[link]	= FALSE;
				enquire_link_flag[link]	= TRUE;				
				temp_status = ESTABLISHED;
				temp_status = temp_status<<((link%4)*2);
				smpp_hearbeat_status[link/4]	|= temp_status;
				platform_heartbeat_len = (MAX_SMPP_LINK%4)?(MAX_SMPP_LINK/4+1):(MAX_SMPP_LINK/4);
				set_status(SMPP_HEARTBEAT_COMPONENT_ID, platform_heartbeat_len, smpp_hearbeat_status);
				if(callBackFunc[link].link_proc!= NULL)				
					callBackFunc[link].link_proc(link,TRUE);
				interEvent[link][inter_tail[link]]	= 0;
				inter_tail[link]	= (inter_tail[link]+1)&0x7;
				return;

				break;		
			default:
				break;
			}
			interEvent[link][inter_tail[link]]	= 0;
			inter_tail[link]	= (inter_tail[link]+1)&0x7;
			//IDLE state:: internal event end.
			break;
		case WAITING:
			switch (exterEvent[link][exter_tail[link]]) {
			case Close:
				smpp_state[link] = IDLE;
				temp_status = IDLE;
				dst_ref[link] = 0;
				temp_status = temp_status<<((link%4)*2);
				smpp_hearbeat_status[link/4]	|= temp_status;
				break;
			default:
				break;
			}
			exterEvent[link][exter_tail[link]]	= 0;
			exter_tail[link]	= (exter_tail[link]+1)&0x7;
			//WAITING state:: external event end.
			//WAITING state:: Internal event start.
			switch (interEvent[link][inter_tail[link]]) 
			{
			case SessionInitTimeout:
				session_init_flag[link]	= FALSE;
				smpp_state[link] = IDLE;
				temp_status = IDLE;
				dst_ref[link] = 0;
				temp_status = temp_status<<((link%4)*2);
				smpp_hearbeat_status[link/4]	|= temp_status;
				break;
			case BindReceiverResp:
				//if (0 == flag) {
				session_init_flag[link]	= FALSE;
				enquire_link_flag[link]	= TRUE;
				smpp_state[link] = ESTABLISHED;
				temp_status = ESTABLISHED;
				temp_status = temp_status<<((link%4)*2);
				smpp_hearbeat_status[link/4]	|= temp_status;
				platform_heartbeat_len = (MAX_SMPP_LINK%4)?(MAX_SMPP_LINK/4+1):(MAX_SMPP_LINK/4);
				set_status(SMPP_HEARTBEAT_COMPONENT_ID, platform_heartbeat_len, smpp_hearbeat_status);
				if(callBackFunc[link].link_proc!= NULL)				
					callBackFunc[link].link_proc(link,TRUE);
				interEvent[link][inter_tail[link]]	= 0;
				inter_tail[link]	= (inter_tail[link]+1)&0x7;
				return;

				/*	
				}
				else
					smpp_state[link] = WAITING;
				*/
				break;
			case BindTransmitterResp:
			case BindTransceiverResp:
				//if (1 == flag) {
				session_init_flag[link]	= FALSE;
				enquire_link_flag[link]	= TRUE;
				smpp_state[link] = ESTABLISHED;
				temp_status = ESTABLISHED;
				temp_status = temp_status<<((link%4)*2);
				smpp_hearbeat_status[link/4]	|= temp_status;
				platform_heartbeat_len = (MAX_SMPP_LINK%4)?(MAX_SMPP_LINK/4+1):(MAX_SMPP_LINK/4);
				set_status(SMPP_HEARTBEAT_COMPONENT_ID, platform_heartbeat_len, smpp_hearbeat_status);
				if(callBackFunc[link].link_proc!= NULL)				
					callBackFunc[link].link_proc(link,TRUE);
				interEvent[link][inter_tail[link]]	= 0;
				inter_tail[link]	= (inter_tail[link]+1)&0x7;
				return;

				/*	
				} 
				else
					smpp_state[link] = WAITING;
				*/	
				break;
			case BindReceiver:
				//if (2 == flag) {
				smpp_PrimitiveSend(link, BindReceiverResp);
				session_init_flag[link]	= FALSE;
				enquire_link_flag[link]	= TRUE;
				smpp_state[link] = ESTABLISHED;
				temp_status = ESTABLISHED;
				temp_status = temp_status<<((link%4)*2);
				smpp_hearbeat_status[link/4]	|= temp_status;
				platform_heartbeat_len = (MAX_SMPP_LINK%4)?(MAX_SMPP_LINK/4+1):(MAX_SMPP_LINK/4);
				set_status(SMPP_HEARTBEAT_COMPONENT_ID, platform_heartbeat_len, smpp_hearbeat_status);
				if(callBackFunc[link].link_proc!= NULL)				
					callBackFunc[link].link_proc(link,TRUE);
				interEvent[link][inter_tail[link]]	= 0;
				inter_tail[link]	= (inter_tail[link]+1)&0x7;
				return;
				/*
				} 
				else
					smpp_state[link] = WAITING;
				*/	
				break;
			default:
				break;
			}
			interEvent[link][inter_tail[link]]	= 0;
			inter_tail[link]	= (inter_tail[link]+1)&0x7;
			//WAITING state:: internal event end.
			break;
		case ESTABLISHED:
			switch (exterEvent[link][exter_tail[link]])
			{
			case Close:
				smpp_state[link] = SUSPEND;
				smpp_PrimitiveSend(link, Unbind);
				//smpp_state[link] = SUSPEND;
				temp_status = IDLE;
				temp_status = temp_status<<((link%4)*2);
				smpp_hearbeat_status[link/4]	|= temp_status;
				break;
			default:
				break;
			}
			exterEvent[link][exter_tail[link]]	= 0;
			exter_tail[link]	= (exter_tail[link]+1)&0x7;
			//ESTABLISHED state:: external event end.
			//ESTABLISHED state:: internal event start.
			switch (interEvent[link][inter_tail[link]])
			{
			//normal messages
			case Unbind:
				smpp_PrimitiveSend(link, UnbindResp);
				dst_ref[link] = 0;
				smpp_closeTCPConnection(link);
				enquire_link_flag[link]	= FALSE;
				inactivity_flag[link]	= FALSE;
				inactivity_timer[link] = 0;
				smpp_state[link] = IDLE;
				temp_status = IDLE;
				temp_status = temp_status<<((link%4)*2);
				smpp_hearbeat_status[link/4]	|= temp_status;
				platform_heartbeat_len = (MAX_SMPP_LINK%4)?(MAX_SMPP_LINK/4+1):(MAX_SMPP_LINK/4);
				set_status(SMPP_HEARTBEAT_COMPONENT_ID, platform_heartbeat_len, smpp_hearbeat_status);
				if(callBackFunc[link].link_proc!= NULL)				
					callBackFunc[link].link_proc(link,FALSE);
				return;
				break;
			case SubmitSM:
			case SubmitSMResp:
			case SubmitMulti:
			case SubmitMultiResp:
			case DeliverSM:
			case DeliverSMResp:
			case DataSM:
			case DataSMResp:
			case QuerySM:
			case QuerySMResp:
			case CancelSM:
			case CancelSMResp:
			case ReplaceSM:
			case ReplaceSMResp:
				enquire_link_timer[link]	= 0;
				inactivity_flag[link]	= FALSE;
				inactivity_timer[link]	= 0;
				smpp_state[link] = ESTABLISHED;
				temp_status = ESTABLISHED;
				temp_status = temp_status<<((link%4)*2);
				smpp_hearbeat_status[link/4]	|= temp_status;
				break;
			case EnquireLinkTimeout:
				smpp_state[link] = ESTABLISHED;
				smpp_PrimitiveSend(link, EnquireLink);
				inactivity_flag[link]	= TRUE;
				//smpp_state[link] = ESTABLISHED;
				temp_status = ESTABLISHED;
				temp_status = temp_status<<((link%4)*2);
				smpp_hearbeat_status[link/4]	|= temp_status;
				break;
			case EnquireLink:
				smpp_state[link] = ESTABLISHED;
				smpp_PrimitiveSend(link, EnquireLinkResp);
				enquire_link_timer[link]	= 0;
				//smpp_state[link] = ESTABLISHED;
				temp_status = ESTABLISHED;
				temp_status = temp_status<<((link%4)*2);
				smpp_hearbeat_status[link/4]	|= temp_status;
				break;
			case EnquireLinkResp:
				enquire_link_timer[link]	= 0;
				inactivity_flag[link]	= FALSE;
				inactivity_timer[link]	= 0;
				smpp_state[link] = ESTABLISHED;
				temp_status = ESTABLISHED;
				temp_status = temp_status<<((link%4)*2);
				smpp_hearbeat_status[link/4]	|= temp_status;
				break;
			case InactivityTimeout:
				//smpp_PrimitiveSend(link, Unbind);
				//smpp_state[link] = SUSPEND;
				dst_ref[link] = 0;
				if (smpp_param[link].link_type == SMPP_TCP)
				{
					smpp_closeTCPConnection(link);
				}
				enquire_link_flag[link]	= FALSE;
				inactivity_flag[link]	= FALSE;
				inactivity_timer[link]  = 0;
				smpp_state[link] = IDLE;
				temp_status = IDLE;
				temp_status = temp_status<<((link%4)*2);
				smpp_hearbeat_status[link/4]	|= temp_status;
				platform_heartbeat_len = (MAX_SMPP_LINK%4)?(MAX_SMPP_LINK/4+1):(MAX_SMPP_LINK/4);
				set_status(SMPP_HEARTBEAT_COMPONENT_ID, platform_heartbeat_len, smpp_hearbeat_status);
				if(callBackFunc[link].link_proc!= NULL)				
					callBackFunc[link].link_proc(link,FALSE);
				return;
				break;
			/* error handing messages */
			case BindTransmitter:
				smpp_state[link] = ESTABLISHED;
//				smpp_sendBindResp(link, BindTransmitterResp, ESME_RALYBND);
				smpp_sendBindResp(link, BindTransmitterResp, 0);
				enquire_link_timer[link]	= 0;
				inactivity_flag[link]	= FALSE;
				inactivity_timer[link]	= 0;				
				//smpp_state[link] = ESTABLISHED;
				temp_status = ESTABLISHED;
				temp_status = temp_status<<((link%4)*2);
				smpp_hearbeat_status[link/4]	|= temp_status;
				break;
			case BindReceiver:
				smpp_state[link]	= ESTABLISHED;
//				smpp_sendBindResp(link, BindReceiverResp,	 ESME_RALYBND);
				smpp_sendBindResp(link, BindReceiverResp,	 0);				
				enquire_link_timer[link]	= 0;
				inactivity_flag[link]	= FALSE;
				inactivity_timer[link]	= 0;				
				//smpp_state[link]	= ESTABLISHED;
				temp_status = ESTABLISHED;
				temp_status = temp_status<<((link%4)*2);
				smpp_hearbeat_status[link/4]	|= temp_status;
				break;
			case BindTransceiver:
				smpp_state[link]	= ESTABLISHED;
//				smpp_sendBindResp(link, BindTransceiverResp, ESME_RALYBND);
				smpp_sendBindResp(link, BindTransceiverResp, 0);				
				enquire_link_timer[link]	= 0;
				inactivity_flag[link]	= FALSE;
				inactivity_timer[link]	= 0;				
				//smpp_state[link]	= ESTABLISHED;
				temp_status = ESTABLISHED;
				temp_status = temp_status<<((link%4)*2);
				smpp_hearbeat_status[link/4]	|= temp_status;
				break;
			default:
				smpp_state[link]	= ESTABLISHED;
				temp_status = ESTABLISHED;
				temp_status = temp_status<<((link%4)*2);
				smpp_hearbeat_status[link/4]	|= temp_status;
				break;
			}
			interEvent[link][inter_tail[link]]	= 0;
			inter_tail[link]	= (inter_tail[link]+1)&0x7;
			//ESTABLISHED state:: internal event end.
			break;
		case SUSPEND:
			//SUSPEND state:: internal event start.
			suspend_timer ++;
			switch (interEvent[link][inter_tail[link]])
			{
			case UnbindResp:
				suspend_timer = 0;
				dst_ref[link] = 0;
				smpp_closeTCPConnection(link);
				enquire_link_flag[link]	= FALSE;
				inactivity_flag[link]	= FALSE;
				inactivity_timer[link]  = 0;
				smpp_state[link] = IDLE;
				temp_status = IDLE;
				temp_status = temp_status<<((link%4)*2);
				smpp_hearbeat_status[link/4]	|= temp_status;
				platform_heartbeat_len = (MAX_SMPP_LINK%4)?(MAX_SMPP_LINK/4+1):(MAX_SMPP_LINK/4);
				set_status(SMPP_HEARTBEAT_COMPONENT_ID, platform_heartbeat_len, smpp_hearbeat_status);
				if(callBackFunc[link].link_proc!= NULL)				
					callBackFunc[link].link_proc(link,FALSE);
				return;
				break;
/*			case InactivityTimeout://ch
				if(callBackFunc[link].link_proc!= NULL)
				callBackFunc[link].link_proc(link,FALSE);
				dst_ref[link] = 0;
				if (smpp_param[link].link_type == SMPP_TCP)
					smpp_closeTCPConnection(link);
				enquire_link_flag[link] = FALSE;
				inactivity_flag[link]   = FALSE;
				inactivity_timer[link]  = 0;
				smpp_state[link] = IDLE;
				temp_status = IDLE;
				temp_status = temp_status<<((link%4)*2);
				smpp_hearbeat_status[link/4]    |= temp_status;
				break;				
			case SessionInitTimeout://ch
				if(callBackFunc[link].link_proc!= NULL)
				callBackFunc[link].link_proc(link,FALSE);
				dst_ref[link] = 0;
				if (smpp_param[link].link_type == SMPP_TCP)
					smpp_closeTCPConnection(link);
				enquire_link_flag[link] = FALSE;
				inactivity_flag[link]   = FALSE;
				inactivity_timer[link]  = 0;
				smpp_state[link] = IDLE;
				temp_status = IDLE;
				temp_status = temp_status<<((link%4)*2);
				smpp_hearbeat_status[link/4]    |= temp_status;
				break;			*/	
			default:
				break;
			}
			interEvent[link][inter_tail[link]]	= 0;
			inter_tail[link]	= (inter_tail[link]+1)&0x7;
			if( suspend_timer++ > smpp_param[link].inactivity_timer)
			{
				suspend_timer = 0;
				dst_ref[link] = 0;
				if (smpp_param[link].link_type == SMPP_TCP)
					smpp_closeTCPConnection(link);
				enquire_link_flag[link] = FALSE;
				inactivity_flag[link]   = FALSE;
				inactivity_timer[link]  = 0;
				smpp_state[link] = IDLE;
				temp_status = IDLE;
				temp_status = temp_status<<((link%4)*2);
				smpp_hearbeat_status[link/4]    |= temp_status;
				platform_heartbeat_len = (MAX_SMPP_LINK%4)?(MAX_SMPP_LINK/4+1):(MAX_SMPP_LINK/4);
				set_status(SMPP_HEARTBEAT_COMPONENT_ID, platform_heartbeat_len, smpp_hearbeat_status);
				if(callBackFunc[link].link_proc!= NULL)
					callBackFunc[link].link_proc(link,FALSE);
				return;
			}
			//SUSPEND state:: internal event end.
			break;
		default:
			break;
		} //end switch(state)
	} //end for(froc...

	//platform heartbeat
	platform_heartbeat_len = (MAX_SMPP_LINK%4)?(MAX_SMPP_LINK/4+1):(MAX_SMPP_LINK/4);
	set_status(SMPP_HEARTBEAT_COMPONENT_ID, platform_heartbeat_len, smpp_hearbeat_status);
}

void init_link(u32 link)
{	
	BYTE	temp_status;
	dst_ref[link] = 0;
	smpp_closeTCPConnection(link);
	enquire_link_flag[link]	= FALSE;
	inactivity_flag[link]	= FALSE;
	inactivity_timer[link]  = 0;
	smpp_state[link] = IDLE;
	temp_status = IDLE;
	temp_status = temp_status<<((link%4)*2);
	smpp_hearbeat_status[link/4]	|= temp_status;
	if(callBackFunc[link].link_proc!= NULL)
		callBackFunc[link].link_proc(link,FALSE);
	return;	
}

