]> git.meshlink.io Git - catta/blob - avahi-client/client.c
* Remove most of the debug printf()s from avahi-client code and make sure errors...
[catta] / avahi-client / client.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 <avahi-client/client.h>
27 #include <avahi-common/dbus.h>
28 #include <avahi-common/llist.h>
29 #include <avahi-common/error.h>
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33
34 #define DBUS_API_SUBJECT_TO_CHANGE
35 #include <dbus/dbus.h>
36 #include <dbus/dbus-glib-lowlevel.h>
37
38 #include <stdlib.h>
39
40 #include "client.h"
41 #include "internal.h"
42
43 int
44 avahi_client_set_errno (AvahiClient *client, int error)
45 {
46     if (client == NULL) return error;
47
48     client->error = error;
49
50     return error;
51 }
52     
53 static
54 void avahi_client_state_change (AvahiClient *client, int state)
55 {
56     if (client == NULL || client->callback == NULL) 
57         return;
58
59     client->callback (client, state, client->user_data);
60 }
61
62 void
63 avahi_client_state_request_callback (DBusPendingCall *call, void *data)
64 {
65     AvahiClient *client = data;
66     DBusError error;
67     DBusMessage *reply;
68     int state, type;
69
70     dbus_error_init (&error);
71
72     reply = dbus_pending_call_steal_reply (call);
73
74     type = dbus_message_get_type (reply);
75
76     if (type == DBUS_MESSAGE_TYPE_METHOD_RETURN)
77     {
78         dbus_message_get_args (reply, &error, DBUS_TYPE_INT32, &state, DBUS_TYPE_INVALID);
79         
80         if (dbus_error_is_set (&error))
81             return;
82         
83         avahi_client_state_change (client, state);
84     } else if (type == DBUS_MESSAGE_TYPE_ERROR) {
85         dbus_set_error_from_message (&error, reply);
86     }
87
88     dbus_pending_call_unref (call);
89 }
90
91 void
92 avahi_client_schedule_state_request (AvahiClient *client)
93 {
94     DBusMessage *message;
95     DBusPendingCall *pcall;
96
97     if (client == NULL) return;
98
99     message = dbus_message_new_method_call (AVAHI_DBUS_NAME, AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "GetState");
100
101     dbus_connection_send_with_reply (client->bus, message, &pcall, -1);
102
103     dbus_pending_call_set_notify (pcall, avahi_client_state_request_callback, client, NULL);
104 }
105
106 static DBusHandlerResult
107 filter_func (DBusConnection *bus, DBusMessage *message, void *data)
108 {
109     AvahiClient *client = data;
110     DBusError error;
111     
112     printf ("dbus: interface=%s, path=%s, member=%s\n",
113             dbus_message_get_interface (message),
114             dbus_message_get_path (message),
115             dbus_message_get_member (message));
116
117     dbus_error_init (&error);
118
119     if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
120         gchar *name, *old, *new;
121         dbus_message_get_args(message, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &old, DBUS_TYPE_STRING, &new, DBUS_TYPE_INVALID);
122         
123         if (dbus_error_is_set (&error)) {
124             dbus_error_free (&error);
125             goto out;
126         }
127
128         if (strcmp (name, AVAHI_DBUS_NAME) == 0) {
129
130             if (old == NULL && new != NULL) {
131                 avahi_client_state_change (client, AVAHI_CLIENT_RECONNECTED);
132             } else if (old != NULL && new == NULL) {
133                 avahi_client_state_change (client, AVAHI_CLIENT_DISCONNECTED);
134                 /* XXX: we really need to expire all entry groups */
135             }
136         }
137     } else if (dbus_message_is_signal (message, AVAHI_DBUS_NAME, "StateChanged")) {
138         /* XXX: todo */
139         printf ("server statechange\n");
140     } else if (dbus_message_is_signal (message, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "StateChanged")) {
141         const char *path;
142         AvahiEntryGroup *n, *group = NULL;
143         path = dbus_message_get_path (message);
144
145         for (n = client->groups; n != NULL; n = n->groups_next)
146         {
147             if (strcmp (n->path, path) == 0)
148             {
149                 group = n;
150                 break;
151             }
152         }
153         
154         if (group != NULL) {
155             int state;
156             DBusError error;
157             dbus_error_init (&error);
158             dbus_message_get_args (message, &error, DBUS_TYPE_INT32, &state, DBUS_TYPE_INVALID);
159             if (dbus_error_is_set (&error))
160                 goto out;
161             
162             avahi_entry_group_state_change (group, state);
163         }
164     } else if (dbus_message_is_signal (message, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, "ItemNew")) {
165         return avahi_domain_browser_event (client, AVAHI_BROWSER_NEW, message);
166     } else if (dbus_message_is_signal (message, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, "ItemRemove")) {
167         return avahi_domain_browser_event (client, AVAHI_BROWSER_REMOVE, message);
168     } else if (dbus_message_is_signal (message, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, "ItemNew")) {
169         return avahi_service_type_browser_event (client, AVAHI_BROWSER_NEW, message);
170     } else if (dbus_message_is_signal (message, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, "ItemRemove")) {
171         return avahi_service_type_browser_event (client, AVAHI_BROWSER_REMOVE, message);
172     } else if (dbus_message_is_signal (message, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, "ItemNew")) {
173         return avahi_service_browser_event (client, AVAHI_BROWSER_NEW, message);
174     } else if (dbus_message_is_signal (message, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, "ItemRemove")) {
175         return avahi_service_browser_event (client, AVAHI_BROWSER_REMOVE, message);
176     }
177
178     return DBUS_HANDLER_RESULT_HANDLED;
179
180 out: 
181     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
182 }
183
184 AvahiClient *
185 avahi_client_new (AvahiClientCallback callback, void *user_data)
186 {
187     AvahiClient *tmp = NULL;
188     DBusError error;
189
190     dbus_error_init (&error);
191
192     if (!(tmp = malloc(sizeof(AvahiClient))))
193         goto fail;
194
195     AVAHI_LLIST_HEAD_INIT(AvahiEntryGroup, tmp->groups);
196     AVAHI_LLIST_HEAD_INIT(AvahiDomainBrowser, tmp->domain_browsers);
197     AVAHI_LLIST_HEAD_INIT(AvahiServiceBrowser, tmp->service_browsers);
198     AVAHI_LLIST_HEAD_INIT(AvahiServiceTypeBrowser, tmp->service_type_browsers);
199     
200     tmp->bus = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
201
202     if (dbus_error_is_set (&error)) {
203         goto fail;
204     }
205
206     dbus_connection_setup_with_g_main (tmp->bus, NULL);
207     dbus_connection_set_exit_on_disconnect (tmp->bus, FALSE);
208
209     if (!dbus_connection_add_filter (tmp->bus, filter_func, tmp, NULL))
210     {
211         goto fail;
212     }
213
214     dbus_bus_add_match (tmp->bus,
215             "type='signal', "
216             "interface='" AVAHI_DBUS_INTERFACE_SERVER "', "
217             "sender='" AVAHI_DBUS_NAME "', "
218             "path='" AVAHI_DBUS_PATH_SERVER "'",
219             &error);
220
221     if (dbus_error_is_set (&error))
222     {
223         goto fail;
224     }   
225
226     dbus_bus_add_match (tmp->bus,
227             "type='signal', "
228             "interface='" DBUS_INTERFACE_DBUS "', "
229             "sender='" DBUS_SERVICE_DBUS "', "
230             "path='" DBUS_PATH_DBUS "'",
231             &error);
232
233     if (dbus_error_is_set (&error))
234     {
235         goto fail;
236     }
237
238     tmp->callback = callback;
239     tmp->user_data = user_data;
240
241     avahi_client_schedule_state_request (tmp);
242
243     avahi_client_set_errno (tmp, AVAHI_OK);
244     return tmp;
245
246 fail:
247     free (tmp);
248
249     if (dbus_error_is_set(&error))
250         dbus_error_free(&error);
251         
252     return NULL;
253 }
254
255 static char*
256 avahi_client_get_string_reply_and_block (AvahiClient *client, char *method, char *param)
257 {
258     DBusMessage *message;
259     DBusMessage *reply;
260     DBusError error;
261     char *ret, *new;
262
263     if (client == NULL || method == NULL) return NULL;
264
265     dbus_error_init (&error);
266
267     message = dbus_message_new_method_call (AVAHI_DBUS_NAME, AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, method);
268
269     if (param != NULL)
270     {
271         if (!dbus_message_append_args (message, DBUS_TYPE_STRING, &param, DBUS_TYPE_INVALID))
272         {
273             avahi_client_set_errno (client, AVAHI_ERR_DBUS_ERROR);
274             return NULL;
275         }
276     }
277     
278     reply = dbus_connection_send_with_reply_and_block (client->bus, message, -1, &error);
279
280     if (dbus_error_is_set (&error))
281     {
282         dbus_error_free (&error);
283         dbus_message_unref (message);
284
285         avahi_client_set_errno (client, AVAHI_ERR_DBUS_ERROR);
286         return NULL;
287     }
288
289     if (reply == NULL)
290     {
291         dbus_message_unref (message);
292
293         avahi_client_set_errno (client, AVAHI_ERR_DBUS_ERROR);
294         return NULL;
295     }
296
297     dbus_message_get_args (reply, &error, DBUS_TYPE_STRING, &ret, DBUS_TYPE_INVALID);
298
299     if (dbus_error_is_set (&error))
300     {
301         dbus_error_free (&error);
302
303         avahi_client_set_errno (client, AVAHI_ERR_DBUS_ERROR);
304         return NULL;
305     }
306
307     new = strdup (ret);
308
309     avahi_client_set_errno (client, AVAHI_OK);
310     return new;
311 }
312
313 char*
314 avahi_client_get_version_string (AvahiClient *client)
315 {
316     return avahi_client_get_string_reply_and_block (client, "GetVersionString", NULL);
317 }
318
319 char*
320 avahi_client_get_domain_name (AvahiClient *client)
321 {
322     return avahi_client_get_string_reply_and_block (client, "GetDomainName", NULL);
323 }
324
325 char*
326 avahi_client_get_host_name (AvahiClient *client)
327 {
328     return avahi_client_get_string_reply_and_block (client, "GetHostName", NULL);
329 }
330
331 char*
332 avahi_client_get_host_name_fqdn (AvahiClient *client)
333 {
334     return avahi_client_get_string_reply_and_block (client, "GetHostNameFqdn", NULL);
335 }