made libssh::ssh_connect a non-blocking feature

- extended error handling when connecting via ssh
This commit is contained in:
vladimir.kuznetsov 2023-06-10 05:25:41 +03:00
parent c3f39ad24d
commit cd3263db50
10 changed files with 54 additions and 34 deletions

View file

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

View file

@ -24,6 +24,7 @@ QString errorString(ErrorCode code){
case(SshInternalError): return QObject::tr("Ssh internal error");
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(SshTimeoutError): return QObject::tr("Timeout connecting to server");
// Libssh sftp errors
case(SshSftpEofError): return QObject::tr("Sftp error: End-of-file encountered");

View file

@ -10,6 +10,8 @@ const uint32_t S_IRWXU = 0644;
#endif
namespace libssh {
const QString libsshTimeoutError = "Timeout connecting to";
std::function<QString()> Client::m_passphraseCallback;
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_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) {
qDebug() << ssh_get_error(m_session);
return fromLibsshErrorCode(ssh_get_error_code(m_session));
return fromLibsshErrorCode();
}
std::string authUsername = credentials.userName.toStdString();
@ -78,8 +89,8 @@ namespace libssh {
ssh_key_free(privateKey);
}
if (authResult != SSH_OK) {
qDebug() << ssh_get_error(m_session);
ErrorCode errorCode = fromLibsshErrorCode(ssh_get_error_code(m_session));
qCritical() << ssh_get_error(m_session);
ErrorCode errorCode = fromLibsshErrorCode();
if (errorCode == ErrorCode::NoError) {
errorCode = ErrorCode::SshPrivateKeyFormatError;
}
@ -88,8 +99,7 @@ namespace libssh {
} else {
authResult = ssh_userauth_password(m_session, authUsername.c_str(), credentials.secretData.toStdString().c_str());
if (authResult != SSH_OK) {
qDebug() << ssh_get_error(m_session);
return fromLibsshErrorCode(ssh_get_error_code(m_session));
return fromLibsshErrorCode();
}
}
}
@ -188,16 +198,15 @@ namespace libssh {
ErrorCode Client::writeResponse(const QString &data)
{
if (m_channel == nullptr) {
qDebug() << "ssh channel not initialized";
return fromLibsshErrorCode(ssh_get_error_code(m_session));
qCritical() << "ssh channel not initialized";
return fromLibsshErrorCode();
}
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));
return fromLibsshErrorCode();
}
qDebug() << ssh_get_error(m_session);
return fromLibsshErrorCode(ssh_get_error_code(m_session));
return fromLibsshErrorCode();
}
ErrorCode Client::closeChannel()
@ -212,8 +221,7 @@ namespace libssh {
ssh_channel_free(m_channel);
m_channel = nullptr;
}
qDebug() << ssh_get_error(m_session);
return fromLibsshErrorCode(ssh_get_error_code(m_session));
return fromLibsshErrorCode();
}
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);
m_sftpSession = nullptr;
}
qDebug() << ssh_get_error(m_session);
qCritical() << ssh_get_error(m_session);
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) {
case(SSH_NO_ERROR): return ErrorCode::NoError;
case(SSH_REQUEST_DENIED): return ErrorCode::SshRequsetDeniedError;

View file

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