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