1// Copyright 2013 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 MOJO_SYSTEM_MESSAGE_IN_TRANSIT_H_
6#define MOJO_SYSTEM_MESSAGE_IN_TRANSIT_H_
7
8#include <stddef.h>
9#include <stdint.h>
10
11#include <vector>
12
13#include "base/macros.h"
14#include "base/memory/aligned_memory.h"
15#include "base/memory/scoped_ptr.h"
16#include "mojo/system/dispatcher.h"
17#include "mojo/system/memory.h"
18#include "mojo/system/system_impl_export.h"
19
20namespace mojo {
21namespace system {
22
23class Channel;
24class TransportData;
25
26// This class is used to represent data in transit. It is thread-unsafe.
27//
28// |MessageInTransit| buffers:
29//
30// A |MessageInTransit| can be serialized by writing the main buffer and then,
31// if it has one, the transport data buffer. Both buffers are
32// |kMessageAlignment|-byte aligned and a multiple of |kMessageAlignment| bytes
33// in size.
34//
35// The main buffer consists of the header (of type |Header|, which is an
36// internal detail of this class) followed immediately by the message data
37// (accessed by |bytes()| and of size |num_bytes()|, and also
38// |kMessageAlignment|-byte aligned), and then any padding needed to make the
39// main buffer a multiple of |kMessageAlignment| bytes in size.
40//
41// See |TransportData| for a description of the (serialized) transport data
42// buffer.
43class MOJO_SYSTEM_IMPL_EXPORT MessageInTransit {
44 public:
45  typedef uint16_t Type;
46  // Messages that are forwarded to |MessagePipeEndpoint|s.
47  static const Type kTypeMessagePipeEndpoint = 0;
48  // Messages that are forwarded to |MessagePipe|s.
49  static const Type kTypeMessagePipe = 1;
50  // Messages that are consumed by the |Channel|.
51  static const Type kTypeChannel = 2;
52  // Messages that are consumed by the |RawChannel| (implementation).
53  static const Type kTypeRawChannel = 3;
54
55  typedef uint16_t Subtype;
56  // Subtypes for type |kTypeMessagePipeEndpoint|:
57  static const Subtype kSubtypeMessagePipeEndpointData = 0;
58  // Subtypes for type |kTypeMessagePipe|:
59  // Nothing currently.
60  // Subtypes for type |kTypeChannel|:
61  static const Subtype kSubtypeChannelRunMessagePipeEndpoint = 0;
62  static const Subtype kSubtypeChannelRemoveMessagePipeEndpoint = 1;
63  static const Subtype kSubtypeChannelRemoveMessagePipeEndpointAck = 2;
64  // Subtypes for type |kTypeRawChannel|:
65  static const Subtype kSubtypeRawChannelPosixExtraPlatformHandles = 0;
66
67  typedef uint32_t EndpointId;
68  // Never a valid endpoint ID.
69  static const EndpointId kInvalidEndpointId = 0;
70
71  // Messages (the header and data) must always be aligned to a multiple of this
72  // quantity (which must be a power of 2).
73  static const size_t kMessageAlignment = 8;
74
75  // Forward-declare |Header| so that |View| can use it:
76 private:
77  struct Header;
78
79 public:
80  // This represents a view of serialized message data in a raw buffer.
81  class MOJO_SYSTEM_IMPL_EXPORT View {
82   public:
83    // Constructs a view from the given buffer of the given size. (The size must
84    // be as provided by |MessageInTransit::GetNextMessageSize()|.) The buffer
85    // must remain alive/unmodified through the lifetime of this object.
86    // |buffer| should be |kMessageAlignment|-byte aligned.
87    View(size_t message_size, const void* buffer);
88
89    // Checks that the given |View| appears to be for a valid message, within
90    // predetermined limits (e.g., |num_bytes()| and |main_buffer_size()|, that
91    // |transport_data_buffer()|/|transport_data_buffer_size()| is for valid
92    // transport data -- see |TransportData::ValidateBuffer()|).
93    //
94    // It returns true (and leaves |error_message| alone) if this object appears
95    // to be a valid message (according to the above) and false, pointing
96    // |*error_message| to a suitable error message, if not.
97    bool IsValid(size_t serialized_platform_handle_size,
98                 const char** error_message) const;
99
100    // API parallel to that for |MessageInTransit| itself (mostly getters for
101    // header data).
102    const void* main_buffer() const { return buffer_; }
103    size_t main_buffer_size() const {
104      return RoundUpMessageAlignment(sizeof(Header) + header()->num_bytes);
105    }
106    const void* transport_data_buffer() const {
107      return (total_size() > main_buffer_size())
108                 ? static_cast<const char*>(buffer_) + main_buffer_size()
109                 : nullptr;
110    }
111    size_t transport_data_buffer_size() const {
112      return total_size() - main_buffer_size();
113    }
114    size_t total_size() const { return header()->total_size; }
115    uint32_t num_bytes() const { return header()->num_bytes; }
116    const void* bytes() const {
117      return static_cast<const char*>(buffer_) + sizeof(Header);
118    }
119    Type type() const { return header()->type; }
120    Subtype subtype() const { return header()->subtype; }
121    EndpointId source_id() const { return header()->source_id; }
122    EndpointId destination_id() const { return header()->destination_id; }
123
124   private:
125    const Header* header() const { return static_cast<const Header*>(buffer_); }
126
127    const void* const buffer_;
128
129    // Though this struct is trivial, disallow copy and assign, since it doesn't
130    // own its data. (If you're copying/assigning this, you're probably doing
131    // something wrong.)
132    DISALLOW_COPY_AND_ASSIGN(View);
133  };
134
135  // |bytes| is optional; if null, the message data will be zero-initialized.
136  MessageInTransit(Type type,
137                   Subtype subtype,
138                   uint32_t num_bytes,
139                   const void* bytes);
140  // |bytes| should be valid (and non-null), unless |num_bytes| is zero.
141  MessageInTransit(Type type,
142                   Subtype subtype,
143                   uint32_t num_bytes,
144                   UserPointer<const void> bytes);
145  // Constructs a |MessageInTransit| from a |View|.
146  explicit MessageInTransit(const View& message_view);
147
148  ~MessageInTransit();
149
150  // Gets the size of the next message from |buffer|, which has |buffer_size|
151  // bytes currently available, returning true and setting |*next_message_size|
152  // on success. |buffer| should be aligned on a |kMessageAlignment| boundary
153  // (and on success, |*next_message_size| will be a multiple of
154  // |kMessageAlignment|).
155  // TODO(vtl): In |RawChannelPosix|, the alignment requirements are currently
156  // satisified on a faith-based basis.
157  static bool GetNextMessageSize(const void* buffer,
158                                 size_t buffer_size,
159                                 size_t* next_message_size);
160
161  // Makes this message "own" the given set of dispatchers. The dispatchers must
162  // not be referenced from anywhere else (in particular, not from the handle
163  // table), i.e., each dispatcher must have a reference count of 1. This
164  // message must not already have dispatchers.
165  void SetDispatchers(scoped_ptr<DispatcherVector> dispatchers);
166
167  // Sets the |TransportData| for this message. This should only be done when
168  // there are no dispatchers and no existing |TransportData|.
169  void SetTransportData(scoped_ptr<TransportData> transport_data);
170
171  // Serializes any dispatchers to the secondary buffer. This message must not
172  // already have a secondary buffer (so this must only be called once). The
173  // caller must ensure (e.g., by holding on to a reference) that |channel|
174  // stays alive through the call.
175  void SerializeAndCloseDispatchers(Channel* channel);
176
177  // Gets the main buffer and its size (in number of bytes), respectively.
178  const void* main_buffer() const { return main_buffer_.get(); }
179  size_t main_buffer_size() const { return main_buffer_size_; }
180
181  // Gets the transport data buffer (if any).
182  const TransportData* transport_data() const { return transport_data_.get(); }
183  TransportData* transport_data() { return transport_data_.get(); }
184
185  // Gets the total size of the message (see comment in |Header|, below).
186  size_t total_size() const { return header()->total_size; }
187
188  // Gets the size of the message data.
189  uint32_t num_bytes() const { return header()->num_bytes; }
190
191  // Gets the message data (of size |num_bytes()| bytes).
192  const void* bytes() const { return main_buffer_.get() + sizeof(Header); }
193  void* bytes() { return main_buffer_.get() + sizeof(Header); }
194
195  Type type() const { return header()->type; }
196  Subtype subtype() const { return header()->subtype; }
197  EndpointId source_id() const { return header()->source_id; }
198  EndpointId destination_id() const { return header()->destination_id; }
199
200  void set_source_id(EndpointId source_id) { header()->source_id = source_id; }
201  void set_destination_id(EndpointId destination_id) {
202    header()->destination_id = destination_id;
203  }
204
205  // Gets the dispatchers attached to this message; this may return null if
206  // there are none. Note that the caller may mutate the set of dispatchers
207  // (e.g., take ownership of all the dispatchers, leaving the vector empty).
208  DispatcherVector* dispatchers() { return dispatchers_.get(); }
209
210  // Returns true if this message has dispatchers attached.
211  bool has_dispatchers() const {
212    return dispatchers_ && !dispatchers_->empty();
213  }
214
215  // Rounds |n| up to a multiple of |kMessageAlignment|.
216  static inline size_t RoundUpMessageAlignment(size_t n) {
217    return (n + kMessageAlignment - 1) & ~(kMessageAlignment - 1);
218  }
219
220 private:
221  // To allow us to make compile-assertions about |Header| in the .cc file.
222  struct PrivateStructForCompileAsserts;
223
224  // Header for the data (main buffer). Must be a multiple of
225  // |kMessageAlignment| bytes in size. Must be POD.
226  struct Header {
227    // Total size of the message, including the header, the message data
228    // ("bytes") including padding (to make it a multiple of |kMessageAlignment|
229    // bytes), and serialized handle information. Note that this may not be the
230    // correct value if dispatchers are attached but
231    // |SerializeAndCloseDispatchers()| has not been called.
232    uint32_t total_size;
233    Type type;                  // 2 bytes.
234    Subtype subtype;            // 2 bytes.
235    EndpointId source_id;       // 4 bytes.
236    EndpointId destination_id;  // 4 bytes.
237    // Size of actual message data.
238    uint32_t num_bytes;
239    uint32_t unused;
240  };
241
242  const Header* header() const {
243    return reinterpret_cast<const Header*>(main_buffer_.get());
244  }
245  Header* header() { return reinterpret_cast<Header*>(main_buffer_.get()); }
246
247  void ConstructorHelper(Type type, Subtype subtype, uint32_t num_bytes);
248  void UpdateTotalSize();
249
250  const size_t main_buffer_size_;
251  const scoped_ptr<char, base::AlignedFreeDeleter> main_buffer_;  // Never null.
252
253  scoped_ptr<TransportData> transport_data_;  // May be null.
254
255  // Any dispatchers that may be attached to this message. These dispatchers
256  // should be "owned" by this message, i.e., have a ref count of exactly 1. (We
257  // allow a dispatcher entry to be null, in case it couldn't be duplicated for
258  // some reason.)
259  scoped_ptr<DispatcherVector> dispatchers_;
260
261  DISALLOW_COPY_AND_ASSIGN(MessageInTransit);
262};
263
264}  // namespace system
265}  // namespace mojo
266
267#endif  // MOJO_SYSTEM_MESSAGE_IN_TRANSIT_H_
268