QDeclarativeDebug: Allow reconnects to QML debugger port

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>
This commit is contained in:
Kai Koehne 2011-09-19 12:29:10 +02:00 committed by Qt by Nokia
parent 4bca5b2ff8
commit 940069e463
3 changed files with 101 additions and 68 deletions

View 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;
QString name;
if (name != QLatin1String("QDeclarativeDebugServer")
|| op != 0) {
qWarning("QDeclarativeDebugServer: Invalid hello message");
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);
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);
}
qWarning("QDeclarativeDebugServer: Connection established");
} else if (op == 1) {
// 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;
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);
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);
}
qWarning("QDeclarativeDebugServer: Connection established");
} else {
QString debugServer(QLatin1String("QDeclarativeDebugServer"));
QString name;
in >> name;
if (name == debugServer) {
int op = -1;
in >> op;
if (op == 1) {
// 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;
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 {
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");
}
}
}

View 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);

View 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;