Merge branch 'dev-qjsonstruct-omitting-default-value' into dev

* dev-qjsonstruct-omitting-default-value:
  fix: fixed compilation for Qt6
  fix: make QV2RAY_RULE_ENABLED, QV2RAY_RULE_TAG mandatory
  fix, plugin: fixed BuiltinProtocolSupport causing null in JSON
  update, qjsonstruct: tweaks
  fix, test: fixed vmess testing 2
  fix, QJsonStruct: make some fields mandatory
  fix, test: fixed vmess testing
  add: support omitting default values
This commit is contained in:
QxQ 2020-12-15 20:15:13 +08:00
commit 8d35e54739
22 changed files with 508 additions and 102 deletions

View File

@ -267,6 +267,7 @@ include(cmake/libcurl.cmake)
include(cmake/libsemver.cmake)
include(cmake/protobuf.cmake)
include(cmake/backend.cmake)
include(3rdparty/QJsonStruct/QJsonStruct.cmake)
# ==================================================================================
# Qv2ray Base, Qt Libraries, Qv2ray GUI Libraries, libThreads

View File

@ -16,9 +16,7 @@ if(CMAKE_BUILD_TYPE MATCHES "^[Dd][Ee][Bb][Uu][Gg]$" OR NOT DEFINED CMAKE_BUILD_
add_custom_target(lupdate
COMMENT "Generating Translation Sources"
COMMAND lupdate
${QV2RAY_BASE_SOURCES}
${QV2RAY_UI_SOURCES}
${QVPLUGIN_INTERFACE_HEADERS}
${CMAKE_SOURCE_DIR}/src
-ts translations/en_US.ts
-locations none
-no-obsolete

View File

@ -1 +1 @@
6096
6097

View File

@ -10,10 +10,3 @@
// Add key value pair into JSON named 'root'
#define JADDEx(field) root.insert(#field, field);
#define JADD(...) FOR_EACH(JADDEx, __VA_ARGS__)
#define JAUTOREMOVE(jObj, key) \
{ \
if ((jObj[key].isArray() && jObj[key].toArray().isEmpty()) || (jObj[key].isObject() && jObj[key].toObject().isEmpty()) || \
(jObj[key].isString() && jObj[key].toString().isEmpty())) \
jObj.remove(key); \
}

View File

@ -37,6 +37,7 @@ namespace Qv2ray::base::objects
}
void loadJson(const QJsonValue &___json_object_)
{
DNSServerObject ___qjsonstruct_default_check;
// Hack to convert simple DNS settings to complex format.
if (___json_object_.isString())
{
@ -55,6 +56,7 @@ namespace Qv2ray::base::objects
[[nodiscard]] const QJsonObject toJson() const
{
QJsonObject ___json_object_;
DNSServerObject ___qjsonstruct_default_check;
FOREACH_CALL_FUNC(___SERIALIZE_TO_JSON_EXTRACT_B_F, F(QV2RAY_DNS_IS_COMPLEX_DNS, address, port, domains, expectIPs));
return ___json_object_;
}
@ -79,7 +81,7 @@ namespace Qv2ray::base::objects
{
QString user;
QString pass;
AccountObject(){};
JSONSTRUCT_COMPARE(AccountObject, user, pass)
JSONSTRUCT_REGISTER(AccountObject, F(user, pass))
};
//
@ -90,19 +92,27 @@ namespace Qv2ray::base::objects
QString QV2RAY_RULE_TAG = "New Rule";
//
QString type = "field";
QList<QString> domain;
QList<QString> ip;
QString port = "1-65535";
QString network;
QList<QString> source;
QList<QString> user;
QList<QString> inboundTag;
QList<QString> protocol;
QString attrs;
QString outboundTag;
QString balancerTag;
JSONSTRUCT_REGISTER(RuleObject, F(QV2RAY_RULE_ENABLED, QV2RAY_RULE_TAG, type, domain, ip, port, network, source, user, inboundTag, protocol,
attrs, outboundTag, balancerTag))
// Addresses
QList<QString> source;
QList<QString> domain;
QList<QString> ip;
// Ports
QString sourcePort;
QString port;
//
QString network;
QList<QString> protocol;
QString attrs;
JSONSTRUCT_COMPARE(RuleObject, type, outboundTag, balancerTag, //
QV2RAY_RULE_ENABLED, QV2RAY_RULE_TAG, //
domain, ip, port, sourcePort, network, source, inboundTag, protocol, attrs)
JSONSTRUCT_REGISTER(RuleObject, //
A(type, outboundTag, balancerTag), //
A(QV2RAY_RULE_ENABLED, QV2RAY_RULE_TAG), //
F(domain, ip, port, sourcePort, network, source, inboundTag, protocol, attrs))
};
//
//
@ -110,6 +120,7 @@ namespace Qv2ray::base::objects
{
QString tag;
QList<QString> selector;
JSONSTRUCT_COMPARE(BalancerObject, tag, selector)
JSONSTRUCT_REGISTER(BalancerObject, F(tag, selector))
};
//
@ -120,8 +131,21 @@ namespace Qv2ray::base::objects
{
QString version = "1.1";
QString method = "GET";
QList<QString> path;
QList<QString> path = { "/" };
QMap<QString, QList<QString>> headers;
HTTPRequestObject()
{
headers = {
{ "Host", { "www.baidu.com", "www.bing.com" } },
{ "User-Agent",
{ "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
"Mozilla/5.0 (iPhone; CPU iPhone OS 10_0_2 like Mac OS X) AppleWebKit/601.1 (KHTML, like Gecko) CriOS/53.0.2785.109 Mobile/14A456 Safari/601.1.46" } },
{ "Accept-Encoding", { "gzip, deflate" } },
{ "Connection", { "keep-alive" } },
{ "Pragma", { "no-cache" } }
};
}
JSONSTRUCT_COMPARE(HTTPRequestObject, version, method, path, headers)
JSONSTRUCT_REGISTER(HTTPRequestObject, F(version, method, path, headers))
};
//
@ -132,6 +156,14 @@ namespace Qv2ray::base::objects
QString status = "200";
QString reason = "OK";
QMap<QString, QList<QString>> headers;
HTTPResponseObject()
{
headers = { { "Content-Type", { "application/octet-stream", "video/mpeg" } }, //
{ "Transfer-Encoding", { "chunked" } }, //
{ "Connection", { "keep-alive" } }, //
{ "Pragma", { "no-cache" } } };
}
JSONSTRUCT_COMPARE(HTTPResponseObject, version, status, reason, headers)
JSONSTRUCT_REGISTER(HTTPResponseObject, F(version, status, reason, headers))
};
//
@ -141,6 +173,7 @@ namespace Qv2ray::base::objects
QString type = "none";
HTTPRequestObject request;
HTTPResponseObject response;
JSONSTRUCT_COMPARE(TCPHeader_Internal, type, request, response)
JSONSTRUCT_REGISTER(TCPHeader_Internal, F(type, request, response))
};
//
@ -148,6 +181,7 @@ namespace Qv2ray::base::objects
struct ObfsHeaderObject
{
QString type = "none";
JSONSTRUCT_COMPARE(ObfsHeaderObject, type)
JSONSTRUCT_REGISTER(ObfsHeaderObject, F(type))
};
//
@ -155,7 +189,7 @@ namespace Qv2ray::base::objects
struct TCPObject
{
TCPHeader_Internal header;
TCPObject(){};
JSONSTRUCT_COMPARE(TCPObject, header)
JSONSTRUCT_REGISTER(TCPObject, F(header))
};
//
@ -172,6 +206,7 @@ namespace Qv2ray::base::objects
QString seed;
ObfsHeaderObject header;
KCPObject(){};
JSONSTRUCT_COMPARE(KCPObject, mtu, tti, uplinkCapacity, downlinkCapacity, congestion, readBufferSize, writeBufferSize, seed, header)
JSONSTRUCT_REGISTER(KCPObject, F(mtu, tti, uplinkCapacity, downlinkCapacity, congestion, readBufferSize, writeBufferSize, header, seed))
};
//
@ -180,6 +215,7 @@ namespace Qv2ray::base::objects
{
QString path = "/";
QMap<QString, QString> headers;
JSONSTRUCT_COMPARE(WebSocketObject, path, headers)
JSONSTRUCT_REGISTER(WebSocketObject, F(path, headers))
};
//
@ -188,6 +224,7 @@ namespace Qv2ray::base::objects
{
QList<QString> host;
QString path = "/";
JSONSTRUCT_COMPARE(HttpObject, host, path)
JSONSTRUCT_REGISTER(HttpObject, F(host, path))
};
//
@ -195,6 +232,7 @@ namespace Qv2ray::base::objects
struct DomainSocketObject
{
QString path = "/";
JSONSTRUCT_COMPARE(DomainSocketObject, path)
JSONSTRUCT_REGISTER(DomainSocketObject, F(path))
};
//
@ -204,7 +242,7 @@ namespace Qv2ray::base::objects
QString security;
QString key;
ObfsHeaderObject header;
QuicObject(){};
JSONSTRUCT_COMPARE(QuicObject, security, key, header)
JSONSTRUCT_REGISTER(QuicObject, F(security, key, header))
};
//
@ -214,6 +252,7 @@ namespace Qv2ray::base::objects
int mark = 255;
bool tcpFastOpen = false;
QString tproxy = "off";
JSONSTRUCT_COMPARE(SockoptObject, mark, tcpFastOpen, tproxy)
JSONSTRUCT_REGISTER(SockoptObject, F(mark, tcpFastOpen, tproxy))
};
//
@ -225,6 +264,7 @@ namespace Qv2ray::base::objects
QString keyFile;
QList<QString> certificate;
QList<QString> key;
JSONSTRUCT_COMPARE(CertificateObject, usage, certificateFile, keyFile, certificate, key)
JSONSTRUCT_REGISTER(CertificateObject, F(usage, certificateFile, keyFile, certificate, key))
};
//
@ -233,13 +273,12 @@ namespace Qv2ray::base::objects
{
QString serverName;
bool allowInsecure = false;
bool allowInsecureCiphers = false;
bool disableSessionResumption = true;
bool disableSystemRoot = false;
QList<QString> alpn = { "http/1.1" };
QList<CertificateObject> certificates;
JSONSTRUCT_REGISTER(TLSObject,
F(serverName, allowInsecure, allowInsecureCiphers, disableSessionResumption, alpn, certificates, disableSystemRoot))
JSONSTRUCT_COMPARE(TLSObject, serverName, allowInsecure, disableSessionResumption, disableSystemRoot, alpn, certificates)
JSONSTRUCT_REGISTER(TLSObject, F(serverName, allowInsecure, disableSessionResumption, disableSystemRoot, alpn, certificates))
};
//
//
@ -247,13 +286,12 @@ namespace Qv2ray::base::objects
{
QString serverName;
bool allowInsecure = false;
bool allowInsecureCiphers = false;
bool disableSessionResumption = true;
bool disableSystemRoot = false;
QList<QString> alpn = { "http/1.1" };
QList<CertificateObject> certificates;
JSONSTRUCT_REGISTER(XTLSObject,
F(serverName, allowInsecure, allowInsecureCiphers, disableSessionResumption, alpn, certificates, disableSystemRoot))
JSONSTRUCT_COMPARE(XTLSObject, serverName, allowInsecure, disableSessionResumption, disableSystemRoot, alpn, certificates)
JSONSTRUCT_REGISTER(XTLSObject, F(serverName, allowInsecure, disableSessionResumption, disableSystemRoot, alpn, certificates))
};
} // namespace transfer
//
@ -271,8 +309,12 @@ namespace Qv2ray::base::objects
transfer::HttpObject httpSettings;
transfer::DomainSocketObject dsSettings;
transfer::QuicObject quicSettings;
JSONSTRUCT_REGISTER(StreamSettingsObject, F(network, security, sockopt, tcpSettings, tlsSettings, xtlsSettings, kcpSettings, wsSettings,
httpSettings, dsSettings, quicSettings))
JSONSTRUCT_COMPARE(StreamSettingsObject, //
network, security, sockopt, //
tcpSettings, tlsSettings, xtlsSettings, kcpSettings, wsSettings, httpSettings, dsSettings, quicSettings)
JSONSTRUCT_REGISTER(StreamSettingsObject, //
F(network, security, sockopt),
F(tcpSettings, tlsSettings, xtlsSettings, kcpSettings, wsSettings, httpSettings, dsSettings, quicSettings))
};
//
// Some protocols from: https://v2ray.com/chapter_02/02_protocols.html
@ -289,12 +331,14 @@ namespace Qv2ray::base::objects
int alterId = VMESS_USER_ALTERID_DEFAULT;
QString security = "auto";
int level = 0;
JSONSTRUCT_COMPARE(UserObject, id, alterId, security, level)
JSONSTRUCT_REGISTER(UserObject, F(id, alterId, security, level))
};
QString address;
int port = 0;
int port;
QList<UserObject> users;
JSONSTRUCT_COMPARE(VMessServerObject, address, port, users)
JSONSTRUCT_REGISTER(VMessServerObject, F(address, port, users))
};
//
@ -305,6 +349,7 @@ namespace Qv2ray::base::objects
QString method = "aes-256-cfb";
QString password;
int port;
JSONSTRUCT_COMPARE(ShadowSocksServerObject, address, method, password)
JSONSTRUCT_REGISTER(ShadowSocksServerObject, F(address, port, method, password))
};
} // namespace protocol

