Merge branch 'feature/new-gui' of github.com:amnezia-vpn/amnezia-client into feature/new-gui

This commit is contained in:
vladimir.kuznetsov 2023-06-16 13:49:19 +09:00
commit 4224e8314b
10 changed files with 54 additions and 34 deletions

View file

@ -36,7 +36,7 @@ enum ErrorCode
// Ssh connection errors // Ssh connection errors
SshRequsetDeniedError, SshInterruptedError, SshInternalError, SshRequsetDeniedError, SshInterruptedError, SshInternalError,
SshPrivateKeyError, SshPrivateKeyFormatError, SshPrivateKeyError, SshPrivateKeyFormatError, SshTimeoutError,
// Ssh sftp errors // Ssh sftp errors
SshSftpEofError, SshSftpNoSuchFileError, SshSftpPermissionDeniedError, SshSftpEofError, SshSftpNoSuchFileError, SshSftpPermissionDeniedError,

View file

@ -24,6 +24,7 @@ QString errorString(ErrorCode code){
case(SshInternalError): return QObject::tr("Ssh internal error"); case(SshInternalError): return QObject::tr("Ssh internal error");
case(SshPrivateKeyError): return QObject::tr("Invalid private key or invalid passphrase entered"); case(SshPrivateKeyError): return QObject::tr("Invalid private key or invalid passphrase entered");
case(SshPrivateKeyFormatError): return QObject::tr("The selected private key format is not supported, use openssh ED25519 key types or PEM key types"); case(SshPrivateKeyFormatError): return QObject::tr("The selected private key format is not supported, use openssh ED25519 key types or PEM key types");
case(SshTimeoutError): return QObject::tr("Timeout connecting to server");
// Libssh sftp errors // Libssh sftp errors
case(SshSftpEofError): return QObject::tr("Sftp error: End-of-file encountered"); case(SshSftpEofError): return QObject::tr("Sftp error: End-of-file encountered");

View file

@ -10,6 +10,8 @@ const uint32_t S_IRWXU = 0644;
#endif #endif
namespace libssh { namespace libssh {
const QString libsshTimeoutError = "Timeout connecting to";
std::function<QString()> Client::m_passphraseCallback; std::function<QString()> Client::m_passphraseCallback;
Client::Client(QObject *parent) : QObject(parent) Client::Client(QObject *parent) : QObject(parent)
@ -45,11 +47,20 @@ namespace libssh {
ssh_options_set(m_session, SSH_OPTIONS_USER, hostUsername.c_str()); ssh_options_set(m_session, SSH_OPTIONS_USER, hostUsername.c_str());
ssh_options_set(m_session, SSH_OPTIONS_LOG_VERBOSITY, &logVerbosity); ssh_options_set(m_session, SSH_OPTIONS_LOG_VERBOSITY, &logVerbosity);
int connectionResult = ssh_connect(m_session); QFutureWatcher<int> watcher;
QFuture<int> future = QtConcurrent::run([this]() {
return ssh_connect(m_session);
});
QEventLoop wait;
connect(&watcher, &QFutureWatcher<ErrorCode>::finished, &wait, &QEventLoop::quit);
watcher.setFuture(future);
wait.exec();
int connectionResult = watcher.result();
if (connectionResult != SSH_OK) { if (connectionResult != SSH_OK) {
qDebug() << ssh_get_error(m_session); return fromLibsshErrorCode();
return fromLibsshErrorCode(ssh_get_error_code(m_session));
} }
std::string authUsername = credentials.userName.toStdString(); std::string authUsername = credentials.userName.toStdString();
@ -78,8 +89,8 @@ namespace libssh {
ssh_key_free(privateKey); ssh_key_free(privateKey);
} }
if (authResult != SSH_OK) { if (authResult != SSH_OK) {
qDebug() << ssh_get_error(m_session); qCritical() << ssh_get_error(m_session);
ErrorCode errorCode = fromLibsshErrorCode(ssh_get_error_code(m_session)); ErrorCode errorCode = fromLibsshErrorCode();
if (errorCode == ErrorCode::NoError) { if (errorCode == ErrorCode::NoError) {
errorCode = ErrorCode::SshPrivateKeyFormatError; errorCode = ErrorCode::SshPrivateKeyFormatError;
} }
@ -88,8 +99,7 @@ namespace libssh {
} else { } else {
authResult = ssh_userauth_password(m_session, authUsername.c_str(), credentials.secretData.toStdString().c_str()); authResult = ssh_userauth_password(m_session, authUsername.c_str(), credentials.secretData.toStdString().c_str());
if (authResult != SSH_OK) { if (authResult != SSH_OK) {
qDebug() << ssh_get_error(m_session); return fromLibsshErrorCode();
return fromLibsshErrorCode(ssh_get_error_code(m_session));
} }
} }
} }
@ -188,16 +198,15 @@ namespace libssh {
ErrorCode Client::writeResponse(const QString &data) ErrorCode Client::writeResponse(const QString &data)
{ {
if (m_channel == nullptr) { if (m_channel == nullptr) {
qDebug() << "ssh channel not initialized"; qCritical() << "ssh channel not initialized";
return fromLibsshErrorCode(ssh_get_error_code(m_session)); return fromLibsshErrorCode();
} }
int bytesWritten = ssh_channel_write(m_channel, data.toUtf8(), (uint32_t)data.size()); int bytesWritten = ssh_channel_write(m_channel, data.toUtf8(), (uint32_t)data.size());
if (bytesWritten == data.size() && ssh_channel_write(m_channel, "\n", 1)) { if (bytesWritten == data.size() && ssh_channel_write(m_channel, "\n", 1)) {
return fromLibsshErrorCode(ssh_get_error_code(m_session)); return fromLibsshErrorCode();
} }
qDebug() << ssh_get_error(m_session); return fromLibsshErrorCode();
return fromLibsshErrorCode(ssh_get_error_code(m_session));
} }
ErrorCode Client::closeChannel() ErrorCode Client::closeChannel()
@ -212,8 +221,7 @@ namespace libssh {
ssh_channel_free(m_channel); ssh_channel_free(m_channel);
m_channel = nullptr; m_channel = nullptr;
} }
qDebug() << ssh_get_error(m_session); return fromLibsshErrorCode();
return fromLibsshErrorCode(ssh_get_error_code(m_session));
} }
ErrorCode Client::sftpFileCopy(const SftpOverwriteMode overwriteMode, const std::string& localPath, const std::string& remotePath, const std::string& fileDesc) ErrorCode Client::sftpFileCopy(const SftpOverwriteMode overwriteMode, const std::string& localPath, const std::string& remotePath, const std::string& fileDesc)
@ -312,12 +320,21 @@ namespace libssh {
sftp_free(m_sftpSession); sftp_free(m_sftpSession);
m_sftpSession = nullptr; m_sftpSession = nullptr;
} }
qDebug() << ssh_get_error(m_session); qCritical() << ssh_get_error(m_session);
return errorCode; return errorCode;
} }
ErrorCode Client::fromLibsshErrorCode(int errorCode) ErrorCode Client::fromLibsshErrorCode()
{ {
int errorCode = ssh_get_error_code(m_session);
if (errorCode != SSH_NO_ERROR) {
QString errorMessage = ssh_get_error(m_session);
qCritical() << errorMessage;
if (errorMessage.contains(libsshTimeoutError)) {
return ErrorCode::SshTimeoutError;
}
}
switch (errorCode) { switch (errorCode) {
case(SSH_NO_ERROR): return ErrorCode::NoError; case(SSH_NO_ERROR): return ErrorCode::NoError;
case(SSH_REQUEST_DENIED): return ErrorCode::SshRequsetDeniedError; case(SSH_REQUEST_DENIED): return ErrorCode::SshRequsetDeniedError;

View file

@ -40,7 +40,7 @@ namespace libssh {
private: private:
ErrorCode closeChannel(); ErrorCode closeChannel();
ErrorCode closeSftpSession(); ErrorCode closeSftpSession();
ErrorCode fromLibsshErrorCode(int errorCode); ErrorCode fromLibsshErrorCode();
ErrorCode fromLibsshSftpErrorCode(int errorCode); ErrorCode fromLibsshSftpErrorCode(int errorCode);
static int callback(const char *prompt, char *buf, size_t len, int echo, int verify, void *userdata); static int callback(const char *prompt, char *buf, size_t len, int echo, int verify, void *userdata);

View file

@ -19,13 +19,14 @@ public:
QObject *parent = nullptr); QObject *parent = nullptr);
bool isConnected(); bool isConnected();
void setIsConnected(bool isConnected); void setIsConnected(bool isConnected); //todo take state from vpnconnection?
public slots: public slots:
void openConnection(); void openConnection();
void closeConnection(); void closeConnection();
QString getLastConnectionError(); QString getLastConnectionError();
Vpn::ConnectionState connectionState(){return {};}; //todo update ConnectButton text on page change
signals: signals:
void connectToVpn(int serverIndex, const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig); void connectToVpn(int serverIndex, const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig);

View file

@ -24,10 +24,10 @@ Button {
radius: 16 radius: 16
color: { color: {
if (root.enabled) { if (root.enabled) {
if(root.pressed) { if (root.pressed) {
return pressedColor return pressedColor
} }
return hovered ? hoveredColor : defaultColor return root.hovered ? hoveredColor : defaultColor
} else { } else {
return disabledColor return disabledColor
} }

View file

@ -27,15 +27,17 @@ Popup {
background: Rectangle { background: Rectangle {
anchors.fill: parent anchors.fill: parent
color: Qt.rgba(215/255, 216/255, 219/255, 0.95) color: "white"//Qt.rgba(215/255, 216/255, 219/255, 0.95)
radius: 4 radius: 4
} }
contentItem: RowLayout { contentItem: RowLayout {
width: parent.width anchors.fill: parent
anchors.leftMargin: 16
anchors.rightMargin: 16
CaptionTextType { CaptionTextType {
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignLeft
Layout.fillWidth: true Layout.fillWidth: true
text: root.popupErrorMessageText text: root.popupErrorMessageText
@ -44,7 +46,7 @@ Popup {
BasicButtonType { BasicButtonType {
visible: closeButtonVisible visible: closeButtonVisible
defaultColor: Qt.rgba(215/255, 216/255, 219/255, 0.95) defaultColor: "white"//"transparent"//Qt.rgba(215/255, 216/255, 219/255, 0.95)
hoveredColor: "#C1C2C5" hoveredColor: "#C1C2C5"
pressedColor: "#AEB0B7" pressedColor: "#AEB0B7"
disabledColor: "#494B50" disabledColor: "#494B50"
@ -52,7 +54,7 @@ Popup {
textColor: "#0E0E11" textColor: "#0E0E11"
borderWidth: 0 borderWidth: 0
text: "Close" text: qsTr("Close")
onClicked: { onClicked: {
root.close() root.close()
} }

View file

@ -74,6 +74,7 @@ PageType {
PageController.replaceStartPage() PageController.replaceStartPage()
} else { } else {
goToStartPage() goToStartPage()
goToPage(PageEnum.PageSettingsServersList)
} }
} }
questionDrawer.noButtonFunction = function() { questionDrawer.noButtonFunction = function() {

View file

@ -16,6 +16,9 @@ Window {
minimumWidth: GC.isDesktop() ? 360 : 0 minimumWidth: GC.isDesktop() ? 360 : 0
minimumHeight: GC.isDesktop() ? 640 : 0 minimumHeight: GC.isDesktop() ? 640 : 0
color: "#0E0E11"
// todo
onClosing: function() { onClosing: function() {
console.debug("QML onClosing signal") console.debug("QML onClosing signal")
UiLogic.onCloseWindow() UiLogic.onCloseWindow()
@ -23,11 +26,6 @@ Window {
title: "AmneziaVPN" title: "AmneziaVPN"
Rectangle {
anchors.fill: parent
color: "#0E0E11"
}
StackViewType { StackViewType {
id: rootStackView id: rootStackView

View file

@ -336,7 +336,7 @@ void VpnConnection::connectToVpn(int serverIndex,
ErrorCode e = ErrorCode::NoError; ErrorCode e = ErrorCode::NoError;
m_vpnConfiguration = createVpnConfiguration(serverIndex, credentials, container, containerConfig); m_vpnConfiguration = createVpnConfiguration(serverIndex, credentials, container, containerConfig, &e);
if (e) { if (e) {
emit connectionStateChanged(Vpn::ConnectionState::Error); emit connectionStateChanged(Vpn::ConnectionState::Error);
return; return;
@ -345,7 +345,7 @@ void VpnConnection::connectToVpn(int serverIndex,
#if !defined (Q_OS_ANDROID) && !defined (Q_OS_IOS) #if !defined (Q_OS_ANDROID) && !defined (Q_OS_IOS)
m_vpnProtocol.reset(VpnProtocol::factory(container, m_vpnConfiguration)); m_vpnProtocol.reset(VpnProtocol::factory(container, m_vpnConfiguration));
if (!m_vpnProtocol) { if (!m_vpnProtocol) {
emit Vpn::ConnectionState::Error; emit connectionStateChanged(Vpn::ConnectionState::Error);
return; return;
} }
m_vpnProtocol->prepare(); m_vpnProtocol->prepare();
@ -371,7 +371,7 @@ void VpnConnection::connectToVpn(int serverIndex,
createProtocolConnections(); createProtocolConnections();
e = m_vpnProtocol.data()->start(); e = m_vpnProtocol.data()->start();
if (e) emit Vpn::ConnectionState::Error; if (e) emit connectionStateChanged(Vpn::ConnectionState::Error);
} }
void VpnConnection::createProtocolConnections() { void VpnConnection::createProtocolConnections() {