/****************************************************/
/*	MTP3LITE Implementation Program				*/
/*	Version 10.0.1									*/
/*	Designed By Ying Min							*/
/*	Last Update: 2005-04-7							*/
/*	Modify : Victor Luo, 2005-07-14		add TCP client for mtp3lite*/
/****************************************************/

#include "./include/mtp3.h"
#include "./include/mtpstm.h"
#include "./include/mtp3lite.h"
#include "./include/mtpext.h"
#include "./include/mtpfunc.h"

BYTE 			mtp3lite_ka_msg[3];
mtp3lite_lk 	mtp3lite_link[256];
int				mtp3lite_listen_fd;
BYTE			mtp3lite_msg_buf[256][MTP3LITE_MSG_BUF_SIZE_PER_LINK];
BYTE			mtp3lite_rem_len[256];
BYTE			mtp3lite_id_fg[256];

/*@ignore@*/
void mtp3lite_print_msg(BYTE *ptr, WORD len)
{
	int	i;

	for (i = 0; i < len; i++)
	{
		printf("%X ", ptr[i]);
	}
	printf("\n");
}

void mtp3lite_init_lk(BYTE lk)
{
	mtp3lite_link[lk].connfd = -1;
	mtp3lite_link[lk].cliSockfd = -1;
	mtp3lite_link[lk].remote_port = 0;
	mtp3lite_link[lk].local_inactive = 2000; 	// 20 seconds
	mtp3lite_link[lk].local_reconnect = 10; 	// 10 * 2.56 seconds
	mtp3lite_link[lk].remote_inactive = mtp3_para->lk[lk].inactive * 100;
	mtp3lite_link[lk].remote_inactive_timeouts = mtp3_para->lk[lk].inactive_tm;
	mtp3lite_link[lk].init_guard_timer = 2000;	// 20 seconds
	mtp3lite_msg_buf[lk][0] = 0;
	mtp3lite_rem_len[lk] = 0;
	mtp3lite_id_fg[lk] = 0;
}

void mtp3lite_init_ka_msg(void)
{
	mtp3lite_ka_msg[0] = 2;
	mtp3lite_ka_msg[1] = 0x4B;
	mtp3lite_ka_msg[2] = 0x41;
}

int mtp3lite_Init_TCPSocket(struct sockaddr_in saddr,int needBind)
{ //flag,0=client, 1=server
  	int		sock;
  	long 	sockbuf = 40*1024;
  	int 	on = 1, timeout = 20;

    sock = socket(AF_INET, SOCK_STREAM, 0);

  	if (sock < 0)
  	{
    	fprintf(stderr,"Socket() failed\n");
    	return -3;
  	}

  	if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
        &sockbuf, sizeof(sockbuf)) != 0)
    {
     	fprintf(stderr,"set socket buffer failed\n");
     	return -4;
  	}

  	if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
         &on,sizeof(on)) != 0)
    {
    	fprintf(stderr,"set addr reusable failed\n");
     	return -5;
  	}

    if (setsockopt(sock,SOL_SOCKET, SO_KEEPALIVE,
         &timeout, sizeof(timeout)) != 0)
    {
       fprintf(stderr,"set keepalive failed\n");
       return -6;
    }

  	if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0)
  	{
    	fprintf(stderr,"set nonblock failed\n");
     	return -7;
  	}

 	if(needBind)
 	{
  		if (bind(sock, (struct sockaddr*)&saddr, sizeof(struct sockaddr)) < 0)
  		{
    		fprintf(stderr,"MTP3LITE bind failed,port:%d\n",htons(saddr.sin_port));
       		close(sock);
       		return -2;
  		}
  	}
  	return sock;
}

