You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

184 lines
4.6 KiB

// utun_instance.c - Root instance implementation
#include "utun_instance.h"
#include "config_parser.h"
#include "tun_if.h"
#include "routing.h"
#include "etcp_connections.h"
#include "../u_async/u_async.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
// Global instance for signal handlers
static utun_instance_t *g_instance = NULL;
// Create and initialize root instance
utun_instance_t* utun_instance_create(const char *config_file, const char *log_file) {
utun_instance_t *instance = calloc(1, sizeof(utun_instance_t));
if (!instance) return NULL;
// Initialize basic fields
instance->running = 0;
instance->log_fp = NULL;
// Load configuration
instance->config = parse_config(config_file);
if (!instance->config) {
fprintf(stderr, "Failed to load config from %s\n", config_file);
free(instance);
return NULL;
}
// Open log file
if (log_file) {
instance->log_fp = fopen(log_file, "a");
if (!instance->log_fp) {
fprintf(stderr, "Failed to open log file %s: %s\n", log_file, strerror(errno));
}
}
// Create uasync instance
instance->ua = uasync_create();
if (!instance->ua) {
fprintf(stderr, "Failed to create uasync instance\n");
utun_instance_destroy(instance);
return NULL;
}
// uasync has built-in wakeup mechanism, no need for manual pipe
// Set global instance
utun_instance_set(instance);
return instance;
}
// Destroy instance and cleanup resources
void utun_instance_destroy(utun_instance_t *instance) {
if (!instance) return;
// Stop running
instance->running = 0;
// Cleanup components
if (instance->ua) {
uasync_destroy(instance->ua);
}
if (instance->routing_table) {
routing_table_destroy(instance->routing_table);
}
// Cleanup connections
if (instance->connections) {
for (int i = 0; i < instance->connection_count; i++) {
if (instance->connections[i]) {
conn_destroy(instance->connections[i]);
}
}
free(instance->connections);
}
// 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);
}
// Initialize all components
int utun_instance_init(utun_instance_t *instance) {
if (!instance || !instance->config) return -1;
// Initialize TUN device
if (tun_create(&instance->tun) < 0) {
fprintf(stderr, "Failed to create TUN device\n");
return -1;
}
// Configure TUN device
if (tun_set_ip(instance->tun.ifname, instance->config->global.tun_ip) < 0) {
fprintf(stderr, "Failed to set TUN IP\n");
tun_close(&instance->tun);
return -1;
}
if (instance->config->global.mtu > 0) {
if (tun_set_mtu(instance->tun.ifname, instance->config->global.mtu) < 0) {
fprintf(stderr, "Failed to set TUN MTU\n");
tun_close(&instance->tun);
return -1;
}
}
if (tun_set_up(instance->tun.ifname) < 0) {
fprintf(stderr, "Failed to bring up TUN interface\n");
tun_close(&instance->tun);
return -1;
}
// Create routing table
instance->routing_table = routing_table_create();
if (!instance->routing_table) {
fprintf(stderr, "Failed to create routing table\n");
return -1;
}
// Subnets configuration will be added later from connection configs
// For now just return success
return 0;
}
// Start main event loop
int utun_instance_run(utun_instance_t *instance) {
if (!instance || !instance->ua) return -1;
instance->running = 1;
// Run main loop
while (instance->running) {
uasync_poll(instance->ua, 1000); // 100ms timeout
}
return 0;
}
// Stop instance
void utun_instance_stop(utun_instance_t *instance) {
if (!instance) return;
instance->running = 0;
// Wakeup main loop using built-in uasync wakeup
if (instance->ua) {
uasync_wakeup(instance->ua);
}
}
// Global instance access
utun_instance_t* utun_instance_get(void) {
return g_instance;
}
void utun_instance_set(utun_instance_t *instance) {
g_instance = instance;
}