/* 
** PACS-WLL 2000 project, Prepaid System.
** 
** The module Copyright (C) 2000-2001 interWAVE Inc.
** Written completely by Zhang Shuzhong at iCRD January, 2001
**
** file name: iptrans.c
** CVS: $Id: iptrans.c,v 1.9 2001/02/09 08:53:43 zhangsz Exp $
**
** Description: IP transceiver common module of PACS-WLL Project.     
**
*/
#include    <stdarg.h>        /* ANSI C header file */
#include    <syslog.h>
#include    <sys/io.h>
#include    <error.h>

#include    "../../debug/src/include/debug.h"
#include    "./include/iptrans.h"
#include    "./include/dbsync.h"

/*@ignore@*/
#define     PROG_NAME     		"iptrans"
#define     OID_IPTRANS   		1
#define  	IPTR_DEBUG_ID 		0
#define  	BASE_ID_LEN  		15
#define  	MAX_DEBUG_MESSAGES  1
#define  	MAX_TELNET_TIME  	(10*100*3600)
#define  	MAX_MULTICAST_TIME 	(100*60*2000) //TWO MINUTES

#define     TELNET_PORT			15

#define		TYPE_UDP			0
#define		TYPE_TCP			1

#define		ACCESS_BUFFERED		0
#define		ACCESS_DIRECT		1

int			port_convert_flag = 0;

typedef struct _PORT_STATUS
{
	unsigned short 	portno;
	int				sockfd;
	unsigned char	type;   		/*0/1/2/=UDP/TCP/MULITICAST*/
	unsigned char	capability;		/*0-6*/
	unsigned char	buffered;       /*whether buffered or not*/
	int				connfd;
	DWORD			peerip;
	int				peerport;
	int				recvcounter;
	//int			sendcounter;
	unsigned char	convert_flag;
	unsigned short	real_portno;
}PORT_STATUS;

PORT_STATUS 		 port_status[PORT_NUM];
iptrans_status		 iptransInfo;

extern int           debug;            /* defined in errorlog.c */
extern int           under_develop;   /* defined in errorlog.c */            
static int           iptrans_shm_id;
static int           iptrans_sem_id;
static struct termio prev_termio;
static iptrans_shm   *iptrans_shm_ptr;
static DWORD         IPTRANS_OID_PREFIX[]={1,3,6,1,4,1,1373,1,3,2,2,1};
static BYTE          IPTRANS_VERSION[3]={0x08,0x03,0x01};
static int           nowPeriod,lstPeriod=0;
static DWORD        startTime[96];
static int			 sendcounter;
extern int errno;

u_char	 warningFlag = 0x01;


socklen_t           clilen;
struct  sockaddr_in cliaddr;

const   BYTE	IPTR_PAGE_POINT = 14;
const   BYTE    IPTR_LINE_POINT = 15;
static	BYTE	*disp_ptr ;

static u_short parportadd   = 0x37a;
static u_char  iptr_led_bit = 2;
static int	   debug_messages=0;

int SetAsciioutMsg(int flag, const char *fmt, ...);
static char *iptrGetASCTime();
static char *iptrFormatOutput();
/*----------------------------------------------------*/
int	GetRealPortID(unsigned short port)
{
	int		retval = -1;
	int		loop;
	
	for(loop=0;loop<PORT_NUM;loop++)
	{
		if(port_status[loop].convert_flag == 1 
		   &&
		   port_status[loop].real_portno == port)
			return loop;
						
	}
	
	return 	retval;
}

void SetDebugFlag(void)
{
    debug = DEBUG;                    /* DEBUG defined in debug.h */
    under_develop = UNDER_DEVELOP;     /* UNDER_DEVELOP defined in debug.h */
}

/* 
** Handler of terminatation,
** process while received a signal from user.
*/
static void Terminate(int sig)
{
int retval, i;

    usleep(100000);
    retval = (int) shmdt(0);
    if (retval == -1) log_ret("%s: %s: shmdt", PROG_NAME, FUNCTION_MACRO);
    retval = shmctl(iptrans_shm_id, IPC_RMID, NULL);
    if (retval == -1) log_ret("%s: %s: shmctl", PROG_NAME, FUNCTION_MACRO);
    retval = semctl(iptrans_sem_id, PORT_NUM, IPC_RMID, NULL);
    if (retval == -1) log_ret("%s: %s: semctl", PROG_NAME, FUNCTION_MACRO);
    for (i=0; i<PORT_NUM; i++)
        close(port_status[i].sockfd);
    exit(sig);
}

/* Receive message from UDP socket */
void
iptrRecvMessage(iptrans_shm *shm_ptr, int sem_id,int index)
{
int                 port;
struct sockaddr_in  sin;
int                 nbytes, len;    
BYTE                bcd_buf[MAXBUFLEN],flagport;
port_stat           *pstat;
message_list        msgbuf;
DWORD              flag;
char                buf[MAXBUFLEN];
int                 i = 0;
in_buffer           *pbuf;
int                 list_num, ds_flag=NO;
int                 loop,port_id,srcport;
int 				showlen=0;
    
    list_num=IN_LIST_NUM;
    len = sizeof(struct sockaddr);
    
    for(loop=0;loop<PORT_NUM;loop++)
    {
      
	  if(port_status[loop].buffered == ACCESS_DIRECT) 
	  	continue;
	  	
	  flagport = port_status[loop].capability;	  	
	  
      if(flagport == 0){
        continue;
      }
      else if(flagport == 1){
         if(index %32!=0) continue;
      }
      else if(flagport == 2){
         if(index %16 != 0) continue;
      }
      else if(flagport == 3){
         if(index % 8 != 0) continue;
      }
      else if(flagport == 4){
         if(index % 4 != 0) continue;
      }
      else if(flagport == 5){
         if(index % 2 != 0) continue;
      }
      

      pbuf = (in_buffer *) &shm_ptr -> msgPortIn[loop];
      pstat=(port_stat *) &iptransInfo.msgPortStat[loop];
 
      if(port_status[loop].type == TYPE_TCP)
      {
          Receive_TCP(loop,pbuf,pstat);
          continue;
      }            

      nbytes = recvfrom(port_status[loop].sockfd, &bcd_buf, MAX_CONTENT_LEN, 
                   0, (struct sockaddr *) &sin, &len);
        if (nbytes < 0) {
            continue;
        }
        port=loop+PORT_BASE_NUM;
        msgbuf.msgSrcIP = sin.sin_addr.s_addr; 
        msgbuf.msgSrcPort = ntohs(sin.sin_port);
	    srcport = msgbuf.msgSrcPort-PORT_BASE_NUM;
        msgbuf.msgDstPort = port; 
        msgbuf.msgLength = nbytes;
        msgbuf.msgBroadcast = NO;
        memcpy(msgbuf.msgContent,bcd_buf,nbytes);
        
        iptrSemLock(PROG_NAME, iptrans_sem_id, 1, 1, IPC_NOWAIT);
        /* write to buffer and statistics of packets.  */
        if(! iptrWriteMsg(pbuf,&msgbuf,list_num))
	    {
	       iptransInfo.debug_msg.port_status[loop] ++;
	       //SendHeartbeat();
		   continue;
		}
        pstat->portStatus = 1;
        pstat->inPackets ++;
        pstat->inBytes += nbytes;

        iptransInfo.snmp_data.iptrans_cdr[nowPeriod].cdr_record[loop].inPackets ++;
        iptransInfo.snmp_data.iptrans_cdr[nowPeriod].cdr_record[loop].inBytes +=nbytes;
        iptrSemUnlock(PROG_NAME, iptrans_sem_id, 1, 1, IPC_NOWAIT);


#if UNDER_DEVELOP
	if(debug_messages>=MAX_DEBUG_MESSAGES) continue;
    if(iptransInfo.debug_msg.logflag == 0x00)
       continue;
    if(iptransInfo.debug_msg.logflag != 0xffffffff)
    {
      if(iptransInfo.debug_msg.srclog !=0)
      {
        flag = iptransInfo.debug_msg.srclog;
        if((flag>>srcport) !=0x01)
 	  continue;
      }
      if(iptransInfo.debug_msg.dstlog !=0)
      {
         flag = iptransInfo.debug_msg.dstlog;
 	 if((flag>>loop) !=0x01)
	  continue;
      }
    }
    showlen = nbytes;
	if(showlen>256) showlen = 256;
	debug_messages++;
    SetAsciioutMsg(1,
        "Read Subscript: %03d Write Subscript: %03d Port: %d\r\n", 
        pbuf->msgReadSub, pbuf->msgWriteSub, msgbuf.msgSrcPort);
    if (ds_flag == NO) {
         BcdToAscii(buf, msgbuf.msgContent, 2*showlen);
         iptrFormatOutput(buf, 2*showlen, 2, ' ');
    } else {
         memcpy(buf, msgbuf.msgContent, nbytes);
         buf[nbytes] = 0;
    }
    SetAsciioutMsg(0,"Current time: %s\r\n", iptrGetASCTime(NULL));
    SetAsciioutMsg(0,
   	"got packet from %s %d #%d\r\n",    
        (char *)inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), i);
    SetAsciioutMsg(0,
        "packet is %d bytes (chars) long, contains:\r\n%s\r\n", nbytes, buf);
    i++;
#endif 
        
  } /* loop */

}  
/* end of RecvMessage -------------------*/

