1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CHROMECAST_MEDIA_CMA_IPC_MEDIA_MESSAGE_H_
6#define CHROMECAST_MEDIA_CMA_IPC_MEDIA_MESSAGE_H_
7
8#include <stddef.h>
9
10#include "base/basictypes.h"
11#include "base/callback.h"
12#include "base/macros.h"
13#include "base/memory/scoped_ptr.h"
14
15namespace chromecast {
16namespace media {
17class MediaMemoryChunk;
18
19// MediaMessage -
20// Represents a media message, including:
21// - a message header that gives for example the message size or its type,
22// - the content of the message,
23// - and some possible padding if the content does not occupy the whole
24//   reserved space.
25//
26class MediaMessage {
27 public:
28  // Memory allocator: given a number of bytes to allocate,
29  // return the pointer to the allocated block if successful
30  // or NULL if allocation failed.
31  typedef base::Callback<scoped_ptr<MediaMemoryChunk>(size_t)>
32      MemoryAllocatorCB;
33
34  // Creates a message with no associated memory for its content, i.e.
35  // each write on this message is a dummy operation.
36  // This type of message can be useful to calculate first the size of the
37  // message, before allocating the real message.
38  static scoped_ptr<MediaMessage> CreateDummyMessage(uint32 type);
39
40  // Creates a message with a capacity of at least |msg_content_capacity|
41  // bytes. The actual content size can be smaller than its capacity.
42  // The message can be populated with some Write functions.
43  static scoped_ptr<MediaMessage> CreateMessage(
44      uint32 type,
45      const MemoryAllocatorCB& memory_allocator,
46      size_t msg_content_capacity);
47
48  // Creates a message of type |type| whose serialized structure is stored
49  // in |mem|.
50  static scoped_ptr<MediaMessage> CreateMessage(
51      uint32 type,
52      scoped_ptr<MediaMemoryChunk> mem);
53
54  // Creates a message from a memory area which already contains
55  // the serialized structure of the message.
56  // Only Read functions can be invoked on this type of message.
57  static scoped_ptr<MediaMessage> MapMessage(
58      scoped_ptr<MediaMemoryChunk> mem);
59
60  // Return the minimum size of a message.
61  static size_t minimum_msg_size() {
62    return offsetof(SerializedMsg, content);
63  }
64
65  ~MediaMessage();
66
67  // Indicate whether the underlying serialized structure of the message is
68  // available.
69  // Note: the serialized structure might be unavailable in case of a dummy
70  // message or if the underlying memory has been invalidated.
71  bool IsSerializedMsgAvailable() const;
72
73  // Return the message and the total size of the message
74  // incuding the header, the content and the possible padding.
75  const void* msg() const { return msg_read_only_; }
76  size_t size() const { return cached_msg_.header.size; }
77
78  // Return the size of the message without padding.
79  size_t actual_size() const {
80    return minimum_msg_size() + cached_msg_.header.content_size;
81  }
82
83  // Return the size of the content of the message.
84  size_t content_size() const { return cached_msg_.header.content_size; }
85
86  // Return the type of the message.
87  uint32 type() const { return cached_msg_.header.type; }
88
89  // Append a POD to the message.
90  // Return true if the POD has been succesfully written.
91  template<typename T> bool WritePod(T* const& pod);
92  template<typename T> bool WritePod(const T& pod) {
93    return WriteBuffer(&pod, sizeof(T));
94  }
95
96  // Append a raw buffer to the message.
97  bool WriteBuffer(const void* src, size_t size);
98
99  // Read a POD from the message.
100  template<typename T> bool ReadPod(T* pod) {
101    return ReadBuffer(pod, sizeof(T));
102  }
103
104  // Read |size| bytes from the message from the last read position
105  // and write it to |dst|.
106  bool ReadBuffer(void* dst, size_t size);
107
108  // Return a pointer to a buffer of size |size|.
109  // Return NULL if not successful.
110  const void* GetBuffer(size_t size);
111  void* GetWritableBuffer(size_t size);
112
113 private:
114  MediaMessage(uint32 type, size_t msg_size);
115  MediaMessage(uint32 type, scoped_ptr<MediaMemoryChunk> memory);
116  MediaMessage(scoped_ptr<MediaMemoryChunk> memory);
117
118  struct Header {
119    // Total size of the message (including both header & content).
120    uint32 size;
121    // Indicate the message type.
122    uint32 type;
123    // Actual size of the content in the message.
124    uint32 content_size;
125  };
126
127  struct SerializedMsg {
128    // Message header.
129    Header header;
130
131    // Start of the content of the message.
132    // Use uint8_t since no special alignment is needed.
133    uint8 content;
134  };
135
136  // Indicate whether the message is a dummy message, i.e. a message without
137  // a complete underlying serialized structure: only the message header is
138  // available.
139  bool is_dummy_msg_;
140
141  // |cached_msg_| is used for 2 purposes:
142  // - to create a dummy message
143  // - for security purpose: cache the msg header to avoid browser security
144  // issues.
145  SerializedMsg cached_msg_;
146  Header* const cached_header_;
147
148  SerializedMsg* msg_;
149  SerializedMsg* msg_read_only_;
150
151  // Memory allocated to store the underlying serialized structure into memory.
152  // Note: a dummy message has no underlying serialized structure:
153  // |mem_| is a null pointer in that case.
154  scoped_ptr<MediaMemoryChunk> mem_;
155
156  // Read iterator into the message.
157  size_t rd_offset_;
158
159  DISALLOW_COPY_AND_ASSIGN(MediaMessage);
160};
161
162}  // namespace media
163}  // namespace chromecast
164
165#endif
166