2
* @file avahi_publisher.c cache synchronization using AVAHI
4
* Copyright (C) 2007 Lars Lindner <lars.lindner@gmail.com>
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
#include "sync/avahi_publisher.h"
25
#include <glib/gi18n.h>
26
#include <glib-object.h>
28
#include <avahi-client/lookup.h>
29
#include <avahi-client/publish.h>
30
#include <avahi-client/client.h>
31
#include <avahi-common/error.h>
32
#include <avahi-glib/glib-malloc.h>
33
#include <avahi-glib/glib-watch.h>
35
static void liferea_avahi_publisher_class_init (LifereaAvahiPublisherClass *klass);
36
static void liferea_avahi_publisher_init (LifereaAvahiPublisher *publisher);
37
static void liferea_avahi_publisher_finalize (GObject *object);
39
#define LIFEREA_AVAHI_PUBLISHER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), LIFEREA_AVAHI_PUBLISHER_TYPE, LifereaAvahiPublisherPrivate))
41
struct LifereaAvahiPublisherPrivate {
44
AvahiEntryGroup *entry_group;
60
static guint signals [LAST_SIGNAL] = { 0, };
61
static GObjectClass *parent_class = NULL;
63
static gpointer liferea_avahi_publisher = NULL;
66
liferea_avahi_publisher_error_quark (void)
68
static GQuark quark = 0;
70
quark = g_quark_from_static_string ("liferea_avahi_publisher_error");
76
client_cb (AvahiClient *client,
77
AvahiClientState state,
78
LifereaAvahiPublisher *publisher)
81
* check to make sure we're in the _RUNNING state before we publish
82
* check for COLLISION state and remove published information
85
/* Called whenever the client or server state changes */
88
case AVAHI_CLIENT_S_RUNNING:
90
/* The server has startup successfully and registered its host
91
* name on the network, so it's time to create our services */
95
case AVAHI_CLIENT_S_COLLISION:
97
/* Let's drop our registered services. When the server is back
98
* in AVAHI_SERVER_RUNNING state we will register them
99
* again with the new host name. */
100
if (publisher->priv->entry_group) {
101
avahi_entry_group_reset (publisher->priv->entry_group);
105
case AVAHI_CLIENT_FAILURE:
107
g_warning ("Client failure: %s\n", avahi_strerror (avahi_client_errno (client)));
109
case AVAHI_CLIENT_CONNECTING:
110
case AVAHI_CLIENT_S_REGISTERING:
117
avahi_client_init (LifereaAvahiPublisher *publisher)
121
avahi_set_allocator (avahi_glib_allocator ());
123
publisher->priv->poll = avahi_glib_poll_new (NULL, G_PRIORITY_DEFAULT);
125
if (! publisher->priv->poll) {
126
g_warning ("Unable to create AvahiGlibPoll object for mDNS");
129
AvahiClientFlags flags;
132
publisher->priv->client = avahi_client_new (avahi_glib_poll_get (publisher->priv->poll),
134
(AvahiClientCallback)client_cb,
140
entry_group_cb (AvahiEntryGroup *group,
141
AvahiEntryGroupState state,
142
LifereaAvahiPublisher *publisher)
144
if (state == AVAHI_ENTRY_GROUP_ESTABLISHED) {
146
g_signal_emit (publisher, signals [PUBLISHED], 0, publisher->priv->name);
148
} else if (state == AVAHI_ENTRY_GROUP_COLLISION) {
149
g_warning ("MDNS name collision");
151
g_signal_emit (publisher, signals [NAME_COLLISION], 0, publisher->priv->name);
156
create_service (LifereaAvahiPublisher *publisher)
160
if (publisher->priv->entry_group == NULL) {
161
publisher->priv->entry_group = avahi_entry_group_new (publisher->priv->client,
162
(AvahiEntryGroupCallback)entry_group_cb,
165
avahi_entry_group_reset (publisher->priv->entry_group);
168
if (publisher->priv->entry_group == NULL) {
169
g_warning ("Could not create AvahiEntryGroup for publishing");
173
ret = avahi_entry_group_add_service (publisher->priv->entry_group,
177
publisher->priv->name,
181
publisher->priv->port,
182
"Password=false" /* txt_record */,
186
g_warning ("Could not add service: %s", avahi_strerror (ret));
190
ret = avahi_entry_group_commit (publisher->priv->entry_group);
193
g_warning ("Could not commit service: %s", avahi_strerror (ret));
201
liferea_avahi_publisher_publish (LifereaAvahiPublisher *publisher,
205
if (publisher->priv->client == NULL) {
206
g_warning ("The avahi MDNS service is not running") ;
210
publisher->priv->port = port;
211
publisher->priv->name = name;
213
return create_service (publisher);
217
liferea_avahi_publisher_get_type (void)
219
static GType type = 0;
221
if (G_UNLIKELY (type == 0))
223
static const GTypeInfo our_info =
225
sizeof (LifereaAvahiPublisherClass),
226
NULL, /* base_init */
227
NULL, /* base_finalize */
228
(GClassInitFunc) liferea_avahi_publisher_class_init,
230
NULL, /* class_data */
231
sizeof (LifereaAvahiPublisher),
233
(GInstanceInitFunc) liferea_avahi_publisher_init
236
type = g_type_register_static (G_TYPE_OBJECT,
237
"LifereaAvahiPublisher",
245
liferea_avahi_publisher_class_init (LifereaAvahiPublisherClass *klass)
247
GObjectClass *object_class = G_OBJECT_CLASS (klass);
249
parent_class = g_type_class_peek_parent (klass);
251
object_class->finalize = liferea_avahi_publisher_finalize;
253
g_type_class_add_private (object_class, sizeof(LifereaAvahiPublisherPrivate));
257
liferea_avahi_publisher_init (LifereaAvahiPublisher *publisher)
259
publisher->priv = LIFEREA_AVAHI_PUBLISHER_GET_PRIVATE (publisher);
261
avahi_client_init (publisher);
265
liferea_avahi_publisher_finalize (GObject *object)
267
LifereaAvahiPublisher *publisher;
269
publisher = LIFEREA_AVAHI_PUBLISHER (object);
271
g_return_if_fail (publisher->priv != NULL);
273
if (publisher->priv->entry_group)
274
avahi_entry_group_free (publisher->priv->entry_group);
276
if (publisher->priv->client)
277
avahi_client_free (publisher->priv->client);
279
if (publisher->priv->poll)
280
avahi_glib_poll_free (publisher->priv->poll);
282
g_free (publisher->priv->name);
284
G_OBJECT_CLASS (parent_class)->finalize (object);
287
LifereaAvahiPublisher *
288
liferea_avahi_publisher_new (void)
292
/* check service name preference and set default if necessary */
293
serviceName = conf_get_str_value (SYNC_AVAHI_SERVICE_NAME);
294
if (g_str_equal (serviceName, "")) {
295
g_free (serviceName);
296
serviceName = g_strdup_printf (_("Liferea Sync %s@%s"), g_get_user_name(), g_get_host_name ());
297
conf_set_str_value (SYNC_AVAHI_SERVICE_NAME, serviceName);
299
g_free (serviceName);
301
if (liferea_avahi_publisher) {
302
g_object_ref (liferea_avahi_publisher);
304
liferea_avahi_publisher = g_object_new (LIFEREA_AVAHI_PUBLISHER_TYPE, NULL);
305
g_object_add_weak_pointer (liferea_avahi_publisher, (gpointer *) &liferea_avahi_publisher);
308
return liferea_avahi_publisher;