From 037e989c3e618bef8120ba2df3a22abc57f9eaf8 Mon Sep 17 00:00:00 2001 From: Javier Date: Sat, 10 Mar 2018 17:44:47 +0100 Subject: drop udisks dependency (instead use gio volume monitor) --- mdns.c | 186 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 mdns.c (limited to 'mdns.c') diff --git a/mdns.c b/mdns.c new file mode 100644 index 0000000..b4def8d --- /dev/null +++ b/mdns.c @@ -0,0 +1,186 @@ +#include "rodisc.h" + +#include +#include + +static GaClient *mdns_client; +static GaEntryGroup *mdns_group; +static GaEntryGroupService *mdns_service; + +static guint disc_change_count = 0; + +static void mdns_service_freeze() +{ + g_return_if_fail(mdns_service); + ga_entry_group_service_freeze(mdns_service); +} + +static void mdns_service_thaw() +{ + GError *error = NULL; + g_return_if_fail(mdns_service); + if (!ga_entry_group_service_thaw(mdns_service, &error)) { + g_warning("Could not update service TXT entries: %s", error->message); + g_error_free(error); + } +} + +static void mdns_service_update() +{ + GError *error = NULL; + + g_return_if_fail(mdns_service); + + // "sys=waMA=00:00:00:00:00:00,adVF=0x4,adDT=0x2,adCC=0" + // waMA = MAC address + // adVF = Volume flags (0x200 "ask me first") + // adDT = Supported media? + // adCC = Disc change count? + + guint flags = 0; + guint media = 2; + gchar *record = + g_strdup_printf("waMA=00:00:00:00:00:00,adVF=0x%x,adDT=0x%x,adCC=%u", + flags, media, disc_change_count); + + if (!ga_entry_group_service_set(mdns_service, "sys", record, &error)) + { + g_warning("Could not update main TXT record: %s", error->message); + g_error_free(error); + } + + g_free(record); +} + +static void mdns_service_update_disc(RODisc *disc) +{ + GError *error = NULL; + + g_return_if_fail(mdns_service); + + // "CdRom0=adVN=DiscLabel,adVT=public.cd-media" + gchar *record = g_strdup_printf("adVN=%s,adVT=%s", disc->label, disc->type); + + const gchar *uri_basename = &disc->uri[1]; // Skip first '/' + if (!ga_entry_group_service_set(mdns_service, uri_basename, record, &error)) + { + g_warning("Could not update TXT record for disc at '%s': %s", + disc->uri, error->message); + g_error_free(error); + } + + g_free(record); +} + +static void mdns_service_remove_disc(RODisc *disc) +{ + GError *error = NULL; + g_return_if_fail(mdns_service); + const gchar *uri_basename = &disc->uri[1]; + if (!ga_entry_group_service_remove_key(mdns_service, uri_basename, &error)) { + g_warning("Could not update TXT record for disc at '%s': %s", + disc->uri, error->message); + g_error_free(error); + } +} + +static void mdns_register_service() +{ + GError * error = NULL; + if (!mdns_group) { + mdns_group = ga_entry_group_new(); + + if (!ga_entry_group_attach(mdns_group, mdns_client, &error)) { + g_warning("Could not attach MDNS group to client: %s", error->message); + g_error_free(error); + return; + } + } + + const gchar *name = avahi_client_get_host_name(mdns_client->avahi_client); + const unsigned int port = server_get_port(); + mdns_service = ga_entry_group_add_service(mdns_group, + name, RODISC_MDNS_SERVICE, + port, &error, + NULL); + if (!mdns_service) { + g_warning("Could not create service: %s", error->message); + g_error_free(error); + return; + } + + // Create TXT records, disc records, etc. + mdns_service_update(); + rodisc_refresh_all(); + + if (!ga_entry_group_commit(mdns_group, &error)) { + g_warning("Could not announce MDNS service: %s", error->message); + g_error_free(error); + return; + } +} + +static void mdns_client_state_changed_cb(GaClient *client, GaClientState state, gpointer user_data) +{ + switch (state) { + case GA_CLIENT_STATE_FAILURE: + g_warning("MDNS client state failure"); + break; + case GA_CLIENT_STATE_S_RUNNING: + g_debug("MDNS client found server running"); + mdns_register_service(); + break; + case GA_CLIENT_STATE_S_COLLISION: + case GA_CLIENT_STATE_S_REGISTERING: + g_message("MDNS collision"); + if (mdns_group) { + ga_entry_group_reset(mdns_group, NULL); + mdns_service = 0; + } + break; + default: + // Do nothing + break; + } +} + +bool mdns_start() +{ + GError *error = NULL; + + mdns_client = ga_client_new(GA_CLIENT_FLAG_NO_FLAGS); + + g_signal_connect(mdns_client, "state-changed", + G_CALLBACK(mdns_client_state_changed_cb), NULL); + + if (!ga_client_start(mdns_client, &error)) { + g_printerr("Could not start MDNS client: %s\n", error->message); + g_error_free(error); + return false; + } + + return true; +} + +void mdns_stop() +{ + g_object_unref(mdns_client); +} + +void mdns_publish(RODisc *disc) +{ + mdns_service_freeze(); + disc_change_count++; + mdns_service_update_disc(disc); + mdns_service_update(); + mdns_service_thaw(); +} + +void mdns_unpublish(RODisc *disc) +{ + mdns_service_freeze(); + disc_change_count++; + mdns_service_remove_disc(disc); + mdns_service_update(); + mdns_service_thaw(); +} -- cgit v1.2.3