Hello community,
here is the log from the commit of package kdnssd-framework for
openSUSE:Factory checked in at 2018-12-19 13:40:41
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/kdnssd-framework (Old)
and /work/SRC/openSUSE:Factory/.kdnssd-framework.new.28833 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "kdnssd-framework"
Wed Dec 19 13:40:41 2018 rev:59 rq:658559 version:5.53.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/kdnssd-framework/kdnssd-framework.changes
2018-11-14 14:34:01.275289395 +0100
+++
/work/SRC/openSUSE:Factory/.kdnssd-framework.new.28833/kdnssd-framework.changes
2018-12-19 13:40:43.000015923 +0100
@@ -1,0 +2,13 @@
+Sun Dec 09 19:43:43 UTC 2018 - [email protected]
+
+- Update to 5.53.0
+ * New feature release
+ * For more details please see:
+ * https://www.kde.org/announcements/kde-frameworks-5.53.0.php
+- Changes since 5.52.0:
+ * actually install the version header
+ * do not leak resolver in remoteservice
+ * prevent avahi signal racing
+ * fix for macOS
+
+-------------------------------------------------------------------
Old:
----
kdnssd-5.52.0.tar.xz
New:
----
kdnssd-5.53.0.tar.xz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ kdnssd-framework.spec ++++++
--- /var/tmp/diff_new_pack.CM6ovZ/_old 2018-12-19 13:40:43.544015154 +0100
+++ /var/tmp/diff_new_pack.CM6ovZ/_new 2018-12-19 13:40:43.548015148 +0100
@@ -17,14 +17,14 @@
%define lname libKF5DNSSD5
-%define _tar_path 5.52
+%define _tar_path 5.53
# Full KF5 version (e.g. 5.33.0)
%{!?_kf5_version: %global _kf5_version %{version}}
# Last major and minor KF5 version (e.g. 5.33)
%{!?_kf5_bugfix_version: %define _kf5_bugfix_version %(echo %{_kf5_version} |
awk -F. '{print $1"."$2}')}
%bcond_without lang
Name: kdnssd-framework
-Version: 5.52.0
+Version: 5.53.0
Release: 0
Summary: Network service discovery using Zeroconf
License: LGPL-2.1-or-later
++++++ kdnssd-5.52.0.tar.xz -> kdnssd-5.53.0.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/kdnssd-5.52.0/CMakeLists.txt
new/kdnssd-5.53.0/CMakeLists.txt
--- old/kdnssd-5.52.0/CMakeLists.txt 2018-11-03 19:00:31.000000000 +0100
+++ new/kdnssd-5.53.0/CMakeLists.txt 2018-12-01 15:54:54.000000000 +0100
@@ -1,10 +1,10 @@
cmake_minimum_required(VERSION 3.0)
-set(KF5_VERSION "5.52.0") # handled by release scripts
+set(KF5_VERSION "5.53.0") # handled by release scripts
project(KDNSSD VERSION ${KF5_VERSION})
include(FeatureSummary)
-find_package(ECM 5.52.0 NO_MODULE)
+find_package(ECM 5.53.0 NO_MODULE)
set_package_properties(ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake
Modules." URL
"https://projects.kde.org/projects/kdesupport/extra-cmake-modules")
feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND
FATAL_ON_MISSING_REQUIRED_PACKAGES)
@@ -21,7 +21,7 @@
option(BUILD_QCH "Build API documentation in QCH format (for e.g. Qt
Assistant, Qt Creator & KDevelop)" OFF)
add_feature_info(QCH ${BUILD_QCH} "API documentation in QCH format (for e.g.
Qt Assistant, Qt Creator & KDevelop)")
-set(REQUIRED_QT_VERSION 5.8.0)
+set(REQUIRED_QT_VERSION 5.9.0)
find_package(Qt5 ${REQUIRED_QT_VERSION} CONFIG REQUIRED Network)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
@@ -33,9 +33,10 @@
include(CMakePackageConfigHelpers)
ecm_setup_version(PROJECT VARIABLE_PREFIX KDNSSD
- SOVERSION 5 VERSION_HEADER
"${CMAKE_CURRENT_BINARY_DIR}/kdnssd_version.h"
- PACKAGE_VERSION_FILE
"${CMAKE_CURRENT_BINARY_DIR}/KF5DNSSDConfigVersion.cmake"
- SOVERSION 5)
+ VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/kdnssd_version.h"
+ PACKAGE_VERSION_FILE
"${CMAKE_CURRENT_BINARY_DIR}/KF5DNSSDConfigVersion.cmake"
+ SOVERSION 5)
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/kdnssd_version.h DESTINATION
${KDE_INSTALL_INCLUDEDIR_KF5} COMPONENT Devel)
configure_file(config-kdnssd.h.cmake
${CMAKE_CURRENT_BINARY_DIR}/config-kdnssd.h )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/kdnssd-5.52.0/po/zh_CN/kdnssd5_qt.po
new/kdnssd-5.53.0/po/zh_CN/kdnssd5_qt.po
--- old/kdnssd-5.52.0/po/zh_CN/kdnssd5_qt.po 2018-11-03 19:00:31.000000000
+0100
+++ new/kdnssd-5.53.0/po/zh_CN/kdnssd5_qt.po 2018-12-01 15:54:54.000000000
+0100
@@ -13,7 +13,7 @@
msgid ""
msgstr ""
"Project-Id-Version: kdeorg\n"
-"PO-Revision-Date: 2018-10-09 18:39\n"
+"PO-Revision-Date: 2018-11-12 09:13\n"
"Last-Translator: guoyunhe <[email protected]>\n"
"Language-Team: Chinese Simplified\n"
"Language: zh_CN\n"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/kdnssd-5.52.0/src/CMakeLists.txt
new/kdnssd-5.53.0/src/CMakeLists.txt
--- old/kdnssd-5.52.0/src/CMakeLists.txt 2018-11-03 19:00:31.000000000
+0100
+++ new/kdnssd-5.53.0/src/CMakeLists.txt 2018-12-01 15:54:54.000000000
+0100
@@ -18,6 +18,7 @@
avahi_server_interface.cpp
avahi_serviceresolver_interface.cpp
avahi_entrygroup_interface.cpp
+ avahi_listener.cpp
)
qt5_add_dbus_interface (kdnssd_LIB_SRCS
org.freedesktop.Avahi.DomainBrowser.xml avahi_domainbrowser_interface )
qt5_add_dbus_interface (kdnssd_LIB_SRCS
org.freedesktop.Avahi.ServiceBrowser.xml avahi_servicebrowser_interface )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/kdnssd-5.52.0/src/avahi-domainbrowser.cpp
new/kdnssd-5.53.0/src/avahi-domainbrowser.cpp
--- old/kdnssd-5.52.0/src/avahi-domainbrowser.cpp 2018-11-03
19:00:31.000000000 +0100
+++ new/kdnssd-5.53.0/src/avahi-domainbrowser.cpp 2018-12-01
15:54:54.000000000 +0100
@@ -1,6 +1,7 @@
/* This file is part of the KDE project
*
* Copyright (C) 2004 Jakub Stachowski <[email protected]>
+ * Copyright (C) 2018 Harald Sitter <[email protected]>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -45,18 +46,58 @@
return;
}
d->m_started = true;
+
+ // 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" path 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.DomainBrowser",
+ "ItemNew",
+ d,
+
SLOT(gotGlobalItemNew(int,int,QString,uint,QDBusMessage)));
+ QDBusConnection::systemBus()
+ .connect("org.freedesktop.Avahi",
+ "",
+ "org.freedesktop.Avahi.DomainBrowser",
+ "ItemRemove",
+ d,
+
SLOT(gotGlobalItemRemove(int,int,QString,uint,QDBusMessage)));
+ QDBusConnection::systemBus()
+ .connect("org.freedesktop.Avahi",
+ "",
+ "org.freedesktop.Avahi.DomainBrowser",
+ "AllForNow",
+ d,
+ SLOT(gotGlobalAllForNow(QDBusMessage)));
+ d->m_dbusObjectPath.clear();
+
org::freedesktop::Avahi::Server s(QStringLiteral("org.freedesktop.Avahi"),
QStringLiteral("/"), QDBusConnection::systemBus());
QDBusReply<QDBusObjectPath> rep = s.DomainBrowserNew(-1, -1, QString(),
(d->m_type == Browsing) ?
AVAHI_DOMAIN_BROWSER_BROWSE :
AVAHI_DOMAIN_BROWSER_REGISTER, 0);
-
if (!rep.isValid()) {
return;
}
- org::freedesktop::Avahi::DomainBrowser *b = new
org::freedesktop::Avahi::DomainBrowser(QStringLiteral("org.freedesktop.Avahi"),
rep.value().path(),
- QDBusConnection::systemBus());
- connect(b, SIGNAL(ItemNew(int,int,QString,uint)), d,
SLOT(gotNewDomain(int,int,QString,uint)));
- connect(b, SIGNAL(ItemRemove(int,int,QString,uint)), d,
SLOT(gotRemoveDomain(int,int,QString,uint)));
- d->m_browser = b;
+
+ d->m_dbusObjectPath = rep.value().path();
+
+ // This is held because we need to explicitly Free it!
+ d->m_browser = new org::freedesktop::Avahi::DomainBrowser(
+ s.service(),
+ d->m_dbusObjectPath,
+ s.connection());
+
if (d->m_type == Browsing) {
QString domains_evar =
QString::fromLocal8Bit(qgetenv("AVAHI_BROWSE_DOMAINS"));
if (!domains_evar.isEmpty()) {
@@ -72,9 +113,38 @@
while (!domains_cfg.atEnd()) {
d->gotNewDomain(-1, -1,
QString::fromUtf8(domains_cfg.readLine().data()).trimmed(), 0);
}
+ }
+}
+void DomainBrowserPrivate::gotGlobalItemNew(int interface,
+ int protocol,
+ const QString &domain,
+ uint flags,
+ QDBusMessage msg)
+{
+ if (!isOurMsg(msg)) {
+ return;
}
+ gotNewDomain(interface, protocol, domain, flags);
+}
+void DomainBrowserPrivate::gotGlobalItemRemove(int interface,
+ int protocol,
+ const QString &domain,
+ uint flags,
+ QDBusMessage msg)
+{
+ if (!isOurMsg(msg)) {
+ return;
+ }
+ gotRemoveDomain(interface, protocol, domain, flags);
+}
+
+void DomainBrowserPrivate::gotGlobalAllForNow(QDBusMessage msg)
+{
+ if (!isOurMsg(msg)) {
+ return;
+ }
}
void DomainBrowserPrivate::gotNewDomain(int, int, const QString &domain, uint)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/kdnssd-5.52.0/src/avahi-domainbrowser_p.h
new/kdnssd-5.53.0/src/avahi-domainbrowser_p.h
--- old/kdnssd-5.52.0/src/avahi-domainbrowser_p.h 2018-11-03
19:00:31.000000000 +0100
+++ new/kdnssd-5.53.0/src/avahi-domainbrowser_p.h 2018-12-01
15:54:54.000000000 +0100
@@ -23,12 +23,13 @@
#include <QSet>
#include "domainbrowser.h"
+#include "avahi_listener_p.h"
#include "avahi_domainbrowser_interface.h"
namespace KDNSSD
{
-class DomainBrowserPrivate : public QObject
+class DomainBrowserPrivate : public QObject, public AvahiListener
{
Q_OBJECT
public:
@@ -45,10 +46,24 @@
DomainBrowser *m_parent = nullptr;
bool m_started = false;
QSet<QString> m_domains;
+
public Q_SLOTS:
+ // NB: The global slots are runtime connected! If their signature changes
+ // make sure the SLOT() signature gets updated!
+ void gotGlobalItemNew(int interface,
+ int protocol,
+ const QString &domain,
+ uint flags,
+ QDBusMessage msg);
+ void gotGlobalItemRemove(int interface,
+ int protocol,
+ const QString &domain,
+ uint flags,
+ QDBusMessage msg);
+ void gotGlobalAllForNow(QDBusMessage msg);
+
void gotNewDomain(int, int, const QString &, uint);
void gotRemoveDomain(int, int, const QString &, uint);
-
};
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/kdnssd-5.52.0/src/avahi-publicservice.cpp
new/kdnssd-5.53.0/src/avahi-publicservice.cpp
--- old/kdnssd-5.52.0/src/avahi-publicservice.cpp 2018-11-03
19:00:31.000000000 +0100
+++ new/kdnssd-5.53.0/src/avahi-publicservice.cpp 2018-12-01
15:54:54.000000000 +0100
@@ -62,6 +62,16 @@
}
}
+void PublicServicePrivate::gotGlobalStateChanged(int state,
+ const QString &error,
+ QDBusMessage msg)
+{
+ if (!isOurMsg(msg)) {
+ return;
+ }
+ groupStateChanged(state, error);
+}
+
void PublicService::setServiceName(const QString &serviceName)
{
K_D;
@@ -157,12 +167,38 @@
{
registerTypes();
if (!m_group) {
+ // 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" path 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.EntryGroup",
+ "StateChanged",
+ this,
+
SLOT(gotGlobalStateChanged(int,QString,QDBusMessage)));
+ m_dbusObjectPath.clear();
+
QDBusReply<QDBusObjectPath> rep = m_server->EntryGroupNew();
if (!rep.isValid()) {
return false;
}
- m_group = new
org::freedesktop::Avahi::EntryGroup("org.freedesktop.Avahi",
rep.value().path(), QDBusConnection::systemBus());
- connect(m_group, SIGNAL(StateChanged(int,QString)), this,
SLOT(groupStateChanged(int,QString)));
+
+ m_dbusObjectPath = rep.value().path();
+
+ m_group = new
org::freedesktop::Avahi::EntryGroup("org.freedesktop.Avahi",
+ m_dbusObjectPath,
+
QDBusConnection::systemBus());
}
if (m_serviceName.isNull()) {
QDBusReply<QString> rep = m_server->GetHostName();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/kdnssd-5.52.0/src/avahi-publicservice_p.h
new/kdnssd-5.53.0/src/avahi-publicservice_p.h
--- old/kdnssd-5.52.0/src/avahi-publicservice_p.h 2018-11-03
19:00:31.000000000 +0100
+++ new/kdnssd-5.53.0/src/avahi-publicservice_p.h 2018-12-01
15:54:54.000000000 +0100
@@ -25,6 +25,7 @@
#include "servicebase_p.h"
#include <avahi-common/defs.h>
#include "publicservice.h"
+#include "avahi_listener_p.h"
#include "avahi_server_interface.h"
#include "avahi_entrygroup_interface.h"
@@ -33,7 +34,7 @@
namespace KDNSSD
{
-class PublicServicePrivate : public QObject, public ServiceBasePrivate
+class PublicServicePrivate : public QObject, public ServiceBasePrivate, public
AvahiListener
{
Q_OBJECT
public:
@@ -69,6 +70,10 @@
void tryApply();
public Q_SLOTS:
+ // NB: The global slots are runtime connected! If their signature changes
+ // make sure the SLOT() signature gets updated!
+ void gotGlobalStateChanged(int state, const QString &error, QDBusMessage
msg);
+
void serverStateChanged(int, const QString &);
void groupStateChanged(int, const QString &);
};
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/kdnssd-5.52.0/src/avahi-remoteservice.cpp
new/kdnssd-5.53.0/src/avahi-remoteservice.cpp
--- old/kdnssd-5.52.0/src/avahi-remoteservice.cpp 2018-11-03
19:00:31.000000000 +0100
+++ new/kdnssd-5.53.0/src/avahi-remoteservice.cpp 2018-12-01
15:54:54.000000000 +0100
@@ -1,6 +1,7 @@
/* This file is part of the KDE project
*
* Copyright (C) 2004, 2005 Jakub Stachowski <[email protected]>
+ * Copyright (C) 2018 Harald Sitter <[email protected]>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -56,6 +57,38 @@
}
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" path 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_dbusObjectPath.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
@@ -66,12 +99,13 @@
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()));
+ d->m_dbusObjectPath = rep.value().path();
+
+ // This is held because we need to explicitly Free it!
+ d->m_resolver = new org::freedesktop::Avahi::ServiceResolver(
+ s.service(),
+ d->m_dbusObjectPath,
+ s.connection());
d->m_running = true;
}
@@ -89,6 +123,34 @@
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,
+ uint flags,
+ QDBusMessage msg)
+{
+ if (!isOurMsg(msg)) {
+ return;
+ }
+ gotFound(interface, protocol, name, type, domain, host, aprotocol, address,
+ port, txt, flags);
+}
+
+void RemoteServicePrivate::gotGlobalError(QDBusMessage msg)
+{
+ if (!isOurMsg(msg)) {
+ return;
+ }
+ 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;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/kdnssd-5.52.0/src/avahi-remoteservice_p.h
new/kdnssd-5.53.0/src/avahi-remoteservice_p.h
--- old/kdnssd-5.52.0/src/avahi-remoteservice_p.h 2018-11-03
19:00:31.000000000 +0100
+++ new/kdnssd-5.53.0/src/avahi-remoteservice_p.h 2018-12-01
15:54:54.000000000 +0100
@@ -26,6 +26,7 @@
#include <QMap>
#include "servicebase_p.h"
#include "remoteservice.h"
+#include "avahi_listener_p.h"
#include "avahi_serviceresolver_interface.h"
#define K_D RemoteServicePrivate* d=static_cast<RemoteServicePrivate*>(this->d)
@@ -33,7 +34,7 @@
namespace KDNSSD
{
-class RemoteServicePrivate : public QObject, public ServiceBasePrivate
+class RemoteServicePrivate : public QObject, public ServiceBasePrivate, public
AvahiListener
{
Q_OBJECT
public:
@@ -53,7 +54,35 @@
void stop();
private Q_SLOTS:
- void gotFound(int, int, const QString &name, const QString &type, const
QString &domain, const QString &host, int aprotocol, const QString &address,
ushort port, const QList<QByteArray> &txt, uint flags);
+ // NB: The global slots are runtime connected! If their signature changes
+ // make sure the SLOT() signature gets updated!
+ void 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,
+ uint flags,
+ QDBusMessage msg);
+ void gotGlobalError(QDBusMessage msg);
+
+ void gotFound(
+ 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,
+ uint flags);
void gotError();
};
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/kdnssd-5.52.0/src/avahi-servicebrowser.cpp
new/kdnssd-5.53.0/src/avahi-servicebrowser.cpp
--- old/kdnssd-5.52.0/src/avahi-servicebrowser.cpp 2018-11-03
19:00:31.000000000 +0100
+++ new/kdnssd-5.53.0/src/avahi-servicebrowser.cpp 2018-12-01
15:54:54.000000000 +0100
@@ -1,6 +1,7 @@
/* This file is part of the KDE project
*
* Copyright (C) 2004 Jakub Stachowski <[email protected]>
+ * Copyright (C) 2018 Harald Sitter <[email protected]>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -25,6 +26,7 @@
#include "avahi_server_interface.h"
#include <QHash>
#include <QHostAddress>
+
namespace KDNSSD
{
@@ -59,28 +61,67 @@
if (d->m_running) {
return;
}
+
+ // 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" path 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.ServiceBrowser",
+ "ItemNew",
+ d,
+
SLOT(gotGlobalItemNew(int,int,QString,QString,QString,uint,QDBusMessage)));
+ QDBusConnection::systemBus()
+ .connect("org.freedesktop.Avahi",
+ "",
+ "org.freedesktop.Avahi.ServiceBrowser",
+ "ItemRemove",
+ d,
+
SLOT(gotGlobalItemRemove(int,int,QString,QString,QString,uint,QDBusMessage)));
+ QDBusConnection::systemBus()
+ .connect("org.freedesktop.Avahi",
+ "",
+ "org.freedesktop.Avahi.ServiceBrowser",
+ "AllForNow",
+ d,
+ SLOT(gotGlobalAllForNow(QDBusMessage)));
+ d->m_dbusObjectPath.clear();
+
org::freedesktop::Avahi::Server s(QStringLiteral("org.freedesktop.Avahi"),
QStringLiteral("/"), QDBusConnection::systemBus());
+
QString fullType = d->m_type;
if (!d->m_subtype.isEmpty()) {
fullType = d->m_subtype + QStringLiteral("._sub.") + d->m_type;
}
QDBusReply<QDBusObjectPath> rep = s.ServiceBrowserNew(-1, -1, fullType,
domainToDNS(d->m_domain), 0);
-
if (!rep.isValid()) {
emit finished();
return;
}
+
+ d->m_dbusObjectPath = rep.value().path();
d->m_running = true;
d->m_browserFinished = true;
- org::freedesktop::Avahi::ServiceBrowser *b = new
org::freedesktop::Avahi::ServiceBrowser(QStringLiteral("org.freedesktop.Avahi"),
rep.value().path(),
- QDBusConnection::systemBus());
- connect(b, SIGNAL(ItemNew(int,int,QString,QString,QString,uint)), d,
- SLOT(gotNewService(int,int,QString,QString,QString,uint)));
- connect(b, SIGNAL(ItemRemove(int,int,QString,QString,QString,uint)), d,
- SLOT(gotRemoveService(int,int,QString,QString,QString,uint)));
- connect(b, SIGNAL(AllForNow()), d, SLOT(browserFinished()));
- d->m_browser = b;
- connect(&d->m_timer, SIGNAL(timeout()), d, SLOT(browserFinished()));
+
+ // This is held because we need to explicitly Free it!
+ d->m_browser = new org::freedesktop::Avahi::ServiceBrowser(
+ s.service(),
+ d->m_dbusObjectPath,
+ s.connection());
+
+ connect(&d->m_timer, &QTimer::timeout,
+ d, &ServiceBrowserPrivate::browserFinished);
d->m_timer.start(domainIsLocal(d->m_domain) ? TIMEOUT_LAST_SERVICE :
TIMEOUT_START_WAN);
}
@@ -104,6 +145,42 @@
}
}
+void ServiceBrowserPrivate::gotGlobalItemNew(int interface,
+ int protocol,
+ const QString &name,
+ const QString &type,
+ const QString &domain,
+ uint flags,
+ QDBusMessage msg)
+{
+ if (!isOurMsg(msg)) {
+ return;
+ }
+ gotNewService(interface, protocol, name, type, domain, flags);
+}
+
+void ServiceBrowserPrivate::gotGlobalItemRemove(int interface,
+ int protocol,
+ const QString &name,
+ const QString &type,
+ const QString &domain,
+ uint flags,
+ QDBusMessage msg)
+{
+ if (!isOurMsg(msg)) {
+ return;
+ }
+ gotRemoveService(interface, protocol, name, type, domain, flags);
+}
+
+void ServiceBrowserPrivate::gotGlobalAllForNow(QDBusMessage msg)
+{
+ if (!isOurMsg(msg)) {
+ return;
+ }
+ browserFinished();
+}
+
RemoteService::Ptr ServiceBrowserPrivate::find(RemoteService::Ptr s, const
QList<RemoteService::Ptr> &where) const
{
Q_FOREACH (const RemoteService::Ptr &i, where) if (*s == *i) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/kdnssd-5.52.0/src/avahi-servicebrowser_p.h
new/kdnssd-5.53.0/src/avahi-servicebrowser_p.h
--- old/kdnssd-5.52.0/src/avahi-servicebrowser_p.h 2018-11-03
19:00:31.000000000 +0100
+++ new/kdnssd-5.53.0/src/avahi-servicebrowser_p.h 2018-12-01
15:54:54.000000000 +0100
@@ -25,14 +25,16 @@
#include <QList>
#include <QTimer>
#include "servicebrowser.h"
+#include "avahi_listener_p.h"
#include "avahi_servicebrowser_interface.h"
namespace KDNSSD
{
-class ServiceBrowserPrivate : public QObject
+class ServiceBrowserPrivate : public QObject, public AvahiListener
{
Q_OBJECT
+ friend class ServiceBrowser; // So the public class may functor connect.
public:
ServiceBrowserPrivate(ServiceBrowser *parent) : QObject(),
m_running(false), m_browser(nullptr), m_parent(parent)
{}
@@ -62,6 +64,25 @@
void browserFinished();
void queryFinished();
void serviceResolved(bool success);
+
+ // NB: The global slots are runtime connected! If their signature changes
+ // make sure the SLOT() signature gets updated!
+ void gotGlobalItemNew(int interface,
+ int protocol,
+ const QString &name,
+ const QString &type,
+ const QString &domain,
+ uint flags,
+ QDBusMessage msg);
+ void gotGlobalItemRemove(int interface,
+ int protocol,
+ const QString &name,
+ const QString &type,
+ const QString &domain,
+ uint flags,
+ QDBusMessage msg);
+ void gotGlobalAllForNow(QDBusMessage msg);
+
void gotNewService(int, int, const QString &, const QString &, const
QString &, uint);
void gotRemoveService(int, int, const QString &, const QString &, const
QString &, uint);
};
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/kdnssd-5.52.0/src/avahi-servicetypebrowser.cpp
new/kdnssd-5.53.0/src/avahi-servicetypebrowser.cpp
--- old/kdnssd-5.52.0/src/avahi-servicetypebrowser.cpp 2018-11-03
19:00:31.000000000 +0100
+++ new/kdnssd-5.53.0/src/avahi-servicetypebrowser.cpp 2018-12-01
15:54:54.000000000 +0100
@@ -1,6 +1,7 @@
/* This file is part of the KDE project
*
* Copyright (C) 2004,2007 Jakub Stachowski <[email protected]>
+ * Copyright (C) 2018 Harald Sitter <[email protected]>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -45,19 +46,59 @@
return;
}
d->m_started = true;
+
+ // 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" path 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.ServiceTypeBrowser",
+ "ItemNew",
+ d,
+
SLOT(gotGlobalItemNew(int,int,QString,QString,uint,QDBusMessage)));
+ QDBusConnection::systemBus()
+ .connect("org.freedesktop.Avahi",
+ "",
+ "org.freedesktop.Avahi.ServiceTypeBrowser",
+ "ItemRemove",
+ d,
+
SLOT(gotGlobalItemRemove(int,int,QString,QString,uint,QDBusMessage)));
+ QDBusConnection::systemBus()
+ .connect("org.freedesktop.Avahi",
+ "",
+ "org.freedesktop.Avahi.ServiceTypeBrowser",
+ "AllForNow",
+ d,
+ SLOT(gotGlobalAllForNow(QDBusMessage)));
+ d->m_dbusObjectPath.clear();
+
org::freedesktop::Avahi::Server s(QStringLiteral("org.freedesktop.Avahi"),
QStringLiteral("/"), QDBusConnection::systemBus());
- QDBusReply<QDBusObjectPath> rep = s.ServiceTypeBrowserNew(-1, -1,
d->m_domain, 0);
+ QDBusReply<QDBusObjectPath> rep = s.ServiceTypeBrowserNew(-1, -1,
d->m_domain, 0);
if (!rep.isValid()) {
return;
}
- org::freedesktop::Avahi::ServiceTypeBrowser *b = new
org::freedesktop::Avahi::ServiceTypeBrowser(QStringLiteral("org.freedesktop.Avahi"),
rep.value().path(),
- QDBusConnection::systemBus());
- connect(b, SIGNAL(ItemNew(int,int,QString,QString,uint)), d,
SLOT(gotNewServiceType(int,int,QString,QString,uint)));
- connect(b, SIGNAL(ItemRemove(int,int,QString,QString,uint)), d,
SLOT(gotRemoveServiceType(int,int,QString,QString,uint)));
- connect(b, SIGNAL(AllForNow()), d, SLOT(finished()));
+
+ d->m_dbusObjectPath = rep.value().path();
+
+ // This is held because we need to explicitly Free it!
+ d->m_browser = new org::freedesktop::Avahi::ServiceTypeBrowser(
+ s.service(),
+ d->m_dbusObjectPath,
+ s.connection());
+
connect(&d->m_timer, SIGNAL(timeout()), d, SLOT(finished()));
- d->m_browser = b;
d->m_timer.start(domainIsLocal(d->m_domain) ? TIMEOUT_LAST_SERVICE :
TIMEOUT_START_WAN);
}
@@ -67,6 +108,40 @@
emit m_parent->finished();
}
+void ServiceTypeBrowserPrivate::gotGlobalItemNew(int interface,
+ int protocol,
+ const QString &type,
+ const QString &domain,
+ uint flags,
+ QDBusMessage msg)
+{
+ if (!isOurMsg(msg)) {
+ return;
+ }
+ gotNewServiceType(interface, protocol, type, domain, flags);
+}
+
+void ServiceTypeBrowserPrivate::gotGlobalItemRemove(int interface,
+ int protocol,
+ const QString &type,
+ const QString &domain,
+ uint flags,
+ QDBusMessage msg)
+{
+ if (!isOurMsg(msg)) {
+ return;
+ }
+ gotRemoveServiceType(interface, protocol, type, domain, flags);
+}
+
+void ServiceTypeBrowserPrivate::gotGlobalAllForNow(QDBusMessage msg)
+{
+ if (!isOurMsg(msg)) {
+ return;
+ }
+ finished();
+}
+
void ServiceTypeBrowserPrivate::gotNewServiceType(int, int, const QString
&type, const QString &, uint)
{
m_timer.start(TIMEOUT_LAST_SERVICE);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/kdnssd-5.52.0/src/avahi-servicetypebrowser_p.h
new/kdnssd-5.53.0/src/avahi-servicetypebrowser_p.h
--- old/kdnssd-5.52.0/src/avahi-servicetypebrowser_p.h 2018-11-03
19:00:31.000000000 +0100
+++ new/kdnssd-5.53.0/src/avahi-servicetypebrowser_p.h 2018-12-01
15:54:54.000000000 +0100
@@ -24,12 +24,13 @@
#include <QStringList>
#include <QTimer>
#include "servicetypebrowser.h"
+#include "avahi_listener_p.h"
#include "avahi_servicetypebrowser_interface.h"
namespace KDNSSD
{
-class ServiceTypeBrowserPrivate : public QObject
+class ServiceTypeBrowserPrivate : public QObject, public AvahiListener
{
Q_OBJECT
public:
@@ -47,11 +48,28 @@
QStringList m_servicetypes;
QString m_domain;
QTimer m_timer;
+
private Q_SLOTS:
+ // NB: The global slots are runtime connected! If their signature changes
+ // make sure the SLOT() signature gets updated!
+ void gotGlobalItemNew(int interface,
+ int protocol,
+ const QString &type,
+ const QString &domain,
+ uint flags,
+ QDBusMessage msg);
+ void gotGlobalItemRemove(int interface,
+ int protocol,
+ const QString &type,
+ const QString &domain,
+ uint flags,
+ QDBusMessage msg);
+ void gotGlobalAllForNow(QDBusMessage msg);
+
+
void gotNewServiceType(int, int, const QString &, const QString &, uint);
void gotRemoveServiceType(int, int, const QString &, const QString &,
uint);
void finished();
-
};
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/kdnssd-5.52.0/src/avahi_listener.cpp
new/kdnssd-5.53.0/src/avahi_listener.cpp
--- old/kdnssd-5.52.0/src/avahi_listener.cpp 1970-01-01 01:00:00.000000000
+0100
+++ new/kdnssd-5.53.0/src/avahi_listener.cpp 2018-12-01 15:54:54.000000000
+0100
@@ -0,0 +1,35 @@
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2018 Harald Sitter <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "avahi_listener_p.h"
+
+namespace KDNSSD {
+
+AvahiListener::AvahiListener()
+{
+}
+
+AvahiListener::~AvahiListener()
+{
+}
+
+
+
+} // namespace KDNSSD
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/kdnssd-5.52.0/src/avahi_listener_p.h
new/kdnssd-5.53.0/src/avahi_listener_p.h
--- old/kdnssd-5.52.0/src/avahi_listener_p.h 1970-01-01 01:00:00.000000000
+0100
+++ new/kdnssd-5.53.0/src/avahi_listener_p.h 2018-12-01 15:54:54.000000000
+0100
@@ -0,0 +1,54 @@
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2018 Harald Sitter <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef AVAHILISTENER_H
+#define AVAHILISTENER_H
+
+#include <QDBusMessage>
+#include <QString>
+
+namespace KDNSSD {
+
+// Assists with listening to Avahi for all signals and then checking if the
+// a given dbus message is meant for us or not.
+// Subclass and set the object path to object path you should be listening to.
+// Messages may then be run through isOurMsg to determine if they target the
+// object at hand.
+class AvahiListener
+{
+public:
+ explicit AvahiListener();
+ virtual ~AvahiListener();
+
+ // This method gets called a lot but doesn't do much. Suggest inlining.
+ inline bool isOurMsg(const QDBusMessage &msg) const
+ {
+ if (m_dbusObjectPath.isEmpty() || m_dbusObjectPath != msg.path()) {
+ return false;
+ }
+ return true;
+ }
+
+ QString m_dbusObjectPath; // public so !Private objects can access it
+};
+
+} // namespace KDNSSD
+
+#endif // AVAHILISTENER_H
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/kdnssd-5.52.0/src/mdnsd-publicservice.cpp
new/kdnssd-5.53.0/src/mdnsd-publicservice.cpp
--- old/kdnssd-5.52.0/src/mdnsd-publicservice.cpp 2018-11-03
19:00:31.000000000 +0100
+++ new/kdnssd-5.53.0/src/mdnsd-publicservice.cpp 2018-12-01
15:54:54.000000000 +0100
@@ -160,7 +160,7 @@
TXTRecordCreate(&txt, 0, 0);
QMap<QString, QByteArray>::ConstIterator itEnd = d->m_textData.cend();
for (QMap<QString, QByteArray>::ConstIterator it = d->m_textData.cbegin();
it != itEnd; ++it) {
- if (TXTRecordSetValue(&txt, it.key().toUtf8(), it.value().length(),
it.value()) != kDNSServiceErr_NoError) {
+ if (TXTRecordSetValue(&txt, it.key().toUtf8().constData(),
it.value().length(), it.value().constData()) != kDNSServiceErr_NoError) {
TXTRecordDeallocate(&txt);
emit published(false);
return;
@@ -171,7 +171,7 @@
Q_FOREACH (const QString &subtype, d->m_subtypes) {
fullType += ',' + subtype;
}
- if (DNSServiceRegister(&ref, 0, 0, d->m_serviceName.toUtf8(),
fullType.toLatin1().constData(), domainToDNS(d->m_domain), NULL,
+ if (DNSServiceRegister(&ref, 0, 0, d->m_serviceName.toUtf8().constData(),
fullType.toLatin1().constData(), domainToDNS(d->m_domain).constData(), NULL,
htons(d->m_port), TXTRecordGetLength(&txt),
TXTRecordGetBytesPtr(&txt), publish_callback,
reinterpret_cast<void *>(d)) ==
kDNSServiceErr_NoError) {
d->setRef(ref);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/kdnssd-5.52.0/src/mdnsd-remoteservice.cpp
new/kdnssd-5.53.0/src/mdnsd-remoteservice.cpp
--- old/kdnssd-5.52.0/src/mdnsd-remoteservice.cpp 2018-11-03
19:00:31.000000000 +0100
+++ new/kdnssd-5.53.0/src/mdnsd-remoteservice.cpp 2018-12-01
15:54:54.000000000 +0100
@@ -82,8 +82,8 @@
d->m_resolved = false;
//qDebug() << this << ":Starting resolve of : " << d->m_serviceName << " "
<< d->m_type << " " << d->m_domain << "\n";
DNSServiceRef ref;
- if (DNSServiceResolve(&ref, 0, 0, d->m_serviceName.toUtf8(),
d->m_type.toLatin1().constData(),
- domainToDNS(d->m_domain),
(DNSServiceResolveReply)resolve_callback, reinterpret_cast<void *>(d))
+ if (DNSServiceResolve(&ref, 0, 0, d->m_serviceName.toUtf8().constData(),
d->m_type.toLatin1().constData(),
+ domainToDNS(d->m_domain).constData(),
(DNSServiceResolveReply)resolve_callback, reinterpret_cast<void *>(d))
== kDNSServiceErr_NoError) {
d->setRef(ref);
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/kdnssd-5.52.0/src/mdnsd-servicebrowser.cpp
new/kdnssd-5.53.0/src/mdnsd-servicebrowser.cpp
--- old/kdnssd-5.52.0/src/mdnsd-servicebrowser.cpp 2018-11-03
19:00:31.000000000 +0100
+++ new/kdnssd-5.53.0/src/mdnsd-servicebrowser.cpp 2018-12-01
15:54:54.000000000 +0100
@@ -100,7 +100,7 @@
fullType = d->m_subtype + "._sub." + d->m_type;
}
if (DNSServiceBrowse(&ref, 0, 0, fullType.toLatin1().constData(),
- domainToDNS(d->m_domain), query_callback,
reinterpret_cast<void *>(d))
+ domainToDNS(d->m_domain).constData(), query_callback,
reinterpret_cast<void *>(d))
== kDNSServiceErr_NoError) {
d->setRef(ref);
}