* Fixed some bugs noticed by rereading the whole implementation
* Added checksum generation and checking The data itself is now checksummed too (unlike R5 where only the header gets a checksum). This might be a performance problem for larger messages. Opinions? git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16482 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -63,6 +63,9 @@ struct BMessage::message_header {
|
|||||||
ssize_t fields_available;
|
ssize_t fields_available;
|
||||||
ssize_t data_available;
|
ssize_t data_available;
|
||||||
|
|
||||||
|
uint32 fields_checksum;
|
||||||
|
uint32 data_checksum;
|
||||||
|
|
||||||
int32 target;
|
int32 target;
|
||||||
int32 current_specifier;
|
int32 current_specifier;
|
||||||
area_id shared_area;
|
area_id shared_area;
|
||||||
|
|||||||
+36
-11
@@ -120,7 +120,7 @@ BMessage::operator=(const BMessage &other)
|
|||||||
fHeader->shared_area = -1;
|
fHeader->shared_area = -1;
|
||||||
fHeader->fields_available = 0;
|
fHeader->fields_available = 0;
|
||||||
fHeader->data_available = 0;
|
fHeader->data_available = 0;
|
||||||
what = fHeader->what;
|
fHeader->what = what = other.what;
|
||||||
fQueueLink = other.fQueueLink;
|
fQueueLink = other.fQueueLink;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -176,6 +176,7 @@ BMessage::_InitHeader()
|
|||||||
|
|
||||||
fHeader->format = kMessageMagic4;
|
fHeader->format = kMessageMagic4;
|
||||||
fHeader->flags = MESSAGE_FLAG_VALID;
|
fHeader->flags = MESSAGE_FLAG_VALID;
|
||||||
|
fHeader->what = what;
|
||||||
fHeader->current_specifier = -1;
|
fHeader->current_specifier = -1;
|
||||||
fHeader->shared_area = -1;
|
fHeader->shared_area = -1;
|
||||||
|
|
||||||
@@ -801,6 +802,8 @@ BMessage::_NativeFlatten(char *buffer, ssize_t size) const
|
|||||||
|
|
||||||
/* we have to sync the what code as it is a public member */
|
/* we have to sync the what code as it is a public member */
|
||||||
fHeader->what = what;
|
fHeader->what = what;
|
||||||
|
fHeader->fields_checksum = BPrivate::CalculateChecksum((uint8 *)fFields, fHeader->fields_size);
|
||||||
|
fHeader->data_checksum = BPrivate::CalculateChecksum((uint8 *)fData, fHeader->data_size);
|
||||||
|
|
||||||
memcpy(buffer, fHeader, min_c(sizeof(message_header), (size_t)size));
|
memcpy(buffer, fHeader, min_c(sizeof(message_header), (size_t)size));
|
||||||
buffer += sizeof(message_header);
|
buffer += sizeof(message_header);
|
||||||
@@ -830,6 +833,8 @@ BMessage::_NativeFlatten(BDataIO *stream, ssize_t *size) const
|
|||||||
|
|
||||||
/* we have to sync the what code as it is a public member */
|
/* we have to sync the what code as it is a public member */
|
||||||
fHeader->what = what;
|
fHeader->what = what;
|
||||||
|
fHeader->fields_checksum = BPrivate::CalculateChecksum((uint8 *)fFields, fHeader->fields_size);
|
||||||
|
fHeader->data_checksum = BPrivate::CalculateChecksum((uint8 *)fData, fHeader->data_size);
|
||||||
|
|
||||||
ssize_t result1 = stream->Write(fHeader, sizeof(message_header));
|
ssize_t result1 = stream->Write(fHeader, sizeof(message_header));
|
||||||
if (result1 != sizeof(message_header))
|
if (result1 != sizeof(message_header))
|
||||||
@@ -903,7 +908,6 @@ BMessage::Unflatten(const char *flatBuffer)
|
|||||||
fHeader->data_available = 0;
|
fHeader->data_available = 0;
|
||||||
what = fHeader->what;
|
what = fHeader->what;
|
||||||
|
|
||||||
/* ToDo: better message validation (checksum) */
|
|
||||||
if (fHeader->format != kMessageMagic4 ||
|
if (fHeader->format != kMessageMagic4 ||
|
||||||
!(fHeader->flags & MESSAGE_FLAG_VALID)) {
|
!(fHeader->flags & MESSAGE_FLAG_VALID)) {
|
||||||
_Clear();
|
_Clear();
|
||||||
@@ -928,6 +932,14 @@ BMessage::Unflatten(const char *flatBuffer)
|
|||||||
memcpy(fData, flatBuffer, fHeader->data_size);
|
memcpy(fData, flatBuffer, fHeader->data_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fHeader->fields_checksum != BPrivate::CalculateChecksum((uint8 *)fFields, fHeader->fields_size)
|
||||||
|
|| fHeader->data_checksum != BPrivate::CalculateChecksum((uint8 *)fData, fHeader->data_size)) {
|
||||||
|
debug_printf("checksum mismatch\n");
|
||||||
|
_Clear();
|
||||||
|
_InitHeader();
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -975,7 +987,6 @@ BMessage::Unflatten(BDataIO *stream)
|
|||||||
return (result >= 0 ? B_ERROR : result);
|
return (result >= 0 ? B_ERROR : result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ToDo: better message validation (checksum) */
|
|
||||||
if (fHeader->format != kMessageMagic4 ||
|
if (fHeader->format != kMessageMagic4 ||
|
||||||
!(fHeader->flags & MESSAGE_FLAG_VALID)) {
|
!(fHeader->flags & MESSAGE_FLAG_VALID)) {
|
||||||
_Clear();
|
_Clear();
|
||||||
@@ -1009,6 +1020,14 @@ BMessage::Unflatten(BDataIO *stream)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fHeader->fields_checksum != BPrivate::CalculateChecksum((uint8 *)fFields, fHeader->fields_size)
|
||||||
|
|| fHeader->data_checksum != BPrivate::CalculateChecksum((uint8 *)fData, fHeader->data_size)) {
|
||||||
|
debug_printf("checksum mismatch\n");
|
||||||
|
_Clear();
|
||||||
|
_InitHeader();
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1035,6 +1054,7 @@ BMessage::AddSpecifier(const char *property, int32 index)
|
|||||||
if (result < B_OK)
|
if (result < B_OK)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
result = message.AddInt32("index", index);
|
||||||
if (result < B_OK)
|
if (result < B_OK)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
@@ -1206,6 +1226,10 @@ BMessage::_FlattenToArea(message_header **_header) const
|
|||||||
DEBUG_FUNCTION_ENTER;
|
DEBUG_FUNCTION_ENTER;
|
||||||
message_header *header = (message_header *)malloc(sizeof(message_header));
|
message_header *header = (message_header *)malloc(sizeof(message_header));
|
||||||
memcpy(header, fHeader, sizeof(message_header));
|
memcpy(header, fHeader, sizeof(message_header));
|
||||||
|
|
||||||
|
header->what = what;
|
||||||
|
header->fields_available = 0;
|
||||||
|
header->data_available = 0;
|
||||||
*_header = header;
|
*_header = header;
|
||||||
|
|
||||||
if (header->shared_area >= B_OK)
|
if (header->shared_area >= B_OK)
|
||||||
@@ -1215,8 +1239,8 @@ BMessage::_FlattenToArea(message_header **_header) const
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
uint8 *address = NULL;
|
uint8 *address = NULL;
|
||||||
ssize_t size = sizeof(int32) + header->fields_size + header->data_size;
|
ssize_t size = header->fields_size + header->data_size;
|
||||||
size = ((size + B_PAGE_SIZE) & ~(B_PAGE_SIZE - 1)) + B_PAGE_SIZE;
|
size = (size + B_PAGE_SIZE) & ~(B_PAGE_SIZE - 1);
|
||||||
area_id area = create_area("Shared BMessage data", (void **)&address,
|
area_id area = create_area("Shared BMessage data", (void **)&address,
|
||||||
B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
|
B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
|
||||||
|
|
||||||
@@ -1228,15 +1252,16 @@ BMessage::_FlattenToArea(message_header **_header) const
|
|||||||
|
|
||||||
if (header->fields_size > 0) {
|
if (header->fields_size > 0) {
|
||||||
memcpy(address, fFields, header->fields_size);
|
memcpy(address, fFields, header->fields_size);
|
||||||
|
header->fields_checksum = BPrivate::CalculateChecksum((uint8 *)address, header->fields_size);
|
||||||
address += header->fields_size;
|
address += header->fields_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header->data_size > 0)
|
if (header->data_size > 0) {
|
||||||
memcpy(address, fData, header->data_size);
|
memcpy(address, fData, header->data_size);
|
||||||
|
header->data_checksum = BPrivate::CalculateChecksum((uint8 *)address, header->data_size);
|
||||||
|
}
|
||||||
|
|
||||||
header->shared_area = area;
|
header->shared_area = area;
|
||||||
header->fields_available = 0;
|
|
||||||
header->data_available = 0;
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1285,6 +1310,7 @@ BMessage::_Reference(message_header *header)
|
|||||||
what = fHeader->what;
|
what = fHeader->what;
|
||||||
|
|
||||||
if (fHeader->shared_area < B_OK) {
|
if (fHeader->shared_area < B_OK) {
|
||||||
|
/* if there is no data at all we don't need the area */
|
||||||
if (fHeader->fields_size == 0 && header->data_size == 0)
|
if (fHeader->fields_size == 0 && header->data_size == 0)
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
@@ -1305,7 +1331,6 @@ BMessage::_Reference(message_header *header)
|
|||||||
fFields = (field_header *)address;
|
fFields = (field_header *)address;
|
||||||
address += fHeader->fields_size;
|
address += fHeader->fields_size;
|
||||||
fData = address;
|
fData = address;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2511,10 +2536,10 @@ BMessage::ReplaceMessage(const char *name, const BMessage *message)
|
|||||||
status_t
|
status_t
|
||||||
BMessage::ReplaceMessage(const char *name, int32 index, const BMessage *message)
|
BMessage::ReplaceMessage(const char *name, int32 index, const BMessage *message)
|
||||||
{
|
{
|
||||||
ssize_t size = message->FlattenedSize();
|
ssize_t size = message->_NativeFlattenedSize();
|
||||||
char buffer[size];
|
char buffer[size];
|
||||||
|
|
||||||
status_t error = message->Flatten(buffer, size);
|
status_t error = message->_NativeFlatten(buffer, size);
|
||||||
|
|
||||||
if (error >= B_OK)
|
if (error >= B_OK)
|
||||||
error = ReplaceData(name, B_MESSAGE_TYPE, index, &buffer, size);
|
error = ReplaceData(name, B_MESSAGE_TYPE, index, &buffer, size);
|
||||||
|
|||||||
Reference in New Issue
Block a user