diff --git a/src/chat/chat_profile.c b/src/chat/chat_profile.c index 5540c84a..f70a19d5 100644 --- a/src/chat/chat_profile.c +++ b/src/chat/chat_profile.c @@ -163,6 +163,7 @@ void chat_core_sync_my_addresses(void) { if (!addr || !addr->ss_family) { ts = ts->next; continue; } if (addr->ss_family == AF_INET) { struct sockaddr_in* sin = (struct sockaddr_in*)addr; + if (sin->sin_addr.s_addr == 0) { ts = ts->next; continue; } // skip 0.0.0.0 sqlite3_bind_int64(tcp_ins, 1, (sqlite3_int64)g_cc.my_node_id); sqlite3_bind_int(tcp_ins, 2, 4); sqlite3_bind_blob(tcp_ins, 3, &sin->sin_addr, 4, SQLITE_STATIC); @@ -175,6 +176,7 @@ void chat_core_sync_my_addresses(void) { tcp_written++; } else if (addr->ss_family == AF_INET6) { struct sockaddr_in6* sin6 = (struct sockaddr_in6*)addr; + if (memcmp(&sin6->sin6_addr, &in6addr_any, 16) == 0) { ts = ts->next; continue; } // skip :: sqlite3_bind_int64(tcp_ins, 1, (sqlite3_int64)g_cc.my_node_id); sqlite3_bind_int(tcp_ins, 2, 6); sqlite3_bind_blob(tcp_ins, 3, &sin6->sin6_addr, 16, SQLITE_STATIC); diff --git a/src/transport_layer/etcp_connections.c b/src/transport_layer/etcp_connections.c index 47932f3e..f0a39551 100644 --- a/src/transport_layer/etcp_connections.c +++ b/src/transport_layer/etcp_connections.c @@ -213,7 +213,9 @@ void etcp_link_restart_init_timer(struct ETCP_LINK* link) { void etcp_link_enter_init(struct ETCP_LINK* link) {// DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, ""); if (!link) return; + int old_state = link->link_state; link->link_state = 1; // handshake + etcp_fire_link_status_cbk(link, old_state, link->link_status); if (link->is_server != 0) return; etcp_link_send_init(link,1,0);// init with reset etcp_link_restart_init_timer(link); @@ -222,7 +224,9 @@ void etcp_link_enter_init(struct ETCP_LINK* link) {// void etcp_link_enter_reinit(struct ETCP_LINK* link) { DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, ""); if (!link) return; + int old_state = link->link_state; link->link_state = 2; // reconnect + etcp_fire_link_status_cbk(link, old_state, link->link_status); etcp_on_link_down(link->etcp); if (link->is_server != 0) return; etcp_conn_reinit(link->etcp); @@ -324,7 +328,9 @@ static void keepalive_timer_cb(void* arg) { if (elapsed > timeout_units) { if (link->recv_keepalive != 0) { link->recv_keepalive = 0; + int old_link_status = link->link_status; link->link_status = 0; + etcp_fire_link_status_cbk(link, link->link_state, old_link_status); etcp_on_link_down(link->etcp); DEBUG_INFO(DEBUG_CATEGORY_KEEPALIVE, "[%s] Conn:%s Link down: link_id=%d state=%d init=%d ka=%d remote_ka=%d tmo: %llu>%llu els=%llums", link->etcp->log_name, link->conn?link->conn->name:"???", link->local_link_id, link->link_state, link->initialized, link->recv_keepalive, link->remote_keepalive, (unsigned long long)timeout_units, (unsigned long long)elapsed, (unsigned long long)(elapsed/10)); DEBUG_WARN(DEBUG_CATEGORY_KEEPALIVE, "[%s] Link %p (local_id=%d) recv status changed to DOWN - no packets for %llu ms", link->etcp->log_name, link, link->local_link_id, (unsigned long long)(elapsed/10)); @@ -1475,7 +1481,7 @@ static void send_init_response(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pk memory_pool_free(e_sock->instance->pkt_pool, pkt); link->initialized = 1; - link->link_state = 3; + { int old_state = link->link_state; link->link_state = 3; etcp_fire_link_status_cbk(link, old_state, link->link_status); } if (link->init_timer) { uasync_cancel_timeout(link->etcp->instance->ua, link->init_timer); link->init_timer = NULL; @@ -1579,7 +1585,7 @@ static int handle_init_response_client(struct ETCP_SOCKET* e_sock, struct ETCP_D etcp_update_log_name(link->etcp); link->initialized = 1;// получен init response (client) - link->link_state = 3; // connected + { int old_state = link->link_state; link->link_state = 3; etcp_fire_link_status_cbk(link, old_state, link->link_status); } if (link->init_timer) { uasync_cancel_timeout(link->etcp->instance->ua, link->init_timer); link->init_timer = NULL; @@ -2057,6 +2063,8 @@ process_decrypted: int was_up = link->link_status; link->link_status = link->remote_keepalive && link->recv_keepalive; + if (link->link_status != was_up) + etcp_fire_link_status_cbk(link, link->link_state, was_up); if (link->link_status && !was_up && link->initialized) { DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "[%s] Link %d status popped UP: recv_ka=%d remote_ka=%d state=%d init=%d → calling loadbalancer_link_ready", link->etcp->log_name, link->local_link_id, link->recv_keepalive, link->remote_keepalive, link->link_state, link->initialized); loadbalancer_link_ready(link); @@ -2091,7 +2099,7 @@ process_decrypted: if (link->link_state == 2) {// из recovery получен нормальный пакет - восстанавливаем линк в нормальный режим start_keepalive_timer(link); etcp_link_send_keepalive(link); // Start keepalive timer - link->link_state = 3; // connected + { int old_state = link->link_state; link->link_state = 3; etcp_fire_link_status_cbk(link, old_state, link->link_status); } } @@ -2120,7 +2128,7 @@ ec_fr: int init_sockets(struct UTUN_INSTANCE* instance) { DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, ""); if (!instance || !instance->config) return -1; - if (instance->etcp_sockets || instance->stcp_server) { + if (instance->etcp_sockets || instance->stcp_servers) { DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Sockets already initialized, skipping"); return 0; } @@ -2179,14 +2187,16 @@ int init_sockets(struct UTUN_INSTANCE* instance) { // TCP transport: create stcp_server instead of UDP socket if (server->transport) { - uint16_t port = ntohs(((struct sockaddr_in*)&server->ip)->sin_port); + uint16_t port = 0; + if (server->ip.ss_family == AF_INET) port = ntohs(((struct sockaddr_in*)&server->ip)->sin_port); + else if (server->ip.ss_family == AF_INET6) port = ntohs(((struct sockaddr_in6*)&server->ip)->sin6_port); struct stcp_link_config scfg = {.ua = instance->ua, .my_keys = &instance->my_keys, .inst = instance}; struct stcp_server *tsrv = stcp_server_listen(&scfg, port, tcp_server_on_link, instance); if (!tsrv) { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Failed to create TCP server for %s", server->name); fail_count++; } else { - instance->stcp_server = tsrv; + stcp_server_list_add(instance, tsrv); tcp_socket_add(instance, server); success_count++; DEBUG_INFO(DEBUG_CATEGORY_ETCP, "TCP server %s on port %u", server->name, port); @@ -2233,7 +2243,7 @@ int init_connections(struct UTUN_INSTANCE* instance) { int socket_result = 0; // If sockets already exist (created by init_sockets), check stored status - if (instance->etcp_sockets || instance->stcp_server) { + if (instance->etcp_sockets || instance->stcp_servers) { if (instance->socket_init_status == 1) { socket_result = 1; } diff --git a/src/transport_layer/etcp_dump.c b/src/transport_layer/etcp_dump.c index a64e50ec..b2211d34 100644 --- a/src/transport_layer/etcp_dump.c +++ b/src/transport_layer/etcp_dump.c @@ -193,7 +193,7 @@ void etcp_dump_sockets(struct UTUN_INSTANCE* instance) { s = s->next; idx++; } if (idx == 0) DHDR("--- NO SOCKETS ---"); - if (instance->stcp_server) DLOG("TCP: stcp_server ACTIVE"); + if (instance->stcp_servers) DLOG("TCP: stcp_servers count=%d", stcp_server_list_count(instance)); if (instance->tcp_connections) DLOG("TCP: tcp_connections queue %d entries", queue_entry_count(instance->tcp_connections)); DHDR("=== END DUMP SOCKETS ==="); diff --git a/src/transport_layer/stcp_link.c b/src/transport_layer/stcp_link.c index 03f49881..ba1fbc6d 100644 --- a/src/transport_layer/stcp_link.c +++ b/src/transport_layer/stcp_link.c @@ -15,6 +15,7 @@ #include struct stcp_server { + struct stcp_server *next; // linked list in UTUN_INSTANCE struct stcp_server *srv; // stcp_server from stcp_server.h struct stcp_link_config cfg; stcp_server_on_link_cb on_link; @@ -236,3 +237,29 @@ void stcp_link_set_on_close(struct stcp_link *link, void (*cb)(struct stcp_link link->on_close_cb = cb; link->close_arg = arg; } + +void stcp_server_list_add(struct UTUN_INSTANCE *inst, struct stcp_server *srv) { + if (!inst || !srv) return; + srv->next = inst->stcp_servers; + inst->stcp_servers = srv; + DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "stcp_server_list_add: %p total=%d", (void*)srv, stcp_server_list_count(inst)); +} + +void stcp_server_list_destroy_all(struct UTUN_INSTANCE *inst) { + if (!inst) return; + int count = 0; + while (inst->stcp_servers) { + struct stcp_server *next = inst->stcp_servers->next; + stcp_link_server_destroy(inst->stcp_servers); + inst->stcp_servers = next; + count++; + } + DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "stcp_server_list_destroy_all: destroyed %d servers", count); +} + +int stcp_server_list_count(struct UTUN_INSTANCE *inst) { + if (!inst) return 0; + int n = 0; + for (struct stcp_server *s = inst->stcp_servers; s; s = s->next) n++; + return n; +} diff --git a/src/transport_layer/stcp_link.h b/src/transport_layer/stcp_link.h index 94b825a7..0e8aeb45 100644 --- a/src/transport_layer/stcp_link.h +++ b/src/transport_layer/stcp_link.h @@ -37,6 +37,11 @@ struct stcp_server *stcp_server_listen(struct stcp_link_config *cfg, uint16_t po stcp_server_on_link_cb on_link, void *arg); void stcp_link_server_destroy(struct stcp_server *srv); +/* Server list management (multiple servers per instance) */ +void stcp_server_list_add(struct UTUN_INSTANCE *inst, struct stcp_server *srv); +void stcp_server_list_destroy_all(struct UTUN_INSTANCE *inst); +int stcp_server_list_count(struct UTUN_INSTANCE *inst); + // ====== TCP client link ====== struct stcp_link *stcp_link_connect(struct stcp_link_config *cfg); diff --git a/src/utun_instance.c b/src/utun_instance.c index 31fcf1b3..232f42b9 100644 --- a/src/utun_instance.c +++ b/src/utun_instance.c @@ -560,11 +560,8 @@ void utun_instance_destroy(struct UTUN_INSTANCE *instance) { // Cleanup firewall fw_free(&instance->fw); - // Cleanup TCP server - if (instance->stcp_server) { - stcp_link_server_destroy(instance->stcp_server); - instance->stcp_server = NULL; - } + // Cleanup TCP servers + stcp_server_list_destroy_all(instance); // Cleanup networks queue if (instance->networks) { diff --git a/src/utun_instance.h b/src/utun_instance.h index 59cb83b0..111ae062 100644 --- a/src/utun_instance.h +++ b/src/utun_instance.h @@ -125,6 +125,7 @@ struct UTUN_INSTANCE { // Callback chain for new ETCP connections struct etcp_inst_cbk_entry* new_conn_cbks; + struct etcp_link_status_cbk_entry* link_status_cbks; struct etcp_status_cbk_entry* conn_status_cbks; // instance-level: NEW/UP/DOWN/DELETE struct etcp_socket_cbk_entry* socket_cbks; // instance-level: socket ADDR/STATUS changes struct nodeinfo_cbk_entry* nodeinfo_cbks; // глобальная подписка на изменения nodeinfo @@ -137,7 +138,7 @@ struct UTUN_INSTANCE { // Active sockets (UDP) struct ETCP_SOCKET* etcp_sockets;// linked-list struct TCP_SOCKET* tcp_sockets; // linked-list [TCP-only] - struct stcp_server *stcp_server; // TCP server (single for now) + struct stcp_server *stcp_servers; // TCP servers linked list (via stcp_link.c) void* socket_monitor; // SOCKET_MONITOR* (opaque, transport_layer/socket_monitor.c) // Pending one-shot pings (for callback on PONG or timeout) diff --git a/tools/chatgui/transport/node_config.cpp b/tools/chatgui/transport/node_config.cpp index 836c497b..9247b5f5 100644 --- a/tools/chatgui/transport/node_config.cpp +++ b/tools/chatgui/transport/node_config.cpp @@ -328,7 +328,8 @@ bool NodeConfig::saveFull() { for (auto& srv : m_servers) { out << "[server:" << srv.first << "]\n"; - out << "addr=" << srv.second << "\n\n"; + out << "addr=" << srv.second << "\n"; + out << "type=public\n\n"; } for (auto& cli : m_clients) {