/*
 *========================================================================
 *
 *   시스템명 : 요금징수 시스템
 *   파 일 명 :
 *   작 성 자 : 오효섭 (catacath@neighbor21.co.kr)
 *   작 성 일 : 2012.10.04
 *   수 정 일 :
 *   설    명 :
 *
 *========================================================================
*/

/*==========================================================================*/
/* Head  정의                                                               */
/*==========================================================================*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <time.h>
#include <signal.h>
#include <errno.h>
#include <sys/ipc.h>
#include <sys/time.h>
#include <sys/msg.h>
#include "lane_trace.h"
#include "snd_rcv_knd.h"
#include "hi_ctrl.h"
#include "lo_ctrl.h"
#include "hi_packet_format.h"
#include "file_lb.h"
#include "lb_func_list.h"

FILE    *debug;
char    debug_f[128];

int    lane_typ;

#define    _LINE_TEST_      1         /* 회선테스트 적용    */
#define    _LINE_TEST_SEC  60         /* 회선테스트 SEC    */
int    line_check_flag    = 0;         /* 1 Setting시 회선차단*/

#define    _LCL_ADDR_CHK    1          /* ADDRESS CHECK 적용     */
char      lcl_addr[15+1];

#define    SAVE_BUFFER_CNT  4

int     conn_sock;            /* SOCK Descriptor         */
uchar   r_buffer [4096];      /* SOCK recv buffer         */
uchar   s_buffer [4096];      /* SOCK send buffer         */
uchar   rs_buffer[4096 * SAVE_BUFFER_CNT];    /* SOCK recv save buffer */
int     r_length;             /* SOCK length to be read      */
int     s_length;             /* SOCK send length         */
int     rs_length=0;             /* SOCK recv save length  */

struct  oracon *oracon;        /* 오라클 상태관리 GLOBAL */
int     oraconn =  0;          /* 오라클 상태관리 LOCAL  */
int     oracon_old =  1;       /* 오라클 상태 전송유무    */
int     oracon_snd =  0;       /* 오라클 상태 전송유무    */
int     db_errno;

void      SIG_term();            /* signal handler  */
struct    hi_comm_ctrl    hi_comm_ctrl;            /* High-level Comm. Control Block */

int  f_errno  ;            /* fcontrol lib 전용 Error 변수    */
int  f_recnum ;

void   trace_stop();            /* signal handler        */
int  trace_data();
int  trace_packet();

struct    {
    int    cmd;
    char    nam[50];
} kind_cmd[] = {
    /* TCS 차로 제어기 */
	{ AZN_RQ_SEQ_NO            , "전송연번요구"                 },
	{ AZN_SEQ_NO_DATA          , "전송연번 Data"                },
	{ AZN_COMM_CONTINUE_RQ     , "교신재개요구"                 },
	{ AZN_RQ_ACCUML_DATA       , "축적Data전송요구"             },
	{ AZN_ACCUML_DATA_OK       , "축적Data전송완료"             },
	{ AZN_CONFRM_REPLY         , "확인응답"                     },
	{ AZN_TM_RQ                , "시각요구"                     },
	{ AZN_TM_DATA              , "시각Data"                     },
	{ AZN_DAY_CHNG             , "일변경Mark Data"              },
	{ AZN_DAY_END              , "일마감Data"                   },
	{ AZN_TBL_CMD              , "Table 지령"                   },
	{ AZN_CMD_REPLY            , "지령응답"                     },
	{ AZN_TBL_ORDER            , "Table 요구"                   },
	{ AZN_TBL_DATA             , "Table Data"                   },
	{ AZN_WARR_SND_NO          , "보증전송연번"                 },
	{ AZN_LANE_STAT            , "차로 Status"                  },
	{ AZN_RPR_DATA             , "보수 Data"                    },
	{ AZN_CLOSE_LANE_PASS      , "폐쇄차로통행 Data"            },
	{ AZN_SENS_DATA            , "감지데이타"                   },
	{ AZN_WRK_STRT             , "근무개시보고"                 },
	{ AZN_CARD_DATA            , "카드처리(출구처리)Data"       },
	{ AZN_CAR_NO_DATA          , "처리차량번호데이터"           },
	{ AZN_ENT_DATA             , "입구처리Data"                 },
	{ AZN_ISS_INFO             , "발행정보 조회"                },
	{ AZN_ISS_INFO_RSPNS       , "발행정보 조회 결과"           },
	{ AZN_PERD_TAG_SALE        , "기간권 TAG 판매 등록 요청"    },
	{ AZN_PERD_TAG_SALE_RSPNS  , "기간권 TAG 판매 등록 응답"    },
	{ AZN_RGSTR_TAG_CHRG       , "기명권 TAG 충전 요청"         },
	{ AZN_RGSTR_TAG_CHRG_RSPNS , "기명권 TAG 충전 응답"         },
	{ AZN_PREV_TR_INFO         , "직전거래 내역 요청"           },
	{ AZN_PREV_TR_INFO_RSPNS   , "직전거래 내역 응답"           },
	{ AZN_TAG_CNCL_CHRG        , "기명권 직전 충전 취소 요청"   },
	{ AZN_TAG_CNCL_CHRG_RSPNS  , "기명권 직전 충전 취소 응답"   },
	{ AZN_OUT_WRK_END_DATA     , "근무종료(출구) Data"          },
	{ AZN_IN_WRK_END_DATA      , "근무종료(입구) Data"          },
	{ AZN_LANE_LINE_TEST       , "차로측기동 회선 Test Data"    },
	{ AZN_LANE_LINE_TEST_REPLY , "차로측기동 회선 Test 응답"    },
	{ AZN_PLZ_LINE_TEST        , "영업소측기동 회선 Test Data"  },
	{ AZN_PLZ_LINE_TEST_REPLY  , "영업소측기동 회선 Test 응답"  },
	{ AZN_REQ_TAG_INFO         , "TAG 정보 조회"                },
	{ AZN_REQ_TAG_INFO_REPLY   , "TAG 정보 조회 결과 응답"      },
	{ AZN_IN_WAY_SPCL_PRCS     , "입구 특별처리 Data"           },
	{ AZN_OFC_PRCS_DATA        , "사무실처리 Data"              },
	{ AZN_ETCS_VIO_PRCS_DATA   , "ETCS 출구위반 입구 수납"      },
	{ AZN_TBL_DUMP             , "Table Dump Data"              },
    { -1                       , ""                             }
};