View File

@ -79,7 +79,7 @@ namespace Qv2ray::base::objects::complex
meta.realOutbound = out;
return meta;
}
explicit OutboundObjectMeta() : metaType(METAOUTBOUND_ORIGINAL){};
OutboundObjectMeta() : metaType(METAOUTBOUND_ORIGINAL){};
JSONSTRUCT_REGISTER(OutboundObjectMeta, F(metaType, displayName, connectionId, outboundTags, chainPortAllocation))
};

View File

@ -113,6 +113,11 @@ namespace Qv2ray::base
bool overrideForwardProxyConfig = false;
config::QvConfig_ForwardProxy forwardProxyConfig;
//
JSONSTRUCT_COMPARE(GroupRoutingConfig, //
overrideDNS, dnsConfig, //
overrideRoute, routeConfig, //
overrideConnectionConfig, connectionConfig, //
overrideForwardProxyConfig, forwardProxyConfig)
JSONSTRUCT_REGISTER(GroupRoutingConfig, //
F(overrideRoute, routeConfig), //
F(overrideDNS, dnsConfig), //
@ -135,8 +140,10 @@ namespace Qv2ray::base
QList<QString> ExcludeKeywords;
SubscriptionFilterRelation IncludeRelation = RELATION_OR;
SubscriptionFilterRelation ExcludeRelation = RELATION_AND;
JSONSTRUCT_REGISTER(SubscriptionConfigObject,
F(updateInterval, address, type, IncludeRelation, ExcludeRelation, IncludeKeywords, ExcludeKeywords))
JSONSTRUCT_COMPARE(SubscriptionConfigObject, address, type, updateInterval, //
IncludeKeywords, ExcludeKeywords, IncludeRelation, ExcludeRelation)
JSONSTRUCT_REGISTER(SubscriptionConfigObject, F(updateInterval, address, type),
F(IncludeRelation, ExcludeRelation, IncludeKeywords, ExcludeKeywords))
};
struct GroupObject : __Qv2rayConfigObjectBase
@ -146,6 +153,7 @@ namespace Qv2ray::base
GroupRoutingId routeConfigId;
SubscriptionConfigObject subscriptionOption;
GroupObject() : __Qv2rayConfigObjectBase(){};
JSONSTRUCT_COMPARE(GroupObject, isSubscription, connections, routeConfigId, subscriptionOption)
JSONSTRUCT_REGISTER(GroupObject, F(connections, isSubscription, routeConfigId, subscriptionOption), B(__Qv2rayConfigObjectBase))
};
@ -197,6 +205,10 @@ namespace Qv2ray::base
{
return JsonStructHelper::Serialize(entries);
}
friend bool operator==(const ConnectionStatsObject &left, const ConnectionStatsObject &right)
{
return left.toJson() == right.toJson();
}
void loadJson(const QJsonValue &d)
{
JsonStructHelper::Deserialize(entries, d);
@ -218,6 +230,7 @@ namespace Qv2ray::base
ConnectionStatsObject stats;
//
int __qvConnectionRefCount = 0;
JSONSTRUCT_COMPARE(ConnectionObject, lastConnected, latency, importSource, stats, displayName, creationDate, lastUpdatedDate)
JSONSTRUCT_REGISTER(ConnectionObject, F(lastConnected, latency, importSource, stats), B(__Qv2rayConfigObjectBase))
};

