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