snowflake changes from global static variables to one instance per thread

This commit is contained in:
luwenpeng
2024-08-23 15:21:07 +08:00
parent 3014e0feef
commit 6808e6ba29
30 changed files with 420 additions and 167 deletions

View File

@@ -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)

View File

@@ -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;

View File

@@ -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

View File

@@ -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)

View File

@@ -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)

View File

@@ -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);

View File

@@ -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();
}

View File

@@ -1,6 +1,5 @@
#include <gtest/gtest.h>
#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");

View File

@@ -1,7 +1,6 @@
#include <gtest/gtest.h>
#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");

View File

@@ -1,7 +1,6 @@
#include <gtest/gtest.h>
#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");

View File

@@ -1,6 +1,5 @@
#include <gtest/gtest.h>
#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();
}

View File

@@ -1,11 +1,9 @@
#include <gtest/gtest.h>
#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");

View File

@@ -2,10 +2,8 @@
#include <gtest/gtest.h>
#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();
}

View File

@@ -2,10 +2,8 @@
#include <gtest/gtest.h>
#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();
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -2,10 +2,8 @@
#include <gtest/gtest.h>
#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();
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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");

View File

@@ -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");

View File

@@ -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");

View File

@@ -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");

View File

@@ -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)
target_link_libraries(snowflake log)
add_subdirectory(test)

View File

@@ -1,57 +1,61 @@
#include <time.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#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 = (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;
}

View File

@@ -7,16 +7,24 @@ extern "C"
#include <stdint.h>
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
}

View File

@@ -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)

View File

@@ -0,0 +1,48 @@
#include <gtest/gtest.h>
#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();
}

View File

@@ -0,0 +1,38 @@
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include "snowflake.h"
int main(int argc, char **argv)
{
if (argc != 2)
{
printf("Usage: %s <id>\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;
}

View File

@@ -1,19 +1,12 @@
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <stdarg.h>
#include <time.h>
#include <pthread.h>
#include <arpa/inet.h>
#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"