int mtp3lite_InitServerSocket()
{
  	struct 	sockaddr_in sin_addr;

   	memset(&sin_addr, 0, sizeof(struct sockaddr));
    sin_addr.sin_family = AF_INET;
    //sin_addr.sin_port = htons(mtp3lite_port);
    sin_addr.sin_port = mtp3_para->mtp3lite_port;
    sin_addr.sin_addr.s_addr = INADDR_ANY;
    bzero(&(sin_addr.sin_zero),8);

    if ((mtp3lite_listen_fd = mtp3lite_Init_TCPSocket(sin_addr,1)) < 0)
    {
   		printf("MTP3LITE TCP Socket(%X) Init Failed!\n", mtp3_para->mtp3lite_port);
		exit(1);
	}
	else
    	listen(mtp3lite_listen_fd, 1);

  	printf("mtp3lite_listen_fd: %d\n", mtp3lite_listen_fd);

  	return 1;
}

int isMtp3LiteClientLink(BYTE lk)
{
	//4bits:none sigtran, link enable, mtp3lite enable,client
	if ((mtp3_para->lk[lk].e1_lk_type & 0x1f)==0x15 && mtp3_para->lk[lk].remote_ip>0)
	{
		return 1;
	}
	return 0;
}

int checkIfOveridesocket(BYTE lk)
{
	int i;
	for(i=0;i<lk;i++)
	{
		if(isMtp3LiteClientLink(i) && mtp3_para->lk[lk].remote_ip==mtp3_para->lk[i].remote_ip)
		{
			printf("mtp3lite client, lk %d is overide with %d \n",lk,i);
			return 1;
		}
	}
	return 0;
}


int mtp3lite_InitClientSocket(BYTE lk)
{
  	struct 	sockaddr_in sin_addr;
 	int 	socketfd;

   	bzero(&sin_addr,sizeof(struct sockaddr));
    sin_addr.sin_family = AF_INET;
    //sin_addr.sin_port = htons(mtp3lite_port);

	mtp3lite_link[lk].cliSockfd = -1;
	if (isMtp3LiteClientLink(lk) && !checkIfOveridesocket(lk))
	{
    	//sin_addr.sin_port = mtp3_para->mtp3lite_port; //server port,tmp
    	//sin_addr.sin_addr.s_addr = mtp3_para->lk[lk].remote_ip;
    	//bzero(&(sin_addr.sin_zero),8);
    	if ((socketfd = mtp3lite_Init_TCPSocket(sin_addr,0)) < 0)
    	{
   			printf("MTP3LITE TCP Client Socket(%d) Init Failed!\n",mtp3_para->mtp3lite_port);
			//exit(1);
			return 0;
		}
		mtp3lite_link[lk].cliSockfd = socketfd;
		printf("mtp3lite: init client socket link=%d\n",lk);
	}

  	return 1;
}

int mtp3lite_CloseTcpConn(BYTE link)
{
	 if(mtp3lite_link[link].connfd>=0)
	 	close(mtp3lite_link[link].connfd);
	 if(mtp3lite_link[link].cliSockfd>=0)
	 	close(mtp3lite_link[link].cliSockfd);
	 mtp3lite_init_lk(link);

	 return 1;
}

int mtp3lite_get_lk_by_ip(struct sockaddr_in *client_addr)
{
	int 	lk;

	for (lk = 0; lk < 256; lk++)
	{
		if ((mtp3_para->lk[lk].remote_ip == client_addr->sin_addr.s_addr) &&
			(mtp3_para->lk[lk].e1_to_mtp3 == mtp3_localip) &&
			((mtp3_para->lk[lk].e1_lk_type & 0x1f) == 0x05) &&	// Server & MTP3LITE & Enabled
			(mtp3ObjState.lk_command[lk]!=0))					//Command enabled
		{
			if (mtp3lite_link[lk].connfd > 0)
			{
				mtp3lite_CloseTcpConn(lk);
    			mtp3lite_updateStatus(lk, MTP2_STATE_STOP, MTP3LITE_INACTIVITY_TIMEOUT);
			}
			else if (mtp3lite_link[lk].init_guard_timer == 0)
				return lk;
			return -1;
		}
	}

	return -1;
}

