* Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
* Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "utils/includes.h"
WPAS_DBUS_INTERFACE_MAX) != 0)
continue;
- /* Handle access permissions or missing getter */
- if (dsc->getter == NULL || dsc->access == W)
+ /* Skip write-only properties */
+ if (dsc->getter == NULL)
continue;
if (!dbus_message_iter_open_container(dict_iter,
DBUS_TYPE_DICT_ENTRY,
- NULL, &entry_iter)) {
- dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
- "no memory");
- return FALSE;
- }
- if (!dbus_message_iter_append_basic(&entry_iter,
+ NULL, &entry_iter) ||
+ !dbus_message_iter_append_basic(&entry_iter,
DBUS_TYPE_STRING,
- &dsc->dbus_property)) {
- dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
- "no memory");
- return FALSE;
- }
+ &dsc->dbus_property))
+ goto error;
/* An error getting a property fails the request entirely */
if (!dsc->getter(&entry_iter, error, user_data))
return FALSE;
- dbus_message_iter_close_container(dict_iter, &entry_iter);
+ if (!dbus_message_iter_close_container(dict_iter, &entry_iter))
+ goto error;
}
return TRUE;
+
+error:
+ dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
+ return FALSE;
}
return reply;
}
- wpa_dbus_dict_close_write(&iter, &dict_iter);
+ if (!wpa_dbus_dict_close_write(&iter, &dict_iter)) {
+ dbus_message_unref(reply);
+ return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+ "out of memory");
+ }
+
return reply;
}
if (arg->dir == ARG_IN) {
size_t blen = registered_sig + MAX_SIG_LEN - pos;
ret = os_snprintf(pos, blen, "%s", arg->type);
- if (ret < 0 || (size_t) ret >= blen)
+ if (os_snprintf_error(blen, ret))
return 0;
pos += ret;
}
NULL);
}
- if (dsc->access == W || dsc->getter == NULL) {
+ if (dsc->getter == NULL) {
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Property is write-only");
}
NULL);
}
- if (dsc->access == R || dsc->setter == NULL) {
+ if (dsc->setter == NULL) {
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Property is read-only");
}
if (!obj_desc) {
wpa_printf(MSG_ERROR, "dbus: %s: Could not obtain object's "
"private data: %s", __func__, path);
- } else {
- eloop_cancel_timeout(flush_object_timeout_handler, con,
- obj_desc);
+ return 0;
}
+ eloop_cancel_timeout(flush_object_timeout_handler, con, obj_desc);
+
if (!dbus_connection_unregister_object_path(con, path))
return -1;
static dbus_bool_t put_changed_properties(
const struct wpa_dbus_object_desc *obj_dsc, const char *interface,
- DBusMessageIter *dict_iter)
+ DBusMessageIter *dict_iter, int clear_changed)
{
DBusMessageIter entry_iter;
const struct wpa_dbus_property_desc *dsc;
continue;
if (os_strcmp(dsc->dbus_interface, interface) != 0)
continue;
- obj_dsc->prop_changed_flags[i] = 0;
+ if (clear_changed)
+ obj_dsc->prop_changed_flags[i] = 0;
if (!dbus_message_iter_open_container(dict_iter,
DBUS_TYPE_DICT_ENTRY,
}
-static void send_prop_changed_signal(
+static void do_send_prop_changed_signal(
+ DBusConnection *con, const char *path, const char *interface,
+ const struct wpa_dbus_object_desc *obj_dsc)
+{
+ DBusMessage *msg;
+ DBusMessageIter signal_iter, dict_iter;
+
+ msg = dbus_message_new_signal(path, DBUS_INTERFACE_PROPERTIES,
+ "PropertiesChanged");
+ if (msg == NULL)
+ return;
+
+ dbus_message_iter_init_append(msg, &signal_iter);
+
+ if (!dbus_message_iter_append_basic(&signal_iter, DBUS_TYPE_STRING,
+ &interface))
+ goto err;
+
+ /* Changed properties dict */
+ if (!dbus_message_iter_open_container(&signal_iter, DBUS_TYPE_ARRAY,
+ "{sv}", &dict_iter))
+ goto err;
+
+ if (!put_changed_properties(obj_dsc, interface, &dict_iter, 0))
+ goto err;
+
+ if (!dbus_message_iter_close_container(&signal_iter, &dict_iter))
+ goto err;
+
+ /* Invalidated properties array (empty) */
+ if (!dbus_message_iter_open_container(&signal_iter, DBUS_TYPE_ARRAY,
+ "s", &dict_iter))
+ goto err;
+
+ if (!dbus_message_iter_close_container(&signal_iter, &dict_iter))
+ goto err;
+
+ dbus_connection_send(con, msg, NULL);
+
+out:
+ dbus_message_unref(msg);
+ return;
+
+err:
+ wpa_printf(MSG_DEBUG, "dbus: %s: Failed to construct signal",
+ __func__);
+ goto out;
+}
+
+
+static void do_send_deprecated_prop_changed_signal(
DBusConnection *con, const char *path, const char *interface,
const struct wpa_dbus_object_desc *obj_dsc)
{
"{sv}", &dict_iter))
goto err;
- if (!put_changed_properties(obj_dsc, interface, &dict_iter))
+ if (!put_changed_properties(obj_dsc, interface, &dict_iter, 1))
goto err;
if (!dbus_message_iter_close_container(&signal_iter, &dict_iter))
}
+static void send_prop_changed_signal(
+ DBusConnection *con, const char *path, const char *interface,
+ const struct wpa_dbus_object_desc *obj_dsc)
+{
+ /*
+ * First, send property change notification on the standardized
+ * org.freedesktop.DBus.Properties interface. This call will not
+ * clear the property change bits, so that they are preserved for
+ * the call that follows.
+ */
+ do_send_prop_changed_signal(con, path, interface, obj_dsc);
+
+ /*
+ * Now send PropertiesChanged on our own interface for backwards
+ * compatibility. This is deprecated and will be removed in a future
+ * release.
+ */
+ do_send_deprecated_prop_changed_signal(con, path, interface, obj_dsc);
+
+ /* Property change bits have now been cleared. */
+}
+
+
static void flush_object_timeout_handler(void *eloop_ctx, void *timeout_ctx)
{
DBusConnection *con = eloop_ctx;
return;
eloop_cancel_timeout(flush_object_timeout_handler, con, obj_desc);
- dsc = obj_desc->properties;
for (dsc = obj_desc->properties, i = 0; dsc && dsc->dbus_property;
dsc++, i++) {
if (obj_desc->prop_changed_flags == NULL ||