#include #include "session_table.h" #include "log.h" struct session_table { struct session_node *root_by_id; struct session_node *root_by_addr; uint64_t session_node_count; }; // Note: session_addr must be initialized by memset(0) before use !!! struct session_table *session_table_create() { struct session_table *table = (struct session_table *)calloc(1, sizeof(struct session_table)); assert(table); table->session_node_count = 0; return table; } void session_table_destory(struct session_table *table) { if (table) { struct session_node *temp = NULL; struct session_node *node = NULL; HASH_ITER(hh1, table->root_by_id, node, temp) { HASH_DELETE(hh1, table->root_by_id, node); HASH_DELETE(hh2, table->root_by_addr, node); if (node->val_freecb && node->val_data) { node->val_freecb(node->val_data); } free(node); node = NULL; } free(table); table = NULL; } } uint64_t session_table_count(struct session_table *table) { if (table) { return table->session_node_count; } else { return 0; } } // session_addr : deep copy // val_data : shallow copy (malloc by user, free by val_freecb) int session_table_insert(struct session_table *table, uint64_t session_id, const struct addr_tuple4 *session_addr, void *val_data, const fn_free_cb *val_freecb) { struct session_node *temp = NULL; HASH_FIND(hh1, table->root_by_id, &session_id, sizeof(session_id), temp); if (temp) { LOG_DEBUG("session table insert: key %lu exists", session_id); return -1; } temp = (struct session_node *)calloc(1, sizeof(struct session_node)); assert(temp); temp->session_id = session_id; memcpy(&temp->session_addr, session_addr, sizeof(struct addr_tuple4)); temp->val_data = val_data; temp->val_freecb = val_freecb; HASH_ADD(hh1, table->root_by_id, session_id, sizeof(temp->session_id), temp); HASH_ADD(hh2, table->root_by_addr, session_addr, sizeof(temp->session_addr), temp); LOG_DEBUG("session table insert: key %lu success", session_id); table->session_node_count++; return 0; } int session_table_delete_by_id(struct session_table *table, uint64_t session_id) { struct session_node *temp = NULL; HASH_FIND(hh1, table->root_by_id, &session_id, sizeof(session_id), temp); if (!temp) { LOG_DEBUG("session table delete: key %lu not exists", session_id); return -1; } HASH_DELETE(hh1, table->root_by_id, temp); HASH_DELETE(hh2, table->root_by_addr, temp); if (temp->val_freecb && temp->val_data) { temp->val_freecb(temp->val_data); temp->val_data = NULL; } free(temp); temp = NULL; LOG_DEBUG("session table delete: key %lu success", session_id); table->session_node_count--; return 0; } int session_table_delete_by_addr(struct session_table *table, const struct addr_tuple4 *session_addr) { struct session_node *temp = NULL; char *addr_str = addr_tuple4_to_str(session_addr); HASH_FIND(hh2, table->root_by_addr, session_addr, sizeof(struct addr_tuple4), temp); if (!temp) { struct addr_tuple4 reverse_addr; addr_tuple4_reverse(session_addr, &reverse_addr); HASH_FIND(hh2, table->root_by_addr, &reverse_addr, sizeof(struct addr_tuple4), temp); if (!temp) { LOG_DEBUG("session table delete: key %s not exists", addr_str); free(addr_str); return -1; } } HASH_DELETE(hh1, table->root_by_id, temp); HASH_DELETE(hh2, table->root_by_addr, temp); if (temp->val_freecb && temp->val_data) { temp->val_freecb(temp->val_data); temp->val_data = NULL; } free(temp); temp = NULL; LOG_DEBUG("session table delete: key %s success", addr_str); free(addr_str); addr_str = NULL; table->session_node_count--; return 0; } struct session_node *session_table_search_by_id(struct session_table *table, uint64_t session_id) { struct session_node *temp = NULL; HASH_FIND(hh1, table->root_by_id, &session_id, sizeof(session_id), temp); if (!temp) { LOG_DEBUG("session table search: key %lu not exists", session_id); return NULL; } LOG_DEBUG("session table search: key %lu success", session_id); return temp; } struct session_node *session_table_search_by_addr(struct session_table *table, const struct addr_tuple4 *session_addr) { struct session_node *temp = NULL; char *addr_str = addr_tuple4_to_str(session_addr); HASH_FIND(hh2, table->root_by_addr, session_addr, sizeof(struct addr_tuple4), temp); if (!temp) { struct addr_tuple4 reverse_addr; addr_tuple4_reverse(session_addr, &reverse_addr); HASH_FIND(hh2, table->root_by_addr, &reverse_addr, sizeof(struct addr_tuple4), temp); if (!temp) { LOG_DEBUG("session table search: key %s not exists", addr_str); free(addr_str); addr_str = NULL; return NULL; } } LOG_DEBUG("session table search: key %s success", addr_str); free(addr_str); addr_str = NULL; return temp; }