View File

@ -1,5 +1,5 @@
#pragma once
#include "3rdparty/QJsonStruct/QJsonStruct.hpp"
#include "QJsonStruct.hpp"
#include "base/models/CoreObjectModels.hpp"
namespace Qv2ray::base::config
{
@ -11,28 +11,19 @@ namespace Qv2ray::base::config
QList<QString> block;
QList<QString> proxy;
QvRouteConfig_Impl(){};
friend bool operator==(const QvRouteConfig_Impl &left, const QvRouteConfig_Impl &right)
{
return left.direct == right.direct && left.block == right.block && left.proxy == right.proxy;
}
QvRouteConfig_Impl(const QList<QString> &_direct, const QList<QString> &_block, const QList<QString> &_proxy)
: direct(_direct), //
block(_block), //
proxy(_proxy){};
: direct(_direct), block(_block), proxy(_proxy){};
JSONSTRUCT_COMPARE(QvRouteConfig_Impl, direct, block, proxy)
JSONSTRUCT_REGISTER(QvRouteConfig_Impl, F(proxy, block, direct))
};
QString domainStrategy;
QvRouteConfig_Impl domains;
QvRouteConfig_Impl ips;
friend bool operator==(const QvConfig_Route &left, const QvConfig_Route &right)
{
return left.domainStrategy == right.domainStrategy && left.domains == right.domains && left.ips == right.ips;
}
QvConfig_Route(){};
QvConfig_Route(const QvRouteConfig_Impl &_domains, const QvRouteConfig_Impl &_ips, const QString &ds)
: domainStrategy(ds), //
domains(_domains), //
ips(_ips){};
: domainStrategy(ds), domains(_domains), ips(_ips){};
JSONSTRUCT_COMPARE(QvConfig_Route, domainStrategy, domains, ips)
JSONSTRUCT_REGISTER(QvConfig_Route, F(domainStrategy, domains, ips))
};
@ -41,6 +32,7 @@ namespace Qv2ray::base::config
struct QvConfig_Outbounds
{
int mark = 255;
JSONSTRUCT_COMPARE(QvConfig_Outbounds, mark)
JSONSTRUCT_REGISTER(QvConfig_Outbounds, F(mark))
};
@ -53,6 +45,7 @@ namespace Qv2ray::base::config
bool useAuth = false;
QString username;
QString password;
JSONSTRUCT_COMPARE(QvConfig_ForwardProxy, enableForwardProxy, type, serverAddress, port, useAuth, username, password)
JSONSTRUCT_REGISTER(QvConfig_ForwardProxy, F(enableForwardProxy, type, serverAddress, port, useAuth, username, password))
};
@ -66,22 +59,27 @@ namespace Qv2ray::base::config
bool withLocalDNS = true;
bool dnsIntercept = false;
bool fakeDNS = false;
JSONSTRUCT_COMPARE(QvConfig_Connection, enableProxy, //
bypassCN, bypassBT, bypassLAN, //
v2rayFreedomDNS, withLocalDNS, dnsIntercept, fakeDNS)
JSONSTRUCT_REGISTER(QvConfig_Connection, F(bypassCN, bypassBT, bypassLAN, enableProxy, v2rayFreedomDNS, withLocalDNS, dnsIntercept, fakeDNS))
};
struct QvConfig_SystemProxy
{
bool setSystemProxy = true;
JSONSTRUCT_COMPARE(QvConfig_SystemProxy, setSystemProxy)
JSONSTRUCT_REGISTER(QvConfig_SystemProxy, F(setSystemProxy))
};
struct __Qv2rayConfig_ProtocolInboundBase
{
int port;
int port = 0;
bool useAuth = false;
bool sniffing = false;
objects::AccountObject account;
__Qv2rayConfig_ProtocolInboundBase(int _port = 0) : port(_port){};
__Qv2rayConfig_ProtocolInboundBase(){};
JSONSTRUCT_COMPARE(__Qv2rayConfig_ProtocolInboundBase, port, useAuth, sniffing)
JSONSTRUCT_REGISTER(__Qv2rayConfig_ProtocolInboundBase, F(port, useAuth, sniffing, account))
};
@ -89,13 +87,19 @@ namespace Qv2ray::base::config
{
bool enableUDP = true;
QString localIP = "127.0.0.1";
QvConfig_SocksInbound() : __Qv2rayConfig_ProtocolInboundBase(1089){};
QvConfig_SocksInbound() : __Qv2rayConfig_ProtocolInboundBase()
{
port = 1089;
}
JSONSTRUCT_REGISTER(QvConfig_SocksInbound, B(__Qv2rayConfig_ProtocolInboundBase), F(enableUDP, localIP))
};
struct QvConfig_HttpInbound : __Qv2rayConfig_ProtocolInboundBase
{
QvConfig_HttpInbound() : __Qv2rayConfig_ProtocolInboundBase(8889){};
QvConfig_HttpInbound() : __Qv2rayConfig_ProtocolInboundBase()
{
port = 8889;
}
JSONSTRUCT_REGISTER(QvConfig_HttpInbound, B(__Qv2rayConfig_ProtocolInboundBase))
};
@ -108,6 +112,7 @@ namespace Qv2ray::base::config
bool hasUDP = true;
bool sniffing = true;
QString mode = "tproxy";
JSONSTRUCT_COMPARE(QvConfig_TProxy, tProxyIP, tProxyV6IP, port, hasTCP, hasUDP, sniffing, mode)
JSONSTRUCT_REGISTER(QvConfig_TProxy, F(tProxyIP, tProxyV6IP, port, hasTCP, hasUDP, sniffing, mode))
};
@ -122,6 +127,8 @@ namespace Qv2ray::base::config
QvConfig_HttpInbound httpSettings;
QvConfig_SocksInbound socksSettings;
QvConfig_SystemProxy systemProxySettings;
JSONSTRUCT_COMPARE(QvConfig_Inbounds, listenip, useSocks, useHTTP, useTPROXY, tProxySettings, httpSettings, socksSettings,
systemProxySettings)
JSONSTRUCT_REGISTER(QvConfig_Inbounds, //
F(listenip, useSocks, useHTTP, useTPROXY), //
F(tProxySettings, httpSettings, socksSettings, systemProxySettings))

