#include "common.h"

sock_sess_node_t *find_session_by_socket(int socket)
{
    int hash = socket_hash(socket);
    sock_sess_node_t *sess = NULL;
    struct hlist_node *h1;

    pthread_rwlock_rdlock(&socket_mqtt_var.sock_sess_lock);
    hlist_for_each_entry_safe(sess, h1, &socket_mqtt_var.sock_sn_sess_table->sock_sess_hash[hash], sock_hash_list)
    {
        if (sess->socket == socket)
        {
            dy_syslog(LOG_INFO, "find a session for socket:%d, SN is:%s", socket, sess->sn);
            break;
        }
    }
    pthread_rwlock_unlock(&socket_mqtt_var.sock_sess_lock);
    return sess;
}

sock_sess_node_t *delete_session_by_socket(int socket)
{
    int hash = socket_hash(socket);
    sock_sess_node_t *sess = NULL;
    struct hlist_node *h1;
    char topic[TOPIC_MAX_LEN] = {0};

    pthread_rwlock_wrlock(&socket_mqtt_var.sock_sess_lock);
    hlist_for_each_entry_safe(sess, h1, &socket_mqtt_var.sock_sn_sess_table->sock_sess_hash[hash], sock_hash_list)
    {
        if (sess->socket == socket)
        {
            int hash_sn = hash_string(sess->sn);

            dy_syslog(LOG_INFO, "delete a session for socket:%d, SN is:%s", socket, sess->sn);
            sprintf(topic, "GW/%s/transparent", sess->sn);
            mqtt_session_unsubscribe(sess->mqtt, topic);
            hlist_del(&sess->sn_hash_list);
            hlist_del(&sess->sock_hash_list);
            free(sess);
            break;
        }
    }
    pthread_rwlock_unlock(&socket_mqtt_var.sock_sess_lock);
    return sess;
}

sock_sess_node_t *find_session_by_sn_nolock(const char *const sn)
{
    int hash = hash_string(sn);
    sock_sess_node_t *sess = NULL;
    struct hlist_node *h1;

    hlist_for_each_entry_safe(sess, h1, &socket_mqtt_var.sock_sn_sess_table->sn_sess_hash[hash], sn_hash_list)
    {
        if (strcmp(sess->sn, sn) == 0)
        {
            break;
        }
    }
    return sess;
}

sock_sess_node_t *find_session_by_sn(const char *const sn)
{
    int hash = hash_string(sn);
    sock_sess_node_t *sess = NULL;
    struct hlist_node *h1;

    pthread_rwlock_rdlock(&socket_mqtt_var.sock_sess_lock);
    hlist_for_each_entry_safe(sess, h1, &socket_mqtt_var.sock_sn_sess_table->sn_sess_hash[hash], sn_hash_list)
    {
        if (strcmp(sess->sn, sn) == 0)
        {
            break;
        }
    }
    pthread_rwlock_unlock(&socket_mqtt_var.sock_sess_lock);
    return sess;
}

int add_session_nolock(sock_sess_node_t *sess)
{
    int hash_sk = socket_hash(sess->socket);
    int hash_sn = hash_string(sess->sn);

    hlist_add_head(&sess->sn_hash_list, &socket_mqtt_var.sock_sn_sess_table->sn_sess_hash[hash_sn]);
    hlist_add_head(&sess->sock_hash_list, &socket_mqtt_var.sock_sn_sess_table->sock_sess_hash[hash_sk]);

    return 0;
}

int add_session(sock_sess_node_t *sess)
{
    int hash_sk = socket_hash(sess->socket);
    int hash_sn = hash_string(sess->sn);

    pthread_rwlock_wrlock(&socket_mqtt_var.sock_sess_lock);
    hlist_add_head(&sess->sn_hash_list, &socket_mqtt_var.sock_sn_sess_table->sn_sess_hash[hash_sn]);
    hlist_add_head(&sess->sock_hash_list, &socket_mqtt_var.sock_sn_sess_table->sock_sess_hash[hash_sk]);
    pthread_rwlock_unlock(&socket_mqtt_var.sock_sess_lock);

    return 0;
}

int del_session_nolock(sock_sess_node_t *sess)
{
    hlist_del(&sess->sn_hash_list);
    hlist_del(&sess->sock_hash_list);

    return 0;
}

int del_session(sock_sess_node_t *sess)
{
    pthread_rwlock_wrlock(&socket_mqtt_var.sock_sess_lock);
    hlist_del(&sess->sn_hash_list);
    hlist_del(&sess->sock_hash_list);
    pthread_rwlock_unlock(&socket_mqtt_var.sock_sess_lock);

    return 0;
}
