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
355 g_assert(-error > -AVAHI_OK);
356 g_assert(-error < -AVAHI_ERR_MAX);
358 reply = dbus_message_new_error(m, table[-error], text ? text : avahi_strerror(error));
359 dbus_connection_send(c, reply, NULL);
360 dbus_message_unref(reply);
362 return DBUS_HANDLER_RESULT_HANDLED;
365 static DBusHandlerResult respond_string(DBusConnection *c, DBusMessage *m, const gchar *text) {
368 reply = dbus_message_new_method_return(m);
369 dbus_message_append_args(reply, DBUS_TYPE_STRING, &text, DBUS_TYPE_INVALID);
370 dbus_connection_send(c, reply, NULL);
371 dbus_message_unref(reply);
373 return DBUS_HANDLER_RESULT_HANDLED;
376 static DBusHandlerResult respond_int32(DBusConnection *c, DBusMessage *m, gint32 i) {
379 reply = dbus_message_new_method_return(m);
380 dbus_message_append_args(reply, DBUS_TYPE_INT32, &i, DBUS_TYPE_INVALID);
381 dbus_connection_send(c, reply, NULL);
382 dbus_message_unref(reply);
384 return DBUS_HANDLER_RESULT_HANDLED;
387 static DBusHandlerResult respond_ok(DBusConnection *c, DBusMessage *m) {
390 reply = dbus_message_new_method_return(m);
391 dbus_connection_send(c, reply, NULL);
392 dbus_message_unref(reply);
394 return DBUS_HANDLER_RESULT_HANDLED;
397 static DBusHandlerResult respond_path(DBusConnection *c, DBusMessage *m, const gchar *path) {
400 reply = dbus_message_new_method_return(m);
401 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID);
402 dbus_connection_send(c, reply, NULL);
403 dbus_message_unref(reply);
405 return DBUS_HANDLER_RESULT_HANDLED;
408 static DBusHandlerResult handle_introspect(DBusConnection *c, DBusMessage *m, const gchar *fname) {
411 GError *gerror = NULL;
418 dbus_error_init(&error);
420 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
421 avahi_log_warn("Error parsing Introspect message: %s", error.message);
425 path = g_strdup_printf("%s/%s", AVAHI_DBUS_INTROSPECTION_DIR, fname);
427 if (!(g_file_get_contents(path, &contents, NULL, &gerror))) {
428 avahi_log_warn("Failed to load introspection data: %s", gerror->message);
429 g_error_free(gerror);
436 respond_string(c, m, contents);
439 return DBUS_HANDLER_RESULT_HANDLED;
442 if (dbus_error_is_set(&error))
443 dbus_error_free(&error);
445 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
449 static DBusHandlerResult msg_signal_filter_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
450 GMainLoop *loop = userdata;
453 dbus_error_init(&error);
455 /* avahi_log_debug("dbus: interface=%s, path=%s, member=%s", */
456 /* dbus_message_get_interface(m), */
457 /* dbus_message_get_path(m), */
458 /* dbus_message_get_member(m)); */
460 if (dbus_message_is_signal(m, DBUS_INTERFACE_LOCAL, "Disconnected")) {
461 /* No, we shouldn't quit, but until we get somewhere
462 * usefull such that we can restore our state, we will */
463 avahi_log_warn("Disconnnected from d-bus, terminating...");
464 g_main_loop_quit (loop);
465 return DBUS_HANDLER_RESULT_HANDLED;
467 } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameAcquired")) {
470 if (!dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID)) {
471 avahi_log_warn("Error parsing NameAcquired message");
475 /* avahi_log_info("dbus: name acquired (%s)", name); */
476 return DBUS_HANDLER_RESULT_HANDLED;
478 } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
479 gchar *name, *old, *new;
481 if (!dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &old, DBUS_TYPE_STRING, &new, DBUS_TYPE_INVALID)) {
482 avahi_log_warn("Error parsing NameOwnerChanged message");
489 if ((client = client_get(name, FALSE))) {
490 /* avahi_log_info("dbus: client %s vanished", name); */
497 if (dbus_error_is_set(&error))
498 dbus_error_free(&error);
500 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
503 static void entry_group_callback(AvahiServer *s, AvahiSEntryGroup *g, AvahiEntryGroupState state, gpointer userdata) {
504 EntryGroupInfo *i = userdata;
512 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "StateChanged");
514 dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_INVALID);
515 dbus_message_set_destination(m, i->client->name);
516 dbus_connection_send(server->bus, m, NULL);
517 dbus_message_unref(m);
520 static DBusHandlerResult msg_entry_group_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
522 EntryGroupInfo *i = userdata;
528 dbus_error_init(&error);
530 avahi_log_debug("dbus: interface=%s, path=%s, member=%s",
531 dbus_message_get_interface(m),
532 dbus_message_get_path(m),
533 dbus_message_get_member(m));
536 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
537 return handle_introspect(c, m, "EntryGroup.introspect");
540 if (strcmp(dbus_message_get_sender(m), i->client->name))
541 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
543 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Free")) {
545 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
546 avahi_log_warn("Error parsing EntryGroup::Free message");
551 return respond_ok(c, m);
553 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Commit")) {
555 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
556 avahi_log_warn("Error parsing EntryGroup::Commit message");
560 avahi_s_entry_group_commit(i->entry_group);
561 return respond_ok(c, m);
564 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Reset")) {
566 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
567 avahi_log_warn("Error parsing EntryGroup::Reset message");
571 avahi_s_entry_group_reset(i->entry_group);
572 return respond_ok(c, m);
574 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "IsEmpty")) {
578 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
579 avahi_log_warn("Error parsing EntryGroup::IsEmpty message");
583 b = !!avahi_s_entry_group_is_empty(i->entry_group);
585 reply = dbus_message_new_method_return(m);
586 dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &b, DBUS_TYPE_INVALID);
587 dbus_connection_send(c, reply, NULL);
588 dbus_message_unref(reply);
590 return DBUS_HANDLER_RESULT_HANDLED;
592 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "GetState")) {
593 AvahiEntryGroupState state;
595 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
596 avahi_log_warn("Error parsing EntryGroup::GetState message");
600 state = avahi_s_entry_group_get_state(i->entry_group);
601 return respond_int32(c, m, (gint32) state);
603 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddService")) {
604 gint32 interface, protocol;
605 gchar *type, *name, *domain, *host;
607 AvahiStringList *strlst;
608 DBusMessageIter iter, sub;
611 if (!dbus_message_get_args(
613 DBUS_TYPE_INT32, &interface,
614 DBUS_TYPE_INT32, &protocol,
615 DBUS_TYPE_STRING, &name,
616 DBUS_TYPE_STRING, &type,
617 DBUS_TYPE_STRING, &domain,
618 DBUS_TYPE_STRING, &host,
619 DBUS_TYPE_UINT16, &port,
620 DBUS_TYPE_INVALID) || !type || !name) {
621 avahi_log_warn("Error parsing EntryGroup::AddService message");
625 dbus_message_iter_init(m, &iter);
627 for (j = 0; j < 7; j++)
628 dbus_message_iter_next(&iter);
630 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
631 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_ARRAY) {
632 avahi_log_warn("Error parsing EntryGroup::AddService message 2");
637 dbus_message_iter_recurse(&iter, &sub);
640 DBusMessageIter sub2;
644 if ((at = dbus_message_iter_get_arg_type(&sub)) == DBUS_TYPE_INVALID)
647 g_assert(at == DBUS_TYPE_ARRAY);
649 if (dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_BYTE) {
650 avahi_log_warn("Error parsing EntryGroup::AddService message");
654 dbus_message_iter_recurse(&sub, &sub2);
655 dbus_message_iter_get_fixed_array(&sub2, &k, &n);
656 strlst = avahi_string_list_add_arbitrary(strlst, k, n);
658 dbus_message_iter_next(&sub);
661 if (i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) {
662 avahi_string_list_free(strlst);
663 avahi_log_warn("Too many entries per entry group, client request failed.");
664 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
667 if (domain && !*domain)
673 if (avahi_server_add_service_strlst(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, type, domain, host, port, strlst) < 0) {
674 avahi_string_list_free(strlst);
675 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
679 avahi_string_list_free(strlst);
681 return respond_ok(c, m);
683 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddAddress")) {
684 gint32 interface, protocol;
685 gchar *name, *address;
688 if (!dbus_message_get_args(
690 DBUS_TYPE_INT32, &interface,
691 DBUS_TYPE_INT32, &protocol,
692 DBUS_TYPE_STRING, &name,
693 DBUS_TYPE_STRING, &address,
694 DBUS_TYPE_INVALID) || !name || !address) {
695 avahi_log_warn("Error parsing EntryGroup::AddAddress message");
699 if (i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) {
700 avahi_log_warn("Too many entries per entry group, client request failed.");
701 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
704 if (!(avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))) {
705 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
708 if (avahi_server_add_address(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, 0, name, &a) < 0)
709 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
713 return respond_ok(c, m);
716 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
719 if (dbus_error_is_set(&error))
720 dbus_error_free(&error);
722 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
725 static void host_name_resolver_callback(AvahiSHostNameResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const gchar *host_name, const AvahiAddress *a, gpointer userdata) {
726 HostNameResolverInfo *i = userdata;
732 if (event == AVAHI_RESOLVER_FOUND) {
733 char t[256], *pt = t;
734 gint32 i_interface, i_protocol, i_aprotocol;
738 avahi_address_snprint(t, sizeof(t), a);
740 i_interface = (gint32) interface;
741 i_protocol = (gint32) protocol;
742 i_aprotocol = (gint32) a->family;
744 reply = dbus_message_new_method_return(i->message);
745 dbus_message_append_args(
747 DBUS_TYPE_INT32, &i_interface,
748 DBUS_TYPE_INT32, &i_protocol,
749 DBUS_TYPE_STRING, &host_name,
750 DBUS_TYPE_INT32, &i_aprotocol,
751 DBUS_TYPE_STRING, &pt,
754 dbus_connection_send(server->bus, reply, NULL);
755 dbus_message_unref(reply);
757 g_assert(event == AVAHI_RESOLVER_TIMEOUT);
759 respond_error(server->bus, i->message, AVAHI_ERR_TIMEOUT, NULL);
762 host_name_resolver_free(i);
765 static void address_resolver_callback(AvahiSAddressResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const AvahiAddress *address, const gchar *host_name, gpointer userdata) {
766 AddressResolverInfo *i = userdata;
772 if (event == AVAHI_RESOLVER_FOUND) {
773 char t[256], *pt = t;
774 gint32 i_interface, i_protocol, i_aprotocol;
778 avahi_address_snprint(t, sizeof(t), address);
780 i_interface = (gint32) interface;
781 i_protocol = (gint32) protocol;
782 i_aprotocol = (gint32) address->family;
784 reply = dbus_message_new_method_return(i->message);
785 dbus_message_append_args(
787 DBUS_TYPE_INT32, &i_interface,
788 DBUS_TYPE_INT32, &i_protocol,
789 DBUS_TYPE_INT32, &i_aprotocol,
790 DBUS_TYPE_STRING, &pt,
791 DBUS_TYPE_STRING, &host_name,
794 dbus_connection_send(server->bus, reply, NULL);
795 dbus_message_unref(reply);
797 g_assert(event == AVAHI_RESOLVER_TIMEOUT);
798 respond_error(server->bus, i->message, AVAHI_ERR_TIMEOUT, NULL);
801 address_resolver_free(i);
804 static DBusHandlerResult msg_domain_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
806 DomainBrowserInfo *i = userdata;
812 dbus_error_init(&error);
814 avahi_log_debug("dbus: interface=%s, path=%s, member=%s",
815 dbus_message_get_interface(m),
816 dbus_message_get_path(m),
817 dbus_message_get_member(m));
820 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
821 return handle_introspect(c, m, "DomainBrowser.introspect");
824 if (strcmp(dbus_message_get_sender(m), i->client->name))
825 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
827 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, "Free")) {
829 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
830 avahi_log_warn("Error parsing DomainBrowser::Free message");
834 domain_browser_free(i);
835 return respond_ok(c, m);
839 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
842 if (dbus_error_is_set(&error))
843 dbus_error_free(&error);
845 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
848 static void domain_browser_callback(AvahiSDomainBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const gchar *domain, gpointer userdata) {
849 DomainBrowserInfo *i = userdata;
851 gint32 i_interface, i_protocol;
857 i_interface = (gint32) interface;
858 i_protocol = (gint32) protocol;
860 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, event == AVAHI_BROWSER_NEW ? "ItemNew" : "ItemRemove");
861 dbus_message_append_args(
863 DBUS_TYPE_INT32, &i_interface,
864 DBUS_TYPE_INT32, &i_protocol,
865 DBUS_TYPE_STRING, &domain,
867 dbus_message_set_destination(m, i->client->name);
868 dbus_connection_send(server->bus, m, NULL);
869 dbus_message_unref(m);
872 static DBusHandlerResult msg_service_type_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
874 ServiceTypeBrowserInfo *i = userdata;
880 dbus_error_init(&error);
882 avahi_log_debug("dbus: interface=%s, path=%s, member=%s",
883 dbus_message_get_interface(m),
884 dbus_message_get_path(m),
885 dbus_message_get_member(m));
888 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
889 return handle_introspect(c, m, "ServiceTypeBrowser.introspect");
892 if (strcmp(dbus_message_get_sender(m), i->client->name))
893 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
895 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, "Free")) {
897 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
898 avahi_log_warn("Error parsing ServiceTypeBrowser::Free message");
902 service_type_browser_free(i);
903 return respond_ok(c, m);
907 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
910 if (dbus_error_is_set(&error))
911 dbus_error_free(&error);
913 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
916 static void service_type_browser_callback(AvahiSServiceTypeBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const gchar *type, const gchar *domain, gpointer userdata) {
917 ServiceTypeBrowserInfo *i = userdata;
919 gint32 i_interface, i_protocol;
926 i_interface = (gint32) interface;
927 i_protocol = (gint32) protocol;
929 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, event == AVAHI_BROWSER_NEW ? "ItemNew" : "ItemRemove");
930 dbus_message_append_args(
932 DBUS_TYPE_INT32, &i_interface,
933 DBUS_TYPE_INT32, &i_protocol,
934 DBUS_TYPE_STRING, &type,
935 DBUS_TYPE_STRING, &domain,
937 dbus_message_set_destination(m, i->client->name);
938 dbus_connection_send(server->bus, m, NULL);
939 dbus_message_unref(m);
942 static DBusHandlerResult msg_service_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
944 ServiceBrowserInfo *i = userdata;
950 dbus_error_init(&error);
952 avahi_log_debug("dbus: interface=%s, path=%s, member=%s",
953 dbus_message_get_interface(m),
954 dbus_message_get_path(m),
955 dbus_message_get_member(m));
958 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
959 return handle_introspect(c, m, "ServiceBrowser.Introspect");
962 if (strcmp(dbus_message_get_sender(m), i->client->name))
963 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
965 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, "Free")) {
967 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
968 avahi_log_warn("Error parsing ServiceBrowser::Free message");
972 service_browser_free(i);
973 return respond_ok(c, m);
977 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
980 if (dbus_error_is_set(&error))
981 dbus_error_free(&error);
983 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
986 static void service_browser_callback(AvahiSServiceBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const gchar *name, const gchar *type, const gchar *domain, gpointer userdata) {
987 ServiceBrowserInfo *i = userdata;
989 gint32 i_interface, i_protocol;
997 i_interface = (gint32) interface;
998 i_protocol = (gint32) protocol;
1000 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, event == AVAHI_BROWSER_NEW ? "ItemNew" : "ItemRemove");
1001 dbus_message_append_args(
1003 DBUS_TYPE_INT32, &i_interface,
1004 DBUS_TYPE_INT32, &i_protocol,
1005 DBUS_TYPE_STRING, &name,
1006 DBUS_TYPE_STRING, &type,
1007 DBUS_TYPE_STRING, &domain,
1009 dbus_message_set_destination(m, i->client->name);
1010 dbus_connection_send(server->bus, m, NULL);
1011 dbus_message_unref(m);
1014 static void service_resolver_callback(
1015 AvahiSServiceResolver *r,
1016 AvahiIfIndex interface,
1017 AvahiProtocol protocol,
1018 AvahiResolverEvent event,
1021 const gchar *domain,
1022 const gchar *host_name,
1023 const AvahiAddress *a,
1025 AvahiStringList *txt,
1026 gpointer userdata) {
1028 ServiceResolverInfo *i = userdata;
1033 if (event == AVAHI_RESOLVER_FOUND) {
1034 char t[256], *pt = t;
1035 gint32 i_interface, i_protocol, i_aprotocol;
1039 DBusMessageIter iter, sub;
1041 g_assert(host_name);
1044 avahi_address_snprint(t, sizeof(t), a);
1046 i_interface = (gint32) interface;
1047 i_protocol = (gint32) protocol;
1048 i_aprotocol = (gint32) a->family;
1050 reply = dbus_message_new_method_return(i->message);
1051 dbus_message_append_args(
1053 DBUS_TYPE_INT32, &i_interface,
1054 DBUS_TYPE_INT32, &i_protocol,
1055 DBUS_TYPE_STRING, &name,
1056 DBUS_TYPE_STRING, &type,
1057 DBUS_TYPE_STRING, &domain,
1058 DBUS_TYPE_STRING, &host_name,
1059 DBUS_TYPE_INT32, &i_aprotocol,
1060 DBUS_TYPE_STRING, &pt,
1061 DBUS_TYPE_UINT16, &port,
1064 dbus_message_iter_init_append(reply, &iter);
1065 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "ay", &sub);
1067 for (p = txt, j = n-1; p; p = p->next, j--) {
1068 DBusMessageIter sub2;
1069 const guint8 *data = p->text;
1071 dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "y", &sub2);
1072 dbus_message_iter_append_fixed_array(&sub2, DBUS_TYPE_BYTE, &data, p->size);
1073 dbus_message_iter_close_container(&sub, &sub2);
1076 dbus_message_iter_close_container(&iter, &sub);
1078 dbus_connection_send(server->bus, reply, NULL);
1079 dbus_message_unref(reply);
1081 g_assert(event == AVAHI_RESOLVER_TIMEOUT);
1083 respond_error(server->bus, i->message, AVAHI_ERR_TIMEOUT, NULL);
1086 service_resolver_free(i);
1089 static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1092 dbus_error_init(&error);
1094 avahi_log_debug("dbus: interface=%s, path=%s, member=%s",
1095 dbus_message_get_interface(m),
1096 dbus_message_get_path(m),
1097 dbus_message_get_member(m));
1099 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1100 return handle_introspect(c, m, "Server.introspect");
1102 else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostName")) {
1104 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1105 avahi_log_warn("Error parsing Server::GetHostName message");
1109 return respond_string(c, m, avahi_server_get_host_name(avahi_server));
1111 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetDomainName")) {
1113 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1114 avahi_log_warn("Error parsing Server::GetDomainName message");
1118 return respond_string(c, m, avahi_server_get_domain_name(avahi_server));
1120 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostNameFqdn")) {
1122 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1123 avahi_log_warn("Error parsing Server::GetHostNameFqdn message");
1127 return respond_string(c, m, avahi_server_get_host_name_fqdn(avahi_server));
1129 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetVersionString")) {
1131 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1132 avahi_log_warn("Error parsing Server::GetVersionString message");
1136 return respond_string(c, m, PACKAGE_STRING);
1138 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetState")) {
1139 AvahiServerState state;
1141 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1142 avahi_log_warn("Error parsing Server::GetState message");
1146 state = avahi_server_get_state(avahi_server);
1147 return respond_int32(c, m, (gint32) state);
1149 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceNameByIndex")) {
1154 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INT32, &idx, DBUS_TYPE_INVALID))) {
1155 avahi_log_warn("Error parsing Server::GetNetworkInterfaceNameByIndex message");
1159 #ifdef VALGRIND_WORKAROUND
1160 return respond_string(c, m, "blah");
1163 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1165 g_snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1166 return respond_error(c, m, AVAHI_ERR_OS, txt);
1169 memset(&ifr, 0, sizeof(ifr));
1170 ifr.ifr_ifindex = idx;
1172 if (ioctl(fd, SIOCGIFNAME, &ifr) < 0) {
1174 g_snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1176 return respond_error(c, m, AVAHI_ERR_OS, txt);
1181 return respond_string(c, m, ifr.ifr_name);
1184 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceIndexByName")) {
1189 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1190 avahi_log_warn("Error parsing Server::GetNetworkInterfaceIndexByName message");
1194 #ifdef VALGRIND_WORKAROUND
1195 return respond_int32(c, m, 1);
1197 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1199 g_snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1200 return respond_error(c, m, AVAHI_ERR_OS, txt);
1203 memset(&ifr, 0, sizeof(ifr));
1204 g_snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", n);
1206 if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
1208 g_snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1210 return respond_error(c, m, AVAHI_ERR_OS, txt);
1215 return respond_int32(c, m, ifr.ifr_ifindex);
1218 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeHostName")) {
1221 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1222 avahi_log_warn("Error parsing Server::GetAlternativeHostName message");
1226 t = avahi_alternative_host_name(n);
1227 respond_string(c, m, t);
1230 return DBUS_HANDLER_RESULT_HANDLED;
1232 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeServiceName")) {
1235 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1236 avahi_log_warn("Error parsing Server::GetAlternativeServiceName message");
1240 t = avahi_alternative_service_name(n);
1241 respond_string(c, m, t);
1244 return DBUS_HANDLER_RESULT_HANDLED;
1246 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "EntryGroupNew")) {
1249 static const DBusObjectPathVTable vtable = {
1251 msg_entry_group_impl,
1258 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1259 avahi_log_warn("Error parsing Server::EntryGroupNew message");
1263 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1264 avahi_log_warn("Too many clients, client request failed.");
1265 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1268 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1269 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1270 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1273 i = g_new(EntryGroupInfo, 1);
1274 i->id = ++client->current_id;
1276 i->path = g_strdup_printf("/Client%u/EntryGroup%u", client->id, i->id);
1278 AVAHI_LLIST_PREPEND(EntryGroupInfo, entry_groups, client->entry_groups, i);
1279 client->n_objects++;
1281 if (!(i->entry_group = avahi_s_entry_group_new(avahi_server, entry_group_callback, i))) {
1282 entry_group_free(i);
1283 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1286 dbus_connection_register_object_path(c, i->path, &vtable, i);
1287 return respond_path(c, m, i->path);
1289 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveHostName")) {
1291 gint32 interface, protocol, aprotocol;
1293 HostNameResolverInfo *i;
1295 if (!dbus_message_get_args(
1297 DBUS_TYPE_INT32, &interface,
1298 DBUS_TYPE_INT32, &protocol,
1299 DBUS_TYPE_STRING, &name,
1300 DBUS_TYPE_INT32, &aprotocol,
1301 DBUS_TYPE_INVALID) || !name) {
1302 avahi_log_warn("Error parsing Server::ResolveHostName message");
1306 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1307 avahi_log_warn("Too many clients, client request failed.");
1308 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1311 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1312 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1313 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1316 i = g_new(HostNameResolverInfo, 1);
1318 i->message = dbus_message_ref(m);
1319 AVAHI_LLIST_PREPEND(HostNameResolverInfo, host_name_resolvers, client->host_name_resolvers, i);
1320 client->n_objects++;
1322 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))) {
1323 host_name_resolver_free(i);
1324 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1327 return DBUS_HANDLER_RESULT_HANDLED;
1329 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveAddress")) {
1331 gint32 interface, protocol;
1333 AddressResolverInfo *i;
1336 if (!dbus_message_get_args(
1338 DBUS_TYPE_INT32, &interface,
1339 DBUS_TYPE_INT32, &protocol,
1340 DBUS_TYPE_STRING, &address,
1341 DBUS_TYPE_INVALID) || !address) {
1342 avahi_log_warn("Error parsing Server::ResolveAddress message");
1346 if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
1347 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
1349 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1350 avahi_log_warn("Too many clients, client request failed.");
1351 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1354 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1355 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1356 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1359 i = g_new(AddressResolverInfo, 1);
1361 i->message = dbus_message_ref(m);
1362 AVAHI_LLIST_PREPEND(AddressResolverInfo, address_resolvers, client->address_resolvers, i);
1363 client->n_objects++;
1365 if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, address_resolver_callback, i))) {
1366 address_resolver_free(i);
1367 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1370 return DBUS_HANDLER_RESULT_HANDLED;
1372 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "DomainBrowserNew")) {
1374 DomainBrowserInfo *i;
1375 static const DBusObjectPathVTable vtable = {
1377 msg_domain_browser_impl,
1383 gint32 interface, protocol, type;
1387 if (!dbus_message_get_args(
1389 DBUS_TYPE_INT32, &interface,
1390 DBUS_TYPE_INT32, &protocol,
1391 DBUS_TYPE_STRING, &domain,
1392 DBUS_TYPE_INT32, &type,
1393 DBUS_TYPE_INVALID) || type < 0 || type >= AVAHI_DOMAIN_BROWSER_MAX) {
1394 avahi_log_warn("Error parsing Server::DomainBrowserNew message");
1398 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1399 avahi_log_warn("Too many clients, client request failed.");
1400 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1403 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1404 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1405 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1411 i = g_new(DomainBrowserInfo, 1);
1412 i->id = ++client->current_id;
1414 i->path = g_strdup_printf("/Client%u/DomainBrowser%u", client->id, i->id);
1415 AVAHI_LLIST_PREPEND(DomainBrowserInfo, domain_browsers, client->domain_browsers, i);
1416 client->n_objects++;
1418 if (!(i->domain_browser = avahi_s_domain_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, domain, (AvahiDomainBrowserType) type, domain_browser_callback, i))) {
1419 domain_browser_free(i);
1420 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1423 dbus_connection_register_object_path(c, i->path, &vtable, i);
1424 return respond_path(c, m, i->path);
1426 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceTypeBrowserNew")) {
1428 ServiceTypeBrowserInfo *i;
1429 static const DBusObjectPathVTable vtable = {
1431 msg_service_type_browser_impl,
1437 gint32 interface, protocol;
1440 if (!dbus_message_get_args(
1442 DBUS_TYPE_INT32, &interface,
1443 DBUS_TYPE_INT32, &protocol,
1444 DBUS_TYPE_STRING, &domain,
1445 DBUS_TYPE_INVALID)) {
1446 avahi_log_warn("Error parsing Server::ServiceTypeBrowserNew message");
1450 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1451 avahi_log_warn("Too many clients, client request failed.");
1452 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1456 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1457 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1458 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1464 i = g_new(ServiceTypeBrowserInfo, 1);
1465 i->id = ++client->current_id;
1467 i->path = g_strdup_printf("/Client%u/ServiceTypeBrowser%u", client->id, i->id);
1468 AVAHI_LLIST_PREPEND(ServiceTypeBrowserInfo, service_type_browsers, client->service_type_browsers, i);
1469 client->n_objects++;
1471 if (!(i->service_type_browser = avahi_s_service_type_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, domain, service_type_browser_callback, i))) {
1472 service_type_browser_free(i);
1473 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1476 dbus_connection_register_object_path(c, i->path, &vtable, i);
1477 return respond_path(c, m, i->path);
1479 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceBrowserNew")) {
1481 ServiceBrowserInfo *i;
1482 static const DBusObjectPathVTable vtable = {
1484 msg_service_browser_impl,
1490 gint32 interface, protocol;
1491 gchar *domain, *type;
1493 if (!dbus_message_get_args(
1495 DBUS_TYPE_INT32, &interface,
1496 DBUS_TYPE_INT32, &protocol,
1497 DBUS_TYPE_STRING, &type,
1498 DBUS_TYPE_STRING, &domain,
1499 DBUS_TYPE_INVALID) || !type) {
1500 avahi_log_warn("Error parsing Server::ServiceBrowserNew message");
1504 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1505 avahi_log_warn("Too many clients, client request failed.");
1506 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1510 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1511 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1512 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1518 i = g_new(ServiceBrowserInfo, 1);
1519 i->id = ++client->current_id;
1521 i->path = g_strdup_printf("/Client%u/ServiceBrowser%u", client->id, i->id);
1522 AVAHI_LLIST_PREPEND(ServiceBrowserInfo, service_browsers, client->service_browsers, i);
1523 client->n_objects++;
1525 if (!(i->service_browser = avahi_s_service_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, type, domain, service_browser_callback, i))) {
1526 service_browser_free(i);
1527 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1530 dbus_connection_register_object_path(c, i->path, &vtable, i);
1531 return respond_path(c, m, i->path);
1533 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveService")) {
1535 gint32 interface, protocol, aprotocol;
1536 gchar *name, *type, *domain;
1537 ServiceResolverInfo *i;
1539 if (!dbus_message_get_args(
1541 DBUS_TYPE_INT32, &interface,
1542 DBUS_TYPE_INT32, &protocol,
1543 DBUS_TYPE_STRING, &name,
1544 DBUS_TYPE_STRING, &type,
1545 DBUS_TYPE_STRING, &domain,
1546 DBUS_TYPE_INT32, &aprotocol,
1547 DBUS_TYPE_INVALID) || !name || !type) {
1548 avahi_log_warn("Error parsing Server::ResolveService message");
1552 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1553 avahi_log_warn("Too many clients, client request failed.");
1554 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1557 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1558 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1559 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1565 i = g_new(ServiceResolverInfo, 1);
1567 i->message = dbus_message_ref(m);
1568 AVAHI_LLIST_PREPEND(ServiceResolverInfo, service_resolvers, client->service_resolvers, i);
1569 client->n_objects++;
1571 if (!(i->service_resolver = avahi_s_service_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, type, domain, (AvahiProtocol) aprotocol, service_resolver_callback, i))) {
1572 service_resolver_free(i);
1573 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1576 return DBUS_HANDLER_RESULT_HANDLED;
1579 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1582 if (dbus_error_is_set(&error))
1583 dbus_error_free(&error);
1585 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1588 void dbus_protocol_server_state_changed(AvahiServerState state) {
1595 m = dbus_message_new_signal(AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "StateChanged");
1597 dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_INVALID);
1598 dbus_connection_send(server->bus, m, NULL);
1599 dbus_message_unref(m);
1602 int dbus_protocol_setup(GMainLoop *loop) {
1605 static const DBusObjectPathVTable server_vtable = {
1614 dbus_error_init(&error);
1616 server = g_malloc(sizeof(Server));
1617 server->clients = NULL;
1618 server->current_id = 0;
1619 server->n_clients = 0;
1621 server->bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
1622 if (dbus_error_is_set(&error)) {
1623 avahi_log_warn("dbus_bus_get(): %s", error.message);
1627 dbus_connection_setup_with_g_main(server->bus, NULL);
1628 dbus_connection_set_exit_on_disconnect(server->bus, TRUE);
1630 dbus_bus_request_name(server->bus, AVAHI_DBUS_NAME, 0, &error);
1631 if (dbus_error_is_set(&error)) {
1632 avahi_log_warn("dbus_bus_request_name(): %s", error.message);
1636 dbus_bus_add_match(server->bus, "type='signal',""interface='" DBUS_INTERFACE_DBUS "'", &error);
1638 dbus_connection_add_filter(server->bus, msg_signal_filter_impl, loop, NULL);
1639 dbus_connection_register_object_path(server->bus, AVAHI_DBUS_PATH_SERVER, &server_vtable, NULL);
1645 dbus_connection_disconnect(server->bus);
1646 dbus_connection_unref(server->bus);
1649 dbus_error_free (&error);
1655 void dbus_protocol_shutdown(void) {
1659 while (server->clients)
1660 client_free(server->clients);
1662 g_assert(server->n_clients == 0);
1665 dbus_connection_disconnect(server->bus);
1666 dbus_connection_unref(server->bus);