SSH: Make interface more Qt-ish.

This commit is contained in:
ck
2010-05-10 11:01:56 +02:00
parent 642116e4d2
commit f678fce3a6
6 changed files with 54 additions and 26 deletions

View File

@@ -151,6 +151,9 @@ struct InteractiveSshConnectionPrivate
GenericSshConnection conn; GenericSshConnection conn;
ConnectionOutputReader *outputReader; ConnectionOutputReader *outputReader;
QByteArray remoteOutput;
QMutex mutex;
QWaitCondition waitCond;
}; };
struct NonInteractiveSshConnectionPrivate struct NonInteractiveSshConnectionPrivate
@@ -208,8 +211,12 @@ private:
m_mutex.unlock(); m_mutex.unlock();
QScopedPointer<char, QScopedPointerArrayDeleter<char> > QScopedPointer<char, QScopedPointerArrayDeleter<char> >
output(m_conn->d->conn.ssh->readAndReset(channel, alloc)); output(m_conn->d->conn.ssh->readAndReset(channel, alloc));
if (output) if (output) {
emit m_conn->remoteOutput(QByteArray(output.data())); m_conn->d->mutex.lock();
m_conn->d->remoteOutput += output.data();
emit m_conn->remoteOutputAvailable();
m_conn->d->mutex.unlock();
}
} }
} }
@@ -266,10 +273,25 @@ bool InteractiveSshConnection::sendInput(const QByteArray &input)
void InteractiveSshConnection::quit() void InteractiveSshConnection::quit()
{ {
d->mutex.lock();
d->waitCond.wakeOne();
d->mutex.unlock();
d->outputReader->stop(); d->outputReader->stop();
d->conn.quit(); d->conn.quit();
} }
QByteArray InteractiveSshConnection::waitForRemoteOutput(int msecs)
{
d->mutex.lock();
if (d->remoteOutput.isEmpty())
d->waitCond.wait(&d->mutex, msecs == -1 ? ULONG_MAX : msecs);
const QByteArray remoteOutput = d->remoteOutput;
d->remoteOutput.clear();
d->mutex.unlock();
return remoteOutput;
}
InteractiveSshConnection::Ptr InteractiveSshConnection::create(const SshServerInfo &server) InteractiveSshConnection::Ptr InteractiveSshConnection::create(const SshServerInfo &server)
{ {
return Ptr(new InteractiveSshConnection(server)); return Ptr(new InteractiveSshConnection(server));

View File

@@ -82,12 +82,13 @@ public:
bool start(); bool start();
void quit(); void quit();
bool sendInput(const QByteArray &input); // Should normally end in newline. bool sendInput(const QByteArray &input); // Should normally end in newline.
QByteArray waitForRemoteOutput(int msecs = -1);
bool hasError() const; bool hasError() const;
QString error() const; QString error() const;
~InteractiveSshConnection(); ~InteractiveSshConnection();
signals: signals:
void remoteOutput(const QByteArray &output); void remoteOutputAvailable();
private: private:
InteractiveSshConnection(const SshServerInfo &server); InteractiveSshConnection(const SshServerInfo &server);

View File

@@ -71,12 +71,12 @@ void RemoteGdbProcess::start(const QString &cmd, const QStringList &args)
return; return;
m_command = cmd; m_command = cmd;
m_cmdArgs = args; m_cmdArgs = args;
connect(m_gdbConn.data(), SIGNAL(remoteOutput(QByteArray)), connect(m_gdbConn.data(), SIGNAL(remoteOutputAvailable()),
this, SLOT(handleGdbOutput(QByteArray))); this, SLOT(handleGdbOutput()));
connect(m_appOutputConn.data(), SIGNAL(remoteOutput(QByteArray)), connect(m_appOutputConn.data(), SIGNAL(remoteOutputAvailable()),
this, SLOT(handleAppOutput(QByteArray))); this, SLOT(handleAppOutput()));
connect(m_errOutputConn.data(), SIGNAL(remoteOutput(QByteArray)), connect(m_errOutputConn.data(), SIGNAL(remoteOutputAvailable()),
this, SLOT(handleErrOutput(QByteArray))); this, SLOT(handleErrOutput()));
m_gdbConn->start(); m_gdbConn->start();
m_errOutputConn->start(); m_errOutputConn->start();
m_appOutputConn->start(); m_appOutputConn->start();
@@ -130,7 +130,7 @@ QString RemoteGdbProcess::errorString() const
return m_gdbConn ? m_gdbConn->error() : QString(); return m_gdbConn ? m_gdbConn->error() : QString();
} }
void RemoteGdbProcess::handleGdbOutput(const QByteArray &output) void RemoteGdbProcess::handleGdbOutput()
{ {
#if 0 #if 0
qDebug("%s: output is '%s'", Q_FUNC_INFO, output.data()); qDebug("%s: output is '%s'", Q_FUNC_INFO, output.data());
@@ -139,7 +139,8 @@ void RemoteGdbProcess::handleGdbOutput(const QByteArray &output)
if (m_gdbState == CmdNotYetSent) if (m_gdbState == CmdNotYetSent)
return; return;
m_currentGdbOutput += removeCarriageReturn(output); m_currentGdbOutput
+= removeCarriageReturn(m_gdbConn->waitForRemoteOutput(0));
if (!m_currentGdbOutput.endsWith('\n')) if (!m_currentGdbOutput.endsWith('\n'))
return; return;
@@ -217,15 +218,17 @@ qint64 RemoteGdbProcess::sendInput(const QByteArray &data)
return m_gdbConn->sendInput(data) ? data.size() : 0; return m_gdbConn->sendInput(data) ? data.size() : 0;
} }
void RemoteGdbProcess::handleAppOutput(const QByteArray &output) void RemoteGdbProcess::handleAppOutput()
{ {
const QByteArray output = m_appOutputConn->waitForRemoteOutput(0);
if (!handleAppOrErrOutput(m_appOutputConn, m_appOutputReaderState, if (!handleAppOrErrOutput(m_appOutputConn, m_appOutputReaderState,
m_initialAppOutput, AppOutputFile, output)) m_initialAppOutput, AppOutputFile, output))
m_adapter->handleApplicationOutput(output); m_adapter->handleApplicationOutput(output);
} }
void RemoteGdbProcess::handleErrOutput(const QByteArray &output) void RemoteGdbProcess::handleErrOutput()
{ {
const QByteArray output = m_errOutputConn->waitForRemoteOutput(0);
if (!handleAppOrErrOutput(m_errOutputConn, m_errOutputReaderState, if (!handleAppOrErrOutput(m_errOutputConn, m_errOutputReaderState,
m_initialErrOutput, ErrOutputFile, output)) { m_initialErrOutput, ErrOutputFile, output)) {
m_errorOutput += output; m_errorOutput += output;
@@ -277,14 +280,14 @@ void RemoteGdbProcess::startGdb()
void RemoteGdbProcess::stopReaders() void RemoteGdbProcess::stopReaders()
{ {
if (m_appOutputConn) { if (m_appOutputConn) {
disconnect(m_appOutputConn.data(), SIGNAL(remoteOutput(QByteArray)), disconnect(m_appOutputConn.data(), SIGNAL(remoteOutputAvailable()),
this, SLOT(handleAppOutput(QByteArray))); this, SLOT(handleAppOutput()));
m_appOutputConn->sendInput(CtrlC); m_appOutputConn->sendInput(CtrlC);
m_appOutputConn->quit(); m_appOutputConn->quit();
} }
if (m_errOutputConn) { if (m_errOutputConn) {
disconnect(m_errOutputConn.data(), SIGNAL(remoteOutput(QByteArray)), disconnect(m_errOutputConn.data(), SIGNAL(remoteOutputAvailable()),
this, SLOT(handleErrOutput(QByteArray))); this, SLOT(handleErrOutput()));
m_errOutputConn->sendInput(CtrlC); m_errOutputConn->sendInput(CtrlC);
m_errOutputConn->quit(); m_errOutputConn->quit();
} }
@@ -316,8 +319,8 @@ void RemoteGdbProcess::checkForGdbExit(QByteArray &output)
const QByteArray exitString("^exit"); const QByteArray exitString("^exit");
const int exitPos = output.indexOf(exitString); const int exitPos = output.indexOf(exitString);
if (exitPos != -1) { if (exitPos != -1) {
disconnect(m_gdbConn.data(), SIGNAL(remoteOutput(QByteArray)), disconnect(m_gdbConn.data(), SIGNAL(remoteOutputAvailable()),
this, SLOT(handleGdbOutput(QByteArray))); this, SLOT(handleGdbOutput()));
output.remove(exitPos + exitString.size(), output.size()); output.remove(exitPos + exitString.size(), output.size());
stopReaders(); stopReaders();
emit finished(0, QProcess::NormalExit); emit finished(0, QProcess::NormalExit);

View File

@@ -68,9 +68,9 @@ public:
static const QByteArray CtrlC; static const QByteArray CtrlC;
private slots: private slots:
void handleGdbOutput(const QByteArray &output); void handleGdbOutput();
void handleAppOutput(const QByteArray &output); void handleAppOutput();
void handleErrOutput(const QByteArray &output); void handleErrOutput();
private: private:
enum CmdState { CmdNotYetSent, CmdSent, CmdReceived }; enum CmdState { CmdNotYetSent, CmdSent, CmdReceived };

View File

@@ -102,8 +102,8 @@ MaemoSshRunner::MaemoSshRunner(const Core::SshServerInfo &server,
bool MaemoSshRunner::runInternal() bool MaemoSshRunner::runInternal()
{ {
createConnection(); createConnection();
connect(m_connection.data(), SIGNAL(remoteOutput(QByteArray)), connect(m_connection.data(), SIGNAL(remoteOutputAvailable()),
this, SLOT(handleRemoteOutput(QByteArray))); this, SLOT(handleRemoteOutput()));
m_endMarkerCount = 0; m_endMarkerCount = 0;
m_promptEncountered = false; m_promptEncountered = false;
if (!m_connection->start()) if (!m_connection->start())
@@ -115,8 +115,10 @@ bool MaemoSshRunner::runInternal()
return !m_connection->hasError(); return !m_connection->hasError();
} }
void MaemoSshRunner::handleRemoteOutput(const QByteArray &output) void MaemoSshRunner::handleRemoteOutput()
{ {
const QByteArray output = m_connection->waitForRemoteOutput(0);
// Wait for a prompt before sending the command. // Wait for a prompt before sending the command.
if (!m_promptEncountered) { if (!m_promptEncountered) {
if (output.indexOf(m_prompt) != -1) { if (output.indexOf(m_prompt) != -1) {

View File

@@ -96,7 +96,7 @@ signals:
private: private:
virtual bool runInternal(); virtual bool runInternal();
Q_SLOT void handleRemoteOutput(const QByteArray &output); Q_SLOT void handleRemoteOutput();
static const QByteArray EndMarker; static const QByteArray EndMarker;