7#include <private/qpacketprotocol_p.h>
8#include <private/qpacket_p.h>
9#include <private/qobject_p.h>
11#include <QtCore/qeventloop.h>
12#include <QtCore/qtimer.h>
13#include <QtCore/QHash>
14#include <QtCore/qdatastream.h>
15#include <QtNetwork/qlocalserver.h>
16#include <QtNetwork/qlocalsocket.h>
17#include <QtNetwork/qtcpsocket.h>
27 Q_DECLARE_PUBLIC(QQmlDebugConnection)
51 handshakeTimer.setSingleShot(
true);
52 handshakeTimer.setInterval(3000);
57 Q_Q(QQmlDebugConnection);
58 if (!q->isConnected())
61 QPacket pack(currentDataStreamVersion);
62 pack << serverId << 1 << plugins.keys();
63 protocol->send(pack.data());
69 Q_D(QQmlDebugConnection);
70 QPacket pack(d->currentDataStreamVersion);
71 pack << serverId << 0 << protocolVersion << d->plugins.keys() << d->maximumDataStreamVersion
73 d->protocol->send(pack.data());
79 Q_D(QQmlDebugConnection);
86 Q_D(QQmlDebugConnection);
88 QPacket pack(d->currentDataStreamVersion, d->protocol->read());
93 bool validHello =
false;
94 if (name == clientId) {
101 QStringList pluginNames;
102 QList<
float> pluginVersions;
105 pack >> pluginVersions;
107 const int pluginNamesSize = pluginNames.size();
108 const int pluginVersionsSize = pluginVersions.size();
109 for (
int i = 0; i < pluginNamesSize; ++i) {
110 float pluginVersion = 1.0;
111 if (i < pluginVersionsSize)
112 pluginVersion = pluginVersions.at(i);
113 d->serverPlugins.insert(pluginNames.at(i), pluginVersion);
116 pack >> d->currentDataStreamVersion;
123 qWarning(
"QQmlDebugConnection: Invalid hello message");
130 QHash<QString, QQmlDebugClient *>::Iterator iter = d->plugins.begin();
131 for (; iter != d->plugins.end(); ++iter) {
132 QQmlDebugClient::State newState = QQmlDebugClient::Unavailable;
133 if (d->serverPlugins.contains(iter.key()))
134 newState = QQmlDebugClient::Enabled;
135 iter.value()->stateChanged(newState);
138 d->handshakeTimer.stop();
139 d->handshakeEventLoop.quit();
142 while (d->protocol->packetsAvailable()) {
143 QPacket pack(d->currentDataStreamVersion, d->protocol->read());
147 if (name == clientId) {
153 QHash<QString,
float> oldServerPlugins = d->serverPlugins;
154 d->serverPlugins.clear();
156 QStringList pluginNames;
157 QList<
float> pluginVersions;
160 pack >> pluginVersions;
162 const int pluginNamesSize = pluginNames.size();
163 const int pluginVersionsSize = pluginVersions.size();
164 for (
int i = 0; i < pluginNamesSize; ++i) {
165 float pluginVersion = 1.0;
166 if (i < pluginVersionsSize)
167 pluginVersion = pluginVersions.at(i);
168 d->serverPlugins.insert(pluginNames.at(i), pluginVersion);
171 QHash<QString, QQmlDebugClient *>::Iterator iter = d->plugins.begin();
172 for (; iter != d->plugins.end(); ++iter) {
173 const QString &pluginName = iter.key();
174 QQmlDebugClient::State newState = QQmlDebugClient::Unavailable;
175 if (d->serverPlugins.contains(pluginName))
176 newState = QQmlDebugClient::Enabled;
178 if (oldServerPlugins.contains(pluginName)
179 != d->serverPlugins.contains(pluginName)) {
180 iter.value()->stateChanged(newState);
184 qWarning() <<
"QQmlDebugConnection: Unknown control message id" << op;
187 QHash<QString, QQmlDebugClient *>::Iterator iter = d->plugins.find(name);
188 if (iter == d->plugins.end()) {
191 if (!d->removedPlugins.contains(name)) {
192 qWarning() <<
"QQmlDebugConnection: Message received for missing plugin"
198 while (!pack.atEnd()) {
200 client->messageReceived(message);
209 Q_D(QQmlDebugConnection);
211 qWarning() <<
"QQmlDebugConnection: Did not get handshake answer in time";
212 d->handshakeEventLoop.quit();
217 QObject(*(
new QQmlDebugConnectionPrivate), parent)
219 Q_D(QQmlDebugConnection);
220 connect(&d->handshakeTimer, &QTimer::timeout,
this, &QQmlDebugConnection::handshakeTimeout);
225 Q_D(QQmlDebugConnection);
226 QHash<QString, QQmlDebugClient*>::iterator iter = d->plugins.begin();
227 for (; iter != d->plugins.end(); ++iter)
228 emit iter.value()->stateChanged(QQmlDebugClient::NotConnected);
233 Q_D(
const QQmlDebugConnection);
234 return d->currentDataStreamVersion;
239 Q_D(QQmlDebugConnection);
240 d->maximumDataStreamVersion = maximumVersion;
245 Q_D(
const QQmlDebugConnection);
251 Q_D(
const QQmlDebugConnection);
252 return !d->gotHello && d->device;
257 Q_D(QQmlDebugConnection);
262 QHash<QString, QQmlDebugClient*>::iterator iter = d->plugins.begin();
263 for (; iter != d->plugins.end(); ++iter)
264 emit iter.value()->stateChanged(QQmlDebugClient::NotConnected);
268 d->device->deleteLater();
275 Q_D(QQmlDebugConnection);
276 auto socket = qobject_cast<QAbstractSocket*>(d->device);
278 if (!d->server || (!d->server->hasPendingConnections() &&
279 !d->server->waitForNewConnection(msecs)))
281 }
else if (!socket->waitForConnected(msecs)) {
285 d->handshakeTimer.start();
286 d->handshakeEventLoop.exec();
292 Q_D(
const QQmlDebugConnection);
293 return d->plugins.value(name,
nullptr);
298 Q_D(QQmlDebugConnection);
299 if (d->plugins.contains(name))
301 d->removedPlugins.removeAll(name);
302 d->plugins.insert(name, client);
303 d->advertisePlugins();
309 Q_D(QQmlDebugConnection);
310 if (!d->plugins.contains(name))
312 d->plugins.remove(name);
313 d->removedPlugins.append(name);
314 d->advertisePlugins();
320 Q_D(
const QQmlDebugConnection);
321 return d->serverPlugins.value(serviceName, -1);
326 Q_D(QQmlDebugConnection);
327 if (!isConnected() || !d->serverPlugins.contains(name))
330 QPacket pack(d->currentDataStreamVersion);
331 pack << name << message;
332 d->protocol->send(pack.data());
340 if (
auto socket = qobject_cast<QAbstractSocket *>(device))
342 else if (
auto socket = qobject_cast<QLocalSocket *>(device))
348 Q_D(QQmlDebugConnection);
351 auto socket =
new QTcpSocket(
this);
354 connect(socket, &QAbstractSocket::disconnected,
this, &QQmlDebugConnection::socketDisconnected);
355 connect(socket, &QAbstractSocket::connected,
this, &QQmlDebugConnection::socketConnected);
356 connect(socket,
static_cast<
void(QAbstractSocket::*)(QAbstractSocket::SocketError)>(
357 &QAbstractSocket::errorOccurred),
this, &QQmlDebugConnection::socketError);
358 connect(socket, &QAbstractSocket::stateChanged,
this, &QQmlDebugConnection::socketStateChanged);
359 socket->connectToHost(hostName, port);
364 Q_D(QQmlDebugConnection);
368 d->server->deleteLater();
369 d->server =
new QLocalServer(
this);
371 connect(d->server, &QLocalServer::newConnection,
372 this, &QQmlDebugConnection::newConnection, Qt::QueuedConnection);
373 d->server->listen(fileName);
404 Q_D(QQmlDebugConnection);
406 QLocalSocket *socket = d->server->nextPendingConnection();
410 connect(socket, &QLocalSocket::disconnected,
this, &QQmlDebugConnection::socketDisconnected);
413 connect(translator, &LocalSocketSignalTranslator::socketError,
414 this, &QQmlDebugConnection::socketError);
415 connect(translator, &LocalSocketSignalTranslator::socketStateChanged,
416 this, &QQmlDebugConnection::socketStateChanged);
422 Q_Q(QQmlDebugConnection);
424 protocol =
new QPacketProtocol(device, q);
425 QObject::connect(protocol, &QPacketProtocol::readyRead,
426 q, &QQmlDebugConnection::protocolReadyRead);
431#include <qqmldebugconnection.moc>
433#include "moc_qqmldebugconnection_p.cpp"
void socketStateChanged(QAbstractSocket::SocketState)
QEventLoop handshakeEventLoop
QHash< QString, float > serverPlugins
int maximumDataStreamVersion
QStringList removedPlugins
QHash< QString, QQmlDebugClient * > plugins
int currentDataStreamVersion
QPacketProtocol * protocol
bool isConnecting() const
bool addClient(const QString &name, QQmlDebugClient *client)
void setMaximumDataStreamVersion(int maximumVersion)
bool sendMessage(const QString &name, const QByteArray &message)
bool removeClient(const QString &name)
QQmlDebugClient * client(const QString &name) const
float serviceVersion(const QString &serviceName) const
int currentDataStreamVersion() const
bool waitForConnected(int msecs=30000)
void startLocalServer(const QString &fileName)
void connectToHost(const QString &hostName, quint16 port)
Combined button and popup list for selecting options.
static const QString clientId
static const QString serverId
static QT_BEGIN_NAMESPACE const int protocolVersion