/************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (info@qt.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 "maemousedportsgatherer.h" #include "maemoglobal.h" #include using namespace Utils; namespace Qt4ProjectManager { namespace Internal { MaemoUsedPortsGatherer::MaemoUsedPortsGatherer(QObject *parent) : QObject(parent), m_running(false) { } MaemoUsedPortsGatherer::~MaemoUsedPortsGatherer() {} void MaemoUsedPortsGatherer::start(const Utils::SshConnection::Ptr &connection, const MaemoDeviceConfig::ConstPtr &devConf) { if (m_running) qWarning("Unexpected call of %s in running state", Q_FUNC_INFO); m_usedPorts.clear(); m_remoteStdout.clear(); m_remoteStderr.clear(); m_procRunner = SshRemoteProcessRunner::create(connection); connect(m_procRunner.data(), SIGNAL(connectionError(Utils::SshError)), SLOT(handleConnectionError())); connect(m_procRunner.data(), SIGNAL(processClosed(int)), SLOT(handleProcessClosed(int))); connect(m_procRunner.data(), SIGNAL(processOutputAvailable(QByteArray)), SLOT(handleRemoteStdOut(QByteArray))); connect(m_procRunner.data(), SIGNAL(processErrorOutputAvailable(QByteArray)), SLOT(handleRemoteStdErr(QByteArray))); const QString command = MaemoGlobal::remoteSudo(devConf->osVersion(), m_procRunner->connection()->connectionParameters().userName) + QLatin1String(" lsof -nPi4tcp:") + devConf->freePorts().toString() + QLatin1String(" -F n |grep '^n' |sed -r 's/[^:]*:([[:digit:]]+).*/\\1/g' |sort -n |uniq"); m_procRunner->run(command.toUtf8()); m_running = true; } void MaemoUsedPortsGatherer::stop() { if (!m_running) return; m_running = false; disconnect(m_procRunner->connection().data(), 0, this, 0); if (m_procRunner->process()) m_procRunner->process()->closeChannel(); } int MaemoUsedPortsGatherer::getNextFreePort(MaemoPortList *freePorts) const { while (freePorts->hasMore()) { const int port = freePorts->getNext(); if (!m_usedPorts.contains(port)) return port; } return -1; } void MaemoUsedPortsGatherer::setupUsedPorts() { const QList &portStrings = m_remoteStdout.split('\n'); foreach (const QByteArray &portString, portStrings) { if (portString.isEmpty()) continue; bool ok; const int port = portString.toInt(&ok); if (ok) { m_usedPorts << port; } else { qWarning("%s: Unexpected string '%s' is not a port.", Q_FUNC_INFO, portString.data()); } } emit portListReady(); } void MaemoUsedPortsGatherer::handleConnectionError() { if (!m_running) return; emit error(tr("Connection error: %1"). arg(m_procRunner->connection()->errorString())); stop(); } void MaemoUsedPortsGatherer::handleProcessClosed(int exitStatus) { if (!m_running) return; QString errMsg; switch (exitStatus) { case SshRemoteProcess::FailedToStart: errMsg = tr("Could not start remote process: %1") .arg(m_procRunner->process()->errorString()); break; case SshRemoteProcess::KilledBySignal: errMsg = tr("Remote process crashed: %1") .arg(m_procRunner->process()->errorString()); break; case SshRemoteProcess::ExitedNormally: if (m_procRunner->process()->exitCode() == 0) { setupUsedPorts(); } else { errMsg = tr("Remote process failed: %1") .arg(m_procRunner->process()->errorString()); } break; default: Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid exit status"); } if (!errMsg.isEmpty()) { if (!m_remoteStderr.isEmpty()) { errMsg += tr("\nRemote error output was: %1") .arg(QString::fromUtf8(m_remoteStderr)); } emit error(errMsg); } stop(); } void MaemoUsedPortsGatherer::handleRemoteStdOut(const QByteArray &output) { m_remoteStdout += output; } void MaemoUsedPortsGatherer::handleRemoteStdErr(const QByteArray &output) { m_remoteStderr += output; } } // namespace Internal } // namespace Qt4ProjectManager