diff options
-rw-r--r-- | dbus.c | 241 | ||||
-rw-r--r-- | libnul.h | 8 |
2 files changed, 176 insertions, 73 deletions
@@ -61,7 +61,7 @@ struct nul_dbus_member_t nul_ptr_t * parameters; int n_inputs; int n_outputs; - + nul_fun_def_t * fun_def; nul_fun_def_t * reply_fun; }; @@ -304,12 +304,12 @@ static gboolean do_free (gpointer data) { nul_ptr_t *p; - + for (p = free_us; *p; ++p) g_free (*p); - + nul_ptr_array_free (free_us); - + free_us = nul_ptr_array_new (); idle_handler = 0; @@ -358,7 +358,7 @@ introspect (nul_dbus_object_t *object) { nul_dbus_interface_t *interface = *p; nul_ptr_t *q; - + g_string_append_printf ( xml, " <interface name=\"%s\">\n", interface->name); @@ -393,7 +393,6 @@ introspect (nul_dbus_object_t *object) return idle_free (g_string_free (xml, FALSE)); } - static gboolean decode_message (DBusMessage *message, int n_parameters, @@ -406,7 +405,7 @@ decode_message (DBusMessage *message, const char *error; has_args = dbus_message_iter_init (message, &iter); - + /* FIXME: this function should make sure args are initialized * to NULL values when it fails */ @@ -421,37 +420,37 @@ decode_message (DBusMessage *message, goto fail; } - dbus_type = dbus_message_iter_get_arg_type (&iter); + dbus_type = dbus_message_iter_get_arg_type (&iter); - switch (parameters[i]->type->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; + switch (parameters[i]->type->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; - 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 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; - } + 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; + } if (dbus_type == DBUS_TYPE_INVALID) has_args = FALSE; @@ -466,6 +465,104 @@ fail: return FALSE; } +static gboolean +decode_arg (nul_arg_t **args, + DBusMessageIter *iter, + nul_dbus_parameter_t *parameter, + char **err) +{ + int dbus_type = dbus_message_iter_get_arg_type (iter); + nul_arg_t arg; + + switch (parameter->type->type) + { + case UINT32: + if (dbus_type != DBUS_TYPE_UINT32) + { + *err = "Received wrong type, should be UINT32"; + return FALSE; + } + dbus_message_iter_get_basic (iter, &arg.v_uint32); + break; + + case INT32: + if (dbus_type != DBUS_TYPE_INT32) + { + *err = "Received wrong type, should be INT32"; + return FALSE; + } + dbus_message_iter_get_basic (iter, &arg.v_int32); + break; + + case STRING: + if (dbus_type != DBUS_TYPE_STRING) + { + *err = "Received wrong type, should be STRING"; + return FALSE; + } + dbus_message_iter_get_basic (iter, &arg.v_pointer); + break; + } + + *args = nul_array_append (*args, &arg); + + return TRUE; +} + +static gboolean +ddecode_message (nul_arg_t **args, + DBusMessage *message, + int n_parameters, + nul_dbus_parameter_t **parameters, + char **err) +{ + DBusMessageIter iter; + char *d; + int i; + + if (!err) + err = &d; + + i = 0; + if (dbus_message_iter_init (message, &iter)) + { + do + { + if (i >= n_parameters) + { + *err = "Too many arguments received"; + goto fail; + } + + if (!decode_arg (args, &iter, parameters[i++], err)) + goto fail; + + } while (dbus_message_iter_next (&iter)); + } + + if (i < n_parameters) + { + *err = "Too few arguments received"; + goto fail; + } + + return TRUE; + +fail: + while (i < n_parameters) + { + nul_arg_t arg; + + memset (&arg, 0, sizeof (arg)); + + *args = nul_array_append (*args, &arg); + + i++; + } + + return FALSE; +} + static void encode_message (DBusMessage *message, int n_parameters, @@ -521,20 +618,20 @@ invoke (DBusConnection *connection, DBusMessage *error_reply; nul_arg_t result; int i; - + if (!member->function) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; /* Add the data pointer */ args[0].v_pointer = object->data; - + if (!decode_message ( message, member->n_inputs, (nul_dbus_parameter_t **)member->parameters, &(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; @@ -604,11 +701,11 @@ message_function (DBusConnection *connection, for (p = object->interfaces; *p; ++p) { nul_dbus_interface_t *interface = *p; - + if (strcmp (msg_interface, interface->name) == 0) { nul_ptr_t *q; - + for (q = interface->members; *q; ++q) { nul_dbus_member_t *member = *q; @@ -640,12 +737,12 @@ make_ptr_array (gpointer first, va_list parameters) if (first) { array = nul_ptr_array_append (array, first); - + v = va_arg (parameters, gpointer); while (v) { array = nul_ptr_array_append (array, v); - + v = va_arg (parameters, gpointer); } } @@ -660,7 +757,7 @@ get_idle_id (DBusConnection *connection) { if (idle_id_slot == -1) dbus_connection_allocate_data_slot (&idle_id_slot); - + return (int)dbus_connection_get_data (connection, idle_id_slot); } @@ -669,7 +766,7 @@ set_idle_id (DBusConnection *connection, int id) { if (idle_id_slot == -1) dbus_connection_allocate_data_slot (&idle_id_slot); - + dbus_connection_set_data (connection, idle_id_slot, (void *)id, NULL); } @@ -677,10 +774,10 @@ static gboolean do_dispatch (gpointer data) { DBusConnection *connection = data; - + while (dbus_connection_dispatch (connection) == DBUS_DISPATCH_DATA_REMAINS) ; - + set_idle_id (connection, 0); return FALSE; @@ -720,7 +817,7 @@ ensure_connection (DBusConnection **connection, add_timeout, remove_timeout, toggle_timeout, *connection, NULL); } - + do_dispatch (*connection); } @@ -851,11 +948,11 @@ nul_dbus_service_stop (nul_dbus_service_t *service) if (!service->running) return; - + for (p = service->objects; *p != NULL; ++p) { nul_dbus_object_t *object = *p; - + dbus_connection_unregister_object_path ( service->connection, object->name); } @@ -963,7 +1060,7 @@ make_fun_def (nul_dbus_member_t *member) types = idle_free (g_new0 (nul_type_t, nul_ptr_array_len (member->parameters) + 1)); types[0] = NUL_TYPE_POINTER; /* For object->data */ - + for (i = 1; i < nul_ptr_array_len (member->parameters); ++i) { nul_dbus_parameter_t *par = member->parameters[i - 1]; @@ -988,7 +1085,7 @@ make_reply_fun (nul_dbus_member_t *member) types = idle_free (g_new0 (nul_type_t, nul_ptr_array_len (member->parameters) + 2)); - + n = 0; for (p = member->parameters; *p; ++p) { @@ -1124,8 +1221,11 @@ on_reply (DBusPendingCall *pending, { InvokeInfo *info = data; int n_outputs = info->method->n_outputs; - nul_arg_t *args = idle_free (g_new0 (nul_arg_t, n_outputs + 2)); + nul_dbus_parameter_t **outputs; DBusMessage *reply; + nul_arg_t *args; + nul_arg_t arg; + char *err; if (!info->callback) return; @@ -1140,19 +1240,22 @@ on_reply (DBusPendingCall *pending, return; } - args[n_outputs].v_pointer = NULL; /* GError */ - if (!decode_message (reply, - n_outputs, - (nul_dbus_parameter_t **)&(info->method->parameters[info->method->n_inputs]), - args)) - { - /* FIXME: generate an error into args[n_outputs + 1] */ - args[n_outputs].v_pointer = "ERR"; - } + outputs = (nul_dbus_parameter_t **)&(info->method->parameters[info->method->n_inputs]); - args[n_outputs + 1].v_pointer = info->data; + args = nul_array_new (sizeof (nul_arg_t)); + + if (!ddecode_message (&args, reply, n_outputs, outputs, &err)) + arg.v_pointer = err; + else + arg.v_pointer = NULL; + args = nul_array_append (args, &arg); /* error */ + + arg.v_pointer = info->data; + args = nul_array_append (args, &arg); nul_fun_def_invoke (info->method->reply_fun, (nul_function_t)info->callback, args); + + nul_array_free (args); } /* Decodes strings like this: @@ -1250,14 +1353,14 @@ nul_dbus_invoke (nul_dbus_service_t *service, InvokeInfo *info; DBusPendingCall *pending; nul_ptr_t *p; - + g_return_if_fail (service != NULL); if (!decode_method_desc (method_desc, &object_str, &interface_str, &method_str)) return; object = find_object (service, object_str); - + if (!object) { g_critical ("Object '%s' not found", object_str); @@ -1265,13 +1368,13 @@ nul_dbus_invoke (nul_dbus_service_t *service, } interface = find_interface (object, interface_str); - + if (!interface) { g_critical ("Interface '%s' not found", interface_str); return; } - + method = find_member (interface, method_str); if (!method) @@ -1279,7 +1382,7 @@ nul_dbus_invoke (nul_dbus_service_t *service, g_critical ("Method '%s' not found", method_str); return; } - + message = dbus_message_new_method_call ( service->name, object->name, interface->name, method->name); @@ -1352,9 +1455,9 @@ nul_dbus_service_set_object_data (nul_dbus_service_t *service, gpointer data) { nul_dbus_object_t *object = find_object (service, obj_name); - + g_return_if_fail (object != NULL); - + object->data = data; } @@ -52,15 +52,15 @@ typedef void * const nul_const_ptr_t; /* * Generic arrays */ -nul_ptr_t nul_array_new (int element_size); -nul_ptr_t nul_array_append (nul_ptr_t array, nul_ptr_t element); +nul_ptr_t nul_array_new (int element_size) NUL_UR; +nul_ptr_t nul_array_append (nul_ptr_t array, nul_ptr_t element) NUL_UR; gsize nul_array_len (nul_ptr_t array); void nul_array_free (nul_ptr_t array); /* * Pointer arrays */ -nul_ptr_t *nul_ptr_array_new (void); +nul_ptr_t *nul_ptr_array_new (void) NUL_UR; nul_ptr_t *nul_ptr_array_append (nul_ptr_t *arr, nul_ptr_t data) NUL_UR; gsize nul_ptr_array_len (nul_const_ptr_t *arr); @@ -72,7 +72,7 @@ void nul_ptr_array_free (nul_ptr_t *arr); */ typedef char nul_string_t; -nul_string_t *nul_string_new (void); +nul_string_t *nul_string_new (void) NUL_UR; void nul_string_free (nul_string_t *str); gsize nul_string_len (const nul_string_t *str); gboolean nul_string_empty (const nul_string_t *str); |