stcp: ed25519 pubkey exchange in handshake, fix instance destroy segfault, fix chat_tcp_test
- u_async.c: process immediate_queue BEFORE epoll_wait in uasync_poll - stcp_link.c: defensive NULL etcp_conn/etcp_link in stcp_link_close - utun_instance.c: move stcp_server_list_destroy_all to Phase J (before ETCP), add deferred drain in both Phase J and L - stcp.h/c: STCP_HS_ENC_CLIENT 6→38, STCP_HS_ENC_SERVER 7→39, exchange ed25519_pubkey in both handshake directions - etcp_connections.c: copy peer_ed25519 from STCP to ETCP_CONN in etcp_link_enter_ready_tcp; guard link->etcp in tcp_link_close_cb - chat_sync.c: fix lk->conn NULL dereference for TCP links - test_stcp.c: update stcp_server_create/stcp_client_connect callsites - tools/chat_tcp_test: change transport udp→tcp
This commit is contained in:
1 parent
a3783b5f55
commit
38c9f229bc
1272 files changed
+968388
-1
No files matched your search
@@ -0,0 +1,160 @@
|
||||
// memory_pool.c
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include "memory_pool.h"
|
||||
#include "mem.h"
|
||||
|
||||
// Layout: [user_data: object_size] [canary: 4 bytes] [alloc_loc: pointer] [counter: 1 byte]
|
||||
#define POOL_CANARY_OFF (pool->object_size)
|
||||
#define POOL_LOC_OFF (pool->object_size + 4)
|
||||
#define POOL_COUNTER_OFF (pool->object_size + 4 + sizeof(const char*))
|
||||
#define POOL_ALLOC_SIZE (pool->object_size + 4 + sizeof(const char*) + 1)
|
||||
#define POOL_CANARY_VAL 0xDEADBEAF
|
||||
|
||||
static void pool_init_tags(struct memory_pool* pool, void* obj, const char* location)
|
||||
{
|
||||
uint32_t* canary = (uint32_t*)((uint8_t*)obj + POOL_CANARY_OFF);
|
||||
const char** loc = (const char**)((uint8_t*)obj + POOL_LOC_OFF);
|
||||
uint8_t* counter = (uint8_t*)obj + POOL_COUNTER_OFF;
|
||||
*canary = POOL_CANARY_VAL;
|
||||
*loc = location;
|
||||
*counter = 1;
|
||||
}
|
||||
|
||||
static void pool_check_and_clear_tags(struct memory_pool* pool, void* obj, const char* location)
|
||||
{
|
||||
uint32_t* canary = (uint32_t*)((uint8_t*)obj + POOL_CANARY_OFF);
|
||||
const char** loc = (const char**)((uint8_t*)obj + POOL_LOC_OFF);
|
||||
uint8_t* counter = (uint8_t*)obj + POOL_COUNTER_OFF;
|
||||
|
||||
if (*canary != POOL_CANARY_VAL) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_SYS, "pool_free BUFFER OVERFLOW pool=%p name=%s sz=%zu allocs=%zu reuse=%zu free=%d",
|
||||
pool, pool->name ? pool->name : "?", pool->object_size, pool->allocations, pool->reuse_count, pool->free_count);
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_SYS, " obj=%p alloc=%s free=%s canary=0x%08x expected=0x%08x",
|
||||
obj, *loc ? *loc : "(null)", location, *canary, POOL_CANARY_VAL);
|
||||
if (pool->object_size)
|
||||
log_dump(DEBUG_LEVEL_ERROR, DEBUG_CATEGORY_SYS, " user_data", obj, pool->object_size);
|
||||
volatile int _halt = 1;
|
||||
while (_halt) {}
|
||||
}
|
||||
if (*counter == 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_SYS, "pool_free DOUBLE FREE pool=%p name=%s sz=%zu allocs=%zu reuse=%zu alloc=%s free=%s",
|
||||
pool, pool->name ? pool->name : "?", pool->object_size, pool->allocations, pool->reuse_count,
|
||||
*loc ? *loc : "(null)", location);
|
||||
volatile int _halt = 1;
|
||||
while (_halt) {}
|
||||
}
|
||||
*counter = 0;
|
||||
}
|
||||
|
||||
static size_t g_total_free = 0;
|
||||
|
||||
size_t memory_pool_get_total_free_blocks(void) {
|
||||
return g_total_free;
|
||||
}
|
||||
|
||||
// Инициализировать пул памяти
|
||||
struct memory_pool* memory_pool_init(size_t object_size, const char* name) {
|
||||
struct memory_pool* pool = u_calloc(1, sizeof(struct memory_pool));
|
||||
if (!pool) {
|
||||
return NULL;
|
||||
}
|
||||
pool->free_head = NULL;
|
||||
pool->object_size = object_size;
|
||||
pool->free_count = 0;
|
||||
pool->allocations = 0;
|
||||
pool->reuse_count = 0;
|
||||
pool->alloc_tag_counter = 1;
|
||||
pool->name = name;
|
||||
return pool;
|
||||
}
|
||||
|
||||
// Выделить объект из пула или из malloc
|
||||
void* memory_pool_alloc_impl(struct memory_pool* pool, const char* location) {
|
||||
if (!pool) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pool->free_head) {
|
||||
void* obj = pool->free_head;
|
||||
pool->free_head = *(void**)obj;
|
||||
pool->free_count--;
|
||||
g_total_free--;
|
||||
pool->reuse_count++;
|
||||
memset(obj, 0, pool->object_size);
|
||||
pool_init_tags(pool, obj, location);
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_SYS, "pool_alloc reused: %s, remaining=%zu", location, pool->free_count);
|
||||
return obj;
|
||||
}
|
||||
|
||||
pool->allocations++;
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_SYS, "pool_alloc: %s, total_allocs=%zu", location, pool->allocations);
|
||||
void* obj = u_calloc_impl(1, POOL_ALLOC_SIZE, location);
|
||||
if (obj) pool_init_tags(pool, obj, location);
|
||||
return obj;
|
||||
}
|
||||
|
||||
// Освободить объект в пул или в free
|
||||
void memory_pool_free_impl(struct memory_pool* pool, void* obj, const char* location) {
|
||||
if (!pool || !obj) {
|
||||
return;
|
||||
}
|
||||
|
||||
pool_check_and_clear_tags(pool, obj, location);
|
||||
|
||||
if (pool->free_count < MEMORY_POOL_MAX_FREE) {
|
||||
*(void**)obj = pool->free_head;
|
||||
pool->free_head = obj;
|
||||
pool->free_count++;
|
||||
g_total_free++;
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_SYS, "pool_free returned: %s, free_count=%zu", location, pool->free_count);
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_SYS, "pool_free direct: %s", location);
|
||||
u_free_impl(obj, location);
|
||||
}
|
||||
|
||||
// Получить статистику пула
|
||||
void memory_pool_get_stats(struct memory_pool* pool, size_t* allocations, size_t* reuse_count) {
|
||||
if (!pool) {
|
||||
return;
|
||||
}
|
||||
if (allocations) {
|
||||
*allocations = pool->allocations;
|
||||
}
|
||||
if (reuse_count) {
|
||||
*reuse_count = pool->reuse_count;
|
||||
}
|
||||
}
|
||||
|
||||
// Очистить пул памяти
|
||||
void memory_pool_destroy(struct memory_pool* pool) {
|
||||
if (!pool) {
|
||||
return;
|
||||
}
|
||||
|
||||
void* obj = pool->free_head;
|
||||
while (obj) {
|
||||
void* next = *(void**)obj;
|
||||
g_total_free--;
|
||||
u_free(obj);
|
||||
obj = next;
|
||||
}
|
||||
|
||||
pool->free_head = NULL;
|
||||
pool->free_count = 0;
|
||||
u_free(pool);
|
||||
}
|
||||
|
||||
int memory_pool_is_freed(struct memory_pool* pool, void* obj)
|
||||
{
|
||||
if (!pool || !obj) return 0;
|
||||
void* cur = pool->free_head;
|
||||
while (cur) {
|
||||
if (cur == obj) return 1;
|
||||
cur = *(void**)cur;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Reference in new issue
Block a user