Revert "remove macOS support"

This reverts commit 518ce0187a.
This commit is contained in:
Camille Scholtz
2025-01-30 16:37:01 +01:00
committed by Max Kellermann
parent f15b6a43d3
commit 509786cbf1
33 changed files with 1659 additions and 40 deletions

76
src/zeroconf/Bonjour.cxx Normal file
View File

@@ -0,0 +1,76 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright The Music Player Daemon Project
#include "Bonjour.hxx"
#include "util/Domain.hxx"
#include "Log.hxx"
#include <dns_sd.h>
#include <stdexcept>
#include <arpa/inet.h>
static constexpr Domain bonjour_domain("bonjour");
/**
* A wrapper for DNSServiceRegister() which returns the DNSServiceRef
* and throws on error.
*/
static DNSServiceRef
RegisterBonjour(const char *name, const char *type, unsigned port,
DNSServiceRegisterReply callback, void *ctx)
{
DNSServiceRef ref;
DNSServiceErrorType error = DNSServiceRegister(&ref,
0, 0, name, type,
nullptr, nullptr,
htons(port), 0,
nullptr,
callback, ctx);
if (error != kDNSServiceErr_NoError)
throw std::runtime_error("DNSServiceRegister() failed");
return ref;
}
BonjourHelper::BonjourHelper(EventLoop &_loop, const char *name,
const char *service_type, unsigned port)
:service_ref(RegisterBonjour(name, service_type, port,
Callback, this)),
socket_event(_loop,
BIND_THIS_METHOD(OnSocketReady),
SocketDescriptor(DNSServiceRefSockFD(service_ref)))
{
socket_event.ScheduleRead();
}
void
BonjourHelper::Callback([[maybe_unused]] DNSServiceRef sdRef,
[[maybe_unused]] DNSServiceFlags flags,
DNSServiceErrorType errorCode, const char *name,
[[maybe_unused]] const char *regtype,
[[maybe_unused]] const char *domain,
[[maybe_unused]] void *context) noexcept
{
auto &helper = *(BonjourHelper *)context;
if (errorCode != kDNSServiceErr_NoError) {
LogError(bonjour_domain,
"Failed to register zeroconf service");
helper.Cancel();
} else {
FmtDebug(bonjour_domain,
"Registered zeroconf service with name {:?}",
name);
}
}
std::unique_ptr<BonjourHelper>
BonjourInit(EventLoop &loop, const char *name,
const char *service_type, unsigned port)
{
return std::make_unique<BonjourHelper>(loop, name, service_type, port);
}

55
src/zeroconf/Bonjour.hxx Normal file
View File

@@ -0,0 +1,55 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright The Music Player Daemon Project
#ifndef MPD_ZEROCONF_BONJOUR_HXX
#define MPD_ZEROCONF_BONJOUR_HXX
#include "event/SocketEvent.hxx"
#include <dns_sd.h>
#include <memory>
class EventLoop;
class BonjourHelper final {
const DNSServiceRef service_ref;
SocketEvent socket_event;
public:
BonjourHelper(EventLoop &_loop, const char *name,
const char *service_name, unsigned port);
~BonjourHelper() noexcept {
DNSServiceRefDeallocate(service_ref);
}
BonjourHelper(const BonjourHelper &) = delete;
BonjourHelper &operator=(const BonjourHelper &) = delete;
private:
void Cancel() noexcept {
socket_event.Cancel();
}
static void Callback(DNSServiceRef sdRef, DNSServiceFlags flags,
DNSServiceErrorType errorCode, const char *name,
const char *regtype,
const char *domain,
void *context) noexcept;
/* virtual methods from class SocketMonitor */
void OnSocketReady([[maybe_unused]] unsigned flags) noexcept {
DNSServiceProcessResult(service_ref);
}
};
/**
* Throws on error.
*/
std::unique_ptr<BonjourHelper>
BonjourInit(EventLoop &loop, const char *name,
const char *service_type, unsigned port);
#endif

View File

@@ -3,13 +3,20 @@
#include "Glue.hxx"
#include "Helper.hxx"
#include "avahi/Helper.hxx"
#include "config/Data.hxx"
#include "config/Option.hxx"
#include "Listen.hxx"
#include "util/Domain.hxx"
#include "Log.hxx"
#ifdef HAVE_AVAHI
#include "avahi/Helper.hxx"
#endif
#ifdef HAVE_BONJOUR
#include "Bonjour.hxx"
#endif
#include <climits>
#include <string.h>

