mirror of
https://github.com/Mahdi-zarei/nekoray.git
synced 2025-12-19 05:30:06 +08:00
Implement vless xray config items
This commit is contained in:
parent
721d79f981
commit
a5190e7e4d
@ -293,6 +293,9 @@ set(PROJECT_SOURCES
|
||||
include/configs/common/xrayStreamSetting.h
|
||||
include/configs/outbounds/xrayVless.h
|
||||
include/configs/common/xrayMultiplex.h
|
||||
src/configs/common/xrayMultiplex.cpp
|
||||
src/configs/common/xrayStreamSetting.cpp
|
||||
src/configs/outbounds/xrayVless.cpp
|
||||
)
|
||||
|
||||
if (NOT APPLE AND Qt6_VERSION VERSION_GREATER_EQUAL 6.9.0)
|
||||
|
||||
@ -28,17 +28,14 @@ namespace Configs {
|
||||
|
||||
class xrayReality : public baseConfig {
|
||||
public:
|
||||
QString target;
|
||||
QString privateKey;
|
||||
QString fingerprint;
|
||||
QString serverName;
|
||||
QString fingerprint;
|
||||
QString password;
|
||||
QString shortId;
|
||||
QString spiderX;
|
||||
|
||||
xrayReality() {
|
||||
_add(new configItem("target", &target, string));
|
||||
_add(new configItem("privateKey", &privateKey, string));
|
||||
_add(new configItem("serverName", &serverName, string));
|
||||
_add(new configItem("fingerprint", &fingerprint, string));
|
||||
_add(new configItem("serverName", &serverName, string));
|
||||
_add(new configItem("password", &password, string));
|
||||
@ -57,19 +54,19 @@ namespace Configs {
|
||||
public:
|
||||
QString host;
|
||||
QString path;
|
||||
QString mode;
|
||||
QString mode = "auto";
|
||||
// extra
|
||||
QStringList headers;
|
||||
QString xPaddingBytes;
|
||||
QString xPaddingBytes = "100-1000";
|
||||
bool noGRPCHeader = false;
|
||||
int scMaxEachPostBytes = 1000000; // packet-up only
|
||||
int scMinPostsIntervalMs = 30; // packet-up only
|
||||
// extra/xmux
|
||||
QString maxConcurrency;
|
||||
QString maxConcurrency = "16-32";
|
||||
int maxConnections;
|
||||
int cMaxReuseTimes;
|
||||
QString hMaxRequestTimes;
|
||||
QString hMaxReusableSecs;
|
||||
QString hMaxRequestTimes = "600-900";
|
||||
QString hMaxReusableSecs = "1800-3000";
|
||||
int hKeepAlivePeriod;
|
||||
// todo do we need to add downloadsettings or is it useless?
|
||||
|
||||
|
||||
47
src/configs/common/xrayMultiplex.cpp
Normal file
47
src/configs/common/xrayMultiplex.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
#include "include/configs/common/xrayMultiplex.h"
|
||||
|
||||
#include <QUrlQuery>
|
||||
|
||||
namespace Configs {
|
||||
bool xrayMultiplex::ParseFromLink(const QString &link) {
|
||||
auto url = QUrl(link);
|
||||
if (!url.isValid()) return false;
|
||||
auto query = QUrlQuery(url.query(QUrl::ComponentFormattingOption::FullyDecoded));
|
||||
|
||||
if (query.hasQueryItem("mux")) enabled = query.queryItemValue("mux").replace("1", "true") == "true";
|
||||
if (query.hasQueryItem("mux_concurrency")) concurrency = query.queryItemValue("mux_concurrency").toInt();
|
||||
if (query.hasQueryItem("mux_xudp_concurrency")) xudpConcurrency = query.queryItemValue("mux_xudp_concurrency").toInt();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool xrayMultiplex::ParseFromJson(const QJsonObject &object) {
|
||||
if (object.isEmpty()) return false;
|
||||
if (object.contains("enabled")) enabled = object["enabled"].toBool();
|
||||
if (object.contains("concurrency")) concurrency = object["concurrency"].toInt();
|
||||
if (object.contains("xudpConcurrency")) xudpConcurrency = object["xudpConcurrency"].toInt();
|
||||
return true;
|
||||
}
|
||||
|
||||
QString xrayMultiplex::ExportToLink() {
|
||||
QUrlQuery query;
|
||||
if (!enabled) return "";
|
||||
query.addQueryItem("mux", "true");
|
||||
if (concurrency > 0) query.addQueryItem("mux_concurrency", QString::number(concurrency));
|
||||
if (xudpConcurrency > 0) query.addQueryItem("mux_xudp_concurrency", QString::number(xudpConcurrency));
|
||||
return QUrlQuery(query).toString();
|
||||
}
|
||||
|
||||
QJsonObject xrayMultiplex::ExportToJson() {
|
||||
QJsonObject object;
|
||||
if (!enabled) return object;
|
||||
object["enabled"] = enabled;
|
||||
if (concurrency > 0) object["concurrency"] = concurrency;
|
||||
if (xudpConcurrency > 0) object["xudpConcurrency"] = xudpConcurrency;
|
||||
return object;
|
||||
}
|
||||
|
||||
BuildResult xrayMultiplex::Build() {
|
||||
// TODO add xray default enable mux to settings and use it here
|
||||
return {ExportToJson(), ""};
|
||||
}
|
||||
}
|
||||
253
src/configs/common/xrayStreamSetting.cpp
Normal file
253
src/configs/common/xrayStreamSetting.cpp
Normal file
@ -0,0 +1,253 @@
|
||||
#include "include/configs/common/xrayStreamSetting.h"
|
||||
|
||||
#include <QUrlQuery>
|
||||
#include <QJsonArray>
|
||||
|
||||
#include "include/configs/common/utils.h"
|
||||
|
||||
namespace Configs {
|
||||
bool xrayTLS::ParseFromLink(const QString &link) {
|
||||
auto url = QUrl(link);
|
||||
if (!url.isValid()) return false;
|
||||
auto query = QUrlQuery(url.query(QUrl::ComponentFormattingOption::FullyDecoded));
|
||||
|
||||
if (query.hasQueryItem("sni")) serverName = query.queryItemValue("sni");
|
||||
if (query.hasQueryItem("peer")) serverName = query.queryItemValue("peer");
|
||||
if (query.hasQueryItem("server_name")) serverName = query.queryItemValue("server_name");
|
||||
if (query.hasQueryItem("allowInsecure")) allowInsecure = query.queryItemValue("allowInsecure").replace("1", "true") == "true";
|
||||
if (query.hasQueryItem("allow_insecure")) allowInsecure = query.queryItemValue("allow_insecure").replace("1", "true") == "true";
|
||||
if (query.hasQueryItem("insecure")) allowInsecure = query.queryItemValue("insecure").replace("1", "true") == "true";
|
||||
if (query.hasQueryItem("alpn")) alpn = query.queryItemValue("alpn").split(",");
|
||||
if (query.hasQueryItem("fp")) fingerprint = query.queryItemValue("fp");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool xrayTLS::ParseFromJson(const QJsonObject &object) {
|
||||
if (object.isEmpty()) return false;
|
||||
if (object.contains("serverName")) serverName = object["serverName"].toString();
|
||||
if (object.contains("allowInsecure")) allowInsecure = object["allowInsecure"].toBool();
|
||||
if (object.contains("alpn")) QJsonArray2QListString(object["alpn"].toArray());
|
||||
if (object.contains("fingerprint")) fingerprint = object["fingerprint"].toString();
|
||||
return true;
|
||||
}
|
||||
|
||||
QString xrayTLS::ExportToLink() {
|
||||
QUrlQuery query;
|
||||
query.addQueryItem("sni", serverName);
|
||||
if (allowInsecure) query.addQueryItem("allowInsecure", "1");
|
||||
if (!alpn.isEmpty()) query.addQueryItem("alpn", alpn.join(","));
|
||||
if (!fingerprint.isEmpty()) query.addQueryItem("fp", fingerprint);
|
||||
return query.toString();
|
||||
}
|
||||
|
||||
QJsonObject xrayTLS::ExportToJson() {
|
||||
QJsonObject object;
|
||||
object["serverName"] = serverName;
|
||||
if (allowInsecure) object["allowInsecure"] = allowInsecure;
|
||||
if (!alpn.isEmpty()) {
|
||||
object["alpn"] = QListStr2QJsonArray(alpn);
|
||||
}
|
||||
if (!fingerprint.isEmpty()) object["fingerprint"] = fingerprint;
|
||||
return object;
|
||||
}
|
||||
|
||||
BuildResult xrayTLS::Build() {
|
||||
// TODO add xray default fp, and use it here
|
||||
return {ExportToJson(), ""};
|
||||
}
|
||||
|
||||
bool xrayReality::ParseFromLink(const QString &link) {
|
||||
auto url = QUrl(link);
|
||||
if (!url.isValid()) return false;
|
||||
auto query = QUrlQuery(url.query(QUrl::ComponentFormattingOption::FullyDecoded));
|
||||
|
||||
if (query.hasQueryItem("sni")) serverName = query.queryItemValue("sni");
|
||||
if (query.hasQueryItem("peer")) serverName = query.queryItemValue("peer");
|
||||
if (query.hasQueryItem("pbk")) password = query.queryItemValue("pbk");
|
||||
if (query.hasQueryItem("fp")) fingerprint = query.queryItemValue("fp");
|
||||
if (query.hasQueryItem("sid")) shortId = query.queryItemValue("sid");
|
||||
if (query.hasQueryItem("spiderx")) spiderX = query.queryItemValue("spiderx");
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
bool xrayReality::ParseFromJson(const QJsonObject &object) {
|
||||
if (object.isEmpty()) return false;
|
||||
if (object.contains("serverName")) serverName = object["serverName"].toString();
|
||||
if (object.contains("fingerprint")) fingerprint = object["fingerprint"].toString();
|
||||
if (object.contains("password")) password = object["password"].toString();
|
||||
if (object.contains("shortId")) shortId = object["shortId"].toString();
|
||||
if (object.contains("shortId")) shortId = object["shortId"].toString();
|
||||
if (object.contains("spiderX")) spiderX = object["spiderX"].toString();
|
||||
return true;
|
||||
}
|
||||
|
||||
QString xrayReality::ExportToLink() {
|
||||
QUrlQuery query;
|
||||
query.addQueryItem("sni", serverName);
|
||||
if (!fingerprint.isEmpty()) query.addQueryItem("fp", fingerprint);
|
||||
if (!password.isEmpty()) query.addQueryItem("pbk", password);
|
||||
if (!shortId.isEmpty()) query.addQueryItem("sid", shortId);
|
||||
if (!spiderX.isEmpty()) query.addQueryItem("spiderx", spiderX);
|
||||
return query.toString();
|
||||
}
|
||||
|
||||
QJsonObject xrayReality::ExportToJson() {
|
||||
QJsonObject object;
|
||||
object["serverName"] = serverName;
|
||||
if (!fingerprint.isEmpty()) object["fingerprint"] = fingerprint;
|
||||
if (!password.isEmpty()) object["password"] = password;
|
||||
if (!shortId.isEmpty()) object["shortId"] = shortId;
|
||||
if (!spiderX.isEmpty()) object["spiderX"] = spiderX;
|
||||
return object;
|
||||
}
|
||||
|
||||
BuildResult xrayReality::Build() {
|
||||
// TODO handle default fingerprint here too
|
||||
return {ExportToJson(), ""};
|
||||
}
|
||||
|
||||
bool xrayXHTTP::ParseFromLink(const QString &link) {
|
||||
auto url = QUrl(link);
|
||||
if (!url.isValid()) return false;
|
||||
auto query = QUrlQuery(url.query(QUrl::ComponentFormattingOption::FullyDecoded));
|
||||
|
||||
if (query.hasQueryItem("host")) host = query.queryItemValue("host");
|
||||
if (query.hasQueryItem("path")) path = query.queryItemValue("path");
|
||||
if (query.hasQueryItem("mode")) mode = query.queryItemValue("mode");
|
||||
if (query.hasQueryItem("headers")) headers = query.queryItemValue("headers").split(",");
|
||||
if (query.hasQueryItem("x_padding_bytes")) xPaddingBytes = query.queryItemValue("xpaddingbytes");
|
||||
if (query.hasQueryItem("no_grpc_header")) noGRPCHeader = query.queryItemValue("nogrpcheader").replace("1", "true") == "true";
|
||||
if (query.hasQueryItem("sc_max_each_post_bytes")) scMaxEachPostBytes = query.queryItemValue("sc_max_each_post_bytes").toInt();
|
||||
if (query.hasQueryItem("sc_min_posts_interval_ms")) scMinPostsIntervalMs = query.queryItemValue("sc_min_posts_interval_ms").toInt();
|
||||
if (query.hasQueryItem("max_concurrency")) maxConcurrency = query.queryItemValue("max_concurrency");
|
||||
if (query.hasQueryItem("max_connections")) maxConnections = query.queryItemValue("max_connections").toInt();
|
||||
if (query.hasQueryItem("max_reuse_times")) cMaxReuseTimes = query.queryItemValue("max_reuse_times").toInt();
|
||||
if (query.hasQueryItem("max_request_times")) hMaxRequestTimes = query.queryItemValue("max_request_times");
|
||||
if (query.hasQueryItem("max_reusable_secs")) hMaxReusableSecs = query.queryItemValue("max_reusable_secs");
|
||||
if (query.hasQueryItem("keep_alive_period")) hKeepAlivePeriod = query.queryItemValue("keep_alive_period").toInt();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool xrayXHTTP::ParseFromJson(const QJsonObject &object) {
|
||||
if (object.isEmpty()) return false;
|
||||
if (object.contains("host")) host = object["host"].toString();
|
||||
if (object.contains("path")) path = object["path"].toString();
|
||||
if (object.contains("mode")) mode = object["mode"].toString();
|
||||
if (auto exObj = object["ex"].toObject(); !exObj.isEmpty()) {
|
||||
if (exObj.contains("headers") && exObj["headers"].isArray()) {
|
||||
headers = QJsonArray2QListString(exObj["headers"].toArray());
|
||||
}
|
||||
if (exObj.contains("xPaddingBytes")) xPaddingBytes = exObj["xPaddingBytes"].toString();
|
||||
if (exObj.contains("noGRPCHeader")) noGRPCHeader = exObj["noGRPCHeader"].toBool();
|
||||
if (exObj.contains("scMaxEachPostBytes")) scMaxEachPostBytes = exObj["scMaxEachPostBytes"].toInt();
|
||||
if (exObj.contains("scMinPostsIntervalMs")) scMinPostsIntervalMs = exObj["scMinPostsIntervalMs"].toInt();
|
||||
if (auto xmuxObj = exObj["xmux"].toObject(); !xmuxObj.isEmpty()) {
|
||||
if (xmuxObj.contains("maxConcurrency")) maxConcurrency = xmuxObj["maxConcurrency"].toString();
|
||||
if (xmuxObj.contains("maxConnections")) maxConnections = xmuxObj["maxConnections"].toInt();
|
||||
if (xmuxObj.contains("cMaxReuseTimes")) cMaxReuseTimes = xmuxObj["cMaxReuseTimes"].toInt();
|
||||
if (xmuxObj.contains("hMaxRequestTimes")) hMaxRequestTimes = xmuxObj["hMaxRequestTimes"].toString();
|
||||
if (xmuxObj.contains("hMaxReusableSecs")) hMaxReusableSecs = xmuxObj["hMaxReusableSecs"].toString();
|
||||
if (xmuxObj.contains("hKeepAlivePeriod")) hKeepAlivePeriod = xmuxObj["hKeepAlivePeriod"].toInt();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
QString xrayXHTTP::ExportToLink() {
|
||||
QUrlQuery query;
|
||||
if (!host.isEmpty()) query.addQueryItem("host", host);
|
||||
if (!path.isEmpty()) query.addQueryItem("path", path);
|
||||
if (!mode.isEmpty()) query.addQueryItem("mode", mode);
|
||||
if (!headers.isEmpty()) query.addQueryItem("headers", headers.join(","));
|
||||
if (!xPaddingBytes.isEmpty()) query.addQueryItem("x_padding_bytes", xPaddingBytes);
|
||||
if (noGRPCHeader) query.addQueryItem("no_grpc_header", "true");
|
||||
if (scMaxEachPostBytes > 0) query.addQueryItem("sc_max_each_post_bytes", QString::number(scMaxEachPostBytes));
|
||||
if (scMinPostsIntervalMs > 0) query.addQueryItem("sc_min_posts_interval_ms", QString::number(scMinPostsIntervalMs));
|
||||
if (!maxConcurrency.isEmpty()) query.addQueryItem("max_concurrency", maxConcurrency);
|
||||
if (maxConnections > 0) query.addQueryItem("max_connections", QString::number(maxConnections));
|
||||
if (cMaxReuseTimes > 0) query.addQueryItem("max_reuse_times", QString::number(cMaxReuseTimes));
|
||||
if (!hMaxRequestTimes.isEmpty()) query.addQueryItem("max_request_times", hMaxRequestTimes);
|
||||
if (!hMaxReusableSecs.isEmpty()) query.addQueryItem("max_reusable_secs", hMaxReusableSecs);
|
||||
if (hKeepAlivePeriod > 0) query.addQueryItem("keep_alive_period", QString::number(hKeepAlivePeriod));
|
||||
return query.toString();
|
||||
}
|
||||
|
||||
QJsonObject xrayXHTTP::ExportToJson() {
|
||||
QJsonObject obj;
|
||||
if (!host.isEmpty()) obj["host"] = host;
|
||||
if (!path.isEmpty()) obj["path"] = path;
|
||||
if (!mode.isEmpty()) obj["mode"] = mode;
|
||||
QJsonObject extraObj;
|
||||
if (!headers.isEmpty()) extraObj["headers"] = qStringListToJsonObject(headers);
|
||||
if (!xPaddingBytes.isEmpty()) extraObj["xPaddingBytes"] = xPaddingBytes;
|
||||
if (noGRPCHeader) extraObj["noGRPCHeader"] = true;
|
||||
if (scMaxEachPostBytes > 0) extraObj["scMaxEachPostBytes"] = scMaxEachPostBytes;
|
||||
if (scMinPostsIntervalMs > 0) extraObj["scMinPostsIntervalMs"] = scMinPostsIntervalMs;
|
||||
QJsonObject xmuxObj;
|
||||
if (!maxConcurrency.isEmpty()) xmuxObj["maxConcurrency"] = maxConcurrency;
|
||||
if (maxConnections > 0) xmuxObj["maxConnections"] = maxConnections;
|
||||
if (cMaxReuseTimes > 0) xmuxObj["cMaxReuseTimes"] = cMaxReuseTimes;
|
||||
if (!hMaxRequestTimes.isEmpty()) xmuxObj["hMaxRequestTimes"] = hMaxRequestTimes;
|
||||
if (!hMaxReusableSecs.isEmpty()) xmuxObj["hMaxReusableSecs"] = hMaxReusableSecs;
|
||||
if (hKeepAlivePeriod > 0) xmuxObj["hMaxReusableSecs"] = hMaxReusableSecs;
|
||||
if (!xmuxObj.isEmpty()) extraObj["xmux"] = xmuxObj;
|
||||
if (!extraObj.isEmpty()) obj["extra"] = extraObj;
|
||||
return obj;
|
||||
}
|
||||
|
||||
BuildResult xrayXHTTP::Build() {
|
||||
return {ExportToJson(), ""};
|
||||
}
|
||||
|
||||
bool xrayStreamSetting::ParseFromLink(const QString &link) {
|
||||
auto url = QUrl(link);
|
||||
if (!url.isValid()) return false;
|
||||
auto query = QUrlQuery(url.query(QUrl::ComponentFormattingOption::FullyDecoded));
|
||||
|
||||
if (query.hasQueryItem("network")) network = query.queryItemValue("network");
|
||||
if (network != "raw" && network != "xhttp") return false;
|
||||
if (query.hasQueryItem("security")) security = query.queryItemValue("security");
|
||||
if (security == "tls") TLS->ParseFromLink(link);
|
||||
else if (security == "reality") reality->ParseFromLink(link);
|
||||
xhttp->ParseFromLink(link);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool xrayStreamSetting::ParseFromJson(const QJsonObject &object) {
|
||||
if (object.isEmpty()) return false;
|
||||
|
||||
if (object.contains("network")) network = object.value("network").toString();
|
||||
if (network != "raw" && network != "xhttp") return false;
|
||||
if (object.contains("security")) security = object.value("security").toString();
|
||||
if (security == "tls" && object["tlsSettings"].isObject()) TLS->ParseFromJson(object["tlsSettings"].toObject());
|
||||
else if (security == "reality" && object["realitySettings"].isObject()) reality->ParseFromJson(object["realitySettings"].toObject());
|
||||
if (network == "xhttp" && object["xhttpSettings"].isObject()) xhttp->ParseFromJson(object["xhttpSettings"].toObject());
|
||||
return true;
|
||||
}
|
||||
|
||||
QString xrayStreamSetting::ExportToLink() {
|
||||
QUrlQuery query;
|
||||
if (!network.isEmpty()) query.addQueryItem("network", network);
|
||||
if (!security.isEmpty()) query.addQueryItem("security", security);
|
||||
mergeUrlQuery(query, TLS->ExportToLink());
|
||||
mergeUrlQuery(query, reality->ExportToLink());
|
||||
mergeUrlQuery(query, xhttp->ExportToLink());
|
||||
return query.toString();
|
||||
}
|
||||
|
||||
QJsonObject xrayStreamSetting::ExportToJson() {
|
||||
QJsonObject object;
|
||||
object["network"] = network;
|
||||
object["security"] = security;
|
||||
if (security == "tls") object["tlsSettings"] = TLS->ExportToJson();
|
||||
else if (security == "reality") object["realitySettings"] = reality->ExportToJson();
|
||||
if (network == "xhttp") object["xhttpSettings"] = xhttp->ExportToJson();
|
||||
return object;
|
||||
}
|
||||
|
||||
BuildResult xrayStreamSetting::Build() {
|
||||
return {ExportToJson(), ""};
|
||||
}
|
||||
}
|
||||
86
src/configs/outbounds/xrayVless.cpp
Normal file
86
src/configs/outbounds/xrayVless.cpp
Normal file
@ -0,0 +1,86 @@
|
||||
#include "include/configs/outbounds/xrayVless.h"
|
||||
|
||||
#include <QUrlQuery>
|
||||
|
||||
#include "include/configs/common/utils.h"
|
||||
|
||||
namespace Configs {
|
||||
bool xrayVless::ParseFromLink(const QString &link) {
|
||||
auto url = QUrl(link);
|
||||
if (!url.isValid()) return false;
|
||||
auto query = QUrlQuery(url.query(QUrl::ComponentFormattingOption::FullyDecoded));
|
||||
|
||||
outbound::ParseFromLink(link);
|
||||
uuid = url.userName();
|
||||
flow = GetQueryValue(query, "flow", "");
|
||||
streamSetting->ParseFromLink(link);
|
||||
multiplex->ParseFromLink(link);
|
||||
return !(uuid.isEmpty() || server.isEmpty());
|
||||
}
|
||||
|
||||
bool xrayVless::ParseFromJson(const QJsonObject &object) {
|
||||
if (object.isEmpty() || object["protocol"].toString() != "vless") return false;
|
||||
if (auto settingsObj = object["settings"].toObject(); !settingsObj.isEmpty()) {
|
||||
uuid = settingsObj["uuid"].toString();
|
||||
if (settingsObj.contains("encryption")) encryption = settingsObj["encryption"].toString();
|
||||
if (settingsObj.contains("flow")) flow = settingsObj["flow"].toString();
|
||||
}
|
||||
if (auto streamSettings = object["streamSettings"].toObject(); !streamSettings.isEmpty()) {
|
||||
streamSetting->ParseFromJson(streamSettings);
|
||||
}
|
||||
if (auto muxObj = object["mux"].toObject(); !muxObj.isEmpty()) {
|
||||
multiplex->ParseFromJson(muxObj);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
QString xrayVless::ExportToLink() {
|
||||
QUrl url;
|
||||
QUrlQuery query;
|
||||
url.setScheme("vless");
|
||||
url.setUserName(uuid);
|
||||
url.setHost(server);
|
||||
url.setPort(server_port);
|
||||
if (!name.isEmpty()) url.setFragment(name);
|
||||
|
||||
query.addQueryItem("encryption", encryption);
|
||||
if (!flow.isEmpty()) query.addQueryItem("flow", flow);
|
||||
|
||||
mergeUrlQuery(query, streamSetting->ExportToLink());
|
||||
mergeUrlQuery(query, multiplex->ExportToLink());
|
||||
|
||||
if (!query.isEmpty()) url.setQuery(query);
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
QJsonObject xrayVless::ExportToJson() {
|
||||
QJsonObject object;
|
||||
if (!name.isEmpty()) object["tag"] = name;
|
||||
object["protocol"] = "vless";
|
||||
QJsonObject settings;
|
||||
settings["address"] = server;
|
||||
settings["port"] = server_port;
|
||||
settings["id"] = uuid;
|
||||
settings["encryption"] = encryption;
|
||||
settings["flow"] = flow;
|
||||
object["settings"] = settings;
|
||||
if (auto streamObj = streamSetting->ExportToJson(); !streamObj.isEmpty()) object["streamSettings"] = streamObj;
|
||||
if (auto muxObj = multiplex->ExportToJson(); !muxObj.isEmpty()) object["mux"] = muxObj;
|
||||
return object;
|
||||
}
|
||||
|
||||
BuildResult xrayVless::Build() {
|
||||
QJsonObject object;
|
||||
object["protocol"] = "vless";
|
||||
QJsonObject settings;
|
||||
settings["address"] = server;
|
||||
settings["port"] = server_port;
|
||||
settings["id"] = uuid;
|
||||
settings["encryption"] = encryption;
|
||||
settings["flow"] = flow;
|
||||
object["settings"] = settings;
|
||||
if (auto streamObj = streamSetting->Build().object; !streamObj.isEmpty()) object["streamSettings"] = streamObj;
|
||||
if (auto muxObj = multiplex->Build().object; !muxObj.isEmpty()) object["mux"] = muxObj;
|
||||
return {object, ""};
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user