int Receive_TCP(int port,in_buffer *pbuf,port_stat  *pstat)
{
  	  int                 nbytes,len,i,j;
  	  struct sockaddr_in  sin;  
  	  message_list        msgbuf;  

      len = sizeof(struct sockaddr);
      if(port_status[port].connfd<=0 ) return 0;
      
      nbytes = recvfrom(port_status[port].connfd, 
      					msgbuf.msgContent,
      					MAX_CONTENT_LEN,
      					0,
      					(struct sockaddr *) &sin, 
      					&len); 
      if(nbytes<0){
        return 0;
      }
      if(nbytes==0){
	 	//if(errno==ENOTSOCK || errno==ENOTCONN)
		{
         	CloseTcpConn(port);
		}
        return 0;
      }
//      fprintf(stderr,"connfd[%d]: Recv bytes:%d Client IP:%08x\n",
//				port+BASE_PORT_NUM, nbytes,peerip[port]);
      
      msgbuf.msgSrcIP = sin.sin_addr.s_addr; 
      msgbuf.msgSrcPort = ntohs(sin.sin_port); 

      msgbuf.msgDstPort = port+PORT_BASE_NUM; 
      msgbuf.msgLength = nbytes;
      msgbuf.msgBroadcast = NO;

      iptrWriteMsg(pbuf, &msgbuf, IN_LIST_NUM);
      pstat->portStatus = 1;
      pstat->inPackets ++;
      pstat->inBytes +=nbytes;

		if(strncasecmp(msgbuf.msgContent,"exit",4)==0)
			CloseTcpConn(port);      
		else if(msgbuf.msgContent[0]=='q' ||
				msgbuf.msgContent[0] =='Q')
			CloseTcpConn(port);
    
#if UNDER_DEVELOP1  
      msgbuf.msgContent[nbytes] = 0;
      for(i=0;i<nbytes;i++)
      {
	 if((i+1)%20 ==0) fprintf(stderr,"\n");
	 fprintf(stderr,"%02X ",msgbuf.msgContent[i]);
      }
      fprintf(stderr,"\n");
      memset(&msgbuf,0,sizeof(message_list));
#endif	  

}


/* Send message by UDP sockets */
void
iptrSendMessage(iptrans_shm *shm_ptr, int sem_id)
{
	int ii;
int                 ret=0;
struct sockaddr_in  sin;
int                 len=0,sendlen;    
BYTE                bcd_buf[MAXBUFLEN];
out_buffer          *pbuf;
message_list        msgbuf;
int                 port_id,dstport;
int                 broadcast_message = NO;
int                 loop;
char                multiip[15];
DWORD              flag;
int					showlen=0;

char            buf[MAXBUFLEN];
int             i = 0;

    

    for(loop=0;loop<48;loop++)
    {
        len = 0;
        bzero(&sin.sin_zero, sizeof(sin.sin_zero));
        sin.sin_family = AF_INET;
		if(loop%2==0)
			pbuf = (out_buffer *)&iptrans_shm_ptr->msgPortOut;
		else 
   			pbuf = (out_buffer *)&iptrans_shm_ptr->msgPlatPortOut;
        if(pbuf->msgReadSub == pbuf->msgWriteSub) continue;
        else{
            iptrReadMsg(pbuf, (message_list *) &msgbuf, OUT_LIST_NUM);
            port_id = msgbuf.msgSrcPort - PORT_BASE_NUM;
            if (port_id<0 || port_id>=PORT_NUM) 
			{
				if(port_convert_flag)
				{
					port_id = GetRealPortID(msgbuf.msgSrcPort);
					if(port_id<0)
						continue;
				}
            	continue;
			}

            sin.sin_addr.s_addr = msgbuf.msgDstIP;
            sin.sin_port = htons(msgbuf.msgDstPort);
	        dstport = msgbuf.msgDstPort - PORT_BASE_NUM;
            len = msgbuf.msgLength;
            memcpy(bcd_buf, msgbuf.msgContent, len);

            broadcast_message = msgbuf.msgBroadcast;
            if (broadcast_message) {
                ret = setsockopt(port_status[port_id].sockfd, SOL_SOCKET,
                		 SO_BROADCAST,
                         &broadcast_message, sizeof(broadcast_message));
                if (ret < 0)
                    log_ret("%s: %s: setsockopt", PROG_NAME, FUNCTION_MACRO);
            }
            if(port_status[port_id].type == TYPE_TCP)
            {
                if(port_status[port_id].connfd<=0) continue;
	              ret = send(port_status[port_id].connfd, 
	              				&msgbuf.msgContent, len, MSG_NOSIGNAL);	       
            }
            else
            { 
                 ret = sendto(port_status[port_id].sockfd, &bcd_buf, len, 0, 
                    (struct sockaddr *)&sin, sizeof(sin));
                    
            }  
            if (ret < 0) {
                iptransInfo.msgPortStat[port_id].portStatus = -1;
                iptransInfo.msgPortStat[port_id].errorPackets ++;
            }
            else if (port_id >= 0 && port_id < PORT_NUM) {
                iptransInfo.msgPortStat[port_id].outPackets ++;
                sendlen = iptransInfo.msgPortStat[port_id].outBytes;
                iptransInfo.msgPortStat[port_id].outBytes = sendlen + len;

                iptransInfo.snmp_data.iptrans_cdr[nowPeriod].cdr_record[port_id].outPackets ++;
                iptransInfo.snmp_data.iptrans_cdr[nowPeriod].cdr_record[port_id].outBytes +=len;
            }

#if UNDER_DEVELOP
		 if(debug_messages>=MAX_DEBUG_MESSAGES) continue;
         if(iptransInfo.debug_msg.logflag == 0x00000000)
	   continue;
         if(iptransInfo.debug_msg.logflag != 0xffffffff)
         {
	   if(iptransInfo.debug_msg.srclog !=0)
	   {
	     flag = iptransInfo.debug_msg.srclog;
	     if((flag>>port_id) !=0x01)
	       continue;
	   }
	  if(iptransInfo.debug_msg.dstlog !=0)
	  {
	    flag = iptransInfo.debug_msg.dstlog;
	    if((flag>>dstport) !=0x01)
	      continue;	        
	  }
    }
	showlen = len;
	if(showlen>256) showlen = 256;
	debug_messages++;
    SetAsciioutMsg(1,
	   "Read Subscript: %d Write Subscript: %d Port: %d\r\n", 
        pbuf->msgReadSub, pbuf->msgWriteSub, msgbuf.msgSrcPort);
    if (msgbuf.msgDstPort != DS_PORT_NO) {
        BcdToAscii(buf, bcd_buf, 2*(showlen));
        iptrFormatOutput(buf, 2*showlen, 2, ' ');
     } else 
    	 memcpy(buf, bcd_buf, showlen);
 	 SetAsciioutMsg(0,"Current time: %s\r\n", iptrGetASCTime(NULL));
     SetAsciioutMsg(0,"Sent packet to %s %d #%d\r\n",
            (char *)inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), i);
     SetAsciioutMsg(0,
	       "packet is %d bytes long, contains:\r\n%s\r\n", len, buf);
     i ++; 
#endif
    }
  } /* loop */
}  

