KDNSSD

avahi-remoteservice.cpp
1 /*
2  This file is part of the KDE project
3 
4  SPDX-FileCopyrightText: 2004, 2005 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-remoteservice_p.h"
11 #include <netinet/in.h>
12 #include <QEventLoop>
13 #include <QCoreApplication>
14 #include <QDebug>
15 #include "remoteservice.h"
16 #include "avahi_server_interface.h"
17 #include "avahi_serviceresolver_interface.h"
18 namespace KDNSSD
19 {
20 
21 RemoteService::RemoteService(const QString &name, const QString &type, const QString &domain)
22  : ServiceBase(new RemoteServicePrivate(this, name, type, domain))
23 {
24 }
25 
26 RemoteService::~RemoteService()
27 {
28 }
29 
31 {
32  K_D;
33  resolveAsync();
34  while (d->m_running && !d->m_resolved) {
36  }
37  return d->m_resolved;
38 }
39 
41 {
42  K_D;
43  if (d->m_running) {
44  return;
45  }
46  d->m_resolved = false;
47  registerTypes();
48 
49  // Do not race!
50  // https://github.com/lathiat/avahi/issues/9
51  // Avahi's DBus API is incredibly racey with signals getting fired
52  // immediately after a request was made even though we may not yet be
53  // listening. In lieu of a proper upstream fix for this we'll unfortunately
54  // have to resort to this hack:
55  // We register to all signals regardless of path and then filter them once
56  // we know what "our" path is. This is much more fragile than a proper
57  // QDBusInterface assisted signal connection but unfortunately the only way
58  // we can reliably prevent signals getting lost in the race.
59  // This uses a fancy trick whereby using QDBusMessage as last argument will
60  // give us the correct signal argument types as well as the underlying
61  // message so that we may check the message path.
63  .connect("org.freedesktop.Avahi",
64  "",
65  "org.freedesktop.Avahi.ServiceResolver",
66  "Found",
67  d,
68  SLOT(gotGlobalFound(int,int,QString,QString,QString,QString,
69  int,QString,ushort,QList<QByteArray>,
70  uint,QDBusMessage)));
72  .connect("org.freedesktop.Avahi",
73  "",
74  "org.freedesktop.Avahi.ServiceResolver",
75  "Failure",
76  d,
77  SLOT(gotGlobalError(QDBusMessage)));
78  d->m_dbusObjectPath.clear();
79 
80  //qDebug() << this << ":Starting resolve of : " << d->m_serviceName << " " << d->m_type << " " << d->m_domain << "\n";
81  org::freedesktop::Avahi::Server s(QStringLiteral("org.freedesktop.Avahi"), QStringLiteral("/"), QDBusConnection::systemBus());
82  //FIXME: don't use LOOKUP_NO_ADDRESS if NSS unavailable
83  QDBusReply<QDBusObjectPath> rep = s.ServiceResolverNew(-1, -1, d->m_serviceName, d->m_type,
84  domainToDNS(d->m_domain), -1, 8 /*AVAHI_LOOKUP_NO_ADDRESS*/);
85  if (!rep.isValid()) {
86  emit resolved(false);
87  return;
88  }
89 
90  d->m_dbusObjectPath = rep.value().path();
91 
92  // This is held because we need to explicitly Free it!
93  d->m_resolver = new org::freedesktop::Avahi::ServiceResolver(
94  s.service(),
95  d->m_dbusObjectPath,
96  s.connection());
97  d->m_running = true;
98 }
99 
101 {
102  K_D;
103  return d->m_resolved;
104 }
105 
106 void RemoteServicePrivate::gotError()
107 {
108  m_resolved = false;
109  stop();
110 
111  emit m_parent->resolved(false);
112 }
113 
114 void RemoteServicePrivate::gotGlobalFound(int interface,
115  int protocol,
116  const QString &name,
117  const QString &type,
118  const QString &domain,
119  const QString &host,
120  int aprotocol,
121  const QString &address,
122  ushort port,
123  const QList<QByteArray> &txt,
124  uint flags,
125  QDBusMessage msg)
126 {
127  if (!isOurMsg(msg)) {
128  return;
129  }
130  gotFound(interface, protocol, name, type, domain, host, aprotocol, address,
131  port, txt, flags);
132 }
133 
134 void RemoteServicePrivate::gotGlobalError(QDBusMessage msg)
135 {
136  if (!isOurMsg(msg)) {
137  return;
138  }
139  gotError();
140 }
141 
142 void RemoteServicePrivate::gotFound(int, int, const QString &name, const QString &, const QString &domain, const QString &host, int, const QString &, ushort port, const QList<QByteArray> &txt, uint)
143 {
144  m_serviceName = name;
145  m_hostName = host;
146  m_port = port;
147  m_domain = DNSToDomain(domain);
148  for (const QByteArray &x : txt) {
149  int pos = x.indexOf("=");
150  if (pos == -1) {
151  m_textData[x] = QByteArray();
152  } else {
153  m_textData[x.mid(0, pos)] = x.mid(pos + 1, x.size() - pos);
154  }
155  }
156  m_resolved = true;
157  emit m_parent->resolved(true);
158 }
159 
160 void RemoteServicePrivate::stop()
161 {
162  if (m_resolver) {
163  m_resolver->Free();
164  }
165  delete m_resolver;
166  m_resolver = nullptr;
167  m_running = false;
168 }
169 
170 void RemoteService::virtual_hook(int, void *)
171 {
172  // BASE::virtual_hook(int, void*);
173 }
174 
175 }
176 
177 #include "moc_remoteservice.cpp"
178 #include "moc_avahi-remoteservice_p.cpp"
bool resolve()
Resolves the host name and port of service synchronously.
QDBusConnection systemBus()
bool isValid() const const
void resolveAsync()
Resolves the host name and port of service asynchronously.
void processEvents(QEventLoop::ProcessEventsFlags flags)
QDBusReply::Type value() const const
Describes a service.
Definition: servicebase.h:39
unsigned short port() const
The port number of the service.
Definition: servicebase.cpp:52
QString type() const
The type of the service.
Definition: servicebase.cpp:37
QString domain() const
The domain that the service belongs to.
Definition: servicebase.cpp:42
bool isResolved() const
Whether the service has been successfully resolved.
RemoteService(const QString &name, const QString &type, const QString &domain)
Creates an unresolved RemoteService representing the service with the given name, type and domain...
bool connect(const QString &service, const QString &path, const QString &interface, const QString &name, QObject *receiver, const char *slot)
void resolved(bool successful)
Emitted when resolving is complete.
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Wed Sep 23 2020 22:40:34 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.