
#include "MessageSender.h"
#include "hi_ctrl.h"
#include "taglnk_frame.h"
#include "tagbl_struc.h"
#include <iconv.h>
#include "iss_comp.h"

char g_szProcessname[MAX_STRING_SIZE + 1];
char g_szProcessPath[PATH_MAX + 1];

extern int g_nResponseTimeout;
extern int cmd;
extern int type;
extern int job;
extern char szOrganizationID[6+1];
extern char szWorkType[4+1];
extern char szMsgType[4+1];

extern char szRespCode[] = "0000";
//char *szData;
char rcvData[MAX_STRING_SIZE + 1];
char szData[MAX_STRING_SIZE + 1];
char rtnData[MAX_STRING_SIZE + 1];

extern int g_nSerailNo = 1;
pthread_mutex_t g_sSerialMutex = PTHREAD_MUTEX_INITIALIZER;

static    struct    {
    int    cmd;                /* CONTROL COMMAND          */
    int    act;                /* 0:송신 1:응답 2:3자통신  */
    int    work;
    char  *cmd_nm;
} lane_act[] = {
    { NS_RPR_DATA              ,   0,    0 , " 0x76 보수데이터 "},
    { NS_CLOSE_PASS            ,   0,    5 , " 0x73 야간계수 데이터 "},
    { NS_WRK_START             ,   0,    0 , " 0x61 근무개시보고 "},
    { NS_HND_DATA              ,   0,    2 , " 0x17 처리 데이터 "},
    { NS_CRD_HND_DATA          ,   0,    3 , " 0x50 카드처리 데이터 "},
    { NS_WRK_END               ,   0,    4 , " 0x28 근무종료데이터 "},
    //{ NS_REMOTE_LANE_STAT_REPLY,   2,    0 , " 0xD4 원격차로상태응답 "},
    { NS_TBL_ORDER             ,   3,    0 , " 0x24 테이블요구(백그라운드용) "},
	{ NS_REFUND_DATA           ,   0,    2 , " 0x40 환불처리 데이터 "},
	{ NS_LANE_STAT             ,   1,    1 , " 0x75 차로상태(STATUS) "},
    { -1                       ,  -1,   -1 , "                         "}
};

static	struct {
	uchar plz_id[2];
	int lane_no;
	uchar anpr[10];
} anpr_id[20] = 
{
	{"01", 1, "A20201107"},
	{"01", 2, "A20201108"},
	{"01", 3, "A20201109"},
	{"01", 4, "A20211110"},
	{"01", 5, "A20201111"},
	{"01", 6, "A20211112"},
	{"01", 7, "A20201113"},
	{"01", 8, "A20211114"},
	{"03", 1, "A20203115"},
	{"03", 2, "A20213116"},
	{"03", 3, "A10103117"},
	{"03", 4, "A10103118"},
	{"03", 5, "CLOSE    "},
	{"03", 6, "CLOSE    "},
	{"03", 7, "A10103119"},
	{"03", 8, "A10103120"},
	{"03", 9, "A10103121"},
	{"03", 10, "A10103122"},
	{"00", -1, ""}
};

static struct {
	uchar plz_id[2];
	int   lane_no;
	int   tbl_order;
} lane_info[20] =
{
	{"01", 1, 0},
	{"01", 2, 0},
	{"01", 3, 0},
	{"01", 4, 0},
	{"01", 5, 0},
	{"01", 6, 0},
	{"01", 7, 0},
	{"01", 8, 0},
	{"03", 1, 0},
	{"03", 2, 0},
	{"03", 3, 0},
	{"03", 4, 0},
	{"03", 5, 0},
	{"03", 6, 0},
	{"03", 7, 0},
	{"03", 8, 0},
	{"03", 9, 0},
	{"03", 10, 0},
	{"00", -1, -1}
};

int MessageSender(int kind, char *packet, char *path, char *rtn)
{
    char szProcessname[PATH_MAX + 1];
    char *sDataMalloc;
	struct write_info wi;
    struct rcv_lane_data *rd;
    struct bl_struct *sd;
    int nResult;
    int i = 0;

    //DaemonStart();
/* //2019.07.04 InitMessageQueue에 포함
    nResult = SafeStrCopy(szProcessname, sizeof(szProcessname), path);

    if (nResult != SEC_ERR_SUCCESS)
    {
        printf("strcpy_s Error![%d]\n", nResult);
    }

    pFindPointer = szProcessname;
    nResult = SafeStrrChr(szProcessname, strnlen_s(szProcessname, sizeof(szProcessname)), PATH_SEPERATOR, &pFindPointer);

    if (pFindPointer == NULL)
    {
        nResult = SafeStrCopy(g_szProcessname, sizeof(g_szProcessname), szProcessname);
    }
    else
    {
        nResult = SafeStrCopy(g_szProcessname, sizeof(g_szProcessname), pFindPointer + 1);
    }

    GetExecPath(g_szProcessPath, sizeof(g_szProcessPath) - 1, path);

    if (g_szProcessPath == NULL)
    {
        printf("Can't get process path[Cann't load config file]!\nExit Program!");
        return -1;
    }
*/
lane_log("MessageSender Start\n");
/* // 2019.07.04 lane_main에서 1번만 실행하도록 수정
    nResult = InitMessageSenderConfig(path);

    if (nResult != MQ_ERR_SUCCESS)
    {
        printf("Program terminated!!!\n");
        return -1;
    }
*/
lane_log("---------------------------[%s]-----------------------\n", packet);
    WriteLog(LogType_SystemOut,LogLevel_Info, "Process Started![%s]", g_szProcessname);

    memset(szData, 0x00, sizeof(szData));
	memset(rcvData, 0x00, sizeof(rcvData));
	memset(rtnData, 0x00, sizeof(rtnData));
    sprintf(wi.plz_id, "%.2s", PLZ_CODE2);
    nResult = lb_freadx(&wi, FNO_BASICTBL, &hi_comm_ctrl.bas_tbl, FFIRST);

    if (nResult < 0){
        err_log("기초사항-F을 읽을 수 없습니다.", 1);
    }

    lane_log("plz_id[%.2s]\n", hi_comm_ctrl.bas_tbl.plz_id);
    while(1)
    {
        if(lane_act[i].cmd == kind || lane_act[i].cmd == -1) break;
        i++;
    }
    cmd = lane_act[i].cmd;
lane_log("lane_act[%d].cmd[%02x][%d]\n", i, lane_act[i].cmd, lane_act[i].act);
    snprintf(szOrganizationID, 6+1, "%06d", lb_data2atoi(hi_comm_ctrl.bas_tbl.plz_id, 2));
lane_log("Packet[%s]\n", packet);
    //sDataMalloc = szData;
    //szData = (char *)malloc(MAX_STRING_SIZE +1);
	//SafeMemoryAlloc((void **)&sDataMalloc, MAX_STRING_SIZE+ 1);
    if(lane_act[i].act == 3)
    {
		sd = (struct bl_struct *)packet;
		snprintf(szData, sizeof(struct bl_struct)+1, "%s", (char *)sd);
		snprintf(rcvData, sizeof(struct bl_struct)+1, "%s", (char *)sd);
		lane_log("3 szData[%.2s] [%.2s]\n", szData, sd->plz_id);
    }else if(lane_act[i].act == 1)
	{
		sprintf(szData, "%s", packet);
		sprintf(rcvData, "%s", packet);
		lane_log("1 szData[%s]\n", szData);
	}else{
        rd = (struct rcv_lane_data *)packet;
        snprintf(szData, sizeof(struct rcv_lane_data)+1, "%s", (char *)rd);
		snprintf(rcvData, sizeof(struct rcv_lane_data)+1, "%s", (char *)rd);
        lane_log("else szData[%.2s] [%.2s]\n", szData, rd->plz_id);
    }

    if(lane_act[i].act == 2)
        snprintf(szWorkType, 4+1, "%.4s", "9998");
    else if(lane_act[i].act == 1)
        snprintf(szWorkType, 4+1, "%04d", lane_act[i].work);
    else if(lane_act[i].act == 0)
        snprintf(szWorkType, 4+1, "%.4s", "9999");
    else if(lane_act[i].act == 3)
		snprintf(szWorkType, 4+1, "%.2s%.2s", sd->plz_id, sd->lane_no);
    else{
		//SafeFree((void **)&sDataMalloc);
		return -1;
	}
    type = lane_act[i].act;
    job = lane_act[i].work;
lane_log("szWorkType[%s] [%s]\n", szWorkType, lane_act[i].cmd_nm);
    snprintf(szMsgType       , 4+1, "%.4s", "0010");
lane_log("처리할 자료[%s]\n", szData);
    //2019.06.27 InitDoubleLinkedList Main 선언
    InitThread_Before();
lane_log("Queue 초기화\n");

//    if(type == 0)
        nResult = InitThread(ProcThread);
//    else
//        nResult = InitThreadWait(ProcThread);

lane_log("종료[%d]?[%s][%d]\n", type, rtnData, nResult);
    sprintf(rtn, "%s", rtnData);
	//SafeFree((void **)&sDataMalloc);
    //WriteLog(LogType_SystemOut,LogLevel_Info, "Process Stopped![%s]", g_szProcessname);

    return 0;
}

int InitMessageSenderConfig(char *path)
{
    char szConfigfilename[PATH_MAX + 1];
    char szConfigfilenameTemp[PATH_MAX + 1];
    char szValueTemp[MAX_STRING_SIZE + 1];
	char szProcessname[PATH_MAX + 1];
	char *pFindPointer;
    int nResult;

    nResult = SafeStrCopy(szProcessname, sizeof(szProcessname), path);

    if (nResult != SEC_ERR_SUCCESS)
    {
        printf("strcpy_s Error![%d]\n", nResult);
    }

    pFindPointer = szProcessname;
    nResult = SafeStrrChr(szProcessname, strnlen_s(szProcessname, sizeof(szProcessname)), PATH_SEPERATOR, &pFindPointer);

    if (pFindPointer == NULL)
    {
        nResult = SafeStrCopy(g_szProcessname, sizeof(g_szProcessname), szProcessname);
    }
    else
    {
        nResult = SafeStrCopy(g_szProcessname, sizeof(g_szProcessname), pFindPointer + 1);
    }

    GetExecPath(g_szProcessPath, sizeof(g_szProcessPath) - 1, path);

    if (g_szProcessPath == NULL)
    {
        printf("Can't get process path[Cann't load config file]!\nExit Program!");
        return -1;
    }

    snprintf(szConfigfilenameTemp, sizeof(szConfigfilenameTemp), "%s%c%s%c", g_szProcessPath, PATH_SEPERATOR, CONF_FILE_PATH, PATH_SEPERATOR);

    realpath(szConfigfilenameTemp, szConfigfilename);

    snprintf(szValueTemp, sizeof(szValueTemp), "%c", PATH_SEPERATOR);
    nResult = SafeStrCat(szConfigfilename, sizeof(szConfigfilename), szValueTemp, 1);
    nResult = SafeStrCat(szConfigfilename, sizeof(szConfigfilename), g_szProcessname, strnlen_s(g_szProcessname, sizeof(g_szProcessname)));
    nResult = SafeStrCat(szConfigfilename, sizeof(szConfigfilename), CONF_FILE_EXT, strnlen_s(CONF_FILE_EXT, sizeof(CONF_FILE_EXT)));

    printf("Process Name : %s\n", g_szProcessname);
    printf("Process Path : %s\n", g_szProcessPath);
    printf("Config Filename : %s[%d]\n", szConfigfilename, nResult);

    ReadConfigFile(true, szConfigfilename);

    // Read MS_RESPONSE_TIMEOUT_KEY
    if (GetConfigValue(MS_RESPONSE_TIMEOUT_KEY, szValueTemp, sizeof(szValueTemp)) != CONF_ERR_SUCCESS)
    {
        WriteLog(LogType_ErrorOut, LogLevel_Error, "Socket MS_RESPONSE_TIMEOUT_KEY configuration not found!");
        return SOCK_ERR_CONFIG;
    }

    if (SafeStringToInt(szValueTemp, sizeof(szValueTemp), &g_nResponseTimeout) != CONF_ERR_SUCCESS)
    {
        WriteLog(LogType_ErrorOut, LogLevel_Error, "Socket MS_RESPONSE_TIMEOUT_KEY configuration error[ConfigFile:%s]!", szValueTemp);
        return SOCK_ERR_CONFIG;
    }

    // Read CONNECTION_TYPE
    if (GetConfigValue(SOCK_CONF_CONN_TYPE_KEY, szValueTemp, sizeof(szValueTemp)) != CONF_ERR_SUCCESS)
    {
        WriteLog(LogType_ErrorOut, LogLevel_Error, "Socket CONNECTION_TYPE configuration not found[Available Value:Server or Client]!");
        return SOCK_ERR_CONFIG;
    }

    if (MappingStringToInt(szValueTemp, sizeof(szValueTemp), g_sConnTypeInfo, sizeof(g_sConnTypeInfo)/sizeof(struct VALUE_STRING_PAIR_INFO), &g_eConnectionType) != CONF_ERR_SUCCESS)
    {
        WriteLog(LogType_ErrorOut, LogLevel_Error, "Socket Connection Type configuration error[ConfigFile:%s,Available Value:Server or Client]!", szValueTemp);
        return SOCK_ERR_CONFIG;
    }

    if (InitLogConfig() != LOG_ERR_SUCCESS)
    {
        return MS_ERR_CONFIG;
    }

    if (InitSenderMQConfig() != MQ_ERR_SUCCESS)
    {
        return MS_ERR_CONFIG;
    }

    if (InitSender2MQConfig() != MQ_ERR_SUCCESS)
    {
        return MS_ERR_CONFIG;
    }

    if (InitThreadConfig() != THREAD_ERR_SUCCESS)
    {
        return MS_ERR_CONFIG;
    }

    return MS_ERR_SUCCESS;
}