/* end of SendMessage() ----------------------*/

int CloseTcpConn(int index){
	 close(port_status[index].connfd);
	 port_status[index].connfd = -1;
	 port_status[index].peerip = 0;
 	 port_status[index].peerport = 0;     
	 return 1;
}

int  CloseAllMulticastPort()
{
    int i;
    for(i=28;i<PORT_NUM;i++)
    {       
        close(port_status[i].sockfd);
    }
}
/*--------------------------------------------*/
void PutEscToApp()
{
	message_list ipmsg;
	in_buffer *pbuf;
	
	ipmsg.msgSrcIP = port_status[TELNET_PORT].peerip;
	ipmsg.msgSrcPort = port_status[TELNET_PORT].peerport;
	ipmsg.msgDstPort = TELNET_PORT;
	ipmsg.msgContent[0]='x';
	ipmsg.msgLength = 1;
        pbuf = (in_buffer *)&iptrans_shm_ptr -> msgPortIn[TELNET_PORT];
	iptrWriteMsg(pbuf, &ipmsg, IN_LIST_NUM);
}

int TcpConnectCheck(int index)
{
   int  timeout=20;  
	int connfdtmp=0;// 
   char welcome[128]={"Welcome to enter debug world!     (^_^) \n\r"};
   char timeout_prompt[128]={"You have stayed too long\n\r						telnet again please!\n\r"}; 
    	 
   //if(port_status[index].connfd<=0 )
   {
      memset(&cliaddr,0,(clilen=sizeof(struct sockaddr)));
      connfdtmp = accept(port_status[index].sockfd,
      //port_status[index].connfd = accept(port_status[index].sockfd,
						(struct sockaddr *)&cliaddr,&clilen);		
	  if(connfdtmp<=0) return 0;//
	  if(port_status[index].connfd>0)//
	  {

		sprintf(welcome,
				"\n\rSorry! %s:%d has connected to the server\n\r",
		        	(char *)inet_ntoa(cliaddr.sin_addr),
        			ntohs(cliaddr.sin_port));
        send(port_status[index].connfd,welcome,strlen(welcome),MSG_NOSIGNAL);

		sprintf(welcome,
				 "your connection is cut, bye bye!\n\r"); 
        send(port_status[index].connfd,welcome,strlen(welcome),MSG_NOSIGNAL);

		CloseTcpConn(index);	
	  }
/*
      if(port_status[index].connfd<=0){		
			return 0;
	  }
*/	
  	  port_status[index].connfd = connfdtmp; //
      if(port_status[index].connfd>0)
      {
        port_status[index].peerip = cliaddr.sin_addr.s_addr; 
        port_status[index].peerport = ntohs(cliaddr.sin_port);
        fcntl(port_status[index].connfd,F_SETFL,O_NONBLOCK);
        if(setsockopt(port_status[index].connfd,SOL_SOCKET,SO_KEEPALIVE,
         &timeout,sizeof(timeout)) !=0){
         fprintf(stderr,"set keepalive failed\n");
        }
        if(setsockopt(port_status[index].connfd,SOL_SOCKET,SO_KEEPALIVE,
         &timeout,sizeof(timeout)) !=0){
         fprintf(stderr,"set keepalive failed\n");
        }
        send(port_status[index].connfd,welcome,strlen(welcome),MSG_NOSIGNAL);
		if(index==TELNET_PORT)
			PutEscToApp();
      }
   }
 
 return 1;
}
/*--------------------------------------------*/
int iptrDirectRecvMsg(message_list *msgbuf,unsigned short port)
{
	int  				index,len,nbytes;
	BYTE 				bcd_buf[MAX_CONTENT_LEN]; 
	struct sockaddr_in  sin;	
	port_stat			*pstat;
	
	index = port - PORT_BASE_NUM;
	if(index<0 || index>=PORT_NUM)
	{
		return -1;
	}
	
	if(port_status[index].buffered == ACCESS_BUFFERED)
	{
		return iptrGetMessage(msgbuf,port);
	}
	
    if(port_status[index].recvcounter++>128) 
    {
    	return -1;
    }
    
    pstat = &iptransInfo.msgPortStat[index];
    len = sizeof(struct sockaddr);
    
    if(port_status[index].type == TYPE_TCP)
    {
    	if(port_status[index].connfd<=0) return-1;
    	
		nbytes = recvfrom(port_status[index].connfd, 
      					msgbuf->msgContent,
      					MAX_CONTENT_LEN,
      					0,
      					(struct sockaddr *) &sin, 
      					&len); 
      	if(nbytes<0){      		
        	return nbytes;
      	}
      	if(nbytes==0){
	 	//if(errno==ENOTSOCK || errno==ENOTCONN)
			{
         		CloseTcpConn(port);
			}
        	return -1;
      	}
        
      	msgbuf->msgSrcIP = sin.sin_addr.s_addr; 
      	msgbuf->msgSrcPort = ntohs(sin.sin_port); 

      	msgbuf->msgDstPort = index+PORT_BASE_NUM; 
      	msgbuf->msgLength = nbytes;
      	msgbuf->msgBroadcast = NO;
     
      	pstat->portStatus = 1;
      	pstat->inPackets ++;
      	pstat->inBytes +=nbytes;                
        
	  	if(strncasecmp(msgbuf->msgContent,"exit",4)==0)
			CloseTcpConn(index);      
	  	else if(msgbuf->msgContent[0]=='q' ||
			msgbuf->msgContent[0] =='Q')
	  		CloseTcpConn(index);
	  	return nbytes;			    	
    }else{
    	nbytes = recvfrom(port_status[index].sockfd, 
    						msgbuf->msgContent, MAX_CONTENT_LEN, 
                   			0, (struct sockaddr *) &sin, &len);
        if (nbytes < 0) {
            return nbytes;
        }        
        msgbuf->msgSrcIP = sin.sin_addr.s_addr; 
        msgbuf->msgSrcPort = ntohs(sin.sin_port);	    
        msgbuf->msgDstPort = port; 
        msgbuf->msgLength = nbytes;
        msgbuf->msgBroadcast = NO;        
                
        pstat->portStatus = 1;
        pstat->inPackets ++;
        pstat->inBytes += nbytes;

        iptransInfo.snmp_data.iptrans_cdr[nowPeriod].cdr_record[index].inPackets ++;
        iptransInfo.snmp_data.iptrans_cdr[nowPeriod].cdr_record[index].inBytes +=nbytes;        
		return nbytes;			
    }
    		
}

int iptrDirectSendMsg(message_list msgbuf)
{
	int len, port_id,ret,sendlen;
	int broadcast_message=0;
	struct sockaddr_in  sin;	
	
	if(sendcounter++>128) return 0;		
    
	port_id = msgbuf.msgSrcPort - PORT_BASE_NUM;
    if (port_id<0 || port_id>=PORT_NUM) 
	{
		if(port_convert_flag)
		{
				port_id = GetRealPortID(msgbuf.msgSrcPort);
				if(port_id<0)
					return 0;
		}
		else
			return 0;
	}
	
	if(port_status[port_id].buffered == ACCESS_BUFFERED)
	{
		return iptrPutMessage(msgbuf);
	}
	
	len = 0;
    bzero(&sin.sin_zero, sizeof(sin.sin_zero));
    sin.sin_family = AF_INET;    	
    sin.sin_addr.s_addr = msgbuf.msgDstIP;
    sin.sin_port = htons(msgbuf.msgDstPort);
	len = msgbuf.msgLength;
    broadcast_message = msgbuf.msgBroadcast;
    
    if (broadcast_message) {
        ret = setsockopt(port_status[port_id].sockfd, SOL_SOCKET,
        		 SO_BROADCAST,
                 &broadcast_message, sizeof(broadcast_message));
        if (ret < 0)
            log_ret("%s: %s: setsockopt", PROG_NAME, FUNCTION_MACRO);
    }
    if(port_status[port_id].type == TYPE_TCP)
    {
        if(port_status[port_id].connfd<=0) return 0;
	      ret = send(port_status[port_id].connfd, 
	      				&msgbuf.msgContent, len, MSG_NOSIGNAL);	       
    }else{ 
         ret = sendto(port_status[port_id].sockfd, msgbuf.msgContent, len, 0, 
            (struct sockaddr *)&sin, sizeof(sin));
            
    }  
    if (ret < 0) {
        iptransInfo.msgPortStat[port_id].portStatus = -1;
        iptransInfo.msgPortStat[port_id].errorPackets ++;
    }
    else if (port_id >= 0 && port_id < PORT_NUM) {
        iptransInfo.msgPortStat[port_id].outPackets ++;
        sendlen = iptransInfo.msgPortStat[port_id].outBytes;
        iptransInfo.msgPortStat[port_id].outBytes = sendlen + len;

        iptransInfo.snmp_data.iptrans_cdr[nowPeriod].cdr_record[port_id].outPackets ++;
        iptransInfo.snmp_data.iptrans_cdr[nowPeriod].cdr_record[port_id].outBytes +=len;
    }
	
	return 1;
}


