* Added support for unflatting from flattened KMessages. At least when
a buffer is given. * Added method for sending flattened messages. The KMessage support is complete, but for BMessages this is a bit tricky. We currently unflatten the BMessages and send those. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@11060 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
ea69d9d35f
commit
377872556d
@ -328,6 +328,9 @@ virtual void _ReservedMessage3();
|
||||
ssize_t stack_size,
|
||||
bool incl_reply,
|
||||
ssize_t *size = NULL) const;
|
||||
|
||||
status_t _UnflattenKMessage(const char *buffer);
|
||||
|
||||
ssize_t calc_size(uchar flags) const;
|
||||
ssize_t calc_hdr_size(uchar flags) const;
|
||||
ssize_t min_hdr_size() const;
|
||||
@ -355,6 +358,10 @@ virtual void _ReservedMessage3();
|
||||
BMessage *reply,
|
||||
bigtime_t send_timeout,
|
||||
bigtime_t reply_timeout) const;
|
||||
static status_t _SendFlattenedMessage(void *data, int32 size,
|
||||
port_id port, int32 token, bool preferred,
|
||||
bigtime_t timeout);
|
||||
|
||||
enum { sNumReplyPorts = 3 };
|
||||
static port_id sReplyPorts[sNumReplyPorts];
|
||||
static long sReplyPortInUse[sNumReplyPorts];
|
||||
|
@ -54,6 +54,7 @@
|
||||
#ifdef USING_TEMPLATE_MADNESS
|
||||
#include <AppMisc.h>
|
||||
#include <DataBuffer.h>
|
||||
#include <KMessage.h>
|
||||
#include <MessageBody.h>
|
||||
#include <MessageUtils.h>
|
||||
#include <TokenSpace.h>
|
||||
@ -101,6 +102,9 @@ static status_t handle_reply(port_id reply_port,
|
||||
bigtime_t timeout,
|
||||
BMessage* reply);
|
||||
|
||||
static status_t convert_message(const KMessage *fromMessage,
|
||||
BMessage *toMessage);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
extern "C" {
|
||||
void _msg_cache_cleanup_()
|
||||
@ -612,6 +616,16 @@ status_t BMessage::Flatten(BDataIO* stream, ssize_t* size) const
|
||||
//------------------------------------------------------------------------------
|
||||
status_t BMessage::Unflatten(const char* flat_buffer)
|
||||
{
|
||||
if (!flat_buffer)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
// check whether this is a KMessage
|
||||
if (((KMessage::Header*)flat_buffer)->magic
|
||||
== KMessage::kMessageHeaderMagic) {
|
||||
return _UnflattenKMessage(flat_buffer);
|
||||
}
|
||||
|
||||
// assume it's a normal flattened BMessage
|
||||
uint32 size = ((uint32*)flat_buffer)[2];
|
||||
|
||||
BMemoryIO MemIO(flat_buffer, size);
|
||||
@ -1748,8 +1762,24 @@ char* BMessage::stack_flatten(char* stack_ptr, ssize_t stack_size,
|
||||
}
|
||||
return new_ptr;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
ssize_t BMessage::calc_hdr_size(uchar flags) const
|
||||
|
||||
|
||||
status_t
|
||||
BMessage::_UnflattenKMessage(const char *buffer)
|
||||
{
|
||||
// init a real KMessage
|
||||
KMessage message;
|
||||
status_t error = message.SetTo(buffer, ((KMessage::Header*)buffer)->size);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
// let convert_message() do the real job
|
||||
return convert_message(&message, this);
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
BMessage::calc_hdr_size(uchar flags) const
|
||||
{
|
||||
ssize_t size = min_hdr_size();
|
||||
|
||||
@ -1899,8 +1929,60 @@ error:
|
||||
delete_port(reply_port);
|
||||
return err;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
int32 BMessage::sGetCachedReplyPort()
|
||||
|
||||
|
||||
status_t
|
||||
BMessage::_SendFlattenedMessage(void *data, int32 size, port_id port,
|
||||
int32 token, bool preferred, bigtime_t timeout)
|
||||
{
|
||||
if (!data)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
// prepare flattened fields
|
||||
if (((KMessage::Header*)data)->magic == KMessage::kMessageHeaderMagic) {
|
||||
// a KMessage
|
||||
KMessage::Header *header = (KMessage::Header*)data;
|
||||
header->sender = -1;
|
||||
header->targetToken = (preferred ? B_PREFERRED_TOKEN : token);
|
||||
header->replyPort = -1;
|
||||
header->replyToken = B_NULL_TOKEN;
|
||||
|
||||
} else if (*(int32*)data == '1BOF' || *(int32*)data == 'FOB1') {
|
||||
// bool swap = (*(int32*)data == '1BOF');
|
||||
// TODO: Replace the target token. This is not so simple, since the
|
||||
// position of the target token is not always the same. It can even
|
||||
// happen that no target token is included at all (the one who is
|
||||
// flattening the message must set a dummy token at least).
|
||||
|
||||
// dummy implementation to make it work at least
|
||||
|
||||
// unflatten the message
|
||||
BMessage message;
|
||||
status_t error = message.Unflatten((const char*)data);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
// send the message
|
||||
BMessenger messenger;
|
||||
return message._send_(port, token, preferred, timeout, false,
|
||||
messenger);
|
||||
} else {
|
||||
return B_NOT_A_MESSAGE;
|
||||
}
|
||||
|
||||
// send the message
|
||||
status_t error;
|
||||
do {
|
||||
error = write_port_etc(port, 'pjpp', data, size, B_RELATIVE_TIMEOUT,
|
||||
timeout);
|
||||
} while (error == B_INTERRUPTED);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
BMessage::sGetCachedReplyPort()
|
||||
{
|
||||
int index = -1;
|
||||
for (int32 i = 0; i < sNumReplyPorts; i++)
|
||||
@ -3433,3 +3515,54 @@ void BMessage::da_swap_fixed_sized(dyn_array *da)
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#endif // USING_TEMPLATE_MADNESS
|
||||
|
||||
|
||||
// convert_message
|
||||
static
|
||||
status_t
|
||||
convert_message(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();
|
||||
|
||||
// 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 error;
|
||||
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;
|
||||
error = convert_message(&message, &bMessage);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
error = toMessage->AddMessage(field.Name(), &bMessage);
|
||||
} else {
|
||||
// just add it
|
||||
error = toMessage->AddData(field.Name(),
|
||||
field.TypeCode(), data, size,
|
||||
field.HasFixedElementSize(), 1);
|
||||
}
|
||||
} else {
|
||||
error = toMessage->AddData(field.Name(), field.TypeCode(),
|
||||
data, size, field.HasFixedElementSize(), 1);
|
||||
}
|
||||
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
}
|
||||
}
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user