Skip to content

Commit d03ddf9

Browse files
Fix concurrent mDNS resolution by verifying requested hostname
- libsrc/mdns/MdnsBrowser.cpp:119-170 now keeps each resolver self-contained: the resolver’s resolved signal is handled locally (no shared isAddressResolved signal), link‑local results are ignored on the spot, and the completion signal now carries the hostname so concurrent lookups can’t bleed into one another. - include/mdns/MdnsBrowser.h:62-112 reflects the slimmer API—removed the unused slot/signal and updated isFirstAddressResolved to emit both hostname and address. - include/utils/NetUtils.h:109-146 listens for the hostname-tagged completion and ignores unrelated emissions, so every resolveMDnsHostToAddress call exits only when its own hostname was resolved. Courtesy of OpenAI Codex ;) This fixes #1906
1 parent 6097eb6 commit d03ddf9

File tree

4 files changed

+26
-31
lines changed

4 files changed

+26
-31
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4444
- LED-device updates queue up and let Hyperion crash (#1887)
4545
- The color of the backlight threshold is green, not white/gray (#1899)
4646
- Install - Ubuntu 25.10 unable to install due to libcec package (#1934)
47+
- Fix concurrent mDNS resolution (#1906)
4748

4849
---
4950

@@ -61,7 +62,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6162
- **Fixes:**
6263
- WebUI unreachable via IPv6 (#1871)
6364
- Align install_pr script working with default Qt6 builds & show authentication failures (#1871)
64-
65+
6566
- **Build:**
6667
- Added Debian Trixie to PR-builds for early testing
6768

include/mdns/MdnsBrowser.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <QByteArray>
1818
#include <QMap>
1919
#include <QJsonArray>
20+
#include <QString>
2021
#include <QSharedPointer>
2122
#include <QScopedPointer>
2223

@@ -88,8 +89,7 @@ public slots:
8889
*/
8990
void serviceRemoved(const QMdnsEngine::Service& service);
9091

91-
void isAddressResolved(QHostAddress address);
92-
void isFirstAddressResolved(QHostAddress address);
92+
void isFirstAddressResolved(QString hostname, QHostAddress address);
9393

9494
void isServiceRecordResolved(QMdnsEngine::Record serviceRecord) const;
9595

@@ -101,8 +101,6 @@ private slots:
101101
void onServiceUpdated(const QMdnsEngine::Service& service);
102102
void onServiceRemoved(const QMdnsEngine::Service& service);
103103

104-
void onHostNameResolved(const QHostAddress& address);
105-
106104
private:
107105
/// The logger instance for mDNS-Service
108106
QSharedPointer<Logger> _log;

include/utils/NetUtils.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,15 @@ inline bool resolveMDnsHostToAddress(QSharedPointer<Logger> log, const QString&
118118
QEventLoop loop;
119119

120120
// Connect the signal to capture the resolved address
121-
QObject::connect(browser, &MdnsBrowser::isFirstAddressResolved, &loop, [&](QHostAddress addr) {
122-
hostAddress = std::move(addr);
121+
QString const requestedHostname = hostname;
122+
QObject::connect(browser, &MdnsBrowser::isFirstAddressResolved, &loop,
123+
[&, requestedHostname](const QString& resolvedHostname, const QHostAddress& addr) {
124+
if (resolvedHostname.compare(requestedHostname, Qt::CaseInsensitive) != 0)
125+
{
126+
return;
127+
}
128+
129+
hostAddress = addr;
123130
loop.quit();
124131
});
125132

libsrc/mdns/MdnsBrowser.cpp

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -116,21 +116,6 @@ void MdnsBrowser::onServiceRemoved(const QMdnsEngine::Service& service)
116116
emit serviceRemoved(service);
117117
}
118118

119-
void MdnsBrowser::onHostNameResolved(const QHostAddress& address)
120-
{
121-
DebugIf(verboseBrowser, _log, "for address [%s], Thread: %s", QSTRING_CSTR(address.toString()), QSTRING_CSTR(QThread::currentThread()->objectName()));
122-
123-
// Do not publish link local addresses
124-
#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0))
125-
if (!address.isLinkLocal())
126-
#else
127-
if (!address.toString().startsWith("fe80"))
128-
#endif
129-
{
130-
emit isAddressResolved(address);
131-
}
132-
}
133-
134119
void MdnsBrowser::resolveFirstAddress(QSharedPointer<Logger> log, const QString& hostname, std::chrono::milliseconds timeout)
135120
{
136121
qRegisterMetaType<QMdnsEngine::Message>("Message");
@@ -140,24 +125,28 @@ void MdnsBrowser::resolveFirstAddress(QSharedPointer<Logger> log, const QString&
140125
if (hostname.endsWith(".local") || hostname.endsWith(".local."))
141126
{
142127
QMdnsEngine::Resolver const resolver (_server.get(), hostname.toUtf8(), _cache.get());
143-
connect(&resolver, &QMdnsEngine::Resolver::resolved, this, &MdnsBrowser::onHostNameResolved);
144128

145129
DebugIf(verboseBrowser, log, "Wait for resolver on hostname [%s]", QSTRING_CSTR(hostname));
146130

147131
QEventLoop loop;
148132
QTimer timer;
149133

150134
timer.setSingleShot(true);
151-
connect(&timer, &QTimer::timeout, this, [&loop]() {
152-
loop.quit(); // Stop waiting if timeout occurs
153-
});
135+
connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
136+
137+
connect(&resolver, &QMdnsEngine::Resolver::resolved, &loop, [ &loop, &resolvedAddress ](const QHostAddress& address) {
138+
// Ignore link-local addresses
139+
#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0))
140+
if (address.isLinkLocal())
141+
#else
142+
if (address.toString().startsWith("fe80"))
143+
#endif
144+
{
145+
return;
146+
}
154147

155-
std::unique_ptr<QObject> context{new QObject};
156-
QObject* pcontext = context.get();
157-
connect(this, &MdnsBrowser::isAddressResolved, pcontext, [ &loop, &resolvedAddress, context = std::move(context)](const QHostAddress &address) mutable {
158148
resolvedAddress = address;
159149
loop.quit();
160-
context.reset();
161150
});
162151

163152
timer.start(timeout);
@@ -177,7 +166,7 @@ void MdnsBrowser::resolveFirstAddress(QSharedPointer<Logger> log, const QString&
177166
Error(log, "Hostname [%s] is not an mDNS hostname.", QSTRING_CSTR(hostname));
178167
}
179168

180-
emit isFirstAddressResolved(resolvedAddress);
169+
emit isFirstAddressResolved(hostname, resolvedAddress);
181170
}
182171

183172
void MdnsBrowser::resolveServiceInstance(const QByteArray& serviceInstance, const std::chrono::milliseconds waitTime) const

0 commit comments

Comments
 (0)