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