// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROMECAST_MEDIA_CMA_IPC_MEDIA_MESSAGE_H_
#define CHROMECAST_MEDIA_CMA_IPC_MEDIA_MESSAGE_H_
#include <stddef.h>
#include "base/basictypes.h"
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
namespace chromecast {
namespace media {
class MediaMemoryChunk;
// MediaMessage -
// Represents a media message, including:
// - a message header that gives for example the message size or its type,
// - the content of the message,
// - and some possible padding if the content does not occupy the whole
// reserved space.
//
class MediaMessage {
public:
// Memory allocator: given a number of bytes to allocate,
// return the pointer to the allocated block if successful
// or NULL if allocation failed.
typedef base::Callback<scoped_ptr<MediaMemoryChunk>(size_t)>
MemoryAllocatorCB;
// Creates a message with no associated memory for its content, i.e.
// each write on this message is a dummy operation.
// This type of message can be useful to calculate first the size of the
// message, before allocating the real message.
static scoped_ptr<MediaMessage> CreateDummyMessage(uint32 type);
// Creates a message with a capacity of at least |msg_content_capacity|
// bytes. The actual content size can be smaller than its capacity.
// The message can be populated with some Write functions.
static scoped_ptr<MediaMessage> CreateMessage(
uint32 type,
const MemoryAllocatorCB& memory_allocator,
size_t msg_content_capacity);
// Creates a message of type |type| whose serialized structure is stored
// in |mem|.
static scoped_ptr<MediaMessage> CreateMessage(
uint32 type,
scoped_ptr<MediaMemoryChunk> mem);
// Creates a message from a memory area which already contains
// the serialized structure of the message.
// Only Read functions can be invoked on this type of message.
static scoped_ptr<MediaMessage> MapMessage(
scoped_ptr<MediaMemoryChunk> mem);
// Return the minimum size of a message.
static size_t minimum_msg_size() {
return offsetof(SerializedMsg, content);
}
~MediaMessage();
// Indicate whether the underlying serialized structure of the message is
// available.
// Note: the serialized structure might be unavailable in case of a dummy
// message or if the underlying memory has been invalidated.
bool IsSerializedMsgAvailable() const;
// Return the message and the total size of the message
// incuding the header, the content and the possible padding.
const void* msg() const { return msg_read_only_; }
size_t size() const { return cached_msg_.header.size; }
// Return the size of the message without padding.
size_t actual_size() const {
return minimum_msg_size() + cached_msg_.header.content_size;
}
// Return the size of the content of the message.
size_t content_size() const { return cached_msg_.header.content_size; }
// Return the type of the message.
uint32 type() const { return cached_msg_.header.type; }
// Append a POD to the message.
// Return true if the POD has been succesfully written.
template<typename T> bool WritePod(T* const& pod);
template<typename T> bool WritePod(const T& pod) {
return WriteBuffer(&pod, sizeof(T));
}
// Append a raw buffer to the message.
bool WriteBuffer(const void* src, size_t size);
// Read a POD from the message.
template<typename T> bool ReadPod(T* pod) {
return ReadBuffer(pod, sizeof(T));
}
// Read |size| bytes from the message from the last read position
// and write it to |dst|.
bool ReadBuffer(void* dst, size_t size);
// Return a pointer to a buffer of size |size|.
// Return NULL if not successful.
const void* GetBuffer(size_t size);
void* GetWritableBuffer(size_t size);
private:
MediaMessage(uint32 type, size_t msg_size);
MediaMessage(uint32 type, scoped_ptr<MediaMemoryChunk> memory);
MediaMessage(scoped_ptr<MediaMemoryChunk> memory);
struct Header {
// Total size of the message (including both header & content).
uint32 size;
// Indicate the message type.
uint32 type;
// Actual size of the content in the message.
uint32 content_size;
};
struct SerializedMsg {
// Message header.
Header header;
// Start of the content of the message.
// Use uint8_t since no special alignment is needed.
uint8 content;
};
// Indicate whether the message is a dummy message, i.e. a message without
// a complete underlying serialized structure: only the message header is
// available.
bool is_dummy_msg_;
// |cached_msg_| is used for 2 purposes:
// - to create a dummy message
// - for security purpose: cache the msg header to avoid browser security
// issues.
SerializedMsg cached_msg_;
Header* const cached_header_;
SerializedMsg* msg_;
SerializedMsg* msg_read_only_;
// Memory allocated to store the underlying serialized structure into memory.
// Note: a dummy message has no underlying serialized structure:
// |mem_| is a null pointer in that case.
scoped_ptr<MediaMemoryChunk> mem_;
// Read iterator into the message.
size_t rd_offset_;
DISALLOW_COPY_AND_ASSIGN(MediaMessage);
};
} // namespace media
} // namespace chromecast
#endif