diff --git a/deps/dablooms/CMakeLists.txt b/deps/dablooms/CMakeLists.txt index ef8248e..e0618d7 100644 --- a/deps/dablooms/CMakeLists.txt +++ b/deps/dablooms/CMakeLists.txt @@ -1,7 +1,3 @@ -############################################################################### -# dablooms -############################################################################### - add_library(dablooms dablooms.cpp murmur.cpp) target_include_directories(dablooms PUBLIC ${CMAKE_CURRENT_LIST_DIR}) target_link_libraries(dablooms) diff --git a/deps/interval_tree/itree.cpp b/deps/interval_tree/itree.cpp index 5bb68ef..9d7bf74 100644 --- a/deps/interval_tree/itree.cpp +++ b/deps/interval_tree/itree.cpp @@ -399,8 +399,7 @@ int itree_remove(itree_t *tree, interval_t *interval) { return 0; } - // else if (interval_equal(it->interval, interval)) - else if (it->interval->low >= interval->low && it->interval->high <= interval->high) + else if (interval_equal(it->interval, interval)) { break; } diff --git a/deps/interval_tree/itree.h b/deps/interval_tree/itree.h index 505e272..d9abbe1 100644 --- a/deps/interval_tree/itree.h +++ b/deps/interval_tree/itree.h @@ -54,11 +54,9 @@ typedef void (*rel_f)(void *p); /* Interval tree functions */ itree_t *itree_new(dup_f dup, rel_f rel); void itree_delete(itree_t *tree); -// Find the first interval containing the specified interval interval_t *itree_find(itree_t *tree, interval_t *interval); ilist_t *itree_findall(itree_t *tree, interval_t *interval); int itree_insert(itree_t *tree, interval_t *interval); -// Delete the first interval contained by the specified interval int itree_remove(itree_t *tree, interval_t *interval); size_t itree_size(itree_t *tree); diff --git a/deps/interval_tree/test/gtest_interval_tree.cpp b/deps/interval_tree/test/gtest_interval_tree.cpp index 417c275..70c26ca 100644 --- a/deps/interval_tree/test/gtest_interval_tree.cpp +++ b/deps/interval_tree/test/gtest_interval_tree.cpp @@ -113,7 +113,7 @@ TEST(INTERVAL_TREE, FIND) #endif #if 1 -TEST(INTERVAL_TREE, DELETE1) +TEST(INTERVAL_TREE, DELETE) { itree_t *tree; interval_t query; @@ -149,60 +149,18 @@ TEST(INTERVAL_TREE, DELETE1) EXPECT_TRUE(itree_remove(tree, &query) == 0); EXPECT_TRUE(itree_size(tree) == 1); - // delete - query = { - .low = 5, - .high = 9, - }; - EXPECT_TRUE(itree_remove(tree, &query) == 1); - EXPECT_TRUE(itree_size(tree) == 0); - - itree_delete(tree); -} -#endif - -#if 1 -TEST(INTERVAL_TREE, DELETE2) -{ - itree_t *tree; - interval_t query; - interval_t segment; - - // new - tree = itree_new(my_dup, my_rel); - EXPECT_TRUE(tree != nullptr); - EXPECT_TRUE(itree_size(tree) == 0); - - // insert - segment = { - .low = 5, - .high = 9, - .data = (void *)"Hello", - }; - EXPECT_TRUE(itree_insert(tree, &segment) == 1); - EXPECT_TRUE(itree_size(tree) == 1); - - // insert - segment = { - .low = 15, - .high = 19, - .data = (void *)"World", - }; - EXPECT_TRUE(itree_insert(tree, &segment) == 1); - EXPECT_TRUE(itree_size(tree) == 2); - // delete query = { .low = 1, .high = 20, }; - EXPECT_TRUE(itree_remove(tree, &query) == 1); + EXPECT_TRUE(itree_remove(tree, &query) == 0); EXPECT_TRUE(itree_size(tree) == 1); // delete query = { - .low = 1, - .high = 20, + .low = 5, + .high = 9, }; EXPECT_TRUE(itree_remove(tree, &query) == 1); EXPECT_TRUE(itree_size(tree) == 0); diff --git a/deps/toml/CMakeLists.txt b/deps/toml/CMakeLists.txt index 62340e4..4c02fa1 100644 --- a/deps/toml/CMakeLists.txt +++ b/deps/toml/CMakeLists.txt @@ -1,7 +1,3 @@ -############################################################################### -# toml -############################################################################### - add_library(toml toml.cpp) target_include_directories(toml PUBLIC ${CMAKE_CURRENT_LIST_DIR}) target_link_libraries(toml) \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 55fbb37..99a227a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,6 +6,7 @@ add_subdirectory(packet) add_subdirectory(packet_io) add_subdirectory(id_generator) add_subdirectory(ip_reassembly) +add_subdirectory(tcp_reassembly) add_subdirectory(duplicated_packet_filter) add_subdirectory(evicted_session_filter) add_subdirectory(session) diff --git a/src/stellar/stellar.cpp b/src/stellar/stellar.cpp index a60b15e..120efff 100644 --- a/src/stellar/stellar.cpp +++ b/src/stellar/stellar.cpp @@ -236,6 +236,7 @@ static void *main_loop(void *arg) plugin_manager_free_ctx(plug_mgr_ctx); session_manager_free_session(sess_mgr, expired_sess); } + ip_reassembly_expire(ip_reass, now); // TODO // plugin_manager_cron(); diff --git a/src/tcp_reassembly/CMakeLists.txt b/src/tcp_reassembly/CMakeLists.txt new file mode 100644 index 0000000..fb39681 --- /dev/null +++ b/src/tcp_reassembly/CMakeLists.txt @@ -0,0 +1,5 @@ +add_library(tcp_reassembly tcp_reassembly.cpp) +target_include_directories(tcp_reassembly PUBLIC ${CMAKE_CURRENT_LIST_DIR}) +target_link_libraries(tcp_reassembly interval_tree log) + +add_subdirectory(test) \ No newline at end of file diff --git a/src/tcp_reassembly/tcp_reassembly.cpp b/src/tcp_reassembly/tcp_reassembly.cpp new file mode 100644 index 0000000..45f10e8 --- /dev/null +++ b/src/tcp_reassembly/tcp_reassembly.cpp @@ -0,0 +1,350 @@ +#include +#include +#include +#include + +#include "tcp_reassembly.h" +#include "itree.h" + +struct tcp_reassembly +{ + // config + bool enable; + uint32_t max_timeout; + uint32_t max_packets; + uint32_t max_bytes; + + // stat + struct tcp_reassembly_stat stat; + + // runtime + struct itree *c2s_itree; + struct itree *s2c_itree; + uint64_t c2s_exp_seq; + uint64_t s2c_exp_seq; + + // used for timeout + struct segment *head; // del segment from head + struct segment *tail; // add segment to tail +}; + +struct segment +{ + struct tcp_reassembly *assembler; + struct itree *itree; + struct segment *next; + struct segment *prev; + + uint64_t time; + uint32_t offset; + uint32_t len; + char *payload; // Flexible array member +}; + +void *segment_dup(void *p) +{ + return p; +} + +void segment_rel(void *p) +{ + struct segment *seg = (struct segment *)p; + if (seg) + { + struct tcp_reassembly *assembler = seg->assembler; + // delete from list + if (assembler->head == seg) + { + assembler->head = seg->next; + } + if (assembler->tail == seg) + { + assembler->tail = seg->prev; + } + if (seg->prev) + { + seg->prev->next = seg->next; + } + if (seg->next) + { + seg->next->prev = seg->prev; + } + + assembler->stat.bytes -= seg->len; + assembler->stat.packets--; + + free(seg); + } +} + +struct tcp_reassembly *tcp_reassembly_new(bool enable, uint32_t max_timeout, uint32_t max_packets, uint32_t max_bytes) +{ + struct tcp_reassembly *assembler = (struct tcp_reassembly *)calloc(1, sizeof(struct tcp_reassembly)); + if (assembler == NULL) + { + return NULL; + } + + assembler->enable = enable; + assembler->max_timeout = max_timeout; + assembler->max_packets = max_packets; + assembler->max_bytes = max_bytes; + if (!assembler->enable) + { + return assembler; + } + + assembler->c2s_itree = itree_new(segment_dup, segment_rel); + assembler->s2c_itree = itree_new(segment_dup, segment_rel); + if (assembler->c2s_itree == NULL || assembler->s2c_itree == NULL) + { + goto error_out; + } + + return assembler; + +error_out: + tcp_reassembly_free(assembler); + return NULL; +} + +void tcp_reassembly_init(struct tcp_reassembly *assembler, uint32_t c2s_init_seq, uint32_t s2c_init_seq) +{ + if (!assembler->enable) + { + return; + } + + if (c2s_init_seq) + { + assembler->c2s_exp_seq = c2s_init_seq + 1; + } + + if (s2c_init_seq) + { + assembler->s2c_exp_seq = s2c_init_seq + 1; + } +} + +void tcp_reassembly_free(struct tcp_reassembly *assembler) +{ + if (assembler) + { + if (assembler->c2s_itree) + { + itree_delete(assembler->c2s_itree); + } + if (assembler->s2c_itree) + { + itree_delete(assembler->s2c_itree); + } + free(assembler); + } +} + +void tcp_reassembly_expire(struct tcp_reassembly *assembler, uint64_t now) +{ + if (!assembler->enable) + { + return; + } + + struct tcp_reassembly_stat *stat = &assembler->stat; + while (assembler->head) + { + struct segment *seg = assembler->head; + if (now - seg->time < assembler->max_timeout) + { + break; + } + + stat->tcp_segement_timout++; + + struct itree *itree = seg->itree; + interval_t interval = { + .low = seg->offset, + .high = seg->offset + seg->len - 1, + }; + itree_remove(itree, &interval); + } +} + +void tcp_reassembly_update(struct tcp_reassembly *assembler, int direction, uint32_t offset, const char *payload, uint32_t len, uint64_t now) +{ + if (!assembler->enable) + { + return; + } + + struct itree *itree = (direction == 0x01) ? assembler->c2s_itree : assembler->s2c_itree; + uint64_t exp_seq = (direction == 0x01) ? assembler->c2s_exp_seq : assembler->s2c_exp_seq; + + if (len == 0 || offset + len < exp_seq) + { + return; + } + + if (assembler->max_packets > 0 && assembler->stat.packets >= assembler->max_packets) + { + return; + } + + if (assembler->max_bytes > 0 && assembler->stat.bytes >= assembler->max_bytes) + { + return; + } + + struct segment *seg = (struct segment *)calloc(1, sizeof(struct segment) + len); + if (seg == NULL) + { + return; + } + + seg->itree = itree; + seg->assembler = assembler; + seg->time = now; + seg->offset = offset; + seg->len = len; + seg->payload = (char *)seg + sizeof(struct segment); + memcpy(seg->payload, payload, len); + + interval_t interval = { + .low = seg->offset, + .high = seg->offset + seg->len - 1, + .data = seg, + }; + if (itree_insert(itree, &interval) == 0) + { + free(seg); + return; + } + TCP_REASSEMBLE_DEBUG("%s insert [%lu, %lu], segment {ptr: %p, offset: %lu, len: %lu}", + (direction == 0x01) ? "C2S" : "S2C", + seg->offset, seg->offset + seg->len - 1, + seg, seg->offset, seg->len); + + if (assembler->head == NULL) + { + assembler->head = seg; + } + else + { + assembler->tail->next = seg; + seg->prev = assembler->tail; + } + assembler->tail = seg; + + assembler->stat.packets++; + assembler->stat.bytes += len; + + tcp_reassembly_expire(assembler, now); +} + +const char *tcp_reassembly_peek(struct tcp_reassembly *assembler, int direction, uint32_t *len) +{ + *len = 0; + + if (!assembler->enable) + { + return NULL; + } + + struct itree *itree = (direction == 0x01) ? assembler->c2s_itree : assembler->s2c_itree; + uint64_t exp_seq = (direction == 0x01) ? assembler->c2s_exp_seq : assembler->s2c_exp_seq; + + interval_t interval = { + .low = exp_seq, + .high = exp_seq, + }; + interval_t *result = itree_find(itree, &interval); + if (result == NULL) + { + TCP_REASSEMBLE_DEBUG("%s peek [%lu, +∞]: not found", (direction == 0x01) ? "C2S" : "S2C", exp_seq); + return NULL; + } + + struct segment *seg = (struct segment *)result->data; + assert(seg != NULL); + // check overlap + if (seg->offset < exp_seq) + { + TCP_REASSEMBLE_DEBUG("%s peek [%lu, +∞], found [%lu, %lu], segment {ptr: %p, offset: %lu, len: %lu, left trim: %lu}", + (direction == 0x01) ? "C2S" : "S2C", exp_seq, + seg->offset, seg->offset + seg->len - 1, + seg, seg->offset, seg->len, exp_seq - seg->offset); + *len = seg->len - (exp_seq - seg->offset); + return seg->payload + (exp_seq - seg->offset); + } + TCP_REASSEMBLE_DEBUG("%s peek [%lu, +∞], found [%lu, %lu], segment {ptr: %p, offset: %lu, len: %lu}", + (direction == 0x01) ? "C2S" : "S2C", exp_seq, + seg->offset, seg->offset + seg->len - 1, + seg, seg->offset, seg->len); + + *len = seg->len; + return seg->payload; +} + +void tcp_reassembly_consume(struct tcp_reassembly *assembler, int direction, uint32_t len) +{ + if (!assembler->enable) + { + return; + } + + if (len == 0) + { + return; + } + + struct itree *itree = (direction == 0x01) ? assembler->c2s_itree : assembler->s2c_itree; + uint64_t *exp_seq = (direction == 0x01) ? &assembler->c2s_exp_seq : &assembler->s2c_exp_seq; + uint64_t old_exp_seq = *exp_seq; + + *exp_seq += len; + uint64_t new_exp_seq = *exp_seq; + + TCP_REASSEMBLE_DEBUG("%s consume [%lu, %lu], update expect seq %lu -> %lu", + (direction == 0x01) ? "C2S" : "S2C", + old_exp_seq, new_exp_seq - 1, old_exp_seq, new_exp_seq); + + interval_t interval = { + .low = 0, + .high = *exp_seq, + }; + + ilist_t *list = itree_findall(itree, &interval); + if (list == NULL) + { + return; + } + + interval_t *result; + int count = ilist_size(list); + ilisttrav_t *trav = ilisttrav_new(list); + for (int i = 0; i < count; i++) + { + if (i == 0) + { + result = (interval_t *)ilisttrav_first(trav); + } + else + { + result = (interval_t *)ilisttrav_next(trav); + } + if (result && result->high < *exp_seq) + { + struct segment *seg = (struct segment *)result->data; + TCP_REASSEMBLE_DEBUG("%s consume [%lu, %lu], delete [%lu, %lu], segment {ptr: %p, offset: %lu, len: %lu}", + (direction == 0x01) ? "C2S" : "S2C", old_exp_seq, new_exp_seq - 1, + result->low, result->high, seg, seg->offset, seg->len); + itree_remove(itree, result); + } + } + ilisttrav_delete(trav); + ilist_delete(list); +} + +struct tcp_reassembly_stat *tcp_reassembly_get_stat(struct tcp_reassembly *assembler) +{ + return NULL; +} \ No newline at end of file diff --git a/src/tcp_reassembly/tcp_reassembly.h b/src/tcp_reassembly/tcp_reassembly.h new file mode 100644 index 0000000..cb55173 --- /dev/null +++ b/src/tcp_reassembly/tcp_reassembly.h @@ -0,0 +1,45 @@ +#ifndef _TCP_REASSEMBLY_H +#define _TCP_REASSEMBLY_H + +#ifdef __cpluscplus +extern "C" +{ +#endif + +#include "log.h" + +#include + +#define TCP_REASSEMBLE_DEBUG(format, ...) LOG_DEBUG("tcp_reassembly", format, ##__VA_ARGS__) +#define TCP_REASSEMBLE_ERROR(format, ...) LOG_ERROR("tcp_reassembly", format, ##__VA_ARGS__) + +struct tcp_reassembly_stat +{ + uint64_t packets; // current packets + uint64_t bytes; // current bytes + + uint64_t tcp_segement_timout; // total tcp segment timeout +}; + +/* + * If retransmission or overlap occurs, the old data packet may have been consumed by the upper-layer plug-in, + * so the old data packet takes priority and the new data packet will be bypassed. + */ + +struct tcp_reassembly *tcp_reassembly_new(bool enable, uint32_t max_timeout, uint32_t max_packets, uint32_t max_bytes); +void tcp_reassembly_init(struct tcp_reassembly *assembler, uint32_t c2s_init_seq, uint32_t s2c_init_seq); +void tcp_reassembly_free(struct tcp_reassembly *assembler); +void tcp_reassembly_expire(struct tcp_reassembly *assembler, uint64_t now); + +// direction: 1 C2S; 2: S2C +void tcp_reassembly_update(struct tcp_reassembly *assembler, int direction, uint32_t offset, const char *payload, uint32_t len, uint64_t now); +const char *tcp_reassembly_peek(struct tcp_reassembly *assembler, int direction, uint32_t *len); +void tcp_reassembly_consume(struct tcp_reassembly *assembler, int direction, uint32_t len); + +struct tcp_reassembly_stat *tcp_reassembly_get_stat(struct tcp_reassembly *assembler); + +#ifdef __cpluscplus +} +#endif + +#endif diff --git a/src/tcp_reassembly/test/CMakeLists.txt b/src/tcp_reassembly/test/CMakeLists.txt new file mode 100644 index 0000000..b1c8be3 --- /dev/null +++ b/src/tcp_reassembly/test/CMakeLists.txt @@ -0,0 +1,5 @@ +add_executable(gtest_tcp_reassembly gtest_tcp_reassembly.cpp) +target_link_libraries(gtest_tcp_reassembly tcp_reassembly gtest) + +include(GoogleTest) +gtest_discover_tests(gtest_tcp_reassembly) \ No newline at end of file diff --git a/src/tcp_reassembly/test/gtest_tcp_reassembly.cpp b/src/tcp_reassembly/test/gtest_tcp_reassembly.cpp new file mode 100644 index 0000000..9c1ed43 --- /dev/null +++ b/src/tcp_reassembly/test/gtest_tcp_reassembly.cpp @@ -0,0 +1,302 @@ +#include + +#include "tcp_reassembly.h" + +#if 0 +const char *session_peek_tcp_payload(struct session *session, uint32_t *len) +{ + struct session_dir *dir = session_get_cur_dir(session); + struct tcp_reassembly *assembler = session_get_tcp_reassembly(session); + return tcp_reassembly_peek(assembler, dir, len); +} + +void session_consume_tcp_payload(struct session *session, uint32_t len) +{ + struct session_dir *dir = session_get_cur_dir(session); + struct tcp_reassembly *assembler = session_get_tcp_reassembly(session); + tcp_reassembly_consume(assembler, dir, len); +} +#endif + +#if 1 +TEST(TCP_REASSEMBLY, TEST_C2S) +{ + uint32_t len; + int dir = 1; + const char *ptr; + struct tcp_reassembly *assembler; + + assembler = tcp_reassembly_new(1, 10, 16, 1500); + EXPECT_TRUE(assembler != NULL); + + tcp_reassembly_init(assembler, 99, 199); + + /* + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f|g|h|i|j|A|B|C|D|E|F|G|H|I|J| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | | + * +---> 90 +---> 100 +---> 110 + */ + + // C2S + tcp_reassembly_update(assembler, dir, 90, (const char *)"0123456789", 10, 0); + tcp_reassembly_update(assembler, dir, 100, (const char *)"abcdefghij", 10, 0); + tcp_reassembly_update(assembler, dir, 110, (const char *)"ABCDEFGHIJ", 10, 0); + + ptr = tcp_reassembly_peek(assembler, dir, &len); + EXPECT_TRUE(ptr != NULL); + EXPECT_TRUE(len == 10); + EXPECT_TRUE(memcmp(ptr, "abcdefghij", len) == 0); + + ptr = tcp_reassembly_peek(assembler, dir, &len); + EXPECT_TRUE(ptr != NULL); + EXPECT_TRUE(len == 10); + EXPECT_TRUE(memcmp(ptr, "abcdefghij", len) == 0); + tcp_reassembly_consume(assembler, dir, len); + + ptr = tcp_reassembly_peek(assembler, dir, &len); + EXPECT_TRUE(ptr != NULL); + EXPECT_TRUE(len == 10); + EXPECT_TRUE(memcmp(ptr, "ABCDEFGHIJ", len) == 0); + tcp_reassembly_consume(assembler, dir, len); + + ptr = tcp_reassembly_peek(assembler, dir, &len); + EXPECT_TRUE(ptr == NULL); + + tcp_reassembly_free(assembler); +} +#endif + +#if 1 +TEST(TCP_REASSEMBLY, TEST_S2C) +{ + uint32_t len; + int dir = 2; + const char *ptr; + struct tcp_reassembly *assembler; + + assembler = tcp_reassembly_new(1, 10, 16, 1500); + EXPECT_TRUE(assembler != NULL); + + tcp_reassembly_init(assembler, 199, 99); + + /* + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f|g|h|i|j|A|B|C|D|E|F|G|H|I|J| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | | + * +---> 90 +---> 100 +---> 110 + */ + + // C2S + tcp_reassembly_update(assembler, dir, 90, (const char *)"0123456789", 10, 0); + tcp_reassembly_update(assembler, dir, 100, (const char *)"abcdefghij", 10, 0); + tcp_reassembly_update(assembler, dir, 110, (const char *)"ABCDEFGHIJ", 10, 0); + + ptr = tcp_reassembly_peek(assembler, dir, &len); + EXPECT_TRUE(ptr != NULL); + EXPECT_TRUE(len == 10); + EXPECT_TRUE(memcmp(ptr, "abcdefghij", len) == 0); + + ptr = tcp_reassembly_peek(assembler, dir, &len); + EXPECT_TRUE(ptr != NULL); + EXPECT_TRUE(len == 10); + EXPECT_TRUE(memcmp(ptr, "abcdefghij", len) == 0); + tcp_reassembly_consume(assembler, dir, len); + + ptr = tcp_reassembly_peek(assembler, dir, &len); + EXPECT_TRUE(ptr != NULL); + EXPECT_TRUE(len == 10); + EXPECT_TRUE(memcmp(ptr, "ABCDEFGHIJ", len) == 0); + tcp_reassembly_consume(assembler, dir, len); + + ptr = tcp_reassembly_peek(assembler, dir, &len); + EXPECT_TRUE(ptr == NULL); + + tcp_reassembly_free(assembler); +} +#endif + +#if 1 +TEST(TCP_REASSEMBLY, REPEAT1) +{ + uint32_t len; + int dir = 1; + const char *ptr; + struct tcp_reassembly *assembler; + + assembler = tcp_reassembly_new(1, 10, 16, 1500); + EXPECT_TRUE(assembler != NULL); + + tcp_reassembly_init(assembler, 99, 199); + + /* + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f|g|h|i|j| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | |A|B|C|D|E|F|G|H|I|J| + * | +-+-+-+-+-+-+-+-+-+-+ + * | | | + * +---> 90 +---> 100 +---> 109 + */ + + // C2S + tcp_reassembly_update(assembler, dir, 90, (const char *)"0123456789", 10, 0); + tcp_reassembly_update(assembler, dir, 100, (const char *)"abcdefghij", 10, 0); + tcp_reassembly_update(assembler, dir, 100, (const char *)"ABCDEFGHIJ", 10, 0); + + ptr = tcp_reassembly_peek(assembler, dir, &len); + EXPECT_TRUE(ptr != NULL); + EXPECT_TRUE(len == 10); + EXPECT_TRUE(memcmp(ptr, "abcdefghij", len) == 0); + tcp_reassembly_consume(assembler, dir, len); + + ptr = tcp_reassembly_peek(assembler, dir, &len); + EXPECT_TRUE(ptr == NULL); + + tcp_reassembly_free(assembler); +} +#endif + +#if 1 +TEST(TCP_REASSEMBLY, REPEAT2) +{ + uint32_t len; + int dir = 1; + const char *ptr; + struct tcp_reassembly *assembler; + + assembler = tcp_reassembly_new(1, 10, 16, 1500); + EXPECT_TRUE(assembler != NULL); + + tcp_reassembly_init(assembler, 99, 199); + + /* + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|G|H|I|J| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | |a|b|c|d|e|f|g|h|i|j| + * | +-+-+-+-+-+-+-+-+-+-+ + * | | | + * +---> 90 +---> 100 +---> 109 + */ + + // C2S + + tcp_reassembly_update(assembler, dir, 90, (const char *)"0123456789", 10, 0); + tcp_reassembly_update(assembler, dir, 100, (const char *)"ABCDEFGHIJ", 10, 0); + tcp_reassembly_update(assembler, dir, 100, (const char *)"abcdefghij", 10, 0); + + ptr = tcp_reassembly_peek(assembler, dir, &len); + EXPECT_TRUE(ptr != NULL); + EXPECT_TRUE(len == 10); + EXPECT_TRUE(memcmp(ptr, "ABCDEFGHIJ", len) == 0); + tcp_reassembly_consume(assembler, dir, len); + + ptr = tcp_reassembly_peek(assembler, dir, &len); + EXPECT_TRUE(ptr == NULL); + + tcp_reassembly_free(assembler); +} +#endif + +#if 1 +TEST(TCP_REASSEMBLY, OVERLAP) +{ + uint32_t len; + int dir = 1; + const char *ptr; + struct tcp_reassembly *assembler; + + assembler = tcp_reassembly_new(1, 10, 16, 1500); + EXPECT_TRUE(assembler != NULL); + + tcp_reassembly_init(assembler, 89, 199); + + /* + * +-+-+-+-+-+-+-+-+-+-+ + * |0|1|2|3|4|5|6|7|8|9| + * +-+-+-+-+-+-+-+-+-+-+ + * | +-+-+-+-+-+-+-+-+-+-+ + * | |a|b|c|d|e|f|g|h|i|j| + * | +-+-+-+-+-+-+-+-+-+-+ + * | | | +-+-+-+-+-+-+-+-+-+-+ + * | | | |A|B|C|D|E|F|G|H|I|J| + * | | | +-+-+-+-+-+-+-+-+-+-+ + * | | | | | | + * | | | | | +---> 111 + * | | | | +---> 105 + * | | | +---> 102 + * | | +---> 99 + * | +---> 96 + * +---> 90 + * + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |0|1|2|3|4|5|6|7|8|9|e|f|g|h|i|j|E|F|G|H|I|J| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + + // C2S + tcp_reassembly_update(assembler, dir, 90, (const char *)"0123456789", 10, 0); + tcp_reassembly_update(assembler, dir, 96, (const char *)"abcdefghij", 10, 0); + tcp_reassembly_update(assembler, dir, 102, (const char *)"ABCDEFGHIJ", 10, 0); + + ptr = tcp_reassembly_peek(assembler, dir, &len); + EXPECT_TRUE(ptr != NULL); + EXPECT_TRUE(len == 10); + EXPECT_TRUE(memcmp(ptr, "0123456789", len) == 0); + tcp_reassembly_consume(assembler, dir, len); + + ptr = tcp_reassembly_peek(assembler, dir, &len); + EXPECT_TRUE(ptr != NULL); + EXPECT_TRUE(len == 6); + EXPECT_TRUE(memcmp(ptr, "efghij", len) == 0); + tcp_reassembly_consume(assembler, dir, len); + + ptr = tcp_reassembly_peek(assembler, dir, &len); + EXPECT_TRUE(ptr != NULL); + EXPECT_TRUE(len == 6); + EXPECT_TRUE(memcmp(ptr, "EFGHIJ", len) == 0); + tcp_reassembly_consume(assembler, dir, len); + + ptr = tcp_reassembly_peek(assembler, dir, &len); + EXPECT_TRUE(ptr == NULL); + + tcp_reassembly_free(assembler); +} +#endif + +#if 1 +TEST(TCP_REASSEMBLY, MAX_TIMEOUT) +{ + // TODO +} +#endif + +#if 1 +TEST(TCP_REASSEMBLY, MAX_PACKETS) +{ + // TODO +} +#endif + +#if 1 +TEST(TCP_REASSEMBLY, MAX_BYTES) +{ + // TODO +} +#endif + +#if 1 +TEST(TCP_REASSEMBLY, SEQ_WRAPAROUND) +{ + // TODO +} +#endif + +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/src/timestamp/CMakeLists.txt b/src/timestamp/CMakeLists.txt index 41dd2bf..fc59074 100644 --- a/src/timestamp/CMakeLists.txt +++ b/src/timestamp/CMakeLists.txt @@ -1,7 +1,3 @@ -############################################################################### -# timestamp -############################################################################### - add_library(timestamp timestamp.cpp) target_include_directories(timestamp PUBLIC ${CMAKE_CURRENT_LIST_DIR}) target_link_libraries(timestamp)