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:
Axel Dörfler
2015-05-13 23:06:51 +02:00
parent 446d4dca66
commit 5ce80a78c9
5 changed files with 69 additions and 10 deletions
+13 -5
View File
@@ -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);
+45 -1
View File
@@ -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;