Browse Source

+memory check module

fix double free @routing
nodeinfo-routing-update
jeka 4 weeks ago
parent
commit
066a9aa89e
  1. 204
      filelist.txt
  2. 1
      lib/Makefile.am
  3. 174
      lib/ll_queue.h1
  4. 3
      lib/memory_pool.c
  5. 10
      lib/timeout_heap.c
  6. 6
      lib/u_async.c
  7. 7
      net_emulator/net_emulator.c
  8. 5
      src/Makefile.am
  9. 2
      src/config_parser.c
  10. 22
      src/routing.c
  11. 4
      tests/Makefile.am
  12. 8
      tests/test_etcp_two_instances.c
  13. 1
      tests/test_u_async_comprehensive.c

204
filelist.txt

@ -1,40 +1,164 @@
lib/debug_config.c
lib/debug_config.h
lib/ll_queue.c
lib/ll_queue.h
lib/memory_pool.c
lib/memory_pool.h
lib/sha256.c
lib/sha256.h
lib/test_size.c
lib/timeout_heap.c
lib/timeout_heap.h
lib/u_async.c
lib/u_async.h
src/config_parser.c
src/config_parser.h
src/config_updater.c
src/config_updater.h
src/crc32.c
src/crc32.h
src/etcp.c
src/etcp.h
src/etcp_connections.c
src/etcp_connections.h
src/etcp_loadbalancer.c
src/etcp_loadbalancer.h
src/packet_dump.h
src/packet_dump.c
src/pkt_normalizer.c
src/pkt_normalizer.h
src/route_lib.c
src/route_lib.h
src/routing.c
src/routing.h
src/secure_channel.c
src/secure_channel.h
src/tun_if.c
src/tun_if.h
src/utun.c
src/utun_instance.c
src/utun_instance.h
config.h
lib\debug_config.c
lib\debug_config.h
lib\ll_queue.c
lib\ll_queue.h
lib\mem.c
lib\mem.h
lib\memory_pool.c
lib\memory_pool.h
lib\platform_compat.c
lib\platform_compat.h
lib\sha256.c
lib\sha256.h
lib\socket_compat.c
lib\socket_compat.h
lib\timeout_heap.c
lib\timeout_heap.h
lib\u_async.c
lib\u_async.h
lib\wintun.h
net_emulator\net_emulator.c
net_emulator\net_emulator.h
src\config_parser.c
src\config_parser.h
src\config_updater.c
src\config_updater.h
src\control_server.c
src\control_server.h
src\crc32.c
src\crc32.h
src\dummynet.c
src\dummynet.h
src\etcp.c
src\etcp.h
src\etcp_api.c
src\etcp_api.h
src\etcp_connections.c
src\etcp_connections.h
src\etcp_debug.c
src\etcp_debug.h
src\etcp_loadbalancer.c
src\etcp_loadbalancer.h
src\packet_dump.c
src\packet_dump.h
src\pkt_normalizer.c
src\pkt_normalizer.h
src\route_bgp.c
src\route_bgp.h
src\route_lib.c
src\route_lib.h
src\routing.c
src\routing.h
src\secure_channel.c
src\secure_channel.h
src\tun_if.c
src\tun_if.h
src\tun_linux.c
src\tun_route.c
src\tun_route.h
src\tun_windows.c
src\utun.c
src\utun_instance.c
src\utun_instance.h
tests\bench_timeout_heap.c
tests\bench_uasync_timeouts.c
tests\debug_full_test.c
tests\debug_performance.c
tests\debug_simple.c
tests\detailed_test.c
tests\simple_test.c
tests\test_bgp_route_exchange.c
tests\test_config_debug.c
tests\test_control_server.c
tests\test_control_simple.c
tests\test_crash_debug.c
tests\test_crypto.c
tests\test_debug_categories.c
tests\test_dummynet.c
tests\test_ecc_encrypt.c
tests\test_etcp_100_packets.c
tests\test_etcp_api.c
tests\test_etcp_crypto.c
tests\test_etcp_dummynet.c
tests\test_etcp_exit.c
tests\test_etcp_link_id.c
tests\test_etcp_minimal.c
tests\test_etcp_simple_traffic.c
tests\test_etcp_two_instances.c
tests\test_intensive_memory_pool.c
tests\test_intensive_memory_pool_new.c
tests\test_ll_queue.c
tests\test_memory_pool_and_config.c
tests\test_minimal.c
tests\test_minimal_exit.c
tests\test_offset.c
tests\test_packet_dump.c
tests\test_pkt_normalizer_etcp.c
tests\test_pkt_normalizer_standalone.c
tests\test_poll_exact.c
tests\test_poll_multi.c
tests\test_route_lib.c
tests\test_routing_mesh.c
tests\test_simple.c
tests\test_simple2.c
tests\test_socket.c
tests\test_utils.h
tests\test_u_async_comprehensive.c
tests\test_u_async_performance.c
tests\track_test.c
tests\working_crypto_test.c
tinycrypt\lib\include\tinycrypt\aes.h
tinycrypt\lib\include\tinycrypt\cbc_mode.h
tinycrypt\lib\include\tinycrypt\ccm_mode.h
tinycrypt\lib\include\tinycrypt\cmac_mode.h
tinycrypt\lib\include\tinycrypt\constants.h
tinycrypt\lib\include\tinycrypt\ctr_mode.h
tinycrypt\lib\include\tinycrypt\ctr_prng.h
tinycrypt\lib\include\tinycrypt\ecc.h
tinycrypt\lib\include\tinycrypt\ecc_dh.h
tinycrypt\lib\include\tinycrypt\ecc_dsa.h
tinycrypt\lib\include\tinycrypt\ecc_platform_specific.h
tinycrypt\lib\include\tinycrypt\hmac.h
tinycrypt\lib\include\tinycrypt\hmac_prng.h
tinycrypt\lib\include\tinycrypt\sha256.h
tinycrypt\lib\include\tinycrypt\utils.h
tinycrypt\lib\source\aes_decrypt.c
tinycrypt\lib\source\aes_encrypt.c
tinycrypt\lib\source\cbc_mode.c
tinycrypt\lib\source\ccm_mode.c
tinycrypt\lib\source\cmac_mode.c
tinycrypt\lib\source\ctr_mode.c
tinycrypt\lib\source\ctr_prng.c
tinycrypt\lib\source\ecc.c
tinycrypt\lib\source\ecc_dh.c
tinycrypt\lib\source\ecc_dsa.c
tinycrypt\lib\source\ecc_platform_specific.c
tinycrypt\lib\source\hmac.c
tinycrypt\lib\source\hmac_prng.c
tinycrypt\lib\source\sha256.c
tinycrypt\lib\source\utils.c
tinycrypt\tests\test_aes.c
tinycrypt\tests\test_cbc_mode.c
tinycrypt\tests\test_ccm_mode.c
tinycrypt\tests\test_client_server.c
tinycrypt\tests\test_cmac_mode.c
tinycrypt\tests\test_ctr_mode.c
tinycrypt\tests\test_ctr_prng.c
tinycrypt\tests\test_ecc_dh.c
tinycrypt\tests\test_ecc_dsa.c
tinycrypt\tests\test_ecc_utils.c
tinycrypt\tests\test_hmac.c
tinycrypt\tests\test_hmac_prng.c
tinycrypt\tests\test_sha256.c
tinycrypt\tests\include\test_ecc_utils.h
tinycrypt\tests\include\test_utils.h
tools\bping\bping.c
tools\etcpmon\etcpmon_client.c
tools\etcpmon\etcpmon_client.h
tools\etcpmon\etcpmon_graph.c
tools\etcpmon\etcpmon_graph.h
tools\etcpmon\etcpmon_gui.c
tools\etcpmon\etcpmon_gui.h
tools\etcpmon\etcpmon_main.c
tools\etcpmon\etcpmon_protocol.h

