- 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
84 lines
2.3 KiB
C
84 lines
2.3 KiB
C
/*
|
|
* headless_main.c — headless CLI entry point for chatgui-android
|
|
*
|
|
* Runs the uTun core without UI. Opens a JSON control socket for management.
|
|
* Used for debugging the network stack on Linux before Android integration.
|
|
*
|
|
* Usage:
|
|
* ./headless -p <control_port> -l <logfile>
|
|
*
|
|
* Config is read via callbacks (set by utun_config_set_provider before init).
|
|
* For headless, a stub config provider reads from environment variables.
|
|
*/
|
|
#include "../libutun_lite/utun_config_api.h"
|
|
#include "headless_control.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <signal.h>
|
|
#include <unistd.h>
|
|
|
|
/* ── Stub config provider (reads from ENV) ── */
|
|
|
|
static const char* env_get_string(const char* key, const char* def) {
|
|
const char* val = getenv(key);
|
|
return val ? val : def;
|
|
}
|
|
|
|
static int env_get_int(const char* key, int def) {
|
|
const char* val = getenv(key);
|
|
return val ? atoi(val) : def;
|
|
}
|
|
|
|
static const utun_config_provider_t g_env_provider = {
|
|
.get_string = env_get_string,
|
|
.get_int64 = NULL,
|
|
.get_int = env_get_int,
|
|
.get_bool = NULL,
|
|
};
|
|
|
|
/* ── Signal handling ── */
|
|
|
|
static volatile int g_stop = 0;
|
|
|
|
static void sig_handler(int sig) {
|
|
(void)sig;
|
|
g_stop = 1;
|
|
}
|
|
|
|
/* ─── main ─── */
|
|
|
|
int main(int argc, char** argv) {
|
|
int control_port = 9999;
|
|
const char* bind_ip = "127.0.0.1";
|
|
|
|
for (int i = 1; i < argc; i++) {
|
|
if (strcmp(argv[i], "-p") == 0 && i + 1 < argc) control_port = atoi(argv[++i]);
|
|
else if (strcmp(argv[i], "-l") == 0 && i + 1 < argc) fprintf(stderr, "logfile: %s\n", argv[++i]);
|
|
}
|
|
|
|
utun_config_set_provider(&g_env_provider);
|
|
|
|
/* Init control socket (non-uasync for now — simple select-based poll) */
|
|
if (headless_control_init(NULL, bind_ip, control_port) < 0) {
|
|
fprintf(stderr, "headless: failed to init control socket\n");
|
|
return 1;
|
|
}
|
|
|
|
signal(SIGINT, sig_handler);
|
|
signal(SIGTERM, sig_handler);
|
|
|
|
printf("headless: running. control socket on %s:%d\n", bind_ip, control_port);
|
|
printf("headless: connect with: nc %s %d\n", bind_ip, control_port);
|
|
|
|
/* Main loop */
|
|
while (!g_stop) {
|
|
headless_control_poll();
|
|
usleep(10000); /* 10ms to avoid busy-loop */
|
|
}
|
|
|
|
headless_control_destroy();
|
|
printf("headless: stopped.\n");
|
|
return 0;
|
|
}
|