From fddbc09c4a9125fcb168fb31ff300d4132919ea6 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Thu, 27 Jan 2005 23:39:26 +0000 Subject: 2005-01-27 Havoc Pennington * dbus/dbus-message.c: byteswap the message if you init an iterator to read/write from it * dbus/dbus-marshal-byteswap.c: new file implementing _dbus_marshal_byteswap() * dbus/dbus-marshal-basic.c: add _dbus_swap_array() --- dbus/dbus-marshal-byteswap.c | 232 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 232 insertions(+) create mode 100644 dbus/dbus-marshal-byteswap.c (limited to 'dbus/dbus-marshal-byteswap.c') diff --git a/dbus/dbus-marshal-byteswap.c b/dbus/dbus-marshal-byteswap.c new file mode 100644 index 00000000..434d7e4b --- /dev/null +++ b/dbus/dbus-marshal-byteswap.c @@ -0,0 +1,232 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-marshal-byteswap.c Swap a block of marshaled data + * + * Copyright (C) 2005 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-byteswap.h" +#include "dbus-marshal-basic.h" + +/** + * @addtogroup DBusMarshal + * @{ + */ + +static void +byteswap_body_helper (DBusTypeReader *reader, + dbus_bool_t walk_reader_to_end, + int old_byte_order, + int new_byte_order, + unsigned char *p, + unsigned char **new_p) +{ + int current_type; + + while ((current_type = _dbus_type_reader_get_current_type (reader)) != DBUS_TYPE_INVALID) + { + switch (current_type) + { + case DBUS_TYPE_BYTE: + ++p; + break; + + case DBUS_TYPE_BOOLEAN: + case DBUS_TYPE_INT32: + case DBUS_TYPE_UINT32: + { + p = _DBUS_ALIGN_ADDRESS (p, 4); + *((dbus_uint32_t*)p) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)p)); + p += 4; + } + break; + + case DBUS_TYPE_INT64: + case DBUS_TYPE_UINT64: + case DBUS_TYPE_DOUBLE: + { + p = _DBUS_ALIGN_ADDRESS (p, 8); +#ifdef DBUS_HAVE_INT64 + *((dbus_uint64_t*)p) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)p)); +#else + _dbus_swap_array (p, 1, 8); +#endif + p += 8; + } + break; + + case DBUS_TYPE_ARRAY: + case DBUS_TYPE_STRING: + case DBUS_TYPE_OBJECT_PATH: + { + dbus_uint32_t array_len; + + p = _DBUS_ALIGN_ADDRESS (p, 4); + + array_len = _dbus_unpack_uint32 (old_byte_order, p); + + *((dbus_uint32_t*)p) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)p)); + p += 4; + + if (current_type == DBUS_TYPE_ARRAY) + { + int elem_type; + int alignment; + + elem_type = _dbus_type_reader_get_element_type (reader); + alignment = _dbus_type_get_alignment (elem_type); + + p = _DBUS_ALIGN_ADDRESS (p, alignment); + + if (_dbus_type_is_fixed (elem_type)) + { + if (alignment > 1) + _dbus_swap_array (p, array_len / alignment, alignment); + } + else + { + DBusTypeReader sub; + const unsigned char *array_end; + + array_end = p + array_len; + + _dbus_type_reader_recurse (reader, &sub); + + while (p < array_end) + { + byteswap_body_helper (&sub, + FALSE, + old_byte_order, + new_byte_order, + p, &p); + } + } + } + else + { + _dbus_assert (current_type == DBUS_TYPE_STRING || + current_type == DBUS_TYPE_OBJECT_PATH); + + p += (array_len + 1); /* + 1 for nul */ + } + } + break; + + case DBUS_TYPE_SIGNATURE: + { + dbus_uint32_t sig_len; + + sig_len = *p; + + p += (sig_len + 2); /* +2 for len and nul */ + } + break; + + case DBUS_TYPE_VARIANT: + { + /* 1 byte sig len, sig typecodes, align to + * contained-type-boundary, values. + */ + dbus_uint32_t sig_len; + DBusString sig; + DBusTypeReader sub; + int contained_alignment; + + sig_len = *p; + ++p; + + _dbus_string_init_const_len (&sig, p, sig_len); + + p += (sig_len + 1); /* 1 for nul */ + + contained_alignment = _dbus_type_get_alignment (_dbus_first_type_in_signature (&sig, 0)); + + p = _DBUS_ALIGN_ADDRESS (p, contained_alignment); + + _dbus_type_reader_init_types_only (&sub, &sig, 0); + + byteswap_body_helper (&sub, FALSE, old_byte_order, new_byte_order, p, &p); + } + break; + + case DBUS_TYPE_STRUCT: + { + DBusTypeReader sub; + + p = _DBUS_ALIGN_ADDRESS (p, 8); + + _dbus_type_reader_recurse (reader, &sub); + + byteswap_body_helper (&sub, TRUE, old_byte_order, new_byte_order, p, &p); + } + break; + + default: + _dbus_assert_not_reached ("invalid typecode in supposedly-validated signature"); + break; + } + + if (walk_reader_to_end) + _dbus_type_reader_next (reader); + else + break; + } + + if (new_p) + *new_p = p; +} + +/** + * Byteswaps the marshaled data in the given value_str. + * + * @param signature the types in the value_str + * @param signature_start where in signature is the signature + * @param old_byte_order the old byte order + * @param new_byte_order the new byte order + * @param value_str the string containing the body + * @param value_pos where the values start + */ +void +_dbus_marshal_byteswap (const DBusString *signature, + int signature_start, + int old_byte_order, + int new_byte_order, + DBusString *value_str, + int value_pos) +{ + DBusTypeReader reader; + + _dbus_assert (value_pos >= 0); + _dbus_assert (value_pos <= _dbus_string_get_length (value_str)); + + if (old_byte_order == new_byte_order) + return; + + _dbus_type_reader_init_types_only (&reader, + signature, signature_start); + + byteswap_body_helper (&reader, TRUE, + old_byte_order, new_byte_order, + _dbus_string_get_data_len (value_str, value_pos, 0), + NULL); +} + +/** @} */ + +/* Tests in dbus-marshal-byteswap-util.c */ -- cgit