4 This file is part of avahi.
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.
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.
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
30 #include <dbus/dbus.h>
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>
41 static int simple_method_call(AvahiClient *client, const char *path, const char *interface, const char *method) {
42 DBusMessage *message = NULL, *reply = NULL;
46 dbus_error_init(&error);
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);
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);
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);
70 dbus_message_unref(message);
71 dbus_message_unref(reply);
76 if (dbus_error_is_set(&error)) {
77 r = avahi_client_set_dbus_error(client, &error);
78 dbus_error_free(&error);
82 dbus_message_unref(message);
85 dbus_message_unref(reply);
90 AvahiDomainBrowser* avahi_domain_browser_new(
92 AvahiIfIndex interface,
93 AvahiProtocol protocol,
95 AvahiDomainBrowserType btype,
96 AvahiDomainBrowserCallback callback,
99 AvahiDomainBrowser *db = NULL;
100 DBusMessage *message = NULL, *reply;
103 int32_t i_interface, i_protocol, bt;
108 dbus_error_init (&error);
110 if (client->state == AVAHI_CLIENT_DISCONNECTED) {
111 avahi_client_set_errno(client, AVAHI_ERR_BAD_STATE);
118 if (!(db = avahi_new (AvahiDomainBrowser, 1))) {
119 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
124 db->callback = callback;
125 db->userdata = userdata;
128 AVAHI_LLIST_PREPEND(AvahiDomainBrowser, domain_browsers, client->domain_browsers, db);
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);
135 i_interface = interface;
136 i_protocol = protocol;
139 if (!(dbus_message_append_args(
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);
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);
156 if (!dbus_message_get_args (reply, &error, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID) ||
157 dbus_error_is_set(&error) ||
159 avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
163 if (!(db->path = avahi_strdup(path))) {
165 /* FIXME: We don't remove the object on the server side */
167 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
171 dbus_message_unref(message);
172 dbus_message_unref(reply);
178 if (dbus_error_is_set(&error)) {
179 avahi_client_set_dbus_error(client, &error);
180 dbus_error_free(&error);
184 avahi_domain_browser_free(db);
187 dbus_message_unref(message);
190 dbus_message_unref(reply);
195 AvahiClient* avahi_domain_browser_get_client (AvahiDomainBrowser *b)
201 int avahi_domain_browser_free (AvahiDomainBrowser *b) {
208 if (b->path && client->state != AVAHI_CLIENT_DISCONNECTED)
209 r = simple_method_call(client, b->path, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, "Free");
211 AVAHI_LLIST_REMOVE(AvahiDomainBrowser, domain_browsers, client->domain_browsers, b);
219 const char* avahi_domain_browser_get_dbus_path(AvahiDomainBrowser *b) {
225 DBusHandlerResult avahi_domain_browser_event (AvahiClient *client, AvahiBrowserEvent event, DBusMessage *message) {
226 AvahiDomainBrowser *db = NULL;
230 int32_t interface, protocol;
235 dbus_error_init (&error);
237 if (!(path = dbus_message_get_path(message)))
240 for (db = client->domain_browsers; db; db = db->domain_browsers_next)
241 if (strcmp (db->path, path) == 0)
247 if (!dbus_message_get_args(
249 DBUS_TYPE_INT32, &interface,
250 DBUS_TYPE_INT32, &protocol,
251 DBUS_TYPE_STRING, &domain,
252 DBUS_TYPE_INVALID) ||
253 dbus_error_is_set (&error)) {
254 fprintf(stderr, "Failed to parse browser event.\n");
258 db->callback(db, (AvahiIfIndex) interface, (AvahiProtocol) protocol, event, domain, db->userdata);
260 return DBUS_HANDLER_RESULT_HANDLED;
263 dbus_error_free (&error);
264 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
267 /* AvahiServiceTypeBrowser */
268 AvahiServiceTypeBrowser* avahi_service_type_browser_new(
270 AvahiIfIndex interface,
271 AvahiProtocol protocol,
273 AvahiServiceTypeBrowserCallback callback,
276 AvahiServiceTypeBrowser *b = NULL;
277 DBusMessage *message = NULL, *reply;
280 int32_t i_interface, i_protocol;
285 dbus_error_init(&error);
287 if (client->state == AVAHI_CLIENT_DISCONNECTED) {
288 avahi_client_set_errno(client, AVAHI_ERR_BAD_STATE);
295 if (!(b = avahi_new(AvahiServiceTypeBrowser, 1))) {
296 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
301 b->callback = callback;
302 b->userdata = userdata;
305 AVAHI_LLIST_PREPEND(AvahiServiceTypeBrowser, service_type_browsers, client->service_type_browsers, b);
307 if (!(message = dbus_message_new_method_call (AVAHI_DBUS_NAME, AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "ServiceTypeBrowserNew"))) {
308 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
312 i_interface = interface;
313 i_protocol = protocol;
315 if (!dbus_message_append_args(
317 DBUS_TYPE_INT32, &interface,
318 DBUS_TYPE_INT32, &protocol,
319 DBUS_TYPE_STRING, &domain,
320 DBUS_TYPE_INVALID)) {
321 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
325 if (!(reply = dbus_connection_send_with_reply_and_block (client->bus, message, -1, &error)) ||
326 dbus_error_is_set(&error)) {
327 avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
331 if (!dbus_message_get_args (reply, &error, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID) ||
332 dbus_error_is_set(&error) ||
334 avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
338 if (!(b->path = avahi_strdup(path))) {
340 /* FIXME: We don't remove the object on the server side */
342 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
346 dbus_message_unref(message);
347 dbus_message_unref(reply);
353 if (dbus_error_is_set(&error)) {
354 avahi_client_set_dbus_error(client, &error);
355 dbus_error_free(&error);
359 avahi_service_type_browser_free(b);
362 dbus_message_unref(message);
365 dbus_message_unref(reply);
370 AvahiClient* avahi_service_type_browser_get_client (AvahiServiceTypeBrowser *b)
376 int avahi_service_type_browser_free (AvahiServiceTypeBrowser *b) {
383 if (b->path && client->state != AVAHI_CLIENT_DISCONNECTED)
384 r = simple_method_call(client, b->path, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, "Free");
386 AVAHI_LLIST_REMOVE(AvahiServiceTypeBrowser, service_type_browsers, b->client->service_type_browsers, b);
393 const char* avahi_service_type_browser_get_dbus_path(AvahiServiceTypeBrowser *b) {
399 DBusHandlerResult avahi_service_type_browser_event (AvahiClient *client, AvahiBrowserEvent event, DBusMessage *message) {
400 AvahiServiceTypeBrowser *b = NULL;
404 int32_t interface, protocol;
409 dbus_error_init (&error);
411 if (!(path = dbus_message_get_path(message)))
414 for (b = client->service_type_browsers; b; b = b->service_type_browsers_next)
415 if (strcmp (b->path, path) == 0)
421 if (!dbus_message_get_args(
423 DBUS_TYPE_INT32, &interface,
424 DBUS_TYPE_INT32, &protocol,
425 DBUS_TYPE_STRING, &type,
426 DBUS_TYPE_STRING, &domain,
427 DBUS_TYPE_INVALID) ||
428 dbus_error_is_set(&error)) {
429 fprintf(stderr, "Failed to parse browser event.\n");
433 b->callback(b, (AvahiIfIndex) interface, (AvahiProtocol) protocol, event, type, domain, b->userdata);
435 return DBUS_HANDLER_RESULT_HANDLED;
438 dbus_error_free (&error);
439 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
442 /* AvahiServiceBrowser */
444 AvahiServiceBrowser* avahi_service_browser_new(
446 AvahiIfIndex interface,
447 AvahiProtocol protocol,
450 AvahiServiceBrowserCallback callback,
453 AvahiServiceBrowser *b = NULL;
454 DBusMessage *message = NULL, *reply;
457 int32_t i_protocol, i_interface;
463 dbus_error_init(&error);
465 if (client->state == AVAHI_CLIENT_DISCONNECTED) {
466 avahi_client_set_errno(client, AVAHI_ERR_BAD_STATE);
473 if (!(b = avahi_new(AvahiServiceBrowser, 1))) {
474 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
479 b->callback = callback;
480 b->userdata = userdata;
483 AVAHI_LLIST_PREPEND(AvahiServiceBrowser, service_browsers, client->service_browsers, b);
485 if (!(message = dbus_message_new_method_call (AVAHI_DBUS_NAME, AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "ServiceBrowserNew"))) {
486 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
490 i_interface = interface;
491 i_protocol = protocol;
494 if (!dbus_message_append_args(
496 DBUS_TYPE_INT32, &i_interface,
497 DBUS_TYPE_INT32, &i_protocol,
498 DBUS_TYPE_STRING, &type,
499 DBUS_TYPE_STRING, &domain,
500 DBUS_TYPE_INVALID)) {
501 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
505 if (!(reply = dbus_connection_send_with_reply_and_block (client->bus, message, -1, &error)) ||
506 dbus_error_is_set(&error)) {
507 avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
511 if (!dbus_message_get_args (reply, &error, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID) ||
512 dbus_error_is_set(&error) ||
514 avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
518 if (!(b->path = avahi_strdup(path))) {
520 /* FIXME: We don't remove the object on the server side */
522 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
526 dbus_message_unref(message);
527 dbus_message_unref(reply);
532 if (dbus_error_is_set(&error)) {
533 avahi_client_set_dbus_error(client, &error);
534 dbus_error_free(&error);
538 avahi_service_browser_free(b);
541 dbus_message_unref(message);
544 dbus_message_unref(reply);
549 AvahiClient* avahi_service_browser_get_client (AvahiServiceBrowser *b)
555 int avahi_service_browser_free (AvahiServiceBrowser *b) {
562 if (b->path && client->state != AVAHI_CLIENT_DISCONNECTED)
563 r = simple_method_call(client, b->path, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, "Free");
565 AVAHI_LLIST_REMOVE(AvahiServiceBrowser, service_browsers, b->client->service_browsers, b);
572 const char* avahi_service_browser_get_dbus_path(AvahiServiceBrowser *b) {
578 DBusHandlerResult avahi_service_browser_event (AvahiClient *client, AvahiBrowserEvent event, DBusMessage *message) {
579 AvahiServiceBrowser *b = NULL;
582 char *name, *type, *domain;
583 int32_t interface, protocol;
585 dbus_error_init (&error);
587 if (!(path = dbus_message_get_path(message)))
590 for (b = client->service_browsers; b; b = b->service_browsers_next)
591 if (strcmp (b->path, path) == 0)
597 if (!dbus_message_get_args (
599 DBUS_TYPE_INT32, &interface,
600 DBUS_TYPE_INT32, &protocol,
601 DBUS_TYPE_STRING, &name,
602 DBUS_TYPE_STRING, &type,
603 DBUS_TYPE_STRING, &domain,
604 DBUS_TYPE_INVALID) ||
605 dbus_error_is_set(&error)) {
606 fprintf(stderr, "Failed to parse browser event.\n");
610 b->callback(b, (AvahiIfIndex) interface, (AvahiProtocol) protocol, event, name, type, domain, b->userdata);
612 return DBUS_HANDLER_RESULT_HANDLED;
615 dbus_error_free (&error);
616 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;