// 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 #include #include #include #include #include // 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; }