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
);