diff options
Diffstat (limited to 'src/plugins/remotelinux')
-rw-r--r-- | src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.cpp | 11 | ||||
-rw-r--r-- | src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.h | 1 | ||||
-rw-r--r-- | src/plugins/remotelinux/genericlinuxdeviceconfigurationwizard.cpp | 17 | ||||
-rw-r--r-- | src/plugins/remotelinux/linuxdevicetestdialog.cpp | 124 | ||||
-rw-r--r-- | src/plugins/remotelinux/linuxdevicetestdialog.h | 11 | ||||
-rw-r--r-- | src/plugins/remotelinux/linuxdevicetester.cpp | 151 | ||||
-rw-r--r-- | src/plugins/remotelinux/linuxdevicetester.h | 76 | ||||
-rw-r--r-- | src/plugins/remotelinux/remotelinux.pro | 2 | ||||
-rw-r--r-- | src/plugins/remotelinux/remotelinuxapplicationrunner.cpp | 9 | ||||
-rw-r--r-- | src/plugins/remotelinux/remotelinuxusedportsgatherer.cpp | 145 | ||||
-rw-r--r-- | src/plugins/remotelinux/remotelinuxusedportsgatherer.h | 31 | ||||
-rw-r--r-- | src/plugins/remotelinux/simplerunner.cpp | 160 | ||||
-rw-r--r-- | src/plugins/remotelinux/simplerunner.h | 98 | ||||
-rw-r--r-- | src/plugins/remotelinux/startgdbserverdialog.cpp | 25 |
14 files changed, 301 insertions, 560 deletions
diff --git a/src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.cpp b/src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.cpp index 364b5a2792..65f3653308 100644 --- a/src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.cpp +++ b/src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.cpp @@ -93,15 +93,8 @@ QDialog *GenericLinuxDeviceConfigurationFactory::createDeviceAction(const QStrin { Q_ASSERT(supportedDeviceActionIds().contains(actionId)); - if (actionId == QLatin1String(Constants::GenericTestDeviceActionId)) { - QList<LinuxDeviceTester *> tests; - tests.append(new AuthenticationTester(deviceConfig)); - tests.append(new LinuxDeviceTester(deviceConfig, - tr("Checking kernel version..."), - QLatin1String("uname -rsm"))); - tests.append(new UsedPortsTester(deviceConfig)); - return new LinuxDeviceTestDialog(tests, parent); - } + if (actionId == QLatin1String(Constants::GenericTestDeviceActionId)) + return new LinuxDeviceTestDialog(deviceConfig, new GenericLinuxDeviceTester, parent); if (actionId == QLatin1String(Constants::GenericRemoteProcessesActionId)) { return new RemoteLinuxProcessesDialog(new GenericRemoteLinuxProcessList(deviceConfig), parent); diff --git a/src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.h b/src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.h index 931ae931b9..c29f52435f 100644 --- a/src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.h +++ b/src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.h @@ -29,7 +29,6 @@ ** Nokia at qt-info@nokia.com. ** **************************************************************************/ - #ifndef GENERICLINUXDEVICECONFIGURATIONFACTORY_H #define GENERICLINUXDEVICECONFIGURATIONFACTORY_H diff --git a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizard.cpp b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizard.cpp index 8bba285cf4..bbb838d98d 100644 --- a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizard.cpp +++ b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizard.cpp @@ -30,17 +30,12 @@ **************************************************************************/ #include "genericlinuxdeviceconfigurationwizard.h" -#include "genericlinuxdeviceconfigurationfactory.h" #include "genericlinuxdeviceconfigurationwizardpages.h" #include "linuxdevicetestdialog.h" #include "linuxdevicetester.h" #include "portlist.h" #include "remotelinux_constants.h" -#include <extensionsystem/pluginmanager.h> - -#include <utils/qtcassert.h> - using namespace Utils; namespace RemoteLinux { @@ -92,16 +87,8 @@ LinuxDeviceConfiguration::Ptr GenericLinuxDeviceConfigurationWizard::deviceConfi LinuxDeviceConfiguration::Ptr devConf = LinuxDeviceConfiguration::create(d->setupPage.configurationName(), QLatin1String(Constants::GenericLinuxOsType), LinuxDeviceConfiguration::Hardware, PortList::fromString(QLatin1String("10000-10100")), sshParams); - - GenericLinuxDeviceConfigurationFactory *factory = - ExtensionSystem::PluginManager::instance()->getObject<GenericLinuxDeviceConfigurationFactory>(); - QTC_ASSERT(factory, return LinuxDeviceConfiguration::Ptr(0)); - - QDialog *dlg = factory->createDeviceAction(QLatin1String(Constants::GenericTestDeviceActionId), devConf, 0); - QTC_ASSERT(dlg, return LinuxDeviceConfiguration::Ptr(0)); - dlg->exec(); - delete dlg; - + LinuxDeviceTestDialog dlg(devConf, new GenericLinuxDeviceTester(this), this); + dlg.exec(); return devConf; } diff --git a/src/plugins/remotelinux/linuxdevicetestdialog.cpp b/src/plugins/remotelinux/linuxdevicetestdialog.cpp index e19f2c0a9a..dcb9cfbb4a 100644 --- a/src/plugins/remotelinux/linuxdevicetestdialog.cpp +++ b/src/plugins/remotelinux/linuxdevicetestdialog.cpp @@ -32,9 +32,6 @@ #include "linuxdevicetestdialog.h" #include "ui_linuxdevicetestdialog.h" -#include <utils/qtcassert.h> -#include <utils/ssh/sshconnectionmanager.h> - #include <QtGui/QBrush> #include <QtGui/QColor> #include <QtGui/QFont> @@ -43,77 +40,34 @@ namespace RemoteLinux { namespace Internal { - -class LinuxDeviceTestDialogPrivate -{ +class LinuxDeviceTestDialogPrivate { public: - LinuxDeviceTestDialogPrivate(LinuxDeviceTestDialog *qptr, QList<LinuxDeviceTester *> &tester) - : deviceTests(tester), lastTest(0), currentTestPosition(-1), failCount(0), q(qptr) - { } - - ~LinuxDeviceTestDialogPrivate() - { - qDeleteAll(deviceTests); - } - - LinuxDeviceTester *currentTest() - { - return deviceTests.at(currentTestPosition); - } - - void runTest() - { - if (lastTest) - QObject::disconnect(lastTest, 0, q, 0); - - LinuxDeviceTester *curTest = currentTest(); - - QObject::connect(curTest, SIGNAL(progressMessage(QString)), - q, SLOT(handleProgressMessage(QString))); - QObject::connect(curTest, SIGNAL(errorMessage(QString)), - q, SLOT(handleErrorMessage(QString))); - QObject::connect(curTest, SIGNAL(finished(int)), - q, SLOT(handleTestFinished(int))); - - lastTest = curTest; - - q->addText(curTest->headLine(), QLatin1String("black"), true); - q->addText(curTest->commandLine(), QLatin1String("darkGray"), false); - curTest->run(); - } - - bool runNextTest() + LinuxDeviceTestDialogPrivate(AbstractLinuxDeviceTester *tester) + : deviceTester(tester), finished(false) { - ++currentTestPosition; - if (currentTestPosition < deviceTests.count()) { - runTest(); - } else { - currentTestPosition = -1; - lastTest = 0; - } - - return currentTestPosition != -1; } Ui::LinuxDeviceTestDialog ui; - QList<LinuxDeviceTester *> deviceTests; - LinuxDeviceTester *lastTest; - int currentTestPosition; - int failCount; - LinuxDeviceTestDialog *const q; + AbstractLinuxDeviceTester * const deviceTester; + bool finished; }; } // namespace Internal -LinuxDeviceTestDialog::LinuxDeviceTestDialog(QList<LinuxDeviceTester *> tests, QWidget *parent) : - QDialog(parent), - d(new Internal::LinuxDeviceTestDialogPrivate(this, tests)) -{ - QTC_ASSERT(!tests.isEmpty(), return); +using namespace Internal; +LinuxDeviceTestDialog::LinuxDeviceTestDialog(const QSharedPointer<const LinuxDeviceConfiguration> &deviceConfiguration, + AbstractLinuxDeviceTester *deviceTester, QWidget *parent) + : QDialog(parent), d(new LinuxDeviceTestDialogPrivate(deviceTester)) +{ d->ui.setupUi(this); - d->runNextTest(); + d->deviceTester->setParent(this); + connect(d->deviceTester, SIGNAL(progressMessage(QString)), SLOT(handleProgressMessage(QString))); + connect(d->deviceTester, SIGNAL(errorMessage(QString)), SLOT(handleErrorMessage(QString))); + connect(d->deviceTester, SIGNAL(finished(RemoteLinux::AbstractLinuxDeviceTester::TestResult)), + SLOT(handleTestFinished(RemoteLinux::AbstractLinuxDeviceTester::TestResult))); + d->deviceTester->testDevice(deviceConfiguration); } LinuxDeviceTestDialog::~LinuxDeviceTestDialog() @@ -123,22 +77,14 @@ LinuxDeviceTestDialog::~LinuxDeviceTestDialog() void LinuxDeviceTestDialog::reject() { - if (d->currentTestPosition >= 0) { - d->deviceTests.at(d->currentTestPosition)->cancel(); - disconnect(d->deviceTests.at(d->currentTestPosition), 0, this, 0); - } - + if (!d->finished) + d->deviceTester->stopTest(); QDialog::reject(); } void LinuxDeviceTestDialog::handleProgressMessage(const QString &message) { - QString tmp = QLatin1String(" ") + message; - if (tmp.endsWith('\n')) - tmp = tmp.left(tmp.count() - 1); - tmp.replace(QLatin1Char('\n'), QLatin1String("\n ")); - - addText(tmp, QLatin1String("black"), false); + addText(message, QLatin1String("black"), false); } void LinuxDeviceTestDialog::handleErrorMessage(const QString &message) @@ -146,33 +92,15 @@ void LinuxDeviceTestDialog::handleErrorMessage(const QString &message) addText(message, QLatin1String("red"), false); } -void LinuxDeviceTestDialog::handleTestFinished(int result) +void LinuxDeviceTestDialog::handleTestFinished(AbstractLinuxDeviceTester::TestResult result) { - bool abortRun = false; - if (result == LinuxDeviceTester::TestSuccess) { - addText(tr("Ok.\n"), QLatin1String("black"), true); - } else if (result == LinuxDeviceTester::TestCriticalFailure) { - addText(tr("Critical device test failure, aborting.\n"), QLatin1String("red"), true); - ++d->failCount; - abortRun = true; - } else { - addText(tr("Device test failed.\n"), QLatin1String("red"), true); - ++d->failCount; - } - - if (abortRun || !d->runNextTest()) { - if (d->failCount == 0 && !abortRun) { - addText(tr("All device tests finished successfully.\n"), QLatin1String("blue"), true); - } else { - if (!abortRun) { - //: %1: number of failed tests, %2 total tests - addText(tr("%1 device tests of %2 failed.\n").arg(d->failCount).arg(d->deviceTests.count()), - QLatin1String("red"), true); - } - } + d->finished = true; + d->ui.buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Close")); - d->ui.buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Close")); - } + if (result == AbstractLinuxDeviceTester::TestSuccess) + addText(tr("Device test finished successfully."), QLatin1String("blue"), true); + else + addText(tr("Device test failed."), QLatin1String("red"), true); } void LinuxDeviceTestDialog::addText(const QString &text, const QString &color, bool bold) diff --git a/src/plugins/remotelinux/linuxdevicetestdialog.h b/src/plugins/remotelinux/linuxdevicetestdialog.h index 6aa150bcc3..ec8becdce9 100644 --- a/src/plugins/remotelinux/linuxdevicetestdialog.h +++ b/src/plugins/remotelinux/linuxdevicetestdialog.h @@ -47,8 +47,9 @@ class REMOTELINUX_EXPORT LinuxDeviceTestDialog : public QDialog Q_OBJECT public: - // Note: The dialog takes ownership of deviceTests - LinuxDeviceTestDialog(QList<LinuxDeviceTester *> tests, QWidget *parent = 0); + // Note: The dialog takes ownership of deviceTester + explicit LinuxDeviceTestDialog(const QSharedPointer<const LinuxDeviceConfiguration> &deviceConfiguration, + AbstractLinuxDeviceTester * deviceTester, QWidget *parent = 0); ~LinuxDeviceTestDialog(); void reject(); @@ -56,14 +57,12 @@ public: private slots: void handleProgressMessage(const QString &message); void handleErrorMessage(const QString &message); - void handleTestFinished(int result); + void handleTestFinished(RemoteLinux::AbstractLinuxDeviceTester::TestResult result); private: void addText(const QString &text, const QString &color, bool bold); - Internal::LinuxDeviceTestDialogPrivate *const d; - - friend class Internal::LinuxDeviceTestDialogPrivate; + Internal::LinuxDeviceTestDialogPrivate * const d; }; } // namespace RemoteLinux diff --git a/src/plugins/remotelinux/linuxdevicetester.cpp b/src/plugins/remotelinux/linuxdevicetester.cpp index 5d2f4b2c9a..cd9c465174 100644 --- a/src/plugins/remotelinux/linuxdevicetester.cpp +++ b/src/plugins/remotelinux/linuxdevicetester.cpp @@ -35,99 +35,164 @@ #include "remotelinuxusedportsgatherer.h" #include <utils/qtcassert.h> -#include <utils/ssh/sshremoteprocessrunner.h> +#include <utils/ssh/sshremoteprocess.h> #include <utils/ssh/sshconnection.h> -#include <utils/ssh/sshconnectionmanager.h> using namespace Utils; namespace RemoteLinux { namespace Internal { +namespace { -class LinuxDeviceTesterPrivate +enum State { Inactive, Connecting, RunningUname, TestingPorts }; + +} // anonymous namespace + +class GenericLinuxDeviceTesterPrivate { public: - LinuxDeviceTesterPrivate() - { } + GenericLinuxDeviceTesterPrivate() : state(Inactive) {} - QString headLine; + LinuxDeviceConfiguration::ConstPtr deviceConfiguration; + SshConnection::Ptr connection; + SshRemoteProcess::Ptr process; + RemoteLinuxUsedPortsGatherer portsGatherer; + State state; }; } // namespace Internal using namespace Internal; -LinuxDeviceTester::LinuxDeviceTester(const QSharedPointer<const LinuxDeviceConfiguration> &deviceConfiguration, - const QString &headline, const QString &commandline) : - SimpleRunner(deviceConfiguration, commandline), - d(new LinuxDeviceTesterPrivate) +AbstractLinuxDeviceTester::AbstractLinuxDeviceTester(QObject *parent) : QObject(parent) { - d->headLine = headline; } -LinuxDeviceTester::~LinuxDeviceTester() + +GenericLinuxDeviceTester::GenericLinuxDeviceTester(QObject *parent) + : AbstractLinuxDeviceTester(parent), d(new GenericLinuxDeviceTesterPrivate) { - delete d; } -QString LinuxDeviceTester::headLine() const +GenericLinuxDeviceTester::~GenericLinuxDeviceTester() { - return d->headLine; + delete d; } -int LinuxDeviceTester::processFinished(int exitStatus) +void GenericLinuxDeviceTester::testDevice(const LinuxDeviceConfiguration::ConstPtr &deviceConfiguration) { - return SimpleRunner::processFinished(exitStatus) == 0 ? TestSuccess : TestFailure; + QTC_ASSERT(d->state == Inactive, return); + + d->deviceConfiguration = deviceConfiguration; + d->connection = SshConnection::create(deviceConfiguration->sshParameters()); + connect(d->connection.data(), SIGNAL(connected()), SLOT(handleConnected())); + connect(d->connection.data(), SIGNAL(error(Utils::SshError)), + SLOT(handleConnectionFailure())); + + emit progressMessage(tr("Connecting to host...")); + d->state = Connecting; + d->connection->connectToHost(); } -AuthenticationTester::AuthenticationTester(const QSharedPointer<const LinuxDeviceConfiguration> &deviceConfiguration) : - LinuxDeviceTester(deviceConfiguration, tr("Checking authentication data..."), - QLatin1String("echo \"Success!\"")) +void GenericLinuxDeviceTester::stopTest() { - SshConnectionManager::instance().forceNewConnection(sshParameters()); + QTC_ASSERT(d->state != Inactive, return); + + switch (d->state) { + case Connecting: + d->connection->disconnectFromHost(); + break; + case TestingPorts: + d->portsGatherer.stop(); + break; + case RunningUname: + d->process->close(); + break; + case Inactive: + break; + } + + setFinished(TestFailure); } -void AuthenticationTester::handleStdOutput(const QByteArray &data) +SshConnection::Ptr GenericLinuxDeviceTester::connection() const { - m_authenticationSucceded = data.contains("Success!"); - LinuxDeviceTester::handleStdOutput(data); + return d->connection; } -int AuthenticationTester::processFinished(int exitStatus) +void GenericLinuxDeviceTester::handleConnected() { - return LinuxDeviceTester::processFinished(exitStatus) == TestSuccess - && m_authenticationSucceded ? TestSuccess : TestCriticalFailure; + QTC_ASSERT(d->state == Connecting, return); + + d->process = d->connection->createRemoteProcess("uname -rsm"); + connect(d->process.data(), SIGNAL(closed(int)), SLOT(handleProcessFinished(int))); + + emit progressMessage("Checking kernel version..."); + d->state = RunningUname; + d->process->start(); } -UsedPortsTester::UsedPortsTester(const QSharedPointer<const LinuxDeviceConfiguration> &deviceConfiguration) : - LinuxDeviceTester(deviceConfiguration, tr("Checking for available ports..."), QString()), - gatherer(new RemoteLinuxUsedPortsGatherer(deviceConfiguration)) +void GenericLinuxDeviceTester::handleConnectionFailure() { - connect(gatherer, SIGNAL(aboutToStart()), this, SIGNAL(aboutToStart())); - connect(gatherer, SIGNAL(errorMessage(QString)), this, SIGNAL(errorMessage(QString))); - connect(gatherer, SIGNAL(finished(int)), this, SIGNAL(finished(int))); - connect(gatherer, SIGNAL(progressMessage(QString)), this, SIGNAL(progressMessage(QString))); - connect(gatherer, SIGNAL(started()), this, SIGNAL(started())); + QTC_ASSERT(d->state != Inactive, return); + + emit errorMessage(tr("SSH connection failure: %1\n").arg(d->connection->errorString())); + setFinished(TestFailure); } -UsedPortsTester::~UsedPortsTester() +void GenericLinuxDeviceTester::handleProcessFinished(int exitStatus) { - delete gatherer; + QTC_ASSERT(d->state == RunningUname, return); + + if (exitStatus != SshRemoteProcess::ExitedNormally || d->process->exitCode() != 0) { + const QByteArray stderrOutput = d->process->readAllStandardError(); + if (!stderrOutput.isEmpty()) + emit errorMessage(tr("uname failed: %1\n").arg(QString::fromUtf8(stderrOutput))); + else + emit errorMessage(tr("uname failed.\n")); + } else { + emit progressMessage(QString::fromUtf8(d->process->readAllStandardOutput())); + } + + connect(&d->portsGatherer, SIGNAL(error(QString)), SLOT(handlePortsGatheringError(QString))); + connect(&d->portsGatherer, SIGNAL(portListReady()), SLOT(handlePortListReady())); + + emit progressMessage(tr("Checking if specified ports are available...")); + d->state = TestingPorts; + d->portsGatherer.start(d->connection, d->deviceConfiguration); } -QString UsedPortsTester::commandLine() const +void GenericLinuxDeviceTester::handlePortsGatheringError(const QString &message) { - return gatherer->commandLine(); + QTC_ASSERT(d->state == TestingPorts, return); + + emit errorMessage(tr("Error gathering ports: %1\n").arg(message)); + setFinished(TestFailure); } -void UsedPortsTester::run() +void GenericLinuxDeviceTester::handlePortListReady() { - gatherer->run(); + QTC_ASSERT(d->state == TestingPorts, return); + + if (d->portsGatherer.usedPorts().isEmpty()) { + emit progressMessage("All specified ports are available.\n"); + } else { + QString portList; + foreach (const int port, d->portsGatherer.usedPorts()) + portList += QString::number(port) + QLatin1String(", "); + portList.remove(portList.count() - 2, 2); + emit errorMessage(tr("The following specified ports are currently in use: %1\n") + .arg(portList)); + } + setFinished(TestSuccess); } -void UsedPortsTester::cancel() +void GenericLinuxDeviceTester::setFinished(TestResult result) { - gatherer->cancel(); + d->state = Inactive; + disconnect(d->connection.data(), 0, this, 0); + disconnect(&d->portsGatherer, 0, this, 0); + emit finished(result); } } // namespace RemoteLinux diff --git a/src/plugins/remotelinux/linuxdevicetester.h b/src/plugins/remotelinux/linuxdevicetester.h index 7c1df21eae..1a469af806 100644 --- a/src/plugins/remotelinux/linuxdevicetester.h +++ b/src/plugins/remotelinux/linuxdevicetester.h @@ -34,79 +34,65 @@ #include "remotelinux_export.h" -#include "simplerunner.h" - -#include <utils/ssh/sshconnection.h> - #include <QtCore/QObject> #include <QtCore/QSharedPointer> QT_FORWARD_DECLARE_CLASS(QString) +namespace Utils { +class SshConnection; +} + namespace RemoteLinux { class LinuxDeviceConfiguration; -class RemoteLinuxUsedPortsGatherer; namespace Internal { -class LinuxDeviceTesterPrivate; +class GenericLinuxDeviceTesterPrivate; } // namespace Internal -// ----------------------------------------------------------------------- -// LinuxDeviceTester: -// ----------------------------------------------------------------------- - -class REMOTELINUX_EXPORT LinuxDeviceTester : public SimpleRunner +class REMOTELINUX_EXPORT AbstractLinuxDeviceTester : public QObject { Q_OBJECT - + Q_DISABLE_COPY(AbstractLinuxDeviceTester) public: - enum TestResult { TestSuccess = 0, TestFailure, TestCriticalFailure }; + enum TestResult { TestSuccess, TestFailure }; - LinuxDeviceTester(const QSharedPointer<const LinuxDeviceConfiguration> &deviceConfiguration, - const QString &headline, const QString &commandline); - ~LinuxDeviceTester(); + virtual void testDevice(const QSharedPointer<const LinuxDeviceConfiguration> &deviceConfiguration) = 0; + virtual void stopTest() = 0; - virtual QString headLine() const; +signals: + void progressMessage(const QString &message); + void errorMessage(const QString &message); + void finished(RemoteLinux::AbstractLinuxDeviceTester::TestResult result); protected: - int processFinished(int exitStatus); - -private: - Internal::LinuxDeviceTesterPrivate *const d; + explicit AbstractLinuxDeviceTester(QObject *parent = 0); }; -class REMOTELINUX_EXPORT AuthenticationTester : public LinuxDeviceTester -{ - Q_OBJECT - -public: - AuthenticationTester(const QSharedPointer<const LinuxDeviceConfiguration> &deviceConfiguration); - -protected slots: - void handleStdOutput(const QByteArray &data); - -protected: - int processFinished(int exitStatus); - -private: - bool m_authenticationSucceded; -}; -class REMOTELINUX_EXPORT UsedPortsTester : public LinuxDeviceTester +class REMOTELINUX_EXPORT GenericLinuxDeviceTester : public AbstractLinuxDeviceTester { Q_OBJECT - public: - UsedPortsTester(const QSharedPointer<const LinuxDeviceConfiguration> &deviceConfiguration); - ~UsedPortsTester(); + explicit GenericLinuxDeviceTester(QObject *parent = 0); + ~GenericLinuxDeviceTester(); - QString commandLine() const; + void testDevice(const QSharedPointer<const LinuxDeviceConfiguration> &deviceConfiguration); + void stopTest(); - void run(); - void cancel(); + QSharedPointer<Utils::SshConnection> connection() const; + +private slots: + void handleConnected(); + void handleConnectionFailure(); + void handleProcessFinished(int exitStatus); + void handlePortsGatheringError(const QString &message); + void handlePortListReady(); private: - RemoteLinuxUsedPortsGatherer *const gatherer; + void setFinished(TestResult result); + + Internal::GenericLinuxDeviceTesterPrivate * const d; }; } // namespace RemoteLinux diff --git a/src/plugins/remotelinux/remotelinux.pro b/src/plugins/remotelinux/remotelinux.pro index 8852d46111..00990e0252 100644 --- a/src/plugins/remotelinux/remotelinux.pro +++ b/src/plugins/remotelinux/remotelinux.pro @@ -9,7 +9,6 @@ HEADERS += \ embeddedlinuxtargetfactory.h \ embeddedlinuxqtversion.h \ embeddedlinuxqtversionfactory.h \ - simplerunner.h \ remotelinuxplugin.h \ remotelinux_export.h \ linuxdeviceconfiguration.h \ @@ -69,7 +68,6 @@ SOURCES += \ embeddedlinuxtargetfactory.cpp \ embeddedlinuxqtversion.cpp \ embeddedlinuxqtversionfactory.cpp \ - simplerunner.cpp \ remotelinuxplugin.cpp \ linuxdeviceconfiguration.cpp \ linuxdeviceconfigurations.cpp \ diff --git a/src/plugins/remotelinux/remotelinuxapplicationrunner.cpp b/src/plugins/remotelinux/remotelinuxapplicationrunner.cpp index d9a77c4e81..c38b29444d 100644 --- a/src/plugins/remotelinux/remotelinuxapplicationrunner.cpp +++ b/src/plugins/remotelinux/remotelinuxapplicationrunner.cpp @@ -62,8 +62,7 @@ class AbstractRemoteLinuxApplicationRunnerPrivate { public: AbstractRemoteLinuxApplicationRunnerPrivate(const RemoteLinuxRunConfiguration *runConfig) - : portsGatherer(runConfig->deviceConfig()), - devConfig(runConfig->deviceConfig()), + : devConfig(runConfig->deviceConfig()), remoteExecutable(runConfig->remoteExecutableFilePath()), appArguments(runConfig->arguments()), commandPrefix(runConfig->commandPrefix()), @@ -168,7 +167,7 @@ void AbstractRemoteLinuxApplicationRunner::stop() emit remoteProcessFinished(InvalidExitCode); break; case GatheringPorts: - d->portsGatherer.cancel(); + d->portsGatherer.stop(); setInactive(); emit remoteProcessFinished(InvalidExitCode); break; @@ -308,7 +307,7 @@ void AbstractRemoteLinuxApplicationRunner::handleRemoteProcessFinished(int exitS void AbstractRemoteLinuxApplicationRunner::setInactive() { - d->portsGatherer.cancel(); + d->portsGatherer.stop(); if (d->connection) { disconnect(d->connection.data(), 0, this, 0); SshConnectionManager::instance().releaseConnection(d->connection); @@ -423,7 +422,7 @@ void AbstractRemoteLinuxApplicationRunner::handleInitialCleanupDone(bool success } d->state = GatheringPorts; - d->portsGatherer.run(); + d->portsGatherer.start(d->connection, d->devConfig); } void AbstractRemoteLinuxApplicationRunner::handleInitializationsDone(bool success) diff --git a/src/plugins/remotelinux/remotelinuxusedportsgatherer.cpp b/src/plugins/remotelinux/remotelinuxusedportsgatherer.cpp index e0d201ddde..a239edfae0 100644 --- a/src/plugins/remotelinux/remotelinuxusedportsgatherer.cpp +++ b/src/plugins/remotelinux/remotelinuxusedportsgatherer.cpp @@ -33,7 +33,6 @@ #include "linuxdeviceconfiguration.h" #include "portlist.h" -#include <utils/ssh/sshconnectionmanager.h> #include <utils/ssh/sshremoteprocessrunner.h> #include <QtCore/QString> @@ -46,32 +45,23 @@ namespace Internal { class RemoteLinuxUsedPortsGathererPrivate { public: - RemoteLinuxUsedPortsGathererPrivate() - { } + RemoteLinuxUsedPortsGathererPrivate() : running(false) {} + SshRemoteProcessRunner procRunner; PortList portsToCheck; QList<int> usedPorts; - QByteArray keepSake; + QByteArray remoteStdout; + QByteArray remoteStderr; + bool running; // TODO: Redundant due to being in sync with procRunner? }; } // namespace Internal using namespace Internal; -RemoteLinuxUsedPortsGatherer::RemoteLinuxUsedPortsGatherer( - const QSharedPointer<const LinuxDeviceConfiguration> &deviceConfiguration) : - SimpleRunner(deviceConfiguration, - // Match - // 0: 0100007F:706E 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 8141 1 ce498900 300 0 0 2 -1 - // and report ^^^^ this local port number - QLatin1String("FILE=/proc/net/tcp ; " - "echo \"$SSH_CONNECTION\" | grep : > /dev/null && FILE=/proc/net/tcp6 ; " - "sed 's/^\\s\\+[0-9a-fA-F]\\+:\\s\\+[0-9a-fA-F]\\+:\\([0-9a-fA-F]\\+\\)\\s.*$/\\1/' $FILE")), - d(new RemoteLinuxUsedPortsGathererPrivate) +RemoteLinuxUsedPortsGatherer::RemoteLinuxUsedPortsGatherer(QObject *parent) : + QObject(parent), d(new RemoteLinuxUsedPortsGathererPrivate) { - d->portsToCheck = deviceConfiguration->freePorts(); - - connect(this, SIGNAL(aboutToStart()), this, SLOT(cleanup())); } RemoteLinuxUsedPortsGatherer::~RemoteLinuxUsedPortsGatherer() @@ -79,6 +69,48 @@ RemoteLinuxUsedPortsGatherer::~RemoteLinuxUsedPortsGatherer() delete d; } +void RemoteLinuxUsedPortsGatherer::start(const Utils::SshConnection::Ptr &connection, + const LinuxDeviceConfiguration::ConstPtr &devConf) +{ + if (d->running) + qWarning("Unexpected call of %s in running state", Q_FUNC_INFO); + d->portsToCheck = devConf->freePorts(); + d->usedPorts.clear(); + d->remoteStdout.clear(); + d->remoteStderr.clear(); + connect(&d->procRunner, SIGNAL(connectionError()), SLOT(handleConnectionError())); + connect(&d->procRunner, SIGNAL(processClosed(int)), SLOT(handleProcessClosed(int))); + connect(&d->procRunner, SIGNAL(processOutputAvailable(QByteArray)), + SLOT(handleRemoteStdOut(QByteArray))); + connect(&d->procRunner, SIGNAL(processErrorOutputAvailable(QByteArray)), + SLOT(handleRemoteStdErr(QByteArray))); + QString procFilePath; + int addressLength; + if (connection->ipProtocolVersion() == QAbstractSocket::IPv4Protocol) { + procFilePath = QLatin1String("/proc/net/tcp"); + addressLength = 8; + } else { + procFilePath = QLatin1String("/proc/net/tcp6"); + addressLength = 32; + } + const QString command = QString::fromLocal8Bit("sed " + "'s/.*: [[:xdigit:]]\\{%1\\}:\\([[:xdigit:]]\\{4\\}\\).*/\\1/g' %2") + .arg(addressLength).arg(procFilePath); + + // TODO: We should not use an SshRemoteProcessRunner here, because we have to check + // for the type of the connection before we can say what the exact command line is. + d->procRunner.run(command.toUtf8(), connection->connectionParameters()); + d->running = true; +} + +void RemoteLinuxUsedPortsGatherer::stop() +{ + if (!d->running) + return; + d->running = false; + disconnect(&d->procRunner, 0, this, 0); +} + int RemoteLinuxUsedPortsGatherer::getNextFreePort(PortList *freePorts) const { while (freePorts->hasMore()) { @@ -94,20 +126,12 @@ QList<int> RemoteLinuxUsedPortsGatherer::usedPorts() const return d->usedPorts; } -void RemoteLinuxUsedPortsGatherer::handleStdOutput(const QByteArray &output) +void RemoteLinuxUsedPortsGatherer::setupUsedPorts() { - QByteArray data = d->keepSake + output; - - // make sure we only process complete lines: - int lastEol = output.lastIndexOf('\n'); - if (lastEol != output.count() - 1) { - d->keepSake = data.mid(lastEol + 1); - data = data.left(lastEol); - } - - QList<QByteArray> portStrings = data.split('\n'); + QList<QByteArray> portStrings = d->remoteStdout.split('\n'); + portStrings.removeFirst(); foreach (const QByteArray &portString, portStrings) { - if (portString.isEmpty() || portString.contains("local_address")) + if (portString.isEmpty()) continue; bool ok; const int port = portString.toInt(&ok, 16); @@ -119,32 +143,61 @@ void RemoteLinuxUsedPortsGatherer::handleStdOutput(const QByteArray &output) Q_FUNC_INFO, portString.data()); } } + emit portListReady(); } -void RemoteLinuxUsedPortsGatherer::cleanup() +void RemoteLinuxUsedPortsGatherer::handleConnectionError() { - d->keepSake.clear(); - d->usedPorts.clear(); + if (!d->running) + return; + emit error(tr("Connection error: %1").arg(d->procRunner.lastConnectionErrorString())); + stop(); } -int RemoteLinuxUsedPortsGatherer::processFinished(int exitStatus) +void RemoteLinuxUsedPortsGatherer::handleProcessClosed(int exitStatus) { - if (!d->keepSake.isEmpty()) { - d->keepSake.append('\n'); - handleStdOutput(d->keepSake); + if (!d->running) + return; + QString errMsg; + switch (exitStatus) { + case SshRemoteProcess::FailedToStart: + errMsg = tr("Could not start remote process: %1") + .arg(d->procRunner.processErrorString()); + break; + case SshRemoteProcess::KilledBySignal: + errMsg = tr("Remote process crashed: %1") + .arg(d->procRunner.processErrorString()); + break; + case SshRemoteProcess::ExitedNormally: + if (d->procRunner.processExitCode() == 0) { + setupUsedPorts(); + } else { + errMsg = tr("Remote process failed; exit code was %1.") + .arg(d->procRunner.processExitCode()); + } + break; + default: + Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid exit status"); } - if (usedPorts().isEmpty()) { - emit progressMessage("All specified ports are available.\n"); - } else { - QString portList; - foreach (const int port, usedPorts()) - portList += QString::number(port) + QLatin1String(", "); - portList.remove(portList.count() - 2, 2); - emit errorMessage(tr("The following specified ports are currently in use: %1\n") - .arg(portList)); + if (!errMsg.isEmpty()) { + if (!d->remoteStderr.isEmpty()) { + errMsg += tr("\nRemote error output was: %1") + .arg(QString::fromUtf8(d->remoteStderr)); + } + emit error(errMsg); } - return SimpleRunner::processFinished(exitStatus); + stop(); +} + +void RemoteLinuxUsedPortsGatherer::handleRemoteStdOut(const QByteArray &output) +{ + d->remoteStdout += output; +} + +void RemoteLinuxUsedPortsGatherer::handleRemoteStdErr(const QByteArray &output) +{ + d->remoteStderr += output; } } // namespace RemoteLinux diff --git a/src/plugins/remotelinux/remotelinuxusedportsgatherer.h b/src/plugins/remotelinux/remotelinuxusedportsgatherer.h index dec6b00669..a5a51362af 100644 --- a/src/plugins/remotelinux/remotelinuxusedportsgatherer.h +++ b/src/plugins/remotelinux/remotelinuxusedportsgatherer.h @@ -33,9 +33,9 @@ #include "remotelinux_export.h" -#include "simplerunner.h" - #include <QtCore/QList> +#include <QtCore/QObject> +#include <QtCore/QSharedPointer> QT_FORWARD_DECLARE_CLASS(QString) @@ -51,28 +51,33 @@ namespace Internal { class RemoteLinuxUsedPortsGathererPrivate; } // namespace Internal -class REMOTELINUX_EXPORT RemoteLinuxUsedPortsGatherer : public SimpleRunner +class REMOTELINUX_EXPORT RemoteLinuxUsedPortsGatherer : public QObject { Q_OBJECT - + Q_DISABLE_COPY(RemoteLinuxUsedPortsGatherer) public: - explicit RemoteLinuxUsedPortsGatherer(const QSharedPointer<const LinuxDeviceConfiguration> &deviceConfiguration); + explicit RemoteLinuxUsedPortsGatherer(QObject *parent = 0); ~RemoteLinuxUsedPortsGatherer(); - + void start(const QSharedPointer<Utils::SshConnection> &connection, + const QSharedPointer<const LinuxDeviceConfiguration> &devConf); + void stop(); int getNextFreePort(PortList *freePorts) const; // returns -1 if no more are left QList<int> usedPorts() const; -protected slots: - void handleStdOutput(const QByteArray &output); - -protected: - int processFinished(int exitStatus); +signals: + void error(const QString &errMsg); + void portListReady(); private slots: - void cleanup(); + void handleConnectionError(); + void handleProcessClosed(int exitStatus); + void handleRemoteStdOut(const QByteArray &output); + void handleRemoteStdErr(const QByteArray &output); private: - Internal::RemoteLinuxUsedPortsGathererPrivate *const d; + void setupUsedPorts(); + + Internal::RemoteLinuxUsedPortsGathererPrivate * const d; }; } // namespace RemoteLinux diff --git a/src/plugins/remotelinux/simplerunner.cpp b/src/plugins/remotelinux/simplerunner.cpp deleted file mode 100644 index cdebd869aa..0000000000 --- a/src/plugins/remotelinux/simplerunner.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** -** GNU Lesser General Public License Usage -** -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this file. -** Please review the following information to ensure the GNU Lesser General -** Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -**************************************************************************/ - -#include "simplerunner.h" - -#include "linuxdeviceconfiguration.h" - -#include <utils/qtcassert.h> -#include <utils/ssh/sshremoteprocessrunner.h> -#include <utils/ssh/sshconnection.h> -#include <utils/ssh/sshconnectionmanager.h> - -using namespace Utils; - -namespace RemoteLinux { -namespace Internal { - -class SimpleRunnerPrivate -{ -public: - SimpleRunnerPrivate() : process(0), sshParameters(Utils::SshConnectionParameters::NoProxy) - { } - - QString commandline; - - SshRemoteProcessRunner *process; - Utils::SshConnectionParameters sshParameters; -}; - -} // namespace Internal - -using namespace Internal; - -SimpleRunner::SimpleRunner(const QSharedPointer<const LinuxDeviceConfiguration> &deviceConfiguration, - const QString &commandline) : - d(new SimpleRunnerPrivate) -{ - QTC_ASSERT(!deviceConfiguration.isNull(), return); - d->commandline = commandline; - d->sshParameters = deviceConfiguration->sshParameters(); -} - -SimpleRunner::~SimpleRunner() -{ - delete d; -} - -QString SimpleRunner::commandLine() const -{ - return d->commandline; -} - -void SimpleRunner::run() -{ - QTC_ASSERT(!d->process, return); - - d->process = new SshRemoteProcessRunner(this); - - connect(d->process, SIGNAL(connectionError()), this, SLOT(handleConnectionFailure())); - connect(d->process, SIGNAL(processClosed(int)), this, SLOT(handleProcessFinished(int))); - connect(d->process, SIGNAL(processOutputAvailable(QByteArray)), this, SLOT(handleStdOutput(QByteArray))); - connect(d->process, SIGNAL(processErrorOutputAvailable(QByteArray)), - this, SLOT(handleStdError(QByteArray))); - - emit aboutToStart(); - d->process->run(d->commandline.toUtf8(), sshParameters()); - emit started(); -} - -void SimpleRunner::cancel() -{ - if (!d->process) - return; - - d->process->cancel(); - emit finished(-1); -} - -void SimpleRunner::handleConnectionFailure() -{ - QTC_ASSERT(d->process, return); - - emit errorMessage(tr("SSH connection failure: %1\n").arg(d->process->lastConnectionErrorString())); - delete d->process; - d->process = 0; - - emit finished(processFinished(SshRemoteProcess::FailedToStart)); -} - -void SimpleRunner::handleProcessFinished(int exitStatus) -{ - emit finished(processFinished(exitStatus)); -} - -void SimpleRunner::handleStdOutput(const QByteArray &data) -{ - if (data.isEmpty()) - return; - emit progressMessage(QString::fromUtf8(data)); -} - -void SimpleRunner::handleStdError(const QByteArray &data) -{ - if (data.isEmpty()) - return; - emit errorMessage(QString::fromUtf8(data)); -} - -int SimpleRunner::processFinished(int exitStatus) -{ - int exitCode = -1; - if (d->process) - exitCode = d->process->processExitCode(); - delete d->process; - d->process = 0; - - return (exitStatus == SshRemoteProcess::ExitedNormally && exitCode == 0) ? 0 : 1; -} - -void SimpleRunner::setCommandLine(const QString &cmd) -{ - QTC_ASSERT(d->commandline.isEmpty(), return); - d->commandline = cmd; -} - -SshConnectionParameters SimpleRunner::sshParameters() const -{ - return d->sshParameters; -} - -} // namespace RemoteLinux diff --git a/src/plugins/remotelinux/simplerunner.h b/src/plugins/remotelinux/simplerunner.h deleted file mode 100644 index 056d19268b..0000000000 --- a/src/plugins/remotelinux/simplerunner.h +++ /dev/null @@ -1,98 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** -** GNU Lesser General Public License Usage -** -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this file. -** Please review the following information to ensure the GNU Lesser General -** Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -**************************************************************************/ - -#ifndef SIMPLERUNNER_H -#define SIMPLERUNNER_H - -#include "remotelinux_export.h" - -#include <utils/ssh/sshconnection.h> - -#include <QtCore/QObject> - -QT_FORWARD_DECLARE_CLASS(QString) - -namespace RemoteLinux { -class LinuxDeviceConfiguration; - -namespace Internal { -class SimpleRunnerPrivate; -} // namespace Internal - -// ----------------------------------------------------------------------- -// SimpleRunner: -// ----------------------------------------------------------------------- - -class REMOTELINUX_EXPORT SimpleRunner : public QObject -{ - Q_OBJECT - -public: - SimpleRunner(const QSharedPointer<const LinuxDeviceConfiguration> &deviceConfiguration, - const QString &commandline); - ~SimpleRunner(); - - virtual QString commandLine() const; - - virtual void run(); - virtual void cancel(); - -signals: - void aboutToStart(); - void started(); - void progressMessage(const QString &message); - void errorMessage(const QString &message); - // 0 on success, other value on failure. - void finished(int result); - -protected slots: - void handleProcessFinished(int exitStatus); - - virtual void handleConnectionFailure(); - virtual void handleStdOutput(const QByteArray &data); - virtual void handleStdError(const QByteArray &data); - - // 0 on success, any other value on failure. - virtual int processFinished(int exitStatus); - -protected: - void setCommandLine(const QString &cmd); - - Utils::SshConnectionParameters sshParameters() const; - -private: - Internal::SimpleRunnerPrivate *const d; -}; - -} // namespace RemoteLinux - -#endif // SIMPLERUNNER_H diff --git a/src/plugins/remotelinux/startgdbserverdialog.cpp b/src/plugins/remotelinux/startgdbserverdialog.cpp index 879815f72c..794fb6135f 100644 --- a/src/plugins/remotelinux/startgdbserverdialog.cpp +++ b/src/plugins/remotelinux/startgdbserverdialog.cpp @@ -103,14 +103,14 @@ public: QPushButton *closeButton; PathChooser *sysrootPathChooser; - RemoteLinuxUsedPortsGatherer *gatherer; + RemoteLinuxUsedPortsGatherer gatherer; SshRemoteProcessRunner runner; QSettings *settings; QString remoteCommandLine; }; StartGdbServerDialogPrivate::StartGdbServerDialogPrivate(StartGdbServerDialog *q) - : q(q), processList(0), gatherer(0), settings(0) + : q(q), processList(0) { settings = ICore::instance()->settings(); @@ -179,6 +179,8 @@ StartGdbServerDialog::StartGdbServerDialog(QWidget *parent) : d->deviceComboBox->setModel(devices); d->deviceComboBox->setCurrentIndex(d->settings->value(LastDevice).toInt()); + connect(&d->gatherer, SIGNAL(error(QString)), SLOT(portGathererError(QString))); + connect(&d->gatherer, SIGNAL(portListReady()), SLOT(portListReady())); if (devices->rowCount() == 0) { d->tableView->setEnabled(false); } else { @@ -213,15 +215,6 @@ StartGdbServerDialog::~StartGdbServerDialog() void StartGdbServerDialog::attachToDevice(int index) { LinuxDeviceConfigurations *devices = LinuxDeviceConfigurations::instance(); - - if (d->gatherer) - delete d->gatherer; - - d->gatherer = new RemoteLinuxUsedPortsGatherer(devices->deviceAt(index)); - connect(d->gatherer, SIGNAL(finished(RemoteLinux::LinuxDeviceTester::TestResult)), - this, SLOT(portListReady(RemoteLinux::LinuxDeviceTester::TestResult))); - connect(d->gatherer, SIGNAL(errorMessage(QString)), SLOT(portGathererError(QString))); - delete d->processList; d->processList = new GenericRemoteLinuxProcessList(devices->deviceAt(index)); d->proxyModel.setSourceModel(d->processList); @@ -257,8 +250,6 @@ void StartGdbServerDialog::updateProcessList() void StartGdbServerDialog::attachToProcess() { - QTC_ASSERT(d->gatherer, return); - const QModelIndexList &indexes = d->tableView->selectionModel()->selectedIndexes(); if (indexes.empty()) @@ -267,7 +258,7 @@ void StartGdbServerDialog::attachToProcess() LinuxDeviceConfiguration::ConstPtr device = d->currentDevice(); PortList ports = device->freePorts(); - const int port = d->gatherer->getNextFreePort(&ports); + const int port = d->gatherer.getNextFreePort(&ports); const int row = d->proxyModel.mapToSource(indexes.first()).row(); QTC_ASSERT(row >= 0, return); const int pid = d->processList->pidAt(row); @@ -321,11 +312,7 @@ void StartGdbServerDialog::portListReady() void StartGdbServerDialog::startGdbServer() { LinuxDeviceConfiguration::ConstPtr device = d->currentDevice(); - if (d->gatherer) - delete d->gatherer; - d->gatherer = new RemoteLinuxUsedPortsGatherer(device); - - d->gatherer->run(); + d->gatherer.start(SshConnection::create(device->sshParameters()), device); } void StartGdbServerDialog::attachToRemoteProcess() |