QDeclarativeDebug: Allow reconnects to QML debugger port
authorKai Koehne <kai.koehne@nokia.com>
Mon, 19 Sep 2011 10:29:10 +0000 (12:29 +0200)
committerQt by Nokia <qt-info@nokia.com>
Tue, 20 Sep 2011 06:47:27 +0000 (08:47 +0200)
Allow a new client to attach once the old one was disconnected.
Done by Aurindam Jana.

Change-Id: Id85045204cc011ec6e02db2658173e652b75c07e
Reviewed-on: http://codereview.qt-project.org/5132
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Aurindam Jana <aurindam.jana@nokia.com>

src/declarative/debugger/qdeclarativedebugserver.cpp
src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp
tests/auto/declarative/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp

index 883e1a8..f815f33 100644 (file)
@@ -243,75 +243,66 @@ void QDeclarativeDebugServer::receiveMessage(const QByteArray &message)
     Q_D(QDeclarativeDebugServer);
 
     QDataStream in(message);
-    if (!d->gotHello) {
-        QString name;
-        int op;
-        in >> name >> op;
-
-        if (name != QLatin1String("QDeclarativeDebugServer")
-                || op != 0) {
-            qWarning("QDeclarativeDebugServer: Invalid hello message");
-            d->connection->disconnect();
-            return;
-        }
-
-        int version;
-        in >> version >> d->clientPlugins;
-
-        // Send the hello answer immediately, since it needs to arrive before
-        // the plugins below start sending messages.
-        QByteArray helloAnswer;
-        {
-            QDataStream out(&helloAnswer, QIODevice::WriteOnly);
-            out << QString(QLatin1String("QDeclarativeDebugClient")) << 0 << protocolVersion << d->plugins.keys();
-        }
-        d->connection->send(helloAnswer);
-
-        d->gotHello = true;
-
-        QHash<QString, QDeclarativeDebugService*>::Iterator iter = d->plugins.begin();
-        for (; iter != d->plugins.end(); ++iter) {
-            QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::Unavailable;
-            if (d->clientPlugins.contains(iter.key()))
-                newStatus = QDeclarativeDebugService::Enabled;
-            iter.value()->d_func()->status = newStatus;
-            iter.value()->statusChanged(newStatus);
-        }
+    QString name;
+
+    in >> name;
+    if (name == QLatin1String("QDeclarativeDebugServer")) {
+        int op = -1;
+        in >> op;
+        if (op == 0) {
+            int version;
+            in >> version >> d->clientPlugins;
+
+            // Send the hello answer immediately, since it needs to arrive before
+            // the plugins below start sending messages.
+            QByteArray helloAnswer;
+            {
+                QDataStream out(&helloAnswer, QIODevice::WriteOnly);
+                out << QString(QLatin1String("QDeclarativeDebugClient")) << 0 << protocolVersion << d->plugins.keys();
+            }
+            d->connection->send(helloAnswer);
 
-        qWarning("QDeclarativeDebugServer: Connection established");
-    } else {
+            d->gotHello = true;
 
-        QString debugServer(QLatin1String("QDeclarativeDebugServer"));
+            QHash<QString, QDeclarativeDebugService*>::Iterator iter = d->plugins.begin();
+            for (; iter != d->plugins.end(); ++iter) {
+                QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::Unavailable;
+                if (d->clientPlugins.contains(iter.key()))
+                    newStatus = QDeclarativeDebugService::Enabled;
+                iter.value()->d_func()->status = newStatus;
+                iter.value()->statusChanged(newStatus);
+            }
 
-        QString name;
-        in >> name;
+            qWarning("QDeclarativeDebugServer: Connection established");
 
-        if (name == debugServer) {
-            int op = -1;
-            in >> op;
+        } else if (op == 1) {
 
-            if (op == 1) {
-                // Service Discovery
-                QStringList oldClientPlugins = d->clientPlugins;
-                in >> d->clientPlugins;
+            // Service Discovery
+            QStringList oldClientPlugins = d->clientPlugins;
+            in >> d->clientPlugins;
 
-                QHash<QString, QDeclarativeDebugService*>::Iterator iter = d->plugins.begin();
-                for (; iter != d->plugins.end(); ++iter) {
-                    const QString pluginName = iter.key();
-                    QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::Unavailable;
-                    if (d->clientPlugins.contains(pluginName))
-                        newStatus = QDeclarativeDebugService::Enabled;
+            QHash<QString, QDeclarativeDebugService*>::Iterator iter = d->plugins.begin();
+            for (; iter != d->plugins.end(); ++iter) {
+                const QString pluginName = iter.key();
+                QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::Unavailable;
+                if (d->clientPlugins.contains(pluginName))
+                    newStatus = QDeclarativeDebugService::Enabled;
 
-                    if (oldClientPlugins.contains(pluginName)
-                            != d->clientPlugins.contains(pluginName)) {
-                        iter.value()->d_func()->status = newStatus;
-                        iter.value()->statusChanged(newStatus);
-                    }
+                if (oldClientPlugins.contains(pluginName)
+                        != d->clientPlugins.contains(pluginName)) {
+                    iter.value()->d_func()->status = newStatus;
+                    iter.value()->statusChanged(newStatus);
                 }
-            } else {
-                qWarning("QDeclarativeDebugServer: Invalid control message %d", op);
             }
+
         } else {
+            qWarning("QDeclarativeDebugServer: Invalid control message %d", op);
+            d->connection->disconnect();
+            return;
+        }
+
+    } else {
+        if (d->gotHello) {
             QByteArray message;
             in >> message;
 
@@ -328,7 +319,10 @@ void QDeclarativeDebugServer::receiveMessage(const QByteArray &message)
                                           Q_ARG(QString, name),
                                           Q_ARG(QByteArray, message));
             }
+        } else {
+            qWarning("QDeclarativeDebugServer: Invalid hello message");
         }
+
     }
 }
 
index abc60e1..512ea65 100644 (file)
@@ -168,13 +168,14 @@ void QTcpServerConnection::newConnection()
 {
     Q_D(QTcpServerConnection);
 
-    if (d->socket) {
+    if (d->socket && d->socket->peerPort()) {
         qWarning("QDeclarativeDebugServer: Another client is already connected");
         QTcpSocket *faultyConnection = d->tcpServer->nextPendingConnection();
         delete faultyConnection;
         return;
     }
 
+    delete d->socket;
     d->socket = d->tcpServer->nextPendingConnection();
     d->socket->setParent(this);
     d->protocol = new QPacketProtocol(d->socket, this);
index b53a92c..220669a 100644 (file)
@@ -50,6 +50,9 @@
 #include "../../../shared/util.h"
 #include "../shared/debugutil_p.h"
 
+#define PORT 13770
+#define STR_PORT "13770"
+
 class tst_QDeclarativeDebugClient : public QObject
 {
     Q_OBJECT
@@ -63,11 +66,14 @@ private slots:
     void name();
     void status();
     void sendMessage();
+    void parallelConnect();
+    void sequentialConnect();
 };
 
 void tst_QDeclarativeDebugClient::initTestCase()
 {
-    QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugServer: Waiting for connection on port 13770...");
+    const QString waitingMsg = QString("QDeclarativeDebugServer: Waiting for connection on port %1...").arg(PORT);
+    QTest::ignoreMessage(QtWarningMsg, waitingMsg.toAscii().constData());
     new QDeclarativeEngine(this);
 
     m_conn = new QDeclarativeDebugConnection(this);
@@ -75,7 +81,7 @@ void tst_QDeclarativeDebugClient::initTestCase()
     QDeclarativeDebugTestClient client("tst_QDeclarativeDebugClient::handshake()", m_conn);
     QDeclarativeDebugTestService service("tst_QDeclarativeDebugClient::handshake()");
 
-    m_conn->connectToHost("127.0.0.1", 13770);
+    m_conn->connectToHost("127.0.0.1", PORT);
 
     QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugServer: Connection established");
     bool ok = m_conn->waitForConnected();
@@ -134,14 +140,46 @@ void tst_QDeclarativeDebugClient::sendMessage()
     QCOMPARE(resp, msg);
 }
 
+void tst_QDeclarativeDebugClient::parallelConnect()
+{
+    QDeclarativeDebugConnection connection2;
+
+    connection2.connectToHost("127.0.0.1", PORT);
+    QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugServer: Another client is already connected");
+    // will connect & immediately disconnect
+    QVERIFY(connection2.waitForConnected());
+    QTRY_COMPARE(connection2.state(), QAbstractSocket::UnconnectedState);
+    QVERIFY(m_conn->isConnected());
+}
+
+void tst_QDeclarativeDebugClient::sequentialConnect()
+{
+    QDeclarativeDebugConnection connection2;
+    QDeclarativeDebugTestClient client2("tst_QDeclarativeDebugClient::handshake()", &connection2);
+    QDeclarativeDebugTestService service("tst_QDeclarativeDebugClient::handshake()");
+
+    m_conn->close();
+    QVERIFY(!m_conn->isConnected());
+    QCOMPARE(m_conn->state(), QAbstractSocket::UnconnectedState);
+
+    // Make sure that the disconnect is actually delivered to the server
+    QGuiApplication::processEvents();
+
+    connection2.connectToHost("127.0.0.1", PORT);
+    QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugServer: Connection established");
+    QVERIFY(connection2.waitForConnected());
+    QVERIFY(connection2.isConnected());
+    QTRY_VERIFY(client2.status() == QDeclarativeDebugClient::Enabled);
+}
+
 int main(int argc, char *argv[])
 {
     int _argc = argc + 1;
     char **_argv = new char*[_argc];
     for (int i = 0; i < argc; ++i)
         _argv[i] = argv[i];
-    char arg[] = "-qmljsdebugger=port:13770";
-    _argv[_argc - 1] = arg;
+
+    _argv[_argc - 1] = "-qmljsdebugger=port:" STR_PORT;
 
     QGuiApplication app(_argc, _argv);
     tst_QDeclarativeDebugClient tc;