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