Compare commits
7 commits
master
...
work/udp-p
Author | SHA1 | Date | |
---|---|---|---|
|
3895d2823b | ||
|
fcf4930b4f | ||
|
1759a3f4f3 | ||
|
7ee85192c4 | ||
|
841d2c1476 | ||
|
8c69e48e2f | ||
|
9e51b7d814 |
7 changed files with 222 additions and 52 deletions
|
@ -65,7 +65,7 @@ else()
|
||||||
find_package(Qca-qt${QT_MAJOR_VERSION} ${QCA_MIN_VERSION} REQUIRED)
|
find_package(Qca-qt${QT_MAJOR_VERSION} ${QCA_MIN_VERSION} REQUIRED)
|
||||||
set(Qca_LIBRARY qca-qt${QT_MAJOR_VERSION})
|
set(Qca_LIBRARY qca-qt${QT_MAJOR_VERSION})
|
||||||
|
|
||||||
set(KF5_REQUIRED_COMPONENTS I18n ConfigWidgets DBusAddons IconThemes Notifications KIO KCMUtils Service Solid Kirigami2 People WindowSystem GuiAddons)
|
set(KF5_REQUIRED_COMPONENTS I18n ConfigWidgets DBusAddons IconThemes Notifications KIO KCMUtils Service Solid Kirigami2 People WindowSystem GuiAddons DNSSD)
|
||||||
set(KF5_OPTIONAL_COMPONENTS DocTools)
|
set(KF5_OPTIONAL_COMPONENTS DocTools)
|
||||||
|
|
||||||
set_package_properties(KF5Kirigami2 PROPERTIES
|
set_package_properties(KF5Kirigami2 PROPERTIES
|
||||||
|
|
|
@ -64,6 +64,7 @@ PRIVATE
|
||||||
Qt${QT_MAJOR_VERSION}::DBus
|
Qt${QT_MAJOR_VERSION}::DBus
|
||||||
KF5::I18n
|
KF5::I18n
|
||||||
KF5::ConfigCore
|
KF5::ConfigCore
|
||||||
|
KF5::DNSSD
|
||||||
)
|
)
|
||||||
|
|
||||||
if(${KF5KIO_FOUND})
|
if(${KF5KIO_FOUND})
|
||||||
|
|
|
@ -8,6 +8,7 @@ set(backends_kdeconnect_SRCS
|
||||||
backends/lan/compositeuploadjob.cpp
|
backends/lan/compositeuploadjob.cpp
|
||||||
backends/lan/uploadjob.cpp
|
backends/lan/uploadjob.cpp
|
||||||
backends/lan/socketlinereader.cpp
|
backends/lan/socketlinereader.cpp
|
||||||
|
backends/lan/mdnsdiscovery.cpp
|
||||||
|
|
||||||
PARENT_SCOPE
|
PARENT_SCOPE
|
||||||
)
|
)
|
||||||
|
|
|
@ -37,14 +37,13 @@
|
||||||
static const int MAX_UNPAIRED_CONNECTIONS = 42;
|
static const int MAX_UNPAIRED_CONNECTIONS = 42;
|
||||||
static const int MAX_REMEMBERED_IDENTITY_PACKETS = 42;
|
static const int MAX_REMEMBERED_IDENTITY_PACKETS = 42;
|
||||||
|
|
||||||
LanLinkProvider::LanLinkProvider(bool testMode, quint16 udpBroadcastPort, quint16 udpListenPort)
|
LanLinkProvider::LanLinkProvider(bool testMode)
|
||||||
: m_server(new Server(this))
|
: m_server(new Server(this))
|
||||||
, m_udpSocket(this)
|
, m_udpSocket(this)
|
||||||
, m_tcpPort(0)
|
, m_tcpPort(0)
|
||||||
, m_udpBroadcastPort(udpBroadcastPort)
|
|
||||||
, m_udpListenPort(udpListenPort)
|
|
||||||
, m_testMode(testMode)
|
, m_testMode(testMode)
|
||||||
, m_combineBroadcastsTimer(this)
|
, m_combineBroadcastsTimer(this)
|
||||||
|
, m_mdnsDiscovery(this)
|
||||||
{
|
{
|
||||||
m_combineBroadcastsTimer.setInterval(0); // increase this if waiting a single event-loop iteration is not enough
|
m_combineBroadcastsTimer.setInterval(0); // increase this if waiting a single event-loop iteration is not enough
|
||||||
m_combineBroadcastsTimer.setSingleShot(true);
|
m_combineBroadcastsTimer.setSingleShot(true);
|
||||||
|
@ -82,12 +81,12 @@ void LanLinkProvider::onStart()
|
||||||
{
|
{
|
||||||
const QHostAddress bindAddress = m_testMode ? QHostAddress::LocalHost : QHostAddress::Any;
|
const QHostAddress bindAddress = m_testMode ? QHostAddress::LocalHost : QHostAddress::Any;
|
||||||
|
|
||||||
bool success = m_udpSocket.bind(bindAddress, m_udpListenPort, QUdpSocket::ShareAddress);
|
bool success = m_udpSocket.bind(bindAddress, UDP_PORT, QUdpSocket::ShareAddress);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
QAbstractSocket::SocketError sockErr = m_udpSocket.error();
|
QAbstractSocket::SocketError sockErr = m_udpSocket.error();
|
||||||
// Refer to https://doc.qt.io/qt-5/qabstractsocket.html#SocketError-enum to decode socket error number
|
// Refer to https://doc.qt.io/qt-5/qabstractsocket.html#SocketError-enum to decode socket error number
|
||||||
QString errorMessage = QString::fromLatin1(QMetaEnum::fromType<QAbstractSocket::SocketError>().valueToKey(sockErr));
|
QString errorMessage = QString::fromLatin1(QMetaEnum::fromType<QAbstractSocket::SocketError>().valueToKey(sockErr));
|
||||||
qCritical(KDECONNECT_CORE) << QLatin1String("Failed to bind UDP socket on port") << m_udpListenPort << QLatin1String("with error") << errorMessage;
|
qCritical(KDECONNECT_CORE) << QLatin1String("Failed to bind UDP socket on port") << UDP_PORT << QLatin1String("with error") << errorMessage;
|
||||||
}
|
}
|
||||||
Q_ASSERT(success);
|
Q_ASSERT(success);
|
||||||
|
|
||||||
|
@ -101,12 +100,17 @@ void LanLinkProvider::onStart()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onNetworkChange();
|
broadcastUdpIdentityPacket();
|
||||||
|
m_mdnsDiscovery.startAnnouncing();
|
||||||
|
m_mdnsDiscovery.startDiscovering();
|
||||||
|
|
||||||
qCDebug(KDECONNECT_CORE) << "LanLinkProvider started";
|
qCDebug(KDECONNECT_CORE) << "LanLinkProvider started";
|
||||||
}
|
}
|
||||||
|
|
||||||
void LanLinkProvider::onStop()
|
void LanLinkProvider::onStop()
|
||||||
{
|
{
|
||||||
|
m_mdnsDiscovery.stopAnnouncing();
|
||||||
|
m_mdnsDiscovery.stopDiscovering();
|
||||||
m_udpSocket.close();
|
m_udpSocket.close();
|
||||||
m_server->close();
|
m_server->close();
|
||||||
qCDebug(KDECONNECT_CORE) << "LanLinkProvider stopped";
|
qCDebug(KDECONNECT_CORE) << "LanLinkProvider stopped";
|
||||||
|
@ -125,44 +129,26 @@ void LanLinkProvider::onNetworkChange()
|
||||||
void LanLinkProvider::broadcastToNetwork()
|
void LanLinkProvider::broadcastToNetwork()
|
||||||
{
|
{
|
||||||
if (!m_server->isListening()) {
|
if (!m_server->isListening()) {
|
||||||
// Not started
|
qWarning() << "TCP server not listening, not broadcasting";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_ASSERT(m_tcpPort != 0);
|
Q_ASSERT(m_tcpPort != 0);
|
||||||
|
|
||||||
|
broadcastUdpIdentityPacket();
|
||||||
|
m_mdnsDiscovery.stopDiscovering();
|
||||||
|
m_mdnsDiscovery.startDiscovering();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LanLinkProvider::broadcastUdpIdentityPacket()
|
||||||
|
{
|
||||||
|
if (qEnvironmentVariableIsSet("KDECONNECT_DISABLE_UDP_BROADCAST")) {
|
||||||
|
qWarning() << "Not broadcasting UDP because KDECONNECT_DISABLE_UDP_BROADCAST is set";
|
||||||
|
return;
|
||||||
|
}
|
||||||
qCDebug(KDECONNECT_CORE()) << "Broadcasting identity packet";
|
qCDebug(KDECONNECT_CORE()) << "Broadcasting identity packet";
|
||||||
|
|
||||||
QList<QHostAddress> destinations = getBroadcastAddresses();
|
QList<QHostAddress> addresses = getBroadcastAddresses();
|
||||||
|
|
||||||
NetworkPacket np = KdeConnectConfig::instance().deviceInfo().toIdentityPacket();
|
|
||||||
np.set(QStringLiteral("tcpPort"), m_tcpPort);
|
|
||||||
#if defined(Q_OS_MAC) || defined(Q_OS_FREEBSD)
|
|
||||||
// On macOS and FreeBSD, the too large UDP packet (larger than MTU) causes
|
|
||||||
// incomplete transmission.
|
|
||||||
// We remove the capacitilities to reduce the discovery packet to the min
|
|
||||||
// MTU of the interfaces with broadcast feature.
|
|
||||||
int mtu = 1500;
|
|
||||||
for (const QNetworkInterface &iface : QNetworkInterface::allInterfaces()) {
|
|
||||||
if ((iface.flags() & QNetworkInterface::IsUp) && (iface.flags() & QNetworkInterface::IsRunning) && (iface.flags() & QNetworkInterface::CanBroadcast)) {
|
|
||||||
int ifaceMtu = iface.maximumTransmissionUnit();
|
|
||||||
if (ifaceMtu < mtu && ifaceMtu > 0) {
|
|
||||||
mtu = ifaceMtu;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
QByteArray payload = np.serialize();
|
|
||||||
if (payload.length() > mtu) {
|
|
||||||
// First try to drop the less important outgoing capabilities
|
|
||||||
np.set(QStringLiteral("outgoingCapabilities"), QStringList());
|
|
||||||
payload = np.serialize();
|
|
||||||
}
|
|
||||||
if (payload.length() > mtu) {
|
|
||||||
// If still too large, drop the incoming capabilities
|
|
||||||
np.set(QStringLiteral("incomingCapabilities"), QStringList());
|
|
||||||
payload = np.serialize();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(Q_OS_WIN) || defined(Q_OS_FREEBSD)
|
#if defined(Q_OS_WIN) || defined(Q_OS_FREEBSD)
|
||||||
// On Windows and FreeBSD we need to broadcast from every local IP address to reach all networks
|
// On Windows and FreeBSD we need to broadcast from every local IP address to reach all networks
|
||||||
|
@ -175,17 +161,18 @@ void LanLinkProvider::broadcastToNetwork()
|
||||||
if (sourceAddress.protocol() == QAbstractSocket::IPv4Protocol && sourceAddress != QHostAddress::LocalHost) {
|
if (sourceAddress.protocol() == QAbstractSocket::IPv4Protocol && sourceAddress != QHostAddress::LocalHost) {
|
||||||
qCDebug(KDECONNECT_CORE()) << "Broadcasting as" << sourceAddress;
|
qCDebug(KDECONNECT_CORE()) << "Broadcasting as" << sourceAddress;
|
||||||
sendSocket.bind(sourceAddress);
|
sendSocket.bind(sourceAddress);
|
||||||
sendBroadcasts(sendSocket, np, destinations);
|
sendUdpIdentityPacket(sendSocket, addresses);
|
||||||
sendSocket.close();
|
sendSocket.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
sendBroadcasts(m_udpSocket, np, destinations);
|
sendUdpIdentityPacket(addresses);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QList<QHostAddress> LanLinkProvider::getBroadcastAddresses()
|
QList<QHostAddress> LanLinkProvider::getBroadcastAddresses()
|
||||||
{
|
{
|
||||||
const QStringList customDevices = KdeConnectConfig::instance().customDevices();
|
const QStringList customDevices = KdeConnectConfig::instance().customDevices();
|
||||||
|
@ -209,12 +196,31 @@ QList<QHostAddress> LanLinkProvider::getBroadcastAddresses()
|
||||||
return destinations;
|
return destinations;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LanLinkProvider::sendBroadcasts(QUdpSocket &socket, const NetworkPacket &np, const QList<QHostAddress> &addresses)
|
void LanLinkProvider::sendUdpIdentityPacket(const QList<QHostAddress> &addresses)
|
||||||
{
|
{
|
||||||
const QByteArray payload = np.serialize();
|
sendUdpIdentityPacket(m_udpSocket, addresses);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LanLinkProvider::sendUdpIdentityPacket(QUdpSocket &socket, const QList<QHostAddress> &addresses)
|
||||||
|
{
|
||||||
|
DeviceInfo myDeviceInfo = KdeConnectConfig::instance().deviceInfo();
|
||||||
|
NetworkPacket identityPacket = myDeviceInfo.toIdentityPacket();
|
||||||
|
identityPacket.set(QStringLiteral("tcpPort"), m_tcpPort);
|
||||||
|
const QByteArray payload = identityPacket.serialize();
|
||||||
|
|
||||||
for (auto &address : addresses) {
|
for (auto &address : addresses) {
|
||||||
socket.writeDatagram(payload, address, m_udpBroadcastPort);
|
qint64 bytes = socket.writeDatagram(payload, address, UDP_PORT);
|
||||||
|
if (bytes == -1 && socket.error() == QAbstractSocket::DatagramTooLargeError) {
|
||||||
|
// On macOS and FreeBSD, UDP broadcasts larger than MTU get dropped. See:
|
||||||
|
// https://opensource.apple.com/source/xnu/xnu-3789.1.32/bsd/netinet/ip_output.c.auto.html#:~:text=/*%20don%27t%20allow%20broadcast%20messages%20to%20be%20fragmented%20*/
|
||||||
|
// We remove the capabilities to reduce the size of the packet.
|
||||||
|
// This should only happen for broadcasts, so UDP packets sent from MDNS discoveries should still work.
|
||||||
|
qWarning() << "Identity packet to" << address << "got rejected because it was too large. Retrying without including the capabilities";
|
||||||
|
identityPacket.set(QStringLiteral("outgoingCapabilities"), QStringList());
|
||||||
|
identityPacket.set(QStringLiteral("incomingCapabilities"), QStringList());
|
||||||
|
const QByteArray smallPayload = identityPacket.serialize();
|
||||||
|
socket.writeDatagram(smallPayload, address, UDP_PORT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,7 +301,7 @@ void LanLinkProvider::connectError(QAbstractSocket::SocketError socketError)
|
||||||
qCDebug(KDECONNECT_CORE) << "Fallback (1), try reverse connection (send udp packet)" << socket->errorString();
|
qCDebug(KDECONNECT_CORE) << "Fallback (1), try reverse connection (send udp packet)" << socket->errorString();
|
||||||
NetworkPacket np = KdeConnectConfig::instance().deviceInfo().toIdentityPacket();
|
NetworkPacket np = KdeConnectConfig::instance().deviceInfo().toIdentityPacket();
|
||||||
np.set(QStringLiteral("tcpPort"), m_tcpPort);
|
np.set(QStringLiteral("tcpPort"), m_tcpPort);
|
||||||
m_udpSocket.writeDatagram(np.serialize(), m_receivedIdentityPackets[socket].sender, m_udpBroadcastPort);
|
m_udpSocket.writeDatagram(np.serialize(), m_receivedIdentityPackets[socket].sender, UDP_PORT);
|
||||||
|
|
||||||
// The socket we created didn't work, and we didn't manage
|
// The socket we created didn't work, and we didn't manage
|
||||||
// to create a LanDeviceLink from it, deleting everything.
|
// to create a LanDeviceLink from it, deleting everything.
|
||||||
|
@ -350,7 +356,7 @@ void LanLinkProvider::tcpSocketConnected()
|
||||||
// The socket doesn't seem to work, so we can't create the connection.
|
// The socket doesn't seem to work, so we can't create the connection.
|
||||||
|
|
||||||
qCDebug(KDECONNECT_CORE) << "Fallback (2), try reverse connection (send udp packet)";
|
qCDebug(KDECONNECT_CORE) << "Fallback (2), try reverse connection (send udp packet)";
|
||||||
m_udpSocket.writeDatagram(np2.serialize(), m_receivedIdentityPackets[socket].sender, m_udpBroadcastPort);
|
m_udpSocket.writeDatagram(np2.serialize(), m_receivedIdentityPackets[socket].sender, UDP_PORT);
|
||||||
|
|
||||||
// Cleanup the network packet now. The socket should be deleted via the disconnected() signal.
|
// Cleanup the network packet now. The socket should be deleted via the disconnected() signal.
|
||||||
// We don't do this on success, because it is done later in the encrypted() slot.
|
// We don't do this on success, because it is done later in the encrypted() slot.
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "backends/linkprovider.h"
|
#include "backends/linkprovider.h"
|
||||||
#include "kdeconnectcore_export.h"
|
#include "kdeconnectcore_export.h"
|
||||||
#include "landevicelink.h"
|
#include "landevicelink.h"
|
||||||
|
#include "mdnsdiscovery.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
|
|
||||||
class KDECONNECTCORE_EXPORT LanLinkProvider : public LinkProvider
|
class KDECONNECTCORE_EXPORT LanLinkProvider : public LinkProvider
|
||||||
|
@ -26,10 +27,8 @@ class KDECONNECTCORE_EXPORT LanLinkProvider : public LinkProvider
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @param testMode Some special overrides needed while testing
|
* @param testMode Some special overrides needed while testing
|
||||||
* @param udpBroadcastPort Port which should be used for *sending* identity packets
|
|
||||||
* @param udpListenPort Port which should be used for *receiving* identity packets
|
|
||||||
*/
|
*/
|
||||||
LanLinkProvider(bool testMode = false, quint16 udpBroadcastPort = UDP_PORT, quint16 udpListenPort = UDP_PORT);
|
LanLinkProvider(bool testMode = false);
|
||||||
~LanLinkProvider() override;
|
~LanLinkProvider() override;
|
||||||
|
|
||||||
QString name() override
|
QString name() override
|
||||||
|
@ -37,6 +36,8 @@ public:
|
||||||
return QStringLiteral("LanLinkProvider");
|
return QStringLiteral("LanLinkProvider");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sendUdpIdentityPacket(const QList<QHostAddress> &addresses);
|
||||||
|
|
||||||
static void configureSslSocket(QSslSocket *socket, const QString &deviceId, bool isDeviceTrusted);
|
static void configureSslSocket(QSslSocket *socket, const QString &deviceId, bool isDeviceTrusted);
|
||||||
static void configureSocket(QSslSocket *socket);
|
static void configureSocket(QSslSocket *socket);
|
||||||
|
|
||||||
|
@ -67,15 +68,13 @@ private:
|
||||||
void onNetworkConfigurationChanged(const QNetworkConfiguration &config);
|
void onNetworkConfigurationChanged(const QNetworkConfiguration &config);
|
||||||
void addLink(QSslSocket *socket, const DeviceInfo &deviceInfo);
|
void addLink(QSslSocket *socket, const DeviceInfo &deviceInfo);
|
||||||
QList<QHostAddress> getBroadcastAddresses();
|
QList<QHostAddress> getBroadcastAddresses();
|
||||||
void sendBroadcasts(QUdpSocket &socket, const NetworkPacket &np, const QList<QHostAddress> &addresses);
|
void sendUdpIdentityPacket(QUdpSocket &socket, const QList<QHostAddress> &addresses);
|
||||||
|
void broadcastUdpIdentityPacket();
|
||||||
|
|
||||||
Server *m_server;
|
Server *m_server;
|
||||||
QUdpSocket m_udpSocket;
|
QUdpSocket m_udpSocket;
|
||||||
quint16 m_tcpPort;
|
quint16 m_tcpPort;
|
||||||
|
|
||||||
quint16 m_udpBroadcastPort;
|
|
||||||
quint16 m_udpListenPort;
|
|
||||||
|
|
||||||
QMap<QString, LanDeviceLink *> m_links;
|
QMap<QString, LanDeviceLink *> m_links;
|
||||||
|
|
||||||
struct PendingConnect {
|
struct PendingConnect {
|
||||||
|
@ -86,6 +85,8 @@ private:
|
||||||
QNetworkConfiguration m_lastConfig;
|
QNetworkConfiguration m_lastConfig;
|
||||||
const bool m_testMode;
|
const bool m_testMode;
|
||||||
QTimer m_combineBroadcastsTimer;
|
QTimer m_combineBroadcastsTimer;
|
||||||
|
|
||||||
|
MdnsDiscovery m_mdnsDiscovery;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
120
core/backends/lan/mdnsdiscovery.cpp
Normal file
120
core/backends/lan/mdnsdiscovery.cpp
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
/**
|
||||||
|
* SPDX-FileCopyrightText: 2023 Albert Vaca <albertvaka@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mdnsdiscovery.h"
|
||||||
|
|
||||||
|
#include "core_debug.h"
|
||||||
|
#include "kdeconnectconfig.h"
|
||||||
|
#include "lanlinkprovider.h"
|
||||||
|
|
||||||
|
#include <KDNSSD/DNSSD/PublicService>
|
||||||
|
#include <KDNSSD/DNSSD/RemoteService>
|
||||||
|
#include <KDNSSD/DNSSD/ServiceBrowser>
|
||||||
|
|
||||||
|
const QString kServiceName = QStringLiteral("_kdeconnect._udp");
|
||||||
|
|
||||||
|
MdnsDiscovery::MdnsDiscovery(LanLinkProvider *lanLinkProvider)
|
||||||
|
: lanLinkProvider(lanLinkProvider)
|
||||||
|
{
|
||||||
|
switch (KDNSSD::ServiceBrowser::isAvailable()) {
|
||||||
|
case KDNSSD::ServiceBrowser::Stopped:
|
||||||
|
qWarning() << "mDNS or Avahi daemons are not running, mDNS discovery not available";
|
||||||
|
break;
|
||||||
|
case KDNSSD::ServiceBrowser::Working:
|
||||||
|
qCDebug(KDECONNECT_CORE) << "mDNS discovery is available";
|
||||||
|
break;
|
||||||
|
case KDNSSD::ServiceBrowser::Unsupported:
|
||||||
|
qWarning() << "mDNS discovery not available (library built without DNS-SD support)";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MdnsDiscovery::~MdnsDiscovery()
|
||||||
|
{
|
||||||
|
stopAnnouncing();
|
||||||
|
stopDiscovering();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MdnsDiscovery::startAnnouncing()
|
||||||
|
{
|
||||||
|
if (m_publisher != nullptr) {
|
||||||
|
qCDebug(KDECONNECT_CORE) << "MDNS already announcing";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
qCDebug(KDECONNECT_CORE) << "MDNS start announcing";
|
||||||
|
|
||||||
|
KdeConnectConfig &config = KdeConnectConfig::instance();
|
||||||
|
|
||||||
|
m_publisher = new KDNSSD::PublicService(config.deviceId(), kServiceName, LanLinkProvider::UDP_PORT, QStringLiteral("local"));
|
||||||
|
m_publisher->setParent(this);
|
||||||
|
|
||||||
|
// We can't fit the device certificate in this field, so this is not enough info to create a Device and won't be used.
|
||||||
|
QMap<QString, QByteArray> data;
|
||||||
|
data[QStringLiteral("id")] = config.deviceId().toUtf8();
|
||||||
|
data[QStringLiteral("name")] = config.name().toUtf8();
|
||||||
|
data[QStringLiteral("type")] = config.deviceType().toString().toUtf8();
|
||||||
|
data[QStringLiteral("protocol")] = QString::number(NetworkPacket::s_protocolVersion).toUtf8();
|
||||||
|
m_publisher->setTextData(data);
|
||||||
|
|
||||||
|
connect(m_publisher, &KDNSSD::PublicService::published, [](bool successful) {
|
||||||
|
if (successful) {
|
||||||
|
qCDebug(KDECONNECT_CORE) << "MDNS published successfully";
|
||||||
|
} else {
|
||||||
|
qWarning() << "MDNS failed to publish";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
m_publisher->publishAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MdnsDiscovery::stopAnnouncing()
|
||||||
|
{
|
||||||
|
if (m_publisher != nullptr) {
|
||||||
|
qCDebug(KDECONNECT_CORE) << "MDNS stop announcing";
|
||||||
|
delete m_publisher;
|
||||||
|
m_publisher = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MdnsDiscovery::startDiscovering()
|
||||||
|
{
|
||||||
|
if (m_serviceBrowser != nullptr) {
|
||||||
|
qCDebug(KDECONNECT_CORE) << "MDNS already discovering";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
qCDebug(KDECONNECT_CORE) << "MDNS start discovering";
|
||||||
|
|
||||||
|
m_serviceBrowser = new KDNSSD::ServiceBrowser(kServiceName, true);
|
||||||
|
|
||||||
|
connect(m_serviceBrowser, &KDNSSD::ServiceBrowser::serviceAdded, [this](KDNSSD::RemoteService::Ptr service) {
|
||||||
|
if (KdeConnectConfig::instance().deviceId() == service->serviceName()) {
|
||||||
|
qCDebug(KDECONNECT_CORE) << "Discovered myself, ignoring";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
qCDebug(KDECONNECT_CORE) << "Discovered " << service->serviceName() << " at " << service->hostName();
|
||||||
|
QHostAddress address(service->hostName());
|
||||||
|
lanLinkProvider->sendUdpIdentityPacket(QList<QHostAddress>{address});
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(m_serviceBrowser, &KDNSSD::ServiceBrowser::serviceRemoved, [](KDNSSD::RemoteService::Ptr service) {
|
||||||
|
qCDebug(KDECONNECT_CORE) << "Lost " << service->serviceName();
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(m_serviceBrowser, &KDNSSD::ServiceBrowser::finished, []() {
|
||||||
|
qCDebug(KDECONNECT_CORE) << "Finished discovery";
|
||||||
|
});
|
||||||
|
|
||||||
|
m_serviceBrowser->startBrowse();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MdnsDiscovery::stopDiscovering()
|
||||||
|
{
|
||||||
|
if (m_serviceBrowser != nullptr) {
|
||||||
|
qCDebug(KDECONNECT_CORE) << "MDNS stop discovering";
|
||||||
|
delete m_serviceBrowser;
|
||||||
|
m_serviceBrowser = nullptr;
|
||||||
|
}
|
||||||
|
}
|
41
core/backends/lan/mdnsdiscovery.h
Normal file
41
core/backends/lan/mdnsdiscovery.h
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
/**
|
||||||
|
* SPDX-FileCopyrightText: 2023 Albert Vaca Cintora <albertvaka@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KDECONNECT_MDNS_DISCOVERY_H
|
||||||
|
#define KDECONNECT_MDNS_DISCOVERY_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "kdeconnectcore_export.h"
|
||||||
|
|
||||||
|
class LanLinkProvider;
|
||||||
|
namespace KDNSSD
|
||||||
|
{
|
||||||
|
class PublicService;
|
||||||
|
class ServiceBrowser;
|
||||||
|
};
|
||||||
|
|
||||||
|
class KDECONNECTCORE_EXPORT MdnsDiscovery : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit MdnsDiscovery(LanLinkProvider *parent);
|
||||||
|
~MdnsDiscovery();
|
||||||
|
|
||||||
|
void startDiscovering();
|
||||||
|
void stopDiscovering();
|
||||||
|
|
||||||
|
void stopAnnouncing();
|
||||||
|
void startAnnouncing();
|
||||||
|
|
||||||
|
private:
|
||||||
|
LanLinkProvider *lanLinkProvider = nullptr;
|
||||||
|
KDNSSD::PublicService *m_publisher = nullptr;
|
||||||
|
KDNSSD::ServiceBrowser *m_serviceBrowser = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // KDECONNECT_SERVER_H
|
Loading…
Reference in a new issue