Browse Source

connection: логировать только connect/reconnect/disconnect; фиксы конфига чатгуи

- категория connection теперь только жизненный цикл соединения; INIT/PING/keepalive
  переклассифицированы в ETCP/SOCKET/KEEPALIVE/REALITY/ROUTING, удалены дубли
- settingsdialog: устранён дубль my_node_name в конфиге (двухпроходная запись + только при изменении)
- storagesettingspage: канонические ключи storage_total_size/storage_unit_size с суффиксом M/G
- audiodevicesettingspage: compressor_max_gain_db min 0→1
- etcp_connections: %s-баг в логе TCP link (addr → sockaddr_storage_to_str)
- docs/sample: [chatserver], актуализированы ключи хранилища
v2
evgeny 3 weeks ago
parent
commit
b7da6547c1
  1. 10
      AGENTS.md
  2. 2
      lib/debug_config.h
  3. 14
      lib/getmyip.c
  4. 2
      src/routing_layer/conn_mgr_core.c
  5. 4
      src/transport_layer/etcp.c
  6. 246
      src/transport_layer/etcp_connections.c
  7. 8
      src/transport_layer/node_conn_direct.c
  8. 6
      tools/chatgui-android/AGENTS.md
  9. 2
      tools/chatgui/src/audiodevicesettingspage.cpp
  10. 25
      tools/chatgui/src/settingsdialog.cpp
  11. 4
      tools/chatgui/src/storagesettingspage.cpp
  12. 5
      utun.conf.sample

10
AGENTS.md

