1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
3
* Copyright (C) 2005 Charles Schmidt <cschmidt2@emich.edu>
4
* Copyright (C) 2006 William Jon McCann <mccann@jhu.edu>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
28
#include <glib/gi18n.h>
29
#include <glib-object.h>
32
#include <avahi-client/lookup.h>
33
#include <avahi-client/publish.h>
35
#include <avahi-client/client.h>
36
#include <avahi-common/error.h>
37
#include <avahi-glib/glib-malloc.h>
38
#include <avahi-glib/glib-watch.h>
40
#include "rb-daap-mdns-publisher.h"
43
static void rb_daap_mdns_publisher_class_init (RBDaapMdnsPublisherClass *klass);
44
static void rb_daap_mdns_publisher_init (RBDaapMdnsPublisher *publisher);
45
static void rb_daap_mdns_publisher_finalize (GObject *object);
47
#define RB_DAAP_MDNS_PUBLISHER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), RB_TYPE_DAAP_MDNS_PUBLISHER, RBDaapMdnsPublisherPrivate))
49
struct RBDaapMdnsPublisherPrivate
53
AvahiEntryGroup *entry_group;
57
gboolean password_required;
70
static guint signals [LAST_SIGNAL] = { 0, };
72
G_DEFINE_TYPE (RBDaapMdnsPublisher, rb_daap_mdns_publisher, G_TYPE_OBJECT)
74
static gpointer publisher_object = NULL;
77
rb_daap_mdns_publisher_error_quark (void)
79
static GQuark quark = 0;
81
quark = g_quark_from_static_string ("rb_daap_mdns_publisher_error");
87
client_cb (AvahiClient *client,
88
AvahiClientState state,
89
RBDaapMdnsPublisher *publisher)
92
* check to make sure we're in the _RUNNING state before we publish
93
* check for COLLISION state and remove published information
96
/* Called whenever the client or server state changes */
99
case AVAHI_CLIENT_S_RUNNING:
101
/* The server has startup successfully and registered its host
102
* name on the network, so it's time to create our services */
106
case AVAHI_CLIENT_S_COLLISION:
108
/* Let's drop our registered services. When the server is back
109
* in AVAHI_SERVER_RUNNING state we will register them
110
* again with the new host name. */
111
if (publisher->priv->entry_group) {
112
avahi_entry_group_reset (publisher->priv->entry_group);
116
#ifdef HAVE_AVAHI_0_6
117
case AVAHI_CLIENT_FAILURE:
119
g_warning ("Client failure: %s\n", avahi_strerror (avahi_client_errno (client)));
121
case AVAHI_CLIENT_CONNECTING:
122
case AVAHI_CLIENT_S_REGISTERING:
130
avahi_client_init (RBDaapMdnsPublisher *publisher)
134
avahi_set_allocator (avahi_glib_allocator ());
136
publisher->priv->poll = avahi_glib_poll_new (NULL, G_PRIORITY_DEFAULT);
138
if (! publisher->priv->poll) {
139
rb_debug ("Unable to create AvahiGlibPoll object for mDNS");
142
#ifdef HAVE_AVAHI_0_5
143
publisher->priv->client = avahi_client_new (avahi_glib_poll_get (publisher->priv->poll),
144
(AvahiClientCallback) client_cb,
148
#ifdef HAVE_AVAHI_0_6
150
AvahiClientFlags flags;
153
publisher->priv->client = avahi_client_new (avahi_glib_poll_get (publisher->priv->poll),
155
(AvahiClientCallback)client_cb,
163
entry_group_cb (AvahiEntryGroup *group,
164
AvahiEntryGroupState state,
165
RBDaapMdnsPublisher *publisher)
167
if (state == AVAHI_ENTRY_GROUP_ESTABLISHED) {
169
g_signal_emit (publisher, signals [PUBLISHED], 0, publisher->priv->name);
171
} else if (state == AVAHI_ENTRY_GROUP_COLLISION) {
172
g_warning ("MDNS name collision");
174
g_signal_emit (publisher, signals [NAME_COLLISION], 0, publisher->priv->name);
179
create_service (RBDaapMdnsPublisher *publisher,
183
const char *txt_record;
185
if (publisher->priv->entry_group == NULL) {
186
publisher->priv->entry_group = avahi_entry_group_new (publisher->priv->client,
187
(AvahiEntryGroupCallback)entry_group_cb,
190
avahi_entry_group_reset (publisher->priv->entry_group);
193
if (publisher->priv->entry_group == NULL) {
194
rb_debug ("Could not create AvahiEntryGroup for publishing");
196
RB_DAAP_MDNS_PUBLISHER_ERROR,
197
RB_DAAP_MDNS_PUBLISHER_ERROR_FAILED,
199
_("Could not create AvahiEntryGroup for publishing"));
204
g_message ("Service name:%s port:%u password:%d",
205
publisher->priv->name,
206
publisher->priv->port,
207
publisher->priv->password_required);
210
if (publisher->priv->password_required) {
211
txt_record = "Password=true";
213
txt_record = "Password=false";
216
ret = avahi_entry_group_add_service (publisher->priv->entry_group,
219
#ifdef HAVE_AVAHI_0_6
222
publisher->priv->name,
226
publisher->priv->port,
232
RB_DAAP_MDNS_PUBLISHER_ERROR,
233
RB_DAAP_MDNS_PUBLISHER_ERROR_FAILED,
235
_("Could not add service"),
236
avahi_strerror (ret));
240
ret = avahi_entry_group_commit (publisher->priv->entry_group);
244
RB_DAAP_MDNS_PUBLISHER_ERROR,
245
RB_DAAP_MDNS_PUBLISHER_ERROR_FAILED,
247
_("Could not commit service"),
248
avahi_strerror (ret));
256
refresh_service (RBDaapMdnsPublisher *publisher,
259
return create_service (publisher, error);
263
publisher_set_name_internal (RBDaapMdnsPublisher *publisher,
267
g_free (publisher->priv->name);
268
publisher->priv->name = g_strdup (name);
274
rb_daap_mdns_publisher_set_name (RBDaapMdnsPublisher *publisher,
278
g_return_val_if_fail (publisher != NULL, FALSE);
280
publisher_set_name_internal (publisher, name, error);
282
if (publisher->priv->entry_group) {
283
refresh_service (publisher, error);
290
publisher_set_port_internal (RBDaapMdnsPublisher *publisher,
294
publisher->priv->port = port;
300
rb_daap_mdns_publisher_set_port (RBDaapMdnsPublisher *publisher,
304
g_return_val_if_fail (publisher != NULL, FALSE);
306
publisher_set_port_internal (publisher, port, error);
308
if (publisher->priv->entry_group) {
309
refresh_service (publisher, error);
316
publisher_set_password_required_internal (RBDaapMdnsPublisher *publisher,
320
publisher->priv->password_required = required;
325
rb_daap_mdns_publisher_set_password_required (RBDaapMdnsPublisher *publisher,
329
g_return_val_if_fail (publisher != NULL, FALSE);
331
publisher_set_password_required_internal (publisher, required, error);
333
if (publisher->priv->entry_group) {
334
refresh_service (publisher, error);
341
rb_daap_mdns_publisher_publish (RBDaapMdnsPublisher *publisher,
344
gboolean password_required,
347
if (publisher->priv->client == NULL) {
349
RB_DAAP_MDNS_PUBLISHER_ERROR,
350
RB_DAAP_MDNS_PUBLISHER_ERROR_NOT_RUNNING,
352
_("The avahi MDNS service is not running"));
356
publisher_set_name_internal (publisher, name, NULL);
357
publisher_set_port_internal (publisher, port, NULL);
358
publisher_set_password_required_internal (publisher, password_required, NULL);
360
return create_service (publisher, error);
364
rb_daap_mdns_publisher_withdraw (RBDaapMdnsPublisher *publisher,
367
if (publisher->priv->client == NULL) {
369
RB_DAAP_MDNS_PUBLISHER_ERROR,
370
RB_DAAP_MDNS_PUBLISHER_ERROR_NOT_RUNNING,
372
_("The avahi MDNS service is not running"));
376
if (publisher->priv->entry_group == NULL) {
378
RB_DAAP_MDNS_PUBLISHER_ERROR,
379
RB_DAAP_MDNS_PUBLISHER_ERROR_FAILED,
381
_("The MDNS service is not published"));
385
avahi_entry_group_reset (publisher->priv->entry_group);
386
avahi_entry_group_free (publisher->priv->entry_group);
387
publisher->priv->entry_group = NULL;
393
rb_daap_mdns_publisher_set_property (GObject *object,
400
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
406
rb_daap_mdns_publisher_get_property (GObject *object,
413
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
419
rb_daap_mdns_publisher_class_init (RBDaapMdnsPublisherClass *klass)
421
GObjectClass *object_class = G_OBJECT_CLASS (klass);
423
object_class->finalize = rb_daap_mdns_publisher_finalize;
424
object_class->get_property = rb_daap_mdns_publisher_get_property;
425
object_class->set_property = rb_daap_mdns_publisher_set_property;
427
signals [PUBLISHED] =
428
g_signal_new ("published",
429
G_TYPE_FROM_CLASS (object_class),
431
G_STRUCT_OFFSET (RBDaapMdnsPublisherClass, published),
434
g_cclosure_marshal_VOID__STRING,
437
signals [NAME_COLLISION] =
438
g_signal_new ("name-collision",
439
G_TYPE_FROM_CLASS (object_class),
441
G_STRUCT_OFFSET (RBDaapMdnsPublisherClass, name_collision),
444
g_cclosure_marshal_VOID__STRING,
448
g_type_class_add_private (klass, sizeof (RBDaapMdnsPublisherPrivate));
452
rb_daap_mdns_publisher_init (RBDaapMdnsPublisher *publisher)
454
publisher->priv = RB_DAAP_MDNS_PUBLISHER_GET_PRIVATE (publisher);
456
avahi_client_init (publisher);
460
rb_daap_mdns_publisher_finalize (GObject *object)
462
RBDaapMdnsPublisher *publisher;
464
g_return_if_fail (object != NULL);
465
g_return_if_fail (RB_IS_DAAP_MDNS_PUBLISHER (object));
467
publisher = RB_DAAP_MDNS_PUBLISHER (object);
469
g_return_if_fail (publisher->priv != NULL);
471
if (publisher->priv->entry_group) {
472
avahi_entry_group_free (publisher->priv->entry_group);
475
if (publisher->priv->client) {
476
avahi_client_free (publisher->priv->client);
479
if (publisher->priv->poll) {
480
avahi_glib_poll_free (publisher->priv->poll);
483
g_free (publisher->priv->name);
485
G_OBJECT_CLASS (rb_daap_mdns_publisher_parent_class)->finalize (object);
488
RBDaapMdnsPublisher *
489
rb_daap_mdns_publisher_new (void)
491
if (publisher_object) {
492
g_object_ref (publisher_object);
494
publisher_object = g_object_new (RB_TYPE_DAAP_MDNS_PUBLISHER, NULL);
495
g_object_add_weak_pointer (publisher_object,
496
(gpointer *) &publisher_object);
499
return RB_DAAP_MDNS_PUBLISHER (publisher_object);