View File

@ -42,12 +42,14 @@ namespace Qv2ray::base::safetype
{
T1 value1;
T2 value2;
JSONSTRUCT_REGISTER(___qvpair_t, F(value1, value2))
private:
typedef QvPair<T1, T2> ___qvpair_t;
friend bool operator==(const QvPair<T1, T2> &one, const QvPair<T1, T2> &another)
{
return another.value1 == one.value1 && another.value2 == one.value2;
}
JSONSTRUCT_REGISTER(___qvpair_t, F(value1, value2)) private : typedef QvPair<T1, T2> ___qvpair_t;
};
template<typename enumKey, typename TValue, typename = typename std::enable_if<std::is_enum<enumKey>::value>::type>
template<typename enumKey, typename TValue, typename = typename std::enable_if_t<std::is_enum_v<enumKey>>>
struct QvEnumMap : QMap<enumKey, TValue>
{
// WARN: Changing this will break all existing JSON.

View File

@ -23,6 +23,10 @@ namespace Qv2ray::base::config
this->width = w;
this->style = s;
};
friend bool operator==(const QvGraphPenConfig &one, const QvGraphPenConfig &another)
{
return one.R == another.R && one.G == another.G && one.B == another.B && one.width == another.width && one.style == another.style;
}
JSONSTRUCT_REGISTER(QvGraphPenConfig, F(R, G, B, width, style))
};
@ -31,6 +35,7 @@ namespace Qv2ray::base::config
bool useOutboundStats = true;
bool hasDirectStats = true;
safetype::QvEnumMap<StatisticsType, safetype::QvPair<QvGraphPenConfig>> colorConfig;
JSONSTRUCT_COMPARE(Qv2rayConfig_Graph, useOutboundStats, hasDirectStats, colorConfig)
JSONSTRUCT_REGISTER(Qv2rayConfig_Graph, F(useOutboundStats, hasDirectStats, colorConfig))
};
@ -46,6 +51,8 @@ namespace Qv2ray::base::config
int maximumLogLines = 500;
int maxJumpListCount = 20;
bool useOldShareLinkFormat = false;
JSONSTRUCT_COMPARE(Qv2rayConfig_UI, theme, language, quietMode, graphConfig, useDarkTheme, useDarkTrayIcon, maximumLogLines, maxJumpListCount,
recentConnections, useOldShareLinkFormat)
JSONSTRUCT_REGISTER(Qv2rayConfig_UI, F(theme, language, quietMode, graphConfig, useDarkTheme, useDarkTrayIcon, maximumLogLines,
maxJumpListCount, recentConnections, useOldShareLinkFormat))
};
@ -55,6 +62,7 @@ namespace Qv2ray::base::config
QMap<QString, bool> pluginStates;
bool v2rayIntegration = true;
int portAllocationStart = 15000;
JSONSTRUCT_COMPARE(Qv2rayConfig_Plugin, pluginStates, v2rayIntegration, portAllocationStart)
JSONSTRUCT_REGISTER(Qv2rayConfig_Plugin, F(pluginStates, v2rayIntegration, portAllocationStart))
};
@ -93,6 +101,10 @@ namespace Qv2ray::base::config
#undef _VARNAME_VCOREPATH_
#undef _VARNAME_VASSETSPATH_
JSONSTRUCT_COMPARE(Qv2rayConfig_Kernel, enableAPI, statsPort, //
v2CorePath_linux, v2AssetsPath_linux, //
v2CorePath_macx, v2AssetsPath_macx, //
v2CorePath_win, v2AssetsPath_win)
JSONSTRUCT_REGISTER(Qv2rayConfig_Kernel, //
F(enableAPI, statsPort), //
F(v2CorePath_linux, v2AssetsPath_linux), //
@ -109,6 +121,7 @@ namespace Qv2ray::base::config
};
UpdateChannel updateChannel = CHANNEL_STABLE;
QString ignoredVersion;
JSONSTRUCT_COMPARE(Qv2rayConfig_Update, updateChannel, ignoredVersion)
JSONSTRUCT_REGISTER(Qv2rayConfig_Update, F(ignoredVersion, updateChannel))
};
@ -119,7 +132,10 @@ namespace Qv2ray::base::config
bool testLatencyPeriodcally = false;
bool disableSystemRoot = false;
bool testLatencyOnConnected = false;
JSONSTRUCT_REGISTER(Qv2rayConfig_Advanced, F(setAllowInsecure, setSessionResumption, testLatencyPeriodcally, disableSystemRoot, testLatencyOnConnected))
JSONSTRUCT_COMPARE(Qv2rayConfig_Advanced, setAllowInsecure, setSessionResumption, testLatencyPeriodcally, disableSystemRoot,
testLatencyOnConnected)
JSONSTRUCT_REGISTER(Qv2rayConfig_Advanced,
F(setAllowInsecure, setSessionResumption, testLatencyPeriodcally, disableSystemRoot, testLatencyOnConnected))
};
enum Qv2rayLatencyTestingMethod
@ -145,6 +161,7 @@ namespace Qv2ray::base::config
QString type = "http";
int port = 8000;
QString userAgent = "Qv2ray/$VERSION WebRequestHelper";
JSONSTRUCT_COMPARE(Qv2rayConfig_Network, latencyTestingMethod, latencyRealPingTestURL, proxyType, type, address, port, userAgent)
JSONSTRUCT_REGISTER(Qv2rayConfig_Network, F(latencyTestingMethod, latencyRealPingTestURL, proxyType, type, address, port, userAgent))
};
@ -183,9 +200,11 @@ namespace Qv2ray::base::config
#else
Q_DISABLE_COPY_MOVE(Qv2rayConfigObject);
#endif
JSONSTRUCT_COMPARE(Qv2rayConfigObject, config_version, logLevel, autoStartId, lastConnectedId, autoStartBehavior, uiConfig, pluginConfig,
kernelConfig, updateConfig, networkConfig, inboundConfig, outboundConfig, advancedConfig, defaultRouteConfig)
JSONSTRUCT_REGISTER_NOCOPYMOVE(Qv2rayConfigObject, //
F(config_version, autoStartId, lastConnectedId, autoStartBehavior, logLevel), //
F(uiConfig, advancedConfig, pluginConfig, updateConfig, kernelConfig, networkConfig), //
F(inboundConfig, outboundConfig, defaultRouteConfig))
A(config_version, autoStartId, lastConnectedId, autoStartBehavior, logLevel), //
A(uiConfig, advancedConfig, pluginConfig, updateConfig, kernelConfig, networkConfig), //
A(inboundConfig, outboundConfig, defaultRouteConfig))
};
} // namespace Qv2ray::base::config

