2008-09-07 01:48:05 +03:00
|
|
|
/*
|
|
|
|
* LASH
|
|
|
|
*
|
|
|
|
* Copyright (C) 2008 Juuso Alasuutari <juuso.alasuutari@gmail.com>
|
|
|
|
* Copyright (C) 2008 Nedko Arnaudov
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
2009-07-12 22:56:19 +03:00
|
|
|
#include "object_path.h"
|
|
|
|
#include "../common/safety.h"
|
|
|
|
#include "../common/debug.h"
|
2009-07-13 00:15:44 +03:00
|
|
|
#include "introspection.h" /* g_dbus_interface_dtor_introspectable */
|
|
|
|
#include "error.h" /* lash_dbus_error() */
|
2008-09-07 01:48:05 +03:00
|
|
|
|
|
|
|
static DBusHandlerResult
|
|
|
|
object_path_handler(DBusConnection *connection,
|
|
|
|
DBusMessage *message,
|
|
|
|
void *data);
|
|
|
|
|
|
|
|
static void
|
|
|
|
object_path_handler_unregister(DBusConnection *conn,
|
|
|
|
void *data);
|
|
|
|
|
|
|
|
object_path_t *
|
|
|
|
object_path_new(const char *name,
|
|
|
|
void *context,
|
|
|
|
int num_ifaces,
|
|
|
|
...)
|
|
|
|
{
|
2009-07-13 00:15:44 +03:00
|
|
|
if (!name || !name[0] || num_ifaces < 1) {
|
|
|
|
lash_debug("Invalid arguments");
|
|
|
|
return NULL;
|
|
|
|
}
|
2008-09-07 01:48:05 +03:00
|
|
|
|
2009-07-13 00:15:44 +03:00
|
|
|
lash_debug("Creating object path");
|
2008-09-07 01:48:05 +03:00
|
|
|
|
2009-07-13 00:15:44 +03:00
|
|
|
object_path_t *path;
|
|
|
|
va_list argp;
|
|
|
|
const interface_t **iface_pptr;
|
2008-09-07 01:48:05 +03:00
|
|
|
|
2009-07-13 00:15:44 +03:00
|
|
|
path = lash_malloc(1, sizeof(object_path_t));
|
|
|
|
path->name = lash_strdup(name);
|
|
|
|
path->interfaces = lash_malloc(num_ifaces + 2, sizeof(interface_t *));
|
2008-09-07 01:48:05 +03:00
|
|
|
|
2009-07-13 00:15:44 +03:00
|
|
|
va_start(argp, num_ifaces);
|
2008-09-07 01:48:05 +03:00
|
|
|
|
2009-07-13 00:15:44 +03:00
|
|
|
iface_pptr = path->interfaces;
|
|
|
|
*iface_pptr = &g_dbus_interface_dtor_introspectable;
|
|
|
|
for (++iface_pptr;
|
|
|
|
(*iface_pptr = va_arg(argp, const interface_t *));
|
|
|
|
++iface_pptr);
|
2008-09-07 01:48:05 +03:00
|
|
|
|
2009-07-13 00:15:44 +03:00
|
|
|
va_end(argp);
|
2008-09-07 01:48:05 +03:00
|
|
|
|
2009-07-13 00:15:44 +03:00
|
|
|
if ((path->introspection = introspection_new(path))) {
|
|
|
|
path->context = context;
|
|
|
|
return path;
|
|
|
|
}
|
2008-09-07 01:48:05 +03:00
|
|
|
|
2009-07-13 00:15:44 +03:00
|
|
|
lash_error("Failed to create object path");
|
|
|
|
object_path_destroy(path);
|
2008-09-07 01:48:05 +03:00
|
|
|
|
2009-07-13 00:15:44 +03:00
|
|
|
return NULL;
|
2008-09-07 01:48:05 +03:00
|
|
|
}
|
|
|
|
|
2009-07-31 01:40:04 +03:00
|
|
|
bool
|
2008-09-07 01:48:05 +03:00
|
|
|
object_path_register(DBusConnection *conn,
|
|
|
|
object_path_t *path)
|
|
|
|
{
|
2009-07-13 00:15:44 +03:00
|
|
|
if (!conn || !path || !path->name || !path->interfaces) {
|
|
|
|
lash_debug("Invalid arguments");
|
2009-07-31 01:40:04 +03:00
|
|
|
return false;
|
2009-07-13 00:15:44 +03:00
|
|
|
}
|
2008-09-07 01:48:05 +03:00
|
|
|
|
2009-07-13 00:15:44 +03:00
|
|
|
lash_debug("Registering object path");
|
2008-09-07 01:48:05 +03:00
|
|
|
|
2009-07-13 00:15:44 +03:00
|
|
|
DBusObjectPathVTable vtable =
|
|
|
|
{
|
|
|
|
object_path_handler_unregister,
|
|
|
|
object_path_handler,
|
|
|
|
NULL, NULL, NULL, NULL
|
|
|
|
};
|
2008-09-07 01:48:05 +03:00
|
|
|
|
2009-07-13 00:15:44 +03:00
|
|
|
dbus_connection_register_object_path(conn, path->name,
|
|
|
|
&vtable, (void *) path);
|
2008-09-07 01:48:05 +03:00
|
|
|
|
2009-07-31 01:40:04 +03:00
|
|
|
return true;
|
2008-09-07 01:48:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
object_path_destroy(object_path_t *path)
|
|
|
|
{
|
2009-07-13 00:15:44 +03:00
|
|
|
lash_debug("Destroying object path");
|
|
|
|
|
|
|
|
if (path) {
|
|
|
|
if (path->name) {
|
|
|
|
free(path->name);
|
|
|
|
path->name = NULL;
|
|
|
|
}
|
|
|
|
if (path->interfaces) {
|
|
|
|
free(path->interfaces);
|
|
|
|
path->interfaces = NULL;
|
|
|
|
}
|
|
|
|
introspection_destroy(path);
|
|
|
|
free(path);
|
|
|
|
path = NULL;
|
|
|
|
}
|
2008-09-07 01:48:05 +03:00
|
|
|
#ifdef LASH_DEBUG
|
2009-07-13 00:15:44 +03:00
|
|
|
else
|
|
|
|
lash_debug("Nothing to destroy");
|
2008-09-07 01:48:05 +03:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static DBusHandlerResult
|
|
|
|
object_path_handler(DBusConnection *connection,
|
|
|
|
DBusMessage *message,
|
|
|
|
void *data)
|
|
|
|
{
|
2009-07-13 00:15:44 +03:00
|
|
|
const char *interface_name;
|
|
|
|
const interface_t **iface_pptr;
|
|
|
|
method_call_t call;
|
|
|
|
|
|
|
|
/* Check if the message is a method call. If not, ignore it. */
|
|
|
|
if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_METHOD_CALL) {
|
|
|
|
goto handled;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get the invoked method's name and make sure it's non-NULL. */
|
|
|
|
if (!(call.method_name = dbus_message_get_member(message))) {
|
|
|
|
lash_dbus_error(&call, LASH_DBUS_ERROR_UNKNOWN_METHOD,
|
|
|
|
"Received method call with empty method name");
|
|
|
|
goto send_return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Initialize our data. */
|
|
|
|
call.connection = connection;
|
|
|
|
call.message = message;
|
|
|
|
call.interface = NULL; /* To be set by the default interface handler */
|
|
|
|
call.context = data;
|
|
|
|
call.reply = NULL;
|
|
|
|
|
|
|
|
/* Check if there's an interface specified for this method call. */
|
|
|
|
if ((interface_name = dbus_message_get_interface(message))) {
|
|
|
|
for (iface_pptr = (const interface_t **) ((object_path_t *) data)->interfaces;
|
|
|
|
iface_pptr && *iface_pptr;
|
|
|
|
++iface_pptr) {
|
|
|
|
if (strcmp(interface_name, (*iface_pptr)->name) == 0) {
|
|
|
|
if ((*iface_pptr)->handler(*iface_pptr, &call)) {
|
|
|
|
goto send_return;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* No interface was specified so we have to try them all. This is
|
|
|
|
* dictated by the D-Bus specification which states that method calls
|
|
|
|
* omitting the interface must never be rejected.
|
|
|
|
*/
|
|
|
|
|
|
|
|
for (iface_pptr = (const interface_t **) ((object_path_t *) data)->interfaces;
|
|
|
|
iface_pptr && *iface_pptr;
|
|
|
|
++iface_pptr) {
|
|
|
|
if ((*iface_pptr)->handler(*iface_pptr, &call)) {
|
|
|
|
goto send_return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
lash_dbus_error(&call, LASH_DBUS_ERROR_UNKNOWN_METHOD,
|
|
|
|
"Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist",
|
|
|
|
call.method_name, dbus_message_get_signature(message), interface_name);
|
2008-09-07 01:48:05 +03:00
|
|
|
|
|
|
|
send_return:
|
2009-07-13 00:15:44 +03:00
|
|
|
method_return_send(&call);
|
2008-09-07 01:48:05 +03:00
|
|
|
|
|
|
|
handled:
|
2009-07-13 00:15:44 +03:00
|
|
|
return DBUS_HANDLER_RESULT_HANDLED;
|
2008-09-07 01:48:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
object_path_handler_unregister(DBusConnection *conn,
|
|
|
|
void *data)
|
|
|
|
{
|
|
|
|
#ifdef LASH_DEBUG
|
2009-07-13 00:15:44 +03:00
|
|
|
object_path_t *path = data;
|
|
|
|
lash_debug("Message handler of object path %s was unregistered",
|
|
|
|
(path && path->name) ? path->name : "<unknown>");
|
2008-09-07 01:48:05 +03:00
|
|
|
#endif /* LASH_DEBUG */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* EOF */
|