mirror of
https://github.com/Mahdi-zarei/nekoray.git
synced 2025-12-19 05:30:06 +08:00
remove naive and extra core support
This commit is contained in:
parent
bf8de2e9e9
commit
3688295d66
22
3rdparty/VT100Parser.hpp
vendored
22
3rdparty/VT100Parser.hpp
vendored
@ -1,22 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
|
||||
inline QString cleanVT100String(const QString &in) {
|
||||
QString out;
|
||||
bool in_033 = false;
|
||||
for (auto &&chr: in) {
|
||||
if (chr == '\033') {
|
||||
in_033 = true;
|
||||
continue;
|
||||
}
|
||||
if (in_033) {
|
||||
if (chr == 'm') {
|
||||
in_033 = false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
out += chr;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
11
3rdparty/fix_old_qt.h
vendored
11
3rdparty/fix_old_qt.h
vendored
@ -1,11 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
|
||||
|
||||
inline QString qEnvironmentVariable(const char *varName) {
|
||||
return qgetenv(varName);
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -100,7 +100,6 @@ set(PROJECT_SOURCES
|
||||
|
||||
src/configs/proxy/AbstractBean.cpp
|
||||
src/configs/proxy/Bean2CoreObj_box.cpp
|
||||
src/configs/proxy/Bean2External.cpp
|
||||
src/configs/proxy/Bean2Link.cpp
|
||||
src/configs/proxy/Link2Bean.cpp
|
||||
include/configs/proxy/ChainBean.hpp # translate
|
||||
@ -108,7 +107,8 @@ set(PROJECT_SOURCES
|
||||
include/configs/sub/GroupUpdater.hpp
|
||||
src/configs/sub/GroupUpdater.cpp
|
||||
|
||||
src/sys/ExternalProcess.cpp
|
||||
include/sys/Process.hpp
|
||||
src/sys/Process.cpp
|
||||
src/sys/AutoRun.cpp
|
||||
|
||||
include/ui/setting/ThemeManager.hpp
|
||||
@ -143,10 +143,6 @@ set(PROJECT_SOURCES
|
||||
src/ui/profile/edit_trojan_vless.cpp
|
||||
include/ui/profile/edit_trojan_vless.ui
|
||||
|
||||
include/ui/profile/edit_naive.h
|
||||
src/ui/profile/edit_naive.cpp
|
||||
include/ui/profile/edit_naive.ui
|
||||
|
||||
include/ui/profile/edit_quic.h
|
||||
src/ui/profile/edit_quic.cpp
|
||||
include/ui/profile/edit_quic.ui
|
||||
@ -209,7 +205,7 @@ set(PROJECT_SOURCES
|
||||
src/sys/macos/MacOS.cpp
|
||||
|
||||
src/sys/AutoRun.cpp
|
||||
src/sys/ExternalProcess.cpp
|
||||
src/sys/Process.cpp
|
||||
include/ui/mainwindow_interface.h
|
||||
)
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
#ifndef NKR_NO_GRPC
|
||||
|
||||
#include "go/grpc_server/gen/libcore.pb.h"
|
||||
#include "core/grpc_server/gen/libcore.pb.h"
|
||||
#include <QString>
|
||||
|
||||
namespace QtGrpc {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "include/dataStore/ProxyEntity.hpp"
|
||||
#include "include/sys/ExternalProcess.hpp"
|
||||
#include "include/sys/Process.hpp"
|
||||
|
||||
namespace NekoGui {
|
||||
class BuildConfigResult {
|
||||
@ -12,8 +12,6 @@ namespace NekoGui {
|
||||
QList<std::shared_ptr<NekoGui_traffic::TrafficData>> outboundStats; // all, but not including "bypass" "block"
|
||||
std::shared_ptr<NekoGui_traffic::TrafficData> outboundStat; // main
|
||||
QStringList ignoreConnTag;
|
||||
|
||||
std::list<std::shared_ptr<NekoGui_fmt::ExternalBuildResult>> extRs;
|
||||
};
|
||||
|
||||
class BuildTestConfigResult {
|
||||
|
||||
@ -12,18 +12,6 @@ namespace NekoGui_fmt {
|
||||
QString error;
|
||||
};
|
||||
|
||||
struct ExternalBuildResult {
|
||||
public:
|
||||
QString program;
|
||||
QStringList env;
|
||||
QStringList arguments;
|
||||
//
|
||||
QString tag;
|
||||
//
|
||||
QString error;
|
||||
QString config_export;
|
||||
};
|
||||
|
||||
class AbstractBean : public JsonStore {
|
||||
public:
|
||||
int version;
|
||||
@ -62,12 +50,8 @@ namespace NekoGui_fmt {
|
||||
|
||||
//
|
||||
|
||||
virtual int NeedExternal(bool isFirstProfile) { return 0; };
|
||||
|
||||
virtual CoreObjOutboundBuildResult BuildCoreObjSingBox() { return {}; };
|
||||
|
||||
virtual ExternalBuildResult BuildExternal(int mapping_port, int socks_port, int external_stat) { return {}; };
|
||||
|
||||
virtual QString ToShareLink() { return {}; };
|
||||
};
|
||||
|
||||
|
||||
@ -31,7 +31,7 @@ namespace NekoGui_fmt {
|
||||
return core;
|
||||
};
|
||||
|
||||
QString DisplayCoreType() override { return NeedExternal(true) == 0 ? software_core_name : core; };
|
||||
QString DisplayCoreType() override { return software_core_name; };
|
||||
|
||||
QString DisplayAddress() override {
|
||||
if (core == "internal") {
|
||||
@ -43,10 +43,6 @@ namespace NekoGui_fmt {
|
||||
return AbstractBean::DisplayAddress();
|
||||
};
|
||||
|
||||
int NeedExternal(bool isFirstProfile) override;
|
||||
|
||||
ExternalBuildResult BuildExternal(int mapping_port, int socks_port, int external_stat) override;
|
||||
|
||||
CoreObjOutboundBuildResult BuildCoreObjSingBox() override;
|
||||
};
|
||||
} // namespace NekoGui_fmt
|
||||
@ -1,41 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "AbstractBean.hpp"
|
||||
|
||||
namespace NekoGui_fmt {
|
||||
class NaiveBean : public AbstractBean {
|
||||
public:
|
||||
QString username = "";
|
||||
QString password = "";
|
||||
QString protocol = "https";
|
||||
QString extra_headers = "";
|
||||
QString sni = "";
|
||||
QString certificate = "";
|
||||
int insecure_concurrency = 0;
|
||||
|
||||
bool disable_log = false;
|
||||
|
||||
NaiveBean() : AbstractBean(0) {
|
||||
_add(new configItem("username", &username, itemType::string));
|
||||
_add(new configItem("password", &password, itemType::string));
|
||||
_add(new configItem("protocol", &protocol, itemType::string));
|
||||
_add(new configItem("extra_headers", &extra_headers, itemType::string));
|
||||
_add(new configItem("sni", &sni, itemType::string));
|
||||
_add(new configItem("certificate", &certificate, itemType::string));
|
||||
_add(new configItem("insecure_concurrency", &insecure_concurrency, itemType::integer));
|
||||
_add(new configItem("disable_log", &disable_log, itemType::boolean));
|
||||
};
|
||||
|
||||
QString DisplayCoreType() override { return "Naive"; };
|
||||
|
||||
QString DisplayType() override { return "Naive"; };
|
||||
|
||||
int NeedExternal(bool isFirstProfile) override;
|
||||
|
||||
ExternalBuildResult BuildExternal(int mapping_port, int socks_port, int external_stat) override;
|
||||
|
||||
bool TryParseLink(const QString &link);
|
||||
|
||||
QString ToShareLink() override;
|
||||
};
|
||||
} // namespace NekoGui_fmt
|
||||
@ -97,9 +97,7 @@ namespace NekoGui_fmt {
|
||||
}
|
||||
|
||||
QString DisplayCoreType() override {
|
||||
if (NeedExternal(true) == 0) {
|
||||
return software_core_name;
|
||||
} else if (proxy_type == proxy_TUIC) {
|
||||
if (proxy_type == proxy_TUIC) {
|
||||
return "tuic";
|
||||
} else if (proxy_type == proxy_Hysteria) {
|
||||
return "hysteria";
|
||||
@ -118,10 +116,6 @@ namespace NekoGui_fmt {
|
||||
}
|
||||
};
|
||||
|
||||
int NeedExternal(bool isFirstProfile) override;
|
||||
|
||||
ExternalBuildResult BuildExternal(int mapping_port, int socks_port, int external_stat) override;
|
||||
|
||||
CoreObjOutboundBuildResult BuildCoreObjSingBox() override;
|
||||
|
||||
bool TryParseLink(const QString &link);
|
||||
|
||||
@ -5,7 +5,6 @@
|
||||
#include "ChainBean.hpp"
|
||||
#include "VMessBean.hpp"
|
||||
#include "TrojanVLESSBean.hpp"
|
||||
#include "NaiveBean.hpp"
|
||||
#include "QUICBean.hpp"
|
||||
#include "WireguardBean.h"
|
||||
#include "SSHBean.h"
|
||||
|
||||
@ -19,8 +19,6 @@ inline std::function<void()> MF_release_runguard;
|
||||
class QWidget;
|
||||
inline QWidget *mainwindow;
|
||||
inline std::function<void(QString)> MW_show_log;
|
||||
inline std::function<void(QString, QString)> MW_show_log_ext;
|
||||
inline std::function<void(QString)> MW_show_log_ext_vt100;
|
||||
inline std::function<void(QString, QString)> MW_dialog_message;
|
||||
|
||||
// Dispatchers
|
||||
|
||||
@ -4,36 +4,25 @@
|
||||
#include <QProcess>
|
||||
|
||||
namespace NekoGui_sys {
|
||||
class ExternalProcess : public QProcess {
|
||||
class CoreProcess : public QProcess
|
||||
{
|
||||
public:
|
||||
QString tag;
|
||||
QString program;
|
||||
QStringList arguments;
|
||||
QStringList env;
|
||||
|
||||
bool managed = true; // MW_dialog_message
|
||||
|
||||
ExternalProcess();
|
||||
~ExternalProcess();
|
||||
CoreProcess();
|
||||
~CoreProcess();
|
||||
|
||||
// start & kill is one time
|
||||
|
||||
virtual void Start();
|
||||
void Start();
|
||||
|
||||
void Kill();
|
||||
|
||||
protected:
|
||||
bool started = false;
|
||||
bool killed = false;
|
||||
bool crashed = false;
|
||||
};
|
||||
|
||||
class CoreProcess : public ExternalProcess {
|
||||
public:
|
||||
CoreProcess(const QString &core_path, const QStringList &args);
|
||||
|
||||
void Start() override;
|
||||
|
||||
void Restart();
|
||||
|
||||
int start_profile_when_core_is_up = -1;
|
||||
@ -42,10 +31,12 @@ namespace NekoGui_sys {
|
||||
bool show_stderr = false;
|
||||
bool failed_to_start = false;
|
||||
bool restarting = false;
|
||||
};
|
||||
|
||||
// 手动管理
|
||||
inline std::list<std::shared_ptr<ExternalProcess>> running_ext;
|
||||
protected:
|
||||
bool started = false;
|
||||
bool killed = false;
|
||||
bool crashed = false;
|
||||
};
|
||||
|
||||
inline QAtomicInt logCounter;
|
||||
} // namespace NekoGui_sys
|
||||
@ -1,41 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include "profile_editor.h"
|
||||
#include "ui_edit_naive.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace Ui {
|
||||
class EditNaive;
|
||||
}
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class EditNaive : public QWidget, public ProfileEditor {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit EditNaive(QWidget *parent = nullptr);
|
||||
|
||||
~EditNaive() override;
|
||||
|
||||
void onStart(std::shared_ptr<NekoGui::ProxyEntity> _ent) override;
|
||||
|
||||
bool onEnd() override;
|
||||
|
||||
QList<QPair<QPushButton *, QString>> get_editor_cached() override;
|
||||
|
||||
private:
|
||||
Ui::EditNaive *ui;
|
||||
std::shared_ptr<NekoGui::ProxyEntity> ent;
|
||||
|
||||
struct {
|
||||
QString certificate;
|
||||
QString extra_headers;
|
||||
} CACHE;
|
||||
|
||||
private slots:
|
||||
|
||||
void on_certificate_clicked();
|
||||
|
||||
void on_extra_headers_clicked();
|
||||
};
|
||||
@ -1,131 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>EditNaive</class>
|
||||
<widget class="QWidget" name="EditNaive">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>525</width>
|
||||
<height>304</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">EditNaive</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Username</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="MyLineEdit" name="username"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Password</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="MyLineEdit" name="password"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Protocol</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="protocol">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">https</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">quic</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Extra headers</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QPushButton" name="extra_headers">
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>SNI</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="MyLineEdit" name="sni"/>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Certificate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QPushButton" name="certificate">
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Insecure concurrency</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="MyLineEdit" name="insecure_concurrency"/>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Disable logs</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QCheckBox" name="disable_log">
|
||||
<property name="text">
|
||||
<string>Turn on this option if your connection is lost after a while</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>MyLineEdit</class>
|
||||
<extends>QLineEdit</extends>
|
||||
<header>include/ui/utils/MyLineEdit.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@ -25,7 +25,6 @@ private:
|
||||
Ui::DialogBasicSettings *ui;
|
||||
|
||||
struct {
|
||||
QJsonObject extraCore;
|
||||
QString custom_inbound;
|
||||
bool needRestart = false;
|
||||
} CACHE;
|
||||
|
||||
@ -756,61 +756,6 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_6">
|
||||
<attribute name="title">
|
||||
<string>Extra Core</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<widget class="QScrollArea" name="extra_core_box_scrollArea">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Shape::NoFrame</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="extra_core_box_scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>700</width>
|
||||
<height>402</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<widget class="QWidget" name="horizontalWidget_4" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_8">
|
||||
<item>
|
||||
<widget class="QPushButton" name="extra_core_add">
|
||||
<property name="text">
|
||||
<string>Add</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="extra_core_del">
|
||||
<property name="text">
|
||||
<string>Delete</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_5">
|
||||
<attribute name="title">
|
||||
<string>Security</string>
|
||||
|
||||
@ -11,17 +11,6 @@
|
||||
#define BOX_UNDERLYING_DNS_EXPORT dataStore->core_box_underlying_dns.isEmpty() ? (status->forExport ? "local" : "underlying://0.0.0.0") : dataStore->core_box_underlying_dns
|
||||
|
||||
namespace NekoGui {
|
||||
|
||||
QStringList getAutoBypassExternalProcessPaths(const std::shared_ptr<BuildConfigResult> &result) {
|
||||
QStringList paths;
|
||||
for (const auto &extR: result->extRs) {
|
||||
auto path = extR->program;
|
||||
if (path.trimmed().isEmpty()) continue;
|
||||
paths << path.replace("\\", "/");
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
|
||||
QString genTunName() {
|
||||
auto tun_name = "nekoray-tun";
|
||||
#ifdef Q_OS_MACOS
|
||||
@ -281,83 +270,12 @@ namespace NekoGui {
|
||||
status->result->outboundStat = ent->traffic_data;
|
||||
}
|
||||
|
||||
// chain rules: this
|
||||
auto ext_mapping_port = 0;
|
||||
auto ext_socks_port = 0;
|
||||
auto thisExternalStat = ent->bean->NeedExternal(isFirstProfile);
|
||||
if (thisExternalStat < 0) {
|
||||
status->result->error = "This configuration cannot be set automatically, please try another.";
|
||||
return {};
|
||||
}
|
||||
|
||||
// determine port
|
||||
if (thisExternalStat > 0) {
|
||||
if (ent->type == "custom") {
|
||||
auto bean = ent->CustomBean();
|
||||
if (IsValidPort(bean->mapping_port)) {
|
||||
ext_mapping_port = bean->mapping_port;
|
||||
} else {
|
||||
ext_mapping_port = MkPort();
|
||||
}
|
||||
if (IsValidPort(bean->socks_port)) {
|
||||
ext_socks_port = bean->socks_port;
|
||||
} else {
|
||||
ext_socks_port = MkPort();
|
||||
}
|
||||
} else {
|
||||
ext_mapping_port = MkPort();
|
||||
ext_socks_port = MkPort();
|
||||
}
|
||||
}
|
||||
if (thisExternalStat == 2) dataStore->need_keep_vpn_off = true;
|
||||
if (thisExternalStat == 1) {
|
||||
// mapping
|
||||
status->inbounds += QJsonObject{
|
||||
{"type", "direct"},
|
||||
{"tag", tagOut + "-mapping"},
|
||||
{"listen", "127.0.0.1"},
|
||||
{"listen_port", ext_mapping_port},
|
||||
{"override_address", ent->bean->serverAddress},
|
||||
{"override_port", ent->bean->serverPort},
|
||||
};
|
||||
// no chain rule and not outbound, so need to set to direct
|
||||
if (isFirstProfile) {
|
||||
status->routingRules += QJsonObject{
|
||||
{"inbound", QJsonArray{tagOut + "-mapping"}},
|
||||
{"outbound", "direct"},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Outbound
|
||||
|
||||
QJsonObject outbound;
|
||||
|
||||
if (thisExternalStat > 0) {
|
||||
auto extR = ent->bean->BuildExternal(ext_mapping_port, ext_socks_port, thisExternalStat);
|
||||
if (extR.program.isEmpty()) {
|
||||
status->result->error = QObject::tr("Core not found: %1").arg(ent->bean->DisplayCoreType());
|
||||
return {};
|
||||
}
|
||||
if (!extR.error.isEmpty()) { // rejected
|
||||
status->result->error = extR.error;
|
||||
return {};
|
||||
}
|
||||
extR.tag = ent->bean->DisplayType();
|
||||
status->result->extRs.emplace_back(std::make_shared<NekoGui_fmt::ExternalBuildResult>(extR));
|
||||
BuildOutbound(ent, status, outbound, tagOut);
|
||||
|
||||
// SOCKS OUTBOUND
|
||||
outbound["type"] = "socks";
|
||||
outbound["server"] = "127.0.0.1";
|
||||
outbound["server_port"] = ext_socks_port;
|
||||
// outbound misc
|
||||
outbound["tag"] = tagOut;
|
||||
ent->traffic_data->id = ent->id;
|
||||
ent->traffic_data->tag = tagOut.toStdString();
|
||||
status->result->outboundStats += ent->traffic_data;
|
||||
} else {
|
||||
BuildOutbound(ent, status, outbound, tagOut);
|
||||
}
|
||||
|
||||
// apply custom outbound settings
|
||||
MergeJson(QString2QJsonObject(ent->bean->custom_outbound), outbound);
|
||||
@ -377,7 +295,6 @@ namespace NekoGui {
|
||||
|
||||
status->outbounds += outbound;
|
||||
pastTag = tagOut;
|
||||
pastExternalStat = thisExternalStat;
|
||||
index++;
|
||||
}
|
||||
|
||||
|
||||
@ -52,7 +52,6 @@ namespace NekoGui_fmt {
|
||||
bool noResolve = false;
|
||||
if (dynamic_cast<ChainBean *>(this) != nullptr) noResolve = true;
|
||||
if (dynamic_cast<CustomBean *>(this) != nullptr) noResolve = true;
|
||||
if (dynamic_cast<NaiveBean *>(this) != nullptr) noResolve = true;
|
||||
if (IsIpAddress(serverAddress)) noResolve = true;
|
||||
if (noResolve) {
|
||||
onFinished();
|
||||
|
||||
@ -1,336 +0,0 @@
|
||||
#include "include/dataStore/ProxyEntity.hpp"
|
||||
#include "include/configs/proxy/includes.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include <QUrl>
|
||||
|
||||
#define WriteTempFile(fn, data) \
|
||||
QDir dir; \
|
||||
if (!dir.exists("temp")) dir.mkdir("temp"); \
|
||||
QFile f(QString("temp/") + fn); \
|
||||
bool ok = f.open(QIODevice::WriteOnly | QIODevice::Truncate); \
|
||||
if (ok) { \
|
||||
f.write(data); \
|
||||
} else { \
|
||||
result.error = f.errorString(); \
|
||||
} \
|
||||
f.close(); \
|
||||
auto TempFile = QFileInfo(f).absoluteFilePath();
|
||||
|
||||
namespace NekoGui_fmt {
|
||||
// -1: Cannot use this config
|
||||
// 0: Internal
|
||||
// 1: Mapping External
|
||||
// 2: Direct External
|
||||
|
||||
int NaiveBean::NeedExternal(bool isFirstProfile) {
|
||||
if (isFirstProfile) {
|
||||
if (NekoGui::dataStore->spmode_vpn) {
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int QUICBean::NeedExternal(bool isFirstProfile) {
|
||||
auto hysteriaCore = [=] {
|
||||
if (isFirstProfile) {
|
||||
if (NekoGui::dataStore->spmode_vpn && hyProtocol != hysteria_protocol_facktcp) {
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
} else {
|
||||
if (hyProtocol == hysteria_protocol_facktcp) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
};
|
||||
|
||||
auto hysteria2Core = [=] {
|
||||
if (isFirstProfile) {
|
||||
if (NekoGui::dataStore->spmode_vpn) {
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
return 1;
|
||||
};
|
||||
|
||||
auto tuicCore = [=] {
|
||||
if (isFirstProfile) {
|
||||
if (NekoGui::dataStore->spmode_vpn) {
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
return 1;
|
||||
};
|
||||
|
||||
if (IS_NEKO_BOX) {
|
||||
if (!forceExternal && (proxy_type == proxy_TUIC || hyProtocol == hysteria_protocol_udp)) {
|
||||
// sing-box support
|
||||
return 0;
|
||||
} else {
|
||||
// hysteria core support
|
||||
return hysteriaCore();
|
||||
}
|
||||
} else if (proxy_type == proxy_TUIC) {
|
||||
return tuicCore();
|
||||
} else if (proxy_type == proxy_Hysteria2) {
|
||||
return hysteria2Core();
|
||||
} else {
|
||||
return hysteriaCore();
|
||||
}
|
||||
}
|
||||
|
||||
int CustomBean::NeedExternal(bool isFirstProfile) {
|
||||
if (core == "internal" || core == "internal-full") return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
ExternalBuildResult NaiveBean::BuildExternal(int mapping_port, int socks_port, int external_stat) {
|
||||
ExternalBuildResult result{NekoGui::dataStore->extraCore->Get("naive")};
|
||||
|
||||
auto is_direct = external_stat == 2;
|
||||
auto domain_address = sni.isEmpty() ? serverAddress : sni;
|
||||
auto connect_address = is_direct ? serverAddress : "127.0.0.1";
|
||||
auto connect_port = is_direct ? serverPort : mapping_port;
|
||||
domain_address = WrapIPV6Host(domain_address);
|
||||
connect_address = WrapIPV6Host(connect_address);
|
||||
|
||||
auto proxy_url = QUrl();
|
||||
proxy_url.setScheme(protocol);
|
||||
proxy_url.setUserName(username);
|
||||
proxy_url.setPassword(password);
|
||||
proxy_url.setPort(connect_port);
|
||||
proxy_url.setHost(domain_address);
|
||||
|
||||
if (!disable_log) result.arguments += "--log";
|
||||
result.arguments += "--listen=socks://127.0.0.1:" + Int2String(socks_port);
|
||||
result.arguments += "--proxy=" + proxy_url.toString(QUrl::FullyEncoded);
|
||||
if (domain_address != connect_address)
|
||||
result.arguments += "--host-resolver-rules=MAP " + domain_address + " " + connect_address;
|
||||
if (insecure_concurrency > 0) result.arguments += "--insecure-concurrency=" + Int2String(insecure_concurrency);
|
||||
if (!extra_headers.trimmed().isEmpty()) result.arguments += "--extra-headers=" + extra_headers;
|
||||
if (!certificate.trimmed().isEmpty()) {
|
||||
WriteTempFile("naive_" + GetRandomString(10) + ".crt", certificate.toUtf8());
|
||||
result.env += "SSL_CERT_FILE=" + TempFile;
|
||||
}
|
||||
|
||||
auto config_export = QStringList{result.program};
|
||||
config_export += result.arguments;
|
||||
result.config_export = QStringList2Command(config_export);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ExternalBuildResult QUICBean::BuildExternal(int mapping_port, int socks_port, int external_stat) {
|
||||
if (proxy_type == proxy_TUIC) {
|
||||
ExternalBuildResult result{NekoGui::dataStore->extraCore->Get("tuic")};
|
||||
|
||||
QJsonObject relay;
|
||||
|
||||
relay["uuid"] = uuid;
|
||||
relay["password"] = password;
|
||||
relay["udp_relay_mode"] = udpRelayMode;
|
||||
relay["congestion_control"] = congestionControl;
|
||||
relay["zero_rtt_handshake"] = zeroRttHandshake;
|
||||
relay["disable_sni"] = disableSni;
|
||||
if (!heartbeat.trimmed().isEmpty()) relay["heartbeat"] = heartbeat;
|
||||
if (!alpn.trimmed().isEmpty()) relay["alpn"] = QListStr2QJsonArray(alpn.split(","));
|
||||
|
||||
if (!caText.trimmed().isEmpty()) {
|
||||
WriteTempFile("tuic_" + GetRandomString(10) + ".crt", caText.toUtf8());
|
||||
QJsonArray certificate;
|
||||
certificate.append(TempFile);
|
||||
relay["certificates"] = certificate;
|
||||
}
|
||||
|
||||
// The most confused part of TUIC......
|
||||
if (serverAddress == sni) {
|
||||
relay["server"] = serverAddress + ":" + Int2String(serverPort);
|
||||
} else {
|
||||
relay["server"] = sni + ":" + Int2String(serverPort);
|
||||
relay["ip"] = serverAddress;
|
||||
}
|
||||
|
||||
QJsonObject local{
|
||||
{"server", "127.0.0.1:" + Int2String(socks_port)},
|
||||
};
|
||||
|
||||
QJsonObject config{
|
||||
{"relay", relay},
|
||||
{"local", local},
|
||||
};
|
||||
|
||||
//
|
||||
|
||||
result.config_export = QJsonObject2QString(config, false);
|
||||
WriteTempFile("tuic_" + GetRandomString(10) + ".json", result.config_export.toUtf8());
|
||||
result.arguments = QStringList{"-c", TempFile};
|
||||
|
||||
return result;
|
||||
} else if (proxy_type == proxy_Hysteria2) {
|
||||
ExternalBuildResult result{NekoGui::dataStore->extraCore->Get("hysteria2")};
|
||||
|
||||
QJsonObject config;
|
||||
|
||||
auto server = WrapIPV6Host(serverAddress) + ":" + Int2String(serverPort);;
|
||||
|
||||
QJsonObject transport;
|
||||
transport["type"] = "udp";
|
||||
config["transport"] = transport;
|
||||
|
||||
config["server"] = server;
|
||||
config["socks5"] = QJsonObject{
|
||||
{"listen", "127.0.0.1:" + Int2String(socks_port)},
|
||||
{"disableUDP", false},
|
||||
};
|
||||
config["auth"] = password;
|
||||
|
||||
QJsonObject bandwidth;
|
||||
if (uploadMbps > 0) bandwidth["up"] = Int2String(uploadMbps) + " mbps";
|
||||
if (downloadMbps > 0) bandwidth["down"] = Int2String(downloadMbps) + " mbps";
|
||||
config["bandwidth"] = bandwidth;
|
||||
|
||||
QJsonObject quic;
|
||||
if (streamReceiveWindow > 0) quic["initStreamReceiveWindow"] = streamReceiveWindow;
|
||||
if (connectionReceiveWindow > 0) quic["initConnReceiveWindow"] = connectionReceiveWindow;
|
||||
if (disableMtuDiscovery) quic["disablePathMTUDiscovery"] = true;
|
||||
config["quic"] = quic;
|
||||
|
||||
config["fastOpen"] = true;
|
||||
config["lazy"] = true;
|
||||
|
||||
if (!obfsPassword.isEmpty()) {
|
||||
QJsonObject obfs;
|
||||
obfs["type"] = "salamander";
|
||||
obfs["salamander"] = QJsonObject{
|
||||
{"password", obfsPassword},
|
||||
};
|
||||
|
||||
config["obfs"] = obfs;
|
||||
}
|
||||
|
||||
QJsonObject tls;
|
||||
auto sniGen = sni;
|
||||
if (sni.isEmpty() && !IsIpAddress(serverAddress)) sniGen = serverAddress;
|
||||
tls["sni"] = sniGen;
|
||||
if (allowInsecure) tls["insecure"] = true;
|
||||
if (!caText.trimmed().isEmpty()) {
|
||||
WriteTempFile("hysteria2_" + GetRandomString(10) + ".crt", caText.toUtf8());
|
||||
QJsonArray certificate;
|
||||
certificate.append(TempFile);
|
||||
tls["certificates"] = certificate;
|
||||
}
|
||||
config["tls"] = tls;
|
||||
|
||||
result.config_export = QJsonObject2QString(config, false);
|
||||
WriteTempFile("hysteria2_" + GetRandomString(10) + ".json", result.config_export.toUtf8());
|
||||
result.arguments = QStringList{"-c", TempFile};
|
||||
|
||||
return result;
|
||||
|
||||
} else { // Hysteria
|
||||
ExternalBuildResult result{NekoGui::dataStore->extraCore->Get("hysteria")};
|
||||
|
||||
QJsonObject config;
|
||||
|
||||
// determine server format
|
||||
auto is_direct = external_stat == 2;
|
||||
auto sniGen = sni;
|
||||
if (sni.isEmpty() && !IsIpAddress(serverAddress)) sniGen = serverAddress;
|
||||
|
||||
auto server = WrapIPV6Host(serverAddress) + ":" + Int2String(serverPort);
|
||||
config["server"] = is_direct ? server : "127.0.0.1:" + Int2String(mapping_port);
|
||||
|
||||
// listen
|
||||
config["socks5"] = QJsonObject{
|
||||
{"listen", "127.0.0.1:" + Int2String(socks_port)},
|
||||
};
|
||||
|
||||
// misc
|
||||
|
||||
config["retry"] = 5;
|
||||
config["fast_open"] = true;
|
||||
config["lazy_start"] = true;
|
||||
config["obfs"] = obfsPassword;
|
||||
config["up_mbps"] = uploadMbps;
|
||||
config["down_mbps"] = downloadMbps;
|
||||
|
||||
if (authPayloadType == hysteria_auth_base64) config["auth"] = authPayload;
|
||||
if (authPayloadType == hysteria_auth_string) config["auth_str"] = authPayload;
|
||||
|
||||
if (hyProtocol == hysteria_protocol_facktcp) config["protocol"] = "faketcp";
|
||||
if (hyProtocol == hysteria_protocol_wechat_video) config["protocol"] = "wechat-video";
|
||||
|
||||
if (!sniGen.isEmpty()) config["server_name"] = sniGen;
|
||||
if (!alpn.isEmpty()) config["alpn"] = alpn;
|
||||
|
||||
if (!caText.trimmed().isEmpty()) {
|
||||
WriteTempFile("hysteria_" + GetRandomString(10) + ".crt", caText.toUtf8());
|
||||
config["ca"] = TempFile;
|
||||
}
|
||||
|
||||
if (allowInsecure) config["insecure"] = true;
|
||||
if (streamReceiveWindow > 0) config["recv_window_conn"] = streamReceiveWindow;
|
||||
if (connectionReceiveWindow > 0) config["recv_window"] = connectionReceiveWindow;
|
||||
if (disableMtuDiscovery) config["disable_mtu_discovery"] = true;
|
||||
|
||||
//
|
||||
|
||||
result.config_export = QJsonObject2QString(config, false);
|
||||
WriteTempFile("hysteria_" + GetRandomString(10) + ".json", result.config_export.toUtf8());
|
||||
result.arguments = QStringList{"--no-check", "-c", TempFile};
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
ExternalBuildResult CustomBean::BuildExternal(int mapping_port, int socks_port, int external_stat) {
|
||||
ExternalBuildResult result{NekoGui::dataStore->extraCore->Get(core)};
|
||||
|
||||
result.arguments = command; // TODO split?
|
||||
|
||||
for (int i = 0; i < result.arguments.length(); i++) {
|
||||
auto arg = result.arguments[i];
|
||||
arg = arg.replace("%mapping_port%", Int2String(mapping_port));
|
||||
arg = arg.replace("%socks_port%", Int2String(socks_port));
|
||||
arg = arg.replace("%server_addr%", serverAddress);
|
||||
arg = arg.replace("%server_port%", Int2String(serverPort));
|
||||
result.arguments[i] = arg;
|
||||
}
|
||||
|
||||
if (!config_simple.trimmed().isEmpty()) {
|
||||
auto config = config_simple;
|
||||
config = config.replace("%mapping_port%", Int2String(mapping_port));
|
||||
config = config.replace("%socks_port%", Int2String(socks_port));
|
||||
config = config.replace("%server_addr%", serverAddress);
|
||||
config = config.replace("%server_port%", Int2String(serverPort));
|
||||
|
||||
// suffix
|
||||
QString suffix;
|
||||
if (!config_suffix.isEmpty()) {
|
||||
suffix = "." + config_suffix;
|
||||
} else if (!QString2QJsonObject(config).isEmpty()) {
|
||||
// trojan-go: unsupported config format: xxx.tmp. use .yaml or .json instead.
|
||||
suffix = ".json";
|
||||
}
|
||||
|
||||
// write config
|
||||
WriteTempFile("custom_" + GetRandomString(10) + suffix, config.toUtf8());
|
||||
for (int i = 0; i < result.arguments.count(); i++) {
|
||||
result.arguments[i] = result.arguments[i].replace("%config%", TempFile);
|
||||
}
|
||||
|
||||
result.config_export = config;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace NekoGui_fmt
|
||||
@ -177,17 +177,6 @@ namespace NekoGui_fmt {
|
||||
return url.toString(QUrl::FullyEncoded);
|
||||
}
|
||||
|
||||
QString NaiveBean::ToShareLink() {
|
||||
QUrl url;
|
||||
url.setScheme("naive+" + protocol);
|
||||
url.setUserName(username);
|
||||
url.setPassword(password);
|
||||
url.setHost(serverAddress);
|
||||
url.setPort(serverPort);
|
||||
if (!name.isEmpty()) url.setFragment(name);
|
||||
return url.toString(QUrl::FullyEncoded);
|
||||
}
|
||||
|
||||
QString QUICBean::ToShareLink() {
|
||||
QUrl url;
|
||||
if (proxy_type == proxy_Hysteria) {
|
||||
|
||||
@ -258,22 +258,6 @@ namespace NekoGui_fmt {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NaiveBean::TryParseLink(const QString &link) {
|
||||
auto url = QUrl(link);
|
||||
if (!url.isValid()) return false;
|
||||
|
||||
protocol = url.scheme().replace("naive+", "");
|
||||
if (protocol != "https" && protocol != "quic") return false;
|
||||
|
||||
name = url.fragment(QUrl::FullyDecoded);
|
||||
serverAddress = url.host();
|
||||
serverPort = url.port();
|
||||
username = url.userName();
|
||||
password = url.password();
|
||||
|
||||
return !(username.isEmpty() || password.isEmpty() || serverAddress.isEmpty());
|
||||
}
|
||||
|
||||
bool QUICBean::TryParseLink(const QString &link) {
|
||||
auto url = QUrl(link);
|
||||
auto query = QUrlQuery(url.query());
|
||||
|
||||
@ -172,14 +172,6 @@ namespace NekoGui_sub {
|
||||
if (!ok) return;
|
||||
}
|
||||
|
||||
// Naive
|
||||
if (str.startsWith("naive+")) {
|
||||
needFix = false;
|
||||
ent = NekoGui::ProfileManager::NewProxyEntity("naive");
|
||||
auto ok = ent->NaiveBean()->TryParseLink(str);
|
||||
if (!ok) return;
|
||||
}
|
||||
|
||||
// Hysteria1
|
||||
if (str.startsWith("hysteria://")) {
|
||||
needFix = false;
|
||||
|
||||
@ -215,8 +215,6 @@ namespace NekoGui {
|
||||
bean = new NekoGui_fmt::TrojanVLESSBean(NekoGui_fmt::TrojanVLESSBean::proxy_Trojan);
|
||||
} else if (type == "vless") {
|
||||
bean = new NekoGui_fmt::TrojanVLESSBean(NekoGui_fmt::TrojanVLESSBean::proxy_VLESS);
|
||||
} else if (type == "naive") {
|
||||
bean = new NekoGui_fmt::NaiveBean();
|
||||
} else if (type == "hysteria") {
|
||||
bean = new NekoGui_fmt::QUICBean(NekoGui_fmt::QUICBean::proxy_Hysteria);
|
||||
} else if (type == "hysteria2") {
|
||||
|
||||
@ -23,11 +23,7 @@
|
||||
#endif
|
||||
|
||||
QStringList SplitLines(const QString &_string) {
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
||||
return _string.split(QRegularExpression("[\r\n]"), Qt::SplitBehaviorFlags::SkipEmptyParts);
|
||||
#else
|
||||
return _string.split(QRegularExpression("[\r\n]"), QString::SkipEmptyParts);
|
||||
#endif
|
||||
}
|
||||
|
||||
QStringList SplitLinesSkipSharp(const QString &_string, int maxLine) {
|
||||
|
||||
@ -3,7 +3,6 @@
|
||||
#include <QApplication>
|
||||
#include <QDir>
|
||||
|
||||
#include "3rdparty/fix_old_qt.h"
|
||||
#include "include/global/NekoGui.hpp"
|
||||
|
||||
// macOS headers (possibly OBJ-c)
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#include "include/sys/ExternalProcess.hpp"
|
||||
#include "include/sys/Process.hpp"
|
||||
#include "include/global/NekoGui.hpp"
|
||||
|
||||
#include <QTimer>
|
||||
@ -8,61 +8,20 @@
|
||||
|
||||
namespace NekoGui_sys {
|
||||
|
||||
ExternalProcess::ExternalProcess() : QProcess() {
|
||||
// qDebug() << "[Debug] ExternalProcess()" << this << running_ext;
|
||||
CoreProcess::CoreProcess() : QProcess() {
|
||||
this->env = QProcessEnvironment::systemEnvironment().toStringList();
|
||||
}
|
||||
|
||||
ExternalProcess::~ExternalProcess() {
|
||||
// qDebug() << "[Debug] ~ExternalProcess()" << this << running_ext;
|
||||
CoreProcess::~CoreProcess() {
|
||||
}
|
||||
|
||||
void ExternalProcess::Start() {
|
||||
if (started) return;
|
||||
started = true;
|
||||
|
||||
if (managed) {
|
||||
connect(this, &QProcess::readyReadStandardOutput, this, [&]() {
|
||||
auto log = readAllStandardOutput();
|
||||
if (logCounter.fetchAndAddRelaxed(log.count("\n")) > NekoGui::dataStore->max_log_line) return;
|
||||
MW_show_log_ext_vt100(log);
|
||||
});
|
||||
connect(this, &QProcess::readyReadStandardError, this, [&]() {
|
||||
MW_show_log_ext_vt100(readAllStandardError().trimmed());
|
||||
});
|
||||
connect(this, &QProcess::errorOccurred, this, [&](QProcess::ProcessError error) {
|
||||
if (!killed) {
|
||||
crashed = true;
|
||||
MW_show_log_ext(tag, "errorOccurred:" + errorString());
|
||||
MW_dialog_message("ExternalProcess", "Crashed");
|
||||
}
|
||||
});
|
||||
connect(this, &QProcess::stateChanged, this, [&](QProcess::ProcessState state) {
|
||||
if (state == QProcess::NotRunning) {
|
||||
if (killed) { // 用户命令退出
|
||||
MW_show_log_ext(tag, "External core stopped");
|
||||
} else if (!crashed) { // 异常退出
|
||||
crashed = true;
|
||||
MW_show_log_ext(tag, "[Error] Program exited accidentally: " + errorString());
|
||||
Kill();
|
||||
MW_dialog_message("ExternalProcess", "Crashed");
|
||||
}
|
||||
}
|
||||
});
|
||||
MW_show_log_ext(tag, "External core starting: " + env.join(" ") + " " + program + " " + arguments.join(" "));
|
||||
}
|
||||
|
||||
QProcess::setEnvironment(env);
|
||||
QProcess::start(program, arguments);
|
||||
}
|
||||
|
||||
void ExternalProcess::Kill() {
|
||||
void CoreProcess::Kill() {
|
||||
if (killed) return;
|
||||
killed = true;
|
||||
|
||||
if (!crashed) {
|
||||
QProcess::kill();
|
||||
QProcess::waitForFinished(500);
|
||||
kill();
|
||||
waitForFinished(500);
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,10 +29,9 @@ namespace NekoGui_sys {
|
||||
|
||||
QElapsedTimer coreRestartTimer;
|
||||
|
||||
CoreProcess::CoreProcess(const QString &core_path, const QStringList &args) : ExternalProcess() {
|
||||
ExternalProcess::managed = false;
|
||||
ExternalProcess::program = core_path;
|
||||
ExternalProcess::arguments = args;
|
||||
CoreProcess::CoreProcess(const QString &core_path, const QStringList &args) : QProcess() {
|
||||
program = core_path;
|
||||
arguments = args;
|
||||
|
||||
connect(this, &QProcess::readyReadStandardOutput, this, [&]() {
|
||||
auto log = readAllStandardOutput();
|
||||
@ -87,7 +45,7 @@ namespace NekoGui_sys {
|
||||
}
|
||||
} else if (log.contains("failed to serve")) {
|
||||
// The core failed to start
|
||||
QProcess::kill();
|
||||
kill();
|
||||
}
|
||||
}
|
||||
if (logCounter.fetchAndAddRelaxed(log.count("\n")) > NekoGui::dataStore->max_log_line) return;
|
||||
@ -141,15 +99,19 @@ namespace NekoGui_sys {
|
||||
|
||||
void CoreProcess::Start() {
|
||||
show_stderr = false;
|
||||
ExternalProcess::Start();
|
||||
if (started) return;
|
||||
started = true;
|
||||
|
||||
setEnvironment(env);
|
||||
start(program, arguments);
|
||||
write((NekoGui::dataStore->core_token + "\n").toUtf8());
|
||||
}
|
||||
|
||||
void CoreProcess::Restart() {
|
||||
restarting = true;
|
||||
QProcess::kill();
|
||||
QProcess::waitForFinished(500);
|
||||
ExternalProcess::started = false;
|
||||
kill();
|
||||
waitForFinished(500);
|
||||
started = false;
|
||||
Start();
|
||||
restarting = false;
|
||||
}
|
||||
@ -3,7 +3,7 @@
|
||||
#include "include/dataStore/ProfileFilter.hpp"
|
||||
#include "include/configs/configBuilder.hpp"
|
||||
#include "include/configs/sub/GroupUpdater.hpp"
|
||||
#include "include/sys/ExternalProcess.hpp"
|
||||
#include "include/sys/Process.hpp"
|
||||
#include "include/sys/AutoRun.hpp"
|
||||
|
||||
#include "include/ui/setting/ThemeManager.hpp"
|
||||
@ -16,7 +16,6 @@
|
||||
#include "include/ui/setting/dialog_hotkey.h"
|
||||
|
||||
#include "3rdparty/qrcodegen.hpp"
|
||||
#include "3rdparty/VT100Parser.hpp"
|
||||
#include "3rdparty/qv2ray/v2/ui/LogHighlighter.hpp"
|
||||
#include "3rdparty/ZxingQtReader.hpp"
|
||||
#include "include/ui/group/dialog_edit_group.h"
|
||||
@ -154,12 +153,6 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
|
||||
MW_show_log = [=](const QString &log) {
|
||||
runOnUiThread([=] { show_log_impl(log); });
|
||||
};
|
||||
MW_show_log_ext = [=](const QString &tag, const QString &log) {
|
||||
runOnUiThread([=] { show_log_impl("[" + tag + "] " + log); });
|
||||
};
|
||||
MW_show_log_ext_vt100 = [=](const QString &log) {
|
||||
runOnUiThread([=] { show_log_impl(cleanVT100String(log)); });
|
||||
};
|
||||
|
||||
// table UI
|
||||
ui->proxyListTable->callback_save_order = [=] {
|
||||
|
||||
@ -12,24 +12,6 @@
|
||||
#include <QDesktopServices>
|
||||
#include <QMessageBox>
|
||||
|
||||
// ext core
|
||||
|
||||
std::list<std::shared_ptr<NekoGui_sys::ExternalProcess>> CreateExtCFromExtR(const std::list<std::shared_ptr<NekoGui_fmt::ExternalBuildResult>> &extRs, bool start) {
|
||||
// plz run and start in same thread
|
||||
std::list<std::shared_ptr<NekoGui_sys::ExternalProcess>> l;
|
||||
for (const auto &extR: extRs) {
|
||||
std::shared_ptr<NekoGui_sys::ExternalProcess> extC(new NekoGui_sys::ExternalProcess());
|
||||
extC->tag = extR->tag;
|
||||
extC->program = extR->program;
|
||||
extC->arguments = extR->arguments;
|
||||
extC->env = extR->env;
|
||||
l.emplace_back(extC);
|
||||
//
|
||||
if (start) extC->Start();
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
// grpc
|
||||
|
||||
using namespace NekoGui_rpc;
|
||||
@ -52,9 +34,6 @@ void MainWindow::RunSpeedTest(const QString& config, bool useDefault, const QStr
|
||||
return;
|
||||
}
|
||||
|
||||
std::list<std::shared_ptr<NekoGui_sys::ExternalProcess>> extCs;
|
||||
QSemaphore extSem;
|
||||
|
||||
libcore::TestReq req;
|
||||
for (const auto &item: outboundTags) {
|
||||
req.add_outbound_tags(item.toStdString());
|
||||
@ -67,18 +46,6 @@ void MainWindow::RunSpeedTest(const QString& config, bool useDefault, const QStr
|
||||
bool rpcOK;
|
||||
auto result = defaultClient->Test(&rpcOK, req);
|
||||
//
|
||||
if (!extCs.empty()) {
|
||||
runOnUiThread(
|
||||
[&] {
|
||||
for (const auto &extC: extCs) {
|
||||
extC->Kill();
|
||||
}
|
||||
extSem.release();
|
||||
},
|
||||
DS_cores);
|
||||
extSem.acquire();
|
||||
}
|
||||
//
|
||||
if (!rpcOK) return;
|
||||
|
||||
for (const auto &res: result.results()) {
|
||||
@ -313,13 +280,6 @@ void MainWindow::neko_start(int _id) {
|
||||
NekoGui::dataStore->ignoreConnTag = result->ignoreConnTag;
|
||||
NekoGui_traffic::trafficLooper->loop_enabled = true;
|
||||
|
||||
runOnUiThread(
|
||||
[=] {
|
||||
auto extCs = CreateExtCFromExtR(result->extRs, true);
|
||||
NekoGui_sys::running_ext.splice(NekoGui_sys::running_ext.end(), extCs);
|
||||
},
|
||||
DS_cores);
|
||||
|
||||
NekoGui::dataStore->UpdateStartedId(ent->id);
|
||||
running = ent;
|
||||
|
||||
@ -417,16 +377,6 @@ void MainWindow::neko_stop(bool crash, bool sem, bool manual) {
|
||||
return;
|
||||
}
|
||||
|
||||
runOnUiThread(
|
||||
[=] {
|
||||
while (!NekoGui_sys::running_ext.empty()) {
|
||||
auto extC = NekoGui_sys::running_ext.front();
|
||||
extC->Kill();
|
||||
NekoGui_sys::running_ext.pop_front();
|
||||
}
|
||||
},
|
||||
DS_cores);
|
||||
|
||||
auto neko_stop_stage2 = [=] {
|
||||
if (!crash) {
|
||||
bool rpcOK;
|
||||
|
||||
@ -5,7 +5,6 @@
|
||||
#include "include/ui/profile/edit_chain.h"
|
||||
#include "include/ui/profile/edit_vmess.h"
|
||||
#include "include/ui/profile/edit_trojan_vless.h"
|
||||
#include "include/ui/profile/edit_naive.h"
|
||||
#include "include/ui/profile/edit_quic.h"
|
||||
#include "include/ui/profile/edit_wireguard.h"
|
||||
#include "include/ui/profile/edit_ssh.h"
|
||||
@ -156,7 +155,6 @@ DialogEditProfile::DialogEditProfile(const QString &_type, int profileOrGroupId,
|
||||
LOAD_TYPE("trojan")
|
||||
LOAD_TYPE("vmess")
|
||||
LOAD_TYPE("vless")
|
||||
LOAD_TYPE("naive")
|
||||
LOAD_TYPE("hysteria")
|
||||
LOAD_TYPE("hysteria2")
|
||||
LOAD_TYPE("tuic")
|
||||
@ -164,7 +162,6 @@ DialogEditProfile::DialogEditProfile(const QString &_type, int profileOrGroupId,
|
||||
LOAD_TYPE("ssh")
|
||||
ui->type->addItem(tr("Custom (%1 outbound)").arg(software_core_name), "internal");
|
||||
ui->type->addItem(tr("Custom (%1 config)").arg(software_core_name), "internal-full");
|
||||
ui->type->addItem(tr("Custom (Extra Core)"), "custom");
|
||||
LOAD_TYPE("chain")
|
||||
|
||||
// type changed
|
||||
@ -213,10 +210,6 @@ void DialogEditProfile::typeSelected(const QString &newType) {
|
||||
auto _innerWidget = new EditTrojanVLESS(this);
|
||||
innerWidget = _innerWidget;
|
||||
innerEditor = _innerWidget;
|
||||
} else if (type == "naive") {
|
||||
auto _innerWidget = new EditNaive(this);
|
||||
innerWidget = _innerWidget;
|
||||
innerEditor = _innerWidget;
|
||||
} else if (type == "hysteria" || type == "hysteria2" || type == "tuic") {
|
||||
auto _innerWidget = new EditQUIC(this);
|
||||
innerWidget = _innerWidget;
|
||||
@ -229,7 +222,7 @@ void DialogEditProfile::typeSelected(const QString &newType) {
|
||||
auto _innerWidget = new EditSSH(this);
|
||||
innerWidget = _innerWidget;
|
||||
innerEditor = _innerWidget;
|
||||
} else if (type == "custom" || type == "internal" || type == "internal-full") {
|
||||
} else if (type == "internal" || type == "internal-full") {
|
||||
auto _innerWidget = new EditCustom(this);
|
||||
innerWidget = _innerWidget;
|
||||
innerEditor = _innerWidget;
|
||||
|
||||
@ -114,16 +114,6 @@ void EditCustom::onStart(std::shared_ptr<NekoGui::ProxyEntity> _ent) {
|
||||
MessageBoxInfo(software_name, result->error);
|
||||
return;
|
||||
}
|
||||
for (const auto &extR: result->extRs) {
|
||||
auto command = QStringList{extR->program};
|
||||
command += extR->arguments;
|
||||
auto btn = QMessageBox::information(this, tr("Preview config"),
|
||||
QString("Command: %1\n\n%2").arg(QStringList2Command(command), extR->config_export),
|
||||
"OK", "Copy", "", 0, 0);
|
||||
if (btn == 1) {
|
||||
QApplication::clipboard()->setText(extR->config_export);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -1,67 +0,0 @@
|
||||
#include "include/ui/profile/edit_naive.h"
|
||||
|
||||
#include "include/configs/proxy/NaiveBean.hpp"
|
||||
|
||||
#include <QInputDialog>
|
||||
|
||||
EditNaive::EditNaive(QWidget *parent) : QWidget(parent), ui(new Ui::EditNaive) {
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
EditNaive::~EditNaive() {
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void EditNaive::onStart(std::shared_ptr<NekoGui::ProxyEntity> _ent) {
|
||||
this->ent = _ent;
|
||||
auto bean = this->ent->NaiveBean();
|
||||
|
||||
P_LOAD_STRING(username);
|
||||
P_LOAD_STRING(password);
|
||||
P_LOAD_COMBO_STRING(protocol);
|
||||
P_C_LOAD_STRING(extra_headers);
|
||||
P_LOAD_STRING(sni);
|
||||
P_C_LOAD_STRING(certificate);
|
||||
P_LOAD_INT(insecure_concurrency);
|
||||
P_LOAD_BOOL(disable_log);
|
||||
}
|
||||
|
||||
bool EditNaive::onEnd() {
|
||||
auto bean = this->ent->NaiveBean();
|
||||
|
||||
P_SAVE_STRING(username);
|
||||
P_SAVE_STRING(password);
|
||||
P_SAVE_COMBO_STRING(protocol);
|
||||
P_C_SAVE_STRING(extra_headers);
|
||||
P_SAVE_STRING(sni);
|
||||
P_C_SAVE_STRING(certificate);
|
||||
P_SAVE_INT(insecure_concurrency);
|
||||
P_SAVE_BOOL(disable_log);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QList<QPair<QPushButton *, QString>> EditNaive::get_editor_cached() {
|
||||
return {
|
||||
{ui->certificate, CACHE.certificate},
|
||||
{ui->extra_headers, CACHE.extra_headers},
|
||||
};
|
||||
}
|
||||
|
||||
void EditNaive::on_certificate_clicked() {
|
||||
bool ok;
|
||||
auto txt = QInputDialog::getMultiLineText(this, tr("Certificate"), "", CACHE.certificate, &ok);
|
||||
if (ok) {
|
||||
CACHE.certificate = txt;
|
||||
editor_cache_updated();
|
||||
}
|
||||
}
|
||||
|
||||
void EditNaive::on_extra_headers_clicked() {
|
||||
bool ok;
|
||||
auto txt = QInputDialog::getMultiLineText(this, tr("Extra headers"), "", CACHE.extra_headers, &ok);
|
||||
if (ok) {
|
||||
CACHE.extra_headers = txt;
|
||||
editor_cache_updated();
|
||||
}
|
||||
}
|
||||
@ -15,44 +15,6 @@
|
||||
#include <QTimer>
|
||||
#include <qfontdatabase.h>
|
||||
|
||||
class ExtraCoreWidget : public QWidget {
|
||||
public:
|
||||
QString coreName;
|
||||
|
||||
QLabel *label_name;
|
||||
MyLineEdit *lineEdit_path;
|
||||
QPushButton *pushButton_pick;
|
||||
|
||||
explicit ExtraCoreWidget(QJsonObject *extraCore, const QString &coreName_,
|
||||
QWidget *parent = nullptr)
|
||||
: QWidget(parent) {
|
||||
coreName = coreName_;
|
||||
label_name = new QLabel;
|
||||
label_name->setText(coreName);
|
||||
lineEdit_path = new MyLineEdit;
|
||||
lineEdit_path->setText(extraCore->value(coreName).toString());
|
||||
pushButton_pick = new QPushButton;
|
||||
pushButton_pick->setText(QObject::tr("Select"));
|
||||
auto layout = new QHBoxLayout;
|
||||
layout->addWidget(label_name);
|
||||
layout->addWidget(lineEdit_path);
|
||||
layout->addWidget(pushButton_pick);
|
||||
setLayout(layout);
|
||||
setContentsMargins(0, 0, 0, 0);
|
||||
//
|
||||
connect(pushButton_pick, &QPushButton::clicked, this, [=] {
|
||||
auto fn = QFileDialog::getOpenFileName(this, QObject::tr("Select"), QDir::currentPath(),
|
||||
"", nullptr, QFileDialog::Option::ReadOnly);
|
||||
if (!fn.isEmpty()) {
|
||||
lineEdit_path->setText(fn);
|
||||
}
|
||||
});
|
||||
connect(lineEdit_path, &QLineEdit::textChanged, this, [=](const QString &newTxt) {
|
||||
extraCore->insert(coreName, newTxt);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
DialogBasicSettings::DialogBasicSettings(QWidget *parent)
|
||||
: QDialog(parent), ui(new Ui::DialogBasicSettings) {
|
||||
ui->setupUi(this);
|
||||
@ -169,46 +131,6 @@ DialogBasicSettings::DialogBasicSettings(QWidget *parent)
|
||||
MW_show_log("Removed all rule-set files");
|
||||
});
|
||||
|
||||
//
|
||||
CACHE.extraCore = QString2QJsonObject(NekoGui::dataStore->extraCore->core_map);
|
||||
if (!CACHE.extraCore.contains("naive")) CACHE.extraCore.insert("naive", "");
|
||||
if (!CACHE.extraCore.contains("hysteria")) CACHE.extraCore.insert("hysteria", "");
|
||||
if (!CACHE.extraCore.contains("hysteria2")) CACHE.extraCore.insert("hysteria2", "");
|
||||
if (!CACHE.extraCore.contains("tuic")) CACHE.extraCore.insert("tuic", "");
|
||||
//
|
||||
auto extra_core_layout = ui->extra_core_box_scrollAreaWidgetContents->layout();
|
||||
for (const auto &s: CACHE.extraCore.keys()) {
|
||||
extra_core_layout->addWidget(new ExtraCoreWidget(&CACHE.extraCore, s));
|
||||
}
|
||||
//
|
||||
connect(ui->extra_core_add, &QPushButton::clicked, this, [=] {
|
||||
bool ok;
|
||||
auto s = QInputDialog::getText(nullptr, tr("Add"),
|
||||
tr("Please input the core name."),
|
||||
QLineEdit::Normal, "", &ok)
|
||||
.trimmed();
|
||||
if (s.isEmpty() || !ok) return;
|
||||
if (CACHE.extraCore.contains(s)) return;
|
||||
extra_core_layout->addWidget(new ExtraCoreWidget(&CACHE.extraCore, s));
|
||||
CACHE.extraCore.insert(s, "");
|
||||
});
|
||||
connect(ui->extra_core_del, &QPushButton::clicked, this, [=] {
|
||||
bool ok;
|
||||
auto s = QInputDialog::getItem(nullptr, tr("Delete"),
|
||||
tr("Please select the core name."),
|
||||
CACHE.extraCore.keys(), 0, false, &ok);
|
||||
if (s.isEmpty() || !ok) return;
|
||||
for (int i = 0; i < extra_core_layout->count(); i++) {
|
||||
auto item = extra_core_layout->itemAt(i);
|
||||
auto ecw = dynamic_cast<ExtraCoreWidget *>(item->widget());
|
||||
if (ecw != nullptr && ecw->coreName == s) {
|
||||
ecw->deleteLater();
|
||||
CACHE.extraCore.remove(s);
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Mux
|
||||
D_LOAD_INT(mux_concurrency)
|
||||
D_LOAD_COMBO_STRING(mux_protocol)
|
||||
@ -290,7 +212,6 @@ void DialogBasicSettings::accept() {
|
||||
D_SAVE_INT_ENABLE(sub_auto_update, sub_auto_update_enable)
|
||||
|
||||
// Core
|
||||
NekoGui::dataStore->extraCore->core_map = QJsonObject2QString(CACHE.extraCore, true);
|
||||
NekoGui::dataStore->disable_traffic_stats = ui->disable_stats->isChecked();
|
||||
|
||||
// Assets
|
||||
|
||||
Loading…
Reference in New Issue
Block a user