From 1cba566ca3b7ad60adbb43208f0dba62781c156b Mon Sep 17 00:00:00 2001
From: Friedemann Kleint <Friedemann.Kleint@nokia.com>
Date: Mon, 6 Dec 2010 13:52:47 +0100
Subject: [PATCH] Symbian: Start on a test client for CODA.

---
 tests/tools/codaclient/codaclient.pro         |  12 +
 .../codaclient/codaclientapplication.cpp      | 321 ++++++++++++++++++
 .../tools/codaclient/codaclientapplication.h  |  84 +++++
 tests/tools/codaclient/main.cpp               |  55 +++
 tests/tools/tools.pro                         |   3 +-
 5 files changed, 474 insertions(+), 1 deletion(-)
 create mode 100644 tests/tools/codaclient/codaclient.pro
 create mode 100644 tests/tools/codaclient/codaclientapplication.cpp
 create mode 100644 tests/tools/codaclient/codaclientapplication.h
 create mode 100644 tests/tools/codaclient/main.cpp

diff --git a/tests/tools/codaclient/codaclient.pro b/tests/tools/codaclient/codaclient.pro
new file mode 100644
index 0000000000..0744400300
--- /dev/null
+++ b/tests/tools/codaclient/codaclient.pro
@@ -0,0 +1,12 @@
+DEFINES += SYMBIANUTILS_INCLUDE_PRI
+include(../../../src/shared/symbianutils/symbianutils.pri)
+
+QT       += core gui network
+TARGET = codaclient
+TEMPLATE = app
+CONFIG += console
+
+SOURCES += main.cpp \
+    codaclientapplication.cpp
+
+HEADERS  += codaclientapplication.h
diff --git a/tests/tools/codaclient/codaclientapplication.cpp b/tests/tools/codaclient/codaclientapplication.cpp
new file mode 100644
index 0000000000..f06c37241e
--- /dev/null
+++ b/tests/tools/codaclient/codaclientapplication.cpp
@@ -0,0 +1,321 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "codaclientapplication.h"
+
+#include "tcftrkdevice.h"
+#include <QtNetwork/QTcpSocket>
+
+#include <cstdio>
+
+static const char usageC[] =
+"\n%1 v0.1 built "__DATE__"\n\n"
+"Test client for Symbian CODA\n\n"
+"Usage:\n"
+"%1 launch [-d] address:port binary uid [--] [arguments]\n"
+"%1 install     address:port sis-file targetdrive\n"
+"%1 copy        address:port local-file remote-file\n"
+"\nOptions:\n"
+"-d            Launch under Debug control\n";
+
+static const unsigned short defaultPort = 65029;
+
+static inline QString fixSlashes(QString s)
+{
+    s.replace(QLatin1Char('/'), QLatin1Char('\\'));
+    return s;
+}
+
+CodaClientApplication::CodaClientApplication(int &argc, char **argv) :
+    QCoreApplication(argc, argv),
+    m_mode(Invalid),
+    m_port(defaultPort),
+    m_launchUID(0),
+    m_launchDebug(false),
+    m_installTargetDrive(QLatin1String("C:")),
+    m_verbose(0)
+{
+    setApplicationName(QLatin1String("codaclient"));
+}
+
+CodaClientApplication::~CodaClientApplication()
+{
+}
+
+QString CodaClientApplication::usage()
+{
+    return QString::fromLatin1(usageC)
+            .arg(QCoreApplication::applicationName());
+}
+
+static inline CodaClientApplication::Mode modeArg(const QString &a)
+{
+    if (a == QLatin1String("launch"))
+        return CodaClientApplication::Launch;
+    if (a == QLatin1String("install"))
+        return CodaClientApplication::Install;
+    if (a == QLatin1String("copy"))
+        return CodaClientApplication::Copy;
+    return CodaClientApplication::Invalid;
+}
+
+bool CodaClientApplication::parseArgument(const QString &a, int argNumber, QString *errorMessage)
+{
+    switch (argNumber) {
+    case 1:
+        m_mode = modeArg(a);
+        if (m_mode == Invalid) {
+            *errorMessage = QLatin1String("Invalid mode");
+            return false;
+        }
+        return true;
+    case 2:  { // Address/port
+        m_address = a;
+        const int colonPos = m_address.indexOf(':');
+        if (colonPos != -1) {
+            m_port = m_address.mid(colonPos + 1).toUInt();
+            m_address.truncate(colonPos);
+        }
+    }
+        break;
+    case 3:
+        switch (m_mode) {
+        case Launch:
+            m_launchBinary = fixSlashes(a);
+            break;
+        case Install:
+            m_installSisFile = a;
+            break;
+        case Copy:
+            m_copyLocalFile = a;
+            break;
+        default:
+            break;
+        }
+        return true;
+    case 4:
+        switch (m_mode) {
+        case Launch:
+            m_launchUID = a.toUInt(0, 0);
+            if (!m_launchUID) {
+                *errorMessage = QLatin1String("Invalid UID");
+                return false;
+            }
+            break;
+        case Install:
+            m_installTargetDrive = a;
+            break;
+        case Copy:
+            m_copyRemoteFile = fixSlashes(a);
+            break;
+        default:
+            break;
+        }
+        return true;
+
+    default:
+        if (m_mode == Launch)
+            m_launchArgs.push_back(a);
+        break;
+    }
+    return true;
+}
+
+CodaClientApplication::ParseArgsResult CodaClientApplication::parseArguments(QString *errorMessage)
+{
+    int argNumber = 1;
+    const QStringList args = QCoreApplication::arguments();
+    const QStringList::const_iterator cend = args.constEnd();
+    QStringList::const_iterator it = args.constBegin();
+    bool optionsEnd = false;
+    for (++it; it != cend; ++it) {
+        if (!optionsEnd  && *it == QLatin1String("--")) {
+            optionsEnd = true;
+            continue;
+        }
+        if (!optionsEnd &&  it->startsWith(QLatin1Char('-')) && it->size() == 2) {
+            switch (it->at(1).toAscii()) {
+            case 'v':
+                m_verbose++;
+                break;
+            case 'd':
+                m_launchDebug = true;
+                break;
+            default:
+                *errorMessage = QString::fromLatin1("Invalid option %1").arg(*it);
+                return ParseArgsError;
+            }
+        } else {
+            if (!parseArgument(*it, argNumber++, errorMessage))
+                return ParseArgsError;
+        }
+    } //for loop
+    // Basic Check & init
+    switch (m_mode) {
+    case Invalid:
+        return ParseArgsError;
+    case Launch:
+        if (m_address.isEmpty() || !m_launchUID || m_launchBinary.isEmpty()) {
+            *errorMessage = QString::fromLatin1("Not enough parameters for launch.");
+            return ParseInitError;
+        }
+        break;
+    case Install:
+        if (m_address.isEmpty() || m_installSisFile.isEmpty()) {
+            *errorMessage = QString::fromLatin1("Not enough parameters for install.");
+            return ParseInitError;
+        }
+        break;
+    case Copy:
+        if (m_address.isEmpty() || m_copyLocalFile.isEmpty() || m_copyRemoteFile.isEmpty()) {
+            *errorMessage = QString::fromLatin1("Not enough parameters for copy.");
+            return ParseInitError;
+        }
+        break;
+    default:
+        break;
+    }
+    return ParseArgsOk;
+}
+
+bool CodaClientApplication::start()
+{
+    switch (m_mode) {
+    case Launch: {
+        const QString args = m_launchArgs.join(QString(QLatin1Char(' ')));
+        std::printf("Launching 0x%x '%s '%s' on %s:%hu (debug: %d)\n",
+                    m_launchUID, qPrintable(m_launchBinary),
+                    qPrintable(args), qPrintable(m_address), m_port,
+                    m_launchDebug);
+    }
+        break;
+    case Install:
+        std::printf("Installing '%s' to '%s' on %s:%hu\n",
+                    qPrintable(m_installSisFile), qPrintable(m_installTargetDrive),
+                    qPrintable(m_address), m_port);
+        break;
+    case Copy:
+        std::printf("Copying '%s' to '%s' on %s:%hu\n",
+                    qPrintable(m_copyLocalFile), qPrintable(m_copyRemoteFile),
+                    qPrintable(m_address), m_port);
+        break;
+    case Invalid:
+        break;
+    }
+    // Start connection
+    const QSharedPointer<QTcpSocket> tcfTrkSocket(new QTcpSocket);
+    m_trkDevice.reset(new tcftrk::TcfTrkDevice);
+    m_trkDevice->setVerbose(m_verbose);
+    connect(m_trkDevice.data(), SIGNAL(error(QString)),
+        this, SLOT(slotError(QString)));
+    connect(m_trkDevice.data(), SIGNAL(logMessage(QString)),
+        this, SLOT(slotTrkLogMessage(QString)));
+    connect(m_trkDevice.data(), SIGNAL(tcfEvent(tcftrk::TcfTrkEvent)),
+        this, SLOT(slotTcftrkEvent(tcftrk::TcfTrkEvent)));
+    m_trkDevice->setDevice(tcfTrkSocket);
+    tcfTrkSocket->connectToHost(m_address, m_port);
+    std::printf("Connecting...\n");
+    return true;
+}
+
+void CodaClientApplication::slotError(const QString &e)
+{
+    std::fprintf(stderr, "Error: %s\n", qPrintable(e));
+    doExit(-1);
+}
+
+void CodaClientApplication::slotTrkLogMessage(const QString &m)
+{
+    std::printf("%s\n", qPrintable(m));
+}
+
+void CodaClientApplication::handleCreateProcess(const tcftrk::TcfTrkCommandResult &result)
+{
+    const bool ok = result.type == tcftrk::TcfTrkCommandResult::SuccessReply;
+    if (ok) {
+        std::printf("Launch succeeded: %s\n", qPrintable(result.toString()));
+        if (!m_launchDebug)
+            doExit(0);
+    } else {
+        std::fprintf(stderr, "Launch failed: %s\n", qPrintable(result.toString()));
+        doExit(-1);
+    }
+}
+
+void CodaClientApplication::slotTcftrkEvent (const tcftrk::TcfTrkEvent &ev)
+{
+    std::printf("Event: %s\n", qPrintable(ev.toString()));
+    switch (ev.type()) {
+    case tcftrk::TcfTrkEvent::LocatorHello: // Commands accepted now
+        switch (m_mode) {
+        case Launch:
+            m_trkDevice->sendProcessStartCommand(tcftrk::TcfTrkCallback(this, &CodaClientApplication::handleCreateProcess),
+                                                 m_launchBinary, m_launchUID, m_launchArgs, QString(), m_launchDebug);
+            break;
+        case Install:
+            break;
+        case Copy:
+            break;
+        case Invalid:
+            break;
+        }
+        break;
+    case tcftrk::TcfTrkEvent::RunControlModuleLoadSuspended:  {
+        // Debug mode start: Continue:
+        const tcftrk::TcfTrkRunControlModuleLoadContextSuspendedEvent &me =
+                static_cast<const tcftrk::TcfTrkRunControlModuleLoadContextSuspendedEvent &>(ev);
+        if (me.info().requireResume) {
+            std::printf("Continuing...\n");
+            m_trkDevice->sendRunControlResumeCommand(tcftrk::TcfTrkCallback(), me.id());
+        }
+    }
+        break;
+    case tcftrk::TcfTrkEvent::RunControlContextRemoved: // App terminated in debug mode
+        doExit(0);
+        break;
+    default:
+        break;
+    }
+}
+
+void CodaClientApplication::doExit(int ex)
+{
+    if (!m_trkDevice.isNull()) {
+        const QSharedPointer<QIODevice> dev = m_trkDevice->device();
+        if (QAbstractSocket *socket = qobject_cast<QAbstractSocket *>(dev.data())) {
+            if (socket->state() == QAbstractSocket::ConnectedState)
+                socket->disconnectFromHost();
+        } else {
+            if (dev->isOpen())
+                dev->close();
+        }
+    }
+    std::printf("Exiting (%d)\n", ex);
+    exit(ex);
+}
diff --git a/tests/tools/codaclient/codaclientapplication.h b/tests/tools/codaclient/codaclientapplication.h
new file mode 100644
index 0000000000..cbe7a37b16
--- /dev/null
+++ b/tests/tools/codaclient/codaclientapplication.h
@@ -0,0 +1,84 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef CODACLIENTAPPLICATION_H
+#define CODACLIENTAPPLICATION_H
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QStringList>
+#include <QtCore/QSharedPointer>
+
+namespace tcftrk {
+    struct TcfTrkCommandResult;
+    class TcfTrkDevice;
+    class TcfTrkEvent;
+}
+
+class CodaClientApplication : public QCoreApplication
+{
+    Q_OBJECT
+public:
+    enum Mode { Invalid, Launch, Copy, Install };
+
+    explicit CodaClientApplication(int &argc, char **argv);
+    ~CodaClientApplication();
+
+    enum ParseArgsResult { ParseArgsOk, ParseArgsError, ParseInitError, ParseArgsHelp };
+    ParseArgsResult parseArguments(QString *errorMessage);
+
+    bool start();
+
+    static QString usage();
+
+private slots:
+    void slotError(const QString &);
+    void slotTrkLogMessage(const QString &);
+    void slotTcftrkEvent(const tcftrk::TcfTrkEvent &);
+
+private:
+    bool parseArgument(const QString &a, int argNumber, QString *errorMessage);
+    void handleCreateProcess(const tcftrk::TcfTrkCommandResult &result);
+    void doExit(int ex);
+
+    Mode m_mode;
+    QString m_address;
+    unsigned short m_port;
+    QString m_launchBinary;
+    QStringList m_launchArgs;
+    unsigned m_launchUID;
+    bool m_launchDebug;
+    QString m_installSisFile;
+    QString m_installTargetDrive;
+    QString m_copyLocalFile;
+    QString m_copyRemoteFile;
+    unsigned m_verbose;
+    QScopedPointer<tcftrk::TcfTrkDevice> m_trkDevice;
+};
+
+#endif // CODACLIENTAPPLICATION_H
diff --git a/tests/tools/codaclient/main.cpp b/tests/tools/codaclient/main.cpp
new file mode 100644
index 0000000000..1b3bc8319c
--- /dev/null
+++ b/tests/tools/codaclient/main.cpp
@@ -0,0 +1,55 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "codaclientapplication.h"
+
+#include <cstdio>
+
+int main(int argc, char *argv[])
+{
+    CodaClientApplication app(argc, argv);
+
+    QString errorMessage;
+    const CodaClientApplication::ParseArgsResult ar = app.parseArguments(&errorMessage);
+    if (!errorMessage.isEmpty())
+        std::fprintf(stderr, "\nError: %s\n\n", qPrintable(errorMessage));
+    switch (ar) {
+    case CodaClientApplication::ParseArgsError:
+        std::printf("%s", qPrintable(CodaClientApplication::usage()));
+        return -1;
+    case CodaClientApplication::ParseArgsHelp:
+        std::printf("%s", qPrintable(CodaClientApplication::usage()));
+        return 0;
+    case CodaClientApplication::ParseInitError:
+        return -1;
+    case CodaClientApplication::ParseArgsOk:
+        break;
+    }
+    return app.start() ? app.exec() : 0;
+}
diff --git a/tests/tools/tools.pro b/tests/tools/tools.pro
index f3040fe923..81a1a0d710 100644
--- a/tests/tools/tools.pro
+++ b/tests/tools/tools.pro
@@ -3,4 +3,5 @@ TEMPLATE=subdirs
 SUBDIRS= \
 trklauncher \
 cplusplus-dump \
-qml-ast2dot
+qml-ast2dot \
+codaclient
-- 
GitLab