diff --git a/headers/private/app/MessageAdapter.h b/headers/private/app/MessageAdapter.h new file mode 100644 index 0000000000..c2e866606f --- /dev/null +++ b/headers/private/app/MessageAdapter.h @@ -0,0 +1,54 @@ +/* + * Copyright 2007, Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Michael Lotz + */ +#ifndef _MESSAGE_ADAPTER_H_ +#define _MESSAGE_ADAPTER_H_ + +#include +#include + +// message formats +#define MESSAGE_FORMAT_R5 'FOB1' +#define MESSAGE_FORMAT_R5_SWAPPED '1BOF' +#define MESSAGE_FORMAT_DANO 'FOB2' +#define MESSAGE_FORMAT_DANO_SWAPPED '2BOF' +#define MESSAGE_FORMAT_HAIKU '1FMH' +#define MESSAGE_FORMAT_HAIKU_SWAPPED 'HMF1' + +namespace BPrivate { + +class MessageAdapter { +public: +static ssize_t FlattenedSize(uint32 format, const BMessage *from); + +static status_t Flatten(uint32 format, const BMessage *from, + char *buffer, ssize_t *size); +static status_t Flatten(uint32 format, const BMessage *from, + BDataIO *stream, ssize_t *size); + +static status_t Unflatten(uint32 format, BMessage *into, + const char *buffer); +static status_t Unflatten(uint32 format, BMessage *into, + BDataIO *stream); + +private: +static status_t _ConvertKMessage(const KMessage *from, BMessage *to); + +static ssize_t _R5FlattenedSize(const BMessage *from); + +static status_t _FlattenR5Message(uint32 format, const BMessage *from, + char *buffer, ssize_t *size); + +static status_t _UnflattenR5Message(uint32 format, BMessage *into, + BDataIO *stream); +static status_t _UnflattenDanoMessage(uint32 format, BMessage *into, + BDataIO *stream); +}; + +} // namespace BPrivate + +#endif // _MESSAGE_ADAPTER_H_ diff --git a/headers/private/kernel/util/KMessage.h b/headers/private/kernel/util/KMessage.h index 7c811e8a4c..da7f0fb3d4 100644 --- a/headers/private/kernel/util/KMessage.h +++ b/headers/private/kernel/util/KMessage.h @@ -16,6 +16,7 @@ class BMessage; namespace BPrivate { class KMessageField; +class MessageAdapter; // KMessage class KMessage { @@ -102,6 +103,7 @@ public: private: friend class KMessageField; + friend class MessageAdapter; friend class ::BMessage; // not so nice, but makes things easier struct Header { diff --git a/src/kits/app/Jamfile b/src/kits/app/Jamfile index 500c8a88d2..27860a977c 100644 --- a/src/kits/app/Jamfile +++ b/src/kits/app/Jamfile @@ -30,7 +30,6 @@ MergeObject app_kit.o : AreaLink.cpp Cursor.cpp Clipboard.cpp - dano_message.cpp DesktopLink.cpp DirectMessageTarget.cpp Handler.cpp @@ -41,6 +40,7 @@ MergeObject app_kit.o : Looper.cpp LooperList.cpp Message.cpp + MessageAdapter.cpp MessageFilter.cpp MessageQueue.cpp MessageRunner.cpp @@ -48,7 +48,6 @@ MergeObject app_kit.o : MessageUtils.cpp PropertyInfo.cpp PortLink.cpp - r5_message.cpp RegistrarDefs.cpp RegistrarThread.cpp RegistrarThreadManager.cpp diff --git a/src/kits/app/Message.cpp b/src/kits/app/Message.cpp index 4d0adb3367..42a313c174 100644 --- a/src/kits/app/Message.cpp +++ b/src/kits/app/Message.cpp @@ -5,12 +5,8 @@ * Authors: * Michael Lotz */ - - -#include "dano_message.h" -#include "r5_message.h" - #include +#include #include #include @@ -41,14 +37,6 @@ #define DEBUG_FUNCTION_ENTER2 //debug_printf("thread: 0x%x; line: %04ld: func: %s\n", find_thread(NULL), __LINE__, __PRETTY_FUNCTION__); -static const uint32 kMessageMagicR5 = 'FOB1'; -static const uint32 kMessageMagicR5Swapped = '1BOF'; -static const uint32 kMessageMagicDano = 'FOB2'; -static const uint32 kMessageMagicDanoSwapped = '2BOF'; -static const uint32 kMessageMagicHaiku = '1FMH'; -static const uint32 kMessageMagicHaikuSwapped = 'HMF1'; - - const char *B_SPECIFIER_ENTRY = "specifiers"; const char *B_PROPERTY_ENTRY = "property"; const char *B_PROPERTY_NAME_ENTRY = "name"; @@ -56,8 +44,6 @@ const char *B_PROPERTY_NAME_ENTRY = "name"; static status_t handle_reply(port_id replyPort, int32 *pCode, bigtime_t timeout, BMessage *reply); -static status_t convert_message(const KMessage *fromMessage, - BMessage *toMessage); extern "C" { // private os function to set the owning team of an area @@ -77,6 +63,7 @@ BMessage::BMessage() _InitCommon(); } + BMessage::BMessage(BMessage *other) { DEBUG_FUNCTION_ENTER; @@ -84,6 +71,7 @@ BMessage::BMessage(BMessage *other) *this = *other; } + BMessage::BMessage(uint32 _what) { DEBUG_FUNCTION_ENTER; @@ -195,7 +183,7 @@ BMessage::_InitHeader() fHeader = (message_header *)malloc(sizeof(message_header)); memset(fHeader, 0, sizeof(message_header) - sizeof(fHeader->hash_table)); - fHeader->format = kMessageMagicHaiku; + fHeader->format = MESSAGE_FORMAT_HAIKU; fHeader->flags = MESSAGE_FLAG_VALID; fHeader->what = what; fHeader->current_specifier = -1; @@ -379,10 +367,10 @@ BMessage::IsReply() const } -template static uint8 * +template static uint8 * print_to_stream_type(uint8* pointer) { - Type *item = (Type *)pointer; + Type *item = (Type *)pointer; item->PrintToStream(); return (uint8 *)(item+1); } @@ -417,7 +405,7 @@ BMessage::_PrintToStream(const char* indent) const } else printf("0x%lx", what); printf(") {\n"); - + field_header *field = fFields; for (int32 i = 0; i < fHeader->field_count; i++, field++) { value = B_BENDIAN_TO_HOST_INT32(field->type); @@ -473,7 +461,7 @@ BMessage::_PrintToStream(const char* indent) const printf("bool(%s)\n", *((bool *)pointer)!= 0 ? "true" : "false"); pointer += sizeof(bool); break; - + case B_FLOAT_TYPE: pointer = print_type("float(%.4f)\n", pointer); break; @@ -481,27 +469,27 @@ BMessage::_PrintToStream(const char* indent) const case B_DOUBLE_TYPE: pointer = print_type("double(%.8f)\n", pointer); break; - + case B_REF_TYPE: { ssize_t size = *(ssize_t *)pointer; pointer += sizeof(ssize_t); entry_ref ref; BPrivate::entry_ref_unflatten(&ref, (char *)pointer, size); - + printf("entry_ref(device=%ld, directory=%lld, name=\"%s\", ", ref.device, ref.directory, ref.name); - + BPath path(&ref); printf("path=\"%s\")\n", path.Path()); pointer += size; break; } - + case B_MESSAGE_TYPE: { char buffer[1024]; sprintf(buffer, "%s ", indent); - + BMessage message; const ssize_t size = *(const ssize_t *)pointer; pointer += sizeof(ssize_t); @@ -514,7 +502,7 @@ BMessage::_PrintToStream(const char* indent) const pointer += size; break; } - + default: { printf("(type = '%.4s')(size = %ld)\n", (char *)&value, size); } @@ -761,7 +749,7 @@ ssize_t BMessage::FlattenedSize() const { DEBUG_FUNCTION_ENTER; - return BPrivate::r5_message_flattened_size(this); + return BPrivate::MessageAdapter::FlattenedSize(MESSAGE_FORMAT_R5, this); } @@ -769,7 +757,8 @@ status_t BMessage::Flatten(char *buffer, ssize_t size) const { DEBUG_FUNCTION_ENTER; - return BPrivate::flatten_r5_message(this, buffer, size); + return BPrivate::MessageAdapter::Flatten(MESSAGE_FORMAT_R5, this, buffer, + &size); } @@ -777,7 +766,8 @@ status_t BMessage::Flatten(BDataIO *stream, ssize_t *size) const { DEBUG_FUNCTION_ENTER; - return BPrivate::flatten_r5_message(this, stream, size); + return BPrivate::MessageAdapter::Flatten(MESSAGE_FORMAT_R5, this, stream, + size); } @@ -801,8 +791,6 @@ BMessage::_NativeFlatten(char *buffer, ssize_t size) const /* we have to sync the what code as it is a public member */ fHeader->what = what; - //fHeader->fields_checksum = BPrivate::CalculateChecksum((uint8 *)fFields, fHeader->fields_size); - //fHeader->data_checksum = BPrivate::CalculateChecksum((uint8 *)fData, fHeader->data_size); memcpy(buffer, fHeader, min_c(sizeof(message_header), (size_t)size)); buffer += sizeof(message_header); @@ -832,8 +820,6 @@ BMessage::_NativeFlatten(BDataIO *stream, ssize_t *size) const /* we have to sync the what code as it is a public member */ fHeader->what = what; - //fHeader->fields_checksum = BPrivate::CalculateChecksum((uint8 *)fFields, fHeader->fields_size); - //fHeader->data_checksum = BPrivate::CalculateChecksum((uint8 *)fData, fHeader->data_size); ssize_t result1 = stream->Write(fHeader, sizeof(message_header)); if (result1 != sizeof(message_header)) @@ -962,6 +948,15 @@ BMessage::_Reference(message_header *header) fFields = (field_header *)address; address += fHeader->fields_size; fData = address; + + if (fHeader->fields_checksum != BPrivate::CalculateChecksum((uint8 *)fFields, fHeader->fields_size) + || fHeader->data_checksum != BPrivate::CalculateChecksum((uint8 *)fData, fHeader->data_size)) { + debug_printf("checksum mismatch\n"); + _Clear(); + _InitHeader(); + return B_BAD_VALUE; + } + return B_OK; } @@ -1017,33 +1012,8 @@ BMessage::Unflatten(const char *flatBuffer) return B_BAD_VALUE; uint32 format = *(uint32 *)flatBuffer; - if (format != kMessageMagicHaiku) { - if (format == KMessage::kMessageHeaderMagic) { - KMessage message; - status_t result = message.SetTo(flatBuffer, - ((KMessage::Header*)flatBuffer)->size); - if (result != B_OK) - return result; - - return convert_message(&message, this); - } - - try { - if (format == kMessageMagicR5 || format == kMessageMagicR5Swapped) - return BPrivate::unflatten_r5_message(format, this, flatBuffer); - - if (format == kMessageMagicDano || format == kMessageMagicDanoSwapped) { - BMemoryIO stream(flatBuffer + sizeof(uint32), - BPrivate::dano_message_flattened_size(flatBuffer)); - return BPrivate::unflatten_dano_message(format, stream, *this); - } - } catch (status_t error) { - MakeEmpty(); - return error; - } - - return B_NOT_A_MESSAGE; - } + if (format != MESSAGE_FORMAT_HAIKU) + return BPrivate::MessageAdapter::Unflatten(format, this, flatBuffer); // native message unflattening @@ -1056,7 +1026,7 @@ BMessage::Unflatten(const char *flatBuffer) memcpy(fHeader, flatBuffer, sizeof(message_header)); flatBuffer += sizeof(message_header); - if (fHeader->format != kMessageMagicHaiku + if (fHeader->format != MESSAGE_FORMAT_HAIKU || !(fHeader->flags & MESSAGE_FLAG_VALID)) { free(fHeader); fHeader = NULL; @@ -1093,14 +1063,6 @@ BMessage::Unflatten(const char *flatBuffer) } } - /*if (fHeader->fields_checksum != BPrivate::CalculateChecksum((uint8 *)fFields, fHeader->fields_size) - || fHeader->data_checksum != BPrivate::CalculateChecksum((uint8 *)fData, fHeader->data_size)) { - debug_printf("checksum mismatch 1\n"); - _Clear(); - _InitHeader(); - return B_BAD_VALUE; - }*/ - return B_OK; } @@ -1114,20 +1076,8 @@ BMessage::Unflatten(BDataIO *stream) uint32 format = 0; stream->Read(&format, sizeof(uint32)); - if (format != kMessageMagicHaiku) { - try { - if (format == kMessageMagicR5 || format == kMessageMagicR5Swapped) - return BPrivate::unflatten_r5_message(format, this, stream); - - if (format == kMessageMagicDano || format == kMessageMagicDanoSwapped) - return BPrivate::unflatten_dano_message(format, *stream, *this); - } catch (status_t error) { - MakeEmpty(); - return error; - } - - return B_NOT_A_MESSAGE; - } + if (format != MESSAGE_FORMAT_HAIKU) + return BPrivate::MessageAdapter::Unflatten(format, this, stream); // native message unflattening @@ -1143,7 +1093,7 @@ BMessage::Unflatten(BDataIO *stream) sizeof(message_header) - sizeof(uint32)); result -= sizeof(message_header) - sizeof(uint32); - if (result != B_OK || fHeader->format != kMessageMagicHaiku + if (result != B_OK || fHeader->format != MESSAGE_FORMAT_HAIKU || !(fHeader->flags & MESSAGE_FLAG_VALID)) { free(fHeader); fHeader = NULL; @@ -1184,14 +1134,6 @@ BMessage::Unflatten(BDataIO *stream) return B_BAD_VALUE; } - /*if (fHeader->fields_checksum != BPrivate::CalculateChecksum((uint8 *)fFields, fHeader->fields_size) - || fHeader->data_checksum != BPrivate::CalculateChecksum((uint8 *)fData, fHeader->data_size)) { - debug_printf("checksum mismatch 2\n"); - _Clear(); - _InitHeader(); - return B_BAD_VALUE; - }*/ - return B_OK; } @@ -1329,7 +1271,7 @@ BMessage::GetCurrentSpecifier(int32 *index, BMessage *specifier, int32 *what, } } - return B_OK; + return B_OK; } @@ -1887,7 +1829,7 @@ BMessage::_SendMessage(port_id port, team_id portOwner, int32 token, port_info info; get_port_info(port, &info); void *address = NULL; - _kern_transfer_area(header->shared_area, &address, B_ANY_ADDRESS, + _kern_transfer_area(header->shared_area, &address, B_ANY_ADDRESS, info.team); #endif } else { @@ -2075,11 +2017,11 @@ BMessage::_SendFlattenedMessage(void *data, int32 size, port_id port, uint32 magic = *(uint32 *)data; - if (magic == kMessageMagicHaiku || magic == kMessageMagicHaikuSwapped) { + if (magic == MESSAGE_FORMAT_HAIKU || magic == MESSAGE_FORMAT_HAIKU_SWAPPED) { message_header *header = (message_header *)data; header->target = token; header->flags |= MESSAGE_FLAG_WAS_DELIVERED; - } else if (magic == kMessageMagicR5) { + } else if (magic == MESSAGE_FORMAT_R5) { uint8 *header = (uint8 *)data; header += sizeof(uint32) /* magic */ + sizeof(uint32) /* checksum */ + sizeof(ssize_t) /* flattenedSize */ + sizeof(int32) /* what */ @@ -2134,63 +2076,6 @@ handle_reply(port_id replyPort, int32 *_code, bigtime_t timeout, } -static status_t -convert_message(const KMessage *fromMessage, BMessage *toMessage) -{ - DEBUG_FUNCTION_ENTER2; - if (!fromMessage || !toMessage) - return B_BAD_VALUE; - - // make empty and init what of the target message - toMessage->MakeEmpty(); - toMessage->what = fromMessage->What(); - - BMessage::Private toPrivate(toMessage); - toPrivate.SetTarget(fromMessage->TargetToken()); - toPrivate.SetReply(B_SYSTEM_TEAM, fromMessage->ReplyPort(), - fromMessage->ReplyToken()); - - // iterate through the fields and import them in the target message - KMessageField field; - while (fromMessage->GetNextField(&field) == B_OK) { - int32 elementCount = field.CountElements(); - if (elementCount > 0) { - for (int32 i = 0; i < elementCount; i++) { - int32 size; - const void *data = field.ElementAt(i, &size); - status_t result; - - if (field.TypeCode() == B_MESSAGE_TYPE) { - // message type: if it's a KMessage, convert it - KMessage message; - if (message.SetTo(data, size) == B_OK) { - BMessage bMessage; - result = convert_message(&message, &bMessage); - if (result < B_OK) - return result; - - result = toMessage->AddMessage(field.Name(), &bMessage); - } else { - // just add it - result = toMessage->AddData(field.Name(), - field.TypeCode(), data, size, - field.HasFixedElementSize(), 1); - } - } else { - result = toMessage->AddData(field.Name(), field.TypeCode(), - data, size, field.HasFixedElementSize(), 1); - } - - if (result < B_OK) - return result; - } - } - } - - return B_OK; -} - - void BMessage::_ReservedMessage1(void) {}; void BMessage::_ReservedMessage2(void) {}; void BMessage::_ReservedMessage3(void) {}; diff --git a/src/kits/app/MessageAdapter.cpp b/src/kits/app/MessageAdapter.cpp new file mode 100644 index 0000000000..c6dc3a8f9d --- /dev/null +++ b/src/kits/app/MessageAdapter.cpp @@ -0,0 +1,772 @@ +/* + * Copyright 2005-2007, Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Axel Dörfler, axeld@pinc-software.de + * Michael Lotz + */ +#include +#include +#include + +namespace BPrivate { + +#define R5_MESSAGE_FLAG_VALID 0x01 +#define R5_MESSAGE_FLAG_INCLUDE_TARGET 0x02 +#define R5_MESSAGE_FLAG_INCLUDE_REPLY 0x04 +#define R5_MESSAGE_FLAG_SCRIPT_MESSAGE 0x08 + +#define R5_FIELD_FLAG_VALID 0x01 +#define R5_FIELD_FLAG_MINI_DATA 0x02 +#define R5_FIELD_FLAG_FIXED_SIZE 0x04 +#define R5_FIELD_FLAG_SINGLE_ITEM 0x08 + + +enum { + SECTION_MESSAGE_HEADER = 'FOB2', + SECTION_OFFSET_TABLE = 'STof', + SECTION_TARGET_INFORMATION = 'ENwh', + SECTION_SINGLE_ITEM_DATA = 'SGDa', + SECTION_FIXED_SIZE_ARRAY_DATA = 'FADa', + SECTION_VARIABLE_SIZE_ARRAY_DATA = 'VADa', + SECTION_SORTED_INDEX_TABLE = 'DXIn', + SECTION_END_OF_DATA = 'DDEn' +}; + + +struct r5_message_header { + uint32 magic; + uint32 checksum; + ssize_t flattened_size; + int32 what; + uint8 flags; +} _PACKED; + +struct dano_section_header { + uint32 code; + ssize_t size; + uint8 data[0]; +} _PACKED; + +struct dano_message_header { + int32 what; + int32 padding; +} _PACKED; + +typedef struct offset_table_s { + int32 indexTable; + int32 endOfData; + int64 padding; +} OffsetTable; + +struct dano_single_item { + type_code type; + ssize_t item_size; + uint8 name_length; + char name[0]; +} _PACKED; + +struct dano_fixed_size_array { + type_code type; + ssize_t size_per_item; + uint8 name_length; + char name[0]; +} _PACKED; + + +struct dano_variable_size_array { + type_code type; + int32 padding; + uint8 name_length; + char name[0]; +} _PACKED; + + +inline int32 +pad_to_8(int32 value) +{ + return (value + 7) & ~7; +} + + +ssize_t +MessageAdapter::FlattenedSize(uint32 format, const BMessage *from) +{ + switch (format) { + case MESSAGE_FORMAT_R5: + case MESSAGE_FORMAT_R5_SWAPPED: + return _R5FlattenedSize(from); + } + + return -1; +} + + +status_t +MessageAdapter::Flatten(uint32 format, const BMessage *from, char *buffer, + ssize_t *size) +{ + switch (format) { + case MESSAGE_FORMAT_R5: + case MESSAGE_FORMAT_R5_SWAPPED: + return _FlattenR5Message(format, from, buffer, size); + } + + return B_ERROR; +} + + +status_t +MessageAdapter::Flatten(uint32 format, const BMessage *from, BDataIO *stream, + ssize_t *size) +{ + switch (format) { + case MESSAGE_FORMAT_R5: + case MESSAGE_FORMAT_R5_SWAPPED: + { + ssize_t flattenedSize = _R5FlattenedSize(from); + char *buffer = (char *)malloc(flattenedSize); + if (!buffer) + return B_NO_MEMORY; + + status_t result = _FlattenR5Message(format, from, buffer, + &flattenedSize); + if (result < B_OK) { + free(buffer); + return result; + } + + ssize_t written = stream->Write(buffer, flattenedSize); + if (written != flattenedSize) { + free(buffer); + return (written >= 0 ? B_ERROR : written); + } + + if (size) + *size = flattenedSize; + + free(buffer); + return B_OK; + } + } + + return B_ERROR; +} + + +status_t +MessageAdapter::Unflatten(uint32 format, BMessage *into, const char *buffer) +{ + if (format == KMessage::kMessageHeaderMagic) { + KMessage message; + status_t result = message.SetTo(buffer, + ((KMessage::Header *)buffer)->size); + if (result != B_OK) + return result; + + return _ConvertKMessage(&message, into); + } + + try { + switch (format) { + case MESSAGE_FORMAT_R5: + case MESSAGE_FORMAT_R5_SWAPPED: + { + r5_message_header *header = (r5_message_header *)buffer; + BMemoryIO stream(buffer + sizeof(uint32), + header->flattened_size - sizeof(uint32)); + return _UnflattenR5Message(format, into, &stream); + } + + case MESSAGE_FORMAT_DANO: + case MESSAGE_FORMAT_DANO_SWAPPED: + { + dano_section_header *header = (dano_section_header *)buffer; + ssize_t size = header->size; + if (header->code == MESSAGE_FORMAT_DANO_SWAPPED) + size = __swap_int32(size); + + BMemoryIO stream(buffer + sizeof(uint32), size - sizeof(uint32)); + return _UnflattenDanoMessage(format, into, &stream); + } + } + } catch (status_t error) { + into->MakeEmpty(); + return error; + } + + return B_NOT_A_MESSAGE; +} + + +status_t +MessageAdapter::Unflatten(uint32 format, BMessage *into, BDataIO *stream) +{ + try { + switch (format) { + case MESSAGE_FORMAT_R5: + case MESSAGE_FORMAT_R5_SWAPPED: + return _UnflattenR5Message(format, into, stream); + + case MESSAGE_FORMAT_DANO: + case MESSAGE_FORMAT_DANO_SWAPPED: + return _UnflattenDanoMessage(format, into, stream); + } + } catch (status_t error) { + into->MakeEmpty(); + return error; + } + + return B_NOT_A_MESSAGE; +} + + +status_t +MessageAdapter::_ConvertKMessage(const KMessage *fromMessage, + BMessage *toMessage) +{ + if (!fromMessage || !toMessage) + return B_BAD_VALUE; + + // make empty and init what of the target message + toMessage->MakeEmpty(); + toMessage->what = fromMessage->What(); + + BMessage::Private toPrivate(toMessage); + toPrivate.SetTarget(fromMessage->TargetToken()); + toPrivate.SetReply(B_SYSTEM_TEAM, fromMessage->ReplyPort(), + fromMessage->ReplyToken()); + + // iterate through the fields and import them in the target message + KMessageField field; + while (fromMessage->GetNextField(&field) == B_OK) { + int32 elementCount = field.CountElements(); + if (elementCount > 0) { + for (int32 i = 0; i < elementCount; i++) { + int32 size; + const void *data = field.ElementAt(i, &size); + status_t result; + + if (field.TypeCode() == B_MESSAGE_TYPE) { + // message type: if it's a KMessage, convert it + KMessage message; + if (message.SetTo(data, size) == B_OK) { + BMessage bMessage; + result = _ConvertKMessage(&message, &bMessage); + if (result < B_OK) + return result; + + result = toMessage->AddMessage(field.Name(), &bMessage); + } else { + // just add it + result = toMessage->AddData(field.Name(), + field.TypeCode(), data, size, + field.HasFixedElementSize(), 1); + } + } else { + result = toMessage->AddData(field.Name(), field.TypeCode(), + data, size, field.HasFixedElementSize(), 1); + } + + if (result < B_OK) + return result; + } + } + } + + return B_OK; +} + + +ssize_t +MessageAdapter::_R5FlattenedSize(const BMessage *from) +{ + BMessage::Private messagePrivate((BMessage *)from); + BMessage::message_header* header = messagePrivate.GetMessageHeader(); + + // header size (variable, depending on the flags) + + ssize_t flattenedSize = sizeof(r5_message_header); + + if (header->target != B_NULL_TOKEN) + flattenedSize += sizeof(int32); + + if (header->reply_port >= 0 && header->reply_target != B_NULL_TOKEN + && header->reply_team >= 0) { + // reply info + big flags + flattenedSize += sizeof(port_id) + sizeof(int32) + sizeof(team_id) + 4; + } + + // field size + + uint8 *data = messagePrivate.GetMessageData(); + BMessage::field_header *field = messagePrivate.GetMessageFields(); + for (int32 i = 0; i < header->field_count; i++, field++) { + // flags and type + flattenedSize += 1 + sizeof(type_code); + +#if 0 + bool miniData = field->dataSize <= 255 && field->count <= 255; +#else + // ToDo: we don't know the R5 dataSize yet (padding) + bool miniData = false; +#endif + + // item count + if (field->count > 1) + flattenedSize += (miniData ? sizeof(uint8) : sizeof(uint32)); + + // data size + flattenedSize += (miniData ? sizeof(uint8) : sizeof(size_t)); + + // name length and name + flattenedSize += 1 + min_c(field->name_length - 1, 255); + + // data + if (field->flags & FIELD_FLAG_FIXED_SIZE) + flattenedSize += field->data_size; + else { + uint8 *source = data + field->offset + field->name_length; + + for (int32 i = 0; i < field->count; i++) { + ssize_t itemSize = *(ssize_t *)source + sizeof(ssize_t); + flattenedSize += pad_to_8(itemSize); + source += itemSize; + } + } + } + + // pseudo field with flags 0 + return flattenedSize + 1; +} + + +status_t +MessageAdapter::_FlattenR5Message(uint32 format, const BMessage *from, + char *buffer, ssize_t *size) +{ + BMessage::Private messagePrivate((BMessage *)from); + BMessage::message_header *header = messagePrivate.GetMessageHeader(); + uint8 *data = messagePrivate.GetMessageData(); + + r5_message_header *r5header = (r5_message_header *)buffer; + uint8 *pointer = (uint8 *)buffer + sizeof(r5_message_header); + + r5header->magic = MESSAGE_FORMAT_R5; + r5header->what = from->what; + r5header->checksum = 0; + + uint8 flags = R5_MESSAGE_FLAG_VALID; + if (header->target != B_NULL_TOKEN) { + *(int32 *)pointer = header->target; + pointer += sizeof(int32); + flags |= R5_MESSAGE_FLAG_INCLUDE_TARGET; + } + + if (header->reply_port >= 0 && header->reply_target != B_NULL_TOKEN + && header->reply_team >= 0) { + // reply info + *(port_id *)pointer = header->reply_port; + pointer += sizeof(port_id); + *(int32 *)pointer = header->reply_target; + pointer += sizeof(int32); + *(team_id *)pointer = header->reply_team; + pointer += sizeof(team_id); + + // big flags + *pointer = (header->reply_target == B_PREFERRED_TOKEN ? 1 : 0); + pointer++; + + *pointer = (header->flags & MESSAGE_FLAG_REPLY_REQUIRED ? 1 : 0); + pointer++; + + *pointer = (header->flags & MESSAGE_FLAG_REPLY_DONE ? 1 : 0); + pointer++; + + *pointer = (header->flags & MESSAGE_FLAG_IS_REPLY ? 1 : 0); + pointer++; + + flags |= R5_MESSAGE_FLAG_INCLUDE_REPLY; + } + + if (header->flags & MESSAGE_FLAG_HAS_SPECIFIERS) + flags |= R5_MESSAGE_FLAG_SCRIPT_MESSAGE; + + r5header->flags = flags; + + // store the header size - used for the checksum later + ssize_t headerSize = (uint32)pointer - (uint32)buffer; + + // collect and add the data + BMessage::field_header *field = messagePrivate.GetMessageFields(); + for (int32 i = 0; i < header->field_count; i++, field++) { + flags = R5_FIELD_FLAG_VALID; + + if (field->count == 1) + flags |= R5_FIELD_FLAG_SINGLE_ITEM; + // ToDo: we don't really know the data size now (padding missing) + if (field->data_size <= 255 && field->count <= 255) + ;//flags |= R5_FIELD_FLAG_MINI_DATA; + if (field->flags & FIELD_FLAG_FIXED_SIZE) + flags |= R5_FIELD_FLAG_FIXED_SIZE; + + *pointer = flags; + pointer++; + + *(type_code *)pointer = field->type; + pointer += sizeof(type_code); + + if (!(flags & R5_FIELD_FLAG_SINGLE_ITEM)) { + if (flags & R5_FIELD_FLAG_MINI_DATA) { + *pointer = (uint8)field->count; + pointer++; + } else { + *(int32 *)pointer = field->count; + pointer += sizeof(int32); + } + } + + // we may have to adjust this to account for padding later + uint8 *fieldSize = pointer; + if (flags & R5_FIELD_FLAG_MINI_DATA) { + *pointer = (uint8)field->data_size; + pointer++; + } else { + *(ssize_t *)pointer = field->data_size; + pointer += sizeof(ssize_t); + } + + // name + int32 nameLength = min_c(field->name_length - 1, 255); + *pointer = (uint8)nameLength; + pointer++; + + strncpy((char *)pointer, (char *)data + field->offset, nameLength); + pointer += nameLength; + + // data + uint8 *source = data + field->offset + field->name_length; + if (flags & R5_FIELD_FLAG_FIXED_SIZE) { + memcpy(pointer, source, field->data_size); + pointer += field->data_size; + } else { + uint8 *previous = pointer; + for (int32 i = 0; i < field->count; i++) { + ssize_t itemSize = *(ssize_t *)source + sizeof(ssize_t); + memcpy(pointer, source, itemSize); + pointer += pad_to_8(itemSize); + source += itemSize; + } + + // adjust the field size to the padded value + if (flags & R5_FIELD_FLAG_MINI_DATA) + *fieldSize = (uint8)(pointer - previous); + else + *(ssize_t *)fieldSize = (pointer - previous); + } + } + + // terminate the fields with a pseudo field with flags 0 (not valid) + *pointer = 0; + pointer++; + + // calculate the flattened size from the pointers + r5header->flattened_size = (uint32)pointer - (uint32)buffer; + r5header->checksum = CalculateChecksum((uint8 *)(buffer + 8), + headerSize - 8); + + if (size) + *size = r5header->flattened_size; + + return B_OK; +} + + +status_t +MessageAdapter::_UnflattenR5Message(uint32 format, BMessage *into, + BDataIO *stream) +{ + into->MakeEmpty(); + + BMessage::Private messagePrivate(into); + BMessage::message_header *header = messagePrivate.GetMessageHeader(); + + TReadHelper reader(stream); + if (format == MESSAGE_FORMAT_R5_SWAPPED) + reader.SetSwap(true); + + // the stream is already advanced by the size of the "format" + r5_message_header r5header; + reader(((uint8 *)&r5header) + sizeof(uint32), + sizeof(r5header) - sizeof(uint32)); + + header->what = into->what = r5header.what; + if (r5header.flags & R5_MESSAGE_FLAG_INCLUDE_TARGET) + reader(header->target); + + if (r5header.flags & R5_MESSAGE_FLAG_INCLUDE_REPLY) { + // reply info + reader(header->reply_port); + reader(header->reply_target); + reader(header->reply_team); + + // big flags + uint8 bigFlag; + reader(bigFlag); + if (bigFlag) + header->reply_target = B_PREFERRED_TOKEN; + + reader(bigFlag); + if (bigFlag) + header->flags |= MESSAGE_FLAG_REPLY_REQUIRED; + + reader(bigFlag); + if (bigFlag) + header->flags |= MESSAGE_FLAG_REPLY_DONE; + + reader(bigFlag); + if (bigFlag) + header->flags |= MESSAGE_FLAG_IS_REPLY; + } + + if (r5header.flags & R5_MESSAGE_FLAG_SCRIPT_MESSAGE) + header->flags |= MESSAGE_FLAG_HAS_SPECIFIERS; + + uint8 flags; + reader(flags); + while (flags & R5_FIELD_FLAG_VALID) { + bool fixedSize = flags & R5_FIELD_FLAG_FIXED_SIZE; + bool miniData = flags & R5_FIELD_FLAG_MINI_DATA; + bool singleItem = flags & R5_FIELD_FLAG_SINGLE_ITEM; + + type_code type; + reader(type); + + int32 itemCount; + if (!singleItem) { + if (miniData) { + uint8 miniCount; + reader(miniCount); + itemCount = miniCount; + } else + reader(itemCount); + } else + itemCount = 1; + + ssize_t dataSize; + if (miniData) { + uint8 miniSize; + reader(miniSize); + dataSize = miniSize; + } else + reader(dataSize); + + if (dataSize <= 0) + return B_ERROR; + + // name + uint8 nameLength; + reader(nameLength); + + char nameBuffer[256]; + reader(nameBuffer, nameLength); + nameBuffer[nameLength] = '\0'; + + uint8 *buffer = (uint8 *)malloc(dataSize); + uint8 *pointer = buffer; + reader(buffer, dataSize); + + status_t result = B_OK; + ssize_t itemSize = 0; + if (fixedSize) + itemSize = dataSize / itemCount; + + for (int32 i = 0; i < itemCount; i++) { + if (!fixedSize) { + itemSize = *(ssize_t *)pointer; + pointer += sizeof(ssize_t); + } + + result = into->AddData(nameBuffer, type, pointer, itemSize, + fixedSize, itemCount); + + if (result < B_OK) { + free(buffer); + return result; + } + + if (fixedSize) + pointer += itemSize; + else + pointer += pad_to_8(itemSize + sizeof(ssize_t)) - sizeof(ssize_t); + } + + free(buffer); + + // flags of next field or termination byte + reader(flags); + } + + return B_OK; +} + + +status_t +MessageAdapter::_UnflattenDanoMessage(uint32 format, BMessage *into, + BDataIO *stream) +{ + into->MakeEmpty(); + + TReadHelper reader(stream); + if (format == MESSAGE_FORMAT_DANO_SWAPPED) + reader.SetSwap(true); + + ssize_t size; + reader(size); + + dano_message_header header; + reader(header); + into->what = header.what; + + size -= sizeof(dano_section_header) + sizeof(dano_message_header); + int32 offset = 0; + + while (offset < size) { + dano_section_header sectionHeader; + reader(sectionHeader); + + // be safe. this shouldn't be necessary but in some testcases it was. + sectionHeader.size = pad_to_8(sectionHeader.size); + + if (offset + sectionHeader.size > size || sectionHeader.size < 0) + return B_BAD_DATA; + + ssize_t fieldSize = sectionHeader.size - sizeof(dano_section_header); + uint8 *fieldBuffer = NULL; + if (fieldSize > 0) { + // there may be no data. we shouldn't fail because of that + fieldBuffer = (uint8 *)malloc(fieldSize); + if (fieldBuffer == NULL) + throw (status_t)B_NO_MEMORY; + + reader(fieldBuffer, fieldSize); + } + + switch (sectionHeader.code) { + case SECTION_OFFSET_TABLE: + case SECTION_TARGET_INFORMATION: + case SECTION_SORTED_INDEX_TABLE: + case SECTION_END_OF_DATA: + // discard + break; + + case SECTION_SINGLE_ITEM_DATA: { + dano_single_item *field = (dano_single_item *)fieldBuffer; + + int32 dataOffset = sizeof(dano_single_item) + + field->name_length + 1; + dataOffset = pad_to_8(dataOffset); + + if (offset + dataOffset + field->item_size > size) + return B_BAD_DATA; + + // support for fixed size is not possible with a single item + bool fixedSize = false; + switch (field->type) { + case B_RECT_TYPE: + case B_POINT_TYPE: + case B_INT8_TYPE: + case B_INT16_TYPE: + case B_INT32_TYPE: + case B_INT64_TYPE: + case B_BOOL_TYPE: + case B_FLOAT_TYPE: + case B_DOUBLE_TYPE: + case B_POINTER_TYPE: + case B_MESSENGER_TYPE: + fixedSize = true; + break; + default: + break; + } + + status_t result = into->AddData(field->name, field->type, + fieldBuffer + dataOffset, field->item_size, fixedSize); + + if (result < B_OK) { + free(fieldBuffer); + throw result; + } + break; + } + + case SECTION_FIXED_SIZE_ARRAY_DATA: { + dano_fixed_size_array *field + = (dano_fixed_size_array *)fieldBuffer; + + int32 dataOffset = sizeof(dano_fixed_size_array) + + field->name_length + 1; + dataOffset = pad_to_8(dataOffset); + int32 count = *(int32 *)(fieldBuffer + dataOffset); + dataOffset += 8; /* count and padding */ + + if (offset + dataOffset + count * field->size_per_item > size) + return B_BAD_DATA; + + status_t result = B_OK; + for (int32 i = 0; i < count; i++) { + result = into->AddData(field->name, field->type, + fieldBuffer + dataOffset, field->size_per_item, true, + count); + + if (result < B_OK) { + free(fieldBuffer); + throw result; + } + + dataOffset += field->size_per_item; + } + break; + } + + case SECTION_VARIABLE_SIZE_ARRAY_DATA: { + dano_variable_size_array *field + = (dano_variable_size_array *)fieldBuffer; + + int32 dataOffset = sizeof(dano_variable_size_array) + + field->name_length + 1; + dataOffset = pad_to_8(dataOffset); + int32 count = *(int32 *)(fieldBuffer + dataOffset); + dataOffset += sizeof(int32); + ssize_t totalSize = *(ssize_t *)(fieldBuffer + dataOffset); + dataOffset += sizeof(ssize_t); + + int32 *endPoints = (int32 *)(fieldBuffer + dataOffset + + totalSize); + + status_t result = B_OK; + for (int32 i = 0; i < count; i++) { + int32 itemOffset = (i > 0 ? pad_to_8(endPoints[i - 1]) : 0); + + result = into->AddData(field->name, field->type, + fieldBuffer + dataOffset + itemOffset, + endPoints[i] - itemOffset, false, count); + + if (result < B_OK) { + free(fieldBuffer); + throw result; + } + } + break; + } + } + + free(fieldBuffer); + offset += sectionHeader.size; + } + + return B_OK; +} + +} // namespace BPrivate diff --git a/src/kits/app/dano_message.cpp b/src/kits/app/dano_message.cpp deleted file mode 100644 index c21ef67356..0000000000 --- a/src/kits/app/dano_message.cpp +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright 2005-2006, Haiku. - * Distributed under the terms of the MIT License. - * - * Authors: - * Axel Dörfler, axeld@pinc-software.de - * Michael Lotz, mmlr@mlotz.ch - */ - - -#include "dano_message.h" - -#include - -#include -#include -#include - - -enum { - SECTION_MESSAGE_HEADER = 'FOB2', - SECTION_OFFSET_TABLE = 'STof', - SECTION_TARGET_INFORMATION = 'ENwh', - SECTION_SINGLE_ITEM_DATA = 'SGDa', - SECTION_FIXED_SIZE_ARRAY_DATA = 'FADa', - SECTION_VARIABLE_SIZE_ARRAY_DATA = 'VADa', - SECTION_SORTED_INDEX_TABLE = 'DXIn', - SECTION_END_OF_DATA = 'DDEn' -}; - - -struct section_header { - uint32 code; - ssize_t size; - uint8 data[0]; -} _PACKED; - -struct message_header { - int32 what; - int32 padding; -} _PACKED; - -typedef struct offset_table_s { - int32 indexTable; - int32 endOfData; - int64 padding; -} OffsetTable; - -struct single_item { - type_code type; - ssize_t item_size; - uint8 name_length; - char name[0]; -} _PACKED; - -struct fixed_size_array { - type_code type; - ssize_t size_per_item; - uint8 name_length; - char name[0]; -} _PACKED; - - -struct variable_size_array { - type_code type; - int32 padding; - uint8 name_length; - char name[0]; -} _PACKED; - - -static const uint32 kMessageFormatSwapped = '2BOF'; - - -inline int32 -pad_to_8(int32 value) -{ - return (value + 7) & ~7; -} - - -ssize_t -BPrivate::dano_message_flattened_size(const char *buffer) -{ - section_header *header = (section_header *)buffer; - - // The size contains the message format that won't be part of - // the buffer unflatten_dano_message() will get - - if (header->code == kMessageFormatSwapped) - return __swap_int32(header->size) - sizeof(header->code); - - return header->size - sizeof(header->code); -} - - -status_t -BPrivate::unflatten_dano_message(uint32 format, BDataIO &stream, - BMessage &message) -{ - TReadHelper reader(&stream); - message.MakeEmpty(); - - if (format == kMessageFormatSwapped) - reader.SetSwap(true); - - ssize_t size; - reader(size); - - message_header header; - reader(header); - message.what = header.what; - - size -= sizeof(section_header) + sizeof(message_header); - int32 offset = 0; - - while (offset < size) { - section_header sectionHeader; - reader(sectionHeader); - - // be safe. this shouldn't be necessary but in some testcases it was. - sectionHeader.size = pad_to_8(sectionHeader.size); - - if (offset + sectionHeader.size > size || sectionHeader.size < 0) - return B_BAD_DATA; - - ssize_t fieldSize = sectionHeader.size - sizeof(section_header); - uint8 *fieldBuffer = NULL; - if (fieldSize > 0) { - // there may be no data. we shouldn't fail because of that - fieldBuffer = (uint8 *)malloc(fieldSize); - if (fieldBuffer == NULL) - throw (status_t)B_NO_MEMORY; - - reader(fieldBuffer, fieldSize); - } - - switch (sectionHeader.code) { - case SECTION_OFFSET_TABLE: - case SECTION_TARGET_INFORMATION: - case SECTION_SORTED_INDEX_TABLE: - case SECTION_END_OF_DATA: - // discard - break; - - case SECTION_SINGLE_ITEM_DATA: { - single_item *field = (single_item *)fieldBuffer; - - int32 dataOffset = sizeof(single_item) + field->name_length + 1; - dataOffset = pad_to_8(dataOffset); - - if (offset + dataOffset + field->item_size > size) - return B_BAD_DATA; - - // support for fixed size is not possible with a single item - bool fixedSize = false; - switch (field->type) { - case B_RECT_TYPE: - case B_POINT_TYPE: - case B_INT8_TYPE: - case B_INT16_TYPE: - case B_INT32_TYPE: - case B_INT64_TYPE: - case B_BOOL_TYPE: - case B_FLOAT_TYPE: - case B_DOUBLE_TYPE: - case B_POINTER_TYPE: - case B_MESSENGER_TYPE: - fixedSize = true; - break; - default: - break; - } - - status_t result = message.AddData(field->name, field->type, - fieldBuffer + dataOffset, field->item_size, fixedSize); - - if (result < B_OK) { - free(fieldBuffer); - throw result; - } - break; - } - - case SECTION_FIXED_SIZE_ARRAY_DATA: { - fixed_size_array *field = (fixed_size_array *)fieldBuffer; - - int32 dataOffset = sizeof(fixed_size_array) + field->name_length + 1; - dataOffset = pad_to_8(dataOffset); - int32 count = *(int32 *)(fieldBuffer + dataOffset); - dataOffset += 8; /* count and padding */ - - if (offset + dataOffset + count * field->size_per_item > size) - return B_BAD_DATA; - - status_t result = B_OK; - for (int32 i = 0; i < count; i++) { - result = message.AddData(field->name, field->type, - fieldBuffer + dataOffset, field->size_per_item, true, - count); - - if (result < B_OK) { - free(fieldBuffer); - throw result; - } - - dataOffset += field->size_per_item; - } - break; - } - - case SECTION_VARIABLE_SIZE_ARRAY_DATA: { - variable_size_array *field = (variable_size_array *)fieldBuffer; - - int32 dataOffset = sizeof(variable_size_array) + field->name_length + 1; - dataOffset = pad_to_8(dataOffset); - int32 count = *(int32 *)(fieldBuffer + dataOffset); - dataOffset += sizeof(int32); - ssize_t totalSize = *(ssize_t *)(fieldBuffer + dataOffset); - dataOffset += sizeof(ssize_t); - - int32 *endPoints = (int32 *)(fieldBuffer + dataOffset - + totalSize); - - status_t result = B_OK; - for (int32 i = 0; i < count; i++) { - int32 itemOffset = (i > 0 ? pad_to_8(endPoints[i - 1]) : 0); - - result = message.AddData(field->name, field->type, - fieldBuffer + dataOffset + itemOffset, - endPoints[i] - itemOffset, false, count); - - if (result < B_OK) { - free(fieldBuffer); - throw result; - } - } - break; - } - } - - free(fieldBuffer); - offset += sectionHeader.size; - } - - return B_OK; -} diff --git a/src/kits/app/dano_message.h b/src/kits/app/dano_message.h deleted file mode 100644 index 3cdfdf3dc0..0000000000 --- a/src/kits/app/dano_message.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2005, Haiku. - * Distributed under the terms of the MIT License. - * - * Authors: - * Axel Dörfler, axeld@pinc-software.de - */ -#ifndef DANO_MESSAGE_H -#define DANO_MESSAGE_H - - -#include - -class BMessage; -class BDataIO; - - -namespace BPrivate { - -status_t unflatten_dano_message(uint32 format, BDataIO& stream, BMessage& message); -ssize_t dano_message_flattened_size(const char* buffer); - -} - -#endif // DANO_MESSAGE_H diff --git a/src/kits/app/r5_message.cpp b/src/kits/app/r5_message.cpp deleted file mode 100644 index eb36710345..0000000000 --- a/src/kits/app/r5_message.cpp +++ /dev/null @@ -1,412 +0,0 @@ -/* - * Copyright 2005, Haiku Inc. All rights reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Michael Lotz - */ - -#include "r5_message.h" - -#include -#include -#include -#include - -#define R5_MESSAGE_FLAG_VALID 0x01 -#define R5_MESSAGE_FLAG_INCLUDE_TARGET 0x02 -#define R5_MESSAGE_FLAG_INCLUDE_REPLY 0x04 -#define R5_MESSAGE_FLAG_SCRIPT_MESSAGE 0x08 - -#define R5_FIELD_FLAG_VALID 0x01 -#define R5_FIELD_FLAG_MINI_DATA 0x02 -#define R5_FIELD_FLAG_FIXED_SIZE 0x04 -#define R5_FIELD_FLAG_SINGLE_ITEM 0x08 - -namespace BPrivate { - -static const uint32 kR5MessageMagic = 'FOB1'; -static const uint32 kR5MessageMagicSwapped = '1BOF'; - - -struct r5_message_header { - uint32 magic; // kR5MessageMagic - uint32 checksum; - ssize_t flattened_size; - int32 what; - uint8 flags; -} _PACKED; - - -inline int32 -pad_to_8(int32 value) -{ - return (value + 7) & ~7; -} - - -ssize_t -r5_message_flattened_size(const BMessage *message) -{ - BMessage::Private messagePrivate((BMessage *)message); - BMessage::message_header* header = messagePrivate.GetMessageHeader(); - - // header size (variable, depending on the flags) - - ssize_t flattenedSize = sizeof(r5_message_header); - - if (header->target != B_NULL_TOKEN) - flattenedSize += sizeof(int32); - - if (header->reply_port >= 0 && header->reply_target != B_NULL_TOKEN - && header->reply_team >= 0) { - // reply info + big flags - flattenedSize += sizeof(port_id) + sizeof(int32) + sizeof(team_id) + 4; - } - - // field size - - uint8 *data = messagePrivate.GetMessageData(); - BMessage::field_header* field = messagePrivate.GetMessageFields(); - for (int32 i = 0; i < header->field_count; i++, field++) { - // flags and type - flattenedSize += 1 + sizeof(type_code); - -#if 0 - bool miniData = field->dataSize <= 255 && field->count <= 255; -#else - // ToDo: we don't know the R5 dataSize yet (padding) - bool miniData = false; -#endif - - // item count - if (field->count > 1) - flattenedSize += (miniData ? sizeof(uint8) : sizeof(uint32)); - - // data size - flattenedSize += (miniData ? sizeof(uint8) : sizeof(size_t)); - - // name length and name - flattenedSize += 1 + min_c(field->name_length - 1, 255); - - // data - if (field->flags & FIELD_FLAG_FIXED_SIZE) - flattenedSize += field->data_size; - else { - uint8 *source = data + field->offset + field->name_length; - - for (int32 i = 0; i < field->count; i++) { - ssize_t itemSize = *(ssize_t *)source + sizeof(ssize_t); - flattenedSize += pad_to_8(itemSize); - source += itemSize; - } - } - } - - // pseudo field with flags 0 - return flattenedSize + 1; -} - - -status_t -flatten_r5_message(const BMessage *message, char *buffer, ssize_t size) -{ - BMessage::Private messagePrivate((BMessage *)message); - BMessage::message_header* header = messagePrivate.GetMessageHeader(); - uint8* data = messagePrivate.GetMessageData(); - - r5_message_header* r5header = (r5_message_header *)buffer; - uint8* pointer = (uint8 *)buffer + sizeof(r5_message_header); - - r5header->magic = kR5MessageMagic; - r5header->what = message->what; - r5header->checksum = 0; - - uint8 flags = R5_MESSAGE_FLAG_VALID; - if (header->target != B_NULL_TOKEN) { - *(int32 *)pointer = header->target; - pointer += sizeof(int32); - flags |= R5_MESSAGE_FLAG_INCLUDE_TARGET; - } - - if (header->reply_port >= 0 && header->reply_target != B_NULL_TOKEN - && header->reply_team >= 0) { - // reply info - *(port_id *)pointer = header->reply_port; - pointer += sizeof(port_id); - *(int32 *)pointer = header->reply_target; - pointer += sizeof(int32); - *(team_id *)pointer = header->reply_team; - pointer += sizeof(team_id); - - // big flags - *pointer = (header->reply_target == B_PREFERRED_TOKEN ? 1 : 0); - pointer++; - - *pointer = (header->flags & MESSAGE_FLAG_REPLY_REQUIRED ? 1 : 0); - pointer++; - - *pointer = (header->flags & MESSAGE_FLAG_REPLY_DONE ? 1 : 0); - pointer++; - - *pointer = (header->flags & MESSAGE_FLAG_IS_REPLY ? 1 : 0); - pointer++; - - flags |= R5_MESSAGE_FLAG_INCLUDE_REPLY; - } - - if (header->flags & MESSAGE_FLAG_HAS_SPECIFIERS) - flags |= R5_MESSAGE_FLAG_SCRIPT_MESSAGE; - - r5header->flags = flags; - - // store the header size - used for the checksum later - ssize_t headerSize = (uint32)pointer - (uint32)buffer; - - // collect and add the data - BMessage::field_header* field = messagePrivate.GetMessageFields(); - for (int32 i = 0; i < header->field_count; i++, field++) { - flags = R5_FIELD_FLAG_VALID; - - if (field->count == 1) - flags |= R5_FIELD_FLAG_SINGLE_ITEM; - // ToDo: we don't really know the data size now (padding missing) - if (field->data_size <= 255 && field->count <= 255) - ;//flags |= R5_FIELD_FLAG_MINI_DATA; - if (field->flags & FIELD_FLAG_FIXED_SIZE) - flags |= R5_FIELD_FLAG_FIXED_SIZE; - - *pointer = flags; - pointer++; - - *(type_code *)pointer = field->type; - pointer += sizeof(type_code); - - if (!(flags & R5_FIELD_FLAG_SINGLE_ITEM)) { - if (flags & R5_FIELD_FLAG_MINI_DATA) { - *pointer = (uint8)field->count; - pointer++; - } else { - *(int32 *)pointer = field->count; - pointer += sizeof(int32); - } - } - - // we may have to adjust this to account for padding later - uint8 *fieldSize = pointer; - if (flags & R5_FIELD_FLAG_MINI_DATA) { - *pointer = (uint8)field->data_size; - pointer++; - } else { - *(ssize_t *)pointer = field->data_size; - pointer += sizeof(ssize_t); - } - - // name - int32 nameLength = min_c(field->name_length - 1, 255); - *pointer = (uint8)nameLength; - pointer++; - - strncpy((char *)pointer, (char *)data + field->offset, nameLength); - pointer += nameLength; - - // data - uint8 *source = data + field->offset + field->name_length; - if (flags & R5_FIELD_FLAG_FIXED_SIZE) { - memcpy(pointer, source, field->data_size); - pointer += field->data_size; - } else { - uint8 *previous = pointer; - for (int32 i = 0; i < field->count; i++) { - ssize_t itemSize = *(ssize_t *)source + sizeof(ssize_t); - memcpy(pointer, source, itemSize); - pointer += pad_to_8(itemSize); - source += itemSize; - } - - // adjust the field size to the padded value - if (flags & R5_FIELD_FLAG_MINI_DATA) - *fieldSize = (uint8)(pointer - previous); - else - *(ssize_t *)fieldSize = (pointer - previous); - } - } - - // terminate the fields with a pseudo field with flags 0 (not valid) - *pointer = 0; - pointer++; - - // calculate the flattened size from the pointers - r5header->flattened_size = (uint32)pointer - (uint32)buffer; - r5header->checksum = BPrivate::CalculateChecksum((uint8 *)(buffer + 8), - headerSize - 8); - return B_OK; -} - - -status_t -flatten_r5_message(const BMessage *message, BDataIO *stream, ssize_t *_size) -{ - // ToDo: This is not very cheap... - ssize_t size = r5_message_flattened_size(message); - char *buffer = (char *)malloc(size); - if (!buffer) - return B_NO_MEMORY; - - status_t result = flatten_r5_message(message, buffer, size); - if (result < B_OK) { - free(buffer); - return result; - } - - ssize_t written = stream->Write(buffer, size); - if (written != size) { - free(buffer); - return (written >= 0 ? B_ERROR : written); - } - - if (_size) - *_size = size; - - free(buffer); - return B_OK; -} - - -status_t -unflatten_r5_message(uint32 format, BMessage *message, const char *flatBuffer) -{ - r5_message_header *r5header = (r5_message_header *)flatBuffer; - BMemoryIO stream(flatBuffer + 4, r5header->flattened_size - 4); - return unflatten_r5_message(format, message, &stream); -} - - -status_t -unflatten_r5_message(uint32 format, BMessage *message, BDataIO *stream) -{ - message->MakeEmpty(); - - TReadHelper reader(stream); - BMessage::Private messagePrivate(message); - BMessage::message_header *header = messagePrivate.GetMessageHeader(); - - if (format == kR5MessageMagicSwapped) - reader.SetSwap(true); - - // the stream is already advanced by the size of the "format" - r5_message_header r5header; - reader(((uint8 *)&r5header) + sizeof(uint32), - sizeof(r5header) - sizeof(uint32)); - - header->what = message->what = r5header.what; - if (r5header.flags & R5_MESSAGE_FLAG_INCLUDE_TARGET) - reader(header->target); - - if (r5header.flags & R5_MESSAGE_FLAG_INCLUDE_REPLY) { - // reply info - reader(header->reply_port); - reader(header->reply_target); - reader(header->reply_team); - - // big flags - uint8 bigFlag; - reader(bigFlag); - if (bigFlag) - header->reply_target = B_PREFERRED_TOKEN; - - reader(bigFlag); - if (bigFlag) - header->flags |= MESSAGE_FLAG_REPLY_REQUIRED; - - reader(bigFlag); - if (bigFlag) - header->flags |= MESSAGE_FLAG_REPLY_DONE; - - reader(bigFlag); - if (bigFlag) - header->flags |= MESSAGE_FLAG_IS_REPLY; - } - - if (r5header.flags & R5_MESSAGE_FLAG_SCRIPT_MESSAGE) - header->flags |= MESSAGE_FLAG_HAS_SPECIFIERS; - - uint8 flags; - reader(flags); - while (flags & R5_FIELD_FLAG_VALID) { - bool fixedSize = flags & R5_FIELD_FLAG_FIXED_SIZE; - bool miniData = flags & R5_FIELD_FLAG_MINI_DATA; - bool singleItem = flags & R5_FIELD_FLAG_SINGLE_ITEM; - - type_code type; - reader(type); - - int32 itemCount; - if (!singleItem) { - if (miniData) { - uint8 miniCount; - reader(miniCount); - itemCount = miniCount; - } else - reader(itemCount); - } else - itemCount = 1; - - ssize_t dataSize; - if (miniData) { - uint8 miniSize; - reader(miniSize); - dataSize = miniSize; - } else - reader(dataSize); - - if (dataSize <= 0) - return B_ERROR; - - // name - uint8 nameLength; - reader(nameLength); - - char nameBuffer[256]; - reader(nameBuffer, nameLength); - nameBuffer[nameLength] = '\0'; - - uint8 *buffer = (uint8 *)malloc(dataSize); - uint8 *pointer = buffer; - reader(buffer, dataSize); - - status_t result = B_OK; - ssize_t itemSize = 0; - if (fixedSize) - itemSize = dataSize / itemCount; - - for (int32 i = 0; i < itemCount; i++) { - if (!fixedSize) { - itemSize = *(ssize_t *)pointer; - pointer += sizeof(ssize_t); - } - - result = message->AddData(nameBuffer, type, pointer, itemSize, - fixedSize, itemCount); - - if (result < B_OK) { - free(buffer); - return result; - } - - if (fixedSize) - pointer += itemSize; - else - pointer += pad_to_8(itemSize + sizeof(ssize_t)) - sizeof(ssize_t); - } - - free(buffer); - - // flags of next field or termination byte - reader(flags); - } - - return B_OK; -} - -} // namespace BPrivate diff --git a/src/kits/app/r5_message.h b/src/kits/app/r5_message.h deleted file mode 100644 index 677484cb2e..0000000000 --- a/src/kits/app/r5_message.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2005, Haiku Inc. All rights reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Michael Lotz - */ -#ifndef _R5_MESSAGE_H_ -#define _R5_MESSAGE_H_ - - -#include - -class BMessage; -class BDataIO; - - -namespace BPrivate { - -ssize_t r5_message_flattened_size(const BMessage *message); -status_t flatten_r5_message(const BMessage *message, char *buffer, ssize_t size); -status_t flatten_r5_message(const BMessage *message, BDataIO *stream, ssize_t *size); -status_t unflatten_r5_message(uint32 format, BMessage *message, const char *flatBuffer); -status_t unflatten_r5_message(uint32 format, BMessage *message, BDataIO *stream); - -} - -#endif // _R5_MESSAGE_H_