#include "v2g_context.h"

#define DEFAULT_TCP_PORT              61341

int v2g_tcp_server_init(v2g_context_t* v2g)
{
    if (v2g)
    {
        mlog_d(LOG_TAG_V2G, "Enter...\n");
        v2g->tcp_server_quit = 0;
        if (get_ipv6_address(v2g->if_name, &v2g->local_tcp_addr, NULL, 0) == 0)
        {
            v2g->local_tcp_addr.sin6_port = htons(DEFAULT_TCP_PORT);
            v2g->tcp_socket= create_listen_socket_bind_ipv6(&v2g->local_tcp_addr);
            mlog_d(LOG_TAG_V2G, "tcp_socket:%d\n", v2g->tcp_socket);
            mthread_init(&v2g->tcp_thread, v2g_tcp_server_loop, v2g);
             mlog_d(LOG_TAG_V2G, "LEAVE...\n");
            return 0;
        }
    }
    return -1;
}

void v2g_tcp_server_exit(v2g_context_t* v2g)
{
    if (v2g)
    {
        printd("step\n");
        if (v2g->tcp_server_quit == 0)
        {
            v2g->tcp_server_quit = 1;
            mthread_exit(&v2g->tcp_thread);
        }
        if (v2g->tcp_socket > 0)
        {
            close(v2g->tcp_socket);
            v2g->tcp_socket = -1;
            memset(&v2g->local_tcp_addr, 0, sizeof(struct sockaddr_in6));
        }
        if (v2g->next_client == &v2g->client[0])
        {
            v2g_connect_t* conn = (v2g_connect_t*)&v2g->client[0];
            v2g_tcp_client_exit(conn);
            v2g->next_client = NULL;
        }
    }
}

void* v2g_tcp_server_loop(void* args)
{
    v2g_context_t* v2g = (v2g_context_t*)args;
    while(v2g->tcp_server_quit == 0)
    {
        struct sockaddr_in6 addr;
        socklen_t addrlen = sizeof(addr);
        char client_addr[INET6_ADDRSTRLEN];
        if (v2g->next_client == NULL)
        {
            v2g_connect_t* conn = (v2g_connect_t*)&v2g->client[0];
            memset(conn, 0, sizeof(v2g_connect_t));
            printd("wait new connection.\n");
            conn->tcp_socket = accept(v2g->tcp_socket, (struct sockaddr*)&addr, &addrlen);
            if (conn->tcp_socket > 0)
            {
                const char* client_ip = inet_ntop(AF_INET6, &addr, client_addr, sizeof(client_addr));
                if (client_ip != NULL) {
                    mlog_d(LOG_TAG_V2G, "Incoming connection on %s from [%s]:%u", v2g->if_name, client_ip, ntohs(addr.sin6_port));
                } else {
                    mlog_e(LOG_TAG_V2G, "Incoming connection on %s, but inet_ntop failed: %s", v2g->if_name, strerror(errno));
                }
                v2g_tcp_client_init(conn, v2g);
                v2g->next_client = conn;
            }
        }else{
            sleep(1);
        }
    }
    return NULL;
}