nat: prioritize mapping candidates and label unknown NAT explicitly

This commit is contained in:
evgeny committed 2026-10-17 17:47:18 +02:00
1 parent 6037819269
commit 79d8789410
3 files changed
+21 -7

No files matched your search

+7 -3
View File
@@ -48,6 +48,7 @@ struct nat_wire {
struct nat_pair {
uint64_t group, observer, helper;
uint8_t helper_priority; /* Сначала публичный endpoint C, затем приватный, затем один наблюдатель. */
uint8_t observer_endpoint[ROUTE_ADDR_WIRE_SIZE], helper_endpoint[ROUTE_ADDR_WIRE_SIZE];
};
struct nat_recheck_wire { uint8_t cmd, command, version, socket_id, address[ROUTE_ADDR_WIRE_SIZE]; };
@@ -223,6 +224,8 @@ static int node_udp_endpoint(struct NAT_DETECTION *detector, const struct TOPO_N
}
static int pair_after(struct nat_pair a, struct nat_pair b) {
if (!a.group || !b.group) return a.group != 0;
if (a.helper_priority != b.helper_priority) return a.helper_priority > b.helper_priority;
if (a.group != b.group) return a.group > b.group;
if (a.observer != b.observer) return a.observer > b.observer;
if (a.helper != b.helper) return a.helper > b.helper;
@@ -255,7 +258,7 @@ static int select_pair(struct nat_socket *state) {
node_udp_endpoint(detector, bn, state->local.ss_family, 0, previous_b, &ba, &bs)) {
if (!state->socket->is_tcp && route_ping_addr_encode(previous_b, &ba)) break;
observers++;
struct nat_pair observer_only = {.group = group->group_id, .observer = observer};
struct nat_pair observer_only = {.group = group->group_id, .observer = observer, .helper_priority = 2};
memcpy(observer_only.observer_endpoint, previous_b, sizeof(previous_b));
if (!state->socket->is_tcp && pair_after(observer_only, state->cursor) &&
(!single.group || pair_after(single, observer_only))) {
@@ -271,7 +274,8 @@ static int select_pair(struct nat_socket *state) {
for (; more_c; more_c = !state->socket->is_tcp &&
node_udp_endpoint(detector, cn, state->local.ss_family, 1, previous_c, &ca, &cs)) {
if (!state->socket->is_tcp && route_ping_addr_encode(previous_c, &ca)) break;
struct nat_pair candidate = {.group = group->group_id, .observer = observer, .helper = helper};
struct nat_pair candidate = {.group = group->group_id, .observer = observer, .helper = helper,
.helper_priority = !public_address(detector, &ca)};
memcpy(candidate.observer_endpoint, previous_b, sizeof(previous_b));
memcpy(candidate.helper_endpoint, previous_c, sizeof(previous_c));
if (state->using_fallback) {
@@ -1286,7 +1290,7 @@ static void owner_start(struct nat_socket *state) {
}
if (!state->cycling) {
state->cycling = 1; state->cursor = (struct nat_pair){0}; state->fallback = (struct nat_pair){0};
state->using_fallback = 0; state->prefer_fresh = 1;
state->using_fallback = 0; state->prefer_fresh = state->measured_profile.mapping != ADDRESS_MAP_UNKNOWN;
state->cycle_deadline = get_time_tb() + NAT_ROUND_TB;
}
history_load(state);
+1 -1
View File
@@ -61,7 +61,7 @@ QVariant MemberListModel::data(const QModelIndex& index, int role) const {
QString sub;
if (it->rtt >= 0) sub += QString("rtt=%1ms").arg(it->rtt / 10);
if (it->natType >= 0) {
static const char* nat[] = {"NET","DIR","EIM","DEP","?","CONTACT"};
static const char* nat[] = {"NET","DIR","EIM","DEP","NAT type=UNKNOWN","CONTACT"};
const char* nt = (it->natType <= 5) ? nat[it->natType] : "?";
if (!sub.isEmpty()) sub += " ";
sub += nt;
+13 -3
View File
@@ -12,6 +12,7 @@
#include <cstring>
#include "../../../lib/platform_compat.h"
#include "../../../src/routing_layer/topo_node.h"
static QString hex16(uint64_t v) {
return QString("%1").arg(v, 16, 16, QChar('0')).toUpper();
@@ -49,7 +50,15 @@ QString NodesPage::protoStr(int protocol) {
}
static QString addrTypeStr(int t) {
switch (t) { case 0: return "NETIF"; case 1: return "DIRECT"; case 2: return "NAT_EIM"; case 3: return "NAT_DEPENDENT"; case 4: return "UNKNOWN"; case 5: return "CONTACT_REQUIRED"; default: return QString("?%1").arg(t); }
switch (t) {
case ADDR_TYPE_NETIF: return "NETIF";
case ADDR_TYPE_DIRECT: return "DIRECT";
case ADDR_TYPE_NAT_EIM: return "NAT type=EIM";
case ADDR_TYPE_NAT_STRICT: return "NAT type=STRICT";
case ADDR_TYPE_NAT: return "NAT type=UNKNOWN";
case ADDR_TYPE_CONTACT: return "CONTACT_REQUIRED";
default: return QString("?%1").arg(t);
}
}
NodesPage::NodesPage(DbManager* db, QWidget* parent)
@@ -199,7 +208,7 @@ void NodesPage::refreshNodes() {
sqlite3_stmt* na = nullptr;
sqlite3_prepare_v2(d,
"SELECT family, protocol, address, port, rtt, addr_type"
"SELECT family, protocol, address, port, rtt, addr_type, address_kind"
" FROM node_addresses WHERE node_id=? ORDER BY family, port",
-1, &na, nullptr);
if (na) {
@@ -214,13 +223,14 @@ void NodesPage::refreshNodes() {
int port = sqlite3_column_int(na, 3);
int rtt = sqlite3_column_int(na, 4);
int addrType = sqlite3_column_int(na, 5);
int kind = sqlite3_column_int(na, 6);
if (addr && addrSz > 0) {
dump += QString(" %1:%2 %3 %4 rtt=%5ms\n")
.arg(addrStr(addr, family))
.arg(port)
.arg(protoStr(proto))
.arg(addrTypeStr(addrType))
.arg(kind == TOPO_ADDR_INTERFACE ? QStringLiteral("INTERFACE") : addrTypeStr(addrType))
.arg(rtt > 0 ? QString::number(rtt / 10) : "-");
}
ac++;