diff --git a/src/mumble/Zeroconf.cpp b/src/mumble/Zeroconf.cpp index 868cf1d62..ebefcdbe7 100644 --- a/src/mumble/Zeroconf.cpp +++ b/src/mumble/Zeroconf.cpp @@ -5,39 +5,36 @@ #include "Zeroconf.h" -#define SYMBOL_EXISTS(symbol) (GetProcAddress(handle, symbol)) +#define GET_SYMBOL(symbol) (symbol = reinterpret_cast< decltype(symbol) >(GetProcAddress(handle, #symbol))) Zeroconf::Zeroconf() : m_ok(false) { qRegisterMetaType< uint16_t >("uint16_t"); qRegisterMetaType< BonjourRecord >("BonjourRecord"); qRegisterMetaType< QList< BonjourRecord > >("QList"); -#ifdef Q_OS_WIN64 - static bool winDnsUnavailable = false; - if (!winDnsUnavailable) { - auto handle = GetModuleHandle(L"dnsapi.dll"); - if (handle) { - if (SYMBOL_EXISTS("DnsServiceBrowse") && SYMBOL_EXISTS("DnsServiceBrowseCancel") - && SYMBOL_EXISTS("DnsServiceResolve") && SYMBOL_EXISTS("DnsServiceResolveCancel") - && SYMBOL_EXISTS("DnsServiceFreeInstance")) { - m_ok = true; - return; - } - } +#ifdef Q_OS_WIN + auto handle = GetModuleHandle(L"dnsapi.dll"); + if (handle) { + GET_SYMBOL(DnsServiceBrowse); + GET_SYMBOL(DnsServiceBrowseCancel); + GET_SYMBOL(DnsServiceResolve); + GET_SYMBOL(DnsServiceResolveCancel); + GET_SYMBOL(DnsServiceFreeInstance); - winDnsUnavailable = true; - qWarning("Zeroconf: Native mDNS/DNS-SD API not available, falling back to third-party API"); - } - - static bool dnssdLoadFailed = false; - if (!dnssdLoadFailed) { - auto handle = LoadLibrary(L"dnssd.DLL"); - if (!handle) { - dnssdLoadFailed = true; - qWarning("Zeroconf: Failed to load dnssd.dll, assuming third-party API is not available"); + if (DnsServiceBrowse && DnsServiceBrowseCancel && DnsServiceResolve && DnsServiceResolveCancel + && DnsServiceFreeInstance) { + m_ok = true; return; } - FreeLibrary(handle); } + + qWarning("Zeroconf: Native mDNS/DNS-SD API not available, falling back to third-party API"); + + handle = LoadLibrary(L"dnssd.dll"); + if (!handle) { + qWarning("Zeroconf: Failed to load dnssd.dll, assuming third-party API is not available"); + return; + } + FreeLibrary(handle); #endif resetHelperBrowser(); resetHelperResolver(); @@ -80,7 +77,7 @@ bool Zeroconf::startBrowser(const QString &serviceType) { m_helperBrowser->browseForServiceType(serviceType); return true; } -#ifdef Q_OS_WIN64 +#ifdef Q_OS_WIN const QString queryName = serviceType + QLatin1String(".local"); DNS_SERVICE_BROWSE_REQUEST request{}; @@ -110,7 +107,7 @@ bool Zeroconf::stopBrowser() { resetHelperBrowser(); return true; } -#ifdef Q_OS_WIN64 +#ifdef Q_OS_WIN if (m_cancelBrowser) { const auto ret = DnsServiceBrowseCancel(m_cancelBrowser.get()); if (ret == ERROR_SUCCESS || ret == ERROR_CANCELLED) { @@ -134,7 +131,7 @@ bool Zeroconf::startResolver(const BonjourRecord &record) { m_helperResolver->resolveBonjourRecord(record); return true; } -#ifdef Q_OS_WIN64 +#ifdef Q_OS_WIN stopResolver(record); auto qualifiedHostname = record.serviceName.toStdWString() + L"." + record.registeredType.toStdWString() @@ -160,7 +157,7 @@ bool Zeroconf::startResolver(const BonjourRecord &record) { #endif return false; } -#ifdef Q_OS_WIN64 +#ifdef Q_OS_WIN bool Zeroconf::stopResolver(const BonjourRecord &record) { if (!m_ok) { return false; @@ -200,7 +197,7 @@ bool Zeroconf::cleanupResolvers() { } auto result = true; -#ifdef Q_OS_WIN64 +#ifdef Q_OS_WIN for (auto i = 0; i < m_resolvers.size(); ++i) { if (!stopResolver(m_resolvers[i])) { result = false; @@ -228,7 +225,7 @@ void Zeroconf::helperResolverError(const BonjourRecord record, const DNSServiceE qWarning("Zeroconf: Third-party resolver API reports error %d", error); emit resolveError(record); } -#ifdef Q_OS_WIN64 +#ifdef Q_OS_WIN void WINAPI Zeroconf::callbackBrowseComplete(const DWORD status, void *context, DNS_RECORD *records) { auto zeroconf = static_cast< Zeroconf * >(context); zeroconf->m_cancelBrowser.reset(); @@ -283,9 +280,12 @@ void WINAPI Zeroconf::callbackBrowseComplete(const DWORD status, void *context, } void WINAPI Zeroconf::callbackResolveComplete(const DWORD status, void *context, DNS_SERVICE_INSTANCE *instance) { + auto resolver = static_cast< Resolver * >(context); + auto zeroconf = resolver->m_zeroconf; + if (status != ERROR_SUCCESS) { if (instance) { - DnsServiceFreeInstance(instance); + zeroconf->DnsServiceFreeInstance(instance); } if (status != ERROR_CANCELLED) { @@ -299,10 +299,8 @@ void WINAPI Zeroconf::callbackResolveComplete(const DWORD status, void *context, return; } - auto resolverContext = static_cast< Resolver * >(context); - emit resolverContext->m_zeroconf->recordResolved(resolverContext->m_record, - QString::fromWCharArray(instance->pszHostName), instance->wPort); + emit zeroconf->recordResolved(resolver->m_record, QString::fromWCharArray(instance->pszHostName), instance->wPort); - DnsServiceFreeInstance(instance); + zeroconf->DnsServiceFreeInstance(instance); } #endif diff --git a/src/mumble/Zeroconf.h b/src/mumble/Zeroconf.h index addc99239..87506c3b3 100644 --- a/src/mumble/Zeroconf.h +++ b/src/mumble/Zeroconf.h @@ -11,7 +11,7 @@ #include -#ifdef Q_OS_WIN64 +#ifdef Q_OS_WIN # include #endif @@ -20,7 +20,7 @@ private: Q_OBJECT Q_DISABLE_COPY(Zeroconf) protected: -#ifdef Q_OS_WIN64 +#ifdef Q_OS_WIN struct Resolver { Zeroconf *m_zeroconf; BonjourRecord m_record; @@ -35,7 +35,7 @@ protected: QList< BonjourRecord > m_records; std::unique_ptr< BonjourServiceBrowser > m_helperBrowser; std::unique_ptr< BonjourServiceResolver > m_helperResolver; -#ifdef Q_OS_WIN64 +#ifdef Q_OS_WIN QList< Resolver > m_resolvers; std::unique_ptr< DNS_SERVICE_CANCEL > m_cancelBrowser; @@ -51,7 +51,13 @@ protected: void helperResolverRecordResolved(const BonjourRecord record, const QString hostname, const int port); void helperBrowserError(const DNSServiceErrorType error) const; void helperResolverError(const BonjourRecord record, const DNSServiceErrorType error); - +#ifdef Q_OS_WIN + DNS_STATUS(WINAPI *DnsServiceBrowse)(PDNS_SERVICE_BROWSE_REQUEST pRequest, PDNS_SERVICE_CANCEL pCancel); + DNS_STATUS(WINAPI *DnsServiceBrowseCancel)(PDNS_SERVICE_CANCEL pCancelHandle); + DNS_STATUS(WINAPI *DnsServiceResolve)(PDNS_SERVICE_RESOLVE_REQUEST pRequest, PDNS_SERVICE_CANCEL pCancel); + DNS_STATUS(WINAPI *DnsServiceResolveCancel)(PDNS_SERVICE_CANCEL pCancelHandle); + VOID(WINAPI *DnsServiceFreeInstance)(PDNS_SERVICE_INSTANCE pInstance); +#endif public: inline bool isOk() const { return m_ok; } inline QList< BonjourRecord > currentRecords() const { @@ -62,7 +68,7 @@ public: bool stopBrowser(); bool startResolver(const BonjourRecord &record); -#ifdef Q_OS_WIN64 +#ifdef Q_OS_WIN bool stopResolver(const BonjourRecord &record); #endif bool cleanupResolvers(); diff --git a/src/murmur/Zeroconf.cpp b/src/murmur/Zeroconf.cpp index 2e1dcae84..4727c592e 100644 --- a/src/murmur/Zeroconf.cpp +++ b/src/murmur/Zeroconf.cpp @@ -5,37 +5,33 @@ #include "Zeroconf.h" -#define SYMBOL_EXISTS(symbol) (GetProcAddress(handle, symbol)) +#define GET_SYMBOL(symbol) (symbol = reinterpret_cast< decltype(symbol) >(GetProcAddress(handle, #symbol))) Zeroconf::Zeroconf() : m_ok(false) { -#ifdef Q_OS_WIN64 - static bool winDnsUnavailable = false; - if (!winDnsUnavailable) { - auto handle = GetModuleHandle(L"dnsapi.dll"); - if (handle) { - if (SYMBOL_EXISTS("DnsServiceConstructInstance") && SYMBOL_EXISTS("DnsServiceFreeInstance") - && SYMBOL_EXISTS("DnsServiceRegister") && SYMBOL_EXISTS("DnsServiceDeRegister") - && SYMBOL_EXISTS("DnsServiceRegisterCancel")) { - m_ok = true; - return; - } - } +#ifdef Q_OS_WIN + auto handle = GetModuleHandle(L"dnsapi.dll"); + if (handle) { + GET_SYMBOL(DnsServiceConstructInstance); + GET_SYMBOL(DnsServiceFreeInstance); + GET_SYMBOL(DnsServiceRegister); + GET_SYMBOL(DnsServiceDeRegister); + GET_SYMBOL(DnsServiceRegisterCancel); - winDnsUnavailable = true; - qWarning("Zeroconf: Native mDNS/DNS-SD API not available, falling back to third-party API"); - } - - static bool dnssdLoadFailed = false; - if (!dnssdLoadFailed) { - auto handle = LoadLibrary(L"dnssd.DLL"); - if (!handle) { - dnssdLoadFailed = true; - qWarning("Zeroconf: Failed to load dnssd.dll, assuming third-party API is not available"); + if (DnsServiceConstructInstance && DnsServiceFreeInstance && DnsServiceRegister && DnsServiceDeRegister + && DnsServiceRegisterCancel) { + m_ok = true; return; } - - FreeLibrary(handle); } + + qWarning("Zeroconf: Native mDNS/DNS-SD API not available, falling back to third-party API"); + + handle = LoadLibrary(L"dnssd.dll"); + if (!handle) { + qWarning("Zeroconf: Failed to load dnssd.dll, assuming third-party API is not available"); + return; + } + FreeLibrary(handle); #endif resetHelper(); @@ -64,7 +60,7 @@ bool Zeroconf::registerService(const BonjourRecord &record, const uint16_t port) m_helper->registerService(record, port); return true; } -#ifdef Q_OS_WIN64 +#ifdef Q_OS_WIN DWORD size = 0; GetComputerNameEx(ComputerNameDnsHostname, nullptr, &size); std::vector< wchar_t > hostname(size); @@ -118,7 +114,7 @@ bool Zeroconf::unregisterService() { resetHelper(); return true; } -#ifdef Q_OS_WIN64 +#ifdef Q_OS_WIN if (m_cancel) { const auto ret = DnsServiceRegisterCancel(m_cancel.get()); if (ret == ERROR_SUCCESS || ret == ERROR_CANCELLED) { @@ -142,17 +138,18 @@ bool Zeroconf::unregisterService() { void Zeroconf::helperError(const DNSServiceErrorType error) { qWarning("Zeroconf: Third-party API reports error %d, service registration probably failed", error); } -#ifdef Q_OS_WIN64 +#ifdef Q_OS_WIN void WINAPI Zeroconf::callbackRegisterComplete(const DWORD status, void *context, DNS_SERVICE_INSTANCE *instance) { + auto zeroconf = static_cast< Zeroconf * >(context); + if (instance) { - DnsServiceFreeInstance(instance); + zeroconf->DnsServiceFreeInstance(instance); } if (status == ERROR_CANCELLED) { return; } - auto zeroconf = static_cast< Zeroconf * >(context); zeroconf->m_cancel.reset(); if (status != ERROR_SUCCESS) { diff --git a/src/murmur/Zeroconf.h b/src/murmur/Zeroconf.h index 598897735..4dd953ed5 100644 --- a/src/murmur/Zeroconf.h +++ b/src/murmur/Zeroconf.h @@ -10,7 +10,7 @@ #include -#ifdef Q_OS_WIN64 +#ifdef Q_OS_WIN # include #endif @@ -21,14 +21,22 @@ private: protected: bool m_ok; std::unique_ptr< BonjourServiceRegister > m_helper; -#ifdef Q_OS_WIN64 +#ifdef Q_OS_WIN std::unique_ptr< DNS_SERVICE_CANCEL > m_cancel; std::unique_ptr< DNS_SERVICE_REGISTER_REQUEST > m_request; static void WINAPI callbackRegisterComplete(const DWORD status, void *context, DNS_SERVICE_INSTANCE *instance); #endif void helperError(const DNSServiceErrorType error); - +#ifdef Q_OS_WIN + PDNS_SERVICE_INSTANCE(WINAPI *DnsServiceConstructInstance) + (PCWSTR pServiceName, PCWSTR pHostName, PIP4_ADDRESS pIp4, PIP6_ADDRESS pIp6, WORD wPort, WORD wPriority, + WORD wWeight, DWORD dwPropertiesCount, PCWSTR *keys, PCWSTR *values); + VOID(WINAPI *DnsServiceFreeInstance)(PDNS_SERVICE_INSTANCE pInstance); + DWORD(WINAPI *DnsServiceRegister)(PDNS_SERVICE_REGISTER_REQUEST pRequest, PDNS_SERVICE_CANCEL pCancel); + DWORD(WINAPI *DnsServiceDeRegister)(PDNS_SERVICE_REGISTER_REQUEST pRequest, PDNS_SERVICE_CANCEL pCancel); + DWORD(WINAPI *DnsServiceRegisterCancel)(PDNS_SERVICE_CANCEL pCancelHandle); +#endif public: inline bool isOk() const { return m_ok; }