- Fixed incorrect init_connections() call in test_etcp_simple_traffic.c (was calling server_instance instead of client_instance) - Fixed double free in timeout_heap_pop() when handling deleted elements - Enhanced NULL pointer safety in uasync_print_resources() by removing complex heap manipulation - Added debug logging to timeout_heap_pop() for better error tracking Test results: test_etcp_simple_traffic now passes without double free errors
231 lines
6.8 KiB
Plaintext
Executable File
231 lines
6.8 KiB
Plaintext
Executable File
// utun_instance.c - Root instance implementation
|
|
#include "utun_instance.h"
|
|
#include "config_parser.h"
|
|
#include "config_updater.h"
|
|
#include "tun_if.h"
|
|
#include "routing.h"
|
|
#include "etcp_connections.h"
|
|
#include "etcp.h"
|
|
#include "../lib/u_async.h"
|
|
#include "../lib/debug_config.h"
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <unistd.h>
|
|
#include <arpa/inet.h>
|
|
|
|
// Forward declarations
|
|
static void tun_read_callback(int fd, void* user_arg);
|
|
static uint32_t get_dest_ip(const uint8_t *packet, size_t len);
|
|
|
|
// Global instance for signal handlers
|
|
static struct UTUN_INSTANCE *g_instance = NULL;
|
|
|
|
// Create and initialize root instance
|
|
struct UTUN_INSTANCE* utun_instance_create(struct UASYNC* ua, const char *config_file, const char *log_file) {
|
|
struct UTUN_INSTANCE *instance = calloc(1, sizeof(struct UTUN_INSTANCE));
|
|
if (!instance) return NULL;
|
|
|
|
// Initialize basic fields
|
|
instance->running = 0;
|
|
instance->log_fp = NULL;
|
|
instance->ua = ua;
|
|
|
|
// Ensure keys and node_id exist in config
|
|
if (config_ensure_keys_and_node_id(config_file) < 0) {
|
|
DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "Failed to ensure keys and node_id in config: %s", config_file);
|
|
free(instance);
|
|
return NULL;
|
|
}
|
|
|
|
// Load configuration
|
|
instance->config = parse_config(config_file);
|
|
if (!instance->config) {
|
|
DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "Failed to load config from %s", config_file);
|
|
free(instance);
|
|
return NULL;
|
|
}
|
|
|
|
// Open log file
|
|
if (log_file) {
|
|
instance->log_fp = fopen(log_file, "a");
|
|
if (!instance->log_fp) {
|
|
DEBUG_ERROR(DEBUG_CATEGORY_MEMORY, "Failed to open log file %s: %s", log_file, strerror(errno));
|
|
}
|
|
}
|
|
// Set node_id from config
|
|
instance->node_id = instance->config->global.my_node_id;
|
|
|
|
// Set my keys
|
|
if (sc_init_local_keys(&instance->my_keys, instance->config->global.my_public_key_hex, instance->config->global.my_private_key_hex)) {
|
|
DEBUG_ERROR(DEBUG_CATEGORY_MEMORY, "Failed to initialize local keys");
|
|
}
|
|
|
|
|
|
instance->pkt_pool=memory_pool_init(PACKET_DATA_SIZE+100);
|
|
/*
|
|
// Initialize TUN device
|
|
if (tun_create(&instance->tun) < 0) {
|
|
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to create TUN device");
|
|
return -1;
|
|
}
|
|
|
|
// Configure TUN device
|
|
if (tun_set_ip(instance->tun.ifname, instance->config->global.tun_ip) < 0) {
|
|
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to set TUN IP");
|
|
tun_close(&instance->tun);
|
|
return -1;
|
|
}
|
|
|
|
if (instance->config->global.mtu > 0) {
|
|
if (tun_set_mtu(instance->tun.ifname, instance->config->global.mtu) < 0) {
|
|
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to set TUN MTU");
|
|
tun_close(&instance->tun);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
if (tun_set_up(instance->tun.ifname) < 0) {
|
|
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to bring up TUN interface");
|
|
tun_close(&instance->tun);
|
|
return -1;
|
|
}
|
|
|
|
// Create routing table
|
|
instance->routing_table = routing_table_create();
|
|
if (!instance->routing_table) {
|
|
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "Failed to create routing table");
|
|
return -1;
|
|
}
|
|
*/
|
|
// Initialize connections from configuration - moved to utun_instance_init
|
|
// to avoid double initialization
|
|
/*
|
|
if (init_connections(instance) < 0) {
|
|
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Failed to initialize connections");
|
|
// Cleanup will be handled by utun_instance_destroy
|
|
return NULL;
|
|
}
|
|
*/
|
|
|
|
return instance;
|
|
}
|
|
|
|
// Destroy instance and cleanup resources
|
|
void utun_instance_destroy(struct UTUN_INSTANCE *instance) {
|
|
if (!instance) return;
|
|
|
|
printf("[INSTANCE_DESTROY] Starting cleanup for instance %p\n", instance);
|
|
|
|
// Stop running
|
|
instance->running = 0;
|
|
|
|
// Cleanup ETCP sockets and connections FIRST (before destroying uasync)
|
|
printf("[INSTANCE_DESTROY] Cleaning up ETCP sockets and connections\n");
|
|
if (instance->etcp_sockets) {
|
|
printf("[INSTANCE_DESTROY] Found ETCP sockets to cleanup\n");
|
|
struct ETCP_SOCKET* sock = instance->etcp_sockets;
|
|
while (sock) {
|
|
struct ETCP_SOCKET* next = sock->next;
|
|
printf("[INSTANCE_DESTROY] Removing socket %p, fd=%d\n", sock, sock->fd);
|
|
etcp_socket_remove(sock); // Полный cleanup сокета
|
|
sock = next;
|
|
}
|
|
instance->etcp_sockets = NULL;
|
|
printf("[INSTANCE_DESTROY] ETCP sockets cleanup complete\n");
|
|
}
|
|
|
|
if (instance->connections) {
|
|
printf("[INSTANCE_DESTROY] Found ETCP connections to cleanup\n");
|
|
struct ETCP_CONN* conn = instance->connections;
|
|
while (conn) {
|
|
struct ETCP_CONN* next = conn->next;
|
|
printf("[INSTANCE_DESTROY] Closing connection %p\n", conn);
|
|
etcp_connection_close(conn); // Закрыть соединение
|
|
conn = next;
|
|
}
|
|
instance->connections = NULL;
|
|
printf("[INSTANCE_DESTROY] ETCP connections cleanup complete\n");
|
|
}
|
|
|
|
// Cleanup other components
|
|
if (instance->routing_table) {
|
|
routing_table_destroy(instance->routing_table);
|
|
}
|
|
|
|
// Cleanup TUN
|
|
if (instance->tun.fd >= 0) {
|
|
tun_close(&instance->tun);
|
|
}
|
|
|
|
// Cleanup config
|
|
if (instance->config) {
|
|
free_config(instance->config);
|
|
}
|
|
|
|
// Close log file
|
|
if (instance->log_fp) {
|
|
fclose(instance->log_fp);
|
|
}
|
|
|
|
// FINALLY destroy uasync (after all resources are cleaned up)
|
|
printf("[INSTANCE_DESTROY] Destroying uasync instance\n");
|
|
if (instance->ua) {
|
|
uasync_destroy(instance->ua);
|
|
}
|
|
|
|
// Free the instance memory
|
|
printf("[INSTANCE_DESTROY] Freeing instance memory\n");
|
|
free(instance);
|
|
printf("[INSTANCE_DESTROY] Instance destroyed completely\n");
|
|
|
|
// Cleanup TUN
|
|
if (instance->tun.fd >= 0) {
|
|
tun_close(&instance->tun);
|
|
}
|
|
|
|
// Cleanup config
|
|
if (instance->config) {
|
|
free_config(instance->config);
|
|
}
|
|
|
|
// Close log file
|
|
if (instance->log_fp) {
|
|
fclose(instance->log_fp);
|
|
}
|
|
|
|
// uasync cleanup will handle its built-in wakeup pipe
|
|
|
|
// Clear global instance
|
|
if (g_instance == instance) {
|
|
g_instance = NULL;
|
|
}
|
|
|
|
free(instance);
|
|
}
|
|
|
|
// Stop instance
|
|
void utun_instance_stop(struct UTUN_INSTANCE *instance) {
|
|
if (!instance) return;
|
|
instance->running = 0;
|
|
// Wakeup main loop using built-in uasync wakeup
|
|
if (instance->ua) {
|
|
memory_pool_destroy(instance->pkt_pool);
|
|
uasync_wakeup(instance->ua);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
int utun_instance_init(struct UTUN_INSTANCE *instance) {
|
|
if (!instance) return -1;
|
|
|
|
// Initialize connections
|
|
if (init_connections(instance) < 0) {
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|