diff --git a/Build.Counter b/Build.Counter index c7720795..d0e5260c 100644 --- a/Build.Counter +++ b/Build.Counter @@ -1 +1 @@ -1620 +1636 diff --git a/src/QvConfigUpgrade.cpp b/src/QvConfigUpgrade.cpp index 78880d04..7ae05717 100644 --- a/src/QvConfigUpgrade.cpp +++ b/src/QvConfigUpgrade.cpp @@ -57,83 +57,48 @@ namespace Qv2ray case 4: { // From 2 to 3, we changed the "proxyCN" to "bypassCN" as it's easier to understand.... auto v2_oldProxyCN = root["proxyCN"].toBool(); - root.remove("proxyCN"); - root.insert("bypassCN", !v2_oldProxyCN); - UPDATELOG("Upgrading proxyCN to bypassCN and changed the value to " + to_string(!v2_oldProxyCN)) - break; - } - - case 5: { + // auto v3_oldrunAsRoot = root["runAsRoot"].toBool(); // From 3 to 4, we changed 'runAsRoot' to 'tProxySupport' root.remove("runAsRoot"); root.insert("tProxySupport", v3_oldrunAsRoot); UPDATELOG("Upgrading runAsRoot to tProxySupport, the value is not changed: " + to_string(v3_oldrunAsRoot)) - break; - } - - case 6: { - root["enableStats"] = true; - UPDATELOG("Default statistics enabled.") - break; - } - - case 7: { + // + // QString path; path = QV2RAY_DEFAULT_VCORE_PATH; root["v2CorePath"] = path; UPDATELOG("Added v2CorePath to the config file.") - break; - } - - case 8: { + // auto lang = root["language"].toString(); QJsonObject uiSettings; uiSettings["language"] = lang; root["uiConfig"] = uiSettings; UPDATELOG("Reconstructing config file.") - break; - } - - case 9: { - root["uiConfig"] = root["UISettings"]; - root.remove("UISettings"); - UPDATELOG("Renamed UISettings to uiConfig.") - break; - } - - case 10: { + // root["inboundConfig"] = root["inBoundSettings"]; root.remove("inBoundSettings"); UPDATELOG("Renamed inBoundSettings to inboundConfig.") - break; - } - - case 11: { + // //connectionConfig QJsonObject o; o["dnsList"] = root["dnsList"]; o["withLocalDNS"] = root["withLocalDNS"]; o["enableProxy"] = root["enableProxy"]; - o["bypassCN"] = root["bypassCN"]; - o["enableStats"] = root["enableStats"]; - o["statsPort"] = root["statsPort"]; + o["bypassCN"] = !v2_oldProxyCN; + o["enableStats"] = true; + o["statsPort"] = 13459; + UPDATELOG("Default statistics enabled.") root["connectionConfig"] = o; UPDATELOG("Renamed some connection configs to connectionConfig.") - break; - } - - case 12: { + // auto inbound = root["inboundConfig"].toObject(); auto pacConfig = inbound["pacConfig"].toObject(); pacConfig["enablePAC"] = pacConfig["usePAC"].toBool(); inbound["pacConfig"] = pacConfig; root["inboundConfig"] = inbound; UPDATELOG("Renamed usePAC to enablePAC.") - break; - } - - case 13: { + // ConfigIdentifier i; i.connectionName = root["autoStartConfig"].toString().toStdString(); root["autoStartConfig"] = GetRootObject(i); diff --git a/src/components/QvTCPing.cpp b/src/components/QvTCPing.cpp index 53fdb286..311eaefc 100644 --- a/src/components/QvTCPing.cpp +++ b/src/components/QvTCPing.cpp @@ -5,33 +5,34 @@ namespace Qv2ray { namespace Components { - TCPingModel::TCPingModel(int defaultCount, QObject *parent) : QObject(parent) + QvTCPingModel::QvTCPingModel(int defaultCount, QObject *parent) : QObject(parent) { count = defaultCount; } - void TCPingModel::StartPing(const QString &connectionName, const QString &hostName, int port) + void QvTCPingModel::StartPing(const QString &connectionName, const QString &hostName, int port) { QvTCPingData data; data.hostName = hostName; data.port = port; data.connectionName = connectionName; auto watcher = new QFutureWatcher(this); - watcher->setFuture(QtConcurrent::run(&TCPingModel::startTestLatency, data, count)); + DEBUG(MODULE_NETWORK, "Start Ping: " + hostName.toStdString() + ":" + to_string(port)) + watcher->setFuture(QtConcurrent::run(&QvTCPingModel::startTestLatency, data, count)); pingWorkingThreads.enqueue(watcher); connect(watcher, &QFutureWatcher::finished, this, [this, watcher]() { this->pingWorkingThreads.removeOne(watcher); auto result = watcher->result(); - LOG(MODULE_NETWORK, "Ping finished: " + result.hostName.toStdString() + ":" + to_string(result.port) + " --> " + to_string(result.avg) + "ms") + DEBUG(MODULE_NETWORK, "Ping finished: " + result.hostName.toStdString() + ":" + to_string(result.port) + " --> " + to_string(result.avg) + "ms") if (!result.errorMessage.isEmpty()) { - LOG(MODULE_NETWORK, "--> " + result.errorMessage.toStdString()) + LOG(MODULE_NETWORK, "Ping --> " + result.errorMessage.toStdString()) } emit this->PingFinished(result); }); } - QvTCPingData TCPingModel::startTestLatency(QvTCPingData data, const int count) + QvTCPingData QvTCPingModel::startTestLatency(QvTCPingData data, const int count) { double successCount = 0, errorCount = 0; addrinfo *resolved; @@ -75,7 +76,7 @@ namespace Qv2ray } currentCount++; - sleep(1); + QThread::msleep(500); } data.avg = data.avg / successCount; @@ -83,7 +84,7 @@ namespace Qv2ray return data; } - int TCPingModel::resolveHost(const string &host, int port, addrinfo **res) + int QvTCPingModel::resolveHost(const string &host, int port, addrinfo **res) { addrinfo hints; #ifdef _WIN32 @@ -99,7 +100,7 @@ namespace Qv2ray return getaddrinfo(host.c_str(), to_string(port).c_str(), &hints, res); } - int TCPingModel::testLatency(struct addrinfo *addr, struct timeval *rtt) + int QvTCPingModel::testLatency(struct addrinfo *addr, struct timeval *rtt) { int fd; struct timeval start; diff --git a/src/components/QvTCPing.hpp b/src/components/QvTCPing.hpp index f0674640..c399bee5 100644 --- a/src/components/QvTCPing.hpp +++ b/src/components/QvTCPing.hpp @@ -26,14 +26,13 @@ namespace Qv2ray double min = 999999999999999.0, max = 0.0, avg = 0.0; }; // - // - class TCPingModel : public QObject + class QvTCPingModel : public QObject { Q_OBJECT public: - explicit TCPingModel(int defaultCount = 5, QObject *parent = nullptr); + explicit QvTCPingModel(int defaultCount = 5, QObject *parent = nullptr); void StartPing(const QString &connectionName, const QString &hostName, int port); signals: void PingFinished(QvTCPingData data); diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index e1ef753f..1395b133 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -56,7 +56,7 @@ MainWindow *MainWindow::mwInstance = nullptr; MainWindow::MainWindow(QWidget *parent): - QMainWindow(parent), vinstance(), uploadList(), downloadList(), HTTPRequestHelper(), + QMainWindow(parent), vinstance(), uploadList(), downloadList(), hTray(new QSystemTrayIcon(this)), vCoreLogHighlighter(), qvAppLogHighlighter() { MainWindow::mwInstance = this; @@ -86,6 +86,10 @@ MainWindow::MainWindow(QWidget *parent): logTimerId = startTimer(500); // pacServer = new PACServer(); + tcpingModel = new QvTCPingModel(5, this); + requestHelper = new QvHttpRequestHelper(); + connect(tcpingModel, &QvTCPingModel::PingFinished, this, &MainWindow::onPingFinished); + // this->setWindowIcon(QIcon(":/icons/qv2ray.png")); hTray->setIcon(QIcon(currentConfig.uiConfig.useDarkTrayIcon ? ":/icons/ui_dark/tray.png" : ":/icons/ui_light/tray.png")); importConfigButton->setIcon(QICON_R("import.png")); @@ -154,8 +158,6 @@ MainWindow::MainWindow(QWidget *parent): listMenu->addAction(action_RCM_ShareQR); // ReloadConnections(); - connect(&HTTPRequestHelper, &QvHttpRequestHelper::httpRequestFinished, this, &MainWindow::VersionUpdate); - HTTPRequestHelper.get("https://api.github.com/repos/lhy0403/Qv2ray/releases/latest"); // // For charts uploadSerie = new QSplineSeries(this); @@ -221,6 +223,8 @@ MainWindow::MainWindow(QWidget *parent): this->show(); } + connect(requestHelper, &QvHttpRequestHelper::httpRequestFinished, this, &MainWindow::VersionUpdate); + requestHelper->get("https://api.github.com/repos/lhy0403/Qv2ray/releases/latest"); StartProcessingPlugins(); } @@ -229,6 +233,7 @@ void MainWindow::SetEditWidgetEnable(bool enabled) removeConfigButton->setEnabled(enabled); editConfigButton->setEnabled(enabled); duplicateBtn->setEnabled(enabled); + pingTestBtn->setEnabled(enabled); editJsonBtn->setEnabled(enabled); shareBtn->setEnabled(enabled); } @@ -320,6 +325,7 @@ void MainWindow::ReloadConnections() _o.subscriptionName = ""; _o.connectionName = _regularConnections.keys()[i]; _o.config = _regularConnections.values()[i]; + _o.latency = 0; connections[_o.connectionName] = _o; connectionListWidget->addTopLevelItem(new QTreeWidgetItem(QStringList() << _o.connectionName)); } @@ -337,6 +343,7 @@ void MainWindow::ReloadConnections() _o.subscriptionName = subName; _o.connectionName = _subsConnections.values()[i].keys()[j]; _o.config = _subsConnections.values()[i].values()[j]; + _o.latency = 0; auto connName = _o.connectionName + " (" + tr("Subscription:") + " " + _o.subscriptionName + ")"; connections[connName] = _o; subTopLevel->addChild(new QTreeWidgetItem(QStringList() << connName)); @@ -418,10 +425,13 @@ void MainWindow::on_startButton_clicked() bool startFlag = this->vinstance->StartConnection(CurrentFullConfig, currentConfig.connectionConfig.enableStats, currentConfig.connectionConfig.statsPort); if (startFlag) { + on_pingTestBtn_clicked(); + if (currentConfig.connectionConfig.enableStats) { speedTimerId = startTimer(1000); } + pingTimerId = startTimer(60000); this->hTray->showMessage("Qv2ray", tr("Connected To Server: ") + CurrentConnectionName, this->windowIcon()); hTray->setToolTip(TRAY_TOOLTIP_PREFIX NEWLINE + tr("Connected To Server: ") + CurrentConnectionName); statusLabel->setText(tr("Connected") + ": " + CurrentConnectionName); @@ -525,6 +535,7 @@ void MainWindow::on_stopButton_clicked() // Is running or starting this->vinstance->StopConnection(); killTimer(speedTimerId); + killTimer(pingTimerId); hTray->setToolTip(TRAY_TOOLTIP_PREFIX); QFile(QV2RAY_GENERATED_FILE_PATH).remove(); statusLabel->setText(tr("Disconnected")); @@ -631,6 +642,12 @@ void MainWindow::ShowAndSetConnection(QString guiConnectionName, bool SetConnect auto isComplexConfig = CheckIsComplexConfig(root); routeCountLabel->setText(isComplexConfig ? tr("Complex") : tr("Simple")); + if (conf.latency == 0.0) { + latencyLabel->setText(tr("No data yet")); + } else { + latencyLabel->setText(QString::number(conf.latency) + " " + tr("ms")); + } + if (conf.configType == CON_SUBSCRIPTION) { routeCountLabel->setText(routeCountLabel->text().append(" (" + tr("From subscription") + ":" + conf.subscriptionName + ")")); } @@ -962,6 +979,13 @@ void MainWindow::on_editJsonBtn_clicked() void MainWindow::on_pingTestBtn_clicked() { // Ping + if (!IsSelectionConnectable) { + return; + } + + // We get data from UI? + auto alias = connectionListWidget->currentItem()->text(0); + tcpingModel->StartPing(alias, _hostLabel->text(), stoi(_portLabel->text().isEmpty() ? "0" : _portLabel->text().toStdString())); } void MainWindow::on_shareBtn_clicked() { @@ -1038,6 +1062,8 @@ void MainWindow::timerEvent(QTimerEvent *event) if (!lastLog.isEmpty()) { qvAppLogBrowser->append(lastLog); } + } else if (event->timerId() == pingTimerId) { + on_pingTestBtn_clicked(); } } void MainWindow::on_duplicateBtn_clicked() @@ -1065,11 +1091,6 @@ void MainWindow::on_duplicateBtn_clicked() this->OnConfigListChanged(false); } -void MainWindow::on_masterLogBrowser_textChanged() -{ - //setMasterLogHBar(); -} - void MainWindow::on_subsButton_clicked() { SubscribeEditor w; @@ -1088,3 +1109,16 @@ void MainWindow::on_connectionListWidget_itemSelectionChanged() _portLabel->setText(tr("N/A")); } } + +void MainWindow::onPingFinished(QvTCPingData data) +{ + if (!connections.contains(data.connectionName)) { + return; + } + + connections[data.connectionName].latency = data.avg; + + if (data.connectionName == CurrentConnectionName) { + ShowAndSetConnection(CurrentConnectionName, false, false); + } +} diff --git a/src/ui/w_MainWindow.hpp b/src/ui/w_MainWindow.hpp index 43458008..54f35f73 100644 --- a/src/ui/w_MainWindow.hpp +++ b/src/ui/w_MainWindow.hpp @@ -6,14 +6,15 @@ #include #include +#include "ui_w_MainWindow.h" + #include "QvUtils.hpp" #include "QvCoreInteractions.hpp" #include "QvCoreConfigOperations.hpp" #include "QvHTTPRequestHelper.hpp" #include "QvPACHandler.hpp" #include "QvLogHighlighter.hpp" - -#include "ui_w_MainWindow.h" +#include "QvTCPing.hpp" enum TREENODEOBJECT_TYPE { CON_REGULAR = 1, @@ -24,6 +25,7 @@ struct ConnectionObject { TREENODEOBJECT_TYPE configType; QString subscriptionName; QString connectionName; + double latency; CONFIGROOT config; }; @@ -38,6 +40,7 @@ class MainWindow : public QMainWindow, Ui::MainWindow void DisConnect() const; void ReConnect() const; public slots: + void onPingFinished(QvTCPingData data); void UpdateVCoreLog(const QString &log); void OnConfigListChanged(bool need_restart); private slots: @@ -80,8 +83,6 @@ class MainWindow : public QMainWindow, Ui::MainWindow void on_duplicateBtn_clicked(); - void on_masterLogBrowser_textChanged(); - void on_subsButton_clicked(); public: @@ -101,7 +102,6 @@ class MainWindow : public QMainWindow, Ui::MainWindow void on_action_RCM_EditJson_triggered(); void on_action_RCM_ConvToComplex_triggered(); void on_action_RCM_RenameConnection_triggered(); - void on_connectionListWidget_itemSelectionChanged(); private: @@ -127,16 +127,19 @@ class MainWindow : public QMainWindow, Ui::MainWindow // int logTimerId; int speedTimerId; + int pingTimerId; // void ShowAndSetConnection(QString currentText, bool SetConnection, bool Apply); void ReloadConnections(); // - QvHttpRequestHelper HTTPRequestHelper; + // + QvHttpRequestHelper *requestHelper; QSystemTrayIcon *hTray; PACServer *pacServer; + QvTCPingModel *tcpingModel; SyntaxHighlighter *vCoreLogHighlighter; SyntaxHighlighter *qvAppLogHighlighter; - + // Qv2rayConfig currentConfig; QList logTextBrowsers; diff --git a/src/ui/w_MainWindow.ui b/src/ui/w_MainWindow.ui index 5a578129..b5e43f7c 100644 --- a/src/ui/w_MainWindow.ui +++ b/src/ui/w_MainWindow.ui @@ -334,6 +334,20 @@ + + + + Latency + + + + + + + + + + @@ -377,7 +391,7 @@ - false + true Ping Test