Paste P271

Masterwork From Distant Lands
ActivePublic

Authored by sitter on Oct 17 2018, 1:01 PM.
diff --git a/src/avahi-remoteservice.cpp b/src/avahi-remoteservice.cpp
index bcdacad..ef1b22c 100644
--- a/src/avahi-remoteservice.cpp
+++ b/src/avahi-remoteservice.cpp
@@ -1,6 +1,7 @@
/* This file is part of the KDE project
*
* Copyright (C) 2004, 2005 Jakub Stachowski <qbast@go2.pl>
+ * Copyright (C) 2018 Harald Sitter <sitter@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -56,22 +57,53 @@ void RemoteService::resolveAsync()
}
d->m_resolved = false;
registerTypes();
+
+ // Do not race!
+ // https://github.com/lathiat/avahi/issues/9
+ // Avahi's DBus API is incredibly racey with signals getting fired
+ // immediately after a request was made even though we may not yet be
+ // listening. In lieu of a proper upstream fix for this we'll unfortunately
+ // have to resort to this hack:
+ // We register to all signals regardless of path and then filter them once
+ // we know what "our" wath is. This is much more fragile than a proper
+ // QDBusInterface assisted signal connection but unfortunately the only way
+ // we can reliably prevent signals getting lost in the race.
+ // This uses a fancy trick whereby using QDBusMessage as last argument will
+ // give us the correct signal argument types as well as the underlying
+ // message so that we may check the message path.
+ QDBusConnection::systemBus()
+ .connect("org.freedesktop.Avahi",
+ "",
+ "org.freedesktop.Avahi.ServiceResolver",
+ "Found",
+ d,
+ SLOT(gotGlobalFound(int,int,QString,QString,QString,QString,
+ int,QString,ushort,QList<QByteArray>,
+ uint,QDBusMessage)));
+ QDBusConnection::systemBus()
+ .connect("org.freedesktop.Avahi",
+ "",
+ "org.freedesktop.Avahi.ServiceResolver",
+ "Failure",
+ d,
+ SLOT(gotGlobalError(QDBusMessage)));
+
+ d->m_resolverPath.clear();
+
//qDebug() << this << ":Starting resolve of : " << d->m_serviceName << " " << d->m_type << " " << d->m_domain << "\n";
org::freedesktop::Avahi::Server s(QStringLiteral("org.freedesktop.Avahi"), QStringLiteral("/"), QDBusConnection::systemBus());
//FIXME: don't use LOOKUP_NO_ADDRESS if NSS unavailable
QDBusReply<QDBusObjectPath> rep = s.ServiceResolverNew(-1, -1, d->m_serviceName, d->m_type,
domainToDNS(d->m_domain), -1, 8 /*AVAHI_LOOKUP_NO_ADDRESS*/);
+
if (!rep.isValid()) {
emit resolved(false);
return;
}
- org::freedesktop::Avahi::ServiceResolver *b = new org::freedesktop::Avahi::ServiceResolver("org.freedesktop.Avahi", rep.value().path(),
- QDBusConnection::systemBus());
- connect(b, SIGNAL(Found(int, int, const QString &, const QString &, const QString &, const QString &, int, const QString &, ushort,
- const QList<QByteArray> &, uint)), d, SLOT(gotFound(int, int, const QString &, const QString &, const QString &, const QString &,
- int, const QString &, ushort, const QList<QByteArray> &, uint)));
- connect(b, SIGNAL(Failure(QString)), d, SLOT(gotError()));
+ // We cannot race up until here since our eventloop will be blocked.
+ // At least until we return.
+ d->m_resolverPath = rep.value().path();
d->m_running = true;
}
@@ -89,6 +121,35 @@ void RemoteServicePrivate::gotError()
emit m_parent->resolved(false);
}
+void RemoteServicePrivate::gotGlobalFound(int interface,
+ int protocol,
+ const QString &name,
+ const QString &type,
+ const QString &domain,
+ const QString &host,
+ int aprotocol,
+ const QString &address,
+ ushort port,
+ const QList<QByteArray> &txt,
+ QDBusMessage msg)
+{
+ if (!isOurMsg(msg)) {
+ return;
+ }
+ qDebug() << msg;
+ gotFound(interface, protocol, name, type, domain, host, aprotocol, address,
+ port, txt, flags);
+}
+
+void RemoteServicePrivate::gotGlobalError(QDBusMessage msg)
+{
+ if (!isOurMsg(msg)) {
+ return;
+ }
+ qDebug() << msg;
+ gotError();
+}
+
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)
{
m_serviceName = name;
@@ -117,6 +178,16 @@ void RemoteServicePrivate::stop()
m_running = false;
}
+bool RemoteServicePrivate::isOurMsg(const QDBusMessage &msg) const
+{
+ if (m_resolverPath.isEmpty() || m_resolverPath != msg.path()) {
+#warning FIXME this needs to be dropped. due to the nature of the global listener we'll have lots of unexpected on async resolve calls
+ qWarning() << "UNEXPECTED MSG" << msg;
+ return false;
+ }
+ return true;
+}
+
void RemoteService::virtual_hook(int, void *)
{
// BASE::virtual_hook(int, void*);
sitter edited the content of this paste. (Show Details)Oct 17 2018, 1:01 PM
sitter changed the title of this paste from untitled to Masterwork From Distant Lands.