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

#define _MAIN_MODULE_
#define _THREAD_

#include <time.h>
#ifdef _THREAD_
#include <pthread.h>
#endif
#include "path_def.h"
#include "mmi_handler.h"
#include "lb_func_list.h"
#include "func_list.h"

#ifdef _THREAD_
pthread_mutex_t mutex_lock = PTHREAD_MUTEX_INITIALIZER;
#endif

static int sockfd;
/*
 *========================================================================
 *
 *   함 수 명 : server_close
 *   작 성 자 : 오효섭 (catacath@neighbor21.co.kr)
 *   작 성 일 : 2012.10.10
 *   수 정 일 :
 *   설    명 : 
 *
 *========================================================================
*/

void server_close(sig)
int sig;
{
    proc_log("eways_tcs_client_adapter process end (%d)\n",sig);  
    close(sockfd);
    exit(0);
}

/*
 *========================================================================
 *
 *   함 수 명 : SIG_Alarm
 *   작 성 자 : 오효섭 (catacath@neighbor21.co.kr)
 *   작 성 일 : 2012.10.10
 *   수 정 일 :
 *   설    명 : 
 *
 *========================================================================
*/

void SIG_Alarm(sig)
int sig;
{
    signal(SIGALRM,  SIG_Alarm); 
}

/*
 *========================================================================
 *
 *   함 수 명 : wait_loop
 *   작 성 자 : 오효섭 (catacath@neighbor21.co.kr)
 *   작 성 일 : 2012.10.10
 *   수 정 일 :
 *   설    명 : 
 *
 *========================================================================
*/

#ifdef _THREAD_
int wait_loop(void *data)
#else
int wait_loop(int sock_fd)
#endif
{
    char  msg[9999]; memset(msg, 0x00, sizeof(msg));
    int length, result;

#ifdef _THREAD_
    pthread_mutex_lock(&mutex_lock);
    int   sock_fd = *((int *)data);
#endif

    if(recv_msg(sock_fd, msg) < 0)      
    {
        send_reply(sock_fd, "000000", "000000", 0, 0, 1);
        return (-1);
    }

    packet_handler(sock_fd, msg);

    close(sock_fd);
#ifdef _THREAD_
    pthread_mutex_unlock(&mutex_lock);
#endif
    return 0;
}

/*
 *========================================================================
 *
 *   함 수 명 : wait_sock
 *   작 성 자 : 오효섭 (catacath@neighbor21.co.kr)
 *   작 성 일 : 2012.10.10
 *   수 정 일 :
 *   설    명 : initialize socket handling
 *
 *========================================================================
*/

int wait_sock(port)
int port;
{
    int        new_sock_fd, cli_len, child_pid;
    struct     sockaddr_in    cli_addr, serv_addr;
    static int opt=1;
#if 0
    struct linger solinger;
#endif
#ifdef _THREAD_
    pthread_t p_thread;
#endif
    if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
        perror("server: can't open stream socket");

    bzero((char *) &serv_addr, sizeof(serv_addr));
    serv_addr.sin_family      = AF_INET;
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    serv_addr.sin_port        = htons(port);
    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof (opt));

    while(1)
    if(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr))<0)
    {
        proc_log("port = %d\n",port);
        perror("server: can't bind local address");
        server_close(0);
//        sleep(3);
    }else break;

#if 0
// 해당 프로세스에서는 응답을 필히 받아야 하므로 사용에 부적합 하다.
        solinger.l_onoff = 1;
        solinger.l_linger  = 0;
        if (setsockopt(sockfd, SOL_SOCKET, SO_LINGER, &solinger, sizeof(struct linger)) == -1) {
            perror("setsockopt(SO_LINGER)");
        }
#endif

    listen(sockfd, 5);

    signalSet(server_close);
    signal(SIGCHLD,  SIG_IGN); 
    signal(SIGALRM,  SIG_Alarm); 

    while(1)
    {
        alarm(5);
        cli_len = sizeof(cli_addr);
        new_sock_fd = accept(sockfd, (struct sockaddr *) &cli_addr, &cli_len);
        alarm(0);
        if (new_sock_fd < 0) continue;

#ifdef _THREAD_
        pthread_mutex_init(&mutex_lock, NULL);

        child_pid = pthread_create(&p_thread, NULL, (void *)wait_loop, (void *)&new_sock_fd);
#if 0
        pthread_tryjoin_np
#endif
        if(!child_pid) pthread_detach(p_thread);
        proc_log("TRMN Connected Thread new_sock_fd =(%d)\n",new_sock_fd);
#else
        proc_log("TRMN Connected new_sock_fd =(%d)\n",new_sock_fd);

        child_pid = fork();
        if ( child_pid < 0)
        {
            perror("server: fork error");
            proc_log("child_pid = %d \n",child_pid);
            close(new_sock_fd);
            exit(0);
        }
        else if (child_pid == 0)
        {    /* child process */
            proc_log("TRMN Disconnected sockfd %d\n",sockfd);
            close(sockfd);           /* close original socket */

            wait_loop(new_sock_fd);

            proc_log("TRMN Disconnected new_sock_fd %d\n",new_sock_fd);
            shutdown (new_sock_fd, 2);
            close (new_sock_fd);
            exit(0);
        }
        close(new_sock_fd);        /* parent process */
#endif
    }
    return 0;
}

/*
 *========================================================================
 *
 *   함 수 명 : wait_sock
 *   작 성 자 : 오효섭 (catacath@neighbor21.co.kr)
 *   작 성 일 : 2012.10.10
 *   수 정 일 :
 *   설    명 : main loop and initialize some data
 *
 *========================================================================
*/

int main(argc, argv)
int argc;
char ** argv;
{
    int  port;

    if (argc==2) {
        if (!isdigit(*argv[1])) {
            fprintf(stderr,"Usage: %s [ port # ]\n",argv[0]);
            return(1);
        }
        else
        if ((port=atoi((char *)argv[1]))<=1024) {
            fprintf(stderr,"Error!! :: Illegal port number.\n");
            return(1);
        }
    }

    mkdir(LOG_DIR,0755);
    chdir(LOG_DIR);

    port=atoi(lb_get_inifile(INI_FILE, "MMI_PORT","MSG_PORT"));

    proc_log(" Running game on port %d.\n",port); 

    wait_sock(port);
    return 0;
}