char   trace_buf[4096];      /* trace buffer        */
int    trace_len;            /* tarce data length   */
int    trace_queue;          /* tracing queue id    */
int    trace_lane_no;        /* tracing crbh        */
int    short_form;           /* short form trace    */
FILE   *trace_log_file;      /* trace logging file  */
struct   trace_tag   *tff;   /* trace frame format  */
struct   msg_buf    *tmb;    /* trace tmb           */
struct   msqid_ds     md;

/*
 *========================================================================
 *
 *   함 수 명 : main
 *   작 성 자 : 오효섭 (catacath@nate.com)
 *   작 성 일 : 2012.10.08
 *   수 정 일 :
 *   설    명 : 하위차로 I/F 통신 TRACE 프로그램 MAIN PROCEDURE
 *
 *========================================================================
*/
int main(int argc, char *argv[])
{
    extern    int    optind,  opterr, optopt;
    extern    char    *optarg;
    int    options, plz_id, lane_no, high_level;
    int    len, ret;

    signal(SIGINT,  trace_stop);
    signal(SIGHUP,  trace_stop);
    signal(SIGTERM, trace_stop);

    lane_no = -1;
    plz_id = 0;
    high_level = 0;
    trace_log_file = NULL;
    short_form = 0;
    lane_typ = 0;

    opterr = 0;
    while((options = getopt(argc, argv, "l:f:t:hs")) != EOF)
    {
        switch (options)
        {
            case 't': /* 차로타입   */
                lane_typ = atoi(optarg);
 
              break;
            case 'p': /* 영업소번호 */
                plz_id = atoi(optarg);
                break;
            case 'l': /* 차로번호   */
                lane_no = atoi(optarg);
                break;
            case 'h': /* high level only */
                high_level = 1;
                break;
            case 'f': /* trace logging */
                trace_log_file = fopen(optarg, "w");
                break;
            case 's': /* short format */
                short_form = 1;
                break;
            default:
                break;
        }
    }

    ret = lb_user_chg();

    printf("USER CHG [%d]\n", ret);

    trace_queue = msgget(KQ_LCTR, IPC_CREAT | 0666);

    if (trace_queue < 0)
    {
        fprintf(stderr, "Can't creat trace queue....\n");
        exit(0);
    }

    msgctl(trace_queue, IPC_STAT, &md);
    md.msg_qbytes = (64 * 1024) - 1;
    msgctl(trace_queue, IPC_SET, &md);

    tmb = (struct msg_buf *)trace_buf;

    for (;;)
    {

        trace_len = msgrcv(trace_queue, tmb, sizeof(trace_buf)-16, 0, MSG_NOERROR);
        if (trace_len <= 0)
            break;
        if (lane_no != -1 && tmb->msg_type != lane_no)
            continue;

        trace_lane_no = tmb->msg_type;

        trace_lane_no = lane_no;

        tff = (struct trace_tag *)tmb->msg_text;

        if (high_level && tff->div == 1)
            continue;

        len = sizeof(struct trace_tag);
        trace_len -= len;

        switch (tff->div)
        {
            case 0:  /* high level trace */
                trace_data(&tmb->msg_text[len],trace_len);
                break;
            default: /* low level trace */
                trace_packet(&tmb->msg_text[len],trace_len);
                break;
        }
{
FILE *fp1;
char path[128];
memset(path,0x0,sizeof(path));
sprintf(path,"/tmp/trace.txt");
fp1 = fopen(path,"a+t");
fprintf(fp1,"plz_id[%d]lane_no %d -------------------------------------------\n", plz_id, lane_no);
fclose(fp1);
}
    }

    msgctl(trace_queue, IPC_RMID, &md);
    exit(0);
}

