]> git.meshlink.io Git - catta/blob - avahi-core/subscribe.c
rename libavahi-core to avahi-core
[catta] / avahi-core / subscribe.c
1 /* $Id$ */
2
3 /***
4   This file is part of avahi.
5  
6   avahi is free software; you can redistribute it and/or modify it
7   under the terms of the GNU Lesser General Public License as
8   published by the Free Software Foundation; either version 2.1 of the
9   License, or (at your option) any later version.
10  
11   avahi is distributed in the hope that it will be useful, but WITHOUT
12   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13   or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
14   Public License for more details.
15  
16   You should have received a copy of the GNU Lesser General Public
17   License along with avahi; if not, write to the Free Software
18   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19   USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include "subscribe.h"
27 #include "util.h"
28
29 static void elapse(AvahiTimeEvent *e, void *userdata) {
30     AvahiSubscription *s = userdata;
31     GTimeVal tv;
32     gchar *t;
33     
34     g_assert(s);
35
36     avahi_server_post_query(s->server, s->interface, s->protocol, s->key);
37
38     if (s->n_query++ <= 8)
39         s->sec_delay *= 2;
40
41     g_message("%i. Continuous querying for %s", s->n_query, t = avahi_key_to_string(s->key));
42     g_free(t);
43     
44     avahi_elapse_time(&tv, s->sec_delay*1000, 0);
45     avahi_time_event_queue_update(s->server->time_event_queue, s->time_event, &tv);
46 }
47
48 struct cbdata {
49     AvahiSubscription *subscription;
50     AvahiInterface *interface;
51 };
52
53 static gpointer scan_cache_callback(AvahiCache *c, AvahiKey *pattern, AvahiCacheEntry *e, gpointer userdata) {
54     struct cbdata *cbdata = userdata;
55
56     g_assert(c);
57     g_assert(pattern);
58     g_assert(e);
59     g_assert(cbdata);
60
61     cbdata->subscription->callback(
62         cbdata->subscription,
63         e->record,
64         cbdata->interface->hardware->index,
65         cbdata->interface->protocol,
66         AVAHI_SUBSCRIPTION_NEW,
67         cbdata->subscription->userdata);
68
69     return NULL;
70 }
71
72 static void scan_interface_callback(AvahiInterfaceMonitor *m, AvahiInterface *i, gpointer userdata) {
73     AvahiSubscription *s = userdata;
74     struct cbdata cbdata = { s, i };
75
76     g_assert(m);
77     g_assert(i);
78     g_assert(s);
79
80     avahi_cache_walk(i->cache, s->key, scan_cache_callback, &cbdata);
81 }
82
83 AvahiSubscription *avahi_subscription_new(AvahiServer *server, AvahiKey *key, gint interface, guchar protocol, AvahiSubscriptionCallback callback, gpointer userdata) {
84     AvahiSubscription *s, *t;
85     GTimeVal tv;
86
87     g_assert(server);
88     g_assert(key);
89     g_assert(callback);
90
91     g_assert(!avahi_key_is_pattern(key));
92     
93     s = g_new(AvahiSubscription, 1);
94     s->server = server;
95     s->key = avahi_key_ref(key);
96     s->interface = interface;
97     s->protocol = protocol;
98     s->callback = callback;
99     s->userdata = userdata;
100     s->n_query = 1;
101     s->sec_delay = 1;
102
103     avahi_server_post_query(s->server, s->interface, s->protocol, s->key);
104     
105     avahi_elapse_time(&tv, s->sec_delay*1000, 0);
106     s->time_event = avahi_time_event_queue_add(server->time_event_queue, &tv, elapse, s);
107
108     AVAHI_LLIST_PREPEND(AvahiSubscription, subscriptions, server->subscriptions, s);
109
110     /* Add the new entry to the subscription hash table */
111     t = g_hash_table_lookup(server->subscription_hashtable, key);
112     AVAHI_LLIST_PREPEND(AvahiSubscription, by_key, t, s);
113     g_hash_table_replace(server->subscription_hashtable, key, t);
114
115     /* Scan the caches */
116     avahi_interface_monitor_walk(s->server->monitor, s->interface, s->protocol, scan_interface_callback, s);
117     
118     return s;
119 }
120
121 void avahi_subscription_free(AvahiSubscription *s) {
122     AvahiSubscription *t;
123     
124     g_assert(s);
125
126     AVAHI_LLIST_REMOVE(AvahiSubscription, subscriptions, s->server->subscriptions, s);
127
128     t = g_hash_table_lookup(s->server->subscription_hashtable, s->key);
129     AVAHI_LLIST_REMOVE(AvahiSubscription, by_key, t, s);
130     if (t)
131         g_hash_table_replace(s->server->subscription_hashtable, t->key, t);
132     else
133         g_hash_table_remove(s->server->subscription_hashtable, s->key);
134     
135     avahi_time_event_queue_remove(s->server->time_event_queue, s->time_event);
136     avahi_key_unref(s->key);
137
138     
139     g_free(s);
140 }
141
142 void avahi_subscription_notify(AvahiServer *server, AvahiInterface *i, AvahiRecord *record, AvahiSubscriptionEvent event) {
143     AvahiSubscription *s;
144     
145     g_assert(server);
146     g_assert(record);
147
148     for (s = g_hash_table_lookup(server->subscription_hashtable, record->key); s; s = s->by_key_next)
149         if (avahi_interface_match(i, s->interface, s->protocol))
150             s->callback(s, record, i->hardware->index, i->protocol, event, s->userdata);
151 }
152
153 gboolean avahi_is_subscribed(AvahiServer *server, AvahiKey *k) {
154     g_assert(server);
155     g_assert(k);
156
157     return !!g_hash_table_lookup(server->subscription_hashtable, k);
158 }