diff options
-rw-r--r-- | dbus/dbus-marshal-basic.c | 2945 | ||||
-rw-r--r-- | dbus/dbus-marshal-basic.h | 400 | ||||
-rw-r--r-- | dbus/dbus-marshal-recursive.c | 713 | ||||
-rw-r--r-- | dbus/dbus-marshal-recursive.h | 112 | ||||
-rw-r--r-- | dbus/dbus-protocol-new.h | 180 |
5 files changed, 4350 insertions, 0 deletions
diff --git a/dbus/dbus-marshal-basic.c b/dbus/dbus-marshal-basic.c new file mode 100644 index 00000000..76477279 --- /dev/null +++ b/dbus/dbus-marshal-basic.c @@ -0,0 +1,2945 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-marshal-basic.c Marshalling routines for basic (primitive) types + * + * Copyright (C) 2002 CodeFactory AB + * Copyright (C) 2003, 2004 Red Hat, Inc. + * + * Licensed under the Academic Free License version 2.1 + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "dbus-marshal-basic.h" +#include "dbus-internals.h" +#define DBUS_CAN_USE_DBUS_STRING_PRIVATE 1 +#include "dbus-string-private.h" + +#include <string.h> + +/** + * @defgroup DBusMarshal marshaling and unmarshaling + * @ingroup DBusInternals + * @brief functions to marshal/unmarshal data from the wire + * + * Types and functions related to converting primitive data types from + * wire format to native machine format, and vice versa. + * + * A signature is just a string with multiple types one after the other. + * for example a type is "i" or "(ii)", a signature is "i(ii)" + * where i is int and (ii) is struct { int; int; } + * + * @{ + */ + +static dbus_uint32_t +unpack_4_octets (int byte_order, + const unsigned char *data) +{ + _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data); + + if (byte_order == DBUS_LITTLE_ENDIAN) + return DBUS_UINT32_FROM_LE (*(dbus_uint32_t*)data); + else + return DBUS_UINT32_FROM_BE (*(dbus_uint32_t*)data); +} + +#ifndef DBUS_HAVE_INT64 +/* from ORBit */ +static void +swap_bytes (unsigned char *data, + unsigned int len) +{ + unsigned char *p1 = data; + unsigned char *p2 = data + len - 1; + + while (p1 < p2) + { + unsigned char tmp = *p1; + *p1 = *p2; + *p2 = tmp; + + --p2; + ++p1; + } +} +#endif /* !DBUS_HAVE_INT64 */ + +/** + * Union used to manipulate 8 bytes as if they + * were various types. + */ +typedef union +{ +#ifdef DBUS_HAVE_INT64 + dbus_int64_t s; /**< 64-bit integer */ + dbus_uint64_t u; /**< 64-bit unsinged integer */ +#endif + double d; /**< double */ +} DBusOctets8; + +static DBusOctets8 +unpack_8_octets (int byte_order, + const unsigned char *data) +{ + DBusOctets8 r; + + _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data); + _dbus_assert (sizeof (r) == 8); + +#ifdef DBUS_HAVE_INT64 + if (byte_order == DBUS_LITTLE_ENDIAN) + r.u = DBUS_UINT64_FROM_LE (*(dbus_uint64_t*)data); + else + r.u = DBUS_UINT64_FROM_BE (*(dbus_uint64_t*)data); +#else + r.d = *(double*)data; + if (byte_order != DBUS_COMPILER_BYTE_ORDER) + swap_bytes ((unsigned char*) &r, sizeof (r)); +#endif + + return r; +} + +/** + * Unpacks a 32 bit unsigned integer from a data pointer + * + * @param byte_order The byte order to use + * @param data the data pointer + * @returns the integer + */ +dbus_uint32_t +_dbus_unpack_uint32 (int byte_order, + const unsigned char *data) +{ + return unpack_4_octets (byte_order, data); +} + +/** + * Unpacks a 32 bit signed integer from a data pointer + * + * @param byte_order The byte order to use + * @param data the data pointer + * @returns the integer + */ +dbus_int32_t +_dbus_unpack_int32 (int byte_order, + const unsigned char *data) +{ + return (dbus_int32_t) unpack_4_octets (byte_order, data); +} + +#ifdef DBUS_HAVE_INT64 +/** + * Unpacks a 64 bit unsigned integer from a data pointer + * + * @param byte_order The byte order to use + * @param data the data pointer + * @returns the integer + */ +dbus_uint64_t +_dbus_unpack_uint64 (int byte_order, + const unsigned char *data) +{ + DBusOctets8 r; + + r = unpack_8_octets (byte_order, data); + + return r.u; +} + +/** + * Unpacks a 64 bit signed integer from a data pointer + * + * @param byte_order The byte order to use + * @param data the data pointer + * @returns the integer + */ +dbus_int64_t +_dbus_unpack_int64 (int byte_order, + const unsigned char *data) +{ + DBusOctets8 r; + + r = unpack_8_octets (byte_order, data); + + return r.s; +} + +#endif /* DBUS_HAVE_INT64 */ + +static void +pack_4_octets (dbus_uint32_t value, + int byte_order, + unsigned char *data) +{ + _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data); + + if ((byte_order) == DBUS_LITTLE_ENDIAN) + *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_LE (value); + else + *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_BE (value); +} + +static void +pack_8_octets (DBusOctets8 value, + int byte_order, + unsigned char *data) +{ + _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data); + +#ifdef DBUS_HAVE_INT64 + if ((byte_order) == DBUS_LITTLE_ENDIAN) + *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_LE (value.u); + else + *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_BE (value.u); +#else + memcpy (data, &value, 8); + if (byte_order != DBUS_COMPILER_BYTE_ORDER) + swap_bytes ((unsigned char *)data, 8); +#endif +} + +/** + * Packs a 32 bit unsigned integer into a data pointer. + * + * @param value the value + * @param byte_order the byte order to use + * @param data the data pointer + */ +void +_dbus_pack_uint32 (dbus_uint32_t value, + int byte_order, + unsigned char *data) +{ + pack_4_octets (value, byte_order, data); +} + +/** + * Packs a 32 bit signed integer into a data pointer. + * + * @param value the value + * @param byte_order the byte order to use + * @param data the data pointer + */ +void +_dbus_pack_int32 (dbus_int32_t value, + int byte_order, + unsigned char *data) +{ + pack_4_octets ((dbus_uint32_t) value, byte_order, data); +} + +#ifdef DBUS_HAVE_INT64 +/** + * Packs a 64 bit unsigned integer into a data pointer. + * + * @param value the value + * @param byte_order the byte order to use + * @param data the data pointer + */ +void +_dbus_pack_uint64 (dbus_uint64_t value, + int byte_order, + unsigned char *data) +{ + DBusOctets8 r; + r.u = value; + pack_8_octets (r, byte_order, data); +} + +/** + * Packs a 64 bit signed integer into a data pointer. + * + * @param value the value + * @param byte_order the byte order to use + * @param data the data pointer + */ +void +_dbus_pack_int64 (dbus_int64_t value, + int byte_order, + unsigned char *data) +{ + DBusOctets8 r; + r.s = value; + pack_8_octets (r, byte_order, data); +} +#endif /* DBUS_HAVE_INT64 */ + +static void +set_4_octets (DBusString *str, + int byte_order, + int offset, + dbus_uint32_t value) +{ + char *data; + + _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN || + byte_order == DBUS_BIG_ENDIAN); + + data = _dbus_string_get_data_len (str, offset, 4); + + _dbus_pack_uint32 (value, byte_order, data); +} + +static void +set_8_octets (DBusString *str, + int byte_order, + int offset, + DBusOctets8 value) +{ + char *data; + + _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN || + byte_order == DBUS_BIG_ENDIAN); + + data = _dbus_string_get_data_len (str, offset, 8); + + pack_8_octets (value, byte_order, data); +} + +/** + * Sets the 4 bytes at the given offset to a marshaled signed integer, + * replacing anything found there previously. + * + * @param str the string to write the marshalled int to + * @param offset the byte offset where int should be written + * @param byte_order the byte order to use + * @param value the value + * + */ +void +_dbus_marshal_set_int32 (DBusString *str, + int byte_order, + int offset, + dbus_int32_t value) +{ + set_4_octets (str, byte_order, offset, (dbus_uint32_t) value); +} + +/** + * Sets the 4 bytes at the given offset to a marshaled unsigned + * integer, replacing anything found there previously. + * + * @param str the string to write the marshalled int to + * @param offset the byte offset where int should be written + * @param byte_order the byte order to use + * @param value the value + * + */ +void +_dbus_marshal_set_uint32 (DBusString *str, + int byte_order, + int offset, + dbus_uint32_t value) +{ + set_4_octets (str, byte_order, offset, value); +} + +#ifdef DBUS_HAVE_INT64 + +/** + * Sets the 8 bytes at the given offset to a marshaled signed integer, + * replacing anything found there previously. + * + * @param str the string to write the marshalled int to + * @param offset the byte offset where int should be written + * @param byte_order the byte order to use + * @param value the value + * + */ +void +_dbus_marshal_set_int64 (DBusString *str, + int byte_order, + int offset, + dbus_int64_t value) +{ + DBusOctets8 r; + r.s = value; + set_8_octets (str, byte_order, offset, r); +} + +/** + * Sets the 8 bytes at the given offset to a marshaled unsigned + * integer, replacing anything found there previously. + * + * @param str the string to write the marshalled int to + * @param offset the byte offset where int should be written + * @param byte_order the byte order to use + * @param value the value + * + */ +void +_dbus_marshal_set_uint64 (DBusString *str, + int byte_order, + int offset, + dbus_uint64_t value) +{ + DBusOctets8 r; + r.u = value; + set_8_octets (str, byte_order, offset, r); +} +#endif /* DBUS_HAVE_INT64 */ + +/** + * Sets the existing marshaled string at the given offset with + * a new marshaled string. The given offset must point to + * an existing string or the wrong length will be deleted + * and replaced with the new string. + * + * Note: no attempt is made by this function to re-align + * any data which has been already marshalled after this + * string. Use with caution. + * + * @param str the string to write the marshalled string to + * @param offset the byte offset where string should be written + * @param byte_order the byte order to use + * @param value the value + * @param len the length to use + * @returns #TRUE on success + * + */ +dbus_bool_t +_dbus_marshal_set_string (DBusString *str, + int byte_order, + int offset, + const DBusString *value, + int len) +{ + int old_len; + + _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN || + byte_order == DBUS_BIG_ENDIAN); + + old_len = _dbus_demarshal_uint32 (str, byte_order, + offset, NULL); + + if (!_dbus_string_replace_len (value, 0, len, + str, offset + 4, old_len)) + return FALSE; + + _dbus_marshal_set_uint32 (str, byte_order, + offset, len); + + return TRUE; +} + +/** + * Sets the existing marshaled object path at the given offset to a new + * value. The given offset must point to an existing object path or this + * function doesn't make sense. + * + * @todo implement this function + * + * @param str the string to write the marshalled path to + * @param offset the byte offset where path should be written + * @param byte_order the byte order to use + * @param path the new path + * @param path_len number of elements in the path + */ +void +_dbus_marshal_set_object_path (DBusString *str, + int byte_order, + int offset, + const char **path, + int path_len) +{ + + /* FIXME */ +} + +static dbus_bool_t +marshal_4_octets (DBusString *str, + int byte_order, + dbus_uint32_t value) +{ + _dbus_assert (sizeof (value) == 4); + + if (byte_order != DBUS_COMPILER_BYTE_ORDER) + value = DBUS_UINT32_SWAP_LE_BE (value); + + return _dbus_string_append_4_aligned (str, + (const unsigned char *)&value); +} + +static dbus_bool_t +marshal_8_octets (DBusString *str, + int byte_order, + DBusOctets8 value) +{ + _dbus_assert (sizeof (value) == 8); + + if (byte_order != DBUS_COMPILER_BYTE_ORDER) + pack_8_octets (value, byte_order, (unsigned char*) &value); /* pack into self, swapping as we go */ + + return _dbus_string_append_8_aligned (str, + (const unsigned char *)&value); +} + +/** + * Marshals a double value. + * + * @param str the string to append the marshalled value to + * @param byte_order the byte order to use + * @param value the value + * @returns #TRUE on success + */ +dbus_bool_t +_dbus_marshal_double (DBusString *str, + int byte_order, + double value) +{ + DBusOctets8 r; + r.d = value; + return marshal_8_octets (str, byte_order, r); +} + +/** + * Marshals a 32 bit signed integer value. + * + * @param str the string to append the marshalled value to + * @param byte_order the byte order to use + * @param value the value + * @returns #TRUE on success + */ +dbus_bool_t +_dbus_marshal_int32 (DBusString *str, + int byte_order, + dbus_int32_t value) +{ + return marshal_4_octets (str, byte_order, (dbus_uint32_t) value); +} + +/** + * Marshals a 32 bit unsigned integer value. + * + * @param str the string to append the marshalled value to + * @param byte_order the byte order to use + * @param value the value + * @returns #TRUE on success + */ +dbus_bool_t +_dbus_marshal_uint32 (DBusString *str, + int byte_order, + dbus_uint32_t value) +{ + return marshal_4_octets (str, byte_order, value); +} + + +#ifdef DBUS_HAVE_INT64 +/** + * Marshals a 64 bit signed integer value. + * + * @param str the string to append the marshalled value to + * @param byte_order the byte order to use + * @param value the value + * @returns #TRUE on success + */ +dbus_bool_t +_dbus_marshal_int64 (DBusString *str, + int byte_order, + dbus_int64_t value) +{ + DBusOctets8 r; + r.s = value; + return marshal_8_octets (str, byte_order, r); +} + +/** + * Marshals a 64 bit unsigned integer value. + * + * @param str the string to append the marshalled value to + * @param byte_order the byte order to use + * @param value the value + * @returns #TRUE on success + */ +dbus_bool_t +_dbus_marshal_uint64 (DBusString *str, + int byte_order, + dbus_uint64_t value) +{ + DBusOctets8 r; + r.u = value; + return marshal_8_octets (str, byte_order, r); +} + +#endif /* DBUS_HAVE_INT64 */ + +/** + * Marshals a UTF-8 string + * + * @todo: If the string append fails we need to restore + * the old length. (also for other marshallers) + * + * @param str the string to append the marshalled value to + * @param byte_order the byte order to use + * @param value the string + * @returns #TRUE on success + */ +dbus_bool_t +_dbus_marshal_string (DBusString *str, + int byte_order, + const char *value) +{ + int len, old_string_len; + + old_string_len = _dbus_string_get_length (str); + + len = strlen (value); + + if (!_dbus_marshal_uint32 (str, byte_order, len)) + { + /* Restore the previous length */ + _dbus_string_set_length (str, old_string_len); + + return FALSE; + } + + return _dbus_string_append_len (str, value, len + 1); +} + +/** + * Marshals a UTF-8 string + * + * @todo: If the string append fails we need to restore + * the old length. (also for other marshallers) + * + * @param str the string to append the marshalled value to + * @param byte_order the byte order to use + * @param value the string + * @param len length of string to marshal in bytes + * @returns #TRUE on success + */ +dbus_bool_t +_dbus_marshal_string_len (DBusString *str, + int byte_order, + const char *value, + int len) +{ + int old_string_len; + + old_string_len = _dbus_string_get_length (str); + + if (!_dbus_marshal_uint32 (str, byte_order, len)) + { + /* Restore the previous length */ + _dbus_string_set_length (str, old_string_len); + + return FALSE; + } + + if (!_dbus_string_append_len (str, value, len)) + return FALSE; + + /* add a nul byte */ + if (!_dbus_string_lengthen (str, 1)) + return FALSE; + + return TRUE; +} + +/** + * Marshals a byte array + * + * @param str the string to append the marshalled value to + * @param byte_order the byte order to use + * @param value the array + * @param len number of elements in the array + * @returns #TRUE on success + */ +dbus_bool_t +_dbus_marshal_byte_array (DBusString *str, + int byte_order, + const unsigned char *value, + int len) +{ + int old_string_len; + + old_string_len = _dbus_string_get_length (str); + + if (!_dbus_marshal_uint32 (str, byte_order, len)) + { + /* Restore the previous length */ + _dbus_string_set_length (str, old_string_len); + + return FALSE; + } + + if (len == 0) + return TRUE; + else + return _dbus_string_append_len (str, value, len); +} + +static dbus_bool_t +marshal_4_octets_array (DBusString *str, + int byte_order, + const dbus_uint32_t *value, + int len) +{ + int old_string_len; + int array_start; + + old_string_len = _dbus_string_get_length (str); + + if (!_dbus_marshal_uint32 (str, byte_order, len * 4)) + goto error; + + array_start = _dbus_string_get_length (str); + + if (!_dbus_string_append_len (str, (const unsigned char*) value, + len * 4)) + goto error; + + if (byte_order != DBUS_COMPILER_BYTE_ORDER) + { + const unsigned char *d; + const unsigned char *end; + + d = _dbus_string_get_data (str) + array_start; + end = d + len * 4; + while (d != end) + { + *((dbus_uint32_t*)d) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)d)); + d += 4; + } + } + + return TRUE; + + error: + /* Restore previous length */ + _dbus_string_set_length (str, old_string_len); + + return FALSE; +} + +static dbus_bool_t +marshal_8_octets_array (DBusString *str, + int byte_order, + const DBusOctets8 *value, + int len) +{ + int old_string_len; + int array_start; + + old_string_len = _dbus_string_get_length (str); + + if (!_dbus_marshal_uint32 (str, byte_order, len * 8)) + goto error; + + array_start = _dbus_string_get_length (str); + + if (!_dbus_string_append_len (str, (const unsigned char*) value, + len * 8)) + goto error; + + if (byte_order != DBUS_COMPILER_BYTE_ORDER) + { + const unsigned char *d; + const unsigned char *end; + + d = _dbus_string_get_data (str) + array_start; + end = d + len * 8; + while (d != end) + { +#ifdef DBUS_HAVE_INT64 + *((dbus_uint64_t*)d) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)d)); +#else + swap_bytes ((unsigned char*) d, 8); +#endif + d += 8; + } + } + + return TRUE; + + error: + /* Restore previous length */ + _dbus_string_set_length (str, old_string_len); + + return FALSE; +} + +/** + * Marshals a 32 bit signed integer array + * + * @param str the string to append the marshalled value to + * @param byte_order the byte order to use + * @param value the array + * @param len the length of the array + * @returns #TRUE on success + */ +dbus_bool_t +_dbus_marshal_int32_array (DBusString *str, + int byte_order, + const dbus_int32_t *value, + int len) +{ + return marshal_4_octets_array (str, byte_order, + (const dbus_uint32_t*) value, + len); +} + +/** + * Marshals a 32 bit unsigned integer array + * + * @param str the string to append the marshalled value to + * @param byte_order the byte order to use + * @param value the array + * @param len the length of the array + * @returns #TRUE on success + */ +dbus_bool_t +_dbus_marshal_uint32_array (DBusString *str, + int byte_order, + const dbus_uint32_t *value, + int len) +{ + return marshal_4_octets_array (str, byte_order, + value, + len); +} + +#ifdef DBUS_HAVE_INT64 + +/** + * Marshals a 64 bit signed integer array + * + * @param str the string to append the marshalled value to + * @param byte_order the byte order to use + * @param value the array + * @param len the length of the array + * @returns #TRUE on success + */ +dbus_bool_t +_dbus_marshal_int64_array (DBusString *str, + int byte_order, + const dbus_int64_t *value, + int len) +{ + return marshal_8_octets_array (str, byte_order, + (const DBusOctets8*) value, + len); +} + +/** + * Marshals a 64 bit unsigned integer array + * + * @param str the string to append the marshalled value to + * @param byte_order the byte order to use + * @param value the array + * @param len the length of the array + * @returns #TRUE on success + */ +dbus_bool_t +_dbus_marshal_uint64_array (DBusString *str, + int byte_order, + const dbus_uint64_t *value, + int len) +{ + return marshal_8_octets_array (str, byte_order, + (const DBusOctets8*) value, + len); +} + +#endif /* DBUS_HAVE_INT64 */ + +/** + * Marshals a double array + * + * @param str the string to append the marshalled value to + * @param byte_order the byte order to use + * @param value the array + * @param len the length of the array + * @returns #TRUE on success + */ +dbus_bool_t +_dbus_marshal_double_array (DBusString *str, + int byte_order, + const double *value, + int len) +{ + return marshal_8_octets_array (str, byte_order, + (const DBusOctets8*) value, + len); +} + +/** + * Marshals a string array + * + * @param str the string to append the marshalled value to + * @param byte_order the byte order to use + * @param value the array + * @param len the length of the array + * @returns #TRUE on success + */ +dbus_bool_t +_dbus_marshal_string_array (DBusString *str, + int byte_order, + const char **value, + int len) +{ + int i, old_string_len, array_start; + + old_string_len = _dbus_string_get_length (str); + + /* Set the length to 0 temporarily */ + if (!_dbus_marshal_uint32 (str, byte_order, 0)) + goto error; + + array_start = _dbus_string_get_length (str); + + for (i = 0; i < len; i++) + if (!_dbus_marshal_string (str, byte_order, value[i])) + goto error; + + /* Write the length now that we know it */ + _dbus_marshal_set_uint32 (str, byte_order, + _DBUS_ALIGN_VALUE (old_string_len, sizeof(dbus_uint32_t)), + _dbus_string_get_length (str) - array_start); + + return TRUE; + + error: + /* Restore previous length */ + _dbus_string_set_length (str, old_string_len); + + return FALSE; +} + +/** + * Marshals an object path value. + * + * @param str the string to append the marshalled value to + * @param byte_order the byte order to use + * @param path the path + * @param path_len length of the path + * @returns #TRUE on success + */ +dbus_bool_t +_dbus_marshal_object_path (DBusString *str, + int byte_order, + const char **path, + int path_len) +{ + int array_start, old_string_len; + int i; + + old_string_len = _dbus_string_get_length (str); + + /* Set the length to 0 temporarily */ + if (!_dbus_marshal_uint32 (str, byte_order, 0)) + goto nomem; + + array_start = _dbus_string_get_length (str); + + i = 0; + while (i < path_len) + { + if (!_dbus_string_append_byte (str, '/')) + goto nomem; + + if (!_dbus_string_append (str, path[0])) + goto nomem; + + ++i; + } + + /* Write the length now that we know it */ + _dbus_marshal_set_uint32 (str, byte_order, + _DBUS_ALIGN_VALUE (old_string_len, sizeof(dbus_uint32_t)), + _dbus_string_get_length (str) - array_start); + + return TRUE; + + nomem: + /* Restore the previous length */ + _dbus_string_set_length (str, old_string_len); + + return FALSE; +} + +static dbus_uint32_t +demarshal_4_octets (const DBusString *str, + int byte_order, + int pos, + int *new_pos) +{ + const DBusRealString *real = (const DBusRealString*) str; + + pos = _DBUS_ALIGN_VALUE (pos, 4); + + if (new_pos) + *new_pos = pos + 4; + + return unpack_4_octets (byte_order, real->str + pos); +} + +static DBusOctets8 +demarshal_8_octets (const DBusString *str, + int byte_order, + int pos, + int *new_pos) +{ + const DBusRealString *real = (const DBusRealString*) str; + + pos = _DBUS_ALIGN_VALUE (pos, 8); + + if (new_pos) + *new_pos = pos + 8; + + return unpack_8_octets (byte_order, real->str + pos); +} + +/** + * Demarshals a double. + * + * @param str the string containing the data + * @param byte_order the byte order + * @param pos the position in the string + * @param new_pos the new position of the string + * @returns the demarshaled double. + */ +double +_dbus_demarshal_double (const DBusString *str, + int byte_order, + int pos, + int *new_pos) +{ + DBusOctets8 r; + + r = demarshal_8_octets (str, byte_order, pos, new_pos); + + return r.d; +} + +/** + * Demarshals a 32 bit signed integer. + * + * @param str the string containing the data + * @param byte_order the byte order + * @param pos the position in the string + * @param new_pos the new position of the string + * @returns the demarshaled integer. + */ +dbus_int32_t +_dbus_demarshal_int32 (const DBusString *str, + int byte_order, + int pos, + int *new_pos) +{ + return (dbus_int32_t) demarshal_4_octets (str, byte_order, pos, new_pos); +} + +/** + * Demarshals a 32 bit unsigned integer. + * + * @param str the string containing the data + * @param byte_order the byte order + * @param pos the position in the string + * @param new_pos the new position of the string + * @returns the demarshaled integer. + */ +dbus_uint32_t +_dbus_demarshal_uint32 (const DBusString *str, + int byte_order, + int pos, + int *new_pos) +{ + return demarshal_4_octets (str, byte_order, pos, new_pos); +} + +#ifdef DBUS_HAVE_INT64 + +/** + * Demarshals a 64 bit signed integer. + * + * @param str the string containing the data + * @param byte_order the byte order + * @param pos the position in the string + * @param new_pos the new position of the string + * @returns the demarshaled integer. + */ +dbus_int64_t +_dbus_demarshal_int64 (const DBusString *str, + int byte_order, + int pos, + int *new_pos) +{ + DBusOctets8 r; + + r = demarshal_8_octets (str, byte_order, pos, new_pos); + + return r.s; +} + +/** + * Demarshals a 64 bit unsigned integer. + * + * @param str the string containing the data + * @param byte_order the byte order + * @param pos the position in the string + * @param new_pos the new position of the string + * @returns the demarshaled integer. + */ +dbus_uint64_t +_dbus_demarshal_uint64 (const DBusString *str, + int byte_order, + int pos, + int *new_pos) +{ + DBusOctets8 r; + + r = demarshal_8_octets (str, byte_order, pos, new_pos); + + return r.u; +} + +#endif /* DBUS_HAVE_INT64 */ + +/** + * Demarshals a basic type + * + * @param str the string containing the data + * @param type type of value to demarshal + * @param value pointer to return value data + * @param byte_order the byte order + * @param pos pointer to position in the string, + * updated on return to new position + **/ +void +_dbus_demarshal_basic_type (const DBusString *str, + int type, + void *value, + int byte_order, + int *pos) +{ + const char *str_data = _dbus_string_get_const_data (str); + + switch (type) + { + case DBUS_TYPE_BYTE: + case DBUS_TYPE_BOOLEAN: + *(unsigned char *) value = _dbus_string_get_byte (str, *pos); + (*pos)++; + break; + case DBUS_TYPE_INT32: + case DBUS_TYPE_UINT32: + *pos = _DBUS_ALIGN_VALUE (*pos, 4); + *(dbus_uint32_t *) value = *(dbus_uint32_t *)(str_data + *pos); + if (byte_order != DBUS_COMPILER_BYTE_ORDER) + *(dbus_uint32_t *) value = DBUS_UINT32_SWAP_LE_BE (*(dbus_uint32_t *) value); + *pos += 4; + break; +#ifdef DBUS_HAVE_INT64 + case DBUS_TYPE_INT64: + case DBUS_TYPE_UINT64: +#endif /* DBUS_HAVE_INT64 */ + case DBUS_TYPE_DOUBLE: + *pos = _DBUS_ALIGN_VALUE (*pos, 8); + memcpy (value, str_data + *pos, 8); + if (byte_order != DBUS_COMPILER_BYTE_ORDER) +#ifdef DBUS_HAVE_INT64 + *(dbus_uint64_t *) value = DBUS_UINT64_SWAP_LE_BE (*(dbus_uint64_t *) value); +#else + swap_bytes (value, 8); +#endif + *pos += 8; + break; + default: + _dbus_assert_not_reached ("not a basic type"); + break; + } +} + +/** + * Demarshals an UTF-8 string. + * + * @todo Should we check the string to make sure + * that it's valid UTF-8, and maybe "fix" the string + * if it's broken? + * + * @todo Should probably demarshal to a DBusString, + * having memcpy() in here is Evil(tm). + * + * @param str the string containing the data + * @param byte_order the byte order + * @param pos the position in the string + * @param new_pos the new position of the string + * @returns the demarshaled string. + */ +char * +_dbus_demarshal_string (const DBusString *str, + int byte_order, + int pos, + int *new_pos) +{ + int len; + char *retval; + const char *data; + + len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos); + + retval = dbus_malloc (len + 1); + + if (!retval) + return NULL; + + data = _dbus_string_get_const_data_len (str, pos, len + 1); + + if (!data) + return NULL; + + memcpy (retval, data, len + 1); + + if (new_pos) + *new_pos = pos + len + 1; + + return retval; +} + +/** + * Demarshals a byte array. + * + * @todo Should probably demarshal to a DBusString, + * having memcpy() in here is Evil(tm). + * + * @param str the string containing the data + * @param byte_order the byte order + * @param pos the position in the string + * @param new_pos the new position of the string + * @param array the array + * @param array_len length of the demarshaled data + + * @returns #TRUE on success + */ +dbus_bool_t +_dbus_demarshal_byte_array (const DBusString *str, + int byte_order, + int pos, + int *new_pos, + unsigned char **array, + int *array_len) +{ + int len; + unsigned char *retval; + const char *data; + + len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos); + + if (len == 0) + { + *array_len = len; + *array = NULL; + + if (new_pos) + *new_pos = pos; + + return TRUE; + } + + retval = dbus_malloc (len); + + if (!retval) + return FALSE; + + data = _dbus_string_get_const_data_len (str, pos, len); + + if (!data) + { + dbus_free (retval); + return FALSE; + } + + memcpy (retval, data, len); + + if (new_pos) + *new_pos = pos + len; + + *array = retval; + *array_len = len; + + return TRUE; +} + +static dbus_bool_t +demarshal_4_octets_array (const DBusString *str, + int byte_order, + int pos, + int *new_pos, + dbus_uint32_t **array, + int *array_len) +{ + int len, i; + dbus_uint32_t *retval; + int byte_len; + + byte_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos); + len = byte_len / 4; + + if (len == 0) + { + *array_len = 0; + *array = NULL; + + if (new_pos) + *new_pos = pos; + + return TRUE; + } + + if (!_dbus_string_copy_data_len (str, (char**) &retval, + pos, byte_len)) + return FALSE; + + if (byte_order != DBUS_COMPILER_BYTE_ORDER) + { + for (i = 0; i < len; i++) + retval[i] = DBUS_UINT32_SWAP_LE_BE (retval[i]); + } + + if (new_pos) + *new_pos = pos + byte_len; + + *array_len = len; + *array = retval; + + return TRUE; +} + +static dbus_bool_t +demarshal_8_octets_array (const DBusString *str, + int byte_order, + int pos, + int *new_pos, + DBusOctets8 **array, + int *array_len) +{ + int len, i; + DBusOctets8 *retval; + int byte_len; + + byte_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos); + len = byte_len / 8; + + if (len == 0) + { + *array_len = 0; + *array = NULL; + + if (new_pos) + *new_pos = pos; + + return TRUE; + } + + if (!_dbus_string_copy_data_len (str, (char**) &retval, + pos, byte_len)) + return FALSE; + + if (byte_order != DBUS_COMPILER_BYTE_ORDER) + { + for (i = 0; i < len; i++) + { +#ifdef DBUS_HAVE_INT64 + retval[i].u = DBUS_UINT64_SWAP_LE_BE (retval[i].u); +#else + swap_bytes ((unsigned char *) &retval[i], 8); +#endif + } + } + + if (new_pos) + *new_pos = pos + byte_len; + + *array_len = len; + *array = retval; + + return TRUE; +} + +/** + * Demarshals a 32 bit signed integer array. + * + * @param str the string containing the data + * @param byte_order the byte order + * @param pos the position in the string + * @param new_pos the new position of the string + * @param array the array + * @param array_len length of the demarshaled data + * @returns #TRUE on success + */ +dbus_bool_t +_dbus_demarshal_int32_array (const DBusString *str, + int byte_order, + int pos, + int *new_pos, + dbus_int32_t **array, + int *array_len) +{ + return demarshal_4_octets_array (str, byte_order, pos, new_pos, + (dbus_uint32_t**) array, array_len); +} + +/** + * Demarshals a 32 bit unsigned integer array. + * + * @param str the string containing the data + * @param byte_order the byte order + * @param pos the position in the string + * @param new_pos the new position of the string + * @param array the array + * @param array_len length of the demarshaled data + * @returns #TRUE on success + */ +dbus_bool_t +_dbus_demarshal_uint32_array (const DBusString *str, + int byte_order, + int pos, + int *new_pos, + dbus_uint32_t **array, + int *array_len) +{ + return demarshal_4_octets_array (str, byte_order, pos, new_pos, + array, array_len); +} + +#ifdef DBUS_HAVE_INT64 + +/** + * Demarshals a 64 bit signed integer array. + * + * @param str the string containing the data + * @param byte_order the byte order + * @param pos the position in the string + * @param new_pos the new position of the string + * @param array the array + * @param array_len length of the demarshaled data + * @returns #TRUE on success + */ +dbus_bool_t +_dbus_demarshal_int64_array (const DBusString *str, + int byte_order, + int pos, + int *new_pos, + dbus_int64_t **array, + int *array_len) +{ + return demarshal_8_octets_array (str, byte_order, pos, new_pos, + (DBusOctets8**) array, array_len); +} + +/** + * Demarshals a 64 bit unsigned integer array. + * + * @param str the string containing the data + * @param byte_order the byte order + * @param pos the position in the string + * @param new_pos the new position of the string + * @param array the array + * @param array_len length of the demarshaled data + * @returns #TRUE on success + */ +dbus_bool_t +_dbus_demarshal_uint64_array (const DBusString *str, + int byte_order, + int pos, + int *new_pos, + dbus_uint64_t **array, + int *array_len) +{ + return demarshal_8_octets_array (str, byte_order, pos, new_pos, + (DBusOctets8**) array, array_len); +} + +#endif /* DBUS_HAVE_INT64 */ + +/** + * Demarshals a double array. + * + * @param str the string containing the data + * @param byte_order the byte order + * @param pos the position in the string + * @param new_pos the new position of the string + * @param array the array + * @param array_len length of the demarshaled data + * @returns #TRUE on success + */ +dbus_bool_t +_dbus_demarshal_double_array (const DBusString *str, + int byte_order, + int pos, + int *new_pos, + double **array, + int *array_len) +{ + return demarshal_8_octets_array (str, byte_order, pos, new_pos, + (DBusOctets8**) array, array_len); +} + + +/** + * Demarshals an array of basic types + * + * @param str the string containing the data + * @param element_type type of array elements to demarshal + * @param array pointer to pointer to array data + * @param array_len pointer to array length + * @param byte_order the byte order + * @param pos pointer to position in the string, + * updated on return to new position + **/ +dbus_bool_t +_dbus_demarshal_basic_type_array (const DBusString *str, + int element_type, + void **array, + int *array_len, + int byte_order, + int *pos) +{ + switch (element_type) + { + case DBUS_TYPE_BOOLEAN: + /* FIXME: do we want to post-normalize these ? */ + case DBUS_TYPE_BYTE: + return _dbus_demarshal_byte_array (str, byte_order, *pos, pos, + (unsigned char **)array, array_len); + break; + case DBUS_TYPE_INT32: + case DBUS_TYPE_UINT32: + return demarshal_4_octets_array (str, byte_order, *pos, pos, + (dbus_uint32_t **)array, array_len); + break; +#ifdef DBUS_HAVE_INT64 + case DBUS_TYPE_INT64: + case DBUS_TYPE_UINT64: +#endif /* DBUS_HAVE_INT64 */ + case DBUS_TYPE_DOUBLE: + return demarshal_8_octets_array (str, byte_order, *pos, pos, + (DBusOctets8**) array, array_len); + default: + _dbus_assert_not_reached ("not a basic type"); + break; + } + return FALSE; +} + +/** + * Demarshals a string array. + * + * @param str the string containing the data + * @param byte_order the byte order + * @param pos the position in the string + * @param new_pos the new position of the string + * @param array the array + * @param array_len location for length of the demarshaled data or NULL + * @returns #TRUE on success + */ +dbus_bool_t +_dbus_demarshal_string_array (const DBusString *str, + int byte_order, + int pos, + int *new_pos, + char ***array, + int *array_len) +{ + int bytes_len, i; + int len, allocated; + int end_pos; + char **retval; + + bytes_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos); + + if (bytes_len == 0) + { + *array_len = 0; + *array = NULL; + + if (new_pos) + *new_pos = pos; + + return TRUE; + } + + len = 0; + allocated = 4; + end_pos = pos + bytes_len; + + retval = dbus_new (char *, allocated); + + if (!retval) + return FALSE; + + while (pos < end_pos) + { + retval[len] = _dbus_demarshal_string (str, byte_order, pos, &pos); + + if (retval[len] == NULL) + goto error; + + len += 1; + + if (len >= allocated - 1) /* -1 for NULL termination */ + { + char **newp; + newp = dbus_realloc (retval, + sizeof (char*) * allocated * 2); + if (newp == NULL) + goto error; + + allocated *= 2; + retval = newp; + } + } + + retval[len] = NULL; + + if (new_pos) + *new_pos = pos; + + *array = retval; + *array_len = len; + + return TRUE; + + error: + for (i = 0; i < len; i++) + dbus_free (retval[i]); + dbus_free (retval); + + return FALSE; +} + +/** Set to 1 to get a bunch of spew about disassembling the path string */ +#define VERBOSE_DECOMPOSE 0 + +/** + * Decompose an object path. A path of just "/" is + * represented as an empty vector of strings. + * + * @param data the path data + * @param len the length of the path string + * @param path address to store new object path + * @param path_len length of stored path + */ +dbus_bool_t +_dbus_decompose_path (const char* data, + int len, + char ***path, + int *path_len) +{ + char **retval; + int n_components; + int i, j, comp; + + _dbus_assert (data != NULL); + +#if VERBOSE_DECOMPOSE + _dbus_verbose ("Decomposing path \"%s\"\n", + data); +#endif + + n_components = 0; + i = 0; + while (i < len) + { + if (data[i] == '/') + n_components += 1; + ++i; + } + + retval = dbus_new0 (char*, n_components + 1); + + if (retval == NULL) + return FALSE; + + comp = 0; + i = 0; + while (i < len) + { + if (data[i] == '/') + ++i; + j = i; + + while (j < len && data[j] != '/') + ++j; + + /* Now [i, j) is the path component */ + _dbus_assert (i < j); + _dbus_assert (data[i] != '/'); + _dbus_assert (j == len || data[j] == '/'); + +#if VERBOSE_DECOMPOSE + _dbus_verbose (" (component in [%d,%d))\n", + i, j); +#endif + + retval[comp] = _dbus_memdup (&data[i], j - i + 1); + if (retval[comp] == NULL) + { + dbus_free_string_array (retval); + return FALSE; + } + retval[comp][j-i] = '\0'; +#if VERBOSE_DECOMPOSE + _dbus_verbose (" (component %d = \"%s\")\n", + comp, retval[comp]); +#endif + + ++comp; + i = j; + } + _dbus_assert (i == len); + + *path = retval; + if (path_len) + *path_len = n_components; + + return TRUE; +} + +/** + * Demarshals an object path. A path of just "/" is + * represented as an empty vector of strings. + * + * @param str the string containing the data + * @param byte_order the byte order + * @param pos the position in the string + * @param new_pos the new position of the string + * @param path address to store new object path + * @param path_len length of stored path + */ +dbus_bool_t +_dbus_demarshal_object_path (const DBusString *str, + int byte_order, + int pos, + int *new_pos, + char ***path, + int *path_len) +{ + int len; + const char *data; + + len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos); + data = _dbus_string_get_const_data_len (str, pos, len + 1); + + if (!_dbus_decompose_path (data, len, path, path_len)) + return FALSE; + + if (new_pos) + *new_pos = pos + len + 1; + + return TRUE; +} + +/** + * Returns the position right after the end of an argument. PERFORMS + * NO VALIDATION WHATSOEVER. The message must have been previously + * validated. + * + * @param str a string + * @param byte_order the byte order to use + * @param type the type of the argument + * @param pos the pos where the arg starts + * @param end_pos pointer where the position right + * after the end position will follow + * @returns TRUE if more data exists after the arg + */ +dbus_bool_t +_dbus_marshal_get_arg_end_pos (const DBusString *str, + int byte_order, + int type, + int pos, + int *end_pos) +{ + if (pos >= _dbus_string_get_length (str)) + return FALSE; + + switch (type) + { + case DBUS_TYPE_INVALID: + return FALSE; + break; + + case DBUS_TYPE_NIL: + *end_pos = pos; + break; + + case DBUS_TYPE_BYTE: + *end_pos = pos + 1; + break; + + case DBUS_TYPE_BOOLEAN: + *end_pos = pos + 1; + break; + + case DBUS_TYPE_INT32: + case DBUS_TYPE_UINT32: + *end_pos = _DBUS_ALIGN_VALUE (pos, 4) + 4; + break; + + case DBUS_TYPE_INT64: + case DBUS_TYPE_UINT64: + case DBUS_TYPE_DOUBLE: + + *end_pos = _DBUS_ALIGN_VALUE (pos, 8) + 8; + break; + + case DBUS_TYPE_OBJECT_PATH: + case DBUS_TYPE_STRING: + { + int len; + + /* Demarshal the length */ + len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos); + + *end_pos = pos + len + 1; + } + break; + + case DBUS_TYPE_CUSTOM: + { + int len; + + /* Demarshal the string length */ + len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos); + + pos += len + 1; + + /* Demarshal the data length */ + len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos); + + *end_pos = pos + len; + } + break; + + case DBUS_TYPE_ARRAY: + { + int len; + + /* Demarshal the length */ + len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos); + + *end_pos = pos + len; + } + break; + + case DBUS_TYPE_DICT: + { + int len; + + /* Demarshal the length */ + len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos); + + *end_pos = pos + len; + } + break; + + default: + _dbus_warn ("Unknown message arg type %d\n", type); + _dbus_assert_not_reached ("Unknown message argument type\n"); + return FALSE; + } + + if (*end_pos > _dbus_string_get_length (str)) + return FALSE; + + return TRUE; +} + +/** + * Demarshals and validates a length; returns < 0 if the validation + * fails. The length is required to be small enough that + * len*sizeof(double) will not overflow, and small enough to fit in a + * signed integer. DOES NOT check whether the length points + * beyond the end of the string, because it doesn't know the + * size of array elements. + * + * @param str the string + * @param byte_order the byte order + * @param pos the unaligned string position (snap to next aligned) + * @param new_pos return location for new position. + */ +static int +demarshal_and_validate_len (const DBusString *str, + int byte_order, + int pos, + int *new_pos) +{ + int align_4 = _DBUS_ALIGN_VALUE (pos, 4); + unsigned int len; + + _dbus_assert (new_pos != NULL); + + if ((align_4 + 4) > _dbus_string_get_length (str)) + { + _dbus_verbose ("not enough room in message for array length\n"); + return -1; + } + + if (!_dbus_string_validate_nul (str, pos, + align_4 - pos)) + { + _dbus_verbose ("array length alignment padding not initialized to nul at %d\n", pos); + return -1; + } + + len = _dbus_demarshal_uint32 (str, byte_order, align_4, new_pos); + + /* note that the len is the number of bytes, so we need it to be + * at least SIZE_T_MAX, but make it smaller just to keep things + * sane. We end up using ints for most sizes to avoid unsigned mess + * so limit to maximum 32-bit signed int divided by at least 8, more + * for a bit of paranoia margin. INT_MAX/32 is about 65 megabytes. + */ +#define MAX_ARRAY_LENGTH (((unsigned int)_DBUS_INT_MAX) / 32) + if (len > MAX_ARRAY_LENGTH) + { + _dbus_verbose ("array length %u exceeds maximum of %u at pos %d\n", + len, MAX_ARRAY_LENGTH, pos); + return -1; + } + else + return (int) len; +} + +static dbus_bool_t +validate_string (const DBusString *str, + int pos, + int len_without_nul, + int *end_pos) +{ + *end_pos = pos + len_without_nul + 1; + + if (*end_pos > _dbus_string_get_length (str)) + { + _dbus_verbose ("string length outside length of the message\n"); + return FALSE; + } + + if (_dbus_string_get_byte (str, pos + len_without_nul) != '\0') + { + _dbus_verbose ("string arg not nul-terminated\n"); + return FALSE; + } + + if (!_dbus_string_validate_utf8 (str, pos, len_without_nul)) + { + _dbus_verbose ("string is not valid UTF-8\n"); + return FALSE; + } + + return TRUE; +} + +/** + * Validates and returns a typecode at a specific position + * in the message + * + * @param str a string + * @param type the type of the argument + * @param pos the pos where the typecode starts + * @param end_pos pointer where the position right + * after the end position will follow + * @returns #TRUE if the type is valid. + */ +dbus_bool_t +_dbus_marshal_validate_type (const DBusString *str, + int pos, + int *type, + int *end_pos) +{ + const char *data; + + if (pos >= _dbus_string_get_length (str)) + return FALSE; + + data = _dbus_string_get_const_data_len (str, pos, 1); + + if (_dbus_type_is_valid (*data)) + { + *type = *data; + if (end_pos != NULL) + *end_pos = pos + 1; + return TRUE; + } + + _dbus_verbose ("'%c' %d invalid type code\n", (int) *data, (int) *data); + + return FALSE; +} + +/* Faster validator for array data that doesn't call + * validate_arg for each value + */ +static dbus_bool_t +validate_array_data (const DBusString *str, + int byte_order, + int depth, + int type, + int array_type_pos, + int pos, + int *new_pos, + int end) +{ + switch (type) + { + case DBUS_TYPE_INVALID: + return FALSE; + break; + + case DBUS_TYPE_NIL: + break; + + case DBUS_TYPE_OBJECT_PATH: + case DBUS_TYPE_STRING: + case DBUS_TYPE_CUSTOM: + case DBUS_TYPE_ARRAY: + case DBUS_TYPE_DICT: + /* This clean recursion to validate_arg is what we + * are doing logically for all types, but we don't + * really want to call validate_arg for every byte + * in a byte array, so the primitive types are + * special-cased. + */ + while (pos < end) + { + if (!_dbus_marshal_validate_arg (str, byte_order, depth, + type, array_type_pos, pos, &pos)) + return FALSE; + } + break; + + case DBUS_TYPE_BYTE: + pos = end; + break; + + case DBUS_TYPE_BOOLEAN: + while (pos < end) + { + unsigned char c; + + c = _dbus_string_get_byte (str, pos); + + if (!(c == 0 || c == 1)) + { + _dbus_verbose ("boolean value must be either 0 or 1, not %d\n", c); + return FALSE; + } + + ++pos; + } + break; + + case DBUS_TYPE_INT32: + case DBUS_TYPE_UINT32: + /* Call validate arg one time to check alignment padding + * at start of array + */ + if (!_dbus_marshal_validate_arg (str, byte_order, depth, + type, array_type_pos, pos, &pos)) + return FALSE; + pos = _DBUS_ALIGN_VALUE (end, 4); + break; + + case DBUS_TYPE_INT64: + case DBUS_TYPE_UINT64: + case DBUS_TYPE_DOUBLE: + /* Call validate arg one time to check alignment padding + * at start of array + */ + if (!_dbus_marshal_validate_arg (str, byte_order, depth, + type, array_type_pos, pos, &pos)) + return FALSE; + pos = _DBUS_ALIGN_VALUE (end, 8); + break; + + default: + _dbus_verbose ("Unknown message arg type %d\n", type); + return FALSE; + } + + *new_pos = pos; + + return TRUE; +} + +/** + * Validates an argument of a specific type, checking that it + * is well-formed, for example no ludicrous length fields, strings + * are nul-terminated, etc. + * Returns the end position of the argument in end_pos, and + * returns #TRUE if a valid arg begins at "pos" + * + * @todo security: need to audit this function. + * + * @param str a string + * @param byte_order the byte order to use + * @param depth current recursion depth, to prevent excessive recursion + * @param type the type of the argument + * @param array_type_pos the position of the current array type, or + * -1 if not in an array + * @param pos the pos where the arg starts + * @param end_pos pointer where the position right + * after the end position will follow + * @returns #TRUE if the arg is valid. + */ +dbus_bool_t +_dbus_marshal_validate_arg (const DBusString *str, + int byte_order, + int depth, + int type, + int array_type_pos, + int pos, + int *end_pos) +{ + if (pos > _dbus_string_get_length (str)) + { + _dbus_verbose ("Validation went off the end of the message\n"); + return FALSE; + } + +#define MAX_VALIDATION_DEPTH 32 + + if (depth > MAX_VALIDATION_DEPTH) + { + _dbus_verbose ("Maximum recursion depth reached validating message\n"); + return FALSE; + } + + switch (type) + { + case DBUS_TYPE_INVALID: + return FALSE; + break; + + case DBUS_TYPE_NIL: + *end_pos = pos; + break; + + case DBUS_TYPE_BYTE: + if (1 > _dbus_string_get_length (str) - pos) + { + _dbus_verbose ("no room for byte value\n"); + return FALSE; + } + + *end_pos = pos + 1; + break; + + case DBUS_TYPE_BOOLEAN: + { + unsigned char c; + + if (1 > _dbus_string_get_length (str) - pos) + { + _dbus_verbose ("no room for boolean value\n"); + return FALSE; + } + + c = _dbus_string_get_byte (str, pos); + + if (!(c == 0 || c == 1)) + { + _dbus_verbose ("boolean value must be either 0 or 1, not %d\n", c); + return FALSE; + } + + *end_pos = pos + 1; + } + break; + + case DBUS_TYPE_INT32: + case DBUS_TYPE_UINT32: + { + int align_4 = _DBUS_ALIGN_VALUE (pos, 4); + + if (!_dbus_string_validate_nul (str, pos, + align_4 - pos)) + { + _dbus_verbose ("int32/uint32 alignment padding not initialized to nul\n"); + return FALSE; + } + + *end_pos = align_4 + 4; + } + break; + + case DBUS_TYPE_INT64: + case DBUS_TYPE_UINT64: + case DBUS_TYPE_DOUBLE: + { + int align_8 = _DBUS_ALIGN_VALUE (pos, 8); + + _dbus_verbose_bytes_of_string (str, pos, (align_8 + 8 - pos)); + + if (!_dbus_string_validate_nul (str, pos, + align_8 - pos)) + { + _dbus_verbose ("double/int64/uint64/objid alignment padding not initialized to nul at %d\n", pos); + return FALSE; + } + + *end_pos = align_8 + 8; + } + break; + + case DBUS_TYPE_OBJECT_PATH: + case DBUS_TYPE_STRING: + { + int len; + + /* Demarshal the length, which does NOT include + * nul termination + */ + len = demarshal_and_validate_len (str, byte_order, pos, &pos); + if (len < 0) + return FALSE; + + if (!validate_string (str, pos, len, end_pos)) + return FALSE; + + if (type == DBUS_TYPE_OBJECT_PATH) + { + if (!_dbus_string_validate_path (str, pos, len)) + return FALSE; + } + } + break; + + case DBUS_TYPE_CUSTOM: + { + int len; + + /* Demarshal the string length, which does NOT include + * nul termination + */ + len = demarshal_and_validate_len (str, byte_order, pos, &pos); + if (len < 0) + return FALSE; + + if (!validate_string (str, pos, len, &pos)) + return FALSE; + + /* Validate data */ + len = demarshal_and_validate_len (str, byte_order, pos, &pos); + if (len < 0) + return FALSE; + + *end_pos = pos + len; + } + break; + + case DBUS_TYPE_ARRAY: + { + int len; + int end; + int array_type; + + if (array_type_pos == -1) + { + array_type_pos = pos; + + do + { + if (!_dbus_marshal_validate_type (str, pos, &array_type, &pos)) + { + _dbus_verbose ("invalid array type\n"); + return FALSE; + } + + /* NIL values take up no space, so you couldn't iterate over an array of them. + * array of nil seems useless anyway; the useful thing might be array of + * (nil OR string) but we have no framework for that. + */ + if (array_type == DBUS_TYPE_NIL) + { + _dbus_verbose ("array of NIL is not allowed\n"); + return FALSE; + } + } + while (array_type == DBUS_TYPE_ARRAY); + } + else + array_type_pos++; + + if (!_dbus_marshal_validate_type (str, array_type_pos, &array_type, NULL)) + { + _dbus_verbose ("invalid array type\n"); + return FALSE; + } + + len = demarshal_and_validate_len (str, byte_order, pos, &pos); + if (len < 0) + { + _dbus_verbose ("invalid array length (<0)\n"); + return FALSE; + } + + if (len > _dbus_string_get_length (str) - pos) + { + _dbus_verbose ("array length outside length of the message\n"); + return FALSE; + } + + end = pos + len; + + if (len > 0 && !validate_array_data (str, byte_order, depth + 1, + array_type, array_type_pos, + pos, &pos, end)) + { + _dbus_verbose ("invalid array data\n"); + return FALSE; + } + + if (pos < end) + { + /* This should not be able to happen, as long as validate_arg moves forward; + * but the check is here just to be paranoid. + */ + _dbus_verbose ("array length %d specified was longer than actual array contents by %d\n", + len, end - pos); + return FALSE; + } + + if (pos > end) + { + _dbus_verbose ("array contents exceeds array length %d by %d\n", len, pos - end); + return FALSE; + } + + *end_pos = pos; + } + break; + + case DBUS_TYPE_DICT: + { + int dict_type; + int len; + int end; + + len = demarshal_and_validate_len (str, byte_order, pos, &pos); + if (len < 0) + return FALSE; + + if (len > _dbus_string_get_length (str) - pos) + { + _dbus_verbose ("dict length outside length of the message\n"); + return FALSE; + } + + end = pos + len; + + while (pos < end) + { + /* Validate name */ + if (!_dbus_marshal_validate_arg (str, byte_order, depth + 1, + DBUS_TYPE_STRING, -1, pos, &pos)) + return FALSE; + + if (!_dbus_marshal_validate_type (str, pos, &dict_type, &pos)) + { + _dbus_verbose ("invalid dict entry type at offset %d\n", pos); + return FALSE; + } + + /* Validate element */ + if (!_dbus_marshal_validate_arg (str, byte_order, depth + 1, + dict_type, -1, pos, &pos)) + { + _dbus_verbose ("dict arg invalid at offset %d\n", pos); + return FALSE; + } + } + + if (pos > end) + { + _dbus_verbose ("dict contents exceed stated dict length\n"); + return FALSE; + } + + *end_pos = pos; + } + break; + + default: + _dbus_verbose ("Unknown message arg type %d\n", type); + return FALSE; + } + + if (*end_pos > _dbus_string_get_length (str)) + return FALSE; + + return TRUE; +} + +/** + * Return #TRUE if the typecode is a valid typecode + * + * @returns #TRUE if valid + */ +dbus_bool_t +_dbus_type_is_valid (int typecode) +{ + switch (typecode) + { + case DBUS_TYPE_NIL: + case DBUS_TYPE_BYTE: + case DBUS_TYPE_BOOLEAN: + case DBUS_TYPE_INT32: + case DBUS_TYPE_UINT32: + case DBUS_TYPE_INT64: + case DBUS_TYPE_UINT64: + case DBUS_TYPE_DOUBLE: + case DBUS_TYPE_STRING: + case DBUS_TYPE_CUSTOM: + case DBUS_TYPE_ARRAY: + case DBUS_TYPE_DICT: + case DBUS_TYPE_OBJECT_PATH: + return TRUE; + + default: + return FALSE; + } +} + +/** + * If in verbose mode, print a block of binary data. + * + * @todo right now it prints even if not in verbose mode + * + * @param data the data + * @param len the length of the data + */ +void +_dbus_verbose_bytes (const unsigned char *data, + int len) +{ + int i; + const unsigned char *aligned; + + _dbus_assert (len >= 0); + + /* Print blanks on first row if appropriate */ + aligned = _DBUS_ALIGN_ADDRESS (data, 4); + if (aligned > data) + aligned -= 4; + _dbus_assert (aligned <= data); + + if (aligned != data) + { + _dbus_verbose ("%4d\t%p: ", - (data - aligned), aligned); + while (aligned != data) + { + _dbus_verbose (" "); + ++aligned; + } + } + + /* now print the bytes */ + i = 0; + while (i < len) + { + if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i]) + { + _dbus_verbose ("%4d\t%p: ", + i, &data[i]); + } + + if (data[i] >= 32 && + data[i] <= 126) + _dbus_verbose (" '%c' ", data[i]); + else + _dbus_verbose ("0x%s%x ", + data[i] <= 0xf ? "0" : "", data[i]); + + ++i; + + if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i]) + { + if (i > 3) + _dbus_verbose ("BE: %d LE: %d", + _dbus_unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]), + _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4])); + + if (i > 7 && + _DBUS_ALIGN_ADDRESS (&data[i], 8) == &data[i]) + { + _dbus_verbose (" dbl: %g", + *(double*)&data[i-8]); + } + + _dbus_verbose ("\n"); + } + } + + _dbus_verbose ("\n"); +} + +/** + * Dump the given part of the string to verbose log. + * + * @param str the string + * @param start the start of range to dump + * @param len length of range + */ +void +_dbus_verbose_bytes_of_string (const DBusString *str, + int start, + int len) +{ + const char *d; + int real_len; + + real_len = _dbus_string_get_length (str); + + _dbus_assert (start >= 0); + + if (start > real_len) + { + _dbus_verbose (" [%d,%d) is not inside string of length %d\n", + start, len, real_len); + return; + } + + if ((start + len) > real_len) + { + _dbus_verbose (" [%d,%d) extends outside string of length %d\n", + start, len, real_len); + len = real_len - start; + } + + d = _dbus_string_get_const_data_len (str, start, len); + + _dbus_verbose_bytes (d, len); +} + +/** + * Marshals a basic type + * + * @param str string to marshal to + * @param type type of value + * @param value pointer to value + * @param byte_order byte order + * @returns #TRUE on success + **/ +dbus_bool_t +_dbus_marshal_basic_type (DBusString *str, + char type, + void *value, + int byte_order) +{ + dbus_bool_t retval; + + switch (type) + { + case DBUS_TYPE_BYTE: + case DBUS_TYPE_BOOLEAN: + retval = _dbus_string_append_byte (str, *(unsigned char *)value); + break; + case DBUS_TYPE_INT32: + case DBUS_TYPE_UINT32: + return marshal_4_octets (str, byte_order, *(dbus_uint32_t *)value); + break; +#ifdef DBUS_HAVE_INT64 + case DBUS_TYPE_INT64: + case DBUS_TYPE_UINT64: + retval = _dbus_marshal_uint64 (str, byte_order, *(dbus_uint64_t *)value); + break; +#endif /* DBUS_HAVE_INT64 */ + case DBUS_TYPE_DOUBLE: + retval = _dbus_marshal_double (str, byte_order, *(double *)value); + break; + default: + _dbus_assert_not_reached ("not a basic type"); + retval = FALSE; + break; + } + return retval; +} + +/** + * Marshals a basic type array + * + * @param str string to marshal to + * @param element_type type of array elements + * @param value pointer to value + * @param len length of value data in elements + * @param byte_order byte order + * @returns #TRUE on success + **/ +dbus_bool_t +_dbus_marshal_basic_type_array (DBusString *str, + char element_type, + const void *value, + int len, + int byte_order) +{ + switch (element_type) + { + case DBUS_TYPE_BOOLEAN: + /* FIXME: we canonicalize to 0 or 1 for the single boolean case + * should we here too ? */ + case DBUS_TYPE_BYTE: + return _dbus_marshal_byte_array (str, byte_order, value, len); + break; + case DBUS_TYPE_INT32: + case DBUS_TYPE_UINT32: + return marshal_4_octets_array (str, byte_order, value, len); + break; +#ifdef DBUS_HAVE_INT64 + case DBUS_TYPE_INT64: + case DBUS_TYPE_UINT64: +#endif /* DBUS_HAVE_INT64 */ + case DBUS_TYPE_DOUBLE: + return marshal_8_octets_array (str, byte_order, value, len); + break; + default: + _dbus_assert_not_reached ("non basic type in array"); + break; + } + return FALSE; +} + +/** @} */ + +#ifdef DBUS_BUILD_TESTS +#include "dbus-test.h" +#include <stdio.h> + +dbus_bool_t +_dbus_marshal_test (void) +{ + DBusString str; + char *tmp1, *tmp2; + int pos = 0, len; + dbus_int32_t array1[3] = { 0x123, 0x456, 0x789 }, *array2; +#ifdef DBUS_HAVE_INT64 + dbus_int64_t array3[3] = { DBUS_INT64_CONSTANT (0x123ffffffff), + DBUS_INT64_CONSTANT (0x456ffffffff), + DBUS_INT64_CONSTANT (0x789ffffffff) }, *array4; +#endif + char *s; + DBusString t; + + if (!_dbus_string_init (&str)) + _dbus_assert_not_reached ("failed to init string"); + + /* Marshal doubles */ + if (!_dbus_marshal_double (&str, DBUS_BIG_ENDIAN, 3.14)) + _dbus_assert_not_reached ("could not marshal double value"); + if (!_dbus_demarshal_double (&str, DBUS_BIG_ENDIAN, pos, &pos) == 3.14) + _dbus_assert_not_reached ("demarshal failed"); + + if (!_dbus_marshal_double (&str, DBUS_LITTLE_ENDIAN, 3.14)) + _dbus_assert_not_reached ("could not marshal double value"); + if (!_dbus_demarshal_double (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 3.14) + _dbus_assert_not_reached ("demarshal failed"); + + /* Marshal signed integers */ + if (!_dbus_marshal_int32 (&str, DBUS_BIG_ENDIAN, -12345678)) + _dbus_assert_not_reached ("could not marshal signed integer value"); + if (!_dbus_demarshal_int32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == -12345678) + _dbus_assert_not_reached ("demarshal failed"); + + if (!_dbus_marshal_int32 (&str, DBUS_LITTLE_ENDIAN, -12345678)) + _dbus_assert_not_reached ("could not marshal signed integer value"); + if (!_dbus_demarshal_int32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == -12345678) + _dbus_assert_not_reached ("demarshal failed"); + + /* Marshal unsigned integers */ + if (!_dbus_marshal_uint32 (&str, DBUS_BIG_ENDIAN, 0x12345678)) + _dbus_assert_not_reached ("could not marshal signed integer value"); + if (!_dbus_demarshal_uint32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == 0x12345678) + _dbus_assert_not_reached ("demarshal failed"); + + if (!_dbus_marshal_uint32 (&str, DBUS_LITTLE_ENDIAN, 0x12345678)) + _dbus_assert_not_reached ("could not marshal signed integer value"); + if (!_dbus_demarshal_uint32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 0x12345678) + _dbus_assert_not_reached ("demarshal failed"); + +#ifdef DBUS_HAVE_INT64 + /* Marshal signed integers */ + if (!_dbus_marshal_int64 (&str, DBUS_BIG_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7))) + _dbus_assert_not_reached ("could not marshal signed integer value"); + if (_dbus_demarshal_int64 (&str, DBUS_BIG_ENDIAN, pos, &pos) != DBUS_INT64_CONSTANT (-0x123456789abc7)) + _dbus_assert_not_reached ("demarshal failed"); + + if (!_dbus_marshal_int64 (&str, DBUS_LITTLE_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7))) + _dbus_assert_not_reached ("could not marshal signed integer value"); + if (_dbus_demarshal_int64 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) != DBUS_INT64_CONSTANT (-0x123456789abc7)) + _dbus_assert_not_reached ("demarshal failed"); + + /* Marshal unsigned integers */ + if (!_dbus_marshal_uint64 (&str, DBUS_BIG_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7))) + _dbus_assert_not_reached ("could not marshal signed integer value"); + if (!(_dbus_demarshal_uint64 (&str, DBUS_BIG_ENDIAN, pos, &pos) == DBUS_UINT64_CONSTANT (0x123456789abc7))) + _dbus_assert_not_reached ("demarshal failed"); + + if (!_dbus_marshal_uint64 (&str, DBUS_LITTLE_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7))) + _dbus_assert_not_reached ("could not marshal signed integer value"); + if (!(_dbus_demarshal_uint64 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == DBUS_UINT64_CONSTANT (0x123456789abc7))) + _dbus_assert_not_reached ("demarshal failed"); +#endif /* DBUS_HAVE_INT64 */ + + /* Marshal strings */ + tmp1 = "This is the dbus test string"; + if (!_dbus_marshal_string (&str, DBUS_BIG_ENDIAN, tmp1)) + _dbus_assert_not_reached ("could not marshal string"); + tmp2 = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, pos, &pos); + if (!strcmp (tmp1, tmp2) == 0) + _dbus_assert_not_reached ("demarshal failed"); + dbus_free (tmp2); + + tmp1 = "This is the dbus test string"; + if (!_dbus_marshal_string (&str, DBUS_LITTLE_ENDIAN, tmp1)) + _dbus_assert_not_reached ("could not marshal string"); + tmp2 = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, pos, &pos); + if (!strcmp (tmp1, tmp2) == 0) + _dbus_assert_not_reached ("demarshal failed"); + dbus_free (tmp2); + + /* Marshal signed integer arrays */ + if (!_dbus_marshal_int32_array (&str, DBUS_BIG_ENDIAN, array1, 3)) + _dbus_assert_not_reached ("could not marshal integer array"); + if (!_dbus_demarshal_int32_array (&str, DBUS_BIG_ENDIAN, pos, &pos, &array2, &len)) + _dbus_assert_not_reached ("could not demarshal integer array"); + + if (len != 3) + _dbus_assert_not_reached ("Signed integer array lengths differ!\n"); + dbus_free (array2); + +#ifdef DBUS_HAVE_INT64 + /* Marshal 64-bit signed integer arrays */ + if (!_dbus_marshal_int64_array (&str, DBUS_BIG_ENDIAN, array3, 3)) + _dbus_assert_not_reached ("could not marshal integer array"); + if (!_dbus_demarshal_int64_array (&str, DBUS_BIG_ENDIAN, pos, &pos, &array4, &len)) + _dbus_assert_not_reached ("could not demarshal integer array"); + + if (len != 3) + _dbus_assert_not_reached ("Signed integer array lengths differ!\n"); + dbus_free (array4); + + /* set/pack 64-bit integers */ + _dbus_string_set_length (&str, 8); + + /* signed little */ + _dbus_marshal_set_int64 (&str, DBUS_LITTLE_ENDIAN, + 0, DBUS_INT64_CONSTANT (-0x123456789abc7)); + + _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) == + _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN, + _dbus_string_get_const_data (&str))); + + /* signed big */ + _dbus_marshal_set_int64 (&str, DBUS_BIG_ENDIAN, + 0, DBUS_INT64_CONSTANT (-0x123456789abc7)); + + _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) == + _dbus_unpack_int64 (DBUS_BIG_ENDIAN, + _dbus_string_get_const_data (&str))); + + /* signed little pack */ + _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7), + DBUS_LITTLE_ENDIAN, + _dbus_string_get_data (&str)); + + _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) == + _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN, + _dbus_string_get_const_data (&str))); + + /* signed big pack */ + _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7), + DBUS_BIG_ENDIAN, + _dbus_string_get_data (&str)); + + _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) == + _dbus_unpack_int64 (DBUS_BIG_ENDIAN, + _dbus_string_get_const_data (&str))); + + /* unsigned little */ + _dbus_marshal_set_uint64 (&str, DBUS_LITTLE_ENDIAN, + 0, DBUS_UINT64_CONSTANT (0x123456789abc7)); + + _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) == + _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN, + _dbus_string_get_const_data (&str))); + + /* unsigned big */ + _dbus_marshal_set_uint64 (&str, DBUS_BIG_ENDIAN, + 0, DBUS_UINT64_CONSTANT (0x123456789abc7)); + + _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) == + _dbus_unpack_uint64 (DBUS_BIG_ENDIAN, + _dbus_string_get_const_data (&str))); + + /* unsigned little pack */ + _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7), + DBUS_LITTLE_ENDIAN, + _dbus_string_get_data (&str)); + + _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) == + _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN, + _dbus_string_get_const_data (&str))); + + /* unsigned big pack */ + _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7), + DBUS_BIG_ENDIAN, + _dbus_string_get_data (&str)); + + _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) == + _dbus_unpack_uint64 (DBUS_BIG_ENDIAN, + _dbus_string_get_const_data (&str))); + +#endif + + /* set/pack 32-bit integers */ + _dbus_string_set_length (&str, 4); + + /* signed little */ + _dbus_marshal_set_int32 (&str, DBUS_LITTLE_ENDIAN, + 0, -0x123456); + + _dbus_assert (-0x123456 == + _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN, + _dbus_string_get_const_data (&str))); + + /* signed big */ + _dbus_marshal_set_int32 (&str, DBUS_BIG_ENDIAN, + 0, -0x123456); + + _dbus_assert (-0x123456 == + _dbus_unpack_int32 (DBUS_BIG_ENDIAN, + _dbus_string_get_const_data (&str))); + + /* signed little pack */ + _dbus_pack_int32 (-0x123456, + DBUS_LITTLE_ENDIAN, + _dbus_string_get_data (&str)); + + _dbus_assert (-0x123456 == + _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN, + _dbus_string_get_const_data (&str))); + + /* signed big pack */ + _dbus_pack_int32 (-0x123456, + DBUS_BIG_ENDIAN, + _dbus_string_get_data (&str)); + + _dbus_assert (-0x123456 == + _dbus_unpack_int32 (DBUS_BIG_ENDIAN, + _dbus_string_get_const_data (&str))); + + /* unsigned little */ + _dbus_marshal_set_uint32 (&str, DBUS_LITTLE_ENDIAN, + 0, 0x123456); + + _dbus_assert (0x123456 == + _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN, + _dbus_string_get_const_data (&str))); + + /* unsigned big */ + _dbus_marshal_set_uint32 (&str, DBUS_BIG_ENDIAN, + 0, 0x123456); + + _dbus_assert (0x123456 == + _dbus_unpack_uint32 (DBUS_BIG_ENDIAN, + _dbus_string_get_const_data (&str))); + + /* unsigned little pack */ + _dbus_pack_uint32 (0x123456, + DBUS_LITTLE_ENDIAN, + _dbus_string_get_data (&str)); + + _dbus_assert (0x123456 == + _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN, + _dbus_string_get_const_data (&str))); + + /* unsigned big pack */ + _dbus_pack_uint32 (0x123456, + DBUS_BIG_ENDIAN, + _dbus_string_get_data (&str)); + + _dbus_assert (0x123456 == + _dbus_unpack_uint32 (DBUS_BIG_ENDIAN, + _dbus_string_get_const_data (&str))); + + + /* Strings */ + + _dbus_string_set_length (&str, 0); + + _dbus_marshal_string (&str, DBUS_LITTLE_ENDIAN, + "Hello world"); + + s = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, 0, NULL); + _dbus_assert (strcmp (s, "Hello world") == 0); + dbus_free (s); + + _dbus_string_init_const (&t, "Hello world foo"); + + _dbus_marshal_set_string (&str, DBUS_LITTLE_ENDIAN, 0, + &t, _dbus_string_get_length (&t)); + + s = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, 0, NULL); + _dbus_assert (strcmp (s, "Hello world foo") == 0); + dbus_free (s); + + _dbus_string_init_const (&t, "Hello"); + + _dbus_marshal_set_string (&str, DBUS_LITTLE_ENDIAN, 0, + &t, _dbus_string_get_length (&t)); + + s = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, 0, NULL); + _dbus_assert (strcmp (s, "Hello") == 0); + dbus_free (s); + + /* Strings (big endian) */ + + _dbus_string_set_length (&str, 0); + + _dbus_marshal_string (&str, DBUS_BIG_ENDIAN, + "Hello world"); + + s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL); + _dbus_assert (strcmp (s, "Hello world") == 0); + dbus_free (s); + + _dbus_string_init_const (&t, "Hello world foo"); + + _dbus_marshal_set_string (&str, DBUS_BIG_ENDIAN, 0, + &t, _dbus_string_get_length (&t)); + + s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL); + _dbus_assert (strcmp (s, "Hello world foo") == 0); + dbus_free (s); + + _dbus_string_init_const (&t, "Hello"); + + _dbus_marshal_set_string (&str, DBUS_BIG_ENDIAN, 0, + &t, _dbus_string_get_length (&t)); + + s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL); + _dbus_assert (strcmp (s, "Hello") == 0); + dbus_free (s); + + _dbus_string_free (&str); + + return TRUE; +} + +#endif /* DBUS_BUILD_TESTS */ diff --git a/dbus/dbus-marshal-basic.h b/dbus/dbus-marshal-basic.h new file mode 100644 index 00000000..25db7cc5 --- /dev/null +++ b/dbus/dbus-marshal-basic.h @@ -0,0 +1,400 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-marshal-basic.h Marshalling routines for basic (primitive) types + * + * Copyright (C) 2002 CodeFactory AB + * Copyright (C) 2004 Red Hat, Inc. + * + * Licensed under the Academic Free License version 2.1 + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef DBUS_MARSHAL_H +#define DBUS_MARSHAL_H + +#include <config.h> +#include <dbus/dbus-protocol.h> +#include <dbus/dbus-types.h> +#include <dbus/dbus-arch-deps.h> +#include <dbus/dbus-string.h> + +#ifndef PACKAGE +#error "config.h not included here" +#endif + +/****************************************************** Remove later */ +#undef DBUS_TYPE_INVALID +#undef DBUS_TYPE_BYTE +#undef DBUS_TYPE_INT32 +#undef DBUS_TYPE_UINT32 +#undef DBUS_TYPE_INT64 +#undef DBUS_TYPE_UINT64 +#undef DBUS_TYPE_DOUBLE +#undef DBUS_TYPE_STRING +#undef DBUS_TYPE_OBJECT_PATH +#undef DBUS_TYPE_ARRAY +#undef DBUS_TYPE_DICT +#undef DBUS_TYPE_VARIANT +#undef DBUS_TYPE_STRUCT +#undef DBUS_NUMBER_OF_TYPES + +/* Never a legitimate type */ +#define DBUS_TYPE_INVALID ((int) '\0') + +/* Primitive types */ +#define DBUS_TYPE_BYTE ((int) 'y') +#define DBUS_TYPE_BOOLEAN ((int) 'b') +#define DBUS_TYPE_INT32 ((int) 'i') + +#define DBUS_TYPE_UINT32 ((int) 'u') +#define DBUS_TYPE_INT64 ((int) 'x') +#define DBUS_TYPE_UINT64 ((int) 't') + +#define DBUS_TYPE_DOUBLE ((int) 'd') +#define DBUS_TYPE_STRING ((int) 's') +#define DBUS_TYPE_OBJECT_PATH ((int) 'o') + +/* Compound types */ +#define DBUS_TYPE_ARRAY ((int) 'a') +#define DBUS_TYPE_DICT ((int) 'm') +#define DBUS_TYPE_VARIANT ((int) 'v') + +/* STRUCT is sort of special since its code can't appear in a type string, + * instead DBUS_STRUCT_BEGIN_CHAR has to appear + */ +#define DBUS_TYPE_STRUCT ((int) 'r') + +/* Does not count INVALID */ +#define DBUS_NUMBER_OF_TYPES (13) + +/* characters other than typecodes that appear in type signatures */ +#define DBUS_STRUCT_BEGIN_CHAR ((int) '(') +#define DBUS_STRUCT_END_CHAR ((int) ')') +#define DBUS_NAME_DELIMITER_CHAR ((int) '\'') +/****************************************************** Remove later */ + +#ifdef WORDS_BIGENDIAN +#define DBUS_COMPILER_BYTE_ORDER DBUS_BIG_ENDIAN +#else +#define DBUS_COMPILER_BYTE_ORDER DBUS_LITTLE_ENDIAN +#endif + +#define DBUS_UINT32_SWAP_LE_BE_CONSTANT(val) ((dbus_uint32_t) ( \ + (((dbus_uint32_t) (val) & (dbus_uint32_t) 0x000000ffU) << 24) | \ + (((dbus_uint32_t) (val) & (dbus_uint32_t) 0x0000ff00U) << 8) | \ + (((dbus_uint32_t) (val) & (dbus_uint32_t) 0x00ff0000U) >> 8) | \ + (((dbus_uint32_t) (val) & (dbus_uint32_t) 0xff000000U) >> 24))) + +#ifdef DBUS_HAVE_INT64 + +#define DBUS_UINT64_SWAP_LE_BE_CONSTANT(val) ((dbus_uint64_t) ( \ + (((dbus_uint64_t) (val) & \ + (dbus_uint64_t) DBUS_UINT64_CONSTANT (0x00000000000000ff)) << 56) | \ + (((dbus_uint64_t) (val) & \ + (dbus_uint64_t) DBUS_UINT64_CONSTANT (0x000000000000ff00)) << 40) | \ + (((dbus_uint64_t) (val) & \ + (dbus_uint64_t) DBUS_UINT64_CONSTANT (0x0000000000ff0000)) << 24) | \ + (((dbus_uint64_t) (val) & \ + (dbus_uint64_t) DBUS_UINT64_CONSTANT (0x00000000ff000000)) << 8) | \ + (((dbus_uint64_t) (val) & \ + (dbus_uint64_t) DBUS_UINT64_CONSTANT (0x000000ff00000000)) >> 8) | \ + (((dbus_uint64_t) (val) & \ + (dbus_uint64_t) DBUS_UINT64_CONSTANT (0x0000ff0000000000)) >> 24) | \ + (((dbus_uint64_t) (val) & \ + (dbus_uint64_t) DBUS_UINT64_CONSTANT (0x00ff000000000000)) >> 40) | \ + (((dbus_uint64_t) (val) & \ + (dbus_uint64_t) DBUS_UINT64_CONSTANT (0xff00000000000000)) >> 56))) +#endif /* DBUS_HAVE_INT64 */ + +#define DBUS_UINT32_SWAP_LE_BE(val) (DBUS_UINT32_SWAP_LE_BE_CONSTANT (val)) +#define DBUS_INT32_SWAP_LE_BE(val) ((dbus_int32_t)DBUS_UINT32_SWAP_LE_BE_CONSTANT (val)) + +#ifdef DBUS_HAVE_INT64 +#define DBUS_UINT64_SWAP_LE_BE(val) (DBUS_UINT64_SWAP_LE_BE_CONSTANT (val)) +#define DBUS_INT64_SWAP_LE_BE(val) ((dbus_int64_t)DBUS_UINT64_SWAP_LE_BE_CONSTANT (val)) +#endif /* DBUS_HAVE_INT64 */ + +#ifdef WORDS_BIGENDIAN +#define DBUS_INT32_TO_BE(val) ((dbus_int32_t) (val)) +#define DBUS_UINT32_TO_BE(val) ((dbus_uint32_t) (val)) +#define DBUS_INT32_TO_LE(val) (DBUS_INT32_SWAP_LE_BE (val)) +#define DBUS_UINT32_TO_LE(val) (DBUS_UINT32_SWAP_LE_BE (val)) +# ifdef DBUS_HAVE_INT64 +#define DBUS_INT64_TO_BE(val) ((dbus_int64_t) (val)) +#define DBUS_UINT64_TO_BE(val) ((dbus_uint64_t) (val)) +#define DBUS_INT64_TO_LE(val) (DBUS_INT64_SWAP_LE_BE (val)) +#define DBUS_UINT64_TO_LE(val) (DBUS_UINT64_SWAP_LE_BE (val)) +# endif /* DBUS_HAVE_INT64 */ +#else +#define DBUS_INT32_TO_LE(val) ((dbus_int32_t) (val)) +#define DBUS_UINT32_TO_LE(val) ((dbus_uint32_t) (val)) +#define DBUS_INT32_TO_BE(val) ((dbus_int32_t) DBUS_UINT32_SWAP_LE_BE (val)) +#define DBUS_UINT32_TO_BE(val) (DBUS_UINT32_SWAP_LE_BE (val)) +# ifdef DBUS_HAVE_INT64 +#define DBUS_INT64_TO_LE(val) ((dbus_int64_t) (val)) +#define DBUS_UINT64_TO_LE(val) ((dbus_uint64_t) (val)) +#define DBUS_INT64_TO_BE(val) ((dbus_int64_t) DBUS_UINT64_SWAP_LE_BE (val)) +#define DBUS_UINT64_TO_BE(val) (DBUS_UINT64_SWAP_LE_BE (val)) +# endif /* DBUS_HAVE_INT64 */ +#endif + +/* The transformation is symmetric, so the FROM just maps to the TO. */ +#define DBUS_INT32_FROM_LE(val) (DBUS_INT32_TO_LE (val)) +#define DBUS_UINT32_FROM_LE(val) (DBUS_UINT32_TO_LE (val)) +#define DBUS_INT32_FROM_BE(val) (DBUS_INT32_TO_BE (val)) +#define DBUS_UINT32_FROM_BE(val) (DBUS_UINT32_TO_BE (val)) +#ifdef DBUS_HAVE_INT64 +#define DBUS_INT64_FROM_LE(val) (DBUS_INT64_TO_LE (val)) +#define DBUS_UINT64_FROM_LE(val) (DBUS_UINT64_TO_LE (val)) +#define DBUS_INT64_FROM_BE(val) (DBUS_INT64_TO_BE (val)) +#define DBUS_UINT64_FROM_BE(val) (DBUS_UINT64_TO_BE (val)) +#endif /* DBUS_HAVE_INT64 */ + +void _dbus_pack_int32 (dbus_int32_t value, + int byte_order, + unsigned char *data); +dbus_int32_t _dbus_unpack_int32 (int byte_order, + const unsigned char *data); +void _dbus_pack_uint32 (dbus_uint32_t value, + int byte_order, + unsigned char *data); +dbus_uint32_t _dbus_unpack_uint32 (int byte_order, + const unsigned char *data); +#ifdef DBUS_HAVE_INT64 +void _dbus_pack_int64 (dbus_int64_t value, + int byte_order, + unsigned char *data); +dbus_int64_t _dbus_unpack_int64 (int byte_order, + const unsigned char *data); +void _dbus_pack_uint64 (dbus_uint64_t value, + int byte_order, + unsigned char *data); +dbus_uint64_t _dbus_unpack_uint64 (int byte_order, + const unsigned char *data); +#endif /* DBUS_HAVE_INT64 */ + +void _dbus_marshal_set_int32 (DBusString *str, + int byte_order, + int offset, + dbus_int32_t value); +void _dbus_marshal_set_uint32 (DBusString *str, + int byte_order, + int offset, + dbus_uint32_t value); +#ifdef DBUS_HAVE_INT64 +void _dbus_marshal_set_int64 (DBusString *str, + int byte_order, + int offset, + dbus_int64_t value); +void _dbus_marshal_set_uint64 (DBusString *str, + int byte_order, + int offset, + dbus_uint64_t value); +#endif /* DBUS_HAVE_INT64 */ + +dbus_bool_t _dbus_marshal_set_string (DBusString *str, + int byte_order, + int offset, + const DBusString *value, + int len); +void _dbus_marshal_set_object_path (DBusString *str, + int byte_order, + int offset, + const char **path, + int path_len); + +dbus_bool_t _dbus_marshal_int32 (DBusString *str, + int byte_order, + dbus_int32_t value); +dbus_bool_t _dbus_marshal_uint32 (DBusString *str, + int byte_order, + dbus_uint32_t value); +#ifdef DBUS_HAVE_INT64 +dbus_bool_t _dbus_marshal_int64 (DBusString *str, + int byte_order, + dbus_int64_t value); +dbus_bool_t _dbus_marshal_uint64 (DBusString *str, + int byte_order, + dbus_uint64_t value); +#endif /* DBUS_HAVE_INT64 */ +dbus_bool_t _dbus_marshal_double (DBusString *str, + int byte_order, + double value); +dbus_bool_t _dbus_marshal_string (DBusString *str, + int byte_order, + const char *value); +dbus_bool_t _dbus_marshal_string_len (DBusString *str, + int byte_order, + const char *value, + int len); +dbus_bool_t _dbus_marshal_basic_type (DBusString *str, + char type, + void *value, + int byte_order); +dbus_bool_t _dbus_marshal_byte_array (DBusString *str, + int byte_order, + const unsigned char *value, + int len); +dbus_bool_t _dbus_marshal_int32_array (DBusString *str, + int byte_order, + const dbus_int32_t *value, + int len); +dbus_bool_t _dbus_marshal_uint32_array (DBusString *str, + int byte_order, + const dbus_uint32_t *value, + int len); +#ifdef DBUS_HAVE_INT64 +dbus_bool_t _dbus_marshal_int64_array (DBusString *str, + int byte_order, + const dbus_int64_t *value, + int len); +dbus_bool_t _dbus_marshal_uint64_array (DBusString *str, + int byte_order, + const dbus_uint64_t *value, + int len); +#endif /* DBUS_HAVE_INT64 */ +dbus_bool_t _dbus_marshal_double_array (DBusString *str, + int byte_order, + const double *value, + int len); +dbus_bool_t _dbus_marshal_basic_type_array (DBusString *str, + char element_type, + const void *value, + int len, + int byte_order); + +dbus_bool_t _dbus_marshal_string_array (DBusString *str, + int byte_order, + const char **value, + int len); +dbus_bool_t _dbus_marshal_object_path (DBusString *str, + int byte_order, + const char **path, + int path_len); + +double _dbus_demarshal_double (const DBusString *str, + int byte_order, + int pos, + int *new_pos); +dbus_int32_t _dbus_demarshal_int32 (const DBusString *str, + int byte_order, + int pos, + int *new_pos); +dbus_uint32_t _dbus_demarshal_uint32 (const DBusString *str, + int byte_order, + int pos, + int *new_pos); +#ifdef DBUS_HAVE_INT64 +dbus_int64_t _dbus_demarshal_int64 (const DBusString *str, + int byte_order, + int pos, + int *new_pos); +dbus_uint64_t _dbus_demarshal_uint64 (const DBusString *str, + int byte_order, + int pos, + int *new_pos); +#endif /* DBUS_HAVE_INT64 */ +void _dbus_demarshal_basic_type (const DBusString *str, + int type, + void *value, + int byte_order, + int *pos); +char * _dbus_demarshal_string (const DBusString *str, + int byte_order, + int pos, + int *new_pos); +dbus_bool_t _dbus_demarshal_byte_array (const DBusString *str, + int byte_order, + int pos, + int *new_pos, + unsigned char **array, + int *array_len); +dbus_bool_t _dbus_demarshal_int32_array (const DBusString *str, + int byte_order, + int pos, + int *new_pos, + dbus_int32_t **array, + int *array_len); +dbus_bool_t _dbus_demarshal_uint32_array (const DBusString *str, + int byte_order, + int pos, + int *new_pos, + dbus_uint32_t **array, + int *array_len); +#ifdef DBUS_HAVE_INT64 +dbus_bool_t _dbus_demarshal_int64_array (const DBusString *str, + int byte_order, + int pos, + int *new_pos, + dbus_int64_t **array, + int *array_len); +dbus_bool_t _dbus_demarshal_uint64_array (const DBusString *str, + int byte_order, + int pos, + int *new_pos, + dbus_uint64_t **array, + int *array_len); +#endif /* DBUS_HAVE_INT64 */ +dbus_bool_t _dbus_demarshal_double_array (const DBusString *str, + int byte_order, + int pos, + int *new_pos, + double **array, + int *array_len); +dbus_bool_t _dbus_demarshal_basic_type_array (const DBusString *str, + int type, + void **array, + int *array_len, + int byte_order, + int *pos); + +dbus_bool_t _dbus_demarshal_string_array (const DBusString *str, + int byte_order, + int pos, + int *new_pos, + char ***array, + int *array_len); +dbus_bool_t _dbus_decompose_path (const char* data, + int len, + char ***path, + int *path_len); +dbus_bool_t _dbus_demarshal_object_path (const DBusString *str, + int byte_order, + int pos, + int *new_pos, + char ***path, + int *path_len); + +dbus_bool_t _dbus_marshal_get_arg_end_pos (const DBusString *str, + int byte_order, + int type, + int pos, + int *end_pos); +dbus_bool_t _dbus_marshal_validate_type (const DBusString *str, + int pos, + int *type, + int *end_pos); +dbus_bool_t _dbus_marshal_validate_arg (const DBusString *str, + int depth, + int byte_order, + int type, + int array_type_pos, + int pos, + int *end_pos); + +dbus_bool_t _dbus_type_is_valid (int typecode); + +#endif /* DBUS_MARSHAL_H */ diff --git a/dbus/dbus-marshal-recursive.c b/dbus/dbus-marshal-recursive.c new file mode 100644 index 00000000..eb85a2c4 --- /dev/null +++ b/dbus/dbus-marshal-recursive.c @@ -0,0 +1,713 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-marshal-recursive.c Marshalling routines for recursive types + * + * Copyright (C) 2004 Red Hat, Inc. + * + * Licensed under the Academic Free License version 2.1 + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "dbus-marshal-recursive.h" +#include "dbus-internals.h" + +/** + * @addtogroup DBusMarshal + * @{ + */ + +void +_dbus_type_reader_init (DBusTypeReader *reader, + int byte_order, + const DBusString *type_str, + int type_pos, + const DBusString *value_str, + int value_pos) +{ + + +} + +int +_dbus_type_reader_get_value_end (DBusTypeReader *reader) +{ + + +} + +int +_dbus_type_reader_get_type_end (DBusTypeReader *reader) +{ + + +} + +int +_dbus_type_reader_get_current_type (DBusTypeReader *reader) +{ + + +} + +int +_dbus_type_reader_get_array_type (DBusTypeReader *reader) +{ + + +} + +void +_dbus_type_reader_read_basic (DBusTypeReader *reader, + void *value) +{ + + +} + +dbus_bool_t +_dbus_type_reader_read_array (DBusTypeReader *reader, + int type, + void **array, + int *array_len) +{ + + +} + +void +_dbus_type_reader_recurse (DBusTypeReader *reader) +{ + + +} + +void +_dbus_type_reader_unrecurse (DBusTypeReader *reader) +{ + + +} + +dbus_bool_t +_dbus_type_reader_next (DBusTypeReader *reader) +{ + + + +} + +void +_dbus_type_writer_init (DBusTypeWriter *writer, + int byte_order, + DBusString *type_str, + int type_pos, + DBusString *value_str, + int value_pos) +{ + + +} + +dbus_bool_t +_dbus_type_writer_write_basic (DBusTypeWriter *writer, + int type, + const void *value) +{ + + +} + +dbus_bool_t +_dbus_type_writer_write_array (DBusTypeWriter *writer, + int type, + const void *array, + int array_len) +{ + + +} + +dbus_bool_t +_dbus_type_writer_recurse (DBusTypeWriter *writer, + int container_type) +{ + + +} + +dbus_bool_t +_dbus_type_writer_unrecurse (DBusTypeWriter *writer) +{ + + +} + +/** @} */ /* end of DBusMarshal group */ + +#ifdef DBUS_BUILD_TESTS +#include "dbus-test.h" +#include <stdio.h> +#include <stdlib.h> + +typedef struct +{ + DBusString signature; + DBusString body; +} DataBlock; + +typedef struct +{ + int saved_sig_len; + int saved_body_len; +} DataBlockState; + +static dbus_bool_t +data_block_init (DataBlock *block) +{ + if (!_dbus_string_init (&block->signature)) + return FALSE; + + if (!_dbus_string_init (&block->body)) + { + _dbus_string_free (&block->signature); + return FALSE; + } + + return TRUE; +} + +static void +data_block_free (DataBlock *block) +{ + _dbus_string_free (&block->signature); + _dbus_string_free (&block->body); +} + +static void +data_block_save (DataBlock *block, + DataBlockState *state) +{ + state->saved_sig_len = _dbus_string_get_length (&block->signature); + state->saved_body_len = _dbus_string_get_length (&block->body); +} + +static void +data_block_restore (DataBlock *block, + DataBlockState *state) +{ + /* These set_length should be shortening things so should always work */ + + if (!_dbus_string_set_length (&block->signature, + state->saved_sig_len)) + _dbus_assert_not_reached ("could not restore signature length"); + + if (!_dbus_string_set_length (&block->body, + state->saved_body_len)) + _dbus_assert_not_reached ("could not restore body length"); +} + +static void +data_block_init_reader_writer (DataBlock *block, + int byte_order, + DBusTypeReader *reader, + DBusTypeWriter *writer) +{ + _dbus_type_reader_init (reader, + byte_order, + &block->signature, + _dbus_string_get_length (&block->signature), + &block->body, + _dbus_string_get_length (&block->body)); + + _dbus_type_writer_init (writer, + byte_order, + &block->signature, + _dbus_string_get_length (&block->signature), + &block->body, + _dbus_string_get_length (&block->body)); +} + +#define SAMPLE_INT32 12345678 +#define SAMPLE_INT32_ALTERNATE 53781429 +static dbus_bool_t +write_int32 (DataBlock *block, + DBusTypeWriter *writer) +{ + dbus_int32_t v = SAMPLE_INT32; + + return _dbus_type_writer_write_basic (writer, + DBUS_TYPE_INT32, + &v); +} + +static void +check_expected_type (DBusTypeReader *reader, + int expected) +{ + int t; + + t = _dbus_type_reader_get_current_type (reader); + + if (t != expected) + { + _dbus_warn ("Read type %s while expecting %s\n", + _dbus_type_to_string (t), + _dbus_type_to_string (expected)); + exit (1); + } +} + +static dbus_bool_t +read_int32 (DataBlock *block, + DBusTypeReader *reader) +{ + dbus_int32_t v; + + check_expected_type (reader, DBUS_TYPE_INT32); + + _dbus_type_reader_read_basic (reader, + (dbus_int32_t*) &v); + + _dbus_assert (v == SAMPLE_INT32); + + return TRUE; +} + +static dbus_bool_t +write_struct_with_int32s (DataBlock *block, + DBusTypeWriter *writer) +{ + dbus_int32_t v; + DataBlockState saved; + + data_block_save (block, &saved); + + if (!_dbus_type_writer_recurse (writer, + DBUS_TYPE_STRUCT)) + return FALSE; + + v = SAMPLE_INT32; + if (!_dbus_type_writer_write_basic (writer, + DBUS_TYPE_INT32, + &v)) + { + data_block_restore (block, &saved); + return FALSE; + } + + v = SAMPLE_INT32_ALTERNATE; + if (!_dbus_type_writer_write_basic (writer, + DBUS_TYPE_INT32, + &v)) + { + data_block_restore (block, &saved); + return FALSE; + } + + if (!_dbus_type_writer_unrecurse (writer)) + { + data_block_restore (block, &saved); + return FALSE; + } + + return TRUE; +} + +static dbus_bool_t +read_struct_with_int32s (DataBlock *block, + DBusTypeReader *reader) +{ + dbus_int32_t v; + + check_expected_type (reader, DBUS_TYPE_STRUCT); + + _dbus_type_reader_recurse (reader); + + check_expected_type (reader, DBUS_TYPE_INT32); + + _dbus_type_reader_read_basic (reader, + (dbus_int32_t*) &v); + + _dbus_assert (v == SAMPLE_INT32); + + _dbus_type_reader_next (reader); + check_expected_type (reader, DBUS_TYPE_INT32); + + _dbus_type_reader_read_basic (reader, + (dbus_int32_t*) &v); + + _dbus_assert (v == SAMPLE_INT32_ALTERNATE); + + _dbus_type_reader_unrecurse (reader); + + return TRUE; +} + +static dbus_bool_t +write_struct_of_structs (DataBlock *block, + DBusTypeWriter *writer) +{ + DataBlockState saved; + + data_block_save (block, &saved); + + if (!_dbus_type_writer_recurse (writer, + DBUS_TYPE_STRUCT)) + return FALSE; + + if (!write_struct_with_int32s (block, writer)) + { + data_block_restore (block, &saved); + return FALSE; + } + if (!write_struct_with_int32s (block, writer)) + { + data_block_restore (block, &saved); + return FALSE; + } + if (!write_struct_with_int32s (block, writer)) + { + data_block_restore (block, &saved); + return FALSE; + } + + if (!_dbus_type_writer_unrecurse (writer)) + { + data_block_restore (block, &saved); + return FALSE; + } + + return TRUE; +} + +static dbus_bool_t +read_struct_of_structs (DataBlock *block, + DBusTypeReader *reader) +{ + check_expected_type (reader, DBUS_TYPE_STRUCT); + + _dbus_type_reader_recurse (reader); + + if (!read_struct_with_int32s (block, reader)) + return FALSE; + _dbus_type_reader_next (reader); + if (!read_struct_with_int32s (block, reader)) + return FALSE; + _dbus_type_reader_next (reader); + if (!read_struct_with_int32s (block, reader)) + return FALSE; + + _dbus_type_reader_unrecurse (reader); + + return TRUE; +} + +static dbus_bool_t +write_struct_of_structs_of_structs (DataBlock *block, + DBusTypeWriter *writer) +{ + DataBlockState saved; + + data_block_save (block, &saved); + + if (!_dbus_type_writer_recurse (writer, + DBUS_TYPE_STRUCT)) + return FALSE; + + if (!write_struct_of_structs (block, writer)) + { + data_block_restore (block, &saved); + return FALSE; + } + if (!write_struct_of_structs (block, writer)) + { + data_block_restore (block, &saved); + return FALSE; + } + + if (!_dbus_type_writer_unrecurse (writer)) + { + data_block_restore (block, &saved); + return FALSE; + } + + return TRUE; +} + +static dbus_bool_t +read_struct_of_structs_of_structs (DataBlock *block, + DBusTypeReader *reader) +{ + check_expected_type (reader, DBUS_TYPE_STRUCT); + + _dbus_type_reader_recurse (reader); + + if (!read_struct_of_structs (block, reader)) + return FALSE; + _dbus_type_reader_next (reader); + if (!read_struct_of_structs (block, reader)) + return FALSE; + + _dbus_type_reader_unrecurse (reader); + + return TRUE; +} + +typedef enum { + ITEM_INVALID = -1, + ITEM_INT32 = 0, + ITEM_STRUCT_WITH_INT32S, + ITEM_STRUCT_OF_STRUCTS, + ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, + ITEM_LAST +} WhichItem; + + +typedef dbus_bool_t (* WriteItemFunc) (DataBlock *block, + DBusTypeWriter *writer); +typedef dbus_bool_t (* ReadItemFunc) (DataBlock *block, + DBusTypeReader *reader); + +typedef struct +{ + WhichItem which; + WriteItemFunc write_item_func; + ReadItemFunc read_item_func; +} CheckMarshalItem; + +static CheckMarshalItem items[] = { + { ITEM_INT32, write_int32, read_int32 }, + { ITEM_STRUCT_WITH_INT32S, write_struct_with_int32s, read_struct_with_int32s }, + { ITEM_STRUCT_OF_STRUCTS, write_struct_of_structs, read_struct_of_structs }, + { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, + write_struct_of_structs_of_structs, + read_struct_of_structs_of_structs } +}; + +typedef struct +{ + /* Array of items in the above items[]; -1 terminated */ + int items[20]; +} TestRun; + +static TestRun runs[] = { + { { ITEM_INVALID } }, + + /* INT32 */ + { { ITEM_INT32, ITEM_INVALID } }, + { { ITEM_INT32, ITEM_INT32, ITEM_INVALID } }, + { { ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INVALID } }, + + /* STRUCT_WITH_INT32S */ + { { ITEM_STRUCT_WITH_INT32S, ITEM_INVALID } }, + { { ITEM_STRUCT_WITH_INT32S, ITEM_STRUCT_WITH_INT32S, ITEM_INVALID } }, + { { ITEM_STRUCT_WITH_INT32S, ITEM_INT32, ITEM_STRUCT_WITH_INT32S, ITEM_INVALID } }, + { { ITEM_INT32, ITEM_STRUCT_WITH_INT32S, ITEM_INT32, ITEM_STRUCT_WITH_INT32S, ITEM_INVALID } }, + { { ITEM_INT32, ITEM_STRUCT_WITH_INT32S, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_STRUCT_WITH_INT32S, ITEM_INVALID } }, + + /* STRUCT_OF_STRUCTS */ + { { ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } }, + { { ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } }, + { { ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } }, + { { ITEM_STRUCT_WITH_INT32S, ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } }, + { { ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } }, + { { ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } }, + + /* STRUCT_OF_STRUCTS_OF_STRUCTS */ + { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } }, + { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } }, + { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } }, + { { ITEM_STRUCT_WITH_INT32S, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } }, + { { ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } }, + { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } } + +}; + +static dbus_bool_t +perform_one_run (DataBlock *block, + int byte_order, + TestRun *run) +{ + DBusTypeReader reader; + DBusTypeWriter writer; + int i; + DataBlockState saved; + dbus_bool_t retval; + + retval = FALSE; + + data_block_save (block, &saved); + + data_block_init_reader_writer (block, + byte_order, + &reader, &writer); + + i = 0; + while (run->items[i] != ITEM_INVALID) + { + CheckMarshalItem *item = &items[run->items[i]]; + if (!(* item->write_item_func) (block, &writer)) + goto out; + ++i; + } + + i = 0; + while (run->items[i] != ITEM_INVALID) + { + CheckMarshalItem *item = &items[run->items[i]]; + + if (!(* item->read_item_func) (block, &reader)) + goto out; + + _dbus_type_reader_next (&reader); + + ++i; + } + + retval = TRUE; + + out: + data_block_restore (block, &saved); + return retval; +} + +static dbus_bool_t +perform_all_runs (int byte_order, + int initial_offset) +{ + int i; + DataBlock block; + dbus_bool_t retval; + + retval = FALSE; + + if (!data_block_init (&block)) + return FALSE; + + if (!_dbus_string_lengthen (&block.signature, initial_offset)) + goto out; + + if (!_dbus_string_lengthen (&block.body, initial_offset)) + goto out; + + i = 0; + while (i < _DBUS_N_ELEMENTS (runs)) + { + if (!perform_one_run (&block, byte_order, &runs[i])) + goto out; + + ++i; + } + + retval = TRUE; + + out: + data_block_free (&block); + + return retval; +} + +static dbus_bool_t +perform_all_items (int byte_order, + int initial_offset) +{ + int i; + DataBlock block; + dbus_bool_t retval; + TestRun run; + + retval = FALSE; + + if (!data_block_init (&block)) + return FALSE; + + + if (!_dbus_string_lengthen (&block.signature, initial_offset)) + goto out; + + if (!_dbus_string_lengthen (&block.body, initial_offset)) + goto out; + + /* Create a run containing all the items */ + i = 0; + while (i < _DBUS_N_ELEMENTS (items)) + { + _dbus_assert (i == items[i].which); + + run.items[i] = items[i].which; + + ++i; + } + + run.items[i] = ITEM_INVALID; + + if (!perform_one_run (&block, byte_order, &run)) + goto out; + + retval = TRUE; + + out: + data_block_free (&block); + + return retval; +} + +static dbus_bool_t +recursive_marshal_test_iteration (void *data) +{ + int i; + + i = 0; + while (i < 18) + { + if (!perform_all_runs (DBUS_LITTLE_ENDIAN, i)) + return FALSE; + if (!perform_all_runs (DBUS_BIG_ENDIAN, i)) + return FALSE; + if (!perform_all_items (DBUS_LITTLE_ENDIAN, i)) + return FALSE; + if (!perform_all_items (DBUS_BIG_ENDIAN, i)) + return FALSE; + + ++i; + } + + return TRUE; +} + +dbus_bool_t _dbus_marshal_recursive_test (void); + +dbus_bool_t +_dbus_marshal_recursive_test (void) +{ + _dbus_test_oom_handling ("recursive marshaling", + recursive_marshal_test_iteration, + NULL); + + return TRUE; +} + +#if 1 +int +main (int argc, char **argv) +{ + _dbus_marshal_recursive_test (); + + return 0; +} +#endif /* main() */ + +#endif /* DBUS_BUILD_TESTS */ diff --git a/dbus/dbus-marshal-recursive.h b/dbus/dbus-marshal-recursive.h new file mode 100644 index 00000000..19960ec8 --- /dev/null +++ b/dbus/dbus-marshal-recursive.h @@ -0,0 +1,112 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-marshal-recursive.h Marshalling routines for recursive types + * + * Copyright (C) 2004 Red Hat, Inc. + * + * Licensed under the Academic Free License version 2.1 + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef DBUS_MARSHAL_RECURSIVE_H +#define DBUS_MARSHAL_RECURSIVE_H + +#include <config.h> +#include <dbus/dbus-marshal-basic.h> + +#ifndef PACKAGE +#error "config.h not included here" +#endif + +/* Notes on my plan to implement this: + * - also have DBusTypeWriter (heh) + * - TypeReader has accessors for: + * . basic type + * . array of basic type (efficiency hack) + * . another type reader + * - a dict will appear to be a list of string, whatever, string, whatever + * - a variant will contain another TypeReader + * - a struct will be a list of whatever, whatever, whatever + * + * So the basic API usage is to go next, next, next; if the + * item is a basic type or basic array then read the item; + * if it's another type reader then process it; if it's + * a container type (struct, array, variant, dict) then + * recurse. + * + */ + +struct DBusTypeReader +{ + int byte_order; + const DBusString *type_str; + int type_pos; + const DBusString *value_str; + int value_pos; +}; + +typedef struct DBusTypeReader DBusTypeReader; + +struct DBusTypeWriter +{ + int byte_order; + DBusString *type_str; + int type_pos; + DBusString *value_str; + int value_pos; +}; + +typedef struct DBusTypeWriter DBusTypeWriter; + +void _dbus_type_reader_init (DBusTypeReader *reader, + int byte_order, + const DBusString *type_str, + int type_pos, + const DBusString *value_str, + int value_pos); +int _dbus_type_reader_get_value_end (DBusTypeReader *reader); +int _dbus_type_reader_get_type_end (DBusTypeReader *reader); +int _dbus_type_reader_get_current_type (DBusTypeReader *reader); +int _dbus_type_reader_get_array_type (DBusTypeReader *reader); +void _dbus_type_reader_read_basic (DBusTypeReader *reader, + void *value); +dbus_bool_t _dbus_type_reader_read_array (DBusTypeReader *reader, + int type, + void **array, + int *array_len); +void _dbus_type_reader_recurse (DBusTypeReader *reader); +void _dbus_type_reader_unrecurse (DBusTypeReader *reader); +dbus_bool_t _dbus_type_reader_next (DBusTypeReader *reader); + + +void _dbus_type_writer_init (DBusTypeWriter *writer, + int byte_order, + DBusString *type_str, + int type_pos, + DBusString *value_str, + int value_pos); +dbus_bool_t _dbus_type_writer_write_basic (DBusTypeWriter *writer, + int type, + const void *value); +dbus_bool_t _dbus_type_writer_write_array (DBusTypeWriter *writer, + int type, + const void *array, + int array_len); +dbus_bool_t _dbus_type_writer_recurse (DBusTypeWriter *writer, + int container_type); +dbus_bool_t _dbus_type_writer_unrecurse (DBusTypeWriter *writer); + +#endif /* DBUS_MARSHAL_RECURSIVE_H */ diff --git a/dbus/dbus-protocol-new.h b/dbus/dbus-protocol-new.h new file mode 100644 index 00000000..b029f0fb --- /dev/null +++ b/dbus/dbus-protocol-new.h @@ -0,0 +1,180 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-protocol.h D-Bus protocol constants + * + * Copyright (C) 2002, 2003 CodeFactory AB + * Copyright (C) 2004 Red Hat, Inc. + * + * Licensed under the Academic Free License version 2.1 + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef DBUS_PROTOCOL_H +#define DBUS_PROTOCOL_H + +/* Don't include anything in here from anywhere else. It's + * intended for use by any random library. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Message byte order */ +#define DBUS_LITTLE_ENDIAN ('l') /* LSB first */ +#define DBUS_BIG_ENDIAN ('B') /* MSB first */ + +/* Protocol version */ +#define DBUS_MAJOR_PROTOCOL_VERSION 1 + +/* Never a legitimate type */ +#define DBUS_TYPE_INVALID ((int) '\0') + +/* Primitive types */ +#define DBUS_TYPE_BYTE ((int) 'y') +#define DBUS_TYPE_BOOLEAN ((int) 'b') +#define DBUS_TYPE_INT32 ((int) 'i') + +#define DBUS_TYPE_UINT32 ((int) 'u') +#define DBUS_TYPE_INT64 ((int) 'x') +#define DBUS_TYPE_UINT64 ((int) 't') + +#define DBUS_TYPE_DOUBLE ((int) 'd') +#define DBUS_TYPE_STRING ((int) 's') +#define DBUS_TYPE_OBJECT_PATH ((int) 'o') + +/* Compound types */ +#define DBUS_TYPE_ARRAY ((int) 'a') +#define DBUS_TYPE_DICT ((int) 'm') +#define DBUS_TYPE_VARIANT ((int) 'v') + +/* STRUCT is sort of special since its code can't appear in a type string, + * instead DBUS_STRUCT_BEGIN_CHAR has to appear + */ +#define DBUS_TYPE_STRUCT ((int) 'r') + +/* Does not count INVALID */ +#define DBUS_NUMBER_OF_TYPES (13) + +/* characters other than typecodes that appear in type signatures */ +#define DBUS_STRUCT_BEGIN_CHAR ((int) '(') +#define DBUS_STRUCT_END_CHAR ((int) ')') +#define DBUS_NAME_DELIMITER_CHAR ((int) '\'') + +/* Max length in bytes of a service or interface or member name */ +#define DBUS_MAXIMUM_NAME_LENGTH 256 + +/* Max length of a match rule string */ +#define DBUS_MAXIMUM_MATCH_RULE_LENGTH 1024 + +/* Types of message */ +#define DBUS_MESSAGE_TYPE_INVALID 0 +#define DBUS_MESSAGE_TYPE_METHOD_CALL 1 +#define DBUS_MESSAGE_TYPE_METHOD_RETURN 2 +#define DBUS_MESSAGE_TYPE_ERROR 3 +#define DBUS_MESSAGE_TYPE_SIGNAL 4 + +/* Header flags */ +#define DBUS_HEADER_FLAG_NO_REPLY_EXPECTED 0x1 +#define DBUS_HEADER_FLAG_AUTO_ACTIVATION 0x2 + +/* Header fields */ +#define DBUS_HEADER_FIELD_INVALID 0 +#define DBUS_HEADER_FIELD_PATH 1 +#define DBUS_HEADER_FIELD_INTERFACE 2 +#define DBUS_HEADER_FIELD_MEMBER 3 +#define DBUS_HEADER_FIELD_ERROR_NAME 4 +#define DBUS_HEADER_FIELD_REPLY_SERIAL 5 +#define DBUS_HEADER_FIELD_DESTINATION 6 +#define DBUS_HEADER_FIELD_SENDER 7 +#define DBUS_HEADER_FIELD_SIGNATURE 8 + +#define DBUS_HEADER_FIELD_LAST DBUS_HEADER_FIELD_SIGNATURE + +/* Services */ +#define DBUS_SERVICE_ORG_FREEDESKTOP_DBUS "org.freedesktop.DBus" + +/* Paths */ +#define DBUS_PATH_ORG_FREEDESKTOP_DBUS "/org/freedesktop/DBus" +#define DBUS_PATH_ORG_FREEDESKTOP_LOCAL "/org/freedesktop/Local" + +/* Interfaces, these #define don't do much other than + * catch typos at compile time + */ +#define DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS "org.freedesktop.DBus" +#define DBUS_INTERFACE_ORG_FREEDESKTOP_INTROSPECTABLE "org.freedesktop.Introspectable" + +/* This is a special interface whose methods can only be invoked + * by the local implementation (messages from remote apps aren't + * allowed to specify this interface). + */ +#define DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL "org.freedesktop.Local" + +/* Service owner flags */ +#define DBUS_SERVICE_FLAG_PROHIBIT_REPLACEMENT 0x1 +#define DBUS_SERVICE_FLAG_REPLACE_EXISTING 0x2 + +/* Service replies */ +#define DBUS_SERVICE_REPLY_PRIMARY_OWNER 0x1 +#define DBUS_SERVICE_REPLY_IN_QUEUE 0x2 +#define DBUS_SERVICE_REPLY_SERVICE_EXISTS 0x4 +#define DBUS_SERVICE_REPLY_ALREADY_OWNER 0x8 + +/* Activation replies */ +#define DBUS_ACTIVATION_REPLY_ACTIVATED 0x0 +#define DBUS_ACTIVATION_REPLY_ALREADY_ACTIVE 0x1 + +/* Errors */ +/* WARNING these get autoconverted to an enum in dbus-glib.h. Thus, + * if you change the order it breaks the ABI. Keep them in order. + * Also, don't change the formatting since that will break the sed + * script. + */ +#define DBUS_ERROR_FAILED "org.freedesktop.DBus.Error.Failed" +#define DBUS_ERROR_NO_MEMORY "org.freedesktop.DBus.Error.NoMemory" +#define DBUS_ERROR_ACTIVATE_SERVICE_NOT_FOUND "org.freedesktop.DBus.Error.ServiceNotFound" +#define DBUS_ERROR_SERVICE_DOES_NOT_EXIST "org.freedesktop.DBus.Error.ServiceDoesNotExist" +#define DBUS_ERROR_SERVICE_HAS_NO_OWNER "org.freedesktop.DBus.Error.ServiceHasNoOwner" +#define DBUS_ERROR_NO_REPLY "org.freedesktop.DBus.Error.NoReply" +#define DBUS_ERROR_IO_ERROR "org.freedesktop.DBus.Error.IOError" +#define DBUS_ERROR_BAD_ADDRESS "org.freedesktop.DBus.Error.BadAddress" +#define DBUS_ERROR_NOT_SUPPORTED "org.freedesktop.DBus.Error.NotSupported" +#define DBUS_ERROR_LIMITS_EXCEEDED "org.freedesktop.DBus.Error.LimitsExceeded" +#define DBUS_ERROR_ACCESS_DENIED "org.freedesktop.DBus.Error.AccessDenied" +#define DBUS_ERROR_AUTH_FAILED "org.freedesktop.DBus.Error.AuthFailed" +#define DBUS_ERROR_NO_SERVER "org.freedesktop.DBus.Error.NoServer" +#define DBUS_ERROR_TIMEOUT "org.freedesktop.DBus.Error.Timeout" +#define DBUS_ERROR_NO_NETWORK "org.freedesktop.DBus.Error.NoNetwork" +#define DBUS_ERROR_ADDRESS_IN_USE "org.freedesktop.DBus.Error.AddressInUse" +#define DBUS_ERROR_DISCONNECTED "org.freedesktop.DBus.Error.Disconnected" +#define DBUS_ERROR_INVALID_ARGS "org.freedesktop.DBus.Error.InvalidArgs" +#define DBUS_ERROR_FILE_NOT_FOUND "org.freedesktop.DBus.Error.FileNotFound" +#define DBUS_ERROR_UNKNOWN_METHOD "org.freedesktop.DBus.Error.UnknownMethod" +#define DBUS_ERROR_TIMED_OUT "org.freedesktop.DBus.Error.TimedOut" +#define DBUS_ERROR_MATCH_RULE_NOT_FOUND "org.freedesktop.DBus.Error.MatchRuleNotFound" +#define DBUS_ERROR_MATCH_RULE_INVALID "org.freedesktop.DBus.Error.MatchRuleInvalid" +#define DBUS_ERROR_SPAWN_EXEC_FAILED "org.freedesktop.DBus.Error.Spawn.ExecFailed" +#define DBUS_ERROR_SPAWN_FORK_FAILED "org.freedesktop.DBus.Error.Spawn.ForkFailed" +#define DBUS_ERROR_SPAWN_CHILD_EXITED "org.freedesktop.DBus.Error.Spawn.ChildExited" +#define DBUS_ERROR_SPAWN_CHILD_SIGNALED "org.freedesktop.DBus.Error.Spawn.ChildSignaled" +#define DBUS_ERROR_SPAWN_FAILED "org.freedesktop.DBus.Error.Spawn.Failed" +#define DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN "org.freedesktop.DBus.Error.UnixProcessIdUnknown" + +#ifdef __cplusplus +} +#endif + +#endif /* DBUS_PROTOCOL_H */ |