DBus: Refactor array adding, add binary arrays

Some new code we're working on will require the dbus type "aay" (an
array of arrays of bytes). To add this, refactor the array code to
reduce code duplication by given a type string to the array starting
code, and also add code to create and parse such arrays from or into an
array of struct wpabuf respectively.

Since there's no unique DBus type for this, add a "fake"
WPAS_DBUS_TYPE_BINARRAY type that is separate from the regular DBus
types for parsing.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Johannes Berg 2011-06-12 14:47:49 -07:00 committed by Jouni Malinen
parent 58f80e2aeb
commit 911e97e400
2 changed files with 235 additions and 27 deletions

View file

@ -16,6 +16,7 @@
#include <dbus/dbus.h> #include <dbus/dbus.h>
#include "common.h" #include "common.h"
#include "wpabuf.h"
#include "dbus_dict_helpers.h" #include "dbus_dict_helpers.h"
@ -443,11 +444,12 @@ dbus_bool_t wpa_dbus_dict_append_byte_array(DBusMessageIter *iter_dict,
/** /**
* Begin a string array entry in the dict * Begin an array entry in the dict
* *
* @param iter_dict A valid DBusMessageIter returned from * @param iter_dict A valid DBusMessageIter returned from
* wpa_dbus_dict_open_write() * wpa_dbus_dict_open_write()
* @param key The key of the dict item * @param key The key of the dict item
* @param type The type of the contained data
* @param iter_dict_entry A private DBusMessageIter provided by the caller to * @param iter_dict_entry A private DBusMessageIter provided by the caller to
* be passed to wpa_dbus_dict_end_string_array() * be passed to wpa_dbus_dict_end_string_array()
* @param iter_dict_val A private DBusMessageIter provided by the caller to * @param iter_dict_val A private DBusMessageIter provided by the caller to
@ -457,12 +459,21 @@ dbus_bool_t wpa_dbus_dict_append_byte_array(DBusMessageIter *iter_dict,
* @return TRUE on success, FALSE on failure * @return TRUE on success, FALSE on failure
* *
*/ */
dbus_bool_t wpa_dbus_dict_begin_string_array(DBusMessageIter *iter_dict, dbus_bool_t wpa_dbus_dict_begin_array(DBusMessageIter *iter_dict,
const char *key, const char *key, const char *type,
DBusMessageIter *iter_dict_entry, DBusMessageIter *iter_dict_entry,
DBusMessageIter *iter_dict_val, DBusMessageIter *iter_dict_val,
DBusMessageIter *iter_array) DBusMessageIter *iter_array)
{ {
char array_type[10];
int err;
err = os_snprintf(array_type, sizeof(array_type),
DBUS_TYPE_ARRAY_AS_STRING "%s",
type);
if (err < 0 || err > (int) sizeof(array_type))
return FALSE;
if (!iter_dict || !iter_dict_entry || !iter_dict_val || !iter_array) if (!iter_dict || !iter_dict_entry || !iter_dict_val || !iter_array)
return FALSE; return FALSE;
@ -472,20 +483,31 @@ dbus_bool_t wpa_dbus_dict_begin_string_array(DBusMessageIter *iter_dict,
if (!dbus_message_iter_open_container(iter_dict_entry, if (!dbus_message_iter_open_container(iter_dict_entry,
DBUS_TYPE_VARIANT, DBUS_TYPE_VARIANT,
DBUS_TYPE_ARRAY_AS_STRING array_type,
DBUS_TYPE_STRING_AS_STRING,
iter_dict_val)) iter_dict_val))
return FALSE; return FALSE;
if (!dbus_message_iter_open_container(iter_dict_val, DBUS_TYPE_ARRAY, if (!dbus_message_iter_open_container(iter_dict_val, DBUS_TYPE_ARRAY,
DBUS_TYPE_STRING_AS_STRING, type, iter_array))
iter_array))
return FALSE; return FALSE;
return TRUE; return TRUE;
} }
dbus_bool_t wpa_dbus_dict_begin_string_array(DBusMessageIter *iter_dict,
const char *key,
DBusMessageIter *iter_dict_entry,
DBusMessageIter *iter_dict_val,
DBusMessageIter *iter_array)
{
return wpa_dbus_dict_begin_array(
iter_dict, key,
DBUS_TYPE_STRING_AS_STRING,
iter_dict_entry, iter_dict_val, iter_array);
}
/** /**
* Add a single string element to a string array dict entry * Add a single string element to a string array dict entry
* *
@ -508,23 +530,67 @@ dbus_bool_t wpa_dbus_dict_string_array_add_element(DBusMessageIter *iter_array,
/** /**
* End a string array dict entry * Add a single byte array element to a string array dict entry
*
* @param iter_array A valid DBusMessageIter returned from
* wpa_dbus_dict_begin_array()'s iter_array
* parameter -- note that wpa_dbus_dict_begin_array()
* must have been called with "ay" as the type
* @param value The data to be added to the dict entry's array
* @param value_len The length of the data
* @return TRUE on success, FALSE on failure
*
*/
dbus_bool_t wpa_dbus_dict_bin_array_add_element(DBusMessageIter *iter_array,
const u8 *value,
size_t value_len)
{
DBusMessageIter iter_bytes;
size_t i;
if (!iter_array || !value)
return FALSE;
if (!dbus_message_iter_open_container(iter_array, DBUS_TYPE_ARRAY,
DBUS_TYPE_BYTE_AS_STRING,
&iter_bytes))
return FALSE;
for (i = 0; i < value_len; i++) {
if (!dbus_message_iter_append_basic(&iter_bytes,
DBUS_TYPE_BYTE,
&(value[i])))
return FALSE;
}
if (!dbus_message_iter_close_container(iter_array, &iter_bytes))
return FALSE;
return TRUE;
}
/**
* End an array dict entry
* *
* @param iter_dict A valid DBusMessageIter returned from * @param iter_dict A valid DBusMessageIter returned from
* wpa_dbus_dict_open_write() * wpa_dbus_dict_open_write()
* @param iter_dict_entry A private DBusMessageIter returned from * @param iter_dict_entry A private DBusMessageIter returned from
* wpa_dbus_dict_end_string_array() * wpa_dbus_dict_begin_string_array() or
* wpa_dbus_dict_begin_array()
* @param iter_dict_val A private DBusMessageIter returned from * @param iter_dict_val A private DBusMessageIter returned from
* wpa_dbus_dict_end_string_array() * wpa_dbus_dict_begin_string_array() or
* wpa_dbus_dict_begin_array()
* @param iter_array A DBusMessageIter returned from * @param iter_array A DBusMessageIter returned from
* wpa_dbus_dict_end_string_array() * wpa_dbus_dict_begin_string_array() or
* wpa_dbus_dict_begin_array()
* @return TRUE on success, FALSE on failure * @return TRUE on success, FALSE on failure
* *
*/ */
dbus_bool_t wpa_dbus_dict_end_string_array(DBusMessageIter *iter_dict, dbus_bool_t wpa_dbus_dict_end_array(DBusMessageIter *iter_dict,
DBusMessageIter *iter_dict_entry, DBusMessageIter *iter_dict_entry,
DBusMessageIter *iter_dict_val, DBusMessageIter *iter_dict_val,
DBusMessageIter *iter_array) DBusMessageIter *iter_array)
{ {
if (!iter_dict || !iter_dict_entry || !iter_dict_val || !iter_array) if (!iter_dict || !iter_dict_entry || !iter_dict_val || !iter_array)
return FALSE; return FALSE;
@ -583,6 +649,52 @@ dbus_bool_t wpa_dbus_dict_append_string_array(DBusMessageIter *iter_dict,
} }
/**
* Convenience function to add an wpabuf binary array to the dict.
*
* @param iter_dict A valid DBusMessageIter returned from
* wpa_dbus_dict_open_write()
* @param key The key of the dict item
* @param items The array of wpabuf structures
* @param num_items The number of strings in the array
* @return TRUE on success, FALSE on failure
*
*/
dbus_bool_t wpa_dbus_dict_append_wpabuf_array(DBusMessageIter *iter_dict,
const char *key,
const struct wpabuf **items,
const dbus_uint32_t num_items)
{
DBusMessageIter iter_dict_entry, iter_dict_val, iter_array;
dbus_uint32_t i;
if (!key)
return FALSE;
if (!items && (num_items != 0))
return FALSE;
if (!wpa_dbus_dict_begin_array(iter_dict, key,
DBUS_TYPE_ARRAY_AS_STRING
DBUS_TYPE_BYTE_AS_STRING,
&iter_dict_entry, &iter_dict_val,
&iter_array))
return FALSE;
for (i = 0; i < num_items; i++) {
if (!wpa_dbus_dict_bin_array_add_element(&iter_array,
wpabuf_head(items[i]),
wpabuf_len(items[i])))
return FALSE;
}
if (!wpa_dbus_dict_end_array(iter_dict, &iter_dict_entry,
&iter_dict_val, &iter_array))
return FALSE;
return TRUE;
}
/*****************************************************/ /*****************************************************/
/* Stuff for reading dicts */ /* Stuff for reading dicts */
/*****************************************************/ /*****************************************************/
@ -615,8 +727,7 @@ dbus_bool_t wpa_dbus_dict_open_read(DBusMessageIter *iter,
#define BYTE_ARRAY_ITEM_SIZE (sizeof(char)) #define BYTE_ARRAY_ITEM_SIZE (sizeof(char))
static dbus_bool_t _wpa_dbus_dict_entry_get_byte_array( static dbus_bool_t _wpa_dbus_dict_entry_get_byte_array(
DBusMessageIter *iter, int array_type, DBusMessageIter *iter, struct wpa_dbus_dict_entry *entry)
struct wpa_dbus_dict_entry *entry)
{ {
dbus_uint32_t count = 0; dbus_uint32_t count = 0;
dbus_bool_t success = FALSE; dbus_bool_t success = FALSE;
@ -733,6 +844,66 @@ done:
} }
#define BIN_ARRAY_CHUNK_SIZE 10
#define BIN_ARRAY_ITEM_SIZE (sizeof(struct wpabuf *))
static dbus_bool_t _wpa_dbus_dict_entry_get_binarray(
DBusMessageIter *iter, struct wpa_dbus_dict_entry *entry)
{
struct wpa_dbus_dict_entry tmpentry;
size_t buflen = 0;
int i;
if (dbus_message_iter_get_element_type(iter) != DBUS_TYPE_BYTE)
return FALSE;
entry->array_type = WPAS_DBUS_TYPE_BINARRAY;
entry->array_len = 0;
entry->binarray_value = NULL;
while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_ARRAY) {
DBusMessageIter iter_array;
if (entry->array_len == buflen) {
struct wpabuf **newbuf;
buflen += BIN_ARRAY_CHUNK_SIZE;
newbuf = os_realloc(entry->binarray_value,
buflen * BIN_ARRAY_ITEM_SIZE);
if (!newbuf)
goto cleanup;
entry->binarray_value = newbuf;
}
dbus_message_iter_recurse(iter, &iter_array);
if (_wpa_dbus_dict_entry_get_byte_array(&iter_array, &tmpentry)
== FALSE)
goto cleanup;
entry->binarray_value[entry->array_len] =
wpabuf_alloc_ext_data((u8 *) tmpentry.bytearray_value,
tmpentry.array_len);
if (entry->binarray_value[entry->array_len] == NULL) {
wpa_dbus_dict_entry_clear(&tmpentry);
goto cleanup;
}
entry->array_len++;
dbus_message_iter_next(iter);
}
return TRUE;
cleanup:
for (i = 0; i < (int) entry->array_len; i++)
wpabuf_free(entry->binarray_value[i]);
os_free(entry->binarray_value);
entry->array_len = 0;
entry->binarray_value = NULL;
return FALSE;
}
static dbus_bool_t _wpa_dbus_dict_entry_get_array( static dbus_bool_t _wpa_dbus_dict_entry_get_array(
DBusMessageIter *iter_dict_val, struct wpa_dbus_dict_entry *entry) DBusMessageIter *iter_dict_val, struct wpa_dbus_dict_entry *entry)
{ {
@ -748,7 +919,6 @@ static dbus_bool_t _wpa_dbus_dict_entry_get_array(
switch (array_type) { switch (array_type) {
case DBUS_TYPE_BYTE: case DBUS_TYPE_BYTE:
success = _wpa_dbus_dict_entry_get_byte_array(&iter_array, success = _wpa_dbus_dict_entry_get_byte_array(&iter_array,
array_type,
entry); entry);
break; break;
case DBUS_TYPE_STRING: case DBUS_TYPE_STRING:
@ -756,6 +926,8 @@ static dbus_bool_t _wpa_dbus_dict_entry_get_array(
array_type, array_type,
entry); entry);
break; break;
case DBUS_TYPE_ARRAY:
success = _wpa_dbus_dict_entry_get_binarray(&iter_array, entry);
default: default:
break; break;
} }
@ -917,6 +1089,11 @@ void wpa_dbus_dict_entry_clear(struct wpa_dbus_dict_entry *entry)
break; break;
} }
break; break;
case WPAS_DBUS_TYPE_BINARRAY:
for (i = 0; i < entry->array_len; i++)
wpabuf_free(entry->binarray_value[i]);
os_free(entry->binarray_value);
break;
} }
memset(entry, 0, sizeof(struct wpa_dbus_dict_entry)); memset(entry, 0, sizeof(struct wpa_dbus_dict_entry));

View file

@ -15,6 +15,8 @@
#ifndef DBUS_DICT_HELPERS_H #ifndef DBUS_DICT_HELPERS_H
#define DBUS_DICT_HELPERS_H #define DBUS_DICT_HELPERS_H
#include "wpabuf.h"
/* /*
* Adding a dict to a DBusMessage * Adding a dict to a DBusMessage
*/ */
@ -74,7 +76,13 @@ dbus_bool_t wpa_dbus_dict_append_byte_array(DBusMessageIter *iter_dict,
const char *value, const char *value,
const dbus_uint32_t value_len); const dbus_uint32_t value_len);
/* Manual construction and addition of string array elements */ /* Manual construction and addition of array elements */
dbus_bool_t wpa_dbus_dict_begin_array(DBusMessageIter *iter_dict,
const char *key, const char *type,
DBusMessageIter *iter_dict_entry,
DBusMessageIter *iter_dict_val,
DBusMessageIter *iter_array);
dbus_bool_t wpa_dbus_dict_begin_string_array(DBusMessageIter *iter_dict, dbus_bool_t wpa_dbus_dict_begin_string_array(DBusMessageIter *iter_dict,
const char *key, const char *key,
DBusMessageIter *iter_dict_entry, DBusMessageIter *iter_dict_entry,
@ -84,10 +92,24 @@ dbus_bool_t wpa_dbus_dict_begin_string_array(DBusMessageIter *iter_dict,
dbus_bool_t wpa_dbus_dict_string_array_add_element(DBusMessageIter *iter_array, dbus_bool_t wpa_dbus_dict_string_array_add_element(DBusMessageIter *iter_array,
const char *elem); const char *elem);
dbus_bool_t wpa_dbus_dict_end_string_array(DBusMessageIter *iter_dict, dbus_bool_t wpa_dbus_dict_bin_array_add_element(DBusMessageIter *iter_array,
DBusMessageIter *iter_dict_entry, const u8 *value,
DBusMessageIter *iter_dict_val, size_t value_len);
DBusMessageIter *iter_array);
dbus_bool_t wpa_dbus_dict_end_array(DBusMessageIter *iter_dict,
DBusMessageIter *iter_dict_entry,
DBusMessageIter *iter_dict_val,
DBusMessageIter *iter_array);
static inline dbus_bool_t
wpa_dbus_dict_end_string_array(DBusMessageIter *iter_dict,
DBusMessageIter *iter_dict_entry,
DBusMessageIter *iter_dict_val,
DBusMessageIter *iter_array)
{
return wpa_dbus_dict_end_array(iter_dict, iter_dict_entry,
iter_dict_val, iter_array);
}
/* Convenience function to add a whole string list */ /* Convenience function to add a whole string list */
dbus_bool_t wpa_dbus_dict_append_string_array(DBusMessageIter *iter_dict, dbus_bool_t wpa_dbus_dict_append_string_array(DBusMessageIter *iter_dict,
@ -95,14 +117,22 @@ dbus_bool_t wpa_dbus_dict_append_string_array(DBusMessageIter *iter_dict,
const char **items, const char **items,
const dbus_uint32_t num_items); const dbus_uint32_t num_items);
dbus_bool_t wpa_dbus_dict_append_wpabuf_array(DBusMessageIter *iter_dict,
const char *key,
const struct wpabuf **items,
const dbus_uint32_t num_items);
/* /*
* Reading a dict from a DBusMessage * Reading a dict from a DBusMessage
*/ */
#define WPAS_DBUS_TYPE_BINARRAY (DBUS_NUMBER_OF_TYPES + 100)
struct wpa_dbus_dict_entry { struct wpa_dbus_dict_entry {
int type; /** the dbus type of the dict entry's value */ int type; /** the dbus type of the dict entry's value */
int array_type; /** the dbus type of the array elements if the dict int array_type; /** the dbus type of the array elements if the dict
entry value contains an array */ entry value contains an array, or the special
WPAS_DBUS_TYPE_BINARRAY */
const char *key; /** key of the dict entry */ const char *key; /** key of the dict entry */
/** Possible values of the property */ /** Possible values of the property */
@ -119,6 +149,7 @@ struct wpa_dbus_dict_entry {
double double_value; double double_value;
char *bytearray_value; char *bytearray_value;
char **strarray_value; char **strarray_value;
struct wpabuf **binarray_value;
}; };
dbus_uint32_t array_len; /** length of the array if the dict entry's dbus_uint32_t array_len; /** length of the array if the dict entry's
value contains an array */ value contains an array */