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 int avahi_domain_browser_free (AvahiDomainBrowser *b) {
202 if (b->path && client->state != AVAHI_CLIENT_DISCONNECTED)
203 r = simple_method_call(client, b->path, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, "Free");
205 AVAHI_LLIST_REMOVE(AvahiDomainBrowser, domain_browsers, client->domain_browsers, b);
213 const char* avahi_domain_browser_get_dbus_path(AvahiDomainBrowser *b) {
219 DBusHandlerResult avahi_domain_browser_event (AvahiClient *client, AvahiBrowserEvent event, DBusMessage *message) {
220 AvahiDomainBrowser *db = NULL;
224 int32_t interface, protocol;
229 dbus_error_init (&error);
231 if (!(path = dbus_message_get_path(message)))
234 for (db = client->domain_browsers; db; db = db->domain_browsers_next)
235 if (strcmp (db->path, path) == 0)
241 if (!dbus_message_get_args(
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");
252 db->callback(db, (AvahiIfIndex) interface, (AvahiProtocol) protocol, event, domain, db->userdata);
254 return DBUS_HANDLER_RESULT_HANDLED;
257 dbus_error_free (&error);
258 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
261 /* AvahiServiceTypeBrowser */
262 AvahiServiceTypeBrowser* avahi_service_type_browser_new(
264 AvahiIfIndex interface,
265 AvahiProtocol protocol,
267 AvahiServiceTypeBrowserCallback callback,
270 AvahiServiceTypeBrowser *b = NULL;
271 DBusMessage *message = NULL, *reply;
274 int32_t i_interface, i_protocol;
279 dbus_error_init(&error);
281 if (client->state == AVAHI_CLIENT_DISCONNECTED) {
282 avahi_client_set_errno(client, AVAHI_ERR_BAD_STATE);
289 if (!(b = avahi_new(AvahiServiceTypeBrowser, 1))) {
290 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
295 b->callback = callback;
296 b->userdata = userdata;
299 AVAHI_LLIST_PREPEND(AvahiServiceTypeBrowser, service_type_browsers, client->service_type_browsers, b);
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);
306 i_interface = interface;
307 i_protocol = protocol;
309 if (!dbus_message_append_args(
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);
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);
325 if (!dbus_message_get_args (reply, &error, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID) ||
326 dbus_error_is_set(&error) ||
328 avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
332 if (!(b->path = avahi_strdup(path))) {
334 /* FIXME: We don't remove the object on the server side */
336 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
340 dbus_message_unref(message);
341 dbus_message_unref(reply);
347 if (dbus_error_is_set(&error)) {
348 avahi_client_set_dbus_error(client, &error);
349 dbus_error_free(&error);
353 avahi_service_type_browser_free(b);
356 dbus_message_unref(message);
359 dbus_message_unref(reply);
364 int avahi_service_type_browser_free (AvahiServiceTypeBrowser *b) {
371 if (b->path && client->state != AVAHI_CLIENT_DISCONNECTED)
372 r = simple_method_call(client, b->path, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, "Free");
374 AVAHI_LLIST_REMOVE(AvahiServiceTypeBrowser, service_type_browsers, b->client->service_type_browsers, b);
381 const char* avahi_service_type_browser_get_dbus_path(AvahiServiceTypeBrowser *b) {
387 DBusHandlerResult avahi_service_type_browser_event (AvahiClient *client, AvahiBrowserEvent event, DBusMessage *message) {
388 AvahiServiceTypeBrowser *b = NULL;
392 int32_t interface, protocol;
397 dbus_error_init (&error);
399 if (!(path = dbus_message_get_path(message)))
402 for (b = client->service_type_browsers; b; b = b->service_type_browsers_next)
403 if (strcmp (b->path, path) == 0)
409 if (!dbus_message_get_args(
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");
421 b->callback(b, (AvahiIfIndex) interface, (AvahiProtocol) protocol, event, type, domain, b->userdata);
423 return DBUS_HANDLER_RESULT_HANDLED;
426 dbus_error_free (&error);
427 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
430 /* AvahiServiceBrowser */
432 AvahiServiceBrowser* avahi_service_browser_new(
434 AvahiIfIndex interface,
435 AvahiProtocol protocol,
438 AvahiServiceBrowserCallback callback,
441 AvahiServiceBrowser *b = NULL;
442 DBusMessage *message = NULL, *reply;
445 int32_t i_protocol, i_interface;
451 dbus_error_init(&error);
453 if (client->state == AVAHI_CLIENT_DISCONNECTED) {
454 avahi_client_set_errno(client, AVAHI_ERR_BAD_STATE);
461 if (!(b = avahi_new(AvahiServiceBrowser, 1))) {
462 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
467 b->callback = callback;
468 b->userdata = userdata;
471 AVAHI_LLIST_PREPEND(AvahiServiceBrowser, service_browsers, client->service_browsers, b);
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);
478 i_interface = interface;
479 i_protocol = protocol;
482 if (!dbus_message_append_args(
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);
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);
499 if (!dbus_message_get_args (reply, &error, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID) ||
500 dbus_error_is_set(&error) ||
502 avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
506 if (!(b->path = avahi_strdup(path))) {
508 /* FIXME: We don't remove the object on the server side */
510 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
514 dbus_message_unref(message);
515 dbus_message_unref(reply);
520 if (dbus_error_is_set(&error)) {
521 avahi_client_set_dbus_error(client, &error);
522 dbus_error_free(&error);
526 avahi_service_browser_free(b);
529 dbus_message_unref(message);
532 dbus_message_unref(reply);
537 int avahi_service_browser_free (AvahiServiceBrowser *b) {
544 if (b->path && client->state != AVAHI_CLIENT_DISCONNECTED)
545 r = simple_method_call(client, b->path, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, "Free");
547 AVAHI_LLIST_REMOVE(AvahiServiceBrowser, service_browsers, b->client->service_browsers, b);
554 const char* avahi_service_browser_get_dbus_path(AvahiServiceBrowser *b) {
560 DBusHandlerResult avahi_service_browser_event (AvahiClient *client, AvahiBrowserEvent event, DBusMessage *message) {
561 AvahiServiceBrowser *b = NULL;
564 char *name, *type, *domain;
565 int32_t interface, protocol;
567 dbus_error_init (&error);
569 if (!(path = dbus_message_get_path(message)))
572 for (b = client->service_browsers; b; b = b->service_browsers_next)
573 if (strcmp (b->path, path) == 0)
576 if (!dbus_message_get_args (
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");
589 b->callback(b, (AvahiIfIndex) interface, (AvahiProtocol) protocol, event, name, type, domain, b->userdata);
591 return DBUS_HANDLER_RESULT_HANDLED;
594 dbus_error_free (&error);
595 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;