From e7f7deadc389558ea4be1faf15dc1e4f09ccb358 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Thu, 11 Apr 2019 23:50:55 +0200 Subject: [PATCH] Workaround zeroconf breaking because of broken multicast hardware --- .../hardware/network/avahi/qtavahiservice.cpp | 45 ++++++++++++++++--- .../hardware/network/avahi/qtavahiservice.h | 8 ++++ 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/libnymea-core/hardware/network/avahi/qtavahiservice.cpp b/libnymea-core/hardware/network/avahi/qtavahiservice.cpp index 5d74cc0f..022193e4 100644 --- a/libnymea-core/hardware/network/avahi/qtavahiservice.cpp +++ b/libnymea-core/hardware/network/avahi/qtavahiservice.cpp @@ -53,6 +53,7 @@ #include "loggingcategories.h" #include +#include namespace nymeaserver { @@ -66,6 +67,14 @@ QtAvahiService::QtAvahiService(QObject *parent) : d_ptr->client = new QtAvahiClient(this); d_ptr->client->start(); + + m_reregisterTimer.setInterval(60000); + m_reregisterTimer.setSingleShot(true); + connect(&m_reregisterTimer, &QTimer::timeout, this, [this](){ + qCDebug(dcAvahi()) << "Re-registering services."; + resetService(); + registerService(m_name, m_hostAddress, m_port, m_serviceType, m_txtRecords); + }); } /*! Destructs this \l{QtAvahiService}. */ @@ -124,6 +133,14 @@ bool QtAvahiService::registerService(const QString &name, const QHostAddress &ho return false; } + // Cache all values locally at first + m_name = name; + m_hostAddress = hostAddress; + m_port = port; + m_serviceType = serviceType; + m_txtRecords = txtRecords; + + // Now set up avahi d_ptr->name = name; d_ptr->hostAddress = hostAddress; d_ptr->port = port; @@ -190,6 +207,10 @@ bool QtAvahiService::registerService(const QString &name, const QHostAddress &ho return false; } + // Reregister every minute in order to work around low quality network hardware which + // doesn't properly keep multicast sessions alive. + // https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=736641 + m_reregisterTimer.start(); return true; } @@ -204,6 +225,7 @@ void QtAvahiService::resetService() d_ptr->serviceList = nullptr; } avahi_entry_group_reset(d_ptr->group); + m_reregisterTimer.stop(); } /*! Update the TXT record of this service. Returns true of the record could be updated. */ @@ -212,11 +234,26 @@ bool QtAvahiService::updateTxtRecord(const QHash &txtRecords) if (!d_ptr->group) return false; + m_txtRecords = txtRecords; + // Add the service + AvahiIfIndex ifIndex = AVAHI_IF_UNSPEC; + if (d_ptr->hostAddress != QHostAddress("0.0.0.0")) { + foreach (const QNetworkInterface &interface, QNetworkInterface::allInterfaces()) { + foreach (const QNetworkAddressEntry &addressEntry, interface.addressEntries()) { + QPair subnet = QHostAddress::parseSubnet(addressEntry.ip().toString() + "/" + addressEntry.netmask().toString()); + if (d_ptr->hostAddress.isInSubnet(subnet.first, subnet.second)) { + ifIndex = interface.index(); + break; + } + } + } + } + d_ptr->serviceList = QtAvahiServicePrivate::createTxtList(txtRecords); d_ptr->error = avahi_entry_group_update_service_txt_strlst(d_ptr->group, - AVAHI_IF_UNSPEC, - AVAHI_PROTO_INET, + ifIndex, + d_ptr->hostAddress.protocol() == QAbstractSocket::IPv6Protocol ? AVAHI_PROTO_INET6 : AVAHI_PROTO_INET, (AvahiPublishFlags) 0, d_ptr->name.toLatin1().data(), d_ptr->type.toLatin1().data(), @@ -254,7 +291,7 @@ bool QtAvahiService::handlCollision() char* alt = avahi_alternative_service_name(name().toStdString().data()); QString alternativeServiceName = QLatin1String(alt); free(alt); - qCDebug(dcAvahi()) << "Service name colision. Picking alternative service name" << alternativeServiceName; + qCDebug(dcAvahi()) << "Service name collision. Picking alternative service name" << alternativeServiceName; resetService(); return registerService(alternativeServiceName, hostAddress(), port(), serviceType(), txtRecords()); @@ -284,8 +321,6 @@ void QtAvahiService::onStateChanged(const QtAvahiServiceState &state) case QtAvahiServiceStateFailure: qCWarning(dcAvahi()) << this << "failure: " << errorString(); break; - default: - break; } } diff --git a/libnymea-core/hardware/network/avahi/qtavahiservice.h b/libnymea-core/hardware/network/avahi/qtavahiservice.h index 6af0634c..339d48bd 100644 --- a/libnymea-core/hardware/network/avahi/qtavahiservice.h +++ b/libnymea-core/hardware/network/avahi/qtavahiservice.h @@ -27,6 +27,7 @@ #include #include #include +#include namespace nymeaserver { @@ -78,6 +79,13 @@ private: QtAvahiServiceState m_state; Q_DECLARE_PRIVATE(QtAvahiService) + QTimer m_reregisterTimer; + + QString m_name; + QHostAddress m_hostAddress; + quint16 m_port; + QString m_serviceType; + QHash m_txtRecords; }; QDebug operator <<(QDebug dbg, QtAvahiService *service);