View File

@ -14,9 +14,9 @@ namespace Qv2ray::core::connection::generation::routing
if (withLocalhost)
servers.push_front("localhost");
root["servers"] = servers;
JAUTOREMOVE(root, "clientIp");
JAUTOREMOVE(root, "hosts");
JAUTOREMOVE(root, "tag");
// JAUTOREMOVE(root, "clientIp");
// JAUTOREMOVE(root, "hosts");
// JAUTOREMOVE(root, "tag");
return root;
}

View File

@ -97,8 +97,6 @@ namespace Qv2ray::core::handler
groupObject[key.toString()] = groups[key].toJson();
}
StringToFile(JsonToString(groupObject), QV2RAY_CONFIG_DIR + "groups.json");
RouteManager->SaveRoutes();
SaveGlobalSettings();
}
void QvConfigHandler::timerEvent(QTimerEvent *event)
@ -341,7 +339,6 @@ namespace Qv2ray::core::handler
void QvConfigHandler::StopConnection() // const ConnectionId &id
{
kernelHandler->StopConnection();
SaveConnectionConfig();
}
void QvConfigHandler::p_OnKernelCrashed(const ConnectionGroupPair &id, const QString &errMessage)

View File

@ -1,5 +1,5 @@
#pragma once
#include "3rdparty/QJsonStruct/QJsonStruct.hpp"
#include "QJsonStruct.hpp"
// GUI TOOLS
#define RED(obj) \
@ -16,6 +16,7 @@ struct HTTPSOCKSUserObject
QString user;
QString pass;
int level = 0;
JSONSTRUCT_COMPARE(HTTPSOCKSUserObject, user, pass, level)
JSONSTRUCT_REGISTER(HTTPSOCKSUserObject, F(user, pass, level))
};
//
@ -25,6 +26,7 @@ struct SocksServerObject
QString address = "0.0.0.0";
int port = 0;
QList<HTTPSOCKSUserObject> users;
JSONSTRUCT_COMPARE(SocksServerObject, address, port, users)
JSONSTRUCT_REGISTER(SocksServerObject, F(address, port, users))
};
@ -35,6 +37,7 @@ struct HttpServerObject
QString address = "0.0.0.0";
int port = 0;
QList<HTTPSOCKSUserObject> users;
JSONSTRUCT_COMPARE(HttpServerObject, address, port, users)
JSONSTRUCT_REGISTER(HttpServerObject, F(address, port, users))
};
@ -46,6 +49,7 @@ struct ShadowSocksServerObject
QString method = "aes-256-cfb";
QString password;
int port = 0;
JSONSTRUCT_COMPARE(ShadowSocksServerObject, address, method, password)
JSONSTRUCT_REGISTER(ShadowSocksServerObject, F(address, port, method, password))
};
@ -58,12 +62,14 @@ struct VLESSServerObject
QString id;
QString encryption = "none";
QString flow;
JSONSTRUCT_REGISTER(UserObject, F(id, encryption, flow))
JSONSTRUCT_COMPARE(UserObject, id, encryption, flow)
JSONSTRUCT_REGISTER(UserObject, A(encryption), F(id, flow))
};
QString address;
int port = 0;
QList<UserObject> users;
JSONSTRUCT_COMPARE(VLESSServerObject, address, port, users)
JSONSTRUCT_REGISTER(VLESSServerObject, F(address, port, users))
};
@ -78,11 +84,13 @@ struct VMessServerObject
int alterId = VMESS_USER_ALTERID_DEFAULT;
QString security = "auto";
int level = 0;
JSONSTRUCT_COMPARE(UserObject, id, alterId, security, level)
JSONSTRUCT_REGISTER(UserObject, F(id, alterId, security, level))
};
QString address;
int port = 0;
QList<UserObject> users;
JSONSTRUCT_COMPARE(VMessServerObject, address, port, users)
JSONSTRUCT_REGISTER(VMessServerObject, F(address, port, users))
};

