mirror of
https://github.com/MatsuriDayo/nekoray.git
synced 2025-12-17 12:34:37 +03:00
feat: add TUIC protocol (#781)
--------- Co-authored-by: 2022-blake3-chacha8-poly1305 <139959885+xchacha20-ietf-poly1305@users.noreply.github.com> Co-authored-by: arm64v8a <48624112+arm64v8a@users.noreply.github.com>
This commit is contained in:
@@ -213,9 +213,9 @@ set(PROJECT_SOURCES
|
||||
ui/edit/edit_naive.cpp
|
||||
ui/edit/edit_naive.ui
|
||||
|
||||
ui/edit/edit_hysteria.h
|
||||
ui/edit/edit_hysteria.cpp
|
||||
ui/edit/edit_hysteria.ui
|
||||
ui/edit/edit_quic.h
|
||||
ui/edit/edit_quic.cpp
|
||||
ui/edit/edit_quic.ui
|
||||
|
||||
ui/edit/edit_custom.h
|
||||
ui/edit/edit_custom.cpp
|
||||
|
||||
@@ -45,6 +45,7 @@ https://matsuridayo.github.io
|
||||
* VMess
|
||||
* VLESS
|
||||
* Trojan
|
||||
* TUIC ( sing-box )
|
||||
* NaïveProxy ( Custom Core )
|
||||
* Hysteria ( Custom Core or sing-box )
|
||||
* Custom Outbound
|
||||
|
||||
@@ -185,7 +185,9 @@ namespace NekoGui {
|
||||
} else if (type == "naive") {
|
||||
bean = new NekoGui_fmt::NaiveBean();
|
||||
} else if (type == "hysteria") {
|
||||
bean = new NekoGui_fmt::HysteriaBean();
|
||||
bean = new NekoGui_fmt::QUICBean(NekoGui_fmt::QUICBean::proxy_Hysteria);
|
||||
} else if (type == "tuic") {
|
||||
bean = new NekoGui_fmt::QUICBean(NekoGui_fmt::QUICBean::proxy_TUIC);
|
||||
} else if (type == "custom") {
|
||||
bean = new NekoGui_fmt::CustomBean();
|
||||
} else {
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace NekoGui_fmt {
|
||||
|
||||
class NaiveBean;
|
||||
|
||||
class HysteriaBean;
|
||||
class QUICBean;
|
||||
|
||||
class CustomBean;
|
||||
|
||||
@@ -65,8 +65,8 @@ namespace NekoGui {
|
||||
return (NekoGui_fmt::NaiveBean *) bean.get();
|
||||
};
|
||||
|
||||
[[nodiscard]] NekoGui_fmt::HysteriaBean *HysteriaBean() const {
|
||||
return (NekoGui_fmt::HysteriaBean *) bean.get();
|
||||
[[nodiscard]] NekoGui_fmt::QUICBean *QUICBean() const {
|
||||
return (NekoGui_fmt::QUICBean *) bean.get();
|
||||
};
|
||||
|
||||
[[nodiscard]] NekoGui_fmt::CustomBean *CustomBean() const {
|
||||
|
||||
@@ -169,36 +169,47 @@ namespace NekoGui_fmt {
|
||||
return result;
|
||||
}
|
||||
|
||||
CoreObjOutboundBuildResult HysteriaBean::BuildCoreObjSingBox() {
|
||||
CoreObjOutboundBuildResult QUICBean::BuildCoreObjSingBox() {
|
||||
CoreObjOutboundBuildResult result;
|
||||
|
||||
QJsonObject coreTlsObj{
|
||||
{"enabled", true},
|
||||
{"disable_sni", disableSni},
|
||||
{"insecure", allowInsecure},
|
||||
{"certificate", caText.trimmed()},
|
||||
{"server_name", sni},
|
||||
};
|
||||
if (!alpn.trimmed().isEmpty()) coreTlsObj["alpn"] = QJsonArray{alpn};
|
||||
if (!alpn.trimmed().isEmpty()) coreTlsObj["alpn"] = QList2QJsonArray(alpn.split(","));
|
||||
|
||||
QJsonObject coreHysteriaObj{
|
||||
{"type", "hysteria"},
|
||||
QJsonObject outbound{
|
||||
{"server", serverAddress},
|
||||
{"server_port", serverPort},
|
||||
{"obfs", obfsPassword},
|
||||
{"disable_mtu_discovery", disableMtuDiscovery},
|
||||
{"recv_window", streamReceiveWindow},
|
||||
{"recv_window_conn", connectionReceiveWindow},
|
||||
{"up_mbps", uploadMbps},
|
||||
{"down_mbps", downloadMbps},
|
||||
{"tls", coreTlsObj},
|
||||
};
|
||||
|
||||
if (!hopPort.trimmed().isEmpty()) coreHysteriaObj["hop_ports"] = hopPort;
|
||||
if (proxy_type == proxy_Hysteria) {
|
||||
outbound["type"] = "hysteria";
|
||||
outbound["obfs"] = obfsPassword;
|
||||
outbound["disable_mtu_discovery"] = disableMtuDiscovery;
|
||||
outbound["recv_window"] = streamReceiveWindow;
|
||||
outbound["recv_window_conn"] = connectionReceiveWindow;
|
||||
outbound["up_mbps"] = uploadMbps;
|
||||
outbound["down_mbps"] = downloadMbps;
|
||||
|
||||
if (authPayloadType == hysteria_auth_base64) coreHysteriaObj["auth"] = authPayload;
|
||||
if (authPayloadType == hysteria_auth_string) coreHysteriaObj["auth_str"] = authPayload;
|
||||
if (!hopPort.trimmed().isEmpty()) outbound["hop_ports"] = hopPort;
|
||||
if (authPayloadType == hysteria_auth_base64) outbound["auth"] = authPayload;
|
||||
if (authPayloadType == hysteria_auth_string) outbound["auth_str"] = authPayload;
|
||||
} else if (proxy_type == proxy_TUIC) {
|
||||
outbound["type"] = "tuic";
|
||||
outbound["uuid"] = uuid;
|
||||
outbound["password"] = password;
|
||||
outbound["congestion_control"] = congestionControl;
|
||||
outbound["udp_relay_mode"] = udpRelayMode;
|
||||
outbound["zero_rtt_handshake"] = zeroRttHandshake;
|
||||
if (!heartbeat.trimmed().isEmpty()) outbound["heartbeat"] = heartbeat;
|
||||
}
|
||||
|
||||
result.outbound = coreHysteriaObj;
|
||||
result.outbound = outbound;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,29 +35,41 @@ namespace NekoGui_fmt {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int HysteriaBean::NeedExternal(bool isFirstProfile) {
|
||||
int QUICBean::NeedExternal(bool isFirstProfile) {
|
||||
auto hysteriaCore = [=] {
|
||||
if (isFirstProfile) {
|
||||
if (NekoGui::dataStore->spmode_vpn && protocol != hysteria_protocol_facktcp && hopPort.trimmed().isEmpty()) {
|
||||
if (NekoGui::dataStore->spmode_vpn && hyProtocol != hysteria_protocol_facktcp && hopPort.trimmed().isEmpty()) {
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
} else {
|
||||
if (protocol == hysteria_protocol_facktcp || !hopPort.trimmed().isEmpty()) {
|
||||
if (hyProtocol == hysteria_protocol_facktcp || !hopPort.trimmed().isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
};
|
||||
|
||||
auto tuicCore = [=] {
|
||||
if (isFirstProfile) {
|
||||
if (NekoGui::dataStore->spmode_vpn) {
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
return 1;
|
||||
};
|
||||
|
||||
if (IS_NEKO_BOX) {
|
||||
if (protocol == hysteria_protocol_udp) {
|
||||
if (proxy_type == proxy_TUIC || hyProtocol == hysteria_protocol_udp) {
|
||||
// sing-box support
|
||||
return 0;
|
||||
} else {
|
||||
// hysteria core support
|
||||
return hysteriaCore();
|
||||
}
|
||||
} else if (proxy_type == proxy_TUIC) {
|
||||
return tuicCore();
|
||||
} else {
|
||||
return hysteriaCore();
|
||||
}
|
||||
@@ -104,7 +116,53 @@ namespace NekoGui_fmt {
|
||||
return result;
|
||||
}
|
||||
|
||||
ExternalBuildResult HysteriaBean::BuildExternal(int mapping_port, int socks_port, int external_stat) {
|
||||
ExternalBuildResult QUICBean::BuildExternal(int mapping_port, int socks_port, int external_stat) {
|
||||
if (proxy_type == proxy_TUIC) {
|
||||
ExternalBuildResult result{NekoGui::dataStore->extraCore->Get("tuic")};
|
||||
|
||||
QJsonObject relay;
|
||||
|
||||
relay["uuid"] = uuid;
|
||||
relay["password"] = password;
|
||||
relay["udp_relay_mode"] = udpRelayMode;
|
||||
relay["congestion_control"] = congestionControl;
|
||||
relay["zero_rtt_handshake"] = zeroRttHandshake;
|
||||
relay["disable_sni"] = disableSni;
|
||||
if (!heartbeat.trimmed().isEmpty()) relay["heartbeat"] = heartbeat;
|
||||
if (!alpn.trimmed().isEmpty()) relay["alpn"] = QList2QJsonArray(alpn.split(","));
|
||||
|
||||
if (!caText.trimmed().isEmpty()) {
|
||||
WriteTempFile("tuic_" + GetRandomString(10) + ".crt", caText.toUtf8());
|
||||
QJsonArray certificate;
|
||||
certificate.append(TempFile);
|
||||
relay["certificates"] = certificate;
|
||||
}
|
||||
|
||||
// The most confused part of TUIC......
|
||||
if (serverAddress == sni) {
|
||||
relay["server"] = serverAddress + ":" + Int2String(serverPort);
|
||||
} else {
|
||||
relay["server"] = sni + ":" + Int2String(serverPort);
|
||||
relay["ip"] = serverAddress;
|
||||
}
|
||||
|
||||
QJsonObject local{
|
||||
{"server", "127.0.0.1:" + Int2String(socks_port)},
|
||||
};
|
||||
|
||||
QJsonObject config{
|
||||
{"relay", relay},
|
||||
{"local", local},
|
||||
};
|
||||
|
||||
//
|
||||
|
||||
result.config_export = QJsonObject2QString(config, false);
|
||||
WriteTempFile("tuic_" + GetRandomString(10) + ".json", result.config_export.toUtf8());
|
||||
result.arguments = QStringList{"-c", TempFile};
|
||||
|
||||
return result;
|
||||
} else { // Hysteria
|
||||
ExternalBuildResult result{NekoGui::dataStore->extraCore->Get("hysteria")};
|
||||
|
||||
QJsonObject config;
|
||||
@@ -139,8 +197,8 @@ namespace NekoGui_fmt {
|
||||
if (authPayloadType == hysteria_auth_base64) config["auth"] = authPayload;
|
||||
if (authPayloadType == hysteria_auth_string) config["auth_str"] = authPayload;
|
||||
|
||||
if (protocol == hysteria_protocol_facktcp) config["protocol"] = "faketcp";
|
||||
if (protocol == hysteria_protocol_wechat_video) config["protocol"] = "wechat-video";
|
||||
if (hyProtocol == hysteria_protocol_facktcp) config["protocol"] = "faketcp";
|
||||
if (hyProtocol == hysteria_protocol_wechat_video) config["protocol"] = "wechat-video";
|
||||
|
||||
if (!sniGen.isEmpty()) config["server_name"] = sniGen;
|
||||
if (!alpn.isEmpty()) config["alpn"] = alpn;
|
||||
@@ -164,6 +222,7 @@ namespace NekoGui_fmt {
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
ExternalBuildResult CustomBean::BuildExternal(int mapping_port, int socks_port, int external_stat) {
|
||||
ExternalBuildResult result{NekoGui::dataStore->extraCore->Get(core)};
|
||||
@@ -206,4 +265,5 @@ namespace NekoGui_fmt {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace NekoGui_fmt
|
||||
@@ -1,3 +1,4 @@
|
||||
#include "QUICBean.hpp"
|
||||
#include "db/ProxyEntity.hpp"
|
||||
#include "fmt/includes.h"
|
||||
|
||||
@@ -127,8 +128,9 @@ namespace NekoGui_fmt {
|
||||
return url.toString(QUrl::FullyEncoded);
|
||||
}
|
||||
|
||||
QString HysteriaBean::ToShareLink() {
|
||||
QString QUICBean::ToShareLink() {
|
||||
QUrl url;
|
||||
if (proxy_type == proxy_Hysteria) {
|
||||
url.setScheme("hysteria");
|
||||
url.setHost(serverAddress);
|
||||
url.setPort(serverPort);
|
||||
@@ -140,8 +142,8 @@ namespace NekoGui_fmt {
|
||||
q.addQueryItem("obfsParam", obfsPassword);
|
||||
}
|
||||
if (authPayloadType == hysteria_auth_string) q.addQueryItem("auth", authPayload);
|
||||
if (protocol == hysteria_protocol_facktcp) q.addQueryItem("protocol", "faketcp");
|
||||
if (protocol == hysteria_protocol_wechat_video) q.addQueryItem("protocol", "wechat-video");
|
||||
if (hyProtocol == hysteria_protocol_facktcp) q.addQueryItem("protocol", "faketcp");
|
||||
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 (!sni.isEmpty()) q.addQueryItem("peer", sni);
|
||||
@@ -150,6 +152,9 @@ namespace NekoGui_fmt {
|
||||
if (streamReceiveWindow > 0) q.addQueryItem("recv_window_conn", Int2String(streamReceiveWindow));
|
||||
if (!q.isEmpty()) url.setQuery(q);
|
||||
if (!name.isEmpty()) url.setFragment(name);
|
||||
} else if (proxy_type == proxy_TUIC) {
|
||||
// TODO std link
|
||||
}
|
||||
return url.toString(QUrl::FullyEncoded);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "fmt/AbstractBean.hpp"
|
||||
|
||||
namespace NekoGui_fmt {
|
||||
class HysteriaBean : public AbstractBean {
|
||||
public:
|
||||
static constexpr int hysteria_protocol_udp = 0;
|
||||
static constexpr int hysteria_protocol_facktcp = 1;
|
||||
static constexpr int hysteria_protocol_wechat_video = 2;
|
||||
|
||||
int protocol = 0;
|
||||
|
||||
//
|
||||
|
||||
static constexpr int hysteria_auth_none = 0;
|
||||
static constexpr int hysteria_auth_string = 1;
|
||||
static constexpr int hysteria_auth_base64 = 2;
|
||||
|
||||
int authPayloadType = 0;
|
||||
QString authPayload = "";
|
||||
QString obfsPassword = "";
|
||||
|
||||
//
|
||||
|
||||
int uploadMbps = 100;
|
||||
int downloadMbps = 100;
|
||||
|
||||
qint64 streamReceiveWindow = 0;
|
||||
qint64 connectionReceiveWindow = 0;
|
||||
bool disableMtuDiscovery = false;
|
||||
|
||||
bool allowInsecure = false;
|
||||
QString sni = "";
|
||||
QString alpn = ""; // only 1
|
||||
QString caText = "";
|
||||
|
||||
//
|
||||
|
||||
int hopInterval = 10;
|
||||
QString hopPort = "";
|
||||
|
||||
HysteriaBean() : AbstractBean(0) {
|
||||
_add(new configItem("protocol", &protocol, itemType::integer));
|
||||
_add(new configItem("authPayloadType", &authPayloadType, itemType::integer));
|
||||
_add(new configItem("authPayload", &authPayload, itemType::string));
|
||||
_add(new configItem("obfsPassword", &obfsPassword, itemType::string));
|
||||
_add(new configItem("uploadMbps", &uploadMbps, itemType::integer));
|
||||
_add(new configItem("downloadMbps", &downloadMbps, itemType::integer));
|
||||
_add(new configItem("streamReceiveWindow", &streamReceiveWindow, itemType::integer64));
|
||||
_add(new configItem("connectionReceiveWindow", &connectionReceiveWindow, itemType::integer64));
|
||||
_add(new configItem("disableMtuDiscovery", &disableMtuDiscovery, itemType::boolean));
|
||||
_add(new configItem("allowInsecure", &allowInsecure, itemType::boolean));
|
||||
_add(new configItem("sni", &sni, itemType::string));
|
||||
_add(new configItem("alpn", &alpn, itemType::string));
|
||||
_add(new configItem("caText", &caText, itemType::string));
|
||||
_add(new configItem("hopInterval", &hopInterval, itemType::integer));
|
||||
_add(new configItem("hopPort", &hopPort, itemType::string));
|
||||
};
|
||||
|
||||
QString DisplayAddress() override {
|
||||
if (!hopPort.trimmed().isEmpty()) return WrapIPV6Host(serverAddress) + ":" + hopPort;
|
||||
return ::DisplayAddress(serverAddress, serverPort);
|
||||
}
|
||||
|
||||
QString DisplayCoreType() override { return NeedExternal(true) == 0 ? software_core_name : "Hysteria"; };
|
||||
|
||||
QString DisplayType() override { return "Hysteria"; };
|
||||
|
||||
int NeedExternal(bool isFirstProfile) override;
|
||||
|
||||
ExternalBuildResult BuildExternal(int mapping_port, int socks_port, int external_stat) override;
|
||||
|
||||
CoreObjOutboundBuildResult BuildCoreObjSingBox() override;
|
||||
|
||||
bool TryParseLink(const QString &link);
|
||||
|
||||
QString ToShareLink() override;
|
||||
};
|
||||
} // namespace NekoGui_fmt
|
||||
@@ -1,3 +1,4 @@
|
||||
#include "QUICBean.hpp"
|
||||
#include "db/ProxyEntity.hpp"
|
||||
#include "fmt/includes.h"
|
||||
|
||||
@@ -174,11 +175,14 @@ namespace NekoGui_fmt {
|
||||
return !(username.isEmpty() || password.isEmpty() || serverAddress.isEmpty());
|
||||
}
|
||||
|
||||
bool HysteriaBean::TryParseLink(const QString &link) {
|
||||
bool QUICBean::TryParseLink(const QString &link) {
|
||||
// https://hysteria.network/docs/uri-scheme/
|
||||
auto url = QUrl(link);
|
||||
auto query = QUrlQuery(url.query());
|
||||
if (url.host().isEmpty() || url.port() == -1 || !query.hasQueryItem("upmbps") || !query.hasQueryItem("downmbps")) return false;
|
||||
if (url.host().isEmpty() || url.port() == -1) return false;
|
||||
|
||||
if (url.scheme() == "hysteria") {
|
||||
if (!query.hasQueryItem("upmbps") || !query.hasQueryItem("downmbps")) return false;
|
||||
|
||||
name = url.fragment();
|
||||
serverAddress = url.host();
|
||||
@@ -192,14 +196,14 @@ namespace NekoGui_fmt {
|
||||
|
||||
auto protocolStr = (query.hasQueryItem("protocol") ? query.queryItemValue("protocol") : "udp").toLower();
|
||||
if (protocolStr == "faketcp") {
|
||||
protocol = NekoGui_fmt::HysteriaBean::hysteria_protocol_facktcp;
|
||||
hyProtocol = NekoGui_fmt::QUICBean::hysteria_protocol_facktcp;
|
||||
} else if (protocolStr.startsWith("wechat")) {
|
||||
protocol = NekoGui_fmt::HysteriaBean::hysteria_protocol_wechat_video;
|
||||
hyProtocol = NekoGui_fmt::QUICBean::hysteria_protocol_wechat_video;
|
||||
}
|
||||
|
||||
if (query.hasQueryItem("auth")) {
|
||||
authPayload = query.queryItemValue("auth");
|
||||
authPayloadType = NekoGui_fmt::HysteriaBean::hysteria_auth_string;
|
||||
authPayloadType = NekoGui_fmt::QUICBean::hysteria_auth_string;
|
||||
}
|
||||
|
||||
alpn = query.queryItemValue("alpn");
|
||||
@@ -207,6 +211,10 @@ namespace NekoGui_fmt {
|
||||
|
||||
connectionReceiveWindow = query.queryItemValue("recv_window").toInt();
|
||||
streamReceiveWindow = query.queryItemValue("recv_window_conn").toInt();
|
||||
} else {
|
||||
// TODO TUIC std link
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
103
fmt/QUICBean.hpp
Normal file
103
fmt/QUICBean.hpp
Normal file
@@ -0,0 +1,103 @@
|
||||
#pragma once
|
||||
|
||||
#include "fmt/AbstractBean.hpp"
|
||||
|
||||
namespace NekoGui_fmt {
|
||||
class QUICBean : public AbstractBean {
|
||||
public:
|
||||
static constexpr int proxy_Hysteria = 0;
|
||||
static constexpr int proxy_TUIC = 1;
|
||||
int proxy_type = proxy_Hysteria;
|
||||
|
||||
// Hysteria
|
||||
|
||||
static constexpr int hysteria_protocol_udp = 0;
|
||||
static constexpr int hysteria_protocol_facktcp = 1;
|
||||
static constexpr int hysteria_protocol_wechat_video = 2;
|
||||
int hyProtocol = 0;
|
||||
|
||||
static constexpr int hysteria_auth_none = 0;
|
||||
static constexpr int hysteria_auth_string = 1;
|
||||
static constexpr int hysteria_auth_base64 = 2;
|
||||
int authPayloadType = 0;
|
||||
|
||||
QString authPayload = "";
|
||||
QString obfsPassword = "";
|
||||
|
||||
int uploadMbps = 100;
|
||||
int downloadMbps = 100;
|
||||
|
||||
qint64 streamReceiveWindow = 0;
|
||||
qint64 connectionReceiveWindow = 0;
|
||||
bool disableMtuDiscovery = false;
|
||||
|
||||
int hopInterval = 10;
|
||||
QString hopPort = "";
|
||||
|
||||
// TUIC
|
||||
|
||||
QString uuid = "";
|
||||
QString password = "";
|
||||
QString congestionControl = "bbr";
|
||||
QString udpRelayMode = "native";
|
||||
bool zeroRttHandshake = false;
|
||||
QString heartbeat = "10s";
|
||||
|
||||
// TLS
|
||||
|
||||
bool allowInsecure = false;
|
||||
QString sni = "";
|
||||
QString alpn = "";
|
||||
QString caText = "";
|
||||
bool disableSni = false;
|
||||
|
||||
explicit QUICBean(int _proxy_type) : AbstractBean(0) {
|
||||
proxy_type = _proxy_type;
|
||||
if (proxy_type == proxy_Hysteria) {
|
||||
_add(new configItem("protocol", &hyProtocol, itemType::integer));
|
||||
_add(new configItem("authPayloadType", &authPayloadType, itemType::integer));
|
||||
_add(new configItem("authPayload", &authPayload, itemType::string));
|
||||
_add(new configItem("obfsPassword", &obfsPassword, itemType::string));
|
||||
_add(new configItem("uploadMbps", &uploadMbps, itemType::integer));
|
||||
_add(new configItem("downloadMbps", &downloadMbps, itemType::integer));
|
||||
_add(new configItem("streamReceiveWindow", &streamReceiveWindow, itemType::integer64));
|
||||
_add(new configItem("connectionReceiveWindow", &connectionReceiveWindow, itemType::integer64));
|
||||
_add(new configItem("disableMtuDiscovery", &disableMtuDiscovery, itemType::boolean));
|
||||
_add(new configItem("hopInterval", &hopInterval, itemType::integer));
|
||||
_add(new configItem("hopPort", &hopPort, itemType::string));
|
||||
} else if (proxy_type == proxy_TUIC) {
|
||||
_add(new configItem("uuid", &uuid, itemType::string));
|
||||
_add(new configItem("password", &password, itemType::string));
|
||||
_add(new configItem("congestionControl", &congestionControl, itemType::string));
|
||||
_add(new configItem("udpRelayMode", &udpRelayMode, itemType::string));
|
||||
_add(new configItem("zeroRttHandshake", &zeroRttHandshake, itemType::boolean));
|
||||
_add(new configItem("heartbeat", &heartbeat, itemType::string));
|
||||
}
|
||||
// TLS
|
||||
_add(new configItem("allowInsecure", &allowInsecure, itemType::boolean));
|
||||
_add(new configItem("sni", &sni, itemType::string));
|
||||
_add(new configItem("alpn", &alpn, itemType::string));
|
||||
_add(new configItem("caText", &caText, itemType::string));
|
||||
_add(new configItem("disableSni", &disableSni, itemType::boolean));
|
||||
};
|
||||
|
||||
QString DisplayAddress() override {
|
||||
if (!hopPort.trimmed().isEmpty()) return WrapIPV6Host(serverAddress) + ":" + hopPort;
|
||||
return ::DisplayAddress(serverAddress, serverPort);
|
||||
}
|
||||
|
||||
QString DisplayCoreType() override { return NeedExternal(true) == 0 ? software_core_name : "Hysteria"; };
|
||||
|
||||
QString DisplayType() override { return proxy_type == proxy_TUIC ? "TUIC" : "Hysteria"; };
|
||||
|
||||
int NeedExternal(bool isFirstProfile) override;
|
||||
|
||||
ExternalBuildResult BuildExternal(int mapping_port, int socks_port, int external_stat) override;
|
||||
|
||||
CoreObjOutboundBuildResult BuildCoreObjSingBox() override;
|
||||
|
||||
bool TryParseLink(const QString &link);
|
||||
|
||||
QString ToShareLink() override;
|
||||
};
|
||||
} // namespace NekoGui_fmt
|
||||
@@ -6,5 +6,5 @@
|
||||
#include "VMessBean.hpp"
|
||||
#include "TrojanVLESSBean.hpp"
|
||||
#include "NaiveBean.hpp"
|
||||
#include "HysteriaBean.hpp"
|
||||
#include "QUICBean.hpp"
|
||||
#include "CustomBean.hpp"
|
||||
|
||||
@@ -28,6 +28,7 @@ require (
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||
github.com/gofrs/uuid/v5 v5.0.0 // indirect
|
||||
github.com/golang/mock v1.6.0 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/google/btree v1.1.2 // indirect
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
|
||||
@@ -48,14 +49,12 @@ require (
|
||||
github.com/pierrec/lz4/v4 v4.1.14 // indirect
|
||||
github.com/pires/go-proxyproto v0.7.0 // indirect
|
||||
github.com/quic-go/qpack v0.4.0 // indirect
|
||||
github.com/quic-go/qtls-go1-18 v0.2.0 // indirect
|
||||
github.com/quic-go/qtls-go1-19 v0.3.2 // indirect
|
||||
github.com/quic-go/qtls-go1-20 v0.2.2 // indirect
|
||||
github.com/quic-go/qtls-go1-20 v0.3.1 // indirect
|
||||
github.com/sagernet/cloudflare-tls v0.0.0-20221031050923-d70792f4c3a0 // indirect
|
||||
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 // indirect
|
||||
github.com/sagernet/gvisor v0.0.0-20230627031050-1ab0276e0dd2 // indirect
|
||||
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 // indirect
|
||||
github.com/sagernet/quic-go v0.0.0-20230731154841-cdc97aca6239 // indirect
|
||||
github.com/sagernet/quic-go v0.0.0-20230809023643-d720ed35ac2b // indirect
|
||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 // indirect
|
||||
github.com/sagernet/sing v0.2.10-0.20230807080248-4db0062caa0a // indirect
|
||||
github.com/sagernet/sing-dns v0.1.9-0.20230731012726-ad50da89b659 // indirect
|
||||
@@ -63,7 +62,7 @@ require (
|
||||
github.com/sagernet/sing-shadowsocks v0.2.4 // indirect
|
||||
github.com/sagernet/sing-shadowsocks2 v0.1.3 // indirect
|
||||
github.com/sagernet/sing-shadowtls v0.1.4 // indirect
|
||||
github.com/sagernet/sing-tun v0.1.12-0.20230808064040-326c20ab22af // indirect
|
||||
github.com/sagernet/sing-tun v0.1.12-0.20230808120247-47ab78d303db // indirect
|
||||
github.com/sagernet/sing-vmess v0.1.7 // indirect
|
||||
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 // indirect
|
||||
github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9 // indirect
|
||||
|
||||
@@ -60,6 +60,7 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
||||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
@@ -120,12 +121,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
|
||||
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
|
||||
github.com/quic-go/qtls-go1-18 v0.2.0 h1:5ViXqBZ90wpUcZS0ge79rf029yx0dYB0McyPJwqqj7U=
|
||||
github.com/quic-go/qtls-go1-18 v0.2.0/go.mod h1:moGulGHK7o6O8lSPSZNoOwcLvJKJ85vVNc7oJFD65bc=
|
||||
github.com/quic-go/qtls-go1-19 v0.3.2 h1:tFxjCFcTQzK+oMxG6Zcvp4Dq8dx4yD3dDiIiyc86Z5U=
|
||||
github.com/quic-go/qtls-go1-19 v0.3.2/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI=
|
||||
github.com/quic-go/qtls-go1-20 v0.2.2 h1:WLOPx6OY/hxtTxKV1Zrq20FtXtDEkeY00CGQm8GEa3E=
|
||||
github.com/quic-go/qtls-go1-20 v0.2.2/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM=
|
||||
github.com/quic-go/qtls-go1-20 v0.3.1 h1:O4BLOM3hwfVF3AcktIylQXyl7Yi2iBNVy5QsV+ySxbg=
|
||||
github.com/quic-go/qtls-go1-20 v0.3.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sagernet/cloudflare-tls v0.0.0-20221031050923-d70792f4c3a0 h1:KyhtFFt1Jtp5vW2ohNvstvQffTOQ/s5vENuGXzdA+TM=
|
||||
github.com/sagernet/cloudflare-tls v0.0.0-20221031050923-d70792f4c3a0/go.mod h1:D4SFEOkJK+4W1v86ZhX0jPM0rAL498fyQAChqMtes/I=
|
||||
@@ -135,8 +132,8 @@ github.com/sagernet/gvisor v0.0.0-20230627031050-1ab0276e0dd2 h1:dnkKrzapqtAwjTS
|
||||
github.com/sagernet/gvisor v0.0.0-20230627031050-1ab0276e0dd2/go.mod h1:1JUiV7nGuf++YFm9eWZ8q2lrwHmhcUGzptMl/vL1+LA=
|
||||
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE=
|
||||
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
|
||||
github.com/sagernet/quic-go v0.0.0-20230731154841-cdc97aca6239 h1:UwKDwYDzGc9FGBYm3pr7SpaEQcjYdnfjtRDvePHtcBA=
|
||||
github.com/sagernet/quic-go v0.0.0-20230731154841-cdc97aca6239/go.mod h1:5rilP6WxqIl/4ypZbMjr+MK+STxuCEvO5yVtEyYNZ6g=
|
||||
github.com/sagernet/quic-go v0.0.0-20230809023643-d720ed35ac2b h1:+hpCW1zw03nnJDx+5tF9ETb6bKl2VSftv4KMGZAHC2Q=
|
||||
github.com/sagernet/quic-go v0.0.0-20230809023643-d720ed35ac2b/go.mod h1:w+nln6f/ZtyPpGbFxmgd5iYFVMmgS+gpD5hu5GAqC1I=
|
||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc=
|
||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
|
||||
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
||||
@@ -153,8 +150,8 @@ github.com/sagernet/sing-shadowsocks2 v0.1.3 h1:WXoLvCFi5JTFBRYorf1YePGYIQyJ/zbs
|
||||
github.com/sagernet/sing-shadowsocks2 v0.1.3/go.mod h1:DOhJc/cLeqRv0wuePrQso+iUmDxOnWF4eT/oMcRzYFw=
|
||||
github.com/sagernet/sing-shadowtls v0.1.4 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k=
|
||||
github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4=
|
||||
github.com/sagernet/sing-tun v0.1.12-0.20230808064040-326c20ab22af h1:gC2vTbt2wrfPv3P33fLIrtM6YUt1w7muRrMk62g6Ykk=
|
||||
github.com/sagernet/sing-tun v0.1.12-0.20230808064040-326c20ab22af/go.mod h1:XsyIVKd/Qp+2SdLZWGbavHtcpE7J7XU3S1zJmcoj9Ck=
|
||||
github.com/sagernet/sing-tun v0.1.12-0.20230808120247-47ab78d303db h1:jOwG+7u4NtQVwXj5pFnGeNnDoa2cv83O5x4NLKN8y/c=
|
||||
github.com/sagernet/sing-tun v0.1.12-0.20230808120247-47ab78d303db/go.mod h1:XsyIVKd/Qp+2SdLZWGbavHtcpE7J7XU3S1zJmcoj9Ck=
|
||||
github.com/sagernet/sing-vmess v0.1.7 h1:TM8FFLsXmlXH9XT8/oDgc6PC5BOzrg6OzyEe01is2r4=
|
||||
github.com/sagernet/sing-vmess v0.1.7/go.mod h1:1qkC1L1T2sxnS/NuO6HU72S8TkltV+EXoKGR29m/Yss=
|
||||
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 h1:HuE6xSwco/Xed8ajZ+coeYLmioq0Qp1/Z2zczFaV8as=
|
||||
@@ -188,6 +185,7 @@ github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695AP
|
||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY=
|
||||
github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
|
||||
github.com/zeebo/blake3 v0.2.3 h1:TFoLXsjeXqRNFxSbk35Dk4YtszE/MQQGK10BH4ptoTg=
|
||||
@@ -221,6 +219,7 @@ golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvx
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
|
||||
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -232,6 +231,7 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
|
||||
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
||||
@@ -242,6 +242,7 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -253,7 +254,9 @@ golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@@ -277,6 +280,7 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.10.0 h1:tvDr/iQoUqNdohiYm0LmmKcBk+q86lb9EprIUFhHHGg=
|
||||
golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
if [ ! -z $ENV_NEKORAY ]; then
|
||||
export COMMIT_SING_BOX_EXTRA="00286b4baa9dabdce79d40ccd63a90c862a72254"
|
||||
export COMMIT_SING_BOX_EXTRA="df902756f9c50257c48c580e2b5f1b5b190f89bc"
|
||||
export COMMIT_MATSURI_XRAY="f6843e4e1442341e88ac34c09ca2d243cdcc09f6"
|
||||
fi
|
||||
|
||||
|
||||
@@ -129,7 +129,7 @@ namespace NekoGui_sub {
|
||||
if (str.startsWith("hysteria://")) {
|
||||
needFix = false;
|
||||
ent = NekoGui::ProfileManager::NewProxyEntity("hysteria");
|
||||
auto ok = ent->HysteriaBean()->TryParseLink(str);
|
||||
auto ok = ent->QUICBean()->TryParseLink(str);
|
||||
if (!ok) return;
|
||||
}
|
||||
|
||||
@@ -373,28 +373,26 @@ namespace NekoGui_sub {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (type_clash == "hysteria") {
|
||||
auto bean = ent->HysteriaBean();
|
||||
} else if (type == "hysteria") {
|
||||
auto bean = ent->QUICBean();
|
||||
|
||||
bean->hopPort = Node2QString(proxy["ports"]);
|
||||
if (bean->serverPort == 0) bean->hopPort = Node2QString(proxy["port"]);
|
||||
|
||||
bean->allowInsecure = Node2Bool(proxy["skip-cert-verify"]);
|
||||
auto alpn = Node2QStringList(proxy["alpn"]);
|
||||
bean->caText = Node2QString(proxy["ca-str"]);
|
||||
if (!alpn.isEmpty()) bean->alpn = alpn[0];
|
||||
bean->sni = Node2QString(proxy["sni"]);
|
||||
|
||||
bean->name = Node2QString(proxy["name"]);
|
||||
bean->serverAddress = Node2QString(proxy["server"]);
|
||||
bean->serverPort = Node2Int(proxy["port"]);
|
||||
bean->hopPort = Node2QString(proxy["ports"]);
|
||||
if (bean->serverPort == 0) bean->hopPort = Node2QString(proxy["port"]);
|
||||
|
||||
auto auth_str = FIRST_OR_SECOND(Node2QString(proxy["auth_str"]), Node2QString(proxy["auth-str"]));
|
||||
auto auth = Node2QString(proxy["auth"]);
|
||||
if (!auth_str.isEmpty()) {
|
||||
bean->authPayloadType = NekoGui_fmt::HysteriaBean::hysteria_auth_string;
|
||||
bean->authPayloadType = NekoGui_fmt::QUICBean::hysteria_auth_string;
|
||||
bean->authPayload = auth_str;
|
||||
}
|
||||
if (!auth.isEmpty()) {
|
||||
bean->authPayloadType = NekoGui_fmt::HysteriaBean::hysteria_auth_base64;
|
||||
bean->authPayloadType = NekoGui_fmt::QUICBean::hysteria_auth_base64;
|
||||
bean->authPayload = auth;
|
||||
}
|
||||
bean->obfsPassword = Node2QString(proxy["obfs"]);
|
||||
@@ -407,6 +405,30 @@ namespace NekoGui_sub {
|
||||
auto downMbps = Node2QString(proxy["down"]).split(" ")[0].toInt();
|
||||
if (upMbps > 0) bean->uploadMbps = upMbps;
|
||||
if (downMbps > 0) bean->downloadMbps = downMbps;
|
||||
} else if (type == "tuic") {
|
||||
auto bean = ent->QUICBean();
|
||||
|
||||
bean->uuid = Node2QString(proxy["uuid"]);
|
||||
bean->password = Node2QString(proxy["password"]);
|
||||
|
||||
if (Node2Int(proxy["heartbeat-interval"]) != 0) {
|
||||
bean->heartbeat = Int2String(Node2Int(proxy["heartbeat-interval"])) + "ms";
|
||||
}
|
||||
|
||||
bean->udpRelayMode = Node2QString(proxy["udp-relay-mode"]);
|
||||
bean->congestionControl = Node2QString(proxy["congestion-controller"]);
|
||||
|
||||
bean->disableSni = Node2Bool(proxy["disable-sni"]);
|
||||
bean->zeroRttHandshake = Node2Bool(proxy["reduce-rtt"]);
|
||||
bean->allowInsecure = Node2Bool(proxy["skip-cert-verify"]);
|
||||
bean->alpn = Node2QStringList(proxy["alpn"]).join(",");
|
||||
bean->caText = Node2QString(proxy["ca-str"]);
|
||||
bean->sni = Node2QString(proxy["sni"]);
|
||||
|
||||
if (!Node2QString(proxy["ip"]).isEmpty()) {
|
||||
if (bean->sni.isEmpty()) bean->sni = bean->serverAddress;
|
||||
bean->serverAddress = Node2QString(proxy["ip"]);
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -856,7 +856,38 @@ This needs to be run NekoBox with administrator privileges.</source>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditHysteria</name>
|
||||
<name>EditNaive</name>
|
||||
<message>
|
||||
<source>Protocol</source>
|
||||
<translation>پروتکل</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Password</source>
|
||||
<translation>رمزعبور</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Extra headers</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>SNI</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Username</source>
|
||||
<translation>نام کاربری</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Certificate</source>
|
||||
<translation type="unfinished">گواهی</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Insecure concurrency</source>
|
||||
<translation>همزمانی ناامن</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditQUIC</name>
|
||||
<message>
|
||||
<source>Certificate</source>
|
||||
<translation type="unfinished">گواهی</translation>
|
||||
@@ -905,36 +936,33 @@ This needs to be run NekoBox with administrator privileges.</source>
|
||||
<source>Auth Payload</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditNaive</name>
|
||||
<message>
|
||||
<source>Protocol</source>
|
||||
<translation>پروتکل</translation>
|
||||
<source>Disable SNI</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Password</source>
|
||||
<translation>رمزعبور</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Extra headers</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>SNI</source>
|
||||
<source>Generate UUID</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Username</source>
|
||||
<translation>نام کاربری</translation>
|
||||
<source>Heartbeat</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Certificate</source>
|
||||
<translation type="unfinished">گواهی</translation>
|
||||
<source>Zero Rtt Handshake</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Insecure concurrency</source>
|
||||
<translation>همزمانی ناامن</translation>
|
||||
<source>Congestion Control</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>UDP Relay Mode</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
|
||||
@@ -852,7 +852,38 @@ https://matsuridayo.github.io/n-configuration/#vpn-tun</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditHysteria</name>
|
||||
<name>EditNaive</name>
|
||||
<message>
|
||||
<source>Protocol</source>
|
||||
<translation>Протокол</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Password</source>
|
||||
<translation>Пароль</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Extra headers</source>
|
||||
<translation>Дополнительные заголовки</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>SNI</source>
|
||||
<translation>SNI</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Username</source>
|
||||
<translation>Имя пользователя</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Certificate</source>
|
||||
<translation>Сертификат</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Insecure concurrency</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditQUIC</name>
|
||||
<message>
|
||||
<source>Auth Type</source>
|
||||
<translation>Тип авторизации</translation>
|
||||
@@ -901,36 +932,33 @@ https://matsuridayo.github.io/n-configuration/#vpn-tun</translation>
|
||||
<source>Auth Payload</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditNaive</name>
|
||||
<message>
|
||||
<source>Protocol</source>
|
||||
<translation>Протокол</translation>
|
||||
<source>Disable SNI</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Password</source>
|
||||
<translation>Пароль</translation>
|
||||
<translation type="unfinished">Пароль</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Extra headers</source>
|
||||
<translation>Дополнительные заголовки</translation>
|
||||
<source>Generate UUID</source>
|
||||
<translation type="unfinished">Сгенерировать</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>SNI</source>
|
||||
<translation>SNI</translation>
|
||||
<source>Heartbeat</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Username</source>
|
||||
<translation>Имя пользователя</translation>
|
||||
<source>Zero Rtt Handshake</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Certificate</source>
|
||||
<translation>Сертификат</translation>
|
||||
<source>Congestion Control</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Insecure concurrency</source>
|
||||
<translation></translation>
|
||||
<source>UDP Relay Mode</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
|
||||
@@ -856,7 +856,38 @@ This needs to be run NekoBox with administrator privileges.</source>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditHysteria</name>
|
||||
<name>EditNaive</name>
|
||||
<message>
|
||||
<source>Protocol</source>
|
||||
<translation>协议</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Password</source>
|
||||
<translation>密码</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Extra headers</source>
|
||||
<translation>附加标头</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>SNI</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Username</source>
|
||||
<translation>用户名</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Certificate</source>
|
||||
<translation>证书</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Insecure concurrency</source>
|
||||
<translation>不安全并发</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditQUIC</name>
|
||||
<message>
|
||||
<source>Certificate</source>
|
||||
<translation>证书</translation>
|
||||
@@ -905,36 +936,33 @@ This needs to be run NekoBox with administrator privileges.</source>
|
||||
<source>Auth Payload</source>
|
||||
<translation>认证有效载荷</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditNaive</name>
|
||||
<message>
|
||||
<source>Protocol</source>
|
||||
<translation>协议</translation>
|
||||
<source>Generate UUID</source>
|
||||
<translation>生成 UUID</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Password</source>
|
||||
<translation>密码</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Extra headers</source>
|
||||
<translation>附加标头</translation>
|
||||
<source>Zero Rtt Handshake</source>
|
||||
<translation>0-Rtt 握手</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>SNI</source>
|
||||
<translation></translation>
|
||||
<source>UDP Relay Mode</source>
|
||||
<translation>UDP 中继模式</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Username</source>
|
||||
<translation>用户名</translation>
|
||||
<source>Congestion Control</source>
|
||||
<translation>拥塞控制</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Certificate</source>
|
||||
<translation>证书</translation>
|
||||
<source>Heartbeat</source>
|
||||
<translation>心跳包发送间隔</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Insecure concurrency</source>
|
||||
<translation>不安全并发</translation>
|
||||
<source>Disable SNI</source>
|
||||
<translation>不发送服务器名称指示</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
|
||||
@@ -169,6 +169,7 @@ DialogBasicSettings::DialogBasicSettings(QWidget *parent)
|
||||
CACHE.extraCore = QString2QJsonObject(NekoGui::dataStore->extraCore->core_map);
|
||||
if (!CACHE.extraCore.contains("naive")) CACHE.extraCore.insert("naive", "");
|
||||
if (!CACHE.extraCore.contains("hysteria")) CACHE.extraCore.insert("hysteria", "");
|
||||
if (!CACHE.extraCore.contains("tuic")) CACHE.extraCore.insert("tuic", "");
|
||||
//
|
||||
auto extra_core_layout = ui->extra_core_box_scrollAreaWidgetContents->layout();
|
||||
for (const auto &s: CACHE.extraCore.keys()) {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include "ui/edit/edit_vmess.h"
|
||||
#include "ui/edit/edit_trojan_vless.h"
|
||||
#include "ui/edit/edit_naive.h"
|
||||
#include "ui/edit/edit_hysteria.h"
|
||||
#include "ui/edit/edit_quic.h"
|
||||
#include "ui/edit/edit_custom.h"
|
||||
|
||||
#include "fmt/includes.h"
|
||||
@@ -32,7 +32,7 @@ DialogEditProfile::DialogEditProfile(const QString &_type, int profileOrGroupId,
|
||||
connect(ui->network, &QComboBox::currentTextChanged, this, [=](const QString &txt) {
|
||||
ui->network_box->setTitle(network_title_base.arg(txt));
|
||||
// 传输设置
|
||||
if (txt == "tcp" || (!IS_NEKO_BOX && txt == "quic")) {
|
||||
if (txt == "tcp") {
|
||||
ui->header_type->setVisible(true);
|
||||
ui->header_type_l->setVisible(true);
|
||||
ui->path->setVisible(true);
|
||||
@@ -121,6 +121,7 @@ DialogEditProfile::DialogEditProfile(const QString &_type, int profileOrGroupId,
|
||||
LOAD_TYPE("vless")
|
||||
LOAD_TYPE("naive")
|
||||
LOAD_TYPE("hysteria")
|
||||
LOAD_TYPE("tuic")
|
||||
ui->type->addItem(tr("Custom (%1 outbound)").arg(software_core_name), "internal");
|
||||
ui->type->addItem(tr("Custom (%1 config)").arg(software_core_name), "internal-full");
|
||||
ui->type->addItem(tr("Custom (Extra Core)"), "custom");
|
||||
@@ -176,8 +177,8 @@ void DialogEditProfile::typeSelected(const QString &newType) {
|
||||
auto _innerWidget = new EditNaive(this);
|
||||
innerWidget = _innerWidget;
|
||||
innerEditor = _innerWidget;
|
||||
} else if (type == "hysteria") {
|
||||
auto _innerWidget = new EditHysteria(this);
|
||||
} else if (type == "hysteria" || type == "tuic") {
|
||||
auto _innerWidget = new EditQUIC(this);
|
||||
innerWidget = _innerWidget;
|
||||
innerEditor = _innerWidget;
|
||||
} else if (type == "custom" || type == "internal" || type == "internal-full") {
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
#include "edit_hysteria.h"
|
||||
#include "ui_edit_hysteria.h"
|
||||
|
||||
#include "fmt/HysteriaBean.hpp"
|
||||
|
||||
#include <QInputDialog>
|
||||
|
||||
EditHysteria::EditHysteria(QWidget *parent) : QWidget(parent), ui(new Ui::EditHysteria) {
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
EditHysteria::~EditHysteria() {
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void EditHysteria::onStart(std::shared_ptr<NekoGui::ProxyEntity> _ent) {
|
||||
this->ent = _ent;
|
||||
auto bean = this->ent->HysteriaBean();
|
||||
|
||||
P_LOAD_STRING(hopPort);
|
||||
P_LOAD_INT(hopInterval);
|
||||
P_LOAD_INT(uploadMbps);
|
||||
P_LOAD_INT(downloadMbps);
|
||||
P_LOAD_COMBO_INT(protocol);
|
||||
P_LOAD_BOOL(disableMtuDiscovery)
|
||||
P_LOAD_STRING(obfsPassword);
|
||||
P_LOAD_COMBO_INT(authPayloadType);
|
||||
P_LOAD_STRING(authPayload);
|
||||
P_LOAD_STRING(sni);
|
||||
P_LOAD_STRING(alpn);
|
||||
P_LOAD_BOOL(allowInsecure)
|
||||
P_C_LOAD_STRING(caText);
|
||||
P_LOAD_INT(streamReceiveWindow);
|
||||
P_LOAD_INT(connectionReceiveWindow);
|
||||
}
|
||||
|
||||
bool EditHysteria::onEnd() {
|
||||
auto bean = this->ent->HysteriaBean();
|
||||
|
||||
P_SAVE_STRING(hopPort);
|
||||
P_SAVE_INT(hopInterval);
|
||||
P_SAVE_INT(uploadMbps);
|
||||
P_SAVE_INT(downloadMbps);
|
||||
P_SAVE_COMBO_INT(protocol);
|
||||
P_SAVE_BOOL(disableMtuDiscovery)
|
||||
P_SAVE_STRING(obfsPassword);
|
||||
P_SAVE_COMBO_INT(authPayloadType);
|
||||
P_SAVE_STRING(authPayload);
|
||||
P_SAVE_STRING(sni);
|
||||
P_SAVE_STRING(alpn);
|
||||
P_SAVE_BOOL(allowInsecure)
|
||||
P_C_SAVE_STRING(caText);
|
||||
P_SAVE_INT(streamReceiveWindow);
|
||||
P_SAVE_INT(connectionReceiveWindow);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QList<QPair<QPushButton *, QString>> EditHysteria::get_editor_cached() {
|
||||
return {
|
||||
{ui->certificate, CACHE.caText},
|
||||
};
|
||||
}
|
||||
|
||||
void EditHysteria::on_certificate_clicked() {
|
||||
bool ok;
|
||||
auto txt = QInputDialog::getMultiLineText(this, tr("Certificate"), "", CACHE.caText, &ok);
|
||||
if (ok) {
|
||||
CACHE.caText = txt;
|
||||
editor_cache_updated();
|
||||
}
|
||||
}
|
||||
@@ -1,242 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>EditHysteria</class>
|
||||
<widget class="QWidget" name="EditHysteria">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>500</width>
|
||||
<height>600</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">EditHysteria</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>Hop Port</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="MyLineEdit" name="hopPort"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>Hop Interval (s)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="MyLineEdit" name="hopInterval"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Upload (Mbps)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="MyLineEdit" name="uploadMbps"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Download (Mbps)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="MyLineEdit" name="downloadMbps"/>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Protocol</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QComboBox" name="protocol">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">QUIC</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">FakeTCP</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">wechat-video</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="disableMtuDiscovery">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Disable MTU Discovery</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Obfs Password</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="MyLineEdit" name="obfsPassword"/>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Auth Type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QComboBox" name="authPayloadType">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">NONE</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">STRING</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">BASE64</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Auth Payload</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="MyLineEdit" name="authPayload"/>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>SNI</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="MyLineEdit" name="sni"/>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="toolTip">
|
||||
<string notr="true">Only 1 value</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">ALPN</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="MyLineEdit" name="alpn"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="allowInsecure">
|
||||
<property name="text">
|
||||
<string>Allow Insecure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Certificate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<widget class="QPushButton" name="certificate">
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="text">
|
||||
<string notr="true">recv_window</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="1">
|
||||
<widget class="MyLineEdit" name="streamReceiveWindow"/>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string notr="true">recv_window_conn</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="1">
|
||||
<widget class="MyLineEdit" name="connectionReceiveWindow"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>MyLineEdit</class>
|
||||
<extends>QLineEdit</extends>
|
||||
<header>ui/widget/MyLineEdit.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>hopPort</tabstop>
|
||||
<tabstop>hopInterval</tabstop>
|
||||
<tabstop>uploadMbps</tabstop>
|
||||
<tabstop>downloadMbps</tabstop>
|
||||
<tabstop>protocol</tabstop>
|
||||
<tabstop>disableMtuDiscovery</tabstop>
|
||||
<tabstop>obfsPassword</tabstop>
|
||||
<tabstop>authPayloadType</tabstop>
|
||||
<tabstop>authPayload</tabstop>
|
||||
<tabstop>sni</tabstop>
|
||||
<tabstop>alpn</tabstop>
|
||||
<tabstop>allowInsecure</tabstop>
|
||||
<tabstop>certificate</tabstop>
|
||||
<tabstop>streamReceiveWindow</tabstop>
|
||||
<tabstop>connectionReceiveWindow</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
132
ui/edit/edit_quic.cpp
Normal file
132
ui/edit/edit_quic.cpp
Normal file
@@ -0,0 +1,132 @@
|
||||
#include "edit_quic.h"
|
||||
#include "ui_edit_quic.h"
|
||||
|
||||
#include "fmt/QUICBean.hpp"
|
||||
|
||||
#include <QInputDialog>
|
||||
#include <QUuid>
|
||||
|
||||
EditQUIC::EditQUIC(QWidget *parent) : QWidget(parent), ui(new Ui::EditQUIC) {
|
||||
ui->setupUi(this);
|
||||
connect(ui->uuidgen, &QPushButton::clicked, this, [=] { ui->uuid->setText(QUuid::createUuid().toString().remove("{").remove("}")); });
|
||||
}
|
||||
|
||||
EditQUIC::~EditQUIC() {
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void EditQUIC::onStart(std::shared_ptr<NekoGui::ProxyEntity> _ent) {
|
||||
this->ent = _ent;
|
||||
auto bean = this->ent->QUICBean();
|
||||
|
||||
if (bean->proxy_type == NekoGui_fmt::QUICBean::proxy_Hysteria) {
|
||||
P_LOAD_STRING(hopPort);
|
||||
P_LOAD_INT(hopInterval);
|
||||
P_LOAD_INT(uploadMbps);
|
||||
P_LOAD_INT(downloadMbps);
|
||||
P_LOAD_COMBO_INT(hyProtocol);
|
||||
P_LOAD_BOOL(disableMtuDiscovery)
|
||||
P_LOAD_STRING(obfsPassword);
|
||||
P_LOAD_COMBO_INT(authPayloadType);
|
||||
P_LOAD_STRING(authPayload);
|
||||
P_LOAD_INT(streamReceiveWindow);
|
||||
P_LOAD_INT(connectionReceiveWindow);
|
||||
|
||||
ui->uuid->hide();
|
||||
ui->uuid_l->hide();
|
||||
ui->uuidgen->hide();
|
||||
ui->password->hide();
|
||||
ui->password_l->hide();
|
||||
ui->congestionControl->hide();
|
||||
ui->congestionControl_l->hide();
|
||||
ui->udpRelayMode->hide();
|
||||
ui->udpRelayMode_l->hide();
|
||||
ui->zeroRttHandshake->hide();
|
||||
ui->heartbeat->hide();
|
||||
ui->heartbeat_l->hide();
|
||||
} else if (bean->proxy_type == NekoGui_fmt::QUICBean::proxy_TUIC) {
|
||||
P_LOAD_STRING(uuid);
|
||||
P_LOAD_STRING(password);
|
||||
P_LOAD_COMBO_STRING(congestionControl);
|
||||
P_LOAD_COMBO_STRING(udpRelayMode);
|
||||
P_LOAD_BOOL(zeroRttHandshake);
|
||||
P_LOAD_STRING(heartbeat);
|
||||
|
||||
ui->hopPort->hide();
|
||||
ui->hopPort_l->hide();
|
||||
ui->hopInterval->hide();
|
||||
ui->hopInterval_l->hide();
|
||||
ui->uploadMbps->hide();
|
||||
ui->uploadMbps_l->hide();
|
||||
ui->downloadMbps->hide();
|
||||
ui->downloadMbps_l->hide();
|
||||
ui->hyProtocol->hide();
|
||||
ui->hyProtocol_l->hide();
|
||||
ui->disableMtuDiscovery->hide();
|
||||
ui->obfsPassword->hide();
|
||||
ui->obfsPassword_l->hide();
|
||||
ui->authPayload->hide();
|
||||
ui->authPayload_l->hide();
|
||||
ui->authPayloadType->hide();
|
||||
ui->authPayloadType_l->hide();
|
||||
ui->streamReceiveWindow->hide();
|
||||
ui->streamReceiveWindow_l->hide();
|
||||
ui->connectionReceiveWindow->hide();
|
||||
ui->connectionReceiveWindow_l->hide();
|
||||
}
|
||||
|
||||
// TLS
|
||||
P_LOAD_STRING(sni);
|
||||
P_LOAD_STRING(alpn);
|
||||
P_C_LOAD_STRING(caText);
|
||||
P_LOAD_BOOL(allowInsecure);
|
||||
P_LOAD_BOOL(disableSni);
|
||||
}
|
||||
|
||||
bool EditQUIC::onEnd() {
|
||||
auto bean = this->ent->QUICBean();
|
||||
|
||||
// Hysteria
|
||||
P_SAVE_STRING(hopPort);
|
||||
P_SAVE_INT(hopInterval);
|
||||
P_SAVE_INT(uploadMbps);
|
||||
P_SAVE_INT(downloadMbps);
|
||||
P_SAVE_COMBO_INT(hyProtocol);
|
||||
P_SAVE_BOOL(disableMtuDiscovery)
|
||||
P_SAVE_STRING(obfsPassword);
|
||||
P_SAVE_COMBO_INT(authPayloadType);
|
||||
P_SAVE_STRING(authPayload);
|
||||
P_SAVE_INT(streamReceiveWindow);
|
||||
P_SAVE_INT(connectionReceiveWindow);
|
||||
|
||||
// TUIC
|
||||
P_SAVE_STRING(uuid);
|
||||
P_SAVE_STRING(password);
|
||||
P_SAVE_COMBO_STRING(congestionControl);
|
||||
P_SAVE_COMBO_STRING(udpRelayMode);
|
||||
P_SAVE_BOOL(zeroRttHandshake);
|
||||
P_SAVE_STRING(heartbeat);
|
||||
|
||||
// TLS
|
||||
P_SAVE_STRING(sni);
|
||||
P_SAVE_STRING(alpn);
|
||||
P_SAVE_BOOL(allowInsecure);
|
||||
P_C_SAVE_STRING(caText);
|
||||
P_SAVE_BOOL(disableSni);
|
||||
return true;
|
||||
}
|
||||
|
||||
QList<QPair<QPushButton *, QString>> EditQUIC::get_editor_cached() {
|
||||
return {
|
||||
{ui->certificate, CACHE.caText},
|
||||
};
|
||||
}
|
||||
|
||||
void EditQUIC::on_certificate_clicked() {
|
||||
bool ok;
|
||||
auto txt = QInputDialog::getMultiLineText(this, tr("Certificate"), "", CACHE.caText, &ok);
|
||||
if (ok) {
|
||||
CACHE.caText = txt;
|
||||
editor_cache_updated();
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <QGridLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include "profile_editor.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace Ui {
|
||||
class EditHysteria;
|
||||
class EditQUIC;
|
||||
}
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class EditHysteria : public QWidget, public ProfileEditor {
|
||||
class EditQUIC : public QWidget, public ProfileEditor {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit EditHysteria(QWidget *parent = nullptr);
|
||||
explicit EditQUIC(QWidget *parent = nullptr);
|
||||
|
||||
~EditHysteria() override;
|
||||
~EditQUIC() override;
|
||||
|
||||
void onStart(std::shared_ptr<NekoGui::ProxyEntity> _ent) override;
|
||||
|
||||
@@ -24,7 +26,7 @@ public:
|
||||
QList<QPair<QPushButton *, QString>> get_editor_cached() override;
|
||||
|
||||
private:
|
||||
Ui::EditHysteria *ui;
|
||||
Ui::EditQUIC *ui;
|
||||
std::shared_ptr<NekoGui::ProxyEntity> ent;
|
||||
|
||||
struct {
|
||||
436
ui/edit/edit_quic.ui
Normal file
436
ui/edit/edit_quic.ui
Normal file
@@ -0,0 +1,436 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>EditQUIC</class>
|
||||
<widget class="QWidget" name="EditQUIC">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>500</width>
|
||||
<height>600</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">EditHysteria</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="upBox">
|
||||
<item row="1" column="1">
|
||||
<layout class="QHBoxLayout" name="downloadMbpsLay">
|
||||
<item>
|
||||
<widget class="QLabel" name="downloadMbps_l">
|
||||
<property name="text">
|
||||
<string>Download (Mbps)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="MyLineEdit" name="downloadMbps"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<layout class="QHBoxLayout" name="hopPortLay">
|
||||
<item>
|
||||
<widget class="QLabel" name="hopPort_l">
|
||||
<property name="text">
|
||||
<string>Hop Port</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="MyLineEdit" name="hopPort"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<layout class="QHBoxLayout" name="udpRelayModeLay">
|
||||
<item>
|
||||
<widget class="QLabel" name="udpRelayMode_l">
|
||||
<property name="text">
|
||||
<string>UDP Relay Mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="udpRelayMode">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">native</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">quic</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<layout class="QHBoxLayout" name="congestionControlLay">
|
||||
<item>
|
||||
<widget class="QLabel" name="congestionControl_l">
|
||||
<property name="text">
|
||||
<string>Congestion Control</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="congestionControl">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">bbr</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">cubic</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">new_reno</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<layout class="QHBoxLayout" name="uploadMbpsLay">
|
||||
<item>
|
||||
<widget class="QLabel" name="uploadMbps_l">
|
||||
<property name="text">
|
||||
<string>Upload (Mbps)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="MyLineEdit" name="uploadMbps"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QHBoxLayout" name="hopIntervalLay">
|
||||
<item>
|
||||
<widget class="QLabel" name="hopInterval_l">
|
||||
<property name="text">
|
||||
<string>Hop Interval (s)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="MyLineEdit" name="hopInterval"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="zeroRttHandshake">
|
||||
<property name="text">
|
||||
<string>Zero Rtt Handshake</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<layout class="QHBoxLayout" name="heartbeatLay">
|
||||
<item>
|
||||
<widget class="QLabel" name="heartbeat_l">
|
||||
<property name="text">
|
||||
<string>Heartbeat</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="MyLineEdit" name="heartbeat">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="obfuscation">
|
||||
<item row="1" column="1">
|
||||
<widget class="MyLineEdit" name="obfsPassword"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="obfsPassword_l">
|
||||
<property name="text">
|
||||
<string>Obfs Password</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="hyProtocol_l">
|
||||
<property name="text">
|
||||
<string>Protocol</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QComboBox" name="hyProtocol">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">QUIC</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">FakeTCP</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">wechat-video</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="disableMtuDiscovery">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Disable MTU Discovery</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="authentication">
|
||||
<item row="2" column="1">
|
||||
<widget class="MyLineEdit" name="uuid"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="authPayloadType_l">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Auth Type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="authPayload_l">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Auth Payload</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="password_l">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Password</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="uuid_l">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">UUID</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QPushButton" name="uuidgen">
|
||||
<property name="text">
|
||||
<string>Generate UUID</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" colspan="2">
|
||||
<widget class="MyLineEdit" name="password"/>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="2">
|
||||
<widget class="MyLineEdit" name="authPayload"/>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="2">
|
||||
<widget class="QComboBox" name="authPayloadType">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">NONE</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">STRING</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">BASE64</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="TLS" rowstretch="0,0,0">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="certificate_l">
|
||||
<property name="text">
|
||||
<string>Certificate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QPushButton" name="certificate">
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="MyLineEdit" name="alpn"/>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QCheckBox" name="disableSni">
|
||||
<property name="text">
|
||||
<string>Disable SNI</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="MyLineEdit" name="sni"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="alpn_l">
|
||||
<property name="text">
|
||||
<string notr="true">ALPN</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QCheckBox" name="allowInsecure">
|
||||
<property name="text">
|
||||
<string>Allow Insecure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Maximum</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="sni_l">
|
||||
<property name="text">
|
||||
<string>SNI</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="flowControlWindow">
|
||||
<item>
|
||||
<widget class="QLabel" name="streamReceiveWindow_l">
|
||||
<property name="text">
|
||||
<string notr="true">recv_window</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="MyLineEdit" name="streamReceiveWindow"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="connectionReceiveWindow_l">
|
||||
<property name="text">
|
||||
<string notr="true">recv_window_conn</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="MyLineEdit" name="connectionReceiveWindow"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>MyLineEdit</class>
|
||||
<extends>QLineEdit</extends>
|
||||
<header>ui/widget/MyLineEdit.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>hopPort</tabstop>
|
||||
<tabstop>hopInterval</tabstop>
|
||||
<tabstop>uploadMbps</tabstop>
|
||||
<tabstop>downloadMbps</tabstop>
|
||||
<tabstop>congestionControl</tabstop>
|
||||
<tabstop>udpRelayMode</tabstop>
|
||||
<tabstop>heartbeat</tabstop>
|
||||
<tabstop>zeroRttHandshake</tabstop>
|
||||
<tabstop>hyProtocol</tabstop>
|
||||
<tabstop>disableMtuDiscovery</tabstop>
|
||||
<tabstop>obfsPassword</tabstop>
|
||||
<tabstop>authPayloadType</tabstop>
|
||||
<tabstop>authPayload</tabstop>
|
||||
<tabstop>uuid</tabstop>
|
||||
<tabstop>uuidgen</tabstop>
|
||||
<tabstop>password</tabstop>
|
||||
<tabstop>sni</tabstop>
|
||||
<tabstop>disableSni</tabstop>
|
||||
<tabstop>alpn</tabstop>
|
||||
<tabstop>allowInsecure</tabstop>
|
||||
<tabstop>certificate</tabstop>
|
||||
<tabstop>streamReceiveWindow</tabstop>
|
||||
<tabstop>connectionReceiveWindow</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
Reference in New Issue
Block a user