Dual license dbus helpers to match the libdbus licensing
[ladish.git] / dbus / object_path.c
blob13dd11c3a51665beaad844aa7d2cf8325eff98fa
1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
2 /*
3 * LADI Session Handler (ladish)
5 * Copyright (C) 2008, 2009 Nedko Arnaudov <nedko@arnaudov.name>
6 * Copyright (C) 2008 Juuso Alasuutari <juuso.alasuutari@gmail.com>
8 **************************************************************************
9 * This file contains D-Bus object path helpers
10 **************************************************************************
12 * Licensed under the Academic Free License version 2.1
14 * LADI Session Handler is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * LADI Session Handler is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with LADI Session Handler. If not, see <http://www.gnu.org/licenses/>
26 * or write to the Free Software Foundation, Inc.,
27 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
30 #include "../common.h"
31 #include "object_path.h"
32 #include "../common/safety.h"
33 #include "introspection.h" /* g_dbus_interface_dtor_introspectable */
34 #include "error.h" /* lash_dbus_error() */
36 static DBusHandlerResult
37 object_path_handler(DBusConnection *connection,
38 DBusMessage *message,
39 void *data);
41 static void
42 object_path_handler_unregister(DBusConnection *conn,
43 void *data);
45 struct dbus_object_path *
46 dbus_object_path_new(const char *name,
47 void *context,
48 int num_ifaces,
49 ...)
51 if (!name || !name[0] || num_ifaces < 0)
53 lash_error("Invalid arguments");
54 return NULL;
57 lash_debug("Creating object path");
59 struct dbus_object_path *path;
60 va_list argp;
61 const interface_t **iface_pptr;
63 path = lash_malloc(1, sizeof(struct dbus_object_path));
64 path->name = lash_strdup(name);
65 path->interfaces = lash_malloc(num_ifaces + 2, sizeof(interface_t *));
67 va_start(argp, num_ifaces);
69 iface_pptr = path->interfaces;
70 *iface_pptr++ = &g_dbus_interface_dtor_introspectable;
71 while (num_ifaces > 0)
73 *iface_pptr++ = va_arg(argp, const interface_t *);
74 num_ifaces--;
76 *iface_pptr = NULL;
78 va_end(argp);
80 if ((path->introspection = introspection_new(path))) {
81 path->context = context;
82 return path;
85 lash_error("Failed to create object path");
86 dbus_object_path_destroy(NULL, path);
88 return NULL;
91 bool
92 dbus_object_path_register(DBusConnection *conn,
93 struct dbus_object_path *path)
95 if (!conn || !path || !path->name || !path->interfaces) {
96 lash_debug("Invalid arguments");
97 return false;
100 lash_debug("Registering object path");
102 DBusObjectPathVTable vtable =
104 object_path_handler_unregister,
105 object_path_handler,
106 NULL, NULL, NULL, NULL
109 dbus_connection_register_object_path(conn, path->name,
110 &vtable, (void *) path);
112 return true;
115 void dbus_object_path_destroy(DBusConnection * connection_ptr, struct dbus_object_path * path_ptr)
117 lash_debug("Destroying object path");
119 if (path_ptr)
121 if (connection_ptr != NULL && !dbus_connection_unregister_object_path(connection_ptr, path_ptr->name))
123 lash_error("dbus_connection_unregister_object_path() failed.");
126 if (path_ptr->name)
128 free(path_ptr->name);
129 path_ptr->name = NULL;
132 if (path_ptr->interfaces)
134 free(path_ptr->interfaces);
135 path_ptr->interfaces = NULL;
138 introspection_destroy(path_ptr);
139 free(path_ptr);
141 #ifdef LASH_DEBUG
142 else
144 lash_debug("Nothing to destroy");
146 #endif
150 static DBusHandlerResult
151 object_path_handler(DBusConnection *connection,
152 DBusMessage *message,
153 void *data)
155 const char *interface_name;
156 const interface_t **iface_pptr;
157 method_call_t call;
159 /* Check if the message is a method call. If not, ignore it. */
160 if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_METHOD_CALL) {
161 goto handled;
164 /* Get the invoked method's name and make sure it's non-NULL. */
165 if (!(call.method_name = dbus_message_get_member(message))) {
166 lash_dbus_error(&call, LASH_DBUS_ERROR_UNKNOWN_METHOD,
167 "Received method call with empty method name");
168 goto send_return;
171 /* Initialize our data. */
172 call.connection = connection;
173 call.message = message;
174 call.interface = NULL; /* To be set by the default interface handler */
175 call.context = data;
176 call.reply = NULL;
178 /* Check if there's an interface specified for this method call. */
179 if ((interface_name = dbus_message_get_interface(message)))
181 for (iface_pptr = (const interface_t **) ((struct dbus_object_path *) data)->interfaces;
182 iface_pptr && *iface_pptr;
183 ++iface_pptr)
185 if (strcmp(interface_name, (*iface_pptr)->name) == 0)
187 if ((*iface_pptr)->handler(*iface_pptr, &call))
189 goto send_return;
192 break;
196 else
198 /* No interface was specified so we have to try them all. This is
199 * dictated by the D-Bus specification which states that method calls
200 * omitting the interface must never be rejected.
203 for (iface_pptr = (const interface_t **) ((struct dbus_object_path *) data)->interfaces;
204 iface_pptr && *iface_pptr;
205 ++iface_pptr) {
206 if ((*iface_pptr)->handler(*iface_pptr, &call)) {
207 goto send_return;
212 lash_dbus_error(&call, LASH_DBUS_ERROR_UNKNOWN_METHOD,
213 "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist",
214 call.method_name, dbus_message_get_signature(message), interface_name);
216 send_return:
217 method_return_send(&call);
219 handled:
220 return DBUS_HANDLER_RESULT_HANDLED;
223 static void
224 object_path_handler_unregister(DBusConnection *conn,
225 void *data)
227 #ifdef LASH_DEBUG
228 struct dbus_object_path *path = data;
229 lash_debug("Message handler of object path %s was unregistered",
230 (path && path->name) ? path->name : "<unknown>");
231 #endif /* LASH_DEBUG */
234 /* EOF */