1
lib/Makefile.am

@ -23,6 +23,7 @@ libuasync_a_SOURCES = \
libuasync_a_CFLAGS = \
-D_ISOC99_SOURCE \
-DDEBUG_OUTPUT_STDERR \
-g \
-I$(top_srcdir)/src \
-I$(top_srcdir)/lib

174
lib/ll_queue.h1

@ -1,174 +0,0 @@
// ll_queue.h - Упрощенная архитектура: разделение создания элементов и работы с очередью
#ifndef LL_QUEUE_H
#define LL_QUEUE_H
#include <stddef.h> // для size_t
#include <stdint.h> // для uint64_t
#include "memory_pool.h" // для struct memory_pool
// Предварительные объявления
struct ll_queue;
struct ll_entry;
struct queue_waiter;
struct memory_pool;
struct UASYNC;
// Автозабор элемента из очереди. вызывается когда в очереди что-то есть и коллбэк не занят обработкой.
// Параметры: указатель на очередь, указатель на структуру элемента (struct ll_entry*), пользовательский аргумент
// Когда коллбэк закончит обрабатывать элемент он должен вызвать queue_resume_callback - сообщить о готовности получить следующий элемент (приём очередным вызовом коллбэка в следующем цикле mainloop).
typedef void (*queue_callback_fn)(struct ll_queue* q, void* arg);
// Структура элемента - переменный размер, данные расположены сразу после структуры
struct ll_entry {
struct ll_entry* next; // Указатель на следующий элемент в очереди
struct ll_entry* prev; // Указатель на предыдущий элемент в очереди
uint16_t size; // Размер доступной памяти после блока ll_entry - т.е. data[size]. используется для добавления доп. параметров
uint16_t len; // размер пакета (dgram)
uint16_t memlen; // размер выделенной памяти (dgram)
uint16_t int_len; // размер (private, not use!)
uint8_t* dgram; // данные пакета
void (*dgram_free_fn)(uint8_t* data, void* arg); // функция освобождения блока
struct memory_pool* dgram_pool; // Пул, из которого выделен этот элемент (NULL, если выделен через malloc)
uint32_t id; // Идентификатор для хеш-поиска
struct ll_entry* hash_next; // Следующий в хеш-цепочке
struct memory_pool* pool; // Пул, из которого выделен этот элемент (NULL, если выделен через malloc)
uint8_t data[0];
};
// Ожидающий добавления элементов в очередь (пока очередь не освободться до нужного размера чтобы не забивать)
struct queue_waiter {
int max_packets; // Максимальное количество пакетов
size_t max_bytes; // Максимальное количество байт (0 = не проверять байты)
void (*callback)(struct ll_queue* q, void* arg); // Коллбэк для вызова
void* callback_arg; // Аргумент коллбэка
};
typedef void (*queue_threshold_callback_fn)(struct ll_queue* q, void* arg);
// Структура очереди
struct ll_queue {
struct ll_entry* head; // Первый элемент (извлекается отсюда)
struct ll_entry* tail; // Последний элемент (добавляется сюда)
int count; // Текущее количество элементов
size_t total_bytes; // Общий размер данных всех элементов (байт)
int size_limit; // Максимальное количество (-1 = без ограничения)
queue_callback_fn callback; // Функция коллбэка
void* callback_arg; // Пользовательский аргумент для коллбэка
int callback_suspended;
void* resume_timeout_id; // ID таймаута uasync для отложенного возобновления
struct UASYNC* ua; // Экземпляр uasync для таймеров
struct queue_waiter waiter; // Встроенный одиночный waiter
// Хеш-таблица для быстрого поиска по ID
struct ll_entry** hash_table;
size_t hash_size;
};
// ==================== Управление очередью ====================
// Создать новую пустую очередь
// ua - экземпляр uasync для таймеров (обязательный параметр)
// hash_size - размер хеш-таблицы для быстрого поиска (0 = без хеш-таблицы)
// Возвращает: указатель на очередь или NULL при ошибке выделения памяти
struct ll_queue* queue_new(struct UASYNC* ua, size_t hash_size);
// Освободить очередь и все её элементы
// ВАЖНО: освобождает только структуру очереди, элементы в очереди НЕ освобождаются!
// Элементы должны быть предварительно извлечены через queue_data_get() и освобождены через queue_data_free()
void queue_free(struct ll_queue* q);
// Установить максимальное количество элементов в очереди
// При превышении лимита новый элемент автоматически освобождается
void queue_set_size_limit(struct ll_queue* q, int lim);
// ==================== Асинхронное ожидание передачи ====================
// Зарегистрировать одноразовый коллбэк, который будет вызван когда очередь будет иметь
// не более max_packets пакетов и не более max_bytes байт (если max_bytes != 0).
// Если условие уже выполнено, коллбэк вызывается немедленно.
// Возвращает указатель на waiter для возможной отмены через queue_cancel_wait
struct queue_waiter* queue_wait_threshold(struct ll_queue* q, int max_packets, size_t max_bytes,
queue_threshold_callback_fn callback, void* arg);
// Отменить ожидание (удалить waiter из списка)
void queue_cancel_wait(struct ll_queue* q, struct queue_waiter* waiter);
// Получить общий размер данных в очереди (байт)
static inline size_t queue_total_bytes(struct ll_queue* q) {
if (!q) return 0;
return q->total_bytes;
}
// ==================== Асинхронное ожидание приёма ====================
// Установить функцию и аргумент коллбэка для автозабора из очереди
// Коллбэк вызывается когда в очереди есть элемент и разрешен коллбэк
// обработчик должен обработать этот пакет (может использовать асинхронное ожидание). Когда будет готов к приёму следующего - должен вызвать resume_callback. обработка строго по одному пакету.
void queue_set_callback(struct ll_queue* q, queue_callback_fn cbk_fn, void* arg);
// обрабатывается строго одина пакет за вызов
// Возобновить коллбэки после обработки элемента переданного в коллбэке (тянуть дополнительные элементы из очереди не предусмотернные api нельзя).
// эта функция должна вызываться всегда после того как cbk_fn обработала пакет (можно с ожиданием через async), иначе очередь застрянет.
// Если в очереди остались элементы, запланирует вызов коллбэка через uasync_set_timeout(0)
// Это предотвращает накопление рекурсии в стеке вызовов
void queue_resume_callback(struct ll_queue* q);
// ==================== Управление элементами ====================
// выделить ll_entry и память под кодограмму
struct ll_entry* ll_alloc_lldgram(uint16_t len);
// Создать новый элемент с областью данных указанного размера
// Память выделяется одним блоком: [struct ll_entry][область данных data_size байт]
// Возвращает: указатель на структуру элемента (struct ll_entry*) или NULL при ошибке выделения памяти
struct ll_entry* queue_entry_new(size_t data_size);
// Создать новый элемент из пула (размер был определен при создании пула)
// Возвращает: указатель на структуру элемента (struct ll_entry*) или NULL при ошибке выделения памяти
struct ll_entry* queue_entry_new_from_pool(struct memory_pool* pool);
// Освободить только entry (не влияет на очереди, dgram не освобождает)
void queue_entry_free(struct ll_entry* entry);
// Освободить только entry->dgram (не влияет на очереди)
void queue_dgram_free(struct ll_entry* entry);
//void queue_data_free(void* data);
// ==================== Операции с очередью ====================
// Добавить элемент в конец очереди (FIFO)
// Если очередь была пустой и коллбэки разрешены - вызывает коллбэк
// Возвращает: 0 при успехе, -1 если превышен лимит размера (элемент освобожден)
int queue_data_put(struct ll_queue* q, struct ll_entry* entry, uint32_t id);
// Добавить элемент в начало очереди (LIFO, высокий приоритет)
// Если очередь была пустой и коллбэки разрешены - вызывает коллбэк
// Возвращает: 0 при успехе, -1 если превышен лимит размера (элемент освобожден)
int queue_data_put_first(struct ll_queue* q, struct ll_entry* entry, uint32_t id);
// Извлечь элемент из начала очереди
// При извлечении приостанавливает коллбэки (callback_suspended = 1) чтобы предотвратить рекурсию
// Возвращает: указатель на структуру элемента (struct ll_entry*) или NULL если очередь пуста
// ПРИМЕЧАНИЕ: не освобождает память элемента
struct ll_entry* queue_data_get(struct ll_queue* q);
// Получить текущее количество элементов в очереди
int queue_entry_count(struct ll_queue* q);
// ==================== Поиск и удаление по ID ====================
// Найти элемент по ID
// Возвращает: указатель на структуру элемента (struct ll_entry*) или NULL если не найден
struct ll_entry* queue_find_data_by_id(struct ll_queue* q, uint32_t id);
// Удалить элемент из очереди по указателю на структуру элемента
// Возвращает: 0 при успехе, -1 если элемент не найден
// ПРИМЕЧАНИЕ: НЕ изменяет ref_count элемента, просто удаляет из очереди
int queue_remove_data(struct ll_queue* q, struct ll_entry* entry);
#endif // LL_QUEUE_H