int mtp3lite_DirectSendMsg(BYTE link, int len, BYTE *msg_ptr)
{
	struct sockaddr_in  sin;

	if ((MTP3_LINK_TYPE(link) != LKTYPE_MTP3_LITE) 	|| 		// Not MTP3LITE
		!(mtp3_para->lk[link].e1_lk_type & 0x01) 	||		// Not Enabled
		(mtp3ObjState.lk_command[link] == 0)		||		// Command Disabled
		(mtp3lite_link[link].connfd <= 0))					// Link Not Established
		return -1;

    bzero(&sin.sin_zero, sizeof(sin.sin_zero));
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = mtp3_para->lk[link].remote_ip;
    sin.sin_port = mtp3lite_link[link].remote_port;

	return send(mtp3lite_link[link].connfd, msg_ptr, len, MSG_NOSIGNAL);
}

int mtp3liteTcpConnect(int sock,struct sockaddr_in *sin_addr)
{
	if (connect(sock, (struct sockaddr *)sin_addr, sizeof(struct sockaddr)) < 0)
	{
		return 0;
	}
	else
	{
		printf("tcpConnect success, ip=%s\n",inet_ntoa(sin_addr->sin_addr));
		return 1;
	}
}

int mtp3lite_TcpConnectCheck()
{
   	int					timeout = 20;
	int					connfdtmp = 0;
   	socklen_t           clilen;
	struct  sockaddr_in cliaddr;
	int					link;
	static BYTE	 		cliLk=0;

    bzero(&cliaddr,(clilen = sizeof(struct sockaddr)));

    connfdtmp = accept(mtp3lite_listen_fd,(struct sockaddr *)&cliaddr,&clilen);
	if (connfdtmp <= 0)//no connect request , check client socke
	{
		link = cliLk++;
		if (!isMtp3LiteClientLink(link))
			return 0;
		if (mtp3lite_link[link].connfd > 0)
			return 0;
		else if (mtp3lite_link[link].local_reconnect > 0)
		{
			mtp3lite_link[link].local_reconnect--;
			return 0;
		}

		if (mtp3lite_link[link].cliSockfd <= 0)
		{
			if (!mtp3lite_InitClientSocket(link))
				mtp3lite_init_lk(link);
		}
		cliaddr.sin_family = AF_INET;
		cliaddr.sin_port = mtp3_para->mtp3lite_port;
		cliaddr.sin_addr.s_addr = mtp3_para->lk[link].remote_ip;
		bzero(&(cliaddr.sin_zero),8);
		connfdtmp = mtp3lite_link[link].cliSockfd;
		if (!mtp3liteTcpConnect(connfdtmp, &cliaddr))
		{
			if ((errno != EINPROGRESS) && (errno != EALREADY))
				mtp3lite_CloseTcpConn(link);
			return 0;
		}
	}
	else if ((link = mtp3lite_get_lk_by_ip(&cliaddr)) < 0)
	{
		close(connfdtmp);
		return 0;
	}

	mtp3lite_init_lk(link);
	mtp3lite_link[link].init_guard_timer = 0;
	mtp3lite_link[link].connfd = connfdtmp;
	mtp3lite_link[link].cliSockfd = connfdtmp;
  	mtp3lite_link[link].remote_port = cliaddr.sin_port;
  	printf("link[%d] connfd: %d, rem_port: %d\n", link, connfdtmp, ntohs(mtp3lite_link[link].remote_port));

    fcntl(mtp3lite_link[link].connfd,F_SETFL,O_NONBLOCK);
    if (setsockopt(mtp3lite_link[link].connfd,SOL_SOCKET,SO_KEEPALIVE,
        &timeout,sizeof(timeout)) != 0)
   	fprintf(stderr,"set keepalive failed\n");
    if (setsockopt(mtp3lite_link[link].connfd,SOL_SOCKET,SO_KEEPALIVE,
        &timeout,sizeof(timeout)) !=0)
  	fprintf(stderr,"set keepalive failed\n");

    mtp3lite_updateStatus(link, MTP2_STATE_WORKING, 0);
//    mtp3lite_DirectSendMsg(link, 3, mtp3lite_ka_msg);

	return 1;
}

