refactor: change session key from address list to six tuple

This commit is contained in:
luwenpeng
2023-12-14 15:23:13 +08:00
parent 5620ac211b
commit a232045764
14 changed files with 773 additions and 563 deletions

View File

@@ -4,7 +4,6 @@
add_library(session_manager
session.cpp
session_address.cpp
session_pool.cpp
session_table.cpp
session_timer.cpp
@@ -14,6 +13,7 @@ target_include_directories(session_manager PUBLIC ${CMAKE_SOURCE_DIR}/deps/timeo
target_include_directories(session_manager PUBLIC ${CMAKE_SOURCE_DIR}/src/packet)
target_include_directories(session_manager PUBLIC ${CMAKE_SOURCE_DIR}/src/session)
target_include_directories(session_manager PUBLIC ${CMAKE_SOURCE_DIR}/src/timestamp)
target_include_directories(session_manager PUBLIC ${CMAKE_SOURCE_DIR}/src/crc32)
target_link_libraries(session_manager timeout)
###############################################################################
@@ -24,10 +24,6 @@ add_executable(gtest_session gtest_session.cpp)
target_include_directories(gtest_session PUBLIC ${CMAKE_CURRENT_LIST_DIR})
target_link_libraries(gtest_session session_manager gtest)
add_executable(gtest_session_address gtest_session_address.cpp)
target_include_directories(gtest_session_address PUBLIC ${CMAKE_CURRENT_LIST_DIR})
target_link_libraries(gtest_session_address session_manager gtest)
add_executable(gtest_session_pool gtest_session_pool.cpp)
target_include_directories(gtest_session_pool PUBLIC ${CMAKE_CURRENT_LIST_DIR})
target_link_libraries(gtest_session_pool session_manager gtest)
@@ -42,7 +38,6 @@ target_link_libraries(gtest_session_timer session_manager gtest)
include(GoogleTest)
gtest_discover_tests(gtest_session)
gtest_discover_tests(gtest_session_address)
gtest_discover_tests(gtest_session_pool)
gtest_discover_tests(gtest_session_table)
gtest_discover_tests(gtest_session_timer)

View File

@@ -2,6 +2,39 @@
#include "session_private.h"
#define SESSION_KEY_IPV4_TCP(name) \
struct session_key name; \
memset(&name, 0, sizeof(struct session_key)); \
(name).ip_type = IP_TYPE_V4; \
(name).src_addr.v4.s_addr = inet_addr("192.168.1.2"); \
(name).dst_addr.v4.s_addr = inet_addr("192.168.1.3"); \
(name).src_port = htons(1234); \
(name).dst_port = htons(5678); \
(name).ip_proto = IPPROTO_TCP; \
(name).security_zone = 0;
#define SESSION_KEY_IPV6_UDP(name) \
struct session_key name; \
memset(&name, 0, sizeof(struct session_key)); \
(name).ip_type = IP_TYPE_V6; \
inet_pton(AF_INET6, "2001:db8:0:0:0:ff00:42:8329", &(name).src_addr.v6); \
inet_pton(AF_INET6, "2001:db8:0:0:0:ff00:42:832a", &(name).dst_addr.v6); \
(name).src_port = htons(1234); \
(name).dst_port = htons(5678); \
(name).ip_proto = IPPROTO_UDP; \
(name).security_zone = 0;
#define SESSION_KEY_IPV6_TCP(name) \
struct session_key name; \
memset(&name, 0, sizeof(struct session_key)); \
(name).ip_type = IP_TYPE_V6; \
inet_pton(AF_INET6, "2001:db8:0:0:0:ff00:42:8329", &(name).src_addr.v6); \
inet_pton(AF_INET6, "2001:db8:0:0:0:ff00:42:832a", &(name).dst_addr.v6); \
(name).src_port = htons(1234); \
(name).dst_port = htons(5678); \
(name).ip_proto = IPPROTO_TCP; \
(name).security_zone = 0;
void free_ex_data(struct session *sess, uint8_t idx, void *ex_ptr, void *arg)
{
if (ex_ptr)
@@ -78,6 +111,67 @@ TEST(SESSION, EV_QUEUE)
}
}
TEST(SESSION, SESSION_KEY)
{
char buf[128] = {0};
SESSION_KEY_IPV4_TCP(key1);
SESSION_KEY_IPV6_UDP(key2);
SESSION_KEY_IPV6_TCP(key3);
struct session_key reverse_key1;
struct session_key reverse_key2;
struct session_key reverse_key3;
struct session_key reverse_temp;
// tostring
memset(buf, 0, sizeof(buf));
session_key_tostring(&key1, buf, sizeof(buf));
EXPECT_STREQ(buf, "192.168.1.2:1234 -> 192.168.1.3:5678, proto: 6, zone: 0");
memset(buf, 0, sizeof(buf));
session_key_tostring(&key2, buf, sizeof(buf));
EXPECT_STREQ(buf, "2001:db8::ff00:42:8329:1234 -> 2001:db8::ff00:42:832a:5678, proto: 17, zone: 0");
memset(buf, 0, sizeof(buf));
session_key_tostring(&key3, buf, sizeof(buf));
EXPECT_STREQ(buf, "2001:db8::ff00:42:8329:1234 -> 2001:db8::ff00:42:832a:5678, proto: 6, zone: 0");
// reverse
session_key_reverse(&key1, &reverse_key1);
session_key_reverse(&key2, &reverse_key2);
session_key_reverse(&key3, &reverse_key3);
memset(buf, 0, sizeof(buf));
session_key_tostring(&reverse_key1, buf, sizeof(buf));
EXPECT_STREQ(buf, "192.168.1.3:5678 -> 192.168.1.2:1234, proto: 6, zone: 0");
memset(buf, 0, sizeof(buf));
session_key_tostring(&reverse_key2, buf, sizeof(buf));
EXPECT_STREQ(buf, "2001:db8::ff00:42:832a:5678 -> 2001:db8::ff00:42:8329:1234, proto: 17, zone: 0");
memset(buf, 0, sizeof(buf));
session_key_tostring(&reverse_key3, buf, sizeof(buf));
EXPECT_STREQ(buf, "2001:db8::ff00:42:832a:5678 -> 2001:db8::ff00:42:8329:1234, proto: 6, zone: 0");
// hash
EXPECT_TRUE(session_key_hash(&key1) == session_key_hash(&reverse_key1));
EXPECT_TRUE(session_key_hash(&key2) == session_key_hash(&reverse_key2));
EXPECT_TRUE(session_key_hash(&key3) == session_key_hash(&reverse_key3));
// cmp
EXPECT_TRUE(session_key_cmp(&key1, &key1) == 0);
EXPECT_TRUE(session_key_cmp(&key2, &key2) == 0);
EXPECT_TRUE(session_key_cmp(&key3, &key3) == 0);
EXPECT_TRUE(session_key_cmp(&key1, &reverse_key1) != 0);
EXPECT_TRUE(session_key_cmp(&key2, &reverse_key2) != 0);
EXPECT_TRUE(session_key_cmp(&key3, &reverse_key3) != 0);
session_key_reverse(&reverse_key1, &reverse_temp);
EXPECT_TRUE(session_key_cmp(&key1, &reverse_temp) == 0);
session_key_reverse(&reverse_key2, &reverse_temp);
EXPECT_TRUE(session_key_cmp(&key2, &reverse_temp) == 0);
session_key_reverse(&reverse_key3, &reverse_temp);
EXPECT_TRUE(session_key_cmp(&key3, &reverse_temp) == 0);
}
int main(int argc, char **argv)
{
::testing::InitGoogleTest(&argc, argv);

View File

@@ -1,100 +0,0 @@
#include <gtest/gtest.h>
#include "session_address.h"
#define SESSION_ADDRESS_IPV4_TCP(name) \
struct session_address name = {0}; \
(name).layers[0].type = LAYER_IPV4; \
(name).layers[0].tuple.ipv4.src.s_addr = inet_addr("192.168.1.2"); \
(name).layers[0].tuple.ipv4.dst.s_addr = inet_addr("192.168.1.3"); \
(name).layers[1].type = LAYER_TCP; \
(name).layers[1].tuple.tcp.src = htons(1234); \
(name).layers[1].tuple.tcp.dst = htons(5678); \
(name).used = 2;
#define SESSION_ADDRESS_IPV6_UDP(name) \
struct session_address name = {0}; \
(name).layers[0].type = LAYER_IPV6; \
inet_pton(AF_INET6, "2001:db8:0:0:0:ff00:42:8329", &(name).layers[0].tuple.ipv6.src); \
inet_pton(AF_INET6, "2001:db8:0:0:0:ff00:42:832a", &(name).layers[0].tuple.ipv6.dst); \
(name).layers[1].type = LAYER_UDP; \
(name).layers[1].tuple.udp.src = htons(2345); \
(name).layers[1].tuple.udp.dst = htons(443); \
(name).used = 2;
#define SESSION_ADDRESS_IPV4_UDP_IPV6_TCP(name) \
struct session_address name = {0}; \
(name).layers[0].type = LAYER_IPV4; \
(name).layers[0].tuple.ipv4.src.s_addr = inet_addr("192.168.1.2"); \
(name).layers[0].tuple.ipv4.dst.s_addr = inet_addr("192.168.1.3"); \
(name).layers[1].type = LAYER_UDP; \
(name).layers[1].tuple.udp.src = htons(1234); \
(name).layers[1].tuple.udp.dst = htons(5678); \
(name).layers[2].type = LAYER_IPV6; \
inet_pton(AF_INET6, "2001:db8:0:0:0:ff00:42:8329", &(name).layers[2].tuple.ipv6.src); \
inet_pton(AF_INET6, "2001:db8:0:0:0:ff00:42:832a", &(name).layers[2].tuple.ipv6.dst); \
(name).layers[3].type = LAYER_TCP; \
(name).layers[3].tuple.tcp.src = htons(2345); \
(name).layers[3].tuple.tcp.dst = htons(443); \
(name).used = 4;
TEST(SESSION_ADDRESS, TOSTRING)
{
char buff[256] = {0};
SESSION_ADDRESS_IPV4_TCP(sess1_addr);
SESSION_ADDRESS_IPV6_UDP(sess2_addr);
SESSION_ADDRESS_IPV4_UDP_IPV6_TCP(sess3_addr);
session_address_tostring(&sess1_addr, buff, sizeof(buff));
EXPECT_STREQ(buff, "192.168.1.2-192.168.1.3/1234-5678/");
session_address_tostring(&sess2_addr, buff, sizeof(buff));
EXPECT_STREQ(buff, "2001:db8::ff00:42:8329-2001:db8::ff00:42:832a/2345-443/");
session_address_tostring(&sess3_addr, buff, sizeof(buff));
EXPECT_STREQ(buff, "192.168.1.2-192.168.1.3/1234-5678/2001:db8::ff00:42:8329-2001:db8::ff00:42:832a/2345-443/");
}
TEST(SESSION_ADDRESS, REVERSE)
{
char buff[256] = {0};
SESSION_ADDRESS_IPV4_TCP(sess1_addr);
SESSION_ADDRESS_IPV6_UDP(sess2_addr);
SESSION_ADDRESS_IPV4_UDP_IPV6_TCP(sess3_addr);
session_address_reverse(&sess1_addr);
session_address_reverse(&sess2_addr);
session_address_reverse(&sess3_addr);
session_address_tostring(&sess1_addr, buff, sizeof(buff));
EXPECT_STREQ(buff, "192.168.1.3-192.168.1.2/5678-1234/");
session_address_tostring(&sess2_addr, buff, sizeof(buff));
EXPECT_STREQ(buff, "2001:db8::ff00:42:832a-2001:db8::ff00:42:8329/443-2345/");
session_address_tostring(&sess3_addr, buff, sizeof(buff));
EXPECT_STREQ(buff, "192.168.1.3-192.168.1.2/5678-1234/2001:db8::ff00:42:832a-2001:db8::ff00:42:8329/443-2345/");
}
TEST(SESSION_ADDRESS, SELFCMP)
{
SESSION_ADDRESS_IPV4_TCP(sess1_addr);
SESSION_ADDRESS_IPV6_UDP(sess2_addr);
SESSION_ADDRESS_IPV4_UDP_IPV6_TCP(sess3_addr);
EXPECT_TRUE(session_address_selfcmp(&sess1_addr) < 0);
EXPECT_TRUE(session_address_selfcmp(&sess2_addr) < 0);
EXPECT_TRUE(session_address_selfcmp(&sess3_addr) < 0);
session_address_reverse(&sess1_addr);
session_address_reverse(&sess2_addr);
session_address_reverse(&sess3_addr);
EXPECT_TRUE(session_address_selfcmp(&sess1_addr) > 0);
EXPECT_TRUE(session_address_selfcmp(&sess2_addr) > 0);
EXPECT_TRUE(session_address_selfcmp(&sess3_addr) > 0);
}
int main(int argc, char **argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@@ -1,44 +1,40 @@
#include <gtest/gtest.h>
#include "session_address.h"
#include "session_pool.h"
#include "session_table.h"
#define SESSION_ADDRESS_IPV4_TCP(name) \
struct session_address name = {0}; \
(name).layers[0].type = LAYER_IPV4; \
(name).layers[0].tuple.ipv4.src.s_addr = inet_addr("192.168.1.2"); \
(name).layers[0].tuple.ipv4.dst.s_addr = inet_addr("192.168.1.3"); \
(name).layers[1].type = LAYER_TCP; \
(name).layers[1].tuple.tcp.src = htons(1234); \
(name).layers[1].tuple.tcp.dst = htons(5678); \
(name).used = 2;
#define SESSION_KEY_IPV4_TCP(name) \
struct session_key name; \
memset(&name, 0, sizeof(struct session_key)); \
(name).ip_type = IP_TYPE_V4; \
(name).src_addr.v4.s_addr = inet_addr("192.168.1.2"); \
(name).dst_addr.v4.s_addr = inet_addr("192.168.1.3"); \
(name).src_port = htons(1234); \
(name).dst_port = htons(5678); \
(name).ip_proto = IPPROTO_TCP; \
(name).security_zone = 0;
#define SESSION_ADDRESS_IPV6_UDP(name) \
struct session_address name = {0}; \
(name).layers[0].type = LAYER_IPV6; \
inet_pton(AF_INET6, "2001:db8:0:0:0:ff00:42:8329", &(name).layers[0].tuple.ipv6.src); \
inet_pton(AF_INET6, "2001:db8:0:0:0:ff00:42:832a", &(name).layers[0].tuple.ipv6.dst); \
(name).layers[1].type = LAYER_UDP; \
(name).layers[1].tuple.udp.src = htons(2345); \
(name).layers[1].tuple.udp.dst = htons(443); \
(name).used = 2;
#define SESSION_KEY_IPV6_UDP(name) \
struct session_key name; \
memset(&name, 0, sizeof(struct session_key)); \
(name).ip_type = IP_TYPE_V6; \
inet_pton(AF_INET6, "2001:db8:0:0:0:ff00:42:8329", &(name).src_addr.v6); \
inet_pton(AF_INET6, "2001:db8:0:0:0:ff00:42:832a", &(name).dst_addr.v6); \
(name).src_port = htons(1234); \
(name).dst_port = htons(5678); \
(name).ip_proto = IPPROTO_UDP; \
(name).security_zone = 0;
#define SESSION_ADDRESS_IPV4_UDP_IPV6_TCP(name) \
struct session_address name = {0}; \
(name).layers[0].type = LAYER_IPV4; \
(name).layers[0].tuple.ipv4.src.s_addr = inet_addr("192.168.1.2"); \
(name).layers[0].tuple.ipv4.dst.s_addr = inet_addr("192.168.1.3"); \
(name).layers[1].type = LAYER_UDP; \
(name).layers[1].tuple.udp.src = htons(1234); \
(name).layers[1].tuple.udp.dst = htons(5678); \
(name).layers[2].type = LAYER_IPV6; \
inet_pton(AF_INET6, "2001:db8:0:0:0:ff00:42:8329", &(name).layers[2].tuple.ipv6.src); \
inet_pton(AF_INET6, "2001:db8:0:0:0:ff00:42:832a", &(name).layers[2].tuple.ipv6.dst); \
(name).layers[3].type = LAYER_TCP; \
(name).layers[3].tuple.tcp.src = htons(2345); \
(name).layers[3].tuple.tcp.dst = htons(443); \
(name).used = 4;
#define SESSION_KEY_IPV6_TCP(name) \
struct session_key name; \
memset(&name, 0, sizeof(struct session_key)); \
(name).ip_type = IP_TYPE_V6; \
inet_pton(AF_INET6, "2001:db8:0:0:0:ff00:42:8329", &(name).src_addr.v6); \
inet_pton(AF_INET6, "2001:db8:0:0:0:ff00:42:832a", &(name).dst_addr.v6); \
(name).src_port = htons(1234); \
(name).dst_port = htons(5678); \
(name).ip_proto = IPPROTO_TCP; \
(name).security_zone = 0;
static void session_free_callback(struct session *sess, void *arg)
{
@@ -58,9 +54,17 @@ TEST(SESSION_TABLE, OP_SESSION)
struct session_pool *sess_pool = NULL;
struct session_table *sess_table = NULL;
SESSION_ADDRESS_IPV4_TCP(sess1_addr);
SESSION_ADDRESS_IPV6_UDP(sess2_addr);
SESSION_ADDRESS_IPV4_UDP_IPV6_TCP(sess3_addr);
SESSION_KEY_IPV4_TCP(sess1_key);
SESSION_KEY_IPV6_UDP(sess2_key);
SESSION_KEY_IPV6_TCP(sess3_key);
struct session_key sess1_key_reversed;
struct session_key sess2_key_reversed;
struct session_key sess3_key_reversed;
session_key_reverse(&sess1_key, &sess1_key_reversed);
session_key_reverse(&sess2_key, &sess2_key_reversed);
session_key_reverse(&sess3_key, &sess3_key_reversed);
// Create
sess_pool = session_pool_create(3);
@@ -69,56 +73,53 @@ TEST(SESSION_TABLE, OP_SESSION)
EXPECT_TRUE(sess_table != NULL);
session_table_set_freecb(sess_table, session_free_callback, sess_pool);
// Add session
// Add
sess1 = session_pool_alloc(sess_pool);
EXPECT_TRUE(sess1 != NULL);
session_set_id(sess1, 1);
session_set_address(sess1, &sess1_addr);
session_set_key(sess1, &sess1_key);
sess2 = session_pool_alloc(sess_pool);
EXPECT_TRUE(sess2 != NULL);
session_set_id(sess2, 2);
session_set_address(sess2, &sess2_addr);
session_set_key(sess2, &sess2_key);
sess3 = session_pool_alloc(sess_pool);
EXPECT_TRUE(sess3 != NULL);
session_set_id(sess3, 3);
session_set_address(sess3, &sess3_addr);
session_set_key(sess3, &sess3_key);
EXPECT_TRUE(session_table_add_session(sess_table, sess1) == 0);
EXPECT_TRUE(session_table_add_session(sess_table, &sess1_key, sess1) == 0);
EXPECT_TRUE(session_table_get_count(sess_table) == 1);
EXPECT_TRUE(session_table_add_session(sess_table, sess2) == 0);
EXPECT_TRUE(session_table_add_session(sess_table, &sess2_key, sess2) == 0);
EXPECT_TRUE(session_table_get_count(sess_table) == 2);
EXPECT_TRUE(session_table_add_session(sess_table, sess3) == 0);
EXPECT_TRUE(session_table_add_session(sess_table, &sess3_key, sess3) == 0);
EXPECT_TRUE(session_table_get_count(sess_table) == 3);
// Search session with id
EXPECT_TRUE(session_table_find_session_by_id(sess_table, 1) == sess1);
EXPECT_TRUE(session_table_find_session_by_id(sess_table, 2) == sess2);
EXPECT_TRUE(session_table_find_session_by_id(sess_table, 3) == sess3);
// Search
EXPECT_TRUE(session_table_find_session(sess_table, &sess1_key) == sess1);
EXPECT_TRUE(session_table_find_session(sess_table, &sess2_key) == sess2);
EXPECT_TRUE(session_table_find_session(sess_table, &sess3_key) == sess3);
// Search session with address
session_address_reverse(&sess3_addr);
EXPECT_TRUE(session_table_find_session_by_addr(sess_table, &sess1_addr) == sess1);
EXPECT_TRUE(session_table_find_session_by_addr(sess_table, &sess2_addr) == sess2);
EXPECT_TRUE(session_table_find_session_by_addr(sess_table, &sess3_addr) == sess3);
EXPECT_TRUE(session_table_find_session(sess_table, &sess1_key_reversed) == sess1);
EXPECT_TRUE(session_table_find_session(sess_table, &sess2_key_reversed) == sess2);
EXPECT_TRUE(session_table_find_session(sess_table, &sess3_key_reversed) == sess3);
// Delete session with id
session_table_delete_session_by_id(sess_table, 1);
// Delete
session_table_delete_session(sess_table, &sess1_key);
EXPECT_TRUE(session_table_get_count(sess_table) == 2);
EXPECT_TRUE(session_table_find_session_by_id(sess_table, 1) == NULL);
EXPECT_TRUE(session_table_find_session_by_addr(sess_table, &sess1_addr) == NULL);
EXPECT_TRUE(session_table_find_session(sess_table, &sess1_key) == NULL);
EXPECT_TRUE(session_table_find_session(sess_table, &sess1_key_reversed) == NULL);
session_table_delete_session_by_id(sess_table, 2);
session_table_delete_session(sess_table, &sess2_key_reversed);
EXPECT_TRUE(session_table_get_count(sess_table) == 1);
EXPECT_TRUE(session_table_find_session_by_id(sess_table, 2) == NULL);
EXPECT_TRUE(session_table_find_session_by_addr(sess_table, &sess2_addr) == NULL);
EXPECT_TRUE(session_table_find_session(sess_table, &sess2_key) == NULL);
EXPECT_TRUE(session_table_find_session(sess_table, &sess2_key_reversed) == NULL);
// Delete session with address
session_table_delete_session_by_addr(sess_table, &sess3_addr);
session_table_delete_session(sess_table, &sess3_key);
EXPECT_TRUE(session_table_get_count(sess_table) == 0);
EXPECT_TRUE(session_table_find_session_by_id(sess_table, 3) == NULL);
EXPECT_TRUE(session_table_find_session_by_addr(sess_table, &sess3_addr) == NULL);
EXPECT_TRUE(session_table_find_session(sess_table, &sess3_key) == NULL);
EXPECT_TRUE(session_table_find_session(sess_table, &sess3_key_reversed) == NULL);
// Destroy
session_table_destroy(sess_table);
@@ -133,9 +134,9 @@ TEST(SESSION_TABLE, FIND_OLDEST_NEWEST)
struct session_pool *sess_pool = NULL;
struct session_table *sess_table = NULL;
SESSION_ADDRESS_IPV4_TCP(sess1_addr);
SESSION_ADDRESS_IPV6_UDP(sess2_addr);
SESSION_ADDRESS_IPV4_UDP_IPV6_TCP(sess3_addr);
SESSION_KEY_IPV4_TCP(sess1_key);
SESSION_KEY_IPV6_UDP(sess2_key);
SESSION_KEY_IPV6_TCP(sess3_key);
// Create
sess_pool = session_pool_create(3);
@@ -152,38 +153,38 @@ TEST(SESSION_TABLE, FIND_OLDEST_NEWEST)
sess1 = session_pool_alloc(sess_pool);
EXPECT_TRUE(sess1 != NULL);
session_set_id(sess1, 1);
session_set_address(sess1, &sess1_addr);
EXPECT_TRUE(session_table_add_session(sess_table, sess1) == 0);
session_set_key(sess1, &sess1_key);
EXPECT_TRUE(session_table_add_session(sess_table, &sess1_key, sess1) == 0);
EXPECT_TRUE(session_table_find_oldest_session(sess_table) == sess1);
EXPECT_TRUE(session_table_find_newest_session(sess_table) == sess1);
sess2 = session_pool_alloc(sess_pool);
EXPECT_TRUE(sess2 != NULL);
session_set_id(sess2, 2);
session_set_address(sess2, &sess2_addr);
EXPECT_TRUE(session_table_add_session(sess_table, sess2) == 0);
session_set_key(sess2, &sess2_key);
EXPECT_TRUE(session_table_add_session(sess_table, &sess2_key, sess2) == 0);
EXPECT_TRUE(session_table_find_oldest_session(sess_table) == sess1);
EXPECT_TRUE(session_table_find_newest_session(sess_table) == sess2);
sess3 = session_pool_alloc(sess_pool);
EXPECT_TRUE(sess3 != NULL);
session_set_id(sess3, 3);
session_set_address(sess3, &sess3_addr);
EXPECT_TRUE(session_table_add_session(sess_table, sess3) == 0);
session_set_key(sess3, &sess3_key);
EXPECT_TRUE(session_table_add_session(sess_table, &sess3_key, sess3) == 0);
EXPECT_TRUE(session_table_find_oldest_session(sess_table) == sess1);
EXPECT_TRUE(session_table_find_newest_session(sess_table) == sess3);
// Delete Session
session_table_delete_session_by_id(sess_table, 1);
session_table_delete_session(sess_table, &sess1_key);
EXPECT_TRUE(session_table_find_oldest_session(sess_table) == sess2);
EXPECT_TRUE(session_table_find_newest_session(sess_table) == sess3);
session_table_delete_session_by_id(sess_table, 2);
session_table_delete_session(sess_table, &sess2_key);
EXPECT_TRUE(session_table_find_oldest_session(sess_table) == sess3);
EXPECT_TRUE(session_table_find_newest_session(sess_table) == sess3);
session_table_delete_session_by_id(sess_table, 3);
session_table_delete_session(sess_table, &sess3_key);
EXPECT_TRUE(session_table_find_oldest_session(sess_table) == NULL);
EXPECT_TRUE(session_table_find_newest_session(sess_table) == NULL);

View File

@@ -1,5 +1,6 @@
#include <assert.h>
#include "crc32_hash.h"
#include "session_private.h"
#define EX_KEY_MAX_LEN 64
@@ -65,6 +66,134 @@ static bool event_queue_pop(struct event_queue *queue, uint32_t *event)
return true;
}
/******************************************************************************
* session key
******************************************************************************/
uint32_t session_key_hash(const struct session_key *key)
{
uint32_t hash = crc32_hash(&key->security_zone, sizeof(key->security_zone), key->ip_proto);
if (key->ip_type == IP_TYPE_V4)
{
uint32_t src_addr_hash = crc32_hash(&key->src_addr.v4, sizeof(key->src_addr.v4), hash);
uint32_t dst_addr_hash = crc32_hash(&key->dst_addr.v4, sizeof(key->dst_addr.v4), hash);
hash = src_addr_hash + dst_addr_hash;
}
else
{
uint32_t src_addr_hash = crc32_hash(&key->src_addr.v6, sizeof(key->src_addr.v6), hash);
uint32_t dst_addr_hash = crc32_hash(&key->dst_addr.v6, sizeof(key->dst_addr.v6), hash);
hash = src_addr_hash + dst_addr_hash;
}
uint32_t src_port_hash = crc32_hash(&key->src_port, sizeof(key->src_port), hash);
uint32_t dst_port_hash = crc32_hash(&key->dst_port, sizeof(key->dst_port), hash);
hash = src_port_hash + dst_port_hash;
return hash;
}
// return 0: equal
// return -1: not equal
int session_key_cmp(const struct session_key *key1, const struct session_key *key2)
{
if (key1->ip_type != key2->ip_type)
{
return -1;
}
if (key1->src_port != key2->src_port)
{
return -1;
}
if (key1->dst_port != key2->dst_port)
{
return -1;
}
if (key1->ip_proto != key2->ip_proto)
{
return -1;
}
if (key1->security_zone != key2->security_zone)
{
return -1;
}
if (key1->ip_type == IP_TYPE_V4)
{
if (key1->src_addr.v4.s_addr != key2->src_addr.v4.s_addr)
{
return -1;
}
if (key1->dst_addr.v4.s_addr != key2->dst_addr.v4.s_addr)
{
return -1;
}
}
else
{
if (memcmp(&key1->src_addr.v6, &key2->src_addr.v6, sizeof(key1->src_addr.v6)) != 0)
{
return -1;
}
if (memcmp(&key1->dst_addr.v6, &key2->dst_addr.v6, sizeof(key1->dst_addr.v6)) != 0)
{
return -1;
}
}
return 0;
}
void session_key_reverse(const struct session_key *in, struct session_key *out)
{
out->ip_type = in->ip_type;
out->src_port = in->dst_port;
out->dst_port = in->src_port;
out->ip_proto = in->ip_proto;
out->security_zone = in->security_zone;
if (in->ip_type == IP_TYPE_V4)
{
out->src_addr.v4.s_addr = in->dst_addr.v4.s_addr;
out->dst_addr.v4.s_addr = in->src_addr.v4.s_addr;
}
else
{
memcpy(&out->src_addr.v6, &in->dst_addr.v6, sizeof(in->dst_addr.v6));
memcpy(&out->dst_addr.v6, &in->src_addr.v6, sizeof(in->src_addr.v6));
}
}
void session_key_tostring(const struct session_key *key, char *buf, uint32_t buf_len)
{
char src_addr[INET6_ADDRSTRLEN] = {0};
char dst_addr[INET6_ADDRSTRLEN] = {0};
if (key->ip_type == IP_TYPE_V4)
{
inet_ntop(AF_INET, &key->src_addr.v4, src_addr, sizeof(src_addr));
inet_ntop(AF_INET, &key->dst_addr.v4, dst_addr, sizeof(dst_addr));
}
else
{
inet_ntop(AF_INET6, &key->src_addr.v6, src_addr, sizeof(src_addr));
inet_ntop(AF_INET6, &key->dst_addr.v6, dst_addr, sizeof(dst_addr));
}
snprintf(buf, buf_len, "%s:%u -> %s:%u, proto: %u, zone: %lu",
src_addr, ntohs(key->src_port),
dst_addr, ntohs(key->dst_port),
key->ip_proto,
key->security_zone);
}
/******************************************************************************
* session
******************************************************************************/
@@ -86,15 +215,15 @@ uint64_t session_get_id(struct session *sess)
return sess->id;
}
// session address
void session_set_address(struct session *sess, struct session_address *addr)
// session key
void session_set_key(struct session *sess, struct session_key *key)
{
memcpy(&sess->addr, addr, sizeof(struct session_address));
memcpy(&sess->key, key, sizeof(struct session_key));
}
struct session_address *session_get0_address(struct session *sess)
struct session_key *session_get0_key(struct session *sess)
{
return &sess->addr;
return &sess->key;
}
// session state

View File

@@ -7,22 +7,23 @@ extern "C"
#endif
#include <stdint.h>
#include "session_address.h"
#include <arpa/inet.h>
enum session_state
{
SESSION_STATE_NONE = 0,
SESSION_STATE_INIT = 0,
SESSION_STATE_OPENING,
SESSION_STATE_ACTIVE,
SESSION_STATE_CLOSING,
SESSION_STATE_DISCARD,
SESSION_STATE_CLOSING,
SESSION_STATE_CLOSED,
};
enum session_type
{
SESSION_TYPE_NONE = 0,
SESSION_TYPE_TCP,
SESSION_TYPE_TCP_STREAM,
SESSION_TYPE_UDP,
};
@@ -32,14 +33,37 @@ enum session_event
SESSION_EVENT_OPENING,
SESSION_EVENT_ACTIVE,
SESSION_EVENT_CLOSING,
SESSION_EVENT_DISCARD,
SESSION_EVENT_TIMEOUT,
// Add new event before SESSION_EVENT_MAX
SESSION_EVENT_MAX,
};
union ip_address
{
struct in_addr v4; /* network order */
struct in6_addr v6; /* network order */
};
enum ip_type
{
IP_TYPE_V4,
IP_TYPE_V6,
};
struct session_key
{
enum ip_type ip_type;
// six tuple
union ip_address src_addr; /* network order */
union ip_address dst_addr; /* network order */
uint16_t src_port; /* network order */
uint16_t dst_port; /* network order */
uint16_t ip_proto; /* network order */
uint64_t security_zone;
};
struct metadata
{
char data[64]; // TODO
@@ -47,6 +71,15 @@ struct metadata
struct session;
/******************************************************************************
* session key
******************************************************************************/
uint32_t session_key_hash(const struct session_key *key);
int session_key_cmp(const struct session_key *key1, const struct session_key *key2);
void session_key_reverse(const struct session_key *in, struct session_key *out);
void session_key_tostring(const struct session_key *key, char *buf, uint32_t buf_len);
/******************************************************************************
* session base info
******************************************************************************/
@@ -57,9 +90,9 @@ void session_init(struct session *sess);
void session_set_id(struct session *sess, uint64_t id);
uint64_t session_get_id(struct session *sess);
// session address
void session_set_address(struct session *sess, struct session_address *addr);
struct session_address *session_get0_address(struct session *sess);
// session key
void session_set_key(struct session *sess, struct session_key *key);
struct session_key *session_get0_key(struct session *sess);
// session state
void session_set_state(struct session *sess, enum session_state state);

View File

@@ -1,185 +0,0 @@
#include <string.h>
#include <stdio.h>
#include "session_address.h"
void session_address_init(struct session_address *addr, const struct packet *packet)
{
memset(addr, 0, sizeof(struct session_address));
// TODO
}
void session_address_tostring(const struct session_address *addr, char *buf, size_t len)
{
char *ptr = buf;
size_t used = 0;
size_t tlen = 0;
for (int i = 0; i < addr->used; i++)
{
const struct layer_tuple *tuple = &addr->layers[i];
switch (tuple->type)
{
case LAYER_IPV4:
if (len - used < 32)
{
return;
}
inet_ntop(AF_INET, &tuple->tuple.ipv4.src, ptr, len - used);
tlen = strlen(ptr);
used += tlen;
ptr += tlen;
*ptr++ = '-';
used += 1;
inet_ntop(AF_INET, &tuple->tuple.ipv4.dst, ptr, len - used);
tlen = strlen(ptr);
used += tlen;
ptr += tlen;
*ptr++ = '/';
used += 1;
break;
case LAYER_IPV6:
if (len - used < 64)
{
return;
}
inet_ntop(AF_INET6, &tuple->tuple.ipv6.src, ptr, len - used);
tlen = strlen(ptr);
used += tlen;
ptr += tlen;
*ptr++ = '-';
used += 1;
inet_ntop(AF_INET6, &tuple->tuple.ipv6.dst, ptr, len - used);
tlen = strlen(ptr);
used += tlen;
ptr += tlen;
*ptr++ = '/';
used += 1;
break;
case LAYER_TCP:
if (len - used < 16)
{
return;
}
snprintf(ptr, len - used, "%u-%u", ntohs(tuple->tuple.tcp.src), ntohs(tuple->tuple.tcp.dst));
tlen = strlen(ptr);
used += tlen;
ptr += tlen;
*ptr++ = '/';
used += 1;
break;
case LAYER_UDP:
if (len - used < 16)
{
return;
}
snprintf(ptr, len - used, "%u-%u", ntohs(tuple->tuple.udp.src), ntohs(tuple->tuple.udp.dst));
tlen = strlen(ptr);
used += tlen;
ptr += tlen;
*ptr++ = '/';
used += 1;
break;
default:
return;
}
}
}
void session_address_reverse(struct session_address *addr)
{
for (int i = 0; i < addr->used; i++)
{
struct layer_tuple *tuple = &addr->layers[i];
switch (tuple->type)
{
case LAYER_IPV4:
{
struct in_addr tmp = tuple->tuple.ipv4.src;
tuple->tuple.ipv4.src = tuple->tuple.ipv4.dst;
tuple->tuple.ipv4.dst = tmp;
break;
}
case LAYER_IPV6:
{
struct in6_addr tmp = tuple->tuple.ipv6.src;
tuple->tuple.ipv6.src = tuple->tuple.ipv6.dst;
tuple->tuple.ipv6.dst = tmp;
break;
}
case LAYER_TCP:
{
uint16_t tmp = tuple->tuple.tcp.src;
tuple->tuple.tcp.src = tuple->tuple.tcp.dst;
tuple->tuple.tcp.dst = tmp;
break;
}
case LAYER_UDP:
{
uint16_t tmp = tuple->tuple.udp.src;
tuple->tuple.udp.src = tuple->tuple.udp.dst;
tuple->tuple.udp.dst = tmp;
break;
}
default:
return;
}
}
}
// cmp src and dst
// return: src - dst
int session_address_selfcmp(struct session_address *addr)
{
int ret = 0;
for (int i = 0; i < addr->used; i++)
{
struct layer_tuple *tuple = &addr->layers[i];
switch (tuple->type)
{
case LAYER_IPV4:
{
ret = tuple->tuple.ipv4.src.s_addr - tuple->tuple.ipv4.dst.s_addr;
if (ret != 0)
{
return ret;
}
break;
}
case LAYER_IPV6:
{
for (int j = 0; j < 16; j++)
{
ret = tuple->tuple.ipv6.src.s6_addr[j] - tuple->tuple.ipv6.dst.s6_addr[j];
if (ret != 0)
{
return ret;
}
}
break;
}
case LAYER_TCP:
{
ret = tuple->tuple.tcp.src - tuple->tuple.tcp.dst;
if (ret != 0)
{
return ret;
}
break;
}
case LAYER_UDP:
{
ret = tuple->tuple.udp.src - tuple->tuple.udp.dst;
if (ret != 0)
{
return ret;
}
break;
}
default:
break;
}
}
return 0;
}

View File

@@ -1,74 +0,0 @@
#ifndef _SESSION_ADDRESS_H
#define _SESSION_ADDRESS_H
#ifdef __cpluscplus
extern "C"
{
#endif
#include <arpa/inet.h>
#include "packet.h"
#define SESSION_ADDR_MAX_LAYER 8
enum layer_type
{
LAYER_IPV4 = 0,
LAYER_IPV6 = 1,
LAYER_TCP = 2,
LAYER_UDP = 3,
};
struct ipv4_address
{
struct in_addr src; /* network order */
struct in_addr dst; /* network order */
};
struct ipv6_address
{
struct in6_addr src; /* network order */
struct in6_addr dst; /* network order */
};
struct tcp_port
{
uint16_t src; /* network order */
uint16_t dst; /* network order */
};
struct udp_port
{
uint16_t src; /* network order */
uint16_t dst; /* network order */
};
struct layer_tuple
{
enum layer_type type;
union
{
struct ipv4_address ipv4;
struct ipv6_address ipv6;
struct tcp_port tcp;
struct udp_port udp;
} tuple;
};
struct session_address
{
uint8_t used;
struct layer_tuple layers[SESSION_ADDR_MAX_LAYER];
};
void session_address_init(struct session_address *addr, const struct packet *packet);
void session_address_tostring(const struct session_address *addr, char *buf, size_t len);
void session_address_reverse(struct session_address *addr);
int session_address_selfcmp(struct session_address *addr);
#ifdef __cpluscplus
}
#endif
#endif

View File

@@ -28,12 +28,12 @@ struct session_manager
* private API
******************************************************************************/
static void session_manager_handle_new_session(struct session_manager *mgr, struct session *sess, const struct packet *pkt, struct session_address *addr)
static void session_manager_handle_new_session(struct session_manager *mgr, struct session_key *key, struct session *sess, const struct packet *pkt)
{
// TODO
}
static void session_manager_handle_old_session(struct session_manager *mgr, struct session *sess, const struct packet *pkt, struct session_address *addr)
static void session_manager_handle_old_session(struct session_manager *mgr, struct session_key *key, struct session *sess, const struct packet *pkt)
{
// TODO
}
@@ -95,7 +95,7 @@ static void handshake_expire_cb(struct session *sess, void *arg)
assert(mgr != NULL);
session_set_state(sess, SESSION_STATE_DISCARD);
session_push_event(sess, SESSION_EVENT_DISCARD);
session_push_event(sess, SESSION_EVENT_CLOSING);
session_manager_enqueue_ready_session(mgr, sess);
}
@@ -168,24 +168,12 @@ void session_manager_set_session_eventcb(struct session_manager *mgr, session_ev
mgr->arg = arg;
}
struct session *session_manager_find_session_by_id(struct session_manager *mgr, uint64_t id)
struct session *session_manager_find_sessions(struct session_manager *mgr, const struct packet *pkt)
{
struct session *sess = session_table_find_session_by_id(mgr->sess_table, id);
if (sess)
{
session_set_last_time(sess, timestamp_get_msec());
// TODO
}
struct session_key key;
// TODO packet to key
return sess;
}
struct session *session_manager_find_session_by_packet(struct session_manager *mgr, const struct packet *pkt)
{
struct session_address addr;
session_address_init(&addr, pkt);
struct session *sess = session_table_find_session_by_addr(mgr->sess_table, &addr);
struct session *sess = session_table_find_session(mgr->sess_table, &key);
if (sess == NULL)
{
if (session_pool_get_count(mgr->sess_pool) == 1)
@@ -193,18 +181,18 @@ struct session *session_manager_find_session_by_packet(struct session_manager *m
struct session *oldest_sess = session_table_find_oldest_session(mgr->sess_table);
assert(oldest_sess == NULL);
session_set_state(oldest_sess, SESSION_STATE_DISCARD);
session_push_event(oldest_sess, SESSION_EVENT_DISCARD);
session_push_event(oldest_sess, SESSION_EVENT_CLOSING);
session_manager_enqueue_ready_session(mgr, oldest_sess);
}
sess = session_pool_alloc(mgr->sess_pool);
assert(sess != NULL);
session_manager_handle_new_session(mgr, sess, pkt, &addr);
session_manager_handle_new_session(mgr, &key, sess, pkt);
}
else
{
session_manager_handle_old_session(mgr, sess, pkt, &addr);
session_manager_handle_old_session(mgr, &key, sess, pkt);
}
return sess;

View File

@@ -12,7 +12,7 @@ extern "C"
* session manager = session pool + session table + session timer
*
* session pool : alloc and free session
* session table : find session by session id or session addr
* session table : find session by session key
* session timer : session timeout
* session manager: manage session pool, session table and session timer
*/
@@ -23,10 +23,7 @@ void session_manager_destroy(struct session_manager *mgr);
typedef void (*session_event_cb)(struct session *sess, uint32_t event, void *arg);
void session_manager_set_session_eventcb(struct session_manager *mgr, session_event_cb cb, void *arg);
struct session *session_manager_find_session_by_id(struct session_manager *mgr, uint64_t id);
struct session *session_manager_find_session_by_packet(struct session_manager *mgr, const struct packet *pkt);
struct session *session_manager_find_session(struct session_manager *mgr, const struct packet *pkt);
void session_manager_dispatch(struct session_manager *mgr);
#ifdef __cpluscplus

View File

@@ -13,7 +13,6 @@ extern "C"
#include "timeout.h"
#include "uthash.h"
#include "session.h"
#include "session_address.h"
#define EX_DATA_MAX_COUNT 128
#define SESSION_EVENT_QUEUE_SIZE 256
@@ -27,6 +26,9 @@ struct event_queue
struct session
{
// session id
uint64_t id;
// session state
enum session_state state;
@@ -81,15 +83,13 @@ struct session
******************************/
// session table key
uint64_t id;
struct session_address addr;
struct session_key key;
struct session *next_ptr;
struct session *prev_ptr;
// session table handle
UT_hash_handle hh1; /* handle for root_id hash table */
UT_hash_handle hh2; /* handle for root_addr hash table */
UT_hash_handle hh;
/******************************
* Session Manager Zone

View File

@@ -1,12 +1,13 @@
#include <assert.h>
#define HASH_FUNCTION(keyptr, keylen, hashv) HASH_FUNCTION_OVERWRITE(keyptr, keylen, &hashv)
#define HASH_KEYCMP(a, b, len) HASH_KEYCMP_OVERWRITE(a, b, len)
#include "session_table.h"
#include "session_private.h"
struct session_table
{
struct session *root_id;
struct session *root_addr;
struct session *root;
session_free_cb free_cb;
void *arg;
uint64_t count;
@@ -15,6 +16,35 @@ struct session_table
struct session *newest_ptr;
};
/******************************************************************************
* Private API
******************************************************************************/
static void HASH_FUNCTION_OVERWRITE(const struct session_key *key, unsigned int keylen, uint32_t *hashv)
{
*hashv = session_key_hash(key);
}
static int HASH_KEYCMP_OVERWRITE(const void *key1, const void *key2, size_t len)
{
struct session_key *sess_key1 = (struct session_key *)key1;
struct session_key *sess_key2 = (struct session_key *)key2;
if (session_key_cmp(sess_key1, sess_key2) == 0)
{
return 0;
}
struct session_key reverse_key;
session_key_reverse(sess_key2, &reverse_key);
if (session_key_cmp(sess_key1, &reverse_key) == 0)
{
return 0;
}
return -1;
}
static void session_table_add_session_to_linklist(struct session_table *table, struct session *sess)
{
if (table == NULL || sess == NULL)
@@ -69,6 +99,10 @@ static void session_table_del_session_from_linklist(struct session_table *table,
sess->next_ptr = NULL;
}
/******************************************************************************
* Public API
******************************************************************************/
struct session_table *session_table_create()
{
struct session_table *table = (struct session_table *)calloc(1, sizeof(struct session_table));
@@ -85,17 +119,14 @@ void session_table_destroy(struct session_table *table)
{
struct session *node = NULL;
struct session *tmp = NULL;
HASH_ITER(hh1, table->root_id, node, tmp)
HASH_ITER(hh, table->root, node, tmp)
{
HASH_DELETE(hh1, table->root_id, node);
HASH_DELETE(hh2, table->root_addr, node);
HASH_DELETE(hh, table->root, node);
if (table->free_cb && node)
{
table->free_cb(node, table->arg);
}
}
table->count--;
free(table);
@@ -122,86 +153,48 @@ void session_table_set_freecb(struct session_table *table, session_free_cb free_
}
}
int session_table_add_session(struct session_table *table, struct session *sess)
int session_table_add_session(struct session_table *table, const struct session_key *key, struct session *sess)
{
if (table == NULL || sess == NULL)
{
return -1;
}
if (session_table_find_session_by_id(table, sess->id) || session_table_find_session_by_addr(table, &sess->addr))
if (session_table_find_session(table, key))
{
return -1;
}
if (session_address_selfcmp(&sess->addr) > 0)
{
session_address_reverse(&sess->addr);
}
HASH_ADD(hh1, table->root_id, id, sizeof(sess->id), sess);
HASH_ADD(hh2, table->root_addr, addr, sizeof(sess->addr), sess);
HASH_ADD(hh, table->root, key, sizeof(sess->key), sess);
session_table_add_session_to_linklist(table, sess);
table->count++;
return 0;
}
void session_table_delete_session_by_id(struct session_table *table, uint64_t id)
void session_table_delete_session(struct session_table *table, const struct session_key *key)
{
if (table == NULL)
{
return;
}
struct session *sess = session_table_find_session_by_id(table, id);
struct session *sess = session_table_find_session(table, key);
if (sess == NULL)
{
return;
}
HASH_DELETE(hh1, table->root_id, sess);
HASH_DELETE(hh2, table->root_addr, sess);
HASH_DELETE(hh, table->root, sess);
if (table->free_cb && sess)
{
table->free_cb(sess, table->arg);
}
session_table_del_session_from_linklist(table, sess);
table->count--;
}
void session_table_delete_session_by_addr(struct session_table *table, struct session_address *addr)
{
if (table == NULL)
{
return;
}
struct session *sess = session_table_find_session_by_addr(table, addr);
if (sess == NULL)
{
return;
}
HASH_DELETE(hh1, table->root_id, sess);
HASH_DELETE(hh2, table->root_addr, sess);
if (table->free_cb && sess)
{
table->free_cb(sess, table->arg);
}
session_table_del_session_from_linklist(table, sess);
table->count--;
}
struct session *session_table_find_session_by_id(struct session_table *table, uint64_t id)
struct session *session_table_find_session(struct session_table *table, const struct session_key *key)
{
if (table == NULL)
{
@@ -209,25 +202,7 @@ struct session *session_table_find_session_by_id(struct session_table *table, ui
}
struct session *sess = NULL;
HASH_FIND(hh1, table->root_id, &id, sizeof(id), sess);
return sess;
}
struct session *session_table_find_session_by_addr(struct session_table *table, struct session_address *addr)
{
if (table == NULL)
{
return NULL;
}
if (session_address_selfcmp(addr) > 0)
{
session_address_reverse(addr);
}
struct session *sess = NULL;
HASH_FIND(hh2, table->root_addr, addr, sizeof(struct session_address), sess);
HASH_FIND(hh, table->root, key, sizeof(struct session_key), sess);
return sess;
}

View File

@@ -17,11 +17,9 @@ typedef void (*session_free_cb)(struct session *sess, void *arg);
void session_table_set_freecb(struct session_table *table, session_free_cb free_cb, void *arg);
// return 0: success
// return -1: failed
int session_table_add_session(struct session_table *table, struct session *sess);
void session_table_delete_session_by_id(struct session_table *table, uint64_t id);
void session_table_delete_session_by_addr(struct session_table *table, struct session_address *addr);
struct session *session_table_find_session_by_id(struct session_table *table, uint64_t id);
struct session *session_table_find_session_by_addr(struct session_table *table, struct session_address *addr);
int session_table_add_session(struct session_table *table, const struct session_key *key, struct session *sess);
void session_table_delete_session(struct session_table *table, const struct session_key *key);
struct session *session_table_find_session(struct session_table *table, const struct session_key *key);
struct session *session_table_find_oldest_session(struct session_table *table);
struct session *session_table_find_newest_session(struct session_table *table);