- Адреса узлов вынесены из wire-протокола member_sync/merkle/join/welcome в BGP/topo_group: node_addresses теперь пишет только topo_node_sqlite_addrs_put (источник истины ni->v4/v6_addrs), классификация config_type/nat_type в sockmeta - Жёсткая анти-подделка: node_id=derive(x25519), ed25519 сверяется с доверенной таблицей nodes, NODEINFO node_id/pubkey mismatch отклоняется как forgery - Единые member_sync_build_join_msg (112Б) и member_sync_build_update_msg: устранён баг _verify_join_sig (join_ts по смещению 80 вместо 104, длина 104→112), который рушил приём мемберов; все 7 мест подписи/проверки join_sig через хелпер - Единое обновление своего мембера chat_core_update_my_member (вместо sync_my_addresses) - Android standby: пауза таймеров (broadcast/db_sync/merkle_sync/chat_sync) через standby_wait - name[16] → name[MAX_CONN_NAME_LEN] с truncation-warning в парсере - conn_mgr: etcp_connect_cancel_by_node (use-after-free при отмене invite), промоушен conn в ncd после успешного invite - Android GUI: foreground-gating опросов, сохранение портов интерфейсов, фикс udp-log flush - chatgui: персистентный db_path; мелкие DEBUG-логи epoll/pool
138 lines
5.0 KiB
C
138 lines
5.0 KiB
C
/*
|
|
* android_udp_log.c — non-blocking UDP log sender for Android
|
|
*
|
|
* Called ONLY from uasync worker thread (bridge_debug_hook).
|
|
* No mutex needed. Flushes at 16KB threshold or via uasync timer.
|
|
*/
|
|
#include "android_udp_log.h"
|
|
#include "../libutun_lite/instance_lite.h"
|
|
#include "../../../lib/u_async.h"
|
|
#include "../../../lib/platform_compat.h"
|
|
#include "../../../lib/socket_compat.h"
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
|
|
#define UDP_BUF_SIZE 65536
|
|
#define UDP_FLUSH_BYTES 16384
|
|
#define UDP_FLUSH_TB 2000 /* 200ms in uasync timebase (0.1ms units) */
|
|
|
|
#ifdef __ANDROID__
|
|
#include <android/log.h>
|
|
#define ULOG(fmt, ...) __android_log_print(ANDROID_LOG_DEBUG, "utun-udplog", fmt, ##__VA_ARGS__)
|
|
#else
|
|
#define ULOG(fmt, ...) fprintf(stderr, "utun-udplog: " fmt "\n", ##__VA_ARGS__)
|
|
#endif
|
|
|
|
static int g_udp_fd = -1;
|
|
static struct sockaddr_in g_udp_addr;
|
|
static int g_udp_has_addr = 0;
|
|
static int g_udp_stopping = 0;
|
|
static char g_udp_buf[UDP_BUF_SIZE];
|
|
static int g_udp_buf_len = 0;
|
|
static void* g_udp_timer = NULL;
|
|
static int g_udp_sent_first = 0;
|
|
static int64_t g_udp_total_sent = 0;
|
|
static int g_udp_send_errors = 0;
|
|
|
|
static void udp_reschedule_timer(void) {
|
|
if (g_udp_stopping) return;
|
|
if (g_udp_timer) return;
|
|
struct UASYNC* ua = instance_lite_get_uasync();
|
|
if (ua) g_udp_timer = uasync_set_timeout(ua, UDP_FLUSH_TB, NULL, udp_trampoline, "udp_log_flush");
|
|
}
|
|
|
|
static void udp_open_socket(void) {
|
|
if (g_udp_fd >= 0 || !g_udp_has_addr) return;
|
|
g_udp_fd = (int)socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0);
|
|
if (g_udp_fd < 0) { ULOG("socket() failed: %s (errno=%d)", strerror(errno), errno); return; }
|
|
if (connect(g_udp_fd, (struct sockaddr*)&g_udp_addr, sizeof(g_udp_addr)) < 0) {
|
|
ULOG("connect() to %s:%d failed: %s (errno=%d)",
|
|
inet_ntoa(g_udp_addr.sin_addr), (int)ntohs(g_udp_addr.sin_port), strerror(errno), errno);
|
|
close(g_udp_fd); g_udp_fd = -1; return;
|
|
}
|
|
ULOG("socket opened fd=%d -> %s:%d", g_udp_fd,
|
|
inet_ntoa(g_udp_addr.sin_addr), (int)ntohs(g_udp_addr.sin_port));
|
|
}
|
|
|
|
static void udp_do_send(const char* data, int len) {
|
|
if (g_udp_fd < 0) { udp_open_socket(); if (g_udp_fd < 0) return; }
|
|
ssize_t sent = send(g_udp_fd, data, len, MSG_DONTWAIT);
|
|
if (sent >= 0) {
|
|
g_udp_total_sent += sent;
|
|
if (!g_udp_sent_first) { ULOG("first send OK: %zd bytes, total=%lld", sent, (long long)g_udp_total_sent); g_udp_sent_first = 1; }
|
|
return;
|
|
}
|
|
g_udp_send_errors++;
|
|
if (g_udp_send_errors <= 3 || g_udp_send_errors % 100 == 0)
|
|
ULOG("send() error #%d: %s (errno=%d)", g_udp_send_errors, strerror(errno), errno);
|
|
if (errno == ECONNREFUSED || errno == ENETUNREACH || errno == EHOSTUNREACH) {
|
|
close(g_udp_fd);
|
|
g_udp_fd = -1;
|
|
}
|
|
}
|
|
|
|
void udp_trampoline(void* arg) {
|
|
(void)arg;
|
|
if (g_udp_buf_len > 0) {
|
|
udp_do_send(g_udp_buf, g_udp_buf_len);
|
|
g_udp_buf_len = 0;
|
|
}
|
|
g_udp_timer = NULL;
|
|
/* перевзводим только если остались неотправленные данные */
|
|
if (g_udp_buf_len > 0) udp_reschedule_timer();
|
|
}
|
|
|
|
void udp_log_set_target(const char* ip, int port) {
|
|
g_udp_buf_len = 0;
|
|
g_udp_stopping = 0;
|
|
g_udp_sent_first = 0;
|
|
g_udp_total_sent = 0;
|
|
g_udp_send_errors = 0;
|
|
if (g_udp_fd >= 0) { close(g_udp_fd); g_udp_fd = -1; }
|
|
if (ip && port > 0) {
|
|
memset(&g_udp_addr, 0, sizeof(g_udp_addr));
|
|
g_udp_addr.sin_family = AF_INET;
|
|
g_udp_addr.sin_port = htons((unsigned short)port);
|
|
g_udp_has_addr = (inet_pton(AF_INET, ip, &g_udp_addr.sin_addr) == 1);
|
|
ULOG("set target %s:%d -> has_addr=%d", ip, port, g_udp_has_addr);
|
|
} else {
|
|
g_udp_has_addr = 0;
|
|
ULOG("set target disabled (ip=%s port=%d)", ip ? ip : "null", port);
|
|
}
|
|
}
|
|
|
|
void udp_log_write(const char* data, int len) {
|
|
if (!data || len <= 0 || !g_udp_has_addr) return;
|
|
|
|
if (g_udp_fd < 0) udp_open_socket();
|
|
|
|
if (g_udp_buf_len + len > UDP_BUF_SIZE) {
|
|
if (g_udp_buf_len > 0) { udp_do_send(g_udp_buf, g_udp_buf_len); g_udp_buf_len = 0; }
|
|
if (len > UDP_BUF_SIZE) return;
|
|
}
|
|
memcpy(g_udp_buf + g_udp_buf_len, data, len);
|
|
g_udp_buf_len += len;
|
|
if (g_udp_buf_len >= UDP_FLUSH_BYTES) {
|
|
udp_do_send(g_udp_buf, g_udp_buf_len);
|
|
g_udp_buf_len = 0;
|
|
} else {
|
|
udp_reschedule_timer(); /* взвести flush для частичных данных */
|
|
}
|
|
}
|
|
|
|
void udp_log_cancel_timer(void) {
|
|
g_udp_stopping = 1;
|
|
struct UASYNC* ua = instance_lite_get_uasync();
|
|
if (ua && g_udp_timer) uasync_cancel_timeout(ua, g_udp_timer);
|
|
g_udp_timer = NULL;
|
|
}
|
|
|
|
void udp_log_stop(void) {
|
|
g_udp_stopping = 1;
|
|
if (g_udp_buf_len > 0) { udp_do_send(g_udp_buf, g_udp_buf_len); g_udp_buf_len = 0; }
|
|
ULOG("stop: total_sent=%lld bytes, errors=%d", (long long)g_udp_total_sent, g_udp_send_errors);
|
|
if (g_udp_fd >= 0) { close(g_udp_fd); g_udp_fd = -1; }
|
|
g_udp_has_addr = 0;
|
|
}
|