zeroconf/avahi/Init: return a std::unique_ptr<AvahiHelper>

This commit is contained in:
Max Kellermann 2021-02-24 14:27:05 +01:00
parent b01ef1b9a6
commit 975d5be046
5 changed files with 64 additions and 42 deletions

View File

@ -18,7 +18,6 @@
*/ */
#include "Glue.hxx" #include "Glue.hxx"
#include "avahi/Init.hxx"
#include "config/Data.hxx" #include "config/Data.hxx"
#include "config/Option.hxx" #include "config/Option.hxx"
#include "Listen.hxx" #include "Listen.hxx"
@ -26,6 +25,10 @@
#include "Log.hxx" #include "Log.hxx"
#include "util/Compiler.h" #include "util/Compiler.h"
#ifdef HAVE_AVAHI
#include "avahi/Helper.hxx"
#endif
#ifdef HAVE_BONJOUR #ifdef HAVE_BONJOUR
#include "Bonjour.hxx" #include "Bonjour.hxx"
#endif #endif
@ -52,6 +55,10 @@ static constexpr Domain zeroconf_domain("zeroconf");
static int zeroconfEnabled; static int zeroconfEnabled;
#ifdef HAVE_AVAHI
static std::unique_ptr<AvahiHelper> avahi_helper;
#endif
#ifdef HAVE_BONJOUR #ifdef HAVE_BONJOUR
static std::unique_ptr<BonjourHelper> bonjour_helper; static std::unique_ptr<BonjourHelper> bonjour_helper;
#endif #endif
@ -89,7 +96,7 @@ ZeroconfInit(const ConfigData &config, [[maybe_unused]] EventLoop &loop)
} }
#ifdef HAVE_AVAHI #ifdef HAVE_AVAHI
AvahiInit(loop, serviceName, listen_port); avahi_helper = AvahiInit(loop, serviceName, listen_port);
#endif #endif
#ifdef HAVE_BONJOUR #ifdef HAVE_BONJOUR
@ -100,14 +107,11 @@ ZeroconfInit(const ConfigData &config, [[maybe_unused]] EventLoop &loop)
void void
ZeroconfDeinit() noexcept ZeroconfDeinit() noexcept
{ {
#ifdef HAVE_AVAHI
avahi_helper.reset();
#endif
#ifdef HAVE_BONJOUR #ifdef HAVE_BONJOUR
bonjour_helper.reset(); bonjour_helper.reset();
#endif #endif
if (!zeroconfEnabled)
return;
#ifdef HAVE_AVAHI
AvahiDeinit();
#endif /* HAVE_AVAHI */
} }

View File