3
lib/memory_pool.c

@ -1,7 +1,8 @@
// memory_pool.c
#include "memory_pool.h"
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "memory_pool.h"
#include "mem.h"
// Инициализировать пул памяти

10
lib/timeout_heap.c

@ -4,6 +4,7 @@
#include "debug_config.h"
#include <stdlib.h>
#include <stdio.h> // For potential error printing, optional
#include "mem.h"
// Helper macros for 1-based indices
#define PARENT(i) ((i) / 2)
@ -11,13 +12,20 @@
#define RIGHT_CHILD(i) (2 * (i) + 1)
TimeoutHeap *timeout_heap_create(size_t initial_capacity) {
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Creating TH1...");
TimeoutHeap *h = u_malloc(sizeof(TimeoutHeap));
if (!h) return NULL;
if (!h) {
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "TH0 error...");
return NULL;
}
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Creating TH2...");
h->heap = u_malloc(sizeof(TimeoutEntry) * initial_capacity);
if (!h->heap) {
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "TH1 error...");
u_free(h);
return NULL;
}
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Creating TH3...");
h->size = 0;
h->capacity = initial_capacity;
h->freed_count = 0;

6
lib/u_async.c

@ -1112,7 +1112,9 @@ struct UASYNC* uasync_create(void) {
ua->wakeup_initialized = 0;
ua->posted_tasks_head = NULL;
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Creating SA...");
ua->sockets = socket_array_create(16);
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Creating SA1...");
if (!ua->sockets) {
if (ua->wakeup_initialized) {
#ifdef _WIN32
@ -1146,6 +1148,7 @@ struct UASYNC* uasync_create(void) {
// Set callback to u_free timeout nodes and update counters
timeout_heap_set_free_callback(ua->timeout_heap, ua, timeout_node_free_callback);
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Creating TH1...");
// Initialize epoll on Linux
ua->epoll_fd = -1;
ua->use_epoll = 0;
@ -1168,6 +1171,8 @@ struct UASYNC* uasync_create(void) {
}
#endif
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Creating TH2...");
#ifdef _WIN32
// Windows: self-connected UDP socket for wakeup
SOCKET r = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
@ -1223,6 +1228,7 @@ struct UASYNC* uasync_create(void) {
pthread_mutex_init(&ua->posted_lock, NULL);
#endif
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Creating TH3...");
return ua;
}

7
net_emulator/net_emulator.c

@ -2,6 +2,7 @@
#define _POSIX_C_SOURCE 200809L
#include "net_emulator.h"
#include "u_async.h"
#include "mem.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -347,7 +348,7 @@ static void socket_callback(int fd, void *user_arg) {
g_packet_counter, delay_ms, selected_rule->probability_percent);
// Allocate packet buffer for delayed sending
delayed_packet_t *packet = malloc(sizeof(delayed_packet_t));
delayed_packet_t *packet = u_malloc(sizeof(delayed_packet_t));
if (!packet) {
fprintf(stderr, "Failed to allocate packet buffer\n");
return;
@ -372,7 +373,7 @@ static void socket_callback(int fd, void *user_arg) {
// Convert delay to u_async timebase (0.1ms)
int delay_tb = delay_ms * 10;
if (!ep->emulator || !ep->emulator->ua) {
free(packet);
u_free(packet);
return;
}
uasync_set_timeout(ep->emulator->ua, delay_tb, packet, (timeout_callback_t)send_delayed_packet);
@ -393,7 +394,7 @@ static void send_delayed_packet(void *user_arg) {
nsent, inet_ntoa(packet->to_addr.sin_addr), ntohs(packet->to_addr.sin_port));
}
free(packet);
u_free(packet);
}
// Initialize network emulator

5
src/Makefile.am

@ -25,7 +25,7 @@ utun_CORE_SOURCES = \
# Platform-specific TUN sources
if OS_WINDOWS
utun_TUN_SOURCES = tun_windows.c
utun_TUN_LIBS = -liphlpapi -lws2_32 -ladvapi32 -lbcrypt
utun_TUN_LIBS = -liphlpapi -lws2_32 -ladvapi32 -lbcrypt -ldbghelp
else
utun_TUN_SOURCES = tun_linux.c
utun_TUN_LIBS =
@ -59,6 +59,7 @@ utun_CORE_CFLAGS = \
-I$(top_srcdir)/lib \
-I$(top_srcdir)/tinycrypt/lib/include \
-I$(top_srcdir)/tinycrypt/lib/source \
-g \
$(DEBUG_FLAGS)
utun_CFLAGS = $(utun_CORE_CFLAGS)
@ -92,7 +93,7 @@ TINYCRYPT_OBJS = \
utun-utils.o
# Rules to build TinyCrypt objects (for tests)
TINYCRYPT_CFLAGS = -I$(top_srcdir)/tinycrypt/lib/include -I$(top_srcdir)/tinycrypt/lib/source
TINYCRYPT_CFLAGS = -g -I$(top_srcdir)/tinycrypt/lib/include -I$(top_srcdir)/tinycrypt/lib/source
utun-aes_encrypt.o: $(TINYCRYPT_SRCDIR)/aes_encrypt.c
$(AM_V_CC)$(COMPILE) $(TINYCRYPT_CFLAGS) -c -o $@ $<

2
src/config_parser.c

@ -38,7 +38,7 @@ static uint32_t parse_debug_categories(const char *value);
/* Parse debug categories from comma-separated string */
static uint32_t parse_debug_categories(const char *value) {
uint32_t categories = 0;
char *value_copy = strdup(value);
char *value_copy = u_strdup(value);
if (!value_copy) return DEBUG_CATEGORY_ALL; // Default to all on error
char *token = strtok(value_copy, ",");

22
src/routing.c

@ -164,6 +164,8 @@ static void routing_pkt_from_tun_cb(struct ll_queue* q, void* arg) {
struct ETCP_FRAGMENT* pkt = (struct ETCP_FRAGMENT*)queue_data_get(instance->tun->output_queue);
if (!pkt) return;
bool pkt_freed = false;
if (pkt->ll.dgram && pkt->ll.len > 0) {
dump_ip_packet("TUN->routing", (const uint8_t*)pkt->ll.dgram, pkt->ll.len);
@ -171,7 +173,9 @@ static void routing_pkt_from_tun_cb(struct ll_queue* q, void* arg) {
if (dst_ip == 0) {
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "Failed to extract destination IP, dropping packet");
u_free(pkt->ll.dgram);
pkt->ll.dgram = NULL;
memory_pool_free(instance->tun->pool, pkt);
pkt_freed = true;
} else {
struct in_addr addr;
addr.s_addr = htonl(dst_ip);
@ -180,24 +184,32 @@ static void routing_pkt_from_tun_cb(struct ll_queue* q, void* arg) {
if (!routes || routes->routes == 0) {
DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "No route to %s, dropping packet", ip_to_str(&addr, AF_INET).str);
u_free(pkt->ll.dgram);
pkt->ll.dgram = NULL;
memory_pool_free(instance->tun->pool, pkt);
pkt_freed = true;
} else {
struct ETCP_CONN* conn = routes->entries[0]->next_hop;
if (!conn) {
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "Route to %s has no next_hop, dropping packet", ip_to_str(&addr, AF_INET).str);
u_free(pkt->ll.dgram);
pkt->ll.dgram = NULL;
memory_pool_free(instance->tun->pool, pkt);
pkt_freed = true;
} else if (!conn->normalizer) {
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "Connection for %s has no normalizer, dropping packet", ip_to_str(&addr, AF_INET).str);
u_free(pkt->ll.dgram);
pkt->ll.dgram = NULL;
memory_pool_free(instance->tun->pool, pkt);
pkt_freed = true;
} else {
size_t etcp_data_len = 1 + pkt->ll.len;
struct ll_entry* entry = ll_alloc_lldgram(etcp_data_len);
if (!entry) {
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "Failed to allocate entry for ETCP send");
u_free(pkt->ll.dgram);
pkt->ll.dgram = NULL;
memory_pool_free(instance->tun->pool, pkt);
pkt_freed = true;
} else {
entry->dgram[0] = ETCP_ID_DATA;
memcpy(entry->dgram + 1, pkt->ll.dgram, pkt->ll.len);
@ -210,19 +222,23 @@ static void routing_pkt_from_tun_cb(struct ll_queue* q, void* arg) {
queue_dgram_free(entry);
}
u_free(pkt->ll.dgram);
memory_pool_free(instance->tun->pool, pkt);
goto cleanup;
}
}
}
}
} else {
memory_pool_free(instance->tun->pool, pkt);
pkt_freed = true;
}
cleanup:
if (!pkt_freed) {
if (pkt->ll.dgram) {
u_free(pkt->ll.dgram);
}
memory_pool_free(instance->tun->pool, pkt);
}
queue_resume_callback(instance->tun->output_queue);
}

4
tests/Makefile.am

@ -27,7 +27,7 @@ check_PROGRAMS = \
bench_uasync_timeouts
# Basic includes
AM_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/lib -I$(top_srcdir)/tinycrypt/lib/include -I$(top_srcdir)/tinycrypt/lib/source
AM_CFLAGS = -g -I$(top_srcdir)/src -I$(top_srcdir)/lib -I$(top_srcdir)/tinycrypt/lib/include -I$(top_srcdir)/tinycrypt/lib/source
# TinyCrypt source files
TINYCRYPT_SRCDIR = $(top_srcdir)/tinycrypt/lib/source
@ -81,7 +81,7 @@ ETCP_FULL_OBJS = \
# Windows-specific libraries (advapi32 for CryptGenRandom, ws2_32 for sockets)
if OS_WINDOWS
WIN_LIBS = -lws2_32 -liphlpapi -ladvapi32 -lbcrypt
WIN_LIBS = -lws2_32 -liphlpapi -ladvapi32 -lbcrypt -ldbghelp
else
WIN_LIBS =
endif

8
tests/test_etcp_two_instances.c

@ -263,12 +263,16 @@ int main() {
// Create server instance
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Creating server instance...");
ua = uasync_create();
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Creating server instance ok...");
server_instance = utun_instance_create(ua, server_config_path);
if (!server_instance) {
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Failed to create server instance");
return 1;
}
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "UTUN instance ok...");
// Initialize ETCP connections regardless of TUN state
if (init_connections(server_instance) < 0) {
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Failed to initialize server connections");
@ -321,7 +325,7 @@ int main() {
}
}
}
// Start monitoring
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Starting connection monitoring...\n");
monitor_timeout_id = uasync_set_timeout(ua, 100, NULL, monitor_connections);

1
tests/test_u_async_comprehensive.c

@ -12,6 +12,7 @@
#include "u_async.h"
#include "timeout_heap.h"
#include "debug_config.h"
#include "../lib/mem.h"
/* Test statistics */
static struct {

Loading…
Cancel
Save