/*------------------------------------------------*/
int iptrGetMessage(message_list *msgGet,int port_in)
{
   int  port=0;
   u_short readSub, writeSub;
   in_buffer *pbuf;
   port=port_in-PORT_BASE_NUM;
   if(port<0 || port>=PORT_NUM) return 0;

	pbuf = &iptrans_shm_ptr->msgPortIn[port];
	readSub = pbuf->msgReadSub%IN_LIST_NUM;
	writeSub = pbuf->msgWriteSub;
	if(readSub == writeSub) return 0;
    memcpy(msgGet,
			&pbuf->msgList[readSub], 
			sizeof(struct message_list));//msgPut.msgLength+44);
	pbuf->msgReadSub = (pbuf->msgReadSub+1) % IN_LIST_NUM;
	return 1;

}

int iptrPutMessage(message_list msgPut)
{
   out_buffer *pbuf;
	static int reflag=0;
	
	if(reflag == 1){
	 iptransInfo.debug_msg.port_status[10] ++;
	 return 0;
	}
	reflag = 1;
   pbuf = &iptrans_shm_ptr->msgPortOut;
   
   pbuf->msgWriteSub = (pbuf->msgWriteSub) % OUT_LIST_NUM;
   memcpy(&pbuf->msgList[pbuf->msgWriteSub],
		&msgPut,
		sizeof(struct message_list));//msgPut.msgLength+44);
   pbuf->msgWriteSub = (pbuf->msgWriteSub+1) % OUT_LIST_NUM;
   reflag = 0;
   return 1;   
}

int iptrPlatPutMessage(message_list msgPut)
{
   out_buffer *pbuf;
	static int reflag = 0;
	if(reflag == 1){
	 iptransInfo.debug_msg.port_status[11] ++;
		return 0;
    }
	reflag = 1;
   pbuf = &iptrans_shm_ptr->msgPlatPortOut;
   pbuf->msgWriteSub = (pbuf->msgWriteSub) % OUT_LIST_NUM;
   
   memcpy(&pbuf->msgList[pbuf->msgWriteSub],
		&msgPut,
		sizeof(struct message_list));//msgPut.msgLength+44);
   pbuf->msgWriteSub = (pbuf->msgWriteSub+1) % OUT_LIST_NUM;
	reflag = 0;
   return 1;   
}

/*--------------------------------------------*/
void iptrans_timer()
{
   int 				i;
   static int 		count = 0;
   struct timeval 	tmnow;
   message_list		msgbuf;
   
   debug_messages = 0;   
   sendcounter = 0;
   
   for(i=0;i<PORT_NUM;i++)
   {    
      iptrRecvMessage(iptrans_shm_ptr,iptrans_sem_id,i);
      
      port_status[i].recvcounter = 0;
      if(port_status[i].type == TYPE_TCP)
      	TcpConnectCheck(i);
   }
   iptrSendMessage(iptrans_shm_ptr,iptrans_sem_id);      
/*
    //testing code
   if(iptrDirectRecvMsg(&msgbuf,4966)>=0){
   	 msgbuf.msgSrcPort = 4966;
     iptrDirectSendMsg(msgbuf);
   }
*/   
   ReadAsciin();
   
   if(count++==1000)
   {
    count = 0;        
    SendHeartbeat();

    nowPeriod = GetNowPeriod();
    if(nowPeriod != lstPeriod)
    {
       gettimeofday(&tmnow,NULL);
       startTime[nowPeriod] = tmnow.tv_sec;
       lstPeriod = nowPeriod;
       memset(&iptransInfo.snmp_data.iptrans_cdr[nowPeriod],0,PORT_NUM*20);
    }

   }
   
}

int InitMulticastPort()
{
  int i,port;
  struct sockaddr_in sin_addr;
  char   ip3,ip[16];

  for(i=28;i<PORT_NUM;i++)
  {
     port=i+PORT_BASE_NUM; 
     ip3=i-27;
     sprintf(ip,"239.255.%d.1",ip3);  
     memset(&sin_addr,0,sizeof(struct sockaddr));
     sin_addr.sin_family=AF_INET;
     sin_addr.sin_port=htons(port);
     sin_addr.sin_addr.s_addr=inet_addr(ip);
     bzero(&(sin_addr.sin_zero),8);
     port_status[i].sockfd = Init_UDPSocket(sin_addr,1,0);
     if(port_status[i].sockfd<0) 
     	printf("Socket(%d) failed\n",i+PORT_BASE_NUM);
   }
   return 1; 
}

int InitSocket()
{
  int i,port;
  struct sockaddr_in sin_addr;
  char   ip3,ip[16];
 
  //InitMulticastPort();

  for(i=0;i<PORT_NUM;i++)
  {
     port=i+PORT_BASE_NUM;    
	 if(port_status[i].convert_flag)
		port = port_status[i].real_portno;

     memset(&sin_addr,0,sizeof(struct sockaddr));
     sin_addr.sin_family=AF_INET;
     sin_addr.sin_port=htons(port);
     sin_addr.sin_addr.s_addr=GetLocalIP(); // INADDR_ANY;
     bzero(&(sin_addr.sin_zero),8);
     
     if(port_status[i].type == TYPE_TCP )
     {
          port_status[i].sockfd = Init_UDPSocket(sin_addr,0,1);
          listen(port_status[i].sockfd,1);
     }
     else
     {
          port_status[i].sockfd = Init_UDPSocket(sin_addr,0,0);
     }
     if(port_status[i].sockfd<0)
      	printf("Socket(%d) failed\n",port);  
  }
  
  return 1;
}

