aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@theqtcompany.com>2015-09-16 13:23:19 +0200
committerUlf Hermann <ulf.hermann@theqtcompany.com>2015-10-15 08:23:15 +0000
commit2f03049d4cabfac822bcf6b5886b078d70064968 (patch)
treee79c7cdc5e300d8889d0525d0a3b1f5582921aa1
parent1a123472ba0e56d1fd772db430e6d4532f672a6e (diff)
Put QPacketProtocol into its own static library
We need it in 3 places in qtdeclarative and we could also use it in QtCreator. We don't want to bundle it with the debug client code as it is also necessary for the server. QPacket replaces QQmlDebugStream as it has the same purpose. This also fixes the inconsitent handling of data stream versions. Change-Id: I650fae353f267511c551b427d9169f4d718aa7f2 Reviewed-by: Simon Hausmann <simon.hausmann@theqtcompany.com>
-rw-r--r--src/plugins/qmltooling/packetprotocol/packetprotocol.pro11
-rw-r--r--src/plugins/qmltooling/packetprotocol/qpacketprotocol.cpp302
-rw-r--r--src/plugins/qmltooling/packetprotocol/qpacketprotocol_p.h (renamed from tools/qmlprofiler/qpacketprotocol.h)75
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.cpp6
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp20
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp14
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/abstractviewinspector.cpp23
-rw-r--r--src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.cpp1
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlenginecontrolservice.cpp8
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp6
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp20
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp27
-rw-r--r--src/plugins/qmltooling/qmldbg_server/qmldbg_server.pro4
-rw-r--r--src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp33
-rw-r--r--src/plugins/qmltooling/qmltooling.pro3
-rw-r--r--src/plugins/qmltooling/shared/qpacketprotocol.cpp531
-rw-r--r--src/qml/debugger/debugger.pri6
-rw-r--r--src/qml/debugger/qpacket.cpp147
-rw-r--r--src/qml/debugger/qpacket_p.h (renamed from src/plugins/qmltooling/shared/qpacketprotocol.h)87
-rw-r--r--src/qml/debugger/qqmldebugservice.cpp26
-rw-r--r--src/qml/debugger/qqmldebugservice_p.h11
-rw-r--r--src/quick/util/qquickprofiler.cpp7
-rw-r--r--sync.profile1
-rw-r--r--tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp129
-rw-r--r--tests/auto/qml/debugger/shared/debugutil.pri4
-rw-r--r--tests/auto/qml/debugger/shared/qqmldebugclient.cpp8
-rw-r--r--tools/qmlprofiler/qmlprofiler.pro8
-rw-r--r--tools/qmlprofiler/qpacketprotocol.cpp527
-rw-r--r--tools/qmlprofiler/qqmldebugclient.cpp8
29 files changed, 624 insertions, 1429 deletions
diff --git a/src/plugins/qmltooling/packetprotocol/packetprotocol.pro b/src/plugins/qmltooling/packetprotocol/packetprotocol.pro
new file mode 100644
index 0000000000..a6b8f26bb1
--- /dev/null
+++ b/src/plugins/qmltooling/packetprotocol/packetprotocol.pro
@@ -0,0 +1,11 @@
+TARGET = QtPacketProtocol
+QT = core-private qml-private
+CONFIG += static internal_module
+
+HEADERS = \
+ qpacketprotocol_p.h
+
+SOURCES = \
+ qpacketprotocol.cpp
+
+load(qt_module)
diff --git a/src/plugins/qmltooling/packetprotocol/qpacketprotocol.cpp b/src/plugins/qmltooling/packetprotocol/qpacketprotocol.cpp
new file mode 100644
index 0000000000..9f9dbfee90
--- /dev/null
+++ b/src/plugins/qmltooling/packetprotocol/qpacketprotocol.cpp
@@ -0,0 +1,302 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** 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 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qpacketprotocol_p.h"
+
+#include <QtCore/QElapsedTimer>
+#include <private/qiodevice_p.h>
+#include <private/qobject_p.h>
+#include <private/qpacket_p.h>
+
+QT_BEGIN_NAMESPACE
+
+static const int MAX_PACKET_SIZE = 0x7FFFFFFF;
+
+/*!
+ \class QPacketProtocol
+ \internal
+
+ \brief The QPacketProtocol class encapsulates communicating discrete packets
+ across fragmented IO channels, such as TCP sockets.
+
+ QPacketProtocol makes it simple to send arbitrary sized data "packets" across
+ fragmented transports such as TCP and UDP.
+
+ As transmission boundaries are not respected, sending packets over protocols
+ like TCP frequently involves "stitching" them back together at the receiver.
+ QPacketProtocol makes this easier by performing this task for you. Packet
+ data sent using QPacketProtocol is prepended with a 4-byte size header
+ allowing the receiving QPacketProtocol to buffer the packet internally until
+ it has all been received. QPacketProtocol does not perform any sanity
+ checking on the size or on the data, so this class should only be used in
+ prototyping or trusted situations where DOS attacks are unlikely.
+
+ QPacketProtocol does not perform any communications itself. Instead it can
+ operate on any QIODevice that supports the QIODevice::readyRead() signal. A
+ logical "packet" is encapsulated by the companion QPacket class. The
+ following example shows two ways to send data using QPacketProtocol. The
+ transmitted data is equivalent in both.
+
+ \code
+ QTcpSocket socket;
+ // ... connect socket ...
+
+ QPacketProtocol protocol(&socket);
+
+ // Send a packet
+ QPacket packet;
+ packet << "Hello world" << 123;
+ protocol.send(packet);
+ \endcode
+
+ Likewise, the following shows how to read data from QPacketProtocol, assuming
+ that the QPacketProtocol::readyRead() signal has been emitted.
+
+ \code
+ // ... QPacketProtocol::readyRead() is emitted ...
+
+ int a;
+ QByteArray b;
+
+ // Receive packet the quick way
+ protocol.read() >> a >> b;
+
+ // Receive packet the longer way
+ QPacket packet = protocol.read();
+ p >> a >> b;
+ \endcode
+
+ \ingroup io
+ \sa QPacket
+*/
+
+class QPacketProtocolPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QPacketProtocol)
+public:
+ QPacketProtocolPrivate(QIODevice *dev);
+
+ QList<qint64> sendingPackets;
+ QList<QByteArray> packets;
+ QByteArray inProgress;
+ qint32 inProgressSize;
+ bool waitingForPacket;
+ QIODevice *dev;
+};
+
+/*!
+ Construct a QPacketProtocol instance that works on \a dev with the
+ specified \a parent.
+ */
+QPacketProtocol::QPacketProtocol(QIODevice *dev, QObject *parent)
+ : QObject(*(new QPacketProtocolPrivate(dev)), parent)
+{
+ Q_ASSERT(4 == sizeof(qint32));
+ Q_ASSERT(dev);
+
+ QObject::connect(dev, SIGNAL(readyRead()),
+ this, SLOT(readyToRead()));
+ QObject::connect(dev, SIGNAL(aboutToClose()),
+ this, SLOT(aboutToClose()));
+ QObject::connect(dev, SIGNAL(bytesWritten(qint64)),
+ this, SLOT(bytesWritten(qint64)));
+}
+
+/*!
+ \fn void QPacketProtocol::send(const QPacket & packet)
+
+ Transmit the \a packet.
+ */
+void QPacketProtocol::send(const QPacket & p)
+{
+ Q_D(QPacketProtocol);
+
+ QByteArray data = p.data();
+ if (data.isEmpty())
+ return; // We don't send empty packets
+ qint64 sendSize = data.size() + sizeof(qint32);
+
+ d->sendingPackets.append(sendSize);
+ qint32 sendSize32 = sendSize;
+ qint64 writeBytes = d->dev->write((char *)&sendSize32, sizeof(qint32));
+ Q_UNUSED(writeBytes);
+ Q_ASSERT(writeBytes == sizeof(qint32));
+ writeBytes = d->dev->write(data);
+ Q_ASSERT(writeBytes == data.size());
+}
+
+/*!
+ Returns the number of received packets yet to be read.
+ */
+qint64 QPacketProtocol::packetsAvailable() const
+{
+ Q_D(const QPacketProtocol);
+ return d->packets.count();
+}
+
+/*!
+ Return the next unread packet, or an invalid QPacket instance if no packets
+ are available. This method does NOT block.
+ */
+QPacket QPacketProtocol::read()
+{
+ Q_D(QPacketProtocol);
+
+ // Hope for in-place construction here, until we get move semantics for QBuffer
+ return QPacket(d->packets.isEmpty() ? QByteArray() : d->packets.takeFirst());
+}
+
+/*!
+ This function locks until a new packet is available for reading and the
+ \l{QIODevice::}{readyRead()} signal has been emitted. The function
+ will timeout after \a msecs milliseconds; the default timeout is
+ 30000 milliseconds.
+
+ The function returns true if the readyRead() signal is emitted and
+ there is new data available for reading; otherwise it returns false
+ (if an error occurred or the operation timed out).
+ */
+
+bool QPacketProtocol::waitForReadyRead(int msecs)
+{
+ Q_D(QPacketProtocol);
+ if (!d->packets.isEmpty())
+ return true;
+
+ QElapsedTimer stopWatch;
+ stopWatch.start();
+
+ d->waitingForPacket = true;
+ do {
+ if (!d->dev->waitForReadyRead(msecs))
+ return false;
+ if (!d->waitingForPacket)
+ return true;
+ msecs = qt_subtract_from_timeout(msecs, stopWatch.elapsed());
+ } while (true);
+}
+
+/*!
+ Return the QIODevice passed to the QPacketProtocol constructor.
+*/
+void QPacketProtocol::aboutToClose()
+{
+ Q_D(QPacketProtocol);
+ d->inProgress.clear();
+ d->sendingPackets.clear();
+ d->inProgressSize = -1;
+}
+
+void QPacketProtocol::bytesWritten(qint64 bytes)
+{
+ Q_D(QPacketProtocol);
+ Q_ASSERT(!d->sendingPackets.isEmpty());
+
+ while (bytes) {
+ if (d->sendingPackets.at(0) > bytes) {
+ d->sendingPackets[0] -= bytes;
+ bytes = 0;
+ } else {
+ bytes -= d->sendingPackets.at(0);
+ d->sendingPackets.removeFirst();
+ }
+ }
+}
+
+void QPacketProtocol::readyToRead()
+{
+ Q_D(QPacketProtocol);
+ while (true) {
+ // Need to get trailing data
+ if (-1 == d->inProgressSize) {
+ // We need a size header of sizeof(qint32)
+ if (sizeof(qint32) > (uint)d->dev->bytesAvailable())
+ return;
+
+ // Read size header
+ int read = d->dev->read((char *)&d->inProgressSize, sizeof(qint32));
+ Q_ASSERT(read == sizeof(qint32));
+ Q_UNUSED(read);
+
+ // Check sizing constraints
+ if (d->inProgressSize > MAX_PACKET_SIZE) {
+ QObject::disconnect(d->dev, SIGNAL(readyRead()),
+ this, SLOT(readyToRead()));
+ QObject::disconnect(d->dev, SIGNAL(aboutToClose()),
+ this, SLOT(aboutToClose()));
+ QObject::disconnect(d->dev, SIGNAL(bytesWritten(qint64)),
+ this, SLOT(bytesWritten(qint64)));
+ d->dev = 0;
+ emit invalidPacket();
+ return;
+ }
+
+ d->inProgressSize -= sizeof(qint32);
+ } else {
+ d->inProgress.append(d->dev->read(d->inProgressSize - d->inProgress.size()));
+
+ if (d->inProgressSize == d->inProgress.size()) {
+ // Packet has arrived!
+ d->packets.append(d->inProgress);
+ d->inProgressSize = -1;
+ d->inProgress.clear();
+
+ d->waitingForPacket = false;
+ emit readyRead();
+ } else
+ return;
+ }
+ }
+}
+
+QPacketProtocolPrivate::QPacketProtocolPrivate(QIODevice *dev) :
+ inProgressSize(-1), waitingForPacket(false), dev(dev)
+{
+}
+
+/*!
+ \fn void QPacketProtocol::readyRead()
+
+ Emitted whenever a new packet is received. Applications may use
+ QPacketProtocol::read() to retrieve this packet.
+ */
+
+/*!
+ \fn void QPacketProtocol::invalidPacket()
+
+ A packet larger than the maximum allowable packet size was received. The
+ packet will be discarded and, as it indicates corruption in the protocol, no
+ further packets will be received.
+ */
+
+QT_END_NAMESPACE
diff --git a/tools/qmlprofiler/qpacketprotocol.h b/src/plugins/qmltooling/packetprotocol/qpacketprotocol_p.h
index 17608033f4..6ed803809f 100644
--- a/tools/qmlprofiler/qpacketprotocol.h
+++ b/src/plugins/qmltooling/packetprotocol/qpacketprotocol_p.h
@@ -31,79 +31,50 @@
**
****************************************************************************/
-#ifndef QPACKETPROTOCOL_H
-#define QPACKETPROTOCOL_H
+#ifndef QPACKETPROTOCOL_P_H
+#define QPACKETPROTOCOL_P_H
#include <QtCore/qobject.h>
-#include <QtCore/qdatastream.h>
+#include <private/qpacket_p.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
QT_BEGIN_NAMESPACE
+
class QIODevice;
-class QBuffer;
-QT_END_NAMESPACE
-class QPacket;
-class QPacketAutoSend;
-class QPacketProtocolPrivate;
+class QPacketProtocolPrivate;
class QPacketProtocol : public QObject
{
Q_OBJECT
+ Q_DECLARE_PRIVATE(QPacketProtocol)
public:
explicit QPacketProtocol(QIODevice *dev, QObject *parent = 0);
- virtual ~QPacketProtocol();
-
- qint32 maximumPacketSize() const;
- qint32 setMaximumPacketSize(qint32);
- QPacketAutoSend send();
void send(const QPacket &);
-
qint64 packetsAvailable() const;
QPacket read();
-
bool waitForReadyRead(int msecs = 3000);
- void clear();
-
- QIODevice *device();
-
Q_SIGNALS:
void readyRead();
void invalidPacket();
- void packetWritten();
-private:
- QPacketProtocolPrivate *d;
+private Q_SLOTS:
+ void aboutToClose();
+ void bytesWritten(qint64 bytes);
+ void readyToRead();
};
+QT_END_NAMESPACE
-class QPacket : public QDataStream
-{
-public:
- QPacket();
- QPacket(const QPacket &);
- virtual ~QPacket();
-
- void clear();
- bool isEmpty() const;
- QByteArray data() const;
-
-protected:
- friend class QPacketProtocol;
- QPacket(const QByteArray &ba);
- QByteArray b;
- QBuffer *buf;
-};
-
-class QPacketAutoSend : public QPacket
-{
-public:
- virtual ~QPacketAutoSend();
-
-private:
- friend class QPacketProtocol;
- QPacketAutoSend(QPacketProtocol *);
- QPacketProtocol *p;
-};
-
-#endif
+#endif // QPACKETPROTOCOL_P_H
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.cpp
index ee1047d2b0..e7b9f24ae7 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.cpp
@@ -33,6 +33,7 @@
#include "qdebugmessageservice.h"
#include <private/qqmldebugconnector_p.h>
+#include <private/qpacket_p.h>
#include <QDataStream>
@@ -63,13 +64,12 @@ void QDebugMessageServiceImpl::sendDebugMessage(QtMsgType type,
//We do not want to alter the message handling mechanism
//We just eavesdrop and forward the messages to a port
//only if a client is connected to it.
- QByteArray message;
- QQmlDebugStream ws(&message, QIODevice::WriteOnly);
+ QPacket ws;
ws << QByteArray("MESSAGE") << type << buf.toUtf8();
ws << QString::fromLatin1(ctxt.file).toUtf8();
ws << ctxt.line << QString::fromLatin1(ctxt.function).toUtf8();
- emit messageToClient(name(), message);
+ emit messageToClient(name(), ws.data());
if (oldMsgHandler)
(*oldMsgHandler)(type, ctxt, buf);
}
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
index 8f53dc6d50..09c352e8ad 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
@@ -45,6 +45,7 @@
#include <private/qqmlvaluetype_p.h>
#include <private/qqmlvmemetaobject_p.h>
#include <private/qqmlexpression_p.h>
+#include <private/qpacket_p.h>
#include <QtCore/qdebug.h>
#include <QtCore/qmetaobject.h>
@@ -440,14 +441,13 @@ QList<QObject*> QQmlEngineDebugServiceImpl::objectForLocationInfo(const QString
void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message)
{
- QQmlDebugStream ds(message);
+ QPacket ds(message);
QByteArray type;
int queryId;
ds >> type >> queryId;
- QByteArray reply;
- QQmlDebugStream rs(&reply, QIODevice::WriteOnly);
+ QPacket rs;
if (type == "LIST_ENGINES") {
rs << QByteArray("LIST_ENGINES_R");
@@ -617,7 +617,7 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message)
rs << QByteArray("SET_METHOD_BODY_R") << queryId << ok;
}
- emit messageToClient(name(), reply);
+ emit messageToClient(name(), rs.data());
}
bool QQmlEngineDebugServiceImpl::setBinding(int objectId,
@@ -769,12 +769,9 @@ bool QQmlEngineDebugServiceImpl::setMethodBody(int objectId, const QString &meth
void QQmlEngineDebugServiceImpl::propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value)
{
- QByteArray reply;
- QQmlDebugStream rs(&reply, QIODevice::WriteOnly);
-
+ QPacket rs;
rs << QByteArray("UPDATE_WATCH") << id << objectId << QByteArray(property.name()) << valueContents(value);
-
- emit messageToClient(name(), reply);
+ emit messageToClient(name(), rs.data());
}
void QQmlEngineDebugServiceImpl::engineAboutToBeAdded(QQmlEngine *engine)
@@ -804,12 +801,11 @@ void QQmlEngineDebugServiceImpl::objectCreated(QQmlEngine *engine, QObject *obje
int objectId = QQmlDebugService::idForObject(object);
int parentId = QQmlDebugService::idForObject(object->parent());
- QByteArray reply;
- QQmlDebugStream rs(&reply, QIODevice::WriteOnly);
+ QPacket rs;
//unique queryId -1
rs << QByteArray("OBJECT_CREATED") << -1 << engineId << objectId << parentId;
- emit messageToClient(name(), reply);
+ emit messageToClient(name(), rs.data());
}
void QQmlEngineDebugServiceImpl::setStatesDelegate(QQmlDebugStatesDelegate *delegate)
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp
index bedabd0a63..14333e01f6 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp
@@ -36,7 +36,7 @@
#include <private/qv4engine_p.h>
#include <private/qv4function_p.h>
#include <private/qqmldebugconnector_p.h>
-
+#include <private/qpacket_p.h>
#include <private/qv8engine_p.h>
#include <QtCore/QJsonArray>
@@ -674,7 +674,7 @@ void QV4DebugServiceImpl::messageReceived(const QByteArray &message)
{
QMutexLocker lock(&m_configMutex);
- QQmlDebugStream ms(message);
+ QPacket ms(message);
QByteArray header;
ms >> header;
@@ -715,11 +715,10 @@ void QV4DebugServiceImpl::messageReceived(const QByteArray &message)
void QV4DebugServiceImpl::sendSomethingToSomebody(const char *type, int magicNumber)
{
- QByteArray response;
- QQmlDebugStream rs(&response, QIODevice::WriteOnly);
+ QPacket rs;
rs << QByteArray(type)
<< QByteArray::number(int(version())) << QByteArray::number(magicNumber);
- emit messageToClient(name(), packMessage(type, response));
+ emit messageToClient(name(), packMessage(type, rs.data()));
}
void QV4DebugServiceImpl::handleV8Request(const QByteArray &payload)
@@ -739,11 +738,10 @@ void QV4DebugServiceImpl::handleV8Request(const QByteArray &payload)
QByteArray QV4DebugServiceImpl::packMessage(const QByteArray &command, const QByteArray &message)
{
- QByteArray reply;
- QQmlDebugStream rs(&reply, QIODevice::WriteOnly);
+ QPacket rs;
static const QByteArray cmd("V8DEBUG");
rs << cmd << command << message;
- return reply;
+ return rs.data();
}
void QV4DebugServiceImpl::send(QJsonObject v8Payload)
diff --git a/src/plugins/qmltooling/qmldbg_inspector/abstractviewinspector.cpp b/src/plugins/qmltooling/qmldbg_inspector/abstractviewinspector.cpp
index fa6dca7aca..d1bba54969 100644
--- a/src/plugins/qmltooling/qmldbg_inspector/abstractviewinspector.cpp
+++ b/src/plugins/qmltooling/qmldbg_inspector/abstractviewinspector.cpp
@@ -40,6 +40,7 @@
#include <QtCore/private/qabstractanimation_p.h>
#include <QtQml/private/qqmldebugconnector_p.h>
#include <QtQml/private/qqmlcontext_p.h>
+#include <QtQml/private/qpacket_p.h>
#include <QtGui/QMouseEvent>
#include <QtGui/QTouchEvent>
@@ -262,18 +263,16 @@ void AbstractViewInspector::onQmlObjectDestroyed(QObject *object)
QPair<int, int> ids = m_hashObjectsTobeDestroyed.take(object);
- QByteArray response;
-
- QQmlDebugStream rs(&response, QIODevice::WriteOnly);
+ QPacket rs;
rs << QByteArray(RESPONSE) << ids.first << true << ids.second;
- emit m_debugService->messageToClient(m_debugService->name(), response);
+ emit m_debugService->messageToClient(m_debugService->name(), rs.data());
}
void AbstractViewInspector::handleMessage(const QByteArray &message)
{
bool success = true;
- QQmlDebugStream ds(message);
+ QPacket ds(message);
QByteArray type;
ds >> type;
@@ -358,16 +357,14 @@ void AbstractViewInspector::handleMessage(const QByteArray &message)
}
- QByteArray response;
- QQmlDebugStream rs(&response, QIODevice::WriteOnly);
+ QPacket rs;
rs << QByteArray(RESPONSE) << requestId << success;
- emit m_debugService->messageToClient(m_debugService->name(), response);
+ emit m_debugService->messageToClient(m_debugService->name(), rs.data());
}
void AbstractViewInspector::sendCurrentObjects(const QList<QObject*> &objects)
{
- QByteArray message;
- QQmlDebugStream ds(&message, QIODevice::WriteOnly);
+ QPacket ds;
ds << QByteArray(EVENT) << m_eventId++ << QByteArray(SELECT);
@@ -377,7 +374,7 @@ void AbstractViewInspector::sendCurrentObjects(const QList<QObject*> &objects)
debugIds << QQmlDebugService::idForObject(object);
ds << debugIds;
- emit m_debugService->messageToClient(m_debugService->name(), message);
+ emit m_debugService->messageToClient(m_debugService->name(), ds.data());
}
void AbstractViewInspector::sendQmlFileReloaded(bool success)
@@ -387,10 +384,10 @@ void AbstractViewInspector::sendQmlFileReloaded(bool success)
QByteArray response;
- QQmlDebugStream rs(&response, QIODevice::WriteOnly);
+ QPacket rs;
rs << QByteArray(RESPONSE) << m_reloadEventId << success;
- emit m_debugService->messageToClient(m_debugService->name(), response);
+ emit m_debugService->messageToClient(m_debugService->name(), rs.data());
}
QString AbstractViewInspector::idStringForObject(QObject *obj) const
diff --git a/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.cpp b/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.cpp
index 057bf9523e..478cbf5514 100644
--- a/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.cpp
+++ b/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.cpp
@@ -32,7 +32,6 @@
****************************************************************************/
#include "qlocalclientconnectionfactory.h"
-#include "qpacketprotocol.h"
#include "qqmldebugserver.h"
#include <QtCore/qplugin.h>
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlenginecontrolservice.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlenginecontrolservice.cpp
index 8f697f1571..b4dfa86e56 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qqmlenginecontrolservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlenginecontrolservice.cpp
@@ -33,6 +33,7 @@
#include "qqmlenginecontrolservice.h"
#include <QQmlEngine>
+#include <private/qpacket_p.h>
QT_BEGIN_NAMESPACE
@@ -44,7 +45,7 @@ QQmlEngineControlServiceImpl::QQmlEngineControlServiceImpl(QObject *parent) :
void QQmlEngineControlServiceImpl::messageReceived(const QByteArray &message)
{
QMutexLocker lock(&dataMutex);
- QQmlDebugStream d(message);
+ QPacket d(message);
int command;
int engineId;
d >> command >> engineId;
@@ -106,10 +107,9 @@ void QQmlEngineControlServiceImpl::engineRemoved(QQmlEngine *engine)
void QQmlEngineControlServiceImpl::sendMessage(QQmlEngineControlServiceImpl::MessageType type, QQmlEngine *engine)
{
- QByteArray message;
- QQmlDebugStream d(&message, QIODevice::WriteOnly);
+ QPacket d;
d << type << idForObject(engine);
- emit messageToClient(name(), message);
+ emit messageToClient(name(), d.data());
}
void QQmlEngineControlServiceImpl::stateChanged(State)
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp
index 245900abae..8879cc4037 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp
@@ -33,6 +33,7 @@
#include "qqmlprofileradapter.h"
#include <private/qqmldebugserviceinterfaces_p.h>
+#include <private/qpacket_p.h>
QT_BEGIN_NAMESPACE
@@ -72,7 +73,7 @@ static void qQmlProfilerDataToByteArrays(const QQmlProfilerData *d, QList<QByteA
continue;
//### using QDataStream is relatively expensive
- QQmlDebugStream ds(&data, QIODevice::WriteOnly);
+ QPacket ds;
ds << d->time << decodedMessageType << decodedDetailType;
switch (decodedMessageType) {
@@ -92,8 +93,7 @@ static void qQmlProfilerDataToByteArrays(const QQmlProfilerData *d, QList<QByteA
Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid message type.");
break;
}
- messages << data;
- data.clear();
+ messages << ds.data();
}
}
}
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp
index 65b99ef7ca..2ce5610c7e 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp
@@ -36,6 +36,7 @@
#include "qqmlprofileradapter.h"
#include "qqmlprofilerservicefactory.h"
#include <private/qqmlengine_p.h>
+#include <private/qpacket_p.h>
#include <QtCore/qdatastream.h>
#include <QtCore/qurl.h>
@@ -202,8 +203,7 @@ void QQmlProfilerServiceImpl::startProfiling(QQmlEngine *engine, quint64 feature
{
QMutexLocker lock(&m_configMutex);
- QByteArray message;
- QQmlDebugStream d(&message, QIODevice::WriteOnly);
+ QPacket d;
d << m_timer.nsecsElapsed() << (int)Event << (int)StartTrace;
bool startedAny = false;
@@ -239,7 +239,7 @@ void QQmlProfilerServiceImpl::startProfiling(QQmlEngine *engine, quint64 feature
emit startFlushTimer();
}
- emit messageToClient(name(), message);
+ emit messageToClient(name(), d.data());
}
/*!
@@ -299,10 +299,8 @@ void QQmlProfilerServiceImpl::sendMessages()
{
QList<QByteArray> messages;
- QByteArray data;
-
+ QPacket traceEnd;
if (m_waitingForStop) {
- QQmlDebugStream traceEnd(&data, QIODevice::WriteOnly);
traceEnd << m_timer.nsecsElapsed() << (int)Event << (int)EndTrace;
QSet<QQmlEngine *> seen;
@@ -331,12 +329,11 @@ void QQmlProfilerServiceImpl::sendMessages()
if (m_waitingForStop) {
//indicate completion
- messages << data;
- data.clear();
+ messages << traceEnd.data();
- QQmlDebugStream ds(&data, QIODevice::WriteOnly);
+ QPacket ds;
ds << (qint64)-1 << (int)Complete;
- messages << data;
+ messages << ds.data();
m_waitingForStop = false;
}
@@ -369,8 +366,7 @@ void QQmlProfilerServiceImpl::messageReceived(const QByteArray &message)
{
QMutexLocker lock(&m_configMutex);
- QByteArray rwData = message;
- QQmlDebugStream stream(&rwData, QIODevice::ReadOnly);
+ QPacket stream(message);
int engineId = -1;
quint64 features = std::numeric_limits<quint64>::max();
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp
index 3498555f65..991ef4b6ba 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp
+++ b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp
@@ -34,6 +34,8 @@
#include "qv4profileradapter.h"
#include "qqmlprofilerservice.h"
+#include <private/qpacket_p.h>
+
QT_BEGIN_NAMESPACE
QV4ProfilerAdapter::QV4ProfilerAdapter(QQmlProfilerService *service, QV4::ExecutionEngine *engine) :
@@ -62,13 +64,12 @@ QV4ProfilerAdapter::QV4ProfilerAdapter(QQmlProfilerService *service, QV4::Execut
qint64 QV4ProfilerAdapter::appendMemoryEvents(qint64 until, QList<QByteArray> &messages)
{
- QByteArray message;
while (m_memoryData.length() > m_memoryPos && m_memoryData[m_memoryPos].timestamp <= until) {
- QQmlDebugStream d(&message, QIODevice::WriteOnly);
+ QPacket d;
QV4::Profiling::MemoryAllocationProperties &props = m_memoryData[m_memoryPos];
d << props.timestamp << MemoryAllocation << props.type << props.size;
++m_memoryPos;
- messages.append(message);
+ messages.append(d.data());
}
return m_memoryData.length() == m_memoryPos ? -1 : m_memoryData[m_memoryPos].timestamp;
}
@@ -94,7 +95,6 @@ qint64 QV4ProfilerAdapter::finalizeMessages(qint64 until, QList<QByteArray> &mes
qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages)
{
- QByteArray message;
while (true) {
while (!m_stack.isEmpty() &&
(m_functionCallPos == m_functionCallData.length() ||
@@ -103,9 +103,9 @@ qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &message
return finalizeMessages(until, messages, m_stack.top());
appendMemoryEvents(m_stack.top(), messages);
- QQmlDebugStream d(&message, QIODevice::WriteOnly);
+ QPacket d;
d << m_stack.pop() << RangeEnd << Javascript;
- messages.append(message);
+ messages.append(d.data());
}
while (m_functionCallPos != m_functionCallData.length() &&
(m_stack.empty() || m_functionCallData[m_functionCallPos].start < m_stack.top())) {
@@ -116,19 +116,16 @@ qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &message
appendMemoryEvents(props.start, messages);
- QQmlDebugStream d_start(&message, QIODevice::WriteOnly);
+ QPacket d_start;
d_start << props.start << RangeStart << Javascript;
- messages.push_back(message);
- message.clear();
- QQmlDebugStream d_location(&message, QIODevice::WriteOnly);
+ messages.push_back(d_start.data());
+ QPacket d_location;
d_location << props.start << RangeLocation << Javascript << props.file << props.line
<< props.column;
- messages.push_back(message);
- message.clear();
- QQmlDebugStream d_data(&message, QIODevice::WriteOnly);
+ messages.push_back(d_location.data());
+ QPacket d_data;
d_data << props.start << RangeData << Javascript << props.name;
- messages.push_back(message);
- message.clear();
+ messages.push_back(d_data.data());
m_stack.push(props.end);
++m_functionCallPos;
}
diff --git a/src/plugins/qmltooling/qmldbg_server/qmldbg_server.pro b/src/plugins/qmltooling/qmldbg_server/qmldbg_server.pro
index 5e2d0874df..7347a7598f 100644
--- a/src/plugins/qmltooling/qmldbg_server/qmldbg_server.pro
+++ b/src/plugins/qmltooling/qmldbg_server/qmldbg_server.pro
@@ -1,5 +1,5 @@
TARGET = qmldbg_server
-QT = qml-private core-private
+QT = qml-private packetprotocol-private
PLUGIN_TYPE = qmltooling
PLUGIN_CLASS_NAME = QQmlDebugServerFactory
@@ -7,12 +7,10 @@ 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 d3a8d1f0d1..bfbeef5856 100644
--- a/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp
+++ b/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp
@@ -33,7 +33,6 @@
#include "qqmldebugserver.h"
#include "qqmldebugserverfactory.h"
-#include "qpacketprotocol.h"
#include "qqmldebugserverconnection.h"
#include <private/qqmldebugservice_p.h>
@@ -41,6 +40,8 @@
#include <private/qqmlglobal_p.h>
#include <private/qqmldebugpluginmanager_p.h>
#include <private/qqmldebugserviceinterfaces_p.h>
+#include <private/qpacketprotocol_p.h>
+#include <private/qpacket_p.h>
#include <QtCore/QAtomicInt>
#include <QtCore/QDir>
@@ -48,9 +49,6 @@
#include <QtCore/QStringList>
#include <QtCore/qwaitcondition.h>
-#include <private/qobject_p.h>
-#include <private/qcoreapplication_p.h>
-
QT_BEGIN_NAMESPACE
/*
@@ -431,7 +429,7 @@ void QQmlDebugServerImpl::receiveMessage()
if (!m_protocol)
return;
- QQmlDebugStream in(m_protocol->read().data());
+ QPacket in(m_protocol->read().data());
QString name;
@@ -445,16 +443,17 @@ void QQmlDebugServerImpl::receiveMessage()
//Get the supported QDataStream version
if (!in.atEnd()) {
- in >> QQmlDebugStream::s_dataStreamVersion;
- if (QQmlDebugStream::s_dataStreamVersion > QDataStream().version())
- QQmlDebugStream::s_dataStreamVersion = QDataStream().version();
+ int dataStreamVersion;
+ in >> dataStreamVersion;
+ if (dataStreamVersion > QDataStream().version())
+ dataStreamVersion = QDataStream().version();
+ QPacket::setDataStreamVersion(dataStreamVersion);
}
// Send the hello answer immediately, since it needs to arrive before
// the plugins below start sending messages.
- QByteArray helloAnswer;
- QQmlDebugStream out(&helloAnswer, QIODevice::WriteOnly);
+ QPacket out;
QStringList pluginNames;
QList<float> pluginVersions;
const int count = m_plugins.count();
@@ -467,11 +466,9 @@ void QQmlDebugServerImpl::receiveMessage()
}
out << QString(QStringLiteral("QDeclarativeDebugClient")) << 0 << protocolVersion
- << pluginNames << pluginVersions << QQmlDebugStream::s_dataStreamVersion;
+ << pluginNames << pluginVersions << QPacket::dataStreamVersion();
- QPacket pack;
- pack.writeRawData(helloAnswer.data(), helloAnswer.length());
- m_protocol->send(pack);
+ m_protocol->send(out);
m_connection->flush();
QMutexLocker helloLock(&m_helloMutex);
@@ -653,13 +650,9 @@ bool QQmlDebugServerImpl::canSendMessage(const QString &name)
void QQmlDebugServerImpl::doSendMessage(const QString &name, const QByteArray &message)
{
- QByteArray prefixed;
- QQmlDebugStream out(&prefixed, QIODevice::WriteOnly);
+ QPacket out;
out << name << message;
-
- QPacket pack;
- pack.writeRawData(prefixed.data(), prefixed.length());
- m_protocol->send(pack);
+ m_protocol->send(out);
}
void QQmlDebugServerImpl::sendMessage(const QString &name, const QByteArray &message)
diff --git a/src/plugins/qmltooling/qmltooling.pro b/src/plugins/qmltooling/qmltooling.pro
index e00e75599b..75da89f3e8 100644
--- a/src/plugins/qmltooling/qmltooling.pro
+++ b/src/plugins/qmltooling/qmltooling.pro
@@ -8,7 +8,10 @@ SUBDIRS += \
# Services
SUBDIRS += \
+ packetprotocol \
qmldbg_debugger \
qmldbg_profiler
+qmldbg_server.depends = packetprotocol
+
qtHaveModule(quick): SUBDIRS += qmldbg_inspector
diff --git a/src/plugins/qmltooling/shared/qpacketprotocol.cpp b/src/plugins/qmltooling/shared/qpacketprotocol.cpp
deleted file mode 100644
index 9a58f803c1..0000000000
--- a/src/plugins/qmltooling/shared/qpacketprotocol.cpp
+++ /dev/null
@@ -1,531 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** 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 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qpacketprotocol.h"
-
-#include <QtCore/QBuffer>
-#include <QtCore/QElapsedTimer>
-#include <private/qiodevice_p.h>
-
-QT_BEGIN_NAMESPACE
-
-static const unsigned int MAX_PACKET_SIZE = 0x7FFFFFFF;
-
-/*!
- \class QPacketProtocol
- \internal
-
- \brief The QPacketProtocol class encapsulates communicating discrete packets
- across fragmented IO channels, such as TCP sockets.
-
- QPacketProtocol makes it simple to send arbitrary sized data "packets" across
- fragmented transports such as TCP and UDP.
-
- As transmission boundaries are not respected, sending packets over protocols
- like TCP frequently involves "stitching" them back together at the receiver.
- QPacketProtocol makes this easier by performing this task for you. Packet
- data sent using QPacketProtocol is prepended with a 4-byte size header
- allowing the receiving QPacketProtocol to buffer the packet internally until
- it has all been received. QPacketProtocol does not perform any sanity
- checking on the size or on the data, so this class should only be used in
- prototyping or trusted situations where DOS attacks are unlikely.
-
- QPacketProtocol does not perform any communications itself. Instead it can
- operate on any QIODevice that supports the QIODevice::readyRead() signal. A
- logical "packet" is encapsulated by the companion QPacket class. The
- following example shows two ways to send data using QPacketProtocol. The
- transmitted data is equivalent in both.
-
- \code
- QTcpSocket socket;
- // ... connect socket ...
-
- QPacketProtocol protocol(&socket);
-
- // Send packet the quick way
- protocol.send() << "Hello world" << 123;
-
- // Send packet the longer way
- QPacket packet;
- packet << "Hello world" << 123;
- protocol.send(packet);
- \endcode
-
- Likewise, the following shows how to read data from QPacketProtocol, assuming
- that the QPacketProtocol::readyRead() signal has been emitted.
-
- \code
- // ... QPacketProtocol::readyRead() is emitted ...
-
- int a;
- QByteArray b;
-
- // Receive packet the quick way
- protocol.read() >> a >> b;
-
- // Receive packet the longer way
- QPacket packet = protocol.read();
- p >> a >> b;
- \endcode
-
- \ingroup io
- \sa QPacket
-*/
-
-class QPacketProtocolPrivate : public QObject
-{
- Q_OBJECT
-public:
- QPacketProtocolPrivate(QPacketProtocol *parent, QIODevice *_dev)
- : QObject(parent), inProgressSize(-1), maxPacketSize(MAX_PACKET_SIZE),
- waitingForPacket(false), dev(_dev)
- {
- Q_ASSERT(4 == sizeof(qint32));
-
- QObject::connect(this, SIGNAL(readyRead()),
- parent, SIGNAL(readyRead()));
- QObject::connect(this, SIGNAL(packetWritten()),
- parent, SIGNAL(packetWritten()));
- QObject::connect(this, SIGNAL(invalidPacket()),
- parent, SIGNAL(invalidPacket()));
- QObject::connect(dev, SIGNAL(readyRead()),
- this, SLOT(readyToRead()));
- QObject::connect(dev, SIGNAL(aboutToClose()),
- this, SLOT(aboutToClose()));
- QObject::connect(dev, SIGNAL(bytesWritten(qint64)),
- this, SLOT(bytesWritten(qint64)));
- }
-
-Q_SIGNALS:
- void readyRead();
- void packetWritten();
- void invalidPacket();
-
-public Q_SLOTS:
- void aboutToClose()
- {
- inProgress.clear();
- sendingPackets.clear();
- inProgressSize = -1;
- }
-
- void bytesWritten(qint64 bytes)
- {
- Q_ASSERT(!sendingPackets.isEmpty());
-
- while (bytes) {
- if (sendingPackets.at(0) > bytes) {
- sendingPackets[0] -= bytes;
- bytes = 0;
- } else {
- bytes -= sendingPackets.at(0);
- sendingPackets.removeFirst();
- emit packetWritten();
- }
- }
- }
-
- void readyToRead()
- {
- while (true) {
- // Need to get trailing data
- if (-1 == inProgressSize) {
- // We need a size header of sizeof(qint32)
- if (sizeof(qint32) > (uint)dev->bytesAvailable())
- return;
-
- // Read size header
- int read = dev->read((char *)&inProgressSize, sizeof(qint32));
- Q_ASSERT(read == sizeof(qint32));
- Q_UNUSED(read);
-
- // Check sizing constraints
- if (inProgressSize > maxPacketSize) {
- QObject::disconnect(dev, SIGNAL(readyRead()),
- this, SLOT(readyToRead()));
- QObject::disconnect(dev, SIGNAL(aboutToClose()),
- this, SLOT(aboutToClose()));
- QObject::disconnect(dev, SIGNAL(bytesWritten(qint64)),
- this, SLOT(bytesWritten(qint64)));
- dev = 0;
- emit invalidPacket();
- return;
- }
-
- inProgressSize -= sizeof(qint32);
- } else {
- inProgress.append(dev->read(inProgressSize - inProgress.size()));
-
- if (inProgressSize == inProgress.size()) {
- // Packet has arrived!
- packets.append(inProgress);
- inProgressSize = -1;
- inProgress.clear();
-
- waitingForPacket = false;
- emit readyRead();
- } else
- return;
- }
- }
- }
-
-public:
- QList<qint64> sendingPackets;
- QList<QByteArray> packets;
- QByteArray inProgress;
- qint32 inProgressSize;
- qint32 maxPacketSize;
- bool waitingForPacket;
- QIODevice *dev;
-};
-
-/*!
- Construct a QPacketProtocol instance that works on \a dev with the
- specified \a parent.
- */
-QPacketProtocol::QPacketProtocol(QIODevice *dev, QObject *parent)
- : QObject(parent), d(new QPacketProtocolPrivate(this, dev))
-{
- Q_ASSERT(dev);
-}
-
-/*!
- Destroys the QPacketProtocol instance.
- */
-QPacketProtocol::~QPacketProtocol()
-{
-}
-
-/*!
- Returns the maximum packet size allowed. By default this is
- 2,147,483,647 bytes.
-
- If a packet claiming to be larger than the maximum packet size is received,
- the QPacketProtocol::invalidPacket() signal is emitted.
-
- \sa QPacketProtocol::setMaximumPacketSize()
- */
-qint32 QPacketProtocol::maximumPacketSize() const
-{
- return d->maxPacketSize;
-}
-
-/*!
- Sets the maximum allowable packet size to \a max.
-
- \sa QPacketProtocol::maximumPacketSize()
- */
-qint32 QPacketProtocol::setMaximumPacketSize(qint32 max)
-{
- if (max > (signed)sizeof(qint32))
- d->maxPacketSize = max;
- return d->maxPacketSize;
-}
-
-/*!
- Returns a streamable object that is transmitted on destruction. For example
-
- \code
- protocol.send() << "Hello world" << 123;
- \endcode
-
- will send a packet containing "Hello world" and 123. To construct more
- complex packets, explicitly construct a QPacket instance.
- */
-QPacketAutoSend QPacketProtocol::send()
-{
- return QPacketAutoSend(this);
-}
-
-/*!
- \fn void QPacketProtocol::send(const QPacket & packet)
-
- Transmit the \a packet.
- */
-void QPacketProtocol::send(const QPacket & p)
-{
- if (p.b.isEmpty())
- return; // We don't send empty packets
-
- qint64 sendSize = p.b.size() + sizeof(qint32);
-
- d->sendingPackets.append(sendSize);
- qint32 sendSize32 = sendSize;
- qint64 writeBytes = d->dev->write((char *)&sendSize32, sizeof(qint32));
- Q_UNUSED(writeBytes);
- Q_ASSERT(writeBytes == sizeof(qint32));
- writeBytes = d->dev->write(p.b);
- Q_ASSERT(writeBytes == p.b.size());
-}
-
-/*!
- Returns the number of received packets yet to be read.
- */
-qint64 QPacketProtocol::packetsAvailable() const
-{
- return d->packets.count();
-}
-
-/*!
- Discard any unread packets.
- */
-void QPacketProtocol::clear()
-{
- d->packets.clear();
-}
-
-/*!
- Return the next unread packet, or an invalid QPacket instance if no packets
- are available. This method does NOT block.
- */
-QPacket QPacketProtocol::read()
-{
- if (0 == d->packets.count())
- return QPacket();
-
- QPacket rv(d->packets.at(0));
- d->packets.removeFirst();
- return rv;
-}
-
-/*!
- This function locks until a new packet is available for reading and the
- \l{QIODevice::}{readyRead()} signal has been emitted. The function
- will timeout after \a msecs milliseconds; the default timeout is
- 30000 milliseconds.
-
- The function returns true if the readyRead() signal is emitted and
- there is new data available for reading; otherwise it returns false
- (if an error occurred or the operation timed out).
- */
-
-bool QPacketProtocol::waitForReadyRead(int msecs)
-{
- if (!d->packets.isEmpty())
- return true;
-
- QElapsedTimer stopWatch;
- stopWatch.start();
-
- d->waitingForPacket = true;
- do {
- if (!d->dev->waitForReadyRead(msecs))
- return false;
- if (!d->waitingForPacket)
- return true;
- msecs = qt_subtract_from_timeout(msecs, stopWatch.elapsed());
- } while (true);
-}
-
-/*!
- Return the QIODevice passed to the QPacketProtocol constructor.
-*/
-QIODevice *QPacketProtocol::device()
-{
- return d->dev;
-}
-
-/*!
- \fn void QPacketProtocol::readyRead()
-
- Emitted whenever a new packet is received. Applications may use
- QPacketProtocol::read() to retrieve this packet.
- */
-
-/*!
- \fn void QPacketProtocol::invalidPacket()
-
- A packet larger than the maximum allowable packet size was received. The
- packet will be discarded and, as it indicates corruption in the protocol, no
- further packets will be received.
- */
-
-/*!
- \fn void QPacketProtocol::packetWritten()
-
- Emitted each time a packet is completing written to the device. This signal
- may be used for communications flow control.
- */
-
-/*!
- \class QPacket
- \internal
-
- \brief The QPacket class encapsulates an unfragmentable packet of data to be
- transmitted by QPacketProtocol.
-
- The QPacket class works together with QPacketProtocol to make it simple to
- send arbitrary sized data "packets" across fragmented transports such as TCP
- and UDP.
-
- QPacket provides a QDataStream interface to an unfragmentable packet.
- Applications should construct a QPacket, propagate it with data and then
- transmit it over a QPacketProtocol instance. For example:
- \code
- QPacketProtocol protocol(...);
-
- QPacket myPacket;
- myPacket << "Hello world!" << 123;
- protocol.send(myPacket);
- \endcode
-
- As long as both ends of the connection are using the QPacketProtocol class,
- the data within this packet will be delivered unfragmented at the other end,
- ready for extraction.
-
- \code
- QByteArray greeting;
- int count;
-
- QPacket myPacket = protocol.read();
-
- myPacket >> greeting >> count;
- \endcode
-
- Only packets returned from QPacketProtocol::read() may be read from. QPacket
- instances constructed by directly by applications are for transmission only
- and are considered "write only". Attempting to read data from them will
- result in undefined behavior.
-
- \ingroup io
- \sa QPacketProtocol
- */
-
-/*!
- Constructs an empty write-only packet.
- */
-QPacket::QPacket()
- : QDataStream(), buf(0)
-{
- buf = new QBuffer(&b);
- buf->open(QIODevice::WriteOnly);
- setDevice(buf);
- setVersion(QDataStream::Qt_4_7);
-}
-
-/*!
- Destroys the QPacket instance.
- */
-QPacket::~QPacket()
-{
- if (buf) {
- delete buf;
- buf = 0;
- }
-}
-
-/*!
- Creates a copy of \a other. The initial stream positions are shared, but the
- two packets are otherwise independent.
- */
-QPacket::QPacket(const QPacket & other)
- : QDataStream(), b(other.b), buf(0)
-{
- buf = new QBuffer(&b);
- buf->open(other.buf->openMode());
- setDevice(buf);
-}
-
-/*!
- \internal
- */
-QPacket::QPacket(const QByteArray & ba)
- : QDataStream(), b(ba), buf(0)
-{
- buf = new QBuffer(&b);
- buf->open(QIODevice::ReadOnly);
- setDevice(buf);
-}
-
-/*!
- Returns true if this packet is empty - that is, contains no data.
- */
-bool QPacket::isEmpty() const
-{
- return b.isEmpty();
-}
-
-/*!
- Returns raw packet data.
- */
-QByteArray QPacket::data() const
-{
- return b;
-}
-
-/*!
- Clears data in the packet. This is useful for reusing one writable packet.
- For example
- \code
- QPacketProtocol protocol(...);
-
- QPacket packet;
-
- packet << "Hello world!" << 123;
- protocol.send(packet);
-
- packet.clear();
- packet << "Goodbyte world!" << 789;
- protocol.send(packet);
- \endcode
- */
-void QPacket::clear()
-{
- QBuffer::OpenMode oldMode = buf->openMode();
- buf->close();
- b.clear();
- buf->setBuffer(&b); // reset QBuffer internals with new size of b.
- buf->open(oldMode);
-}
-
-/*!
- \class QPacketAutoSend
- \internal
-
- \internal
- */
-QPacketAutoSend::QPacketAutoSend(QPacketProtocol *_p)
- : QPacket(), p(_p)
-{
-}
-
-QPacketAutoSend::~QPacketAutoSend()
-{
- if (!b.isEmpty())
- p->send(*this);
-}
-
-QT_END_NAMESPACE
-
-#include <qpacketprotocol.moc>
diff --git a/src/qml/debugger/debugger.pri b/src/qml/debugger/debugger.pri
index 30a44eedd1..62b375f72f 100644
--- a/src/qml/debugger/debugger.pri
+++ b/src/qml/debugger/debugger.pri
@@ -6,7 +6,8 @@ SOURCES += \
$$PWD/qqmldebugservice.cpp \
$$PWD/qqmldebugserviceinterfaces.cpp \
$$PWD/qqmlabstractprofileradapter.cpp \
- $$PWD/qqmlprofiler.cpp
+ $$PWD/qqmlprofiler.cpp \
+ $$PWD/qpacket.cpp
HEADERS += \
$$PWD/qqmldebugconnector_p.h \
@@ -18,6 +19,7 @@ HEADERS += \
$$PWD/qqmldebug.h \
$$PWD/qqmlprofilerdefinitions_p.h \
$$PWD/qqmlabstractprofileradapter_p.h \
- $$PWD/qqmlprofiler_p.h
+ $$PWD/qqmlprofiler_p.h \
+ $$PWD/qpacket_p.h
INCLUDEPATH += $$PWD
diff --git a/src/qml/debugger/qpacket.cpp b/src/qml/debugger/qpacket.cpp
new file mode 100644
index 0000000000..30f2191689
--- /dev/null
+++ b/src/qml/debugger/qpacket.cpp
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** 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 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qpacket_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QPacket
+ \internal
+
+ \brief The QPacket class encapsulates an unfragmentable packet of data to be
+ transmitted by QPacketProtocol.
+
+ The QPacket class works together with QPacketProtocol to make it simple to
+ send arbitrary sized data "packets" across fragmented transports such as TCP
+ and UDP.
+
+ QPacket provides a QDataStream interface to an unfragmentable packet.
+ Applications should construct a QPacket, propagate it with data and then
+ transmit it over a QPacketProtocol instance. For example:
+ \code
+ QPacketProtocol protocol(...);
+
+ QPacket myPacket;
+ myPacket << "Hello world!" << 123;
+ protocol.send(myPacket);
+ \endcode
+
+ As long as both ends of the connection are using the QPacketProtocol class,
+ the data within this packet will be delivered unfragmented at the other end,
+ ready for extraction.
+
+ \code
+ QByteArray greeting;
+ int count;
+
+ QPacket myPacket = protocol.read();
+
+ myPacket >> greeting >> count;
+ \endcode
+
+ Only packets constructed from raw byte arrays may be read from. Empty QPacket
+ instances are for transmission only and are considered "write only". Attempting
+ to read data from them will result in undefined behavior.
+
+ \ingroup io
+ \sa QPacketProtocol
+ */
+
+int QPacket::s_dataStreamVersion = QDataStream::Qt_4_7;
+
+void QPacket::setDataStreamVersion(int dataStreamVersion)
+{
+ s_dataStreamVersion = dataStreamVersion;
+}
+
+int QPacket::dataStreamVersion()
+{
+ return s_dataStreamVersion;
+}
+
+/*!
+ Constructs an empty write-only packet.
+ */
+QPacket::QPacket()
+{
+ init(QIODevice::WriteOnly);
+}
+
+/*!
+ Creates a copy of \a other. The initial stream positions are shared, but the
+ two packets are otherwise independent.
+ */
+QPacket::QPacket(const QPacket &other) : QDataStream()
+{
+ assign(other);
+}
+
+QPacket &QPacket::operator=(const QPacket &other)
+{
+ if (this != &other) {
+ buf.close();
+ assign(other);
+ }
+ return *this;
+}
+
+QPacket::QPacket(const QByteArray &data)
+{
+ buf.setData(data);
+ init(QIODevice::ReadOnly);
+}
+
+/*!
+ Returns raw packet data.
+ */
+QByteArray QPacket::data() const
+{
+ return buf.data();
+}
+
+void QPacket::init(QIODevice::OpenMode mode)
+{
+ buf.open(mode);
+ setDevice(&buf);
+ setVersion(s_dataStreamVersion);
+}
+
+void QPacket::assign(const QPacket &other)
+{
+ buf.setData(other.buf.data());
+ init(other.buf.openMode());
+ buf.seek(other.buf.pos());
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/shared/qpacketprotocol.h b/src/qml/debugger/qpacket_p.h
index c571e8d2b8..759ed25145 100644
--- a/src/plugins/qmltooling/shared/qpacketprotocol.h
+++ b/src/qml/debugger/qpacket_p.h
@@ -31,81 +31,46 @@
**
****************************************************************************/
-#ifndef QPACKETPROTOCOL_H
-#define QPACKETPROTOCOL_H
+#ifndef QPACKET_P_H
+#define QPACKET_P_H
-#include <QtCore/qobject.h>
#include <QtCore/qdatastream.h>
+#include <QtCore/qbuffer.h>
+#include <QtQml/private/qtqmlglobal_p.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
QT_BEGIN_NAMESPACE
-class QIODevice;
-class QBuffer;
-class QPacket;
-class QPacketAutoSend;
-class QPacketProtocolPrivate;
-
-class QPacketProtocol : public QObject
-{
- Q_OBJECT
-public:
- explicit QPacketProtocol(QIODevice *dev, QObject *parent = 0);
- virtual ~QPacketProtocol();
-
- qint32 maximumPacketSize() const;
- qint32 setMaximumPacketSize(qint32);
-
- QPacketAutoSend send();
- void send(const QPacket &);
-
- qint64 packetsAvailable() const;
- QPacket read();
-
- bool waitForReadyRead(int msecs = 3000);
-
- void clear();
-
- QIODevice *device();
-
-Q_SIGNALS:
- void readyRead();
- void invalidPacket();
- void packetWritten();
-
-private:
- QPacketProtocolPrivate *d;
-};
-
-
-class QPacket : public QDataStream
+class Q_QML_PRIVATE_EXPORT QPacket : public QDataStream
{
public:
QPacket();
- QPacket(const QPacket &);
- virtual ~QPacket();
+ QPacket(const QPacket &other);
+ explicit QPacket(const QByteArray &ba);
+ QPacket &operator=(const QPacket &other);
- void clear();
- bool isEmpty() const;
QByteArray data() const;
-protected:
- friend class QPacketProtocol;
- QPacket(const QByteArray &ba);
- QByteArray b;
- QBuffer *buf;
-};
-
-class QPacketAutoSend : public QPacket
-{
-public:
- virtual ~QPacketAutoSend();
+ static int dataStreamVersion();
+ static void setDataStreamVersion(int dataStreamVersion);
private:
- friend class QPacketProtocol;
- QPacketAutoSend(QPacketProtocol *);
- QPacketProtocol *p;
+ static int s_dataStreamVersion;
+ void init(QIODevice::OpenMode mode);
+ void assign(const QPacket &other);
+ QBuffer buf;
};
QT_END_NAMESPACE
-#endif
+#endif // QPACKET_P_H
diff --git a/src/qml/debugger/qqmldebugservice.cpp b/src/qml/debugger/qqmldebugservice.cpp
index 0b07f320ec..bbcf67a54b 100644
--- a/src/qml/debugger/qqmldebugservice.cpp
+++ b/src/qml/debugger/qqmldebugservice.cpp
@@ -200,32 +200,6 @@ void QQmlDebugService::engineRemoved(QQmlEngine *)
{
}
-int QQmlDebugStream::s_dataStreamVersion = QDataStream::Qt_4_7;
-
-QQmlDebugStream::QQmlDebugStream()
- : QDataStream()
-{
- setVersion(s_dataStreamVersion);
-}
-
-QQmlDebugStream::QQmlDebugStream(QIODevice *d)
- : QDataStream(d)
-{
- setVersion(s_dataStreamVersion);
-}
-
-QQmlDebugStream::QQmlDebugStream(QByteArray *ba, QIODevice::OpenMode flags)
- : QDataStream(ba, flags)
-{
- setVersion(s_dataStreamVersion);
-}
-
-QQmlDebugStream::QQmlDebugStream(const QByteArray &ba)
- : QDataStream(ba)
-{
- setVersion(s_dataStreamVersion);
-}
-
QT_END_NAMESPACE
#include "qqmldebugservice.moc"
diff --git a/src/qml/debugger/qqmldebugservice_p.h b/src/qml/debugger/qqmldebugservice_p.h
index 3d692133cc..8b58f57349 100644
--- a/src/qml/debugger/qqmldebugservice_p.h
+++ b/src/qml/debugger/qqmldebugservice_p.h
@@ -96,17 +96,6 @@ signals:
void messagesToClient(const QString &name, const QList<QByteArray> &messages);
};
-class Q_QML_PRIVATE_EXPORT QQmlDebugStream : public QDataStream
-{
-public:
- static int s_dataStreamVersion;
-
- QQmlDebugStream();
- explicit QQmlDebugStream(QIODevice *d);
- QQmlDebugStream(QByteArray *ba, QIODevice::OpenMode flags);
- QQmlDebugStream(const QByteArray &ba);
-};
-
QT_END_NAMESPACE
#endif // QQMLDEBUGSERVICE_H
diff --git a/src/quick/util/qquickprofiler.cpp b/src/quick/util/qquickprofiler.cpp
index 77ffda474a..44fdbc5da8 100644
--- a/src/quick/util/qquickprofiler.cpp
+++ b/src/quick/util/qquickprofiler.cpp
@@ -34,6 +34,7 @@
#include "qquickprofiler_p.h"
#include <QCoreApplication>
#include <private/qqmldebugserviceinterfaces_p.h>
+#include <private/qpacket_p.h>
QT_BEGIN_NAMESPACE
@@ -46,7 +47,6 @@ quint64 QQuickProfiler::featuresEnabled = 0;
// (see tst_qqmldebugtrace::trace() benchmark)
void QQuickProfilerData::toByteArrays(QList<QByteArray> &messages) const
{
- QByteArray data;
Q_ASSERT_X(((messageType | detailType) & (1 << 31)) == 0, Q_FUNC_INFO, "You can use at most 31 message types and 31 detail types.");
for (uint decodedMessageType = 0; (messageType >> decodedMessageType) != 0; ++decodedMessageType) {
if ((messageType & (1 << decodedMessageType)) == 0)
@@ -57,7 +57,7 @@ void QQuickProfilerData::toByteArrays(QList<QByteArray> &messages) const
continue;
//### using QDataStream is relatively expensive
- QQmlDebugStream ds(&data, QIODevice::WriteOnly);
+ QPacket ds;
ds << time << decodedMessageType << decodedDetailType;
switch (decodedMessageType) {
@@ -103,8 +103,7 @@ void QQuickProfilerData::toByteArrays(QList<QByteArray> &messages) const
Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid message type.");
break;
}
- messages << data;
- data.clear();
+ messages << ds.data();
}
}
}
diff --git a/sync.profile b/sync.profile
index 28d0698da9..6695d98f27 100644
--- a/sync.profile
+++ b/sync.profile
@@ -5,6 +5,7 @@
"QtQuickParticles" => "$basedir/src/particles",
"QtQuickTest" => "$basedir/src/qmltest",
"QtQmlDevTools" => "$basedir/src/qmldevtools",
+ "QtPacketProtocol" => "$basedir/src/plugins/qmltooling/packetprotocol",
);
%moduleheaders = ( # restrict the module headers to those found in relative path
"QtQmlDevTools" => "../qml/parser;../qml/jsruntime;../qml/qml/ftw;../qml/compiler;../qml/memory;.",
diff --git a/tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp b/tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp
index db9e621d54..816ac3f278 100644
--- a/tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp
+++ b/tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp
@@ -38,7 +38,8 @@
#include <QDebug>
#include <QBuffer>
-#include "../../../../../src/plugins/qmltooling/shared/qpacketprotocol.h"
+#include <private/qpacketprotocol_p.h>
+#include <private/qpacket_p.h>
#include "debugutil_p.h"
@@ -55,18 +56,10 @@ private slots:
void init();
void cleanup();
- void maximumPacketSize();
- void setMaximumPacketSize();
- void setMaximumPacketSize_data();
void send();
- void send_data();
void packetsAvailable();
void packetsAvailable_data();
- void clear();
void read();
- void device();
-
- void tst_QPacket_clear();
};
void tst_QPacketProtocol::init()
@@ -95,48 +88,17 @@ void tst_QPacketProtocol::cleanup()
delete m_server;
}
-void tst_QPacketProtocol::maximumPacketSize()
-{
- QPacketProtocol p(m_client);
- QCOMPARE(p.maximumPacketSize(), 0x7FFFFFFF);
-}
-
-void tst_QPacketProtocol::setMaximumPacketSize()
-{
- QFETCH(qint32, size);
- QFETCH(qint32, expected);
-
- QPacketProtocol out(m_serverConn);
- QCOMPARE(out.setMaximumPacketSize(size), expected);
-}
-
-void tst_QPacketProtocol::setMaximumPacketSize_data()
-{
- QTest::addColumn<int>("size");
- QTest::addColumn<int>("expected");
-
- QTest::newRow("invalid") << qint32(sizeof(qint32) - 1) << qint32(0x7FFFFFFF);
- QTest::newRow("still invalid") << qint32(sizeof(qint32)) << qint32(0x7FFFFFFF);
- QTest::newRow("valid") << qint32(sizeof(qint32) + 1) << qint32(sizeof(qint32) + 1);
-}
-
void tst_QPacketProtocol::send()
{
- QFETCH(bool, useAutoSend);
-
QPacketProtocol in(m_client);
QPacketProtocol out(m_serverConn);
QByteArray ba;
int num;
- if (useAutoSend) {
- out.send() << "Hello world" << 123;
- } else {
- QPacket packet;
- packet << "Hello world" << 123;
- out.send(packet);
- }
+ QPacket packet;
+ packet << "Hello world" << 123;
+ out.send(packet);
QVERIFY(QQmlDebugTest::waitForSignal(&in, SIGNAL(readyRead())));
@@ -146,14 +108,6 @@ void tst_QPacketProtocol::send()
QCOMPARE(num, 123);
}
-void tst_QPacketProtocol::send_data()
-{
- QTest::addColumn<bool>("useAutoSend");
-
- QTest::newRow("auto send") << true;
- QTest::newRow("no auto send") << false;
-}
-
void tst_QPacketProtocol::packetsAvailable()
{
QFETCH(int, packetCount);
@@ -164,8 +118,11 @@ void tst_QPacketProtocol::packetsAvailable()
QCOMPARE(out.packetsAvailable(), qint64(0));
QCOMPARE(in.packetsAvailable(), qint64(0));
- for (int i=0; i<packetCount; i++)
- out.send() << "Hello";
+ for (int i=0; i<packetCount; i++) {
+ QPacket packet;
+ packet << "Hello";
+ out.send(packet);
+ }
QVERIFY(QQmlDebugTest::waitForSignal(&in, SIGNAL(readyRead())));
QCOMPARE(in.packetsAvailable(), qint64(packetCount));
@@ -180,79 +137,35 @@ void tst_QPacketProtocol::packetsAvailable_data()
QTest::newRow("10") << 10;
}
-void tst_QPacketProtocol::clear()
-{
- QPacketProtocol in(m_client);
- QPacketProtocol out(m_serverConn);
-
- out.send() << 123;
- out.send() << 456;
- QVERIFY(QQmlDebugTest::waitForSignal(&in, SIGNAL(readyRead())));
-
- in.clear();
- QVERIFY(in.read().isEmpty());
-}
-
void tst_QPacketProtocol::read()
{
QPacketProtocol in(m_client);
QPacketProtocol out(m_serverConn);
- QVERIFY(in.read().isEmpty());
+ QVERIFY(in.read().atEnd());
+
+ QPacket packet;
+ packet << 123;
+ out.send(packet);
- out.send() << 123;
- out.send() << 456;
+ QPacket packet2;
+ packet2 << 456;
+ out.send(packet2);
QVERIFY(QQmlDebugTest::waitForSignal(&in, SIGNAL(readyRead())));
int num;
QPacket p1 = in.read();
- QVERIFY(!p1.isEmpty());
+ QVERIFY(!p1.atEnd());
p1 >> num;
QCOMPARE(num, 123);
QPacket p2 = in.read();
- QVERIFY(!p2.isEmpty());
+ QVERIFY(!p2.atEnd());
p2 >> num;
QCOMPARE(num, 456);
- QVERIFY(in.read().isEmpty());
-}
-
-void tst_QPacketProtocol::device()
-{
- QPacketProtocol p(m_client);
- QCOMPARE(p.device(), m_client);
-}
-
-void tst_QPacketProtocol::tst_QPacket_clear()
-{
- QPacketProtocol protocol(m_client);
-
- QPacket packet;
-
- packet << "Hello world!" << 123;
- protocol.send(packet);
-
- packet.clear();
- QVERIFY(packet.isEmpty());
- packet << "Goodbyte world!" << 789;
- protocol.send(packet);
-
- QByteArray ba;
- int num;
- QPacketProtocol in(m_serverConn);
- QVERIFY(QQmlDebugTest::waitForSignal(&in, SIGNAL(readyRead())));
-
- QPacket p1 = in.read();
- p1 >> ba >> num;
- QCOMPARE(ba, QByteArray("Hello world!") + '\0');
- QCOMPARE(num, 123);
-
- QPacket p2 = in.read();
- p2 >> ba >> num;
- QCOMPARE(ba, QByteArray("Goodbyte world!") + '\0');
- QCOMPARE(num, 789);
+ QVERIFY(in.read().atEnd());
}
QTEST_MAIN(tst_QPacketProtocol)
diff --git a/tests/auto/qml/debugger/shared/debugutil.pri b/tests/auto/qml/debugger/shared/debugutil.pri
index cb9c761395..73ed647061 100644
--- a/tests/auto/qml/debugger/shared/debugutil.pri
+++ b/tests/auto/qml/debugger/shared/debugutil.pri
@@ -1,8 +1,8 @@
+QT += packetprotocol-private
+
HEADERS += $$PWD/debugutil_p.h \
$$PWD/qqmldebugclient.h \
- $$PWD/../../../../../src/plugins/qmltooling/shared/qpacketprotocol.h
SOURCES += $$PWD/debugutil.cpp \
$$PWD/qqmldebugclient.cpp \
- $$PWD/../../../../../src/plugins/qmltooling/shared/qpacketprotocol.cpp
diff --git a/tests/auto/qml/debugger/shared/qqmldebugclient.cpp b/tests/auto/qml/debugger/shared/qqmldebugclient.cpp
index f350614a47..00de8f9f7e 100644
--- a/tests/auto/qml/debugger/shared/qqmldebugclient.cpp
+++ b/tests/auto/qml/debugger/shared/qqmldebugclient.cpp
@@ -32,7 +32,9 @@
****************************************************************************/
#include "qqmldebugclient.h"
-#include "../../../../../src/plugins/qmltooling/shared/qpacketprotocol.h"
+
+#include <private/qpacketprotocol_p.h>
+#include <private/qpacket_p.h>
#include <QtCore/qdebug.h>
#include <QtCore/qeventloop.h>
@@ -138,7 +140,7 @@ void QQmlDebugConnectionPrivate::readyRead()
QStringList pluginNames;
QList<float> pluginVersions;
pack >> pluginNames;
- if (!pack.isEmpty())
+ if (!pack.atEnd())
pack >> pluginVersions;
const int pluginNamesSize = pluginNames.size();
@@ -192,7 +194,7 @@ void QQmlDebugConnectionPrivate::readyRead()
QStringList pluginNames;
QList<float> pluginVersions;
pack >> pluginNames;
- if (!pack.isEmpty())
+ if (!pack.atEnd())
pack >> pluginVersions;
const int pluginNamesSize = pluginNames.size();
diff --git a/tools/qmlprofiler/qmlprofiler.pro b/tools/qmlprofiler/qmlprofiler.pro
index 4fa36f5127..e38ba928e2 100644
--- a/tools/qmlprofiler/qmlprofiler.pro
+++ b/tools/qmlprofiler/qmlprofiler.pro
@@ -1,4 +1,4 @@
-QT = qml qml-private network core-private
+QT = qml qml-private network core-private packetprotocol-private
CONFIG += no_import_scan
SOURCES += main.cpp \
@@ -6,8 +6,7 @@ SOURCES += main.cpp \
commandlistener.cpp \
qqmldebugclient.cpp \
qmlprofilerdata.cpp \
- qmlprofilerclient.cpp \
- qpacketprotocol.cpp
+ qmlprofilerclient.cpp
HEADERS += \
qmlprofilerapplication.h \
@@ -16,7 +15,6 @@ HEADERS += \
qmlprofilerdata.h \
qmlprofilerclient.h \
qmlprofilereventlocation.h \
- qqmldebugclient.h \
- qpacketprotocol.h
+ qqmldebugclient.h
load(qt_tool)
diff --git a/tools/qmlprofiler/qpacketprotocol.cpp b/tools/qmlprofiler/qpacketprotocol.cpp
deleted file mode 100644
index 096bc142c5..0000000000
--- a/tools/qmlprofiler/qpacketprotocol.cpp
+++ /dev/null
@@ -1,527 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** 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 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qpacketprotocol.h"
-
-#include <QtCore/QBuffer>
-#include <QtCore/QElapsedTimer>
-#include <private/qiodevice_p.h> // for qt_subtract_from_timeout
-
-static const unsigned int MAX_PACKET_SIZE = 0x7FFFFFFF;
-
-/*!
- \class QPacketProtocol
- \internal
-
- \brief The QPacketProtocol class encapsulates communicating discrete packets
- across fragmented IO channels, such as TCP sockets.
-
- QPacketProtocol makes it simple to send arbitrary sized data "packets" across
- fragmented transports such as TCP and UDP.
-
- As transmission boundaries are not respected, sending packets over protocols
- like TCP frequently involves "stitching" them back together at the receiver.
- QPacketProtocol makes this easier by performing this task for you. Packet
- data sent using QPacketProtocol is prepended with a 4-byte size header
- allowing the receiving QPacketProtocol to buffer the packet internally until
- it has all been received. QPacketProtocol does not perform any sanity
- checking on the size or on the data, so this class should only be used in
- prototyping or trusted situations where DOS attacks are unlikely.
-
- QPacketProtocol does not perform any communications itself. Instead it can
- operate on any QIODevice that supports the QIODevice::readyRead() signal. A
- logical "packet" is encapsulated by the companion QPacket class. The
- following example shows two ways to send data using QPacketProtocol. The
- transmitted data is equivalent in both.
-
- \code
- QTcpSocket socket;
- // ... connect socket ...
-
- QPacketProtocol protocol(&socket);
-
- // Send packet the quick way
- protocol.send() << "Hello world" << 123;
-
- // Send packet the longer way
- QPacket packet;
- packet << "Hello world" << 123;
- protocol.send(packet);
- \endcode
-
- Likewise, the following shows how to read data from QPacketProtocol, assuming
- that the QPacketProtocol::readyRead() signal has been emitted.
-
- \code
- // ... QPacketProtocol::readyRead() is emitted ...
-
- int a;
- QByteArray b;
-
- // Receive packet the quick way
- protocol.read() >> a >> b;
-
- // Receive packet the longer way
- QPacket packet = protocol.read();
- p >> a >> b;
- \endcode
-
- \ingroup io
- \sa QPacket
-*/
-
-class QPacketProtocolPrivate : public QObject
-{
- Q_OBJECT
-public:
- QPacketProtocolPrivate(QPacketProtocol *parent, QIODevice *_dev)
- : QObject(parent), inProgressSize(-1), maxPacketSize(MAX_PACKET_SIZE),
- waitingForPacket(false), dev(_dev)
- {
- Q_ASSERT(4 == sizeof(qint32));
-
- QObject::connect(this, SIGNAL(readyRead()),
- parent, SIGNAL(readyRead()));
- QObject::connect(this, SIGNAL(packetWritten()),
- parent, SIGNAL(packetWritten()));
- QObject::connect(this, SIGNAL(invalidPacket()),
- parent, SIGNAL(invalidPacket()));
- QObject::connect(dev, SIGNAL(readyRead()),
- this, SLOT(readyToRead()));
- QObject::connect(dev, SIGNAL(aboutToClose()),
- this, SLOT(aboutToClose()));
- QObject::connect(dev, SIGNAL(bytesWritten(qint64)),
- this, SLOT(bytesWritten(qint64)));
- }
-
-Q_SIGNALS:
- void readyRead();
- void packetWritten();
- void invalidPacket();
-
-public Q_SLOTS:
- void aboutToClose()
- {
- inProgress.clear();
- sendingPackets.clear();
- inProgressSize = -1;
- }
-
- void bytesWritten(qint64 bytes)
- {
- Q_ASSERT(!sendingPackets.isEmpty());
-
- while (bytes) {
- if (sendingPackets.at(0) > bytes) {
- sendingPackets[0] -= bytes;
- bytes = 0;
- } else {
- bytes -= sendingPackets.at(0);
- sendingPackets.removeFirst();
- emit packetWritten();
- }
- }
- }
-
- void readyToRead()
- {
- while (true) {
- // Need to get trailing data
- if (-1 == inProgressSize) {
- // We need a size header of sizeof(qint32)
- if (sizeof(qint32) > (uint)dev->bytesAvailable())
- return;
-
- // Read size header
- int read = dev->read((char *)&inProgressSize, sizeof(qint32));
- Q_ASSERT(read == sizeof(qint32));
- Q_UNUSED(read);
-
- // Check sizing constraints
- if (inProgressSize > maxPacketSize) {
- QObject::disconnect(dev, SIGNAL(readyRead()),
- this, SLOT(readyToRead()));
- QObject::disconnect(dev, SIGNAL(aboutToClose()),
- this, SLOT(aboutToClose()));
- QObject::disconnect(dev, SIGNAL(bytesWritten(qint64)),
- this, SLOT(bytesWritten(qint64)));
- dev = 0;
- emit invalidPacket();
- return;
- }
-
- inProgressSize -= sizeof(qint32);
- } else {
- inProgress.append(dev->read(inProgressSize - inProgress.size()));
-
- if (inProgressSize == inProgress.size()) {
- // Packet has arrived!
- packets.append(inProgress);
- inProgressSize = -1;
- inProgress.clear();
-
- waitingForPacket = false;
- emit readyRead();
- } else
- return;
- }
- }
- }
-
-public:
- QList<qint64> sendingPackets;
- QList<QByteArray> packets;
- QByteArray inProgress;
- qint32 inProgressSize;
- qint32 maxPacketSize;
- bool waitingForPacket;
- QIODevice *dev;
-};
-
-/*!
- Construct a QPacketProtocol instance that works on \a dev with the
- specified \a parent.
- */
-QPacketProtocol::QPacketProtocol(QIODevice *dev, QObject *parent)
- : QObject(parent), d(new QPacketProtocolPrivate(this, dev))
-{
- Q_ASSERT(dev);
-}
-
-/*!
- Destroys the QPacketProtocol instance.
- */
-QPacketProtocol::~QPacketProtocol()
-{
-}
-
-/*!
- Returns the maximum packet size allowed. By default this is
- 2,147,483,647 bytes.
-
- If a packet claiming to be larger than the maximum packet size is received,
- the QPacketProtocol::invalidPacket() signal is emitted.
-
- \sa QPacketProtocol::setMaximumPacketSize()
- */
-qint32 QPacketProtocol::maximumPacketSize() const
-{
- return d->maxPacketSize;
-}
-
-/*!
- Sets the maximum allowable packet size to \a max.
-
- \sa QPacketProtocol::maximumPacketSize()
- */
-qint32 QPacketProtocol::setMaximumPacketSize(qint32 max)
-{
- if (max > (signed)sizeof(qint32))
- d->maxPacketSize = max;
- return d->maxPacketSize;
-}
-
-/*!
- Returns a streamable object that is transmitted on destruction. For example
-
- \code
- protocol.send() << "Hello world" << 123;
- \endcode
-
- will send a packet containing "Hello world" and 123. To construct more
- complex packets, explicitly construct a QPacket instance.
- */
-QPacketAutoSend QPacketProtocol::send()
-{
- return QPacketAutoSend(this);
-}
-
-/*!
- \fn void QPacketProtocol::send(const QPacket & packet)
-
- Transmit the \a packet.
- */
-void QPacketProtocol::send(const QPacket & p)
-{
- if (p.b.isEmpty())
- return; // We don't send empty packets
-
- qint64 sendSize = p.b.size() + sizeof(qint32);
-
- d->sendingPackets.append(sendSize);
- qint32 sendSize32 = sendSize;
- qint64 writeBytes = d->dev->write((char *)&sendSize32, sizeof(qint32));
- Q_UNUSED(writeBytes);
- Q_ASSERT(writeBytes == sizeof(qint32));
- writeBytes = d->dev->write(p.b);
- Q_ASSERT(writeBytes == p.b.size());
-}
-
-/*!
- Returns the number of received packets yet to be read.
- */
-qint64 QPacketProtocol::packetsAvailable() const
-{
- return d->packets.count();
-}
-
-/*!
- Discard any unread packets.
- */
-void QPacketProtocol::clear()
-{
- d->packets.clear();
-}
-
-/*!
- Return the next unread packet, or an invalid QPacket instance if no packets
- are available. This method does NOT block.
- */
-QPacket QPacketProtocol::read()
-{
- if (0 == d->packets.count())
- return QPacket();
-
- QPacket rv(d->packets.at(0));
- d->packets.removeFirst();
- return rv;
-}
-
-/*!
- This function locks until a new packet is available for reading and the
- \l{QIODevice::}{readyRead()} signal has been emitted. The function
- will timeout after \a msecs milliseconds; the default timeout is
- 30000 milliseconds.
-
- The function returns true if the readyRead() signal is emitted and
- there is new data available for reading; otherwise it returns false
- (if an error occurred or the operation timed out).
- */
-
-bool QPacketProtocol::waitForReadyRead(int msecs)
-{
- if (!d->packets.isEmpty())
- return true;
-
- QElapsedTimer stopWatch;
- stopWatch.start();
-
- d->waitingForPacket = true;
- do {
- if (!d->dev->waitForReadyRead(msecs))
- return false;
- if (!d->waitingForPacket)
- return true;
- msecs = qt_subtract_from_timeout(msecs, stopWatch.elapsed());
- } while (true);
-}
-
-/*!
- Return the QIODevice passed to the QPacketProtocol constructor.
-*/
-QIODevice *QPacketProtocol::device()
-{
- return d->dev;
-}
-
-/*!
- \fn void QPacketProtocol::readyRead()
-
- Emitted whenever a new packet is received. Applications may use
- QPacketProtocol::read() to retrieve this packet.
- */
-
-/*!
- \fn void QPacketProtocol::invalidPacket()
-
- A packet larger than the maximum allowable packet size was received. The
- packet will be discarded and, as it indicates corruption in the protocol, no
- further packets will be received.
- */
-
-/*!
- \fn void QPacketProtocol::packetWritten()
-
- Emitted each time a packet is completing written to the device. This signal
- may be used for communications flow control.
- */
-
-/*!
- \class QPacket
- \internal
-
- \brief The QPacket class encapsulates an unfragmentable packet of data to be
- transmitted by QPacketProtocol.
-
- The QPacket class works together with QPacketProtocol to make it simple to
- send arbitrary sized data "packets" across fragmented transports such as TCP
- and UDP.
-
- QPacket provides a QDataStream interface to an unfragmentable packet.
- Applications should construct a QPacket, propagate it with data and then
- transmit it over a QPacketProtocol instance. For example:
- \code
- QPacketProtocol protocol(...);
-
- QPacket myPacket;
- myPacket << "Hello world!" << 123;
- protocol.send(myPacket);
- \endcode
-
- As long as both ends of the connection are using the QPacketProtocol class,
- the data within this packet will be delivered unfragmented at the other end,
- ready for extraction.
-
- \code
- QByteArray greeting;
- int count;
-
- QPacket myPacket = protocol.read();
-
- myPacket >> greeting >> count;
- \endcode
-
- Only packets returned from QPacketProtocol::read() may be read from. QPacket
- instances constructed by directly by applications are for transmission only
- and are considered "write only". Attempting to read data from them will
- result in undefined behavior.
-
- \ingroup io
- \sa QPacketProtocol
- */
-
-/*!
- Constructs an empty write-only packet.
- */
-QPacket::QPacket()
- : QDataStream(), buf(0)
-{
- buf = new QBuffer(&b);
- buf->open(QIODevice::WriteOnly);
- setDevice(buf);
- setVersion(QDataStream::Qt_4_7);
-}
-
-/*!
- Destroys the QPacket instance.
- */
-QPacket::~QPacket()
-{
- if (buf) {
- delete buf;
- buf = 0;
- }
-}
-
-/*!
- Creates a copy of \a other. The initial stream positions are shared, but the
- two packets are otherwise independent.
- */
-QPacket::QPacket(const QPacket & other)
- : QDataStream(), b(other.b), buf(0)
-{
- buf = new QBuffer(&b);
- buf->open(other.buf->openMode());
- setDevice(buf);
-}
-
-/*!
- \internal
- */
-QPacket::QPacket(const QByteArray & ba)
- : QDataStream(), b(ba), buf(0)
-{
- buf = new QBuffer(&b);
- buf->open(QIODevice::ReadOnly);
- setDevice(buf);
-}
-
-/*!
- Returns true if this packet is empty - that is, contains no data.
- */
-bool QPacket::isEmpty() const
-{
- return b.isEmpty();
-}
-
-/*!
- Returns raw packet data.
- */
-QByteArray QPacket::data() const
-{
- return b;
-}
-
-/*!
- Clears data in the packet. This is useful for reusing one writable packet.
- For example
- \code
- QPacketProtocol protocol(...);
-
- QPacket packet;
-
- packet << "Hello world!" << 123;
- protocol.send(packet);
-
- packet.clear();
- packet << "Goodbyte world!" << 789;
- protocol.send(packet);
- \endcode
- */
-void QPacket::clear()
-{
- QBuffer::OpenMode oldMode = buf->openMode();
- buf->close();
- b.clear();
- buf->setBuffer(&b); // reset QBuffer internals with new size of b.
- buf->open(oldMode);
-}
-
-/*!
- \class QPacketAutoSend
- \internal
-
- \internal
- */
-QPacketAutoSend::QPacketAutoSend(QPacketProtocol *_p)
- : QPacket(), p(_p)
-{
-}
-
-QPacketAutoSend::~QPacketAutoSend()
-{
- if (!b.isEmpty())
- p->send(*this);
-}
-
-#include <qpacketprotocol.moc>
diff --git a/tools/qmlprofiler/qqmldebugclient.cpp b/tools/qmlprofiler/qqmldebugclient.cpp
index f87d4b0a7c..d661c71e1c 100644
--- a/tools/qmlprofiler/qqmldebugclient.cpp
+++ b/tools/qmlprofiler/qqmldebugclient.cpp
@@ -32,7 +32,9 @@
****************************************************************************/
#include "qqmldebugclient.h"
-#include "qpacketprotocol.h"
+
+#include <private/qpacketprotocol_p.h>
+#include <private/qpacket_p.h>
#include <QtCore/qdebug.h>
#include <QtCore/qstringlist.h>
@@ -119,7 +121,7 @@ void QQmlDebugConnectionPrivate::readyRead()
QStringList pluginNames;
QList<float> pluginVersions;
pack >> pluginNames;
- if (!pack.isEmpty())
+ if (!pack.atEnd())
pack >> pluginVersions;
const int pluginNamesSize = pluginNames.size();
@@ -169,7 +171,7 @@ void QQmlDebugConnectionPrivate::readyRead()
QStringList pluginNames;
QList<float> pluginVersions;
pack >> pluginNames;
- if (!pack.isEmpty())
+ if (!pack.atEnd())
pack >> pluginVersions;
const int pluginNamesSize = pluginNames.size();