8#include <private/qpacketprotocol_p.h>
9#include <private/qpacket_p.h>
10#include <private/qobject_p.h>
12#include <QtCore/qeventloop.h>
13#include <QtCore/qtimer.h>
14#include <QtCore/QHash>
15#include <QtCore/qdatastream.h>
16#include <QtNetwork/qlocalserver.h>
17#include <QtNetwork/qlocalsocket.h>
18#include <QtNetwork/qtcpsocket.h>
28 Q_DECLARE_PUBLIC(QQmlDebugConnection)
52 handshakeTimer.setSingleShot(
true);
53 handshakeTimer.setInterval(3000);
58 Q_Q(QQmlDebugConnection);
59 if (!q->isConnected())
62 QPacket pack(currentDataStreamVersion);
63 pack << serverId << 1 << plugins.keys();
64 protocol->send(pack.data());
70 Q_D(QQmlDebugConnection);
71 QPacket pack(d->currentDataStreamVersion);
72 pack << serverId << 0 << protocolVersion << d->plugins.keys() << d->maximumDataStreamVersion
74 d->protocol->send(pack.data());
80 Q_D(QQmlDebugConnection);
87 Q_D(QQmlDebugConnection);
89 QPacket pack(d->currentDataStreamVersion, d->protocol->read());
94 bool validHello =
false;
95 if (name == clientId) {
102 QStringList pluginNames;
103 QList<
float> pluginVersions;
106 pack >> pluginVersions;
108 const int pluginNamesSize = pluginNames.size();
109 const int pluginVersionsSize = pluginVersions.size();
110 for (
int i = 0; i < pluginNamesSize; ++i) {
111 float pluginVersion = 1.0;
112 if (i < pluginVersionsSize)
113 pluginVersion = pluginVersions.at(i);
114 d->serverPlugins.insert(pluginNames.at(i), pluginVersion);
117 pack >> d->currentDataStreamVersion;
124 qWarning(
"QQmlDebugConnection: Invalid hello message");
131 QHash<QString, QQmlDebugClient *>::Iterator iter = d->plugins.begin();
132 for (; iter != d->plugins.end(); ++iter) {
133 QQmlDebugClient::State newState = QQmlDebugClient::Unavailable;
134 if (d->serverPlugins.contains(iter.key()))
135 newState = QQmlDebugClient::Enabled;
136 iter.value()->stateChanged(newState);
139 d->handshakeTimer.stop();
140 d->handshakeEventLoop.quit();
143 while (d->protocol->packetsAvailable()) {
144 QPacket pack(d->currentDataStreamVersion, d->protocol->read());
148 if (name == clientId) {
154 QHash<QString,
float> oldServerPlugins = d->serverPlugins;
155 d->serverPlugins.clear();
157 QStringList pluginNames;
158 QList<
float> pluginVersions;
161 pack >> pluginVersions;
163 const int pluginNamesSize = pluginNames.size();
164 const int pluginVersionsSize = pluginVersions.size();
165 for (
int i = 0; i < pluginNamesSize; ++i) {
166 float pluginVersion = 1.0;
167 if (i < pluginVersionsSize)
168 pluginVersion = pluginVersions.at(i);
169 d->serverPlugins.insert(pluginNames.at(i), pluginVersion);
172 QHash<QString, QQmlDebugClient *>::Iterator iter = d->plugins.begin();
173 for (; iter != d->plugins.end(); ++iter) {
174 const QString &pluginName = iter.key();
175 QQmlDebugClient::State newState = QQmlDebugClient::Unavailable;
176 if (d->serverPlugins.contains(pluginName))
177 newState = QQmlDebugClient::Enabled;
179 if (oldServerPlugins.contains(pluginName)
180 != d->serverPlugins.contains(pluginName)) {
181 iter.value()->stateChanged(newState);
185 qWarning() <<
"QQmlDebugConnection: Unknown control message id" << op;
188 QHash<QString, QQmlDebugClient *>::Iterator iter = d->plugins.find(name);
189 if (iter == d->plugins.end()) {
192 if (!d->removedPlugins.contains(name)) {
193 qWarning() <<
"QQmlDebugConnection: Message received for missing plugin"
199 while (!pack.atEnd()) {
201 client->messageReceived(message);
210 Q_D(QQmlDebugConnection);
212 qWarning() <<
"QQmlDebugConnection: Did not get handshake answer in time";
213 d->handshakeEventLoop.quit();
218 QObject(*(
new QQmlDebugConnectionPrivate), parent)
220 Q_D(QQmlDebugConnection);
221 connect(&d->handshakeTimer, &QTimer::timeout,
this, &QQmlDebugConnection::handshakeTimeout);
226 Q_D(QQmlDebugConnection);
227 QHash<QString, QQmlDebugClient*>::iterator iter = d->plugins.begin();
228 for (; iter != d->plugins.end(); ++iter)
229 emit iter.value()->stateChanged(QQmlDebugClient::NotConnected);
234 Q_D(
const QQmlDebugConnection);
235 return d->currentDataStreamVersion;
240 Q_D(QQmlDebugConnection);
241 d->maximumDataStreamVersion = maximumVersion;
246 Q_D(
const QQmlDebugConnection);
252 Q_D(
const QQmlDebugConnection);
253 return !d->gotHello && d->device;
258 Q_D(QQmlDebugConnection);
263 QHash<QString, QQmlDebugClient*>::iterator iter = d->plugins.begin();
264 for (; iter != d->plugins.end(); ++iter)
265 emit iter.value()->stateChanged(QQmlDebugClient::NotConnected);
269 d->device->deleteLater();
276 Q_D(QQmlDebugConnection);
277 auto socket = qobject_cast<QAbstractSocket*>(d->device);
279 if (!d->server || (!d->server->hasPendingConnections() &&
280 !d->server->waitForNewConnection(msecs)))
282 }
else if (!socket->waitForConnected(msecs)) {
286 d->handshakeTimer.start();
287 d->handshakeEventLoop.exec();
293 Q_D(
const QQmlDebugConnection);
294 return d->plugins.value(name,
nullptr);
299 Q_D(QQmlDebugConnection);
300 if (d->plugins.contains(name))
302 d->removedPlugins.removeAll(name);
303 d->plugins.insert(name, client);
304 d->advertisePlugins();
310 Q_D(QQmlDebugConnection);
311 if (!d->plugins.contains(name))
313 d->plugins.remove(name);
314 d->removedPlugins.append(name);
315 d->advertisePlugins();
321 Q_D(
const QQmlDebugConnection);
322 return d->serverPlugins.value(serviceName, -1);
327 Q_D(QQmlDebugConnection);
328 if (!isConnected() || !d->serverPlugins.contains(name))
331 QPacket pack(d->currentDataStreamVersion);
332 pack << name << message;
333 d->protocol->send(pack.data());
341 if (
auto socket = qobject_cast<QAbstractSocket *>(device))
343 else if (
auto socket = qobject_cast<QLocalSocket *>(device))
349 Q_D(QQmlDebugConnection);
352 auto socket =
new QTcpSocket(
this);
355 connect(socket, &QAbstractSocket::disconnected,
this, &QQmlDebugConnection::socketDisconnected);
356 connect(socket, &QAbstractSocket::connected,
this, &QQmlDebugConnection::socketConnected);
357 connect(socket,
static_cast<
void(QAbstractSocket::*)(QAbstractSocket::SocketError)>(
358 &QAbstractSocket::errorOccurred),
this, &QQmlDebugConnection::socketError);
359 connect(socket, &QAbstractSocket::stateChanged,
this, &QQmlDebugConnection::socketStateChanged);
360 socket->connectToHost(hostName, port);
365 Q_D(QQmlDebugConnection);
369 d->server->deleteLater();
370 d->server =
new QLocalServer(
this);
372 connect(d->server, &QLocalServer::newConnection,
373 this, &QQmlDebugConnection::newConnection, Qt::QueuedConnection);
374 d->server->listen(fileName);
405 Q_D(QQmlDebugConnection);
407 QLocalSocket *socket = d->server->nextPendingConnection();
411 connect(socket, &QLocalSocket::disconnected,
this, &QQmlDebugConnection::socketDisconnected);
414 connect(translator, &LocalSocketSignalTranslator::socketError,
415 this, &QQmlDebugConnection::socketError);
416 connect(translator, &LocalSocketSignalTranslator::socketStateChanged,
417 this, &QQmlDebugConnection::socketStateChanged);
423 Q_Q(QQmlDebugConnection);
425 protocol =
new QPacketProtocol(device, q);
426 QObject::connect(protocol, &QPacketProtocol::readyRead,
427 q, &QQmlDebugConnection::protocolReadyRead);
432#include <qqmldebugconnection.moc>
434#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