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.
118 lines
4.7 KiB
118 lines
4.7 KiB
/* |
|
* chat_status.c — сбор статуса (NTP + ETCP connections) и отправка в GUI |
|
* |
|
* Вынесено из chat_core.c для уменьшения размера модуля. |
|
*/ |
|
|
|
#include "chat_core_priv.h" |
|
#include "gui_bridge.h" |
|
|
|
#include "../../../src/utun_instance.h" |
|
#include "../../../src/ntp_time.h" |
|
#include "../../../lib/ll_queue.h" |
|
#include "../../../lib/platform_compat.h" |
|
#include "etcp.h" |
|
#include "etcp_connections.h" |
|
|
|
static const char* nat_type_str(uint8_t t) { |
|
switch (t) { case 0: return "UNKNOWN"; case 1: return "EIM"; case 2: return "STRICT"; case 3: return "DIRECT"; default: return "?"; } |
|
} |
|
|
|
static void get_node_name(uint64_t node_id, char* out, size_t sz) { |
|
out[0] = '\0'; |
|
if (!g_cc.db || node_id == 0) return; |
|
sqlite3_stmt* st = NULL; |
|
if (sqlite3_prepare_v2(g_cc.db, "SELECT name FROM nodes WHERE node_id=?", -1, &st, NULL) != SQLITE_OK) return; |
|
sqlite3_bind_int64(st, 1, (sqlite3_int64)node_id); |
|
if (sqlite3_step(st) == SQLITE_ROW) { |
|
const char* n = (const char*)sqlite3_column_text(st, 0); |
|
if (n) snprintf(out, sz, "%s", n); |
|
} |
|
sqlite3_finalize(st); |
|
} |
|
|
|
static void chat_core_collect_status(void) { |
|
char buf[8192]; int off = 0; |
|
|
|
if (!g_cc.initialized || !g_cc.inst) { |
|
off = snprintf(buf, sizeof(buf), "uTun not initialized\n"); |
|
gui_bridge_post(GUI_EVT_STATUS_REFRESH, (const uint8_t*)buf, off); |
|
return; |
|
} |
|
|
|
struct NTP_TIME* ntp = &g_cc.inst->ntp; |
|
off += snprintf(buf + off, sizeof(buf) - off, "=== NTP ===\n"); |
|
off += snprintf(buf + off, sizeof(buf) - off, "Enabled: %s\n", ntp->enabled ? "yes" : "no"); |
|
off += snprintf(buf + off, sizeof(buf) - off, "Synced: %s\n", ntp->synced ? "yes" : "no"); |
|
off += snprintf(buf + off, sizeof(buf) - off, "Offset: %.1f s\n", ntp->offset_us / 1000000.0); |
|
if (ntp->server_count > 0 && ntp->servers) { |
|
off += snprintf(buf + off, sizeof(buf) - off, "Servers: %d\n", ntp->server_count); |
|
for (int i = 0; i < ntp->server_count && ntp->servers[i]; i++) |
|
off += snprintf(buf + off, sizeof(buf) - off, " [%d] %s%s\n", i, ntp->servers[i], |
|
i == ntp->server_current ? " (current)" : ""); |
|
} |
|
if (ntp->synced && ntp->last_sync_tb > 0) { |
|
uint64_t now_tb = get_time_tb(); |
|
uint64_t ago_sec = (now_tb - ntp->last_sync_tb) / 10000; |
|
off += snprintf(buf + off, sizeof(buf) - off, "Last sync: %llu sec ago\n", (unsigned long long)ago_sec); |
|
} |
|
|
|
int conn_count = 0; |
|
struct ll_entry* entry = g_cc.inst->connections->head; |
|
while (entry) { conn_count++; entry = entry->next; } |
|
off += snprintf(buf + off, sizeof(buf) - off, "=== Connections (%d) ===\n", conn_count); |
|
|
|
uint64_t my_id = g_cc.inst->node_id; |
|
entry = g_cc.inst->connections->head; |
|
while (entry) { |
|
struct conn_queue_entry* ce = (struct conn_queue_entry*)entry->data; |
|
if (!ce || !ce->conn) { entry = entry->next; continue; } |
|
|
|
uint64_t pid = ce->peer_node_id; |
|
struct ETCP_CONN* conn = ce->conn; |
|
|
|
int link_count = 0; |
|
struct ETCP_LINK* tl = conn->links; |
|
while (tl) { link_count++; tl = tl->next; } |
|
|
|
const char* init_str = conn->initialized ? "" : "(!init)"; |
|
|
|
char myhex[5], peerhex[5]; |
|
snprintf(myhex, sizeof(myhex), "%04llX", (unsigned long long)(my_id & 0xFFFF)); |
|
snprintf(peerhex, sizeof(peerhex), "%04llX", (unsigned long long)(pid & 0xFFFF)); |
|
|
|
char peername[64]; |
|
get_node_name(pid, peername, sizeof(peername)); |
|
|
|
if (peername[0]) |
|
off += snprintf(buf + off, sizeof(buf) - off, "[%s]→[%s] %s ETCP:%s%s(%dL)\n", |
|
myhex, peerhex, peername, |
|
conn->links_up ? "UP" : "DOWN", init_str, link_count); |
|
else |
|
off += snprintf(buf + off, sizeof(buf) - off, "[%s]→[%s] ETCP:%s%s(%dL)\n", |
|
myhex, peerhex, |
|
conn->links_up ? "UP" : "DOWN", init_str, link_count); |
|
|
|
int link_idx = 0; |
|
struct ETCP_LINK* link = conn->links; |
|
while (link) { |
|
char rtt_str[32]; rtt_str[0] = '\0'; |
|
if (link->rtt_last > 0) snprintf(rtt_str, sizeof(rtt_str), " / rtt=%ums", link->rtt_last / 10); |
|
off += snprintf(buf + off, sizeof(buf) - off, " LINK#%d: %s /NAT=%s%s\n", |
|
link_idx, |
|
link->link_status ? "UP" : "DOWN", |
|
nat_type_str(link->nat_type), |
|
rtt_str); |
|
link = link->next; link_idx++; |
|
} |
|
|
|
entry = entry->next; |
|
} |
|
|
|
gui_bridge_post(GUI_EVT_STATUS_REFRESH, (const uint8_t*)buf, off); |
|
} |
|
|
|
void chat_core_collect_status_trampoline(void* arg) { |
|
(void)arg; |
|
chat_core_collect_status(); |
|
}
|
|
|