Merge from Widevine repo of http://go/wvgerrit/121950 Remove term "Master" from "Widevine Master License Agreement". Bug: 168562298 Change-Id: I655babf1bc447f4872f6a0f849107262be42df7a
172 lines
5.7 KiB
C
172 lines
5.7 KiB
C
/*
|
|
* Copyright 2019 Google LLC. All Rights Reserved. This file and proprietary
|
|
* source code may only be used and distributed under the Widevine
|
|
* License Agreement.
|
|
*/
|
|
|
|
#include "odk_message.h"
|
|
#include "odk_message_priv.h"
|
|
|
|
#include <assert.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
/*
|
|
* C11 defines static_assert in assert.h. If it is available, force a compile
|
|
* time error if the abstract ODK_Message struct size does not match its
|
|
* implementation. If static_assert is not available, the runtime assert in
|
|
* InitMessage will catch the mismatch at the time a message is initialized.
|
|
*/
|
|
#ifdef static_assert
|
|
static_assert(
|
|
sizeof(ODK_Message) >= sizeof(ODK_Message_Impl),
|
|
"sizeof(ODK_Message) is too small. You can increase "
|
|
"SIZE_OF_ODK_MESSAGE_IMPL in odk_message.h to make it large enough.");
|
|
#endif
|
|
|
|
/*
|
|
* Create a message structure that references a separate data buffer. An
|
|
* initialized message is returned. The caller is responsible for ensuring that
|
|
* the buffer remains allocated for the lifetime of the message. |buffer| may be
|
|
* NULL. Serialization into a message with a NULL buffer will cause the message
|
|
* size to be incremented, but no data will be written into the message
|
|
* buffer. This is useful for calculating the amount of space a message will
|
|
* need, prior to doing the actual serialization. The buffer contents are
|
|
* unchanged by this function.
|
|
*/
|
|
ODK_Message ODK_Message_Create(uint8_t* buffer, size_t capacity) {
|
|
assert(sizeof(ODK_Message) >= sizeof(ODK_Message_Impl));
|
|
ODK_Message message;
|
|
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)&message;
|
|
message_impl->base = buffer;
|
|
message_impl->capacity = capacity;
|
|
message_impl->size = 0;
|
|
message_impl->read_offset = 0;
|
|
message_impl->status = MESSAGE_STATUS_OK;
|
|
return message;
|
|
}
|
|
|
|
/*
|
|
* Erase the contents of the message, set it to an empty state by setting the
|
|
* message size and read offset to 0, effectively erasing the contents of the
|
|
* message. The message data buffer pointer remains unchanged, i.e. the message
|
|
* retains ownership of the buffer. The message buffer is zero-filled. The
|
|
* message status is reset to MESSAGE_STATUS_OK.
|
|
*/
|
|
void ODK_Message_Clear(ODK_Message* message) {
|
|
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
|
|
assert(message_impl != NULL);
|
|
message_impl->read_offset = 0;
|
|
message_impl->size = 0;
|
|
message_impl->status = MESSAGE_STATUS_OK;
|
|
if (message_impl->base) {
|
|
memset(message_impl->base, 0, message_impl->capacity);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Reset read pointer to the beginning of the message and clear status
|
|
* so that parsing of the message will restart at the beginning of the
|
|
* message. The message status is reset to MESSAGE_STATUS_OK.
|
|
*/
|
|
void ODK_Message_Reset(ODK_Message* message) {
|
|
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
|
|
assert(message_impl != NULL);
|
|
message_impl->read_offset = 0;
|
|
message_impl->status = MESSAGE_STATUS_OK;
|
|
}
|
|
|
|
/*
|
|
* Return a pointer to the message data buffer, i.e. the message payload.
|
|
* This is the buffer address that was passed into ODK_Message_Create.
|
|
*/
|
|
uint8_t* ODK_Message_GetBase(ODK_Message* message) {
|
|
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
|
|
assert(message_impl != NULL);
|
|
return message_impl->base;
|
|
}
|
|
|
|
/*
|
|
* Get the maximum number of bytes the message can hold.
|
|
*/
|
|
size_t ODK_Message_GetCapacity(ODK_Message* message) {
|
|
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
|
|
assert(message_impl != NULL);
|
|
return message_impl->capacity;
|
|
}
|
|
|
|
/*
|
|
* Get the number of bytes currently in the message
|
|
*/
|
|
size_t ODK_Message_GetSize(ODK_Message* message) {
|
|
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
|
|
assert(message_impl != NULL);
|
|
return message_impl->size;
|
|
}
|
|
|
|
/*
|
|
* Get the offset of where the next bytes will be read from the message data
|
|
* buffer.
|
|
*/
|
|
size_t ODK_Message_GetOffset(ODK_Message* message) {
|
|
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
|
|
assert(message_impl != NULL);
|
|
return message_impl->read_offset;
|
|
}
|
|
|
|
/*
|
|
* Return the status of the message
|
|
*/
|
|
ODK_MessageStatus ODK_Message_GetStatus(ODK_Message* message) {
|
|
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
|
|
assert(message_impl != NULL);
|
|
return message_impl->status;
|
|
}
|
|
|
|
/*
|
|
* Set the message status to a specific value
|
|
*/
|
|
void ODK_Message_SetStatus(ODK_Message* message, ODK_MessageStatus status) {
|
|
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
|
|
assert(message_impl != NULL);
|
|
/* preserve the first error */
|
|
if (message_impl->status == MESSAGE_STATUS_OK) {
|
|
message_impl->status = status;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Set the size of the message to a value. This may be needed after writing data
|
|
* into the message data buffer.
|
|
*/
|
|
void ODK_Message_SetSize(ODK_Message* message, size_t size) {
|
|
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
|
|
assert(message_impl != NULL);
|
|
assert(size <= message_impl->capacity);
|
|
message_impl->size = size;
|
|
}
|
|
|
|
/*
|
|
* Test if the integrity of a message. This means that the status must be
|
|
* MESSAGE_STATUS_OK and that the base, read_offset, size and capacity of the
|
|
* message are within the range of valid values. The message's base pointer
|
|
* may be NULL if the buffer has not been assigned yet, that is not invalid.
|
|
*/
|
|
bool ODK_Message_IsValid(ODK_Message* message) {
|
|
assert(message);
|
|
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
|
|
if (message_impl == NULL) {
|
|
return false;
|
|
}
|
|
if (message_impl->status != MESSAGE_STATUS_OK) {
|
|
return false;
|
|
}
|
|
if (message_impl->read_offset > message_impl->capacity ||
|
|
message_impl->size > message_impl->capacity ||
|
|
message_impl->read_offset > message_impl->size) {
|
|
message_impl->status = MESSAGE_STATUS_OVERFLOW_ERROR;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|