View File

@ -29,6 +29,7 @@ ADD_SOURCE(inbound socksin)
set(BUILTIN_PROTOCOL_PLUGIN_SOURCES
${PLUGIN_UI_SOURCE}
${CMAKE_CURRENT_LIST_DIR}/../common/CommonTypes.hpp
${CMAKE_CURRENT_LIST_DIR}/BuiltinProtocolPlugin.hpp
${CMAKE_CURRENT_LIST_DIR}/BuiltinProtocolPlugin.cpp
${CMAKE_CURRENT_LIST_DIR}/core/OutboundHandler.cpp

View File

@ -20,7 +20,10 @@ void BlackholeOutboundEditor::changeEvent(QEvent *e)
void BlackholeOutboundEditor::SetContent(const QJsonObject &_content)
{
this->content = _content;
PLUGIN_EDITOR_LOADING_SCOPE({ responseTypeCB->setCurrentText(content["response"].toObject()["response"].toString()); })
PLUGIN_EDITOR_LOADING_SCOPE({
if (content.contains("response") && content["response"].toObject().contains("type"))
responseTypeCB->setCurrentText(content["response"].toObject()["type"].toString());
})
}
void BlackholeOutboundEditor::on_responseTypeCB_currentTextChanged(const QString &arg1)

View File

@ -114,7 +114,7 @@ void OutboundEditor::reloadGUI()
tag = originalConfig["tag"].toString();
tagTxt->setText(tag);
outboundType = originalConfig["protocol"].toString("vmess");
muxConfig = originalConfig["mux"].toObject();
muxConfig = originalConfig.contains("mux") ? originalConfig["mux"].toObject() : QJsonObject{};
useForwardProxy = originalConfig[QV2RAY_USE_FPROXY_KEY].toBool(false);
streamSettingsWidget->SetStreamObject(StreamSettingsObject::fromJson(originalConfig["streamSettings"].toObject()));
//

View File

@ -239,8 +239,6 @@ CONFIGROOT RouteEditor::OpenEditor()
{
const auto &ruleObject = rules[ruleTag];
auto ruleJson = ruleObject.toJson();
JAUTOREMOVE(ruleJson, "network");
JAUTOREMOVE(ruleJson, "port");
if (ruleJson["outboundTag"].toString().isEmpty())
ruleJson.remove("outboundTag");
else

View File

@ -64,7 +64,7 @@ void QvNodeRuleWidget::setValue(std::shared_ptr<RuleObject> _ruleptr)
routePortTxt->setText(rule.port);
//
// Users
const auto users = rule.user.join(NEWLINE);
const auto sourcePorts = rule.sourcePort;
//
// Incoming Sources
const auto sources = rule.source.join(NEWLINE);
@ -115,11 +115,6 @@ void QvNodeRuleWidget::on_routePortTxt_textEdited(const QString &arg1)
LOADINGCHECK
rule.port = arg1;
}
void QvNodeRuleWidget::on_routeUserTxt_textEdited(const QString &arg1)
{
LOADINGCHECK
rule.user = SplitLines(arg1);
}
void QvNodeRuleWidget::on_netUDPRB_clicked()
{

View File

@ -27,7 +27,6 @@ class QvNodeRuleWidget
void on_hostList_textChanged();
void on_ipList_textChanged();
void on_routePortTxt_textEdited(const QString &arg1);
void on_routeUserTxt_textEdited(const QString &arg1);
void on_netUDPRB_clicked();
void on_netTCPRB_clicked();
void on_sourceIPList_textChanged();

View File

@ -153,25 +153,13 @@ void StreamSettingsWidget::on_wsHeadersTxt_textChanged()
void StreamSettingsWidget::on_tcpRequestDefBtn_clicked()
{
tcpRequestTxt->clear();
tcpRequestTxt->setPlainText("{\"version\":\"1.1\",\"method\":\"GET\",\"path\":[\"/\"],\"headers\":"
"{\"Host\":[\"www.baidu.com\",\"www.bing.com\"],\"User-Agent\":"
"[\"Mozilla/5.0 (Windows NT 10.0; WOW64) "
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36\","
"\"Mozilla/5.0 (iPhone; CPU iPhone OS 10_0_2 like Mac OS X) "
"AppleWebKit/601.1 (KHTML, like Gecko) CriOS/53.0.2785.109 Mobile/14A456 "
"Safari/601.1.46\"],\"Accept-Encoding\":[\"gzip, deflate\"],"
"\"Connection\":[\"keep-alive\"],\"Pragma\":\"no-cache\"}}");
tcpRequestTxt->setPlainText(JsonToString(transfer::HTTPRequestObject().toJson()["headers"].toObject()));
}
void StreamSettingsWidget::on_tcpRespDefBtn_clicked()
{
tcpRespTxt->clear();
tcpRespTxt->setPlainText("{\"version\":\"1.1\",\"status\":\"200\",\""
"reason\":\"OK\",\"headers\":{\"Content-Typ"
"e\":[\"application/octet-stream\",\"video/"
"mpeg\"],\"Transfer-Encoding\":[\"chunked\""
"],\"Connection\":[\"keep-alive\"],\"Pragma"
"\":\"no-cache\"}}");
tcpRespTxt->setPlainText(JsonToString(transfer::HTTPResponseObject().toJson()["headers"].toObject()));
}
void StreamSettingsWidget::on_soMarkSpinBox_valueChanged(int arg1)

View File

@ -35,15 +35,13 @@ SCENARIO("Test Parse VMess V2 url", "[ParseVMessV2]")
const auto portParsed = QJsonIO::GetValue(result, "outbounds", 0, "settings", "vnext", 0, "port").toInt();
const auto idParsed = QJsonIO::GetValue(result, "outbounds", 0, "settings", "vnext", 0, "users", 0, "id").toString();
const auto alterIdParsed = QJsonIO::GetValue(result, "outbounds", 0, "settings", "vnext", 0, "users", 0, "alterId").toInt();
const auto typeParsed = QJsonIO::GetValue(result, "outbounds", 0, "streamSettings", "tcpSettings", "header", "type").toString();
REQUIRE(commentParsed.toStdString() == comment.toStdString());
REQUIRE(addressParsed.toStdString() == address.toStdString());
REQUIRE(portParsed == port);
REQUIRE(idParsed.toStdString() == uuid.toStdString());
REQUIRE(alterIdParsed == alterId);
REQUIRE(networkParsed.toStdString() == network.toStdString());
REQUIRE(typeParsed.toStdString() == "none");
REQUIRE(networkParsed.toStdString() == "");
}
}
}
@ -88,8 +86,6 @@ SCENARIO("Test Parse VMess V1 url", "[ParseVMessV1]")
REQUIRE(idParsed.toStdString() == uuid.toStdString());
REQUIRE(alterIdParsed == alterId);
REQUIRE(networkParsed.toStdString() == network.toStdString());
REQUIRE(typeParsed.toStdString() == "none");
REQUIRE(tlsParsed.toStdString() == "none");
}
}
}

