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