From 2b0209d65660954271a79ea72e24c79bfa0f17c2 Mon Sep 17 00:00:00 2001 From: Philip Schuchardt Date: Tue, 6 Jul 2021 19:26:24 -0400 Subject: [PATCH 1/9] Fix to #5 Moved Ssh2Channel.h and Ssh2Debug.h to src/include --- src/{ => include}/Ssh2Channel.h | 0 src/{ => include}/Ssh2Debug.h | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/{ => include}/Ssh2Channel.h (100%) rename src/{ => include}/Ssh2Debug.h (100%) diff --git a/src/Ssh2Channel.h b/src/include/Ssh2Channel.h similarity index 100% rename from src/Ssh2Channel.h rename to src/include/Ssh2Channel.h diff --git a/src/Ssh2Debug.h b/src/include/Ssh2Debug.h similarity index 100% rename from src/Ssh2Debug.h rename to src/include/Ssh2Debug.h From de2e0bcb362fd91ddb72a8350385110d3b55113c Mon Sep 17 00:00:00 2001 From: Philip Schuchardt Date: Tue, 6 Jul 2021 19:29:49 -0400 Subject: [PATCH 2/9] Forgot to add CMakeList.txt changes for issue #5 --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index f29d8c8..5a16c0c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,8 @@ add_library(qlibssh2 STATIC src/include/Ssh2Process.h src/include/Ssh2Scp.h src/include/Ssh2Types.h + src/include/Ssh2Debug.h + src/include/Ssh2Channel.h ) target_include_directories(qlibssh2 From e1eb44e837f1001501b72503431212d233526911 Mon Sep 17 00:00:00 2001 From: Philip Schuchardt Date: Tue, 6 Jul 2021 19:37:22 -0400 Subject: [PATCH 3/9] Fix for issue #4 - using add_subdirectory --- CMakeLists.txt | 57 +++++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f29d8c8..323664b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,36 +46,37 @@ target_link_libraries(qlibssh2 target_compile_features(qlibssh2 PUBLIC cxx_std_17) -# --- Create installed package -include(CMakePackageConfigHelpers) -include(GNUInstallDirs) -set(PACKAGE_NAME ${CMAKE_PROJECT_NAME}) +if(NOT ${QLIBSSH2_SKIP_INSTALL_PACKAGE}) + # --- Create installed package + include(CMakePackageConfigHelpers) + include(GNUInstallDirs) + set(PACKAGE_NAME ${CMAKE_PROJECT_NAME}) -set(TARGETS_FILE ${CMAKE_INSTALL_LIBDIR}/cmake/${PACKAGE_NAME}/${PACKAGE_NAME}Targets.cmake) -configure_package_config_file( - cmake/${PACKAGE_NAME}Config.cmake.in - ${CMAKE_BINARY_DIR}/${PACKAGE_NAME}Config.cmake - INSTALL_DESTINATION + set(TARGETS_FILE ${CMAKE_INSTALL_LIBDIR}/cmake/${PACKAGE_NAME}/${PACKAGE_NAME}Targets.cmake) + configure_package_config_file( + cmake/${PACKAGE_NAME}Config.cmake.in + ${CMAKE_BINARY_DIR}/${PACKAGE_NAME}Config.cmake + INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PACKAGE_NAME} - PATH_VARS + PATH_VARS TARGETS_FILE -) + ) -get_filename_component(TARGETS_FILE_WLE ${TARGETS_FILE} NAME_WLE) -install(TARGETS qlibssh2 - EXPORT ${TARGETS_FILE_WLE} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} -) -install(EXPORT ${TARGETS_FILE_WLE} - NAMESPACE QLIBSSH2:: - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PACKAGE_NAME} -) -install( - FILES + get_filename_component(TARGETS_FILE_WLE ${TARGETS_FILE} NAME_WLE) + install(TARGETS qlibssh2 + EXPORT ${TARGETS_FILE_WLE} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + ) + install(EXPORT ${TARGETS_FILE_WLE} + NAMESPACE QLIBSSH2:: + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PACKAGE_NAME} + ) + install( + FILES ${CMAKE_BINARY_DIR}/${PACKAGE_NAME}Config.cmake - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PACKAGE_NAME} -) -install(DIRECTORY src/include/ - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PACKAGE_NAME} -) - + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PACKAGE_NAME} + ) + install(DIRECTORY src/include/ + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PACKAGE_NAME} + ) +endif() From 7c45dcc67b5de11d867c3fe9f6581a93eefc6f62 Mon Sep 17 00:00:00 2001 From: Philip Schuchardt Date: Thu, 8 Jul 2021 20:50:36 -0400 Subject: [PATCH 4/9] Fix to issue #8 - Fixed crash This removes the reference counting on libssh2_init() and libssh2_exit() If a instance of Ssh2Client is ever created, then connection is mad with QCoreApplication to exit libssh2 using libssh2_exit() --- src/Ssh2Client.cpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/Ssh2Client.cpp b/src/Ssh2Client.cpp index fc04d33..71e9103 100644 --- a/src/Ssh2Client.cpp +++ b/src/Ssh2Client.cpp @@ -32,6 +32,7 @@ SOFTWARE. #include #include +#include using namespace qlibssh2; @@ -42,19 +43,17 @@ std::atomic ssh2_initializations_count(0); void initializeSsh2() { - if (ssh2_initializations_count == 0) + if (ssh2_initializations_count == 0) { libssh2_init(0); + QObject::connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, + QCoreApplication::instance(), []() + { + libssh2_exit(); + }); + } ssh2_initializations_count++; }; -void freeSsh2() -{ - if (ssh2_initializations_count == 1) - libssh2_exit(); - if (ssh2_initializations_count > 0) - ssh2_initializations_count--; -}; - ssize_t libssh_recv(int socket, void* buffer, size_t length, int flags, void** abstract) { Q_UNUSED(socket); @@ -104,7 +103,6 @@ Ssh2Client::~Ssh2Client() closeSession(); if (state() == ConnectedState) waitForDisconnected(); - freeSsh2(); } void Ssh2Client::connectToHost(const QString& hostName, qint16 port) From a3d0068a7f76208cad48322d1de4efbf86a7be75 Mon Sep 17 00:00:00 2001 From: Philip Schuchardt Date: Fri, 9 Jul 2021 19:10:39 -0400 Subject: [PATCH 5/9] Fix issue #10 - exitcode not reporting correctly Switched from channel_send_eof() to channel_close() fixes the exitcode issue --- src/Ssh2Channel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ssh2Channel.cpp b/src/Ssh2Channel.cpp index b70b359..6589a5b 100644 --- a/src/Ssh2Channel.cpp +++ b/src/Ssh2Channel.cpp @@ -200,7 +200,7 @@ std::error_code Ssh2Channel::closeChannelSession() std::error_code error_code = ssh2_success; libssh2_channel_flush_ex(ssh2_channel_, 0); libssh2_channel_flush_ex(ssh2_channel_, 1); - const int ssh2_method_result = libssh2_channel_send_eof(ssh2_channel_); + const int ssh2_method_result = libssh2_channel_close(ssh2_channel_); switch (ssh2_method_result) { case LIBSSH2_ERROR_EAGAIN: setSsh2ChannelState(ChannelStates::Closing); From 133555a65941555247111db06c485c4b6d4101a4 Mon Sep 17 00:00:00 2001 From: Philip Schuchardt Date: Thu, 22 Jul 2021 19:53:05 -0400 Subject: [PATCH 6/9] Fixed grammer in error message --- src/Ssh2Types.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ssh2Types.cpp b/src/Ssh2Types.cpp index fd0e53e..165105a 100644 --- a/src/Ssh2Types.cpp +++ b/src/Ssh2Types.cpp @@ -42,7 +42,7 @@ class Ssh2ErrorCategory : public std::error_category { switch (static_cast(ev)) { case ErrorReadKnownHosts: - return "Error in read known hosts file"; + return "Error in reading known hosts file"; case ErrorWriteKnownHosts: return "Error in writing to known hosts file"; case SessionStartupError: From 292e009aa4ab1e219b21b593dc1a905a6b513b43 Mon Sep 17 00:00:00 2001 From: Philip Schuchardt Date: Tue, 30 Aug 2022 15:33:47 -0600 Subject: [PATCH 7/9] CMakeLists.txt uses Qt6 instead of Qt5 --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f29d8c8..db6bed0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16) project(QLibssh2 LANGUAGES CXX) -find_package(Qt5 REQUIRED +find_package(Qt6 REQUIRED Core Network ) @@ -39,8 +39,8 @@ target_include_directories(qlibssh2 target_link_libraries(qlibssh2 PUBLIC - Qt5::Core - Qt5::Network + Qt6::Core + Qt6::Network Libssh2::libssh2 ) From 13dac1c6ff4abdddf552a23820d5bfb5d26c5b3e Mon Sep 17 00:00:00 2001 From: Philip Schuchardt Date: Wed, 31 Aug 2022 13:20:13 -0600 Subject: [PATCH 8/9] Fixed crashing issues in QIODevice from upgrading to Qt6 In Qt6 QIODevice now uses ringbuffer for reading data, they're allocated with setReadChannelCount(), which is qt private method. Without setting the readChannelCount() connections aren't terminated and when reading stderr for process, QIODevice just crashes when calling readAll(). --- CMakeLists.txt | 2 ++ src/Ssh2Channel.cpp | 20 +++++++++++++++++--- src/Ssh2Process.cpp | 3 ++- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index de11462..f55f6ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,6 +44,8 @@ target_link_libraries(qlibssh2 Qt6::Core Qt6::Network Libssh2::libssh2 + PRIVATE + Qt::CorePrivate ) target_compile_features(qlibssh2 PUBLIC cxx_std_17) diff --git a/src/Ssh2Channel.cpp b/src/Ssh2Channel.cpp index 6589a5b..7cbc798 100644 --- a/src/Ssh2Channel.cpp +++ b/src/Ssh2Channel.cpp @@ -27,6 +27,9 @@ SOFTWARE. #include +//Qt includes +#include + using namespace qlibssh2; Ssh2Channel::Ssh2Channel(Ssh2Client* ssh2_client) @@ -75,6 +78,11 @@ qint64 Ssh2Channel::readData(char* data, qint64 maxlen) result = -1; } + + if(result == LIBSSH2_ERROR_EAGAIN) { + return 0; + } + return result; } @@ -181,11 +189,14 @@ std::error_code Ssh2Channel::openChannelSession() setSsh2ChannelState(Opening); error_code = Ssh2Error::TryAgain; break; - case 0: + case 0: { QIODevice::open(QIODevice::ReadWrite | QIODevice::Unbuffered); setSsh2ChannelState(Opened); + QIODevicePrivate *d = reinterpret_cast(Ssh2Channel::d_ptr.data()); + d->setReadChannelCount(2); error_code = ssh2_success; break; + } default: { debugSsh2Error(ssh2_method_result); error_code = Ssh2Error::FailedToOpenChannel; @@ -216,8 +227,9 @@ std::error_code Ssh2Channel::closeChannelSession() nullptr, nullptr, nullptr); - if (result == 0) + if (result == 0) { exit_signal_ = QString(exit_signal); + } destroyChannel(); } break; default: { @@ -249,9 +261,11 @@ void Ssh2Channel::checkChannelData(const Ssh2Channel::ChannelStream& stream_id) setCurrentReadChannel(1); break; } + const QByteArray data = readAll(); - if (data.size()) + if (data.size()) { emit newChannelData(data, stream_id); + } } QString Ssh2Channel::exitSignal() const diff --git a/src/Ssh2Process.cpp b/src/Ssh2Process.cpp index f597889..a503549 100644 --- a/src/Ssh2Process.cpp +++ b/src/Ssh2Process.cpp @@ -85,7 +85,8 @@ void Ssh2Process::onSsh2ChannelStateChanged(const ChannelStates& state) std::error_code Ssh2Process::execSsh2Process() { std::error_code error_code = ssh2_success; - const int ssh2_method_result = libssh2_channel_exec(ssh2Channel(), qPrintable(command_)); + const QByteArray command = command_.toLocal8Bit(); + const int ssh2_method_result = libssh2_channel_exec(ssh2Channel(), command.constData()); switch (ssh2_method_result) { case LIBSSH2_ERROR_EAGAIN: setSsh2ProcessState(Starting); From acceb1c5674413261396756b90b73e78bdb59372 Mon Sep 17 00:00:00 2001 From: Philip Schuchardt Date: Wed, 31 Aug 2022 13:21:20 -0600 Subject: [PATCH 9/9] Fixed abort in ssh2client The crash has to do with disconnection of signal and slots. Qt6 is more strict on using slots after objects have been destroyed. I've changed the ssh2client deconstructor to wait until client is fully disconnected from the QTCPSocket. --- src/Ssh2Client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ssh2Client.cpp b/src/Ssh2Client.cpp index 71e9103..9558e65 100644 --- a/src/Ssh2Client.cpp +++ b/src/Ssh2Client.cpp @@ -101,7 +101,7 @@ Ssh2Client::Ssh2Client(Ssh2Settings ssh2_settings, Ssh2Client::~Ssh2Client() { closeSession(); - if (state() == ConnectedState) + if (state() != UnconnectedState) waitForDisconnected(); }