diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 1cb942f..92c7b18 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1,5 +1,5 @@ set(SOURCE stellar_config.cpp stellar_stat.cpp stellar_core.cpp) -set(LIBRARY session_manager plugin_manager ip_reassembly packet_io packet pthread fieldstat4 toml nmx_pool) +set(LIBRARY session_manager plugin_manager ip_reassembly packet_io snowflake packet pthread fieldstat4 toml nmx_pool) set(PLUGIN http glimpse_detector) diff --git a/src/core/stellar_config.h b/src/core/stellar_config.h index d4d622e..d1d5500 100644 --- a/src/core/stellar_config.h +++ b/src/core/stellar_config.h @@ -6,7 +6,6 @@ extern "C" #endif #include "packet_io.h" -#include "snowflake.h" #include "ip_reassembly.h" #include "session_manager.h" @@ -26,6 +25,12 @@ struct schedule_options uint64_t packet_io_yield_interval; // range: [1, 60000] (ms) }; +struct snowflake_options +{ + uint8_t snowflake_base; + uint8_t snowflake_offset; +}; + struct stellar_config { struct packet_io_options pkt_io_opts; diff --git a/src/core/stellar_core.cpp b/src/core/stellar_core.cpp index baac4e1..7f83d7d 100644 --- a/src/core/stellar_core.cpp +++ b/src/core/stellar_core.cpp @@ -59,6 +59,7 @@ struct stellar_thread uint16_t idx; uint64_t is_runing; struct schedule_data sched_data; + struct snowflake *snowflake; struct ip_reassembly *ip_mgr; struct session_manager *sess_mgr; struct stellar *st; @@ -84,7 +85,10 @@ struct stellar struct stellar_config config; }; -static thread_local uint16_t __thread_id = 0; // TODO +static thread_local uint16_t __current_thread_idx = UINT16_MAX; +static thread_local struct snowflake *__current_thread_snowflake = NULL; + +uint64_t stellar_generate_session_id(uint64_t now_sec); /****************************************************************************** * Stellar Thread Main Loop @@ -191,7 +195,9 @@ static void *work_thread(void *arg) struct packet_io *packet_io = runtime->packet_io; struct plugin_manager_schema *plug_mgr = runtime->plug_mgr; uint16_t thr_idx = thread->idx; - __thread_id = thr_idx; + + __current_thread_idx = thr_idx; + __current_thread_snowflake = thread->snowflake; memset(packets, 0, sizeof(packets)); @@ -407,12 +413,19 @@ static int stellar_thread_init(struct stellar *st) thread->sched_data.merge_stat_interval = config->sched_opts.merge_stat_interval; thread->sched_data.packet_io_yield_interval = config->sched_opts.packet_io_yield_interval; + thread->snowflake = snowflake_new(i, config->snowflake_opts.snowflake_base, config->snowflake_opts.snowflake_offset); + if (thread->snowflake == NULL) + { + STELLAR_LOG_ERROR("unable to create snowflake id generator"); + return -1; + } thread->sess_mgr = session_manager_new(&config->sess_mgr_opts, now_ms); if (thread->sess_mgr == NULL) { STELLAR_LOG_ERROR("unable to create session manager"); return -1; } + session_manager_set_session_id_generator(thread->sess_mgr, stellar_generate_session_id); thread->ip_mgr = ip_reassembly_new(&config->ip_reass_opts); if (thread->ip_mgr == NULL) { @@ -436,8 +449,9 @@ static void stellar_thread_clean(struct stellar *st) struct stellar_thread *thread = &runtime->threads[i]; if (ATOMIC_READ(&thread->is_runing) == 0) { - session_manager_free(thread->sess_mgr); ip_reassembly_free(thread->ip_mgr); + session_manager_free(thread->sess_mgr); + snowflake_free(thread->snowflake); } } STELLAR_LOG_FATAL("worker thread context cleaned"); @@ -526,12 +540,6 @@ struct stellar *stellar_new(const char *stellar_cfg_file, const char *plugin_cfg } stellar_config_print(config); - if (snowflake_id_init(&config->snowflake_opts) != 0) - { - STELLAR_LOG_ERROR("unable to init id generator"); - goto error_out; - } - runtime->stat = stellar_stat_new(config->pkt_io_opts.nr_threads); if (runtime->stat == NULL) { @@ -666,7 +674,30 @@ struct session_manager *stellar_get_session_manager(const struct stellar *st) uint16_t stellar_get_current_thread_index() { - return __thread_id; + if (__current_thread_idx == UINT16_MAX) + { + printf("get current thread index before set\n"); + abort(); + return UINT16_MAX; + } + else + { + return __current_thread_idx; + } +} + +uint64_t stellar_generate_session_id(uint64_t now_sec) +{ + if (__current_thread_snowflake == NULL) + { + printf("get current thread snowflake before set\n"); + abort(); + return 0; + } + else + { + return snowflake_generate(__current_thread_snowflake, now_sec); + } } // only send user crafted packet, can't send packet which come from network diff --git a/src/session/CMakeLists.txt b/src/session/CMakeLists.txt index 3f0f5db..e632679 100644 --- a/src/session/CMakeLists.txt +++ b/src/session/CMakeLists.txt @@ -8,9 +8,9 @@ add_library(session_manager session_transition.cpp ) target_include_directories(session_manager PUBLIC ${CMAKE_CURRENT_LIST_DIR}) -target_include_directories(session_manager PUBLIC ${CMAKE_SOURCE_DIR}/src/stellar) +target_include_directories(session_manager PUBLIC ${CMAKE_SOURCE_DIR}/src/core) target_include_directories(session_manager PUBLIC ${CMAKE_SOURCE_DIR}/include) target_include_directories(session_manager PUBLIC ${CMAKE_SOURCE_DIR}/src/utils) -target_link_libraries(session_manager timeout snowflake packet dablooms log tcp_reassembly) +target_link_libraries(session_manager timeout packet tcp_reassembly) add_subdirectory(test) \ No newline at end of file diff --git a/src/session/session_manager.cpp b/src/session/session_manager.cpp index 4fb4e86..a9cb5e1 100644 --- a/src/session/session_manager.cpp +++ b/src/session/session_manager.cpp @@ -6,7 +6,6 @@ #include "utils.h" #include "packet_helper.h" #include "packet_filter.h" -#include "snowflake.h" #include "session_private.h" #include "session_pool.h" #include "session_table.h" @@ -37,6 +36,7 @@ struct session_manager * because the function is called by pluin and has no time input. */ uint64_t now_ms; + session_id_generate_fn id_generator; }; #define EVICTE_SESSION_BURST (RX_BURST_MAX) @@ -535,7 +535,15 @@ static void session_update(struct session_manager *mgr, struct session *sess, en { if (session_get_current_state(sess) == SESSION_STATE_INIT) { - session_set_id(sess, snowflake_id_generate(mgr->now_ms / 1000)); + if (mgr->id_generator) + { + uint64_t sess_id = mgr->id_generator(mgr->now_ms / 1000); + session_set_id(sess, sess_id); + } + else + { + session_set_id(sess, 0); + } enum packet_direction pkt_dir = packet_get_direction(pkt); if (dir == FLOW_DIRECTION_C2S) { @@ -974,6 +982,11 @@ void session_manager_free(struct session_manager *mgr) } } +void session_manager_set_session_id_generator(struct session_manager *mgr, session_id_generate_fn generator) +{ + mgr->id_generator = generator; +} + void session_manager_record_duplicated_packet(struct session_manager *mgr, const struct packet *pkt) { if (mgr->opts.duplicated_packet_filter_enable) diff --git a/src/session/session_manager.h b/src/session/session_manager.h index 4e1d2be..a7ede4b 100644 --- a/src/session/session_manager.h +++ b/src/session/session_manager.h @@ -132,6 +132,9 @@ struct session_scan_opts struct session_manager; struct session_manager *session_manager_new(struct session_manager_options *opts, uint64_t now_ms); void session_manager_free(struct session_manager *mgr); + +typedef uint64_t (*session_id_generate_fn)(uint64_t now_ms); +void session_manager_set_session_id_generator(struct session_manager *mgr, session_id_generate_fn generator); void session_manager_record_duplicated_packet(struct session_manager *mgr, const struct packet *pkt); struct session *session_manager_new_session(struct session_manager *mgr, const struct packet *pkt, uint64_t now_ms); diff --git a/src/session/test/gtest_case_tcp_fast_open.cpp b/src/session/test/gtest_case_tcp_fast_open.cpp index 4216655..3680faa 100644 --- a/src/session/test/gtest_case_tcp_fast_open.cpp +++ b/src/session/test/gtest_case_tcp_fast_open.cpp @@ -3,10 +3,8 @@ #include "tuple.h" #include "packet_private.h" #include "packet_parser.h" -#include "snowflake.h" #include "session_private.h" #include "session_manager.h" -#include "tcp_reassembly.h" struct session_manager_options opts = { // max session number @@ -48,6 +46,12 @@ struct session_manager_options opts = { .tcp_reassembly_max_segments = 16, }; +static uint64_t session_id_generator(uint64_t now_ms __attribute__((unused))) +{ + static uint64_t count = 0; + return (++count); +} + /****************************************************************************** * case: TCP init -> opening (by TCP Fast Open) ******************************************************************************/ @@ -310,6 +314,7 @@ TEST(CASE, TCP_FAST_OPEN) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // C2S SYN Packet printf("\n=> Packet Parse: TCP C2S fast open packet\n"); @@ -420,11 +425,6 @@ TEST(CASE, TCP_FAST_OPEN) int main(int argc, char **argv) { - struct snowflake_options opt = { - .snowflake_base = 1, - .snowflake_offset = 2, - }; - snowflake_id_init(&opt); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); -} +} \ No newline at end of file diff --git a/src/session/test/gtest_filter_tcp_dupkt.cpp b/src/session/test/gtest_filter_tcp_dupkt.cpp index 1b5a8bd..93c3243 100644 --- a/src/session/test/gtest_filter_tcp_dupkt.cpp +++ b/src/session/test/gtest_filter_tcp_dupkt.cpp @@ -1,6 +1,5 @@ #include -#include "packet_helper.h" #include "packet_private.h" #include "packet_parser.h" #include "session_private.h" @@ -47,12 +46,18 @@ struct session_manager_options opts = { .tcp_reassembly_max_segments = 16, }; +static uint64_t session_id_generator(uint64_t now_ms __attribute__((unused))) +{ + static uint64_t count = 0; + return (++count); +} + static void packet_set_ip_id(struct packet *pkt, uint16_t ip_id) { const struct layer_private *ipv4_layer = packet_get_innermost_layer(pkt, LAYER_PROTO_IPV4); EXPECT_TRUE(ipv4_layer); struct ip *hdr = (struct ip *)ipv4_layer->hdr_ptr; - ip4_hdr_set_ipid(hdr, ip_id); + hdr->ip_id = htons(ip_id); } #if 1 @@ -65,6 +70,7 @@ TEST(TCP_DUPKT_FILTER_ENABLE, SYN_DUP) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // C2S SYN Packet printf("\n=> Packet Parse: TCP C2S SYN packet\n"); @@ -131,6 +137,7 @@ TEST(TCP_DUPKT_FILTER_ENABLE, SYNACK_DUP) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // S2C SYNACK Packet printf("\n=> Packet Parse: TCP S2C SYNACK packet\n"); @@ -198,6 +205,7 @@ TEST(TCP_DUPKT_FILTER_ENABLE, SKIP) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // C2S SYN Packet printf("\n=> Packet Parse: TCP C2S SYN packet\n"); @@ -284,6 +292,7 @@ TEST(TCP_DUPKT_FILTER_DISABLE, SYN_DUP) mgr = session_manager_new(&_opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // C2S SYN Packet printf("\n=> Packet Parse: TCP C2S SYN packet\n"); @@ -334,6 +343,7 @@ TEST(TCP_DUPKT_FILTER_DISABLE, SYNACK_DUP) mgr = session_manager_new(&_opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // S2C SYNACK Packet printf("\n=> Packet Parse: TCP S2C SYNACK packet\n"); @@ -375,4 +385,4 @@ int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); -} +} \ No newline at end of file diff --git a/src/session/test/gtest_overload_evict_tcp_sess.cpp b/src/session/test/gtest_overload_evict_tcp_sess.cpp index 632df10..a50d858 100644 --- a/src/session/test/gtest_overload_evict_tcp_sess.cpp +++ b/src/session/test/gtest_overload_evict_tcp_sess.cpp @@ -1,7 +1,6 @@ #include #include "utils.h" -#include "packet_helper.h" #include "packet_private.h" #include "packet_parser.h" #include "session_private.h" @@ -48,12 +47,18 @@ struct session_manager_options opts = { .tcp_reassembly_max_segments = 16, }; +static uint64_t session_id_generator(uint64_t now_ms __attribute__((unused))) +{ + static uint64_t count = 0; + return (++count); +} + static void packet_set_ip_src_addr(struct packet *pkt, uint32_t addr) { const struct layer_private *ipv4_layer = packet_get_innermost_layer(pkt, LAYER_PROTO_IPV4); EXPECT_TRUE(ipv4_layer); struct ip *hdr = (struct ip *)ipv4_layer->hdr_ptr; - ip4_hdr_set_src_addr(hdr, addr); + hdr->ip_src.s_addr = htonl(addr); } #if 1 @@ -65,6 +70,7 @@ TEST(TCP_OVERLOAD, EVICT_OLD_SESS) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // C2S SYN Packet printf("\n=> Packet Parse: TCP C2S SYN packet\n"); @@ -106,6 +112,7 @@ TEST(TCP_OVERLOAD, EVICT_NEW_SESS) mgr = session_manager_new(&_opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // C2S SYN Packet printf("\n=> Packet Parse: TCP C2S SYN packet\n"); diff --git a/src/session/test/gtest_overload_evict_udp_sess.cpp b/src/session/test/gtest_overload_evict_udp_sess.cpp index bdbd1bb..7137896 100644 --- a/src/session/test/gtest_overload_evict_udp_sess.cpp +++ b/src/session/test/gtest_overload_evict_udp_sess.cpp @@ -1,7 +1,6 @@ #include #include "utils.h" -#include "packet_helper.h" #include "packet_private.h" #include "packet_parser.h" #include "session_private.h" @@ -48,12 +47,18 @@ struct session_manager_options opts = { .tcp_reassembly_max_segments = 16, }; +static uint64_t session_id_generator(uint64_t now_ms __attribute__((unused))) +{ + static uint64_t count = 0; + return (++count); +} + static void packet_set_ip_src_addr(struct packet *pkt, uint32_t addr) { const struct layer_private *ipv4_layer = packet_get_innermost_layer(pkt, LAYER_PROTO_IPV4); EXPECT_TRUE(ipv4_layer); struct ip *hdr = (struct ip *)ipv4_layer->hdr_ptr; - ip4_hdr_set_src_addr(hdr, addr); + hdr->ip_src.s_addr = htonl(addr); } #if 1 @@ -66,6 +71,7 @@ TEST(UDP_OVERLOAD, EVICT_OLD_SESS) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // C2S REQ Packet printf("\n=> Packet Parse: UDP C2S REQ packet\n"); @@ -155,6 +161,7 @@ TEST(UDP_OVERLOAD, EVICT_NEW_SESS) mgr = session_manager_new(&_opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // C2S REQ Packet printf("\n=> Packet Parse: UDP C2S REQ packet\n"); diff --git a/src/session/test/gtest_sess_mgr_scan.cpp b/src/session/test/gtest_sess_mgr_scan.cpp index a8984af..708554c 100644 --- a/src/session/test/gtest_sess_mgr_scan.cpp +++ b/src/session/test/gtest_sess_mgr_scan.cpp @@ -1,6 +1,5 @@ #include -#include "snowflake.h" #include "session_private.h" #include "session_manager.h" #include "packet_private.h" @@ -47,6 +46,12 @@ struct session_manager_options opts = { .tcp_reassembly_max_segments = 16, }; +static uint64_t session_id_generator(uint64_t now_ms __attribute__((unused))) +{ + static uint64_t count = 0; + return (++count); +} + static inline void packet_overwrite_src_addr(struct packet *pkt, struct in_addr addr) { const struct layer_private *ipv4_layer = packet_get_innermost_layer(pkt, LAYER_PROTO_IPV4); @@ -128,6 +133,7 @@ TEST(SESS_MGR_SCAN, OPTS) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // new session memset(&pkt, 0, sizeof(pkt)); @@ -388,11 +394,6 @@ TEST(SESS_MGR_SCAN, OPTS) int main(int argc, char **argv) { - struct snowflake_options opt = { - .snowflake_base = 1, - .snowflake_offset = 2, - }; - snowflake_id_init(&opt); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } \ No newline at end of file diff --git a/src/session/test/gtest_sess_mgr_tcp_reassembly.cpp b/src/session/test/gtest_sess_mgr_tcp_reassembly.cpp index f92a6db..9e5d0da 100644 --- a/src/session/test/gtest_sess_mgr_tcp_reassembly.cpp +++ b/src/session/test/gtest_sess_mgr_tcp_reassembly.cpp @@ -1,11 +1,9 @@ #include -#include "packet_helper.h" #include "packet_private.h" #include "packet_parser.h" #include "session_private.h" #include "session_manager.h" -#include "tcp_reassembly.h" #include "test_packets.h" struct session_manager_options opts = { @@ -48,6 +46,12 @@ struct session_manager_options opts = { .tcp_reassembly_max_segments = 16, }; +static uint64_t session_id_generator(uint64_t now_ms __attribute__((unused))) +{ + static uint64_t count = 0; + return (++count); +} + static void hex_dump(const char *payload, uint32_t len) { printf("Payload Length: %u\n", len); @@ -72,6 +76,7 @@ TEST(SESS_MGR_TCP_REASSEMBLY, OUT_OF_ORDER) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // C2S SYN Packet printf("\n=> Packet Parse: TCP C2S SYN packet\n"); @@ -263,6 +268,7 @@ TEST(SESS_MGR_TCP_REASSEMBLY, SEQ_WRAPAROUND) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // C2S SYN Packet printf("\n=> Packet Parse: TCP C2S SYN packet\n"); @@ -350,4 +356,4 @@ int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); -} +} \ No newline at end of file diff --git a/src/session/test/gtest_state_tcp_active_to_closing.cpp b/src/session/test/gtest_state_tcp_active_to_closing.cpp index 219d6a5..5f79726 100644 --- a/src/session/test/gtest_state_tcp_active_to_closing.cpp +++ b/src/session/test/gtest_state_tcp_active_to_closing.cpp @@ -2,10 +2,8 @@ #include #include "tuple.h" -#include "packet_helper.h" #include "packet_private.h" #include "packet_parser.h" -#include "snowflake.h" #include "session_private.h" #include "session_manager.h" #include "test_packets.h" @@ -50,6 +48,12 @@ struct session_manager_options opts = { .tcp_reassembly_max_segments = 16, }; +static uint64_t session_id_generator(uint64_t now_ms __attribute__((unused))) +{ + static uint64_t count = 0; + return (++count); +} + static void build_active_tcp_session(struct session_manager *mgr, struct session *sess) { struct packet pkt; @@ -94,6 +98,7 @@ TEST(TCP_ACTIVE_TO_CLOSING, BY_FIN_FIN) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // C2S SYN Packet & C2S DATA Packet build_active_tcp_session(mgr, sess); @@ -185,6 +190,7 @@ TEST(TCP_ACTIVE_TO_CLOSING, BY_C2S_RST) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // C2S SYN Packet & C2S DATA Packet build_active_tcp_session(mgr, sess); @@ -198,8 +204,7 @@ TEST(TCP_ACTIVE_TO_CLOSING, BY_C2S_RST) const struct layer_private *tcp_layer = packet_get_innermost_layer(&pkt, LAYER_PROTO_TCP); EXPECT_TRUE(tcp_layer); struct tcphdr *hdr = (struct tcphdr *)tcp_layer->hdr_ptr; - tcp_hdr_set_flags(hdr, 0); - tcp_hdr_set_rst_flag(hdr, true); + hdr->th_flags = TH_RST; printf("<= Packet Parse: done\n\n"); // lookup session @@ -271,6 +276,7 @@ TEST(TCP_ACTIVE_TO_CLOSING, BY_S2C_RST) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // C2S SYN Packet & C2S DATA Packet build_active_tcp_session(mgr, sess); @@ -284,8 +290,7 @@ TEST(TCP_ACTIVE_TO_CLOSING, BY_S2C_RST) const struct layer_private *tcp_layer = packet_get_innermost_layer(&pkt, LAYER_PROTO_TCP); EXPECT_TRUE(tcp_layer); struct tcphdr *hdr = (struct tcphdr *)tcp_layer->hdr_ptr; - tcp_hdr_set_flags(hdr, 0); - tcp_hdr_set_rst_flag(hdr, true); + hdr->th_flags = TH_RST; printf("<= Packet Parse: done\n\n"); // lookup session @@ -355,6 +360,7 @@ TEST(TCP_ACTIVE_TO_CLOSING, BY_DATA_TIMEOUT) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // C2S SYN Packet & C2S DATA Packet build_active_tcp_session(mgr, sess); @@ -404,6 +410,7 @@ TEST(TCP_ACTIVE_TO_CLOSING, BY_C2S_HALF_CLOSED_TIMEOUT) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // C2S SYN Packet & C2S DATA Packet build_active_tcp_session(mgr, sess); @@ -483,6 +490,7 @@ TEST(TCP_ACTIVE_TO_CLOSING, BY_S2C_HALF_CLOSED_TIMEOUT) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // C2S SYN Packet & C2S DATA Packet build_active_tcp_session(mgr, sess); @@ -549,11 +557,6 @@ TEST(TCP_ACTIVE_TO_CLOSING, BY_S2C_HALF_CLOSED_TIMEOUT) int main(int argc, char **argv) { - struct snowflake_options opt = { - .snowflake_base = 1, - .snowflake_offset = 2, - }; - snowflake_id_init(&opt); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); -} +} \ No newline at end of file diff --git a/src/session/test/gtest_state_tcp_init_to_opening.cpp b/src/session/test/gtest_state_tcp_init_to_opening.cpp index 26fb4ca..30c07fc 100644 --- a/src/session/test/gtest_state_tcp_init_to_opening.cpp +++ b/src/session/test/gtest_state_tcp_init_to_opening.cpp @@ -2,10 +2,8 @@ #include #include "tuple.h" -#include "packet_helper.h" #include "packet_private.h" #include "packet_parser.h" -#include "snowflake.h" #include "session_private.h" #include "session_manager.h" #include "test_packets.h" @@ -50,6 +48,12 @@ struct session_manager_options opts = { .tcp_reassembly_max_segments = 16, }; +static uint64_t session_id_generator(uint64_t now_ms __attribute__((unused))) +{ + static uint64_t count = 0; + return (++count); +} + /****************************************************************************** * case: TCP init -> opening (by SYN) ******************************************************************************/ @@ -65,6 +69,7 @@ TEST(TCP_INIT_TO_OPENING, BY_SYN) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // C2S SYN Packet printf("\n=> Packet Parse: TCP C2S SYN packet\n"); @@ -142,6 +147,7 @@ TEST(TCP_INIT_TO_OPENING, BY_SYNACK) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // S2C SYNACK Packet printf("\n=> Packet Parse: TCP S2C SYNACK packet\n"); @@ -219,6 +225,7 @@ TEST(TCP_INIT_TO_OPENING, BY_SYN_SYNACK) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // C2S SYN Packet printf("\n=> Packet Parse: TCP C2S SYN packet\n"); @@ -308,6 +315,7 @@ TEST(TCP_INIT_TO_OPENING, BY_SYN_SYNACK_ACK) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // C2S SYN Packet printf("\n=> Packet Parse: TCP C2S SYN packet\n"); @@ -411,6 +419,7 @@ TEST(TCP_INIT_TO_OPENING, BY_SYN_RETRANSMISSION) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // C2S SYN Packet printf("\n=> Packet Parse: TCP C2S SYN packet\n"); @@ -432,7 +441,7 @@ TEST(TCP_INIT_TO_OPENING, BY_SYN_RETRANSMISSION) packet_parse(&pkt, (const char *)syn_retransmission, sizeof(tcp_pkt1_c2s_syn)); const struct layer_private *ipv4_layer = packet_get_innermost_layer(&pkt, LAYER_PROTO_IPV4); struct ip *hdr = (struct ip *)ipv4_layer->hdr_ptr; - ip4_hdr_set_ipid(hdr, 0x1234); + hdr->ip_id = htons(0x1234); printf("<= Packet Parse: done\n\n"); // lookup session @@ -507,6 +516,7 @@ TEST(TCP_INIT_TO_OPENING, BY_SYNACK_RETRANSMISSION) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // S2C SYNACK Packet printf("\n=> Packet Parse: TCP S2C SYNACK packet\n"); @@ -529,7 +539,7 @@ TEST(TCP_INIT_TO_OPENING, BY_SYNACK_RETRANSMISSION) const struct layer_private *ipv4_layer = packet_get_innermost_layer(&pkt, LAYER_PROTO_IPV4); EXPECT_TRUE(ipv4_layer); struct ip *hdr = (struct ip *)ipv4_layer->hdr_ptr; - ip4_hdr_set_ipid(hdr, 0x1234); + hdr->ip_id = htons(0x1234); printf("<= Packet Parse: done\n\n"); // lookup session @@ -602,6 +612,7 @@ TEST(TCP_INIT_TO_OPENING, BY_C2S_ASMMETRIC) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // C2S SYN Packet printf("\n=> Packet Parse: TCP C2S SYN packet\n"); @@ -691,6 +702,7 @@ TEST(TCP_INIT_TO_OPENING, BY_S2C_ASMMETRIC) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // S2C SYNACK Packet printf("\n=> Packet Parse: TCP S2C SYNACK packet\n"); @@ -767,11 +779,6 @@ TEST(TCP_INIT_TO_OPENING, BY_S2C_ASMMETRIC) int main(int argc, char **argv) { - struct snowflake_options opt = { - .snowflake_base = 1, - .snowflake_offset = 2, - }; - snowflake_id_init(&opt); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); -} +} \ No newline at end of file diff --git a/src/session/test/gtest_state_tcp_init_to_opening_to_active_to_closing_to_closed.cpp b/src/session/test/gtest_state_tcp_init_to_opening_to_active_to_closing_to_closed.cpp index 215cab9..98b4ea2 100644 --- a/src/session/test/gtest_state_tcp_init_to_opening_to_active_to_closing_to_closed.cpp +++ b/src/session/test/gtest_state_tcp_init_to_opening_to_active_to_closing_to_closed.cpp @@ -4,7 +4,6 @@ #include "tuple.h" #include "packet_private.h" #include "packet_parser.h" -#include "snowflake.h" #include "session_private.h" #include "session_manager.h" #include "test_packets.h" @@ -49,6 +48,12 @@ struct session_manager_options opts = { .tcp_reassembly_max_segments = 16, }; +static uint64_t session_id_generator(uint64_t now_ms __attribute__((unused))) +{ + static uint64_t count = 0; + return (++count); +} + #if 1 TEST(TCP_INIT_TO_OPENING_TO_ACTIVE_TO_CLOSING_TO_CLOSED, TEST) { @@ -60,6 +65,7 @@ TEST(TCP_INIT_TO_OPENING_TO_ACTIVE_TO_CLOSING_TO_CLOSED, TEST) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // C2S SYN Packet printf("\n=> Packet Parse: TCP C2S SYN packet\n"); @@ -433,11 +439,6 @@ TEST(TCP_INIT_TO_OPENING_TO_ACTIVE_TO_CLOSING_TO_CLOSED, TEST) int main(int argc, char **argv) { - struct snowflake_options opt = { - .snowflake_base = 1, - .snowflake_offset = 2, - }; - snowflake_id_init(&opt); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); -} +} \ No newline at end of file diff --git a/src/session/test/gtest_state_tcp_opening_to_active.cpp b/src/session/test/gtest_state_tcp_opening_to_active.cpp index f49916a..d0fb0aa 100644 --- a/src/session/test/gtest_state_tcp_opening_to_active.cpp +++ b/src/session/test/gtest_state_tcp_opening_to_active.cpp @@ -4,7 +4,6 @@ #include "tuple.h" #include "packet_private.h" #include "packet_parser.h" -#include "snowflake.h" #include "session_private.h" #include "session_manager.h" #include "test_packets.h" @@ -49,6 +48,12 @@ struct session_manager_options opts = { .tcp_reassembly_max_segments = 16, }; +static uint64_t session_id_generator(uint64_t now_ms __attribute__((unused))) +{ + static uint64_t count = 0; + return (++count); +} + /****************************************************************************** * case: TCP opening -> active (by C2S DATA) ******************************************************************************/ @@ -64,6 +69,7 @@ TEST(TCP_OPENING_TO_ACTIVE, BY_SYN_C2S_DATA) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // C2S SYN Packet printf("\n=> Packet Parse: TCP C2S SYN packet\n"); @@ -153,6 +159,7 @@ TEST(TCP_OPENING_TO_ACTIVE, BY_SYNACK_S2C_DATA) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // S2C SYNACK Packet printf("\n=> Packet Parse: TCP S2C SYNACK packet\n"); @@ -229,11 +236,6 @@ TEST(TCP_OPENING_TO_ACTIVE, BY_SYNACK_S2C_DATA) int main(int argc, char **argv) { - struct snowflake_options opt = { - .snowflake_base = 1, - .snowflake_offset = 2, - }; - snowflake_id_init(&opt); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); -} +} \ No newline at end of file diff --git a/src/session/test/gtest_state_tcp_opening_to_closing.cpp b/src/session/test/gtest_state_tcp_opening_to_closing.cpp index 83d5f81..e53630f 100644 --- a/src/session/test/gtest_state_tcp_opening_to_closing.cpp +++ b/src/session/test/gtest_state_tcp_opening_to_closing.cpp @@ -2,10 +2,8 @@ #include #include "tuple.h" -#include "packet_helper.h" #include "packet_private.h" #include "packet_parser.h" -#include "snowflake.h" #include "session_private.h" #include "session_manager.h" #include "test_packets.h" @@ -50,6 +48,12 @@ struct session_manager_options opts = { .tcp_reassembly_max_segments = 16, }; +static uint64_t session_id_generator(uint64_t now_ms __attribute__((unused))) +{ + static uint64_t count = 0; + return (++count); +} + /****************************************************************************** * case: TCP opening -> closing (by FIN-FIN) ******************************************************************************/ @@ -65,6 +69,7 @@ TEST(TCP_OPENING_TO_CLOSING, BY_FIN_FIN) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // C2S SYN Packet printf("\n=> Packet Parse: TCP C2S SYN packet\n"); @@ -165,6 +170,7 @@ TEST(TCP_OPENING_TO_CLOSING, BY_C2S_RST) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // C2S SYN Packet printf("\n=> Packet Parse: TCP C2S SYN packet\n"); @@ -187,8 +193,7 @@ TEST(TCP_OPENING_TO_CLOSING, BY_C2S_RST) const struct layer_private *tcp_layer = packet_get_innermost_layer(&pkt, LAYER_PROTO_TCP); EXPECT_TRUE(tcp_layer); struct tcphdr *hdr = (struct tcphdr *)tcp_layer->hdr_ptr; - tcp_hdr_set_flags(hdr, 0); - tcp_hdr_set_rst_flag(hdr, true); + hdr->th_flags = TH_RST; printf("<= Packet Parse: done\n\n"); // lookup session @@ -260,6 +265,7 @@ TEST(TCP_OPENING_TO_CLOSING, BY_S2C_RST) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // C2S SYN Packet printf("\n=> Packet Parse: TCP C2S SYN packet\n"); @@ -282,8 +288,7 @@ TEST(TCP_OPENING_TO_CLOSING, BY_S2C_RST) const struct layer_private *tcp_layer = packet_get_innermost_layer(&pkt, LAYER_PROTO_TCP); EXPECT_TRUE(tcp_layer); struct tcphdr *hdr = (struct tcphdr *)tcp_layer->hdr_ptr; - tcp_hdr_set_flags(hdr, 0); - tcp_hdr_set_rst_flag(hdr, true); + hdr->th_flags = TH_RST; printf("<= Packet Parse: done\n\n"); // lookup session @@ -354,6 +359,7 @@ TEST(TCP_OPENING_TO_CLOSING, BY_INIT_TIMEOUT) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // C2S SYN Packet printf("\n=> Packet Parse: TCP C2S SYN packet\n"); @@ -412,6 +418,7 @@ TEST(TCP_OPENING_TO_CLOSING, BY_HANDSHAKE_TIMEOUT) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // C2S SYN Packet printf("\n=> Packet Parse: TCP C2S SYN packet\n"); @@ -501,6 +508,7 @@ TEST(TCP_OPENING_TO_CLOSING, BY_DATA_TIMEOUT) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // C2S SYN Packet printf("\n=> Packet Parse: TCP C2S SYN packet\n"); @@ -602,6 +610,7 @@ TEST(TCP_OPENING_TO_CLOSING, BY_C2S_HALF_FIN) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // C2S SYN Packet printf("\n=> Packet Parse: TCP C2S SYN packet\n"); @@ -690,6 +699,7 @@ TEST(TCP_OPENING_TO_CLOSING, BY_S2C_HALF_FIN) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // C2S SYN Packet printf("\n=> Packet Parse: TCP C2S SYN packet\n"); @@ -765,11 +775,6 @@ TEST(TCP_OPENING_TO_CLOSING, BY_S2C_HALF_FIN) int main(int argc, char **argv) { - struct snowflake_options opt = { - .snowflake_base = 1, - .snowflake_offset = 2, - }; - snowflake_id_init(&opt); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); -} +} \ No newline at end of file diff --git a/src/session/test/gtest_state_udp_init_to_opening_to_active_to_closing.cpp b/src/session/test/gtest_state_udp_init_to_opening_to_active_to_closing.cpp index bc0ec50..90a01a0 100644 --- a/src/session/test/gtest_state_udp_init_to_opening_to_active_to_closing.cpp +++ b/src/session/test/gtest_state_udp_init_to_opening_to_active_to_closing.cpp @@ -4,7 +4,6 @@ #include "tuple.h" #include "packet_private.h" #include "packet_parser.h" -#include "snowflake.h" #include "session_private.h" #include "session_manager.h" #include "test_packets.h" @@ -49,6 +48,12 @@ struct session_manager_options opts = { .tcp_reassembly_max_segments = 16, }; +static uint64_t session_id_generator(uint64_t now_ms __attribute__((unused))) +{ + static uint64_t count = 0; + return (++count); +} + #if 1 TEST(UDP_INIT_TO_OPENING_TO_ACTIVE_TO_CLOSING, TEST) { @@ -60,6 +65,7 @@ TEST(UDP_INIT_TO_OPENING_TO_ACTIVE_TO_CLOSING, TEST) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // C2S REQ Packet printf("\n=> Packet Parse: UDP C2S REQ packet\n"); @@ -154,11 +160,6 @@ TEST(UDP_INIT_TO_OPENING_TO_ACTIVE_TO_CLOSING, TEST) int main(int argc, char **argv) { - struct snowflake_options opt = { - .snowflake_base = 1, - .snowflake_offset = 2, - }; - snowflake_id_init(&opt); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); -} +} \ No newline at end of file diff --git a/src/session/test/gtest_state_udp_init_to_opening_to_closing.cpp b/src/session/test/gtest_state_udp_init_to_opening_to_closing.cpp index f555137..bc59eb1 100644 --- a/src/session/test/gtest_state_udp_init_to_opening_to_closing.cpp +++ b/src/session/test/gtest_state_udp_init_to_opening_to_closing.cpp @@ -4,7 +4,6 @@ #include "tuple.h" #include "packet_private.h" #include "packet_parser.h" -#include "snowflake.h" #include "session_private.h" #include "session_manager.h" #include "test_packets.h" @@ -49,6 +48,12 @@ struct session_manager_options opts = { .tcp_reassembly_max_segments = 16, }; +static uint64_t session_id_generator(uint64_t now_ms __attribute__((unused))) +{ + static uint64_t count = 0; + return (++count); +} + /****************************************************************************** * case: UDP init -> opening (by C2S Packet) * case: UDP opening -> closing (by timeout) @@ -65,6 +70,7 @@ TEST(UDP_INIT_TO_OPENING_TO_CLOSING, BY_C2S) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // C2S REQ Packet printf("\n=> Packet Parse: UDP C2S REQ packet\n"); @@ -143,6 +149,7 @@ TEST(UDP_INIT_TO_OPENING_TO_CLOSING, BY_S2C) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // S2C RESP Packet printf("\n=> Packet Parse: UDP S2C RESP packet\n"); @@ -209,11 +216,6 @@ TEST(UDP_INIT_TO_OPENING_TO_CLOSING, BY_S2C) int main(int argc, char **argv) { - struct snowflake_options opt = { - .snowflake_base = 1, - .snowflake_offset = 2, - }; - snowflake_id_init(&opt); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); -} +} \ No newline at end of file diff --git a/src/session/test/gtest_timeout_tcp_data.cpp b/src/session/test/gtest_timeout_tcp_data.cpp index 6037517..47ff9cd 100644 --- a/src/session/test/gtest_timeout_tcp_data.cpp +++ b/src/session/test/gtest_timeout_tcp_data.cpp @@ -47,6 +47,12 @@ struct session_manager_options opts = { .tcp_reassembly_max_segments = 16, }; +static uint64_t session_id_generator(uint64_t now_ms __attribute__((unused))) +{ + static uint64_t count = 0; + return (++count); +} + #if 1 TEST(TIMEOUT, TCP_TIMEOUT_DATA) { @@ -56,6 +62,7 @@ TEST(TIMEOUT, TCP_TIMEOUT_DATA) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // C2S SYN Packet printf("\n=> Packet Parse: TCP C2S SYN packet\n"); diff --git a/src/session/test/gtest_timeout_tcp_handshake.cpp b/src/session/test/gtest_timeout_tcp_handshake.cpp index 638c53f..68d10f5 100644 --- a/src/session/test/gtest_timeout_tcp_handshake.cpp +++ b/src/session/test/gtest_timeout_tcp_handshake.cpp @@ -47,6 +47,12 @@ struct session_manager_options opts = { .tcp_reassembly_max_segments = 16, }; +static uint64_t session_id_generator(uint64_t now_ms __attribute__((unused))) +{ + static uint64_t count = 0; + return (++count); +} + #if 1 TEST(TIMEOUT, TCP_TIMEOUT_HANDSHAKE) { @@ -56,6 +62,7 @@ TEST(TIMEOUT, TCP_TIMEOUT_HANDSHAKE) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // S2C SYNACK Packet printf("\n=> Packet Parse: TCP S2C SYNACK packet\n"); diff --git a/src/session/test/gtest_timeout_tcp_init.cpp b/src/session/test/gtest_timeout_tcp_init.cpp index 6e12406..7d9e1bb 100644 --- a/src/session/test/gtest_timeout_tcp_init.cpp +++ b/src/session/test/gtest_timeout_tcp_init.cpp @@ -47,6 +47,12 @@ struct session_manager_options opts = { .tcp_reassembly_max_segments = 16, }; +static uint64_t session_id_generator(uint64_t now_ms __attribute__((unused))) +{ + static uint64_t count = 0; + return (++count); +} + #if 1 TEST(TIMEOUT, TCP_TIMEOUT_INIT) { @@ -56,6 +62,7 @@ TEST(TIMEOUT, TCP_TIMEOUT_INIT) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // C2S SYN Packet printf("\n=> Packet Parse: TCP C2S SYN packet\n"); diff --git a/src/session/test/gtest_timeout_udp_data.cpp b/src/session/test/gtest_timeout_udp_data.cpp index d815ffb..60bb133 100644 --- a/src/session/test/gtest_timeout_udp_data.cpp +++ b/src/session/test/gtest_timeout_udp_data.cpp @@ -47,6 +47,12 @@ struct session_manager_options opts = { .tcp_reassembly_max_segments = 16, }; +static uint64_t session_id_generator(uint64_t now_ms __attribute__((unused))) +{ + static uint64_t count = 0; + return (++count); +} + #if 1 TEST(TIMEOUT, UDP_TIMEOUT_DATA1) { @@ -56,6 +62,7 @@ TEST(TIMEOUT, UDP_TIMEOUT_DATA1) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // C2S REQ Packet printf("\n=> Packet Parse: UDP C2S REQ packet\n"); @@ -92,6 +99,7 @@ TEST(TIMEOUT, UDP_TIMEOUT_DATA2) mgr = session_manager_new(&opts, 1); EXPECT_TRUE(mgr != NULL); + session_manager_set_session_id_generator(mgr, session_id_generator); // C2S REQ Packet printf("\n=> Packet Parse: UDP C2S REQ packet\n"); diff --git a/src/snowflake/CMakeLists.txt b/src/snowflake/CMakeLists.txt index e68faa6..7ebc441 100644 --- a/src/snowflake/CMakeLists.txt +++ b/src/snowflake/CMakeLists.txt @@ -1,5 +1,5 @@ add_library(snowflake snowflake.cpp) target_include_directories(snowflake PUBLIC ${CMAKE_CURRENT_LIST_DIR}) -target_include_directories(snowflake PUBLIC ${CMAKE_SOURCE_DIR}/src/utils) -target_include_directories(snowflake PUBLIC ${CMAKE_SOURCE_DIR}/include/stellar) -target_link_libraries(snowflake core) \ No newline at end of file +target_link_libraries(snowflake log) + +add_subdirectory(test) \ No newline at end of file diff --git a/src/snowflake/snowflake.cpp b/src/snowflake/snowflake.cpp index bea562a..3c1133d 100644 --- a/src/snowflake/snowflake.cpp +++ b/src/snowflake/snowflake.cpp @@ -1,57 +1,61 @@ -#include -#include +#include +#include #include "log.h" -#include "utils.h" -#include "stellar.h" #include "snowflake.h" -#define snowflake_LOG_ERROR(format, ...) LOG_ERROR("snowflake", format, ##__VA_ARGS__) -#define snowflake_LOG_DEBUG(format, ...) LOG_DEBUG("snowflake", format, ##__VA_ARGS__) +#define SNOWFLAKE_LOG_ERROR(format, ...) LOG_ERROR("snowflake", format, ##__VA_ARGS__) struct snowflake { - uint8_t snowflake_base; // 5bit [0, 31] - uint8_t snowflake_offset; // 7bit [0, 127] - uint64_t device_id; // 12bit [0, 4095] ( base << 7 | offset ) - uint64_t thread[MAX_THREAD_NUM]; + uint8_t worker_base_id; // 5 bit [0, 31] + uint8_t worker_offset_id; // 7 bit [0, 127] + uint64_t thread_id; // limit 256 + uint64_t device_id; // 12 bit [0, 4095] ( base << 7 | offset ) + uint64_t sequence; }; -struct snowflake g_snowflake = {}; - -// return 0: success -// return -1: failed -int snowflake_id_init(const struct snowflake_options *opts) +struct snowflake *snowflake_new(uint16_t thread_id, uint8_t worker_base_id, uint8_t worker_offset_id) { - memset(&g_snowflake, 0, sizeof(struct snowflake)); - - if (opts == NULL) + if (thread_id > 255) { - snowflake_LOG_ERROR("opts is NULL"); - return -1; + SNOWFLAKE_LOG_ERROR("thread_id %u is invalid, range [0, 255]", thread_id); + return NULL; + } + if (worker_base_id > 31) + { + SNOWFLAKE_LOG_ERROR("worker_base_id %u is invalid, range [0, 31]", worker_base_id); + return NULL; + } + if (worker_offset_id > 127) + { + SNOWFLAKE_LOG_ERROR("worker_offset_id %u is invalid, range [0, 127]", worker_offset_id); + return NULL; } - if (opts->snowflake_base > 31) + struct snowflake *sf = (struct snowflake *)calloc(1, sizeof(struct snowflake)); + if (sf == NULL) { - snowflake_LOG_ERROR("snowflake_base %u is invalid, range [0, 31]", opts->snowflake_base); - return -1; + SNOWFLAKE_LOG_ERROR("calloc snowflake failed"); + return NULL; } - if (opts->snowflake_offset > 127) + sf->worker_base_id = worker_base_id; + sf->worker_offset_id = worker_offset_id; + sf->thread_id = thread_id; + sf->device_id = ((worker_base_id << 7) | worker_offset_id) & 0xFFF; + sf->sequence = 0; + + return sf; +} + +void snowflake_free(struct snowflake *sf) +{ + if (sf != NULL) { - snowflake_LOG_ERROR("snowflake_offset %u is invalid, range [0, 127]", opts->snowflake_offset); - return -1; + free(sf); + sf = NULL; } - - g_snowflake.snowflake_base = opts->snowflake_base; - g_snowflake.snowflake_offset = opts->snowflake_offset; - g_snowflake.device_id = ((g_snowflake.snowflake_base << 7) | g_snowflake.snowflake_offset) & 0xFFF; - - snowflake_LOG_DEBUG("snowflake_base: %u, snowflake_offset: %u, device_id: %u", - g_snowflake.snowflake_base, - g_snowflake.snowflake_offset, - g_snowflake.device_id); - return 0; } /* @@ -61,20 +65,41 @@ int snowflake_id_init(const struct snowflake_options *opts) * | 1bit | 12bit device_id | 8bit thread_id | 28bit timestamp in sec | 15bit sequence per thread | * +------+------------------+----------------+------------------------+---------------------------+ */ -uint64_t snowflake_id_generate(uint64_t now_sec) -{ + #define MAX_ID_PER_THREAD (32768) #define MAX_ID_BASE_TIME (268435456L) - uint64_t thr_idx = (uint16_t)stellar_get_current_thread_index(); +uint64_t snowflake_generate(struct snowflake *sf, uint64_t now_sec) +{ + if (sf == NULL) + { + SNOWFLAKE_LOG_ERROR("snowflake is NULL"); + return 0; + } - uint64_t global_id = 0; - uint64_t id_per_thread = (g_snowflake.thread[thr_idx]++) % MAX_ID_PER_THREAD; + uint64_t id = 0; + uint64_t id_per_thread = (sf->sequence++) % MAX_ID_PER_THREAD; uint64_t id_base_time = now_sec % MAX_ID_BASE_TIME; - global_id = (g_snowflake.device_id << 51) | - (thr_idx << 43) | - (id_base_time << 15) | - (id_per_thread); + id = (sf->device_id << 51) | + (sf->thread_id << 43) | + (id_base_time << 15) | + (id_per_thread); - return global_id; + return id; } + +void snowflake_deserialize(uint64_t id, struct snowflake_meta *meta) +{ + if (meta == NULL) + { + return; + } + + meta->sequence = id & 0x7FFF; + meta->time_cycle = MAX_ID_BASE_TIME; + meta->time_relative = (id >> 15) & 0xFFFFFFF; + meta->thread_id = (id >> 43) & 0xFF; + meta->device_id = (id >> 51) & 0xFFF; + meta->worker_base_id = (meta->device_id >> 7) & 0x1F; + meta->worker_offset_id = meta->device_id & 0x7F; +} \ No newline at end of file diff --git a/src/snowflake/snowflake.h b/src/snowflake/snowflake.h index b0b10dd..228b96a 100644 --- a/src/snowflake/snowflake.h +++ b/src/snowflake/snowflake.h @@ -7,16 +7,24 @@ extern "C" #include -struct snowflake_options +struct snowflake; +struct snowflake *snowflake_new(uint16_t thread_id, uint8_t worker_base_id, uint8_t worker_offset_id); +void snowflake_free(struct snowflake *sf); + +struct snowflake_meta { - uint8_t snowflake_base; - uint8_t snowflake_offset; + uint64_t sequence; + uint64_t time_cycle; + uint64_t time_relative; + uint16_t thread_id; + uint16_t device_id; + + uint8_t worker_base_id; + uint8_t worker_offset_id; }; -// return 0: success -// return -1: failed -int snowflake_id_init(const struct snowflake_options *opts); -uint64_t snowflake_id_generate(uint64_t now_sec); +uint64_t snowflake_generate(struct snowflake *sf, uint64_t now_sec); +void snowflake_deserialize(uint64_t id, struct snowflake_meta *meta); #ifdef __cplusplus } diff --git a/src/snowflake/test/CMakeLists.txt b/src/snowflake/test/CMakeLists.txt new file mode 100644 index 0000000..307c1e5 --- /dev/null +++ b/src/snowflake/test/CMakeLists.txt @@ -0,0 +1,8 @@ +add_executable(gtest_snowflake gtest_snowflake.cpp) +target_link_libraries(gtest_snowflake snowflake gtest) + +add_executable(snowflake_tool snowflake_tool.cpp) +target_link_libraries(snowflake_tool snowflake) + +include(GoogleTest) +gtest_discover_tests(gtest_snowflake) \ No newline at end of file diff --git a/src/snowflake/test/gtest_snowflake.cpp b/src/snowflake/test/gtest_snowflake.cpp new file mode 100644 index 0000000..78c4374 --- /dev/null +++ b/src/snowflake/test/gtest_snowflake.cpp @@ -0,0 +1,48 @@ +#include + +#include "snowflake.h" + +TEST(SNOWFLAKE, GENERATE) +{ + uint16_t thread_id = 1; + uint8_t worker_base_id = 2; + uint8_t worker_offset_id = 3; + + struct snowflake *sf = snowflake_new(thread_id, worker_base_id, worker_offset_id); + EXPECT_TRUE(sf != NULL); + EXPECT_TRUE(snowflake_generate(sf, 1000) != 0); + snowflake_free(sf); +} + +TEST(SNOWFLAKE, DESERIALIZE) +{ + uint16_t thread_id = 1; + uint8_t worker_base_id = 2; + uint8_t worker_offset_id = 3; + + struct snowflake *sf = snowflake_new(thread_id, worker_base_id, worker_offset_id); + EXPECT_TRUE(sf != NULL); + + for (uint64_t i = 0; i < 5; i++) + { + uint64_t id = snowflake_generate(sf, i + 1000); + EXPECT_TRUE(id != 0); + + struct snowflake_meta meta = {}; + snowflake_deserialize(id, &meta); + EXPECT_EQ(meta.sequence, i); + EXPECT_EQ(meta.time_relative, i + 1000); + EXPECT_EQ(meta.thread_id, thread_id); + EXPECT_EQ(meta.device_id, (worker_base_id << 7) | worker_offset_id); + EXPECT_EQ(meta.worker_base_id, worker_base_id); + EXPECT_EQ(meta.worker_offset_id, worker_offset_id); + } + + snowflake_free(sf); +} + +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/src/snowflake/test/snowflake_tool.cpp b/src/snowflake/test/snowflake_tool.cpp new file mode 100644 index 0000000..5d0d335 --- /dev/null +++ b/src/snowflake/test/snowflake_tool.cpp @@ -0,0 +1,38 @@ +#include +#include +#include + +#include "snowflake.h" + +int main(int argc, char **argv) +{ + if (argc != 2) + { + printf("Usage: %s \n", argv[0]); + return -1; + } + + uint64_t id = atoll(argv[1]); + struct snowflake_meta meta = {}; + snowflake_deserialize(id, &meta); + + printf("id : %lu\n", id); + printf("base_id : %u\n", meta.worker_base_id); + printf("offset_id : %u\n", meta.worker_offset_id); + printf("device_id : %u\n", meta.device_id); + printf("thread_id : %u\n", meta.thread_id); + printf("time_cycle : %lu sec (%lu year)\n", meta.time_cycle, meta.time_cycle / 3600 / 24 / 365); + printf("time_relative : %lu sec\n", meta.time_relative); + printf("sequence : %lu\n", meta.sequence); + + for (int i = 6; i < 10; i++) + { + char buff[64]; + time_t tt = meta.time_cycle * i + meta.time_relative; + struct tm *tm = localtime(&tt); + strftime(buff, sizeof(buff), "%Y-%m-%d %H:%M:%S", tm); + printf("\ttime_cycle * %d + time_relative => %s\n", i, buff); + } + + return 0; +} \ No newline at end of file diff --git a/test/debug_plugin/debug_plugin.cpp b/test/debug_plugin/debug_plugin.cpp index 24e905e..6d6f85c 100644 --- a/test/debug_plugin/debug_plugin.cpp +++ b/test/debug_plugin/debug_plugin.cpp @@ -1,19 +1,12 @@ -#include -#include -#include -#include -#include #include +#include +#include #include -#include #include -#include #include "utils.h" #include "packet_dump.h" #include "session_private.h" -#include "stellar/session.h" -#include "stellar/packet.h" #include "stellar/stellar_mq.h" #include "stellar/stellar_exdata.h"