]> git.meshlink.io Git - catta/blob - avahi-client/browser.c
34a36015b45076f080974fbba4209a597493a6a9
[catta] / avahi-client / browser.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 <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29
30 #include <dbus/dbus.h>
31
32 #include <avahi-client/client.h>
33 #include <avahi-common/dbus.h>
34 #include <avahi-common/llist.h>
35 #include <avahi-common/error.h>
36 #include <avahi-common/malloc.h>
37
38 #include "client.h"
39 #include "internal.h"
40
41 AvahiDomainBrowser* avahi_domain_browser_new(
42     AvahiClient *client,
43     AvahiIfIndex interface,
44     AvahiProtocol protocol,
45     const char *domain,
46     AvahiDomainBrowserType btype,
47     AvahiDomainBrowserCallback callback,
48     void *userdata) {
49     
50     AvahiDomainBrowser *db = NULL;
51     DBusMessage *message = NULL, *reply = NULL;
52     DBusError error;
53     char *path;
54     int32_t i_interface, i_protocol, bt;
55
56     assert(client);
57     assert(callback);
58
59     dbus_error_init (&error);
60
61     if (client->state == AVAHI_CLIENT_DISCONNECTED) {
62         avahi_client_set_errno(client, AVAHI_ERR_BAD_STATE);
63         goto fail;
64     }
65
66     if (!domain)
67         domain = "";
68
69     if (!(db = avahi_new (AvahiDomainBrowser, 1))) {
70         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
71         goto fail;
72     }
73
74     db->client = client;
75     db->callback = callback;
76     db->userdata = userdata;
77     db->path = NULL;
78
79     AVAHI_LLIST_PREPEND(AvahiDomainBrowser, domain_browsers, client->domain_browsers, db);
80
81     if (!(message = dbus_message_new_method_call (AVAHI_DBUS_NAME, AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "DomainBrowserNew"))) {
82         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
83         goto fail;
84     }
85
86     i_interface = interface;
87     i_protocol = protocol;
88     bt = btype;
89
90     if (!(dbus_message_append_args(
91               message,
92               DBUS_TYPE_INT32, &i_interface,
93               DBUS_TYPE_INT32, &i_protocol,
94               DBUS_TYPE_STRING, &domain,
95               DBUS_TYPE_INT32, &bt,
96               DBUS_TYPE_INVALID))) {
97         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
98         goto fail;
99     }
100
101     if (!(reply = dbus_connection_send_with_reply_and_block (client->bus, message, -1, &error)) ||
102         dbus_error_is_set(&error)) {
103         avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
104         goto fail;
105     }
106
107     if (!dbus_message_get_args (reply, &error, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID) ||
108         dbus_error_is_set(&error) ||
109         !path) {
110         avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
111         goto fail;
112     }
113
114     if (!(db->path = avahi_strdup(path))) {
115
116         /* FIXME: We don't remove the object on the server side */
117
118         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
119         goto fail;
120     }
121
122     dbus_message_unref(message);
123     dbus_message_unref(reply);
124     
125     return db;
126
127 fail:
128
129     if (dbus_error_is_set(&error)) {
130         avahi_client_set_dbus_error(client, &error);
131         dbus_error_free(&error);
132     }
133
134     if (db)
135         avahi_domain_browser_free(db);
136     
137     if (message)
138         dbus_message_unref(message);
139
140     if (reply)
141         dbus_message_unref(reply);
142
143     return NULL;
144 }
145
146 AvahiClient* avahi_domain_browser_get_client (AvahiDomainBrowser *b)
147 {
148     assert(b);
149     return b->client;
150 }
151
152 int avahi_domain_browser_free (AvahiDomainBrowser *b) {
153     AvahiClient *client;
154     int r = AVAHI_OK;
155
156     assert(b);
157     client = b->client;
158
159     if (b->path && client->state != AVAHI_CLIENT_DISCONNECTED)
160         r = avahi_client_simple_method_call(client, b->path, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, "Free");
161
162     AVAHI_LLIST_REMOVE(AvahiDomainBrowser, domain_browsers, client->domain_browsers, b);
163
164     avahi_free(b->path);
165     avahi_free(b);
166
167     return r;
168 }
169
170 DBusHandlerResult avahi_domain_browser_event (AvahiClient *client, AvahiBrowserEvent event, DBusMessage *message) {
171     AvahiDomainBrowser *db = NULL;
172     DBusError error;
173     const char *path;
174     char *domain;
175     int32_t interface, protocol;
176
177     assert(client);
178     assert(message);
179     
180     dbus_error_init (&error);
181
182     if (!(path = dbus_message_get_path(message)))
183         goto fail;
184
185     for (db = client->domain_browsers; db; db = db->domain_browsers_next)
186         if (strcmp (db->path, path) == 0)
187             break;
188
189     if (!db)
190         goto fail;
191
192     if (!dbus_message_get_args(
193               message, &error,
194               DBUS_TYPE_INT32, &interface,
195               DBUS_TYPE_INT32, &protocol,
196               DBUS_TYPE_STRING, &domain,
197               DBUS_TYPE_INVALID) ||
198           dbus_error_is_set (&error)) {
199         fprintf(stderr, "Failed to parse browser event.\n");
200         goto fail;
201     }
202
203     db->callback(db, (AvahiIfIndex) interface, (AvahiProtocol) protocol, event, domain, db->userdata);
204
205     return DBUS_HANDLER_RESULT_HANDLED;
206
207 fail:
208     dbus_error_free (&error);
209     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
210 }
211
212 /* AvahiServiceTypeBrowser */
213 AvahiServiceTypeBrowser* avahi_service_type_browser_new(
214     AvahiClient *client,
215     AvahiIfIndex interface,
216     AvahiProtocol protocol,
217     const char *domain,
218     AvahiServiceTypeBrowserCallback callback,
219     void *userdata) {
220         
221     AvahiServiceTypeBrowser *b = NULL;
222     DBusMessage *message = NULL, *reply = NULL;
223     DBusError error;
224     char *path;
225     int32_t i_interface, i_protocol;
226
227     assert(client);
228     assert(callback);
229
230     dbus_error_init(&error);
231
232     if (client->state == AVAHI_CLIENT_DISCONNECTED) {
233         avahi_client_set_errno(client, AVAHI_ERR_BAD_STATE);
234         goto fail;
235     }
236
237     if (!domain)
238         domain = "";
239
240     if (!(b = avahi_new(AvahiServiceTypeBrowser, 1))) {
241         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
242         goto fail;
243     }
244
245     b->client = client;
246     b->callback = callback;
247     b->userdata = userdata;
248     b->path = NULL;
249
250     AVAHI_LLIST_PREPEND(AvahiServiceTypeBrowser, service_type_browsers, client->service_type_browsers, b);
251
252     if (!(message = dbus_message_new_method_call (AVAHI_DBUS_NAME, AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "ServiceTypeBrowserNew"))) {
253         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
254         goto fail;
255     }
256     
257     i_interface = interface;
258     i_protocol = protocol;
259
260     if (!dbus_message_append_args(
261             message,
262             DBUS_TYPE_INT32, &interface,
263             DBUS_TYPE_INT32, &protocol,
264             DBUS_TYPE_STRING, &domain,
265             DBUS_TYPE_INVALID)) {
266         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
267         goto fail;
268     }
269
270     if (!(reply = dbus_connection_send_with_reply_and_block (client->bus, message, -1, &error)) ||
271         dbus_error_is_set(&error)) {
272         avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
273         goto fail;
274     }
275
276     if (!dbus_message_get_args (reply, &error, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID) ||
277         dbus_error_is_set(&error) ||
278         !path) {
279         avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
280         goto fail;
281     }
282
283     if (!(b->path = avahi_strdup(path))) {
284
285         /* FIXME: We don't remove the object on the server side */
286
287         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
288         goto fail;
289     }
290
291     dbus_message_unref(message);
292     dbus_message_unref(reply);
293
294     return b;
295
296 fail:
297     
298     if (dbus_error_is_set(&error)) {
299         avahi_client_set_dbus_error(client, &error);
300         dbus_error_free(&error);
301     }
302
303     if (b)
304         avahi_service_type_browser_free(b);
305     
306     if (message)
307         dbus_message_unref(message);
308
309     if (reply)
310         dbus_message_unref(reply);
311
312     return NULL;
313 }
314
315 AvahiClient* avahi_service_type_browser_get_client (AvahiServiceTypeBrowser *b)
316 {
317     assert(b);
318     return b->client;
319 }
320
321 int avahi_service_type_browser_free (AvahiServiceTypeBrowser *b) {
322     AvahiClient *client;
323     int r = AVAHI_OK;
324
325     assert(b);
326     client = b->client;
327
328     if (b->path && client->state != AVAHI_CLIENT_DISCONNECTED)
329         r = avahi_client_simple_method_call(client, b->path, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, "Free");
330
331     AVAHI_LLIST_REMOVE(AvahiServiceTypeBrowser, service_type_browsers, b->client->service_type_browsers, b);
332
333     avahi_free(b->path);
334     avahi_free(b);
335     return r;
336 }
337
338 DBusHandlerResult avahi_service_type_browser_event (AvahiClient *client, AvahiBrowserEvent event, DBusMessage *message) {
339     AvahiServiceTypeBrowser *b = NULL;
340     DBusError error;
341     const char *path;
342     char *domain, *type;
343     int32_t interface, protocol;
344
345     assert(client);
346     assert(message);
347     
348     dbus_error_init (&error);
349
350     if (!(path = dbus_message_get_path(message)))
351         goto fail;
352
353     for (b = client->service_type_browsers; b; b = b->service_type_browsers_next)
354         if (strcmp (b->path, path) == 0)
355             break;
356
357     if (!b)
358         goto fail;
359
360     if (!dbus_message_get_args(
361               message, &error,
362               DBUS_TYPE_INT32, &interface,
363               DBUS_TYPE_INT32, &protocol,
364               DBUS_TYPE_STRING, &type,
365               DBUS_TYPE_STRING, &domain,
366               DBUS_TYPE_INVALID) ||
367           dbus_error_is_set(&error)) {
368         fprintf(stderr, "Failed to parse browser event.\n");
369         goto fail;
370     }
371
372     b->callback(b, (AvahiIfIndex) interface, (AvahiProtocol) protocol, event, type, domain, b->userdata);
373
374     return DBUS_HANDLER_RESULT_HANDLED;
375
376 fail:
377     dbus_error_free (&error);
378     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
379 }
380
381 /* AvahiServiceBrowser */
382
383 AvahiServiceBrowser* avahi_service_browser_new(
384     AvahiClient *client,
385     AvahiIfIndex interface,
386     AvahiProtocol protocol,
387     const char *type,
388     const char *domain,
389     AvahiServiceBrowserCallback callback,
390     void *userdata) {
391     
392     AvahiServiceBrowser *b = NULL;
393     DBusMessage *message = NULL, *reply = NULL;
394     DBusError error;
395     char *path;
396     int32_t i_protocol, i_interface;
397
398     assert(client);
399     assert(type);
400     assert(callback);
401
402     dbus_error_init(&error);
403
404     if (client->state == AVAHI_CLIENT_DISCONNECTED) {
405         avahi_client_set_errno(client, AVAHI_ERR_BAD_STATE);
406         goto fail;
407     }
408
409     if (!domain)
410         domain = "";
411
412     if (!(b = avahi_new(AvahiServiceBrowser, 1))) {
413         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
414         goto fail;
415     }
416     
417     b->client = client;
418     b->callback = callback;
419     b->userdata = userdata;
420     b->path = NULL;
421
422     AVAHI_LLIST_PREPEND(AvahiServiceBrowser, service_browsers, client->service_browsers, b);
423
424     if (!(message = dbus_message_new_method_call (AVAHI_DBUS_NAME, AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "ServiceBrowserNew"))) {
425         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
426         goto fail;
427     }
428
429     i_interface = interface;
430     i_protocol = protocol;
431     
432
433     if (!dbus_message_append_args(
434             message,
435             DBUS_TYPE_INT32, &i_interface,
436             DBUS_TYPE_INT32, &i_protocol,
437             DBUS_TYPE_STRING, &type,
438             DBUS_TYPE_STRING, &domain,
439             DBUS_TYPE_INVALID)) {
440         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
441         goto fail;
442     }
443
444     if (!(reply = dbus_connection_send_with_reply_and_block (client->bus, message, -1, &error)) ||
445         dbus_error_is_set(&error)) {
446         avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
447         goto fail;
448     }
449
450     if (!dbus_message_get_args (reply, &error, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID) ||
451         dbus_error_is_set(&error) ||
452         !path) {
453         avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
454         goto fail;
455     }
456
457     if (!(b->path = avahi_strdup(path))) {
458
459         /* FIXME: We don't remove the object on the server side */
460
461         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
462         goto fail;
463     }
464
465     dbus_message_unref(message);
466     dbus_message_unref(reply);
467     
468     return b;
469
470 fail:
471     if (dbus_error_is_set(&error)) {
472         avahi_client_set_dbus_error(client, &error);
473         dbus_error_free(&error);
474     }
475
476     if (b)
477         avahi_service_browser_free(b);
478     
479     if (message)
480         dbus_message_unref(message);
481
482     if (reply)
483         dbus_message_unref(reply);
484
485     return NULL;
486 }
487
488 AvahiClient* avahi_service_browser_get_client (AvahiServiceBrowser *b)
489 {
490     assert(b);
491     return b->client;
492 }
493
494 int avahi_service_browser_free (AvahiServiceBrowser *b) {
495     AvahiClient *client;
496     int r = AVAHI_OK;
497
498     assert(b);
499     client = b->client;
500
501     if (b->path && client->state != AVAHI_CLIENT_DISCONNECTED)
502         r = avahi_client_simple_method_call(client, b->path, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, "Free");
503
504     AVAHI_LLIST_REMOVE(AvahiServiceBrowser, service_browsers, b->client->service_browsers, b);
505
506     avahi_free(b->path);
507     avahi_free(b);
508     return r;
509 }
510
511
512 DBusHandlerResult avahi_service_browser_event (AvahiClient *client, AvahiBrowserEvent event, DBusMessage *message) {
513     AvahiServiceBrowser *b = NULL;
514     DBusError error;
515     const char *path;
516     char *name, *type, *domain;
517     int32_t interface, protocol;
518
519     dbus_error_init (&error);
520
521     if (!(path = dbus_message_get_path(message)))
522         goto fail;
523
524     for (b = client->service_browsers; b; b = b->service_browsers_next)
525         if (strcmp (b->path, path) == 0)
526             break;
527
528     if (!b)
529         goto fail;
530
531     if (!dbus_message_get_args (
532               message, &error,
533               DBUS_TYPE_INT32, &interface,
534               DBUS_TYPE_INT32, &protocol,
535               DBUS_TYPE_STRING, &name,
536               DBUS_TYPE_STRING, &type,
537               DBUS_TYPE_STRING, &domain,
538               DBUS_TYPE_INVALID) ||
539           dbus_error_is_set(&error)) {
540         fprintf(stderr, "Failed to parse browser event.\n");
541         goto fail;
542     }
543
544     b->callback(b, (AvahiIfIndex) interface, (AvahiProtocol) protocol, event, name, type, domain, b->userdata);
545
546     return DBUS_HANDLER_RESULT_HANDLED;
547
548 fail:
549     dbus_error_free (&error);
550     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
551 }
552
553