1 #include "tinysvcmdns.h"
2 
3 extern "C" {
4 #include "mdnsd.h"
5 }
6 
7 #include <QHostInfo>
8 #include <QNetworkInterface>
9 #include <QtEndian>
10 
11 #include "core/logging.h"
12 
CreateMdnsd(uint32_t ipv4,QString ipv6)13 void TinySVCMDNS::CreateMdnsd(uint32_t ipv4, QString ipv6) {
14   // Get our hostname
15   QString host = QHostInfo::localHostName();
16 
17   // Start the service
18   mdnsd* mdnsd = mdnsd_start_bind(ipv4);
19 
20   // Set our hostname
21   mdnsd_set_hostname(mdnsd, QString(host + ".local").toUtf8().constData(),
22                      ipv4);
23 
24   // Add to the list
25   mdnsd_.append(mdnsd);
26 }
27 
TinySVCMDNS()28 TinySVCMDNS::TinySVCMDNS() {
29   // Get all network interfaces
30   QList<QNetworkInterface> network_interfaces =
31       QNetworkInterface::allInterfaces();
32   for (QNetworkInterface network_interface : network_interfaces) {
33     // Only use up and non loopback interfaces
34     if (network_interface.flags().testFlag(network_interface.IsUp) &&
35         !network_interface.flags().testFlag(network_interface.IsLoopBack)) {
36       uint32_t ipv4 = 0;
37       QString ipv6;
38 
39       qLog(Debug) << "Interface" << network_interface.humanReadableName();
40 
41       // Now check all network addresses for this device
42       QList<QNetworkAddressEntry> network_address_entries =
43           network_interface.addressEntries();
44 
45       for (QNetworkAddressEntry network_address_entry :
46            network_address_entries) {
47         QHostAddress host_address = network_address_entry.ip();
48         if (host_address.protocol() == QAbstractSocket::IPv4Protocol) {
49           ipv4 = qToBigEndian(host_address.toIPv4Address());
50           qLog(Debug) << "  ipv4:" << host_address.toString();
51         } else if (host_address.protocol() == QAbstractSocket::IPv6Protocol) {
52           ipv6 = host_address.toString();
53           qLog(Debug) << "  ipv6:" << host_address.toString();
54         }
55       }
56 
57       // Now start the service
58       CreateMdnsd(ipv4, ipv6);
59     }
60   }
61 }
62 
~TinySVCMDNS()63 TinySVCMDNS::~TinySVCMDNS() {
64   for (mdnsd* mdnsd : mdnsd_) {
65     mdnsd_stop(mdnsd);
66   }
67 }
68 
PublishInternal(const QString & domain,const QString & type,const QByteArray & name,quint16 port)69 void TinySVCMDNS::PublishInternal(const QString& domain, const QString& type,
70                                   const QByteArray& name, quint16 port) {
71 
72   // Some pointless text, so tinymDNS publishes the service correctly.
73   const char* txt[] = {"cat=nyan", nullptr};
74 
75   for (mdnsd* mdnsd : mdnsd_) {
76     mdnsd_register_svc(mdnsd, name.constData(),
77                        QString(type + ".local").toUtf8().constData(), port,
78                        nullptr, txt);
79   }
80 }
81