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>
33 #define DBUS_API_SUBJECT_TO_CHANGE
34 #include <dbus/dbus.h>
35 #include <dbus/dbus-glib-lowlevel.h>
37 #include <avahi-common/llist.h>
38 #include <avahi-core/log.h>
39 #include <avahi-core/core.h>
40 #include <avahi-common/dbus.h>
42 #include "dbus-protocol.h"
45 typedef struct Server Server;
46 typedef struct Client Client;
47 typedef struct EntryGroupInfo EntryGroupInfo;
48 typedef struct HostNameResolverInfo HostNameResolverInfo;
49 typedef struct AddressResolverInfo AddressResolverInfo;
50 typedef struct DomainBrowserInfo DomainBrowserInfo;
51 typedef struct ServiceTypeBrowserInfo ServiceTypeBrowserInfo;
52 typedef struct ServiceBrowserInfo ServiceBrowserInfo;
53 typedef struct ServiceResolverInfo ServiceResolverInfo;
55 #define MAX_CLIENTS 20
56 #define MAX_OBJECTS_PER_CLIENT 50
57 #define MAX_ENTRIES_PER_ENTRY_GROUP 20
59 /* #define VALGRIND_WORKAROUND */
61 struct EntryGroupInfo {
64 AvahiSEntryGroup *entry_group;
69 AVAHI_LLIST_FIELDS(EntryGroupInfo, entry_groups);
72 struct HostNameResolverInfo {
74 AvahiSHostNameResolver *host_name_resolver;
77 AVAHI_LLIST_FIELDS(HostNameResolverInfo, host_name_resolvers);
80 struct AddressResolverInfo {
82 AvahiSAddressResolver *address_resolver;
85 AVAHI_LLIST_FIELDS(AddressResolverInfo, address_resolvers);
88 struct DomainBrowserInfo {
91 AvahiSDomainBrowser *domain_browser;
94 AVAHI_LLIST_FIELDS(DomainBrowserInfo, domain_browsers);
97 struct ServiceTypeBrowserInfo {
100 AvahiSServiceTypeBrowser *service_type_browser;
103 AVAHI_LLIST_FIELDS(ServiceTypeBrowserInfo, service_type_browsers);
106 struct ServiceBrowserInfo {
109 AvahiSServiceBrowser *service_browser;
112 AVAHI_LLIST_FIELDS(ServiceBrowserInfo, service_browsers);
115 struct ServiceResolverInfo {
117 AvahiSServiceResolver *service_resolver;
118 DBusMessage *message;
120 AVAHI_LLIST_FIELDS(ServiceResolverInfo, service_resolvers);
129 AVAHI_LLIST_FIELDS(Client, clients);
130 AVAHI_LLIST_HEAD(EntryGroupInfo, entry_groups);
131 AVAHI_LLIST_HEAD(HostNameResolverInfo, host_name_resolvers);
132 AVAHI_LLIST_HEAD(AddressResolverInfo, address_resolvers);
133 AVAHI_LLIST_HEAD(DomainBrowserInfo, domain_browsers);
134 AVAHI_LLIST_HEAD(ServiceTypeBrowserInfo, service_type_browsers);
135 AVAHI_LLIST_HEAD(ServiceBrowserInfo, service_browsers);
136 AVAHI_LLIST_HEAD(ServiceResolverInfo, service_resolvers);
141 AVAHI_LLIST_HEAD(Client, clients);
146 static Server *server = NULL;
148 static void entry_group_free(EntryGroupInfo *i) {
152 avahi_s_entry_group_free(i->entry_group);
153 dbus_connection_unregister_object_path(server->bus, i->path);
155 AVAHI_LLIST_REMOVE(EntryGroupInfo, entry_groups, i->client->entry_groups, i);
157 i->client->n_objects--;
158 g_assert(i->client->n_objects >= 0);
163 static void host_name_resolver_free(HostNameResolverInfo *i) {
166 if (i->host_name_resolver)
167 avahi_s_host_name_resolver_free(i->host_name_resolver);
168 dbus_message_unref(i->message);
169 AVAHI_LLIST_REMOVE(HostNameResolverInfo, host_name_resolvers, i->client->host_name_resolvers, i);
171 i->client->n_objects--;
172 g_assert(i->client->n_objects >= 0);
177 static void address_resolver_free(AddressResolverInfo *i) {
180 if (i->address_resolver)
181 avahi_s_address_resolver_free(i->address_resolver);
182 dbus_message_unref(i->message);
183 AVAHI_LLIST_REMOVE(AddressResolverInfo, address_resolvers, i->client->address_resolvers, i);
185 i->client->n_objects--;
186 g_assert(i->client->n_objects >= 0);
191 static void domain_browser_free(DomainBrowserInfo *i) {
194 if (i->domain_browser)
195 avahi_s_domain_browser_free(i->domain_browser);
196 dbus_connection_unregister_object_path(server->bus, i->path);
198 AVAHI_LLIST_REMOVE(DomainBrowserInfo, domain_browsers, i->client->domain_browsers, i);
200 i->client->n_objects--;
201 g_assert(i->client->n_objects >= 0);
206 static void service_type_browser_free(ServiceTypeBrowserInfo *i) {
209 if (i->service_type_browser)
210 avahi_s_service_type_browser_free(i->service_type_browser);
211 dbus_connection_unregister_object_path(server->bus, i->path);
213 AVAHI_LLIST_REMOVE(ServiceTypeBrowserInfo, service_type_browsers, i->client->service_type_browsers, i);
215 i->client->n_objects--;
216 g_assert(i->client->n_objects >= 0);
221 static void service_browser_free(ServiceBrowserInfo *i) {
224 if (i->service_browser)
225 avahi_s_service_browser_free(i->service_browser);
226 dbus_connection_unregister_object_path(server->bus, i->path);
228 AVAHI_LLIST_REMOVE(ServiceBrowserInfo, service_browsers, i->client->service_browsers, i);
230 i->client->n_objects--;
231 g_assert(i->client->n_objects >= 0);
236 static void service_resolver_free(ServiceResolverInfo *i) {
239 if (i->service_resolver)
240 avahi_s_service_resolver_free(i->service_resolver);
241 dbus_message_unref(i->message);
242 AVAHI_LLIST_REMOVE(ServiceResolverInfo, service_resolvers, i->client->service_resolvers, i);
244 i->client->n_objects--;
245 g_assert(i->client->n_objects >= 0);
250 static void client_free(Client *c) {
255 while (c->entry_groups)
256 entry_group_free(c->entry_groups);
258 while (c->host_name_resolvers)
259 host_name_resolver_free(c->host_name_resolvers);
261 while (c->address_resolvers)
262 address_resolver_free(c->address_resolvers);
264 while (c->domain_browsers)
265 domain_browser_free(c->domain_browsers);
267 while (c->service_type_browsers)
268 service_type_browser_free(c->service_type_browsers);
270 while (c->service_browsers)
271 service_browser_free(c->service_browsers);
273 while (c->service_resolvers)
274 service_resolver_free(c->service_resolvers);
276 g_assert(c->n_objects == 0);
279 AVAHI_LLIST_REMOVE(Client, clients, server->clients, c);
282 server->n_clients --;
283 g_assert(server->n_clients >= 0);
286 static Client *client_get(const gchar *name, gboolean create) {
292 for (client = server->clients; client; client = client->clients_next)
293 if (!strcmp(name, client->name))
299 if (server->n_clients >= MAX_CLIENTS)
302 /* If not existant yet, create a new entry */
303 client = g_new(Client, 1);
304 client->id = server->current_id++;
305 client->name = g_strdup(name);
306 client->current_id = 0;
307 client->n_objects = 0;
308 AVAHI_LLIST_HEAD_INIT(EntryGroupInfo, client->entry_groups);
309 AVAHI_LLIST_HEAD_INIT(HostNameResolverInfo, client->host_name_resolvers);
310 AVAHI_LLIST_HEAD_INIT(AddressResolverInfo, client->address_resolvers);
311 AVAHI_LLIST_HEAD_INIT(DomainBrowserInfo, client->domain_browsers);
312 AVAHI_LLIST_HEAD_INIT(ServiceTypeBrowserInfo, client->service_type_browsers);
313 AVAHI_LLIST_HEAD_INIT(ServiceBrowserInfo, client->service_browsers);
314 AVAHI_LLIST_HEAD_INIT(ServiceResolverInfo, client->service_resolvers);
316 AVAHI_LLIST_PREPEND(Client, clients, server->clients, client);
319 g_assert(server->n_clients > 0);
324 static DBusHandlerResult respond_error(DBusConnection *c, DBusMessage *m, gint error, const gchar *text) {
327 const gchar * const table[- AVAHI_ERR_MAX] = {
329 AVAHI_DBUS_ERR_FAILURE,
330 AVAHI_DBUS_ERR_BAD_STATE,
331 AVAHI_DBUS_ERR_INVALID_HOST_NAME,
332 AVAHI_DBUS_ERR_INVALID_DOMAIN_NAME,
333 AVAHI_DBUS_ERR_NO_NETWORK,
334 AVAHI_DBUS_ERR_INVALID_TTL,
335 AVAHI_DBUS_ERR_IS_PATTERN,
336 AVAHI_DBUS_ERR_LOCAL_COLLISION,
337 AVAHI_DBUS_ERR_INVALID_RECORD,
338 AVAHI_DBUS_ERR_INVALID_SERVICE_NAME,
339 AVAHI_DBUS_ERR_INVALID_SERVICE_TYPE,
340 AVAHI_DBUS_ERR_INVALID_PORT,
341 AVAHI_DBUS_ERR_INVALID_KEY,
342 AVAHI_DBUS_ERR_INVALID_ADDRESS,
343 AVAHI_DBUS_ERR_TIMEOUT,
344 AVAHI_DBUS_ERR_TOO_MANY_CLIENTS,
345 AVAHI_DBUS_ERR_TOO_MANY_OBJECTS,
346 AVAHI_DBUS_ERR_TOO_MANY_ENTRIES,
348 AVAHI_DBUS_ERR_ACCESS_DENIED,
349 AVAHI_DBUS_ERR_INVALID_OPERATION,
350 AVAHI_DBUS_ERR_DBUS_ERROR,
351 AVAHI_DBUS_ERR_NOT_CONNECTED,
352 AVAHI_DBUS_ERR_NO_MEMORY,
353 AVAHI_DBUS_ERR_INVALID_OBJECT
356 g_assert(-error > -AVAHI_OK);
357 g_assert(-error < -AVAHI_ERR_MAX);
359 reply = dbus_message_new_error(m, table[-error], text ? text : avahi_strerror(error));
360 dbus_connection_send(c, reply, NULL);
361 dbus_message_unref(reply);
363 return DBUS_HANDLER_RESULT_HANDLED;
366 static DBusHandlerResult respond_string(DBusConnection *c, DBusMessage *m, const gchar *text) {
369 reply = dbus_message_new_method_return(m);
370 dbus_message_append_args(reply, DBUS_TYPE_STRING, &text, DBUS_TYPE_INVALID);
371 dbus_connection_send(c, reply, NULL);
372 dbus_message_unref(reply);
374 return DBUS_HANDLER_RESULT_HANDLED;
377 static DBusHandlerResult respond_int32(DBusConnection *c, DBusMessage *m, gint32 i) {
380 reply = dbus_message_new_method_return(m);
381 dbus_message_append_args(reply, DBUS_TYPE_INT32, &i, DBUS_TYPE_INVALID);
382 dbus_connection_send(c, reply, NULL);
383 dbus_message_unref(reply);
385 return DBUS_HANDLER_RESULT_HANDLED;
388 static DBusHandlerResult respond_ok(DBusConnection *c, DBusMessage *m) {
391 reply = dbus_message_new_method_return(m);
392 dbus_connection_send(c, reply, NULL);
393 dbus_message_unref(reply);
395 return DBUS_HANDLER_RESULT_HANDLED;
398 static DBusHandlerResult respond_path(DBusConnection *c, DBusMessage *m, const gchar *path) {
401 reply = dbus_message_new_method_return(m);
402 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID);
403 dbus_connection_send(c, reply, NULL);
404 dbus_message_unref(reply);
406 return DBUS_HANDLER_RESULT_HANDLED;
409 static DBusHandlerResult handle_introspect(DBusConnection *c, DBusMessage *m, const gchar *fname) {
412 GError *gerror = NULL;
419 dbus_error_init(&error);
421 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
422 avahi_log_warn("Error parsing Introspect message: %s", error.message);
426 path = g_strdup_printf("%s/%s", AVAHI_DBUS_INTROSPECTION_DIR, fname);
428 if (!(g_file_get_contents(path, &contents, NULL, &gerror))) {
429 avahi_log_warn("Failed to load introspection data: %s", gerror->message);
430 g_error_free(gerror);
437 respond_string(c, m, contents);
440 return DBUS_HANDLER_RESULT_HANDLED;
443 if (dbus_error_is_set(&error))
444 dbus_error_free(&error);
446 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
450 static DBusHandlerResult msg_signal_filter_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
451 GMainLoop *loop = userdata;
454 dbus_error_init(&error);
456 /* avahi_log_debug("dbus: interface=%s, path=%s, member=%s", */
457 /* dbus_message_get_interface(m), */
458 /* dbus_message_get_path(m), */
459 /* dbus_message_get_member(m)); */
461 if (dbus_message_is_signal(m, DBUS_INTERFACE_LOCAL, "Disconnected")) {
462 /* No, we shouldn't quit, but until we get somewhere
463 * usefull such that we can restore our state, we will */
464 avahi_log_warn("Disconnnected from d-bus, terminating...");
465 g_main_loop_quit (loop);
466 return DBUS_HANDLER_RESULT_HANDLED;
468 } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameAcquired")) {
471 if (!dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID)) {
472 avahi_log_warn("Error parsing NameAcquired message");
476 /* avahi_log_info("dbus: name acquired (%s)", name); */
477 return DBUS_HANDLER_RESULT_HANDLED;
479 } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
480 gchar *name, *old, *new;
482 if (!dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &old, DBUS_TYPE_STRING, &new, DBUS_TYPE_INVALID)) {
483 avahi_log_warn("Error parsing NameOwnerChanged message");
490 if ((client = client_get(name, FALSE))) {
491 /* avahi_log_info("dbus: client %s vanished", name); */
498 if (dbus_error_is_set(&error))
499 dbus_error_free(&error);
501 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
504 static void entry_group_callback(AvahiServer *s, AvahiSEntryGroup *g, AvahiEntryGroupState state, gpointer userdata) {
505 EntryGroupInfo *i = userdata;
513 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "StateChanged");
515 dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_INVALID);
516 dbus_message_set_destination(m, i->client->name);
517 dbus_connection_send(server->bus, m, NULL);
518 dbus_message_unref(m);
521 static DBusHandlerResult msg_entry_group_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
523 EntryGroupInfo *i = userdata;
529 dbus_error_init(&error);
531 avahi_log_debug("dbus: interface=%s, path=%s, member=%s",
532 dbus_message_get_interface(m),
533 dbus_message_get_path(m),
534 dbus_message_get_member(m));
537 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
538 return handle_introspect(c, m, "EntryGroup.introspect");
541 if (strcmp(dbus_message_get_sender(m), i->client->name))
542 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
544 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Free")) {
546 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
547 avahi_log_warn("Error parsing EntryGroup::Free message");
552 return respond_ok(c, m);
554 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Commit")) {
556 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
557 avahi_log_warn("Error parsing EntryGroup::Commit message");
561 avahi_s_entry_group_commit(i->entry_group);
562 return respond_ok(c, m);
565 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Reset")) {
567 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
568 avahi_log_warn("Error parsing EntryGroup::Reset message");
572 avahi_s_entry_group_reset(i->entry_group);
573 return respond_ok(c, m);
575 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "IsEmpty")) {
579 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
580 avahi_log_warn("Error parsing EntryGroup::IsEmpty message");
584 b = !!avahi_s_entry_group_is_empty(i->entry_group);
586 reply = dbus_message_new_method_return(m);
587 dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &b, DBUS_TYPE_INVALID);
588 dbus_connection_send(c, reply, NULL);
589 dbus_message_unref(reply);
591 return DBUS_HANDLER_RESULT_HANDLED;
593 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "GetState")) {
594 AvahiEntryGroupState state;
596 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
597 avahi_log_warn("Error parsing EntryGroup::GetState message");
601 state = avahi_s_entry_group_get_state(i->entry_group);
602 return respond_int32(c, m, (gint32) state);
604 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddService")) {
605 gint32 interface, protocol;
606 gchar *type, *name, *domain, *host;
608 AvahiStringList *strlst;
609 DBusMessageIter iter, sub;
612 if (!dbus_message_get_args(
614 DBUS_TYPE_INT32, &interface,
615 DBUS_TYPE_INT32, &protocol,
616 DBUS_TYPE_STRING, &name,
617 DBUS_TYPE_STRING, &type,
618 DBUS_TYPE_STRING, &domain,
619 DBUS_TYPE_STRING, &host,
620 DBUS_TYPE_UINT16, &port,
621 DBUS_TYPE_INVALID) || !type || !name) {
622 avahi_log_warn("Error parsing EntryGroup::AddService message");
626 dbus_message_iter_init(m, &iter);
628 for (j = 0; j < 7; j++)
629 dbus_message_iter_next(&iter);
631 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
632 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_ARRAY) {
633 avahi_log_warn("Error parsing EntryGroup::AddService message 2");
638 dbus_message_iter_recurse(&iter, &sub);
641 DBusMessageIter sub2;
645 if ((at = dbus_message_iter_get_arg_type(&sub)) == DBUS_TYPE_INVALID)
648 g_assert(at == DBUS_TYPE_ARRAY);
650 if (dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_BYTE) {
651 avahi_log_warn("Error parsing EntryGroup::AddService message");
655 dbus_message_iter_recurse(&sub, &sub2);
656 dbus_message_iter_get_fixed_array(&sub2, &k, &n);
657 strlst = avahi_string_list_add_arbitrary(strlst, k, n);
659 dbus_message_iter_next(&sub);
662 if (i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) {
663 avahi_string_list_free(strlst);
664 avahi_log_warn("Too many entries per entry group, client request failed.");
665 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
668 if (domain && !*domain)
674 if (avahi_server_add_service_strlst(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, type, domain, host, port, strlst) < 0) {
675 avahi_string_list_free(strlst);
676 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
680 avahi_string_list_free(strlst);
682 return respond_ok(c, m);
684 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddAddress")) {
685 gint32 interface, protocol;
686 gchar *name, *address;
689 if (!dbus_message_get_args(
691 DBUS_TYPE_INT32, &interface,
692 DBUS_TYPE_INT32, &protocol,
693 DBUS_TYPE_STRING, &name,
694 DBUS_TYPE_STRING, &address,
695 DBUS_TYPE_INVALID) || !name || !address) {
696 avahi_log_warn("Error parsing EntryGroup::AddAddress message");
700 if (i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) {
701 avahi_log_warn("Too many entries per entry group, client request failed.");
702 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
705 if (!(avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))) {
706 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
709 if (avahi_server_add_address(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, 0, name, &a) < 0)
710 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
714 return respond_ok(c, m);
717 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
720 if (dbus_error_is_set(&error))
721 dbus_error_free(&error);
723 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
726 static void host_name_resolver_callback(AvahiSHostNameResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const gchar *host_name, const AvahiAddress *a, gpointer userdata) {
727 HostNameResolverInfo *i = userdata;
733 if (event == AVAHI_RESOLVER_FOUND) {
734 char t[256], *pt = t;
735 gint32 i_interface, i_protocol, i_aprotocol;
739 avahi_address_snprint(t, sizeof(t), a);
741 i_interface = (gint32) interface;
742 i_protocol = (gint32) protocol;
743 i_aprotocol = (gint32) a->family;
745 reply = dbus_message_new_method_return(i->message);
746 dbus_message_append_args(
748 DBUS_TYPE_INT32, &i_interface,
749 DBUS_TYPE_INT32, &i_protocol,
750 DBUS_TYPE_STRING, &host_name,
751 DBUS_TYPE_INT32, &i_aprotocol,
752 DBUS_TYPE_STRING, &pt,
755 dbus_connection_send(server->bus, reply, NULL);
756 dbus_message_unref(reply);
758 g_assert(event == AVAHI_RESOLVER_TIMEOUT);
760 respond_error(server->bus, i->message, AVAHI_ERR_TIMEOUT, NULL);
763 host_name_resolver_free(i);
766 static void address_resolver_callback(AvahiSAddressResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const AvahiAddress *address, const gchar *host_name, gpointer userdata) {
767 AddressResolverInfo *i = userdata;
773 if (event == AVAHI_RESOLVER_FOUND) {
774 char t[256], *pt = t;
775 gint32 i_interface, i_protocol, i_aprotocol;
779 avahi_address_snprint(t, sizeof(t), address);
781 i_interface = (gint32) interface;
782 i_protocol = (gint32) protocol;
783 i_aprotocol = (gint32) address->family;
785 reply = dbus_message_new_method_return(i->message);
786 dbus_message_append_args(
788 DBUS_TYPE_INT32, &i_interface,
789 DBUS_TYPE_INT32, &i_protocol,
790 DBUS_TYPE_INT32, &i_aprotocol,
791 DBUS_TYPE_STRING, &pt,
792 DBUS_TYPE_STRING, &host_name,
795 dbus_connection_send(server->bus, reply, NULL);
796 dbus_message_unref(reply);
798 g_assert(event == AVAHI_RESOLVER_TIMEOUT);
799 respond_error(server->bus, i->message, AVAHI_ERR_TIMEOUT, NULL);
802 address_resolver_free(i);
805 static DBusHandlerResult msg_domain_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
807 DomainBrowserInfo *i = userdata;
813 dbus_error_init(&error);
815 avahi_log_debug("dbus: interface=%s, path=%s, member=%s",
816 dbus_message_get_interface(m),
817 dbus_message_get_path(m),
818 dbus_message_get_member(m));
821 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
822 return handle_introspect(c, m, "DomainBrowser.introspect");
825 if (strcmp(dbus_message_get_sender(m), i->client->name))
826 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
828 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, "Free")) {
830 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
831 avahi_log_warn("Error parsing DomainBrowser::Free message");
835 domain_browser_free(i);
836 return respond_ok(c, m);
840 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
843 if (dbus_error_is_set(&error))
844 dbus_error_free(&error);
846 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
849 static void domain_browser_callback(AvahiSDomainBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const gchar *domain, gpointer userdata) {
850 DomainBrowserInfo *i = userdata;
852 gint32 i_interface, i_protocol;
858 i_interface = (gint32) interface;
859 i_protocol = (gint32) protocol;
861 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, event == AVAHI_BROWSER_NEW ? "ItemNew" : "ItemRemove");
862 dbus_message_append_args(
864 DBUS_TYPE_INT32, &i_interface,
865 DBUS_TYPE_INT32, &i_protocol,
866 DBUS_TYPE_STRING, &domain,
868 dbus_message_set_destination(m, i->client->name);
869 dbus_connection_send(server->bus, m, NULL);
870 dbus_message_unref(m);
873 static DBusHandlerResult msg_service_type_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
875 ServiceTypeBrowserInfo *i = userdata;
881 dbus_error_init(&error);
883 avahi_log_debug("dbus: interface=%s, path=%s, member=%s",
884 dbus_message_get_interface(m),
885 dbus_message_get_path(m),
886 dbus_message_get_member(m));
889 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
890 return handle_introspect(c, m, "ServiceTypeBrowser.introspect");
893 if (strcmp(dbus_message_get_sender(m), i->client->name))
894 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
896 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, "Free")) {
898 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
899 avahi_log_warn("Error parsing ServiceTypeBrowser::Free message");
903 service_type_browser_free(i);
904 return respond_ok(c, m);
908 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
911 if (dbus_error_is_set(&error))
912 dbus_error_free(&error);
914 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
917 static void service_type_browser_callback(AvahiSServiceTypeBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const gchar *type, const gchar *domain, gpointer userdata) {
918 ServiceTypeBrowserInfo *i = userdata;
920 gint32 i_interface, i_protocol;
927 i_interface = (gint32) interface;
928 i_protocol = (gint32) protocol;
930 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, event == AVAHI_BROWSER_NEW ? "ItemNew" : "ItemRemove");
931 dbus_message_append_args(
933 DBUS_TYPE_INT32, &i_interface,
934 DBUS_TYPE_INT32, &i_protocol,
935 DBUS_TYPE_STRING, &type,
936 DBUS_TYPE_STRING, &domain,
938 dbus_message_set_destination(m, i->client->name);
939 dbus_connection_send(server->bus, m, NULL);
940 dbus_message_unref(m);
943 static DBusHandlerResult msg_service_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
945 ServiceBrowserInfo *i = userdata;
951 dbus_error_init(&error);
953 avahi_log_debug("dbus: interface=%s, path=%s, member=%s",
954 dbus_message_get_interface(m),
955 dbus_message_get_path(m),
956 dbus_message_get_member(m));
959 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
960 return handle_introspect(c, m, "ServiceBrowser.Introspect");
963 if (strcmp(dbus_message_get_sender(m), i->client->name))
964 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
966 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, "Free")) {
968 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
969 avahi_log_warn("Error parsing ServiceBrowser::Free message");
973 service_browser_free(i);
974 return respond_ok(c, m);
978 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
981 if (dbus_error_is_set(&error))
982 dbus_error_free(&error);
984 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
987 static void service_browser_callback(AvahiSServiceBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const gchar *name, const gchar *type, const gchar *domain, gpointer userdata) {
988 ServiceBrowserInfo *i = userdata;
990 gint32 i_interface, i_protocol;
998 i_interface = (gint32) interface;
999 i_protocol = (gint32) protocol;
1001 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, event == AVAHI_BROWSER_NEW ? "ItemNew" : "ItemRemove");
1002 dbus_message_append_args(
1004 DBUS_TYPE_INT32, &i_interface,
1005 DBUS_TYPE_INT32, &i_protocol,
1006 DBUS_TYPE_STRING, &name,
1007 DBUS_TYPE_STRING, &type,
1008 DBUS_TYPE_STRING, &domain,
1010 dbus_message_set_destination(m, i->client->name);
1011 dbus_connection_send(server->bus, m, NULL);
1012 dbus_message_unref(m);
1015 static void service_resolver_callback(
1016 AvahiSServiceResolver *r,
1017 AvahiIfIndex interface,
1018 AvahiProtocol protocol,
1019 AvahiResolverEvent event,
1022 const gchar *domain,
1023 const gchar *host_name,
1024 const AvahiAddress *a,
1026 AvahiStringList *txt,
1027 gpointer userdata) {
1029 ServiceResolverInfo *i = userdata;
1034 if (event == AVAHI_RESOLVER_FOUND) {
1035 char t[256], *pt = t;
1036 gint32 i_interface, i_protocol, i_aprotocol;
1040 DBusMessageIter iter, sub;
1042 g_assert(host_name);
1045 avahi_address_snprint(t, sizeof(t), a);
1047 i_interface = (gint32) interface;
1048 i_protocol = (gint32) protocol;
1049 i_aprotocol = (gint32) a->family;
1051 reply = dbus_message_new_method_return(i->message);
1052 dbus_message_append_args(
1054 DBUS_TYPE_INT32, &i_interface,
1055 DBUS_TYPE_INT32, &i_protocol,
1056 DBUS_TYPE_STRING, &name,
1057 DBUS_TYPE_STRING, &type,
1058 DBUS_TYPE_STRING, &domain,
1059 DBUS_TYPE_STRING, &host_name,
1060 DBUS_TYPE_INT32, &i_aprotocol,
1061 DBUS_TYPE_STRING, &pt,
1062 DBUS_TYPE_UINT16, &port,
1065 dbus_message_iter_init_append(reply, &iter);
1066 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "ay", &sub);
1068 for (p = txt, j = n-1; p; p = p->next, j--) {
1069 DBusMessageIter sub2;
1070 const guint8 *data = p->text;
1072 dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "y", &sub2);
1073 dbus_message_iter_append_fixed_array(&sub2, DBUS_TYPE_BYTE, &data, p->size);
1074 dbus_message_iter_close_container(&sub, &sub2);
1077 dbus_message_iter_close_container(&iter, &sub);
1079 dbus_connection_send(server->bus, reply, NULL);
1080 dbus_message_unref(reply);
1082 g_assert(event == AVAHI_RESOLVER_TIMEOUT);
1084 respond_error(server->bus, i->message, AVAHI_ERR_TIMEOUT, NULL);
1087 service_resolver_free(i);
1090 static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1093 dbus_error_init(&error);
1095 avahi_log_debug("dbus: interface=%s, path=%s, member=%s",
1096 dbus_message_get_interface(m),
1097 dbus_message_get_path(m),
1098 dbus_message_get_member(m));
1100 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1101 return handle_introspect(c, m, "Server.introspect");
1103 else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostName")) {
1105 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1106 avahi_log_warn("Error parsing Server::GetHostName message");
1110 return respond_string(c, m, avahi_server_get_host_name(avahi_server));
1112 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetDomainName")) {
1114 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1115 avahi_log_warn("Error parsing Server::GetDomainName message");
1119 return respond_string(c, m, avahi_server_get_domain_name(avahi_server));
1121 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostNameFqdn")) {
1123 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1124 avahi_log_warn("Error parsing Server::GetHostNameFqdn message");
1128 return respond_string(c, m, avahi_server_get_host_name_fqdn(avahi_server));
1130 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetVersionString")) {
1132 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1133 avahi_log_warn("Error parsing Server::GetVersionString message");
1137 return respond_string(c, m, PACKAGE_STRING);
1139 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetState")) {
1140 AvahiServerState state;
1142 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1143 avahi_log_warn("Error parsing Server::GetState message");
1147 state = avahi_server_get_state(avahi_server);
1148 return respond_int32(c, m, (gint32) state);
1150 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceNameByIndex")) {
1155 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INT32, &idx, DBUS_TYPE_INVALID))) {
1156 avahi_log_warn("Error parsing Server::GetNetworkInterfaceNameByIndex message");
1160 #ifdef VALGRIND_WORKAROUND
1161 return respond_string(c, m, "blah");
1164 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1166 g_snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1167 return respond_error(c, m, AVAHI_ERR_OS, txt);
1170 memset(&ifr, 0, sizeof(ifr));
1171 ifr.ifr_ifindex = idx;
1173 if (ioctl(fd, SIOCGIFNAME, &ifr) < 0) {
1175 g_snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1177 return respond_error(c, m, AVAHI_ERR_OS, txt);
1182 return respond_string(c, m, ifr.ifr_name);
1185 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceIndexByName")) {
1190 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1191 avahi_log_warn("Error parsing Server::GetNetworkInterfaceIndexByName message");
1195 #ifdef VALGRIND_WORKAROUND
1196 return respond_int32(c, m, 1);
1198 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1200 g_snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1201 return respond_error(c, m, AVAHI_ERR_OS, txt);
1204 memset(&ifr, 0, sizeof(ifr));
1205 g_snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", n);
1207 if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
1209 g_snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1211 return respond_error(c, m, AVAHI_ERR_OS, txt);
1216 return respond_int32(c, m, ifr.ifr_ifindex);
1219 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeHostName")) {
1222 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1223 avahi_log_warn("Error parsing Server::GetAlternativeHostName message");
1227 t = avahi_alternative_host_name(n);
1228 respond_string(c, m, t);
1231 return DBUS_HANDLER_RESULT_HANDLED;
1233 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeServiceName")) {
1236 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1237 avahi_log_warn("Error parsing Server::GetAlternativeServiceName message");
1241 t = avahi_alternative_service_name(n);
1242 respond_string(c, m, t);
1245 return DBUS_HANDLER_RESULT_HANDLED;
1247 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "EntryGroupNew")) {
1250 static const DBusObjectPathVTable vtable = {
1252 msg_entry_group_impl,
1259 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1260 avahi_log_warn("Error parsing Server::EntryGroupNew message");
1264 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1265 avahi_log_warn("Too many clients, client request failed.");
1266 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1269 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1270 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1271 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1274 i = g_new(EntryGroupInfo, 1);
1275 i->id = ++client->current_id;
1277 i->path = g_strdup_printf("/Client%u/EntryGroup%u", client->id, i->id);
1279 AVAHI_LLIST_PREPEND(EntryGroupInfo, entry_groups, client->entry_groups, i);
1280 client->n_objects++;
1282 if (!(i->entry_group = avahi_s_entry_group_new(avahi_server, entry_group_callback, i))) {
1283 entry_group_free(i);
1284 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1287 dbus_connection_register_object_path(c, i->path, &vtable, i);
1288 return respond_path(c, m, i->path);
1290 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveHostName")) {
1292 gint32 interface, protocol, aprotocol;
1294 HostNameResolverInfo *i;
1296 if (!dbus_message_get_args(
1298 DBUS_TYPE_INT32, &interface,
1299 DBUS_TYPE_INT32, &protocol,
1300 DBUS_TYPE_STRING, &name,
1301 DBUS_TYPE_INT32, &aprotocol,
1302 DBUS_TYPE_INVALID) || !name) {
1303 avahi_log_warn("Error parsing Server::ResolveHostName message");
1307 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1308 avahi_log_warn("Too many clients, client request failed.");
1309 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1312 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1313 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1314 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1317 i = g_new(HostNameResolverInfo, 1);
1319 i->message = dbus_message_ref(m);
1320 AVAHI_LLIST_PREPEND(HostNameResolverInfo, host_name_resolvers, client->host_name_resolvers, i);
1321 client->n_objects++;
1323 if (!(i->host_name_resolver = avahi_s_host_name_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, (AvahiProtocol) aprotocol, host_name_resolver_callback, i))) {
1324 host_name_resolver_free(i);
1325 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1328 return DBUS_HANDLER_RESULT_HANDLED;
1330 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveAddress")) {
1332 gint32 interface, protocol;
1334 AddressResolverInfo *i;
1337 if (!dbus_message_get_args(
1339 DBUS_TYPE_INT32, &interface,
1340 DBUS_TYPE_INT32, &protocol,
1341 DBUS_TYPE_STRING, &address,
1342 DBUS_TYPE_INVALID) || !address) {
1343 avahi_log_warn("Error parsing Server::ResolveAddress message");
1347 if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
1348 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
1350 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1351 avahi_log_warn("Too many clients, client request failed.");
1352 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1355 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1356 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1357 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1360 i = g_new(AddressResolverInfo, 1);
1362 i->message = dbus_message_ref(m);
1363 AVAHI_LLIST_PREPEND(AddressResolverInfo, address_resolvers, client->address_resolvers, i);
1364 client->n_objects++;
1366 if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, address_resolver_callback, i))) {
1367 address_resolver_free(i);
1368 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1371 return DBUS_HANDLER_RESULT_HANDLED;
1373 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "DomainBrowserNew")) {
1375 DomainBrowserInfo *i;
1376 static const DBusObjectPathVTable vtable = {
1378 msg_domain_browser_impl,
1384 gint32 interface, protocol, type;
1388 if (!dbus_message_get_args(
1390 DBUS_TYPE_INT32, &interface,
1391 DBUS_TYPE_INT32, &protocol,
1392 DBUS_TYPE_STRING, &domain,
1393 DBUS_TYPE_INT32, &type,
1394 DBUS_TYPE_INVALID) || type < 0 || type >= AVAHI_DOMAIN_BROWSER_MAX) {
1395 avahi_log_warn("Error parsing Server::DomainBrowserNew message");
1399 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1400 avahi_log_warn("Too many clients, client request failed.");
1401 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1404 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1405 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1406 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1412 i = g_new(DomainBrowserInfo, 1);
1413 i->id = ++client->current_id;
1415 i->path = g_strdup_printf("/Client%u/DomainBrowser%u", client->id, i->id);
1416 AVAHI_LLIST_PREPEND(DomainBrowserInfo, domain_browsers, client->domain_browsers, i);
1417 client->n_objects++;
1419 if (!(i->domain_browser = avahi_s_domain_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, domain, (AvahiDomainBrowserType) type, domain_browser_callback, i))) {
1420 domain_browser_free(i);
1421 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1424 dbus_connection_register_object_path(c, i->path, &vtable, i);
1425 return respond_path(c, m, i->path);
1427 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceTypeBrowserNew")) {
1429 ServiceTypeBrowserInfo *i;
1430 static const DBusObjectPathVTable vtable = {
1432 msg_service_type_browser_impl,
1438 gint32 interface, protocol;
1441 if (!dbus_message_get_args(
1443 DBUS_TYPE_INT32, &interface,
1444 DBUS_TYPE_INT32, &protocol,
1445 DBUS_TYPE_STRING, &domain,
1446 DBUS_TYPE_INVALID)) {
1447 avahi_log_warn("Error parsing Server::ServiceTypeBrowserNew message");
1451 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1452 avahi_log_warn("Too many clients, client request failed.");
1453 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1457 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1458 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1459 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1465 i = g_new(ServiceTypeBrowserInfo, 1);
1466 i->id = ++client->current_id;
1468 i->path = g_strdup_printf("/Client%u/ServiceTypeBrowser%u", client->id, i->id);
1469 AVAHI_LLIST_PREPEND(ServiceTypeBrowserInfo, service_type_browsers, client->service_type_browsers, i);
1470 client->n_objects++;
1472 if (!(i->service_type_browser = avahi_s_service_type_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, domain, service_type_browser_callback, i))) {
1473 service_type_browser_free(i);
1474 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1477 dbus_connection_register_object_path(c, i->path, &vtable, i);
1478 return respond_path(c, m, i->path);
1480 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceBrowserNew")) {
1482 ServiceBrowserInfo *i;
1483 static const DBusObjectPathVTable vtable = {
1485 msg_service_browser_impl,
1491 gint32 interface, protocol;
1492 gchar *domain, *type;
1494 if (!dbus_message_get_args(
1496 DBUS_TYPE_INT32, &interface,
1497 DBUS_TYPE_INT32, &protocol,
1498 DBUS_TYPE_STRING, &type,
1499 DBUS_TYPE_STRING, &domain,
1500 DBUS_TYPE_INVALID) || !type) {
1501 avahi_log_warn("Error parsing Server::ServiceBrowserNew message");
1505 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1506 avahi_log_warn("Too many clients, client request failed.");
1507 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1511 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1512 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1513 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1519 i = g_new(ServiceBrowserInfo, 1);
1520 i->id = ++client->current_id;
1522 i->path = g_strdup_printf("/Client%u/ServiceBrowser%u", client->id, i->id);
1523 AVAHI_LLIST_PREPEND(ServiceBrowserInfo, service_browsers, client->service_browsers, i);
1524 client->n_objects++;
1526 if (!(i->service_browser = avahi_s_service_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, type, domain, service_browser_callback, i))) {
1527 service_browser_free(i);
1528 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1531 dbus_connection_register_object_path(c, i->path, &vtable, i);
1532 return respond_path(c, m, i->path);
1534 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveService")) {
1536 gint32 interface, protocol, aprotocol;
1537 gchar *name, *type, *domain;
1538 ServiceResolverInfo *i;
1540 if (!dbus_message_get_args(
1542 DBUS_TYPE_INT32, &interface,
1543 DBUS_TYPE_INT32, &protocol,
1544 DBUS_TYPE_STRING, &name,
1545 DBUS_TYPE_STRING, &type,
1546 DBUS_TYPE_STRING, &domain,
1547 DBUS_TYPE_INT32, &aprotocol,
1548 DBUS_TYPE_INVALID) || !name || !type) {
1549 avahi_log_warn("Error parsing Server::ResolveService message");
1553 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1554 avahi_log_warn("Too many clients, client request failed.");
1555 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1558 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1559 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1560 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1566 i = g_new(ServiceResolverInfo, 1);
1568 i->message = dbus_message_ref(m);
1569 AVAHI_LLIST_PREPEND(ServiceResolverInfo, service_resolvers, client->service_resolvers, i);
1570 client->n_objects++;
1572 if (!(i->service_resolver = avahi_s_service_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, type, domain, (AvahiProtocol) aprotocol, service_resolver_callback, i))) {
1573 service_resolver_free(i);
1574 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1577 return DBUS_HANDLER_RESULT_HANDLED;
1580 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1583 if (dbus_error_is_set(&error))
1584 dbus_error_free(&error);
1586 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1589 void dbus_protocol_server_state_changed(AvahiServerState state) {
1596 m = dbus_message_new_signal(AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "StateChanged");
1598 dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_INVALID);
1599 dbus_connection_send(server->bus, m, NULL);
1600 dbus_message_unref(m);
1603 int dbus_protocol_setup(GMainLoop *loop) {
1606 static const DBusObjectPathVTable server_vtable = {
1615 dbus_error_init(&error);
1617 server = g_malloc(sizeof(Server));
1618 server->clients = NULL;
1619 server->current_id = 0;
1620 server->n_clients = 0;
1622 server->bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
1623 if (dbus_error_is_set(&error)) {
1624 avahi_log_warn("dbus_bus_get(): %s", error.message);
1628 dbus_connection_setup_with_g_main(server->bus, NULL);
1629 dbus_connection_set_exit_on_disconnect(server->bus, TRUE);
1631 dbus_bus_request_name(server->bus, AVAHI_DBUS_NAME, 0, &error);
1632 if (dbus_error_is_set(&error)) {
1633 avahi_log_warn("dbus_bus_request_name(): %s", error.message);
1637 dbus_bus_add_match(server->bus, "type='signal',""interface='" DBUS_INTERFACE_DBUS "'", &error);
1639 dbus_connection_add_filter(server->bus, msg_signal_filter_impl, loop, NULL);
1640 dbus_connection_register_object_path(server->bus, AVAHI_DBUS_PATH_SERVER, &server_vtable, NULL);
1646 dbus_connection_disconnect(server->bus);
1647 dbus_connection_unref(server->bus);
1650 dbus_error_free (&error);
1656 void dbus_protocol_shutdown(void) {
1660 while (server->clients)
1661 client_free(server->clients);
1663 g_assert(server->n_clients == 0);
1666 dbus_connection_disconnect(server->bus);
1667 dbus_connection_unref(server->bus);