Moved the functionality to flatten and unflatten a BMessage header into
a separate class. This allowed to improve _SendFlattenedMessage() to deal properly with flattened BMessages as well. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@11116 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -295,10 +295,12 @@ virtual ~BMessage();
|
|||||||
class Private;
|
class Private;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
class Header;
|
||||||
|
|
||||||
friend class BMessageQueue;
|
friend class BMessageQueue;
|
||||||
friend class BMessenger;
|
friend class BMessenger;
|
||||||
friend class BApplication;
|
friend class BApplication;
|
||||||
|
friend class Header;
|
||||||
friend class Private;
|
friend class Private;
|
||||||
|
|
||||||
friend inline void _set_message_target_(BMessage *, int32, bool);
|
friend inline void _set_message_target_(BMessage *, int32, bool);
|
||||||
@@ -314,8 +316,6 @@ virtual void _ReservedMessage2();
|
|||||||
virtual void _ReservedMessage3();
|
virtual void _ReservedMessage3();
|
||||||
|
|
||||||
void init_data();
|
void init_data();
|
||||||
status_t flatten_hdr(BDataIO *stream) const;
|
|
||||||
status_t unflatten_hdr(BDataIO *stream, bool& swap);
|
|
||||||
status_t flatten_target_info(BDataIO *stream,
|
status_t flatten_target_info(BDataIO *stream,
|
||||||
ssize_t size,
|
ssize_t size,
|
||||||
uchar flags) const;
|
uchar flags) const;
|
||||||
@@ -331,7 +331,6 @@ virtual void _ReservedMessage3();
|
|||||||
|
|
||||||
ssize_t calc_size(uchar flags) const;
|
ssize_t calc_size(uchar flags) const;
|
||||||
ssize_t calc_hdr_size(uchar flags) const;
|
ssize_t calc_hdr_size(uchar flags) const;
|
||||||
ssize_t min_hdr_size() const;
|
|
||||||
status_t nfind_data( const char *name,
|
status_t nfind_data( const char *name,
|
||||||
type_code type,
|
type_code type,
|
||||||
int32 index,
|
int32 index,
|
||||||
|
|||||||
+394
-254
@@ -101,6 +101,345 @@ static status_t handle_reply(port_id reply_port,
|
|||||||
static status_t convert_message(const KMessage *fromMessage,
|
static status_t convert_message(const KMessage *fromMessage,
|
||||||
BMessage *toMessage);
|
BMessage *toMessage);
|
||||||
|
|
||||||
|
static ssize_t min_hdr_size();
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
class BMessage::Header {
|
||||||
|
public:
|
||||||
|
Header() {}
|
||||||
|
Header(const BMessage &message) { ReadFrom(message); }
|
||||||
|
|
||||||
|
status_t ReadFrom(BDataIO &stream);
|
||||||
|
void ReadFrom(const BMessage &message);
|
||||||
|
status_t WriteTo(BDataIO &stream);
|
||||||
|
void WriteTo(BMessage &message);
|
||||||
|
|
||||||
|
uint32 CalculateCheckSum() const;
|
||||||
|
uint32 CalculateHeaderSize() const;
|
||||||
|
|
||||||
|
bool IsSwapped() const { return fSwapped; }
|
||||||
|
|
||||||
|
bool HasTarget() const { return (fFlags & MSG_FLAG_INCL_TARGET); }
|
||||||
|
void SetTarget(int32 token, bool preferred);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int32 fMagic;
|
||||||
|
int32 fBodySize;
|
||||||
|
uint32 fWhat;
|
||||||
|
uint8 fFlags;
|
||||||
|
int32 fTargetToken;
|
||||||
|
port_id fReplyPort;
|
||||||
|
int32 fReplyToken;
|
||||||
|
team_id fReplyTeam;
|
||||||
|
bool fPreferredTarget;
|
||||||
|
bool fReplyRequired;
|
||||||
|
bool fReplyDone;
|
||||||
|
bool fIsReply;
|
||||||
|
bool fSwapped;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ReadFrom
|
||||||
|
status_t
|
||||||
|
BMessage::Header::ReadFrom(BDataIO &stream)
|
||||||
|
{
|
||||||
|
int32 checkSum;
|
||||||
|
uchar csBuffer[MSG_HEADER_MAX_SIZE];
|
||||||
|
|
||||||
|
TReadHelper read_helper(&stream);
|
||||||
|
TChecksumHelper checksum_helper(csBuffer);
|
||||||
|
int32 flattenedSize;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
// get the checksum
|
||||||
|
read_helper(checkSum);
|
||||||
|
// get the size
|
||||||
|
read_helper(flattenedSize);
|
||||||
|
checksum_helper.Cache(flattenedSize);
|
||||||
|
// Get the what
|
||||||
|
read_helper(fWhat);
|
||||||
|
checksum_helper.Cache(fWhat);
|
||||||
|
// Get the flags
|
||||||
|
read_helper(fFlags);
|
||||||
|
checksum_helper.Cache(fFlags);
|
||||||
|
|
||||||
|
if (fFlags & MSG_FLAG_BIG_ENDIAN) {
|
||||||
|
// TODO: ???
|
||||||
|
// Isn't this already indicated by the byte order of the message version?
|
||||||
|
}
|
||||||
|
if (fFlags & MSG_FLAG_INCL_TARGET) {
|
||||||
|
// Get the target data
|
||||||
|
read_helper(fTargetToken);
|
||||||
|
checksum_helper.Cache(fTargetToken);
|
||||||
|
}
|
||||||
|
if (fFlags & MSG_FLAG_INCL_REPLY) {
|
||||||
|
// Get the reply port
|
||||||
|
read_helper(fReplyPort);
|
||||||
|
read_helper(fReplyToken);
|
||||||
|
read_helper(fReplyTeam);
|
||||||
|
checksum_helper.Cache(fReplyPort);
|
||||||
|
checksum_helper.Cache(fReplyToken);
|
||||||
|
checksum_helper.Cache(fReplyTeam);
|
||||||
|
|
||||||
|
// Get the "big flags"
|
||||||
|
uint8 bigFlags;
|
||||||
|
// Get the preferred flag
|
||||||
|
read_helper(bigFlags);
|
||||||
|
checksum_helper.Cache(bigFlags);
|
||||||
|
fPreferredTarget = bigFlags;
|
||||||
|
|
||||||
|
// Get the reply requirement flag
|
||||||
|
read_helper(bigFlags);
|
||||||
|
checksum_helper.Cache(bigFlags);
|
||||||
|
fReplyRequired = bigFlags;
|
||||||
|
|
||||||
|
// Get the reply done flag
|
||||||
|
read_helper(bigFlags);
|
||||||
|
checksum_helper.Cache(bigFlags);
|
||||||
|
fReplyDone = bigFlags;
|
||||||
|
|
||||||
|
// Get the "is reply" flag
|
||||||
|
read_helper(bigFlags);
|
||||||
|
checksum_helper.Cache(bigFlags);
|
||||||
|
fIsReply = bigFlags;
|
||||||
|
}
|
||||||
|
} catch (status_t& e) {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checkSum != checksum_helper.CheckSum())
|
||||||
|
return B_NOT_A_MESSAGE;
|
||||||
|
|
||||||
|
fBodySize = flattenedSize - CalculateHeaderSize();
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadFrom
|
||||||
|
void
|
||||||
|
BMessage::Header::ReadFrom(const BMessage &message)
|
||||||
|
{
|
||||||
|
fMagic = MSG_FIELD_VERSION;
|
||||||
|
|
||||||
|
fBodySize = message.fBody->FlattenedSize();
|
||||||
|
fWhat = message.what;
|
||||||
|
fFlags = 0;
|
||||||
|
#ifdef B_HOST_IS_BENDIAN
|
||||||
|
fFlags |= MSG_FLAG_BIG_ENDIAN;
|
||||||
|
#endif
|
||||||
|
if (message.HasSpecifiers())
|
||||||
|
fFlags |= MSG_FLAG_SCRIPT_MSG;
|
||||||
|
if (message.fTarget != B_NULL_TOKEN)
|
||||||
|
fFlags |= MSG_FLAG_INCL_TARGET;
|
||||||
|
if (message.fReplyTo.port >= 0 &&
|
||||||
|
message.fReplyTo.target != B_NULL_TOKEN &&
|
||||||
|
message.fReplyTo.team >= 0) {
|
||||||
|
fFlags |= MSG_FLAG_INCL_REPLY;
|
||||||
|
}
|
||||||
|
fTargetToken = message.fTarget;
|
||||||
|
fReplyPort = message.fReplyTo.port;
|
||||||
|
fReplyToken = message.fReplyTo.target;
|
||||||
|
fReplyTeam = message.fReplyTo.team;
|
||||||
|
fPreferredTarget = message.fPreferred;
|
||||||
|
fReplyRequired = message.fReplyRequired;
|
||||||
|
fReplyDone = message.fReplyDone;
|
||||||
|
fIsReply = message.fIsReply;
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteTo
|
||||||
|
status_t
|
||||||
|
BMessage::Header::WriteTo(BDataIO &stream)
|
||||||
|
{
|
||||||
|
status_t err = B_OK;
|
||||||
|
int32 data;
|
||||||
|
|
||||||
|
// Write the version of the binary data format
|
||||||
|
data = fMagic;
|
||||||
|
write_helper(&stream, (const void*)&data, sizeof (data), err);
|
||||||
|
if (!err) {
|
||||||
|
// compute checksum
|
||||||
|
data = CalculateCheckSum();
|
||||||
|
write_helper(&stream, (const void*)&data, sizeof (data), err);
|
||||||
|
}
|
||||||
|
if (!err) {
|
||||||
|
// Write the flattened size of the entire message
|
||||||
|
data = CalculateHeaderSize() + fBodySize;
|
||||||
|
write_helper(&stream, (const void*)&data, sizeof (data), err);
|
||||||
|
}
|
||||||
|
if (!err) {
|
||||||
|
// Write the 'what' member
|
||||||
|
write_helper(&stream, (const void*)&fWhat, sizeof (fWhat), err);
|
||||||
|
}
|
||||||
|
if (!err) {
|
||||||
|
// Write the header flags
|
||||||
|
write_helper(&stream, (const void*)&fFlags, sizeof (fFlags), err);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write targeting info if necessary
|
||||||
|
if (!err && (fFlags & MSG_FLAG_INCL_TARGET)) {
|
||||||
|
data = fPreferredTarget ? B_PREFERRED_TOKEN : fTargetToken;
|
||||||
|
write_helper(&stream, (const void*)&data, sizeof (data), err);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write reply info if necessary
|
||||||
|
if (!err && (fFlags & MSG_FLAG_INCL_REPLY)) {
|
||||||
|
write_helper(&stream, (const void*)&fReplyPort, sizeof(fReplyPort),
|
||||||
|
err);
|
||||||
|
if (!err) {
|
||||||
|
write_helper(&stream, (const void*)&fReplyToken,
|
||||||
|
sizeof(fReplyToken), err);
|
||||||
|
}
|
||||||
|
if (!err) {
|
||||||
|
write_helper(&stream, (const void*)&fReplyTeam,
|
||||||
|
sizeof(fReplyTeam), err);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 bigFlags;
|
||||||
|
if (!err) {
|
||||||
|
bigFlags = fPreferredTarget ? 1 : 0;
|
||||||
|
write_helper(&stream, (const void*)&bigFlags, sizeof(bigFlags),
|
||||||
|
err);
|
||||||
|
}
|
||||||
|
if (!err)
|
||||||
|
{
|
||||||
|
bigFlags = fReplyRequired ? 1 : 0;
|
||||||
|
write_helper(&stream, (const void*)&bigFlags, sizeof(bigFlags),
|
||||||
|
err);
|
||||||
|
}
|
||||||
|
if (!err)
|
||||||
|
{
|
||||||
|
bigFlags = fReplyDone ? 1 : 0;
|
||||||
|
write_helper(&stream, (const void*)&bigFlags, sizeof(bigFlags),
|
||||||
|
err);
|
||||||
|
}
|
||||||
|
if (!err)
|
||||||
|
{
|
||||||
|
bigFlags = fIsReply ? 1 : 0;
|
||||||
|
write_helper(&stream, (const void*)&bigFlags, sizeof(bigFlags),
|
||||||
|
err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteTo
|
||||||
|
void
|
||||||
|
BMessage::Header::WriteTo(BMessage &message)
|
||||||
|
{
|
||||||
|
// Make way for the new data
|
||||||
|
message.MakeEmpty();
|
||||||
|
|
||||||
|
message.what = fWhat;
|
||||||
|
|
||||||
|
message.fHasSpecifiers = fFlags & MSG_FLAG_SCRIPT_MSG;
|
||||||
|
|
||||||
|
if (fFlags & MSG_FLAG_INCL_TARGET) {
|
||||||
|
// Get the target data
|
||||||
|
message.fTarget = fTargetToken;
|
||||||
|
}
|
||||||
|
if (fFlags & MSG_FLAG_INCL_REPLY) {
|
||||||
|
// Get the reply port
|
||||||
|
message.fReplyTo.port = fReplyPort;
|
||||||
|
message.fReplyTo.target = fReplyToken;
|
||||||
|
message.fReplyTo.team = fReplyTeam;
|
||||||
|
|
||||||
|
message.fWasDelivered = true;
|
||||||
|
|
||||||
|
message.fPreferred = fPreferredTarget;
|
||||||
|
if (fPreferredTarget)
|
||||||
|
message.fTarget = B_PREFERRED_TOKEN;
|
||||||
|
|
||||||
|
message.fReplyRequired = fReplyRequired;
|
||||||
|
message.fReplyDone = fReplyDone;
|
||||||
|
message.fIsReply = fIsReply;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CalculateCheckSum
|
||||||
|
uint32
|
||||||
|
BMessage::Header::CalculateCheckSum() const
|
||||||
|
{
|
||||||
|
uchar csBuffer[MSG_HEADER_MAX_SIZE];
|
||||||
|
TChecksumHelper checksum_helper(csBuffer);
|
||||||
|
|
||||||
|
int32 flattenedSize = CalculateHeaderSize() + fBodySize;
|
||||||
|
checksum_helper.Cache(flattenedSize);
|
||||||
|
checksum_helper.Cache(fWhat);
|
||||||
|
checksum_helper.Cache(fFlags);
|
||||||
|
if (fFlags & MSG_FLAG_INCL_TARGET)
|
||||||
|
checksum_helper.Cache(fTargetToken);
|
||||||
|
if (fFlags & MSG_FLAG_INCL_REPLY) {
|
||||||
|
checksum_helper.Cache(fReplyPort);
|
||||||
|
checksum_helper.Cache(fReplyToken);
|
||||||
|
checksum_helper.Cache(fReplyTeam);
|
||||||
|
|
||||||
|
// big flags
|
||||||
|
uint8 bigFlags = (fPreferredTarget ? 1 : 0);
|
||||||
|
checksum_helper.Cache(bigFlags);
|
||||||
|
bigFlags = (fReplyRequired ? 1 : 0);
|
||||||
|
checksum_helper.Cache(bigFlags);
|
||||||
|
bigFlags = (fReplyDone ? 1 : 0);
|
||||||
|
checksum_helper.Cache(bigFlags);
|
||||||
|
bigFlags = (fIsReply ? 1 : 0);
|
||||||
|
checksum_helper.Cache(bigFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
return checksum_helper.CheckSum();
|
||||||
|
}
|
||||||
|
|
||||||
|
// CalculateHeaderSize
|
||||||
|
uint32
|
||||||
|
BMessage::Header::CalculateHeaderSize() const
|
||||||
|
{
|
||||||
|
ssize_t size = min_hdr_size();
|
||||||
|
|
||||||
|
if (fTargetToken != B_NULL_TOKEN)
|
||||||
|
size += sizeof (fTargetToken);
|
||||||
|
|
||||||
|
if (fReplyPort >= 0 && fReplyToken != B_NULL_TOKEN && fReplyTeam >= 0) {
|
||||||
|
size += sizeof (fReplyPort);
|
||||||
|
size += sizeof (fReplyToken);
|
||||||
|
size += sizeof (fReplyTeam);
|
||||||
|
|
||||||
|
size += 4; // For the "big" flags
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTarget
|
||||||
|
void
|
||||||
|
BMessage::Header::SetTarget(int32 token, bool preferred)
|
||||||
|
{
|
||||||
|
fTargetToken = token;
|
||||||
|
if (fTargetToken == B_NULL_TOKEN)
|
||||||
|
fFlags &= ~MSG_FLAG_INCL_TARGET;
|
||||||
|
else
|
||||||
|
fFlags |= MSG_FLAG_INCL_TARGET;
|
||||||
|
|
||||||
|
fPreferredTarget = preferred;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
void BMessage::_ReservedMessage1() {}
|
void BMessage::_ReservedMessage1() {}
|
||||||
void BMessage::_ReservedMessage2() {}
|
void BMessage::_ReservedMessage2() {}
|
||||||
void BMessage::_ReservedMessage3() {}
|
void BMessage::_ReservedMessage3() {}
|
||||||
@@ -591,11 +930,14 @@ status_t BMessage::Unflatten(const char* flat_buffer)
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
status_t BMessage::Unflatten(BDataIO* stream)
|
status_t BMessage::Unflatten(BDataIO* stream)
|
||||||
{
|
{
|
||||||
bool swap;
|
Header header;
|
||||||
status_t err = unflatten_hdr(stream, swap);
|
status_t err = header.ReadFrom(*stream);
|
||||||
|
|
||||||
if (!err)
|
if (!err)
|
||||||
{
|
{
|
||||||
|
header.WriteTo(*this);
|
||||||
|
bool swap = header.IsSwapped();
|
||||||
|
|
||||||
TReadHelper reader(stream, swap);
|
TReadHelper reader(stream, swap);
|
||||||
int8 flags;
|
int8 flags;
|
||||||
type_code type;
|
type_code type;
|
||||||
@@ -1462,242 +1804,24 @@ BPoint BMessage::FindPoint(const char* name, int32 n) const
|
|||||||
FindPoint(name, n, &p);
|
FindPoint(name, n, &p);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
status_t BMessage::flatten_hdr(BDataIO* stream) const
|
|
||||||
{
|
|
||||||
status_t err = B_OK;
|
|
||||||
int32 data = MSG_FIELD_VERSION;
|
|
||||||
|
|
||||||
// Write the version of the binary data format
|
|
||||||
write_helper(stream, (const void*)&data, sizeof (data), err);
|
|
||||||
if (!err)
|
|
||||||
{
|
|
||||||
// faked up checksum; we'll fix it up later
|
|
||||||
write_helper(stream, (const void*)&data, sizeof (data), err);
|
|
||||||
}
|
|
||||||
if (!err)
|
|
||||||
{
|
|
||||||
// Write the flattened size of the entire message
|
|
||||||
data = fBody->FlattenedSize() + calc_hdr_size(0);
|
|
||||||
write_helper(stream, (const void*)&data, sizeof (data), err);
|
|
||||||
}
|
|
||||||
if (!err)
|
|
||||||
{
|
|
||||||
// Write the 'what' member
|
|
||||||
write_helper(stream, (const void*)&what, sizeof (what), err);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 flags = 0;
|
status_t
|
||||||
#ifdef B_HOST_IS_BENDIAN
|
BMessage::real_flatten(char* result, ssize_t size) const
|
||||||
flags |= MSG_FLAG_BIG_ENDIAN;
|
|
||||||
#endif
|
|
||||||
if (HasSpecifiers())
|
|
||||||
{
|
|
||||||
flags |= MSG_FLAG_SCRIPT_MSG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fTarget != B_NULL_TOKEN)
|
|
||||||
{
|
|
||||||
flags |= MSG_FLAG_INCL_TARGET;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fReplyTo.port >= 0 &&
|
|
||||||
fReplyTo.target != B_NULL_TOKEN &&
|
|
||||||
fReplyTo.team >= 0)
|
|
||||||
{
|
|
||||||
flags |= MSG_FLAG_INCL_REPLY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!err)
|
|
||||||
{
|
|
||||||
// Write the header flags
|
|
||||||
write_helper(stream, (const void*)&flags, sizeof (flags), err);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write targeting info if necessary
|
|
||||||
if (!err && (flags & MSG_FLAG_INCL_TARGET))
|
|
||||||
{
|
|
||||||
data = fPreferred ? B_PREFERRED_TOKEN : fTarget;
|
|
||||||
write_helper(stream, (const void*)&data, sizeof (data), err);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write reply info if necessary
|
|
||||||
if (!err && (flags & MSG_FLAG_INCL_REPLY))
|
|
||||||
{
|
|
||||||
write_helper(stream, (const void*)&fReplyTo.port,
|
|
||||||
sizeof (fReplyTo.port), err);
|
|
||||||
if (!err)
|
|
||||||
{
|
|
||||||
write_helper(stream, (const void*)&fReplyTo.target,
|
|
||||||
sizeof (fReplyTo.target), err);
|
|
||||||
}
|
|
||||||
if (!err)
|
|
||||||
{
|
|
||||||
write_helper(stream, (const void*)&fReplyTo.team,
|
|
||||||
sizeof (fReplyTo.team), err);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 bigFlags;
|
|
||||||
if (!err)
|
|
||||||
{
|
|
||||||
bigFlags = fPreferred ? 1 : 0;
|
|
||||||
write_helper(stream, (const void*)&bigFlags,
|
|
||||||
sizeof (bigFlags), err);
|
|
||||||
}
|
|
||||||
if (!err)
|
|
||||||
{
|
|
||||||
bigFlags = fReplyRequired ? 1 : 0;
|
|
||||||
write_helper(stream, (const void*)&bigFlags,
|
|
||||||
sizeof (bigFlags), err);
|
|
||||||
}
|
|
||||||
if (!err)
|
|
||||||
{
|
|
||||||
bigFlags = fReplyDone ? 1 : 0;
|
|
||||||
write_helper(stream, (const void*)&bigFlags,
|
|
||||||
sizeof (bigFlags), err);
|
|
||||||
}
|
|
||||||
if (!err)
|
|
||||||
{
|
|
||||||
bigFlags = fIsReply ? 1 : 0;
|
|
||||||
write_helper(stream, (const void*)&bigFlags,
|
|
||||||
sizeof (bigFlags), err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
status_t BMessage::unflatten_hdr(BDataIO* stream, bool& swap)
|
|
||||||
{
|
|
||||||
status_t err = B_OK;
|
|
||||||
int32 data;
|
|
||||||
int32 checksum;
|
|
||||||
uchar csBuffer[MSG_HEADER_MAX_SIZE];
|
|
||||||
|
|
||||||
TReadHelper read_helper(stream);
|
|
||||||
TChecksumHelper checksum_helper(csBuffer);
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
// Get the message version
|
|
||||||
read_helper(data);
|
|
||||||
if (data == '1BOF')
|
|
||||||
{
|
|
||||||
swap = true;
|
|
||||||
}
|
|
||||||
else if (data == 'FOB1')
|
|
||||||
{
|
|
||||||
swap = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// This is *not* a message
|
|
||||||
return B_NOT_A_MESSAGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make way for the new data
|
|
||||||
MakeEmpty();
|
|
||||||
|
|
||||||
read_helper.SetSwap(swap);
|
|
||||||
|
|
||||||
// get the checksum
|
|
||||||
read_helper(checksum);
|
|
||||||
// get the size
|
|
||||||
read_helper(data);
|
|
||||||
checksum_helper.Cache(data);
|
|
||||||
// Get the what
|
|
||||||
read_helper(what);
|
|
||||||
checksum_helper.Cache(what);
|
|
||||||
// Get the flags
|
|
||||||
uint8 flags = 0;
|
|
||||||
read_helper(flags);
|
|
||||||
checksum_helper.Cache(flags);
|
|
||||||
|
|
||||||
fHasSpecifiers = flags & MSG_FLAG_SCRIPT_MSG;
|
|
||||||
|
|
||||||
if (flags & MSG_FLAG_BIG_ENDIAN)
|
|
||||||
{
|
|
||||||
// TODO: ???
|
|
||||||
// Isn't this already indicated by the byte order of the message version?
|
|
||||||
}
|
|
||||||
if (flags & MSG_FLAG_INCL_TARGET)
|
|
||||||
{
|
|
||||||
// Get the target data
|
|
||||||
read_helper(data);
|
|
||||||
checksum_helper.Cache(data);
|
|
||||||
fTarget = data;
|
|
||||||
}
|
|
||||||
if (flags & MSG_FLAG_INCL_REPLY)
|
|
||||||
{
|
|
||||||
// Get the reply port
|
|
||||||
read_helper(fReplyTo.port);
|
|
||||||
read_helper(fReplyTo.target);
|
|
||||||
read_helper(fReplyTo.team);
|
|
||||||
checksum_helper.Cache(fReplyTo.port);
|
|
||||||
checksum_helper.Cache(fReplyTo.target);
|
|
||||||
checksum_helper.Cache(fReplyTo.team);
|
|
||||||
|
|
||||||
fWasDelivered = true;
|
|
||||||
|
|
||||||
// Get the "big flags"
|
|
||||||
uint8 bigFlags;
|
|
||||||
// Get the preferred flag
|
|
||||||
read_helper(bigFlags);
|
|
||||||
checksum_helper.Cache(bigFlags);
|
|
||||||
fPreferred = bigFlags;
|
|
||||||
if (fPreferred)
|
|
||||||
{
|
|
||||||
fTarget = B_PREFERRED_TOKEN;
|
|
||||||
}
|
|
||||||
// Get the reply requirement flag
|
|
||||||
read_helper(bigFlags);
|
|
||||||
checksum_helper.Cache(bigFlags);
|
|
||||||
fReplyRequired = bigFlags;
|
|
||||||
// Get the reply done flag
|
|
||||||
read_helper(bigFlags);
|
|
||||||
checksum_helper.Cache(bigFlags);
|
|
||||||
fReplyDone = bigFlags;
|
|
||||||
// Get the "is reply" flag
|
|
||||||
read_helper(bigFlags);
|
|
||||||
checksum_helper.Cache(bigFlags);
|
|
||||||
fIsReply = bigFlags;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (status_t& e)
|
|
||||||
{
|
|
||||||
err = e;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (checksum != checksum_helper.CheckSum())
|
|
||||||
err = B_NOT_A_MESSAGE;
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
status_t BMessage::real_flatten(char* result, ssize_t size) const
|
|
||||||
{
|
{
|
||||||
BMemoryIO stream((void*)result, size);
|
BMemoryIO stream((void*)result, size);
|
||||||
status_t err = real_flatten(&stream);
|
return real_flatten(&stream);
|
||||||
|
|
||||||
if (!err)
|
|
||||||
{
|
|
||||||
// Fixup the checksum; it is calculated on data size, what, flags,
|
|
||||||
// and target info (including big flags if appropriate)
|
|
||||||
((uint32*)result)[1] = _checksum_((uchar*)result + (sizeof (uint32) * 2),
|
|
||||||
calc_hdr_size(0) - (sizeof (uint32) * 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
status_t BMessage::real_flatten(BDataIO* stream) const
|
status_t BMessage::real_flatten(BDataIO* stream) const
|
||||||
{
|
{
|
||||||
status_t err = flatten_hdr(stream);
|
Header header(*this);
|
||||||
|
|
||||||
|
status_t err = header.WriteTo(*stream);
|
||||||
|
|
||||||
if (!err)
|
if (!err)
|
||||||
{
|
|
||||||
err = fBody->Flatten(stream);
|
err = fBody->Flatten(stream);
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -1759,19 +1883,6 @@ BMessage::calc_hdr_size(uchar flags) const
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
ssize_t BMessage::min_hdr_size() const
|
|
||||||
{
|
|
||||||
ssize_t size = 0;
|
|
||||||
|
|
||||||
size += 4; // version
|
|
||||||
size += 4; // checksum
|
|
||||||
size += 4; // flattened size
|
|
||||||
size += 4; // 'what'
|
|
||||||
size += 1; // flags
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
status_t BMessage::_send_(port_id port, int32 token, bool preferred,
|
status_t BMessage::_send_(port_id port, int32 token, bool preferred,
|
||||||
bigtime_t timeout, bool reply_required,
|
bigtime_t timeout, bool reply_required,
|
||||||
BMessenger& reply_to) const
|
BMessenger& reply_to) const
|
||||||
@@ -1888,6 +1999,10 @@ error:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Note, that in case of a flattened BMessage setting the target token will
|
||||||
|
// change the header size, if no token was set when the message was flattened.
|
||||||
|
// Hence the message would need to unflattened and flattened again before it
|
||||||
|
// can be sent.
|
||||||
status_t
|
status_t
|
||||||
BMessage::_SendFlattenedMessage(void *data, int32 size, port_id port,
|
BMessage::_SendFlattenedMessage(void *data, int32 size, port_id port,
|
||||||
int32 token, bool preferred, bigtime_t timeout)
|
int32 token, bool preferred, bigtime_t timeout)
|
||||||
@@ -1905,24 +2020,35 @@ BMessage::_SendFlattenedMessage(void *data, int32 size, port_id port,
|
|||||||
header->replyToken = B_NULL_TOKEN;
|
header->replyToken = B_NULL_TOKEN;
|
||||||
|
|
||||||
} else if (*(int32*)data == '1BOF' || *(int32*)data == 'FOB1') {
|
} else if (*(int32*)data == '1BOF' || *(int32*)data == 'FOB1') {
|
||||||
// bool swap = (*(int32*)data == '1BOF');
|
// get the header
|
||||||
// TODO: Replace the target token. This is not so simple, since the
|
BMemoryIO stream(data, size);
|
||||||
// position of the target token is not always the same. It can even
|
Header header;
|
||||||
// happen that no target token is included at all (the one who is
|
status_t error = header.ReadFrom(stream);
|
||||||
// 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)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
// send the message
|
if (!header.HasTarget()) {
|
||||||
BMessenger messenger;
|
// fallback implementation -- the header size would change by
|
||||||
return message._send_(port, token, preferred, timeout, false,
|
// setting the token
|
||||||
messenger);
|
|
||||||
|
// unflatten the message
|
||||||
|
BMessage message;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the target token and replace the header
|
||||||
|
header.SetTarget(token, preferred);
|
||||||
|
stream.Seek(0LL, SEEK_SET);
|
||||||
|
error = header.WriteTo(stream);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
} else {
|
} else {
|
||||||
return B_NOT_A_MESSAGE;
|
return B_NOT_A_MESSAGE;
|
||||||
}
|
}
|
||||||
@@ -2107,3 +2233,17 @@ convert_message(const KMessage *fromMessage, BMessage *toMessage)
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
ssize_t
|
||||||
|
min_hdr_size()
|
||||||
|
{
|
||||||
|
ssize_t size = 0;
|
||||||
|
|
||||||
|
size += 4; // version
|
||||||
|
size += 4; // checksum
|
||||||
|
size += 4; // flattened size
|
||||||
|
size += 4; // 'what'
|
||||||
|
size += 1; // flags
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user