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