KDNSSD

avahi-servicetypebrowser.cpp
1/*
2 This file is part of the KDE project
3
4 SPDX-FileCopyrightText: 2004, 2007 Jakub Stachowski <qbast@go2.pl>
5 SPDX-FileCopyrightText: 2018 Harald Sitter <sitter@kde.org>
6
7 SPDX-License-Identifier: LGPL-2.0-or-later
8*/
9
10#include "avahi-servicetypebrowser_p.h"
11#include "avahi_server_interface.h"
12#include "avahi_servicetypebrowser_interface.h"
13#include "servicetypebrowser.h"
14#include <QSet>
15
16#define UNSPEC -1
17namespace KDNSSD
18{
20 : QObject(parent)
21 , d(new ServiceTypeBrowserPrivate(this))
22{
24 d->m_domain = domain;
25 d->m_timer.setSingleShot(true);
26}
27
28ServiceTypeBrowser::~ServiceTypeBrowser() = default;
29
31{
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.ServiceTypeBrowser",
54 "ItemNew",
55 d,
56 SLOT(gotGlobalItemNew(int, int, QString, QString, uint, QDBusMessage)));
57 QDBusConnection::systemBus().connect("org.freedesktop.Avahi",
58 "",
59 "org.freedesktop.Avahi.ServiceTypeBrowser",
60 "ItemRemove",
61 d,
62 SLOT(gotGlobalItemRemove(int, int, QString, QString, uint, QDBusMessage)));
64 .connect("org.freedesktop.Avahi", "", "org.freedesktop.Avahi.ServiceTypeBrowser", "AllForNow", d, SLOT(gotGlobalAllForNow(QDBusMessage)));
65 d->m_dbusObjectPath.clear();
66
67 org::freedesktop::Avahi::Server s(QStringLiteral("org.freedesktop.Avahi"), QStringLiteral("/"), QDBusConnection::systemBus());
68
69 QDBusReply<QDBusObjectPath> rep = s.ServiceTypeBrowserNew(-1, -1, d->m_domain, 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::ServiceTypeBrowser(s.service(), d->m_dbusObjectPath, s.connection());
78
79 connect(&d->m_timer, SIGNAL(timeout()), d, SLOT(finished()));
80 d->m_timer.start(domainIsLocal(d->m_domain) ? TIMEOUT_LAST_SERVICE : TIMEOUT_START_WAN);
81}
82
83void ServiceTypeBrowserPrivate::finished()
84{
85 m_timer.stop();
86 Q_EMIT m_parent->finished();
87}
88
89void ServiceTypeBrowserPrivate::gotGlobalItemNew(int interface, int protocol, const QString &type, const QString &domain, uint flags, QDBusMessage msg)
90{
91 if (!isOurMsg(msg)) {
92 return;
93 }
94 gotNewServiceType(interface, protocol, type, domain, flags);
95}
96
97void ServiceTypeBrowserPrivate::gotGlobalItemRemove(int interface, int protocol, const QString &type, const QString &domain, uint flags, QDBusMessage msg)
98{
99 if (!isOurMsg(msg)) {
100 return;
101 }
102 gotRemoveServiceType(interface, protocol, type, domain, flags);
103}
104
105void ServiceTypeBrowserPrivate::gotGlobalAllForNow(QDBusMessage msg)
106{
107 if (!isOurMsg(msg)) {
108 return;
109 }
110 finished();
111}
112
113void ServiceTypeBrowserPrivate::gotNewServiceType(int, int, const QString &type, const QString &, uint)
114{
115 m_timer.start(TIMEOUT_LAST_SERVICE);
116 m_servicetypes += type;
117 Q_EMIT m_parent->serviceTypeAdded(type);
118}
119
120void ServiceTypeBrowserPrivate::gotRemoveServiceType(int, int, const QString &type, const QString &, uint)
121{
122 m_timer.start(TIMEOUT_LAST_SERVICE);
123 m_servicetypes.removeAll(type);
124 Q_EMIT m_parent->serviceTypeRemoved(type);
125}
126
128{
129 Q_D(const ServiceTypeBrowser);
130 return d->m_servicetypes;
131}
132
133}
134#include "moc_avahi-servicetypebrowser_p.cpp"
135#include "moc_servicetypebrowser.cpp"
Browses the service types being published on a domain.
void finished()
Emitted when the list of published service types has settled.
QStringList serviceTypes() const
All the service types currently being published.
ServiceTypeBrowser(const QString &domain=QString(), QObject *parent=nullptr)
Create a ServiceTypeBrowser for a domain.
Type type(const QSqlDatabase &db)
QDBusConnection connection() const const
QString service() const const
bool connect(const QString &service, const QString &path, const QString &interface, const QString &name, QObject *receiver, const char *slot)
QDBusConnection systemBus()
bool isValid() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
Q_D(Todo)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:17:48 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.