diff --git a/.gitmodules b/.gitmodules index 98496f5f..745ae70c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "3rdparty/jsoncons"] path = 3rdparty/jsoncons url = https://github.com/danielaparker/jsoncons +[submodule "3rdparty/x2struct"] + path = 3rdparty/x2struct + url = git@github.com:xyz347/x2struct.git diff --git a/3rdparty/x2struct b/3rdparty/x2struct new file mode 160000 index 00000000..084c3cd1 --- /dev/null +++ b/3rdparty/x2struct @@ -0,0 +1 @@ +Subproject commit 084c3cd183ae2450473befa53e987a0ed347a6ff diff --git a/Hv2ray.pro b/Hv2ray.pro index fd6376f8..1d110756 100644 --- a/Hv2ray.pro +++ b/Hv2ray.pro @@ -25,7 +25,7 @@ DEFINES += QT_DEPRECATED_WARNINGS CONFIG += c++11 SOURCES += \ - src/Hutils.cpp \ + src/HUtils.cpp \ src/w_MainWindow.cpp \ src/w_ConnectionEditWindow.cpp \ src/w_ImportConfig.cpp \ @@ -35,14 +35,15 @@ SOURCES += \ src/runguard.cpp HEADERS += \ - src/HUtils.h \ - src/Hv2ConfigObject.h \ + src/HConfigObjects.hpp \ + src/HUtils.hpp \ + src/V2ConfigObjects.hpp \ + src/runguard.hpp \ + src/vinteract.hpp \ src/w_MainWindow.h \ src/w_ConnectionEditWindow.h \ src/w_ImportConfig.h \ - src/w_PrefrencesWindow.h \ - src/vinteract.h \ - src/runguard.h + src/w_PrefrencesWindow.h FORMS += \ src/w_MainWindow.ui \ diff --git a/src/HConfigObjects.hpp b/src/HConfigObjects.hpp new file mode 100644 index 00000000..e0e53a5d --- /dev/null +++ b/src/HConfigObjects.hpp @@ -0,0 +1,76 @@ +#ifndef HCONFIGOBJECTS_HPP +#define HCONFIGOBJECTS_HPP +#include +#include + +#include "V2ConfigObjects.hpp" +#include "vinteract.hpp" + +// Macros +#define HV2RAY_CONFIG_DIR_NAME "/.hv2ray/" +using namespace std; +namespace Hv2ray +{ + namespace HConfigModels + { + struct HInbondSetting { + bool enabled; + string ip; + int port; + bool useAuthentication; + string authUsername; + string authPassword; + HInbondSetting(): enabled(), ip(), port(), useAuthentication(), authUsername(), authPassword() {} + HInbondSetting(bool _e, string _ip, int _p): HInbondSetting() + { + enabled = _e; + port = _p; + ip = _ip; + } +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(enabled, ip, port, useAuthentication, authUsername, authPassword)) +#endif + }; + + struct HvConfigList { + string alias; + string fileName; + int index; + HvConfigList(): alias(), fileName(), index() {} + XTOSTRUCT(O(alias, fileName, index)) + }; + + struct Hv2Config { + string language; + bool runAsRoot; + string logLevel; + //Hv2ray::V2ConfigModels::MuxObject muxSetting; + HInbondSetting httpSetting; + HInbondSetting socksSetting; + list configs; + Hv2Config(): language(), runAsRoot(), logLevel(), httpSetting(), socksSetting(), configs() { } + Hv2Config(string lang, string log, HInbondSetting httpIn, HInbondSetting socksIN): Hv2Config() + { + language = lang; + logLevel = log; + httpSetting = httpIn; + socksSetting = socksIN; + runAsRoot = false; + } +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(language, runAsRoot, logLevel, httpSetting, socksSetting, configs)) +#endif + }; + } + + /// ConfigGlobalConfig is platform-independent as it's solved to be in the best + /// place at first in main.cpp + static QDir ConfigDir; +} + + +#if USE_TODO_FEATURES +JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::HConfigModels::Hv2Config, language, runAsRoot, logLevel, httpSetting, socksSetting) +JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::HConfigModels::HInbondSetting, enabled, ip, port, useAuthentication, authUsername, authPassword) +#endif +#endif // HCONFIGOBJECTS_HPP diff --git a/src/HUtils.cpp b/src/HUtils.cpp new file mode 100644 index 00000000..c3fa48d7 --- /dev/null +++ b/src/HUtils.cpp @@ -0,0 +1,61 @@ +#include "HUtils.hpp" +#include + +namespace Hv2ray +{ + namespace Utils + { + static HConfigModels::Hv2Config GlobalConfig; + void SetGlobalConfig(HConfigModels::Hv2Config conf) + { + GlobalConfig = conf; + } + + HConfigModels::Hv2Config GetGlobalConfig() + { + return GlobalConfig; + } + + void SaveConfig(QFile *configFile) + { + configFile->open(QFile::WriteOnly); + QString jsonConfig = StructToJSON(GetGlobalConfig()); + QTextStream stream(configFile); + stream << jsonConfig << endl; + stream.flush(); + configFile->close(); + } + + void LoadConfig(QFile *configFile) + { + using namespace Hv2ray::HConfigModels; + configFile->open(QFile::ReadOnly); + QTextStream stream(configFile); + auto str = stream.readAll(); + auto config = StructFromJSON(str.toStdString()); + SetGlobalConfig(config); + configFile->close(); + } + + QStringList getAllFilesList(QDir *dir) + { + return dir->entryList(QStringList() << "*" << "*.*", QDir::Hidden | QDir::Files); + } + QTranslator *getTranslator(string lang) + { + QTranslator *translator = new QTranslator(); + translator->load(QString::fromStdString(lang + ".qm"), ":/translations"); + return translator; + } + bool hasFile(QDir *dir, QString fileName) + { + return getAllFilesList(dir).indexOf(fileName) >= 0; + } + void showWarnMessageBox(QWidget *parent, QString title, QString text) + { + QMessageBox::warning(parent, title, text, QMessageBox::Ok | QMessageBox::Default, 0); + } + } +} + + diff --git a/src/HUtils.h b/src/HUtils.hpp similarity index 51% rename from src/HUtils.h rename to src/HUtils.hpp index f92c8a60..a4e662c8 100644 --- a/src/HUtils.h +++ b/src/HUtils.hpp @@ -1,32 +1,30 @@ +#ifndef UTILS_H +#define UTILS_H #include #include #include #include -#include -#include -#include #include #include #include +#include +#include -#include "Hv2ConfigObject.h" +#include -#ifndef UTILS_H -#define UTILS_H +#include "HConfigObjects.hpp" namespace Hv2ray { namespace Utils { - - QJsonObject switchJsonArrayObject(QJsonObject objest, QString value); - QJsonObject findValueFromJsonArray(QJsonArray arr, QString key, QString val); - QJsonObject loadRootObjFromConf(); - QJsonArray getInbounds(); void showWarnMessageBox(QWidget *parent, QString title, QString text); - void overrideInbounds(QString path); - int getIndexByValue(QJsonArray array, QString key, QString val); - + QTranslator *getTranslator(string lang); + void SetGlobalConfig(HConfigModels::Hv2Config conf); + HConfigModels::Hv2Config GetGlobalConfig(); + void SaveConfig(QFile *configFile); + void LoadConfig(QFile *configFile); + /// Get file list in a Dir QStringList getAllFilesList(QDir *dir); bool hasFile(QDir *dir, QString fileName); @@ -34,14 +32,24 @@ namespace Hv2ray QString StructToJSON(const TYPE &t) { string s; +#if USE_TODO_FEATURES encode_json(t, s, indenting::indent); +#else + s = X::tojson(t, "", 4, ' '); +#endif + cout << s << endl; return QString::fromStdString(s); } template - TYPE StructFromJSON(const std::string &str) + TYPE StructFromJSON(const string &str) { - TYPE v = decode_json(str); + TYPE v; +#if USE_TODO_FEATURES + v = decode_json(str); +#else + X::loadjson(str, v, false); +#endif return v; } } diff --git a/src/Hutils.cpp b/src/Hutils.cpp deleted file mode 100644 index ae138047..00000000 --- a/src/Hutils.cpp +++ /dev/null @@ -1,92 +0,0 @@ -#include "HUtils.h" - -using namespace Hv2ray; - -QJsonObject Utils::switchJsonArrayObject(QJsonObject obj, QString value) -{ - QJsonObject returnObj = obj.value(value).isNull() - ? obj.value(value).toObject() - : obj.value(value).toArray().first().toObject(); - return returnObj; -} - -QJsonObject Utils::findValueFromJsonArray(QJsonArray arr, QString key, QString val) -{ - for (const auto obj : arr) { - if (obj.toObject().value(key).toString() == val) { - return obj.toObject(); - } - } - - return QJsonObject(); -} - -QJsonObject Utils::loadRootObjFromConf() -{ - QFile globalConfigFile("Hv2ray.conf"); - globalConfigFile.open(QIODevice::ReadOnly); - QByteArray conf = globalConfigFile.readAll(); - globalConfigFile.close(); - QJsonDocument v2conf(QJsonDocument::fromJson(conf)); - QJsonObject rootObj = v2conf.object(); - return rootObj; -} - -QJsonArray Utils::getInbounds() -{ - QJsonArray inbounds; - inbounds = loadRootObjFromConf().value("inbounds").toArray(); - return inbounds; -} - -void Utils::showWarnMessageBox(QWidget *parent, QString title, QString text) -{ - QMessageBox::warning(parent, title, text, QMessageBox::Ok | QMessageBox::Default, 0); -} - -void Utils::overrideInbounds(QString path) -{ - QFile confFile(path); - confFile.open(QIODevice::ReadOnly); - QByteArray conf = confFile.readAll(); - confFile.close(); - QJsonDocument v2conf(QJsonDocument::fromJson(conf)); - QJsonObject rootObj = v2conf.object(); - QJsonArray modifiedIn = getInbounds(); - rootObj.remove("inbounds"); - rootObj.remove("inbound"); - rootObj.remove("inboundDetour"); - rootObj.insert("inbounds", QJsonValue(modifiedIn)); - v2conf.setObject(rootObj); - conf = v2conf.toJson(QJsonDocument::Indented); - confFile.open(QIODevice::WriteOnly | QIODevice::Truncate); - confFile.write(conf); - confFile.close(); -} - -int Utils::getIndexByValue(QJsonArray array, QString key, QString val) -{ - QJsonArray::iterator it; - int index = 0; - - for (it = array.begin(); it != array.end(); it++) { - if (it->toObject().value(key) == val) { - return index; - } - - index++; - } - - return -1; -} - -/// Get file list in a Dir -QStringList Utils::getAllFilesList(QDir *dir) -{ - return dir->entryList(QStringList() << "*" << "*.*", QDir::Hidden | QDir::Files); -} - -bool Utils::hasFile(QDir *dir, QString fileName) -{ - return getAllFilesList(dir).indexOf(fileName) >= 0; -} diff --git a/src/Hv2ConfigObject.h b/src/Hv2ConfigObject.h deleted file mode 100644 index 3e53dba7..00000000 --- a/src/Hv2ConfigObject.h +++ /dev/null @@ -1,392 +0,0 @@ -#include -#include -#include -#include -#include - -#define USE_JSON_CONS -#ifdef USE_JSON_CONS -#include -#else -#include -using namespace x2struct; -#endif -#ifndef V2CONFIG_H -#define V2CONFIG_H - -// Macros -#define HV2RAY_CONFIG_DIR_NAME "/.hv2ray" - -using namespace std; -using namespace jsoncons; // for convenience -/*------------------------------------------------------------------------------------------------------------*/ - -namespace Hv2ray -{ - namespace V2ConfigModels - { - - struct LogObject { - string access; - string error; - string loglevel; - LogObject(): access(), error(), loglevel() {} - //XTOSTRUCT(O(access, error, loglevel)) - }; - - struct ApiObject { - string tag; - list services; - ApiObject() : tag(), services() {} - //XTOSTRUCT(O(tag, services)) - }; - - struct ServerObject { - string address; - int port; - list domains; - ServerObject(): address(), port(), domains() {} - //XTOSTRUCT(O(address, port, domains)) - }; - - struct DnsObject { - map hosts; - tuple> servers; - DnsObject(): hosts(), servers() {} - //XTOSTRUCT(O(hosts, servers)) - }; - - struct RuleObject { - string type = "field"; - list domain; - list ip; - string port; - string network; - list source; - list user; - string inboundTag; - string protocol; - string attrs; - RuleObject() : type(), domain(), ip(), port(), network(), source(), user(), inboundTag(), protocol(), attrs() {} - //XTOSTRUCT(O(type, domain, ip, port, network, source, user, inboundTag, protocol, attrs)) - }; - struct BalancerObject { - string tag ; - list selector; - BalancerObject() : tag(), selector() {} - //XTOSTRUCT(O(tag, selector)) - }; - - struct RoutingObject { - string domainStrategy; - list rules; - list balancers; - RoutingObject() : domainStrategy(), rules(), balancers() {} - //XTOSTRUCT(O(domainStrategy, rules, balancers)) - }; - - struct SystemPolicyObject { - bool statsInboundUplink; - bool statsInboundDownlink; - SystemPolicyObject() : statsInboundUplink(), statsInboundDownlink() {} - //XTOSTRUCT(O(statsInboundUplink, statsInboundDownlink)) - }; - - struct LevelPolicyObject { - int handshake; - int connIdle; - int uplinkOnly; - int downlinkOnly; - bool statsUserUplink; - bool statsUserDownlink; - int bufferSize; - LevelPolicyObject(): handshake(), connIdle(), uplinkOnly(), downlinkOnly(), statsUserUplink(), statsUserDownlink(), bufferSize() {} - //XTOSTRUCT(O(handshake, connIdle, uplinkOnly, downlinkOnly, statsUserUplink, statsUserDownlink, bufferSize)) - }; - struct PolicyObject { - map level; - list system; - PolicyObject(): level(), system() {} - //XTOSTRUCT(O(level, system)) - }; - - struct HTTPRequestObject { - string version; - string method; - list path; - map> headers; - HTTPRequestObject(): version(), method(), path(), headers() {} - //XTOSTRUCT(O(version, method, path, headers)) - }; - - struct HTTPResponseObject { - string version; - string status; - string reason; - map> headers; - HTTPResponseObject(): version(), status(), reason(), headers() {} - //XTOSTRUCT(O(version, status, reason, headers)) - }; - - struct TCPHeader_M_Object { - string type; - HTTPRequestObject request; - HTTPResponseObject response; - TCPHeader_M_Object(): type(), request(), response() {} - //XTOSTRUCT(O(type, request, response)) - }; - - struct TCPObject { - TCPHeader_M_Object header; - TCPObject(): header() {} - //XTOSTRUCT(O(header)) - }; - - struct HeaderObject { - string type; - HeaderObject(): type() {} - //XTOSTRUCT(O(type)) - }; - - struct KCPObject { - int mtu; - int tti; - int uplinkCapacity; - int downlinkCapacity; - bool congestion; - int readBufferSize; - int writeBufferSize; - HeaderObject header; - KCPObject(): mtu(), tti(), uplinkCapacity(), downlinkCapacity(), congestion(), readBufferSize(), writeBufferSize(), header() {} - //XTOSTRUCT(O(mtu, tti, uplinkCapacity, downlinkCapacity, congestion, readBufferSize, writeBufferSize, header)) - }; - - - struct WebSocketObject { - string path; - map headers; - WebSocketObject(): path(), headers() {} - //XTOSTRUCT(O(path, headers)) - }; - - struct HttpObject { - list host; - string path; - HttpObject() : host(), path() {} - //XTOSTRUCT(O(host, path)) - }; - - struct DomainSocketObject { - string path; - DomainSocketObject(): path() {} - //XTOSTRUCT(O(path)) - }; - - struct QuicObject { - string security; - string key; - HeaderObject header; - QuicObject(): security(), key(), header() {} - //XTOSTRUCT(O(security, key, header)) - }; - - struct TransportObject { - TCPObject tcpSettings; - KCPObject kcpSettings; - WebSocketObject wsSettings; - HttpObject httpSettings; - DomainSocketObject dsSettings; - QuicObject quicSettings; - TransportObject(): tcpSettings(), kcpSettings(), wsSettings(), httpSettings(), dsSettings(), quicSettings() {} - //XTOSTRUCT(O(tcpSettings, kcpSettings, wsSettings, httpSettings, dsSettings, quicSettings)) - }; - - struct SniffingObject { - bool enabled; - string destOverride; - SniffingObject(): enabled(), destOverride() {} - //XTOSTRUCT(O(enabled, destOverride)) - }; - - struct AllocateObject { - string strategy; - int refresh; - int concurrency; - AllocateObject(): strategy(), refresh(), concurrency() {} - //XTOSTRUCT(O(strategy, refresh, concurrency)) - }; - - struct InboundObject { - int port; - string listen; - string protocol; - string settings; - TransportObject streamSettings; - string tag; - SniffingObject sniffing; - AllocateObject allocate; - InboundObject(): port(), listen(), protocol(), settings(), streamSettings(), tag(), sniffing(), allocate() {} - //XTOSTRUCT(O(port, listen, protocol, settings, streamSettings, tag, sniffing, allocate)) - }; - - struct ProxySettingsObject { - string tag; - ProxySettingsObject(): tag() {} - //XTOSTRUCT(O(tag)) - }; - - struct MuxObject { - bool enabled; - int concurrency; - MuxObject(): enabled(), concurrency() {} - //XTOSTRUCT(O(enabled, concurrency)) - }; - - struct OutboundObject { - string sendThrough; - string protocol; - string settings; - string tag; - TransportObject streamSettings; - ProxySettingsObject proxySettings; - MuxObject mux; - OutboundObject(): sendThrough(), protocol(), settings(), tag(), streamSettings(), proxySettings(), mux() {} - //XTOSTRUCT(O(sendThrough, protocol, settings, tag, streamSettings, proxySettings, mux)) - }; - - struct StatsObject { - bool _; // Placeholder... - StatsObject(): _() {} - }; - - struct BridgeObject { - string tag; - string domain; - BridgeObject() : tag(), domain() {} - //XTOSTRUCT(O(tag, domain)) - }; - - struct PortalObject { - string tag; - string domain; - PortalObject() : tag(), domain() {} - //XTOSTRUCT(O(tag, domain)) - }; - - struct ReverseObject { - list bridges; - list portals; - ReverseObject() : bridges(), portals() {} - //XTOSTRUCT(O(bridges, portals)) - }; - struct RootObject { - LogObject log; - ApiObject api; - DnsObject dns; - RoutingObject routing; - list inbounds; - list outbounds; - TransportObject transport; - StatsObject stats; - ReverseObject reverse; - RootObject(): log(), api(), dns(), routing(), inbounds(), outbounds(), transport(), stats(), reverse() {} - //XTOSTRUCT(O(log, api, dns, routing, inbounds, outbounds, transport, stats, reverse)) - }; - } -} -JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::LogObject, access, error, loglevel) -JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::ApiObject, tag, services) -JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::ServerObject, address, port, domains) -JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::DnsObject, hosts, servers) -JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::RuleObject, type, domain, ip, port, network, source, user, inboundTag, protocol, attrs) -JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::BalancerObject, tag, selector) -JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::RoutingObject, domainStrategy, rules, balancers) -JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::SystemPolicyObject, statsInboundUplink, statsInboundDownlink) -JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::LevelPolicyObject, handshake, connIdle, uplinkOnly, downlinkOnly, statsUserUplink, statsUserDownlink, bufferSize) -JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::PolicyObject, level, system) -JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::HTTPRequestObject, version, method, path, headers) -JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::HTTPResponseObject, version, status, reason, headers) -JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::TCPHeader_M_Object, type, request, response) -JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::TCPObject, header) -JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::HeaderObject, type) -JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::KCPObject, mtu, tti, uplinkCapacity, downlinkCapacity, congestion, readBufferSize, writeBufferSize, header) -JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::WebSocketObject, path, headers) -JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::HttpObject, host, path) -JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::DomainSocketObject, path) -JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::QuicObject, security, key, header) -JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::TransportObject, tcpSettings, kcpSettings, wsSettings, httpSettings, dsSettings, quicSettings) -JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::SniffingObject, enabled, destOverride) -JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::AllocateObject, strategy, refresh, concurrency) -JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::InboundObject, port, listen, protocol, settings, streamSettings, tag, sniffing, allocate) -JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::ProxySettingsObject, tag) -JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::MuxObject, enabled, concurrency) -JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::OutboundObject, sendThrough, protocol, settings, tag, streamSettings, proxySettings, mux) -JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::StatsObject, _) -JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::BridgeObject, tag, domain) -JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::PortalObject, tag, domain) -JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::ReverseObject, bridges, portals) -JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::RootObject, log, api, dns, routing, inbounds, outbounds, transport, stats, reverse) - - -namespace Hv2ray -{ - namespace HConfigModels - { - struct HInbondSetting { - bool enabled; - string ip; - int port; - bool useAuthentication; - string authUsername; - string authPassword; - HInbondSetting() {} - HInbondSetting(bool _enabled, string _ip, int _port) - : ip(_ip), authUsername(""), authPassword("") - { - enabled = _enabled; - port = _port; - useAuthentication = false; - } - HInbondSetting(bool _enabled, string _ip, int _port, string _username, string _password) - : ip(_ip), authUsername(_username), authPassword(_password) - { - enabled = _enabled; - port = _port; - useAuthentication = true; - } - //XTOSTRUCT(O(enabled, ip, port, useAuthentication, authUsername, authPassword)) - }; - - struct Hv2Config { - string language; - bool runAsRoot; - string logLevel; - //Hv2ray::V2ConfigModels::MuxObject muxSetting; - HInbondSetting httpSetting; - HInbondSetting socksSetting; - Hv2Config() {} - Hv2Config(string lang, const bool _runAsRoot, const string _loglevel, HInbondSetting _http, HInbondSetting _socks) - : httpSetting(_http), - socksSetting(_socks) - - { - language = lang; - runAsRoot = _runAsRoot; - logLevel = _loglevel; - } - //XTOSTRUCT(O(language, runAsRoot, logLevel, httpSetting, socksSetting)) - }; - } -} -JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::HConfigModels::Hv2Config, language, runAsRoot, logLevel, httpSetting, socksSetting) -JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::HConfigModels::HInbondSetting, enabled, ip, port, useAuthentication, authUsername, authPassword) - -namespace Hv2ray -{ - /// ConfigGlobalConfigthis is platform-independent as it's solved to be in the best - /// place at first in main.cpp - static QDir ConfigDir; - static HConfigModels::Hv2Config GlobalConfig; -} -#endif // V2CONFIG_H - diff --git a/src/V2ConfigObjects.hpp b/src/V2ConfigObjects.hpp new file mode 100644 index 00000000..9765fb76 --- /dev/null +++ b/src/V2ConfigObjects.hpp @@ -0,0 +1,638 @@ +#include +#include + +// TODO Features +#define USE_TODO_FEATURES false + +#if USE_TODO_FEATURES +#include +using namespace jsoncons; +#else +#include +using namespace x2struct; +#endif + +#ifndef V2CONFIG_H +#define V2CONFIG_H + +using namespace std; +/*------------------------------------------------------------------------------------------------------------*/ + +namespace Hv2ray +{ + namespace V2ConfigModels + { + // Two struct defining TYPE parameter to be passed into inbound configs and outbound configs. + struct XOutBoundsType { + }; + struct XInBoundsType { + }; + + struct LogObject { + string access; + string error; + string loglevel; + LogObject(): access(), error(), loglevel() {} +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(access, error, loglevel)) +#endif + }; + + struct ApiObject { + string tag; + list services; + ApiObject() : tag(), services() {} +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(tag, services)) +#endif + }; + namespace DNSObjects + { + struct ServerObject { + string address; + int port; + list domains; + ServerObject(): address(), port(), domains() {} +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(address, port, domains)) +#endif + }; + } + struct DnsObject { + map hosts; +#if USE_TODO_FEATURES + tuple> servers; +#else + // Currently does not support ServerObject as tuple is.... quite complicated... + list servers; +#endif + DnsObject(): hosts(), servers() {} +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(hosts, servers)) +#endif + }; + namespace ROUTINGObjects + { + struct RuleObject { + string type = "field"; + list domain; + list ip; + string port; + string network; + list source; + list user; + string inboundTag; + string protocol; + string attrs; + RuleObject() : type(), domain(), ip(), port(), network(), source(), user(), inboundTag(), protocol(), attrs() {} +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(type, domain, ip, port, network, source, user, inboundTag, protocol, attrs)) +#endif + }; + struct BalancerObject { + string tag ; + list selector; + BalancerObject() : tag(), selector() {} +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(tag, selector)) +#endif + }; + } + + struct RoutingObject { + string domainStrategy; + list rules; + list balancers; + RoutingObject() : domainStrategy(), rules(), balancers() {} +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(domainStrategy, rules, balancers)) +#endif + }; + namespace POLICYObjects + { + struct SystemPolicyObject { + bool statsInboundUplink; + bool statsInboundDownlink; + SystemPolicyObject() : statsInboundUplink(), statsInboundDownlink() {} +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(statsInboundUplink, statsInboundDownlink)) +#endif + }; + + struct LevelPolicyObject { + int handshake; + int connIdle; + int uplinkOnly; + int downlinkOnly; + bool statsUserUplink; + bool statsUserDownlink; + int bufferSize; + LevelPolicyObject(): handshake(), connIdle(), uplinkOnly(), downlinkOnly(), statsUserUplink(), statsUserDownlink(), bufferSize() {} +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(handshake, connIdle, uplinkOnly, downlinkOnly, statsUserUplink, statsUserDownlink, bufferSize)) +#endif + }; + } + struct PolicyObject { + map level; + list system; + PolicyObject(): level(), system() {} +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(level, system)) +#endif + }; + namespace TRANSFERObjects + { + namespace TRANSFERObjectsInternal + { + + struct HTTPRequestObject { + string version; + string method; + list path; + map> headers; + HTTPRequestObject(): version(), method(), path(), headers() {} +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(version, method, path, headers)) +#endif + }; + + struct HTTPResponseObject { + string version; + string status; + string reason; + map> headers; + HTTPResponseObject(): version(), status(), reason(), headers() {} +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(version, status, reason, headers)) +#endif + }; + struct TCPHeader_M_Object { + string type; + HTTPRequestObject request; + HTTPResponseObject response; + TCPHeader_M_Object(): type(), request(), response() {} +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(type, request, response)) +#endif + }; + struct HeaderObject { + string type; + HeaderObject(): type() {} +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(type)) +#endif + }; + } + + + struct TCPObject { + TRANSFERObjectsInternal:: TCPHeader_M_Object header; + TCPObject(): header() {} +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(header)) +#endif + }; + + + struct KCPObject { + int mtu; + int tti; + int uplinkCapacity; + int downlinkCapacity; + bool congestion; + int readBufferSize; + int writeBufferSize; + TRANSFERObjectsInternal:: HeaderObject header; + KCPObject(): mtu(), tti(), uplinkCapacity(), downlinkCapacity(), congestion(), readBufferSize(), writeBufferSize(), header() {} +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(mtu, tti, uplinkCapacity, downlinkCapacity, congestion, readBufferSize, writeBufferSize, header)) +#endif + }; + + + struct WebSocketObject { + string path; + map headers; + WebSocketObject(): path(), headers() {} +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(path, headers)) +#endif + }; + + struct HttpObject { + list host; + string path; + HttpObject() : host(), path() {} +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(host, path)) +#endif + }; + + struct DomainSocketObject { + string path; + DomainSocketObject(): path() {} +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(path)) +#endif + }; + + struct QuicObject { + string security; + string key; + TRANSFERObjectsInternal::HeaderObject header; + QuicObject(): security(), key(), header() {} +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(security, key, header)) +#endif + }; + + + } + struct TransportObject { + TRANSFERObjects::TCPObject tcpSettings; + TRANSFERObjects::KCPObject kcpSettings; + TRANSFERObjects::WebSocketObject wsSettings; + TRANSFERObjects::HttpObject httpSettings; + TRANSFERObjects::DomainSocketObject dsSettings; + TRANSFERObjects::QuicObject quicSettings; + TransportObject(): tcpSettings(), kcpSettings(), wsSettings(), httpSettings(), dsSettings(), quicSettings() {} +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(tcpSettings, kcpSettings, wsSettings, httpSettings, dsSettings, quicSettings)) +#endif + }; + namespace INBOUNDObjects + { + + struct SniffingObject { + bool enabled; + string destOverride; + SniffingObject(): enabled(), destOverride() {} +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(enabled, destOverride)) +#endif + }; + + struct AllocateObject { + string strategy; + int refresh; + int concurrency; + AllocateObject(): strategy(), refresh(), concurrency() {} +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(strategy, refresh, concurrency)) +#endif + }; + } + namespace STREAMSETTINGSObjects + { + struct SockoptObject { + int mark; + bool tcpFastOpen; + string tproxy; + SockoptObject(): mark(), tcpFastOpen(), tproxy() {} +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(mark, tcpFastOpen, tproxy)) +#endif + }; + + struct CertificateObject { + string usage; + string certificateFile; + string keyFile; + list certificate; + list key; + CertificateObject(): usage(), certificateFile(), keyFile(), certificate(), key() {} +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(usage, certificateFile, keyFile, certificate, key)) +#endif + }; + + struct TLSObject { + string serverName; + bool allowInsecure; + list alpn; + list certificates; + bool disableSystemRoot; + TLSObject(): serverName(), allowInsecure(), certificates(), disableSystemRoot() {} +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(serverName, allowInsecure, alpn, certificates, disableSystemRoot)) +#endif + }; + } + + struct StreamSettingsObject { + string network; + string security; + STREAMSETTINGSObjects::SockoptObject sockopt; + STREAMSETTINGSObjects::TLSObject tlsSettings; + TRANSFERObjects::TCPObject tcpSettings; + TRANSFERObjects::KCPObject kcpSettings; + TRANSFERObjects::WebSocketObject wsSettings; + TRANSFERObjects::HttpObject httpSettings; + TRANSFERObjects::DomainSocketObject dsSettings; + TRANSFERObjects::QuicObject quicSettings; + StreamSettingsObject(): network(), security(), sockopt(), tlsSettings(), tcpSettings(), kcpSettings(), wsSettings(), httpSettings(), dsSettings(), quicSettings() {} +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(network, security, sockopt, tcpSettings, tlsSettings, kcpSettings, wsSettings, httpSettings, dsSettings, quicSettings)) +#endif + }; + + template + struct InboundObject { + static_assert(std::is_base_of::value, "XINBOUNDSETTINGOBJECT must extend XInBoundsType"); + int port; + string listen; + string protocol; + XINBOUNDSETTINGOBJECT settings; + StreamSettingsObject streamSettings; + string tag; + INBOUNDObjects::SniffingObject sniffing; + INBOUNDObjects::AllocateObject allocate; + InboundObject(): port(), listen(), protocol(), settings(), streamSettings(), tag(), sniffing(), allocate() {} +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(port, listen, protocol, settings, streamSettings, tag, sniffing, allocate)) +#endif + }; + namespace OUTBOUNDObjects + { + + struct ProxySettingsObject { + string tag; + ProxySettingsObject(): tag() {} +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(tag)) +#endif + }; + + struct MuxObject { + bool enabled; + int concurrency; + MuxObject(): enabled(), concurrency() {} +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(enabled, concurrency)) +#endif + }; + } + template + struct OutboundObject { + static_assert(std::is_base_of::value, "XOUTBOUNDSETTINGOBJECT must extend XOutBoundsType"); + string sendThrough; + string protocol; + XOUTBOUNDSETTINGOBJECT settings; + string tag; + StreamSettingsObject streamSettings; + OUTBOUNDObjects::ProxySettingsObject proxySettings; + OUTBOUNDObjects::MuxObject mux; + OutboundObject(): sendThrough(), protocol(), settings(), tag(), streamSettings(), proxySettings(), mux() {} +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(sendThrough, protocol, settings, tag, streamSettings, proxySettings, mux)) +#endif + }; + + struct StatsObject { + bool _; // Placeholder... + StatsObject(): _() {} +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(_)) +#endif + }; + namespace REVERSEObjects + { + + struct BridgeObject { + string tag; + string domain; + BridgeObject() : tag(), domain() {} +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(tag, domain)) +#endif + }; + + struct PortalObject { + string tag; + string domain; + PortalObject() : tag(), domain() {} +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(tag, domain)) +#endif + }; + + } + struct ReverseObject { + list bridges; + list portals; + ReverseObject() : bridges(), portals() {} +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(bridges, portals)) +#endif + }; +#if USE_TODO_FEATURES + template +#else + template +#endif + struct RootObject { + LogObject log; + ApiObject api; + DnsObject dns; + RoutingObject routing; +#if USE_TODO_FEATURES + // Default support 5 inBounds and 5 outBounds + tuple, InboundObject, InboundObject, InboundObject, InboundObject> inbounds; + tuple, OutboundObject, OutboundObject, OutboundObject, OutboundObject> outbounds; +#else + list> inbounds; + list> outbounds; +#endif + TransportObject transport; + StatsObject stats; + ReverseObject reverse; + PolicyObject policy; + RootObject(): log(), api(), dns(), routing(), inbounds(), outbounds(), transport(), stats(), reverse(), policy() {} +#if USE_TODO_FEATURES == false + XTOSTRUCT(O(log, api, dns, routing, inbounds, outbounds, transport, stats, reverse, policy)) +#endif + }; + } +} + +namespace Hv2ray +{ + namespace V2ConfigModels + { + /// Some protocols from: https://v2ray.com/chapter_02/02_protocols.html + namespace Protocols + { + /// BlackHole Protocol, OutBound + struct BlackHole : XOutBoundsType { + struct ResponseObject { + string type; + }; + ResponseObject response; + }; + + /// DNS, OutBound + struct DNS: XOutBoundsType { + string network; + string address; + int port; + }; + + /// Dokodemo-door, InBound + struct Dokodemo_door : XInBoundsType { + string address; + int port; + string network; + int timeout; + bool followRedirect; + int userLevel; + }; + + /// Freedom, OutBound + struct Freedom: XOutBoundsType { + string domainStrategy; + string redirect; + int userLevel; + }; + + struct AccountObject { + string user; + string pass; + XTOSTRUCT(O(user, pass)) + }; + + /// HTTP, InBound + struct HTTP: XInBoundsType { + int timeout; + list accounts; + bool allowTransparent; + int userLevel; + XTOSTRUCT(O(timeout, accounts, allowTransparent, userLevel)) + }; + + /// MTProto, InBound || OutBound + struct MTProto: XInBoundsType, XOutBoundsType { + struct UserObject { + string email; + int level; + string secret; + }; + list users; + }; + + // We don't add shadowsocks, (As it's quite complex and I'm quite lazy...) + + /// Socks, InBound, OutBound + struct Socks: XInBoundsType, XOutBoundsType { + struct UserObject { + }; + struct ServerObject { + string address; + int port; + list users; + }; + list servers; + string auth; + list accounts; + bool udp; + string ip; + int userLevel; + }; + + struct VMess: XInBoundsType, XOutBoundsType { + struct ServerObject { + struct UserObject { + string id; + int alterId; + string security; + int level; + XTOSTRUCT(O(id, alterId, security, level)) + }; + // OUTBound; + string address; + int port; + list users; + XTOSTRUCT(O(address, port, users)) + }; + list vnext; + // INBound; + struct ClientObject { + string id; + int level; + int alterId; + string email; + XTOSTRUCT(O(id, level, alterId, email)) + }; + list clients; + // detour and default will not be implemented as it's complicated... + bool disableInsecureEncryption; + XTOSTRUCT(O(vnext, clients, disableInsecureEncryption)) + }; + } + } +} + +#if USE_TODO_FEATURES +using namespace Hv2ray; +JSONCONS_MEMBER_TRAITS_DECL(V2ConfigModels::LogObject, access, error, loglevel) +JSONCONS_MEMBER_TRAITS_DECL(V2ConfigModels::ApiObject, tag, services) + +JSONCONS_MEMBER_TRAITS_DECL(V2ConfigModels::DNSObjects::ServerObject, address, port, domains) +JSONCONS_MEMBER_TRAITS_DECL(V2ConfigModels::DnsObject, hosts, servers) + +JSONCONS_MEMBER_TRAITS_DECL(V2ConfigModels::ROUTINGObjects::RuleObject, type, domain, ip, port, network, source, user, inboundTag, protocol, attrs) +JSONCONS_MEMBER_TRAITS_DECL(V2ConfigModels::ROUTINGObjects::BalancerObject, tag, selector) +JSONCONS_MEMBER_TRAITS_DECL(V2ConfigModels::RoutingObject, domainStrategy, rules, balancers) + +JSONCONS_MEMBER_TRAITS_DECL(V2ConfigModels::POLICYObjects::SystemPolicyObject, statsInboundUplink, statsInboundDownlink) +JSONCONS_MEMBER_TRAITS_DECL(V2ConfigModels::POLICYObjects::LevelPolicyObject, handshake, connIdle, uplinkOnly, downlinkOnly, statsUserUplink, statsUserDownlink, bufferSize) +JSONCONS_MEMBER_TRAITS_DECL(V2ConfigModels::PolicyObject, level, system) + +JSONCONS_MEMBER_TRAITS_DECL(V2ConfigModels::TRANSFERObjects::TRANSFERObjectsInternal::HTTPRequestObject, version, method, path, headers) +JSONCONS_MEMBER_TRAITS_DECL(V2ConfigModels::TRANSFERObjects::TRANSFERObjectsInternal::HTTPResponseObject, version, status, reason, headers) +JSONCONS_MEMBER_TRAITS_DECL(V2ConfigModels::TRANSFERObjects::TRANSFERObjectsInternal::TCPHeader_M_Object, type, request, response) +JSONCONS_MEMBER_TRAITS_DECL(V2ConfigModels::TRANSFERObjects::TRANSFERObjectsInternal::HeaderObject, type) + +JSONCONS_MEMBER_TRAITS_DECL(V2ConfigModels::TRANSFERObjects::TCPObject, header) +JSONCONS_MEMBER_TRAITS_DECL(V2ConfigModels::TRANSFERObjects::KCPObject, mtu, tti, uplinkCapacity, downlinkCapacity, congestion, readBufferSize, writeBufferSize, header) +JSONCONS_MEMBER_TRAITS_DECL(V2ConfigModels::TRANSFERObjects::WebSocketObject, path, headers) +JSONCONS_MEMBER_TRAITS_DECL(V2ConfigModels::TRANSFERObjects::HttpObject, host, path) +JSONCONS_MEMBER_TRAITS_DECL(V2ConfigModels::TRANSFERObjects::DomainSocketObject, path) +JSONCONS_MEMBER_TRAITS_DECL(V2ConfigModels::TRANSFERObjects::QuicObject, security, key, header) +JSONCONS_MEMBER_TRAITS_DECL(V2ConfigModels::TransportObject, tcpSettings, kcpSettings, wsSettings, httpSettings, dsSettings, quicSettings) + +JSONCONS_MEMBER_TRAITS_DECL(V2ConfigModels::INBOUNDObjects::SniffingObject, enabled, destOverride) +JSONCONS_MEMBER_TRAITS_DECL(V2ConfigModels::INBOUNDObjects::AllocateObject, strategy, refresh, concurrency) + +JSONCONS_MEMBER_TRAITS_DECL(V2ConfigModels::OUTBOUNDObjects::ProxySettingsObject, tag) +JSONCONS_MEMBER_TRAITS_DECL(V2ConfigModels::OUTBOUNDObjects::MuxObject, enabled, concurrency) + +JSONCONS_MEMBER_TRAITS_DECL(V2ConfigModels::REVERSEObjects::BridgeObject, tag, domain) +JSONCONS_MEMBER_TRAITS_DECL(V2ConfigModels::REVERSEObjects::PortalObject, tag, domain) +JSONCONS_MEMBER_TRAITS_DECL(V2ConfigModels::ReverseObject, bridges, portals) + +JSONCONS_MEMBER_TRAITS_DECL(V2ConfigModels::StatsObject, _) + +JSONCONS_MEMBER_TRAITS_DECL(V2ConfigModels::StreamSettingsObject, tcpSettings, kcpSettings, wsSettings, httpSettings, dsSettings, quicSettings, tlsSettings, sockopt, network, security) +JSONCONS_MEMBER_TRAITS_DECL(V2ConfigModels::STREAMSETTINGSObjects::TLSObject, serverName, allowInsecure, alpn, certificates, disableSystemRoot) +JSONCONS_MEMBER_TRAITS_DECL(V2ConfigModels::STREAMSETTINGSObjects::CertificateObject, usage, certificateFile, keyFile, certificate, key) +JSONCONS_MEMBER_TRAITS_DECL(V2ConfigModels::STREAMSETTINGSObjects::SockoptObject, mark, tcpFastOpen, tproxy) + +// These 3 are used as templates. +JSONCONS_MEMBER_TRAITS_DECL(V2ConfigModels::RootObject, log, api, dns, routing, inbounds, outbounds, transport, stats, reverse, policy) +JSONCONS_MEMBER_TRAITS_DECL(V2ConfigModels::InboundObject, port, listen, protocol, settings, streamSettings, tag, sniffing, allocate) +JSONCONS_MEMBER_TRAITS_DECL(V2ConfigModels::OutboundObject, sendThrough, protocol, settings, tag, streamSettings, proxySettings, mux) + +#endif + +/// Code above has passed these tests. +//using namespace Hv2ray::V2ConfigModels; +//RootObject x; +//InboundObject inH; +//x.inbounds.insert(x.inbounds.end(), inH); +//OutboundObject inV; +//x.outbounds.insert(x.outbounds.end(), inV); +//QString jsonConfig = Utils::StructToJSON(x); +//cout << jsonConfig.toStdString() << endl; +/// +#endif diff --git a/src/main.cpp b/src/main.cpp index 4aa79f0a..82b9d6bf 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,27 +1,22 @@ -#include #include -#include #include -#include -#include #include #include #include -#include -#include "runguard.h" -#include "HUtils.h" -#include "Hv2ConfigObject.h" -#include "w_ConnectionEditWindow.h" +#include "HUtils.hpp" +#include "HConfigObjects.hpp" +#include "runguard.hpp" #include "w_MainWindow.h" using namespace std; using namespace Hv2ray; +using namespace Hv2ray::Utils; using namespace Hv2ray::HConfigModels; -bool firstRunCheck() +bool initializeHv() { - /// Hv2ray Config Path. + /// Hv2ray Config Path and ends with "/" QString configPath = ""; #if defined(__WIN32) || defined(__APPLE__) // For Windows and MacOS, there's no such 'installation' of a software @@ -48,28 +43,22 @@ bool firstRunCheck() } } + QFile configFile(configPath + "hv2ray.conf"); + if (!Utils::hasFile(&ConfigDir, ".initialised")) { // This is first run! // These below genenrated very basic global config. HInbondSetting inHttp = HInbondSetting(true, "127.0.0.1", 8080); HInbondSetting inSocks = HInbondSetting(true, "127.0.0.1", 1080); - GlobalConfig = Hv2Config("zh-CN", false, "info", inHttp, inSocks); - QString jsonConfig = Utils::StructToJSON(GlobalConfig); - QFile configFile(configPath + "/hv2ray.conf"); - - if (!configFile.open(QIODevice::WriteOnly)) { - qDebug() << "Failed to create main config file."; - return false; - } - - QTextStream stream(&configFile); - stream << jsonConfig; - stream.flush(); - configFile.close(); + Hv2Config conf = Hv2Config("zh-CN", "info", inHttp, inSocks); + SetGlobalConfig(conf); + SaveConfig(&configFile); // Create Placeholder for initialise indicator. - QFile initPlaceHolder(configPath + "/.initialised"); + QFile initPlaceHolder(configPath + ".initialised"); initPlaceHolder.open(QFile::WriteOnly); initPlaceHolder.close(); + } else { + LoadConfig(&configFile); } return true; @@ -78,21 +67,6 @@ bool firstRunCheck() int main(int argc, char *argv[]) { QApplication _qApp(argc, argv); - QTranslator translator; - - // - if (translator.load(":/translations/zh-CN.qm", "translations")) { - cout << "Loaded zh-CN translations" << endl; - } else if (translator.load(":/translations/en-US.qm", "translations")) { - cout << "Loaded en-US translations" << endl; - } else { - Utils::showWarnMessageBox( - nullptr, "Failed to load translations 无法加载语言文件", - "Failed to load translations, user experience may be downgraded. \r\n" - "无法加载语言文件,用户体验可能会降级."); - } - - _qApp.installTranslator(&translator); RunGuard guard("Hv2ray-Instance-Identifier"); if (!guard.isSingleInstance()) { @@ -100,11 +74,23 @@ int main(int argc, char *argv[]) return -1; } - // GlobalConfig = StructFromJSON(""); // Set file startup path as Path // WARNING: This may be changed in the future. QDir::setCurrent(QFileInfo(QCoreApplication::applicationFilePath()).path()); - firstRunCheck(); + // Hv2ray Initialize + initializeHv(); + + if (_qApp.installTranslator(getTranslator(GetGlobalConfig().language))) { + cout << "Loaded translations " << GetGlobalConfig().language << endl; + } else if (_qApp.installTranslator(getTranslator("en-US"))) { + cout << "Loaded default translations" << endl; + } else { + showWarnMessageBox( + nullptr, "Failed to load translations 无法加载语言文件", + "Failed to load translations, user experience may be downgraded. \r\n" + "无法加载语言文件,用户体验可能会降级."); + } + // Show MainWindow Ui::MainWindow w; w.show(); diff --git a/src/runguard.cpp b/src/runguard.cpp index 08499903..d8456e04 100644 --- a/src/runguard.cpp +++ b/src/runguard.cpp @@ -1,6 +1,6 @@ #include -#include "runguard.h" +#include "runguard.hpp" namespace Hv2ray { diff --git a/src/runguard.h b/src/runguard.hpp similarity index 100% rename from src/runguard.h rename to src/runguard.hpp diff --git a/src/vinteract.cpp b/src/vinteract.cpp index c6b0bd61..1d53e4a8 100644 --- a/src/vinteract.cpp +++ b/src/vinteract.cpp @@ -2,8 +2,8 @@ #include #include -#include "HUtils.h" -#include "vinteract.h" +#include "HUtils.hpp" +#include "vinteract.hpp" #include "w_MainWindow.h" namespace Hv2ray diff --git a/src/vinteract.h b/src/vinteract.hpp similarity index 100% rename from src/vinteract.h rename to src/vinteract.hpp diff --git a/src/w_ImportConfig.cpp b/src/w_ImportConfig.cpp index a6354c33..ad73ad1c 100644 --- a/src/w_ImportConfig.cpp +++ b/src/w_ImportConfig.cpp @@ -10,8 +10,8 @@ #include "Python.h" #pragma pop_macro("slots") -#include "HUtils.h" -#include "vinteract.h" +#include "HUtils.hpp" +#include "vinteract.hpp" #include "w_ConnectionEditWindow.h" #include "w_ImportConfig.h" diff --git a/src/w_MainWindow.cpp b/src/w_MainWindow.cpp index 80f24f45..1ff13ea6 100644 --- a/src/w_MainWindow.cpp +++ b/src/w_MainWindow.cpp @@ -8,8 +8,8 @@ #include #include -#include "HUtils.h" -#include "vinteract.h" +#include "HUtils.hpp" +#include "vinteract.hpp" #include "w_ConnectionEditWindow.h" #include "w_ImportConfig.h" #include "w_MainWindow.h" diff --git a/src/w_MainWindow.h b/src/w_MainWindow.h index edee6ad2..a9e32b52 100644 --- a/src/w_MainWindow.h +++ b/src/w_MainWindow.h @@ -7,8 +7,8 @@ #include #include "ui_w_MainWindow.h" -#include "vinteract.h" -#include "Hv2ConfigObject.h" +#include "vinteract.hpp" +#include "V2ConfigObjects.hpp" namespace Hv2ray { diff --git a/src/w_MainWindow.ui b/src/w_MainWindow.ui index 95bd3e9c..8d2640b0 100644 --- a/src/w_MainWindow.ui +++ b/src/w_MainWindow.ui @@ -202,6 +202,13 @@ + + + + #ConnectionSettings + + + @@ -215,13 +222,6 @@ - - - - #ConnectionSettings - - - @@ -294,7 +294,6 @@ restartButton clearlogButton listWidget - pushButton logText diff --git a/src/w_PrefrencesWindow.cpp b/src/w_PrefrencesWindow.cpp index cbfa2aed..660c208b 100644 --- a/src/w_PrefrencesWindow.cpp +++ b/src/w_PrefrencesWindow.cpp @@ -8,10 +8,13 @@ #include #include -#include "HUtils.h" -#include "vinteract.h" +#include "HUtils.hpp" +#include "vinteract.hpp" #include "w_PrefrencesWindow.h" + +#ifndef _WIN32 #include +#endif using namespace Hv2ray; using namespace Utils; @@ -20,33 +23,27 @@ namespace Hv2ray { namespace Ui { - PrefrencesWindow::PrefrencesWindow(QWidget *parent) - : QDialog(parent) - , ui(new Ui_PrefrencesWindow) + PrefrencesWindow::PrefrencesWindow(QWidget *parent) : QDialog(parent), CurrentConfig(), ui(new Ui_PrefrencesWindow) { ui->setupUi(this); - rootObj = loadRootObjFromConf(); - QJsonObject http = findValueFromJsonArray(rootObj.value("inbounds").toArray(), "tag", "http-in"); - QJsonObject socks = findValueFromJsonArray(rootObj.value("inbounds").toArray(), "tag", "socks-in"); - - if (rootObj.value("v2suidEnabled").toBool()) { - ui->runAsRootCheckBox->setCheckState(Qt::Checked); - } - - if (!http.isEmpty()) { - ui->httpPortLE->setText(http.value("port").toString()); - ui->httpCB->setCheckState(Qt::Checked); - } else { - ui->httpPortLE->setDisabled(true); - } - - if (!socks.isEmpty()) { - ui->socksPortLE->setText(socks.value("port").toString()); - ui->socksCB->setCheckState(Qt::Checked); - } else { - ui->socksPortLE->setDisabled(true); - } - + CurrentConfig = GetGlobalConfig(); + ui->languageComboBox->setCurrentText(QString::fromStdString(CurrentConfig.language)); + ui->runAsRootCheckBox->setChecked(CurrentConfig.runAsRoot); + ui->logLevelCheckBox->setCurrentText(QString::fromStdString(CurrentConfig.logLevel)); + // + ui->httpCB->setChecked(CurrentConfig.httpSetting.enabled); + ui->httpPortLE->setText(QString::fromStdString(to_string(CurrentConfig.httpSetting.port))); + ui->httpAuthCB->setChecked(CurrentConfig.httpSetting.useAuthentication); + ui->httpAuthUsernameTxt->setText(QString::fromStdString(CurrentConfig.httpSetting.authUsername)); + ui->httpAuthPasswordTxt->setText(QString::fromStdString(CurrentConfig.httpSetting.authPassword)); + ui->httpPortLE->setValidator(new QIntValidator()); + // + ui->socksCB->setChecked(CurrentConfig.socksSetting.enabled); + ui->socksPortLE->setText(QString::fromStdString(to_string(CurrentConfig.socksSetting.port))); + ui->socksAuthCB->setChecked(CurrentConfig.socksSetting.useAuthentication); + ui->socksAuthUsernameTxt->setText(QString::fromStdString(CurrentConfig.socksSetting.authUsername)); + ui->socksAuthPasswordTxt->setText(QString::fromStdString(CurrentConfig.socksSetting.authPassword)); + // ui->httpPortLE->setValidator(new QIntValidator()); ui->socksPortLE->setValidator(new QIntValidator()); parentMW = parent; @@ -61,55 +58,9 @@ namespace Hv2ray { if (v2Instance::checkVCoreExes()) { if (ui->httpPortLE->text().toInt() != ui->socksPortLE->text().toInt()) { - QJsonArray inbounds; - QJsonDocument modifiedDoc; - inbounds = rootObj.value("inbounds").toArray(); - int socksId = getIndexByValue(inbounds, "tag", "socks-in"); - - if (socksId != -1) { - inbounds.removeAt(socksId); - } - - int httpId = getIndexByValue(inbounds, "tag", "http-in"); - - if (httpId != -1) { - inbounds.removeAt(httpId); - } - - rootObj.remove("inbounds"); - rootObj.remove("v2suidEnabled"); - - if (ui->socksCB->isChecked()) { - QJsonObject socks; - QJsonObject settings; - socks.insert("tag", "socks-in"); - socks.insert("port", ui->socksPortLE->text().toInt()); - socks.insert("listen", "127.0.0.1"); - socks.insert("protocol", "socks"); - settings.insert("auth", "noauth"); - settings.insert("udp", true); - settings.insert("ip", "127.0.0.1"); - socks.insert("settings", QJsonValue(settings)); - inbounds.append(socks); - } - - if (ui->httpCB->isChecked()) { - QJsonObject http; - QJsonObject settings; - http.insert("tag", "http-in"); - http.insert("port", ui->httpPortLE->text().toInt()); - http.insert("listen", "127.0.0.1"); - http.insert("protocol", "http"); - settings.insert("auth", "noauth"); - settings.insert("udp", true); - settings.insert("ip", "127.0.0.1"); - http.insert("settings", QJsonValue(settings)); - inbounds.append(http); - } - - rootObj.insert("inbounds", QJsonValue(inbounds)); #ifndef _WIN32 // Set UID and GID in *nix + // The file is actually not here QFileInfo v2rayCoreExeFile("v2ray"); if (ui->runAsRootCheckBox->isChecked() && v2rayCoreExeFile.ownerId() != 0) { @@ -123,21 +74,10 @@ namespace Hv2ray } v2rayCoreExeFile.refresh(); - rootObj.insert("v2suidEnabled", v2rayCoreExeFile.ownerId() == 0); + //rootObj.insert("v2suidEnabled", v2rayCoreExeFile.ownerId() == 0); #else // No such uid gid thing on windows.... #endif - modifiedDoc.setObject(rootObj); - QByteArray byteArray = modifiedDoc.toJson(QJsonDocument::Indented); - QFile confFile("conf/Hv2ray.config.json"); - - if (!confFile.open(QIODevice::WriteOnly)) { - showWarnMessageBox(this, tr("#Prefrences"), tr("#CannotOpenConfigFile")); - qDebug() << "Cannot open Hv2ray.config.json for modifying"; - } - - confFile.write(byteArray); - confFile.close(); } else { showWarnMessageBox(this, tr("Prefrences"), tr("PortNumbersCannotBeSame")); } @@ -150,17 +90,15 @@ namespace Hv2ray ui->httpPortLE->setDisabled(true); } else { ui->httpPortLE->setEnabled(true); - ui->httpPortLE->setText("6666"); } } void PrefrencesWindow::on_socksCB_stateChanged(int checked) { if (checked != Qt::Checked) { - ui->socksPortLE->setDisabled(true); + ui->socksPortLE->setEnabled(false); } else { ui->socksPortLE->setEnabled(true); - ui->socksPortLE->setText("1080"); } } diff --git a/src/w_PrefrencesWindow.h b/src/w_PrefrencesWindow.h index f80b3759..7a7e8579 100644 --- a/src/w_PrefrencesWindow.h +++ b/src/w_PrefrencesWindow.h @@ -3,7 +3,7 @@ #include #include -#include +#include "HConfigObjects.hpp" namespace Hv2ray { @@ -16,7 +16,6 @@ namespace Hv2ray public: explicit PrefrencesWindow(QWidget *parent = nullptr); ~PrefrencesWindow(); - QJsonObject rootObj; QWidget *parentMW; private slots: @@ -29,6 +28,7 @@ namespace Hv2ray void on_runAsRootCheckBox_stateChanged(int arg1); private: + Hv2ray::HConfigModels::Hv2Config CurrentConfig; Ui_PrefrencesWindow *ui; }; } diff --git a/translations/en-US.ts b/translations/en-US.ts index 91111cb4..4d8ba137 100644 --- a/translations/en-US.ts +++ b/translations/en-US.ts @@ -197,56 +197,56 @@ #ConnectionSettings - Connection Settings + Connection Settings #Host - Host + Host #Port - Port + Port #Name - Name + Name #UUID - UUID + UUID #AlterID - Alter ID + Alter ID #Security - Security Settings + Security Settings auto - Auto + Auto aes-128-gcm - aes-128-gcm + aes-128-gcm chacha20-poly1305 - chacha20-poly1305 + chacha20-poly1305 @@ -255,199 +255,199 @@ none - Do not use + Do not use #Transport - Transport Settings + Transport Settings tcp (TCP) - tcp (TCP) + tcp (TCP) http (HTTP) - http (HTTP) + http (HTTP) ws (WebSocket) - ws (WebSocket) + ws (WebSocket) kcp (mKCP) - kcp (mKCP) + kcp (mKCP) domainsocket (Domain Socket) - domainsocket (Domain Socket) + domainsocket (Domain Socket) quic (Quick UDP Internet Connection) - quic (Quick UDP Internet Connection) + quic (Quick UDP Internet Connection) #TransportSettings - Transport Settings + Transport Settings TCP - TCP + TCP http - HTTP + HTTP #Type - Type + Type #Request - Request + Request #InsertDefaultContent - Insert Default Content + Insert Default Content #Response - Response + Response HTTP - HTTP + HTTP #Path - Path + Path WebSocket - WebSocket + WebSocket #Headers - Headers + Headers mKCP - mKCP + mKCP #MTU - MTU + MTU #TTI (ms) - TTI (ms) + TTI (ms) #UplinkCapacity (MB/s) - Uplink Capacity (MB/s) + Uplink Capacity (MB/s) #Congestion - Congestion Control + Congestion Control #Enabled - Enabled + Enabled #DownlinkCapacity (MB/s) - Downlink Capacity (MB/s) + Downlink Capacity (MB/s) #ReadBufferSize (MB) - Read Buffer Size (MB) + Read Buffer Size (MB) #WriteBufferSize (MB) - Write Buffer Size (MB) + Write Buffer Size (MB) #Header - Headers + Headers srtp (SRTP, FaceTime) - srtp (SRTP, FaceTime) + srtp (SRTP, FaceTime) utp (BitTorrent) - utp (BitTorrent) + utp (BitTorrent) wechat-video (WeChat Video Message) - wechat-video (WeChat Video Message) + wechat-video (WeChat Video Message) dtls (DTLS 1.2) - dtls (DTLS 1.2) + dtls (DTLS 1.2) wireguard (WireGuard fake packets) - wireguard (WireGuard fake packets) + wireguard (WireGuard fake packets) DomainSocket - DomainSocket + DomainSocket QUIC - QUIC + QUIC #Key - Key + Key @@ -455,82 +455,82 @@ Import file - Import file + Import file #ImportFrom - Import From + Import From Existing File - Existing File + Existing File VMess Connection String - VMess Connection String + VMess Connection String #FromFile - From file + From file #Path - Path + Path #SelectFile - Select File + Select File #Name - Name + Name #Inbound - Inbound Settings + Inbound Settings #UseCurrent - Use Current Settings + Use Current Settings #UseImported - Use Imported Inbound Settings + Use Imported Inbound Settings #From VMess Connection String - From VMess Connection String + From VMess Connection String #VMess Connection String - VMess Connection String + VMess Connection String OpenConfigFile - Open Config File + Open Config File ImportConfig - Import Config + Import Config CannotGenerateConfig - Failed to generate config file + Failed to generate config file @@ -539,147 +539,147 @@ Hv2ray - Hv2ray + Hv2ray #Start - Start + Start #Stop - Stop + Stop #Restart - Restart + Restart #ClearLog - Clear Log + Clear Log #HostList - Host List + Host List #ConfigDetail - Detailed Config Info + Detailed Config Info #Host - Host + Host #Port - Port + Port #UUID - UUID + UUID #Transport - Transport Settings + Transport Settings #ConnectionSettings - Connection Settings + Connection Settings #File - File + File #NewConnection - New Connection + New Connection #ManuallyInput - Manually Input Config + Manually Input Config #ImportConnection - Import Config File + Import Config File #Exit - Exit + Exit #Preferences - Preferences + Preferences #Hide - Hide + Hide #Quit - Quit + Quit #Show - Show + Show Hv2ray::Ui::PrefrencesWindow - - + + Prefrences - Preferences + Preferences #General - General + General #Language - Language + Language zh-CN - + en-US - + #RunAsRoot - Run v2ray as root + Run v2ray as root @@ -690,7 +690,7 @@ #Enabled - Enabled + Enabled @@ -769,37 +769,35 @@ #Password - Password + Password SOCKS - SOCKS + SOCKS 9001 - + - #Prefrences - Preferences + Preferences - #CannotOpenConfigFile - Cannot open config file + Cannot open config file - + PortNumbersCannotBeSame - Port numbers cannot be the same + Port numbers cannot be the same - + RunAsRootNotOnWindows - Run as root is not avaliable on Windows Platform + Run as root is not avaliable on Windows Platform @@ -1070,12 +1068,12 @@ QObject - + Hv2Ray Hv2ray - + AnotherInstanceRunning Another instance is already running diff --git a/translations/zh-CN.ts b/translations/zh-CN.ts index 01ff455b..1e0f5a54 100644 --- a/translations/zh-CN.ts +++ b/translations/zh-CN.ts @@ -197,56 +197,56 @@ #ConnectionSettings - 连接设置 + 连接设置 #Host - 域名 + 域名 #Port - 端口 + 端口 #Name - 名称 + 名称 #UUID - UUID + UUID #AlterID - Alter ID + Alter ID #Security - 安全设置 + 安全设置 auto - 自动 + 自动 aes-128-gcm - aes-128-gcm + aes-128-gcm chacha20-poly1305 - chacha20-poly1305 + chacha20-poly1305 @@ -255,199 +255,199 @@ none - 不使用 + 不使用 #Transport - 传输设置 + 传输设置 tcp (TCP) - tcp (TCP) + tcp (TCP) http (HTTP) - http (HTTP) + http (HTTP) ws (WebSocket) - ws (WebSocket) + ws (WebSocket) kcp (mKCP) - kcp (mKCP) + kcp (mKCP) domainsocket (Domain Socket) - domainsocket (Domain Socket) + domainsocket (Domain Socket) quic (Quick UDP Internet Connection) - quic (Quick UDP Internet Connection) + quic (Quick UDP Internet Connection) #TransportSettings - 传输设置 + 传输设置 TCP - TCP + TCP http - HTTP + HTTP #Type - 类型 + 类型 #Request - 请求 + 请求 #InsertDefaultContent - 默认值 + 默认值 #Response - 相应 + 相应 HTTP - HTTP + HTTP #Path - 路径 + 路径 WebSocket - WebSocket + WebSocket #Headers - 头伪装 + 头伪装 mKCP - mKCP + mKCP #MTU - 最大传输单元 + 最大传输单元 #TTI (ms) - 传输时间间隔 + 传输时间间隔 #UplinkCapacity (MB/s) - 上行链路容量 (MB/s) + 上行链路容量 (MB/s) #Congestion - 拥塞控制 + 拥塞控制 #Enabled - 启用 + 启用 #DownlinkCapacity (MB/s) - 下行链路容量 (MB/s) + 下行链路容量 (MB/s) #ReadBufferSize (MB) - 读取缓冲区大小 (MB) + 读取缓冲区大小 (MB) #WriteBufferSize (MB) - 写入缓冲区大小 (MB) + 写入缓冲区大小 (MB) #Header - 头伪装 + 头伪装 srtp (SRTP, FaceTime) - srtp (SRTP, FaceTime) + srtp (SRTP, FaceTime) utp (BitTorrent) - utp (BitTorrent) + utp (BitTorrent) wechat-video (WeChat Video Message) - wechat-video (WeChat Video Message) + wechat-video (WeChat Video Message) dtls (DTLS 1.2) - dtls (DTLS 1.2) + dtls (DTLS 1.2) wireguard (WireGuard fake packets) - wireguard (WireGuard fake packets) + wireguard (WireGuard fake packets) DomainSocket - DomainSocket + DomainSocket QUIC - QUIC + QUIC #Key - 密钥 + 密钥 @@ -455,82 +455,82 @@ Import file - 导入文件 + 导入文件 #ImportFrom - 导入源 + 导入源 Existing File - 现有文件 + 现有文件 VMess Connection String - VMess 连接字符串 + VMess 连接字符串 #FromFile - 从文件 + 从文件 #Path - 路径 + 路径 #SelectFile - 选择文件 + 选择文件 #Name - 名称 + 名称 #Inbound - 入站设置 + 入站设置 #UseCurrent - 使用现有设置 + 使用现有设置 #UseImported - 使用导入的设置 + 使用导入的设置 #From VMess Connection String - 从 VMess 连接字符串 + 从 VMess 连接字符串 #VMess Connection String - VMess 连接字符串 + VMess 连接字符串 OpenConfigFile - 打开配置文件 + 打开配置文件 ImportConfig - 导入配置 + 导入配置 CannotGenerateConfig - 无法生成配置文件 + 无法生成配置文件 @@ -539,147 +539,147 @@ Hv2ray - Hv2ray + Hv2ray #Start - 启动 + 启动 #Stop - 停止 + 停止 #Restart - 重新启动 + 重新启动 #ClearLog - 清除日志 + 清除日志 #HostList - 服务器列表 + 服务器列表 #ConfigDetail - 配置详细信息 + 配置详细信息 #Host - 域名 + 域名 #Port - 端口 + 端口 #UUID - UUID + UUID #Transport - 传输设置 + 传输设置 #ConnectionSettings - 连接设置 + 连接设置 #File - 文件 + 文件 #NewConnection - 新建连接 + 新建连接 #ManuallyInput - 手动输入配置 + 手动输入配置 #ImportConnection - 导入配置文件 + 导入配置文件 #Exit - 退出 + 退出 #Preferences - 首选项 + 首选项 #Hide - 隐藏 + 隐藏 #Quit - 退出 + 退出 #Show - 显示 + 显示 Hv2ray::Ui::PrefrencesWindow - - + + Prefrences - 首选项 + 首选项 #General - 一般 + 一般 #Language - 语言 + 语言 zh-CN - + en-US - + #RunAsRoot - 使用 root 启动 + 使用 root 启动 @@ -690,7 +690,7 @@ #Enabled - 启用 + 启用 @@ -769,37 +769,35 @@ #Password - 密码 + 密码 SOCKS - SOCKS + SOCKS 9001 - + - #Prefrences - 首选项 + 首选项 - #CannotOpenConfigFile - 无法打开配置文件 + 无法打开配置文件 - + PortNumbersCannotBeSame - 端口号不能相同 + 端口号不能相同 - + RunAsRootNotOnWindows - Windows 平台不支持这个选项 + Windows 平台不支持这个选项 @@ -1070,12 +1068,12 @@ QObject - + Hv2Ray Hv2ray - + AnotherInstanceRunning 另一个实例正在运行