summaryrefslogtreecommitdiffstats
path: root/src/declarative/debugger/qdeclarativedebugclient.cpp
diff options
context:
space:
mode:
authorKai Koehne <kai.koehne@nokia.com>2010-09-22 19:03:57 (GMT)
committerKai Koehne <kai.koehne@nokia.com>2010-09-28 05:55:32 (GMT)
commitfd9771c29d401d88779ab7c5d7715c9ca41dd723 (patch)
tree0e96e0871e8914f5747bfc1a1314d76a78620b6d /src/declarative/debugger/qdeclarativedebugclient.cpp
parent7b796b4dcdebfba55c4754d241edb334217fc550 (diff)
downloadQt-fd9771c29d401d88779ab7c5d7715c9ca41dd723.zip
Qt-fd9771c29d401d88779ab7c5d7715c9ca41dd723.tar.gz
Qt-fd9771c29d401d88779ab7c5d7715c9ca41dd723.tar.bz2
Make QmlDebug protocol more robust
The protocol so far was client->server only. That is, there was no sane way for a client to check whether a plugin on the server (service) was available or not. E.g. calling Client::setEnabled(true) 'succeeded', without a check whether there is actually a service to talk to. The new protocol replaces this shortcoming by a service discovery mechanism: Both client & service announce their available plugins at handshake time, and later on if there are changes. The status is reflected in Client::status() and Service::Status() , which are either NotConnected - no network connection, or not registered properly Unavailable - TCP/IP connection works, but no plugin with the same name on the other side Enabled - You can connect to plugin on other side The status changes happen automatically (no setEnabled() anymore). Furthermore a version ID was added to the handshake, so that we can extend the protocol further in the future :)
Diffstat (limited to 'src/declarative/debugger/qdeclarativedebugclient.cpp')
-rw-r--r--src/declarative/debugger/qdeclarativedebugclient.cpp199
1 files changed, 141 insertions, 58 deletions
diff --git a/src/declarative/debugger/qdeclarativedebugclient.cpp b/src/declarative/debugger/qdeclarativedebugclient.cpp
index 2e52b40..f7d7243 100644
--- a/src/declarative/debugger/qdeclarativedebugclient.cpp
+++ b/src/declarative/debugger/qdeclarativedebugclient.cpp
@@ -50,6 +50,20 @@
QT_BEGIN_NAMESPACE
+const int protocolVersion = 1;
+const QString serverId = QLatin1String("QDeclarativeDebugServer");
+const QString clientId = QLatin1String("QDeclarativeDebugClient");
+
+class QDeclarativeDebugClientPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarativeDebugClient)
+public:
+ QDeclarativeDebugClientPrivate();
+
+ QString name;
+ QDeclarativeDebugConnection *client;
+};
+
class QDeclarativeDebugConnectionPrivate : public QObject
{
Q_OBJECT
@@ -58,40 +72,123 @@ public:
QDeclarativeDebugConnection *q;
QPacketProtocol *protocol;
- QStringList enabled;
+ bool gotHello;
+ QStringList serverPlugins;
QHash<QString, QDeclarativeDebugClient *> plugins;
+
+ void advertisePlugins();
+
public Q_SLOTS:
void connected();
void readyRead();
};
QDeclarativeDebugConnectionPrivate::QDeclarativeDebugConnectionPrivate(QDeclarativeDebugConnection *c)
-: QObject(c), q(c), protocol(0)
+: QObject(c), q(c), protocol(0), gotHello(false)
{
protocol = new QPacketProtocol(q, this);
QObject::connect(c, SIGNAL(connected()), this, SLOT(connected()));
QObject::connect(protocol, SIGNAL(readyRead()), this, SLOT(readyRead()));
}
+void QDeclarativeDebugConnectionPrivate::advertisePlugins()
+{
+ if (!q->isConnected() || !gotHello)
+ return;
+
+ QPacket pack;
+ pack << serverId << 1 << plugins.keys();
+ protocol->send(pack);
+}
+
void QDeclarativeDebugConnectionPrivate::connected()
{
QPacket pack;
- pack << QString(QLatin1String("QDeclarativeDebugServer")) << enabled;
+ pack << serverId << 0 << protocolVersion << plugins.keys();
protocol->send(pack);
}
void QDeclarativeDebugConnectionPrivate::readyRead()
{
- QPacket pack = protocol->read();
- QString name; QByteArray message;
- pack >> name >> message;
+ if (!gotHello) {
+ QPacket pack = protocol->read();
+ QString name;
+
+ pack >> name;
+
+ bool validHello = false;
+ if (name == clientId) {
+ int op = -1;
+ pack >> op;
+ if (op == 0) {
+ int version = -1;
+ pack >> version;
+ if (version == protocolVersion) {
+ pack >> serverPlugins;
+ validHello = true;
+ }
+ }
+ }
- QHash<QString, QDeclarativeDebugClient *>::Iterator iter =
- plugins.find(name);
- if (iter == plugins.end()) {
- qWarning() << "QDeclarativeDebugConnection: Message received for missing plugin" << name;
- } else {
- (*iter)->messageReceived(message);
+ if (!validHello) {
+ qWarning("QDeclarativeDebugConnection: Invalid hello message");
+ QObject::disconnect(protocol, SIGNAL(readyRead()), this, SLOT(readyRead()));
+ return;
+ }
+
+ qDebug() << "Available server side plugins: " << serverPlugins;
+
+ QHash<QString, QDeclarativeDebugClient *>::Iterator iter = plugins.begin();
+ for (; iter != plugins.end(); ++iter) {
+ QDeclarativeDebugClient::Status newStatus = QDeclarativeDebugClient::Unavailable;
+ if (serverPlugins.contains(iter.key()))
+ newStatus = QDeclarativeDebugClient::Enabled;
+ iter.value()->statusChanged(newStatus);
+ }
+ gotHello = true;
+ }
+
+ while (protocol->packetsAvailable()) {
+ QPacket pack = protocol->read();
+ QString name;
+ pack >> name;
+
+ if (name == clientId) {
+ int op = -1;
+ pack >> op;
+
+ if (op == 1) {
+ // Service Discovery
+ QStringList oldServerPlugins = serverPlugins;
+ pack >> serverPlugins;
+
+ QHash<QString, QDeclarativeDebugClient *>::Iterator iter = plugins.begin();
+ for (; iter != plugins.end(); ++iter) {
+ const QString pluginName = iter.key();
+ QDeclarativeDebugClient::Status newStatus = QDeclarativeDebugClient::Unavailable;
+ if (serverPlugins.contains(pluginName))
+ newStatus = QDeclarativeDebugClient::Enabled;
+
+ if (oldServerPlugins.contains(pluginName)
+ != serverPlugins.contains(pluginName)) {
+ iter.value()->statusChanged(newStatus);
+ }
+ }
+ } else {
+ qWarning() << "QDeclarativeDebugConnection: Unknown control message id" << op;
+ }
+ } else {
+ QByteArray message;
+ pack >> message;
+
+ QHash<QString, QDeclarativeDebugClient *>::Iterator iter =
+ plugins.find(name);
+ if (iter == plugins.end()) {
+ qWarning() << "QDeclarativeDebugConnection: Message received for missing plugin" << name;
+ } else {
+ (*iter)->messageReceived(message);
+ }
+ }
}
}
@@ -100,24 +197,22 @@ QDeclarativeDebugConnection::QDeclarativeDebugConnection(QObject *parent)
{
}
-bool QDeclarativeDebugConnection::isConnected() const
+QDeclarativeDebugConnection::~QDeclarativeDebugConnection()
{
- return state() == ConnectedState;
+ QHash<QString, QDeclarativeDebugClient*>::iterator iter = d->plugins.begin();
+ for (; iter != d->plugins.end(); ++iter) {
+ iter.value()->d_func()->client = 0;
+ iter.value()->statusChanged(QDeclarativeDebugClient::NotConnected);
+ }
}
-class QDeclarativeDebugClientPrivate : public QObjectPrivate
+bool QDeclarativeDebugConnection::isConnected() const
{
- Q_DECLARE_PUBLIC(QDeclarativeDebugClient)
-public:
- QDeclarativeDebugClientPrivate();
-
- QString name;
- QDeclarativeDebugConnection *client;
- bool enabled;
-};
+ return state() == ConnectedState;
+}
QDeclarativeDebugClientPrivate::QDeclarativeDebugClientPrivate()
-: client(0), enabled(false)
+: client(0)
{
}
@@ -137,60 +232,44 @@ QDeclarativeDebugClient::QDeclarativeDebugClient(const QString &name,
d->client = 0;
} else {
d->client->d->plugins.insert(name, this);
+ d->client->d->advertisePlugins();
}
}
-QString QDeclarativeDebugClient::name() const
+QDeclarativeDebugClient::~QDeclarativeDebugClient()
{
Q_D(const QDeclarativeDebugClient);
- return d->name;
+ if (d->client && d->client->d) {
+ d->client->d->plugins.remove(d->name);
+ d->client->d->advertisePlugins();
+ }
}
-bool QDeclarativeDebugClient::isEnabled() const
+QString QDeclarativeDebugClient::name() const
{
Q_D(const QDeclarativeDebugClient);
- return d->enabled;
-}
-
-void QDeclarativeDebugClient::setEnabled(bool e)
-{
- Q_D(QDeclarativeDebugClient);
- if (e == d->enabled)
- return;
-
- d->enabled = e;
-
- if (d->client) {
- if (e)
- d->client->d->enabled.append(d->name);
- else
- d->client->d->enabled.removeAll(d->name);
-
- if (d->client->state() == QTcpSocket::ConnectedState) {
- QPacket pack;
- pack << QString(QLatin1String("QDeclarativeDebugServer"));
- if (e) pack << (int)1;
- else pack << (int)2;
- pack << d->name;
- d->client->d->protocol->send(pack);
- }
- }
+ return d->name;
}
-bool QDeclarativeDebugClient::isConnected() const
+QDeclarativeDebugClient::Status QDeclarativeDebugClient::status() const
{
Q_D(const QDeclarativeDebugClient);
+ if (!d->client
+ || !d->client->isConnected()
+ || !d->client->d->gotHello)
+ return NotConnected;
- if (!d->client)
- return false;
- return d->client->isConnected();
+ if (d->client->d->serverPlugins.contains(d->name))
+ return Enabled;
+
+ return Unavailable;
}
void QDeclarativeDebugClient::sendMessage(const QByteArray &message)
{
Q_D(QDeclarativeDebugClient);
- if (!d->client || !d->client->isConnected())
+ if (status() != Enabled)
return;
QPacket pack;
@@ -198,6 +277,10 @@ void QDeclarativeDebugClient::sendMessage(const QByteArray &message)
d->client->d->protocol->send(pack);
}
+void QDeclarativeDebugClient::statusChanged(Status status)
+{
+}
+
void QDeclarativeDebugClient::messageReceived(const QByteArray &)
{
}