File indexing completed on 2024-05-12 04:58:53

0001 /**
0002  * SPDX-FileCopyrightText: 2023 Albert Vaca Cintora <albertvaka@gmail.com>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005  */
0006 
0007 #ifndef KDECONNECT_MDNS_WRAPPER_H
0008 #define KDECONNECT_MDNS_WRAPPER_H
0009 
0010 #include <QHostAddress>
0011 #include <QMap>
0012 #include <QSocketNotifier>
0013 #include <QString>
0014 #include <QVector>
0015 
0016 #include "kdeconnectcore_export.h"
0017 
0018 /**
0019  * A Qt wrapper for the mdns.h header-only library
0020  * from https://github.com/mjansson/mdns
0021  */
0022 namespace MdnsWrapper
0023 {
0024 class KDECONNECTCORE_EXPORT Discoverer : public QObject
0025 {
0026     Q_OBJECT
0027 
0028 public:
0029     struct MdnsService {
0030         QString name; // The instance-name part in "<instance-name>._<service-type>._tcp.local."
0031         uint16_t port;
0032         QHostAddress address; // An IPv4 address (IPv6 addresses are ignored)
0033         QMap<QString, QString> txtRecords;
0034     };
0035 
0036     // serviceType must be of the form "_<service-type>._<tcp/udp>.local"
0037     void startDiscovering(const QString &serviceType);
0038     void stopDiscovering();
0039 
0040     void sendQuery(const QString &serviceType);
0041 
0042 Q_SIGNALS:
0043     void serviceFound(const MdnsWrapper::Discoverer::MdnsService &service);
0044 
0045 private:
0046     int listenForQueryResponses();
0047     void stopListeningForQueryResponses();
0048 
0049     QVector<QSocketNotifier *> responseSocketNotifiers;
0050 };
0051 
0052 class KDECONNECTCORE_EXPORT Announcer : public QObject
0053 {
0054     Q_OBJECT
0055 
0056 public:
0057     struct AnnouncedInfo {
0058         QByteArray serviceType; // ie: "_<service-type>._tcp.local."
0059         QByteArray serviceInstance; // ie: "<instance-name>._<service-type>._tcp.local."
0060         QByteArray hostname; // ie: "<hostname>.local."
0061         QVector<QHostAddress> addressesV4;
0062         QVector<QHostAddress> addressesV6;
0063         uint16_t port;
0064         QHash<QByteArray, QByteArray> txtRecords;
0065     };
0066 
0067     // serviceType must be of the form "_<service-type>._<tcp/udp>.local"
0068     Announcer(const QString &instanceName, const QString &serviceType, uint16_t port);
0069 
0070     void putTxtRecord(const QString &key, const QString &value)
0071     {
0072         self.txtRecords[key.toLatin1()] = value.toLatin1();
0073     }
0074 
0075     void startAnnouncing();
0076     void stopAnnouncing();
0077 
0078     void sendMulticastAnnounce(bool isGoodbye);
0079 
0080 public Q_SLOTS:
0081     // notify that network interfaces changed since the creation of this Announcer
0082     void onNetworkChange()
0083     {
0084         detectHostAddresses();
0085     }
0086 
0087 private:
0088     int listenForQueries();
0089     void stopListeningForQueries();
0090 
0091     void detectHostAddresses();
0092 
0093     AnnouncedInfo self;
0094 
0095     QSocketNotifier *socketNotifier = nullptr;
0096     QSocketNotifier *socketNotifierV6 = nullptr;
0097 };
0098 
0099 } // namespace MdnsWrapper
0100 
0101 #endif