View File

@@ -1,9 +1,11 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright The Music Player Daemon Project
#pragma once
#ifndef MPD_ZEROCONF_GLUE_HXX
#define MPD_ZEROCONF_GLUE_HXX
#include "Helper.hxx"
#include "config.h"
#include <memory>
@@ -11,8 +13,14 @@ struct ConfigData;
class EventLoop;
class ZeroconfHelper;
#ifdef HAVE_ZEROCONF
/**
* Throws on error.
*/
std::unique_ptr<ZeroconfHelper>
ZeroconfInit(const ConfigData &config, EventLoop &loop);
#endif /* ! HAVE_ZEROCONF */
#endif

View File

@@ -2,10 +2,19 @@
// Copyright The Music Player Daemon Project
#include "Helper.hxx"
#ifdef HAVE_AVAHI
#include "avahi/Helper.hxx"
#define CreateHelper AvahiInit
#endif
#ifdef HAVE_BONJOUR
#include "Bonjour.hxx"
#define CreateHelper BonjourInit
#endif
ZeroconfHelper::ZeroconfHelper(EventLoop &event_loop, const char *name,
const char *service_type, unsigned port)
:helper(AvahiInit(event_loop, name, service_type, port)) {}
:helper(CreateHelper(event_loop, name, service_type, port)) {}
ZeroconfHelper::~ZeroconfHelper() noexcept = default;

View File

@@ -1,15 +1,25 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright The Music Player Daemon Project
#pragma once
#ifndef MPD_ZEROCONF_HELPER_HXX
#define MPD_ZEROCONF_HELPER_HXX
#include "config.h"
#include <memory>
class EventLoop;
class AvahiHelper;
class BonjourHelper;
class ZeroconfHelper final {
#ifdef HAVE_AVAHI
std::unique_ptr<AvahiHelper> helper;
#endif
#ifdef HAVE_BONJOUR
std::unique_ptr<BonjourHelper> helper;
#endif
public:
ZeroconfHelper(EventLoop &event_loop, const char *name,
@@ -17,3 +27,5 @@ public:
~ZeroconfHelper() noexcept;
};
#endif

View File

@@ -3,7 +3,9 @@ zeroconf_option = get_option('zeroconf')
avahi_dep = dependency('', required: false)
if zeroconf_option == 'auto'
if is_android or is_windows
if is_darwin
zeroconf_option = 'bonjour'
elif is_android or is_windows
zeroconf_option = 'disabled'
elif dbus_dep.found()
zeroconf_option = 'avahi'
@@ -17,30 +19,61 @@ if zeroconf_option == 'disabled'
subdir_done()
endif
subdir('avahi')
if zeroconf_option == 'bonjour'
if not compiler.has_header('dns_sd.h')
error('dns_sd.h not found')
endif
if not avahi_dep.found()
zeroconf_dep = dependency('', required: false)
subdir_done()
bonjour_deps = [
]
if not is_darwin
bonjour_deps += declare_dependency(link_args: ['-ldns_sd'])
endif
conf.set('HAVE_BONJOUR', true)
zeroconf = static_library(
'zeroconf_bonjour',
'Glue.cxx',
'Helper.cxx',
'Bonjour.cxx',
include_directories: inc,
dependencies: [
event_dep,
log_dep,
],
)
zeroconf_dep = declare_dependency(
link_with: zeroconf,
dependencies: bonjour_deps,
)
else
subdir('avahi')
if not avahi_dep.found()
zeroconf_dep = dependency('', required: false)
subdir_done()
endif
conf.set('HAVE_AVAHI', true)
zeroconf = static_library(
'zeroconf_bonjour',
'Glue.cxx',
'Helper.cxx',
include_directories: inc,
dependencies: [
avahi_dep,
dbus_dep,
time_dep,
log_dep,
],
)
zeroconf_dep = declare_dependency(
link_with: zeroconf,
)
endif
conf.set('HAVE_AVAHI', true)
zeroconf = static_library(
'zeroconf',
'Glue.cxx',
'Helper.cxx',
include_directories: inc,
dependencies: [
avahi_dep,
dbus_dep,
time_dep,
log_dep,
],
)
zeroconf_dep = declare_dependency(
link_with: zeroconf,
)
conf.set('HAVE_ZEROCONF', true)