diff --git a/client/cmake/3rdparty.cmake b/client/cmake/3rdparty.cmake index 974d64e6..df24d6c7 100644 --- a/client/cmake/3rdparty.cmake +++ b/client/cmake/3rdparty.cmake @@ -1,7 +1,7 @@ set(CLIENT_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/..) -include(${CLIENT_ROOT_DIR}/3rd/QtSsh/src/ssh/qssh.cmake) -include(${CLIENT_ROOT_DIR}/3rd/QtSsh/src/botan/botan.cmake) +#include(${CLIENT_ROOT_DIR}/3rd/QtSsh/src/ssh/qssh.cmake) +#include(${CLIENT_ROOT_DIR}/3rd/QtSsh/src/botan/botan.cmake) if(NOT IOS AND NOT ANDROID) include(${CLIENT_ROOT_DIR}/3rd/SingleApplication/singleapplication.cmake) diff --git a/client/configurators/ssh_configurator.cpp b/client/configurators/ssh_configurator.cpp index f8dc9869..725f6ead 100644 --- a/client/configurators/ssh_configurator.cpp +++ b/client/configurators/ssh_configurator.cpp @@ -14,9 +14,6 @@ #include "core/server_defs.h" #include "utilities.h" -#include "sftpdefs.h" - -using namespace QSsh; SshConfigurator::SshConfigurator(std::shared_ptr settings, std::shared_ptr serverController, QObject *parent): ConfiguratorBase(settings, serverController, parent) diff --git a/client/configurators/wireguard_configurator.cpp b/client/configurators/wireguard_configurator.cpp index 78f44afd..6dd2ab49 100644 --- a/client/configurators/wireguard_configurator.cpp +++ b/client/configurators/wireguard_configurator.cpp @@ -144,7 +144,7 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon arg(connData.clientIP); e = m_serverController->uploadTextFileToContainer(container, credentials, configPart, - protocols::wireguard::serverConfigPath, QSsh::SftpOverwriteMode::SftpAppendToExisting); + protocols::wireguard::serverConfigPath, libssh::SftpOverwriteMode::SftpAppendToExisting); if (e) { if (errorCode) *errorCode = e; diff --git a/client/core/servercontroller.cpp b/client/core/servercontroller.cpp index 6c77e2d2..b9ee2e76 100644 --- a/client/core/servercontroller.cpp +++ b/client/core/servercontroller.cpp @@ -22,6 +22,7 @@ #include #include "containers/containers_defs.h" +#include "debug.h" #include "server_defs.h" #include "settings.h" #include "scripts_registry.h" @@ -43,7 +44,7 @@ ErrorCode ServerController::runScript(const ServerCredentials &credentials, QStr const std::function &cbReadStdOut, const std::function &cbReadStdErr) { - std::shared_ptr session = m_sshClient.getSession(); + std::shared_ptr session = m_sshClient.getSession(); if (!session) { return ErrorCode::SshInternalError; } @@ -117,7 +118,7 @@ ErrorCode ServerController::runContainerScript(const ServerCredentials &credenti ErrorCode ServerController::uploadTextFileToContainer(DockerContainer container, const ServerCredentials &credentials, const QString &file, const QString &path, - QSsh::SftpOverwriteMode overwriteMode) + libssh::SftpOverwriteMode overwriteMode) { ErrorCode e = ErrorCode::NoError; QString tmpFileName = QString("/tmp/%1.tmp").arg(Utils::getRandomString(16)); @@ -141,14 +142,14 @@ ErrorCode ServerController::uploadTextFileToContainer(DockerContainer container, if (e) return e; - if (overwriteMode == QSsh::SftpOverwriteMode::SftpOverwriteExisting) { + if (overwriteMode == libssh::SftpOverwriteMode::SftpOverwriteExisting) { e = runScript(credentials, replaceVars(QString("sudo docker cp %1 $CONTAINER_NAME:/%2").arg(tmpFileName).arg(path), genVarsForScript(credentials, container)), cbReadStd, cbReadStd); if (e) return e; } - else if (overwriteMode == QSsh::SftpOverwriteMode::SftpAppendToExisting) { + else if (overwriteMode == libssh::SftpOverwriteMode::SftpAppendToExisting) { e = runScript(credentials, replaceVars(QString("sudo docker cp %1 $CONTAINER_NAME:/%2").arg(tmpFileName).arg(tmpFileName), genVarsForScript(credentials, container)), cbReadStd, cbReadStd); @@ -231,9 +232,9 @@ ErrorCode ServerController::checkOpenVpnServer(DockerContainer container, const } ErrorCode ServerController::uploadFileToHost(const ServerCredentials &credentials, const QByteArray &data, const QString &remotePath, - QSsh::SftpOverwriteMode overwriteMode) + libssh::SftpOverwriteMode overwriteMode) { - std::shared_ptr session = m_sshClient.getSession(); + std::shared_ptr session = m_sshClient.getSession(); if (!session) { return ErrorCode::SshInternalError; } @@ -249,7 +250,7 @@ ErrorCode ServerController::uploadFileToHost(const ServerCredentials &credential qDebug() << "remotePath" << remotePath; - error = session->sftpFileCopy(localFile.fileName().toStdString(), remotePath.toStdString(), "non_desc"); + error = session->sftpFileCopy(overwriteMode, localFile.fileName().toStdString(), remotePath.toStdString(), "non_desc"); if (error != ErrorCode::NoError) { return error; } diff --git a/client/core/servercontroller.h b/client/core/servercontroller.h index 256e1a43..2892a928 100644 --- a/client/core/servercontroller.h +++ b/client/core/servercontroller.h @@ -4,12 +4,9 @@ #include #include -#include "debug.h" #include "defs.h" - #include "containers/containers_defs.h" -#include "sftpdefs.h" #include "sshclient.h" class Settings; @@ -48,11 +45,11 @@ public: ErrorCode checkOpenVpnServer(DockerContainer container, const ServerCredentials &credentials); ErrorCode uploadFileToHost(const ServerCredentials &credentials, const QByteArray &data, - const QString &remotePath, QSsh::SftpOverwriteMode overwriteMode = QSsh::SftpOverwriteMode::SftpOverwriteExisting); + const QString &remotePath, libssh::SftpOverwriteMode overwriteMode = libssh::SftpOverwriteMode::SftpOverwriteExisting); ErrorCode uploadTextFileToContainer(DockerContainer container, const ServerCredentials &credentials, const QString &file, const QString &path, - QSsh::SftpOverwriteMode overwriteMode = QSsh::SftpOverwriteMode::SftpOverwriteExisting); + libssh::SftpOverwriteMode overwriteMode = libssh::SftpOverwriteMode::SftpOverwriteExisting); QByteArray getTextFileFromContainer(DockerContainer container, const ServerCredentials &credentials, const QString &path, ErrorCode *errorCode = nullptr); @@ -84,7 +81,7 @@ private: std::shared_ptr m_settings; std::shared_ptr m_configurator; - SshClient m_sshClient; + libssh::Client m_sshClient; }; #endif // SERVERCONTROLLER_H diff --git a/client/core/sshclient.cpp b/client/core/sshclient.cpp index 11ef2348..c746eb29 100644 --- a/client/core/sshclient.cpp +++ b/client/core/sshclient.cpp @@ -1,19 +1,18 @@ #include "sshclient.h" -#include -#include +namespace libssh { + Client::Client(QObject *parent) : QObject(parent) + { + ssh_init(); + } -SshClient::SshClient(QObject *parent) : QObject(parent) -{ - ssh_init(); -} + Client::~Client() + { + ssh_finalize(); + } -SshClient::~SshClient() -{ - ssh_finalize(); -} - -std::shared_ptr SshClient::getSession() -{ - return std::make_shared(); + std::shared_ptr Client::getSession() + { + return std::make_shared(); + } } diff --git a/client/core/sshclient.h b/client/core/sshclient.h index c58a776a..548f4312 100644 --- a/client/core/sshclient.h +++ b/client/core/sshclient.h @@ -7,14 +7,16 @@ using namespace amnezia; -class SshClient : public QObject -{ - Q_OBJECT -public: - SshClient(QObject *parent = nullptr); - ~SshClient(); +namespace libssh { + class Client : public QObject + { + Q_OBJECT + public: + Client(QObject *parent = nullptr); + ~Client(); - std::shared_ptr getSession(); -}; + std::shared_ptr getSession(); + }; +} #endif // SSHCLIENT_H diff --git a/client/core/sshsession.cpp b/client/core/sshsession.cpp index 0bd7c501..85f11a55 100644 --- a/client/core/sshsession.cpp +++ b/client/core/sshsession.cpp @@ -4,295 +4,299 @@ #include #include -#include -SshSession::SshSession(QObject *parent) : QObject(parent) -{ +#ifdef Q_OS_WINDOWS +#define S_IRWXU 0 +#endif -} +namespace libssh { + Session::Session(QObject *parent) : QObject(parent) + { -SshSession::~SshSession() -{ - if (m_isNeedSendChannelEof) { - ssh_channel_send_eof(m_channel); - } - if (m_isChannelOpened) { - ssh_channel_free(m_channel); - } - if (m_isSftpInitialized) { - sftp_free(m_sftpSession); - } - if (m_isSessionConnected) { - ssh_disconnect(m_session); - } - ssh_free(m_session); -} - -ErrorCode SshSession::connectToHost(const ServerCredentials &credentials) -{ - if (m_session == NULL) { - return ErrorCode::InternalError; } - int port = credentials.port; - int logVerbosity = SSH_LOG_NOLOG; - std::string hostIp = credentials.hostName.toStdString(); - std::string hostUsername = credentials.userName.toStdString() + "@" + hostIp; - - ssh_options_set(m_session, SSH_OPTIONS_HOST, hostIp.c_str()); - ssh_options_set(m_session, SSH_OPTIONS_PORT, &port); - ssh_options_set(m_session, SSH_OPTIONS_USER, hostUsername.c_str()); - ssh_options_set(m_session, SSH_OPTIONS_LOG_VERBOSITY, &logVerbosity); - - int connectionResult = ssh_connect(m_session); - - if (connectionResult != SSH_OK) { - qDebug() << ssh_get_error(m_session); - return ErrorCode::SshTimeoutError; + Session::~Session() + { + if (m_isNeedSendChannelEof) { + ssh_channel_send_eof(m_channel); + } + if (m_isChannelOpened) { + ssh_channel_free(m_channel); + } + if (m_isSftpInitialized) { + sftp_free(m_sftpSession); + } + if (m_isSessionConnected) { + ssh_disconnect(m_session); + } + ssh_free(m_session); } - m_isSessionConnected = true; + ErrorCode Session::connectToHost(const ServerCredentials &credentials) + { + if (m_session == NULL) { + return ErrorCode::InternalError; + } - std::string authUsername = credentials.userName.toStdString(); + int port = credentials.port; + int logVerbosity = SSH_LOG_NOLOG; + std::string hostIp = credentials.hostName.toStdString(); + std::string hostUsername = credentials.userName.toStdString() + "@" + hostIp; - int authResult = SSH_ERROR; - if (credentials.password.contains("BEGIN") && credentials.password.contains("PRIVATE KEY")) { - ssh_key privateKey; - ssh_pki_import_privkey_base64(credentials.password.toStdString().c_str(), nullptr, nullptr, nullptr, &privateKey); - authResult = ssh_userauth_publickey(m_session, authUsername.c_str(), privateKey); - } - else { - authResult = ssh_userauth_password(m_session, authUsername.c_str(), credentials.password.toStdString().c_str()); + ssh_options_set(m_session, SSH_OPTIONS_HOST, hostIp.c_str()); + ssh_options_set(m_session, SSH_OPTIONS_PORT, &port); + ssh_options_set(m_session, SSH_OPTIONS_USER, hostUsername.c_str()); + ssh_options_set(m_session, SSH_OPTIONS_LOG_VERBOSITY, &logVerbosity); + + int connectionResult = ssh_connect(m_session); + + if (connectionResult != SSH_OK) { + qDebug() << ssh_get_error(m_session); + return ErrorCode::SshTimeoutError; + } + + m_isSessionConnected = true; + + std::string authUsername = credentials.userName.toStdString(); + + int authResult = SSH_ERROR; + if (credentials.password.contains("BEGIN") && credentials.password.contains("PRIVATE KEY")) { + ssh_key privateKey; + ssh_pki_import_privkey_base64(credentials.password.toStdString().c_str(), nullptr, nullptr, nullptr, &privateKey); + authResult = ssh_userauth_publickey(m_session, authUsername.c_str(), privateKey); + } + else { + authResult = ssh_userauth_password(m_session, authUsername.c_str(), credentials.password.toStdString().c_str()); + } + + if (authResult != SSH_OK) { + qDebug() << ssh_get_error(m_session); + return ErrorCode::SshAuthenticationError; + } + + return ErrorCode::NoError; } - if (authResult != SSH_OK) { - qDebug() << ssh_get_error(m_session); - return ErrorCode::SshAuthenticationError; - } + ErrorCode Session::initChannel(const ServerCredentials &credentials) + { + m_session = ssh_new(); - return ErrorCode::NoError; -} + ErrorCode error = connectToHost(credentials); + if (error) { + return error; + } + m_channel = ssh_channel_new(m_session); -ErrorCode SshSession::initChannel(const ServerCredentials &credentials) -{ - m_session = ssh_new(); + if (m_channel == NULL) { + qDebug() << ssh_get_error(m_session); + return ErrorCode::SshAuthenticationError; + } - ErrorCode error = connectToHost(credentials); - if (error) { - return error; - } - m_channel = ssh_channel_new(m_session); + int result = ssh_channel_open_session(m_channel); - if (m_channel == NULL) { - qDebug() << ssh_get_error(m_session); - return ErrorCode::SshAuthenticationError; - } - - int result = ssh_channel_open_session(m_channel); - - if (result == SSH_OK && ssh_channel_is_open(m_channel)) { - qDebug() << "SSH chanel opened"; - m_isChannelOpened = true; - } else { - qDebug() << ssh_get_error(m_session); - return ErrorCode::SshAuthenticationError; - } - - result = ssh_channel_request_pty(m_channel); - if (result != SSH_OK) { - qDebug() << ssh_get_error(m_session); - return ErrorCode::SshInternalError; - } - - result = ssh_channel_change_pty_size(m_channel, 80, 1024); - if (result != SSH_OK) { - qDebug() << ssh_get_error(m_session); - return ErrorCode::SshInternalError; - } - - result = ssh_channel_request_shell(m_channel); - if (result != SSH_OK) { - qDebug() << ssh_get_error(m_session); - return ErrorCode::SshInternalError; - } - - return ErrorCode::NoError; -} - -ErrorCode SshSession::writeToChannel(const QString &data, - const std::function &cbReadStdOut, - const std::function &cbReadStdErr) -{ - if (m_channel == NULL) { - qDebug() << "ssh channel not initialized"; - return ErrorCode::SshAuthenticationError; - } - - QFutureWatcher watcher; - connect(&watcher, &QFutureWatcher::finished, this, &SshSession::writeToChannelFinished); - - QFuture future = QtConcurrent::run([this, &data, &cbReadStdOut, &cbReadStdErr]() { - const size_t bufferSize = 2048; - - int bytesRead = 0; - char buffer[bufferSize]; - - int bytesWritten = ssh_channel_write(m_channel, data.toUtf8(), (uint32_t)data.size()); - ssh_channel_write(m_channel, "\n", 1); - if (bytesWritten == data.size()) { - auto readOutput = [&](bool isStdErr) { - std::string output; - if (ssh_channel_is_open(m_channel) && !ssh_channel_is_eof(m_channel)) { - bytesRead = ssh_channel_read_timeout(m_channel, buffer, sizeof(buffer), isStdErr, 50); - while (bytesRead > 0) - { - output = std::string(buffer, bytesRead); - if (!output.empty()) { - qDebug().noquote() << (isStdErr ? "stdErr" : "stdOut") << QString(output.c_str()); - - if (cbReadStdOut && !isStdErr){ - cbReadStdOut(output.c_str()); - } - if (cbReadStdErr && isStdErr){ - cbReadStdErr(output.c_str()); - } - } - bytesRead = ssh_channel_read_timeout(m_channel, buffer, sizeof(buffer), isStdErr, 500); - } - } - return output; - }; - - readOutput(false); - readOutput(true); + if (result == SSH_OK && ssh_channel_is_open(m_channel)) { + qDebug() << "SSH chanel opened"; + m_isChannelOpened = true; } else { + qDebug() << ssh_get_error(m_session); + return ErrorCode::SshAuthenticationError; + } + + result = ssh_channel_request_pty(m_channel); + if (result != SSH_OK) { qDebug() << ssh_get_error(m_session); return ErrorCode::SshInternalError; } - m_isNeedSendChannelEof = true; + + result = ssh_channel_change_pty_size(m_channel, 80, 1024); + if (result != SSH_OK) { + qDebug() << ssh_get_error(m_session); + return ErrorCode::SshInternalError; + } + + result = ssh_channel_request_shell(m_channel); + if (result != SSH_OK) { + qDebug() << ssh_get_error(m_session); + return ErrorCode::SshInternalError; + } + return ErrorCode::NoError; - }); - watcher.setFuture(future); - - QEventLoop wait; - - QObject::connect(this, &SshSession::writeToChannelFinished, &wait, &QEventLoop::quit); - wait.exec(); - - return watcher.result(); -} - -ErrorCode SshSession::initSftp(const ServerCredentials &credentials) -{ - m_session = ssh_new(); - - ErrorCode error = connectToHost(credentials); - if (error) { - return error; } - m_sftpSession = sftp_new(m_session); + ErrorCode Session::writeToChannel(const QString &data, + const std::function &cbReadStdOut, + const std::function &cbReadStdErr) + { + if (m_channel == NULL) { + qDebug() << "ssh channel not initialized"; + return ErrorCode::SshAuthenticationError; + } - if (m_sftpSession == NULL) { - qDebug() << ssh_get_error(m_session); - return ErrorCode::SshSftpError; + QFutureWatcher watcher; + connect(&watcher, &QFutureWatcher::finished, this, &Session::writeToChannelFinished); + + QFuture future = QtConcurrent::run([this, &data, &cbReadStdOut, &cbReadStdErr]() { + const size_t bufferSize = 2048; + + int bytesRead = 0; + char buffer[bufferSize]; + + int bytesWritten = ssh_channel_write(m_channel, data.toUtf8(), (uint32_t)data.size()); + ssh_channel_write(m_channel, "\n", 1); + if (bytesWritten == data.size()) { + auto readOutput = [&](bool isStdErr) { + std::string output; + if (ssh_channel_is_open(m_channel) && !ssh_channel_is_eof(m_channel)) { + bytesRead = ssh_channel_read_timeout(m_channel, buffer, sizeof(buffer), isStdErr, 50); + while (bytesRead > 0) + { + output = std::string(buffer, bytesRead); + if (!output.empty()) { + qDebug().noquote() << (isStdErr ? "stdErr" : "stdOut") << QString(output.c_str()); + + if (cbReadStdOut && !isStdErr){ + cbReadStdOut(output.c_str()); + } + if (cbReadStdErr && isStdErr){ + cbReadStdErr(output.c_str()); + } + } + bytesRead = ssh_channel_read_timeout(m_channel, buffer, sizeof(buffer), isStdErr, 5000); + } + } + return output; + }; + + readOutput(false); + readOutput(true); + } else { + qDebug() << ssh_get_error(m_session); + return ErrorCode::SshInternalError; + } + m_isNeedSendChannelEof = true; + return ErrorCode::NoError; + }); + watcher.setFuture(future); + + QEventLoop wait; + + QObject::connect(this, &Session::writeToChannelFinished, &wait, &QEventLoop::quit); + wait.exec(); + + return watcher.result(); } - int result = sftp_init(m_sftpSession); + ErrorCode Session::initSftp(const ServerCredentials &credentials) + { + m_session = ssh_new(); - if (result != SSH_OK) { - qDebug() << ssh_get_error(m_session); - return ErrorCode::SshSftpError; - } + ErrorCode error = connectToHost(credentials); + if (error) { + return error; + } - return ErrorCode::NoError; -} + m_sftpSession = sftp_new(m_session); -ErrorCode SshSession::sftpFileCopy(const std::string& localPath, const std::string& remotePath, const std::string& fileDesc) -{ - if (m_sftpSession == NULL) { - qDebug() << "ssh sftp session not initialized"; - return ErrorCode::SshSftpError; - } - - QFutureWatcher watcher; - connect(&watcher, &QFutureWatcher::finished, this, &SshSession::sftpFileCopyFinished); - - QFuture future = QtConcurrent::run([this, &localPath, &remotePath, &fileDesc]() { - int accessType = O_WRONLY | O_CREAT | O_TRUNC; - sftp_file file; - const size_t bufferSize = 16384; - char buffer[bufferSize]; - - file = sftp_open(m_sftpSession, remotePath.c_str(), accessType, 0);//S_IRWXU); - - if (file == NULL) { + if (m_sftpSession == NULL) { qDebug() << ssh_get_error(m_session); return ErrorCode::SshSftpError; } - int localFileSize = std::filesystem::file_size(localPath); - int chunksCount = localFileSize / (bufferSize); + int result = sftp_init(m_sftpSession); - std::ifstream fin(localPath, std::ios::binary | std::ios::in); - - if (fin.is_open()) { - for (int currentChunkId = 0; currentChunkId < chunksCount; currentChunkId++) { - fin.read(buffer, bufferSize); - - int bytesWritten = sftp_write(file, buffer, bufferSize); - - std::string chunk(buffer, bufferSize); - qDebug() << "write -> " << QString(chunk.c_str()); - - if (bytesWritten != bufferSize) { - fin.close(); - sftp_close(file); - qDebug() << ssh_get_error(m_session); - return ErrorCode::SshSftpError; - } - } - - int lastChunkSize = localFileSize % (bufferSize); - - if (lastChunkSize != 0) { - fin.read(buffer, lastChunkSize); - - std::string chunk(buffer, lastChunkSize); - qDebug() << "write -> " << QString(chunk.c_str()); - - int bytesWritten = sftp_write(file, buffer, lastChunkSize); - - if (bytesWritten != lastChunkSize) { - fin.close(); - sftp_close(file); - qDebug() << ssh_get_error(m_session); - return ErrorCode::SshSftpError; - } - } - - } else { - sftp_close(file); - qDebug() << ssh_get_error(m_session); - return ErrorCode::SshSftpError; - } - - fin.close(); - - int result = sftp_close(file); if (result != SSH_OK) { qDebug() << ssh_get_error(m_session); return ErrorCode::SshSftpError; } return ErrorCode::NoError; - }); - watcher.setFuture(future); + } - QEventLoop wait; + ErrorCode Session::sftpFileCopy(const SftpOverwriteMode overwriteMode, const std::string& localPath, const std::string& remotePath, const std::string& fileDesc) + { + if (m_sftpSession == NULL) { + qDebug() << "ssh sftp session not initialized"; + return ErrorCode::SshSftpError; + } - QObject::connect(this, &SshSession::sftpFileCopyFinished, &wait, &QEventLoop::quit); - wait.exec(); + QFutureWatcher watcher; + connect(&watcher, &QFutureWatcher::finished, this, &Session::sftpFileCopyFinished); - return watcher.result(); + QFuture future = QtConcurrent::run([this, overwriteMode, &localPath, &remotePath, &fileDesc]() { + int accessType = O_WRONLY | O_CREAT | overwriteMode; + sftp_file file; + const size_t bufferSize = 16384; + char buffer[bufferSize]; + + file = sftp_open(m_sftpSession, remotePath.c_str(), accessType, S_IRWXU); + + if (file == NULL) { + qDebug() << ssh_get_error(m_session); + return ErrorCode::SshSftpError; + } + + int localFileSize = std::filesystem::file_size(localPath); + int chunksCount = localFileSize / (bufferSize); + + std::ifstream fin(localPath, std::ios::binary | std::ios::in); + + if (fin.is_open()) { + for (int currentChunkId = 0; currentChunkId < chunksCount; currentChunkId++) { + fin.read(buffer, bufferSize); + + int bytesWritten = sftp_write(file, buffer, bufferSize); + + std::string chunk(buffer, bufferSize); + qDebug() << "sftp write: " << QString(chunk.c_str()); + + if (bytesWritten != bufferSize) { + fin.close(); + sftp_close(file); + qDebug() << ssh_get_error(m_session); + return ErrorCode::SshSftpError; + } + } + + int lastChunkSize = localFileSize % (bufferSize); + + if (lastChunkSize != 0) { + fin.read(buffer, lastChunkSize); + + std::string chunk(buffer, lastChunkSize); + qDebug() << "sftp write: " << QString(chunk.c_str()); + + int bytesWritten = sftp_write(file, buffer, lastChunkSize); + + if (bytesWritten != lastChunkSize) { + fin.close(); + sftp_close(file); + qDebug() << ssh_get_error(m_session); + return ErrorCode::SshSftpError; + } + } + } else { + sftp_close(file); + qDebug() << ssh_get_error(m_session); + return ErrorCode::SshSftpError; + } + + fin.close(); + + int result = sftp_close(file); + if (result != SSH_OK) { + qDebug() << ssh_get_error(m_session); + return ErrorCode::SshSftpError; + } + + return ErrorCode::NoError; + }); + watcher.setFuture(future); + + QEventLoop wait; + + QObject::connect(this, &Session::sftpFileCopyFinished, &wait, &QEventLoop::quit); + wait.exec(); + + return watcher.result(); + } } diff --git a/client/core/sshsession.h b/client/core/sshsession.h index 6d86ed83..8c89dba4 100644 --- a/client/core/sshsession.h +++ b/client/core/sshsession.h @@ -3,6 +3,8 @@ #include +#include + #include #include @@ -10,33 +12,42 @@ using namespace amnezia; -class SshSession : public QObject -{ - Q_OBJECT -public: - SshSession(QObject *parent = nullptr); - ~SshSession(); +namespace libssh { + enum SftpOverwriteMode { + /*! Overwrite any existing files */ + SftpOverwriteExisting = O_TRUNC, + /*! Append new content if the file already exists */ + SftpAppendToExisting = O_APPEND + }; - ErrorCode initChannel(const ServerCredentials &credentials); - ErrorCode initSftp(const ServerCredentials &credentials); - ErrorCode writeToChannel(const QString &data, - const std::function &cbReadStdOut, - const std::function &cbReadStdErr); - ErrorCode sftpFileCopy(const std::string& localPath, const std::string& remotePath, const std::string& fileDesc); -private: - ErrorCode connectToHost(const ServerCredentials &credentials); + class Session : public QObject + { + Q_OBJECT + public: + Session(QObject *parent = nullptr); + ~Session(); - ssh_session m_session; - ssh_channel m_channel; - sftp_session m_sftpSession; + ErrorCode initChannel(const ServerCredentials &credentials); + ErrorCode initSftp(const ServerCredentials &credentials); + ErrorCode writeToChannel(const QString &data, + const std::function &cbReadStdOut, + const std::function &cbReadStdErr); + ErrorCode sftpFileCopy(const SftpOverwriteMode overwriteMode, const std::string& localPath, const std::string& remotePath, const std::string& fileDesc); + private: + ErrorCode connectToHost(const ServerCredentials &credentials); - bool m_isChannelOpened = false; - bool m_isSessionConnected = false; - bool m_isNeedSendChannelEof = false; - bool m_isSftpInitialized = false; -signals: - void writeToChannelFinished(); - void sftpFileCopyFinished(); -}; + ssh_session m_session; + ssh_channel m_channel; + sftp_session m_sftpSession; + + bool m_isChannelOpened = false; + bool m_isSessionConnected = false; + bool m_isNeedSendChannelEof = false; + bool m_isSftpInitialized = false; + signals: + void writeToChannelFinished(); + void sftpFileCopyFinished(); + }; +} #endif // SSHSESSION_H diff --git a/client/managementserver.cpp b/client/managementserver.cpp index c8e3b967..ba860941 100644 --- a/client/managementserver.cpp +++ b/client/managementserver.cpp @@ -49,9 +49,9 @@ void ManagementServer::onNewConnection() m_socket = QPointer(m_tcpServer->nextPendingConnection()); if (m_tcpServer) m_tcpServer->close(); - QObject::connect(m_socket.data(), SIGNAL(disconnected()), this, SLOT(onSocketDisconnected())); - QObject::connect(m_socket.data(), SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onSocketError(QAbstractSocket::SocketError))); - QObject::connect(m_socket.data(), SIGNAL(readyRead()), this, SLOT(onReadyRead())); + QObject::connect(m_socket.data(), &QTcpSocket::disconnected, this, &ManagementServer::onSocketDisconnected); + QObject::connect(m_socket.data(), &QTcpSocket::errorOccurred, this, &ManagementServer::onSocketError); + QObject::connect(m_socket.data(), &QTcpSocket::readyRead, this, &ManagementServer::onReadyRead); } void ManagementServer::onSocketError(QAbstractSocket::SocketError socketError)