summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann <sandmann@redhat.com>2008-09-07 10:26:19 -0400
committerSøren Sandmann <sandmann@redhat.com>2008-09-07 10:26:19 -0400
commit51acedbb6059e3d413a449fb9239d67557588067 (patch)
treef6f56119c79cea5907269eb6036c908cedb1eb2a
parent3605605c046d34131a177d0c40bfe73d0acee48d (diff)
Update to latest dbw/invoke
-rw-r--r--dbw-example.c143
-rw-r--r--dbw.c753
-rw-r--r--example.c4
-rw-r--r--invoke.c10
-rw-r--r--libnul.h21
5 files changed, 631 insertions, 300 deletions
diff --git a/dbw-example.c b/dbw-example.c
index 507269a..cf63372 100644
--- a/dbw-example.c
+++ b/dbw-example.c
@@ -1,14 +1,37 @@
+#include <stdio.h>
#include "libnul.h"
+#if 0
+/* This may be a better way of doing it */
+ /* Better:
+ *
+ * dbw_return
+ */
+
+static gboolean
+on_do_stuff (DbwContext *context, int32_t birnan, uint32_t fish, gpointer data)
+{
+ g_print ("do stuff called: ...");
+
+ x = g_strdup_printf ("asdf frasdf %d", fish);
+
+ dbw_return (context, "Birnan was", x);
+
+ g_free (x);
+
+ return TRUE;
+}
+#endif
+
static gboolean
on_do_stuff (gpointer data,
- int32_t birnan, char **emfle,
- uint32_t fish, char **str)
+ int32_t birnan, uint32_t fish,
+ char **emfle, char **str)
{
g_print ("do stuff called: birnan: %d fish: %u\n", birnan, fish);
*emfle = g_strdup_printf ("Birnan was: %d", birnan);
- *str = g_strdup_printf ("Fish was %u\n", fish);
+ *str = g_strdup_printf ("Fish was %u", fish);
return TRUE;
}
@@ -17,26 +40,24 @@ static gboolean
on_another_method (gpointer data, uint32_t x)
{
g_print ("another_method() called in (%s) with parameter %u\n", (char *)data, x);
-
+
return TRUE;
}
static void
load_image (gpointer data, const char *image, int *result)
{
- g_print ("You should like load an image: %s\n", image);
-
+ g_print ("I should like load an image: %s\n", image);
+
*result = 87;
}
-int
-main ()
+static DbwService *
+make_service1 (void)
{
- GMainLoop *loop = g_main_loop_new (NULL, TRUE);
-
- DbwService *service = dbw_session_service (
+ return dbw_session_service (
"com.ssp.whatever",
-
+
dbw_object (
"/com/ssp/whatever/birnan/emfle",
"object_info",
@@ -52,7 +73,7 @@ main ()
dbw_parameter_out ("emfle", dbw_type_string()),
dbw_parameter_out ("str", dbw_type_string()),
NULL),
-
+
dbw_method (
"another_method",
(DbwFunction)on_another_method,
@@ -64,10 +85,14 @@ main ()
NULL),
NULL);
+}
- DbwService *service2 = dbw_session_service (
+static DbwService *
+make_service2 (void)
+{
+ return dbw_session_service (
"org.gnome.siv",
-
+
dbw_object (
"/org/gnome/siv",
NULL,
@@ -87,7 +112,64 @@ main ()
NULL),
NULL);
+}
+static void
+on_do_stuff_reply (const char *emfle, const char *str, const GError *err, gpointer data)
+{
+ g_print ("do stuff reply: \"%s\", \"%s\"\n", emfle, str);
+}
+
+static void
+on_reply (int result, const GError *err, DbwService *service)
+{
+ if (!err)
+ g_print ("The result was %d\n", result);
+ else
+ g_print ("An error occurred\n");
+
+ dbw_invoke (service,
+ "/com/ssp/whatever/birnan/emfle/com.ssp.interface.do_stuff",
+ (DbwFunction)on_do_stuff_reply, NULL,
+ 100, 200);
+}
+
+DbwService *service;
+DbwService *service2;
+
+static gboolean
+invokes (gpointer data)
+{
+ int i;
+
+ printf ("idle\n");
+
+ for (i = 0; i < 30000; ++i)
+ {
+#if 0
+ dbw_service_stop (service);
+ dbw_service_start (service);
+ dbw_service_stop (service);
+ dbw_service_start (service);
+#endif
+
+ dbw_invoke (service2,
+ "/org/gnome/siv/org.gnome.siv.load_image",
+ (DbwFunction)on_reply, service,
+ "LOLCAT.PNG");
+ }
+
+ return FALSE;
+}
+
+int
+main ()
+{
+ GMainLoop *loop = g_main_loop_new (NULL, TRUE);
+
+ service = make_service1 ();
+ service2 = make_service2 ();
+
if (!dbw_service_start (service2))
{
g_print ("siv already exists, asking it to load the images instead\n");
@@ -97,19 +179,12 @@ main ()
{
g_print ("Couldn't start the service\n");
}
- dbw_service_stop (service);
- dbw_service_start (service);
- dbw_service_stop (service);
- dbw_service_start (service);
- dbw_invoke (service2,
- "/org/gnome/siv/org.gnome.siv.load_image",
- NULL,
- NULL,
- "This is the image");
+ g_idle_add (invokes, service);
+ g_idle_add (g_main_loop_quit, loop);
g_main_loop_run (loop);
-
+
return 0;
}
@@ -121,10 +196,10 @@ bah()
"org.gnome.ScreenSaver",
dbw_object (
"/",
-
+
dbw_interface (
"org.gnome.ScreenSaver",
-
+
dbw_method (
"Throttle",
NULL, NULL,
@@ -132,27 +207,27 @@ bah()
dbw_parameter_in ("reason", dbw_type_string()),
dbw_parameter_out ("cookie", dbw_type_uint32()),
NULL),
-
+
dbw_signal (
"ActiveChanged",
dbw_parameter_in ("new_value", dbw_type_bool()),
NULL),
-
+
NULL),
-
+
NULL),
-
+
NULL);
-
+
dbw_invoke (service, "/org.gnome.ScreenSaver.Throttle", reponse, NULL,
"MyApplication", "None of your business");
-
+
if (!dbw_invoke_wait (service, "/org.gnome.ScreenSaver.Throttle", 1000, &err,
"MyApplication", "None of your business", &cookie))
{
g_print ("timeout\n");
}
-
+
dbw_connect (service, "/org.gnome.ScreenSaver.ActiveChanged", on_active_changed, data);
}
#endif
diff --git a/dbw.c b/dbw.c
index 62bfafa..c0fa1ca 100644
--- a/dbw.c
+++ b/dbw.c
@@ -1,7 +1,6 @@
#include <stdarg.h>
#include <dbus/dbus.h>
#include <string.h>
-#include <glib.h>
#include "libnul.h"
#define INTROSPECT_INTERFACE "org.freedesktop.DBus.Introspectable"
@@ -13,6 +12,7 @@ struct DbwService
GPtrArray *objects;
DBusConnection *connection;
gboolean running;
+ DBusBusType type;
};
struct DbwObject
@@ -30,17 +30,21 @@ struct DbwInterface
struct DbwMember
{
+ char * name;
+
/* For now only methods are supported, although
* later we may also have properties and signals
*/
- DbwInterface * interface;
-
+ DbwInterface * interface; /* containing interface */
+
DbwFunction function;
- char * name;
GPtrArray * parameters;
+ int n_inputs;
+ int n_outputs;
FunDef * fun_def;
+ FunDef * reply_fun;
};
struct DbwParameter
@@ -69,9 +73,9 @@ process_watch (DBusWatch *watch, int flags)
DBusMessage *msg;
dbus_watch_handle (watch, flags);
-
+
connection = dbus_watch_get_data (watch);
-
+
while ((msg = dbus_connection_borrow_message (connection)))
{
dbus_connection_return_message (connection, msg);
@@ -84,7 +88,7 @@ static void
on_hangup (gpointer data)
{
DBusWatch *watch = data;
-
+
process_watch (watch, DBUS_WATCH_HANGUP);
}
@@ -92,7 +96,7 @@ static void
on_error (gpointer data)
{
DBusWatch *watch = data;
-
+
process_watch (watch, DBUS_WATCH_ERROR);
}
@@ -100,11 +104,11 @@ static void
on_read (gpointer data)
{
GList *list = data;
-
+
for (list = data; list != NULL; list = list->next)
{
DBusWatch *watch = list->data;
-
+
if (dbus_watch_get_enabled (watch) &&
(dbus_watch_get_flags (watch) & DBUS_WATCH_READABLE))
{
@@ -117,11 +121,11 @@ static void
on_write (gpointer data)
{
GList *list = data;
-
+
for (list = data; list != NULL; list = list->next)
{
DBusWatch *watch = list->data;
-
+
if (dbus_watch_get_enabled (watch) &&
(dbus_watch_get_flags (watch) & DBUS_WATCH_WRITABLE))
{
@@ -135,33 +139,33 @@ update_fd (int fd)
{
int enabled, flags;
GList *watches, *list;
-
+
watches = fd_get_data (fd);
-
+
enabled = FALSE;
flags = 0;
for (list = watches; list != NULL; list = list->next)
{
DBusWatch *watch = list->data;
-
+
if (dbus_watch_get_enabled (watch))
{
enabled = TRUE;
flags |= dbus_watch_get_flags (watch);
}
}
-
+
if (enabled)
{
fd_set_error_callback (fd, on_hangup);
fd_set_hangup_callback (fd, on_error);
-
+
if (flags & DBUS_WATCH_READABLE)
fd_set_read_callback (fd, on_read);
else
fd_set_read_callback (fd, NULL);
-
+
if (flags & DBUS_WATCH_WRITABLE)
fd_set_write_callback (fd, on_write);
else
@@ -181,7 +185,7 @@ add_watch (DBusWatch *watch, void *data)
{
DBusConnection *connection = data;
int fd = dbus_watch_get_unix_fd (watch);
-
+
dbus_watch_set_data (watch, connection, NULL);
/* DBus apparently will create multiple watches for
@@ -190,18 +194,18 @@ add_watch (DBusWatch *watch, void *data)
if (fd_is_watched (fd))
{
GList *watches = fd_get_data (fd);
-
+
watches = g_list_prepend (watches, watch);
-
+
fd_set_data (fd, watches);
}
else
{
fd_add_watch (fd, g_list_prepend (NULL, watch));
}
-
+
update_fd (fd);
-
+
return TRUE;
}
@@ -210,9 +214,9 @@ remove_watch (DBusWatch *watch, void *data)
{
int fd = dbus_watch_get_unix_fd (watch);
GList *watches = fd_get_data (fd);
-
+
watches = g_list_remove (watches, watch);
-
+
if (!watches)
{
fd_remove_watch (fd);
@@ -234,7 +238,7 @@ static gboolean
on_timeout (gpointer data)
{
DBusTimeout *timeout = data;
-
+
dbus_timeout_handle (timeout);
return TRUE;
@@ -244,14 +248,14 @@ static dbus_bool_t
add_timeout (DBusTimeout *timeout, void *data)
{
dbus_timeout_set_data (timeout, GINT_TO_POINTER (0), NULL);
-
+
if (dbus_timeout_get_enabled (timeout))
{
int id;
id = g_timeout_add (dbus_timeout_get_interval (timeout),
on_timeout, timeout);
-
+
dbus_timeout_set_data (timeout, GINT_TO_POINTER (id), NULL);
}
@@ -262,11 +266,11 @@ static void
remove_timeout (DBusTimeout *timeout, void *data)
{
int id = GPOINTER_TO_INT (dbus_timeout_get_data (timeout));
-
+
if (id)
{
g_source_remove (id);
-
+
dbus_timeout_set_data (timeout, GINT_TO_POINTER (0), NULL);
}
}
@@ -275,7 +279,7 @@ static void
toggle_timeout (DBusTimeout *timeout, void *data)
{
remove_timeout (timeout, NULL);
-
+
add_timeout (timeout, NULL);
}
@@ -293,13 +297,13 @@ static gboolean
do_free (gpointer data)
{
int i;
-
+
for (i = 0; i < free_us->len; ++i)
g_free (free_us->pdata[i]);
-
+
g_ptr_array_free (free_us, TRUE);
free_us = g_ptr_array_new ();
-
+
idle_handler = 0;
return FALSE;
@@ -310,12 +314,12 @@ idle_free (gpointer p)
{
if (!free_us)
free_us = g_ptr_array_new ();
-
+
g_ptr_array_add (free_us, p);
-
+
if (!idle_handler)
idle_handler = g_idle_add (do_free, NULL);
-
+
return p;
}
@@ -354,14 +358,14 @@ introspect (DbwObject *object)
{
DbwMember *member = interface->members->pdata[j];
int k;
-
+
g_string_append_printf (
xml, " <method name=\"%s\">\n", member->name);
-
+
for (k = 0; k < member->parameters->len; ++k)
{
DbwParameter *parameter = member->parameters->pdata[k];
-
+
g_string_append_printf (
xml,
" <arg name=\"%s\" direction=\"%s\" type=\"%s\"/>\n",
@@ -369,153 +373,177 @@ introspect (DbwObject *object)
parameter->out? "out" : "in",
make_signature (parameter->type));
}
-
+
g_string_append_printf (
xml, " </method>\n");
}
g_string_append_printf (xml, " </interface>\n");
}
-
+
g_string_append_printf (xml, "</node>\n");
-
+
return idle_free (g_string_free (xml, FALSE));
}
-static DBusHandlerResult
-invoke (DBusConnection *connection,
- DbwObject *object,
- DbwMember *member,
- DBusMessage *message)
+static gboolean
+decode_message (DBusMessage *message,
+ int n_parameters,
+ DbwParameter **parameters,
+ Arg *args)
{
- Arg *args = idle_free (g_new0 (Arg, member->parameters->len + 1));
- DBusMessage *error_reply;
- DBusMessageIter iter;
- Arg result;
- dbus_bool_t has_args;
+ gboolean has_args;
int i;
+ DBusMessageIter iter;
const char *error;
-
- /* Add the data pointer */
- args[0].v_pointer = object->data;
-
- args++; /* skip object data */
has_args = dbus_message_iter_init (message, &iter);
+
+ /* FIXME: this function should make sure args are initialized to NULL values
+ * when it fails
+ */
- for (i = 0; i < member->parameters->len; ++i)
+ for (i = 0; i < n_parameters; ++i)
{
- DbwParameter *parameter = member->parameters->pdata[i];
+ int dbus_type;
- if (parameter->out)
+ if (!has_args)
{
- switch (parameter->type->type)
- {
- case UINT32:
- args[i].v_pointer = &(args[i].v_uint32);
- break;
-
- case INT32:
- args[i].v_pointer = &(args[i].v_int32);
- break;
-
- case STRING:
- args[i].v_pointer = &(args[i].v_pointer);
- break;
- }
+ error = "Received too few arguments method\n";
+ goto fail;
}
- else
+
+ dbus_type = dbus_message_iter_get_arg_type (&iter);
+
+ switch (parameters[i]->type->type)
{
- int dbus_type;
+ case UINT32:
+ if (dbus_type != DBUS_TYPE_UINT32)
+ {
+ error = "Received wrong type, should be UINT32";
+ goto fail;
+ }
+ dbus_message_iter_get_basic (&iter, &(args[i].v_uint32));
+ break;
- if (!has_args)
+ case INT32:
+ if (dbus_type != DBUS_TYPE_INT32)
{
- error = "Received too few arguments method\n";
+ error = "Received wrong type, should be INT32";
goto fail;
}
-
- dbus_type = dbus_message_iter_get_arg_type (&iter);
-
- switch (parameter->type->type)
+ dbus_message_iter_get_basic (&iter, &(args[i].v_int32));
+ break;
+
+ case STRING:
+ if (dbus_type != DBUS_TYPE_STRING)
{
- case UINT32:
- if (dbus_type != DBUS_TYPE_UINT32)
- {
- error = "Received wrong type, should be UINT32";
- goto fail;
- }
- dbus_message_iter_get_basic (&iter, &(args[i].v_uint32));
- break;
-
- case INT32:
- if (dbus_type != DBUS_TYPE_INT32)
- {
- error = "Received wrong type, should be INT32";
- goto fail;
- }
- dbus_message_iter_get_basic (&iter, &(args[i].v_int32));
- break;
-
- case STRING:
- if (dbus_type != DBUS_TYPE_STRING)
- {
- error = "Received wrong type, should be STRING";
- goto fail;
- }
- dbus_message_iter_get_basic (&iter, &(args[i].v_pointer));
- break;
+ error = "Received wrong type, should be STRING";
+ goto fail;
}
+ dbus_message_iter_get_basic (&iter, &(args[i].v_pointer));
+ break;
+ }
+
+ if (dbus_type == DBUS_TYPE_INVALID)
+ has_args = FALSE;
+
+ dbus_message_iter_next (&iter);
+ }
- if (dbus_type == DBUS_TYPE_INVALID)
- has_args = FALSE;
+ return TRUE;
- dbus_message_iter_next (&iter);
+fail:
+ g_print ("ERROR: %s\n", error);
+ return FALSE;
+}
+
+static void
+encode_message (DBusMessage *message,
+ int n_parameters,
+ DbwParameter **parameters,
+ Arg *args)
+{
+ DBusMessageIter iter;
+ int i;
+
+ dbus_message_iter_init_append (message, &iter);
+
+ for (i = 0; i < n_parameters; ++i)
+ {
+ DbwParameter *parameter = parameters[i];
+
+ switch (parameter->type->type)
+ {
+ case UINT32:
+ dbus_message_iter_append_basic (
+ &iter, DBUS_TYPE_UINT32, &(args[i].v_uint32));
+ break;
+
+ case INT32:
+ dbus_message_iter_append_basic (
+ &iter, DBUS_TYPE_INT32, &(args[i].v_int32));
+ break;
+
+ case STRING:
+ dbus_message_iter_append_basic (
+ &iter, DBUS_TYPE_STRING, &(args[i].v_pointer));
+
+ /* FIXME: it feels wrong that we are freeing data
+ * passed in by the user. Maybe we should just make the
+ * user idle_free it.
+ *
+ * Even better actually: Have a dbw_return (...) that
+ * the user is expected to call.
+ */
+ g_free (args[i].v_pointer);
+ break;
}
}
+}
+
+static DBusHandlerResult
+invoke (DBusConnection *connection,
+ DbwObject *object,
+ DbwMember *member,
+ DBusMessage *message)
+{
+ Arg *args = idle_free (g_new0 (Arg, member->parameters->len + 1));
+ DBusMessage *error_reply;
+ Arg result;
+ int i;
+
+ /* Add the data pointer */
+ args[0].v_pointer = object->data;
+
+ if (!decode_message (message, member->n_inputs, (DbwParameter **)member->parameters->pdata, &(args[1])))
+ {
+ error_reply = dbus_message_new_error (message, DBUS_ERROR_FAILED, "FIXME: generate a real error");
+
+ dbus_connection_send (connection, error_reply, NULL);
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ for (i = member->n_inputs; i < member->parameters->len; ++i)
+ {
+ DbwParameter *parameter = member->parameters->pdata[i];
- args--; /* Include object data */
- result = fun_def_invoke (member->fun_def, args);
+ g_assert (parameter->out);
+
+ args[i + 1].v_pointer = &(args[i + 1]);
+ }
+
+ result = fun_def_invoke (member->fun_def, (Function)member->function, args);
if (result.v_int32)
{
DBusMessage *reply = dbus_message_new_method_return (message);
- DBusMessageIter iter;
- int i;
- args++; /* Skip object data */
-
- dbus_message_iter_init_append (reply, &iter);
-
- for (i = 0; i < member->parameters->len; ++i)
- {
- DbwParameter *parameter = member->parameters->pdata[i];
-
- if (parameter->out)
- {
- switch (parameter->type->type)
- {
- case UINT32:
- dbus_message_iter_append_basic (
- &iter, DBUS_TYPE_UINT32, &(args[i].v_uint32));
- break;
-
- case INT32:
- dbus_message_iter_append_basic (
- &iter, DBUS_TYPE_INT32, &(args[i].v_int32));
- break;
-
- case STRING:
- dbus_message_iter_append_basic (
- &iter, DBUS_TYPE_STRING, &(args[i].v_pointer));
-
- /* FIXME: it feels wrong that we are freeing data
- * passed by the user. Maybe we should just make the
- * user idle_free it.
- */
- g_free (args[i].v_pointer);
- break;
- }
- }
- }
+
+ encode_message (reply,
+ member->n_outputs,
+ (DbwParameter **)&(member->parameters->pdata[member->n_inputs]),
+ &(args[member->n_inputs + 1]));
dbus_connection_send (connection, reply, NULL);
dbus_message_unref (reply);
@@ -525,13 +553,7 @@ invoke (DBusConnection *connection,
{
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
-
-fail:
- error_reply = dbus_message_new_error (message, DBUS_ERROR_FAILED, error);
-
- dbus_connection_send (connection, error_reply, NULL);
- return DBUS_HANDLER_RESULT_HANDLED;
}
static DBusHandlerResult
@@ -546,7 +568,7 @@ message_function (DBusConnection *connection,
int i;
g_assert (strcmp (object->name, msg_path) == 0);
-
+
/* Introspection */
if (strcmp (msg_interface, INTROSPECT_INTERFACE) == 0 &&
strcmp (msg_member, INTROSPECT_METHOD) == 0)
@@ -557,31 +579,31 @@ message_function (DBusConnection *connection,
dbus_message_append_args (reply,
DBUS_TYPE_STRING, &xml,
DBUS_TYPE_INVALID);
-
+
dbus_connection_send (connection, reply, NULL);
return DBUS_HANDLER_RESULT_HANDLED;
}
-
+
/* Normal method */
for (i = 0; i < object->interfaces->len; ++i)
{
DbwInterface *interface = object->interfaces->pdata[i];
-
+
if (strcmp (msg_interface, interface->name) == 0)
{
int j;
-
+
for (j = 0; j < interface->members->len; ++j)
{
DbwMember *member = interface->members->pdata[j];
-
+
if (strcmp (member->name, msg_member) == 0)
return invoke (connection, object, member, message);
}
}
}
-
+
g_print ("got unknown message\n");
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
@@ -598,7 +620,7 @@ make_ptr_array (gpointer first, va_list parameters)
{
GPtrArray *array = g_ptr_array_new ();
gpointer v;
-
+
if (first)
{
g_ptr_array_add (array, first);
@@ -611,7 +633,7 @@ make_ptr_array (gpointer first, va_list parameters)
v = va_arg (parameters, gpointer);
}
}
-
+
return array;
}
@@ -637,7 +659,7 @@ ensure_connection (DBusConnection **connection,
*connection, NULL);
}
}
-
+
return *connection;
}
@@ -655,22 +677,22 @@ get_connection (DBusBusType type, DBusError *err)
return NULL;
}
-DbwService *
-dbw_session_service (const char *name,
- DbwObject *object1,
- ...)
+static DbwService *
+make_service (const char *name,
+ DBusBusType type,
+ DbwObject *object1,
+ va_list args)
{
DbwService *service = g_new0 (DbwService, 1);
- va_list parameters;
- DBusError err = DBUS_ERROR_INIT;
-
+
service->name = g_strdup (name);
-
- va_start (parameters, object1);
- service->objects = make_ptr_array (object1, parameters);
- va_end (parameters);
-
- service->connection = get_connection (DBUS_BUS_SESSION, &err);
+
+ service->objects = make_ptr_array (object1, args);
+
+ service->type = type;
+
+ service->connection = get_connection (type, NULL);
+
if (!service->connection)
{
/* FIXME */
@@ -680,13 +702,30 @@ dbw_session_service (const char *name,
return service;
}
+DbwService *
+dbw_session_service (const char *name,
+ DbwObject *object1,
+ ...)
+{
+ va_list args;
+ DbwService *service;
+
+ va_start (args, object1);
+
+ service = make_service (name, DBUS_BUS_SESSION, object1, args);
+
+ va_end (args);
+
+ return service;
+}
+
gboolean
dbw_service_start (DbwService *service)
{
DBusError err = DBUS_ERROR_INIT;
int i;
int result;
-
+
if (service->running)
return FALSE;
@@ -700,7 +739,7 @@ dbw_service_start (DbwService *service)
service->name,
DBUS_NAME_FLAG_DO_NOT_QUEUE,
&err);
-
+
if (result == -1)
{
/* FIXME: handle error */
@@ -712,17 +751,17 @@ dbw_service_start (DbwService *service)
case DBUS_REQUEST_NAME_REPLY_IN_QUEUE:
g_assert_not_reached();
break;
-
+
case DBUS_REQUEST_NAME_REPLY_EXISTS:
g_print ("Couldn't get name\n");
return FALSE;
break;
-
+
case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
g_print ("We own this already (?)\n");
return FALSE;
break;
-
+
case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
break;
}
@@ -731,13 +770,13 @@ dbw_service_start (DbwService *service)
for (i = 0; i < service->objects->len; ++i)
{
DbwObject *object = service->objects->pdata[i];
-
+
dbus_connection_register_object_path (
service->connection, object->name, &vtable, object);
}
-
+
service->running = TRUE;
-
+
return TRUE;
}
@@ -745,20 +784,20 @@ void
dbw_service_stop (DbwService *service)
{
int i;
-
+
if (!service->running)
return;
for (i = 0; i < service->objects->len; ++i)
{
DbwObject *object = service->objects->pdata[i];
-
+
dbus_connection_unregister_object_path (
service->connection, object->name);
}
-
+
dbus_bus_release_name (service->connection, service->name, NULL);
-
+
service->running = FALSE;
}
@@ -769,15 +808,15 @@ dbw_object (const char *name,
...)
{
DbwObject *object = g_new0 (DbwObject, 1);
- va_list parameters;
-
+ va_list args;
+
object->name = g_strdup (name);
object->data = data;
- va_start (parameters, interface1);
- object->interfaces = make_ptr_array (interface1, parameters);
- va_end (parameters);
-
+ va_start (args, interface1);
+ object->interfaces = make_ptr_array (interface1, args);
+ va_end (args);
+
/* Add introspection interface */
/* Note: the actual introspection is special cased in invoke(), but we
@@ -806,17 +845,17 @@ dbw_interface (const char *name,
DbwInterface *interface = g_new0 (DbwInterface, 1);
va_list parameters;
int i;
-
+
interface->name = g_strdup (name);
va_start (parameters, member1);
interface->members = make_ptr_array (member1, parameters);
va_end (parameters);
-
+
for (i = 0; i < interface->members->len; ++i)
{
DbwMember *member = interface->members->pdata[i];
-
+
member->interface = interface;
}
@@ -827,12 +866,75 @@ static DbwType *
type_copy (const DbwType *type)
{
DbwType *copy = g_new0 (DbwType, 1);
-
+
copy->type = type->type;
return copy;
}
+static Type
+invoke_type_from_dbw_type (DbwType *t)
+{
+ switch (t->type)
+ {
+ case INT32:
+ return TYPE_INT32;
+ case UINT32:
+ return TYPE_UINT32;
+ case STRING:
+ return TYPE_POINTER;
+ }
+
+ g_warning ("Unknown type %d\n", t->type);
+ return -1;
+}
+
+static FunDef *
+make_fun_def (DbwMember *member)
+{
+ Type *types;
+ int i;
+
+ types = idle_free (g_new0 (Type, member->parameters->len + 1));
+ types[0] = TYPE_POINTER; /* For object->data */
+
+ for (i = 1; i < member->parameters->len; ++i)
+ {
+ DbwParameter *par = member->parameters->pdata[i - 1];
+
+ if (par->out)
+ types[i] = TYPE_POINTER;
+ else
+ types[i] = invoke_type_from_dbw_type (par->type);
+ }
+
+ return fun_def_new (TYPE_INT,
+ member->parameters->len + 1,
+ types);
+}
+
+static FunDef *
+make_reply_fun (DbwMember *member)
+{
+ Type *types;
+ int i, n;
+
+ types = idle_free (g_new0 (Type, member->parameters->len + 2));
+
+ n = 0;
+ for (i = 0; i < member->parameters->len; ++i)
+ {
+ DbwParameter *par = member->parameters->pdata[i];
+
+ if (par->out)
+ types[n++] = invoke_type_from_dbw_type (par->type);
+ }
+
+ types[n++] = TYPE_POINTER; /* data */
+ types[n++] = TYPE_POINTER; /* const GError *err */
+
+ return fun_def_new (TYPE_VOID, n, types);
+}
DbwMember *
dbw_method (const char *name,
@@ -842,9 +944,8 @@ dbw_method (const char *name,
{
DbwMember *member = g_new0 (DbwMember, 1);
va_list parameters;
- Type *types;
int i;
-
+
member->name = g_strdup (name);
member->function = function;
@@ -852,38 +953,30 @@ dbw_method (const char *name,
member->parameters = make_ptr_array ((DbwType *)parameter1, parameters);
va_end (parameters);
- types = g_new0 (Type, member->parameters->len + 1);
- types[0] = TYPE_POINTER; /* For object->data */
-
- for (i = 1; i < member->parameters->len; ++i)
+ member->n_inputs = 0;
+ member->n_outputs = 0;
+ for (i = 0; i < member->parameters->len; ++i)
{
- DbwParameter *par = member->parameters->pdata[i - 1];
+ DbwParameter *par = member->parameters->pdata[i];
if (par->out)
{
- types[i] = TYPE_POINTER;
+ member->n_outputs++;
}
else
{
- switch (par->type->type)
+ member->n_inputs++;
+
+ if (member->n_outputs)
{
- case INT32:
- types[i] = TYPE_INT32;
- break;
- case UINT32:
- types[i] = TYPE_UINT32;
- break;
- case STRING:
- types[i] = TYPE_POINTER;
- break;
+ g_critical ("All output parameters must be specified after the input parameters");
+ return NULL;
}
}
}
-
- member->fun_def = fun_def_new ((Function)member->function,
- TYPE_INT,
- member->parameters->len + 1,
- types);
+
+ member->fun_def = make_fun_def (member);
+ member->reply_fun = make_reply_fun (member);
return member;
}
@@ -894,7 +987,7 @@ make_parameter (const char *name,
gboolean out)
{
DbwParameter *parameter = g_new0 (DbwParameter, 1);
-
+
parameter->name = g_strdup (name);
parameter->type = type_copy (type);
parameter->out = out;
@@ -920,7 +1013,7 @@ static DbwType *
make_type (Type t)
{
DbwType *type = idle_free (g_new0 (DbwType, 1));
-
+
type->type = t;
return type;
@@ -944,23 +1037,67 @@ dbw_type_string (void)
return make_type (STRING);
}
-/* Decomposes strings like this:
+typedef struct
+{
+ DbwFunction callback;
+ gpointer data;
+ DbwMember *method;
+} InvokeInfo;
+
+static void
+on_reply (DBusPendingCall *pending,
+ gpointer data)
+{
+ InvokeInfo *info = data;
+ int n_outputs = info->method->n_outputs;
+ Arg *args = idle_free (g_new0 (Arg, n_outputs + 2));
+ DBusMessage *reply;
+
+ if (!info->callback)
+ return;
+
+ reply = dbus_pending_call_steal_reply (pending);
+
+ if (!reply)
+ {
+ /* FIXME: can this happen? If it can, we should
+ * generate an error.
+ */
+ return;
+ }
+
+ args[n_outputs].v_pointer = NULL; /* GError */
+ if (!decode_message (reply,
+ n_outputs,
+ (DbwParameter **)&(info->method->parameters->pdata[info->method->n_inputs]),
+ args))
+ {
+ /* FIXME: generate an error into args[n_outputs + 1] */
+ args[n_outputs].v_pointer = "ERR";
+ }
+
+ args[n_outputs + 1].v_pointer = info->data;
+
+ fun_def_invoke (info->method->reply_fun, (Function)info->callback, args);
+}
+
+/* Decodes strings like this:
*
* /org.gnome.ScreenSaver.Throttle
*
*/
static gboolean
-decompose_method (const char *method_desc,
- char **object_path,
- char **interface,
- char **method)
+decode_method_desc (const char *method_desc,
+ char **object_path,
+ char **interface,
+ char **method)
{
char *m;
-
+
g_return_val_if_fail (method_desc != NULL, FALSE);
g_return_val_if_fail (strchr (method_desc, '/') != NULL, FALSE);
g_return_val_if_fail (strchr (method_desc, '.') != NULL, FALSE);
-
+
m = strrchr (method_desc, '/');
*object_path = g_strndup (method_desc, m - method_desc);
method_desc = m + 1;
@@ -968,11 +1105,59 @@ decompose_method (const char *method_desc,
m = strrchr (method_desc, '.');
*interface = g_strndup (method_desc, m - method_desc);
method_desc = m;
-
+
*method = g_strdup (m + 1);
return TRUE;
}
+static DbwObject *
+find_object (DbwService *service, const char *name)
+{
+ int i;
+
+ for (i = 0; i < service->objects->len; ++i)
+ {
+ DbwObject *object = service->objects->pdata[i];
+
+ if (strcmp (object->name, name) == 0)
+ return object;
+ }
+
+ return NULL;
+}
+
+static DbwInterface *
+find_interface (DbwObject *object, const char *name)
+{
+ int i;
+
+ for (i = 0; i < object->interfaces->len; ++i)
+ {
+ DbwInterface *interface = object->interfaces->pdata[i];
+
+ if (strcmp (interface->name, name) == 0)
+ return interface;
+ }
+
+ return NULL;
+}
+
+static DbwMember *
+find_member (DbwInterface *interface, const char *name)
+{
+ int i;
+
+ for (i = 0; i < interface->members->len; ++i)
+ {
+ DbwMember *member = interface->members->pdata[i];
+
+ if (strcmp (member->name, name) == 0)
+ return member;
+ }
+
+ return NULL;
+}
+
void
dbw_invoke (DbwService *service,
const char *method_desc,
@@ -980,20 +1165,92 @@ dbw_invoke (DbwService *service,
gpointer data,
...)
{
- char *object, *interface, *method;
-
- decompose_method (method_desc, &object, &interface, &method);
+ char *object_str, *interface_str, *method_str;
+ DbwObject *object;
+ DbwInterface *interface;
+ DbwMember *method;
+ DBusMessage *message;
+ DBusMessageIter iter;
+ DBusConnection *connection;
+ va_list args;
+ InvokeInfo *info;
+ DBusPendingCall *pending;
+ int i;
- g_print ("Path: %s\n", object);
- g_print ("Interface: %s\n", interface);
- g_print ("Method: %s\n", method);
-}
+ g_return_if_fail (service != NULL);
+
+ decode_method_desc (method_desc, &object_str, &interface_str, &method_str);
+
+ object = find_object (service, object_str);
+ interface = find_interface (object, interface_str);
+ method = find_member (interface, method_str);
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (interface != NULL);
+ g_return_if_fail (method != NULL);
+
+ message = dbus_message_new_method_call (
+ service->name, object->name, interface->name, method->name);
+
+ dbus_message_iter_init_append (message, &iter);
+
+ va_start (args, data);
+
+ for (i = 0; i < method->parameters->len; ++i)
+ {
+ DbwParameter *parameter = method->parameters->pdata[i];
+ int32_t i32;
+ uint32_t u32;
+ const char *s;
+
+ if (parameter->out)
+ continue;
-#if 0
-void
-dbw_proxy_invoke (DbwProxy *proxy)
-{
+ switch (parameter->type->type)
+ {
+ case INT32:
+ i32 = va_arg (args, int32_t);
+
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &i32);
+ break;
+
+ case UINT32:
+ u32 = va_arg (args, uint32_t);
+
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &u32);
+ break;
+
+ case STRING:
+ s = va_arg (args, const char *);
+
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &s);
+ break;
+ }
+ }
+ va_end (args);
+
+ connection = get_connection (service->type, NULL);
+
+ dbus_connection_send_with_reply (connection, message, &pending, -1);
+ if (!pending)
+ {
+ /* FIXME: generate an error and call the callback */
+
+ /* Or alternatively, we should deal with getting disconnected,
+ * though it's not clear what we should do with that
+ */
+ }
+ else
+ {
+ info = g_new0 (InvokeInfo, 1);
+
+ info->callback = callback;
+ info->data = data;
+ info->method = method;
+
+ dbus_pending_call_set_notify (pending, on_reply, info, g_free);
+ }
+
+ dbus_message_unref (message);
}
-#endif
-
diff --git a/example.c b/example.c
index 1b0bea2..d8aa9bf 100644
--- a/example.c
+++ b/example.c
@@ -11,9 +11,9 @@ main ()
};
Arg ret;
- FunDef *def = fun_def_new ((Function)printf, TYPE_INT, 2, arg_types);
+ FunDef *def = fun_def_new (TYPE_INT, 2, arg_types);
- ret = fun_def_invoke (def, args);
+ ret = fun_def_invoke (def, (Function)printf, args);
printf ("returned: %d\n", ret.v_int);
diff --git a/invoke.c b/invoke.c
index 73f9205..7012106 100644
--- a/invoke.c
+++ b/invoke.c
@@ -2,12 +2,11 @@
#include <assert.h>
#include <string.h>
#include <stdio.h>
-#include "libnul.h"
#include "ffi.h"
+#include "libnul.h"
struct FunDef
{
- Function fn;
int n_args;
ffi_type *ffi_ret_type;
ffi_type **ffi_arg_types;
@@ -51,8 +50,7 @@ ffi_type_from_type (Type type)
}
FunDef *
-fun_def_new (Function f,
- Type ret_type,
+fun_def_new (Type ret_type,
int n_args,
Type *arg_types)
{
@@ -79,7 +77,6 @@ fun_def_new (Function f,
def->ffi_ret_type = ffi_type_from_type (ret_type);
- def->fn = f;
def->n_args = n_args;
ffi_prep_cif (&def->ffi_cif, FFI_DEFAULT_ABI, n_args, def->ffi_ret_type, def->ffi_arg_types);
@@ -89,6 +86,7 @@ fun_def_new (Function f,
Arg
fun_def_invoke (FunDef *fun,
+ Function f,
Arg *args)
{
void *stack_args[8];
@@ -104,7 +102,7 @@ fun_def_invoke (FunDef *fun,
for (i = 0; i < fun->n_args; ++i)
ffi_args[i] = &(args[i]);
- ffi_call (&(fun->ffi_cif), fun->fn, &ret, ffi_args);
+ ffi_call (&(fun->ffi_cif), f, &ret, ffi_args);
if (ffi_args != stack_args)
free (ffi_args);
diff --git a/libnul.h b/libnul.h
index 9324e13..635e30a 100644
--- a/libnul.h
+++ b/libnul.h
@@ -16,8 +16,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef INVOKE_H
-#define INVOKE_H
+#ifndef __LIBNUL_H
+#define __LIBNUL_H
#include <stdint.h>
#include <glib.h>
@@ -75,14 +75,15 @@ typedef void (* Function)();
typedef struct FunDef FunDef;
-FunDef *fun_def_new (Function f,
- Type ret_type,
+FunDef *fun_def_new (Type ret_type,
int n_args,
Type *arg_types);
Arg fun_def_invoke (FunDef *fun,
+ Function f,
Arg *args);
void fun_def_free (FunDef *fun);
+
/*
* Watching file descriptors
*/
@@ -156,10 +157,10 @@ DbwProxy *dbw_proxy_new_session_service (const char *bus_name,
const char *object,
const char *interface);
-void
-dbw_invoke (DbwService *service,
- const char *method_desc,
- DbwFunction callback,
- gpointer data,
- ...);
+void dbw_invoke (DbwService *service,
+ const char *method_desc,
+ DbwFunction callback,
+ gpointer data,
+ ...);
+
#endif