RemoteLinux: Fix ports gatherer API.

The ports gatherer used to take an SshConnection for historical reasons
(connection sharing in the absence of a connection manager). This is no
longer required, since all the information needed for creating or
re-using a connection is available from the device.
In addition, the old code assumes the connection is already established,
which some newer callers did not adhere to, so this patch also fixes a
bug.

Change-Id: I3fd7fec7de9b64126358749f727a403bfa1e0a94
Reviewed-by: Nikolai Kosjar <nikolai.kosjar@nokia.com>
This commit is contained in:
Christian Kandeler
2012-04-03 10:23:59 +02:00
parent 23a420eb3f
commit 1348e92971
6 changed files with 62 additions and 57 deletions

View File

@@ -142,7 +142,7 @@ void MaemoDeploymentMounter::handleUnmounted()
break; break;
case UnmountingCurrentDirs: case UnmountingCurrentDirs:
setState(GatheringPorts); setState(GatheringPorts);
m_portsGatherer->start(m_connection, m_devConf); m_portsGatherer->start(m_devConf);
break; break;
case UnmountingCurrentMounts: case UnmountingCurrentMounts:
setState(Inactive); setState(Inactive);

View File

@@ -159,7 +159,7 @@ void GenericLinuxDeviceTester::handleProcessFinished(int exitStatus)
emit progressMessage(tr("Checking if specified ports are available...")); emit progressMessage(tr("Checking if specified ports are available..."));
d->state = TestingPorts; d->state = TestingPorts;
d->portsGatherer.start(d->connection, d->deviceConfiguration); d->portsGatherer.start(d->deviceConfiguration);
} }
void GenericLinuxDeviceTester::handlePortsGatheringError(const QString &message) void GenericLinuxDeviceTester::handlePortsGatheringError(const QString &message)

View File

@@ -422,7 +422,7 @@ void AbstractRemoteLinuxApplicationRunner::handleInitialCleanupDone(bool success
} }
d->state = GatheringPorts; d->state = GatheringPorts;
d->portsGatherer.start(d->connection, d->devConfig); d->portsGatherer.start(d->devConfig);
} }
void AbstractRemoteLinuxApplicationRunner::handleInitializationsDone(bool success) void AbstractRemoteLinuxApplicationRunner::handleInitializationsDone(bool success)

View File

