diff --git a/db/ConfigBuilder.cpp b/db/ConfigBuilder.cpp index 40b92cf..b6a6317 100644 --- a/db/ConfigBuilder.cpp +++ b/db/ConfigBuilder.cpp @@ -429,7 +429,7 @@ namespace NekoRay { {"enabled", true}, {"concurrency", dataStore->mux_cool}, }; - auto stream = GetStreamSettings(ent->bean); + auto stream = GetStreamSettings(ent->bean.data()); if (stream != nullptr && !stream->packet_encoding.isEmpty()) { muxObj["packetEncoding"] = stream->packet_encoding; } diff --git a/fmt/AbstractBean.cpp b/fmt/AbstractBean.cpp index 047ce90..e62068f 100644 --- a/fmt/AbstractBean.cpp +++ b/fmt/AbstractBean.cpp @@ -1,4 +1,9 @@ -#include "AbstractBean.hpp" +#include "includes.h" + +#include + +#include +#include namespace NekoRay::fmt { AbstractBean::AbstractBean(int version) { @@ -33,4 +38,38 @@ namespace NekoRay::fmt { QString AbstractBean::DisplayTypeAndName() { return QString(" [%1] %2").arg(DisplayType(), DisplayName()); } -} \ No newline at end of file + + void AbstractBean::ResolveDomainToIP(const std::function &onFinished) { + bool noResolve = false; + if (dynamic_cast(this) != nullptr) noResolve = true; + if (dynamic_cast(this) != nullptr) noResolve = true; + if (dynamic_cast(this) != nullptr) noResolve = true; + if (IsIpAddress(serverAddress)) noResolve = true; + if (noResolve) { + onFinished(); + return; + } + + QHostInfo::lookupHost(serverAddress, QApplication::instance(), [=](const QHostInfo &host) { + auto addr = host.addresses(); + if (!addr.isEmpty()) { + auto domain = serverAddress; + auto stream = GetStreamSettings(this); + + // replace serverAddress + serverAddress = addr.first().toString(); + + // replace ws tls + if (stream != nullptr) { + if (stream->security == "tls" && !stream->sni.isEmpty()) { + stream->sni = domain; + } + if (stream->network == "ws" && !stream->host.isEmpty()) { + stream->host = domain; + } + } + } + onFinished(); + }); + } +} diff --git a/fmt/AbstractBean.hpp b/fmt/AbstractBean.hpp index c9373b4..abe067b 100644 --- a/fmt/AbstractBean.hpp +++ b/fmt/AbstractBean.hpp @@ -27,8 +27,14 @@ namespace NekoRay::fmt { explicit AbstractBean(int version); + // + QString ToNekorayShareLink(const QString &type); + void ResolveDomainToIP(const std::function &onFinished); + + // + [[nodiscard]] virtual QString DisplayAddress(); [[nodiscard]] virtual QString DisplayName(); @@ -37,6 +43,8 @@ namespace NekoRay::fmt { virtual QString DisplayTypeAndName(); + // + virtual bool NeedExternal() { return false; }; virtual CoreObjOutboundBuildResult BuildCoreObj() { return {}; }; diff --git a/fmt/InsecureHint.cpp b/fmt/InsecureHint.cpp index 82703dc..15cfc47 100644 --- a/fmt/InsecureHint.cpp +++ b/fmt/InsecureHint.cpp @@ -8,7 +8,7 @@ namespace NekoRay::fmt { QString DisplayInsecureHint(const QSharedPointer &bean) { if (!dataStore->insecure_hint) return {}; auto insecure_hint = bean->InsecureHint(); - auto stream = GetStreamSettings(bean); + auto stream = GetStreamSettings(bean.data()); if (stream != nullptr) insecure_hint += "\n" + stream->InsecureHint(); return insecure_hint.trimmed(); } diff --git a/fmt/V2RayStreamSettings.hpp b/fmt/V2RayStreamSettings.hpp index 688cde7..6a0392f 100644 --- a/fmt/V2RayStreamSettings.hpp +++ b/fmt/V2RayStreamSettings.hpp @@ -37,7 +37,7 @@ namespace NekoRay::fmt { [[nodiscard]] QString InsecureHint() const; }; - inline V2rayStreamSettings *GetStreamSettings(const QSharedPointer &bean) { + inline V2rayStreamSettings *GetStreamSettings(AbstractBean *bean) { if (bean == nullptr) return nullptr; auto stream_item = bean->_get("stream"); if (stream_item != nullptr) { diff --git a/main/NekoRay_DataStore.hpp b/main/NekoRay_DataStore.hpp index eff8b6b..99bb152 100644 --- a/main/NekoRay_DataStore.hpp +++ b/main/NekoRay_DataStore.hpp @@ -47,6 +47,7 @@ namespace NekoRay { Routing *routing = new Routing; int imported_count = 0; bool refreshing_group_list = false; + int resolve_count = 0; // Flags bool flag_use_appdata = false; diff --git a/translations/zh_CN.ts b/translations/zh_CN.ts index 192e139..fe64f30 100644 --- a/translations/zh_CN.ts +++ b/translations/zh_CN.ts @@ -1117,6 +1117,14 @@ End: %2 Manual addition of profiles is not allowed in subscription groupings. 订阅分组中不允许手动添加配置。 + + Resolve domain + 将服务器域名解析为 IP + + + Resolving current group domain to IP, if support. + 将当前分组内服务器域名解析为 IP(如果支持)。 + ProxyItem diff --git a/ui/edit/dialog_edit_profile.cpp b/ui/edit/dialog_edit_profile.cpp index bafe8b3..c6e13b5 100644 --- a/ui/edit/dialog_edit_profile.cpp +++ b/ui/edit/dialog_edit_profile.cpp @@ -173,7 +173,7 @@ void DialogEditProfile::typeSelected(const QString &newType) { ui->port_l->setVisible(notChain); // 右边 Outbound: settings - auto stream = GetStreamSettings(ent->bean); + auto stream = GetStreamSettings(ent->bean.data()); if (stream != nullptr) { ui->right_all_w->setVisible(true); ui->network->setCurrentText(stream->network); @@ -249,7 +249,7 @@ void DialogEditProfile::accept() { } // 右边 - auto stream = GetStreamSettings(ent->bean); + auto stream = GetStreamSettings(ent->bean.data()); if (stream != nullptr) { stream->network = ui->network->currentText(); stream->security = ui->security->currentText(); diff --git a/ui/mainwindow.cpp b/ui/mainwindow.cpp index e724ed1..ae790c5 100644 --- a/ui/mainwindow.cpp +++ b/ui/mainwindow.cpp @@ -1147,6 +1147,32 @@ void MainWindow::on_menu_remove_unavailable_triggered() { } } +void MainWindow::on_menu_resolve_domain_triggered() { + if (QMessageBox::question(this, + tr("Confirmation"), + tr("Resolving current group domain to IP, if support.") + ) != QMessageBox::StandardButton::Yes) { + return; + } + if (mw_sub_updating) return; + mw_sub_updating = true; + + auto group = NekoRay::profileManager->CurrentGroup(); + if (group == nullptr) return; + + auto profiles = group->ProfilesWithOrder(); + NekoRay::dataStore->resolve_count = profiles.length(); + + for (const auto &profile: profiles) { + profile->bean->ResolveDomainToIP([=] { + profile->Save(); + if (--NekoRay::dataStore->resolve_count != 0) return; + refresh_proxy_list(); + mw_sub_updating = false; + }); + } +} + void MainWindow::on_proxyListTable_customContextMenuRequested(const QPoint &pos) { ui->menu_server->popup(ui->proxyListTable->viewport()->mapToGlobal(pos)); //弹出菜单 } diff --git a/ui/mainwindow.h b/ui/mainwindow.h index 64f43c6..3b53ffe 100644 --- a/ui/mainwindow.h +++ b/ui/mainwindow.h @@ -109,6 +109,8 @@ private slots: void on_menu_update_subscripton_triggered(); + void on_menu_resolve_domain_triggered(); + void on_proxyListTable_itemDoubleClicked(QTableWidgetItem *item); void on_proxyListTable_customContextMenuRequested(const QPoint &pos); diff --git a/ui/mainwindow.ui b/ui/mainwindow.ui index 64f8a62..3950a6f 100644 --- a/ui/mainwindow.ui +++ b/ui/mainwindow.ui @@ -519,11 +519,15 @@ Current Group - + + + + + @@ -814,6 +818,11 @@ Ctrl+U + + + Resolve domain + +