BMessage: implemented KMessage reply.
* When you receive a message from a KMessage, and reply to it, it will automatically reply as KMessage, too. * This allows to communicate with BLoopers from within the kernel or libroot.so.
This commit is contained in:
@@ -913,6 +913,8 @@ BMessage::SendReply(BMessage* reply, BMessenger replyTo, bigtime_t timeout)
|
||||
BMessenger::Private messengerPrivate(messenger);
|
||||
messengerPrivate.SetTo(fHeader->reply_team, fHeader->reply_port,
|
||||
fHeader->reply_target);
|
||||
if ((fHeader->flags & MESSAGE_FLAG_REPLY_AS_KMESSAGE) != 0)
|
||||
reply->fHeader->flags |= MESSAGE_FLAG_REPLY_AS_KMESSAGE;
|
||||
|
||||
if ((fHeader->flags & MESSAGE_FLAG_REPLY_REQUIRED) != 0) {
|
||||
if ((fHeader->flags & MESSAGE_FLAG_REPLY_DONE) != 0)
|
||||
@@ -923,11 +925,9 @@ BMessage::SendReply(BMessage* reply, BMessenger replyTo, bigtime_t timeout)
|
||||
status_t result = messenger.SendMessage(reply, replyTo, timeout);
|
||||
reply->fHeader->flags &= ~MESSAGE_FLAG_IS_REPLY;
|
||||
|
||||
if (result != B_OK) {
|
||||
if (set_port_owner(messengerPrivate.Port(),
|
||||
if (result != B_OK && set_port_owner(messengerPrivate.Port(),
|
||||
messengerPrivate.Team()) == B_BAD_TEAM_ID) {
|
||||
delete_port(messengerPrivate.Port());
|
||||
}
|
||||
delete_port(messengerPrivate.Port());
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -993,7 +993,8 @@ BMessage::SendReply(BMessage* reply, BMessage* replyToReply,
|
||||
return B_BAD_REPLY;
|
||||
|
||||
reply->AddMessage("_previous_", this);
|
||||
reply->fHeader->flags |= MESSAGE_FLAG_IS_REPLY;
|
||||
reply->fHeader->flags |= MESSAGE_FLAG_IS_REPLY
|
||||
| (fHeader->flags & MESSAGE_FLAG_REPLY_AS_KMESSAGE);
|
||||
status_t result = messenger.SendMessage(reply, replyToReply, sendTimeout,
|
||||
replyTimeout);
|
||||
reply->fHeader->flags &= ~MESSAGE_FLAG_IS_REPLY;
|
||||
@@ -2164,6 +2165,13 @@ BMessage::_SendMessage(port_id port, team_id portOwner, int32 token,
|
||||
header->message_area = transfered;
|
||||
}
|
||||
#endif
|
||||
} else if ((fHeader->flags & MESSAGE_FLAG_REPLY_AS_KMESSAGE) != 0) {
|
||||
KMessage toMessage;
|
||||
result = BPrivate::MessageAdapter::ConvertToKMessage(this, toMessage);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
return toMessage.SendTo(port, token);
|
||||
} else {
|
||||
size = FlattenedSize();
|
||||
buffer = (char*)malloc(size);
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
/*
|
||||
* Copyright 2005-2007, Haiku Inc. All rights reserved.
|
||||
* Copyright 2005-2015, Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Axel Dörfler, axeld@pinc-software.de
|
||||
* Michael Lotz <mmlr@mlotz.ch>
|
||||
*/
|
||||
|
||||
|
||||
#include <MessageAdapter.h>
|
||||
#include <MessagePrivate.h>
|
||||
#include <MessageUtils.h>
|
||||
@@ -237,6 +239,44 @@ MessageAdapter::Unflatten(uint32 format, BMessage *into, BDataIO *stream)
|
||||
}
|
||||
|
||||
|
||||
/*static*/ status_t
|
||||
MessageAdapter::ConvertToKMessage(const BMessage* from, KMessage& to)
|
||||
{
|
||||
if (from == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
BMessage::Private fromPrivate(const_cast<BMessage*>(from));
|
||||
BMessage::message_header* header = fromPrivate.GetMessageHeader();
|
||||
uint8* data = fromPrivate.GetMessageData();
|
||||
|
||||
// Iterate through the fields and import them in the target message
|
||||
BMessage::field_header* field = fromPrivate.GetMessageFields();
|
||||
for (uint32 i = 0; i < header->field_count; i++, field++) {
|
||||
const char* name = (const char*)data + field->offset;
|
||||
const uint8* fieldData = data + field->offset + field->name_length;
|
||||
bool fixedSize = (field->flags & FIELD_FLAG_FIXED_SIZE) != 0;
|
||||
|
||||
if (fixedSize) {
|
||||
status_t status = to.AddArray(name, field->type, fieldData,
|
||||
field->data_size / field->count, field->count);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
} else {
|
||||
for (uint32 i = 0; i < field->count; i++) {
|
||||
uint32 itemSize = *(uint32*)fieldData;
|
||||
fieldData += sizeof(uint32);
|
||||
status_t status = to.AddData(name, field->type, fieldData,
|
||||
itemSize, false);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
fieldData += itemSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/*static*/ status_t
|
||||
MessageAdapter::_ConvertFromKMessage(const KMessage *fromMessage,
|
||||
BMessage *toMessage)
|
||||
@@ -252,6 +292,10 @@ MessageAdapter::_ConvertFromKMessage(const KMessage *fromMessage,
|
||||
toPrivate.SetTarget(fromMessage->TargetToken());
|
||||
toPrivate.SetReply(B_SYSTEM_TEAM, fromMessage->ReplyPort(),
|
||||
fromMessage->ReplyToken());
|
||||
if (fromMessage->ReplyPort() >= 0) {
|
||||
toPrivate.GetMessageHeader()->flags |= MESSAGE_FLAG_REPLY_AS_KMESSAGE
|
||||
| MESSAGE_FLAG_REPLY_REQUIRED;
|
||||
}
|
||||
|
||||
// Iterate through the fields and import them in the target message
|
||||
KMessageField field;
|
||||
|
||||
Reference in New Issue
Block a user