int mtp3lite_DirectRecvMsg(BYTE link)
{
	struct sockaddr_in  sin;
	int  				len, nbytes;
	BYTE				len1;

    len = sizeof(struct sockaddr);
    if ((len1 = mtp3lite_rem_len[link])>0)
    	printf("len1: %d\n", len1);
	nbytes = recvfrom(mtp3lite_link[link].connfd, mtp3lite_msg_buf[link] + len1,
      					MTP3LITE_MSG_BUF_SIZE_PER_LINK - len1, 0, (struct sockaddr *) &sin, &len);

    if (nbytes == 0)
    {
		printf("tcp link[%d] error : %d\n", link, errno);
    	mtp3lite_CloseTcpConn(link);
    	mtp3lite_updateStatus(link, MTP2_STATE_STOP, MTP3LITE_TCP_FAILURE);
    	mtp3lite_rem_len[link] = 0;
    }

    if ((len1 > 0) && (nbytes > 0))
    	nbytes += len1;

    return nbytes;
}
/*
int mtp3lite_decode_tcp_msg(WORD total_len, BYTE link)
{
	BYTE		lk_set, *buf_ptr;
	WORD		sub_len, rem_len, total_hdl_len = 0;
	up_message 	up_msg;
	up_message 	*up_msg_ptr = &up_msg;
	BYTE		nw;

	if (total_len > MTP3LITE_MSG_BUF_SIZE_PER_LINK)
		return -1;

	while (total_hdl_len < total_len)
	{
		buf_ptr = mtp3lite_msg_buf[link] + total_hdl_len;
		rem_len = total_len - total_hdl_len;
		sub_len = buf_ptr[0];

		if (rem_len < (sub_len + 1))
		{
			if (total_hdl_len > 0)
				memcpy(mtp3lite_msg_buf[link], mtp3lite_msg_buf[link] + total_hdl_len, rem_len);
			mtp3lite_rem_len[link] = rem_len;
			//printf("Remain: total_len: %d, total_hld_len: %d, sub_len: %d, rem_len: %d\n", total_len, total_hdl_len, sub_len, rem_len);
			return 1;
		}

		if (sub_len < 2)
			return -1;
		else if (sub_len == 2)
	    {
	       	if ((buf_ptr[1] == 0x4B) && (buf_ptr[2] == 0x41))
	       	{	// Receive Keep Alive Message
	       		mtp3lite_link[link].remote_inactive = mtp3_para->lk[link].inactive * 100;
	       		mtp3lite_link[link].remote_inactive_timeouts = 0;
	       		//mtp3lite_print_msg(buf_ptr, 3);
	       		total_hdl_len += (sub_len + 1);
	       		//printf("KeepAlive: total_len: %d, total_hld_len: %d, sub_len: %d, rem_len: %d\n", total_len, total_hdl_len, sub_len, rem_len);
	       		continue;
	       	}
	       	else
	       		return -1;
	    }

    	if ((buf_ptr[1] > 9) || (buf_ptr[1] == 0))
    		return -1;

	    mtp3lite_link[link].remote_inactive = mtp3_para->lk[link].inactive * 100;
	    mtp3lite_link[link].remote_inactive_timeouts = 0;

       	//mtp3lite_print_msg(buf_ptr, sub_len + 1);

	    up_msg_ptr->len = sub_len;
	    up_msg_ptr->link = link;
	    lk_set = mtp3_para->lk[link].e1_to_linkset;
	    if (lk_set >= 128)
	    	return -1;
		nw = mtp3_para->ls_pro[lk_set] & 3;
	    up_msg_ptr->sio = 0x03 | (nw << 6) | 0x10;//sccp lite always ansi message
		up_msg_ptr->opc = mtp3_para->ls_op_pc[lk_set];
		if (pc_length(up_msg_ptr->sio >> 6) == MTP3_24BIT_PC)
			up_msg_ptr->dpc = mtp3_para->nw[nw].opc24;
		else
			up_msg_ptr->dpc = mtp3_para->nw[nw].opc14;

	    memcpy(up_msg_ptr->msgList, buf_ptr + 1, sub_len);

	    iptrans_msg_flow_2(up_msg_ptr);
	    send_to_sccp_lite(up_msg_ptr);

	    total_hdl_len += (sub_len + 1);
	    //printf("Data: total_len: %d, total_hld_len: %d, sub_len: %d, rem_len: %d\n", total_len, total_hdl_len, sub_len, rem_len);
	}

	mtp3lite_rem_len[link] = 0;
	return 1;
}
*/
/******change to struct: 00, len, 0xfd*****/
int mtp3lite_decode_tcp_msg(WORD total_len, BYTE link)
{
	BYTE		lk_set, *buf_ptr;
	WORD		sub_len, rem_len, total_hdl_len = 0;
	up_message 	up_msg;
	up_message 	*up_msg_ptr = &up_msg;
	BYTE		nw;

	if (total_len > MTP3LITE_MSG_BUF_SIZE_PER_LINK)
		return -1;

	while (total_hdl_len < total_len)
	{
		buf_ptr = mtp3lite_msg_buf[link] + total_hdl_len;
		rem_len = total_len - total_hdl_len;
		sub_len = (buf_ptr[0]<<8) + buf_ptr[1];

		if (rem_len < (sub_len + 1))
		{
			if (total_hdl_len > 0)
				memcpy(mtp3lite_msg_buf[link], mtp3lite_msg_buf[link] + total_hdl_len, rem_len);
			mtp3lite_rem_len[link] = rem_len;
			//printf("Remain: total_len: %d, total_hld_len: %d, sub_len: %d, rem_len: %d\n", total_len, total_hdl_len, sub_len, rem_len);
			return 1;
		}

		if (sub_len < 1)
			return -1;
		else if (sub_len == 1)
	    {
	       	if(buf_ptr[1+2] == 0x6)
	       	{	// Receive Keep Alive Message
	       		mtp3lite_link[link].remote_inactive = mtp3_para->lk[link].inactive * 100;
	       		mtp3lite_link[link].remote_inactive_timeouts = 0;
	       		//mtp3lite_print_msg(buf_ptr, 3);
	       		total_hdl_len += (sub_len + 3);
						mtp3_debug(MTP3DB_EVENT,"mtp3-lite link %d RECV Inditify ACK",link);
	       		//printf("KeepAlive: total_len: %d, total_hld_len: %d, sub_len: %d, rem_len: %d\n", total_len, total_hdl_len, sub_len, rem_len);
	       		continue;
	       	}
	       	else
	       		return -1;
	    }

 //   	if ((buf_ptr[1+2] > 9) || (buf_ptr[1+2] == 0))
  //  		return -1;

	    mtp3lite_link[link].remote_inactive = mtp3_para->lk[link].inactive * 100;
	    mtp3lite_link[link].remote_inactive_timeouts = 0;

       	//mtp3lite_print_msg(buf_ptr, sub_len + 1);

	    up_msg_ptr->len = sub_len;
	    up_msg_ptr->link = link;
	    lk_set = mtp3_para->lk[link].e1_to_linkset;
	    if (lk_set >= 128)
	    	return -1;
		nw = mtp3_para->ls_pro[lk_set] & 3;
	    up_msg_ptr->sio = 0x03 | (nw << 6);//sccp lite always itu message
		up_msg_ptr->opc = mtp3_para->ls_op_pc[lk_set];
		if (pc_length(up_msg_ptr->sio >> 6) == MTP3_24BIT_PC)
			up_msg_ptr->dpc = mtp3_para->nw[nw].opc24;
		else
			up_msg_ptr->dpc = mtp3_para->nw[nw].opc14;

	    memcpy(up_msg_ptr->msgList, buf_ptr + 1 + 2, sub_len);

	    iptrans_msg_flow_2(up_msg_ptr);
	    send_to_sccp_lite(up_msg_ptr);

	    total_hdl_len += (sub_len + 1 + 2);
	    //printf("Data: total_len: %d, total_hld_len: %d, sub_len: %d, rem_len: %d\n", total_len, total_hdl_len, sub_len, rem_len);
	}

	mtp3lite_rem_len[link] = 0;
	return 1;
}