int Init_UDPSocket(struct sockaddr_in saddr,int bFlag,int type)
 /* bFlag =1/0 multicasting /nomulticasting 
    type  0/1  udp/tcp  
 */   
{
  int sock;
  long sockbuf=40*1024; 
  int on=1,delay=0,timeout=20;
  int flag=bFlag;

  if(type==0)  
    sock=socket(AF_INET,SOCK_DGRAM,0);
  else
    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(type==1)
  {
     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(bind(sock,(struct sockaddr*)&saddr,sizeof(struct sockaddr))<0)
  {
     fprintf(stderr,"bind failed,port:%d\n",htons(saddr.sin_port));   
       close(sock);
       return -2;
  } 
  if(flag>0)
  {
    if((mcast_join(sock,(struct sockaddr *)&saddr,sizeof(struct sockaddr),NULL,0))<0)
    {
       fprintf(stderr,"mcast_join failed\n");
       return -7;
    }
  }     
  return sock;
 }



int init_monitor()
{
	BYTE	page;
	BYTE 	*ptr;
	
	iptransInfo.debug_msg.debug_status = 1;
	iptransInfo.debug_msg.debug_status_id[0] =1; 
    iptransInfo.debug_msg.debug_status_id[1] = 3;
	iptransInfo.debug_msg.debug_status_id[2] = 6;
	iptransInfo.debug_msg.debug_status_id[3] = 1;
	iptransInfo.debug_msg.debug_status_id[4] = 4;
	iptransInfo.debug_msg.debug_status_id[5] = 1;
	iptransInfo.debug_msg.debug_status_id[6] = 1373;
	iptransInfo.debug_msg.debug_status_id[7] = 1;
	iptransInfo.debug_msg.debug_status_id[8] = 1;
	iptransInfo.debug_msg.debug_status_id[9] = 2;
	iptransInfo.debug_msg.debug_status_id[10] = 3;
	iptransInfo.debug_msg.debug_status_id[11] = 1;
	iptransInfo.debug_msg.debug_status_id[12] = 2;
	iptransInfo.debug_msg.debug_status_id[13] = 2;
	iptransInfo.debug_msg.debug_status_id[14] = 1;

	iptransInfo.debug_msg.debug_name_id[0] =1; 
    iptransInfo.debug_msg.debug_name_id[1] = 3;
	iptransInfo.debug_msg.debug_name_id[2] = 6;
	iptransInfo.debug_msg.debug_name_id[3] = 1;
	iptransInfo.debug_msg.debug_name_id[4] = 4;
	iptransInfo.debug_msg.debug_name_id[5] = 1;
	iptransInfo.debug_msg.debug_name_id[6] = 1373;
	iptransInfo.debug_msg.debug_name_id[7] = 1;
	iptransInfo.debug_msg.debug_name_id[8] = 1;
	iptransInfo.debug_msg.debug_name_id[9] = 2;
	iptransInfo.debug_msg.debug_name_id[10] = 3;
	iptransInfo.debug_msg.debug_name_id[11] = 1;
	iptransInfo.debug_msg.debug_name_id[12] = 2;
	iptransInfo.debug_msg.debug_name_id[13] = 2;
	iptransInfo.debug_msg.debug_name_id[14] = 2;

	iptransInfo.debug_msg.debug_ascin_id[0] =1; 
    iptransInfo.debug_msg.debug_ascin_id[1] = 3;
	iptransInfo.debug_msg.debug_ascin_id[2] = 6;
	iptransInfo.debug_msg.debug_ascin_id[3] = 1;
	iptransInfo.debug_msg.debug_ascin_id[4] = 4;
	iptransInfo.debug_msg.debug_ascin_id[5] = 1;
	iptransInfo.debug_msg.debug_ascin_id[6] = 1373;
	iptransInfo.debug_msg.debug_ascin_id[7] = 1;
	iptransInfo.debug_msg.debug_ascin_id[8] = 1;
	iptransInfo.debug_msg.debug_ascin_id[9] = 2;
	iptransInfo.debug_msg.debug_ascin_id[10] = 3;
	iptransInfo.debug_msg.debug_ascin_id[11] = 1;
	iptransInfo.debug_msg.debug_ascin_id[12] = 2;
	iptransInfo.debug_msg.debug_ascin_id[13] = 2;
	iptransInfo.debug_msg.debug_ascin_id[14] = 3;

	iptransInfo.debug_msg.debug_ascout_id[0] =1; 
    iptransInfo.debug_msg.debug_ascout_id[1] = 3;
	iptransInfo.debug_msg.debug_ascout_id[2] = 6;
	iptransInfo.debug_msg.debug_ascout_id[3] = 1;
	iptransInfo.debug_msg.debug_ascout_id[4] = 4;
	iptransInfo.debug_msg.debug_ascout_id[5] = 1;
	iptransInfo.debug_msg.debug_ascout_id[6] = 1373;
	iptransInfo.debug_msg.debug_ascout_id[7] = 1;
	iptransInfo.debug_msg.debug_ascout_id[8] = 1;
	iptransInfo.debug_msg.debug_ascout_id[9] = 2;
	iptransInfo.debug_msg.debug_ascout_id[10] = 3;
	iptransInfo.debug_msg.debug_ascout_id[11] = 1;
	iptransInfo.debug_msg.debug_ascout_id[12] = 2;
	iptransInfo.debug_msg.debug_ascout_id[13] = 2;
	iptransInfo.debug_msg.debug_ascout_id[14] = 4;

	iptransInfo.debug_msg.debug_page_title[0] =1; 
    iptransInfo.debug_msg.debug_page_title[1] = 3;
	iptransInfo.debug_msg.debug_page_title[2] = 6;
	iptransInfo.debug_msg.debug_page_title[3] = 1;
	iptransInfo.debug_msg.debug_page_title[4] = 4;
	iptransInfo.debug_msg.debug_page_title[5] = 1;
	iptransInfo.debug_msg.debug_page_title[6] = 1373;
	iptransInfo.debug_msg.debug_page_title[7] = 1;
	iptransInfo.debug_msg.debug_page_title[8] = 1;
	iptransInfo.debug_msg.debug_page_title[9] = 2;
	iptransInfo.debug_msg.debug_page_title[10] = 3;
	iptransInfo.debug_msg.debug_page_title[11] = 1;
	iptransInfo.debug_msg.debug_page_title[12] = 2;
	iptransInfo.debug_msg.debug_page_title[13] = 2;
	iptransInfo.debug_msg.debug_page_title[14] = 5;
    iptransInfo.debug_msg.debug_page_title[15] = 1;

	iptransInfo.debug_msg.debug_page_line[0] =1; 
    iptransInfo.debug_msg.debug_page_line[1] = 3;
	iptransInfo.debug_msg.debug_page_line[2] = 6;
	iptransInfo.debug_msg.debug_page_line[3] = 1;
	iptransInfo.debug_msg.debug_page_line[4] = 4;
	iptransInfo.debug_msg.debug_page_line[5] = 1;
	iptransInfo.debug_msg.debug_page_line[6] = 1373;
	iptransInfo.debug_msg.debug_page_line[7] = 1;
	iptransInfo.debug_msg.debug_page_line[8] = 1;
	iptransInfo.debug_msg.debug_page_line[9] = 2;
	iptransInfo.debug_msg.debug_page_line[10] = 3;
	iptransInfo.debug_msg.debug_page_line[11] = 1;
	iptransInfo.debug_msg.debug_page_line[12] = 2;
	iptransInfo.debug_msg.debug_page_line[13] = 2;
	iptransInfo.debug_msg.debug_page_line[14] = 1;
    iptransInfo.debug_msg.debug_page_line[15] = 2;
    iptransInfo.debug_msg.debug_page_line[16] = 1;

sprintf(iptransInfo.debug_msg.title1_p,"%s",
	" IPTRANS    Version R9V0_01                                      Page 01\n\r\
 Port state  \r\n\
                   00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\r\n\
 Port Status\r\n\
 4950-4965\r\n\
 4966-4981\r\n\
\
 Port Overflow\r\n\
 4950-4965\r\n\
 4966-4981\r\n\
 ");

sprintf(iptransInfo.debug_msg.title2_p,"%s",
	" IPTRANS    Version  R9V0_01                                   Page 02\n\r\
 Flow Statistics (PORT 4950 - 4965)\r\n\
 PortNo            Received                Sent                    Error\r\n\
                   Packets     Bytes       Pakcets     Bytes       Packets\r\n\
 4950\r\n\
 4951\r\n\
 4952\r\n\
 4953\r\n\
 4954\r\n\
 4955\r\n\
 4956\r\n\
 4957\r\n\
 4958\r\n\
 4959\r\n\
 4960\r\n\
 4961\r\n\
 4962\r\n\
 4963\r\n\
 4964\r\n\
 4965"
);

sprintf(iptransInfo.debug_msg.title3_p,"%s",
	" IPTRANS    Version R9V0_01                                    Page 03\n\r\
 Flow Statistics (PORT 4966 - 4981)\r\n\
 PortNo            Received                Sent                    Error\r\n\
                   Packets     Bytes       Pakcets     Bytes       Packets\r\n\
 4966\r\n\
 4967\r\n\
 4968\r\n\
 4969\r\n\
 4970\r\n\
 4971\r\n\
 4972\r\n\
 4973\r\n\
 4974\r\n\
 4975\r\n\
 4976\r\n\
 4977\r\n\
 4978\r\n\
 4979\r\n\
 4980\r\n\
 4981"
);
	debug_set_response(BASE_ID_LEN,iptransInfo.debug_msg.debug_status_id,&iptransInfo.debug_msg.debug_status,1);
	debug_set_response(BASE_ID_LEN,iptransInfo.debug_msg.debug_name_id,"R9V0_01",8);//module name
	debug_set_response(BASE_ID_LEN,iptransInfo.debug_msg.debug_ascin_id,iptransInfo.debug_msg.iptr_asciin_buf,4096);//ascii in buf
	debug_set_response(BASE_ID_LEN,iptransInfo.debug_msg.debug_ascout_id,iptransInfo.debug_msg.iptr_asciout_buf,4096);//ascii out buf
	
	for (page = 1; page < 4; page ++)
	{
		switch (page)
		{
		    case 1:
			    ptr = iptransInfo.debug_msg.title1_p;
			    break;
			case 2://page 1
				ptr = iptransInfo.debug_msg.title2_p;
				break;
			case 3://page 2;
				ptr =  iptransInfo.debug_msg.title3_p;
				break;		
			default:
				break;				
		}
		iptransInfo.debug_msg.debug_page_title[IPTR_PAGE_POINT] = 5 + page;
		debug_set_response(BASE_ID_LEN+1,iptransInfo.debug_msg.debug_page_title,ptr,strlen(ptr));
		iptr_disp_page(page);
	}
	
   return 1;
}


int	iptr_disp_page(int page)
{
	BYTE	disp_line;
	BYTE	disp_length;

	
	iptransInfo.debug_msg.debug_page_line[IPTR_PAGE_POINT] = page + 5;//page
	for (disp_line = 0; disp_line < 16; disp_line++)
	{
		disp_length = iptr_disp_line(page,disp_line);
		iptransInfo.debug_msg.debug_page_line[IPTR_LINE_POINT] = disp_line + 5;//line
		iptransInfo.debug_msg.debug_page_line[IPTR_LINE_POINT+1] = 2;//data pointer
		debug_set_response(BASE_ID_LEN+2,iptransInfo.debug_msg.debug_page_line,disp_ptr,disp_length);
	}
	return 1;
}


int	iptr_disp_line(int page, int line)//return display length,disp data ptr per line
{
	BYTE	disp_length;
	int     loop;

   disp_length = 16;

	switch (page)
	{
	    case 1:
		  switch(line)
		  {
		    case 0:
  		      disp_ptr= (BYTE *)iptransInfo.debug_msg.port_onoff;
		    break;
			case 1:
			  disp_ptr= (BYTE *)&iptransInfo.debug_msg.port_onoff[16];
		    break;
			case 2:
			case 3:
		      disp_length = 0;
		    break;
			case 4:
			  disp_ptr = (BYTE *)iptransInfo.debug_msg.port_status;
		    break;
			case 5:
			  disp_ptr = (BYTE *)&iptransInfo.debug_msg.port_status[16];
	        break;
			default:
   		     disp_length = 0;
		    break;
	       }
		  break;
		case 2://page 2
		  disp_ptr=(BYTE *) &iptransInfo.msgPortStat[line].inPackets;
		  disp_length =20;					
		break;
		case 3://page 3
    	  disp_ptr=(BYTE *)&iptransInfo.msgPortStat[16+line].inPackets;
		  disp_length = 20;					
		break;
		default:
		  disp_length = 0;
		break;
	}
	
	return disp_length;
}

int ReadAsciin()
{
   int pageno,len;
   char cmd[1024]={""};
   
   len = strlen(iptransInfo.debug_msg.iptr_asciin_buf);
   if(len==0)
   {
      return 0;
   }
   pageno = iptransInfo.debug_msg.iptr_asciin_buf[0];
   memcpy(cmd,&iptransInfo.debug_msg.iptr_asciin_buf[1],len-1);

   DecodeAsciin(pageno-1,cmd);

   memset(iptransInfo.debug_msg.iptr_asciin_buf,0,64);
   return 1;
}

int DecodeAsciin(int pageno, char *cmd)
{
   int res,port,no;
   int srcport, dstport;
   DWORD flag=0x01;

   switch(pageno)
   {
      case 0:
        if((res=strcasecmp(cmd,"HELP"))==0)
		{
		   sprintf(iptransInfo.debug_msg.iptr_asciout_buf,
"log help page\r\n\
help           : help  for this page\r\n\
set on portno=n: set port capability (n=0-6)\r\n\
log all/none   : log all message received or sent\r\n\
log error   on : if overflowed, point out which port overflowed\r\n\
log error  off : no message put, even port overflowed\r\n\
log src portno : log message sent from port of portno\r\n\
log dst portno : log message received from port of portno\r\n\
log src portno1 and dst portno2 : log message from portno1 to portno2\r\n\
");
           break;
		}
		else if((res=strcasecmp("LOG ALL",cmd))==0)
		{
		  iptransInfo.debug_msg.logflag = 0xffffffff;
		  break;
		}
		else if((res=strcasecmp("LOG none",cmd))==0)
		{
		  iptransInfo.debug_msg.logflag = 0x00;
		  break;
		}
		else if(strstr(cmd,"and dst 49") && strstr(cmd,"log src 49"))
		{
		  srcport = atoi(&cmd[8]);
		  dstport = atoi(&cmd[21]);
		  if(srcport>=PORT_BASE_NUM+PORT_NUM ||
		     dstport>=PORT_BASE_NUM+PORT_NUM)
			 break;
		  if(srcport<PORT_BASE_NUM ||
		     dstport<PORT_BASE_NUM)
			 break;
		  flag = 0x01;
		  iptransInfo.debug_msg.srclog = (flag<<(srcport-PORT_BASE_NUM));
		  flag = 0x01;
		  iptransInfo.debug_msg.dstlog = (flag<<(dstport-PORT_BASE_NUM));
		  iptransInfo.debug_msg.logflag = 0xfffffffe;
		  break;
		}
        else if(strstr(cmd,"log src 49"))
		{
		  srcport = atoi(&cmd[8]);		  
		  iptransInfo.debug_msg.dstlog = 0x00;
		  if(srcport<PORT_BASE_NUM || srcport>=PORT_BASE_NUM+PORT_NUM)
		    break;
          flag = 0x01;
		  iptransInfo.debug_msg.srclog = (flag<<(srcport-PORT_BASE_NUM));
		  iptransInfo.debug_msg.logflag = 0xfffffffe;
		  break;
		}
        else if(strstr(cmd,"log dst 49"))
		{
		  iptransInfo.debug_msg.srclog = 0x00;
		  dstport = atoi(&cmd[8]);
		  if(dstport<PORT_BASE_NUM || dstport>=PORT_BASE_NUM+PORT_NUM)
		    break;
          flag = 0x01;
		  iptransInfo.debug_msg.dstlog = (flag<<(dstport-PORT_BASE_NUM));
		  iptransInfo.debug_msg.logflag = 0xfffffffe;
		}
        else if(strstr(cmd,"log error off"))
        {
           warningFlag = 0x00;
        }
        else if(strstr(cmd,"log error on"))
        {
           warningFlag = 0x01;
        }
		else if(strstr(cmd,"set on 49"))
		{
		  dstport = atoi(&cmd[7]);
		  if(dstport<PORT_BASE_NUM || dstport>=PORT_BASE_NUM+PORT_NUM)
		  {
          		sprintf(iptransInfo.debug_msg.iptr_asciout_buf,
          			 "error port number, should be : 4950-4972!");
		    break;
		  }
		  dstport -=PORT_BASE_NUM;
		  no = atoi(&cmd[12]);
		  if(no>=6) no = 6;
		  if(dstport == TELNET_PORT && no == 0)
		  {
          		sprintf(iptransInfo.debug_msg.iptr_asciout_buf,
						"The WXC2 debug port cann't be closed!");
				break;
		  }
      	  port_status[dstport].capability = no;
  			iptransInfo.debug_msg.port_onoff[dstport] = no;

			iptrSaveParameter();
		}
		else{
          sprintf(iptransInfo.debug_msg.iptr_asciout_buf,
           "error comamnd!");
        }
	  break;
	  case 1:
	  break;
	  case 2:
	  case 3:
	  if(strcasecmp(cmd,"C")==0)
	  {
	     ClearStatistics(pageno);
		 break;
	  }
	  if(strstr(cmd,"C 49") || strstr(cmd,"c 49"))
	  {
	     port = atoi(&cmd[2]);
		 if(port>=PORT_BASE_NUM && port<PORT_BASE_NUM+PORT_NUM)
		 {
		   ClearPortStatics(port-PORT_BASE_NUM);
		 }
	  }
	  break;
	  default:
	  break;
   }
   return 1;
}

int ClearStatistics(int pageno)
{
   int loop,start;
   start = 0;
   if(pageno==3)
    start = 16;
   for(loop=0;loop<16;loop++)
   {
     ClearPortStatics(start+loop);
   }
   return 1;
}

int ClearPortStatics(int index)
{
   memset(&iptransInfo.msgPortStat[index],0,sizeof(port_stat));
   return 1;
}

int SetAsciioutMsg(int flag, const char *fmt, ...)
{
   va_list        ap;
   char    buf[MAXLINE];

   va_start(ap, fmt);

   vsprintf(buf, fmt, ap);

   if(flag==1)
     sprintf(iptransInfo.debug_msg.iptr_asciout_buf,"%s",buf);
   else
     strcat(iptransInfo.debug_msg.iptr_asciout_buf,buf);

   va_end(ap);
   return 1;
}
/* ====================================================================== */
/* ====================================================================== */

int iptrans_init()
{
    iptrans_initshm();    
    return 1;
}

int iptrMainInit()
{
	struct timeval tmnow;
    
    gettimeofday(&tmnow,NULL);
    nowPeriod = lstPeriod = GetNowPeriod(); 
    startTime[nowPeriod] = tmnow.tv_sec;
   	memcpy(iptransInfo.snmp_data.version,IPTRANS_VERSION,3); 
   	
   	iptrans_init();
   	        
    init_monitor();            
    ConfigurePort();
    InitSocket();

    heartbeat_init(0xffff);
    inquire_setmsg(12,IPTRANS_OID_PREFIX,(void *)get_iptrans);
    inquire_getmsg(12,IPTRANS_OID_PREFIX,(void *)get_iptrans);
    inquire_trapmsg((void *)trap_iptrans);
    
	return 1;
}

int GetNowPeriod()
{
    int nowP;
    long   curr_time;
    struct tm *tmnow,tt;

	tmnow = &tt;
    curr_time = time((long *)0);
    tmnow = localtime(&curr_time);
    
    nowP = (tmnow->tm_hour * 4) + (tmnow->tm_min)/15; 
    return nowP;
}

int iptrans_initshm()
{

    iptrans_shm_ptr = (iptrans_shm *) iptrShmInit(iptrans_shm_id, PROG_NAME,
            IPTRANS_SHM_KEY, sizeof(iptrans_shm), IPTRANS_SHM_PERM|IPC_CREAT);

    if( NULL == iptrans_shm_ptr )
    {
        printf("iptrans share memory fail.\n");
        exit(0);
    }

    
    memset(iptrans_shm_ptr, 0, sizeof(iptrans_shm));

    return 1;
}

int ConfigurePort()
{
	char confile[]={"./conf/iptrans.conf"};
	char s[80],s1[80],work[80];
	int  loop,priority,len,type,direct=0;
	unsigned char conf_state = 0xFF;
  	unsigned short port, realport; 
	char *off;
	FILE *fpConf;
    
	fpConf = fopen(confile,"rb");
	if(fpConf==NULL)
	{
		printf("%s not found!\n",confile);
		for(loop=0;loop<PORT_NUM;loop++)
	  	{
			port_status[loop].capability = 2;
			iptransInfo.debug_msg.port_onoff[loop] = 1;
	  	}
		port_status[0].capability = 6; /* 4950 with highest capability*/
		return 1;
	}
   
   
	strcpy(s,"");
	strcpy(s1,"");
	while(fgets(s,1024,fpConf) !=(char *)0)
	{
		if( (int *)strchr(s,'#') !=NULL) continue;
		if( !strlen(s) ) continue;      
		len = strlen(s);
		if(!strncasecmp(s,"[port transfer]",15))
		{
			conf_state = 1;
			continue;
		}
		else if(!strncasecmp(s,"[port flag]",11))
		{
			conf_state = 0;
			continue;
		}

		switch(conf_state)
		{
			case 1:
				if(s[4] == '=')
				{
					memcpy(work,s,4);
					work[4] = 0;
					port = atoi(work);
					strcpy(work,&s[5]);
					realport = atoi(work);
					if(realport>0)
					{
						port_status[port-PORT_BASE_NUM].convert_flag = 1;
						port_status[port-PORT_BASE_NUM].real_portno = realport;
						port_convert_flag = 1;	
						break;
					}
				}
			case 0:
			default:
	        	if(len !=18 && len !=19) 
    	    	{
        			printf("Error line: %s len=%d\n",s,len);
        			continue;
        		}
       			memcpy(work,s,4);
        		work[4] = 0;
        		port = atoi(work);
				if(port<PORT_BASE_NUM || port>=PORT_BASE_NUM+PORT_NUM)
        		{
        			printf("Error line: %s (error port)!\n",s);
        			continue;
        		}                
        
        		memcpy(work,&s[5],3);
        		work[3] = 0;
        		if(strncasecmp(work,"udp",3)==0)
        		{
        			type = TYPE_UDP;
        		}
				else if(strncasecmp(work,"tcp",3)==0)
        		{
        			type = TYPE_TCP;
        		}
				else
        		{
        			printf("Error line: %s (error socket type)!\n",s);
        			continue;
        		}
        
       			memcpy(work,&s[9],1);
        		work[1] = 0;        
        		priority = atoi(work)%7;
        
        		memcpy(work,&s[11],6);
        		work[6] = 0;
        		if(strncasecmp(work,"direct",6)==0)
        		{
        			direct = ACCESS_DIRECT;
        		}
				else if(strncasecmp(work,"buffer",6)==0)
        		{
        			direct = ACCESS_BUFFERED;
        		}
				else
        		{
        			printf("Error line: %s (error access type)!\n",s);
        			continue;        	
        		}
                        
				port_status[port-PORT_BASE_NUM].type = type;
				port_status[port-PORT_BASE_NUM].capability = priority%7;		
				port_status[port-PORT_BASE_NUM].buffered = direct;
				iptransInfo.debug_msg.port_onoff[port-PORT_BASE_NUM] = 
	    		port_status[port-PORT_BASE_NUM].capability;	
        	break;    
      	}
	}
	
	if(port_status[TELNET_PORT].capability == 0)
	{
		port_status[TELNET_PORT].capability = 2;
		iptransInfo.debug_msg.port_onoff[TELNET_PORT] = 
	   	port_status[TELNET_PORT].capability;	
	}
	fclose(fpConf);
	
	return 1;
}
/*------------------------------------------------*/
int set_iptrans(BYTE oidlen, DWORD *oid, BYTE *pdata, WORD datalen)
{
  int portid;
  if(oidlen<13)  return 0;
  if(oid[11] != OID_IPTRANS)  return 0;
  switch(oid[12])
  {
    case 1:
	  return -1;
	  break;
	case 2:
	  if(oidlen<14) return -1;
	  if(oid[13] ==1) //process configureation
	  {
	     if(pdata[0]==1){
		   
		 }
		 else if(pdata[1]==2)
		 {
		 }
		 else
		 {
		   return -1;
		 }
		 return 1;
	  }
	  else if(oid[13] ==2) //port configure
	  {
	    if(oidlen<15) return -1;
        portid = oid[14];
        if(portid<1 || portid>PORT_NUM)
		  return -1;
		port_status[portid].capability = pdata[0]%7;
		return 1;
	  }
	  else
	  {
	    return -1;
	  }
	  break;
	case 3:
	  return -1;
	  break;
	default:
	  return -1;
	  break;
  }
  return 1;
}

int get_iptrans(BYTE oidlen, DWORD *oid, BYTE *pdata, WORD *vartype)
{
  int  periodid,portid;
  //if(oid[11] != OID_IPTRANS) return -1;
  *vartype = 4;	 
  switch(oid[11])
  {
    case 1:
	  if(oid[12] !=2) return -1; //Only CSTA supported
	  if(oidlen>14) return -1;
	  periodid = oid[13];
	  if(periodid<0 || periodid>95) return -1;
/*	  if(oidlen==16)
	  {
	     portid = oid[15];
		 if(portid<1 || portid>32) return -1;
		 StuffPortCSTA(pdata,periodid,portid);
		 return 20;
	  }
*/        pdata[0] = startTime[periodid]>>24;
          pdata[1] = startTime[periodid]>>16;
          pdata[2] = startTime[periodid]>>8;
          pdata[3] = startTime[periodid];
	  StuffAllCSTA(pdata+4,periodid);
	  return (PORT_NUM*20+4);
	  break;
	case 2:
	  return 0;
	  break;
	case 3:
	  if(oidlen<15) {  //Whole OID of Status
	    return -1;
      }
	  if(oid[13] ==1)
	  {
	    memcpy(pdata,iptransInfo.snmp_data.version,3);
	    return 3;
	  }
	  if(oid[13] ==2)
	  {
	    memcpy(pdata,iptransInfo.debug_msg.port_status,PORT_NUM);
		return PORT_NUM;
	  }
	  else
	  {
	    return -1;
	  }
	  break;
	default:
	  return 0;
	  break;
  }
  return 1;
}

int trap_iptrans(BYTE oidlen, DWORD *oid_ptr, BYTE *msg_ptr, BYTE msg_len)
{
  return 1;
}

int SendHeartbeat()
{
  int    loop;
  BYTE   alarm=0x00;
  BYTE   flag0 = 0x00,
         flag1 = 0x00,
	     flag2 = 0x00,
	     flag3 = 0x00;
  BYTE   status[32];

  for(loop=0;loop<PORT_NUM;loop++)
  {
    if(iptransInfo.debug_msg.port_status[loop])
	{
	 // iptransInfo.debug_msg.port_status[loop] = 0x00;
	   alarm = 2+loop;
	   break;
	}
  }

  memcpy(&status[0],IPTRANS_VERSION,3);
  
  for(loop=0;loop<PORT_NUM;loop++)
  {
    switch(loop/8)
	{
	   case 0:
	    flag0 = flag0 | (iptransInfo.debug_msg.port_onoff[loop]<<(loop%8));
	    break;
	   case 1:
	    flag1 = flag1 | (iptransInfo.debug_msg.port_onoff[loop]<<(loop%8));
	    break;
	   case 2:
	    flag2 = flag2 | (iptransInfo.debug_msg.port_onoff[loop]<<(loop%8));
	    break;
	   default:
	    flag3 = flag3 | (iptransInfo.debug_msg.port_onoff[loop]<<(loop%8));
	    break;
	}
  }
  status[3] = 0x01; //version
  status[4] = flag0;
  status[5] = flag1;
  status[6] = flag2;
  status[7] = flag3;
  set_status(0,8,status);
  set_led(2,9);
  return 1;
}

char *
iptrFormatOutput(char *sp, size_t size, int len, int c)
{
	char       buf[BUFSIZE];
	int        i, j=0;

	strcpy(buf, sp);
	for(i=0; i<size; i+=len) {
		strncpy(sp, buf+i, len);
		sp +=len;
		j +=len;
		if ( (j % 80)!=0 ) {
			*sp++ = c;
			j++;
		}
	}
	*sp = 0;

	return sp;
}

char * iptrGetASCTime(char *timep)
{
	struct tm  *tp, tb;
	long       ltime;

	tp = &tb;
	ltime = time((long *)0);
	tp = localtime(&ltime);
	timep = asctime(tp);
	timep[24] = 0;
	return timep;
}

int StuffAllCSTA(char *pdata, int period)
{
    int loop;
    for(loop=0;loop<PORT_NUM;loop++)
	{
	  StuffPortCSTA(&pdata[loop*20],period,loop);
	}
	return 1;
}

int StuffPortCSTA(char *pdata, int period, int port)
{
  pdata[0]  = iptransInfo.snmp_data.iptrans_cdr[period].cdr_record[port].inPackets>>24;
  pdata[1]  = iptransInfo.snmp_data.iptrans_cdr[period].cdr_record[port].inPackets>>16;
  pdata[2]  = iptransInfo.snmp_data.iptrans_cdr[period].cdr_record[port].inPackets>>8;
  pdata[3]  = iptransInfo.snmp_data.iptrans_cdr[period].cdr_record[port].inPackets;
  pdata[4]  = iptransInfo.snmp_data.iptrans_cdr[period].cdr_record[port].inBytes>>24;      
  pdata[5]  = iptransInfo.snmp_data.iptrans_cdr[period].cdr_record[port].inBytes>>16;
  pdata[6]  = iptransInfo.snmp_data.iptrans_cdr[period].cdr_record[port].inBytes>>8;
  pdata[7]  = iptransInfo.snmp_data.iptrans_cdr[period].cdr_record[port].inBytes;
  pdata[8]  = iptransInfo.snmp_data.iptrans_cdr[period].cdr_record[port].outPackets>>24;
  pdata[9]  = iptransInfo.snmp_data.iptrans_cdr[period].cdr_record[port].outPackets>>16;
  pdata[10] = iptransInfo.snmp_data.iptrans_cdr[period].cdr_record[port].outPackets>>8;
  pdata[11] = iptransInfo.snmp_data.iptrans_cdr[period].cdr_record[port].outPackets;
  pdata[12] = iptransInfo.snmp_data.iptrans_cdr[period].cdr_record[port].outBytes>>24;      
  pdata[13] = iptransInfo.snmp_data.iptrans_cdr[period].cdr_record[port].outBytes>>16;
  pdata[14] = iptransInfo.snmp_data.iptrans_cdr[period].cdr_record[port].outBytes>>8;
  pdata[15] = iptransInfo.snmp_data.iptrans_cdr[period].cdr_record[port].outBytes;
  pdata[16] = iptransInfo.snmp_data.iptrans_cdr[period].cdr_record[port].errorPackets>>24;      
  pdata[17] = iptransInfo.snmp_data.iptrans_cdr[period].cdr_record[port].errorPackets>>16;
  pdata[18] = iptransInfo.snmp_data.iptrans_cdr[period].cdr_record[port].errorPackets>>8;
  pdata[19] = iptransInfo.snmp_data.iptrans_cdr[period].cdr_record[port].errorPackets;
   return 1;
}

int PrintCSTA(int period)
{
   int loop;
   if(period<0) return 0;
   fprintf(stderr,"CSTA of %02d:\n",period);
   fprintf(stderr,"TimeStamp: %08X\n",startTime[period]);
   for(loop=0;loop<644;loop++)
   {
     if((loop+1)%20 ==0) fprintf(stderr,"\n");
     fprintf(stderr,"%02X ",((char *)&iptransInfo.snmp_data.iptrans_cdr[period])[loop]);
   }
   return 1;
}

int iptrSaveParameter()
{
	int loop;
	FILE *fp=NULL;
	char	msg[128];
	char	type[2][16]=
		{"UDP","TCP"};
	char	access[2][16]=
		{"BUFFER","DIRECT"};
	
	fp = fopen("./conf/iptrans.conf.bak","w");
	if(fp == NULL)
	{
			return 0;
	}
	fprintf(fp,"#ipconfig\n");
	fprintf(fp,"#port=type,num,interface\n");
	fprintf(fp,"#type=UDP/TCP\n");
	fprintf(fp,"#num=0-6\n");
	fprintf(fp,"#interface=BUFFER/DIRECT\n");
	fprintf(fp,"\n");

	for(loop=0;loop<PORT_NUM;loop++)
	{	
			sprintf(msg,"%d=%s,%d,%s\n",
							loop+PORT_BASE_NUM,
							type[port_status[loop].type],
							port_status[loop].capability,
							access[port_status[loop].buffered]);
			fprintf(fp,"%s",msg);
	}
	fprintf(fp,"[port transfer]\n");
	for(loop=0;loop<PORT_NUM;loop++)
	{
		if(port_status[loop].convert_flag )
		{
			fprintf(fp,"%d=%d\n",
				loop+PORT_BASE_NUM,
				port_status[loop].real_portno);
		}
	}
	fclose(fp);
	
	rename("./conf/iptrans.conf.bak","./conf/iptrans.conf");
}
/*@end@*/
