Preserve independent NAT details in desktop diagnostics

This commit is contained in:
evgeny committed 2026-10-27 01:48:13 +01:00
1 parent 12c5945eed
commit 75124e0efa
4 files changed
+55 -6

No files matched your search

+9 -3
View File
@@ -1,18 +1,24 @@
/* Представление профиля endpoint в GUI: mapping, доступность входа и источник измерения.
* Использовать для полей enum из address_profile.h; происхождение самого адреса (interface/NAT)
* не подменяет измерение. Функция форматирует строку, не выполняет сетевых проверок. */
#pragma once
#include <QCoreApplication>
#include <QString>
#include "../../../src/routing_layer/address_profile.h"
// Показывает результат измерения отдельно от происхождения адреса (интерфейс или NAT).
/* mapping/inbound/source — enum address_mapping/address_inbound/address_profile_source.
* Возвращает QString с переводом текущего ChatGui; при source=NONE — NAT not determined.
* Известный inbound сохраняется при любом mapping; STUN помечается отдельно. UNKNOWN mapping → NAT?,
* EIM с неизвестным inbound → EIM?. Допустимость полей проверяет вызывающий. */
inline QString addressProfileText(int mapping, int inbound, int source) {
if (source == ADDRESS_SOURCE_NONE) return QCoreApplication::translate("ChatGui", "NAT not determined");
QString text;
switch (mapping) {
case ADDRESS_MAP_UNCHANGED: text = QCoreApplication::translate("ChatGui", "No NAT"); break;
case ADDRESS_MAP_EIM: text = inbound == ADDRESS_IN_UNKNOWN ? "EIM?" : "EIM"; break;
case ADDRESS_MAP_DEPENDENT: return "DEPENDENT";
default: return "NAT?";
case ADDRESS_MAP_DEPENDENT: text = "DEPENDENT"; break;
default: text = "NAT?"; break;
}
if (inbound == ADDRESS_IN_OPEN) text += QCoreApplication::translate("ChatGui", "; inbound open");
else if (inbound == ADDRESS_IN_CONTACT) text += QCoreApplication::translate("ChatGui", "; inbound filtered");
+4 -2
View File
@@ -1,8 +1,10 @@
/* Макросы логирования GUI через общий debug_config, категория GENERAL. */
/* Макросы GUI_ERROR/WARN/INFO/DEBUG: printf-формат и аргументы в общий logger, категория general.
* Уровень, файл и фильтры задаются debug_config; используются стандартные DEBUG_* с контекстом вызова.
* Аргументы форматирования не вычисляются, если уровень отфильтрован. Файл не содержит своего состояния. */
#pragma once
extern "C" {
#include "../../lib/debug_config.h"
#include "../../../lib/debug_config.h"
}
#define GUI_ERROR(fmt, ...) DEBUG_ERROR(DEBUG_CATEGORY_GENERAL, fmt, ##__VA_ARGS__)
+5 -1
View File
@@ -1,10 +1,14 @@
/* Выбор языка интерфейса независимо от регионального формата дат и чисел. */
/* Выбор поддерживаемого языка интерфейса независимо от формата дат и чисел QLocale.
* Не устанавливает QTranslator и не меняет системную locale: возвращает код en/ru. */
#pragma once
#include <QString>
#include <QStringList>
#include <QLocale>
/* preference=en/ru выбирает язык явно; прочие значения (включая system) используют systemLanguages.
* По умолчанию берётся QLocale::system().uiLanguages(). Проверка идёт по порядку списка,
* без учёта регистра/региона (- и _); первый поддерживаемый язык побеждает, иначе возвращается en. */
inline QString resolveGuiLanguage(const QString& preference, const QStringList& systemLanguages = QLocale::system().uiLanguages()) {
if (preference == QStringLiteral("en") || preference == QStringLiteral("ru")) return preference;
for (const QString& language : systemLanguages) {
+37
View File
@@ -1,4 +1,5 @@
#include "../src/gui_language.h"
#include "../src/addressprofiletext.h"
#include "../src/networksettingspage.h"
#include "../transport/node_config.h"
#include "../transport/config_updater.h"
@@ -67,6 +68,42 @@ private slots:
QCOMPARE(resolveGuiLanguage("en", {"ru-RU"}), QString("en"));
}
void addressProfilesKeepIndependentFields_data() {
QTest::addColumn<int>("mapping"); QTest::addColumn<int>("inbound"); QTest::addColumn<int>("source");
QTest::addColumn<QString>("expected");
QTest::newRow("unmeasured") << int(ADDRESS_MAP_UNKNOWN) << int(ADDRESS_IN_UNKNOWN) << int(ADDRESS_SOURCE_NONE)
<< QStringLiteral("NAT not determined");
QTest::newRow("unchanged-untested") << int(ADDRESS_MAP_UNCHANGED) << int(ADDRESS_IN_UNKNOWN) << int(ADDRESS_SOURCE_ETCP)
<< QStringLiteral("No NAT; inbound untested");
QTest::newRow("unchanged-open") << int(ADDRESS_MAP_UNCHANGED) << int(ADDRESS_IN_OPEN) << int(ADDRESS_SOURCE_ETCP)
<< QStringLiteral("No NAT; inbound open");
QTest::newRow("unchanged-filtered-stun") << int(ADDRESS_MAP_UNCHANGED) << int(ADDRESS_IN_CONTACT) << int(ADDRESS_SOURCE_STUN)
<< QStringLiteral("No NAT; inbound filtered (STUN)");
QTest::newRow("eim-untested-stun") << int(ADDRESS_MAP_EIM) << int(ADDRESS_IN_UNKNOWN) << int(ADDRESS_SOURCE_STUN)
<< QStringLiteral("EIM? (STUN)");
QTest::newRow("eim-open") << int(ADDRESS_MAP_EIM) << int(ADDRESS_IN_OPEN) << int(ADDRESS_SOURCE_ETCP)
<< QStringLiteral("EIM; inbound open");
QTest::newRow("eim-filtered") << int(ADDRESS_MAP_EIM) << int(ADDRESS_IN_CONTACT) << int(ADDRESS_SOURCE_ETCP)
<< QStringLiteral("EIM; inbound filtered");
QTest::newRow("dependent-untested") << int(ADDRESS_MAP_DEPENDENT) << int(ADDRESS_IN_UNKNOWN) << int(ADDRESS_SOURCE_ETCP)
<< QStringLiteral("DEPENDENT");
QTest::newRow("dependent-open") << int(ADDRESS_MAP_DEPENDENT) << int(ADDRESS_IN_OPEN) << int(ADDRESS_SOURCE_ETCP)
<< QStringLiteral("DEPENDENT; inbound open");
QTest::newRow("dependent-filtered-stun") << int(ADDRESS_MAP_DEPENDENT) << int(ADDRESS_IN_CONTACT) << int(ADDRESS_SOURCE_STUN)
<< QStringLiteral("DEPENDENT; inbound filtered (STUN)");
QTest::newRow("unknown-open-stun") << int(ADDRESS_MAP_UNKNOWN) << int(ADDRESS_IN_OPEN) << int(ADDRESS_SOURCE_STUN)
<< QStringLiteral("NAT?; inbound open (STUN)");
QTest::newRow("unknown-filtered") << int(ADDRESS_MAP_UNKNOWN) << int(ADDRESS_IN_CONTACT) << int(ADDRESS_SOURCE_ETCP)
<< QStringLiteral("NAT?; inbound filtered");
}
void addressProfilesKeepIndependentFields() {
QFETCH(int, mapping); QFETCH(int, inbound); QFETCH(int, source); QFETCH(QString, expected);
const address_profile profile = {uint8_t(mapping), uint8_t(inbound), uint8_t(source)};
QVERIFY(address_profile_valid(&profile));
QCOMPARE(addressProfileText(mapping, inbound, source), expected);
}
void autoSocketProtocols() {
QTemporaryDir directory;
QVERIFY(directory.isValid());