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
27 #include <sys/ioctl.h>
28 #include <netinet/in.h>
39 #include <dbus/dbus.h>
41 #include <avahi-common/dbus.h>
42 #include <avahi-common/llist.h>
43 #include <avahi-common/malloc.h>
44 #include <avahi-common/dbus.h>
45 #include <avahi-common/dbus-watch-glue.h>
46 #include <avahi-common/alternative.h>
47 #include <avahi-common/error.h>
49 #include <avahi-core/log.h>
50 #include <avahi-core/core.h>
51 #include <avahi-core/lookup.h>
52 #include <avahi-core/publish.h>
54 #include "dbus-protocol.h"
57 typedef struct Server Server;
58 typedef struct Client Client;
59 typedef struct EntryGroupInfo EntryGroupInfo;
60 typedef struct SyncHostNameResolverInfo SyncHostNameResolverInfo;
61 typedef struct AsyncHostNameResolverInfo AsyncHostNameResolverInfo;
62 typedef struct SyncAddressResolverInfo SyncAddressResolverInfo;
63 typedef struct AsyncAddressResolverInfo AsyncAddressResolverInfo;
64 typedef struct DomainBrowserInfo DomainBrowserInfo;
65 typedef struct ServiceTypeBrowserInfo ServiceTypeBrowserInfo;
66 typedef struct ServiceBrowserInfo ServiceBrowserInfo;
67 typedef struct SyncServiceResolverInfo SyncServiceResolverInfo;
68 typedef struct AsyncServiceResolverInfo AsyncServiceResolverInfo;
70 #define MAX_CLIENTS 20
71 #define MAX_OBJECTS_PER_CLIENT 50
72 #define MAX_ENTRIES_PER_ENTRY_GROUP 20
74 /* #define VALGRIND_WORKAROUND 1 */
76 struct EntryGroupInfo {
79 AvahiSEntryGroup *entry_group;
84 AVAHI_LLIST_FIELDS(EntryGroupInfo, entry_groups);
87 struct SyncHostNameResolverInfo {
89 AvahiSHostNameResolver *host_name_resolver;
92 AVAHI_LLIST_FIELDS(SyncHostNameResolverInfo, sync_host_name_resolvers);
95 struct AsyncHostNameResolverInfo {
98 AvahiSHostNameResolver *host_name_resolver;
101 AVAHI_LLIST_FIELDS(AsyncHostNameResolverInfo, async_host_name_resolvers);
104 struct SyncAddressResolverInfo {
106 AvahiSAddressResolver *address_resolver;
107 DBusMessage *message;
109 AVAHI_LLIST_FIELDS(SyncAddressResolverInfo, sync_address_resolvers);
112 struct AsyncAddressResolverInfo {
115 AvahiSAddressResolver *address_resolver;
118 AVAHI_LLIST_FIELDS(AsyncAddressResolverInfo, async_address_resolvers);
121 struct DomainBrowserInfo {
124 AvahiSDomainBrowser *domain_browser;
127 AVAHI_LLIST_FIELDS(DomainBrowserInfo, domain_browsers);
130 struct ServiceTypeBrowserInfo {
133 AvahiSServiceTypeBrowser *service_type_browser;
136 AVAHI_LLIST_FIELDS(ServiceTypeBrowserInfo, service_type_browsers);
139 struct ServiceBrowserInfo {
142 AvahiSServiceBrowser *service_browser;
145 AVAHI_LLIST_FIELDS(ServiceBrowserInfo, service_browsers);
148 struct SyncServiceResolverInfo {
150 AvahiSServiceResolver *service_resolver;
151 DBusMessage *message;
153 AVAHI_LLIST_FIELDS(SyncServiceResolverInfo, sync_service_resolvers);
156 struct AsyncServiceResolverInfo {
159 AvahiSServiceResolver *service_resolver;
162 AVAHI_LLIST_FIELDS(AsyncServiceResolverInfo, async_service_resolvers);
171 AVAHI_LLIST_FIELDS(Client, clients);
172 AVAHI_LLIST_HEAD(EntryGroupInfo, entry_groups);
173 AVAHI_LLIST_HEAD(SyncHostNameResolverInfo, sync_host_name_resolvers);
174 AVAHI_LLIST_HEAD(AsyncHostNameResolverInfo, async_host_name_resolvers);
175 AVAHI_LLIST_HEAD(SyncAddressResolverInfo, sync_address_resolvers);
176 AVAHI_LLIST_HEAD(AsyncAddressResolverInfo, async_address_resolvers);
177 AVAHI_LLIST_HEAD(DomainBrowserInfo, domain_browsers);
178 AVAHI_LLIST_HEAD(ServiceTypeBrowserInfo, service_type_browsers);
179 AVAHI_LLIST_HEAD(ServiceBrowserInfo, service_browsers);
180 AVAHI_LLIST_HEAD(SyncServiceResolverInfo, sync_service_resolvers);
181 AVAHI_LLIST_HEAD(AsyncServiceResolverInfo, async_service_resolvers);
186 AVAHI_LLIST_HEAD(Client, clients);
191 static Server *server = NULL;
193 static void entry_group_free(EntryGroupInfo *i) {
197 avahi_s_entry_group_free(i->entry_group);
198 dbus_connection_unregister_object_path(server->bus, i->path);
200 AVAHI_LLIST_REMOVE(EntryGroupInfo, entry_groups, i->client->entry_groups, i);
202 i->client->n_objects--;
203 assert(i->client->n_objects >= 0);
208 static void sync_host_name_resolver_free(SyncHostNameResolverInfo *i) {
211 if (i->host_name_resolver)
212 avahi_s_host_name_resolver_free(i->host_name_resolver);
213 dbus_message_unref(i->message);
214 AVAHI_LLIST_REMOVE(SyncHostNameResolverInfo, sync_host_name_resolvers, i->client->sync_host_name_resolvers, i);
216 i->client->n_objects--;
217 assert(i->client->n_objects >= 0);
222 static void async_host_name_resolver_free(AsyncHostNameResolverInfo *i) {
225 if (i->host_name_resolver)
226 avahi_s_host_name_resolver_free(i->host_name_resolver);
227 dbus_connection_unregister_object_path(server->bus, i->path);
228 AVAHI_LLIST_REMOVE(AsyncHostNameResolverInfo, async_host_name_resolvers, i->client->async_host_name_resolvers, i);
230 i->client->n_objects--;
231 assert(i->client->n_objects >= 0);
236 static void sync_address_resolver_free(SyncAddressResolverInfo *i) {
239 if (i->address_resolver)
240 avahi_s_address_resolver_free(i->address_resolver);
241 dbus_message_unref(i->message);
242 AVAHI_LLIST_REMOVE(SyncAddressResolverInfo, sync_address_resolvers, i->client->sync_address_resolvers, i);
244 i->client->n_objects--;
245 assert(i->client->n_objects >= 0);
250 static void async_address_resolver_free(AsyncAddressResolverInfo *i) {
253 if (i->address_resolver)
254 avahi_s_address_resolver_free(i->address_resolver);
255 dbus_connection_unregister_object_path(server->bus, i->path);
256 AVAHI_LLIST_REMOVE(AsyncAddressResolverInfo, async_address_resolvers, i->client->async_address_resolvers, i);
258 i->client->n_objects--;
259 assert(i->client->n_objects >= 0);
264 static void domain_browser_free(DomainBrowserInfo *i) {
267 if (i->domain_browser)
268 avahi_s_domain_browser_free(i->domain_browser);
269 dbus_connection_unregister_object_path(server->bus, i->path);
271 AVAHI_LLIST_REMOVE(DomainBrowserInfo, domain_browsers, i->client->domain_browsers, i);
273 i->client->n_objects--;
274 assert(i->client->n_objects >= 0);
279 static void service_type_browser_free(ServiceTypeBrowserInfo *i) {
282 if (i->service_type_browser)
283 avahi_s_service_type_browser_free(i->service_type_browser);
284 dbus_connection_unregister_object_path(server->bus, i->path);
286 AVAHI_LLIST_REMOVE(ServiceTypeBrowserInfo, service_type_browsers, i->client->service_type_browsers, i);
288 i->client->n_objects--;
289 assert(i->client->n_objects >= 0);
294 static void service_browser_free(ServiceBrowserInfo *i) {
297 if (i->service_browser)
298 avahi_s_service_browser_free(i->service_browser);
299 dbus_connection_unregister_object_path(server->bus, i->path);
301 AVAHI_LLIST_REMOVE(ServiceBrowserInfo, service_browsers, i->client->service_browsers, i);
303 i->client->n_objects--;
304 assert(i->client->n_objects >= 0);
309 static void sync_service_resolver_free(SyncServiceResolverInfo *i) {
312 if (i->service_resolver)
313 avahi_s_service_resolver_free(i->service_resolver);
314 dbus_message_unref(i->message);
315 AVAHI_LLIST_REMOVE(SyncServiceResolverInfo, sync_service_resolvers, i->client->sync_service_resolvers, i);
317 i->client->n_objects--;
318 assert(i->client->n_objects >= 0);
323 static void async_service_resolver_free(AsyncServiceResolverInfo *i) {
326 if (i->service_resolver)
327 avahi_s_service_resolver_free(i->service_resolver);
329 dbus_connection_unregister_object_path(server->bus, i->path);
330 AVAHI_LLIST_REMOVE(AsyncServiceResolverInfo, async_service_resolvers, i->client->async_service_resolvers, i);
332 i->client->n_objects--;
333 assert(i->client->n_objects >= 0);
338 static void client_free(Client *c) {
343 while (c->entry_groups)
344 entry_group_free(c->entry_groups);
346 while (c->sync_host_name_resolvers)
347 sync_host_name_resolver_free(c->sync_host_name_resolvers);
349 while (c->async_host_name_resolvers)
350 async_host_name_resolver_free(c->async_host_name_resolvers);
352 while (c->sync_address_resolvers)
353 sync_address_resolver_free(c->sync_address_resolvers);
355 while (c->async_address_resolvers)
356 async_address_resolver_free(c->async_address_resolvers);
358 while (c->domain_browsers)
359 domain_browser_free(c->domain_browsers);
361 while (c->service_type_browsers)
362 service_type_browser_free(c->service_type_browsers);
364 while (c->service_browsers)
365 service_browser_free(c->service_browsers);
367 while (c->sync_service_resolvers)
368 sync_service_resolver_free(c->sync_service_resolvers);
370 while (c->async_service_resolvers)
371 async_service_resolver_free(c->async_service_resolvers);
373 assert(c->n_objects == 0);
376 AVAHI_LLIST_REMOVE(Client, clients, server->clients, c);
379 server->n_clients --;
380 assert(server->n_clients >= 0);
383 static Client *client_get(const char *name, int create) {
389 for (client = server->clients; client; client = client->clients_next)
390 if (!strcmp(name, client->name))
396 if (server->n_clients >= MAX_CLIENTS)
399 /* If not existant yet, create a new entry */
400 client = avahi_new(Client, 1);
401 client->id = server->current_id++;
402 client->name = avahi_strdup(name);
403 client->current_id = 0;
404 client->n_objects = 0;
406 AVAHI_LLIST_HEAD_INIT(EntryGroupInfo, client->entry_groups);
407 AVAHI_LLIST_HEAD_INIT(SyncHostNameResolverInfo, client->sync_host_name_resolvers);
408 AVAHI_LLIST_HEAD_INIT(AsyncHostNameResolverInfo, client->async_host_name_resolvers);
409 AVAHI_LLIST_HEAD_INIT(SyncAddressResolverInfo, client->sync_address_resolvers);
410 AVAHI_LLIST_HEAD_INIT(AsyncAddressResolverInfo, client->async_address_resolvers);
411 AVAHI_LLIST_HEAD_INIT(DomainBrowserInfo, client->domain_browsers);
412 AVAHI_LLIST_HEAD_INIT(ServiceTypeBrowserInfo, client->service_type_browsers);
413 AVAHI_LLIST_HEAD_INIT(ServiceBrowserInfo, client->service_browsers);
414 AVAHI_LLIST_HEAD_INIT(SyncServiceResolverInfo, client->sync_service_resolvers);
415 AVAHI_LLIST_HEAD_INIT(AsyncServiceResolverInfo, client->async_service_resolvers);
417 AVAHI_LLIST_PREPEND(Client, clients, server->clients, client);
420 assert(server->n_clients > 0);
425 static DBusHandlerResult respond_error(DBusConnection *c, DBusMessage *m, int error, const char *text) {
428 assert(-error > -AVAHI_OK);
429 assert(-error < -AVAHI_ERR_MAX);
432 text = avahi_strerror(error);
434 reply = dbus_message_new_error(m, avahi_error_number_to_dbus(error), text);
435 dbus_connection_send(c, reply, NULL);
436 dbus_message_unref(reply);
438 avahi_log_debug(__FILE__": Responding error '%s' (%i)", text, error);
440 return DBUS_HANDLER_RESULT_HANDLED;
443 static DBusHandlerResult respond_string(DBusConnection *c, DBusMessage *m, const char *text) {
446 reply = dbus_message_new_method_return(m);
447 dbus_message_append_args(reply, DBUS_TYPE_STRING, &text, DBUS_TYPE_INVALID);
448 dbus_connection_send(c, reply, NULL);
449 dbus_message_unref(reply);
451 return DBUS_HANDLER_RESULT_HANDLED;
454 static DBusHandlerResult respond_int32(DBusConnection *c, DBusMessage *m, int32_t i) {
457 reply = dbus_message_new_method_return(m);
458 dbus_message_append_args(reply, DBUS_TYPE_INT32, &i, DBUS_TYPE_INVALID);
459 dbus_connection_send(c, reply, NULL);
460 dbus_message_unref(reply);
462 return DBUS_HANDLER_RESULT_HANDLED;
465 static DBusHandlerResult respond_uint32(DBusConnection *c, DBusMessage *m, uint32_t u) {
468 reply = dbus_message_new_method_return(m);
469 dbus_message_append_args(reply, DBUS_TYPE_UINT32, &u, DBUS_TYPE_INVALID);
470 dbus_connection_send(c, reply, NULL);
471 dbus_message_unref(reply);
473 return DBUS_HANDLER_RESULT_HANDLED;
476 static DBusHandlerResult respond_boolean(DBusConnection *c, DBusMessage *m, int b) {
479 reply = dbus_message_new_method_return(m);
480 dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &b, DBUS_TYPE_INVALID);
481 dbus_connection_send(c, reply, NULL);
482 dbus_message_unref(reply);
484 return DBUS_HANDLER_RESULT_HANDLED;
487 static DBusHandlerResult respond_ok(DBusConnection *c, DBusMessage *m) {
490 reply = dbus_message_new_method_return(m);
491 dbus_connection_send(c, reply, NULL);
492 dbus_message_unref(reply);
494 return DBUS_HANDLER_RESULT_HANDLED;
497 static DBusHandlerResult respond_path(DBusConnection *c, DBusMessage *m, const char *path) {
500 reply = dbus_message_new_method_return(m);
501 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID);
502 dbus_connection_send(c, reply, NULL);
503 dbus_message_unref(reply);
505 return DBUS_HANDLER_RESULT_HANDLED;
508 static void append_server_error(DBusMessage *reply) {
511 t = avahi_error_number_to_dbus(avahi_server_errno(avahi_server));
513 dbus_message_append_args(
515 DBUS_TYPE_STRING, &t,
519 static char *file_get_contents(char *fname) {
527 if (!(fd = open(fname, O_RDONLY))) {
528 avahi_log_error("Failed to open %s: %s", fname, strerror(errno));
532 if (fstat(fd, &st) < 0) {
533 avahi_log_error("stat(%s) failed: %s", fname, strerror(errno));
537 if (!(S_ISREG(st.st_mode))) {
538 avahi_log_error("Invalid file %s", fname);
542 if (st.st_size > 1024*1024) { /** 1MB */
543 avahi_log_error("File too large %s", fname);
547 buf = avahi_new(char, st.st_size+1);
549 if ((size = read(fd, buf, st.st_size)) < 0) {
550 avahi_log_error("read() failed: %s\n", strerror(errno));
570 static const char *map_browse_signal_name(AvahiBrowserEvent e) {
572 case AVAHI_BROWSER_NEW : return "ItemNew";
573 case AVAHI_BROWSER_REMOVE : return "ItemRemove";
574 case AVAHI_BROWSER_FAILURE : return "Failure";
575 case AVAHI_BROWSER_CACHE_EXHAUSTED : return "CacheExhausted";
576 case AVAHI_BROWSER_ALL_FOR_NOW : return "AllForNow";
582 static const char *map_resolve_signal_name(AvahiResolverEvent e) {
584 case AVAHI_RESOLVER_FOUND : return "Found";
585 case AVAHI_RESOLVER_FAILURE : return "Failure";
592 static DBusHandlerResult handle_introspect(DBusConnection *c, DBusMessage *m, const char *fname) {
593 char *path, *contents;
600 dbus_error_init(&error);
602 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
603 avahi_log_error("Error parsing Introspect message: %s", error.message);
607 path = avahi_strdup_printf("%s/%s", AVAHI_DBUS_INTROSPECTION_DIR, fname);
608 contents = file_get_contents(path);
612 avahi_log_error("Failed to load introspection data.");
616 respond_string(c, m, contents);
617 avahi_free(contents);
619 return DBUS_HANDLER_RESULT_HANDLED;
622 if (dbus_error_is_set(&error))
623 dbus_error_free(&error);
625 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
629 static DBusHandlerResult msg_signal_filter_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
632 dbus_error_init(&error);
634 /* avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s", */
635 /* dbus_message_get_interface(m), */
636 /* dbus_message_get_path(m), */
637 /* dbus_message_get_member(m)); */
639 if (dbus_message_is_signal(m, DBUS_INTERFACE_LOCAL, "Disconnected")) {
640 /* No, we shouldn't quit, but until we get somewhere
641 * usefull such that we can restore our state, we will */
642 avahi_log_warn("Disconnnected from D-BUS, terminating...");
644 raise(SIGQUIT); /* The signal handler will catch this and terminate the process cleanly*/
646 return DBUS_HANDLER_RESULT_HANDLED;
648 } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameAcquired")) {
651 if (!dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID)) {
652 avahi_log_warn("Error parsing NameAcquired message");
656 /* avahi_log_info(__FILE__": name acquired (%s)", name); */
657 return DBUS_HANDLER_RESULT_HANDLED;
659 } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
660 char *name, *old, *new;
662 if (!dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &old, DBUS_TYPE_STRING, &new, DBUS_TYPE_INVALID)) {
663 avahi_log_warn("Error parsing NameOwnerChanged message");
670 if ((client = client_get(name, FALSE))) {
671 avahi_log_debug(__FILE__": client %s vanished.", name);
678 if (dbus_error_is_set(&error))
679 dbus_error_free(&error);
681 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
684 static void entry_group_callback(AvahiServer *s, AvahiSEntryGroup *g, AvahiEntryGroupState state, void* userdata) {
685 EntryGroupInfo *i = userdata;
693 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "StateChanged");
695 dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_INVALID);
696 dbus_message_set_destination(m, i->client->name);
697 dbus_connection_send(server->bus, m, NULL);
698 dbus_message_unref(m);
701 static int read_strlst(DBusMessage *m, int idx, AvahiStringList **l) {
702 DBusMessageIter iter, sub;
704 AvahiStringList *strlst = NULL;
709 dbus_message_iter_init(m, &iter);
711 for (j = 0; j < idx; j++)
712 dbus_message_iter_next(&iter);
714 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
715 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_ARRAY)
718 dbus_message_iter_recurse(&iter, &sub);
721 DBusMessageIter sub2;
725 if ((at = dbus_message_iter_get_arg_type(&sub)) == DBUS_TYPE_INVALID)
728 assert(at == DBUS_TYPE_ARRAY);
730 if (dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_BYTE)
733 dbus_message_iter_recurse(&sub, &sub2);
734 dbus_message_iter_get_fixed_array(&sub2, &k, &n);
735 strlst = avahi_string_list_add_arbitrary(strlst, k, n);
737 dbus_message_iter_next(&sub);
745 avahi_log_warn("Error parsing TXT data");
747 avahi_string_list_free(strlst);
753 static DBusHandlerResult msg_entry_group_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
755 EntryGroupInfo *i = userdata;
761 dbus_error_init(&error);
763 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
764 dbus_message_get_interface(m),
765 dbus_message_get_path(m),
766 dbus_message_get_member(m));
769 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
770 return handle_introspect(c, m, "EntryGroup.introspect");
773 if (strcmp(dbus_message_get_sender(m), i->client->name))
774 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
776 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Free")) {
778 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
779 avahi_log_warn("Error parsing EntryGroup::Free message");
784 return respond_ok(c, m);
786 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Commit")) {
788 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
789 avahi_log_warn("Error parsing EntryGroup::Commit message");
793 avahi_s_entry_group_commit(i->entry_group);
794 return respond_ok(c, m);
797 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Reset")) {
799 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
800 avahi_log_warn("Error parsing EntryGroup::Reset message");
804 avahi_s_entry_group_reset(i->entry_group);
806 return respond_ok(c, m);
808 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "IsEmpty")) {
810 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
811 avahi_log_warn("Error parsing EntryGroup::IsEmpty message");
815 return respond_boolean(c, m, !!avahi_s_entry_group_is_empty(i->entry_group));
817 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "GetState")) {
818 AvahiEntryGroupState state;
820 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
821 avahi_log_warn("Error parsing EntryGroup::GetState message");
825 state = avahi_s_entry_group_get_state(i->entry_group);
826 return respond_int32(c, m, (int32_t) state);
828 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddService")) {
829 int32_t interface, protocol;
831 char *type, *name, *domain, *host;
833 AvahiStringList *strlst = NULL;
835 if (!dbus_message_get_args(
837 DBUS_TYPE_INT32, &interface,
838 DBUS_TYPE_INT32, &protocol,
839 DBUS_TYPE_UINT32, &flags,
840 DBUS_TYPE_STRING, &name,
841 DBUS_TYPE_STRING, &type,
842 DBUS_TYPE_STRING, &domain,
843 DBUS_TYPE_STRING, &host,
844 DBUS_TYPE_UINT16, &port,
845 DBUS_TYPE_INVALID) ||
847 read_strlst(m, 8, &strlst) < 0) {
848 avahi_log_warn("Error parsing EntryGroup::AddService message");
852 if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) {
853 avahi_string_list_free(strlst);
854 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
857 if (domain && !*domain)
863 if (avahi_server_add_service_strlst(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, type, domain, host, port, strlst) < 0) {
864 avahi_string_list_free(strlst);
865 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
868 if (!(flags & AVAHI_PUBLISH_UPDATE))
871 avahi_string_list_free(strlst);
873 return respond_ok(c, m);
875 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddServiceSubtype")) {
877 int32_t interface, protocol;
879 char *type, *name, *domain, *subtype;
881 if (!dbus_message_get_args(
883 DBUS_TYPE_INT32, &interface,
884 DBUS_TYPE_INT32, &protocol,
885 DBUS_TYPE_UINT32, &flags,
886 DBUS_TYPE_STRING, &name,
887 DBUS_TYPE_STRING, &type,
888 DBUS_TYPE_STRING, &domain,
889 DBUS_TYPE_STRING, &subtype,
890 DBUS_TYPE_INVALID) || !type || !name || !subtype) {
891 avahi_log_warn("Error parsing EntryGroup::AddServiceSubtype message");
895 if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP)
896 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
898 if (domain && !*domain)
901 if (avahi_server_add_service_subtype(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, type, domain, subtype) < 0)
902 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
904 if (!(flags & AVAHI_PUBLISH_UPDATE))
907 return respond_ok(c, m);
909 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "UpdateServiceTxt")) {
910 int32_t interface, protocol;
912 char *type, *name, *domain;
913 AvahiStringList *strlst;
915 if (!dbus_message_get_args(
917 DBUS_TYPE_INT32, &interface,
918 DBUS_TYPE_INT32, &protocol,
919 DBUS_TYPE_UINT32, &flags,
920 DBUS_TYPE_STRING, &name,
921 DBUS_TYPE_STRING, &type,
922 DBUS_TYPE_STRING, &domain,
923 DBUS_TYPE_INVALID) ||
925 read_strlst(m, 6, &strlst)) {
926 avahi_log_warn("Error parsing EntryGroup::UpdateServiceTxt message");
930 if (domain && !*domain)
933 if (avahi_server_update_service_txt_strlst(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, type, domain, strlst) < 0) {
934 avahi_string_list_free(strlst);
935 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
938 avahi_string_list_free(strlst);
940 return respond_ok(c, m);
942 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddAddress")) {
943 int32_t interface, protocol;
945 char *name, *address;
948 if (!dbus_message_get_args(
950 DBUS_TYPE_INT32, &interface,
951 DBUS_TYPE_INT32, &protocol,
952 DBUS_TYPE_UINT32, &flags,
953 DBUS_TYPE_STRING, &name,
954 DBUS_TYPE_STRING, &address,
955 DBUS_TYPE_INVALID) || !name || !address) {
956 avahi_log_warn("Error parsing EntryGroup::AddAddress message");
960 if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP)
961 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
963 if (!(avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a)))
964 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
966 if (avahi_server_add_address(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, &a) < 0)
967 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
969 if (!(flags & AVAHI_PUBLISH_UPDATE))
972 return respond_ok(c, m);
975 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
978 if (dbus_error_is_set(&error))
979 dbus_error_free(&error);
981 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
984 static void sync_host_name_resolver_callback(AvahiSHostNameResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const char *host_name, const AvahiAddress *a, AvahiLookupResultFlags flags, void* userdata) {
985 SyncHostNameResolverInfo *i = userdata;
991 if (event == AVAHI_RESOLVER_FOUND) {
992 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
993 int32_t i_interface, i_protocol, i_aprotocol;
998 avahi_address_snprint(t, sizeof(t), a);
1000 i_interface = (int32_t) interface;
1001 i_protocol = (int32_t) protocol;
1002 i_aprotocol = (int32_t) a->proto;
1003 u_flags = (uint32_t) flags;
1005 reply = dbus_message_new_method_return(i->message);
1006 dbus_message_append_args(
1008 DBUS_TYPE_INT32, &i_interface,
1009 DBUS_TYPE_INT32, &i_protocol,
1010 DBUS_TYPE_STRING, &host_name,
1011 DBUS_TYPE_INT32, &i_aprotocol,
1012 DBUS_TYPE_STRING, &pt,
1013 DBUS_TYPE_UINT32, &u_flags,
1016 dbus_connection_send(server->bus, reply, NULL);
1017 dbus_message_unref(reply);
1019 assert(event == AVAHI_RESOLVER_FAILURE);
1020 respond_error(server->bus, i->message, avahi_server_errno(avahi_server), NULL);
1023 sync_host_name_resolver_free(i);
1026 static void sync_address_resolver_callback(AvahiSAddressResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const AvahiAddress *address, const char *host_name, AvahiLookupResultFlags flags, void* userdata) {
1027 SyncAddressResolverInfo *i = userdata;
1033 if (event == AVAHI_RESOLVER_FOUND) {
1034 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1035 int32_t i_interface, i_protocol, i_aprotocol;
1040 avahi_address_snprint(t, sizeof(t), address);
1042 i_interface = (int32_t) interface;
1043 i_protocol = (int32_t) protocol;
1044 i_aprotocol = (int32_t) address->proto;
1045 u_flags = (uint32_t) flags;
1047 reply = dbus_message_new_method_return(i->message);
1048 dbus_message_append_args(
1050 DBUS_TYPE_INT32, &i_interface,
1051 DBUS_TYPE_INT32, &i_protocol,
1052 DBUS_TYPE_INT32, &i_aprotocol,
1053 DBUS_TYPE_STRING, &pt,
1054 DBUS_TYPE_STRING, &host_name,
1055 DBUS_TYPE_UINT32, &u_flags,
1058 dbus_connection_send(server->bus, reply, NULL);
1059 dbus_message_unref(reply);
1061 assert(event == AVAHI_RESOLVER_FAILURE);
1062 respond_error(server->bus, i->message, avahi_server_errno(avahi_server), NULL);
1065 sync_address_resolver_free(i);
1068 static DBusHandlerResult msg_domain_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1070 DomainBrowserInfo *i = userdata;
1076 dbus_error_init(&error);
1078 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1079 dbus_message_get_interface(m),
1080 dbus_message_get_path(m),
1081 dbus_message_get_member(m));
1084 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1085 return handle_introspect(c, m, "DomainBrowser.introspect");
1087 /* Access control */
1088 if (strcmp(dbus_message_get_sender(m), i->client->name))
1089 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1091 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, "Free")) {
1093 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1094 avahi_log_warn("Error parsing DomainBrowser::Free message");
1098 domain_browser_free(i);
1099 return respond_ok(c, m);
1103 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1106 if (dbus_error_is_set(&error))
1107 dbus_error_free(&error);
1109 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1112 static void domain_browser_callback(AvahiSDomainBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *domain, AvahiLookupResultFlags flags, void* userdata) {
1113 DomainBrowserInfo *i = userdata;
1115 int32_t i_interface, i_protocol;
1121 i_interface = (int32_t) interface;
1122 i_protocol = (int32_t) protocol;
1123 u_flags = (uint32_t) flags;
1125 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, map_browse_signal_name(event));
1127 if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1129 dbus_message_append_args(
1131 DBUS_TYPE_INT32, &i_interface,
1132 DBUS_TYPE_INT32, &i_protocol,
1133 DBUS_TYPE_STRING, &domain,
1134 DBUS_TYPE_UINT32, &u_flags,
1136 } else if (event == AVAHI_BROWSER_FAILURE)
1137 append_server_error(m);
1139 dbus_message_set_destination(m, i->client->name);
1140 dbus_connection_send(server->bus, m, NULL);
1141 dbus_message_unref(m);
1144 static DBusHandlerResult msg_service_type_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1146 ServiceTypeBrowserInfo *i = userdata;
1152 dbus_error_init(&error);
1154 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1155 dbus_message_get_interface(m),
1156 dbus_message_get_path(m),
1157 dbus_message_get_member(m));
1160 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1161 return handle_introspect(c, m, "ServiceTypeBrowser.introspect");
1163 /* Access control */
1164 if (strcmp(dbus_message_get_sender(m), i->client->name))
1165 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1167 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, "Free")) {
1169 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1170 avahi_log_warn("Error parsing ServiceTypeBrowser::Free message");
1174 service_type_browser_free(i);
1175 return respond_ok(c, m);
1179 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1182 if (dbus_error_is_set(&error))
1183 dbus_error_free(&error);
1185 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1188 static void service_type_browser_callback(AvahiSServiceTypeBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *type, const char *domain, AvahiLookupResultFlags flags, void* userdata) {
1189 ServiceTypeBrowserInfo *i = userdata;
1191 int32_t i_interface, i_protocol;
1197 i_interface = (int32_t) interface;
1198 i_protocol = (int32_t) protocol;
1199 u_flags = (uint32_t) flags;
1201 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, map_browse_signal_name(event));
1203 if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1206 dbus_message_append_args(
1208 DBUS_TYPE_INT32, &i_interface,
1209 DBUS_TYPE_INT32, &i_protocol,
1210 DBUS_TYPE_STRING, &type,
1211 DBUS_TYPE_STRING, &domain,
1212 DBUS_TYPE_UINT32, &u_flags,
1214 } else if (event == AVAHI_BROWSER_FAILURE)
1215 append_server_error(m);
1217 dbus_message_set_destination(m, i->client->name);
1218 dbus_connection_send(server->bus, m, NULL);
1219 dbus_message_unref(m);
1222 static DBusHandlerResult msg_service_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1224 ServiceBrowserInfo *i = userdata;
1230 dbus_error_init(&error);
1232 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1233 dbus_message_get_interface(m),
1234 dbus_message_get_path(m),
1235 dbus_message_get_member(m));
1238 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1239 return handle_introspect(c, m, "ServiceBrowser.Introspect");
1241 /* Access control */
1242 if (strcmp(dbus_message_get_sender(m), i->client->name))
1243 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1245 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, "Free")) {
1247 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1248 avahi_log_warn("Error parsing ServiceBrowser::Free message");
1252 service_browser_free(i);
1253 return respond_ok(c, m);
1257 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1260 if (dbus_error_is_set(&error))
1261 dbus_error_free(&error);
1263 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1266 static int is_our_own_service(Client *c, AvahiIfIndex interface, AvahiProtocol protocol, const char *name, const char *type, const char *domain) {
1267 AvahiSEntryGroup *g;
1270 if (avahi_server_get_group_of_service(avahi_server, interface, protocol, name, type, domain, &g) == AVAHI_OK) {
1271 EntryGroupInfo *egi;
1273 for (egi = c->entry_groups; egi; egi = egi->entry_groups_next)
1274 if (egi->entry_group == g)
1281 static void service_browser_callback(AvahiSServiceBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AvahiLookupResultFlags flags, void* userdata) {
1282 ServiceBrowserInfo *i = userdata;
1284 int32_t i_interface, i_protocol;
1290 i_interface = (int32_t) interface;
1291 i_protocol = (int32_t) protocol;
1292 u_flags = (uint32_t) flags;
1294 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, map_browse_signal_name(event));
1296 if (event == AVAHI_BROWSER_NEW) {
1297 /* Patch in AVAHI_LOOKUP_RESULT_OUR_OWN */
1299 if (is_our_own_service(i->client, interface, protocol, name, type, domain) > 0)
1300 flags |= AVAHI_LOOKUP_RESULT_OUR_OWN;
1303 if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1308 dbus_message_append_args(
1310 DBUS_TYPE_INT32, &i_interface,
1311 DBUS_TYPE_INT32, &i_protocol,
1312 DBUS_TYPE_STRING, &name,
1313 DBUS_TYPE_STRING, &type,
1314 DBUS_TYPE_STRING, &domain,
1315 DBUS_TYPE_UINT32, &u_flags,
1317 } else if (event == AVAHI_BROWSER_FAILURE)
1318 append_server_error(m);
1320 dbus_message_set_destination(m, i->client->name);
1321 dbus_connection_send(server->bus, m, NULL);
1322 dbus_message_unref(m);
1325 static void append_string_list(DBusMessage *reply, AvahiStringList *txt) {
1327 DBusMessageIter iter, sub;
1331 dbus_message_iter_init_append(reply, &iter);
1332 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "ay", &sub);
1334 for (p = txt; p; p = p->next) {
1335 DBusMessageIter sub2;
1336 const uint8_t *data = p->text;
1338 dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "y", &sub2);
1339 dbus_message_iter_append_fixed_array(&sub2, DBUS_TYPE_BYTE, &data, p->size);
1340 dbus_message_iter_close_container(&sub, &sub2);
1343 dbus_message_iter_close_container(&iter, &sub);
1346 static void sync_service_resolver_callback(
1347 AvahiSServiceResolver *r,
1348 AvahiIfIndex interface,
1349 AvahiProtocol protocol,
1350 AvahiResolverEvent event,
1354 const char *host_name,
1355 const AvahiAddress *a,
1357 AvahiStringList *txt,
1358 AvahiLookupResultFlags flags,
1361 SyncServiceResolverInfo *i = userdata;
1366 if (event == AVAHI_RESOLVER_FOUND) {
1367 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1368 int32_t i_interface, i_protocol, i_aprotocol;
1378 avahi_address_snprint(t, sizeof(t), a);
1382 /* Patch in AVAHI_LOOKUP_RESULT_OUR_OWN */
1384 if (is_our_own_service(i->client, interface, protocol, name, type, domain) > 0)
1385 flags |= AVAHI_LOOKUP_RESULT_OUR_OWN;
1387 i_interface = (int32_t) interface;
1388 i_protocol = (int32_t) protocol;
1390 i_aprotocol = (int32_t) a->proto;
1392 i_aprotocol = AVAHI_PROTO_UNSPEC;
1393 u_flags = (uint32_t) flags;
1395 reply = dbus_message_new_method_return(i->message);
1396 dbus_message_append_args(
1398 DBUS_TYPE_INT32, &i_interface,
1399 DBUS_TYPE_INT32, &i_protocol,
1400 DBUS_TYPE_STRING, &name,
1401 DBUS_TYPE_STRING, &type,
1402 DBUS_TYPE_STRING, &domain,
1403 DBUS_TYPE_STRING, &host_name,
1404 DBUS_TYPE_INT32, &i_aprotocol,
1405 DBUS_TYPE_STRING, &pt,
1406 DBUS_TYPE_UINT16, &port,
1409 append_string_list(reply, txt);
1411 dbus_message_append_args(
1413 DBUS_TYPE_UINT32, &u_flags,
1416 dbus_connection_send(server->bus, reply, NULL);
1417 dbus_message_unref(reply);
1419 assert(event == AVAHI_RESOLVER_FAILURE);
1421 respond_error(server->bus, i->message, avahi_server_errno(avahi_server), NULL);
1424 sync_service_resolver_free(i);
1427 static void async_address_resolver_callback(AvahiSAddressResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const AvahiAddress *address, const char *host_name, AvahiLookupResultFlags flags, void* userdata) {
1428 AsyncAddressResolverInfo *i = userdata;
1434 reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_ADDRESS_RESOLVER, map_resolve_signal_name(event));
1436 if (event == AVAHI_RESOLVER_FOUND) {
1437 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1438 int32_t i_interface, i_protocol, i_aprotocol;
1443 avahi_address_snprint(t, sizeof(t), address);
1445 i_interface = (int32_t) interface;
1446 i_protocol = (int32_t) protocol;
1447 i_aprotocol = (int32_t) address->proto;
1448 u_flags = (uint32_t) flags;
1450 dbus_message_append_args(
1452 DBUS_TYPE_INT32, &i_interface,
1453 DBUS_TYPE_INT32, &i_protocol,
1454 DBUS_TYPE_INT32, &i_aprotocol,
1455 DBUS_TYPE_STRING, &pt,
1456 DBUS_TYPE_STRING, &host_name,
1457 DBUS_TYPE_UINT32, &u_flags,
1461 assert(event == AVAHI_RESOLVER_FAILURE);
1462 append_server_error(reply);
1465 dbus_message_set_destination(reply, i->client->name);
1466 dbus_connection_send(server->bus, reply, NULL);
1467 dbus_message_unref(reply);
1470 static DBusHandlerResult msg_async_address_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1472 AsyncAddressResolverInfo *i = userdata;
1478 dbus_error_init(&error);
1480 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1481 dbus_message_get_interface(m),
1482 dbus_message_get_path(m),
1483 dbus_message_get_member(m));
1486 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1487 return handle_introspect(c, m, "AddressResolver.Introspect");
1489 /* Access control */
1490 if (strcmp(dbus_message_get_sender(m), i->client->name))
1491 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1493 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ADDRESS_RESOLVER, "Free")) {
1495 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1496 avahi_log_warn("Error parsing AddressResolver::Free message");
1500 async_address_resolver_free(i);
1501 return respond_ok(c, m);
1505 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1508 if (dbus_error_is_set(&error))
1509 dbus_error_free(&error);
1511 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1514 static void async_host_name_resolver_callback(AvahiSHostNameResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const char *host_name, const AvahiAddress *a, AvahiLookupResultFlags flags, void* userdata) {
1515 AsyncHostNameResolverInfo *i = userdata;
1521 reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_HOST_NAME_RESOLVER, map_resolve_signal_name(event));
1523 if (event == AVAHI_RESOLVER_FOUND) {
1524 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1525 int32_t i_interface, i_protocol, i_aprotocol;
1530 avahi_address_snprint(t, sizeof(t), a);
1532 i_interface = (int32_t) interface;
1533 i_protocol = (int32_t) protocol;
1534 i_aprotocol = (int32_t) a->proto;
1535 u_flags = (uint32_t) flags;
1537 dbus_message_append_args(
1539 DBUS_TYPE_INT32, &i_interface,
1540 DBUS_TYPE_INT32, &i_protocol,
1541 DBUS_TYPE_STRING, &host_name,
1542 DBUS_TYPE_INT32, &i_aprotocol,
1543 DBUS_TYPE_STRING, &pt,
1544 DBUS_TYPE_UINT32, &u_flags,
1547 assert(event == AVAHI_RESOLVER_FAILURE);
1548 append_server_error(reply);
1551 dbus_message_set_destination(reply, i->client->name);
1552 dbus_connection_send(server->bus, reply, NULL);
1553 dbus_message_unref(reply);
1556 static DBusHandlerResult msg_async_host_name_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1558 AsyncHostNameResolverInfo *i = userdata;
1564 dbus_error_init(&error);
1566 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1567 dbus_message_get_interface(m),
1568 dbus_message_get_path(m),
1569 dbus_message_get_member(m));
1572 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1573 return handle_introspect(c, m, "HostNameResolver.Introspect");
1575 /* Access control */
1576 if (strcmp(dbus_message_get_sender(m), i->client->name))
1577 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1579 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_HOST_NAME_RESOLVER, "Free")) {
1581 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1582 avahi_log_warn("Error parsing HostNameResolver::Free message");
1586 async_host_name_resolver_free(i);
1587 return respond_ok(c, m);
1590 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1593 if (dbus_error_is_set(&error))
1594 dbus_error_free(&error);
1596 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1599 static void async_service_resolver_callback(
1600 AvahiSServiceResolver *r,
1601 AvahiIfIndex interface,
1602 AvahiProtocol protocol,
1603 AvahiResolverEvent event,
1607 const char *host_name,
1608 const AvahiAddress *a,
1610 AvahiStringList *txt,
1611 AvahiLookupResultFlags flags,
1614 AsyncServiceResolverInfo *i = userdata;
1620 reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_RESOLVER, map_resolve_signal_name(event));
1622 if (event == AVAHI_RESOLVER_FOUND) {
1623 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1624 int32_t i_interface, i_protocol, i_aprotocol;
1629 /* avahi_log_debug(__FILE__": [%s] Successfully resolved service <%s.%s.%s>", i->path, name, type, domain); */
1632 avahi_address_snprint(t, sizeof(t), a);
1639 if (is_our_own_service(i->client, interface, protocol, name, type, domain) > 0)
1640 flags |= AVAHI_LOOKUP_RESULT_OUR_OWN;
1642 i_interface = (int32_t) interface;
1643 i_protocol = (int32_t) protocol;
1645 i_aprotocol = (int32_t) a->proto;
1647 i_aprotocol = AVAHI_PROTO_UNSPEC;
1648 u_flags = (uint32_t) flags;
1650 dbus_message_append_args(
1652 DBUS_TYPE_INT32, &i_interface,
1653 DBUS_TYPE_INT32, &i_protocol,
1654 DBUS_TYPE_STRING, &name,
1655 DBUS_TYPE_STRING, &type,
1656 DBUS_TYPE_STRING, &domain,
1657 DBUS_TYPE_STRING, &host_name,
1658 DBUS_TYPE_INT32, &i_aprotocol,
1659 DBUS_TYPE_STRING, &pt,
1660 DBUS_TYPE_UINT16, &port,
1663 append_string_list(reply, txt);
1665 dbus_message_append_args(
1667 DBUS_TYPE_UINT32, &u_flags,
1670 assert(event == AVAHI_RESOLVER_FAILURE);
1671 append_server_error(reply);
1674 dbus_message_set_destination(reply, i->client->name);
1675 dbus_connection_send(server->bus, reply, NULL);
1676 dbus_message_unref(reply);
1679 static DBusHandlerResult msg_async_service_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1681 AsyncServiceResolverInfo *i = userdata;
1687 dbus_error_init(&error);
1689 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1690 dbus_message_get_interface(m),
1691 dbus_message_get_path(m),
1692 dbus_message_get_member(m));
1695 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1696 return handle_introspect(c, m, "ServiceResolver.Introspect");
1698 /* Access control */
1699 if (strcmp(dbus_message_get_sender(m), i->client->name))
1700 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1702 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_RESOLVER, "Free")) {
1704 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1705 avahi_log_warn("Error parsing ServiceResolver::Free message");
1709 async_service_resolver_free(i);
1710 return respond_ok(c, m);
1713 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1716 if (dbus_error_is_set(&error))
1717 dbus_error_free(&error);
1719 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1722 static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1725 dbus_error_init(&error);
1727 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1728 dbus_message_get_interface(m),
1729 dbus_message_get_path(m),
1730 dbus_message_get_member(m));
1732 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1733 return handle_introspect(c, m, "Server.introspect");
1735 else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostName")) {
1737 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1738 avahi_log_warn("Error parsing Server::GetHostName message");
1742 return respond_string(c, m, avahi_server_get_host_name(avahi_server));
1744 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetDomainName")) {
1746 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1747 avahi_log_warn("Error parsing Server::GetDomainName message");
1751 return respond_string(c, m, avahi_server_get_domain_name(avahi_server));
1753 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostNameFqdn")) {
1755 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1756 avahi_log_warn("Error parsing Server::GetHostNameFqdn message");
1760 return respond_string(c, m, avahi_server_get_host_name_fqdn(avahi_server));
1762 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetVersionString")) {
1764 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1765 avahi_log_warn("Error parsing Server::GetVersionString message");
1769 return respond_string(c, m, PACKAGE_STRING);
1771 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetState")) {
1772 AvahiServerState state;
1774 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1775 avahi_log_warn("Error parsing Server::GetState message");
1779 state = avahi_server_get_state(avahi_server);
1780 return respond_int32(c, m, (int32_t) state);
1782 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetLocalServiceCookie")) {
1784 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1785 avahi_log_warn("Error parsing Server::GetLocalServiceCookie message");
1789 return respond_uint32(c, m, avahi_server_get_local_service_cookie(avahi_server));
1791 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceNameByIndex")) {
1796 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INT32, &idx, DBUS_TYPE_INVALID))) {
1797 avahi_log_warn("Error parsing Server::GetNetworkInterfaceNameByIndex message");
1801 #ifdef VALGRIND_WORKAROUND
1802 return respond_string(c, m, "blah");
1805 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
1806 if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1808 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1809 return respond_error(c, m, AVAHI_ERR_OS, txt);
1812 memset(&ifr, 0, sizeof(ifr));
1814 ifr.ifr_ifindex = idx;
1816 if (ioctl(fd, SIOCGIFNAME, &ifr) < 0) {
1818 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1820 return respond_error(c, m, AVAHI_ERR_OS, txt);
1825 return respond_string(c, m, ifr.ifr_name);
1828 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceIndexByName")) {
1833 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1834 avahi_log_warn("Error parsing Server::GetNetworkInterfaceIndexByName message");
1838 #ifdef VALGRIND_WORKAROUND
1839 return respond_int32(c, m, 1);
1841 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
1842 if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1844 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1845 return respond_error(c, m, AVAHI_ERR_OS, txt);
1848 memset(&ifr, 0, sizeof(ifr));
1849 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", n);
1851 if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
1853 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1855 return respond_error(c, m, AVAHI_ERR_OS, txt);
1860 return respond_int32(c, m, ifr.ifr_ifindex);
1863 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeHostName")) {
1866 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1867 avahi_log_warn("Error parsing Server::GetAlternativeHostName message");
1871 t = avahi_alternative_host_name(n);
1872 respond_string(c, m, t);
1875 return DBUS_HANDLER_RESULT_HANDLED;
1877 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeServiceName")) {
1880 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1881 avahi_log_warn("Error parsing Server::GetAlternativeServiceName message");
1885 t = avahi_alternative_service_name(n);
1886 respond_string(c, m, t);
1889 return DBUS_HANDLER_RESULT_HANDLED;
1891 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "EntryGroupNew")) {
1894 static const DBusObjectPathVTable vtable = {
1896 msg_entry_group_impl,
1903 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1904 avahi_log_warn("Error parsing Server::EntryGroupNew message");
1908 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1909 avahi_log_warn("Too many clients, client request failed.");
1910 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1913 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1914 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1915 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1918 i = avahi_new(EntryGroupInfo, 1);
1919 i->id = ++client->current_id;
1921 i->path = avahi_strdup_printf("/Client%u/EntryGroup%u", client->id, i->id);
1923 AVAHI_LLIST_PREPEND(EntryGroupInfo, entry_groups, client->entry_groups, i);
1924 client->n_objects++;
1926 if (!(i->entry_group = avahi_s_entry_group_new(avahi_server, entry_group_callback, i))) {
1927 entry_group_free(i);
1928 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1931 dbus_connection_register_object_path(c, i->path, &vtable, i);
1932 return respond_path(c, m, i->path);
1934 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveHostName")) {
1936 int32_t interface, protocol, aprotocol;
1939 SyncHostNameResolverInfo *i;
1941 if (!dbus_message_get_args(
1943 DBUS_TYPE_INT32, &interface,
1944 DBUS_TYPE_INT32, &protocol,
1945 DBUS_TYPE_STRING, &name,
1946 DBUS_TYPE_INT32, &aprotocol,
1947 DBUS_TYPE_UINT32, &flags,
1948 DBUS_TYPE_INVALID) || !name) {
1949 avahi_log_warn("Error parsing Server::ResolveHostName message");
1953 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1954 avahi_log_warn("Too many clients, client request failed.");
1955 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1958 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1959 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1960 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1963 i = avahi_new(SyncHostNameResolverInfo, 1);
1965 i->message = dbus_message_ref(m);
1966 AVAHI_LLIST_PREPEND(SyncHostNameResolverInfo, sync_host_name_resolvers, client->sync_host_name_resolvers, i);
1967 client->n_objects++;
1969 if (!(i->host_name_resolver = avahi_s_host_name_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, (AvahiProtocol) aprotocol, (AvahiLookupFlags) flags, sync_host_name_resolver_callback, i))) {
1970 sync_host_name_resolver_free(i);
1971 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1974 return DBUS_HANDLER_RESULT_HANDLED;
1976 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveAddress")) {
1978 int32_t interface, protocol;
1981 SyncAddressResolverInfo *i;
1984 if (!dbus_message_get_args(
1986 DBUS_TYPE_INT32, &interface,
1987 DBUS_TYPE_INT32, &protocol,
1988 DBUS_TYPE_STRING, &address,
1989 DBUS_TYPE_UINT32, &flags,
1990 DBUS_TYPE_INVALID) || !address) {
1991 avahi_log_warn("Error parsing Server::ResolveAddress message");
1995 if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
1996 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
1998 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1999 avahi_log_warn("Too many clients, client request failed.");
2000 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2003 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2004 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2005 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2008 i = avahi_new(SyncAddressResolverInfo, 1);
2010 i->message = dbus_message_ref(m);
2011 AVAHI_LLIST_PREPEND(SyncAddressResolverInfo, sync_address_resolvers, client->sync_address_resolvers, i);
2012 client->n_objects++;
2014 if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, (AvahiLookupFlags) flags, sync_address_resolver_callback, i))) {
2015 sync_address_resolver_free(i);
2016 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2019 return DBUS_HANDLER_RESULT_HANDLED;
2021 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "DomainBrowserNew")) {
2023 DomainBrowserInfo *i;
2024 static const DBusObjectPathVTable vtable = {
2026 msg_domain_browser_impl,
2032 int32_t interface, protocol, type;
2036 if (!dbus_message_get_args(
2038 DBUS_TYPE_INT32, &interface,
2039 DBUS_TYPE_INT32, &protocol,
2040 DBUS_TYPE_STRING, &domain,
2041 DBUS_TYPE_INT32, &type,
2042 DBUS_TYPE_UINT32, &flags,
2043 DBUS_TYPE_INVALID) || type < 0 || type >= AVAHI_DOMAIN_BROWSER_MAX) {
2044 avahi_log_warn("Error parsing Server::DomainBrowserNew message");
2048 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2049 avahi_log_warn("Too many clients, client request failed.");
2050 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2053 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2054 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2055 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2061 i = avahi_new(DomainBrowserInfo, 1);
2062 i->id = ++client->current_id;
2064 i->path = avahi_strdup_printf("/Client%u/DomainBrowser%u", client->id, i->id);
2065 AVAHI_LLIST_PREPEND(DomainBrowserInfo, domain_browsers, client->domain_browsers, i);
2066 client->n_objects++;
2068 if (!(i->domain_browser = avahi_s_domain_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, domain, (AvahiDomainBrowserType) type, (AvahiLookupFlags) flags, domain_browser_callback, i))) {
2069 domain_browser_free(i);
2070 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2073 dbus_connection_register_object_path(c, i->path, &vtable, i);
2074 return respond_path(c, m, i->path);
2076 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceTypeBrowserNew")) {
2078 ServiceTypeBrowserInfo *i;
2079 static const DBusObjectPathVTable vtable = {
2081 msg_service_type_browser_impl,
2087 int32_t interface, protocol;
2091 if (!dbus_message_get_args(
2093 DBUS_TYPE_INT32, &interface,
2094 DBUS_TYPE_INT32, &protocol,
2095 DBUS_TYPE_STRING, &domain,
2096 DBUS_TYPE_UINT32, &flags,
2097 DBUS_TYPE_INVALID)) {
2098 avahi_log_warn("Error parsing Server::ServiceTypeBrowserNew message");
2102 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2103 avahi_log_warn("Too many clients, client request failed.");
2104 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2108 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2109 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2110 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2116 i = avahi_new(ServiceTypeBrowserInfo, 1);
2117 i->id = ++client->current_id;
2119 i->path = avahi_strdup_printf("/Client%u/ServiceTypeBrowser%u", client->id, i->id);
2120 AVAHI_LLIST_PREPEND(ServiceTypeBrowserInfo, service_type_browsers, client->service_type_browsers, i);
2121 client->n_objects++;
2123 if (!(i->service_type_browser = avahi_s_service_type_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, domain, (AvahiLookupFlags) flags, service_type_browser_callback, i))) {
2124 service_type_browser_free(i);
2125 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2128 dbus_connection_register_object_path(c, i->path, &vtable, i);
2129 return respond_path(c, m, i->path);
2131 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceBrowserNew")) {
2133 ServiceBrowserInfo *i;
2134 static const DBusObjectPathVTable vtable = {
2136 msg_service_browser_impl,
2142 int32_t interface, protocol;
2144 char *domain, *type;
2146 if (!dbus_message_get_args(
2148 DBUS_TYPE_INT32, &interface,
2149 DBUS_TYPE_INT32, &protocol,
2150 DBUS_TYPE_STRING, &type,
2151 DBUS_TYPE_STRING, &domain,
2152 DBUS_TYPE_UINT32, &flags,
2153 DBUS_TYPE_INVALID) || !type) {
2154 avahi_log_warn("Error parsing Server::ServiceBrowserNew message");
2158 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2159 avahi_log_warn("Too many clients, client request failed.");
2160 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2164 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2165 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2166 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2172 i = avahi_new(ServiceBrowserInfo, 1);
2173 i->id = ++client->current_id;
2175 i->path = avahi_strdup_printf("/Client%u/ServiceBrowser%u", client->id, i->id);
2176 AVAHI_LLIST_PREPEND(ServiceBrowserInfo, service_browsers, client->service_browsers, i);
2177 client->n_objects++;
2179 if (!(i->service_browser = avahi_s_service_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, type, domain, (AvahiLookupFlags) flags, service_browser_callback, i))) {
2180 service_browser_free(i);
2181 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2184 dbus_connection_register_object_path(c, i->path, &vtable, i);
2185 return respond_path(c, m, i->path);
2187 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveService")) {
2189 int32_t interface, protocol, aprotocol;
2191 char *name, *type, *domain;
2192 SyncServiceResolverInfo *i;
2194 if (!dbus_message_get_args(
2196 DBUS_TYPE_INT32, &interface,
2197 DBUS_TYPE_INT32, &protocol,
2198 DBUS_TYPE_STRING, &name,
2199 DBUS_TYPE_STRING, &type,
2200 DBUS_TYPE_STRING, &domain,
2201 DBUS_TYPE_INT32, &aprotocol,
2202 DBUS_TYPE_UINT32, &flags,
2203 DBUS_TYPE_INVALID) || !type) {
2204 avahi_log_warn("Error parsing Server::ResolveService message");
2208 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2209 avahi_log_warn("Too many clients, client request failed.");
2210 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2213 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2214 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2215 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2224 i = avahi_new(SyncServiceResolverInfo, 1);
2226 i->message = dbus_message_ref(m);
2227 AVAHI_LLIST_PREPEND(SyncServiceResolverInfo, sync_service_resolvers, client->sync_service_resolvers, i);
2228 client->n_objects++;
2230 if (!(i->service_resolver = avahi_s_service_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, type, domain, (AvahiProtocol) aprotocol, (AvahiLookupFlags) flags, sync_service_resolver_callback, i))) {
2231 sync_service_resolver_free(i);
2232 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2235 return DBUS_HANDLER_RESULT_HANDLED;
2237 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceResolverNew")) {
2239 int32_t interface, protocol, aprotocol;
2241 char *name, *type, *domain;
2242 AsyncServiceResolverInfo *i;
2243 static const DBusObjectPathVTable vtable = {
2245 msg_async_service_resolver_impl,
2252 if (!dbus_message_get_args(
2254 DBUS_TYPE_INT32, &interface,
2255 DBUS_TYPE_INT32, &protocol,
2256 DBUS_TYPE_STRING, &name,
2257 DBUS_TYPE_STRING, &type,
2258 DBUS_TYPE_STRING, &domain,
2259 DBUS_TYPE_INT32, &aprotocol,
2260 DBUS_TYPE_UINT32, &flags,
2261 DBUS_TYPE_INVALID) || !type) {
2262 avahi_log_warn("Error parsing Server::ServiceResolverNew message");
2266 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2267 avahi_log_warn(__FILE__": Too many clients, client request failed.");
2268 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2271 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2272 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2273 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2282 i = avahi_new(AsyncServiceResolverInfo, 1);
2283 i->id = ++client->current_id;
2285 i->path = avahi_strdup_printf("/Client%u/ServiceResolver%u", client->id, i->id);
2286 AVAHI_LLIST_PREPEND(AsyncServiceResolverInfo, async_service_resolvers, client->async_service_resolvers, i);
2287 client->n_objects++;
2289 if (!(i->service_resolver = avahi_s_service_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, type, domain, (AvahiProtocol) aprotocol, (AvahiLookupFlags) flags, async_service_resolver_callback, i))) {
2290 async_service_resolver_free(i);
2291 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2294 /* avahi_log_debug(__FILE__": [%s], new service resolver for <%s.%s.%s>", i->path, name, type, domain); */
2296 dbus_connection_register_object_path(c, i->path, &vtable, i);
2297 return respond_path(c, m, i->path);
2299 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "HostNameResolverNew")) {
2301 int32_t interface, protocol, aprotocol;
2304 AsyncHostNameResolverInfo *i;
2305 static const DBusObjectPathVTable vtable = {
2307 msg_async_host_name_resolver_impl,
2314 if (!dbus_message_get_args(
2316 DBUS_TYPE_INT32, &interface,
2317 DBUS_TYPE_INT32, &protocol,
2318 DBUS_TYPE_STRING, &name,
2319 DBUS_TYPE_INT32, &aprotocol,
2320 DBUS_TYPE_UINT32, &flags,
2321 DBUS_TYPE_INVALID) || !name) {
2322 avahi_log_warn("Error parsing Server::HostNameResolverNew message");
2326 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2327 avahi_log_warn(__FILE__": Too many clients, client request failed.");
2328 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2331 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2332 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2333 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2336 i = avahi_new(AsyncHostNameResolverInfo, 1);
2337 i->id = ++client->current_id;
2339 i->path = avahi_strdup_printf("/Client%u/HostNameResolver%u", client->id, i->id);
2340 AVAHI_LLIST_PREPEND(AsyncHostNameResolverInfo, async_host_name_resolvers, client->async_host_name_resolvers, i);
2341 client->n_objects++;
2343 if (!(i->host_name_resolver = avahi_s_host_name_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, aprotocol, (AvahiLookupFlags) flags, async_host_name_resolver_callback, i))) {
2344 async_host_name_resolver_free(i);
2345 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2348 dbus_connection_register_object_path(c, i->path, &vtable, i);
2349 return respond_path(c, m, i->path);
2351 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "AddressResolverNew")) {
2353 int32_t interface, protocol;
2356 AsyncAddressResolverInfo *i;
2358 static const DBusObjectPathVTable vtable = {
2360 msg_async_address_resolver_impl,
2367 if (!dbus_message_get_args(
2369 DBUS_TYPE_INT32, &interface,
2370 DBUS_TYPE_INT32, &protocol,
2371 DBUS_TYPE_STRING, &address,
2372 DBUS_TYPE_UINT32, &flags,
2373 DBUS_TYPE_INVALID) || !address) {
2374 avahi_log_warn("Error parsing Server::AddressResolverNew message");
2378 if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
2379 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
2381 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2382 avahi_log_warn(__FILE__": Too many clients, client request failed.");
2383 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2386 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2387 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2388 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2391 i = avahi_new(AsyncAddressResolverInfo, 1);
2392 i->id = ++client->current_id;
2394 i->path = avahi_strdup_printf("/Client%u/AddressResolver%u", client->id, i->id);
2395 AVAHI_LLIST_PREPEND(AsyncAddressResolverInfo, async_address_resolvers, client->async_address_resolvers, i);
2396 client->n_objects++;
2398 if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, (AvahiLookupFlags) flags, async_address_resolver_callback, i))) {
2399 async_address_resolver_free(i);
2400 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2403 dbus_connection_register_object_path(c, i->path, &vtable, i);
2404 return respond_path(c, m, i->path);
2407 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
2410 if (dbus_error_is_set(&error))
2411 dbus_error_free(&error);
2413 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2416 void dbus_protocol_server_state_changed(AvahiServerState state) {
2423 m = dbus_message_new_signal(AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "StateChanged");
2424 t = (int32_t) state;
2425 dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_INVALID);
2426 dbus_connection_send(server->bus, m, NULL);
2427 dbus_message_unref(m);
2430 int dbus_protocol_setup(const AvahiPoll *poll_api) {
2433 static const DBusObjectPathVTable server_vtable = {
2442 dbus_error_init(&error);
2444 server = avahi_new(Server, 1);
2445 AVAHI_LLIST_HEAD_INIT(Clients, server->clients);
2446 server->current_id = 0;
2447 server->n_clients = 0;
2449 if (!(server->bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
2450 assert(dbus_error_is_set(&error));
2451 avahi_log_error("dbus_bus_get(): %s", error.message);
2455 if (avahi_dbus_connection_glue(server->bus, poll_api) < 0) {
2456 avahi_log_error("avahi_dbus_connection_glue() failed");
2460 if (dbus_bus_request_name(server->bus, AVAHI_DBUS_NAME, DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT, &error) != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
2461 if (dbus_error_is_set(&error)) {
2462 avahi_log_error("dbus_bus_request_name(): %s", error.message);
2466 avahi_log_error("Failed to acquire DBUS name '"AVAHI_DBUS_NAME"'");
2470 if (!(dbus_connection_add_filter(server->bus, msg_signal_filter_impl, (void*) poll_api, NULL))) {
2471 avahi_log_error("dbus_connection_add_filter() failed");
2475 dbus_bus_add_match(server->bus, "type='signal',""interface='" DBUS_INTERFACE_DBUS "'", &error);
2477 if (dbus_error_is_set(&error)) {
2478 avahi_log_error("dbus_bus_add_match(): %s", error.message);
2482 if (!(dbus_connection_register_object_path(server->bus, AVAHI_DBUS_PATH_SERVER, &server_vtable, NULL))) {
2483 avahi_log_error("dbus_connection_register_object_path() failed");
2491 dbus_connection_disconnect(server->bus);
2492 dbus_connection_unref(server->bus);
2495 if (dbus_error_is_set(&error))
2496 dbus_error_free(&error);
2503 void dbus_protocol_shutdown(void) {
2507 while (server->clients)
2508 client_free(server->clients);
2510 assert(server->n_clients == 0);
2513 dbus_connection_disconnect(server->bus);
2514 dbus_connection_unref(server->bus);