@@ -33,7 +33,10 @@
#include "linuxdeviceconfiguration.h" #include "linuxdeviceconfiguration.h"
#include <utils/portlist.h> #include <utils/portlist.h>
#include <utils/ssh/sshremoteprocessrunner.h> #include <utils/qtcassert.h>
#include <utils/ssh/sshconnection.h>
#include <utils/ssh/sshconnectionmanager.h>
#include <utils/ssh/sshremoteprocess.h>
#include <QString> #include <QString>
@@ -45,14 +48,12 @@ namespace Internal {
class RemoteLinuxUsedPortsGathererPrivate class RemoteLinuxUsedPortsGathererPrivate
{ {
public: public:
RemoteLinuxUsedPortsGathererPrivate() : running(false) {} SshConnection::Ptr connection;
SshRemoteProcess::Ptr process;
SshRemoteProcessRunner procRunner;
PortList portsToCheck; PortList portsToCheck;
QList<int> usedPorts; QList<int> usedPorts;
QByteArray remoteStdout; QByteArray remoteStdout;
QByteArray remoteStderr; QByteArray remoteStderr;
bool running; // TODO: Redundant due to being in sync with procRunner?
}; };
} // namespace Internal } // namespace Internal
@@ -69,24 +70,26 @@ RemoteLinuxUsedPortsGatherer::~RemoteLinuxUsedPortsGatherer()
delete d; delete d;
} }
void RemoteLinuxUsedPortsGatherer::start(const Utils::SshConnection::Ptr &connection, void RemoteLinuxUsedPortsGatherer::start(const LinuxDeviceConfiguration::ConstPtr &devConf)
const LinuxDeviceConfiguration::ConstPtr &devConf)
{ {
if (d->running) QTC_ASSERT(!d->connection, return);
qWarning("Unexpected call of %s in running state", Q_FUNC_INFO);
d->portsToCheck = devConf->freePorts(); d->portsToCheck = devConf->freePorts();
d->usedPorts.clear(); d->connection = SshConnectionManager::instance().acquireConnection(devConf->sshParameters());
d->remoteStdout.clear(); connect(d->connection.data(), SIGNAL(error(Utils::SshError)), SLOT(handleConnectionError()));
d->remoteStderr.clear(); if (d->connection->state() == SshConnection::Connected) {
connect(&d->procRunner, SIGNAL(connectionError()), SLOT(handleConnectionError())); handleConnectionEstablished();
connect(&d->procRunner, SIGNAL(processClosed(int)), SLOT(handleProcessClosed(int))); return;
connect(&d->procRunner, SIGNAL(processOutputAvailable(QByteArray)), }
SLOT(handleRemoteStdOut(QByteArray))); connect(d->connection.data(), SIGNAL(connected()), SLOT(handleConnectionEstablished()));
connect(&d->procRunner, SIGNAL(processErrorOutputAvailable(QByteArray)), if (d->connection->state() == SshConnection::Unconnected)
SLOT(handleRemoteStdErr(QByteArray))); d->connection->connectToHost();
}
void RemoteLinuxUsedPortsGatherer::handleConnectionEstablished()
{
QString procFilePath; QString procFilePath;
int addressLength; int addressLength;
if (connection->connectionInfo().localAddress.protocol() == QAbstractSocket::IPv4Protocol) { if (d->connection->connectionInfo().localAddress.protocol() == QAbstractSocket::IPv4Protocol) {
procFilePath = QLatin1String("/proc/net/tcp"); procFilePath = QLatin1String("/proc/net/tcp");
addressLength = 8; addressLength = 8;
} else { } else {
@@ -96,19 +99,28 @@ void RemoteLinuxUsedPortsGatherer::start(const Utils::SshConnection::Ptr &connec
const QString command = QString::fromLatin1("sed " const QString command = QString::fromLatin1("sed "
"'s/.*: [[:xdigit:]]\\{%1\\}:\\([[:xdigit:]]\\{4\\}\\).*/\\1/g' %2") "'s/.*: [[:xdigit:]]\\{%1\\}:\\([[:xdigit:]]\\{4\\}\\).*/\\1/g' %2")
.arg(addressLength).arg(procFilePath); .arg(addressLength).arg(procFilePath);
d->process = d->connection->createRemoteProcess(command.toUtf8());
// TODO: We should not use an SshRemoteProcessRunner here, because we have to check connect(d->process.data(), SIGNAL(closed(int)), SLOT(handleProcessClosed(int)));
// for the type of the connection before we can say what the exact command line is. connect(d->process.data(), SIGNAL(readyReadStandardOutput()), SLOT(handleRemoteStdOut()));
d->procRunner.run(command.toUtf8(), connection->connectionParameters()); connect(d->process.data(), SIGNAL(readyReadStandardError()), SLOT(handleRemoteStdErr()));
d->running = true;
d->process->start();
} }
void RemoteLinuxUsedPortsGatherer::stop() void RemoteLinuxUsedPortsGatherer::stop()
{ {
if (!d->running) if (!d->connection)
return; return;
d->running = false; d->usedPorts.clear();
disconnect(&d->procRunner, 0, this, 0); d->remoteStdout.clear();
d->remoteStderr.clear();
if (d->process)
disconnect(d->process.data(), 0, this, 0);
d->process.clear();
disconnect(d->connection.data(), 0, this, 0);
SshConnectionManager::instance().releaseConnection(d->connection);
d->connection.clear();
} }
int RemoteLinuxUsedPortsGatherer::getNextFreePort(PortList *freePorts) const int RemoteLinuxUsedPortsGatherer::getNextFreePort(PortList *freePorts) const
@@ -148,33 +160,29 @@ void RemoteLinuxUsedPortsGatherer::setupUsedPorts()
void RemoteLinuxUsedPortsGatherer::handleConnectionError() void RemoteLinuxUsedPortsGatherer::handleConnectionError()
{ {
if (!d->running) if (!d->connection)
return; return;
emit error(tr("Connection error: %1").arg(d->procRunner.lastConnectionErrorString())); emit error(tr("Connection error: %1").arg(d->connection->errorString()));
stop(); stop();
} }
void RemoteLinuxUsedPortsGatherer::handleProcessClosed(int exitStatus) void RemoteLinuxUsedPortsGatherer::handleProcessClosed(int exitStatus)
{ {
if (!d->running) if (!d->connection)
return; return;
QString errMsg; QString errMsg;
switch (exitStatus) { switch (exitStatus) {
case SshRemoteProcess::FailedToStart: case SshRemoteProcess::FailedToStart:
errMsg = tr("Could not start remote process: %1") errMsg = tr("Could not start remote process: %1").arg(d->process->errorString());
.arg(d->procRunner.processErrorString());
break; break;
case SshRemoteProcess::KilledBySignal: case SshRemoteProcess::KilledBySignal:
errMsg = tr("Remote process crashed: %1") errMsg = tr("Remote process crashed: %1").arg(d->process->errorString());
.arg(d->procRunner.processErrorString());
break; break;
case SshRemoteProcess::ExitedNormally: case SshRemoteProcess::ExitedNormally:
if (d->procRunner.processExitCode() == 0) { if (d->process->exitCode() == 0)
setupUsedPorts(); setupUsedPorts();
} else { else
errMsg = tr("Remote process failed; exit code was %1.") errMsg = tr("Remote process failed; exit code was %1.").arg(d->process->exitCode());
.arg(d->procRunner.processExitCode());
}
break; break;
default: default:
Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid exit status"); Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid exit status");
@@ -190,14 +198,16 @@ void RemoteLinuxUsedPortsGatherer::handleProcessClosed(int exitStatus)
stop(); stop();
} }
void RemoteLinuxUsedPortsGatherer::handleRemoteStdOut(const QByteArray &output) void RemoteLinuxUsedPortsGatherer::handleRemoteStdOut()
{ {
d->remoteStdout += output; if (d->process)
d->remoteStdout += d->process->readAllStandardOutput();
} }
void RemoteLinuxUsedPortsGatherer::handleRemoteStdErr(const QByteArray &output) void RemoteLinuxUsedPortsGatherer::handleRemoteStdErr()
{ {
d->remoteStderr += output; if (d->process)
d->remoteStderr += d->process->readAllStandardError();
} }
} // namespace RemoteLinux } // namespace RemoteLinux

View File

@@ -39,10 +39,7 @@
QT_FORWARD_DECLARE_CLASS(QString) QT_FORWARD_DECLARE_CLASS(QString)
namespace Utils { namespace Utils { class PortList; }
class PortList;
class SshConnection;
} // namespace Utils
namespace RemoteLinux { namespace RemoteLinux {
class LinuxDeviceConfiguration; class LinuxDeviceConfiguration;
@@ -58,8 +55,7 @@ class REMOTELINUX_EXPORT RemoteLinuxUsedPortsGatherer : public QObject
public: public:
explicit RemoteLinuxUsedPortsGatherer(QObject *parent = 0); explicit RemoteLinuxUsedPortsGatherer(QObject *parent = 0);
~RemoteLinuxUsedPortsGatherer(); ~RemoteLinuxUsedPortsGatherer();
void start(const QSharedPointer<Utils::SshConnection> &connection, void start(const QSharedPointer<const LinuxDeviceConfiguration> &devConf);
const QSharedPointer<const LinuxDeviceConfiguration> &devConf);
void stop(); void stop();
int getNextFreePort(Utils::PortList *freePorts) const; // returns -1 if no more are left int getNextFreePort(Utils::PortList *freePorts) const; // returns -1 if no more are left
QList<int> usedPorts() const; QList<int> usedPorts() const;
@@ -69,10 +65,11 @@ signals:
void portListReady(); void portListReady();
private slots: private slots:
void handleConnectionEstablished();
void handleConnectionError(); void handleConnectionError();
void handleProcessClosed(int exitStatus); void handleProcessClosed(int exitStatus);
void handleRemoteStdOut(const QByteArray &output); void handleRemoteStdOut();
void handleRemoteStdErr(const QByteArray &output); void handleRemoteStdErr();
private: private:
void setupUsedPorts(); void setupUsedPorts();

View File

@@ -325,8 +325,7 @@ void StartGdbServerDialog::startGdbServer()
d->startServerOnly = true; d->startServerOnly = true;
if (exec() == QDialog::Rejected) if (exec() == QDialog::Rejected)
return; return;
LinuxDeviceConfiguration::ConstPtr device = d->currentDevice(); d->gatherer.start(d->currentDevice());
d->gatherer.start(SshConnection::create(device->sshParameters()), device);
} }
void StartGdbServerDialog::attachToRemoteProcess() void StartGdbServerDialog::attachToRemoteProcess()
@@ -334,8 +333,7 @@ void StartGdbServerDialog::attachToRemoteProcess()
d->startServerOnly = false; d->startServerOnly = false;
if (exec() == QDialog::Rejected) if (exec() == QDialog::Rejected)
return; return;
LinuxDeviceConfiguration::ConstPtr device = d->currentDevice(); d->gatherer.start(d->currentDevice());
d->gatherer.start(SshConnection::create(device->sshParameters()), device);
} }
void StartGdbServerDialog::handleConnectionError() void StartGdbServerDialog::handleConnectionError()