*Very* basic read-only Dano/Zeta message support. Only briefly tested.
Not really suited for message sending/retrieval (because target stuff is missing), but should work more or less with disk based messages. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13428 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+197
-185
@@ -1,43 +1,26 @@
|
|||||||
//------------------------------------------------------------------------------
|
/*
|
||||||
// Copyright (c) 2001-2005, OpenBeOS
|
* Copyright 2001-2005, Haiku.
|
||||||
//
|
* Distributed under the terms of the MIT License.
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
*
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
* Authors:
|
||||||
// to deal in the Software without restriction, including without limitation
|
* Erik Jaesler ([email protected])
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
* DarkWyrm <[email protected]>
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
* Ingo Weinhold <[email protected]>
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
*/
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
/** BMessage class creates objects that store data and that
|
||||||
// all copies or substantial portions of the Software.
|
* can be processed in a message loop. BMessage objects
|
||||||
//
|
* are also used as data containers by the archiving and
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* the scripting mechanisms.
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
*/
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
// File Name: Message.h
|
|
||||||
// Author(s): Erik Jaesler ([email protected])
|
|
||||||
// DarkWyrm <[email protected]>
|
|
||||||
// Ingo Weinhold <[email protected]>
|
|
||||||
// Description: BMessage class creates objects that store data and that
|
|
||||||
// can be processed in a message loop. BMessage objects
|
|
||||||
// are also used as data containers by the archiving and
|
|
||||||
// the scripting mechanisms.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// debugging
|
// debugging
|
||||||
//#define DBG(x) x
|
//#define DBG(x) x
|
||||||
#define DBG(x) ;
|
#define DBG(x) ;
|
||||||
#define PRINT(x) DBG({ printf("[%6ld] ", find_thread(NULL)); printf x; })
|
#define PRINT(x) DBG({ printf("[%6ld] ", find_thread(NULL)); printf x; })
|
||||||
|
|
||||||
// Standard Includes -----------------------------------------------------------
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
// System Includes -------------------------------------------------------------
|
|
||||||
#include <Application.h>
|
#include <Application.h>
|
||||||
#include <BlockCache.h>
|
#include <BlockCache.h>
|
||||||
#include <ByteOrder.h>
|
#include <ByteOrder.h>
|
||||||
@@ -47,9 +30,6 @@
|
|||||||
#include <MessengerPrivate.h>
|
#include <MessengerPrivate.h>
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
|
|
||||||
//#include <CRTDBG.H>
|
|
||||||
|
|
||||||
// Project Includes ------------------------------------------------------------
|
|
||||||
#include <AppMisc.h>
|
#include <AppMisc.h>
|
||||||
#include <DataBuffer.h>
|
#include <DataBuffer.h>
|
||||||
#include <KMessage.h>
|
#include <KMessage.h>
|
||||||
@@ -57,10 +37,14 @@
|
|||||||
#include <MessageUtils.h>
|
#include <MessageUtils.h>
|
||||||
#include <TokenSpace.h>
|
#include <TokenSpace.h>
|
||||||
|
|
||||||
// Local Includes --------------------------------------------------------------
|
#include "dano_message.h"
|
||||||
|
|
||||||
// Local Defines ---------------------------------------------------------------
|
|
||||||
#define MSG_FIELD_VERSION 'FOB1'
|
static const uint32 kMessageMagic = 'FOB1';
|
||||||
|
static const uint32 kMessageMagicSwapped = '1BOF';
|
||||||
|
|
||||||
|
static const uint32 kMessageMagicDano = 'FOB2';
|
||||||
|
static const uint32 kMessageMagicDanoSwapped = '2BOF';
|
||||||
|
|
||||||
// flags for the overall message (the bitfield is 1 byte)
|
// flags for the overall message (the bitfield is 1 byte)
|
||||||
#define MSG_FLAG_BIG_ENDIAN 0x01
|
#define MSG_FLAG_BIG_ENDIAN 0x01
|
||||||
@@ -111,6 +95,8 @@ public:
|
|||||||
Header() {}
|
Header() {}
|
||||||
Header(const BMessage &message) { ReadFrom(message); }
|
Header(const BMessage &message) { ReadFrom(message); }
|
||||||
|
|
||||||
|
status_t SetMagic(uint32 magic);
|
||||||
|
|
||||||
status_t ReadFrom(BDataIO &stream);
|
status_t ReadFrom(BDataIO &stream);
|
||||||
void ReadFrom(const BMessage &message);
|
void ReadFrom(const BMessage &message);
|
||||||
status_t WriteTo(BDataIO &stream, bool calculateCheckSum = true) const;
|
status_t WriteTo(BDataIO &stream, bool calculateCheckSum = true) const;
|
||||||
@@ -127,7 +113,7 @@ public:
|
|||||||
void Dump() const;
|
void Dump() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int32 fMagic;
|
uint32 fMagic;
|
||||||
int32 fBodySize;
|
int32 fBodySize;
|
||||||
uint32 fWhat;
|
uint32 fWhat;
|
||||||
uint8 fFlags;
|
uint8 fFlags;
|
||||||
@@ -142,6 +128,24 @@ private:
|
|||||||
bool fSwapped;
|
bool fSwapped;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BMessage::Header::SetMagic(uint32 magic)
|
||||||
|
{
|
||||||
|
if (magic == kMessageMagicSwapped) {
|
||||||
|
fSwapped = true;
|
||||||
|
} else if (magic == kMessageMagic) {
|
||||||
|
fSwapped = false;
|
||||||
|
} else {
|
||||||
|
// This is *not* a message
|
||||||
|
return B_NOT_A_MESSAGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
fMagic = magic;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ReadFrom
|
// ReadFrom
|
||||||
status_t
|
status_t
|
||||||
BMessage::Header::ReadFrom(BDataIO &stream)
|
BMessage::Header::ReadFrom(BDataIO &stream)
|
||||||
@@ -154,19 +158,6 @@ BMessage::Header::ReadFrom(BDataIO &stream)
|
|||||||
int32 flattenedSize;
|
int32 flattenedSize;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Get the message version
|
|
||||||
read_helper(fMagic);
|
|
||||||
|
|
||||||
fSwapped = false;
|
|
||||||
if (fMagic == '1BOF') {
|
|
||||||
fSwapped = true;
|
|
||||||
} else if (fMagic == 'FOB1') {
|
|
||||||
fSwapped = false;
|
|
||||||
} else {
|
|
||||||
// This is *not* a message
|
|
||||||
return B_NOT_A_MESSAGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
read_helper.SetSwap(fSwapped);
|
read_helper.SetSwap(fSwapped);
|
||||||
|
|
||||||
// get the checksum
|
// get the checksum
|
||||||
@@ -237,7 +228,7 @@ BMessage::Header::ReadFrom(BDataIO &stream)
|
|||||||
void
|
void
|
||||||
BMessage::Header::ReadFrom(const BMessage &message)
|
BMessage::Header::ReadFrom(const BMessage &message)
|
||||||
{
|
{
|
||||||
fMagic = MSG_FIELD_VERSION;
|
fMagic = kMessageMagic;
|
||||||
|
|
||||||
fBodySize = message.fBody->FlattenedSize();
|
fBodySize = message.fBody->FlattenedSize();
|
||||||
fWhat = message.what;
|
fWhat = message.what;
|
||||||
@@ -909,172 +900,192 @@ status_t BMessage::Flatten(BDataIO* stream, ssize_t* size) const
|
|||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
status_t BMessage::Unflatten(const char* flat_buffer)
|
|
||||||
|
status_t
|
||||||
|
BMessage::Unflatten(const char* buffer)
|
||||||
{
|
{
|
||||||
if (!flat_buffer)
|
if (!buffer)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
// check whether this is a KMessage
|
uint32 magic = *(uint32*)buffer;
|
||||||
if (((KMessage::Header*)flat_buffer)->magic
|
|
||||||
== KMessage::kMessageHeaderMagic) {
|
// we support several message formats - this list is ordered
|
||||||
return _UnflattenKMessage(flat_buffer);
|
// by importance and frequency
|
||||||
|
|
||||||
|
if (magic == kMessageMagic) {
|
||||||
|
// it appears to be a normal flattened BMessage
|
||||||
|
BMemoryIO memoryStream(buffer, ((uint32*)buffer)[2]);
|
||||||
|
return Unflatten(&memoryStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
// assume it's a normal flattened BMessage
|
// check whether this is a KMessage
|
||||||
uint32 size = ((uint32*)flat_buffer)[2];
|
if (((KMessage::Header*)buffer)->magic
|
||||||
|
== KMessage::kMessageHeaderMagic)
|
||||||
|
return _UnflattenKMessage(buffer);
|
||||||
|
|
||||||
BMemoryIO MemIO(flat_buffer, size);
|
if (magic == kMessageMagicSwapped) {
|
||||||
return Unflatten(&MemIO);
|
// it appears to be a swapped flattened BMessage
|
||||||
|
uint32 size = ((uint32*)buffer)[2];
|
||||||
|
|
||||||
|
BMemoryIO memoryStream(buffer, __swap_int32(size));
|
||||||
|
return Unflatten(&memoryStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (magic == kMessageMagicDano || magic == kMessageMagicDanoSwapped) {
|
||||||
|
// dano style message
|
||||||
|
BMemoryIO memoryStream(buffer, BPrivate::dano_message_size(buffer));
|
||||||
|
return Unflatten(&memoryStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_NOT_A_MESSAGE;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
status_t BMessage::Unflatten(BDataIO* stream)
|
|
||||||
|
status_t
|
||||||
|
BMessage::Unflatten(BDataIO* stream)
|
||||||
{
|
{
|
||||||
|
TReadHelper reader(stream);
|
||||||
Header header;
|
Header header;
|
||||||
status_t err = header.ReadFrom(*stream);
|
status_t status = B_OK;
|
||||||
|
|
||||||
if (err) {
|
// ToDo: while reading from a stream is certainly more convenient than
|
||||||
printf("BMessage::Unflatten(): Reading the header failed: %lx\n", err);
|
// from a buffer, it causes a lot of unnecessary copies, and therefore
|
||||||
}
|
// probably shouldn't be the preferred (or only) route.
|
||||||
|
|
||||||
|
try {
|
||||||
|
uint32 magic;
|
||||||
|
reader(magic);
|
||||||
|
|
||||||
|
status = header.SetMagic(magic);
|
||||||
|
if (status < B_OK) {
|
||||||
|
// we support reading Dano messages from disk as well
|
||||||
|
if (magic == kMessageMagicDano)
|
||||||
|
return BPrivate::unflatten_dano_message(magic, *stream, *this);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = header.ReadFrom(*stream);
|
||||||
|
if (status < B_OK) {
|
||||||
|
printf("BMessage::Unflatten(): Reading the header failed: %lx\n", status);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
if (!err)
|
|
||||||
{
|
|
||||||
header.WriteTo(*this);
|
header.WriteTo(*this);
|
||||||
bool swap = header.IsSwapped();
|
bool swap = header.IsSwapped();
|
||||||
|
|
||||||
TReadHelper reader(stream, swap);
|
|
||||||
int8 flags;
|
|
||||||
type_code type;
|
|
||||||
uint32 count;
|
uint32 count;
|
||||||
uint32 dataLen;
|
uint32 dataLen;
|
||||||
uint8 nameLen;
|
uint8 nameLen;
|
||||||
char name[MSG_NAME_MAX_SIZE];
|
char name[MSG_NAME_MAX_SIZE];
|
||||||
unsigned char* databuffer = NULL;
|
unsigned char* databuffer = NULL;
|
||||||
|
|
||||||
try
|
int8 flags;
|
||||||
{
|
reader(flags);
|
||||||
reader(flags);
|
|
||||||
while (flags != MSG_LAST_ENTRY)
|
while (flags != MSG_LAST_ENTRY) {
|
||||||
{
|
type_code type;
|
||||||
reader(type);
|
reader(type);
|
||||||
// Is there more than one data item? (!flags & MSG_FLAG_SINGLE_ITEM)
|
|
||||||
if (flags & MSG_FLAG_SINGLE_ITEM)
|
// Is there more than one data item?
|
||||||
{
|
if (flags & MSG_FLAG_SINGLE_ITEM) {
|
||||||
count = 1;
|
count = 1;
|
||||||
if (flags & MSG_FLAG_MINI_DATA)
|
if (flags & MSG_FLAG_MINI_DATA) {
|
||||||
{
|
uint8 littleLen;
|
||||||
uint8 littleLen;
|
reader(littleLen);
|
||||||
reader(littleLen);
|
dataLen = littleLen;
|
||||||
dataLen = littleLen;
|
} else
|
||||||
}
|
reader(dataLen);
|
||||||
else
|
} else {
|
||||||
{
|
// Is there a little data?
|
||||||
reader(dataLen);
|
if (flags & MSG_FLAG_MINI_DATA) {
|
||||||
}
|
// Get item count (1 byte)
|
||||||
|
uint8 littleCount;
|
||||||
|
reader(littleCount);
|
||||||
|
count = littleCount;
|
||||||
|
|
||||||
|
// Get data length (1 byte)
|
||||||
|
uint8 littleLen;
|
||||||
|
reader(littleLen);
|
||||||
|
dataLen = littleLen;
|
||||||
|
} else {
|
||||||
|
// Is there a lot of data?
|
||||||
|
// Get item count (4 bytes)
|
||||||
|
reader(count);
|
||||||
|
// Get data length (4 bytes)
|
||||||
|
reader(dataLen);
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
|
||||||
// Is there a little data? (flags & MSG_FLAG_MINI_DATA)
|
|
||||||
if (flags & MSG_FLAG_MINI_DATA)
|
|
||||||
{
|
|
||||||
// Get item count (1 byte)
|
|
||||||
uint8 littleCount;
|
|
||||||
reader(littleCount);
|
|
||||||
count = littleCount;
|
|
||||||
|
|
||||||
// Get data length (1 byte)
|
// Get the name length (1 byte)
|
||||||
uint8 littleLen;
|
reader(nameLen);
|
||||||
reader(littleLen);
|
// Get the name (name length bytes)
|
||||||
dataLen = littleLen;
|
reader(name, nameLen);
|
||||||
}
|
name[nameLen] = '\0';
|
||||||
else
|
|
||||||
{
|
|
||||||
// Is there a lot of data? (!flags & MSG_FLAG_MINI_DATA)
|
|
||||||
// Get item count (4 bytes)
|
|
||||||
reader(count);
|
|
||||||
// Get data length (4 bytes)
|
|
||||||
reader(dataLen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the name length (1 byte)
|
// Copy the data into a new buffer to byte align it
|
||||||
reader(nameLen);
|
databuffer = (unsigned char*)realloc(databuffer, dataLen);
|
||||||
// Get the name (name length bytes)
|
if (!databuffer)
|
||||||
reader(name, nameLen);
|
throw B_NO_MEMORY;
|
||||||
name[nameLen] = '\0';
|
// Get the data
|
||||||
|
reader(databuffer, dataLen);
|
||||||
|
|
||||||
// Copy the data into a new buffer to byte align it
|
if (swap) {
|
||||||
databuffer = (unsigned char*)realloc(databuffer, dataLen);
|
// Is the data fixed size?
|
||||||
if (!databuffer)
|
if ((flags & MSG_FLAG_FIXED_SIZE) != 0) {
|
||||||
throw B_NO_MEMORY;
|
|
||||||
// Get the data
|
|
||||||
reader(databuffer, dataLen);
|
|
||||||
|
|
||||||
// Is the data fixed size? (flags & MSG_FLAG_FIXED_SIZE)
|
|
||||||
if (flags & MSG_FLAG_FIXED_SIZE && swap)
|
|
||||||
{
|
|
||||||
// Make sure to swap the data
|
// Make sure to swap the data
|
||||||
err = swap_data(type, (void*)databuffer, dataLen,
|
status = swap_data(type, (void*)databuffer, dataLen,
|
||||||
B_SWAP_ALWAYS);
|
B_SWAP_ALWAYS);
|
||||||
if (err)
|
if (status < B_OK)
|
||||||
throw err;
|
throw status;
|
||||||
}
|
} else if (type == B_REF_TYPE) {
|
||||||
// Is the data variable size? (!flags & MSG_FLAG_FIXED_SIZE)
|
// Is the data variable size?
|
||||||
else if (swap && type == B_REF_TYPE)
|
|
||||||
{
|
|
||||||
// Apparently, entry_refs are the only variable-length data
|
// Apparently, entry_refs are the only variable-length data
|
||||||
// explicitely swapped -- the dev_t and ino_t
|
// explicitely swapped -- the dev_t and ino_t
|
||||||
// specifically
|
// specifically
|
||||||
byte_swap(*(entry_ref*)databuffer);
|
byte_swap(*(entry_ref*)databuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add each data field to the message
|
|
||||||
uint32 itemSize = 0;
|
|
||||||
if (flags & MSG_FLAG_FIXED_SIZE)
|
|
||||||
{
|
|
||||||
itemSize = dataLen / count;
|
|
||||||
}
|
|
||||||
unsigned char* dataPtr = databuffer;
|
|
||||||
for (uint32 i = 0; i < count; ++i)
|
|
||||||
{
|
|
||||||
// Line up for the next item
|
|
||||||
if (i)
|
|
||||||
{
|
|
||||||
if (flags & MSG_FLAG_FIXED_SIZE)
|
|
||||||
{
|
|
||||||
dataPtr += itemSize;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Have to account for 8-byte boundary padding
|
|
||||||
// We add 4 because padding as calculated during
|
|
||||||
// flattening includes the four-byte size header
|
|
||||||
dataPtr += itemSize + calc_padding(itemSize + 4, 8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((flags & MSG_FLAG_FIXED_SIZE) == 0)
|
|
||||||
{
|
|
||||||
itemSize = *(uint32*)dataPtr;
|
|
||||||
dataPtr += sizeof (uint32);
|
|
||||||
}
|
|
||||||
|
|
||||||
err = AddData(name, type, dataPtr, itemSize,
|
|
||||||
flags & MSG_FLAG_FIXED_SIZE);
|
|
||||||
if (err)
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
|
|
||||||
reader(flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add each data field to the message
|
||||||
|
uint32 itemSize = 0;
|
||||||
|
if (flags & MSG_FLAG_FIXED_SIZE)
|
||||||
|
itemSize = dataLen / count;
|
||||||
|
|
||||||
|
unsigned char* dataPtr = databuffer;
|
||||||
|
|
||||||
|
for (uint32 i = 0; i < count; ++i) {
|
||||||
|
// Line up for the next item
|
||||||
|
if (i) {
|
||||||
|
if (flags & MSG_FLAG_FIXED_SIZE) {
|
||||||
|
dataPtr += itemSize;
|
||||||
|
} else {
|
||||||
|
// Have to account for 8-byte boundary padding
|
||||||
|
// We add 4 because padding as calculated during
|
||||||
|
// flattening includes the four-byte size header
|
||||||
|
dataPtr += itemSize + calc_padding(itemSize + 4, 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flags & MSG_FLAG_FIXED_SIZE) == 0) {
|
||||||
|
itemSize = *(uint32*)dataPtr;
|
||||||
|
dataPtr += sizeof (uint32);
|
||||||
|
}
|
||||||
|
|
||||||
|
status = AddData(name, type, dataPtr, itemSize,
|
||||||
|
flags & MSG_FLAG_FIXED_SIZE);
|
||||||
|
if (status < B_OK)
|
||||||
|
throw status;
|
||||||
|
}
|
||||||
|
|
||||||
|
reader(flags);
|
||||||
}
|
}
|
||||||
catch (status_t& e)
|
} catch (status_t& e) {
|
||||||
{
|
status = e;
|
||||||
err = e;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return status;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
status_t BMessage::AddSpecifier(const char* property)
|
status_t BMessage::AddSpecifier(const char* property)
|
||||||
@@ -2024,7 +2035,8 @@ BMessage::_SendFlattenedMessage(void *data, int32 size, port_id port,
|
|||||||
// a KMessage
|
// a KMessage
|
||||||
KMessage::Header *header = (KMessage::Header*)data;
|
KMessage::Header *header = (KMessage::Header*)data;
|
||||||
header->targetToken = (preferred ? B_PREFERRED_TOKEN : token);
|
header->targetToken = (preferred ? B_PREFERRED_TOKEN : token);
|
||||||
} else if (*(int32*)data == '1BOF' || *(int32*)data == 'FOB1') {
|
} else if (*(uint32*)data == kMessageMagic
|
||||||
|
|| *(uint32*)data == kMessageMagicSwapped) {
|
||||||
// get the header
|
// get the header
|
||||||
BMemoryIO stream(data, size);
|
BMemoryIO stream(data, size);
|
||||||
Header header;
|
Header header;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ APP_KIT_SOURCE =
|
|||||||
Cursor.cpp
|
Cursor.cpp
|
||||||
DataBuffer.cpp
|
DataBuffer.cpp
|
||||||
Clipboard.cpp
|
Clipboard.cpp
|
||||||
|
dano_message.cpp
|
||||||
Handler.cpp
|
Handler.cpp
|
||||||
InitTerminateLibBe.cpp
|
InitTerminateLibBe.cpp
|
||||||
Invoker.cpp
|
Invoker.cpp
|
||||||
|
|||||||
@@ -0,0 +1,122 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2005, Haiku.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Axel Dörfler
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "dano_message.h"
|
||||||
|
|
||||||
|
#include <MessageUtils.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct dano_header {
|
||||||
|
uint32 code;
|
||||||
|
int32 size;
|
||||||
|
uint32 what;
|
||||||
|
uint32 _unknown;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dano_field_header {
|
||||||
|
uint32 code;
|
||||||
|
int32 size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dano_field {
|
||||||
|
uint32 type;
|
||||||
|
int32 data_size;
|
||||||
|
uint8 name_size;
|
||||||
|
char name[0];
|
||||||
|
} _PACKED;
|
||||||
|
|
||||||
|
static const uint32 kMessageFormat = 'FOB2';
|
||||||
|
static const uint32 kMessageFormatSwapped = '2BOF';
|
||||||
|
|
||||||
|
static const uint32 kDataField = 'SGDa';
|
||||||
|
|
||||||
|
|
||||||
|
size_t
|
||||||
|
BPrivate::dano_message_size(const char* buffer)
|
||||||
|
{
|
||||||
|
dano_header* header = (dano_header*)buffer;
|
||||||
|
|
||||||
|
if (header->code == kMessageFormatSwapped)
|
||||||
|
return __swap_int32(header->size);
|
||||||
|
|
||||||
|
return header->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BPrivate::unflatten_dano_message(uint32 magic, BDataIO& stream, BMessage& message)
|
||||||
|
{
|
||||||
|
TReadHelper reader(&stream);
|
||||||
|
message.MakeEmpty();
|
||||||
|
|
||||||
|
if (magic == kMessageFormatSwapped)
|
||||||
|
reader.SetSwap(true);
|
||||||
|
|
||||||
|
int32 size;
|
||||||
|
reader(size);
|
||||||
|
reader(message.what);
|
||||||
|
|
||||||
|
int32 value;
|
||||||
|
reader(value); // unknown
|
||||||
|
|
||||||
|
size -= sizeof(dano_header);
|
||||||
|
int32 offset = 0;
|
||||||
|
|
||||||
|
while (offset < size) {
|
||||||
|
dano_field_header fieldHeader;
|
||||||
|
reader(fieldHeader);
|
||||||
|
printf("field.code = %.4s (%lx), field.size = %ld\n",
|
||||||
|
(char*)&fieldHeader.code, fieldHeader.code, fieldHeader.size);
|
||||||
|
|
||||||
|
if (fieldHeader.size + offset > size)
|
||||||
|
return B_BAD_DATA;
|
||||||
|
|
||||||
|
uint32 fieldSize = fieldHeader.size - sizeof(dano_field_header);
|
||||||
|
char* fieldBuffer = (char*)malloc(fieldSize);
|
||||||
|
if (fieldBuffer == NULL)
|
||||||
|
throw (status_t)B_NO_MEMORY;
|
||||||
|
|
||||||
|
reader(fieldBuffer, fieldSize);
|
||||||
|
|
||||||
|
if (fieldHeader.code == kDataField) {
|
||||||
|
dano_field* field = (dano_field*)fieldBuffer;
|
||||||
|
|
||||||
|
int32 dataOffset = sizeof(dano_field) + field->name_size + 1;
|
||||||
|
dataOffset = (dataOffset + 7) & ~7;
|
||||||
|
// padding
|
||||||
|
|
||||||
|
if (field->data_size + dataOffset + offset > size)
|
||||||
|
return B_BAD_DATA;
|
||||||
|
|
||||||
|
// ToDo: support fixed size for real
|
||||||
|
bool fixedSize = true;
|
||||||
|
if (field->type == B_STRING_TYPE)
|
||||||
|
fixedSize = false;
|
||||||
|
|
||||||
|
status_t status = message.AddData(field->name, field->type,
|
||||||
|
fieldBuffer + dataOffset, field->data_size, fixedSize);
|
||||||
|
|
||||||
|
if (status < B_OK) {
|
||||||
|
free(fieldBuffer);
|
||||||
|
throw status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(fieldBuffer);
|
||||||
|
offset += fieldHeader.size;
|
||||||
|
printf("offset = %ld, size = %ld\n", offset, size);
|
||||||
|
}
|
||||||
|
message.PrintToStream();
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
class BMessage;
|
||||||
|
class BDataIO;
|
||||||
|
|
||||||
|
namespace BPrivate {
|
||||||
|
status_t unflatten_dano_message(uint32 magic, BDataIO& stream, BMessage& message);
|
||||||
|
size_t dano_message_size(const char* buffer);
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user