From 95c3f57b3027e0961a1e32036dcce0383fb5e6ee Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Sun, 27 Jan 2013 22:18:45 +0100 Subject: zeroconf: convert to C++ --- Makefile.am | 9 +- src/Main.cxx | 6 +- src/ZeroconfAvahi.cxx | 266 +++++++++++++++++++++++++++++++++++++++++++++++ src/ZeroconfAvahi.hxx | 29 ++++++ src/ZeroconfBonjour.cxx | 100 ++++++++++++++++++ src/ZeroconfBonjour.hxx | 29 ++++++ src/ZeroconfGlue.cxx | 78 ++++++++++++++ src/ZeroconfGlue.hxx | 45 ++++++++ src/ZeroconfInternal.hxx | 26 +++++ src/zeroconf-avahi.c | 262 ---------------------------------------------- src/zeroconf-bonjour.c | 97 ----------------- src/zeroconf-internal.h | 34 ------ src/zeroconf.c | 75 ------------- src/zeroconf.h | 37 ------- 14 files changed, 581 insertions(+), 512 deletions(-) create mode 100644 src/ZeroconfAvahi.cxx create mode 100644 src/ZeroconfAvahi.hxx create mode 100644 src/ZeroconfBonjour.cxx create mode 100644 src/ZeroconfBonjour.hxx create mode 100644 src/ZeroconfGlue.cxx create mode 100644 src/ZeroconfGlue.hxx create mode 100644 src/ZeroconfInternal.hxx delete mode 100644 src/zeroconf-avahi.c delete mode 100644 src/zeroconf-bonjour.c delete mode 100644 src/zeroconf-internal.h delete mode 100644 src/zeroconf.c delete mode 100644 src/zeroconf.h diff --git a/Makefile.am b/Makefile.am index ee57c752d..cf023a6bd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -117,7 +117,6 @@ mpd_headers = \ src/uri.h \ src/utils.h \ src/string_util.h \ - src/zeroconf.h src/zeroconf-internal.h \ src/timer.h \ src/mpd_error.h @@ -681,14 +680,16 @@ endif if HAVE_ZEROCONF -src_mpd_SOURCES += src/zeroconf.c +src_mpd_SOURCES += \ + src/ZeroconfInternal.hxx \ + src/ZeroconfGlue.cxx src/ZeroconfGlue.hxx if HAVE_AVAHI -src_mpd_SOURCES += src/zeroconf-avahi.c +src_mpd_SOURCES += src/ZeroconfAvahi.cxx src/ZeroconfAvahi.hxx endif if HAVE_BONJOUR -src_mpd_SOURCES += src/zeroconf-bonjour.c +src_mpd_SOURCES += src/ZeroconfBonjour.cxx src/ZeroconfBonjour.hxx endif endif diff --git a/src/Main.cxx b/src/Main.cxx index 6cf9c3457..828462019 100644 --- a/src/Main.cxx +++ b/src/Main.cxx @@ -49,6 +49,7 @@ #include "IOThread.hxx" #include "fs/Path.hxx" #include "PlaylistRegistry.hxx" +#include "ZeroconfGlue.hxx" extern "C" { #include "daemon.h" @@ -56,7 +57,6 @@ extern "C" { #include "audio_config.h" #include "pcm_resample.h" #include "decoder_list.h" -#include "zeroconf.h" } #include "mpd_error.h" @@ -490,7 +490,7 @@ int mpd_main(int argc, char *argv[]) return EXIT_FAILURE; } - initZeroconf(); + ZeroconfInit(); player_create(&global_partition->pc); @@ -551,7 +551,7 @@ int mpd_main(int argc, char *argv[]) } global_partition->pc.Kill(); - finishZeroconf(); + ZeroconfDeinit(); listen_global_finish(); delete client_list; diff --git a/src/ZeroconfAvahi.cxx b/src/ZeroconfAvahi.cxx new file mode 100644 index 000000000..8fa745a69 --- /dev/null +++ b/src/ZeroconfAvahi.cxx @@ -0,0 +1,266 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "ZeroconfAvahi.hxx" +#include "ZeroconfInternal.hxx" +#include "Listen.hxx" +#include "mpd_error.h" + +#include + +#include +#include + +#include +#include +#include +#include + +#include + +#undef G_LOG_DOMAIN +#define G_LOG_DOMAIN "avahi" + +static char *avahiName; +static int avahiRunning; +static AvahiGLibPoll *avahi_glib_poll; +static const AvahiPoll *avahi_poll; +static AvahiClient *avahiClient; +static AvahiEntryGroup *avahiGroup; + +static void avahiRegisterService(AvahiClient * c); + +/* Callback when the EntryGroup changes state */ +static void avahiGroupCallback(AvahiEntryGroup * g, + AvahiEntryGroupState state, + G_GNUC_UNUSED void *userdata) +{ + char *n; + assert(g); + + g_debug("Service group changed to state %d", state); + + switch (state) { + case AVAHI_ENTRY_GROUP_ESTABLISHED: + /* The entry group has been established successfully */ + g_message("Service '%s' successfully established.", + avahiName); + break; + + case AVAHI_ENTRY_GROUP_COLLISION: + /* A service name collision happened. Let's pick a new name */ + n = avahi_alternative_service_name(avahiName); + avahi_free(avahiName); + avahiName = n; + + g_message("Service name collision, renaming service to '%s'", + avahiName); + + /* And recreate the services */ + avahiRegisterService(avahi_entry_group_get_client(g)); + break; + + case AVAHI_ENTRY_GROUP_FAILURE: + g_warning("Entry group failure: %s", + avahi_strerror(avahi_client_errno + (avahi_entry_group_get_client(g)))); + /* Some kind of failure happened while we were registering our services */ + avahiRunning = 0; + break; + + case AVAHI_ENTRY_GROUP_UNCOMMITED: + g_debug("Service group is UNCOMMITED"); + break; + case AVAHI_ENTRY_GROUP_REGISTERING: + g_debug("Service group is REGISTERING"); + } +} + +/* Registers a new service with avahi */ +static void avahiRegisterService(AvahiClient * c) +{ + int ret; + assert(c); + g_debug("Registering service %s/%s", SERVICE_TYPE, avahiName); + + /* If this is the first time we're called, + * let's create a new entry group */ + if (!avahiGroup) { + avahiGroup = avahi_entry_group_new(c, avahiGroupCallback, NULL); + if (!avahiGroup) { + g_warning("Failed to create avahi EntryGroup: %s", + avahi_strerror(avahi_client_errno(c))); + goto fail; + } + } + + /* Add the service */ + /* TODO: This currently binds to ALL interfaces. + * We could maybe add a service per actual bound interface, + * if that's better. */ + ret = avahi_entry_group_add_service(avahiGroup, + AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, + AvahiPublishFlags(0), + avahiName, SERVICE_TYPE, NULL, + NULL, listen_port, NULL); + if (ret < 0) { + g_warning("Failed to add service %s: %s", SERVICE_TYPE, + avahi_strerror(ret)); + goto fail; + } + + /* Tell the server to register the service group */ + ret = avahi_entry_group_commit(avahiGroup); + if (ret < 0) { + g_warning("Failed to commit service group: %s", + avahi_strerror(ret)); + goto fail; + } + return; + +fail: + avahiRunning = 0; +} + +/* Callback when avahi changes state */ +static void avahiClientCallback(AvahiClient * c, AvahiClientState state, + G_GNUC_UNUSED void *userdata) +{ + int reason; + assert(c); + + /* Called whenever the client or server state changes */ + g_debug("Client changed to state %d", state); + + switch (state) { + case AVAHI_CLIENT_S_RUNNING: + g_debug("Client is RUNNING"); + + /* The server has startup successfully and registered its host + * name on the network, so it's time to create our services */ + if (!avahiGroup) + avahiRegisterService(c); + break; + + case AVAHI_CLIENT_FAILURE: + reason = avahi_client_errno(c); + if (reason == AVAHI_ERR_DISCONNECTED) { + g_message("Client Disconnected, will reconnect shortly"); + if (avahiGroup) { + avahi_entry_group_free(avahiGroup); + avahiGroup = NULL; + } + if (avahiClient) + avahi_client_free(avahiClient); + avahiClient = + avahi_client_new(avahi_poll, + AVAHI_CLIENT_NO_FAIL, + avahiClientCallback, NULL, + &reason); + if (!avahiClient) { + g_warning("Could not reconnect: %s", + avahi_strerror(reason)); + avahiRunning = 0; + } + } else { + g_warning("Client failure: %s (terminal)", + avahi_strerror(reason)); + avahiRunning = 0; + } + break; + + case AVAHI_CLIENT_S_COLLISION: + g_debug("Client is COLLISION"); + /* Let's drop our registered services. When the server is back + * in AVAHI_SERVER_RUNNING state we will register them + * again with the new host name. */ + if (avahiGroup) { + g_debug("Resetting group"); + avahi_entry_group_reset(avahiGroup); + } + + case AVAHI_CLIENT_S_REGISTERING: + g_debug("Client is REGISTERING"); + /* The server records are now being established. This + * might be caused by a host name change. We need to wait + * for our own records to register until the host name is + * properly esatblished. */ + + if (avahiGroup) { + g_debug("Resetting group"); + avahi_entry_group_reset(avahiGroup); + } + + break; + + case AVAHI_CLIENT_CONNECTING: + g_debug("Client is CONNECTING"); + } +} + +void +AvahiInit(const char *serviceName) +{ + int error; + g_debug("Initializing interface"); + + if (!avahi_is_valid_service_name(serviceName)) + MPD_ERROR("Invalid zeroconf_name \"%s\"", serviceName); + + avahiName = avahi_strdup(serviceName); + + avahiRunning = 1; + + avahi_glib_poll = avahi_glib_poll_new(NULL, G_PRIORITY_DEFAULT); + avahi_poll = avahi_glib_poll_get(avahi_glib_poll); + + avahiClient = avahi_client_new(avahi_poll, AVAHI_CLIENT_NO_FAIL, + avahiClientCallback, NULL, &error); + + if (!avahiClient) { + g_warning("Failed to create client: %s", + avahi_strerror(error)); + AvahiDeinit(); + } +} + +void +AvahiDeinit(void) +{ + g_debug("Shutting down interface"); + + if (avahiGroup) { + avahi_entry_group_free(avahiGroup); + avahiGroup = NULL; + } + + if (avahiClient) { + avahi_client_free(avahiClient); + avahiClient = NULL; + } + + if (avahi_glib_poll != NULL) { + avahi_glib_poll_free(avahi_glib_poll); + avahi_glib_poll = NULL; + } + + avahi_free(avahiName); + avahiName = NULL; +} diff --git a/src/ZeroconfAvahi.hxx b/src/ZeroconfAvahi.hxx new file mode 100644 index 000000000..2db2523c3 --- /dev/null +++ b/src/ZeroconfAvahi.hxx @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2003-2011 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_ZEROCONF_AVAHI_HXX +#define MPD_ZEROCONF_AVAHI_HXX + +void +AvahiInit(const char *service_name); + +void +AvahiDeinit(); + +#endif diff --git a/src/ZeroconfBonjour.cxx b/src/ZeroconfBonjour.cxx new file mode 100644 index 000000000..929ff6108 --- /dev/null +++ b/src/ZeroconfBonjour.cxx @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "ZeroconfBonjour.hxx" +#include "ZeroconfInternal.hxx" +#include "Listen.hxx" + +#include + +#include + +#undef G_LOG_DOMAIN +#define G_LOG_DOMAIN "bonjour" + +static DNSServiceRef dnsReference; +static GIOChannel *bonjour_channel; + +static void +dnsRegisterCallback(G_GNUC_UNUSED DNSServiceRef sdRef, + G_GNUC_UNUSED DNSServiceFlags flags, + DNSServiceErrorType errorCode, const char *name, + G_GNUC_UNUSED const char *regtype, + G_GNUC_UNUSED const char *domain, + G_GNUC_UNUSED void *context) +{ + if (errorCode != kDNSServiceErr_NoError) { + g_warning("Failed to register zeroconf service."); + + BonjourDeinit(); + } else { + g_debug("Registered zeroconf service with name '%s'", name); + } +} + +static gboolean +bonjour_channel_event(G_GNUC_UNUSED GIOChannel *source, + G_GNUC_UNUSED GIOCondition condition, + G_GNUC_UNUSED gpointer data) +{ + DNSServiceProcessResult(dnsReference); + + return dnsReference != NULL; +} + +void +BonjourInit(const char *service_name) +{ + DNSServiceErrorType error = DNSServiceRegister(&dnsReference, + 0, 0, service_name, + SERVICE_TYPE, NULL, NULL, + g_htons(listen_port), 0, + NULL, + dnsRegisterCallback, + NULL); + + if (error != kDNSServiceErr_NoError) { + g_warning("Failed to register zeroconf service."); + + if (dnsReference) { + DNSServiceRefDeallocate(dnsReference); + dnsReference = NULL; + } + return; + } + + bonjour_channel = g_io_channel_unix_new(DNSServiceRefSockFD(dnsReference)); + g_io_add_watch(bonjour_channel, G_IO_IN, bonjour_channel_event, NULL); +} + +void +BonjourDeinit() +{ + if (bonjour_channel != NULL) { + g_io_channel_unref(bonjour_channel); + bonjour_channel = NULL; + } + + if (dnsReference != NULL) { + DNSServiceRefDeallocate(dnsReference); + dnsReference = NULL; + g_debug("Deregistered Zeroconf service."); + } +} diff --git a/src/ZeroconfBonjour.hxx b/src/ZeroconfBonjour.hxx new file mode 100644 index 000000000..5d2470eb3 --- /dev/null +++ b/src/ZeroconfBonjour.hxx @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_ZEROCONF_BONJOUR_HXX +#define MPD_ZEROCONF_BONJOUR_HXX + +void +BonjourInit(const char *service_name); + +void +BonjourDeinit(); + +#endif diff --git a/src/ZeroconfGlue.cxx b/src/ZeroconfGlue.cxx new file mode 100644 index 000000000..3facd5762 --- /dev/null +++ b/src/ZeroconfGlue.cxx @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2003-2011 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "ZeroconfGlue.hxx" +#include "ZeroconfAvahi.hxx" +#include "ZeroconfBonjour.hxx" +#include "conf.h" +#include "Listen.hxx" + +#include + +/* The default service name to publish + * (overridden by 'zeroconf_name' config parameter) + */ +#define SERVICE_NAME "Music Player" + +#define DEFAULT_ZEROCONF_ENABLED 1 + +static int zeroconfEnabled; + +void +ZeroconfInit() +{ + const char *serviceName; + + zeroconfEnabled = config_get_bool(CONF_ZEROCONF_ENABLED, + DEFAULT_ZEROCONF_ENABLED); + if (!zeroconfEnabled) + return; + + if (listen_port <= 0) { + g_warning("No global port, disabling zeroconf"); + zeroconfEnabled = false; + return; + } + + serviceName = config_get_string(CONF_ZEROCONF_NAME, SERVICE_NAME); + +#ifdef HAVE_AVAHI + AvahiInit(serviceName); +#endif + +#ifdef HAVE_BONJOUR + BonjourInit(serviceName); +#endif +} + +void +ZeroconfDeinit() +{ + if (!zeroconfEnabled) + return; + +#ifdef HAVE_AVAHI + AvahiDeinit(); +#endif /* HAVE_AVAHI */ + +#ifdef HAVE_BONJOUR + BonjourDeinit(); +#endif +} diff --git a/src/ZeroconfGlue.hxx b/src/ZeroconfGlue.hxx new file mode 100644 index 000000000..dcd7b81c0 --- /dev/null +++ b/src/ZeroconfGlue.hxx @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_ZEROCONF_GLUE_HXX +#define MPD_ZEROCONF_GLUE_HXX + +#include "check.h" + +#ifdef HAVE_ZEROCONF + +void +ZeroconfInit(); + +void +ZeroconfDeinit(); + +#else /* ! HAVE_ZEROCONF */ + +static inline void +ZeroconfInit() +{} + +static inline void +ZeroconfDeinit() +{} + +#endif /* ! HAVE_ZEROCONF */ + +#endif diff --git a/src/ZeroconfInternal.hxx b/src/ZeroconfInternal.hxx new file mode 100644 index 000000000..2eadcff6e --- /dev/null +++ b/src/ZeroconfInternal.hxx @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2003-2011 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef ZEROCONF_INTERNAL_H +#define ZEROCONF_INTERNAL_H + +/* The dns-sd service type qualifier to publish */ +#define SERVICE_TYPE "_mpd._tcp" + +#endif diff --git a/src/zeroconf-avahi.c b/src/zeroconf-avahi.c deleted file mode 100644 index d2c6c084c..000000000 --- a/src/zeroconf-avahi.c +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Copyright (C) 2003-2011 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" -#include "zeroconf-internal.h" -#include "Listen.hxx" -#include "mpd_error.h" - -#include - -#include -#include - -#include -#include -#include -#include - -#include - -#undef G_LOG_DOMAIN -#define G_LOG_DOMAIN "avahi" - -static char *avahiName; -static int avahiRunning; -static AvahiGLibPoll *avahi_glib_poll; -static const AvahiPoll *avahi_poll; -static AvahiClient *avahiClient; -static AvahiEntryGroup *avahiGroup; - -static void avahiRegisterService(AvahiClient * c); - -/* Callback when the EntryGroup changes state */ -static void avahiGroupCallback(AvahiEntryGroup * g, - AvahiEntryGroupState state, - G_GNUC_UNUSED void *userdata) -{ - char *n; - assert(g); - - g_debug("Service group changed to state %d", state); - - switch (state) { - case AVAHI_ENTRY_GROUP_ESTABLISHED: - /* The entry group has been established successfully */ - g_message("Service '%s' successfully established.", - avahiName); - break; - - case AVAHI_ENTRY_GROUP_COLLISION: - /* A service name collision happened. Let's pick a new name */ - n = avahi_alternative_service_name(avahiName); - avahi_free(avahiName); - avahiName = n; - - g_message("Service name collision, renaming service to '%s'", - avahiName); - - /* And recreate the services */ - avahiRegisterService(avahi_entry_group_get_client(g)); - break; - - case AVAHI_ENTRY_GROUP_FAILURE: - g_warning("Entry group failure: %s", - avahi_strerror(avahi_client_errno - (avahi_entry_group_get_client(g)))); - /* Some kind of failure happened while we were registering our services */ - avahiRunning = 0; - break; - - case AVAHI_ENTRY_GROUP_UNCOMMITED: - g_debug("Service group is UNCOMMITED"); - break; - case AVAHI_ENTRY_GROUP_REGISTERING: - g_debug("Service group is REGISTERING"); - } -} - -/* Registers a new service with avahi */ -static void avahiRegisterService(AvahiClient * c) -{ - int ret; - assert(c); - g_debug("Registering service %s/%s", SERVICE_TYPE, avahiName); - - /* If this is the first time we're called, - * let's create a new entry group */ - if (!avahiGroup) { - avahiGroup = avahi_entry_group_new(c, avahiGroupCallback, NULL); - if (!avahiGroup) { - g_warning("Failed to create avahi EntryGroup: %s", - avahi_strerror(avahi_client_errno(c))); - goto fail; - } - } - - /* Add the service */ - /* TODO: This currently binds to ALL interfaces. - * We could maybe add a service per actual bound interface, - * if that's better. */ - ret = avahi_entry_group_add_service(avahiGroup, - AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, - 0, avahiName, SERVICE_TYPE, NULL, - NULL, listen_port, NULL); - if (ret < 0) { - g_warning("Failed to add service %s: %s", SERVICE_TYPE, - avahi_strerror(ret)); - goto fail; - } - - /* Tell the server to register the service group */ - ret = avahi_entry_group_commit(avahiGroup); - if (ret < 0) { - g_warning("Failed to commit service group: %s", - avahi_strerror(ret)); - goto fail; - } - return; - -fail: - avahiRunning = 0; -} - -/* Callback when avahi changes state */ -static void avahiClientCallback(AvahiClient * c, AvahiClientState state, - G_GNUC_UNUSED void *userdata) -{ - int reason; - assert(c); - - /* Called whenever the client or server state changes */ - g_debug("Client changed to state %d", state); - - switch (state) { - case AVAHI_CLIENT_S_RUNNING: - g_debug("Client is RUNNING"); - - /* The server has startup successfully and registered its host - * name on the network, so it's time to create our services */ - if (!avahiGroup) - avahiRegisterService(c); - break; - - case AVAHI_CLIENT_FAILURE: - reason = avahi_client_errno(c); - if (reason == AVAHI_ERR_DISCONNECTED) { - g_message("Client Disconnected, will reconnect shortly"); - if (avahiGroup) { - avahi_entry_group_free(avahiGroup); - avahiGroup = NULL; - } - if (avahiClient) - avahi_client_free(avahiClient); - avahiClient = - avahi_client_new(avahi_poll, - AVAHI_CLIENT_NO_FAIL, - avahiClientCallback, NULL, - &reason); - if (!avahiClient) { - g_warning("Could not reconnect: %s", - avahi_strerror(reason)); - avahiRunning = 0; - } - } else { - g_warning("Client failure: %s (terminal)", - avahi_strerror(reason)); - avahiRunning = 0; - } - break; - - case AVAHI_CLIENT_S_COLLISION: - g_debug("Client is COLLISION"); - /* Let's drop our registered services. When the server is back - * in AVAHI_SERVER_RUNNING state we will register them - * again with the new host name. */ - if (avahiGroup) { - g_debug("Resetting group"); - avahi_entry_group_reset(avahiGroup); - } - - case AVAHI_CLIENT_S_REGISTERING: - g_debug("Client is REGISTERING"); - /* The server records are now being established. This - * might be caused by a host name change. We need to wait - * for our own records to register until the host name is - * properly esatblished. */ - - if (avahiGroup) { - g_debug("Resetting group"); - avahi_entry_group_reset(avahiGroup); - } - - break; - - case AVAHI_CLIENT_CONNECTING: - g_debug("Client is CONNECTING"); - } -} - -void init_avahi(const char *serviceName) -{ - int error; - g_debug("Initializing interface"); - - if (!avahi_is_valid_service_name(serviceName)) - MPD_ERROR("Invalid zeroconf_name \"%s\"", serviceName); - - avahiName = avahi_strdup(serviceName); - - avahiRunning = 1; - - avahi_glib_poll = avahi_glib_poll_new(NULL, G_PRIORITY_DEFAULT); - avahi_poll = avahi_glib_poll_get(avahi_glib_poll); - - avahiClient = avahi_client_new(avahi_poll, AVAHI_CLIENT_NO_FAIL, - avahiClientCallback, NULL, &error); - - if (!avahiClient) { - g_warning("Failed to create client: %s", - avahi_strerror(error)); - avahi_finish(); - } -} - -void avahi_finish(void) -{ - g_debug("Shutting down interface"); - - if (avahiGroup) { - avahi_entry_group_free(avahiGroup); - avahiGroup = NULL; - } - - if (avahiClient) { - avahi_client_free(avahiClient); - avahiClient = NULL; - } - - if (avahi_glib_poll != NULL) { - avahi_glib_poll_free(avahi_glib_poll); - avahi_glib_poll = NULL; - } - - avahi_free(avahiName); - avahiName = NULL; -} diff --git a/src/zeroconf-bonjour.c b/src/zeroconf-bonjour.c deleted file mode 100644 index f3776ca29..000000000 --- a/src/zeroconf-bonjour.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2003-2011 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" -#include "zeroconf-internal.h" -#include "Listen.hxx" - -#include - -#include - -#undef G_LOG_DOMAIN -#define G_LOG_DOMAIN "bonjour" - -static DNSServiceRef dnsReference; -static GIOChannel *bonjour_channel; - -static void -dnsRegisterCallback(G_GNUC_UNUSED DNSServiceRef sdRef, - G_GNUC_UNUSED DNSServiceFlags flags, - DNSServiceErrorType errorCode, const char *name, - G_GNUC_UNUSED const char *regtype, - G_GNUC_UNUSED const char *domain, - G_GNUC_UNUSED void *context) -{ - if (errorCode != kDNSServiceErr_NoError) { - g_warning("Failed to register zeroconf service."); - - bonjour_finish(); - } else { - g_debug("Registered zeroconf service with name '%s'", name); - } -} - -static gboolean -bonjour_channel_event(G_GNUC_UNUSED GIOChannel *source, - G_GNUC_UNUSED GIOCondition condition, - G_GNUC_UNUSED gpointer data) -{ - DNSServiceProcessResult(dnsReference); - - return dnsReference != NULL; -} - -void init_zeroconf_osx(const char *serviceName) -{ - DNSServiceErrorType error = DNSServiceRegister(&dnsReference, - 0, 0, serviceName, - SERVICE_TYPE, NULL, NULL, - g_htons(listen_port), 0, - NULL, - dnsRegisterCallback, - NULL); - - if (error != kDNSServiceErr_NoError) { - g_warning("Failed to register zeroconf service."); - - if (dnsReference) { - DNSServiceRefDeallocate(dnsReference); - dnsReference = NULL; - } - return; - } - - bonjour_channel = g_io_channel_unix_new(DNSServiceRefSockFD(dnsReference)); - g_io_add_watch(bonjour_channel, G_IO_IN, bonjour_channel_event, NULL); -} - -void bonjour_finish(void) -{ - if (bonjour_channel != NULL) { - g_io_channel_unref(bonjour_channel); - bonjour_channel = NULL; - } - - if (dnsReference != NULL) { - DNSServiceRefDeallocate(dnsReference); - dnsReference = NULL; - g_debug("Deregistered Zeroconf service."); - } -} diff --git a/src/zeroconf-internal.h b/src/zeroconf-internal.h deleted file mode 100644 index 983e5c556..000000000 --- a/src/zeroconf-internal.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2003-2011 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef ZEROCONF_INTERNAL_H -#define ZEROCONF_INTERNAL_H - -/* The dns-sd service type qualifier to publish */ -#define SERVICE_TYPE "_mpd._tcp" - -void init_avahi(const char *service_name); - -void avahi_finish(void); - -void init_zeroconf_osx(const char *service_name); - -void bonjour_finish(void); - -#endif diff --git a/src/zeroconf.c b/src/zeroconf.c deleted file mode 100644 index a4611b67e..000000000 --- a/src/zeroconf.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2003-2011 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" -#include "zeroconf.h" -#include "zeroconf-internal.h" -#include "conf.h" -#include "Listen.hxx" - -#include - -/* The default service name to publish - * (overridden by 'zeroconf_name' config parameter) - */ -#define SERVICE_NAME "Music Player" - -#define DEFAULT_ZEROCONF_ENABLED 1 - -static int zeroconfEnabled; - -void initZeroconf(void) -{ - const char *serviceName; - - zeroconfEnabled = config_get_bool(CONF_ZEROCONF_ENABLED, - DEFAULT_ZEROCONF_ENABLED); - if (!zeroconfEnabled) - return; - - if (listen_port <= 0) { - g_warning("No global port, disabling zeroconf"); - zeroconfEnabled = false; - return; - } - - serviceName = config_get_string(CONF_ZEROCONF_NAME, SERVICE_NAME); - -#ifdef HAVE_AVAHI - init_avahi(serviceName); -#endif - -#ifdef HAVE_BONJOUR - init_zeroconf_osx(serviceName); -#endif -} - -void finishZeroconf(void) -{ - if (!zeroconfEnabled) - return; - -#ifdef HAVE_AVAHI - avahi_finish(); -#endif /* HAVE_AVAHI */ - -#ifdef HAVE_BONJOUR - bonjour_finish(); -#endif -} diff --git a/src/zeroconf.h b/src/zeroconf.h deleted file mode 100644 index 8e33a3d89..000000000 --- a/src/zeroconf.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2003-2011 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPD_ZEROCONF_H -#define MPD_ZEROCONF_H - -#include "check.h" - -#ifdef HAVE_ZEROCONF - -void initZeroconf(void); -void finishZeroconf(void); - -#else /* ! HAVE_ZEROCONF */ - -static void initZeroconf(void) { } -static void finishZeroconf(void) { } - -#endif /* ! HAVE_ZEROCONF */ - -#endif -- cgit v1.2.3