int send_mtp3lite_id_ack(BYTE link)
{
	BYTE id_ack_msg[4]={0,0x1,0xfe, 0x6};

	mtp3lite_DirectSendMsg(link, 4, id_ack_msg);
	mtp3_debug(MTP3DB_EVENT,"mtp3-lite link %d send Inditify ACK",link);
	return 1;
}

int get_mtp3lite_msg(BYTE link)
{
	int 	nbytes;

	if ((MTP3_LINK_TYPE(link) != LKTYPE_MTP3_LITE) || 		// Not MTP3LITE
		!(mtp3_para->lk[link].e1_lk_type & 0x01) ||			// Not Enabled
		(mtp3ObjState.lk_command[link]==0)		||			// command disabled
		(mtp3lite_link[link].connfd <= 0))					// Link Not Established
	{
		return -1;
	}

	if ((nbytes = mtp3lite_DirectRecvMsg(link)) <= 0)
		return -1;

	//mtp3lite_print_msg(mtp3lite_msg_buf[link], nbytes);

	if (mtp3lite_decode_tcp_msg(nbytes, link) < 0)
	{
		printf("tcp link[%d] decode error!\n", link);
    	mtp3lite_CloseTcpConn(link);
    	mtp3lite_updateStatus(link, MTP2_STATE_STOP, MTP3LITE_TCP_FAILURE);
    	mtp3lite_rem_len[link] = 0;
		return -1;
	}

	return 1;
}

int put_mtp3lite_msg(BYTE *msg_ptr)
{
	BYTE link, ls, nw, pclen, offset;
	WORD len;

	link = msg_ptr[0];
	len = (msg_ptr[1]<<8) + msg_ptr[2];

	if ((MTP3_LINK_TYPE(link) != LKTYPE_MTP3_LITE) || 		// Not MTP3LITE
		!(mtp3_para->lk[link].e1_lk_type & 0x01) ||			// Not Enabled
		(mtp3ObjState.lk_command[link]==0)		||			// Command disabled
		(mtp3lite_link[link].connfd <= 0))					// Link Not Established
		return -1;

	if ((ls = mtp3_para->lk[link].e1_to_linkset) >= 128)
		return -1;

	nw = mtp3_para->ls_pro[ls] & 0x03;
	pclen = (mtp3_para->nw_pro >> nw) & 0x01;

	if (pclen)
	{
		if (len <= 8)
			return -1;
		offset = 9+1;//msg_ptr[offset+1] = sccp data
		msg_ptr[offset-1] = (len - 8)%0xff;
		msg_ptr[offset-2] = (len - 8)/0xff;
		len = len - 7+2;
	}
	else
	{
		if (len <= 5)
			return -1;
		offset = 6+1;
		msg_ptr[offset-1] = (len - 5)%0xff;
		msg_ptr[offset-2] = (len - 5)/0xff;
		len = len - 4+2;
	}
/******change to struct: 00, len, 0xfd*****/
	msg_ptr[offset] = 0xfd;

/******change to struct: 00, len, 0xfd*****/
	mtp3lite_DirectSendMsg(link, len, msg_ptr + offset - 2);
	//mtp3lite_link[link].local_inactive = 2000;

	return 0;
}
/*
int put_mtp3lite_msg(BYTE *msg_ptr)
{
	BYTE link, len, ls, nw, pclen, offset;

	link = msg_ptr[0];
	len = msg_ptr[1];

	if ((MTP3_LINK_TYPE(link) != LKTYPE_MTP3_LITE) || 		// Not MTP3LITE
		!(mtp3_para->lk[link].e1_lk_type & 0x01) ||			// Not Enabled
		(mtp3ObjState.lk_command[link]==0)		||			// Command disabled
		(mtp3lite_link[link].connfd <= 0))					// Link Not Established
		return -1;

	if ((ls = mtp3_para->lk[link].e1_to_linkset) >= 128)
		return -1;

	nw = mtp3_para->ls_pro[ls] & 0x03;
	pclen = (mtp3_para->nw_pro >> nw) & 0x01;

	if (pclen)
	{
		if (len <= 8)
			return -1;
		offset = 9;
		msg_ptr[offset] = len - 8;
		len = len - 7;
	}
	else
	{
		if (len <= 5)
			return -1;
		offset = 6;
		msg_ptr[offset] = len - 5;
		len = len - 4;
	}

	mtp3lite_DirectSendMsg(link, len, msg_ptr + offset);
	//mtp3lite_link[link].local_inactive = 2000;

	return 0;
}
*/
int mtp3lite_chk_lk(BYTE link)
{
//	char str[19]={7,0,0x11,0x83,0x71,0xab,0xdc,0x1a,0x06,0xf6, 0,0,0,1,5,1,3,2,9,4};
	if ((MTP3_LINK_TYPE(link) != LKTYPE_MTP3_LITE) 	|| 		// Not MTP3LITE
		!(mtp3_para->lk[link].e1_lk_type & 0x01) 	||		// Not Enabled
		(mtp3ObjState.lk_command[link] == 0))				// Command disabled
		return 0;

	if (mtp3lite_link[link].init_guard_timer > 0)
		mtp3lite_link[link].init_guard_timer--;

	if (mtp3lite_link[link].connfd <= 0) 					// Link Not Established
		return 0;

	if (mtp3lite_link[link].remote_inactive > 0)
	{
		if (--mtp3lite_link[link].remote_inactive == 0)
		{

//			if (++mtp3lite_link[link].remote_inactive_timeouts >= mtp3_para->lk[link].inactive_tm)
			if(0)
			{
				printf("link[%d] remote inactivity %d seconds timeout %d times!\n", link, mtp3_para->lk[link].inactive, mtp3_para->lk[link].inactive_tm);
				mtp3lite_CloseTcpConn(link);
    			mtp3lite_updateStatus(link, MTP2_STATE_STOP, MTP3LITE_INACTIVITY_TIMEOUT);
			}
			else
			{
				mtp3lite_link[link].remote_inactive = mtp3_para->lk[link].inactive * 100;
			}
		}
	}

	if (mtp3lite_link[link].local_inactive > 0)
	{
		if(mtp3lite_id_fg[link]==0)
		{
			mtp3lite_id_fg[link] = 1;
			send_mtp3lite_id_ack(link);
		}
		if (--mtp3lite_link[link].local_inactive == 0)
		{
//			mtp3lite_DirectSendMsg(link, 3, mtp3lite_ka_msg);
//			put_mtp3lite_msg(&str);
			mtp3lite_link[link].local_inactive = 2000;
		}
	}

	return 1;
}

void deactive_mtp3lite_lk(link)
{
	if ((MTP3_LINK_TYPE(link) == LKTYPE_MTP3_LITE) && 	// MTP3LITE
		(mtp3_para->lk[link].e1_lk_type & 0x01) && 	// Enabled
		(mtp3lite_link[link].connfd > 0))
	{//sccp lite link
		mtp3_debug(MTP3DB_EVENT,"mtp3-lite link %d Deactive by MNG",link);
		mtp3lite_CloseTcpConn(link);
    	mtp3lite_updateStatus(link, MTP2_STATE_STOP, MTP3LITE_INACTIVITY_TIMEOUT);
	}
}

void mtp3lite_init(void)
{
	int	i;

	printf("MTP3LITE Init Start!\n");

	for (i = 0; i < 256; i++)
	{
		mtp3lite_init_lk(i);
		mtp3lite_InitClientSocket(i);
	}

	mtp3lite_listen_fd = -1;

//	mtp3lite_InitServerSocket();

	mtp3lite_init_ka_msg();//keep alive message

	printf("MTP3LITE Init Complete!\n");
}

void mtp3lite_reset(void)
{
	int	link;

	for (link=0;link<256;link++)
	{
		if (mtp3lite_link[link].connfd >=0)
		{
			mtp3lite_CloseTcpConn(link);
			mtp3lite_rem_len[link] = 0;
		}
	}
}

void mtp3lite_timer(void)
{
	int	link;

	mtp3lite_TcpConnectCheck();

	for (link = 0; link < 256; link++)
	{
		get_mtp3lite_msg(link);
		mtp3lite_chk_lk(link);
	}
}
/*@end@*/