void *ProcThread(void *pData)
{
    char cOccurType;
    struct THREAD_INFO *pThreadInfo;
    struct THREAD_INFO SendThreadInfo;
    char szMessageBuffer[MAX_STRING_SIZE + 1];
    struct MESSAGE_INFO sMessageInfo;
    struct MESSAGE_INFO sndMessageInfo;
    int nResult;
    int nRslt = 0;
    int *pnThreadExitCode;
	amqp_queue_purge_ok_t *pQueuePurgeResult;
    char szTopic[MAX_STRING_SIZE + 1];
    char szTargetTopic[MAX_STRING_SIZE + 1];
    char szReplyQueuename[MAX_STRING_SIZE + 1];
    char szReply2Queuename[MAX_STRING_SIZE + 1];
    char szExchangername[MAX_STRING_SIZE + 1];
    uuid_t sUUIDTemp;
    char szSendUUIDString[UUID_STRING_SIZE + 1];
    char szSend2UUIDString[UUID_STRING_SIZE + 1];
    char szRecvUUIDString[UUID_STRING_SIZE + 1];
    char szRecv2UUIDString[UUID_STRING_SIZE + 1];
	char orgCarNo[255+1];
	char szCarNo[255+1];
	char putCarNp[16];
	char nowTbl[2+1];
	
	char procData[MAX_STRING_SIZE + 1]; memset(procData, 0x00, sizeof(procData));
	char webData[MAX_STRING_SIZE + 1]; memset(webData, 0x00, sizeof(webData));
    int nMessageLength;
    //int nPacketLength;
    int nSerialNo;
    int nCompareResult, size, ii;

    //time_t sNow;
    struct tm tNow;
    int nMillisecond;

    //struct timespec sRecvTimeSpec;
    //time_t sRecvNow;
    struct tm tRecvNow;
    int nRecvMillisecond;

    struct timeval sResponseTimeout;

    uint64_t nDeliveryTag;

    int nDiffSec;
    int nDiffMilliSec;
    long nDiffTime;

    bool bMessageMatch;
    bool bTimeout;
	struct hi_lane_stat *hs;
	struct hi_wrk_end  *we;
	struct hi_wrk_start *ws;
	struct hi_crd_hnd_data  *crd;
	struct hi_hnd_data *hnd;
	size_t in_size;
	size_t out_size;
	size_t out_buf_left;
	char* in_buf;
	char* out_buf;
#if 1 //Web 송신 용 (2019/07.30)
	char in_id[4];
	char in_fare[2];
	char in_booth[2];
	char in_date[14];
	char in_st_date[14];
	char in_ed_date[14];
	char in_time[6];
	char d_seq[6];
	char in_seqno[8];
	char in_rf_seqno[8];
	char in_car[16];
	char in_card[16];
	char in_collect[2];
	char in_be_amount[8];
	char in_amount[8];
	char in_re_amount[8];
	char in_terminal_id[9];
	char in_sam_id[16];
	char in_sam_seqno[10];
	char in_card_seqno[10];
	char in_algorithm_id[2];
	char in_key_version[2];
	char in_e_cash[2];
	char in_sam_tot_seqno[10];
	char in_sam_collect_cnt[5];
	char in_sam_tot_amount[10];
	char in_sign_value[8];
	char in_person_code[2];
	char in_zipge_id[12];
	char in_alias_no[10];
	char in_issue_id[7];
	char tmp_chg[20];
	char tmp_iss_cd[6+1];
	char path[255];
	char in_x[3];
	char in_y[3];
	char in_garo[3];
	char in_sero[3];
	char in_card_ret;
	char in_rfid_kbn[2];
	char in_tag[48];
	char in_kind;
	char in_kbn;
	char c_id;
	char in_div;
	
    int  in_cash = 0;
    int  in_k_cash = 0;
    int  in_free = 0;
    int  in_minap = 0;
    int  in_coupon = 0;
    int  in_k_coupon = 0;
    int  in_sun = 0;
    int  in_k_sun = 0;
    int  in_who = 0;
    int  in_k_who = 0;
    int  in_sale = 0;
    int  in_k_sale = 0;
    int  in_total_amount = 0;
    int  in_repay_q = 0;
    int  in_repay_m = 0;
	int  in_prp_q = 0;
    int  in_prp_m = 0;
	int  in_k_prp_q = 0;
    int  in_k_prp_m = 0;
	int  tmp_tag = 0;
	
	struct stat file_info;
	struct iss_comp_tbl iss_comp_tbl_f;
	FILE *fp;
	
	char hnd_div[2];
	char hnd_div_nw[2];
	char tmp_terminal[10];
#endif
lane_log("##### Rcv Data[%s] ##### \n", rcvData);
    memcpy(procData, szData, sizeof(procData));

	iconv_t ic = iconv_open("UTF-8", "EUC-KR");
	
	if(ic == (iconv_t) -1)
	{
		lane_log("###### Not Supported ICONV Code ###### \n");
	}

	//memcpy(nowTbl, tbl_order, sizeof(nowTbl));
	memset(orgCarNo, 0x00, sizeof(orgCarNo));
	memset(szCarNo, 0x00, sizeof(szCarNo));

    pThreadInfo = (struct THREAD_INFO *)pData;
    SafeMemSet(&SendThreadInfo, sizeof(SendThreadInfo), 0, sizeof(SendThreadInfo));
    pthread_mutex_init(&SendThreadInfo.sContextMutex, NULL);
    pthread_mutex_init(&SendThreadInfo.sPublishMQ.sMQMutex, NULL);
    pthread_mutex_init(&SendThreadInfo.sConsumeMQ.sMQMutex, NULL);
    pnThreadExitCode = NULL;
    nResult = SafeMemoryAlloc((void **)&pnThreadExitCode, sizeof(int));
    SendThreadInfo.nThreadIndex = pThreadInfo->nThreadIndex;
    SendThreadInfo.bThreadLoop = true;
    //pnThreadExitCode = SafeAlloc(pnThreadExitCode, sizeof(int));
    *pnThreadExitCode = 0;
    //nSerialNo = 1;
    if (g_eConnectionType == SOCK_CONN_TYPE_SERVER)
    {
        cOccurType = 'S';
    }
    else
    {
        cOccurType = 'C';
    }
/*
    while (pThreadInfo->bThreadLoop)
    {
*/
        if (pThreadInfo->sPublishMQ.bMQConnection == false || pThreadInfo->sPublishMQ.bMQChannelOpen == false
            || pThreadInfo->sConsumeMQ.bMQConnection == false || pThreadInfo->sConsumeMQ.bMQChannelOpen == false)
        {
#if 1
            if (ConnectSenderMQ(pThreadInfo, true) != MQ_ERR_SUCCESS)
#else
            if(ConnectSenderMultiMQ(pThreadInfo, true, type, 0) != MQ_ERR_SUCCESS)
#endif
            {
                WriteLog(LogType_StandardOut, LogLevel_Debug, "[Thread:%02d]Connect SenderMQ is failed!", pThreadInfo->nThreadIndex);
#if 0
                continue;
#else
	            pThreadInfo->nRunState = SOCK_THREAD_STATE_TERMINATED;
			    pthread_mutex_destroy(&pThreadInfo->sContextMutex);
				pthread_mutex_destroy(&pThreadInfo->sPublishMQ.sMQMutex);
				pthread_mutex_destroy(&pThreadInfo->sConsumeMQ.sMQMutex);
				SafeFree((void **)&pThreadInfo);
				SafeFree((void **)&pnThreadExitCode);
                return -1;
#endif
            }
            
            //WriteLog(LogType_StandardOut, LogLevel_Debug, "[Thread:%02d]Connect SenderMQ is succeeded!!", pThreadInfo->nThreadIndex);
lane_log("Type [%d]\n", type);
#if 1
            switch(type)
            {
                case 0:
				case 2:
                    snprintf(szReplyQueuename, sizeof(szReplyQueuename), "%s%s.%02d", g_szMQMessageSendRespQueuename, szOrganizationID, pThreadInfo->nThreadIndex);
                    break;
                case 3:
                    snprintf(szReplyQueuename, sizeof(szReplyQueuename), "%s%s.%02d", g_szMQMessageSendHqctQueuename, szOrganizationID, pThreadInfo->nThreadIndex);
                    break;
                case 1:
				    snprintf(szReplyQueuename, sizeof(szReplyQueuename), "%s%s.%02d", g_szMQMessageSendRealQueuename, szOrganizationID, pThreadInfo->nThreadIndex);
				    //snprintf(szReplyQueuename, sizeof(szReplyQueuename), "%s%s.%02d", g_szMQMessageSendHqctQueuename, szOrganizationID, pThreadInfo->nThreadIndex);
                    break;
            }
#else
            snprintf(szReplyQueuename, sizeof(szReplyQueuename), "%s%s.%02d", g_szMQMessageSendRespQueuename, szOrganizationID, pThreadInfo->nThreadIndex);
#endif
        }

//lane_log("Reply Que 1 [%s]\n", szReplyQueuename);
//sleep(4);
        GetCurrTime(&tNow, &nMillisecond);
        nSerialNo = GetSerialNo();
//lane_log("Serial Que 2 [%d]\n", nSerialNo);
//sleep(4);
        snprintf(szMessageBuffer, sizeof(szMessageBuffer), "%s%c%s%s%08d%04d%02d%02d%02d%02d%02d%s%s", szOrganizationID, cOccurType, szWorkType,
                 szMsgType, nSerialNo++, tNow.tm_year + 1900, tNow.tm_mon + 1, tNow.tm_mday, tNow.tm_hour, tNow.tm_min, tNow.tm_sec, szRespCode, procData);
        //free(szData);
        nMessageLength = strnlen_s(szMessageBuffer, sizeof(szMessageBuffer));
        sMessageInfo.nMessageLength = nMessageLength;
        sMessageInfo.paMessageData = NULL;
//lane_log("Aloc Before\n");
//sleep(4);
        SafeMemoryAlloc((void **)&sMessageInfo.paMessageData, sMessageInfo.nMessageLength + 5);
//lane_log("Aloc After\n");
//sleep(4);
        snprintf(sMessageInfo.paMessageData, sMessageInfo.nMessageLength + 5, "%04X", sMessageInfo.nMessageLength);
        SafeStrCat(sMessageInfo.paMessageData + 4, sMessageInfo.nMessageLength + 1, szMessageBuffer, strnlen_s(szMessageBuffer, sizeof(szMessageBuffer)));
//lane_log("A1\n");
//sleep(4);
        snprintf(szTopic, sizeof(szTopic), "%s.%s%s", szOrganizationID, szWorkType, szMsgType);
#ifdef _WIN32
        uuid_generate(&sUUIDTemp);
        uuid_unparse(&sUUIDTemp, szSendUUIDString);
#else
//lane_log("A2\n");
//sleep(4);
        uuid_generate(sUUIDTemp);
//lane_log("A3\n");
//sleep(4);
        uuid_unparse(sUUIDTemp, szSendUUIDString);
#endif
lane_log("TEST 2 Exchange[%s]\n", g_szMQMessageSendExchangername);
lane_log("TEST 3 Topic[%s]\n", szTopic);
lane_log("TEST 4 Reply[%s][%d]\n", szReplyQueuename, pThreadInfo->sPublishMQ.bMQChannelOpen);
//sleep(4);
#if 1 // 백그라운드 전송 시, 언제나 최신을 처리하기 위한 기존 데이터 삭제(TEST 필)
//lane_log("Back Purge 0[%d][%s][%.2s]\n", type, nowTbl, procData+12);
		if(type == 3)
		{
			memset(in_fare, 0x00, sizeof(in_fare));
			memset(in_booth, 0x00, sizeof(in_booth));
			memset(tmp_chg, 0x00, sizeof(tmp_chg));

			memcpy(in_fare, procData, 2);
			memcpy(in_booth, procData+2, 2);
			memcpy(tmp_chg, procData+12, 2);
			for(ii = 0; ii < 20; ii++)
			{
				if(strncmp(lane_info[ii].plz_id, in_fare, 2) == 0 && lane_info[ii].lane_no == lb_data2atoi(in_booth, 2))
					break;
			}
		}

        //memcpy(nowTbl, lane_info[ii].tbl_order, sizeof(nowTbl));

        if(type == 3 && lane_info[ii].tbl_order == lb_data2atoi(tmp_chg, 2))
		{
			lane_log("Back Purge 1[%x]\n", pThreadInfo->sPublishMQ.sMQConnectionState);
            pQueuePurgeResult = amqp_queue_purge(pThreadInfo->sPublishMQ.sMQConnectionState, 1, amqp_cstring_bytes(g_szMQMessageSendHqctQueuename));
			lane_log("Back Purge 2[%x]\n", pThreadInfo->sPublishMQ.sMQConnectionState);
			//sleep(1);
		}else
			lane_info[ii].tbl_order = lb_data2atoi(tmp_chg, 2);
#endif
        nResult = PutMessageToQueue(pThreadInfo->sPublishMQ.sMQConnectionState, &pThreadInfo->sPublishMQ.bMQConnection, &pThreadInfo->sPublishMQ.bMQChannelOpen, pThreadInfo->nThreadIndex,
                                    g_szMQMessageSendExchangername, szReplyQueuename, szTopic, &sMessageInfo, sMessageInfo.paMessageData, sMessageInfo.nMessageLength,
                                    szSendUUIDString, sizeof(szSendUUIDString), false, NULL);
lane_log("Put After\n");
//sleep(2);
        lane_log("SendData[%d] : [Thread:%02d]%s\n", nResult, pThreadInfo->nThreadIndex, sMessageInfo.paMessageData);
        if (nResult != MS_ERR_SUCCESS)
        {
			lane_log("[Thread:%02d]MQ Data Publish Error[Data:%s]!", pThreadInfo->nThreadIndex, sMessageInfo.paMessageData);
            // 메시지 전송 오류인 경우 처리
            // 오류인 경우 오류 로그에 추가하는 형태의 샘플이지만 DB 처리라면 재전송 여부를 결정해서 재전송 몇번 이내면 재전송 하고 그렇지 않으면 실패 처리하는 로직이 필요하다.
            WriteLog(LogType_StandardOut, LogLevel_Info, "[Thread:%02d]MQ Data Publish Error[Data:%s]!", pThreadInfo->nThreadIndex, sMessageInfo.paMessageData);
        }
        else
        {
			//snprintf((char *)tbl_order, 2+1, "%.2s", szData+12);
            WriteQueueLog(LogType_MQOut, LogLevel_Info, pThreadInfo->nThreadIndex, 'P', g_szMQMessageSendExchangername, szTopic, szSendUUIDString, sMessageInfo.nMessageLength, "%s",
                          sMessageInfo.paMessageData);
			lane_log("[Thread:%02d]MQ Data Publish[Data:%s]!", pThreadInfo->nThreadIndex, sMessageInfo.paMessageData);
            WriteLog(LogType_StandardOut, LogLevel_Info, "[Thread:%02d]MQ Data Publish[Data:%s]!", pThreadInfo->nThreadIndex, sMessageInfo.paMessageData);
            bMessageMatch = false;
            bTimeout = false;
#if 1 //2019.06.28
            if(type == 0)
			{
//lane_log("Send type[%d] End Loot\n", type);
				CloseMQ(pThreadInfo->nThreadIndex, pThreadInfo->sPublishMQ.sMQConnectionState, &pThreadInfo->sPublishMQ.bMQConnection, &pThreadInfo->sPublishMQ.bMQChannelOpen, &pThreadInfo->sPublishMQ.sMQMutex);
				CloseMQ(pThreadInfo->nThreadIndex, pThreadInfo->sConsumeMQ.sMQConnectionState, &pThreadInfo->sConsumeMQ.bMQConnection, &pThreadInfo->sConsumeMQ.bMQChannelOpen, &pThreadInfo->sConsumeMQ.sMQMutex);
//sleep(2);
//lane_log("Send type[%d] End\n", type);
                pThreadInfo->nRunState = SOCK_THREAD_STATE_TERMINATED;
                pthread_mutex_destroy((char *)&pThreadInfo->sContextMutex);
                pthread_mutex_destroy((char *)&pThreadInfo->sPublishMQ.sMQMutex);
                pthread_mutex_destroy((char *)&pThreadInfo->sConsumeMQ.sMQMutex);
//lane_log("Mutex destroy[%d]\n", type);
//sleep(2);
				SafeFree((void **)&pThreadInfo);
				SafeFree((void **)&sMessageInfo.paMessageData);
				SafeFree((void **)&pnThreadExitCode);
//lane_log("SafeFree[%d]\n", type);
//sleep(2);
			    return(nResult);
			}
#endif
#if 0
sleep(2);
            if(type == 2 && nResult == MS_ERR_SUCCESS)
			{
				GetCurrTime(&tNow, &nMillisecond);
				if (SendThreadInfo.sPublishMQ.bMQConnection == false || SendThreadInfo.sPublishMQ.bMQChannelOpen == false
					|| SendThreadInfo.sConsumeMQ.bMQConnection == false || SendThreadInfo.sConsumeMQ.bMQChannelOpen == false)
				{
					if(ConnectSenderMQ(&SendThreadInfo, true) != MQ_ERR_SUCCESS)
					{
						WriteLog(LogType_StandardOut, LogLevel_Debug, "[Thread:%02d]Connect SenderMQ is failed!", SendThreadInfo.nThreadIndex);
						return pnThreadExitCode;
					}
					snprintf(szReply2Queuename, sizeof(szReply2Queuename), "%s%s.%02d", g_szMQMessageSendRealQueuename, szOrganizationID, SendThreadInfo.nThreadIndex);
				}

				switch(job)
				{
					case 2:
						hnd = 0x00;
						hnd = (char*)malloc(sizeof(struct hi_hnd_data)+1);
						memcpy(hnd, procData + 60, sizeof(struct hi_hnd_data));
					    sprintf(in_id, "%.4s", hnd->wrkr_no);
						sprintf(in_fare, "%.2s", procData+2);
						sprintf(in_booth, "%.2s", procData+19);
						sprintf(in_date, "%.8s%.2s%.2s%.2s", hnd->wrk_date, hnd->hnd_info.hnd_hour, hnd->hnd_info.hnd_min, hnd->hnd_info.hnd_sec);
                        sprintf(hnd_div, "%.2s", hnd->hnd_info.rcpt_hnd);
						memcpy(hnd_div_nw, hnd_div, 2);
						in_div = hnd->io_div;
						switch(lb_data2atoi(hnd_div_nw, 2))
						{
							case 10:
								sprintf(hnd_div, "10");
								break;
							case 11:
							case 12:
							case 13:
							case 14:
								sprintf(hnd_div, "11");
								break;
							case 20:
								sprintf(hnd_div, "20");
								break;
							case 21:
								sprintf(hnd_div, "21");
								break;
							case 22:
								sprintf(hnd_div, "22");
								break;
							case 23:
							case 25:
							case 27:
								sprintf(hnd_div, "23");
								break;
							case 24:
							case 26:
							case 28:
								sprintf(hnd_div, "24");
								break;
							case 30:
								sprintf(hnd_div, "30");
								break;
							case 31:
							case 35:
							case 36:
							case 37:
							case 38:
							case 39:
							case 70:
							case 75:
							case 76:
							case 77:
							case 78:
							case 79:
								sprintf(hnd_div, "34");
								break;
							case 32:
								sprintf(hnd_div, "32");
								break;
							case 33:
								sprintf(hnd_div, "33");
								break;
							case 34:
							case 65:
							case 67:
								sprintf(hnd_div, "30");
								break;
							case 71:
							case 74:
								sprintf(hnd_div, "31");
								break;
							case 40:
							case 41:
							case 60:
							case 61:
							case 62:
							case 63:
							case 64:
							case 66:
								sprintf(hnd_div, "40");
								break;
							case 50:
								sprintf(hnd_div, "50");
								break;
							case 51:
								sprintf(hnd_div, "51");
								break;
							case 52:
								sprintf(hnd_div, "52");
								break;
							case 53:
							case 55:
							case 56:
								sprintf(hnd_div, "53");
								break;
							case 54:
								sprintf(hnd_div, "54");
								break;
							default:
								sprintf(hnd_div, "00");
								break;
						}
						sprintf(d_seq, "%.6s", hnd->serial_no);
						sprintf(in_seqno, "%08d", lb_data2atoi(d_seq, 6));
						in_kind = hnd->car_kind;

						memcpy((char *)&in_rf_seqno, (char *)&in_seqno, 8);
#if 0
						sprintf(in_car, "%.16s", hnd->car_no1);
						if(strlen(in_car) == 0)
							sprintf(in_car, "????????????");
#else
                        sprintf(orgCarNo, "%.16s", hnd->car_no1);
lane_log("###### Send Original[%s]\n", orgCarNo);
                        if(strlen(orgCarNo) == 0)
							sprintf(in_car, "????????????");
						else
						{
							in_size = strlen(orgCarNo);
							out_size = sizeof(wchar_t) * in_size * 4;
						
							in_buf = orgCarNo;
							out_buf = szCarNo;
							out_buf_left = out_size;
						
							nResult = iconv(ic, (char *)&in_buf, &in_size, (char *)&out_buf, &out_buf_left);
							if(nResult == -1)
							{
								lane_log("ICONV FAILED [%d]\n", nResult);
							}

lane_log("ICONV in_size[%d] out_size[%d] [%s]\n", in_size, out_size - out_buf_left, szCarNo);

							sprintf(in_car, "%.16s", szCarNo);
						}
#endif
						sprintf(in_collect, "%.2s", hnd->hnd_info.rcpt_hnd);
						sprintf(in_amount, "%.6s", hnd->hnd_info.pass_fare);
						sprintf(in_x, "%.3s", hnd->x_point+1);
						sprintf(in_y, "%.3s", hnd->y_point+1);
						sprintf(in_garo, "%.3s", hnd->img_width+1);
						sprintf(in_sero, "%.3s", hnd->img_heigh+1);
						in_card_ret = hnd->hnd_info.refund_yn;
						c_id = hnd->wrk_no[3];
						switch(lb_data2atoi(hnd_div_nw, 2))
						{
							case 10:
							case 11:
							case 20:
							case 21:
							case 22:
							case 23:
							case 24:
							case 30:
							case 31:
							case 32:
							case 34:
							case 35:
							case 36:
							case 37:
							case 38:
							case 39:
							case 70:
							case 71:
							case 74:
							case 75:
							case 76:
							case 77:
							case 78:
							case 79:
							case 40:
							case 41:
							case 50:
							case 51:
							case 52:
							case 53:
							case 54:
							case 60:
							case 61:
							case 62:
							case 63:
							case 64:
							case 65:
							case 66:
							case 67:
								sprintf(in_rfid_kbn, "00");
								break;
							case 12:
							case 25:
							case 26:
							case 55:
								sprintf(in_rfid_kbn, "01");
								break;
							case 13:
							case 14:
							case 27:
							case 28:
							case 56:
								sprintf(in_rfid_kbn, "03");
								break;
							case 33:
								sprintf(in_rfid_kbn, "02");
								break;
							default:
								sprintf(in_rfid_kbn, "00");
								break;
						}
lane_log("6-1\n");
						//sprintf(in_tag, "%.24s%.24s", hnd->tag_id1, hnd->tag_id2);
lane_log("7\n");
						switch(lb_data2atoi(hnd_div_nw, 2))
						{
							case 31:
								in_kind = '6';
								break;
							case 36:
								in_kind = '7';
								break;
							default:
								in_kind = hnd->car_kind;
								break;
						}
lane_log("8\n");
                        memset(webData, 0x00, sizeof(webData));
						sprintf(webData, "%.4s%.2s%.2s%.14s%08d%08d%-16s%.2s000%.6s%.3s%.3s%.3s%.3s%c%c%.2s%048d%c%.2s%c",
										in_id, in_fare, in_booth, in_date, lb_data2atoi(in_seqno, 8), lb_data2atoi(in_seqno, 8), in_car, in_collect, in_amount, in_x, in_y,
										in_garo, in_sero, in_card_ret, c_id, in_rfid_kbn, tmp_tag, in_kind, hnd_div_nw, in_div);
						free(hnd);
lane_log("###### Send Web Data2[%s]\n", webData);
						break;
					case 3:
						crd = 0x00;
						crd = (char*)malloc(sizeof(struct hi_crd_hnd_data)+1);
						memcpy(crd, procData + 60, sizeof(struct hi_crd_hnd_data));
						sprintf(in_id, "%.4s", crd->wrkr_no);
						sprintf(in_fare, "%.2s", procData+2);
						sprintf(in_booth, "%.2s", procData+19);
						sprintf(in_date, "%.8s", crd->wrk_date);
						sprintf(in_time, "%.2s%.2s%.2s", crd->hnd_hour, crd->hnd_min, crd->hnd_sec);
						memset(tmp_chg, 0x00, sizeof(tmp_chg));
						sprintf(tmp_chg, "%.6s%c", crd->serial_no, '\0');
						sprintf(in_seqno, "%08d", lb_data2atoi(tmp_chg, 6));
						in_kbn = crd->pre_div;
						sprintf(in_card, "%.16s", crd->crd_no);
lane_log("CARD NO [%.16s]\n", in_card);
						sprintf(in_collect, "%.2s", crd->rcpt_div);
						memset(tmp_chg, 0x00, sizeof(tmp_chg));
						sprintf(tmp_chg, "%.8s%c", crd->bef_rcpt_balc, '\0');
						sprintf(in_be_amount, "%08d", lb_data2atoi(crd->bef_rcpt_balc, 8));
						memset(tmp_chg, 0x00, sizeof(tmp_chg));
						sprintf(tmp_chg, "%.6s%c", crd->rcpt_money, '\0');
						sprintf(in_amount, "%08d", lb_data2atoi(crd->rcpt_money, 6));
						memset(tmp_chg, 0x00, sizeof(tmp_chg));
						sprintf(tmp_chg, "%.8s%c", crd->aft_rcpt_balc, '\0');
						sprintf(in_re_amount, "%08d", lb_data2atoi(crd->aft_rcpt_balc, 8));
						memset(tmp_chg, 0x00, sizeof(tmp_chg));
						sprintf(tmp_chg, "%.10s%c", crd->terminal_no, '\0');
lane_log("TERMINAL[%.9s][%.9s]\n", tmp_chg, crd->terminal_no);
						sprintf(tmp_terminal, "%.10s", tmp_chg);
						memcpy((char *)&in_terminal_id, crd->terminal_no+1, 9);
lane_log("TERMINAL[%.9s][%.9s]\n", in_terminal_id, tmp_chg+1);
						sprintf(in_sam_id, "%.16s", crd->psam_id);
						memset(tmp_chg, 0x00, sizeof(tmp_chg));
						sprintf(tmp_chg, "%.8s%c", crd->deal_ser_no, '\0');
						sprintf(in_sam_seqno, "%010u", strtoul(tmp_chg, NULL, 16));
						sprintf(in_card_seqno, "%.10s", crd->crd_ser_no);
						memset(tmp_chg, 0x00, sizeof(tmp_chg));
						sprintf(tmp_chg, "%.2s%c", crd->alg_id, '\0');
						sprintf(in_algorithm_id, "%.2s", tmp_chg);
						memset(tmp_chg, 0x00, sizeof(tmp_chg));
						sprintf(tmp_chg, "%.2s%c", crd->ind_sign1, '\0');
						sprintf(in_key_version, "%.2s", tmp_chg);
						memset(tmp_chg, 0x00, sizeof(tmp_chg));
						sprintf(tmp_chg, "%.2s%c", crd->id_center, '\0');
						sprintf(in_e_cash, "%.2s", tmp_chg);

						memset(tmp_chg, 0x00, sizeof(tmp_chg));
						sprintf(tmp_chg, "%.8s%c", crd->rcpt_deal_ser, '\0');
						sprintf(in_sam_tot_seqno, "%010u", strtoul(tmp_chg, NULL, 16));
						memset(tmp_chg, 0x00, sizeof(tmp_chg));
						sprintf(tmp_chg, "%.4s%c", crd->ind_iss_cnt, '\0');
						sprintf(in_sam_collect_cnt, "%010u", strtoul(tmp_chg, NULL, 16));
						memset(tmp_chg, 0x00, sizeof(tmp_chg));
						sprintf(tmp_chg, "%.8s%c", crd->deal_tot, '\0');
						sprintf(in_sam_tot_amount, "%010u", strtoul(tmp_chg, NULL, 16));
						memset(tmp_chg, 0x00, sizeof(tmp_chg));
						sprintf(tmp_chg, "%.8s%c", crd->psam_sign1, '\0');
						sprintf(in_sign_value, "%.8s", tmp_chg);
lane_log("##########[%.2s][%.2s][%.2s][%.10s][%.10s][%.10s][%.8s]\n", in_algorithm_id, in_key_version, in_e_cash, in_sam_tot_seqno, in_sam_collect_cnt, in_sam_tot_amount, in_sign_value);
						sprintf(in_person_code, "%.2s", crd->another);
						sprintf(in_zipge_id, "9100000000%.2s", in_booth);

						sprintf(in_alias_no, "%.10s", crd->alias_no);
						sprintf(tmp_iss_cd, "%.6s%c", crd->crd_no, '\0');
						sprintf(path, "%s/%s/ISSTBL", DIR_TCS, DIR_BASEINFO);
						fp = fopen(path, "r+");
						if( 0 > stat(path, &file_info))
						{
							proc_log("발행사정보 없음\n");
						}else
						{
							size = file_info.st_size;
							for(ii = 0; ii < (size / sizeof(struct iss_comp_tbl)); ii++)
							{
								fseek(fp, ii * sizeof(struct iss_comp_tbl), SEEK_SET);
								fread(&iss_comp_tbl_f, sizeof(struct iss_comp_tbl), 1, fp);

								if(strncmp(iss_comp_tbl_f.bin_code+2, tmp_iss_cd, 6) == 0)
								break;
							}
						}

						memcpy((char *)&in_terminal_id, crd->terminal_no+1, 9);
lane_log("TERMINAL 2 [%.9s][%.9s]\n", in_terminal_id, crd->terminal_no+1);
						sprintf(in_issue_id, "%.7s", iss_comp_tbl_f.issue_cd);
						memset(webData, 0x00, sizeof(webData));
						sprintf(webData, "%.4s%.2s%.2s%.8s%.6s%.8s%c%.16s%.2s%.8s%.8s%.8s%.9s%.16s%.10s%.10s%.2s%.2s%.2s%.10s%.5s%.10s%.8s%.2s%.12s%.10s%.7s",
										in_id, in_fare, in_booth, in_date, in_time, in_seqno, in_kbn, in_card, in_collect, in_be_amount, in_amount, in_re_amount,
										in_terminal_id, in_sam_id, in_sam_seqno, in_card_seqno, in_algorithm_id, in_key_version, in_e_cash,
										in_sam_tot_seqno, in_sam_collect_cnt, in_sam_tot_amount, in_sign_value, in_person_code, in_zipge_id,
										in_alias_no, in_issue_id);

						free(crd);

lane_log("###### Send Web Data2[%s]\n", webData);
					break;
					case 4:
						if(cmd == NS_WRK_START)
						{
							ws = 0x00;
							ws = (char*)malloc(sizeof(struct hi_wrk_start)+1);
							memcpy(ws, procData + 60, sizeof(struct hi_wrk_start));
							
							sprintf(in_id, "%.4s", ws->wrk_no);
							sprintf(in_fare, "%.2s", procData+2);
							sprintf(in_booth, "%.2s", procData+19);
							sprintf(in_st_date, "%.4s%.2s%.2s%.2s%.2s%.2s",
												ws->wrk_start_year, ws->wrk_start_month, ws->wrk_start_day, ws->wrk_start_hour, ws->wrk_start_min, ws->wrk_start_sec);
							sprintf(in_ed_date, 0x30, sizeof(in_ed_date));
							in_cash = 0;
							in_k_cash = 0;
							in_free = 0;
							in_minap = 0;
							in_coupon = 0;
							in_k_coupon = 0;
							in_sun = 0;
							in_k_sun = 0;
							in_who = 0;
							in_k_who = 0;
							in_sale = 0;
							in_k_sale = 0;
							in_total_amount = 0;
							in_repay_q = 0;
							in_repay_m = 0;
							in_prp_q = 0;
							in_prp_m = 0;
							in_k_prp_q = 0;
							in_k_prp_m = 0;
							c_id = ws->wrk_no[3];
						}else
						{
							we = 0x00;
							we = (char*)malloc(sizeof(struct hi_wrk_end)+1);
							memcpy(we, procData + 60, sizeof(struct hi_wrk_end));
							sprintf(in_id, "%.4s", we->wrkr_no);
							sprintf(in_fare, "%.2s", procData+2);
							sprintf(in_booth, "%.2s", procData+19);
							sprintf(in_st_date, "%.4s%.2s%.2s%.2s%.2s%.2s",
												we->wrk_start_year, we->wrk_start_month, we->wrk_start_day, we->wrk_start_hour, we->wrk_start_min, we->wrk_start_sec);
							sprintf(in_ed_date, "%.4s%.2s%.2s%.2s%.2s%.2s",
												we->wrk_end_year, we->wrk_end_month, we->wrk_end_day, we->wrk_end_hour, we->wrk_end_min, we->wrk_end_sec);
	
							for(ii = 0; ii < 50; ii++)
							{
								memset(tmp_chg, 0x00, sizeof(tmp_chg));
								sprintf(tmp_chg, "%.2s%c", we->hnd_cnt[ii].div, '\0');
								switch(lb_data2atoi(tmp_chg, 2))
								{
									case 10:
										memset(tmp_chg, 0x00, sizeof(tmp_chg));
										sprintf(tmp_chg, "%.4s%c", we->hnd_cnt[ii].cnt, '\0');
										in_cash += lb_data2atoi(tmp_chg, 4);
										break;
									case 11:
									case 12:
									case 13:
									case 14:
										memset(tmp_chg, 0x00, sizeof(tmp_chg));
										sprintf(tmp_chg, "%.4s%c", we->hnd_cnt[ii].cnt, '\0');
										in_k_cash += lb_data2atoi(tmp_chg, 4);
										break;
									case 30:
									case 31:
									case 32:
									case 33:
									case 34:
									case 35:
									case 36:
									case 37:
									case 38:
									case 39:
									case 70:
									case 71:
									case 74:
									case 75:
									case 76:
									case 77:
									case 78:
									case 79:
										memset(tmp_chg, 0x00, sizeof(tmp_chg));
										sprintf(tmp_chg, "%.4s%c", we->hnd_cnt[ii].cnt, '\0');
										in_free += lb_data2atoi(tmp_chg, 4);
										break;
									case 40:
									case 41:
										memset(tmp_chg, 0x00, sizeof(tmp_chg));
										sprintf(tmp_chg, "%.4s%c", we->hnd_cnt[ii].cnt, '\0');
										in_minap += lb_data2atoi(tmp_chg, 4);
										break;
									case 60:
									case 61:
										memset(tmp_chg, 0x00, sizeof(tmp_chg));
										sprintf(tmp_chg, "%.4s%c", we->hnd_cnt[ii].cnt, '\0');
										in_prp_q += lb_data2atoi(tmp_chg, 4);
										memset(tmp_chg, 0x00, sizeof(tmp_chg));
										sprintf(tmp_chg, "%.8s%c", we->hnd_cnt[ii].fare, '\0');
										in_prp_m += lb_data2atoi(tmp_chg, 8);
										break;
									case 62:
									case 63:
									case 64:
									case 65: //사용 안함
									case 66: //사용 안함
									case 67: //사용 안함
										memset(tmp_chg, 0x00, sizeof(tmp_chg));
										sprintf(tmp_chg, "%.4s%c", we->hnd_cnt[ii].cnt, '\0');
										in_k_prp_q += lb_data2atoi(tmp_chg, 4);
										memset(tmp_chg, 0x00, sizeof(tmp_chg));
										sprintf(tmp_chg, "%.8s%c", we->hnd_cnt[ii].fare, '\0');
										in_k_prp_m += lb_data2atoi(tmp_chg, 8);
										break;
									case 51:
										memset(tmp_chg, 0x00, sizeof(tmp_chg));
										sprintf(tmp_chg, "%.4s%c", we->hnd_cnt[ii].cnt, '\0');
										in_coupon += lb_data2atoi(tmp_chg, 4);
										break;
									case 53:
									case 55:
									case 56:
										memset(tmp_chg, 0x00, sizeof(tmp_chg));
										sprintf(tmp_chg, "%.4s%c", we->hnd_cnt[ii].cnt, '\0');
										in_k_coupon += lb_data2atoi(tmp_chg, 4);
										break;
									case 21:
										memset(tmp_chg, 0x00, sizeof(tmp_chg));
										sprintf(tmp_chg, "%.4s%c", we->hnd_cnt[ii].cnt, '\0');
										in_sun += lb_data2atoi(tmp_chg, 4);
										break;
									case 23:
									case 25:
									case 27:
										memset(tmp_chg, 0x00, sizeof(tmp_chg));
										sprintf(tmp_chg, "%.4s%c", we->hnd_cnt[ii].cnt, '\0');
										in_k_sun += lb_data2atoi(tmp_chg, 4);
										break;
									case 22:
										memset(tmp_chg, 0x00, sizeof(tmp_chg));
										sprintf(tmp_chg, "%.4s%c", we->hnd_cnt[ii].cnt, '\0');
										in_who += lb_data2atoi(tmp_chg, 4);
										break;
									case 24:
									case 26:
									case 28:
										memset(tmp_chg, 0x00, sizeof(tmp_chg));
										sprintf(tmp_chg, "%.4s%c", we->hnd_cnt[ii].cnt, '\0');
										in_k_who += lb_data2atoi(tmp_chg, 4);
										break;
									case 52:
										memset(tmp_chg, 0x00, sizeof(tmp_chg));
										sprintf(tmp_chg, "%.4s%c", we->hnd_cnt[ii].cnt, '\0');
										in_sale += lb_data2atoi(tmp_chg, 4);
										break;
									case 54:
										memset(tmp_chg, 0x00, sizeof(tmp_chg));
										sprintf(tmp_chg, "%.4s%c", we->hnd_cnt[ii].cnt, '\0');
										in_k_sale += lb_data2atoi(tmp_chg, 4);
										break;
								}
							}
							memset(tmp_chg, 0x00, sizeof(tmp_chg));
							sprintf(tmp_chg, "%.8s%c", we->tot_fare, '\0');
							in_total_amount = lb_data2atoi(tmp_chg, 8);
							memset(tmp_chg, 0x00, sizeof(tmp_chg));
							sprintf(tmp_chg, "%.4s%c", we->repay_cnt, '\0');
							in_repay_q = lb_data2atoi(tmp_chg, 4);
							memset(tmp_chg, 0x00, sizeof(tmp_chg));
							sprintf(tmp_chg, "%.8s%c", we->repay_fare, '\0');
							in_repay_m = lb_data2atoi(tmp_chg, 8);
							c_id = we->wrk_no[3];
						}
						memset(webData, 0x00, sizeof(webData));
						sprintf(webData, "%.4s%.2s%.2s%.14s%.14s%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%08d%04d%08d%04d%08d%c",
										in_id, in_fare, in_booth, in_st_date, in_ed_date,
										in_cash, in_k_cash, in_free, in_minap, in_coupon, in_k_coupon,
										in_sun, in_k_sun, in_who, in_k_who, in_sale, in_k_sale,
										in_total_amount, in_repay_q, in_repay_m, in_prp_q, in_prp_m, in_k_prp_q, in_k_prp_m, c_id);

lane_log("###### Send Web Data2[%s]\n", webData);
					break;
					case 5:
						sprintf(in_fare, "%.2s", procData+101);
						sprintf(in_booth, "%.2s", procData+78);
						sprintf(in_date, "%.14s", procData+86);
						sprintf(d_seq, "%.6s", procData+80);
					    in_kind = procData[103];
						c_id = procData[100];
lane_log("###### Send Web Data1[%s]\n", procData);
#if 1 //ICONV 처리 (2019.07.29)
                        sprintf(orgCarNo, "%.16s", procData+105);
lane_log("###### Send Original[%s]\n", orgCarNo);
						if(strlen(orgCarNo) == 0)
							sprintf(putCarNp, "????????????");
						else
						{
							in_size = strlen(orgCarNo);
							out_size = sizeof(wchar_t) * in_size * 4;
						
							in_buf = orgCarNo;
							out_buf = szCarNo;
							out_buf_left = out_size;
						
							nResult = iconv(ic, (char *)&in_buf, &in_size, (char *)&out_buf, &out_buf_left);
							if(nResult == -1)
							{
								lane_log("ICONV FAILED [%d]\n", nResult);
							}

lane_log("ICONV in_size[%d] out_size[%d] [%s]\n", in_size, out_size - out_buf_left, szCarNo);
							sprintf(putCarNp, "%.16s", szCarNo);
						}
#endif
						memset(webData, 0x00, sizeof(webData));
						sprintf(webData, "%.2s%.2s%.14s%.6s%-16s%c%c",
										in_fare, in_booth, in_date, d_seq, putCarNp, in_kind, c_id);
lane_log("###### Send Web Data2[%s]\n", webData);
					break;
					default:
					break;
				}
				
				memset(szReply2Queuename, 0x00, sizeof(szReply2Queuename));
				snprintf(szReply2Queuename, sizeof(szReply2Queuename), "%s%s.%02d", g_szMQMessageSendRealQueuename, szOrganizationID, SendThreadInfo.nThreadIndex);
				memset(szWorkType, 0x00, sizeof(szWorkType));
				sprintf((char *)szWorkType, "%04d", job);
lane_log("###### Web Job[%s]\n", szWorkType);
				memset(szTopic, 0x00, sizeof(szTopic));
				snprintf(szTopic, sizeof(szTopic), "%s.%s%s", szOrganizationID, szWorkType, szMsgType);
lane_log("###### Web Topic[%s]\n", szTopic);
				memset(szMessageBuffer, 0x00, sizeof(szMessageBuffer));
				snprintf(szMessageBuffer, sizeof(szMessageBuffer), "%s%c%s%s%08d%04d%02d%02d%02d%02d%02d%s%s", szOrganizationID, cOccurType, szWorkType,
						szMsgType, nSerialNo++, tNow.tm_year + 1900, tNow.tm_mon + 1, tNow.tm_mday, tNow.tm_hour, tNow.tm_min, tNow.tm_sec, szRespCode, webData);
lane_log("###### Web Data[%s]\n", szMessageBuffer);
				nMessageLength = strnlen_s(szMessageBuffer, sizeof(szMessageBuffer));
                sndMessageInfo.nMessageLength = nMessageLength;
                sndMessageInfo.paMessageData = NULL;
                SafeMemoryAlloc((void **)&sndMessageInfo.paMessageData, sndMessageInfo.nMessageLength + 5);
                snprintf(sndMessageInfo.paMessageData, sndMessageInfo.nMessageLength + 5, "%04X", sndMessageInfo.nMessageLength);
                SafeStrCat(sndMessageInfo.paMessageData + 4, sndMessageInfo.nMessageLength + 1, szMessageBuffer, strnlen_s(szMessageBuffer, sizeof(szMessageBuffer)));
printf("#### SndMsg Que 3 [%s]\n", szMessageBuffer);
#ifdef _WIN32
                uuid_generate(&sUUIDTemp);
                uuid_unparse(&sUUIDTemp, szSend2UUIDString);
#else
                uuid_generate(sUUIDTemp);
                uuid_unparse(sUUIDTemp, szSend2UUIDString);
#endif
				nResult = PutMessageToQueue(SendThreadInfo.sPublishMQ.sMQConnectionState, &SendThreadInfo.sPublishMQ.bMQConnection, &SendThreadInfo.sPublishMQ.bMQChannelOpen,
											SendThreadInfo.nThreadIndex, g_szMQMessageSendExchangername, szReply2Queuename, szTopic, &sndMessageInfo, sndMessageInfo.paMessageData,
											sndMessageInfo.nMessageLength,
											szSend2UUIDString, sizeof(szSend2UUIDString), false, NULL);
lane_log("###### Web Service Call[%d]\n", nResult);

#if 1
				iconv_close(ic);
#endif
#if 1 //2019.07.29
				if(nResult == MS_ERR_SUCCESS)
				{
lane_log("Send type[%d] End Loot\n", type);
					CloseMQ(SendThreadInfo.nThreadIndex, SendThreadInfo.sPublishMQ.sMQConnectionState, &SendThreadInfo.sPublishMQ.bMQConnection, &SendThreadInfo.sPublishMQ.bMQChannelOpen, &SendThreadInfo.sPublishMQ.sMQMutex);
					CloseMQ(SendThreadInfo.nThreadIndex, SendThreadInfo.sConsumeMQ.sMQConnectionState, &SendThreadInfo.sConsumeMQ.bMQConnection, &SendThreadInfo.sConsumeMQ.bMQChannelOpen, &SendThreadInfo.sConsumeMQ.sMQMutex);
//sleep(2);
lane_log("Send type[%d] End\n", type);
					
					SendThreadInfo.nRunState = SOCK_THREAD_STATE_TERMINATED;
					pthread_mutex_destroy((char *)&SendThreadInfo.sContextMutex);
					pthread_mutex_destroy((char *)&SendThreadInfo.sPublishMQ.sMQMutex);
					pthread_mutex_destroy((char *)&SendThreadInfo.sConsumeMQ.sMQMutex);
lane_log("Mutex destroy\n", type);
//sleep(2);
					SafeFree((void **)&sndMessageInfo.paMessageData);
lane_log("SafeFree\n", type);
//sleep(2);
					//return(nResult);
				}else
				{
					//lane_log("[Thread:%02d]MQ Data Publish 2 Error[Data:%s]!", pThreadInfo->nThreadIndex, sMessageInfo.paMessageData);
					// 메시지 전송 오류인 경우 처리
					// 오류인 경우 오류 로그에 추가하는 형태의 샘플이지만 DB 처리라면 재전송 여부를 결정해서 재전송 몇번 이내면 재전송 하고 그렇지 않으면 실패 처리하는 로직이 필요하다.
					WriteLog(LogType_StandardOut, LogLevel_Info, "[Thread:%02d]MQ Data Publish 2 Error[Data:%s]!", SendThreadInfo.nThreadIndex, sndMessageInfo.paMessageData);
				}
#endif
			}
#endif
            if (g_bBypassMode)
            {
                do
                {
                    GetCurrTime(&tRecvNow, &nRecvMillisecond);
                    nDiffTime = TimeDiff(&tNow, nMillisecond, &tRecvNow, nRecvMillisecond);
                    nDiffSec = nDiffTime / 1000;
                    nDiffMilliSec = nDiffTime % 1000;

                    if (nDiffMilliSec < 0)
                    {
                        nDiffSec--;
                        nDiffMilliSec += 1000;
                    }

                    sResponseTimeout.tv_sec = g_nResponseTimeout / 1000 - nDiffSec;
                    sResponseTimeout.tv_usec = (g_nResponseTimeout % 1000 - nDiffMilliSec) * 1000;
                    if (sResponseTimeout.tv_usec < 0)
                    {
                        sResponseTimeout.tv_sec--;
                        sResponseTimeout.tv_usec += 1000000;
                    }
                    if (sResponseTimeout.tv_sec < 0 || sResponseTimeout.tv_usec < 0)
                    {
                        WriteLog(LogType_StandardOut, LogLevel_Info, "[Thread:%02d]Response Timeout! - UUID:%s, Message:%s, ProcessTime:%d.%03ds\n", pThreadInfo->nThreadIndex, szSendUUIDString,
                                                                      sMessageInfo.paMessageData, nDiffSec, nDiffMilliSec);
                        bTimeout = true;
                        break;
                    }

                    memset(rtnData, 0x00, sizeof(rtnData));
					memset(procData, 0x00, sizeof(procData));
                    nResult = GetMessageFromQueue(pThreadInfo->sConsumeMQ.sMQConnectionState, szExchangername, sizeof(szExchangername), szMessageBuffer, sizeof(szMessageBuffer),
                                                  szRecvUUIDString, sizeof(szRecvUUIDString), szReplyQueuename, sizeof(szReplyQueuename), &pThreadInfo->sConsumeMQ.bMQConnection,
                                                  &pThreadInfo->sConsumeMQ.bMQChannelOpen, &nDeliveryTag, &sResponseTimeout);
//lane_log("Get Msg[%s][%d]\n", szMessageBuffer, nResult);
                    snprintf(rtnData, strnlen_s(szMessageBuffer+45, sizeof(szMessageBuffer)-45)+1, "%s", szMessageBuffer+45);
lane_log("Rtn Data[%s]\n", rtnData);
                    GetCurrTime(&tRecvNow, &nRecvMillisecond);
                    nDiffTime = TimeDiff(&tNow, nMillisecond, &tRecvNow, nRecvMillisecond);
                    nDiffSec = nDiffTime / 1000;
                    nDiffMilliSec = nDiffTime % 1000;

                    if (nDiffMilliSec < 0)
                    {
                        nDiffSec--;
                        nDiffMilliSec += 1000;
                    }

                    if (nResult == MQ_ERR_TIMEOUT)
                    {
                        //printf("Response Timeout! - UUID:%s, Message:%s, ProcessTime:%d.%03ds\n", );
                        WriteLog(LogType_StandardOut, LogLevel_Info, "[Thread:%02d]Response Timeout! - UUID:%s, Message:%s, ProcessTime:%d.%03ds\n",
                                 pThreadInfo->nThreadIndex, szSendUUIDString, sMessageInfo.paMessageData, nDiffSec, nDiffMilliSec);
                        bTimeout = true;
                        break;
                    }
printf("TEST11[%d][%d][%s]\n", type, nResult, rtnData);

                    nResult = SafeStrCmp(szRecvUUIDString, sizeof(szRecvUUIDString), szSendUUIDString, &nCompareResult);
                    if (nCompareResult != 0)
                    {
                        WriteLog(LogType_StandardOut, LogLevel_Info, "[Thread:%02d]Recv UUID is not matched! - UUID:[Send:%s, Recv:%s], Message:%s, ProcessTime:%d.%03ds\n", pThreadInfo->nThreadIndex, szSendUUIDString, szRecvUUIDString, sMessageInfo.paMessageData, nDiffSec, nDiffMilliSec);
                        amqp_basic_ack(pThreadInfo->sConsumeMQ.sMQConnectionState, 1, nDeliveryTag, 0);
                        continue;
                    }
                    bMessageMatch = true;
                    nMessageLength = strnlen_s(szMessageBuffer, sizeof(szMessageBuffer));
                    amqp_basic_ack(pThreadInfo->sConsumeMQ.sMQConnectionState, 1, nDeliveryTag, 0);
                    WriteQueueLog(LogType_MQOut, LogLevel_Info, pThreadInfo->nThreadIndex, 'C', szReplyQueuename, "", szRecvUUIDString, nMessageLength, "%s", szMessageBuffer);
#if 0
                    WriteLog(LogType_StandardOut, LogLevel_Info, "[Thread:%02d]MQ Data Consume[Data:%s] - ProcessTime:%d.%03ds!", pThreadInfo->nThreadIndex, szMessageBuffer, nDiffSec, nDiffMilliSec);
#endif
                } while (bMessageMatch == false && bTimeout == false);
                if (!bTimeout)
                {
printf("센터 전송 옴[%d]?\n", type);
                    // 전송 완료 처리 필요
                }else
                {
                    memset(rtnData, 0x00, sizeof(rtnData));
                    snprintf(rtnData, sizeof(rtnData), "%02x0002", cmd);
                }
            }
        }
        //sleep(1); // test
/*
    }
*/
    CloseMQ(pThreadInfo->nThreadIndex, pThreadInfo->sPublishMQ.sMQConnectionState, &pThreadInfo->sPublishMQ.bMQConnection, &pThreadInfo->sPublishMQ.bMQChannelOpen, &pThreadInfo->sPublishMQ.sMQMutex);
    CloseMQ(pThreadInfo->nThreadIndex, pThreadInfo->sConsumeMQ.sMQConnectionState, &pThreadInfo->sConsumeMQ.bMQConnection, &pThreadInfo->sConsumeMQ.bMQChannelOpen, &pThreadInfo->sConsumeMQ.sMQMutex);
	pThreadInfo->nRunState = SOCK_THREAD_STATE_TERMINATED;
#if 1 //2019.07.12 메모리 증가로 Mutex Unlock 후 삭제 부분 추가
    pthread_mutex_destroy(&pThreadInfo->sContextMutex);
    pthread_mutex_destroy(&pThreadInfo->sPublishMQ.sMQMutex);
    pthread_mutex_destroy(&pThreadInfo->sConsumeMQ.sMQMutex);
#endif
    SafeFree((void **)&pThreadInfo);
    SafeFree((void **)&sMessageInfo.paMessageData);
    SafeFree((void **)&pnThreadExitCode);
    return 0;
}

int GetSerialNo()
{
    int nSerialNo;
    pthread_mutex_lock(&g_sSerialMutex);
    nSerialNo = g_nSerailNo++;
    pthread_mutex_unlock(&g_sSerialMutex);
    return nSerialNo;
}
