added settings page for v2ray

This commit is contained in:
vladimir.kuznetsov 2023-02-13 18:17:42 +03:00
parent 68830021d6
commit 2b0ba2aff9
9 changed files with 176 additions and 38 deletions

View file

@ -21,20 +21,24 @@ QString V2RayConfigurator::genV2RayConfig(const ServerCredentials &credentials,
{
ErrorCode e = ErrorCode::NoError;
QString v2rayVmessClientUuid = m_serverController->getTextFileFromContainer(container, credentials,
QString v2RayVmessClientUuid = m_serverController->getTextFileFromContainer(container, credentials,
amnezia::protocols::v2ray::v2rayKeyPath, &e);
v2rayVmessClientUuid.replace("\n", "");
if (v2RayVmessClientUuid.isEmpty()) {
e = ErrorCode::V2RayKeyMissing;
return "";
}
v2RayVmessClientUuid.replace("\n", "");
if (e) {
if (errorCode) *errorCode = e;
return "";
}
QString v2RayClientConfig = m_serverController->replaceVars(amnezia::scriptData(ProtocolScriptType::v2ray_client_template, container),
m_serverController->genVarsForScript(credentials, container, containerConfig));
v2RayClientConfig.replace("$V2RAY_VMESS_CLIENT_UUID", v2rayVmessClientUuid);
v2RayClientConfig.replace("$V2RAY_VMESS_CLIENT_UUID", v2RayVmessClientUuid);
v2RayClientConfig = m_serverController->replaceVars(v2RayClientConfig,
m_serverController->genVarsForScript(credentials, container, containerConfig));

View file

@ -67,7 +67,9 @@ enum ErrorCode
OpenSslFailed,
OpenVpnExecutableCrashed,
ShadowSocksExecutableCrashed,
CloakExecutableCrashed
CloakExecutableCrashed,
V2RayExecutableCrashed,
V2RayKeyMissing
};
} // namespace amnezia

View file

@ -42,9 +42,12 @@ QString errorString(ErrorCode code){
case (ShadowSocksExecutableMissing): return QObject::tr("ShadowSocks (ss-local) executable missing");
case (CloakExecutableMissing): return QObject::tr("Cloak (ck-client) executable missing");
case (AmneziaServiceConnectionFailed): return QObject::tr("Amnezia helper service error");
case (V2RayExecutableMissing): return QObject::tr("V2Ray (v2ray) executable missing");
case (OpenSslFailed): return QObject::tr("OpenSSL failed");
// V2Ray errors
case (V2RayExecutableMissing): return QObject::tr("V2Ray (v2ray) executable missing");
case (V2RayKeyMissing): return QObject::tr("V2Ray key missing");
// VPN errors
case (OpenVpnAdaptersInUseError): return QObject::tr("Can't connect: another VPN connection is active");
case (OpenVpnTapAdapterError): return QObject::tr("Can't setup OpenVPN TAP network adapter");

View file

@ -32,7 +32,7 @@ ErrorCode V2RayProtocol::start()
QStringList args = QStringList() << "-c" << m_v2RayConfigFile.fileName();
qDebug().noquote() << "ShadowSocksVpnProtocol::start()"
qDebug().noquote() << "V2RayProtocol::start()"
<< v2RayExecPath() << args.join(" ");
m_v2RayProcess.setProcessChannelMode(QProcess::MergedChannels);
@ -41,14 +41,14 @@ ErrorCode V2RayProtocol::start()
m_v2RayProcess.setArguments(args);
connect(&m_v2RayProcess, &QProcess::readyReadStandardOutput, this, [this](){
qDebug().noquote() << "v2ray:" << m_v2RayProcess.readAllStandardOutput();
qDebug().noquote() << "V2Ray:" << m_v2RayProcess.readAllStandardOutput();
});
connect(&m_v2RayProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [this](int exitCode, QProcess::ExitStatus exitStatus) {
qDebug().noquote() << "V2RayProtocol finished, exitCode, exiStatus" << exitCode << exitStatus;
setConnectionState(VpnProtocol::Disconnected);
if (exitStatus != QProcess::NormalExit){
emit protocolError(amnezia::ErrorCode::ShadowSocksExecutableCrashed); //todo
emit protocolError(amnezia::ErrorCode::V2RayExecutableCrashed);
stop();
}
if (exitCode != 0 ) {
@ -64,8 +64,7 @@ ErrorCode V2RayProtocol::start()
setConnectionState(VpnConnectionState::Connecting);
return OpenVpnProtocol::start();
}
else return ErrorCode::ShadowSocksExecutableMissing;
} else return ErrorCode::V2RayExecutableMissing;
#else
return ErrorCode::NotImplementedError;
#endif

View file

@ -19,7 +19,6 @@ dhcp-option DNS $PRIMARY_DNS
dhcp-option DNS $SECONDARY_DNS
block-outside-dns
# TODO test next 3 lines for (feature/v2ray-container)
socks-proxy 127.0.0.1 $V2RAY_SOCKS_LOCAL_PORT
route $REMOTE_HOST 255.255.255.255 net_gateway
remote 127.0.0.1 $OPENVPN_PORT

View file

@ -104,13 +104,14 @@ void ShadowSocksLogic::onPushButtonSaveClicked()
progressBarFunc.setTextVisibleFunc(true);
progressBarFunc.setTextFunc(QString("Configuring..."));
ErrorCode e = uiLogic()->pageLogic<ServerConfiguringProgressLogic>()->doInstallAction([this, containerConfig, &newContainerConfig](){
auto installAction = [this, containerConfig, &newContainerConfig](){
return m_serverController->updateContainer(m_settings->serverCredentials(uiLogic()->selectedServerIndex),
uiLogic()->selectedDockerContainer,
containerConfig,
newContainerConfig);
},
pageFunc, progressBarFunc,
};
ErrorCode e = uiLogic()->pageLogic<ServerConfiguringProgressLogic>()->doInstallAction(installAction, pageFunc, progressBarFunc,
saveButtonFunc, waitInfoFunc,
busyInfoFuncy, cancelButtonFunc);

View file

@ -11,7 +11,6 @@ using namespace PageEnumNS;
V2RayLogic::V2RayLogic(UiLogic *logic, QObject *parent):
PageProtocolLogicBase(logic, parent),
m_comboBoxCipherText{"chacha20-poly1305"},
m_lineEditPortText{},
m_pushButtonSaveVisible{false},
m_progressBarResetVisible{false},
@ -24,36 +23,31 @@ V2RayLogic::V2RayLogic(UiLogic *logic, QObject *parent):
}
void V2RayLogic::updateProtocolPage(const QJsonObject &ssConfig, DockerContainer container, bool haveAuthData)
void V2RayLogic::updateProtocolPage(const QJsonObject &v2RayConfig, DockerContainer container, bool haveAuthData)
{
set_pageEnabled(haveAuthData);
set_pushButtonSaveVisible(haveAuthData);
set_progressBarResetVisible(haveAuthData);
set_comboBoxCipherText(ssConfig.value(config_key::cipher).
toString(protocols::shadowsocks::defaultCipher));
set_lineEditPortText(v2RayConfig.value(config_key::port).
toString(protocols::v2ray::defaultServerPort));
set_lineEditPortText(ssConfig.value(config_key::port).
toString(protocols::shadowsocks::defaultPort));
set_lineEditPortEnabled(container == DockerContainer::ShadowSocks);
set_lineEditPortEnabled(container == DockerContainer::V2Ray);
}
QJsonObject V2RayLogic::getProtocolConfigFromPage(QJsonObject oldConfig)
{
oldConfig.insert(config_key::cipher, comboBoxCipherText());
oldConfig.insert(config_key::port, lineEditPortText());
return oldConfig;
}
void V2RayLogic::onPushButtonSaveClicked()
{
QJsonObject protocolConfig = m_settings->protocolConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, Proto::ShadowSocks);
QJsonObject protocolConfig = m_settings->protocolConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, Proto::V2Ray);
QJsonObject containerConfig = m_settings->containerConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer);
QJsonObject newContainerConfig = containerConfig;
newContainerConfig.insert(ProtocolProps::protoToString(Proto::ShadowSocks), protocolConfig);
newContainerConfig.insert(ProtocolProps::protoToString(Proto::V2Ray), protocolConfig);
ServerConfiguringProgressLogic::PageFunc pageFunc;
pageFunc.setEnabledFunc = [this] (bool enabled) -> void {
set_pageEnabled(enabled);
@ -104,13 +98,15 @@ void V2RayLogic::onPushButtonSaveClicked()
progressBarFunc.setTextVisibleFunc(true);
progressBarFunc.setTextFunc(QString("Configuring..."));
ErrorCode e = uiLogic()->pageLogic<ServerConfiguringProgressLogic>()->doInstallAction([this, containerConfig, &newContainerConfig](){
auto installAction = [this, containerConfig, &newContainerConfig]() {
return m_serverController->updateContainer(m_settings->serverCredentials(uiLogic()->selectedServerIndex),
uiLogic()->selectedDockerContainer,
containerConfig,
newContainerConfig);
},
pageFunc, progressBarFunc,
};
ErrorCode e = uiLogic()->pageLogic<ServerConfiguringProgressLogic>()->doInstallAction(installAction, pageFunc, progressBarFunc,
saveButtonFunc, waitInfoFunc,
busyInfoFuncy, cancelButtonFunc);

View file

@ -9,21 +9,22 @@ class V2RayLogic : public PageProtocolLogicBase
{
Q_OBJECT
AUTO_PROPERTY(QString, comboBoxCipherText)
AUTO_PROPERTY(QString, lineEditPortText)
AUTO_PROPERTY(bool, pushButtonSaveVisible)
AUTO_PROPERTY(bool, progressBarResetVisible)
AUTO_PROPERTY(bool, lineEditPortEnabled)
AUTO_PROPERTY(QString, lineEditPortText)
AUTO_PROPERTY(bool, labelInfoVisible)
AUTO_PROPERTY(QString, labelInfoText)
AUTO_PROPERTY(int, progressBarResetValue)
AUTO_PROPERTY(int, progressBarResetMaximium)
AUTO_PROPERTY(bool, progressBarResetVisible)
AUTO_PROPERTY(bool, progressBarTextVisible)
AUTO_PROPERTY(QString, progressBarText)
AUTO_PROPERTY(bool, labelServerBusyVisible)
AUTO_PROPERTY(QString, labelServerBusyText)
AUTO_PROPERTY(bool, pushButtonSaveVisible)
AUTO_PROPERTY(bool, pushButtonCancelVisible)
public:
@ -34,7 +35,7 @@ public:
explicit V2RayLogic(UiLogic *uiLogic, QObject *parent = nullptr);
~V2RayLogic() = default;
void updateProtocolPage(const QJsonObject &ssConfig, DockerContainer container, bool haveAuthData) override;
void updateProtocolPage(const QJsonObject &v2rayConfig, DockerContainer container, bool haveAuthData) override;
QJsonObject getProtocolConfigFromPage(QJsonObject oldConfig) override;
private:

View file

@ -1,5 +1,138 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import ProtocolEnum 1.0
import "../"
import "../../Controls"
import "../../Config"
Item {
PageProtocolBase {
id: root
protocol: ProtocolEnum.V2Ray
logic: UiLogic.protocolLogic(protocol)
BackButton {
id: back
enabled: !logic.pushButtonCancelVisible
}
Caption {
id: caption
text: qsTr("V2Ray Settings")
}
ColumnLayout {
id: content
enabled: logic.pageEnabled
anchors.top: caption.bottom
anchors.left: root.left
anchors.right: root.right
anchors.bottom: pb_save.top
anchors.margins: 20
anchors.topMargin: 10
RowLayout {
Layout.fillWidth: true
LabelType {
Layout.preferredWidth: 0.3 * root.width - 10
height: 31
text: qsTr("Port")
}
TextFieldType {
Layout.fillWidth: true
height: 31
text: logic.lineEditPortText
onEditingFinished: {
logic.lineEditPortText = text
}
enabled: logic.lineEditPortEnabled
}
}
Item {
Layout.fillHeight: true
}
LabelType {
horizontalAlignment: Text.AlignHCenter
Layout.maximumWidth: parent.width
Layout.fillWidth: true
visible: logic.labelServerBusyVisible
text: logic.labelServerBusyText
}
LabelType {
horizontalAlignment: Text.AlignHCenter
Layout.maximumWidth: parent.width
Layout.fillWidth: true
visible: logic.labelInfoVisible
text: logic.labelInfoText
}
}
ProgressBar {
id: progressBar_reset
anchors.fill: pb_save
from: 0
to: logic.progressBarResetMaximium
value: logic.progressBarResetValue
visible: logic.progressBarResetVisible
background: Rectangle {
implicitWidth: parent.width
implicitHeight: parent.height
color: "#100A44"
radius: 4
}
contentItem: Item {
implicitWidth: parent.width
implicitHeight: parent.height
Rectangle {
width: progressBar_reset.visualPosition * parent.width
height: parent.height
radius: 4
color: Qt.rgba(255, 255, 255, 0.15);
}
}
LabelType {
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
text: logic.progressBarText
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
font.family: "Lato"
font.styleName: "normal"
font.pixelSize: 16
color: "#D4D4D4"
visible: logic.progressBarTextVisible
}
}
BlueButtonType {
id: pb_save
enabled: logic.pageEnabled
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: root.bottom
anchors.bottomMargin: 20
width: root.width - 60
height: 40
text: qsTr("Save and restart VPN")
visible: logic.pushButtonSaveVisible
onClicked: {
logic.onPushButtonSaveClicked()
}
}
BlueButtonType {
anchors.fill: pb_save
text: qsTr("Cancel")
visible: logic.pushButtonCancelVisible
enabled: logic.pushButtonCancelVisible
onClicked: {
logic.onPushButtonCancelClicked()
}
}
}