View File

@ -2256,6 +2256,14 @@ Output: <byte value="xd"/>
<source>Please upgrade firstly up to Qv2ray v2.0/v2.1 and try again.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Qv2ray has encountered an uncaught exception: </source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Please report a bug via Github with the file located here: </source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Qv2ray::Qv2rayWidgetApplication</name>
@ -3271,4 +3279,339 @@ Maybe you have downloaded the wrong core?</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>dokodemodoorInEditor</name>
<message>
<source>Form</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Address</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Optional when using &quot;Follow Redirect&quot;</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Port</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Network</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>TCP</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>UDP</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Timeout</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Follow Redirect</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Enabled</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>httpInEditor</name>
<message>
<source>Form</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Allow Transparent</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Timeout</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>s</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Users</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Username</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Password</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PluginInboundEditor</name>
<message>
<source>Form</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>socksInEditor</name>
<message>
<source>Form</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>UDP</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Enabled</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>UDP Local IP</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>127.0.0.1</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Auth</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Users</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Username</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Password</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>blackholeOutEditor</name>
<message>
<source>Form</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Response</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Type</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>dnsOutEditor</name>
<message>
<source>Form</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Network</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>TCP</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>UDP</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Original</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Address</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Port</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>freedomOutEditor</name>
<message>
<source>Form</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Domain Strategy</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Redirect</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>:0</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>httpOutEditor</name>
<message>
<source>Form</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Username</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Password</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PluginOutboundEditor</name>
<message>
<source>Form</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>shadowsocksOutEditor</name>
<message>
<source>Form</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Password</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Encryption Method</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>socksOutEditor</name>
<message>
<source>Form</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Username</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Password</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>vlessOutEditor</name>
<message>
<source>Form</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>UUID</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Encryption</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Flow</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&lt;h3&gt;Notes for &lt;code&gt;udp443&lt;/code&gt; Methods&lt;/h3&gt;
&lt;p&gt;Some applications like Google Chrome would attempt to use QUIC protocol instead of TLS, which, won&apos;t benefit from XTLS at all. What&apos;s worse, QUIC over TCP will cause potential congestion control problem, downgrading your experience.&lt;/p&gt;
&lt;p&gt;Non-&lt;code&gt;udp443&lt;/code&gt; methods block UDP 443 outbound traffic to workaround this situation. If you do want to let it go, use at your own peril.&lt;/p&gt;</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>vmessOutEditor</name>
<message>
<source>Form</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>UUID</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Alter ID</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Security</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PluginSettingsWidget</name>
<message>
<source>Form</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>MainWindowForm.ui</name>
<message>
<source>Qv2ray</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>HTTPInboundEditor</name>
<message>
<source>Removing a user</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>You haven&apos;t selected a user yet.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Add a user</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>This user exists already.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SocksInboundEditor</name>
<message>
<source>Removing a user</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>You haven&apos;t selected a user yet.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Add a user</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>This user exists already.</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>