mirror of
https://github.com/MatsuriDayo/nekoray.git
synced 2025-12-17 20:44:38 +03:00
refactor core_process (1)
This commit is contained in:
@@ -399,8 +399,11 @@ namespace NekoRay {
|
|||||||
outbound["settings"] = settings;
|
outbound["settings"] = settings;
|
||||||
|
|
||||||
// EXTERNAL PROCESS
|
// EXTERNAL PROCESS
|
||||||
auto extC = new sys::ExternalProcess(ent->bean->DisplayType(),
|
auto extC = new sys::ExternalProcess();
|
||||||
extR.program, extR.arguments, extR.env);
|
extC->tag = ent->bean->DisplayType();
|
||||||
|
extC->program = extR.program;
|
||||||
|
extC->arguments = extR.arguments;
|
||||||
|
extC->env = extR.env;
|
||||||
status->result->ext += extC;
|
status->result->ext += extC;
|
||||||
} else {
|
} else {
|
||||||
coreR = ent->bean->BuildCoreObj();
|
coreR = ent->bean->BuildCoreObj();
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ namespace NekoRay {
|
|||||||
QString core_token;
|
QString core_token;
|
||||||
int core_port = 19810;
|
int core_port = 19810;
|
||||||
int started_id = -1919;
|
int started_id = -1919;
|
||||||
|
bool core_running = false;
|
||||||
|
bool core_prepare_exit = false;
|
||||||
|
|
||||||
Routing *routing = new Routing;
|
Routing *routing = new Routing;
|
||||||
int imported_count = 0;
|
int imported_count = 0;
|
||||||
|
|||||||
@@ -23,8 +23,6 @@ namespace QtGrpc {
|
|||||||
const char *GrpcStatusMessage = "grpc-message";
|
const char *GrpcStatusMessage = "grpc-message";
|
||||||
const int GrpcMessageSizeHeaderSize = 5;
|
const int GrpcMessageSizeHeaderSize = 5;
|
||||||
|
|
||||||
bool core_crashed = false;
|
|
||||||
|
|
||||||
class Http2GrpcChannelPrivate : public QObject {
|
class Http2GrpcChannelPrivate : public QObject {
|
||||||
private:
|
private:
|
||||||
QString url_base;
|
QString url_base;
|
||||||
@@ -135,7 +133,7 @@ namespace QtGrpc {
|
|||||||
QNetworkReply::NetworkError Call(const QString &methodName,
|
QNetworkReply::NetworkError Call(const QString &methodName,
|
||||||
const google::protobuf::Message &req, google::protobuf::Message *rsp,
|
const google::protobuf::Message &req, google::protobuf::Message *rsp,
|
||||||
int timeout_ms = 0) {
|
int timeout_ms = 0) {
|
||||||
if (core_crashed) return QNetworkReply::NetworkError(-1919);
|
if (!NekoRay::dataStore->core_running) return QNetworkReply::NetworkError(-1919);
|
||||||
|
|
||||||
std::string reqStr;
|
std::string reqStr;
|
||||||
req.SerializeToString(&reqStr);
|
req.SerializeToString(&reqStr);
|
||||||
|
|||||||
@@ -1,57 +1,46 @@
|
|||||||
#include "ExternalProcess.hpp"
|
#include "ExternalProcess.hpp"
|
||||||
|
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
namespace NekoRay::sys {
|
namespace NekoRay::sys {
|
||||||
ExternalProcess::ExternalProcess(const QString &tag,
|
ExternalProcess::ExternalProcess() : QProcess() {}
|
||||||
const QString &program,
|
|
||||||
const QStringList &arguments,
|
|
||||||
const QStringList &env)
|
|
||||||
: QProcess() {
|
|
||||||
this->tag = tag;
|
|
||||||
this->program = program;
|
|
||||||
this->arguments = arguments;
|
|
||||||
this->env = env;
|
|
||||||
this->running_list = &running_ext;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ExternalProcess::Start() {
|
void ExternalProcess::Start() {
|
||||||
if (started) return;
|
if (started) return;
|
||||||
started = true;
|
started = true;
|
||||||
*running_list += this;
|
if (managed) running_ext.push_back(this);
|
||||||
|
|
||||||
if (show_log) {
|
if (show_log) {
|
||||||
connect(this, &QProcess::readyReadStandardOutput, this,
|
connect(this, &QProcess::readyReadStandardOutput, this, [&]() {
|
||||||
[&]() {
|
showLog_ext_vt100(readAllStandardOutput().trimmed());
|
||||||
showLog_ext_vt100(readAllStandardOutput().trimmed());
|
});
|
||||||
});
|
connect(this, &QProcess::readyReadStandardError, this, [&]() {
|
||||||
connect(this, &QProcess::readyReadStandardError, this,
|
showLog_ext_vt100(readAllStandardError().trimmed());
|
||||||
[&]() {
|
});
|
||||||
showLog_ext_vt100(readAllStandardError().trimmed());
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
connect(this, &QProcess::errorOccurred, this,
|
if (managed) {
|
||||||
[&](QProcess::ProcessError error) {
|
connect(this, &QProcess::errorOccurred, this, [&](QProcess::ProcessError error) {
|
||||||
if (!killed) {
|
if (!killed) {
|
||||||
|
crashed = true;
|
||||||
|
showLog_ext(tag, "errorOccurred:" + errorString());
|
||||||
|
dialog_message("ExternalProcess", "Crashed");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
connect(this, &QProcess::stateChanged, this, [&](QProcess::ProcessState state) {
|
||||||
|
if (state == QProcess::NotRunning) {
|
||||||
|
if (killed) { // 用户命令退出
|
||||||
|
showLog_ext(tag, "Stopped");
|
||||||
|
} else if (!crashed) { // 异常退出
|
||||||
crashed = true;
|
crashed = true;
|
||||||
showLog_ext(tag, "[Error] Crashed:" + QProcess::errorString());
|
showLog_ext(tag, "[Error] Program exited accidentally: " + errorString());
|
||||||
|
Kill();
|
||||||
dialog_message("ExternalProcess", "Crashed");
|
dialog_message("ExternalProcess", "Crashed");
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
connect(this, &QProcess::stateChanged, this,
|
});
|
||||||
[&](QProcess::ProcessState state) {
|
showLog_ext(tag, "[Starting] " + env.join(" ") + " " + program + " " + arguments.join(" "));
|
||||||
if (state == QProcess::NotRunning) {
|
}
|
||||||
if (killed) {
|
|
||||||
showLog_ext(tag, "Stopped");
|
|
||||||
} else if (!crashed) {
|
|
||||||
crashed = true;
|
|
||||||
Kill();
|
|
||||||
showLog_ext(tag, "[Error] Program exited accidentally");
|
|
||||||
dialog_message("ExternalProcess", "Crashed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
showLog_ext(tag, "[Starting] " + env.join(" ") + " " + program + " " + arguments.join(" "));
|
|
||||||
|
|
||||||
QProcess::setEnvironment(env);
|
QProcess::setEnvironment(env);
|
||||||
QProcess::start(program, arguments);
|
QProcess::start(program, arguments);
|
||||||
@@ -60,11 +49,71 @@ namespace NekoRay::sys {
|
|||||||
void ExternalProcess::Kill() {
|
void ExternalProcess::Kill() {
|
||||||
if (killed) return;
|
if (killed) return;
|
||||||
killed = true;
|
killed = true;
|
||||||
running_list->removeAll(this);
|
if (managed) running_ext.removeAll(this);
|
||||||
|
|
||||||
if (!crashed) {
|
if (!crashed) {
|
||||||
QProcess::kill();
|
QProcess::kill();
|
||||||
QProcess::waitForFinished(500);
|
QProcess::waitForFinished(500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CoreProcess::CoreProcess(const QString &core_path, const QStringList &args) {
|
||||||
|
ExternalProcess::managed = false;
|
||||||
|
ExternalProcess::show_log = false;
|
||||||
|
ExternalProcess::program = core_path;
|
||||||
|
ExternalProcess::arguments = args;
|
||||||
|
|
||||||
|
connect(this, &QProcess::readyReadStandardOutput, this, [&]() {
|
||||||
|
showLog(readAllStandardOutput().trimmed());
|
||||||
|
});
|
||||||
|
connect(this, &QProcess::readyReadStandardError, this, [&]() {
|
||||||
|
auto log = readAllStandardError().trimmed();
|
||||||
|
if (show_stderr) {
|
||||||
|
showLog(log);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (log.contains("token is set")) {
|
||||||
|
show_stderr = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
connect(this, &QProcess::errorOccurred, this, [&](QProcess::ProcessError error) {
|
||||||
|
if (error == QProcess::ProcessError::FailedToStart) {
|
||||||
|
failed_to_start = true;
|
||||||
|
showLog("start nekoray_core errorOccurred: " + errorString() + "\n");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
connect(this, &QProcess::stateChanged, this, [&](QProcess::ProcessState state) {
|
||||||
|
NekoRay::dataStore->core_running = state == QProcess::Running;
|
||||||
|
|
||||||
|
if (!dataStore->core_prepare_exit && state == QProcess::NotRunning) {
|
||||||
|
if (failed_to_start) return; // no retry
|
||||||
|
|
||||||
|
showLog("[Error] nekoray_core exited, restarting.\n");
|
||||||
|
|
||||||
|
// Restart
|
||||||
|
auto t = new QTimer;
|
||||||
|
connect(t, &QTimer::timeout, this, [=] {
|
||||||
|
Kill();
|
||||||
|
ExternalProcess::started = false;
|
||||||
|
Start();
|
||||||
|
t->deleteLater();
|
||||||
|
});
|
||||||
|
t->setSingleShot(true);
|
||||||
|
t->setInterval(1000);
|
||||||
|
t->start();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void CoreProcess::Start() {
|
||||||
|
show_stderr = false;
|
||||||
|
if (!dataStore->v2ray_asset_dir.isEmpty()) {
|
||||||
|
setEnvironment(QStringList{
|
||||||
|
"V2RAY_LOCATION_ASSET=" + dataStore->v2ray_asset_dir
|
||||||
|
});
|
||||||
|
}
|
||||||
|
ExternalProcess::Start();
|
||||||
|
write((dataStore->core_token + "\n").toUtf8());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,26 +12,34 @@ namespace NekoRay::sys {
|
|||||||
QStringList arguments;
|
QStringList arguments;
|
||||||
QStringList env;
|
QStringList env;
|
||||||
|
|
||||||
|
bool managed = true; // running_ext & stateChanged
|
||||||
bool show_log = true;
|
bool show_log = true;
|
||||||
QList<ExternalProcess *> *running_list;
|
|
||||||
|
|
||||||
ExternalProcess(const QString &tag,
|
ExternalProcess();
|
||||||
const QString &program,
|
|
||||||
const QStringList &arguments,
|
|
||||||
const QStringList &env);
|
|
||||||
|
|
||||||
// start & kill is one time
|
// start & kill is one time
|
||||||
|
|
||||||
void Start();
|
virtual void Start();
|
||||||
|
|
||||||
void Kill();
|
void Kill();
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
bool started = false;
|
bool started = false;
|
||||||
bool killed = false;
|
bool killed = false;
|
||||||
bool crashed = false;
|
bool crashed = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CoreProcess : public ExternalProcess {
|
||||||
|
public:
|
||||||
|
CoreProcess(const QString &core_path, const QStringList &args);
|
||||||
|
|
||||||
|
void Start() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool show_stderr = false;
|
||||||
|
bool failed_to_start = false;
|
||||||
|
};
|
||||||
|
|
||||||
// start & kill change this list
|
// start & kill change this list
|
||||||
inline QList<ExternalProcess *> running_ext;
|
inline QList<ExternalProcess *> running_ext;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,10 +52,6 @@
|
|||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QFileSystemWatcher>
|
#include <QFileSystemWatcher>
|
||||||
|
|
||||||
namespace QtGrpc {
|
|
||||||
extern bool core_crashed;
|
|
||||||
}
|
|
||||||
|
|
||||||
MainWindow::MainWindow(QWidget *parent)
|
MainWindow::MainWindow(QWidget *parent)
|
||||||
: QMainWindow(parent), ui(new Ui::MainWindow) {
|
: QMainWindow(parent), ui(new Ui::MainWindow) {
|
||||||
mainwindow = this;
|
mainwindow = this;
|
||||||
@@ -343,21 +339,14 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
connect(ui->menu_full_test, &QAction::triggered, this, [=]() { speedtest_current_group(2); });
|
connect(ui->menu_full_test, &QAction::triggered, this, [=]() { speedtest_current_group(2); });
|
||||||
refresh_status();
|
refresh_status();
|
||||||
|
|
||||||
// Start Core
|
// Prepare core
|
||||||
NekoRay::dataStore->core_token = GetRandomString(32);
|
NekoRay::dataStore->core_token = GetRandomString(32);
|
||||||
NekoRay::dataStore->core_port = MkPort();
|
NekoRay::dataStore->core_port = MkPort();
|
||||||
if (NekoRay::dataStore->core_port <= 0) NekoRay::dataStore->core_port = 19810;
|
if (NekoRay::dataStore->core_port <= 0) NekoRay::dataStore->core_port = 19810;
|
||||||
|
|
||||||
QString starting_info;
|
|
||||||
auto core_path = NekoRay::dataStore->core_path;
|
auto core_path = NekoRay::dataStore->core_path;
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
if (!core_path.endsWith(".exe")) core_path += ".exe";
|
|
||||||
#endif
|
|
||||||
if (NekoRay::dataStore->flag_use_appdata) {
|
if (NekoRay::dataStore->flag_use_appdata) {
|
||||||
core_path = QApplication::applicationDirPath() + "/nekoray_core";
|
core_path = QApplication::applicationDirPath() + "/nekoray_core";
|
||||||
} else if (!QFile(core_path).exists()) {
|
|
||||||
starting_info = "(not found)";
|
|
||||||
core_path = "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList args;
|
QStringList args;
|
||||||
@@ -368,40 +357,9 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
args.push_back("-debug");
|
args.push_back("-debug");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
showLog("Starting nekoray core " + starting_info + "\n");
|
// Start core
|
||||||
|
core_process = new NekoRay::sys::CoreProcess(core_path, args);
|
||||||
if (!core_path.isEmpty()) {
|
core_process->Start();
|
||||||
core_process = new QProcess;
|
|
||||||
core_process_show_stderr = false;
|
|
||||||
|
|
||||||
connect(core_process, &QProcess::readyReadStandardOutput, this, [&]() {
|
|
||||||
showLog(core_process->readAllStandardOutput().trimmed());
|
|
||||||
});
|
|
||||||
connect(core_process, &QProcess::readyReadStandardError, this, [&]() {
|
|
||||||
auto log = core_process->readAllStandardError().trimmed();
|
|
||||||
if (core_process_show_stderr) {
|
|
||||||
showLog(log);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (log.contains("token is set")) {
|
|
||||||
core_process_show_stderr = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
connect(core_process, &QProcess::stateChanged, this, [&](QProcess::ProcessState state) {
|
|
||||||
if (!prepare_exit_core && state == QProcess::NotRunning) {
|
|
||||||
QtGrpc::core_crashed = true;
|
|
||||||
showLog("[Error] nekoray_core crashed, please restart the program.");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!NekoRay::dataStore->v2ray_asset_dir.isEmpty()) {
|
|
||||||
core_process->setEnvironment(QStringList{
|
|
||||||
"V2RAY_LOCATION_ASSET=" + NekoRay::dataStore->v2ray_asset_dir
|
|
||||||
});
|
|
||||||
}
|
|
||||||
core_process->start(core_path, args);
|
|
||||||
core_process->write((NekoRay::dataStore->core_token + "\n").toUtf8());
|
|
||||||
}
|
|
||||||
|
|
||||||
setup_grpc();
|
setup_grpc();
|
||||||
|
|
||||||
@@ -563,7 +521,7 @@ void MainWindow::on_menu_exit_triggered() {
|
|||||||
//
|
//
|
||||||
on_commitDataRequest();
|
on_commitDataRequest();
|
||||||
//
|
//
|
||||||
prepare_exit_core = true;
|
NekoRay::dataStore->core_prepare_exit = true;
|
||||||
hide();
|
hide();
|
||||||
ExitNekorayCore();
|
ExitNekorayCore();
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#include "main/GuiUtils.hpp"
|
#include "main/GuiUtils.hpp"
|
||||||
|
|
||||||
class QFileSystemWatcher;
|
class QFileSystemWatcher;
|
||||||
|
namespace NekoRay::sys { class CoreProcess; }
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
@@ -120,9 +121,7 @@ private:
|
|||||||
QShortcut *shortcut_ctrl_f = new QShortcut(QKeySequence("Ctrl+F"), this);
|
QShortcut *shortcut_ctrl_f = new QShortcut(QKeySequence("Ctrl+F"), this);
|
||||||
QShortcut *shortcut_esc = new QShortcut(QKeySequence("Esc"), this);
|
QShortcut *shortcut_esc = new QShortcut(QKeySequence("Esc"), this);
|
||||||
//
|
//
|
||||||
QProcess *core_process;
|
NekoRay::sys::CoreProcess *core_process;
|
||||||
bool prepare_exit_core = false;
|
|
||||||
bool core_process_show_stderr = false;
|
|
||||||
qint64 vpn_pid = 0;
|
qint64 vpn_pid = 0;
|
||||||
QFileSystemWatcher *watcher = nullptr;
|
QFileSystemWatcher *watcher = nullptr;
|
||||||
//
|
//
|
||||||
|
|||||||
Reference in New Issue
Block a user