mirror of
https://github.com/Mahdi-zarei/nekoray.git
synced 2025-12-26 03:11:21 +08:00
lots of changes, will clarify later if works
This commit is contained in:
parent
773f07169b
commit
971e56937b
23
.github/workflows/build-qv2ray-cmake.yml
vendored
23
.github/workflows/build-qv2ray-cmake.yml
vendored
@ -25,25 +25,24 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checking out sources
|
- name: Checking out sources
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4.1.4
|
||||||
- name: Go Status
|
- name: Go Status
|
||||||
run: git ls-files go | xargs cat | sha1sum > go_status
|
run: git ls-files go | xargs cat | sha1sum > go_status
|
||||||
- name: Cache Common Download
|
- name: Cache Common Download
|
||||||
id: cache-common
|
id: cache-common
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v4.0.2
|
||||||
with:
|
with:
|
||||||
path: artifacts.tgz
|
path: artifacts.tgz
|
||||||
key: CommonCache-${{ matrix.cross_os }}-${{ matrix.cross_arch }}-${{ hashFiles('libs/*.sh', 'go_status', '*.txt') }}
|
key: CommonCache-${{ matrix.cross_os }}-${{ matrix.cross_arch }}-${{ hashFiles('libs/*.sh', 'go_status', '*.txt') }}
|
||||||
- name: Install Golang
|
- name: Install Golang
|
||||||
if: steps.cache-common.outputs.cache-hit != 'true'
|
if: steps.cache-common.outputs.cache-hit != 'true'
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v5.0.0
|
||||||
with:
|
with:
|
||||||
go-version: ^1.21
|
go-version: ^1.22
|
||||||
- name: Build golang parts
|
- name: Build golang parts
|
||||||
if: steps.cache-common.outputs.cache-hit != 'true'
|
if: steps.cache-common.outputs.cache-hit != 'true'
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
[ ${{ matrix.cross_os }} == public_res ] || ./libs/get_source.sh
|
|
||||||
[ ${{ matrix.cross_os }} == public_res ] || GOOS=${{ matrix.cross_os }} GOARCH=${{ matrix.cross_arch }} ./libs/build_go.sh
|
[ ${{ matrix.cross_os }} == public_res ] || GOOS=${{ matrix.cross_os }} GOARCH=${{ matrix.cross_arch }} ./libs/build_go.sh
|
||||||
[ ${{ matrix.cross_os }} == public_res ] || exit 0
|
[ ${{ matrix.cross_os }} == public_res ] || exit 0
|
||||||
./libs/build_public_res.sh
|
./libs/build_public_res.sh
|
||||||
@ -51,7 +50,7 @@ jobs:
|
|||||||
if: steps.cache-common.outputs.cache-hit != 'true'
|
if: steps.cache-common.outputs.cache-hit != 'true'
|
||||||
run: tar czvf artifacts.tgz ./deployment
|
run: tar czvf artifacts.tgz ./deployment
|
||||||
- name: Uploading Artifact
|
- name: Uploading Artifact
|
||||||
uses: actions/upload-artifact@master
|
uses: actions/upload-artifact@v4.3.3
|
||||||
with:
|
with:
|
||||||
name: NekoRay-${{ github.sha }}-Common-${{ matrix.cross_os }}-${{ matrix.cross_arch }}
|
name: NekoRay-${{ github.sha }}-Common-${{ matrix.cross_os }}-${{ matrix.cross_arch }}
|
||||||
path: artifacts.tgz
|
path: artifacts.tgz
|
||||||
@ -72,7 +71,7 @@ jobs:
|
|||||||
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
|
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
|
||||||
steps:
|
steps:
|
||||||
- name: Checking out sources
|
- name: Checking out sources
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4.1.4
|
||||||
with:
|
with:
|
||||||
submodules: "recursive"
|
submodules: "recursive"
|
||||||
- name: Install MSVC compiler
|
- name: Install MSVC compiler
|
||||||
@ -94,7 +93,7 @@ jobs:
|
|||||||
uses: seanmiddleditch/gha-setup-ninja@v3
|
uses: seanmiddleditch/gha-setup-ninja@v3
|
||||||
- name: Cache Download
|
- name: Cache Download
|
||||||
id: cache-deps
|
id: cache-deps
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v4.0.2
|
||||||
with:
|
with:
|
||||||
path: libs/deps
|
path: libs/deps
|
||||||
key: DepsCache-${{ matrix.platform }}-${{ matrix.arch }}-${{ hashFiles('libs/build_deps_*.sh') }}-Qt${{ matrix.qt_version }}
|
key: DepsCache-${{ matrix.platform }}-${{ matrix.arch }}-${{ hashFiles('libs/build_deps_*.sh') }}-Qt${{ matrix.qt_version }}
|
||||||
@ -141,7 +140,7 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
run: tar czvf artifacts.tgz ./deployment
|
run: tar czvf artifacts.tgz ./deployment
|
||||||
- name: Uploading Artifact
|
- name: Uploading Artifact
|
||||||
uses: actions/upload-artifact@master
|
uses: actions/upload-artifact@v4.3.3
|
||||||
with:
|
with:
|
||||||
name: NekoRay-${{ github.sha }}-${{ matrix.platform }}-${{ matrix.arch }}-Qt${{ matrix.qt_version }}
|
name: NekoRay-${{ github.sha }}-${{ matrix.platform }}-${{ matrix.arch }}-Qt${{ matrix.qt_version }}
|
||||||
path: artifacts.tgz
|
path: artifacts.tgz
|
||||||
@ -154,9 +153,9 @@ jobs:
|
|||||||
- build-go
|
- build-go
|
||||||
steps:
|
steps:
|
||||||
- name: Checking out sources
|
- name: Checking out sources
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4.1.4
|
||||||
- name: Download Artifacts
|
- name: Download Artifacts
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v4.1.7
|
||||||
with:
|
with:
|
||||||
path: download-artifact
|
path: download-artifact
|
||||||
- name: Pack
|
- name: Pack
|
||||||
@ -205,7 +204,7 @@ jobs:
|
|||||||
rm -rf public_res
|
rm -rf public_res
|
||||||
rm -rf *.pdb
|
rm -rf *.pdb
|
||||||
- name: Uploading Artifact
|
- name: Uploading Artifact
|
||||||
uses: actions/upload-artifact@master
|
uses: actions/upload-artifact@v4.3.3
|
||||||
with:
|
with:
|
||||||
name: Deployment-${{ github.sha }}
|
name: Deployment-${{ github.sha }}
|
||||||
path: deployment
|
path: deployment
|
||||||
|
|||||||
18
.github/workflows/update-pkgbuild.yml
vendored
18
.github/workflows/update-pkgbuild.yml
vendored
@ -1,18 +0,0 @@
|
|||||||
name: AUR CI
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
paths-ignore:
|
|
||||||
- '**.md'
|
|
||||||
- 'LICENSE'
|
|
||||||
- '!.github/workflows/**'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
update:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: chitang233/aur-pkgbuild-builder@main
|
|
||||||
with:
|
|
||||||
deploy_key: ${{ secrets.DEPLOY_KEY }}
|
|
||||||
package_name: 'nekoray-git'
|
|
||||||
@ -166,7 +166,6 @@ set(PROJECT_SOURCES
|
|||||||
db/ConfigBuilder.cpp
|
db/ConfigBuilder.cpp
|
||||||
|
|
||||||
fmt/AbstractBean.cpp
|
fmt/AbstractBean.cpp
|
||||||
fmt/Bean2CoreObj_ray.cpp
|
|
||||||
fmt/Bean2CoreObj_box.cpp
|
fmt/Bean2CoreObj_box.cpp
|
||||||
fmt/Bean2External.cpp
|
fmt/Bean2External.cpp
|
||||||
fmt/Bean2Link.cpp
|
fmt/Bean2Link.cpp
|
||||||
|
|||||||
@ -66,11 +66,7 @@ namespace NekoGui {
|
|||||||
if (customBean != nullptr && customBean->core == "internal-full") {
|
if (customBean != nullptr && customBean->core == "internal-full") {
|
||||||
result->coreConfig = QString2QJsonObject(customBean->config_simple);
|
result->coreConfig = QString2QJsonObject(customBean->config_simple);
|
||||||
} else {
|
} else {
|
||||||
if (IS_NEKO_BOX) {
|
BuildConfigSingBox(status);
|
||||||
BuildConfigSingBox(status);
|
|
||||||
} else {
|
|
||||||
BuildConfigV2Ray(status);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply custom config
|
// apply custom config
|
||||||
@ -172,254 +168,6 @@ namespace NekoGui {
|
|||||||
status->ipListDirect += line; \
|
status->ipListDirect += line; \
|
||||||
}
|
}
|
||||||
|
|
||||||
// V2Ray
|
|
||||||
|
|
||||||
void BuildConfigV2Ray(const std::shared_ptr<BuildConfigStatus> &status) {
|
|
||||||
// Log
|
|
||||||
auto logObj = QJsonObject{{"loglevel", dataStore->log_level}};
|
|
||||||
status->result->coreConfig.insert("log", logObj);
|
|
||||||
|
|
||||||
// Inbounds
|
|
||||||
QJsonObject sniffing{
|
|
||||||
{"destOverride", QJsonArray{"http", "tls", "quic"}},
|
|
||||||
{"enabled", true},
|
|
||||||
{"metadataOnly", false},
|
|
||||||
{"routeOnly", dataStore->routing->sniffing_mode == SniffingMode::FOR_ROUTING},
|
|
||||||
};
|
|
||||||
|
|
||||||
// socks-in
|
|
||||||
if (IsValidPort(dataStore->inbound_socks_port) && !status->forTest) {
|
|
||||||
QJsonObject inboundObj;
|
|
||||||
inboundObj["tag"] = "socks-in";
|
|
||||||
inboundObj["protocol"] = "socks";
|
|
||||||
inboundObj["listen"] = dataStore->inbound_address;
|
|
||||||
inboundObj["port"] = dataStore->inbound_socks_port;
|
|
||||||
QJsonObject socksSettings = {{"udp", true}};
|
|
||||||
if (dataStore->routing->sniffing_mode != SniffingMode::DISABLE) {
|
|
||||||
inboundObj["sniffing"] = sniffing;
|
|
||||||
}
|
|
||||||
if (dataStore->inbound_auth->NeedAuth()) {
|
|
||||||
socksSettings["auth"] = "password";
|
|
||||||
socksSettings["accounts"] = QJsonArray{
|
|
||||||
QJsonObject{
|
|
||||||
{"user", dataStore->inbound_auth->username},
|
|
||||||
{"pass", dataStore->inbound_auth->password},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
inboundObj["settings"] = socksSettings;
|
|
||||||
status->inbounds += inboundObj;
|
|
||||||
}
|
|
||||||
// http-in
|
|
||||||
if (IsValidPort(dataStore->inbound_http_port) && !status->forTest) {
|
|
||||||
QJsonObject inboundObj;
|
|
||||||
inboundObj["tag"] = "http-in";
|
|
||||||
inboundObj["protocol"] = "http";
|
|
||||||
inboundObj["listen"] = dataStore->inbound_address;
|
|
||||||
inboundObj["port"] = dataStore->inbound_http_port;
|
|
||||||
if (dataStore->routing->sniffing_mode != SniffingMode::DISABLE) {
|
|
||||||
inboundObj["sniffing"] = sniffing;
|
|
||||||
}
|
|
||||||
if (dataStore->inbound_auth->NeedAuth()) {
|
|
||||||
inboundObj["settings"] = QJsonObject{
|
|
||||||
{"accounts", QJsonArray{
|
|
||||||
QJsonObject{
|
|
||||||
{"user", dataStore->inbound_auth->username},
|
|
||||||
{"pass", dataStore->inbound_auth->password},
|
|
||||||
},
|
|
||||||
}},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
status->inbounds += inboundObj;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Outbounds
|
|
||||||
auto tagProxy = BuildChain(0, status);
|
|
||||||
if (!status->result->error.isEmpty()) return;
|
|
||||||
|
|
||||||
// direct & bypass & block
|
|
||||||
status->outbounds += QJsonObject{
|
|
||||||
{"protocol", "freedom"},
|
|
||||||
{"domainStrategy", dataStore->core_ray_freedom_domainStrategy},
|
|
||||||
{"tag", "direct"},
|
|
||||||
};
|
|
||||||
status->outbounds += QJsonObject{
|
|
||||||
{"protocol", "freedom"},
|
|
||||||
{"domainStrategy", dataStore->core_ray_freedom_domainStrategy},
|
|
||||||
{"tag", "bypass"},
|
|
||||||
};
|
|
||||||
status->outbounds += QJsonObject{
|
|
||||||
{"protocol", "blackhole"},
|
|
||||||
{"tag", "block"},
|
|
||||||
};
|
|
||||||
|
|
||||||
// DNS out
|
|
||||||
if (!status->forTest) {
|
|
||||||
QJsonObject dnsOut;
|
|
||||||
dnsOut["protocol"] = "dns";
|
|
||||||
dnsOut["tag"] = "dns-out";
|
|
||||||
QJsonObject dnsOut_settings;
|
|
||||||
dnsOut_settings["network"] = "tcp";
|
|
||||||
dnsOut_settings["port"] = 53;
|
|
||||||
dnsOut_settings["address"] = "8.8.8.8";
|
|
||||||
dnsOut_settings["userLevel"] = 1;
|
|
||||||
dnsOut["settings"] = dnsOut_settings;
|
|
||||||
dnsOut["proxySettings"] = QJsonObject{{"tag", tagProxy},
|
|
||||||
{"transportLayer", true}};
|
|
||||||
|
|
||||||
status->outbounds += dnsOut;
|
|
||||||
status->routingRules += QJsonObject{
|
|
||||||
{"type", "field"},
|
|
||||||
{"port", "53"},
|
|
||||||
{"inboundTag", QJsonArray{"socks-in", "http-in"}},
|
|
||||||
{"outboundTag", "dns-out"},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// custom inbound
|
|
||||||
if (!status->forTest) QJSONARRAY_ADD(status->inbounds, QString2QJsonObject(dataStore->custom_inbound)["inbounds"].toArray())
|
|
||||||
|
|
||||||
status->result->coreConfig.insert("inbounds", status->inbounds);
|
|
||||||
status->result->coreConfig.insert("outbounds", status->outbounds);
|
|
||||||
|
|
||||||
// user rule
|
|
||||||
if (!status->forTest) {
|
|
||||||
DOMAIN_USER_RULE
|
|
||||||
IP_USER_RULE
|
|
||||||
}
|
|
||||||
|
|
||||||
// final add DNS
|
|
||||||
QJsonObject dns;
|
|
||||||
QJsonArray dnsServers;
|
|
||||||
|
|
||||||
// Remote or FakeDNS
|
|
||||||
QJsonObject dnsServerRemote;
|
|
||||||
dnsServerRemote["address"] = dataStore->routing->remote_dns;
|
|
||||||
dnsServerRemote["domains"] = QList2QJsonArray<QString>(status->domainListDNSRemote);
|
|
||||||
dnsServerRemote["queryStrategy"] = dataStore->routing->remote_dns_strategy;
|
|
||||||
if (!status->forTest) dnsServers += dnsServerRemote;
|
|
||||||
|
|
||||||
// Direct
|
|
||||||
auto directDnsAddress = dataStore->routing->direct_dns;
|
|
||||||
if (directDnsAddress.contains("://")) {
|
|
||||||
auto directDnsIp = SubStrBefore(SubStrAfter(directDnsAddress, "://"), "/");
|
|
||||||
if (IsIpAddress(directDnsIp)) {
|
|
||||||
status->routingRules.push_front(QJsonObject{
|
|
||||||
{"type", "field"},
|
|
||||||
{"ip", QJsonArray{directDnsIp}},
|
|
||||||
{"outboundTag", "direct"},
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
status->routingRules.push_front(QJsonObject{
|
|
||||||
{"type", "field"},
|
|
||||||
{"domain", QJsonArray{directDnsIp}},
|
|
||||||
{"outboundTag", "direct"},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else if (directDnsAddress != "localhost") {
|
|
||||||
status->routingRules.push_front(QJsonObject{
|
|
||||||
{"type", "field"},
|
|
||||||
{"ip", QJsonArray{directDnsAddress}},
|
|
||||||
{"outboundTag", "direct"},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
QJsonObject directObj{
|
|
||||||
{"address", directDnsAddress.replace("https://", "https+local://")},
|
|
||||||
{"queryStrategy", dataStore->routing->direct_dns_strategy},
|
|
||||||
{"domains", QList2QJsonArray<QString>(status->domainListDNSDirect)},
|
|
||||||
};
|
|
||||||
if (dataStore->routing->dns_final_out == "bypass") {
|
|
||||||
dnsServers.prepend(directObj);
|
|
||||||
} else {
|
|
||||||
dnsServers.append(directObj);
|
|
||||||
}
|
|
||||||
|
|
||||||
dns["disableFallback"] = true;
|
|
||||||
dns["servers"] = dnsServers;
|
|
||||||
dns["tag"] = "dns";
|
|
||||||
|
|
||||||
if (dataStore->routing->use_dns_object) {
|
|
||||||
dns = QString2QJsonObject(dataStore->routing->dns_object);
|
|
||||||
}
|
|
||||||
status->result->coreConfig.insert("dns", dns);
|
|
||||||
|
|
||||||
// Routing
|
|
||||||
QJsonObject routing;
|
|
||||||
routing["domainStrategy"] = dataStore->routing->domain_strategy;
|
|
||||||
if (status->forTest) routing["domainStrategy"] = "AsIs";
|
|
||||||
|
|
||||||
// final add user rule (block)
|
|
||||||
QJsonObject routingRule_tmp;
|
|
||||||
routingRule_tmp["type"] = "field";
|
|
||||||
routingRule_tmp["outboundTag"] = "block";
|
|
||||||
if (!status->ipListBlock.isEmpty()) {
|
|
||||||
auto tmp = routingRule_tmp;
|
|
||||||
tmp["ip"] = QList2QJsonArray<QString>(status->ipListBlock);
|
|
||||||
status->routingRules += tmp;
|
|
||||||
}
|
|
||||||
if (!status->domainListBlock.isEmpty()) {
|
|
||||||
auto tmp = routingRule_tmp;
|
|
||||||
tmp["domain"] = QList2QJsonArray<QString>(status->domainListBlock);
|
|
||||||
status->routingRules += tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// final add user rule (proxy)
|
|
||||||
routingRule_tmp["outboundTag"] = "proxy";
|
|
||||||
if (!status->ipListRemote.isEmpty()) {
|
|
||||||
auto tmp = routingRule_tmp;
|
|
||||||
tmp["ip"] = QList2QJsonArray<QString>(status->ipListRemote);
|
|
||||||
status->routingRules += tmp;
|
|
||||||
}
|
|
||||||
if (!status->domainListRemote.isEmpty()) {
|
|
||||||
auto tmp = routingRule_tmp;
|
|
||||||
tmp["domain"] = QList2QJsonArray<QString>(status->domainListRemote);
|
|
||||||
status->routingRules += tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// final add user rule (bypass)
|
|
||||||
routingRule_tmp["outboundTag"] = "bypass";
|
|
||||||
if (!status->ipListDirect.isEmpty()) {
|
|
||||||
auto tmp = routingRule_tmp;
|
|
||||||
tmp["ip"] = QList2QJsonArray<QString>(status->ipListDirect);
|
|
||||||
status->routingRules += tmp;
|
|
||||||
}
|
|
||||||
if (!status->domainListDirect.isEmpty()) {
|
|
||||||
auto tmp = routingRule_tmp;
|
|
||||||
tmp["domain"] = QList2QJsonArray<QString>(status->domainListDirect);
|
|
||||||
status->routingRules += tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// def_outbound
|
|
||||||
if (!status->forTest) status->routingRules += QJsonObject{
|
|
||||||
{"type", "field"},
|
|
||||||
{"port", "0-65535"},
|
|
||||||
{"outboundTag", dataStore->routing->def_outbound},
|
|
||||||
};
|
|
||||||
|
|
||||||
// final add routing rule
|
|
||||||
auto routingRules = QString2QJsonObject(dataStore->routing->custom)["rules"].toArray();
|
|
||||||
if (status->forTest) routingRules = {};
|
|
||||||
if (!status->forTest) QJSONARRAY_ADD(routingRules, QString2QJsonObject(dataStore->custom_route_global)["rules"].toArray())
|
|
||||||
QJSONARRAY_ADD(routingRules, status->routingRules)
|
|
||||||
routing["rules"] = routingRules;
|
|
||||||
status->result->coreConfig.insert("routing", routing);
|
|
||||||
|
|
||||||
// Policy & stats
|
|
||||||
QJsonObject policy;
|
|
||||||
QJsonObject levels;
|
|
||||||
QJsonObject level1;
|
|
||||||
level1["connIdle"] = 30;
|
|
||||||
levels["1"] = level1;
|
|
||||||
policy["levels"] = levels;
|
|
||||||
|
|
||||||
QJsonObject policySystem;
|
|
||||||
policySystem["statsOutboundDownlink"] = true;
|
|
||||||
policySystem["statsOutboundUplink"] = true;
|
|
||||||
policy["system"] = policySystem;
|
|
||||||
status->result->coreConfig.insert("policy", policy);
|
|
||||||
status->result->coreConfig.insert("stats", QJsonObject());
|
|
||||||
}
|
|
||||||
|
|
||||||
QString BuildChainInternal(int chainId, const QList<std::shared_ptr<ProxyEntity>> &ents,
|
QString BuildChainInternal(int chainId, const QList<std::shared_ptr<ProxyEntity>> &ents,
|
||||||
const std::shared_ptr<BuildConfigStatus> &status) {
|
const std::shared_ptr<BuildConfigStatus> &status) {
|
||||||
QString chainTag = "c-" + Int2String(chainId);
|
QString chainTag = "c-" + Int2String(chainId);
|
||||||
@ -472,26 +220,16 @@ namespace NekoGui {
|
|||||||
if (IS_NEKO_BOX) {
|
if (IS_NEKO_BOX) {
|
||||||
replaced["detour"] = tagOut;
|
replaced["detour"] = tagOut;
|
||||||
} else {
|
} else {
|
||||||
replaced["proxySettings"] = QJsonObject{
|
status->result->error = "Xray is no longer supported";
|
||||||
{"tag", tagOut},
|
return {};
|
||||||
{"transportLayer", true},
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
status->outbounds.removeLast();
|
status->outbounds.removeLast();
|
||||||
status->outbounds += replaced;
|
status->outbounds += replaced;
|
||||||
} else {
|
} else {
|
||||||
if (IS_NEKO_BOX) {
|
status->routingRules += QJsonObject{
|
||||||
status->routingRules += QJsonObject{
|
{"inbound", QJsonArray{pastTag + "-mapping"}},
|
||||||
{"inbound", QJsonArray{pastTag + "-mapping"}},
|
{"outbound", tagOut},
|
||||||
{"outbound", tagOut},
|
};
|
||||||
};
|
|
||||||
} else {
|
|
||||||
status->routingRules += QJsonObject{
|
|
||||||
{"type", "field"},
|
|
||||||
{"inboundTag", QJsonArray{pastTag + "-mapping"}},
|
|
||||||
{"outboundTag", tagOut},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// index == 0 means last profile in chain / not chain
|
// index == 0 means last profile in chain / not chain
|
||||||
@ -530,43 +268,20 @@ namespace NekoGui {
|
|||||||
if (thisExternalStat == 2) dataStore->need_keep_vpn_off = true;
|
if (thisExternalStat == 2) dataStore->need_keep_vpn_off = true;
|
||||||
if (thisExternalStat == 1) {
|
if (thisExternalStat == 1) {
|
||||||
// mapping
|
// mapping
|
||||||
if (IS_NEKO_BOX) {
|
status->inbounds += QJsonObject{
|
||||||
status->inbounds += QJsonObject{
|
{"type", "direct"},
|
||||||
{"type", "direct"},
|
{"tag", tagOut + "-mapping"},
|
||||||
{"tag", tagOut + "-mapping"},
|
{"listen", "127.0.0.1"},
|
||||||
{"listen", "127.0.0.1"},
|
{"listen_port", ext_mapping_port},
|
||||||
{"listen_port", ext_mapping_port},
|
{"override_address", ent->bean->serverAddress},
|
||||||
{"override_address", ent->bean->serverAddress},
|
{"override_port", ent->bean->serverPort},
|
||||||
{"override_port", ent->bean->serverPort},
|
};
|
||||||
};
|
|
||||||
} else {
|
|
||||||
status->inbounds += QJsonObject{
|
|
||||||
{"protocol", "dokodemo-door"},
|
|
||||||
{"tag", tagOut + "-mapping"},
|
|
||||||
{"listen", "127.0.0.1"},
|
|
||||||
{"port", ext_mapping_port},
|
|
||||||
{"settings", QJsonObject{
|
|
||||||
// to
|
|
||||||
{"address", ent->bean->serverAddress},
|
|
||||||
{"port", ent->bean->serverPort},
|
|
||||||
{"network", "tcp,udp"},
|
|
||||||
}},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// no chain rule and not outbound, so need to set to direct
|
// no chain rule and not outbound, so need to set to direct
|
||||||
if (isFirstProfile) {
|
if (isFirstProfile) {
|
||||||
if (IS_NEKO_BOX) {
|
status->routingRules += QJsonObject{
|
||||||
status->routingRules += QJsonObject{
|
{"inbound", QJsonArray{tagOut + "-mapping"}},
|
||||||
{"inbound", QJsonArray{tagOut + "-mapping"}},
|
{"outbound", "direct"},
|
||||||
{"outbound", "direct"},
|
};
|
||||||
};
|
|
||||||
} else {
|
|
||||||
status->routingRules += QJsonObject{
|
|
||||||
{"type", "field"},
|
|
||||||
{"inboundTag", QJsonArray{tagOut + "-mapping"}},
|
|
||||||
{"outboundTag", "direct"},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -589,23 +304,11 @@ namespace NekoGui {
|
|||||||
status->result->extRs.emplace_back(std::make_shared<NekoGui_fmt::ExternalBuildResult>(extR));
|
status->result->extRs.emplace_back(std::make_shared<NekoGui_fmt::ExternalBuildResult>(extR));
|
||||||
|
|
||||||
// SOCKS OUTBOUND
|
// SOCKS OUTBOUND
|
||||||
if (IS_NEKO_BOX) {
|
outbound["type"] = "socks";
|
||||||
outbound["type"] = "socks";
|
outbound["server"] = "127.0.0.1";
|
||||||
outbound["server"] = "127.0.0.1";
|
outbound["server_port"] = ext_socks_port;
|
||||||
outbound["server_port"] = ext_socks_port;
|
|
||||||
} else {
|
|
||||||
outbound["protocol"] = "socks";
|
|
||||||
QJsonObject settings;
|
|
||||||
QJsonArray servers;
|
|
||||||
QJsonObject server;
|
|
||||||
server["address"] = "127.0.0.1";
|
|
||||||
server["port"] = ext_socks_port;
|
|
||||||
servers.push_back(server);
|
|
||||||
settings["servers"] = servers;
|
|
||||||
outbound["settings"] = settings;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
const auto coreR = IS_NEKO_BOX ? ent->bean->BuildCoreObjSingBox() : ent->bean->BuildCoreObjV2Ray();
|
const auto coreR = ent->bean->BuildCoreObjSingBox();
|
||||||
if (coreR.outbound.isEmpty()) {
|
if (coreR.outbound.isEmpty()) {
|
||||||
status->result->error = "unsupported outbound";
|
status->result->error = "unsupported outbound";
|
||||||
return {};
|
return {};
|
||||||
@ -624,58 +327,41 @@ namespace NekoGui {
|
|||||||
status->result->outboundStats += ent->traffic_data;
|
status->result->outboundStats += ent->traffic_data;
|
||||||
|
|
||||||
// mux common
|
// mux common
|
||||||
auto needMux = ent->type == "vmess" || ent->type == "trojan" || ent->type == "vless";
|
auto needMux = ent->type == "vmess" || ent->type == "trojan" || ent->type == "vless" || ent->type == "shadowsocks";
|
||||||
needMux &= dataStore->mux_concurrency > 0;
|
needMux &= dataStore->mux_concurrency > 0;
|
||||||
|
|
||||||
if (stream != nullptr) {
|
if (stream != nullptr) {
|
||||||
if (IS_NEKO_BOX) {
|
if (stream->network == "grpc" || stream->network == "quic" || (stream->network == "http" && stream->security == "tls")) {
|
||||||
if (stream->network == "grpc" || stream->network == "quic" || (stream->network == "http" && stream->security == "tls")) {
|
|
||||||
needMux = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (stream->network == "grpc" || stream->network == "quic") {
|
|
||||||
needMux = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (stream->multiplex_status == 0) {
|
|
||||||
if (!dataStore->mux_default_on) needMux = false;
|
|
||||||
} else if (stream->multiplex_status == 1) {
|
|
||||||
needMux = true;
|
|
||||||
} else if (stream->multiplex_status == 2) {
|
|
||||||
needMux = false;
|
needMux = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto mux_state = ent->bean->mux_state;
|
||||||
|
if (mux_state == 0) {
|
||||||
|
if (!dataStore->mux_default_on) needMux = false;
|
||||||
|
} else if (mux_state == 1) {
|
||||||
|
needMux = true;
|
||||||
|
} else if (mux_state == 2) {
|
||||||
|
needMux = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (ent->type == "vless" && outbound["flow"] != "") {
|
if (ent->type == "vless" && outbound["flow"] != "") {
|
||||||
needMux = false;
|
needMux = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// common
|
// common
|
||||||
if (IS_NEKO_BOX) {
|
// apply domain_strategy
|
||||||
// apply domain_strategy
|
outbound["domain_strategy"] = dataStore->routing->outbound_domain_strategy;
|
||||||
outbound["domain_strategy"] = dataStore->routing->outbound_domain_strategy;
|
// apply mux
|
||||||
// apply mux
|
if (!muxApplied && needMux) {
|
||||||
if (!muxApplied && needMux) {
|
auto muxObj = QJsonObject{
|
||||||
auto muxObj = QJsonObject{
|
{"enabled", true},
|
||||||
{"enabled", true},
|
{"protocol", dataStore->mux_protocol},
|
||||||
{"protocol", dataStore->mux_protocol},
|
{"padding", dataStore->mux_padding},
|
||||||
{"padding", dataStore->mux_padding},
|
{"max_streams", dataStore->mux_concurrency},
|
||||||
{"max_streams", dataStore->mux_concurrency},
|
};
|
||||||
};
|
outbound["multiplex"] = muxObj;
|
||||||
outbound["multiplex"] = muxObj;
|
muxApplied = true;
|
||||||
muxApplied = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// apply domain_strategy
|
|
||||||
if (!status->forTest) outbound["domainStrategy"] = dataStore->routing->outbound_domain_strategy;
|
|
||||||
// apply mux
|
|
||||||
if (!muxApplied && needMux) {
|
|
||||||
auto muxObj = QJsonObject{
|
|
||||||
{"enabled", true},
|
|
||||||
{"concurrency", dataStore->mux_concurrency},
|
|
||||||
};
|
|
||||||
outbound["mux"] = muxObj;
|
|
||||||
muxApplied = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply custom outbound settings
|
// apply custom outbound settings
|
||||||
@ -735,7 +421,7 @@ namespace NekoGui {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// tun-in
|
// tun-in
|
||||||
if (IS_NEKO_BOX_INTERNAL_TUN && dataStore->spmode_vpn && !status->forTest) {
|
if (dataStore->spmode_vpn && !status->forTest) {
|
||||||
QJsonObject inboundObj;
|
QJsonObject inboundObj;
|
||||||
inboundObj["tag"] = "tun-in";
|
inboundObj["tag"] = "tun-in";
|
||||||
inboundObj["type"] = "tun";
|
inboundObj["type"] = "tun";
|
||||||
@ -885,7 +571,7 @@ namespace NekoGui {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Fakedns
|
// Fakedns
|
||||||
if (dataStore->fake_dns && IS_NEKO_BOX_INTERNAL_TUN && dataStore->spmode_vpn && !status->forTest) {
|
if (dataStore->fake_dns && dataStore->spmode_vpn && !status->forTest) {
|
||||||
dnsServers += QJsonObject{
|
dnsServers += QJsonObject{
|
||||||
{"tag", "dns-fake"},
|
{"tag", "dns-fake"},
|
||||||
{"address", "fakeip"},
|
{"address", "fakeip"},
|
||||||
@ -927,7 +613,7 @@ namespace NekoGui {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// fakedns rule
|
// fakedns rule
|
||||||
if (dataStore->fake_dns && IS_NEKO_BOX_INTERNAL_TUN && dataStore->spmode_vpn && !status->forTest) {
|
if (dataStore->fake_dns && dataStore->spmode_vpn && !status->forTest) {
|
||||||
dnsRules += QJsonObject{
|
dnsRules += QJsonObject{
|
||||||
{"inbound", "tun-in"},
|
{"inbound", "tun-in"},
|
||||||
{"server", "dns-fake"},
|
{"server", "dns-fake"},
|
||||||
@ -970,11 +656,6 @@ namespace NekoGui {
|
|||||||
add_rule_route(status->ipListDirect, true, "bypass");
|
add_rule_route(status->ipListDirect, true, "bypass");
|
||||||
|
|
||||||
// built-in rules
|
// built-in rules
|
||||||
status->routingRules += QJsonObject{
|
|
||||||
{"network", "udp"},
|
|
||||||
{"port", QJsonArray{135, 137, 138, 139, 5353}},
|
|
||||||
{"outbound", "block"},
|
|
||||||
};
|
|
||||||
status->routingRules += QJsonObject{
|
status->routingRules += QJsonObject{
|
||||||
{"ip_cidr", QJsonArray{"224.0.0.0/3", "ff00::/8"}},
|
{"ip_cidr", QJsonArray{"224.0.0.0/3", "ff00::/8"}},
|
||||||
{"outbound", "block"},
|
{"outbound", "block"},
|
||||||
@ -985,7 +666,7 @@ namespace NekoGui {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// tun user rule
|
// tun user rule
|
||||||
if (IS_NEKO_BOX_INTERNAL_TUN && dataStore->spmode_vpn && !status->forTest) {
|
if (dataStore->spmode_vpn && !status->forTest) {
|
||||||
auto match_out = dataStore->vpn_rule_white ? "proxy" : "bypass";
|
auto match_out = dataStore->vpn_rule_white ? "proxy" : "bypass";
|
||||||
|
|
||||||
QString process_name_rule = dataStore->vpn_rule_process.trimmed();
|
QString process_name_rule = dataStore->vpn_rule_process.trimmed();
|
||||||
@ -1025,7 +706,7 @@ namespace NekoGui {
|
|||||||
QJSONARRAY_ADD(routingRules, status->routingRules)
|
QJSONARRAY_ADD(routingRules, status->routingRules)
|
||||||
auto routeObj = QJsonObject{
|
auto routeObj = QJsonObject{
|
||||||
{"rules", routingRules},
|
{"rules", routingRules},
|
||||||
{"auto_detect_interface", dataStore->spmode_vpn},
|
{"auto_detect_interface", true},
|
||||||
{
|
{
|
||||||
"geoip",
|
"geoip",
|
||||||
QJsonObject{
|
QJsonObject{
|
||||||
|
|||||||
@ -46,8 +46,6 @@ namespace NekoGui {
|
|||||||
|
|
||||||
std::shared_ptr<BuildConfigResult> BuildConfig(const std::shared_ptr<ProxyEntity> &ent, bool forTest, bool forExport);
|
std::shared_ptr<BuildConfigResult> BuildConfig(const std::shared_ptr<ProxyEntity> &ent, bool forTest, bool forExport);
|
||||||
|
|
||||||
void BuildConfigV2Ray(const std::shared_ptr<BuildConfigStatus> &status);
|
|
||||||
|
|
||||||
void BuildConfigSingBox(const std::shared_ptr<BuildConfigStatus> &status);
|
void BuildConfigSingBox(const std::shared_ptr<BuildConfigStatus> &status);
|
||||||
|
|
||||||
QString BuildChain(int chainId, const std::shared_ptr<BuildConfigStatus> &status);
|
QString BuildChain(int chainId, const std::shared_ptr<BuildConfigStatus> &status);
|
||||||
|
|||||||
@ -34,6 +34,7 @@ namespace NekoGui_fmt {
|
|||||||
|
|
||||||
QString custom_config = "";
|
QString custom_config = "";
|
||||||
QString custom_outbound = "";
|
QString custom_outbound = "";
|
||||||
|
int mux_state = 0;
|
||||||
|
|
||||||
explicit AbstractBean(int version);
|
explicit AbstractBean(int version);
|
||||||
|
|
||||||
@ -59,8 +60,6 @@ namespace NekoGui_fmt {
|
|||||||
|
|
||||||
virtual int NeedExternal(bool isFirstProfile) { return 0; };
|
virtual int NeedExternal(bool isFirstProfile) { return 0; };
|
||||||
|
|
||||||
virtual CoreObjOutboundBuildResult BuildCoreObjV2Ray() { return {}; };
|
|
||||||
|
|
||||||
virtual CoreObjOutboundBuildResult BuildCoreObjSingBox() { return {}; };
|
virtual CoreObjOutboundBuildResult BuildCoreObjSingBox() { return {}; };
|
||||||
|
|
||||||
virtual ExternalBuildResult BuildExternal(int mapping_port, int socks_port, int external_stat) { return {}; };
|
virtual ExternalBuildResult BuildExternal(int mapping_port, int socks_port, int external_stat) { return {}; };
|
||||||
|
|||||||
@ -200,10 +200,6 @@ namespace NekoGui_fmt {
|
|||||||
outbound["up_mbps"] = uploadMbps;
|
outbound["up_mbps"] = uploadMbps;
|
||||||
outbound["down_mbps"] = downloadMbps;
|
outbound["down_mbps"] = downloadMbps;
|
||||||
|
|
||||||
if (!hopPort.trimmed().isEmpty()) {
|
|
||||||
outbound["hop_ports"] = hopPort;
|
|
||||||
outbound["hop_interval"] = hopInterval;
|
|
||||||
}
|
|
||||||
if (authPayloadType == hysteria_auth_base64) outbound["auth"] = authPayload;
|
if (authPayloadType == hysteria_auth_base64) outbound["auth"] = authPayload;
|
||||||
if (authPayloadType == hysteria_auth_string) outbound["auth_str"] = authPayload;
|
if (authPayloadType == hysteria_auth_string) outbound["auth_str"] = authPayload;
|
||||||
} else if (proxy_type == proxy_Hysteria2) {
|
} else if (proxy_type == proxy_Hysteria2) {
|
||||||
@ -211,11 +207,7 @@ namespace NekoGui_fmt {
|
|||||||
outbound["password"] = password;
|
outbound["password"] = password;
|
||||||
outbound["up_mbps"] = uploadMbps;
|
outbound["up_mbps"] = uploadMbps;
|
||||||
outbound["down_mbps"] = downloadMbps;
|
outbound["down_mbps"] = downloadMbps;
|
||||||
|
|
||||||
if (!hopPort.trimmed().isEmpty()) {
|
|
||||||
outbound["hop_ports"] = hopPort;
|
|
||||||
outbound["hop_interval"] = hopInterval;
|
|
||||||
}
|
|
||||||
if (!obfsPassword.isEmpty()) {
|
if (!obfsPassword.isEmpty()) {
|
||||||
outbound["obfs"] = QJsonObject{
|
outbound["obfs"] = QJsonObject{
|
||||||
{"type", "salamander"},
|
{"type", "salamander"},
|
||||||
|
|||||||
@ -1,211 +0,0 @@
|
|||||||
#include "db/ProxyEntity.hpp"
|
|
||||||
#include "fmt/includes.h"
|
|
||||||
|
|
||||||
#define MAKE_SETTINGS_STREAM_SETTINGS \
|
|
||||||
outbound["settings"] = settings; \
|
|
||||||
auto streamSettings = stream->BuildStreamSettingsV2Ray(); \
|
|
||||||
outbound["streamSettings"] = streamSettings;
|
|
||||||
|
|
||||||
namespace NekoGui_fmt {
|
|
||||||
QJsonObject V2rayStreamSettings::BuildStreamSettingsV2Ray() {
|
|
||||||
QJsonObject streamSettings{{"network", network}};
|
|
||||||
|
|
||||||
if (network == "ws") {
|
|
||||||
QJsonObject ws;
|
|
||||||
if (!host.isEmpty()) ws["headers"] = QJsonObject{{"Host", host}};
|
|
||||||
// ws path & ed
|
|
||||||
if (!path.isEmpty()) ws["path"] = path;
|
|
||||||
streamSettings["wsSettings"] = ws;
|
|
||||||
} else if (network == "http") {
|
|
||||||
QJsonObject http;
|
|
||||||
if (!path.isEmpty()) http["path"] = path;
|
|
||||||
if (!host.isEmpty()) http["host"] = QList2QJsonArray(host.split(","));
|
|
||||||
streamSettings["httpSettings"] = http;
|
|
||||||
} else if (network == "grpc") {
|
|
||||||
QJsonObject grpc;
|
|
||||||
if (!path.isEmpty()) grpc["serviceName"] = path;
|
|
||||||
streamSettings["grpcSettings"] = grpc;
|
|
||||||
} else if (network == "quic") {
|
|
||||||
QJsonObject quic;
|
|
||||||
if (!header_type.isEmpty()) quic["header"] = QJsonObject{{"type", header_type}};
|
|
||||||
if (!path.isEmpty()) quic["key"] = path;
|
|
||||||
if (!host.isEmpty()) quic["security"] = host;
|
|
||||||
streamSettings["quicSettings"] = quic;
|
|
||||||
} else if (network == "tcp" && !header_type.isEmpty()) {
|
|
||||||
QJsonObject header{{"type", header_type}};
|
|
||||||
if (header_type == "http") {
|
|
||||||
header["request"] = QJsonObject{
|
|
||||||
{"path", QList2QJsonArray(path.split(","))},
|
|
||||||
{"headers", QJsonObject{{"Host", QList2QJsonArray(host.split(","))}}},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
streamSettings["tcpSettings"] = QJsonObject{{"header", header}};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (security == "tls") {
|
|
||||||
QJsonObject tls;
|
|
||||||
if (!utlsFingerprint.isEmpty()) tls["fingerprint"] = utlsFingerprint;
|
|
||||||
if (!sni.trimmed().isEmpty()) tls["serverName"] = sni;
|
|
||||||
if (reality_pbk.trimmed().isEmpty()) {
|
|
||||||
if (allow_insecure || NekoGui::dataStore->skip_cert) tls["allowInsecure"] = true;
|
|
||||||
if (!alpn.trimmed().isEmpty()) tls["alpn"] = QList2QJsonArray(alpn.split(","));
|
|
||||||
if (!certificate.trimmed().isEmpty()) {
|
|
||||||
tls["disableSystemRoot"] = true;
|
|
||||||
tls["certificates"] = QJsonArray{
|
|
||||||
QJsonObject{
|
|
||||||
{"usage", "verify"},
|
|
||||||
{"certificate", QList2QJsonArray(SplitLines(certificate.trimmed()))},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
streamSettings["tlsSettings"] = tls;
|
|
||||||
streamSettings["security"] = "tls";
|
|
||||||
} else {
|
|
||||||
tls["publicKey"] = reality_pbk;
|
|
||||||
tls["shortId"] = reality_sid;
|
|
||||||
tls["spiderX"] = reality_spx;
|
|
||||||
if (utlsFingerprint.isEmpty()) tls["fingerprint"] = "chrome";
|
|
||||||
streamSettings["realitySettings"] = tls;
|
|
||||||
streamSettings["security"] = "reality";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return streamSettings;
|
|
||||||
}
|
|
||||||
|
|
||||||
CoreObjOutboundBuildResult SocksHttpBean::BuildCoreObjV2Ray() {
|
|
||||||
CoreObjOutboundBuildResult result;
|
|
||||||
|
|
||||||
QJsonObject outbound;
|
|
||||||
outbound["protocol"] = socks_http_type == type_HTTP ? "http" : "socks";
|
|
||||||
|
|
||||||
QJsonObject settings;
|
|
||||||
QJsonArray servers;
|
|
||||||
QJsonObject server;
|
|
||||||
|
|
||||||
server["address"] = serverAddress;
|
|
||||||
server["port"] = serverPort;
|
|
||||||
|
|
||||||
QJsonArray users;
|
|
||||||
QJsonObject user;
|
|
||||||
user["user"] = username;
|
|
||||||
user["pass"] = password;
|
|
||||||
users.push_back(user);
|
|
||||||
if (!username.isEmpty() && !password.isEmpty()) server["users"] = users;
|
|
||||||
|
|
||||||
servers.push_back(server);
|
|
||||||
settings["servers"] = servers;
|
|
||||||
|
|
||||||
MAKE_SETTINGS_STREAM_SETTINGS
|
|
||||||
|
|
||||||
result.outbound = outbound;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
CoreObjOutboundBuildResult ShadowSocksBean::BuildCoreObjV2Ray() {
|
|
||||||
CoreObjOutboundBuildResult result;
|
|
||||||
|
|
||||||
QJsonObject outbound{{"protocol", "shadowsocks"}};
|
|
||||||
|
|
||||||
QJsonObject settings;
|
|
||||||
QJsonArray servers;
|
|
||||||
QJsonObject server;
|
|
||||||
|
|
||||||
server["address"] = serverAddress;
|
|
||||||
server["port"] = serverPort;
|
|
||||||
server["method"] = method;
|
|
||||||
server["password"] = password;
|
|
||||||
|
|
||||||
if (uot != 0) {
|
|
||||||
server["uot"] = true;
|
|
||||||
server["UoTVersion"] = uot;
|
|
||||||
} else {
|
|
||||||
server["uot"] = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
servers.push_back(server);
|
|
||||||
settings["servers"] = servers;
|
|
||||||
|
|
||||||
if (!plugin.trimmed().isEmpty()) {
|
|
||||||
settings["plugin"] = SubStrBefore(plugin, ";");
|
|
||||||
settings["pluginOpts"] = SubStrAfter(plugin, ";");
|
|
||||||
}
|
|
||||||
|
|
||||||
MAKE_SETTINGS_STREAM_SETTINGS
|
|
||||||
|
|
||||||
result.outbound = outbound;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
CoreObjOutboundBuildResult VMessBean::BuildCoreObjV2Ray() {
|
|
||||||
CoreObjOutboundBuildResult result;
|
|
||||||
QJsonObject outbound{{"protocol", "vmess"}};
|
|
||||||
|
|
||||||
QJsonObject settings{
|
|
||||||
{"vnext", QJsonArray{
|
|
||||||
QJsonObject{
|
|
||||||
{"address", serverAddress},
|
|
||||||
{"port", serverPort},
|
|
||||||
{"users", QJsonArray{
|
|
||||||
QJsonObject{
|
|
||||||
{"id", uuid.trimmed()},
|
|
||||||
{"alterId", aid},
|
|
||||||
{"security", security},
|
|
||||||
}}},
|
|
||||||
}}}};
|
|
||||||
|
|
||||||
MAKE_SETTINGS_STREAM_SETTINGS
|
|
||||||
|
|
||||||
result.outbound = outbound;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
CoreObjOutboundBuildResult TrojanVLESSBean::BuildCoreObjV2Ray() {
|
|
||||||
CoreObjOutboundBuildResult result;
|
|
||||||
QJsonObject outbound{
|
|
||||||
{"protocol", proxy_type == proxy_VLESS ? "vless" : "trojan"},
|
|
||||||
};
|
|
||||||
|
|
||||||
QJsonObject settings;
|
|
||||||
if (proxy_type == proxy_VLESS) {
|
|
||||||
if (flow == "none") {
|
|
||||||
flow = "";
|
|
||||||
}
|
|
||||||
settings = QJsonObject{
|
|
||||||
{"vnext", QJsonArray{
|
|
||||||
QJsonObject{
|
|
||||||
{"address", serverAddress},
|
|
||||||
{"port", serverPort},
|
|
||||||
{"users", QJsonArray{
|
|
||||||
QJsonObject{
|
|
||||||
{"id", password.trimmed()},
|
|
||||||
{"encryption", "none"},
|
|
||||||
{"flow", flow},
|
|
||||||
}}},
|
|
||||||
}}}};
|
|
||||||
} else {
|
|
||||||
settings = QJsonObject{
|
|
||||||
{"servers", QJsonArray{
|
|
||||||
QJsonObject{
|
|
||||||
{"address", serverAddress},
|
|
||||||
{"port", serverPort},
|
|
||||||
{"password", password},
|
|
||||||
}}}};
|
|
||||||
}
|
|
||||||
|
|
||||||
MAKE_SETTINGS_STREAM_SETTINGS
|
|
||||||
|
|
||||||
result.outbound = outbound;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
CoreObjOutboundBuildResult CustomBean::BuildCoreObjV2Ray() {
|
|
||||||
CoreObjOutboundBuildResult result;
|
|
||||||
|
|
||||||
if (core == "internal") {
|
|
||||||
result.outbound = QString2QJsonObject(config_simple);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
} // namespace NekoGui_fmt
|
|
||||||
@ -64,6 +64,13 @@ namespace NekoGui_fmt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mux
|
||||||
|
if (mux_state == 1) {
|
||||||
|
query.addQueryItem("mux", "true");
|
||||||
|
} else if (mux_state == 2) {
|
||||||
|
query.addQueryItem("mux", "false");
|
||||||
|
}
|
||||||
|
|
||||||
// protocol
|
// protocol
|
||||||
if (proxy_type == proxy_VLESS) {
|
if (proxy_type == proxy_VLESS) {
|
||||||
if (!flow.isEmpty()) {
|
if (!flow.isEmpty()) {
|
||||||
@ -92,6 +99,20 @@ namespace NekoGui_fmt {
|
|||||||
if (!name.isEmpty()) url.setFragment(name);
|
if (!name.isEmpty()) url.setFragment(name);
|
||||||
QUrlQuery q;
|
QUrlQuery q;
|
||||||
if (!plugin.isEmpty()) q.addQueryItem("plugin", plugin);
|
if (!plugin.isEmpty()) q.addQueryItem("plugin", plugin);
|
||||||
|
|
||||||
|
// mux
|
||||||
|
if (mux_state == 1) {
|
||||||
|
q.addQueryItem("mux", "true");
|
||||||
|
} else if (mux_state == 2) {
|
||||||
|
q.addQueryItem("mux", "false");
|
||||||
|
}
|
||||||
|
// uot
|
||||||
|
if (uot == 1) {
|
||||||
|
q.addQueryItem("uot", "1");
|
||||||
|
} else if (uot == 2) {
|
||||||
|
q.addQueryItem("uot", "2");
|
||||||
|
}
|
||||||
|
|
||||||
if (!q.isEmpty()) url.setQuery(q);
|
if (!q.isEmpty()) url.setQuery(q);
|
||||||
//
|
//
|
||||||
auto link = url.toString(QUrl::FullyEncoded);
|
auto link = url.toString(QUrl::FullyEncoded);
|
||||||
@ -164,6 +185,13 @@ namespace NekoGui_fmt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mux
|
||||||
|
if (mux_state == 1) {
|
||||||
|
query.addQueryItem("mux", "true");
|
||||||
|
} else if (mux_state == 2) {
|
||||||
|
query.addQueryItem("mux", "false");
|
||||||
|
}
|
||||||
|
|
||||||
url.setQuery(query);
|
url.setQuery(query);
|
||||||
return url.toString(QUrl::FullyEncoded);
|
return url.toString(QUrl::FullyEncoded);
|
||||||
}
|
}
|
||||||
@ -196,7 +224,6 @@ namespace NekoGui_fmt {
|
|||||||
if (authPayloadType == hysteria_auth_string) q.addQueryItem("auth", authPayload);
|
if (authPayloadType == hysteria_auth_string) q.addQueryItem("auth", authPayload);
|
||||||
if (hyProtocol == hysteria_protocol_facktcp) q.addQueryItem("protocol", "faketcp");
|
if (hyProtocol == hysteria_protocol_facktcp) q.addQueryItem("protocol", "faketcp");
|
||||||
if (hyProtocol == hysteria_protocol_wechat_video) q.addQueryItem("protocol", "wechat-video");
|
if (hyProtocol == hysteria_protocol_wechat_video) q.addQueryItem("protocol", "wechat-video");
|
||||||
if (!hopPort.trimmed().isEmpty()) q.addQueryItem("mport", hopPort);
|
|
||||||
if (allowInsecure) q.addQueryItem("insecure", "1");
|
if (allowInsecure) q.addQueryItem("insecure", "1");
|
||||||
if (!sni.isEmpty()) q.addQueryItem("peer", sni);
|
if (!sni.isEmpty()) q.addQueryItem("peer", sni);
|
||||||
if (!alpn.isEmpty()) q.addQueryItem("alpn", alpn);
|
if (!alpn.isEmpty()) q.addQueryItem("alpn", alpn);
|
||||||
@ -235,7 +262,6 @@ namespace NekoGui_fmt {
|
|||||||
q.addQueryItem("obfs", "salamander");
|
q.addQueryItem("obfs", "salamander");
|
||||||
q.addQueryItem("obfs-password", obfsPassword);
|
q.addQueryItem("obfs-password", obfsPassword);
|
||||||
}
|
}
|
||||||
if (!hopPort.trimmed().isEmpty()) q.addQueryItem("mport", hopPort);
|
|
||||||
if (allowInsecure) q.addQueryItem("insecure", "1");
|
if (allowInsecure) q.addQueryItem("insecure", "1");
|
||||||
if (!sni.isEmpty()) q.addQueryItem("sni", sni);
|
if (!sni.isEmpty()) q.addQueryItem("sni", sni);
|
||||||
if (!q.isEmpty()) url.setQuery(q);
|
if (!q.isEmpty()) url.setQuery(q);
|
||||||
|
|||||||
@ -36,11 +36,7 @@ namespace NekoGui_fmt {
|
|||||||
QString DisplayAddress() override {
|
QString DisplayAddress() override {
|
||||||
if (core == "internal") {
|
if (core == "internal") {
|
||||||
auto obj = QString2QJsonObject(config_simple);
|
auto obj = QString2QJsonObject(config_simple);
|
||||||
if (IS_NEKO_BOX) {
|
return ::DisplayAddress(obj["server"].toString(), obj["server_port"].toInt());
|
||||||
return ::DisplayAddress(obj["server"].toString(), obj["server_port"].toInt());
|
|
||||||
} else {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
} else if (core == "internal-full") {
|
} else if (core == "internal-full") {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -52,7 +48,5 @@ namespace NekoGui_fmt {
|
|||||||
ExternalBuildResult BuildExternal(int mapping_port, int socks_port, int external_stat) override;
|
ExternalBuildResult BuildExternal(int mapping_port, int socks_port, int external_stat) override;
|
||||||
|
|
||||||
CoreObjOutboundBuildResult BuildCoreObjSingBox() override;
|
CoreObjOutboundBuildResult BuildCoreObjSingBox() override;
|
||||||
|
|
||||||
CoreObjOutboundBuildResult BuildCoreObjV2Ray() override;
|
|
||||||
};
|
};
|
||||||
} // namespace NekoGui_fmt
|
} // namespace NekoGui_fmt
|
||||||
@ -100,6 +100,14 @@ namespace NekoGui_fmt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mux
|
||||||
|
auto mux_str = GetQueryValue(query, "mux", "");
|
||||||
|
if (mux_str == "true") {
|
||||||
|
mux_state = 1;
|
||||||
|
} else if (mux_str == "false") {
|
||||||
|
mux_state = 2;
|
||||||
|
}
|
||||||
|
|
||||||
// protocol
|
// protocol
|
||||||
if (proxy_type == proxy_VLESS) {
|
if (proxy_type == proxy_VLESS) {
|
||||||
flow = GetQueryValue(query, "flow", "");
|
flow = GetQueryValue(query, "flow", "");
|
||||||
@ -132,6 +140,13 @@ namespace NekoGui_fmt {
|
|||||||
|
|
||||||
auto query = GetQuery(url);
|
auto query = GetQuery(url);
|
||||||
plugin = query.queryItemValue("plugin").replace("simple-obfs;", "obfs-local;");
|
plugin = query.queryItemValue("plugin").replace("simple-obfs;", "obfs-local;");
|
||||||
|
auto mux_str = GetQueryValue(query, "mux", "");
|
||||||
|
if (mux_str == "true") {
|
||||||
|
mux_state = 1;
|
||||||
|
} else if (mux_str == "false") {
|
||||||
|
mux_state = 2;
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// v2rayN
|
// v2rayN
|
||||||
DECODE_V2RAY_N_1
|
DECODE_V2RAY_N_1
|
||||||
@ -210,6 +225,14 @@ namespace NekoGui_fmt {
|
|||||||
stream->utlsFingerprint = NekoGui::dataStore->utlsFingerprint;
|
stream->utlsFingerprint = NekoGui::dataStore->utlsFingerprint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mux
|
||||||
|
auto mux_str = GetQueryValue(query, "mux", "");
|
||||||
|
if (mux_str == "true") {
|
||||||
|
mux_state = 1;
|
||||||
|
} else if (mux_str == "false") {
|
||||||
|
mux_state = 2;
|
||||||
|
}
|
||||||
|
|
||||||
// type
|
// type
|
||||||
if (stream->network == "ws") {
|
if (stream->network == "ws") {
|
||||||
stream->path = GetQueryValue(query, "path", "");
|
stream->path = GetQueryValue(query, "path", "");
|
||||||
@ -263,7 +286,6 @@ namespace NekoGui_fmt {
|
|||||||
name = url.fragment(QUrl::FullyDecoded);
|
name = url.fragment(QUrl::FullyDecoded);
|
||||||
serverAddress = url.host();
|
serverAddress = url.host();
|
||||||
serverPort = url.port();
|
serverPort = url.port();
|
||||||
hopPort = query.queryItemValue("mport");
|
|
||||||
obfsPassword = query.queryItemValue("obfsParam");
|
obfsPassword = query.queryItemValue("obfsParam");
|
||||||
allowInsecure = QStringList{"1", "true"}.contains(query.queryItemValue("insecure"));
|
allowInsecure = QStringList{"1", "true"}.contains(query.queryItemValue("insecure"));
|
||||||
uploadMbps = query.queryItemValue("upmbps").toInt();
|
uploadMbps = query.queryItemValue("upmbps").toInt();
|
||||||
@ -308,7 +330,6 @@ namespace NekoGui_fmt {
|
|||||||
name = url.fragment(QUrl::FullyDecoded);
|
name = url.fragment(QUrl::FullyDecoded);
|
||||||
serverAddress = url.host();
|
serverAddress = url.host();
|
||||||
serverPort = url.port();
|
serverPort = url.port();
|
||||||
hopPort = query.queryItemValue("mport");
|
|
||||||
obfsPassword = query.queryItemValue("obfs-password");
|
obfsPassword = query.queryItemValue("obfs-password");
|
||||||
allowInsecure = QStringList{"1", "true"}.contains(query.queryItemValue("insecure"));
|
allowInsecure = QStringList{"1", "true"}.contains(query.queryItemValue("insecure"));
|
||||||
|
|
||||||
|
|||||||
@ -23,8 +23,6 @@ namespace NekoGui_fmt {
|
|||||||
|
|
||||||
QString DisplayType() override { return "Shadowsocks"; };
|
QString DisplayType() override { return "Shadowsocks"; };
|
||||||
|
|
||||||
CoreObjOutboundBuildResult BuildCoreObjV2Ray() override;
|
|
||||||
|
|
||||||
CoreObjOutboundBuildResult BuildCoreObjSingBox() override;
|
CoreObjOutboundBuildResult BuildCoreObjSingBox() override;
|
||||||
|
|
||||||
bool TryParseLink(const QString &link);
|
bool TryParseLink(const QString &link);
|
||||||
|
|||||||
@ -26,8 +26,6 @@ namespace NekoGui_fmt {
|
|||||||
|
|
||||||
QString DisplayType() override { return socks_http_type == type_HTTP ? "HTTP" : "Socks"; };
|
QString DisplayType() override { return socks_http_type == type_HTTP ? "HTTP" : "Socks"; };
|
||||||
|
|
||||||
CoreObjOutboundBuildResult BuildCoreObjV2Ray() override;
|
|
||||||
|
|
||||||
CoreObjOutboundBuildResult BuildCoreObjSingBox() override;
|
CoreObjOutboundBuildResult BuildCoreObjSingBox() override;
|
||||||
|
|
||||||
bool TryParseLink(const QString &link);
|
bool TryParseLink(const QString &link);
|
||||||
|
|||||||
@ -24,8 +24,6 @@ namespace NekoGui_fmt {
|
|||||||
|
|
||||||
QString DisplayType() override { return proxy_type == proxy_VLESS ? "VLESS" : "Trojan"; };
|
QString DisplayType() override { return proxy_type == proxy_VLESS ? "VLESS" : "Trojan"; };
|
||||||
|
|
||||||
CoreObjOutboundBuildResult BuildCoreObjV2Ray() override;
|
|
||||||
|
|
||||||
CoreObjOutboundBuildResult BuildCoreObjSingBox() override;
|
CoreObjOutboundBuildResult BuildCoreObjSingBox() override;
|
||||||
|
|
||||||
bool TryParseLink(const QString &link);
|
bool TryParseLink(const QString &link);
|
||||||
|
|||||||
@ -26,8 +26,6 @@ namespace NekoGui_fmt {
|
|||||||
QString reality_pbk = "";
|
QString reality_pbk = "";
|
||||||
QString reality_sid = "";
|
QString reality_sid = "";
|
||||||
QString reality_spx = "";
|
QString reality_spx = "";
|
||||||
// multiplex
|
|
||||||
int multiplex_status = 0;
|
|
||||||
|
|
||||||
V2rayStreamSettings() : JsonStore() {
|
V2rayStreamSettings() : JsonStore() {
|
||||||
_add(new configItem("net", &network, itemType::string));
|
_add(new configItem("net", &network, itemType::string));
|
||||||
@ -46,11 +44,8 @@ namespace NekoGui_fmt {
|
|||||||
_add(new configItem("pbk", &reality_pbk, itemType::string));
|
_add(new configItem("pbk", &reality_pbk, itemType::string));
|
||||||
_add(new configItem("sid", &reality_sid, itemType::string));
|
_add(new configItem("sid", &reality_sid, itemType::string));
|
||||||
_add(new configItem("spx", &reality_spx, itemType::string));
|
_add(new configItem("spx", &reality_spx, itemType::string));
|
||||||
_add(new configItem("mux_s", &multiplex_status, itemType::integer));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject BuildStreamSettingsV2Ray();
|
|
||||||
|
|
||||||
void BuildStreamSettingsSingBox(QJsonObject *outbound);
|
void BuildStreamSettingsSingBox(QJsonObject *outbound);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -21,8 +21,6 @@ namespace NekoGui_fmt {
|
|||||||
|
|
||||||
QString DisplayType() override { return "VMess"; };
|
QString DisplayType() override { return "VMess"; };
|
||||||
|
|
||||||
CoreObjOutboundBuildResult BuildCoreObjV2Ray() override;
|
|
||||||
|
|
||||||
CoreObjOutboundBuildResult BuildCoreObjSingBox() override;
|
CoreObjOutboundBuildResult BuildCoreObjSingBox() override;
|
||||||
|
|
||||||
bool TryParseLink(const QString &link);
|
bool TryParseLink(const QString &link);
|
||||||
|
|||||||
@ -23,15 +23,6 @@ pushd go/cmd/updater
|
|||||||
[ "$GOOS" == "linux" ] && mv $DEST/updater $DEST/launcher || true
|
[ "$GOOS" == "linux" ] && mv $DEST/updater $DEST/launcher || true
|
||||||
popd
|
popd
|
||||||
|
|
||||||
#### Go: nekoray_core ####
|
|
||||||
neko_common="github.com/matsuridayo/libneko/neko_common"
|
|
||||||
pushd ../Xray-core
|
|
||||||
Version_Xray=$(git log --pretty=format:'%h' -n 1)
|
|
||||||
popd
|
|
||||||
pushd go/cmd/nekoray_core
|
|
||||||
go build -v -o $DEST -trimpath -ldflags "-w -s -X $neko_common.Version_v2ray=$Version_Xray -X $neko_common.Version_neko=$version_standalone"
|
|
||||||
popd
|
|
||||||
|
|
||||||
#### Go: nekobox_core ####
|
#### Go: nekobox_core ####
|
||||||
pushd go/cmd/nekobox_core
|
pushd go/cmd/nekobox_core
|
||||||
go build -v -o $DEST -trimpath -ldflags "-w -s -X $neko_common.Version_neko=$version_standalone" -tags "with_clash_api,with_gvisor,with_quic,with_wireguard,with_utls,with_ech"
|
go build -v -o $DEST -trimpath -ldflags "-w -s -X $neko_common.Version_neko=$version_standalone" -tags "with_clash_api,with_gvisor,with_quic,with_wireguard,with_utls,with_ech"
|
||||||
|
|||||||
@ -18,7 +18,6 @@ namespace NekoGui {
|
|||||||
|
|
||||||
namespace CoreType {
|
namespace CoreType {
|
||||||
enum CoreType {
|
enum CoreType {
|
||||||
V2RAY,
|
|
||||||
SING_BOX,
|
SING_BOX,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
// Switch core support
|
// Switch core support
|
||||||
|
|
||||||
namespace NekoGui {
|
namespace NekoGui {
|
||||||
inline int coreType = CoreType::V2RAY;
|
inline int coreType = CoreType::SING_BOX;
|
||||||
|
|
||||||
QString FindCoreAsset(const QString &name);
|
QString FindCoreAsset(const QString &name);
|
||||||
|
|
||||||
|
|||||||
@ -164,19 +164,13 @@ int main(int argc, char* argv[]) {
|
|||||||
if (coreLoaded.isEmpty()) {
|
if (coreLoaded.isEmpty()) {
|
||||||
NekoGui::coreType = -1;
|
NekoGui::coreType = -1;
|
||||||
loadTranslate(QLocale().name());
|
loadTranslate(QLocale().name());
|
||||||
auto dialogFirstSetup = new DialogFirstSetup;
|
NekoGui::coreType = NekoGui::CoreType::SING_BOX;
|
||||||
dialogFirstSetup->exec();
|
QDir().mkdir("groups");
|
||||||
dialogFirstSetup->deleteLater();
|
QFile file;
|
||||||
if (NekoGui::coreType < 0) {
|
file.setFileName("groups/coreType");
|
||||||
return 0;
|
file.open(QIODevice::ReadWrite | QIODevice::Truncate);
|
||||||
} else {
|
file.write(Int2String(NekoGui::coreType).toUtf8());
|
||||||
QDir().mkdir("groups");
|
file.close();
|
||||||
QFile file;
|
|
||||||
file.setFileName("groups/coreType");
|
|
||||||
file.open(QIODevice::ReadWrite | QIODevice::Truncate);
|
|
||||||
file.write(Int2String(NekoGui::coreType).toUtf8());
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
NekoGui::coreType = coreLoaded.toInt();
|
NekoGui::coreType = coreLoaded.toInt();
|
||||||
}
|
}
|
||||||
@ -200,9 +194,6 @@ int main(int argc, char* argv[]) {
|
|||||||
|
|
||||||
// Load dataStore
|
// Load dataStore
|
||||||
switch (NekoGui::coreType) {
|
switch (NekoGui::coreType) {
|
||||||
case NekoGui::CoreType::V2RAY:
|
|
||||||
NekoGui::dataStore->fn = "groups/nekoray.json";
|
|
||||||
break;
|
|
||||||
case NekoGui::CoreType::SING_BOX:
|
case NekoGui::CoreType::SING_BOX:
|
||||||
NekoGui::dataStore->fn = "groups/nekobox.json";
|
NekoGui::dataStore->fn = "groups/nekobox.json";
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -278,7 +278,7 @@ namespace NekoGui_sub {
|
|||||||
|
|
||||||
// sing-mux
|
// sing-mux
|
||||||
auto smux = NodeChild(proxy, {"smux"});
|
auto smux = NodeChild(proxy, {"smux"});
|
||||||
if (Node2Bool(smux["enabled"])) bean->stream->multiplex_status = 1;
|
if (Node2Bool(smux["enabled"])) bean->mux_state = 1;
|
||||||
} else if (type == "socks" || type == "http") {
|
} else if (type == "socks" || type == "http") {
|
||||||
auto bean = ent->SocksHTTPBean();
|
auto bean = ent->SocksHTTPBean();
|
||||||
bean->username = Node2QString(proxy["username"]);
|
bean->username = Node2QString(proxy["username"]);
|
||||||
@ -313,7 +313,7 @@ namespace NekoGui_sub {
|
|||||||
|
|
||||||
// sing-mux
|
// sing-mux
|
||||||
auto smux = NodeChild(proxy, {"smux"});
|
auto smux = NodeChild(proxy, {"smux"});
|
||||||
if (Node2Bool(smux["enabled"])) bean->stream->multiplex_status = 1;
|
if (Node2Bool(smux["enabled"])) bean->mux_state = 1;
|
||||||
|
|
||||||
// opts
|
// opts
|
||||||
auto ws = NodeChild(proxy, {"ws-opts", "ws-opt"});
|
auto ws = NodeChild(proxy, {"ws-opts", "ws-opt"});
|
||||||
@ -358,7 +358,7 @@ namespace NekoGui_sub {
|
|||||||
|
|
||||||
// sing-mux
|
// sing-mux
|
||||||
auto smux = NodeChild(proxy, {"smux"});
|
auto smux = NodeChild(proxy, {"smux"});
|
||||||
if (Node2Bool(smux["enabled"])) bean->stream->multiplex_status = 1;
|
if (Node2Bool(smux["enabled"])) bean->mux_state = 1;
|
||||||
|
|
||||||
// meta packet encoding
|
// meta packet encoding
|
||||||
if (Node2Bool(proxy["xudp"])) bean->stream->packet_encoding = "xudp";
|
if (Node2Bool(proxy["xudp"])) bean->stream->packet_encoding = "xudp";
|
||||||
|
|||||||
@ -218,31 +218,7 @@ DialogBasicSettings::DialogBasicSettings(QWidget *parent)
|
|||||||
});
|
});
|
||||||
|
|
||||||
// switch core
|
// switch core
|
||||||
ui->switch_core_v2ray->setChecked(!IS_NEKO_BOX);
|
|
||||||
ui->switch_core_sing_box->setChecked(IS_NEKO_BOX);
|
ui->switch_core_sing_box->setChecked(IS_NEKO_BOX);
|
||||||
auto switch_core_on_click = [=] {
|
|
||||||
int neko_core_new;
|
|
||||||
if (sender() == ui->switch_core_sing_box) {
|
|
||||||
if (IS_NEKO_BOX) return;
|
|
||||||
neko_core_new = NekoGui::CoreType::SING_BOX;
|
|
||||||
} else {
|
|
||||||
if (!IS_NEKO_BOX) return;
|
|
||||||
neko_core_new = NekoGui::CoreType::V2RAY;
|
|
||||||
}
|
|
||||||
QString core_name_new = dynamic_cast<QRadioButton *>(sender())->text();
|
|
||||||
if (QMessageBox::question(this, tr("Confirmation"),
|
|
||||||
tr("Switching the core to %1, click \"Yes\" to complete the switch and the program will restart. This feature may be unstable, please do not switch frequently.")
|
|
||||||
.arg(core_name_new)) == QMessageBox::StandardButton::Yes) {
|
|
||||||
QFile file;
|
|
||||||
file.setFileName("groups/coreType");
|
|
||||||
file.open(QIODevice::ReadWrite | QIODevice::Truncate);
|
|
||||||
file.write(Int2String(neko_core_new).toUtf8());
|
|
||||||
file.close();
|
|
||||||
MW_dialog_message("", "RestartProgram");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
connect(ui->switch_core_v2ray, &QRadioButton::clicked, this, switch_core_on_click);
|
|
||||||
connect(ui->switch_core_sing_box, &QRadioButton::clicked, this, switch_core_on_click);
|
|
||||||
|
|
||||||
// Mux
|
// Mux
|
||||||
D_LOAD_INT(mux_concurrency)
|
D_LOAD_INT(mux_concurrency)
|
||||||
|
|||||||
@ -13,10 +13,6 @@ DialogFirstSetup::~DialogFirstSetup() {
|
|||||||
|
|
||||||
void DialogFirstSetup::onButtonClicked() {
|
void DialogFirstSetup::onButtonClicked() {
|
||||||
auto s = sender();
|
auto s = sender();
|
||||||
if (s == ui->v2ray) {
|
NekoGui::coreType = NekoGui::CoreType::SING_BOX;
|
||||||
NekoGui::coreType = NekoGui::CoreType::V2RAY;
|
|
||||||
} else if (s == ui->singbox) {
|
|
||||||
NekoGui::coreType = NekoGui::CoreType::SING_BOX;
|
|
||||||
}
|
|
||||||
done(0);
|
done(0);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -236,7 +236,7 @@ void DialogEditProfile::typeSelected(const QString &newType) {
|
|||||||
ui->ws_early_data_length->setText(Int2String(stream->ws_early_data_length));
|
ui->ws_early_data_length->setText(Int2String(stream->ws_early_data_length));
|
||||||
ui->reality_pbk->setText(stream->reality_pbk);
|
ui->reality_pbk->setText(stream->reality_pbk);
|
||||||
ui->reality_sid->setText(stream->reality_sid);
|
ui->reality_sid->setText(stream->reality_sid);
|
||||||
ui->multiplex->setCurrentIndex(stream->multiplex_status);
|
ui->multiplex->setCurrentIndex(ent->bean->mux_state);
|
||||||
CACHE.certificate = stream->certificate;
|
CACHE.certificate = stream->certificate;
|
||||||
} else {
|
} else {
|
||||||
ui->right_all_w->setVisible(false);
|
ui->right_all_w->setVisible(false);
|
||||||
@ -371,7 +371,7 @@ bool DialogEditProfile::onEnd() {
|
|||||||
stream->ws_early_data_length = ui->ws_early_data_length->text().toInt();
|
stream->ws_early_data_length = ui->ws_early_data_length->text().toInt();
|
||||||
stream->reality_pbk = ui->reality_pbk->text();
|
stream->reality_pbk = ui->reality_pbk->text();
|
||||||
stream->reality_sid = ui->reality_sid->text();
|
stream->reality_sid = ui->reality_sid->text();
|
||||||
stream->multiplex_status = ui->multiplex->currentIndex();
|
ent->bean->mux_state = ui->multiplex->currentIndex();
|
||||||
stream->certificate = CACHE.certificate;
|
stream->certificate = CACHE.certificate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -515,7 +515,7 @@ void DialogEditProfile::do_apply_to_group(const std::shared_ptr<NekoGui::Group>
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (key == ui->multiplex) {
|
if (key == ui->multiplex) {
|
||||||
copyStream(&stream->multiplex_status);
|
copyStream(&ent->bean->mux_state);
|
||||||
} else if (key == ui->sni) {
|
} else if (key == ui->sni) {
|
||||||
copyStream(&stream->sni);
|
copyStream(&stream->sni);
|
||||||
} else if (key == ui->alpn) {
|
} else if (key == ui->alpn) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user