fix: auto_socket TCP duplicate sockets + NAT v4 address resolution

auto_socket.c: create_iface_tcp_socket returns stcp_server* instead of int,
ifa->v4_tcp/ifa->v6_tcp now properly track the created server, preventing
duplicate bind/listen on every reconcile_iface call.

etcp_connections.c: tcp_socket_add now resolves interface_addr via
get_interface_ip_by_index/get_interface_ipv6_addr_nl for any type (not just
PUBLIC), preventing NAT TCP v4 sockets from being destroyed due to INADDR_ANY.
This commit is contained in:
evgeny committed 2026-08-07 20:06:30 +03:00
1 parent de61a2dacc
commit 80e77f12c2
12 files changed
+202 -66

No files matched your search

+73 -2
View File
@@ -9,6 +9,7 @@
#include <QLabel>
#include <QDateTime>
#include <QFont>
#include <QSet>
#include "../../../lib/platform_compat.h"
extern "C" {
@@ -16,6 +17,8 @@ extern "C" {
#include "etcp.h"
#include "etcp_connections.h"
#include "../lib/socket_compat.h"
#include "../lib/ll_queue.h"
#include "stcp_link.h"
}
QString AccountList::addrStr(const void* addr, int family) {
@@ -211,6 +214,30 @@ void AccountList::updateDetailDisplay() {
struct ETCP_CONN* conn = nullptr;
if (m_inst) conn = instance_find_conn(m_inst, m_detailNodeId);
bool isSelf = m_db ? (m_detailNodeId == m_db->myNodeId()) : false;
QSet<struct ETCP_LINK*> matchedLinks;
/* Count active TCP connections for own node (shared across all TCP sockets) */
int ownTcpActiveLinks = 0;
if (isSelf && m_inst) {
if (m_inst->connections) {
for (struct ll_entry* e = m_inst->connections->head; e; e = e->next) {
struct conn_queue_entry* ce = (struct conn_queue_entry*)e->data;
if (ce && ce->conn && ce->conn->initialized) {
for (struct ETCP_LINK* lk = ce->conn->links; lk; lk = lk->next) {
if (lk->is_tcp) { ownTcpActiveLinks++; break; }
}
}
}
}
if (m_inst->tcp_connections) {
for (struct ll_entry* e = m_inst->tcp_connections->head; e; e = e->next) {
struct tcp_conn_entry* te = (struct tcp_conn_entry*)e->data;
if (te && te->etcp_conn && te->etcp_conn->initialized) ownTcpActiveLinks++;
}
}
}
for (const auto& a : m_detailAddrs) {
QString proto;
switch (a.protocol) { case 1: proto = "UDP"; break; case 2: proto = "TCP"; break; default: proto = "UDP/TCP"; break; }
@@ -231,6 +258,7 @@ void AccountList::updateDetailDisplay() {
}
if (lfm == a.family && lpo == (uint16_t)a.port && lip == addrStr(a.addr.constData(), a.family)) {
linkColor = (lk->link_state == 3 && lk->link_status == 1) ? "#4CAF50" : "#E53935";
matchedLinks.insert(lk);
break;
}
}
@@ -243,8 +271,51 @@ void AccountList::updateDetailDisplay() {
}
}
}
lines.append(QString("<span style='color:%1;'>●</span> %2:%3:%4")
.arg(linkColor, proto, addrStr(a.addr.constData(), a.family)).arg(a.port));
QString prefix;
if (isSelf && m_inst) {
int linkCount = 0;
if (a.protocol == 1) {
for (struct ETCP_SOCKET* sock = m_inst->etcp_sockets; sock; sock = sock->next) {
uint16_t sp = 0;
const struct sockaddr_storage* addr = sock->interface_addr.ss_family ? &sock->interface_addr : &sock->local_addr;
if (addr->ss_family == AF_INET) sp = ntohs(((const struct sockaddr_in*)addr)->sin_port);
else if (addr->ss_family == AF_INET6) sp = ntohs(((const struct sockaddr_in6*)addr)->sin6_port);
if (sp == (uint16_t)a.port) {
linkCount = sock->links_queue ? queue_entry_count(sock->links_queue) : 0;
break;
}
}
} else if (a.protocol == 2) {
linkCount = ownTcpActiveLinks;
}
if (linkCount > 0) prefix = QString("[%1] ").arg(linkCount);
}
lines.append(QString("%1<span style='color:%2;'>●</span> %3:%4:%5")
.arg(prefix, linkColor, proto, addrStr(a.addr.constData(), a.family)).arg(a.port));
}
/* Show ETCP links that are not in DB (non-self) */
if (conn) {
for (struct ETCP_LINK* lk = conn->links; lk; lk = lk->next) {
if (matchedLinks.contains(lk)) continue;
const struct sockaddr_storage* sa = &lk->remote_addr;
char ipbuf[INET6_ADDRSTRLEN]; QString lip; uint16_t lpo = 0;
if (sa->ss_family == AF_INET) {
struct sockaddr_in* sin = (struct sockaddr_in*)sa;
inet_ntop(AF_INET, &sin->sin_addr, ipbuf, sizeof(ipbuf));
lpo = ntohs(sin->sin_port); lip = QString::fromLocal8Bit(ipbuf);
} else if (sa->ss_family == AF_INET6) {
struct sockaddr_in6* sin6 = (struct sockaddr_in6*)sa;
inet_ntop(AF_INET6, &sin6->sin6_addr, ipbuf, sizeof(ipbuf));
lpo = ntohs(sin6->sin6_port); lip = QString::fromLocal8Bit(ipbuf);
} else { continue; }
QString proto = lk->is_tcp ? "TCP" : "UDP";
QString lc = (lk->link_state == 3 && lk->link_status == 1) ? "#4CAF50" : "#E53935";
lines.append(QString("<span style='color:%1;'>●</span> %2:%3:%4 [link]")
.arg(lc, proto, lip).arg(lpo));
}
}
m_detailText->setHtml(lines.join("<br>"));