Added error handling
Added write to channel in callbacks
This commit is contained in:
parent
f9b2829396
commit
3277717a7f
8 changed files with 125 additions and 122 deletions
|
@ -64,7 +64,7 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::prepareOpenVpnConfig(co
|
||||||
connData.taKey = m_serverController->getTextFileFromContainer(container, credentials, amnezia::protocols::openvpn::taKeyPath, &e);
|
connData.taKey = m_serverController->getTextFileFromContainer(container, credentials, amnezia::protocols::openvpn::taKeyPath, &e);
|
||||||
|
|
||||||
if (connData.caCert.isEmpty() || connData.clientCert.isEmpty() || connData.taKey.isEmpty()) {
|
if (connData.caCert.isEmpty() || connData.clientCert.isEmpty() || connData.taKey.isEmpty()) {
|
||||||
if (errorCode) *errorCode = ErrorCode::RemoteProcessCrashError;
|
if (errorCode) *errorCode = ErrorCode::SshSftpFailureError;
|
||||||
}
|
}
|
||||||
|
|
||||||
return connData;
|
return connData;
|
||||||
|
|
|
@ -76,7 +76,7 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon
|
||||||
{
|
{
|
||||||
QString script = QString("cat %1 | grep AllowedIPs").arg(amnezia::protocols::wireguard::serverConfigPath);
|
QString script = QString("cat %1 | grep AllowedIPs").arg(amnezia::protocols::wireguard::serverConfigPath);
|
||||||
QString stdOut;
|
QString stdOut;
|
||||||
auto cbReadStdOut = [&](const QString &data) {
|
auto cbReadStdOut = [&](const QString &data, libssh::Session &) {
|
||||||
stdOut += data + "\n";
|
stdOut += data + "\n";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -33,14 +33,14 @@ enum ErrorCode
|
||||||
ServerDockerFailedError,
|
ServerDockerFailedError,
|
||||||
|
|
||||||
// Ssh connection errors
|
// Ssh connection errors
|
||||||
SshSocketError, SshTimeoutError, SshProtocolError,
|
SshRequsetDeniedError, SshInterruptedError, SshInternalError,
|
||||||
SshHostKeyError, SshKeyFileError, SshAuthenticationError,
|
|
||||||
SshClosedByServerError, SshInternalError,
|
|
||||||
|
|
||||||
// Ssh remote process errors
|
// Ssh sftp errors
|
||||||
SshRemoteProcessCreationError,
|
SshSftpEofError, SshSftpNoSuchFileError, SshSftpPermissionDeniedError,
|
||||||
FailedToStartRemoteProcessError, RemoteProcessCrashError,
|
SshSftpFailureError, SshSftpBadMessageError, SshSftpNoConnectionError,
|
||||||
SshSftpError,
|
SshSftpConnectionLostError, SshSftpOpUnsupportedError, SshSftpInvalidHandleError,
|
||||||
|
SshSftpNoSuchPathError, SshSftpFileAlreadyExistsError, SshSftpWriteProtectError,
|
||||||
|
SshSftpNoMediaError,
|
||||||
|
|
||||||
// Local errors
|
// Local errors
|
||||||
FailedToSaveConfigData,
|
FailedToSaveConfigData,
|
||||||
|
|
|
@ -16,20 +16,25 @@ QString errorString(ErrorCode code){
|
||||||
case(ServerContainerMissingError): return QObject::tr("Server error: Docker container missing");
|
case(ServerContainerMissingError): return QObject::tr("Server error: Docker container missing");
|
||||||
case(ServerDockerFailedError): return QObject::tr("Server error: Docker failed");
|
case(ServerDockerFailedError): return QObject::tr("Server error: Docker failed");
|
||||||
|
|
||||||
// Ssh connection errors
|
// Libssh errors
|
||||||
case(SshSocketError): return QObject::tr("Ssh connection error");
|
case(SshRequsetDeniedError): return QObject::tr("Ssh request was denied");
|
||||||
case(SshTimeoutError): return QObject::tr("Ssh connection timeout");
|
case(SshInterruptedError): return QObject::tr("Ssh request was interrupted");
|
||||||
case(SshProtocolError): return QObject::tr("Ssh protocol error");
|
|
||||||
case(SshHostKeyError): return QObject::tr("Ssh server ket check failed");
|
|
||||||
case(SshKeyFileError): return QObject::tr("Ssh key file error");
|
|
||||||
case(SshAuthenticationError): return QObject::tr("Ssh authentication error");
|
|
||||||
case(SshClosedByServerError): return QObject::tr("Ssh session closed");
|
|
||||||
case(SshInternalError): return QObject::tr("Ssh internal error");
|
case(SshInternalError): return QObject::tr("Ssh internal error");
|
||||||
|
|
||||||
// Ssh remote process errors
|
// Libssh sftp errors
|
||||||
case(SshRemoteProcessCreationError): return QObject::tr("Failed to create remote process on server");
|
case(SshSftpEofError): return QObject::tr("Sftp error: End-of-file encountered");
|
||||||
case(FailedToStartRemoteProcessError): return QObject::tr("Failed to start remote process on server");
|
case(SshSftpNoSuchFileError): return QObject::tr("Sftp error: File does not exist");
|
||||||
case(RemoteProcessCrashError): return QObject::tr("Remote process on server crashed");
|
case(SshSftpPermissionDeniedError): return QObject::tr("Sftp error: Permission denied");
|
||||||
|
case(SshSftpFailureError): return QObject::tr("Sftp error: Generic failure");
|
||||||
|
case(SshSftpBadMessageError): return QObject::tr("Sftp error: Garbage received from server");
|
||||||
|
case(SshSftpNoConnectionError): return QObject::tr("Sftp error: No connection has been set up");
|
||||||
|
case(SshSftpConnectionLostError): return QObject::tr("Sftp error: There was a connection, but we lost it");
|
||||||
|
case(SshSftpOpUnsupportedError): return QObject::tr("Sftp error: Operation not supported by libssh yet");
|
||||||
|
case(SshSftpInvalidHandleError): return QObject::tr("Sftp error: Invalid file handle");
|
||||||
|
case(SshSftpNoSuchPathError): return QObject::tr("Sftp error: No such file or directory path exists");
|
||||||
|
case(SshSftpFileAlreadyExistsError): return QObject::tr("Sftp error: An attempt to create an already existing file or directory has been made");
|
||||||
|
case(SshSftpWriteProtectError): return QObject::tr("Sftp error: Write-protected filesystem");
|
||||||
|
case(SshSftpNoMediaError): return QObject::tr("Sftp error: No media was in remote drive");
|
||||||
|
|
||||||
// Local errors
|
// Local errors
|
||||||
case (FailedToSaveConfigData): return QObject::tr("Failed to save config to disk");
|
case (FailedToSaveConfigData): return QObject::tr("Failed to save config to disk");
|
||||||
|
|
|
@ -41,8 +41,8 @@ ServerController::~ServerController()
|
||||||
|
|
||||||
|
|
||||||
ErrorCode ServerController::runScript(const ServerCredentials &credentials, QString script,
|
ErrorCode ServerController::runScript(const ServerCredentials &credentials, QString script,
|
||||||
const std::function<void(const QString &)> &cbReadStdOut,
|
const std::function<void(const QString &, libssh::Session &)> &cbReadStdOut,
|
||||||
const std::function<void(const QString &)> &cbReadStdErr) {
|
const std::function<void(const QString &, libssh::Session &)> &cbReadStdErr) {
|
||||||
|
|
||||||
std::shared_ptr<libssh::Session> session = m_sshClient.getSession();
|
std::shared_ptr<libssh::Session> session = m_sshClient.getSession();
|
||||||
if (!session) {
|
if (!session) {
|
||||||
|
@ -96,8 +96,8 @@ ErrorCode ServerController::runScript(const ServerCredentials &credentials, QStr
|
||||||
|
|
||||||
ErrorCode ServerController::runContainerScript(const ServerCredentials &credentials,
|
ErrorCode ServerController::runContainerScript(const ServerCredentials &credentials,
|
||||||
DockerContainer container, QString script,
|
DockerContainer container, QString script,
|
||||||
const std::function<void (const QString &)> &cbReadStdOut,
|
const std::function<void (const QString &, libssh::Session &)> &cbReadStdOut,
|
||||||
const std::function<void (const QString &)> &cbReadStdErr)
|
const std::function<void (const QString &, libssh::Session &)> &cbReadStdErr)
|
||||||
{
|
{
|
||||||
QString fileName = "/opt/amnezia/" + Utils::getRandomString(16) + ".sh";
|
QString fileName = "/opt/amnezia/" + Utils::getRandomString(16) + ".sh";
|
||||||
Debug::appendSshLog("Run container script for " + ContainerProps::containerToString(container) + QStringLiteral(":\n") + script);
|
Debug::appendSshLog("Run container script for " + ContainerProps::containerToString(container) + QStringLiteral(":\n") + script);
|
||||||
|
@ -129,7 +129,7 @@ ErrorCode ServerController::uploadTextFileToContainer(DockerContainer container,
|
||||||
if (e) return e;
|
if (e) return e;
|
||||||
|
|
||||||
QString stdOut;
|
QString stdOut;
|
||||||
auto cbReadStd = [&](const QString &data) {
|
auto cbReadStd = [&](const QString &data, libssh::Session &) {
|
||||||
stdOut += data + "\n";
|
stdOut += data + "\n";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -191,7 +191,7 @@ QByteArray ServerController::getTextFileFromContainer(DockerContainer container,
|
||||||
|
|
||||||
|
|
||||||
QString stdOut;
|
QString stdOut;
|
||||||
auto cbReadStdOut = [&](const QString &data) {
|
auto cbReadStdOut = [&](const QString &data, libssh::Session &) {
|
||||||
stdOut += data;
|
stdOut += data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -257,54 +257,6 @@ ErrorCode ServerController::uploadFileToHost(const ServerCredentials &credential
|
||||||
return ErrorCode::NoError;
|
return ErrorCode::NoError;
|
||||||
}
|
}
|
||||||
|
|
||||||
//ErrorCode ServerController::fromSshConnectionErrorCode(SshError error)
|
|
||||||
//{
|
|
||||||
// switch (error) {
|
|
||||||
// case(SshNoError): return ErrorCode::NoError;
|
|
||||||
// case(QSsh::SshSocketError): return ErrorCode::SshSocketError;
|
|
||||||
// case(QSsh::SshTimeoutError): return ErrorCode::SshTimeoutError;
|
|
||||||
// case(QSsh::SshProtocolError): return ErrorCode::SshProtocolError;
|
|
||||||
// case(QSsh::SshHostKeyError): return ErrorCode::SshHostKeyError;
|
|
||||||
// case(QSsh::SshKeyFileError): return ErrorCode::SshKeyFileError;
|
|
||||||
// case(QSsh::SshAuthenticationError): return ErrorCode::SshAuthenticationError;
|
|
||||||
// case(QSsh::SshClosedByServerError): return ErrorCode::SshClosedByServerError;
|
|
||||||
// case(QSsh::SshInternalError): return ErrorCode::SshInternalError;
|
|
||||||
// default: return ErrorCode::SshInternalError;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//ErrorCode ServerController::fromSshProcessExitStatus(int exitStatus)
|
|
||||||
//{
|
|
||||||
// qDebug() << exitStatus;
|
|
||||||
// switch (SshRemoteProcess::ExitStatus(exitStatus)) {
|
|
||||||
// case(SshRemoteProcess::ExitStatus::NormalExit): return ErrorCode::NoError;
|
|
||||||
// case(SshRemoteProcess::ExitStatus::FailedToStart): return ErrorCode::FailedToStartRemoteProcessError;
|
|
||||||
// case(SshRemoteProcess::ExitStatus::CrashExit): return ErrorCode::RemoteProcessCrashError;
|
|
||||||
// default: return ErrorCode::SshInternalError;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//SshConnectionParameters ServerController::sshParams(const ServerCredentials &credentials)
|
|
||||||
//{
|
|
||||||
// QSsh::SshConnectionParameters sshParams;
|
|
||||||
// if (credentials.password.contains("BEGIN") && credentials.password.contains("PRIVATE KEY")) {
|
|
||||||
// sshParams.authenticationType = QSsh::SshConnectionParameters::AuthenticationTypePublicKey;
|
|
||||||
// sshParams.privateKeyFile = credentials.password;
|
|
||||||
// }
|
|
||||||
// else {
|
|
||||||
// sshParams.authenticationType = QSsh::SshConnectionParameters::AuthenticationTypePassword;
|
|
||||||
// sshParams.setPassword(credentials.password);
|
|
||||||
// }
|
|
||||||
// sshParams.setHost(credentials.hostName);
|
|
||||||
// sshParams.setUserName(credentials.userName);
|
|
||||||
// sshParams.timeout = 10;
|
|
||||||
// sshParams.setPort(credentials.port);
|
|
||||||
// sshParams.hostKeyCheckingMode = QSsh::SshHostKeyCheckingMode::SshHostKeyCheckingNone;
|
|
||||||
// sshParams.options = SshIgnoreDefaultProxy;
|
|
||||||
|
|
||||||
// return sshParams;
|
|
||||||
//}
|
|
||||||
|
|
||||||
ErrorCode ServerController::removeAllContainers(const ServerCredentials &credentials)
|
ErrorCode ServerController::removeAllContainers(const ServerCredentials &credentials)
|
||||||
{
|
{
|
||||||
return runScript(credentials,
|
return runScript(credentials,
|
||||||
|
@ -429,14 +381,14 @@ bool ServerController::isReinstallContainerRequred(DockerContainer container, co
|
||||||
ErrorCode ServerController::installDockerWorker(const ServerCredentials &credentials, DockerContainer container)
|
ErrorCode ServerController::installDockerWorker(const ServerCredentials &credentials, DockerContainer container)
|
||||||
{
|
{
|
||||||
QString stdOut;
|
QString stdOut;
|
||||||
auto cbReadStdOut = [&](const QString &data) {
|
auto cbReadStdOut = [&](const QString &data, libssh::Session &session) {
|
||||||
stdOut += data + "\n";
|
stdOut += data + "\n";
|
||||||
|
|
||||||
// if (data.contains("Automatically restart Docker daemon?")) {
|
if (data.contains("Automatically restart Docker daemon?")) {
|
||||||
// proc->write("yes\n");
|
session.writeToChannel("yes");
|
||||||
// }
|
}
|
||||||
};
|
};
|
||||||
auto cbReadStdErr = [&](const QString &data) {
|
auto cbReadStdErr = [&](const QString &data, libssh::Session &) {
|
||||||
stdOut += data + "\n";
|
stdOut += data + "\n";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -466,7 +418,7 @@ ErrorCode ServerController::buildContainerWorker(const ServerCredentials &creden
|
||||||
if (e) return e;
|
if (e) return e;
|
||||||
|
|
||||||
QString stdOut;
|
QString stdOut;
|
||||||
auto cbReadStdOut = [&](const QString &data) {
|
auto cbReadStdOut = [&](const QString &data, libssh::Session &) {
|
||||||
stdOut += data + "\n";
|
stdOut += data + "\n";
|
||||||
};
|
};
|
||||||
// auto cbReadStdErr = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> proc) {
|
// auto cbReadStdErr = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> proc) {
|
||||||
|
@ -484,7 +436,7 @@ ErrorCode ServerController::buildContainerWorker(const ServerCredentials &creden
|
||||||
ErrorCode ServerController::runContainerWorker(const ServerCredentials &credentials, DockerContainer container, QJsonObject &config)
|
ErrorCode ServerController::runContainerWorker(const ServerCredentials &credentials, DockerContainer container, QJsonObject &config)
|
||||||
{
|
{
|
||||||
QString stdOut;
|
QString stdOut;
|
||||||
auto cbReadStdOut = [&](const QString &data) {
|
auto cbReadStdOut = [&](const QString &data, libssh::Session &) {
|
||||||
stdOut += data + "\n";
|
stdOut += data + "\n";
|
||||||
};
|
};
|
||||||
// auto cbReadStdErr = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> proc) {
|
// auto cbReadStdErr = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> proc) {
|
||||||
|
@ -510,10 +462,10 @@ ErrorCode ServerController::runContainerWorker(const ServerCredentials &credenti
|
||||||
ErrorCode ServerController::configureContainerWorker(const ServerCredentials &credentials, DockerContainer container, QJsonObject &config)
|
ErrorCode ServerController::configureContainerWorker(const ServerCredentials &credentials, DockerContainer container, QJsonObject &config)
|
||||||
{
|
{
|
||||||
QString stdOut;
|
QString stdOut;
|
||||||
auto cbReadStdOut = [&](const QString &data) {
|
auto cbReadStdOut = [&](const QString &data, libssh::Session &) {
|
||||||
stdOut += data + "\n";
|
stdOut += data + "\n";
|
||||||
};
|
};
|
||||||
auto cbReadStdErr = [&](const QString &data) {
|
auto cbReadStdErr = [&](const QString &data, libssh::Session &) {
|
||||||
stdOut += data + "\n";
|
stdOut += data + "\n";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -646,10 +598,10 @@ ServerController::Vars ServerController::genVarsForScript(const ServerCredential
|
||||||
QString ServerController::checkSshConnection(const ServerCredentials &credentials, ErrorCode *errorCode)
|
QString ServerController::checkSshConnection(const ServerCredentials &credentials, ErrorCode *errorCode)
|
||||||
{
|
{
|
||||||
QString stdOut;
|
QString stdOut;
|
||||||
auto cbReadStdOut = [&](const QString &data) {
|
auto cbReadStdOut = [&](const QString &data, libssh::Session &) {
|
||||||
stdOut += data + "\n";
|
stdOut += data + "\n";
|
||||||
};
|
};
|
||||||
auto cbReadStdErr = [&](const QString &data) {
|
auto cbReadStdErr = [&](const QString &data, libssh::Session &) {
|
||||||
stdOut += data + "\n";
|
stdOut += data + "\n";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -59,12 +59,12 @@ public:
|
||||||
QString replaceVars(const QString &script, const Vars &vars);
|
QString replaceVars(const QString &script, const Vars &vars);
|
||||||
|
|
||||||
ErrorCode runScript(const ServerCredentials &credentials, QString script,
|
ErrorCode runScript(const ServerCredentials &credentials, QString script,
|
||||||
const std::function<void(const QString &)> &cbReadStdOut = nullptr,
|
const std::function<void(const QString &, libssh::Session &)> &cbReadStdOut = nullptr,
|
||||||
const std::function<void(const QString &)> &cbReadStdErr = nullptr);
|
const std::function<void(const QString &, libssh::Session &)> &cbReadStdErr = nullptr);
|
||||||
|
|
||||||
ErrorCode runContainerScript(const ServerCredentials &credentials, DockerContainer container, QString script,
|
ErrorCode runContainerScript(const ServerCredentials &credentials, DockerContainer container, QString script,
|
||||||
const std::function<void(const QString &)> &cbReadStdOut = nullptr,
|
const std::function<void(const QString &, libssh::Session &)> &cbReadStdOut = nullptr,
|
||||||
const std::function<void(const QString &)> &cbReadStdErr = nullptr);
|
const std::function<void(const QString &, libssh::Session &)> &cbReadStdErr = nullptr);
|
||||||
|
|
||||||
Vars genVarsForScript(const ServerCredentials &credentials, DockerContainer container = DockerContainer::None, const QJsonObject &config = QJsonObject());
|
Vars genVarsForScript(const ServerCredentials &credentials, DockerContainer container = DockerContainer::None, const QJsonObject &config = QJsonObject());
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ namespace libssh {
|
||||||
|
|
||||||
if (connectionResult != SSH_OK) {
|
if (connectionResult != SSH_OK) {
|
||||||
qDebug() << ssh_get_error(m_session);
|
qDebug() << ssh_get_error(m_session);
|
||||||
return ErrorCode::SshTimeoutError;
|
return fromLibsshErrorCode(ssh_get_error_code(m_session));
|
||||||
}
|
}
|
||||||
|
|
||||||
m_isSessionConnected = true;
|
m_isSessionConnected = true;
|
||||||
|
@ -71,10 +71,10 @@ namespace libssh {
|
||||||
|
|
||||||
if (authResult != SSH_OK) {
|
if (authResult != SSH_OK) {
|
||||||
qDebug() << ssh_get_error(m_session);
|
qDebug() << ssh_get_error(m_session);
|
||||||
return ErrorCode::SshAuthenticationError;
|
return fromLibsshErrorCode(ssh_get_error_code(m_session));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ErrorCode::NoError;
|
return fromLibsshErrorCode(ssh_get_error_code(m_session));
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorCode Session::initChannel(const ServerCredentials &credentials)
|
ErrorCode Session::initChannel(const ServerCredentials &credentials)
|
||||||
|
@ -89,7 +89,7 @@ namespace libssh {
|
||||||
|
|
||||||
if (m_channel == NULL) {
|
if (m_channel == NULL) {
|
||||||
qDebug() << ssh_get_error(m_session);
|
qDebug() << ssh_get_error(m_session);
|
||||||
return ErrorCode::SshAuthenticationError;
|
return fromLibsshErrorCode(ssh_get_error_code(m_session));
|
||||||
}
|
}
|
||||||
|
|
||||||
int result = ssh_channel_open_session(m_channel);
|
int result = ssh_channel_open_session(m_channel);
|
||||||
|
@ -99,37 +99,37 @@ namespace libssh {
|
||||||
m_isChannelOpened = true;
|
m_isChannelOpened = true;
|
||||||
} else {
|
} else {
|
||||||
qDebug() << ssh_get_error(m_session);
|
qDebug() << ssh_get_error(m_session);
|
||||||
return ErrorCode::SshAuthenticationError;
|
return fromLibsshErrorCode(ssh_get_error_code(m_session));
|
||||||
}
|
}
|
||||||
|
|
||||||
result = ssh_channel_request_pty(m_channel);
|
result = ssh_channel_request_pty(m_channel);
|
||||||
if (result != SSH_OK) {
|
if (result != SSH_OK) {
|
||||||
qDebug() << ssh_get_error(m_session);
|
qDebug() << ssh_get_error(m_session);
|
||||||
return ErrorCode::SshInternalError;
|
return fromLibsshErrorCode(ssh_get_error_code(m_session));
|
||||||
}
|
}
|
||||||
|
|
||||||
result = ssh_channel_change_pty_size(m_channel, 80, 1024);
|
result = ssh_channel_change_pty_size(m_channel, 80, 1024);
|
||||||
if (result != SSH_OK) {
|
if (result != SSH_OK) {
|
||||||
qDebug() << ssh_get_error(m_session);
|
qDebug() << ssh_get_error(m_session);
|
||||||
return ErrorCode::SshInternalError;
|
return fromLibsshErrorCode(ssh_get_error_code(m_session));
|
||||||
}
|
}
|
||||||
|
|
||||||
result = ssh_channel_request_shell(m_channel);
|
result = ssh_channel_request_shell(m_channel);
|
||||||
if (result != SSH_OK) {
|
if (result != SSH_OK) {
|
||||||
qDebug() << ssh_get_error(m_session);
|
qDebug() << ssh_get_error(m_session);
|
||||||
return ErrorCode::SshInternalError;
|
return fromLibsshErrorCode(ssh_get_error_code(m_session));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ErrorCode::NoError;
|
return fromLibsshErrorCode(ssh_get_error_code(m_session));
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorCode Session::writeToChannel(const QString &data,
|
ErrorCode Session::writeToChannel(const QString &data,
|
||||||
const std::function<void(const QString &)> &cbReadStdOut,
|
const std::function<void(const QString &, Session &)> &cbReadStdOut,
|
||||||
const std::function<void(const QString &)> &cbReadStdErr)
|
const std::function<void(const QString &, Session &)> &cbReadStdErr)
|
||||||
{
|
{
|
||||||
if (m_channel == NULL) {
|
if (m_channel == NULL) {
|
||||||
qDebug() << "ssh channel not initialized";
|
qDebug() << "ssh channel not initialized";
|
||||||
return ErrorCode::SshAuthenticationError;
|
return fromLibsshErrorCode(ssh_get_error_code(m_session));
|
||||||
}
|
}
|
||||||
|
|
||||||
QFutureWatcher<ErrorCode> watcher;
|
QFutureWatcher<ErrorCode> watcher;
|
||||||
|
@ -142,12 +142,11 @@ namespace libssh {
|
||||||
char buffer[bufferSize];
|
char buffer[bufferSize];
|
||||||
|
|
||||||
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());
|
||||||
ssh_channel_write(m_channel, "\n", 1);
|
if (bytesWritten == data.size() && ssh_channel_write(m_channel, "\n", 1)) {
|
||||||
if (bytesWritten == data.size()) {
|
|
||||||
auto readOutput = [&](bool isStdErr) {
|
auto readOutput = [&](bool isStdErr) {
|
||||||
std::string output;
|
std::string output;
|
||||||
if (ssh_channel_is_open(m_channel) && !ssh_channel_is_eof(m_channel)) {
|
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);
|
bytesRead = ssh_channel_read_timeout(m_channel, buffer, sizeof(buffer), isStdErr, 200);
|
||||||
while (bytesRead > 0)
|
while (bytesRead > 0)
|
||||||
{
|
{
|
||||||
output = std::string(buffer, bytesRead);
|
output = std::string(buffer, bytesRead);
|
||||||
|
@ -155,13 +154,13 @@ namespace libssh {
|
||||||
qDebug().noquote() << (isStdErr ? "stdErr" : "stdOut") << QString(output.c_str());
|
qDebug().noquote() << (isStdErr ? "stdErr" : "stdOut") << QString(output.c_str());
|
||||||
|
|
||||||
if (cbReadStdOut && !isStdErr){
|
if (cbReadStdOut && !isStdErr){
|
||||||
cbReadStdOut(output.c_str());
|
cbReadStdOut(output.c_str(), *this);
|
||||||
}
|
}
|
||||||
if (cbReadStdErr && isStdErr){
|
if (cbReadStdErr && isStdErr){
|
||||||
cbReadStdErr(output.c_str());
|
cbReadStdErr(output.c_str(), *this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bytesRead = ssh_channel_read_timeout(m_channel, buffer, sizeof(buffer), isStdErr, 5000);
|
bytesRead = ssh_channel_read_timeout(m_channel, buffer, sizeof(buffer), isStdErr, 2000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
|
@ -171,21 +170,35 @@ namespace libssh {
|
||||||
readOutput(true);
|
readOutput(true);
|
||||||
} else {
|
} else {
|
||||||
qDebug() << ssh_get_error(m_session);
|
qDebug() << ssh_get_error(m_session);
|
||||||
return ErrorCode::SshInternalError;
|
return fromLibsshErrorCode(ssh_get_error_code(m_session));
|
||||||
}
|
}
|
||||||
m_isNeedSendChannelEof = true;
|
m_isNeedSendChannelEof = true;
|
||||||
return ErrorCode::NoError;
|
return fromLibsshErrorCode(ssh_get_error_code(m_session));
|
||||||
});
|
});
|
||||||
watcher.setFuture(future);
|
watcher.setFuture(future);
|
||||||
|
|
||||||
QEventLoop wait;
|
QEventLoop wait;
|
||||||
|
|
||||||
QObject::connect(this, &Session::writeToChannelFinished, &wait, &QEventLoop::quit);
|
QObject::connect(this, &Session::writeToChannelFinished, &wait, &QEventLoop::quit);
|
||||||
wait.exec();
|
wait.exec();
|
||||||
|
|
||||||
return watcher.result();
|
return watcher.result();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ErrorCode Session::writeToChannel(const QString &data)
|
||||||
|
{
|
||||||
|
if (m_channel == NULL) {
|
||||||
|
qDebug() << "ssh channel not initialized";
|
||||||
|
return fromLibsshErrorCode(ssh_get_error_code(m_session));
|
||||||
|
}
|
||||||
|
|
||||||
|
int bytesWritten = ssh_channel_write(m_channel, data.toUtf8(), (uint32_t)data.size());
|
||||||
|
if (bytesWritten == data.size() && ssh_channel_write(m_channel, "\n", 1)) {
|
||||||
|
return fromLibsshErrorCode(ssh_get_error_code(m_session));
|
||||||
|
}
|
||||||
|
qDebug() << ssh_get_error(m_session);
|
||||||
|
return fromLibsshErrorCode(ssh_get_error_code(m_session));
|
||||||
|
}
|
||||||
|
|
||||||
ErrorCode Session::initSftp(const ServerCredentials &credentials)
|
ErrorCode Session::initSftp(const ServerCredentials &credentials)
|
||||||
{
|
{
|
||||||
m_session = ssh_new();
|
m_session = ssh_new();
|
||||||
|
@ -199,14 +212,14 @@ namespace libssh {
|
||||||
|
|
||||||
if (m_sftpSession == NULL) {
|
if (m_sftpSession == NULL) {
|
||||||
qDebug() << ssh_get_error(m_session);
|
qDebug() << ssh_get_error(m_session);
|
||||||
return ErrorCode::SshSftpError;
|
return fromLibsshErrorCode(ssh_get_error_code(m_session));
|
||||||
}
|
}
|
||||||
|
|
||||||
int result = sftp_init(m_sftpSession);
|
int result = sftp_init(m_sftpSession);
|
||||||
|
|
||||||
if (result != SSH_OK) {
|
if (result != SSH_OK) {
|
||||||
qDebug() << ssh_get_error(m_session);
|
qDebug() << ssh_get_error(m_session);
|
||||||
return ErrorCode::SshSftpError;
|
return fromLibsshSftpErrorCode(sftp_get_error(m_sftpSession));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ErrorCode::NoError;
|
return ErrorCode::NoError;
|
||||||
|
@ -216,7 +229,7 @@ namespace libssh {
|
||||||
{
|
{
|
||||||
if (m_sftpSession == NULL) {
|
if (m_sftpSession == NULL) {
|
||||||
qDebug() << "ssh sftp session not initialized";
|
qDebug() << "ssh sftp session not initialized";
|
||||||
return ErrorCode::SshSftpError;
|
return ErrorCode::SshInternalError;
|
||||||
}
|
}
|
||||||
|
|
||||||
QFutureWatcher<ErrorCode> watcher;
|
QFutureWatcher<ErrorCode> watcher;
|
||||||
|
@ -232,7 +245,7 @@ namespace libssh {
|
||||||
|
|
||||||
if (file == NULL) {
|
if (file == NULL) {
|
||||||
qDebug() << ssh_get_error(m_session);
|
qDebug() << ssh_get_error(m_session);
|
||||||
return ErrorCode::SshSftpError;
|
return fromLibsshSftpErrorCode(sftp_get_error(m_sftpSession));
|
||||||
}
|
}
|
||||||
|
|
||||||
int localFileSize = std::filesystem::file_size(localPath);
|
int localFileSize = std::filesystem::file_size(localPath);
|
||||||
|
@ -253,7 +266,7 @@ namespace libssh {
|
||||||
fin.close();
|
fin.close();
|
||||||
sftp_close(file);
|
sftp_close(file);
|
||||||
qDebug() << ssh_get_error(m_session);
|
qDebug() << ssh_get_error(m_session);
|
||||||
return ErrorCode::SshSftpError;
|
return fromLibsshSftpErrorCode(sftp_get_error(m_sftpSession));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,13 +284,13 @@ namespace libssh {
|
||||||
fin.close();
|
fin.close();
|
||||||
sftp_close(file);
|
sftp_close(file);
|
||||||
qDebug() << ssh_get_error(m_session);
|
qDebug() << ssh_get_error(m_session);
|
||||||
return ErrorCode::SshSftpError;
|
return fromLibsshSftpErrorCode(sftp_get_error(m_sftpSession));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sftp_close(file);
|
sftp_close(file);
|
||||||
qDebug() << ssh_get_error(m_session);
|
qDebug() << ssh_get_error(m_session);
|
||||||
return ErrorCode::SshSftpError;
|
return fromLibsshSftpErrorCode(sftp_get_error(m_sftpSession));
|
||||||
}
|
}
|
||||||
|
|
||||||
fin.close();
|
fin.close();
|
||||||
|
@ -285,7 +298,7 @@ namespace libssh {
|
||||||
int result = sftp_close(file);
|
int result = sftp_close(file);
|
||||||
if (result != SSH_OK) {
|
if (result != SSH_OK) {
|
||||||
qDebug() << ssh_get_error(m_session);
|
qDebug() << ssh_get_error(m_session);
|
||||||
return ErrorCode::SshSftpError;
|
return fromLibsshSftpErrorCode(sftp_get_error(m_sftpSession));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ErrorCode::NoError;
|
return ErrorCode::NoError;
|
||||||
|
@ -293,10 +306,40 @@ namespace libssh {
|
||||||
watcher.setFuture(future);
|
watcher.setFuture(future);
|
||||||
|
|
||||||
QEventLoop wait;
|
QEventLoop wait;
|
||||||
|
|
||||||
QObject::connect(this, &Session::sftpFileCopyFinished, &wait, &QEventLoop::quit);
|
QObject::connect(this, &Session::sftpFileCopyFinished, &wait, &QEventLoop::quit);
|
||||||
wait.exec();
|
wait.exec();
|
||||||
|
|
||||||
return watcher.result();
|
return watcher.result();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ErrorCode Session::fromLibsshErrorCode(int errorCode)
|
||||||
|
{
|
||||||
|
switch (errorCode) {
|
||||||
|
case(SSH_NO_ERROR): return ErrorCode::NoError;
|
||||||
|
case(SSH_REQUEST_DENIED): return ErrorCode::SshRequsetDeniedError;
|
||||||
|
case(SSH_EINTR): return ErrorCode::SshInterruptedError;
|
||||||
|
case(SSH_FATAL): return ErrorCode::SshInternalError;
|
||||||
|
default: return ErrorCode::SshInternalError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ErrorCode Session::fromLibsshSftpErrorCode(int errorCode)
|
||||||
|
{
|
||||||
|
switch (errorCode) {
|
||||||
|
case(SSH_FX_OK): return ErrorCode::NoError;
|
||||||
|
case(SSH_FX_EOF): return ErrorCode::SshSftpEofError;
|
||||||
|
case(SSH_FX_NO_SUCH_FILE): return ErrorCode::SshSftpNoSuchFileError;
|
||||||
|
case(SSH_FX_PERMISSION_DENIED): return ErrorCode::SshSftpPermissionDeniedError;
|
||||||
|
case(SSH_FX_FAILURE): return ErrorCode::SshSftpFailureError;
|
||||||
|
case(SSH_FX_BAD_MESSAGE): return ErrorCode::SshSftpBadMessageError;
|
||||||
|
case(SSH_FX_NO_CONNECTION): return ErrorCode::SshSftpNoConnectionError;
|
||||||
|
case(SSH_FX_CONNECTION_LOST): return ErrorCode::SshSftpConnectionLostError;
|
||||||
|
case(SSH_FX_OP_UNSUPPORTED): return ErrorCode::SshSftpOpUnsupportedError;
|
||||||
|
case(SSH_FX_INVALID_HANDLE): return ErrorCode::SshSftpInvalidHandleError;
|
||||||
|
case(SSH_FX_NO_SUCH_PATH): return ErrorCode::SshSftpNoSuchPathError;
|
||||||
|
case(SSH_FX_FILE_ALREADY_EXISTS): return ErrorCode::SshSftpFileAlreadyExistsError;
|
||||||
|
case(SSH_FX_WRITE_PROTECT): return ErrorCode::SshSftpWriteProtectError;
|
||||||
|
case(SSH_FX_NO_MEDIA): return ErrorCode::SshSftpNoMediaError;
|
||||||
|
default: return ErrorCode::SshSftpFailureError;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,11 +30,14 @@ namespace libssh {
|
||||||
ErrorCode initChannel(const ServerCredentials &credentials);
|
ErrorCode initChannel(const ServerCredentials &credentials);
|
||||||
ErrorCode initSftp(const ServerCredentials &credentials);
|
ErrorCode initSftp(const ServerCredentials &credentials);
|
||||||
ErrorCode writeToChannel(const QString &data,
|
ErrorCode writeToChannel(const QString &data,
|
||||||
const std::function<void(const QString &)> &cbReadStdOut,
|
const std::function<void(const QString &, Session &)> &cbReadStdOut,
|
||||||
const std::function<void(const QString &)> &cbReadStdErr);
|
const std::function<void(const QString &, Session &)> &cbReadStdErr);
|
||||||
|
ErrorCode writeToChannel(const QString &data);
|
||||||
ErrorCode sftpFileCopy(const SftpOverwriteMode overwriteMode, const std::string& localPath, const std::string& remotePath, const std::string& fileDesc);
|
ErrorCode sftpFileCopy(const SftpOverwriteMode overwriteMode, const std::string& localPath, const std::string& remotePath, const std::string& fileDesc);
|
||||||
private:
|
private:
|
||||||
ErrorCode connectToHost(const ServerCredentials &credentials);
|
ErrorCode connectToHost(const ServerCredentials &credentials);
|
||||||
|
ErrorCode fromLibsshErrorCode(int errorCode);
|
||||||
|
ErrorCode fromLibsshSftpErrorCode(int errorCode);
|
||||||
|
|
||||||
ssh_session m_session;
|
ssh_session m_session;
|
||||||
ssh_channel m_channel;
|
ssh_channel m_channel;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue