KDNSSD

avahi-domainbrowser.cpp
1 /*
2  This file is part of the KDE project
3 
4  SPDX-FileCopyrightText: 2004 Jakub Stachowski <[email protected]>
5  SPDX-FileCopyrightText: 2018 Harald Sitter <[email protected]>
6 
7  SPDX-License-Identifier: LGPL-2.0-or-later
8 */
9 
10 #include "avahi-domainbrowser_p.h"
11 #include "avahi_domainbrowser_interface.h"
12 #include "avahi_server_interface.h"
13 #include "domainbrowser.h"
14 #include <QFile>
15 #include <QIODevice>
16 #include <QSet>
17 #include <QStandardPaths>
18 #include <avahi-common/defs.h>
19 
20 namespace KDNSSD
21 {
23  : QObject(parent)
24  , d(new DomainBrowserPrivate(type, this))
25 {
26 }
27 
28 DomainBrowser::~DomainBrowser() = default;
29 
31 {
32  Q_D(DomainBrowser);
33  if (d->m_started) {
34  return;
35  }
36  d->m_started = true;
37 
38  // Do not race!
39  // https://github.com/lathiat/avahi/issues/9
40  // Avahi's DBus API is incredibly racey with signals getting fired
41  // immediately after a request was made even though we may not yet be
42  // listening. In lieu of a proper upstream fix for this we'll unfortunately
43  // have to resort to this hack:
44  // We register to all signals regardless of path and then filter them once
45  // we know what "our" path is. This is much more fragile than a proper
46  // QDBusInterface assisted signal connection but unfortunately the only way
47  // we can reliably prevent signals getting lost in the race.
48  // This uses a fancy trick whereby using QDBusMessage as last argument will
49  // give us the correct signal argument types as well as the underlying
50  // message so that we may check the message path.
51  QDBusConnection::systemBus().connect("org.freedesktop.Avahi",
52  "",
53  "org.freedesktop.Avahi.DomainBrowser",
54  "ItemNew",
55  d,
56  SLOT(gotGlobalItemNew(int, int, QString, uint, QDBusMessage)));
57  QDBusConnection::systemBus().connect("org.freedesktop.Avahi",
58  "",
59  "org.freedesktop.Avahi.DomainBrowser",
60  "ItemRemove",
61  d,
62  SLOT(gotGlobalItemRemove(int, int, QString, uint, QDBusMessage)));
64  .connect("org.freedesktop.Avahi", "", "org.freedesktop.Avahi.DomainBrowser", "AllForNow", d, SLOT(gotGlobalAllForNow(QDBusMessage)));
65  d->m_dbusObjectPath.clear();
66 
67  org::freedesktop::Avahi::Server s(QStringLiteral("org.freedesktop.Avahi"), QStringLiteral("/"), QDBusConnection::systemBus());
69  s.DomainBrowserNew(-1, -1, QString(), (d->m_type == Browsing) ? AVAHI_DOMAIN_BROWSER_BROWSE : AVAHI_DOMAIN_BROWSER_REGISTER, 0);
70  if (!rep.isValid()) {
71  return;
72  }
73 
74  d->m_dbusObjectPath = rep.value().path();
75 
76  // This is held because we need to explicitly Free it!
77  d->m_browser = new org::freedesktop::Avahi::DomainBrowser(s.service(), d->m_dbusObjectPath, s.connection());
78 
79  if (d->m_type == Browsing) {
80  QString domains_evar = QString::fromLocal8Bit(qgetenv("AVAHI_BROWSE_DOMAINS"));
81  if (!domains_evar.isEmpty()) {
82  const QStringList edomains = domains_evar.split(QLatin1Char(':'));
83  for (const QString &s : edomains) {
84  d->gotNewDomain(-1, -1, s, 0);
85  }
86  }
87  // FIXME: watch this file and restart browser if it changes
89  QFile domains_cfg(confDir + QStringLiteral("/avahi/browse-domains"));
90  if (domains_cfg.open(QIODevice::ReadOnly | QIODevice::Text))
91  while (!domains_cfg.atEnd()) {
92  d->gotNewDomain(-1, -1, QString::fromUtf8(domains_cfg.readLine().data()).trimmed(), 0);
93  }
94  }
95 }
96 
97 void DomainBrowserPrivate::gotGlobalItemNew(int interface, int protocol, const QString &domain, uint flags, QDBusMessage msg)
98 {
99  if (!isOurMsg(msg)) {
100  return;
101  }
102  gotNewDomain(interface, protocol, domain, flags);
103 }
104 
105 void DomainBrowserPrivate::gotGlobalItemRemove(int interface, int protocol, const QString &domain, uint flags, QDBusMessage msg)
106 {
107  if (!isOurMsg(msg)) {
108  return;
109  }
110  gotRemoveDomain(interface, protocol, domain, flags);
111 }
112 
113 void DomainBrowserPrivate::gotGlobalAllForNow(QDBusMessage msg)
114 {
115  if (!isOurMsg(msg)) {
116  return;
117  }
118 }
119 
120 void DomainBrowserPrivate::gotNewDomain(int, int, const QString &domain, uint)
121 {
122  QString decoded = DNSToDomain(domain);
123  if (m_domains.contains(decoded)) {
124  return;
125  }
126  m_domains += decoded;
127  Q_EMIT m_parent->domainAdded(decoded);
128 }
129 
130 void DomainBrowserPrivate::gotRemoveDomain(int, int, const QString &domain, uint)
131 {
132  QString decoded = DNSToDomain(domain);
133  if (!m_domains.contains(decoded)) {
134  return;
135  }
136  Q_EMIT m_parent->domainRemoved(decoded);
137  m_domains.remove(decoded);
138 }
139 
141 {
142  Q_D(const DomainBrowser);
143  return d->m_domains.values();
144 }
145 
147 {
148  Q_D(const DomainBrowser);
149  return d->m_started;
150 }
151 
152 }
153 #include "moc_avahi-domainbrowser_p.cpp"
154 #include "moc_domainbrowser.cpp"
bool isRunning() const
Whether the browsing has been started.
DomainType
A type of domain recommendation.
Definition: domainbrowser.h:50
QString writableLocation(QStandardPaths::StandardLocation type)
Domains recommended for browsing for services on (using ServiceBrowser)
Definition: domainbrowser.h:52
QDBusConnection systemBus()
bool isValid() const const
void startBrowse()
Starts browsing.
QString fromLocal8Bit(const char *str, int size)
QString fromUtf8(const char *str, int size)
QDBusReply::Type value() const const
bool isEmpty() const const
QStringList split(const QString &sep, QString::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
virtual bool open(QIODevice::OpenMode mode) override
Browses recommended domains for browsing or publishing to.
Definition: domainbrowser.h:43
virtual bool atEnd() const const override
DomainBrowser(DomainType type, QObject *parent=nullptr)
Standard constructor.
bool connect(const QString &service, const QString &path, const QString &interface, const QString &name, QObject *receiver, const char *slot)
QStringList domains() const
The current known list of domains of the requested DomainType.
Q_EMITQ_EMIT
qint64 readLine(char *data, qint64 maxSize)
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Sun Aug 1 2021 22:40:38 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.