From a010f3a8f92a9a364e9d17d12b06074fde6f8a17 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 16 Jun 2015 13:40:08 +0200 Subject: [PATCH] Deduplicate debug server connection code. The packet protocol can be part of the server, now that the server is not part of QtQml anymore. This enables us to remove some duplicated code from the connections. As an added benefit, with more control over the sending process, QQmlDebugServer can now efficiently send single packets, without creating a QList first. Change-Id: I13cc831e254c02b737e64816d6d3ab051d760995 Reviewed-by: Simon Hausmann --- .../qmldbg_local/qlocalclientconnection.cpp | 54 ++----------- .../qmldbg_local/qlocalclientconnection.h | 8 +- .../qmltooling/qmldbg_local/qmldbg_local.pro | 8 +- .../qmltooling/qmldbg_server/qmldbg_server.pro | 2 + .../qmltooling/qmldbg_server/qqmldebugserver.cpp | 89 +++++++++++++++------- src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro | 8 +- .../qmltooling/qmldbg_tcp/qtcpserverconnection.cpp | 61 ++------------- .../qmltooling/qmldbg_tcp/qtcpserverconnection.h | 8 +- src/plugins/qmltooling/shared/qqmldebugserver.h | 2 +- .../qmltooling/shared/qqmldebugserverconnection.h | 4 +- 10 files changed, 92 insertions(+), 152 deletions(-) diff --git a/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.cpp b/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.cpp index 266f450..cf4512c 100644 --- a/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.cpp +++ b/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.cpp @@ -47,14 +47,12 @@ public: bool block; QString filename; QLocalSocket *socket; - QPacketProtocol *protocol; QQmlDebugServer *debugServer; }; QLocalClientConnectionPrivate::QLocalClientConnectionPrivate() : block(false), socket(0), - protocol(0), debugServer(0) { } @@ -83,21 +81,6 @@ bool QLocalClientConnection::isConnected() const return d->socket && d->socket->state() == QLocalSocket::ConnectedState; } -void QLocalClientConnection::send(const QList &messages) -{ - Q_D(QLocalClientConnection); - - if (!isConnected() || !d->protocol || !d->socket) - return; - - foreach (const QByteArray &message, messages) { - QPacket pack; - pack.writeRawData(message.data(), message.length()); - d->protocol->send(pack); - } - d->socket->flush(); -} - void QLocalClientConnection::disconnect() { Q_D(QLocalClientConnection); @@ -105,19 +88,10 @@ void QLocalClientConnection::disconnect() while (d->socket && d->socket->bytesToWrite() > 0) d->socket->waitForBytesWritten(); - // protocol might still be processing packages at this point - d->protocol->deleteLater(); - d->protocol = 0; d->socket->deleteLater(); d->socket = 0; } -bool QLocalClientConnection::waitForMessage() -{ - Q_D(QLocalClientConnection); - return d->protocol->waitForReadyRead(-1); -} - bool QLocalClientConnection::setPortRange(int portFrom, int portTo, bool block, const QString &hostaddress) { @@ -133,7 +107,7 @@ bool QLocalClientConnection::setFileName(const QString &filename, bool block) Q_D(QLocalClientConnection); d->filename = filename; d->block = block; - return connect(); + return connectToServer(); } void QLocalClientConnection::waitForConnection() @@ -142,7 +116,7 @@ void QLocalClientConnection::waitForConnection() d->socket->waitForConnected(-1); } -bool QLocalClientConnection::connect() +bool QLocalClientConnection::connectToServer() { Q_D(QLocalClientConnection); @@ -155,33 +129,17 @@ bool QLocalClientConnection::connect() return true; } -void QLocalClientConnection::readyRead() +void QLocalClientConnection::flush() { Q_D(QLocalClientConnection); - if (!d->protocol) - return; - - QPacket packet = d->protocol->read(); - - QByteArray content = packet.data(); - d->debugServer->receiveMessage(content); + if (d->socket) + d->socket->flush(); } void QLocalClientConnection::connectionEstablished() { Q_D(QLocalClientConnection); - - d->protocol = new QPacketProtocol(d->socket, this); - QObject::connect(d->protocol, SIGNAL(readyRead()), this, SLOT(readyRead())); - QObject::connect(d->protocol, SIGNAL(invalidPacket()), this, SLOT(invalidPacket())); - - if (d->block) - d->protocol->waitForReadyRead(-1); -} - -void QLocalClientConnection::invalidPacket() -{ - qWarning("QML Debugger: Received a corrupted packet! Giving up ..."); + d->debugServer->setDevice(d->socket); } QT_END_NAMESPACE diff --git a/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.h b/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.h index afc86a2..4d20b8d 100644 --- a/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.h +++ b/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.h @@ -56,19 +56,17 @@ public: bool setFileName(const QString &filename, bool block); bool isConnected() const; - void send(const QList &messages); void disconnect(); - bool waitForMessage(); void waitForConnection(); - bool connect(); + void flush(); private Q_SLOTS: - void readyRead(); void connectionEstablished(); - void invalidPacket(); private: + bool connectToServer(); + QLocalClientConnectionPrivate *d_ptr; }; diff --git a/src/plugins/qmltooling/qmldbg_local/qmldbg_local.pro b/src/plugins/qmltooling/qmldbg_local/qmldbg_local.pro index d8eb5ed..4fa0523 100644 --- a/src/plugins/qmltooling/qmldbg_local/qmldbg_local.pro +++ b/src/plugins/qmltooling/qmldbg_local/qmldbg_local.pro @@ -1,19 +1,17 @@ TARGET = qmldbg_local -QT = qml-private core-private +QT = qml-private PLUGIN_TYPE = qmltooling PLUGIN_CLASS_NAME = QLocalClientConnection load(qt_plugin) SOURCES += \ - $$PWD/qlocalclientconnection.cpp \ - $$PWD/../shared/qpacketprotocol.cpp + $$PWD/qlocalclientconnection.cpp HEADERS += \ $$PWD/qlocalclientconnection.h \ $$PWD/../shared/qqmldebugserver.h \ - $$PWD/../shared/qqmldebugserverconnection.h \ - $$PWD/../shared/qpacketprotocol.h + $$PWD/../shared/qqmldebugserverconnection.h INCLUDEPATH += $$PWD \ $$PWD/../shared diff --git a/src/plugins/qmltooling/qmldbg_server/qmldbg_server.pro b/src/plugins/qmltooling/qmldbg_server/qmldbg_server.pro index 034f29c..5e2d087 100644 --- a/src/plugins/qmltooling/qmldbg_server/qmldbg_server.pro +++ b/src/plugins/qmltooling/qmldbg_server/qmldbg_server.pro @@ -7,10 +7,12 @@ load(qt_plugin) SOURCES += \ $$PWD/qqmldebugserver.cpp \ + $$PWD/../shared/qpacketprotocol.cpp HEADERS += \ $$PWD/qqmldebugserverfactory.h \ $$PWD/../shared/qqmldebugserver.h \ + $$PWD/../shared/qpacketprotocol.h \ $$PWD/../shared/qqmldebugserverconnection.h INCLUDEPATH += $$PWD \ diff --git a/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp b/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp index af77e68..4a4af77 100644 --- a/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp +++ b/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp @@ -33,6 +33,7 @@ #include "qqmldebugserver.h" #include "qqmldebugserverfactory.h" +#include "qpacketprotocol.h" #include "qqmldebugserverconnection.h" #include @@ -101,8 +102,7 @@ public: bool removeService(QQmlDebugService *service); bool open(const QVariantHash &configuration); - - void receiveMessage(const QByteArray &message); + void setDevice(QIODevice *socket); template bool enable(Action action); @@ -116,6 +116,8 @@ private slots: void sendMessages(const QString &name, const QList &messages); void changeServiceState(const QString &serviceName, QQmlDebugService::State state); void removeThread(); + void receiveMessage(); + void invalidPacket(); private: friend struct StartTcpServerAction; @@ -139,6 +141,8 @@ private: bool init(const QString &pluginName, bool block); + bool canSendMessage(const QString &name); + void doSendMessage(const QString &name, const QByteArray &message); QQmlDebugServerConnection *loadConnectionPlugin(const QString &pluginName); QQmlDebugServerConnection *m_connection; @@ -152,6 +156,7 @@ private: QMutex m_helloMutex; QWaitCondition m_helloCondition; QQmlDebugServerThread *m_thread; + QPacketProtocol *m_protocol; #ifndef QT_NO_LIBRARY QPluginLoader m_loader; #endif @@ -478,14 +483,17 @@ bool QQmlDebugServerImpl::enableFromArguments() return false; } -void QQmlDebugServerImpl::receiveMessage(const QByteArray &message) +void QQmlDebugServerImpl::receiveMessage() { typedef QHash::const_iterator DebugServiceConstIt; // to be executed in debugger thread Q_ASSERT(QThread::currentThread() == thread()); - QQmlDebugStream in(message); + if (!m_protocol) + return; + + QQmlDebugStream in(m_protocol->read().data()); QString name; @@ -523,7 +531,10 @@ void QQmlDebugServerImpl::receiveMessage(const QByteArray &message) out << QString(QStringLiteral("QDeclarativeDebugClient")) << 0 << protocolVersion << pluginNames << pluginVersions << QQmlDebugStream::s_dataStreamVersion; - m_connection->send(QList() << helloAnswer); + QPacket pack; + pack.writeRawData(helloAnswer.data(), helloAnswer.length()); + m_protocol->send(pack); + m_connection->flush(); QMutexLocker helloLock(&m_helloMutex); m_gotHello = true; @@ -558,7 +569,7 @@ void QQmlDebugServerImpl::receiveMessage(const QByteArray &message) } else { qWarning("QML Debugger: Invalid control message %d.", op); - m_connection->disconnect(); + invalidPacket(); return; } @@ -700,34 +711,39 @@ bool QQmlDebugServerImpl::removeService(QQmlDebugService *service) return true; } -void QQmlDebugServerImpl::sendMessage(const QString &name, const QByteArray &message) +bool QQmlDebugServerImpl::canSendMessage(const QString &name) { - sendMessages(name, QList() << message); + // to be executed in debugger thread + Q_ASSERT(QThread::currentThread() == thread()); + return m_connection && m_connection->isConnected() && m_protocol && + m_clientPlugins.contains(name); } -void QQmlDebugServerImpl::sendMessages(const QString &name, const QList &messages) +void QQmlDebugServerImpl::doSendMessage(const QString &name, const QByteArray &message) { - // to be executed in debugger thread - Q_ASSERT(QThread::currentThread() == thread()); + QByteArray prefixed; + QQmlDebugStream out(&prefixed, QIODevice::WriteOnly); + out << name << message; - if (!m_connection) - return; + QPacket pack; + pack.writeRawData(prefixed.data(), prefixed.length()); + m_protocol->send(pack); +} - if (!name.isEmpty()) { - if (!m_clientPlugins.contains(name)) - return; - QList prefixedMessages; - prefixedMessages.reserve(messages.count()); - foreach (const QByteArray &message, messages) { - QByteArray prefixed; - QQmlDebugStream out(&prefixed, QIODevice::WriteOnly); - out << name << message; - prefixedMessages << prefixed; - } +void QQmlDebugServerImpl::sendMessage(const QString &name, const QByteArray &message) +{ + if (canSendMessage(name)) { + doSendMessage(name, message); + m_connection->flush(); + } +} - m_connection->send(prefixedMessages); - } else { - m_connection->send(messages); +void QQmlDebugServerImpl::sendMessages(const QString &name, const QList &messages) +{ + if (canSendMessage(name)) { + foreach (const QByteArray &message, messages) + doSendMessage(name, message); + m_connection->flush(); } } @@ -769,6 +785,25 @@ void QQmlDebugServerImpl::EngineCondition::wake() Q_ASSERT_X(numServices >=0, Q_FUNC_INFO, "Woken more often than #services."); } +void QQmlDebugServerImpl::setDevice(QIODevice *socket) +{ + m_protocol = new QPacketProtocol(socket, this); + QObject::connect(m_protocol, SIGNAL(readyRead()), this, SLOT(receiveMessage())); + QObject::connect(m_protocol, SIGNAL(invalidPacket()), this, SLOT(invalidPacket())); + + if (blockingMode()) + m_protocol->waitForReadyRead(-1); +} + +void QQmlDebugServerImpl::invalidPacket() +{ + qWarning("QML Debugger: Received a corrupted packet! Giving up ..."); + m_connection->disconnect(); + // protocol might still be processing packages at this point + m_protocol->deleteLater(); + m_protocol = 0; +} + QQmlDebugConnector *QQmlDebugServerFactory::create(const QString &key) { // Cannot parent it to this because it gets moved to another thread diff --git a/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro b/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro index cb5d1f3..15ba7c7 100644 --- a/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro +++ b/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro @@ -1,19 +1,17 @@ TARGET = qmldbg_tcp -QT = qml-private core-private network +QT = qml-private network PLUGIN_TYPE = qmltooling PLUGIN_CLASS_NAME = QTcpServerConnection load(qt_plugin) SOURCES += \ - $$PWD/qtcpserverconnection.cpp \ - $$PWD/../shared/qpacketprotocol.cpp + $$PWD/qtcpserverconnection.cpp HEADERS += \ $$PWD/qtcpserverconnection.h \ $$PWD/../shared/qqmldebugserver.h \ - $$PWD/../shared/qqmldebugserverconnection.h \ - $$PWD/../shared/qpacketprotocol.h + $$PWD/../shared/qqmldebugserverconnection.h INCLUDEPATH += $$PWD \ $$PWD/../shared diff --git a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp index 4333a9c..7734e5e 100644 --- a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp +++ b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp @@ -32,7 +32,6 @@ ****************************************************************************/ #include "qtcpserverconnection.h" -#include "qpacketprotocol.h" #include "qqmldebugserver.h" #include @@ -50,7 +49,6 @@ public: bool block; QString hostaddress; QTcpSocket *socket; - QPacketProtocol *protocol; QTcpServer *tcpServer; QQmlDebugServer *debugServer; @@ -61,7 +59,6 @@ QTcpServerConnectionPrivate::QTcpServerConnectionPrivate() : portTo(0), block(false), socket(0), - protocol(0), tcpServer(0), debugServer(0) { @@ -92,22 +89,6 @@ bool QTcpServerConnection::isConnected() const return d->socket && d->socket->state() == QTcpSocket::ConnectedState; } -void QTcpServerConnection::send(const QList &messages) -{ - Q_D(QTcpServerConnection); - - if (!isConnected() - || !d->protocol || !d->socket) - return; - - foreach (const QByteArray &message, messages) { - QPacket pack; - pack.writeRawData(message.data(), message.length()); - d->protocol->send(pack); - } - d->socket->flush(); -} - void QTcpServerConnection::disconnect() { Q_D(QTcpServerConnection); @@ -120,19 +101,10 @@ void QTcpServerConnection::disconnect() } } - // protocol might still be processing packages at this point - d->protocol->deleteLater(); - d->protocol = 0; d->socket->deleteLater(); d->socket = 0; } -bool QTcpServerConnection::waitForMessage() -{ - Q_D(QTcpServerConnection); - return d->protocol->waitForReadyRead(-1); -} - bool QTcpServerConnection::setPortRange(int portFrom, int portTo, bool block, const QString &hostaddress) { @@ -158,6 +130,13 @@ void QTcpServerConnection::waitForConnection() d->tcpServer->waitForNewConnection(-1); } +void QTcpServerConnection::flush() +{ + Q_D(QTcpServerConnection); + if (d->socket) + d->socket->flush(); +} + bool QTcpServerConnection::listen() { Q_D(QTcpServerConnection); @@ -193,19 +172,6 @@ bool QTcpServerConnection::listen() } } - -void QTcpServerConnection::readyRead() -{ - Q_D(QTcpServerConnection); - if (!d->protocol) - return; - - QPacket packet = d->protocol->read(); - - QByteArray content = packet.data(); - d->debugServer->receiveMessage(content); -} - void QTcpServerConnection::newConnection() { Q_D(QTcpServerConnection); @@ -220,18 +186,7 @@ void QTcpServerConnection::newConnection() delete d->socket; d->socket = d->tcpServer->nextPendingConnection(); d->socket->setParent(this); - d->protocol = new QPacketProtocol(d->socket, this); - QObject::connect(d->protocol, SIGNAL(readyRead()), this, SLOT(readyRead())); - QObject::connect(d->protocol, SIGNAL(invalidPacket()), this, SLOT(invalidPacket())); - - if (d->block) { - d->protocol->waitForReadyRead(-1); - } -} - -void QTcpServerConnection::invalidPacket() -{ - qWarning("QML Debugger: Received a corrupted packet! Giving up ..."); + d->debugServer->setDevice(d->socket); } QT_END_NAMESPACE diff --git a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h index 68271ab..8b2aed0 100644 --- a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h +++ b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h @@ -56,19 +56,17 @@ public: bool setFileName(const QString &fileName, bool block); bool isConnected() const; - void send(const QList &messages); void disconnect(); - bool waitForMessage(); - bool listen(); void waitForConnection(); + void flush(); private Q_SLOTS: - void readyRead(); void newConnection(); - void invalidPacket(); private: + bool listen(); + QTcpServerConnectionPrivate *d_ptr; }; diff --git a/src/plugins/qmltooling/shared/qqmldebugserver.h b/src/plugins/qmltooling/shared/qqmldebugserver.h index 574930a..a7c1707 100644 --- a/src/plugins/qmltooling/shared/qqmldebugserver.h +++ b/src/plugins/qmltooling/shared/qqmldebugserver.h @@ -54,7 +54,7 @@ class QQmlDebugServer : protected QQmlDebugConnector { Q_OBJECT public: - virtual void receiveMessage(const QByteArray &message) = 0; + virtual void setDevice(QIODevice *socket) = 0; }; QT_END_NAMESPACE diff --git a/src/plugins/qmltooling/shared/qqmldebugserverconnection.h b/src/plugins/qmltooling/shared/qqmldebugserverconnection.h index 592a1d6..04e4c05 100644 --- a/src/plugins/qmltooling/shared/qqmldebugserverconnection.h +++ b/src/plugins/qmltooling/shared/qqmldebugserverconnection.h @@ -55,17 +55,15 @@ class QQmlDebugServer; class QQmlDebugServerConnection { public: - QQmlDebugServerConnection() {} virtual ~QQmlDebugServerConnection() {} virtual void setServer(QQmlDebugServer *server) = 0; virtual bool setPortRange(int portFrom, int portTo, bool bock, const QString &hostaddress) = 0; virtual bool setFileName(const QString &fileName, bool block) = 0; virtual bool isConnected() const = 0; - virtual void send(const QList &messages) = 0; virtual void disconnect() = 0; virtual void waitForConnection() = 0; - virtual bool waitForMessage() = 0; + virtual void flush() = 0; }; #define QQmlDebugServerConnection_iid "org.qt-project.Qt.QQmlDebugServerConnection" -- 2.7.4