/*
 *========================================================================
 *
 *   함 수 명 : trace_stop
 *   작 성 자 : 오효섭 (catacath@nate.com)
 *   작 성 일 : 2012.10.08
 *   수 정 일 :
 *   설    명 : stop trace
 *
 *========================================================================
*/
void trace_stop(int signo)
{
    printf("%d\n", signo);
    if (trace_queue >= 0)
        msgctl(trace_queue, IPC_RMID, &md);

    exit(0);
}

/*
 *========================================================================
 *
 *   함 수 명 : trace_data
 *   작 성 자 : 오효섭 (catacath@nate.com)
 *   작 성 일 : 2012.10.08
 *   수 정 일 :
 *   설    명 : High Level Trace
 *
 *========================================================================
*/
int trace_data(uchar *buf, int len)
{
    struct    tm    *tm;
    struct    hi_packet_format    *hpf;
    int    i, j;

    tm = localtime(&tff->time);
    hpf = (struct hi_packet_format *)buf;
    for (i=0; kind_cmd[i].cmd != -1; i++)
    {
        if(lane_typ)
        {
            if (kind_cmd[i].cmd == hpf->kind) break;
        }
        else
        {
            if (kind_cmd[i].cmd == buf[2]) break;
        }
    }
    fprintf(stdout, "%02d  %02d:%02d:%02d %02X %-50s JB=%02X YB=%04X LN=%d\n",
             trace_lane_no, tm->tm_hour, tm->tm_min, tm->tm_sec,
             hpf->kind, kind_cmd[i].nam, hpf->kind, hpf->seq_no, len);

    if (trace_log_file != NULL)
    {
        fprintf(trace_log_file, "%02d  %02d:%02d:%02d %02X %-50s JB=%02X YB=%04X LN=%d\n",
             trace_lane_no, tm->tm_hour, tm->tm_min, tm->tm_sec,
             hpf->kind, kind_cmd[i].nam, hpf->kind, hpf->seq_no, len);
    }
    if (!short_form)
    {
        for (i=0, j=0; i<len; i++)
        {
            if (j==0)
            {
                fprintf(stdout, "    ");
                if (trace_log_file != NULL)
                    fprintf(trace_log_file, "    ");
            }
            else if (j%4==0)
            {
                fprintf(stdout, " ");
                if (trace_log_file != NULL)
                    fprintf(trace_log_file, " ");
            }

            fprintf(stdout, "%02X", buf[i]);

            if (trace_log_file != NULL)
                fprintf(trace_log_file, "%02X", buf[i]);
            j++;

            if (j>=32)
            {
                fprintf(stdout, "\n");
                if (trace_log_file != NULL)
                    fprintf(trace_log_file, "\n");
                j=0;
            }
        }

        fprintf(stdout, "\n");
        if (trace_log_file != NULL)
            fprintf(trace_log_file, "\n");
    }

    if (trace_log_file != NULL)
        fflush(trace_log_file);

    return (0);
}

/*
 *========================================================================
 *
 *   함 수 명 : trace_packet
 *   작 성 자 : 오효섭 (catacath@nate.com)
 *   작 성 일 : 2012.10.08
 *   수 정 일 :
 *   설    명 : Low Level Trace
 *
 *========================================================================
*/
int trace_packet(uchar *buf, int len)
{
    struct    tm    *tm;
    int    dln;

//    buf[5] = '\0';
    buf[len] = '\0';
    dln = atoi((char *)&buf[1]);
    tm = localtime(&tff->time);

    fprintf(stdout, "[%d]%02d  %02d:%02d:%02d ", dln, trace_lane_no, tm->tm_hour, tm->tm_min, tm->tm_sec);

    if (trace_log_file != NULL)
        fprintf(trace_log_file, "%02d  %02d:%02d:%02d ", trace_lane_no, tm->tm_hour, tm->tm_min, tm->tm_sec);

    fprintf(stdout, "\n");

    if (trace_log_file != NULL)
    {
        fprintf(trace_log_file, "\n");
        fflush(trace_log_file);
    }
    return (0);
}
#if 0
int cmp_seq_no(ushort jsyb1, ushort jsyb2)
{
}
#endif