@ -221,7 +221,7 @@ sc_obfuscate_pubkey(salt, peer_pubkey_bin, my_pubkey_bin, obfuscated_output);
### Debug Levels
`none < error < warn < info < debug < trace`
trace - логируем заходы в функции и важные ветвления внутри функций
debug - всё что нужно для понимание сути происходящего (состояний, важных переменных) алгоритма. тоесть по уровню debug мы должны видеть все важные внутреннии нюансы работы функции включая состояния и переменные.
debug - отладка: всё что нужно для понимание сути происходящего (состояний, важных переменных) алгоритма. тоесть по уровню debug мы должны видеть все важные внутреннии нюансы работы функции включая состояния и переменные.
info - сообщения для пользователя о работе. мы должны видеть в читаемом виде понятные и осмысленные сообщения о каких-либо значимых действиях с точки зрения логики работы модуля или приложения
warn / error - ошибки и предупреждения (аномалии). должны быть во всех ошибочных ветках. Молча вываливаться с ошибкой нельзя, все ошибки и предупреждения должны логироваться.
@ -449,12 +449,12 @@ MEMBER_SYNC=27
## Config Rules
- В серверном конфиге только собственные ключи и нет секций `[client]`
- В клиентском конфиге есть собственные ключи и pubkey каждого сервера в секции `[client]`
- Chat-настройки хранятся в секции `[chat]`. Парсер вызывает `chat_setting_set(key, value)` для каждого ключа — неизвестные ключи вызывают ошибку. Пример:
- Chat-настройки хранятся в секции `[chatserver]` (принимается также `[chat]`). Парсер вызывает `chat_setting_set(key, value)` для каждого ключа — неизвестные ключи вызывают ошибку. Пример:
```ini
[chat]
[chatserver]
storage_autoload=1
storage_autoload_maxsize_mb=10
storage_maxsize_gb=1
storage_unit_size=10M
storage_total_size=1G
opus_codec_preset=1
compressor_enabled=0
compressor_max_gain_db=25

2
lib/debug_config.h

@ -41,7 +41,7 @@ typedef int debug_category_t;
#define DEBUG_CATEGORY_NONE 0
#define DEBUG_CATEGORY_SYS 1 // System: u_async, ll_queue, memory, timing
// #define DEBUG_CATEGORY_LL_QUEUE 2 (merged into SYS)
#define DEBUG_CATEGORY_CONNECTION 3 // Connection: links, keepalive, status events
#define DEBUG_CATEGORY_CONNECTION 3 // Connection: connect/reconnect/disconnect events only
#define DEBUG_CATEGORY_ETCP 4 // ETCP: protocol, BBR, normalizer
#define DEBUG_CATEGORY_CRYPTO 5 // crypto operations
// #define DEBUG_CATEGORY_MEMORY 6 (merged into SYS)

14
lib/getmyip.c

@ -23,24 +23,24 @@ int get_outgoing_local_ip(const struct sockaddr_storage *local_addr,
struct sockaddr_storage *result)
{
if (!local_addr || !remote_addr || !result) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "get_outgoing_local_ip: NULL argument");
DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "get_outgoing_local_ip: NULL argument");
return -1;
}
int family = local_addr->ss_family;
if (family != AF_INET && family != AF_INET6) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "get_outgoing_local_ip: unsupported family %d", family);
DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "get_outgoing_local_ip: unsupported family %d", family);
return -1;
}
if (remote_addr->ss_family != family) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "get_outgoing_local_ip: family mismatch");
DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "get_outgoing_local_ip: family mismatch");
return -1;
}
socket_t sock = socket_create_udp(family);
if (sock == SOCKET_INVALID) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "get_outgoing_local_ip: socket_create_udp failed");
DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "get_outgoing_local_ip: socket_create_udp failed");
return -1;
}
@ -56,7 +56,7 @@ int get_outgoing_local_ip(const struct sockaddr_storage *local_addr,
socklen_t bind_len = (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
if (bind(sock, (struct sockaddr *)&bind_addr, bind_len) != 0) {
int err = socket_get_error();
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "get_outgoing_local_ip: bind failed: %s", socket_strerror(err));
DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "get_outgoing_local_ip: bind failed: %s", socket_strerror(err));
socket_close_wrapper(sock);
return -1;
}
@ -65,7 +65,7 @@ int get_outgoing_local_ip(const struct sockaddr_storage *local_addr,
socklen_t remote_len = (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
if (connect(sock, (struct sockaddr *)remote_addr, remote_len) != 0) {
int err = socket_get_error();
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "get_outgoing_local_ip: connect failed: %s", socket_strerror(err));
DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "get_outgoing_local_ip: connect failed: %s", socket_strerror(err));
socket_close_wrapper(sock);
return -1;
}
@ -75,7 +75,7 @@ int get_outgoing_local_ip(const struct sockaddr_storage *local_addr,
socklen_t local_len = sizeof(local);
if (getsockname(sock, (struct sockaddr *)&local, &local_len) != 0) {
int err = socket_get_error();
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "get_outgoing_local_ip: getsockname failed: %s", socket_strerror(err));
DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "get_outgoing_local_ip: getsockname failed: %s", socket_strerror(err));
socket_close_wrapper(sock);
return -1;
}

2
src/routing_layer/conn_mgr_core.c

@ -740,7 +740,7 @@ void cm_handle_disconnect(struct CONN_MGR* mgr, uint64_t node_id) {
void conn_mgr_router_recv_handler(struct ETCP_CONN* conn, struct ll_entry* entry) {
if (!entry || !entry->dgram || entry->len < ROUTER_SVC_PAYLOAD_OFF + 2) return;
if (!conn || !conn->instance) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "conn_mgr_router_recv: conn=%p", (void*)conn);
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "conn_mgr_router_recv: conn=%p", (void*)conn);
return;
}
uint8_t* d = entry->dgram + ROUTER_SVC_PAYLOAD_OFF; size_t len = entry->len - ROUTER_SVC_PAYLOAD_OFF; uint8_t sub = d[1];

4
src/transport_layer/etcp.c

@ -199,7 +199,7 @@ struct ETCP_CONN* etcp_connection_create(struct UTUN_INSTANCE* instance, char* n
struct ETCP_CONN* etcp = u_calloc(1, sizeof(struct ETCP_CONN));
if (!etcp) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "creating connection failed for instance %p", instance);
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "creating connection failed for instance %p", instance);
return NULL;
}
@ -230,7 +230,7 @@ struct ETCP_CONN* etcp_connection_create(struct UTUN_INSTANCE* instance, char* n
if (!etcp->input_queue || !etcp->output_queue || !etcp->transit_queues ||
!etcp->input_send_q || !etcp->recv_q || !etcp->ack_q ||
!etcp->input_wait_ack || !etcp->inflight_pool || !etcp->io_pool) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "error - closing - input:%p output:%p send:%p wait:%x pool:%p",
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "error - closing - input:%p output:%p send:%p wait:%x pool:%p",
etcp->input_queue, etcp->output_queue, etcp->input_send_q, etcp->input_wait_ack, etcp->inflight_pool);
etcp_connection_close(etcp);
return NULL;

246
src/transport_layer/etcp_connections.c

@ -143,14 +143,14 @@ static void burst_resp_timeout_cb(void* arg) {
#define INIT_TIMEOUT_MAX 50000
static void etcp_link_send_init(struct ETCP_LINK* link, uint8_t reset, uint8_t collision) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "link=%p, is_server=%d, reset=%d, collision=%d", link, link ? link->is_server : -1, reset, collision);
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "link=%p, is_server=%d, reset=%d, collision=%d", link, link ? link->is_server : -1, reset, collision);
if (!link || !link->etcp || !link->etcp->instance) return;
if (link->is_tcp) return; // TCP uses STCP handshake instead of ETCP INIT
struct ETCP_DGRAM* dgram = u_malloc(PACKET_DATA_SIZE);
if (!dgram) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "malloc failed");
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "malloc failed");
return;
}
@ -246,7 +246,7 @@ static void etcp_link_send_init(struct ETCP_LINK* link, uint8_t reset, uint8_t c
}
static void etcp_link_init_timer_cbk(void* arg) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
struct ETCP_LINK* link = (struct ETCP_LINK*)arg;
if (!link || !link->etcp || !link->etcp->instance) return;
@ -265,14 +265,14 @@ static void etcp_link_init_timer_cbk(void* arg) {
}
void etcp_link_restart_init_timer(struct ETCP_LINK* link) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
if (link->init_timer) uasync_cancel_timeout(link->etcp->instance->ua, link->init_timer);
link->init_timeout = INIT_TIMEOUT_INITIAL;
link->init_timer = uasync_set_timeout(link->etcp->instance->ua, link->init_timeout, link, etcp_link_init_timer_cbk, "link_init");
}
void etcp_link_enter_init(struct ETCP_LINK* link) {//
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
if (!link) return;
int old_state = link->link_state;
link->link_state = LINK_STATE_HANDSHAKE; // handshake
@ -284,7 +284,7 @@ void etcp_link_enter_init(struct ETCP_LINK* link) {//
}
void etcp_link_enter_reinit(struct ETCP_LINK* link) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
if (!link) return;
int old_state = link->link_state;
link->link_state = LINK_STATE_TRY_RECONNECT; // reconnect
@ -322,7 +322,7 @@ static void sockaddr_to_key(struct sockaddr_storage* addr, uint8_t key[LINK_ADDR
// find_link_index, realloc_links, insert_link, remove_link — УДАЛЕНЫ. Заменены на ll_queue с хеш-индексом.
static int insert_link_queue(struct ETCP_SOCKET* e_sock, struct ETCP_LINK* link) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
if (!e_sock || !link || !e_sock->links_queue) return -1;
uint8_t key[LINK_ADDR_KEY_SIZE];
@ -336,7 +336,7 @@ static int insert_link_queue(struct ETCP_SOCKET* e_sock, struct ETCP_LINK* link)
uint64_t new_qkey = 0, old_qkey = 0;
if (new_c->conn_queue_entry) new_qkey = ((struct conn_queue_entry*)new_c->conn_queue_entry->data)->peer_node_id;
if (old_c->conn_queue_entry) old_qkey = ((struct conn_queue_entry*)old_c->conn_queue_entry->data)->peer_node_id;
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION,
DEBUG_ERROR(DEBUG_CATEGORY_ETCP,
"!!!!!!!!!!!! LINK ADDR COLLISION !!!!!!!!!!!! addr=%s "
"new: conn=%p [%s] peer=0x%016llx state=%d init=%d up=%d srv=%d tcp=%d qkey=0x%016llx "
"old: conn=%p [%s] peer=0x%016llx state=%d init=%d up=%d srv=%d tcp=%d qkey=0x%016llx",
@ -350,14 +350,14 @@ static int insert_link_queue(struct ETCP_SOCKET* e_sock, struct ETCP_LINK* link)
(unsigned long long)old_qkey);
return -1;
}
DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "insert_link_queue: replacing stale DUP addr in [%s] old_link=%p", e_sock->name, dup_lqe->link);
DEBUG_WARN(DEBUG_CATEGORY_ETCP, "insert_link_queue: replacing stale DUP addr in [%s] old_link=%p", e_sock->name, dup_lqe->link);
if (dup_lqe->link) dup_lqe->link->link_queue_entry = NULL;
queue_remove_data(e_sock->links_queue, dup_qe);
queue_entry_free(dup_qe);
}
struct ll_entry* qe = queue_entry_new(sizeof(struct link_queue_entry));
if (!qe) { DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "queue_entry_new failed"); return -1; }
if (!qe) { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "queue_entry_new failed"); return -1; }
struct link_queue_entry* lqe = (struct link_queue_entry*)qe->data;
memcpy(lqe->key, key, LINK_ADDR_KEY_SIZE);
lqe->link = link;
@ -367,7 +367,7 @@ static int insert_link_queue(struct ETCP_SOCKET* e_sock, struct ETCP_LINK* link)
}
static void remove_link_from_queue(struct ETCP_LINK* link) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
if (!link || !link->link_queue_entry) return;
if (!link->conn || !link->conn->links_queue) return;
queue_remove_data(link->conn->links_queue, link->link_queue_entry);
@ -391,7 +391,7 @@ static int sockaddr_equal(const struct sockaddr_storage* a, const struct sockadd
}
struct ETCP_LINK* etcp_link_find_by_addr(struct ETCP_SOCKET* e_sock, struct sockaddr_storage* addr, int is_tcp) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
if (!e_sock || !addr || !e_sock->links_queue) return NULL;
uint8_t key[LINK_ADDR_KEY_SIZE];
sockaddr_to_key(addr, key, is_tcp);
@ -407,18 +407,18 @@ static void etcp_link_update_remote_addr(struct ETCP_LINK* link, struct ETCP_SOC
const struct sockaddr_storage* new_addr) {
if (!link || !e_sock || !new_addr) return;
if (link->is_tcp) {
DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "[%s] update_remote_addr: TCP link skip", link->etcp->log_name);
DEBUG_WARN(DEBUG_CATEGORY_ETCP, "[%s] update_remote_addr: TCP link skip", link->etcp->log_name);
return;
}
if (link->conn != e_sock) {
DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "[%s] update_remote_addr: link socket [%s] != recv socket [%s], skip",
DEBUG_WARN(DEBUG_CATEGORY_ETCP, "[%s] update_remote_addr: link socket [%s] != recv socket [%s], skip",
link->etcp->log_name, link->conn ? link->conn->name : "-", e_sock->name);
return;
}
remove_link_from_queue(link);
memcpy(&link->remote_addr, new_addr, sizeof(struct sockaddr_storage));
if (insert_link_queue(e_sock, link) < 0)
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "[%s] update_remote_addr: re-index FAILED at %s",
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "[%s] update_remote_addr: re-index FAILED at %s",
link->etcp->log_name, sockaddr_storage_to_str(new_addr).str);
}
@ -436,7 +436,7 @@ struct ETCP_LINK* etcp_select_collision_link(struct ETCP_CONN* conn, const struc
}
struct ETCP_LINK* etcp_link_find_by_remote_id(struct ETCP_CONN* conn, uint8_t remote_link_id) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
if (!conn || remote_link_id == 0) return NULL;
struct ETCP_LINK* l = conn->links;
while (l) {
@ -447,7 +447,7 @@ struct ETCP_LINK* etcp_link_find_by_remote_id(struct ETCP_CONN* conn, uint8_t re
}
int etcp_find_free_local_link_id(struct ETCP_CONN* etcp) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
if (!etcp) return -1;
// Битовый массив для 256 id (32 байта * 8 бит = 256)
@ -478,7 +478,7 @@ int etcp_find_free_local_link_id(struct ETCP_CONN* etcp) {
// ===============================
struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct CFG_SERVER* server) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
if (!instance || !server) return NULL;
struct sockaddr_storage* ip = &server->ip;
@ -509,7 +509,7 @@ struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct CFG_S
if (netif_index == 0) {
netif_index = get_default_route_netif_index(AF_INET6);
if (netif_index == 0) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "Cannot determine default route interface for IPv6 socket %s", name);
DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "Cannot determine default route interface for IPv6 socket %s", name);
u_free(e_sock);
return NULL;
}
@ -517,7 +517,7 @@ struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct CFG_S
int temp = (server->ipv6_mode == CFG_IPV6_MODE_TEMPORARY) ? 1 : 0;
uint8_t v6addr[16];
if (get_interface_ipv6_addr_nl(netif_index, !temp, v6addr) != 0) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "Failed to get %s IPv6 from netif_index=%u for socket %s",
DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "Failed to get %s IPv6 from netif_index=%u for socket %s",
temp ? "temporary" : "permanent", netif_index, name);
u_free(e_sock);
return NULL;
@ -531,7 +531,7 @@ struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct CFG_S
family = ip->ss_family;
e_sock->netif_index = netif_index;
if (family != AF_INET && family != AF_INET6) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "Unsupported address family: %d", family);
DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "Unsupported address family: %d", family);
u_free(e_sock);
return NULL;
}
@ -539,7 +539,7 @@ struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct CFG_S
e_sock->fd = socket_create_udp(family);
if (e_sock->fd == SOCKET_INVALID) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "Failed to create socket: %s",
DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "Failed to create socket: %s",
socket_strerror(socket_get_error()));
u_free(e_sock);
return NULL;
@ -552,13 +552,13 @@ struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct CFG_S
socket_set_buffers(e_sock->fd, 4 * 1024 * 1024, 4 * 1024 * 1024);
if (socket_set_nonblocking(e_sock->fd) != 0) {
DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "Failed to set non-blocking mode");
DEBUG_WARN(DEBUG_CATEGORY_SOCKET, "Failed to set non-blocking mode");
}
if (family == AF_INET6) {
int v6only = 1;
if (setsockopt(e_sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, &v6only, sizeof(v6only)) < 0) {
DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "Failed to set IPV6_V6ONLY: %s", socket_strerror(socket_get_error()));
DEBUG_WARN(DEBUG_CATEGORY_SOCKET, "Failed to set IPV6_V6ONLY: %s", socket_strerror(socket_get_error()));
}
}
@ -571,7 +571,7 @@ struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct CFG_S
#ifdef __FreeBSD__
if (fib > 0) {
if (setsockopt(e_sock->fd, SOL_SOCKET, SO_SETFIB, &fib, sizeof(fib)) < 0) {
DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "Failed to set FIB %d: %s", fib, strerror(errno));
DEBUG_WARN(DEBUG_CATEGORY_SOCKET, "Failed to set FIB %d: %s", fib, strerror(errno));
}
}
#endif
@ -606,7 +606,7 @@ struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct CFG_S
rem_sin->sin_port = htons(53);
inet_pton(AF_INET, "8.8.8.8", &rem_sin->sin_addr);
if (get_outgoing_local_ip(ip, &remote, &e_sock->interface_addr) != 0) {
DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "Failed to detect outgoing local IP for socket %s", e_sock->name);
DEBUG_WARN(DEBUG_CATEGORY_SOCKET, "Failed to detect outgoing local IP for socket %s", e_sock->name);
}
}
} else if (ip->ss_family == AF_INET6) {
@ -705,7 +705,7 @@ struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct CFG_S
e_sock->only_local = only_local;
e_sock->links_queue = queue_new(instance->ua, 256, offsetof(struct link_queue_entry, key), LINK_ADDR_KEY_SIZE, "links");
if (!e_sock->links_queue) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "Failed to create links_queue for socket %s", e_sock->name);
DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "Failed to create links_queue for socket %s", e_sock->name);
socket_close_wrapper(e_sock->fd);
u_free(e_sock);
return NULL;
@ -715,18 +715,17 @@ struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct CFG_S
instance->etcp_sockets = e_sock;
e_sock->socket_id = uasync_add_socket_t(instance->ua, e_sock->fd, etcp_connections_read_callback_socket, NULL, NULL, e_sock);
if (!e_sock->socket_id) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "Failed to register socket with uasync");
DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "Failed to register socket with uasync");
socket_close_wrapper(e_sock->fd);
u_free(e_sock);
return NULL;
}
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "Registered ETCP socket with uasync");
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "[ETCP] Socket %p registered and active", e_sock);
return e_sock;
}
void etcp_socket_remove(struct ETCP_SOCKET* conn) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
if (!conn) return;
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "[ETCP] Removing socket %p, socket_id=%p", conn, conn->socket_id);
@ -865,14 +864,14 @@ void tcp_socket_remove(struct ETCP_SOCKET* sock) {
}
struct ETCP_LINK* etcp_link_new(struct ETCP_CONN* etcp, struct ETCP_SOCKET* conn, struct sockaddr_storage* remote_addr, uint8_t is_server) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
if (!etcp) { DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "null etcp"); return NULL; }
if (etcp->state == 2) { DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "[%s] link_new on deleted conn", etcp->log_name); return NULL; }
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
if (!etcp) { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "null etcp"); return NULL; }
if (etcp->state == 2) { DEBUG_WARN(DEBUG_CATEGORY_ETCP, "[%s] link_new on deleted conn", etcp->log_name); return NULL; }
int is_tcp = (conn == NULL) || conn->is_tcp;
struct ETCP_LINK* link = u_calloc(1, sizeof(struct ETCP_LINK));
if (!link) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "calloc failed - out of memory or pool exhausted");
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "calloc failed - out of memory or pool exhausted");
return NULL;
}
@ -930,7 +929,7 @@ struct ETCP_LINK* etcp_link_new(struct ETCP_CONN* etcp, struct ETCP_SOCKET* conn
// Выделяем свободный local_link_id
int free_id = etcp_find_free_local_link_id(etcp);
if (free_id <= 0) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "no free local_link_id available");
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "no free local_link_id available");
u_free(link);
return NULL;
}
@ -947,7 +946,7 @@ struct ETCP_LINK* etcp_link_new(struct ETCP_CONN* etcp, struct ETCP_SOCKET* conn
link->total_retransmissions = 0;
if (!is_tcp && insert_link_queue(conn, link) < 0) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "Can not insert link to socket");
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Can not insert link to socket");
u_free(link);
return NULL;
}
@ -991,7 +990,7 @@ static void etcp_inflight_nullify_link(struct ll_queue* q, struct ETCP_LINK* dea
}
void etcp_link_close(struct ETCP_LINK* link) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
if (!link) return;
if (link->etcp && link->etcp->last_rr_link == link) link->etcp->last_rr_link = NULL;
@ -1126,7 +1125,7 @@ void etcp_tcp_link_start_connect(struct ETCP_LINK *link, struct sockaddr_storage
link->tcp_link = sl;
if (link->is_server == 0) stcp_link_set_on_close(sl, tcp_link_close_cb, link);
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "[%s] TCP link %d → stcp_link_connect %s:%u rc=%p bind=%s",
link->etcp->log_name, link->local_link_id, addr, port, (void*)sl,
link->etcp->log_name, link->local_link_id, sockaddr_storage_to_str(addr).str, port, (void*)sl,
link->conn ? sockaddr_storage_to_str(&link->conn->interface_addr).str : "auto");
}
@ -1200,10 +1199,10 @@ ssize_t etcp_udp_send(struct ETCP_LINK* link, socket_t fd, const void* buf, size
}
int etcp_encrypt_send(struct ETCP_DGRAM* dgram) {
if (!dgram || !dgram->link) { DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "Null pointer"); return -1; }
if (!dgram || !dgram->link) { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Null pointer"); return -1; }
if (dgram->link->is_tcp) return etcp_tcp_send(dgram);
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[%s] Send rk=%d lk=%d up=%d",
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] Send rk=%d lk=%d up=%d",
dgram->link->etcp->log_name, dgram->link->recv_keepalive, dgram->link->remote_keepalive, dgram->link->link_status);
// Mark that packet was sent (for keepalive logic)
@ -1224,10 +1223,10 @@ int etcp_encrypt_send(struct ETCP_DGRAM* dgram) {
if (debug_should_output(DEBUG_LEVEL_DEBUG, DEBUG_CATEGORY_CRYPTO)) log_dump(DEBUG_LEVEL_DEBUG, DEBUG_CATEGORY_CRYPTO, "Before encryption", dgram->data, dgram->data_len);
sc_encrypt(sc, (uint8_t*)&dgram->timestamp, 3 + len, enc_buf, &enc_buf_len);
if (enc_buf_len == 0) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "eencryption failed for node %016llx", (unsigned long long)dgram->link->etcp->instance->node_id);
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "eencryption failed for node %016llx", (unsigned long long)dgram->link->etcp->instance->node_id);
dgram->link->send_errors++; errcode=2; goto es_err; }
if (enc_buf_len + dgram->noencrypt_len > (size_t)(dgram->link->mtu - udp_ov)) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "packet too long enc=%zu ne=%d mtu=%d", enc_buf_len, dgram->noencrypt_len, dgram->link->mtu);
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "packet too long enc=%zu ne=%d mtu=%d", enc_buf_len, dgram->noencrypt_len, dgram->link->mtu);
dgram->link->send_errors++; errcode=3; goto es_err; }
memcpy(enc_buf+enc_buf_len, dgram->data+len, dgram->noencrypt_len);
@ -1239,24 +1238,24 @@ int etcp_encrypt_send(struct ETCP_DGRAM* dgram) {
ssize_t sent = etcp_udp_send(dgram->link, dgram->link->conn->fd, enc_buf, enc_buf_len + dgram->noencrypt_len,
(struct sockaddr*)addr, addr_len);
if (sent < 0) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "sendto failed, sock_err=%d dst=%s fd=%d",
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "sendto failed, sock_err=%d dst=%s fd=%d",
socket_get_error(), sockaddr_storage_to_str(addr).str, dgram->link->conn->fd);
dgram->link->send_errors++; errcode=4; goto es_err;
}
return (int)sent;
es_err:
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "error %d", errcode);
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "error %d", errcode);
return -1;
}
static int etcp_send_ping_raw(struct ETCP_DGRAM* dgram, socket_t fd, sc_context_t* sc, const struct sockaddr_storage* addr) {
if (!dgram || !sc || !addr) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "Null pointer in ping send");
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Null pointer in ping send");
return -1;
}
int len = dgram->data_len - dgram->noencrypt_len;
if (len < 0 || len > PACKET_DATA_SIZE - IP_UDP_OVERHEAD_V4) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "ping packet data invalid len=%d", len);
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "ping packet data invalid len=%d", len);
return -1;
}
uint8_t enc_buf[1600];
@ -1265,11 +1264,11 @@ static int etcp_send_ping_raw(struct ETCP_DGRAM* dgram, socket_t fd, sc_context_
dgram->flag_up = 1;
sc_encrypt(sc, (uint8_t*)&dgram->timestamp, 3 + len, enc_buf, &enc_buf_len);
if (enc_buf_len == 0) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "encryption failed for ping");
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "encryption failed for ping");
return -1;
}
if (enc_buf_len + dgram->noencrypt_len > (size_t)(PACKET_DATA_SIZE - IP_UDP_OVERHEAD_V4)) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "ping packet too long enc=%zu ne=%d", enc_buf_len, dgram->noencrypt_len);
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "ping packet too long enc=%zu ne=%d", enc_buf_len, dgram->noencrypt_len);
return -1;
}
memcpy(enc_buf + enc_buf_len, dgram->data + len, dgram->noencrypt_len);
@ -1279,10 +1278,10 @@ static int etcp_send_ping_raw(struct ETCP_DGRAM* dgram, socket_t fd, sc_context_
//xaddr[0]=192; xaddr[1]=168; xaddr[2]=10; xaddr[3]=1;
sent = socket_sendto(fd, enc_buf, enc_buf_len + dgram->noencrypt_len, (struct sockaddr*)addr, addr_len);
if (sent < 0) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "sendto failed for ping, err=%d addr=%s fd=%d len=%d", socket_get_error(), sockaddr_storage_to_str(addr).str, fd, enc_buf_len + dgram->noencrypt_len);
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "sendto failed for ping, err=%d addr=%s fd=%d len=%d", socket_get_error(), sockaddr_storage_to_str(addr).str, fd, enc_buf_len + dgram->noencrypt_len);
return -1;
}
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "ping sendto succeeded to %s sent=%zd bytes fd=%d", sockaddr_storage_to_str(addr).str, sent, fd);
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "ping sendto succeeded to %s sent=%zd bytes fd=%d", sockaddr_storage_to_str(addr).str, sent, fd);
return (int)sent;
}
@ -1318,21 +1317,21 @@ int etcp_send_ping_to_socket(struct UTUN_INSTANCE* instance, struct ETCP_SOCKET*
const uint8_t* user_data, size_t user_data_len,
uint8_t flags) {
if (!instance || !e_sock || !peer_pubkey_bin || !addr || timeout_ms <= 0 || !cb) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "bad args");
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "bad args");
return -1;
}
if (e_sock->is_tcp || e_sock->fd == SOCKET_INVALID) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "ping on non-UDP socket name=%s is_tcp=%d fd=%d",
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "ping on non-UDP socket name=%s is_tcp=%d fd=%d",
e_sock->name, e_sock->is_tcp, (int)e_sock->fd);
return -2;
}
if (user_data_len > PACKET_DATA_SIZE - 24 - 2 - SC_PUBKEY_ENC_SIZE) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "user_data too long");
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "user_data too long");
return -2;
}
struct PING_CONTEXT* ctx = u_malloc(sizeof(struct PING_CONTEXT));
if (!ctx) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "malloc ctx");
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "malloc ctx");
return -3;
}
ctx->next = NULL;
@ -1348,7 +1347,7 @@ int etcp_send_ping_to_socket(struct UTUN_INSTANCE* instance, struct ETCP_SOCKET*
ctx->user_data = u_malloc(user_data_len);
if (!ctx->user_data) {
u_free(ctx);
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "malloc user_data");
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "malloc user_data");
return -3;
}
memcpy(ctx->user_data, user_data, user_data_len);
@ -1359,7 +1358,7 @@ int etcp_send_ping_to_socket(struct UTUN_INSTANCE* instance, struct ETCP_SOCKET*
if (!dgram) {
if (ctx->user_data) u_free(ctx->user_data);
u_free(ctx);
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "malloc dgram");
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "malloc dgram");
return -4;
}
dgram->link = NULL;
@ -1394,7 +1393,7 @@ int etcp_send_ping_to_socket(struct UTUN_INSTANCE* instance, struct ETCP_SOCKET*
DEBUG_ERROR(DEBUG_CATEGORY_CRYPTO, "set key failed");
return -5;
}
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "ping send nonce=%016llx timeout=%d ulen=%zu",
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "ping send nonce=%016llx timeout=%d ulen=%zu",
(unsigned long long)ctx->nonce, timeout_ms, user_data_len);
int send_rc = etcp_send_ping_raw(dgram, e_sock->fd, &sc, addr);
u_free(dgram);
@ -1419,7 +1418,7 @@ int etcp_send_ping(struct UTUN_INSTANCE* instance, const uint8_t* peer_pubkey_bi
etcp_ping_callback_t cb, void* user_arg,
const uint8_t* user_data, size_t user_data_len) {
if (!instance || !peer_pubkey_bin || !addr || timeout_ms <= 0 || !cb) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "bad args: inst=%p pubkey=%p addr=%p timeout=%d cb=%p udata=%p udata_len=%zu",
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "bad args: inst=%p pubkey=%p addr=%p timeout=%d cb=%p udata=%p udata_len=%zu",
(void*)instance, (void*)peer_pubkey_bin, (void*)addr, timeout_ms,
(void*)(uintptr_t)cb, (void*)user_data, user_data_len);
return -1;
@ -1427,10 +1426,10 @@ int etcp_send_ping(struct UTUN_INSTANCE* instance, const uint8_t* peer_pubkey_bi
struct ETCP_SOCKET* e_sock = instance->etcp_sockets;
while (e_sock && e_sock->local_addr.ss_family != addr->ss_family) e_sock = e_sock->next;
if (!e_sock) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "no socket for addr_family=%d", addr->ss_family);
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "no socket for addr_family=%d", addr->ss_family);
return -2;
}
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "ping N1 [%s]", sockaddr_storage_to_str(addr).str);
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "ping N1 [%s]", sockaddr_storage_to_str(addr).str);
return etcp_send_ping_to_socket(instance, e_sock, peer_pubkey_bin, addr, timeout_ms,
cb, user_arg, user_data, user_data_len, 0);
}
@ -1450,7 +1449,7 @@ int etcp_send_tcp_ping(struct UTUN_INSTANCE* instance, const uint8_t* peer_pubke
const struct sockaddr_storage* addr, int timeout_ms,
etcp_ping_callback_t cb, void* user_arg) {
if (!instance || !peer_pubkey_bin || !addr || timeout_ms <= 0 || !cb) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "bad args: inst=%p pubkey=%p addr=%p timeout=%d cb=%p",
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "bad args: inst=%p pubkey=%p addr=%p timeout=%d cb=%p",
(void*)instance, (void*)peer_pubkey_bin, (void*)addr, timeout_ms, (void*)(uintptr_t)cb);
return -1;
}
@ -1465,17 +1464,17 @@ int etcp_send_tcp_ping(struct UTUN_INSTANCE* instance, const uint8_t* peer_pubke
snprintf(addr_str, sizeof(addr_str), "%s", ip_to_str(&sin6->sin6_addr, AF_INET6).str);
port = ntohs(sin6->sin6_port);
} else {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "unsupported addr family=%d", addr->ss_family);
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "unsupported addr family=%d", addr->ss_family);
return -2;
}
struct tcp_ping_adapter* a = u_malloc(sizeof(struct tcp_ping_adapter));
if (!a) { DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "malloc adapter"); return -3; }
if (!a) { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "malloc adapter"); return -3; }
a->cb = cb; a->arg = user_arg;
struct stcp_client* cli = stcp_ping_send(instance->ua, addr_str, port, &instance->my_keys, peer_pubkey_bin,
instance->my_ed25519_pubkey, instance->client_type,
instance->keepalive_interval, timeout_ms, tcp_ping_cb_adapter, a);
if (!cli) { u_free(a); return -4; }
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "tcp ping to %s:%u timeout=%d", addr_str, (unsigned)port, timeout_ms);
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "tcp ping to %s:%u timeout=%d", addr_str, (unsigned)port, timeout_ms);
return 0;
}
@ -1483,7 +1482,7 @@ int etcp_send_tcp_ping(struct UTUN_INSTANCE* instance, const uint8_t* peer_pubke
static int handle_ping(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pkt, const struct sockaddr_storage* addr, const uint8_t* decrypted_pubkey, size_t pkt_len) {
if (pkt_len < 23) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "PING too short: pkt_len=%zu from %s", pkt_len, sockaddr_storage_to_str(addr).str);
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "PING too short: pkt_len=%zu from %s", pkt_len, sockaddr_storage_to_str(addr).str);
return 7;
}
uint8_t flags = pkt->data[1];
@ -1495,7 +1494,7 @@ static int handle_ping(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pkt, const
if ((flags & ETCP_PING_FLAG_SEND_RTT) && ulen >= 2) {
uint16_t rtt_val = be16toh(*(uint16_t*)udata);
topo_node_ping_update_rtt(e_sock->instance->topo_groups, peer_id, rtt_val);
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "PING rtt=%u from peer=%016llx", (unsigned)rtt_val, (unsigned long long)peer_id);
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "PING rtt=%u from peer=%016llx", (unsigned)rtt_val, (unsigned long long)peer_id);
}
uint8_t pong_flags = 0;
@ -1527,7 +1526,7 @@ static int handle_ping(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pkt, const
sc_context_t resp_sc;
sc_init_ctx(&resp_sc, &e_sock->instance->my_keys);
if (sc_set_peer_public_key(&resp_sc, decrypted_pubkey, SC_PEER_PUBKEY_BIN) == SC_OK) {
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "PONG send nonce=%016llx flags=%02x to=%s fd=%d",
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "PONG send nonce=%016llx flags=%02x to=%s fd=%d",
(unsigned long long)nonce, (unsigned)pong_flags, sockaddr_storage_to_str(addr).str, e_sock->fd);
etcp_send_ping_raw(resp, e_sock->fd, &resp_sc, addr);
}
@ -1544,7 +1543,7 @@ static void rtt_send_ping_cb(int success, uint16_t rtt, void* arg, uint64_t nonc
static int handle_pong(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pkt, const struct sockaddr_storage* addr, size_t pkt_len) {
if (pkt_len < 23) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "PONG too short: pkt_len=%zu from %s", pkt_len, sockaddr_storage_to_str(addr).str);
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "PONG too short: pkt_len=%zu from %s", pkt_len, sockaddr_storage_to_str(addr).str);
return 7;
}
uint8_t flags = pkt->data[1];
@ -1557,7 +1556,7 @@ static int handle_pong(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pkt, const
udata = pkt->data + 20;
}
}
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "PONG recv nonce=%016llx flags=%02x data_len=%u from=%s socket=%s",
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "PONG recv nonce=%016llx flags=%02x data_len=%u from=%s socket=%s",
(unsigned long long)nonce, (unsigned)flags, (unsigned)pkt->data_len,
sockaddr_storage_to_str(addr).str, e_sock->name);
struct PING_CONTEXT* ctx = e_sock->instance->pending_pings;
@ -1574,7 +1573,7 @@ static int handle_pong(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pkt, const
}
uint64_t now = get_time_tb();
uint16_t rtt = (now >= ctx->send_time) ? (uint16_t)(now - ctx->send_time) : 0;
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "PONG matched nonce=%016llx rtt=%u want_rtt=%d",
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "PONG matched nonce=%016llx rtt=%u want_rtt=%d",
(unsigned long long)nonce, (unsigned)rtt, (flags & ETCP_PING_FLAG_WANT_RTT) ? 1 : 0);
uint64_t pong_peer_id = be64toh(*(uint64_t*)(pkt->data + 2));
@ -1597,7 +1596,7 @@ static int handle_pong(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pkt, const
ctx = ctx->next;
}
if (!found) {
DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "PONG nonce=%016llx NOT FOUND in pending (timeout?)",
DEBUG_WARN(DEBUG_CATEGORY_ETCP, "PONG nonce=%016llx NOT FOUND in pending (timeout?)",
(unsigned long long)nonce);
}
memory_pool_free(e_sock->instance->pkt_pool, pkt);
@ -1610,10 +1609,10 @@ static void send_init_response(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pk
// Set response code: 0x03 (with reset) or 0x05 (without reset)
// response with init (0x03) only if reinit was actually done on server side
if (send_reset != 0) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "send init_response with reset");
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "send init_response with reset");
resp->code = ETCP_INIT_RESPONSE; // 0x03 - with reset
} else {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "send init_response without reset");
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "send init_response without reset");
resp->code = ETCP_INIT_RESPONSE_NOINIT; // 0x05 - without reset
}
*(uint64_t*)resp->node_id = htobe64(e_sock->instance->node_id);
@ -1752,7 +1751,7 @@ static int handle_init_response_client(struct ETCP_SOCKET* e_sock, struct ETCP_D
struct ETCP_INIT_RESPONSE_PKT* resp = (struct ETCP_INIT_RESPONSE_PKT*)pkt->data;
uint64_t server_node_id = be64toh(*(uint64_t*)resp->node_id);
uint64_t resp_reset_id = be64toh(*(uint64_t*)resp->reset_id);
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "INIT_RESPONSE rid=%016llx", (unsigned long long)resp_reset_id);
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "INIT_RESPONSE rid=%016llx", (unsigned long long)resp_reset_id);
etcp_conn_apply_peer_reset_id(link->etcp, resp_reset_id);
link->mtu_remote = be16toh(*(uint16_t*)resp->mtu);
if (link->mtu_remote > PACKET_DATA_MAX_MTU) link->mtu_remote = PACKET_DATA_MAX_MTU;
@ -1811,7 +1810,7 @@ static int handle_init_response_client(struct ETCP_SOCKET* e_sock, struct ETCP_D
}
} else {
// Legacy format without NAT info
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[%s] Received legacy INIT_RESPONSE without NAT info",
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] Received legacy INIT_RESPONSE without NAT info",
link->etcp->log_name);
}
@ -1855,7 +1854,7 @@ static int handle_init_response_client(struct ETCP_SOCKET* e_sock, struct ETCP_D
}
void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
// DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "etcp_connections_read_callback fd=%d, socket=%p", fd, arg);
// !!!!!! DANGER: в этой функции ПРЕДЕЛЬНАЯ АККУРАТНОСТЬ. Если кажется что не туда указатель то невнимательно аланизировал !!!!!
// НЕ РУИНИТЬ (uint8_t*)&pkt->timestamp - это правильно !!!!
@ -1928,7 +1927,7 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
// This handles: no link found, or link without session, or normal decrypt failed
if (recv_len <= SC_PUBKEY_ENC_SIZE + UDP_SC_HDR_SIZE) {
if (e_sock->pkt_format_errors < 2)
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "packet too small for init, size=%zd from %s", recv_len, sockaddr_storage_to_str(&addr).str);
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "packet too small for init, size=%zd from %s", recv_len, sockaddr_storage_to_str(&addr).str);
errorcode=1;
goto ec_fr;
}
@ -1972,12 +1971,12 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
// INIT decryption succeeded - process packet
if (pkt_len<3) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "too short packet, from %s", sockaddr_storage_to_str(&addr).str);
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "too short packet, from %s", sockaddr_storage_to_str(&addr).str);
errorcode=7;
goto ec_fr;
}
if (pkt_len<15) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "decrypted packet too short for INIT header, pkt_len=%zu from %s", pkt_len, sockaddr_storage_to_str(&addr).str);
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "decrypted packet too short for INIT header, pkt_len=%zu from %s", pkt_len, sockaddr_storage_to_str(&addr).str);
errorcode=7;
goto ec_fr;
}
@ -1987,38 +1986,38 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
uint8_t code = pkt->data[0];
uint64_t peer_id = be64toh(*(uint64_t*)(pkt->data + 2));
if (code == ETCP_PING) {
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "X25519 decrypted: PING from peer=0x%016llx src=%s",
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "X25519 decrypted: PING from peer=0x%016llx src=%s",
(unsigned long long)peer_id, sockaddr_storage_to_str(&addr).str);
int ret = handle_ping(e_sock, pkt, &addr, decrypted_pubkey, pkt_len);
if (ret) { errorcode = ret; goto ec_fr; }
return;
}
if (code == ETCP_PONG) {
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "X25519 decrypted: PONG from peer=0x%016llx src=%s",
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "X25519 decrypted: PONG from peer=0x%016llx src=%s",
(unsigned long long)peer_id, sockaddr_storage_to_str(&addr).str);
int ret = handle_pong(e_sock, pkt, &addr, pkt_len);
if (ret) { errorcode = ret; goto ec_fr; }
return;
}
if (code!=ETCP_INIT_REQUEST && code!=ETCP_INIT_REQUEST_NOINIT) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "not an init packet: code=0x%02x (expected 0x02/0x04) from %s — packet dropped",
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "not an init packet: code=0x%02x (expected 0x02/0x04) from %s — packet dropped",
code, sockaddr_storage_to_str(&addr).str);
errorcode=4;
goto ec_fr;
}// не init
if (e_sock->type == CFG_SERVER_TYPE_PRIVATE) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "INIT rejected: socket %s (type=PRIVATE) does not accept incoming connections", e_sock->name);
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "INIT rejected: socket %s (type=PRIVATE) does not accept incoming connections", e_sock->name);
errorcode=8;
goto ec_fr;
}
if (pkt_len < ETCP_INIT_REQ_SIZE) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "INIT REQUEST too short: pkt_len=%zu from %s", pkt_len, sockaddr_storage_to_str(&addr).str);
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "INIT REQUEST too short: pkt_len=%zu from %s", pkt_len, sockaddr_storage_to_str(&addr).str);
errorcode=7;
goto ec_fr;
}
if (link)
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "INIT packet on existing link from=%s log=%s link_state=%d",
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "INIT packet on existing link from=%s log=%s link_state=%d",
sockaddr_storage_to_str(&addr).str,
link->etcp ? link->etcp->log_name : "null", link->link_state);
@ -2026,7 +2025,7 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
struct global_config *global = &e_sock->instance->config->global;
if (!global->allowed_keys_allow_all) {
if (global->allowed_keys_count == 0) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "Connection rejected: no allowed_keys configured, allow_all=0");
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Connection rejected: no allowed_keys configured, allow_all=0");
errorcode=8;
goto ec_fr;
}
@ -2040,7 +2039,7 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
ak = ak->next;
}
if (!found) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "Connection rejected: peer public key not in allowed_keys list");
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Connection rejected: peer public key not in allowed_keys list");
errorcode=8;
goto ec_fr;
}
@ -2065,7 +2064,7 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
struct conn_queue_entry* ce = (struct conn_queue_entry*)ol->etcp->conn_queue_entry->data;
if (ce->peer_node_id == 0) {
conn = ol->etcp;
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[%s] reusing unindexed outbound conn (q_key=0, peer=0x%016llx) for incoming INIT from %s",
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] reusing unindexed outbound conn (q_key=0, peer=0x%016llx) for incoming INIT from %s",
conn->log_name, (unsigned long long)peer_id, sockaddr_storage_to_str(&addr).str);
}
}
@ -2075,7 +2074,7 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
if (!conn || conn->peer_node_id!=peer_id) {// создаём новое подключение [new etcp]
new_conn=1;
conn=etcp_connection_create(e_sock->instance,"");
if (!conn) { errorcode=55; DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "failed to create connection"); goto ec_fr; }
if (!conn) { errorcode=55; DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "failed to create connection"); goto ec_fr; }
memcpy(&conn->crypto_ctx, &sc, sizeof(sc));
DEBUG_DEBUG(DEBUG_CATEGORY_CRYPTO, "CRYPTO_CTX_INIT: log=%s seskey=%02x%02x%02x%02x peer_pub=%02x%02x%02x%02x my_priv=%02x%02x%02x%02x",
conn->log_name,
@ -2090,9 +2089,6 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
conn->peer_node_id = peer_id;
etcp_update_log_name(conn);
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "New connection received on socket %s: log_name=%s peer_id=%lu peer:%s", e_sock->name, conn->log_name, (unsigned long)peer_id, sockaddr_storage_to_str(&addr).str);
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "New connection from %s peer_id=%ld etcp=%p total=%d",
ip_to_str(&addr, addr.ss_family).str, peer_id, conn,
queue_entry_count(e_sock->instance->connections));
}
else {// check keys если существующее подключение
if (memcmp(conn->crypto_ctx.peer_public_key, sc.peer_public_key, SC_PUBKEY_SIZE)) {
@ -2109,7 +2105,7 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
}
if (conn->fin_wait) {
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[%s] received INIT during fin_wait, clearing", conn->log_name);
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] received INIT during fin_wait, clearing", conn->log_name);
conn->fin_wait = 0;
if (conn->fin_wait_clear_cb) { conn->fin_wait_clear_cb(conn, conn->fin_wait_clear_arg); conn->fin_wait_clear_cb = NULL; conn->fin_wait_clear_arg = NULL; }
}
@ -2140,7 +2136,7 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "[%s] remote addr updated: id=%u -> %s",
conn->log_name, existing_link->remote_link_id, sockaddr_storage_to_str(&addr).str);
} else {
DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "[%s] addr %s busy (up/foreign) — link id=%u left as-is",
DEBUG_WARN(DEBUG_CATEGORY_ETCP, "[%s] addr %s busy (up/foreign) — link id=%u left as-is",
conn->log_name, sockaddr_storage_to_str(&addr).str, existing_link->remote_link_id);
}
}
@ -2149,7 +2145,7 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
existing_link = etcp_link_find_by_addr(e_sock, &addr, 0);
if (existing_link && existing_link->etcp == conn) {
if (memcmp(conn->crypto_ctx.peer_public_key, sc.peer_public_key, SC_PUBKEY_SIZE)) {
DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "[%s] link address match but pubkey mismatch, firing node_changed", conn->log_name);
DEBUG_WARN(DEBUG_CATEGORY_ETCP, "[%s] link address match but pubkey mismatch, firing node_changed", conn->log_name);
DEBUG_ERROR(DEBUG_CATEGORY_CRYPTO, "pubkey mismatch on reused link for node %016llx", (unsigned long long)peer_id);
conn->callbacks_running = 1;
etcp_cbk_fire(conn, ETCP_CBK_EVENT_NODE_CHANGED);
@ -2157,11 +2153,11 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
errorcode = 67;
goto ec_fr;
}
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[%s] found existing outbound link by addr for incoming INIT, reusing link=%p",
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] found existing outbound link by addr for incoming INIT, reusing link=%p",
conn->log_name, existing_link);
} else if (existing_link) {
struct ETCP_CONN* old_conn = existing_link->etcp;
DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "[%s] conflicting link at %s belongs to %s, firing node_changed",
DEBUG_WARN(DEBUG_CATEGORY_ETCP, "[%s] conflicting link at %s belongs to %s, firing node_changed",
conn->log_name, sockaddr_storage_to_str(&addr).str, old_conn->log_name);
DEBUG_ERROR(DEBUG_CATEGORY_CRYPTO, "link address conflict for node %016llx, firing node_changed callbacks on %s",
(unsigned long long)peer_id, old_conn->log_name);
@ -2178,10 +2174,10 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
uint8_t send_reset = 0;
if (existing_link && existing_link->etcp == conn) {// существующий линк
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[%s] found existing link for id=%d, socket=[%s]", conn->log_name, req->link_id, e_sock->name);
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] found existing link for id=%d, socket=[%s]", conn->log_name, req->link_id, e_sock->name);
link = existing_link;
if (!sockaddr_equal(&link->remote_addr, &addr)) {
DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "[%s] IP:port changed for remote_link_id=%d socket:[%s] — closing old link, creating new",
DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "[%s] IP:port changed for remote_link_id=%d socket:[%s] — closing old link, creating new",
conn->log_name, req->link_id, e_sock->name);
etcp_link_close(link);
goto create_new_link;
@ -2194,7 +2190,7 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
// ── Collision handling ──
if (req->collision) {
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[%s] INIT collision=1 from peer=%016llx — remote is master, becoming slave",
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] INIT collision=1 from peer=%016llx — remote is master, becoming slave",
conn->log_name, (unsigned long long)peer_id);
etcp_conn_reinit(conn, "collision yield");
send_reset = 1;
@ -2203,13 +2199,13 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
struct ETCP_LINK* ml = etcp_select_collision_link(conn, &addr);
if (ml) {
if (conn->instance->node_id < peer_id) {
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[%s] COLLISION: we=master node_id=%016llx < peer=%016llx — sending collision INIT",
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] COLLISION: we=master node_id=%016llx < peer=%016llx — sending collision INIT",
conn->log_name, (unsigned long long)conn->instance->node_id, (unsigned long long)peer_id);
memory_pool_free(e_sock->instance->pkt_pool, pkt);
etcp_link_send_init(ml, 0, 1);
return;
}
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[%s] COLLISION: peer smaller, yielding master, processing as slave",
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] COLLISION: peer smaller, yielding master, processing as slave",
conn->log_name);
if (ml->init_timer) { uasync_cancel_timeout(conn->instance->ua, ml->init_timer); ml->init_timer = NULL; }
}
@ -2233,10 +2229,10 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
}
} else {
create_new_link:
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[%s] NO existing link for id=%d, socket=[%s]", conn->log_name, req->link_id, e_sock->name);
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] NO existing link for id=%d, socket=[%s]", conn->log_name, req->link_id, e_sock->name);
// Create new link
link = etcp_link_new(conn, e_sock, &addr, 1);
if (!link) { if (new_conn) etcp_connection_close(conn); errorcode=66; DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "failed to create link for connection"); goto ec_fr; }// облом
if (!link) { if (new_conn) etcp_connection_close(conn); errorcode=66; DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "failed to create link for connection"); goto ec_fr; }// облом
link->remote_link_id = req->link_id;
link->remote_socket_id = req->socket_id;
link->remote_only_local = req->only_local;
@ -2244,7 +2240,7 @@ create_new_link:
// ── Collision handling ──
if (req->collision) {
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[%s] INIT collision=1 from peer=%016llx — remote is master, becoming slave",
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] INIT collision=1 from peer=%016llx — remote is master, becoming slave",
conn->log_name, (unsigned long long)peer_id);
etcp_conn_reinit(conn, "collision yield");
send_reset = 1;
@ -2252,7 +2248,7 @@ create_new_link:
// Check if WE have an outbound (master) link
struct ETCP_LINK* ml = etcp_select_collision_link(conn, &addr);
if (ml && conn->instance->node_id < peer_id) {
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[%s] COLLISION: we=master node_id=%016llx < peer=%016llx — sending collision INIT",
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] COLLISION: we=master node_id=%016llx < peer=%016llx — sending collision INIT",
conn->log_name, (unsigned long long)conn->instance->node_id, (unsigned long long)peer_id);
memory_pool_free(e_sock->instance->pkt_pool, pkt);
etcp_link_send_init(ml, 0, 1);
@ -2311,7 +2307,7 @@ int etcp_packet_decrypted(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pkt,
link->remote_keepalive = pkt->flag_up;
if (link->recv_keepalive != 1) {
link->recv_keepalive = 1;
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[%s] Link %d recv_keepalive restored to 1 (was 0) link_status=%d remote_ka=%d state=%d init=%d links_up=%d",
DEBUG_DEBUG(DEBUG_CATEGORY_KEEPALIVE, "[%s] Link %d recv_keepalive restored to 1 (was 0) link_status=%d remote_ka=%d state=%d init=%d links_up=%d",
link->etcp->log_name, link->local_link_id, link->link_status, link->remote_keepalive, link->link_state, link->initialized, link->etcp->links_up);
}
@ -2399,7 +2395,7 @@ int etcp_create_server_socket(struct UTUN_INSTANCE* instance, struct CFG_SERVER*
}
int init_sockets(struct UTUN_INSTANCE* instance) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
if (!instance || !instance->config) return -1;
if (instance->etcp_sockets || instance->stcp_servers) {
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Sockets already initialized, skipping");
@ -2485,7 +2481,7 @@ int init_sockets(struct UTUN_INSTANCE* instance) {
}
success_count++;
DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "Initialized server %s on %s (links: %d)",
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Initialized server %s on %s (links: %d)",
server->name, sockaddr_storage_to_str(&server->ip).str, queue_entry_count(sock->links_queue));
server = server->next;
}
@ -2511,7 +2507,7 @@ struct NODE_CONN_DIRECT* etcp_config_client_reality(struct UTUN_INSTANCE* instan
struct NODE_CONN_DIRECT* handle = NULL;
int r = node_conn_direct_open_node(instance, node_id, NULL, NULL, &handle, &ni_tmp, NULL);
if (r == NCD_ERR || !handle) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "client %s reality: ncd open failed node=0x%016llx", client->name, (unsigned long long)node_id);
DEBUG_ERROR(DEBUG_CATEGORY_REALITY, "client %s reality: ncd open failed node=0x%016llx", client->name, (unsigned long long)node_id);
return NULL;
}
struct ETCP_CONN* conn = node_conn_direct_get_conn(handle);
@ -2520,32 +2516,32 @@ struct NODE_CONN_DIRECT* etcp_config_client_reality(struct UTUN_INSTANCE* instan
int link_count = 0;
for (struct CFG_CLIENT_LINK* cl = client->links; cl; cl = cl->next) {
if (cl->remote_addr.ss_family != AF_INET && cl->remote_addr.ss_family != AF_INET6) {
DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "client %s reality: link without remote addr, skipping", client->name);
DEBUG_WARN(DEBUG_CATEGORY_REALITY, "client %s reality: link without remote addr, skipping", client->name);
continue;
}
struct ETCP_SOCKET* bind_sock = NULL;
if (cl->local_srv) {
for (struct ETCP_SOCKET* s = instance->etcp_sockets; s; s = s->next)
if (strcmp(cl->local_srv->name, s->name) == 0) { bind_sock = s; break; }
if (!bind_sock) DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "client %s reality: bind socket '%s' not found, using auto", client->name, cl->local_srv->name);
else if (!bind_sock->is_tcp) { DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "client %s reality: bind socket '%s' is not TCP, ignoring bind", client->name, cl->local_srv->name); bind_sock = NULL; }
if (!bind_sock) DEBUG_WARN(DEBUG_CATEGORY_REALITY, "client %s reality: bind socket '%s' not found, using auto", client->name, cl->local_srv->name);
else if (!bind_sock->is_tcp) { DEBUG_ERROR(DEBUG_CATEGORY_REALITY, "client %s reality: bind socket '%s' is not TCP, ignoring bind", client->name, cl->local_srv->name); bind_sock = NULL; }
}
struct ETCP_LINK* tlink = etcp_link_new(conn, bind_sock, &cl->remote_addr, 0);
if (!tlink) { DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "client %s reality: etcp_link_new failed", client->name); continue; }
if (!tlink) { DEBUG_ERROR(DEBUG_CATEGORY_REALITY, "client %s reality: etcp_link_new failed", client->name); continue; }
tlink->is_tcp = 1;
tlink->reality = client->reality; tlink->reality_set = 1;
etcp_tcp_link_start_connect(tlink, &cl->remote_addr, 0);
link_count++;
DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "client %s reality: TCP link %d → %s sn=%s bind=%s",
DEBUG_INFO(DEBUG_CATEGORY_REALITY, "client %s reality: TCP link %d → %s sn=%s bind=%s",
client->name, tlink->local_link_id, sockaddr_storage_to_str(&cl->remote_addr).str,
client->reality.server_name, bind_sock ? bind_sock->name : "auto");
}
if (link_count == 0) DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "client %s reality: no links created", client->name);
if (link_count == 0) DEBUG_WARN(DEBUG_CATEGORY_REALITY, "client %s reality: no links created", client->name);
return handle;
}
int init_connections(struct UTUN_INSTANCE* instance) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
if (!instance || !instance->config) return -1;
struct utun_config* config = instance->config;
@ -2569,7 +2565,7 @@ int init_connections(struct UTUN_INSTANCE* instance) {
// Initialize clients via node_conn_direct
struct CFG_CLIENT* client = config->clients;
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "init_connections: clients=%p total_conns=%d", config->clients, queue_entry_count(instance->connections));
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "init_connections: clients=%p total_conns=%d", config->clients, queue_entry_count(instance->connections));
while (client) {
if (strlen(client->peer_public_key_hex) == 0) {
DEBUG_WARN(DEBUG_CATEGORY_CONFIG, "no peer public key configured for client %s", client->name);
@ -2577,11 +2573,11 @@ int init_connections(struct UTUN_INSTANCE* instance) {
}
uint8_t pubkey_bin[SC_PUBKEY_SIZE];
if (sc_hex_to_binary(client->peer_public_key_hex, pubkey_bin, SC_PUBKEY_SIZE) != 0) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "invalid peer pubkey hex for client %s", client->name);
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "invalid peer pubkey hex for client %s", client->name);
client = client->next; continue;
}
uint64_t node_id = sc_derive_node_id_from_pubkey(pubkey_bin);
DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "client %s node_id=0x%016llx", client->name, (unsigned long long)node_id);
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "client %s node_id=0x%016llx", client->name, (unsigned long long)node_id);
if (client->reality_enabled) {
struct NODE_CONN_DIRECT* rhandle = etcp_config_client_reality(instance, client, pubkey_bin, node_id);
@ -2590,7 +2586,7 @@ int init_connections(struct UTUN_INSTANCE* instance) {
if (ch) { ch->node_id = node_id; strncpy(ch->name, client->name, MAX_CONN_NAME_LEN - 1);
ch->handle = rhandle; ch->next = instance->config_conn_handles;
instance->config_conn_handles = ch;
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "client %s saved reality handle to config_conn_handles", client->name); }
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "client %s saved reality handle to config_conn_handles", client->name); }
}
client = client->next; continue;
}
@ -2632,11 +2628,11 @@ int init_connections(struct UTUN_INSTANCE* instance) {
break;
}
conn = node_conn_direct_get_conn(handle);
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "client %s ncd handle=%p conn=%p %s sock=%s",
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "client %s ncd handle=%p conn=%p %s sock=%s",
client->name, handle, conn, r == NCD_NEW ? "NEW" : "REUSED", sock->name);
} else {
struct ETCP_LINK* link = etcp_link_new(conn, sock, &cl->remote_addr, 0);
DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "client %s added link link_id=%d sock=%s", client->name, link ? link->local_link_id : -1, sock->name);
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "client %s added link link_id=%d sock=%s", client->name, link ? link->local_link_id : -1, sock->name);
}
}
@ -2645,7 +2641,7 @@ int init_connections(struct UTUN_INSTANCE* instance) {
if (ch) { ch->node_id = node_id; strncpy(ch->name, client->name, MAX_CONN_NAME_LEN - 1);
ch->handle = handle; ch->next = instance->config_conn_handles;
instance->config_conn_handles = ch;
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "client %s saved handle to config_conn_handles", client->name); }
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "client %s saved handle to config_conn_handles", client->name); }
}
client = client->next;

8
src/transport_layer/node_conn_direct.c

@ -169,9 +169,9 @@ static int ncd_create_links(struct ncd_entry* entry, struct TOPO_NODE* ni,
/* ---- IPv4 ---- */
for (const struct TOPO_ADDR4* a = ni->v4_addrs; a; a = a->next) {
v4_addrs++;
if (a->port == 0 || !(a->protocol & (TOPO_PROTO_UDP | TOPO_PROTO_TCP))) { DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[ncd] v4 skip proto=%02x port=%d node=0x%016llx", a->protocol, (int)a->port, (unsigned long long)nid); v4_skip++; continue; }
if (a->port == 0 || !(a->protocol & (TOPO_PROTO_UDP | TOPO_PROTO_TCP))) { DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[ncd] v4 skip proto=%02x port=%d node=0x%016llx", a->protocol, (int)a->port, (unsigned long long)nid); v4_skip++; continue; }
int zero = 1; for (int j = 0; j < 4; j++) if (a->addr[j] != 0) { zero = 0; break; }
if (zero) { DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[ncd] v4 skip zero-addr node=0x%016llx", (unsigned long long)nid); continue; }
if (zero) { DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[ncd] v4 skip zero-addr node=0x%016llx", (unsigned long long)nid); continue; }
struct sockaddr_in sin; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET;
memcpy(&sin.sin_addr.s_addr, a->addr, 4); sin.sin_port = htons(a->port);
struct sockaddr_storage sa; memcpy(&sa, &sin, sizeof(sin));
@ -198,9 +198,9 @@ static int ncd_create_links(struct ncd_entry* entry, struct TOPO_NODE* ni,
/* ---- IPv6 ---- */
for (const struct TOPO_ADDR6* a = ni->v6_addrs; a; a = a->next) {
v6_addrs++;
if (a->port == 0 || !(a->protocol & (TOPO_PROTO_UDP | TOPO_PROTO_TCP))) { DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[ncd] v6 skip proto=%02x port=%d node=0x%016llx", a->protocol, (int)a->port, (unsigned long long)nid); v6_skip++; continue; }
if (a->port == 0 || !(a->protocol & (TOPO_PROTO_UDP | TOPO_PROTO_TCP))) { DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[ncd] v6 skip proto=%02x port=%d node=0x%016llx", a->protocol, (int)a->port, (unsigned long long)nid); v6_skip++; continue; }
int zero = 1; for (int j = 0; j < 16; j++) if (a->addr[j] != 0) { zero = 0; break; }
if (zero) { DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[ncd] v6 skip zero-addr node=0x%016llx", (unsigned long long)nid); continue; }
if (zero) { DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[ncd] v6 skip zero-addr node=0x%016llx", (unsigned long long)nid); continue; }
int is_ll = (a->addr[0] == 0xfe && (a->addr[1] & 0xc0) == 0x80);
struct sockaddr_in6 sin6; memset(&sin6, 0, sizeof(sin6)); sin6.sin6_family = AF_INET6;
memcpy(&sin6.sin6_addr, a->addr, 16); sin6.sin6_port = htons(a->port);

6
tools/chatgui-android/AGENTS.md

@ -203,10 +203,10 @@ allow_all=yes
[ntp]
enabled=no
[chat]
[chatserver]
storage_autoload=1
storage_autoload_maxsize_mb=10
storage_maxsize_gb=1
storage_unit_size=10M
storage_total_size=1G
opus_codec_preset=1
compressor_enabled=0
compressor_max_gain_db=25

2
tools/chatgui/src/audiodevicesettingspage.cpp

@ -345,7 +345,7 @@ void AudioDeviceSettingsPage::buildCompressorUI(QVBoxLayout* layout) {
};
makeSliderRow("Max gain:", m_compressorMaxGainSlider, m_compressorMaxGainLabel,
0, 50, 1);
1, 50, 1);
makeSliderRow("Rise rate (x/sec):", m_compressorRiseRateSlider, m_compressorRiseRateLabel,
2, 10, 1);

25
tools/chatgui/src/settingsdialog.cpp

@ -214,17 +214,19 @@ void SettingsDialog::onCategoryChanged(int row) {
void SettingsDialog::onSave() {
QString newName = m_nicknameEdit->text().trimmed();
bool nameChanged = (newName != m_oldNickname);
/* update name in uTun if changed */
if (newName != m_oldNickname) {
if (nameChanged) {
char* name_copy = u_strdup(newName.toUtf8().constData());
if (name_copy) gui_bridge_post_uasync_fn(chat_core_update_my_name_trampoline, name_copy);
m_oldNickname = newName;
}
// Save nickname to config
/* Save nickname to config — только при изменении имени, иначе перезапись плодит дубли */
if (nameChanged) {
QFile f(m_configPath);
if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) { accept(); return; }
if (f.open(QIODevice::ReadOnly | QIODevice::Text)) {
QString content = f.readAll();
f.close();
@ -235,18 +237,27 @@ void SettingsDialog::onSave() {
bool found = false;
for (int i = 0; i < lines.size(); i++) {
if (lines[i].trimmed().startsWith("my_node_name=")) {
lines[i] = "my_node_name=" + newName;
found = true;
} else if (!found && lines[i].trimmed() == "[global]") {
if (!found) { lines[i] = "my_node_name=" + newName; found = true; }
else lines.removeAt(i--); /* дубль — удалить */
}
}
if (!found) {
for (int i = 0; i < lines.size(); i++) {
if (lines[i].trimmed() == "[global]") {
lines.insert(i + 1, "my_node_name=" + newName);
found = true;
break;
}
}
if (!found) lines << "my_node_name=" + newName;
}
f.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text);
if (f.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) {
f.write(lines.join('\n').toUtf8());
f.close();
}
}
}
m_networkPage->saveToConfig(m_configPath);

4
tools/chatgui/src/storagesettingspage.cpp

@ -106,7 +106,7 @@ void StorageSettingsPage::applyAndSave() {
if (!m_configPath.isEmpty()) {
postChatSetting(m_configPath, "storage_autoload", autoload);
postChatSetting(m_configPath, "storage_autoload_maxsize_mb", autoloadMaxSize);
postChatSetting(m_configPath, "storage_maxsize_gb", maxGb);
config_update_option(m_configPath, "chatserver", "storage_unit_size", QString::number(autoloadMaxSize) + "M", CONFIG_UPDATE_REPLACE);
config_update_option(m_configPath, "chatserver", "storage_total_size", QString::number(maxGb) + "G", CONFIG_UPDATE_REPLACE);
}
}

5
utun.conf.sample

@ -156,7 +156,12 @@ allow=all
#db_path=/var/lib/utun # путь к SQLite базе данных (обязательно)
#join_password=secret123 # пароль входа в группы (будет в invite-ссылке)
#allowed_groups=all # "all" или hex-ID через запятую
#headless_control_bind=127.0.0.1:9999 # TCP control-socket для headless chat CLI
#storage_total_size=500M # общий лимит медиакеша (0=безлимит)
#storage_unit_size=50M # лимит одного медиафайла (0=отключено)
#storage_autoload=1 # автозагрузка медиавложений (0/1)
#media_download_max_peers=3 # макс. одновременных пиров для загрузки
#opus_codec_preset=1 # пресет Opus (0..4)
#compressor_enabled=0 # компрессор голосовых сообщений (0/1)
#compressor_max_gain_db=25 # макс. gain компрессора, дБ (1..100)
#compressor_rise_rate=10 # скорость нарастания компрессора (1..100)

Loading…
Cancel
Save