DeviceShare: Add UDP discovery for Design Studio

If the network allows UDP broadcasts and if the IP address
of the Qt UI Viewer has changed, we can update the device IP
without expecting the user to update it.

Change-Id: I50a89a9e2412220a3f8200aed807f691e5c9e377
Reviewed-by: Henning Gründl <henning.gruendl@qt.io>
This commit is contained in:
Burak Hancerli
2024-10-24 10:36:34 +02:00
parent cec3838fc4
commit 42cf37a43e
2 changed files with 71 additions and 5 deletions

View File

@@ -6,9 +6,8 @@
#include <QFile>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QRegularExpression>
#include <QUdpSocket>
#include <QNetworkDatagram>
#include <QNetworkInterface>
namespace QmlDesigner::DeviceShare {
@@ -21,6 +20,71 @@ DeviceManager::DeviceManager(QObject *parent, const QString &settingsPath)
m_uuid = QUuid::createUuid().toString(QUuid::WithoutBraces);
writeSettings();
}
initUdpDiscovery();
}
void DeviceManager::initUdpDiscovery()
{
const QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
for (const QNetworkInterface &interface : interfaces) {
if (interface.flags().testFlag(QNetworkInterface::IsUp)
&& interface.flags().testFlag(QNetworkInterface::IsRunning)
&& !interface.flags().testFlag(QNetworkInterface::IsLoopBack)) {
for (const QNetworkAddressEntry &entry : interface.addressEntries()) {
if (entry.ip().protocol() == QAbstractSocket::IPv4Protocol) {
QSharedPointer<QUdpSocket> udpSocket = QSharedPointer<QUdpSocket>::create();
connect(udpSocket.data(),
&QUdpSocket::readyRead,
this,
&DeviceManager::incomingDatagram);
bool retVal = udpSocket->bind(entry.ip(), 53452, QUdpSocket::ShareAddress);
if (!retVal) {
qCWarning(deviceSharePluginLog)
<< "UDP:: Failed to bind to UDP port 53452 on" << entry.ip().toString()
<< "on interface" << interface.name()
<< ". Error:" << udpSocket->errorString();
continue;
}
qCDebug(deviceSharePluginLog) << "UDP:: Listening on" << entry.ip().toString()
<< "port" << udpSocket->localPort();
m_udpSockets.append(udpSocket);
}
}
}
}
}
void DeviceManager::incomingDatagram()
{
const auto udpSocket = qobject_cast<QUdpSocket *>(sender());
if (!udpSocket)
return;
while (udpSocket->hasPendingDatagrams()) {
const QNetworkDatagram datagram = udpSocket->receiveDatagram();
const QJsonDocument doc = QJsonDocument::fromJson(datagram.data());
const QJsonObject message = doc.object();
if (message["name"].toString() != "__qtuiviewer__") {
continue;
}
const QString id = message["id"].toString();
const QString ip = datagram.senderAddress().toString();
qCDebug(deviceSharePluginLog) << "Qt UI VIewer found at" << ip << "with id" << id;
for (const auto &device : m_devices) {
if (device->deviceInfo().deviceId() == id) {
if (device->deviceSettings().ipAddress() != ip) {
qCDebug(deviceSharePluginLog) << "Updating IP address for device" << id;
setDeviceIP(id, ip);
}
}
}
}
}
void DeviceManager::writeSettings()

View File

@@ -3,8 +3,7 @@
#pragma once
#include <QObject>
#include <QTimer>
#include <QUdpSocket>
#include <QWebSocketServer>
#include "device.h"
@@ -37,6 +36,7 @@ public:
private:
// Devices management
QList<QSharedPointer<Device>> m_devices;
QList<QSharedPointer<QUdpSocket>> m_udpSockets;
// settings
const QString m_settingsPath;
@@ -44,6 +44,8 @@ private:
private:
// internal slots
void initUdpDiscovery();
void incomingDatagram();
void incomingConnection();
void readSettings();
void writeSettings();