@ -17,29 +17,23 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#include "Init.hxx" #include "Helper.hxx"
#include "../Internal.hxx"
#include "Client.hxx" #include "Client.hxx"
#include "ConnectionListener.hxx"
#include "ErrorHandler.hxx" #include "ErrorHandler.hxx"
#include "Publisher.hxx" #include "Publisher.hxx"
#include "Service.hxx" #include "Service.hxx"
#include "../Internal.hxx"
#include "util/RuntimeError.hxx" #include "util/RuntimeError.hxx"
#include "Log.hxx" #include "Log.hxx"
#include <avahi-common/domain.h> #include <avahi-common/domain.h>
class AvahiGlue final : Avahi::ErrorHandler { class SharedAvahiClient : public Avahi::ErrorHandler {
public: public:
Avahi::Client client; Avahi::Client client;
Avahi::Publisher publisher;
AvahiGlue(EventLoop &event_loop, SharedAvahiClient(EventLoop &event_loop)
const char *name, std::forward_list<Avahi::Service> services) :client(event_loop, *this) {}
:client(event_loop, *this),
publisher(client, name, std::move(services), *this)
{
}
/* virtual methods from class Avahi::ErrorHandler */ /* virtual methods from class Avahi::ErrorHandler */
bool OnAvahiError(std::exception_ptr e) noexcept override { bool OnAvahiError(std::exception_ptr e) noexcept override {
@ -48,24 +42,38 @@ public:
} }
}; };
static AvahiGlue *avahi_glue; static std::weak_ptr<SharedAvahiClient> shared_avahi_client;
void inline
AvahiInit(EventLoop &loop, const char *serviceName, unsigned port) AvahiHelper::AvahiHelper(std::shared_ptr<SharedAvahiClient> _client,
std::unique_ptr<Avahi::Publisher> _publisher)
:client(std::move(_client)),
publisher(std::move(_publisher)) {}
AvahiHelper::~AvahiHelper() noexcept = default;
std::unique_ptr<AvahiHelper>
AvahiInit(EventLoop &event_loop, const char *service_name, unsigned port)
{ {
if (!avahi_is_valid_service_name(serviceName)) if (!avahi_is_valid_service_name(service_name))
throw FormatRuntimeError("Invalid zeroconf_name \"%s\"", serviceName); throw FormatRuntimeError("Invalid zeroconf_name \"%s\"",
service_name);
auto client = shared_avahi_client.lock();
if (!client)
shared_avahi_client = client =
std::make_shared<SharedAvahiClient>(event_loop);
std::forward_list<Avahi::Service> services; std::forward_list<Avahi::Service> services;
services.emplace_front(AVAHI_IF_UNSPEC, services.emplace_front(AVAHI_IF_UNSPEC,
AVAHI_PROTO_UNSPEC, AVAHI_PROTO_UNSPEC,
SERVICE_TYPE, port); SERVICE_TYPE, port);
avahi_glue = new AvahiGlue(loop, serviceName, std::move(services)); auto publisher = std::make_unique<Avahi::Publisher>(client->client,
} service_name,
std::move(services),
*client);
void return std::make_unique<AvahiHelper>(std::move(client),
AvahiDeinit() std::move(publisher));
{
delete avahi_glue;
} }

View File

@ -17,15 +17,27 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#ifndef MPD_ZEROCONF_AVAHI_HXX #ifndef MPD_ZEROCONF_AVAHI_HELPER_HXX
#define MPD_ZEROCONF_AVAHI_HXX #define MPD_ZEROCONF_AVAHI_HELPER_HXX
#include <memory>
class EventLoop; class EventLoop;
namespace Avahi { class Publisher; }
void class SharedAvahiClient;
AvahiInit(EventLoop &loop, const char *service_name, unsigned port);
void class AvahiHelper final {
AvahiDeinit(); std::shared_ptr<SharedAvahiClient> client;
std::unique_ptr<Avahi::Publisher> publisher;
public:
AvahiHelper(std::shared_ptr<SharedAvahiClient> _client,
std::unique_ptr<Avahi::Publisher> _publisher);
~AvahiHelper() noexcept;
};
std::unique_ptr<AvahiHelper>
AvahiInit(EventLoop &event_loop, const char *service_name, unsigned port);
#endif #endif

View File

@ -6,7 +6,7 @@ endif
avahi = static_library( avahi = static_library(
'avahi', 'avahi',
'Init.cxx', 'Helper.cxx',
'Client.cxx', 'Client.cxx',
'Error.cxx', 'Error.cxx',
'Poll.cxx', 'Poll.cxx',

View File

@ -19,7 +19,7 @@
#include "event/Loop.hxx" #include "event/Loop.hxx"
#include "ShutdownHandler.hxx" #include "ShutdownHandler.hxx"
#include "zeroconf/avahi/Init.hxx" #include "zeroconf/avahi/Helper.hxx"
#include <stdlib.h> #include <stdlib.h>
@ -29,11 +29,9 @@ main([[maybe_unused]] int argc, [[maybe_unused]] char **argv)
EventLoop event_loop; EventLoop event_loop;
const ShutdownHandler shutdown_handler(event_loop); const ShutdownHandler shutdown_handler(event_loop);
AvahiInit(event_loop, "test", 1234); const auto helper = AvahiInit(event_loop, "test", 1234);
event_loop.Run(); event_loop.Run();
AvahiDeinit();
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }