diff --git a/src/session/CMakeLists.txt b/src/session/CMakeLists.txt index 48aae7e..cdecb25 100644 --- a/src/session/CMakeLists.txt +++ b/src/session/CMakeLists.txt @@ -7,11 +7,13 @@ add_library(session_manager session_address.cpp session_pool.cpp session_table.cpp - session_timer.cpp) + session_timer.cpp + session_manager.cpp) target_include_directories(session_manager PUBLIC ${CMAKE_SOURCE_DIR}/deps/uthash) target_include_directories(session_manager PUBLIC ${CMAKE_SOURCE_DIR}/deps/timeout) target_include_directories(session_manager PUBLIC ${CMAKE_SOURCE_DIR}/src/packet) target_include_directories(session_manager PUBLIC ${CMAKE_SOURCE_DIR}/src/session) +target_include_directories(session_manager PUBLIC ${CMAKE_SOURCE_DIR}/src/timestamp) target_link_libraries(session_manager timeout) ############################################################################### diff --git a/src/session/gtest_session_timer.cpp b/src/session/gtest_session_timer.cpp index 25acbc2..d0ac47b 100644 --- a/src/session/gtest_session_timer.cpp +++ b/src/session/gtest_session_timer.cpp @@ -3,7 +3,7 @@ #include "session_timer.h" #include "session_private.h" -static void session_expire(struct session *sess) +static void session_expire(struct session *sess, void *arg) { printf("=== session %lu expired ===\n", session_get_id(sess)); } @@ -16,7 +16,7 @@ TEST(SESSION_TIMER, ADD_DEL) session_init(&sess); session_set_id(&sess, 1); - session_set_expirecb(&sess, session_expire, 1000); + session_set_expirecb(&sess, session_expire, NULL, 1000); session_timer_add_session(timer, &sess); session_timer_del_session(timer, &sess); @@ -39,9 +39,9 @@ TEST(SESSION_TIMER, EXPIRE) session_set_id(&sess1, 1); session_set_id(&sess2, 2); session_set_id(&sess3, 3); - session_set_expirecb(&sess1, session_expire, 5); - session_set_expirecb(&sess2, session_expire, 5); - session_set_expirecb(&sess3, session_expire, 10); + session_set_expirecb(&sess1, session_expire, NULL, 5); + session_set_expirecb(&sess2, session_expire, NULL, 5); + session_set_expirecb(&sess3, session_expire, NULL, 10); session_timer_add_session(timer, &sess1); session_timer_add_session(timer, &sess2); @@ -78,9 +78,9 @@ TEST(SESSION_TIMER, BEFORE_EXPIRE_DEL) session_set_id(&sess1, 1); session_set_id(&sess2, 2); session_set_id(&sess3, 3); - session_set_expirecb(&sess1, session_expire, 5); - session_set_expirecb(&sess2, session_expire, 5); - session_set_expirecb(&sess3, session_expire, 10); + session_set_expirecb(&sess1, session_expire, NULL, 5); + session_set_expirecb(&sess2, session_expire, NULL, 5); + session_set_expirecb(&sess3, session_expire, NULL, 10); session_timer_add_session(timer, &sess1); session_timer_add_session(timer, &sess2); @@ -122,9 +122,9 @@ TEST(SESSION_TIMER, BEFORE_EXPIRE_UPDATE) session_set_id(&sess1, 1); session_set_id(&sess2, 2); session_set_id(&sess3, 3); - session_set_expirecb(&sess1, session_expire, 5); - session_set_expirecb(&sess2, session_expire, 5); - session_set_expirecb(&sess3, session_expire, 10); + session_set_expirecb(&sess1, session_expire, NULL, 5); + session_set_expirecb(&sess2, session_expire, NULL, 5); + session_set_expirecb(&sess3, session_expire, NULL, 10); session_timer_add_session(timer, &sess1); session_timer_add_session(timer, &sess2); @@ -137,7 +137,7 @@ TEST(SESSION_TIMER, BEFORE_EXPIRE_UPDATE) { printf("update timer 2\n"); session_timer_del_session(timer, &sess2); - session_set_expirecb(&sess2, session_expire, 8); + session_set_expirecb(&sess2, session_expire, NULL, 8); session_timer_add_session(timer, &sess2); } do diff --git a/src/session/session.cpp b/src/session/session.cpp index 6dcf6e3..882c43e 100644 --- a/src/session/session.cpp +++ b/src/session/session.cpp @@ -300,13 +300,15 @@ void session_free_ex_data(struct session *sess, uint8_t idx) ******************************************************************************/ // session expire -void session_set_expirecb(struct session *sess, session_expire_cb fn, uint64_t abs_expire_ts) +void session_set_expirecb(struct session *sess, session_expire_cb expire_cb, void *expire_arg, uint64_t expire_abs_ts) { struct timeout *timeout = &sess->timeout; timeout_init(timeout, TIMEOUT_ABS); - timeout_setcb(timeout, fn, sess); - sess->abs_expire_ts = abs_expire_ts; + timeout_setcb(timeout, NULL, sess); + sess->expire_cb = expire_cb; + sess->expire_arg = expire_arg; + sess->expire_abs_ts = expire_abs_ts; } void session_del_expirecb(struct session *sess) @@ -314,14 +316,15 @@ void session_del_expirecb(struct session *sess) struct timeout *timeout = &sess->timeout; timeout_init(timeout, 0); - sess->abs_expire_ts = 0; + sess->expire_cb = NULL; + sess->expire_arg = NULL; + sess->expire_abs_ts = 0; } void session_run_expirecb(struct session *sess) { - struct timeout *timeout = &sess->timeout; - if (timeout->callback.fn) + if (sess->expire_cb) { - timeout->callback.fn(timeout->callback.arg); + sess->expire_cb(sess, sess->expire_arg); } } \ No newline at end of file diff --git a/src/session/session.h b/src/session/session.h index cdb2c0c..5d8e912 100644 --- a/src/session/session.h +++ b/src/session/session.h @@ -132,10 +132,10 @@ void session_free_ex_data(struct session *sess, uint8_t idx); * session expire ******************************************************************************/ -typedef void (*session_expire_cb)(struct session *sess); +typedef void (*session_expire_cb)(struct session *sess, void *arg); // session timer -void session_set_expirecb(struct session *sess, session_expire_cb fn, uint64_t abs_timeout_ts); +void session_set_expirecb(struct session *sess, session_expire_cb expire_cb, void *expire_arg, uint64_t expire_abs_ts); void session_del_expirecb(struct session *sess); void session_run_expirecb(struct session *sess); diff --git a/src/session/session_manager.cpp b/src/session/session_manager.cpp new file mode 100644 index 0000000..67e1709 --- /dev/null +++ b/src/session/session_manager.cpp @@ -0,0 +1,252 @@ +#include +#include + +#include "timestamp.h" +#include "session_manager.h" +#include "session_pool.h" +#include "session_table.h" +#include "session_timer.h" +#include "session_private.h" + +struct session_manager +{ + struct session_pool *sess_pool; + struct session_table *sess_table; + struct session_timer *sess_timer; + + session_event_cb event_cb; + void *arg; + + struct session *queue_head_ptr; + struct session *queue_tail_ptr; +}; + +#define HANDSHAKE_TIMEOUT_MS (5 * 1000) +#define DATA_TIMEOUT_MS (60 * 1000) + +/****************************************************************************** + * private API + ******************************************************************************/ + +static void session_manager_handle_new_session(struct session_manager *mgr, struct session *sess, const struct packet *pkt, struct session_address *addr) +{ + // TODO +} + +static void session_manager_handle_old_session(struct session_manager *mgr, struct session *sess, const struct packet *pkt, struct session_address *addr) +{ + // TODO +} + +// Enqueue ready session to queue tail +static void session_manager_enqueue_ready_session(struct session_manager *mgr, struct session *sess) +{ + if (mgr == NULL || sess == NULL) + { + return; + } + + if (mgr->queue_head_ptr == NULL) + { + mgr->queue_head_ptr = sess; + mgr->queue_tail_ptr = sess; + sess->next_ready_ptr = NULL; + } + else + { + mgr->queue_tail_ptr->next_ready_ptr = sess; + mgr->queue_tail_ptr = sess; + sess->next_ready_ptr = NULL; + } +} + +// Dequeue ready session from queue head +struct session *session_manager_ready_session_dequeue(struct session_manager *mgr) +{ + if (mgr == NULL) + { + return NULL; + } + + struct session *sess = mgr->queue_head_ptr; + if (sess == NULL) + { + return NULL; + } + + if (mgr->queue_head_ptr == mgr->queue_tail_ptr) + { + mgr->queue_head_ptr = NULL; + mgr->queue_tail_ptr = NULL; + } + else + { + mgr->queue_head_ptr = sess->next_ready_ptr; + } + + sess->next_ready_ptr = NULL; + return sess; +} + +// handshake expire set to discard +static void handshake_expire_cb(struct session *sess, void *arg) +{ + struct session_manager *mgr = (struct session_manager *)arg; + assert(mgr != NULL); + + session_set_state(sess, SESSION_STATE_DISCARD); + session_push_event(sess, SESSION_EVENT_DISCARD); + session_manager_enqueue_ready_session(mgr, sess); +} + +// data expire set to closing +static void data_expire_cb(struct session *sess, void *arg) +{ + struct session_manager *mgr = (struct session_manager *)arg; + assert(mgr != NULL); + + session_set_state(sess, SESSION_STATE_CLOSING); + session_push_event(sess, SESSION_EVENT_CLOSING); + session_manager_enqueue_ready_session(mgr, sess); +} + +/****************************************************************************** + * public API + ******************************************************************************/ + +struct session_manager *session_manager_create(uint64_t max_session_num) +{ + struct session_manager *mgr = (struct session_manager *)calloc(1, sizeof(struct session_manager)); + if (mgr == NULL) + { + return NULL; + } + + mgr->sess_pool = session_pool_create(max_session_num); + if (mgr->sess_pool == NULL) + { + goto error; + } + + mgr->sess_table = session_table_create(); + if (mgr->sess_table == NULL) + { + goto error; + } + + mgr->sess_timer = session_timer_create(); + if (mgr->sess_timer == NULL) + { + goto error; + } + + mgr->queue_head_ptr = NULL; + mgr->queue_tail_ptr = NULL; + + return mgr; + +error: + session_manager_destroy(mgr); + return NULL; +} + +void session_manager_destroy(struct session_manager *mgr) +{ + if (mgr) + { + session_timer_destroy(mgr->sess_timer); + session_table_destroy(mgr->sess_table); + session_pool_destroy(mgr->sess_pool); + free(mgr); + mgr = NULL; + } +} + +void session_manager_set_session_eventcb(struct session_manager *mgr, session_event_cb cb, void *arg) +{ + mgr->event_cb = cb; + mgr->arg = arg; +} + +struct session *session_manager_find_session_by_id(struct session_manager *mgr, uint64_t id) +{ + struct session *sess = session_table_find_session_by_id(mgr->sess_table, id); + if (sess) + { + session_set_last_time(sess, timestamp_get_msec()); + // TODO + } + + return sess; +} + +struct session *session_manager_find_session_by_packet(struct session_manager *mgr, const struct packet *pkt) +{ + struct session_address addr; + session_address_init(&addr, pkt); + + struct session *sess = session_table_find_session_by_addr(mgr->sess_table, &addr); + if (sess == NULL) + { + if (session_pool_get_count(mgr->sess_pool) == 1) + { + struct session *oldest_sess = session_table_find_oldest_session(mgr->sess_table); + assert(oldest_sess == NULL); + session_set_state(oldest_sess, SESSION_STATE_DISCARD); + session_push_event(oldest_sess, SESSION_EVENT_DISCARD); + session_manager_enqueue_ready_session(mgr, oldest_sess); + } + + sess = session_pool_alloc(mgr->sess_pool); + assert(sess != NULL); + + session_manager_handle_new_session(mgr, sess, pkt, &addr); + } + else + { + session_manager_handle_old_session(mgr, sess, pkt, &addr); + } + + return sess; +} + +void session_manager_dispatch(struct session_manager *mgr) +{ + uint32_t event; + struct session *sess; + + void *cb_arg = mgr->arg; + session_event_cb event_cb = mgr->event_cb; + + while (1) + { + sess = session_timer_expire_session(mgr->sess_timer, timestamp_get_msec()); + if (sess == NULL) + { + break; + } + session_run_expirecb(sess); + } + + while (1) + { + sess = session_manager_ready_session_dequeue(mgr); + if (sess == NULL) + { + break; + } + + while (1) + { + if (session_pop_event(sess, &event) == false) + { + break; + } + + if (event_cb) + { + event_cb(sess, event, cb_arg); + } + } + }; +} diff --git a/src/session/session_manager.h b/src/session/session_manager.h new file mode 100644 index 0000000..c9c6b35 --- /dev/null +++ b/src/session/session_manager.h @@ -0,0 +1,36 @@ +#ifndef _SESSION_MANAGER_H +#define _SESSION_MANAGER_H + +#ifdef __cpluscplus +extern "C" +{ +#endif + +#include "session.h" + +/* + * session manager = session pool + session table + session timer + * + * session pool : alloc and free session + * session table : find session by session id or session addr + * session timer : session timeout + * session manager: manage session pool, session table and session timer + */ + +struct session_manager; +struct session_manager *session_manager_create(uint64_t max_session_num); +void session_manager_destroy(struct session_manager *mgr); + +typedef void (*session_event_cb)(struct session *sess, uint32_t event, void *arg); +void session_manager_set_session_eventcb(struct session_manager *mgr, session_event_cb cb, void *arg); + +struct session *session_manager_find_session_by_id(struct session_manager *mgr, uint64_t id); +struct session *session_manager_find_session_by_packet(struct session_manager *mgr, const struct packet *pkt); + +void session_manager_dispatch(struct session_manager *mgr); + +#ifdef __cpluscplus +} +#endif + +#endif diff --git a/src/session/session_private.h b/src/session/session_private.h index d478d83..3d8174e 100644 --- a/src/session/session_private.h +++ b/src/session/session_private.h @@ -10,18 +10,11 @@ extern "C" { #endif +#include "timeout.h" #include "uthash.h" #include "session.h" #include "session_address.h" -#define TIMEOUT_CB_OVERRIDE -struct timeout_cb -{ - session_expire_cb fn; - struct session *arg; -}; -#include "timeout.h" - #define EX_DATA_MAX_COUNT 128 #define SESSION_EVENT_QUEUE_SIZE 256 @@ -72,7 +65,9 @@ struct session // session timer struct timeout timeout; - uint64_t abs_expire_ts; + session_expire_cb expire_cb; + void *expire_arg; + uint64_t expire_abs_ts; /****************************** * Session Pool Zone diff --git a/src/session/session_timer.cpp b/src/session/session_timer.cpp index 4938894..1bb7f23 100644 --- a/src/session/session_timer.cpp +++ b/src/session/session_timer.cpp @@ -45,7 +45,7 @@ void session_timer_destroy(struct session_timer *timer) void session_timer_add_session(struct session_timer *timer, struct session *sess) { struct timeout *timeout = &sess->timeout; - timeouts_add(timer->timeouts, timeout, sess->abs_expire_ts); + timeouts_add(timer->timeouts, timeout, sess->expire_abs_ts); } void session_timer_del_session(struct session_timer *timer, struct session *sess)