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.
5 #ifndef MOJO_SYSTEM_MESSAGE_IN_TRANSIT_H_
6 #define MOJO_SYSTEM_MESSAGE_IN_TRANSIT_H_
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"
25 // This class is used to represent data in transit. It is thread-unsafe.
27 // |MessageInTransit| buffers:
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
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.
40 // See |TransportData| for a description of the (serialized) transport data
42 class MOJO_SYSTEM_IMPL_EXPORT MessageInTransit
{
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;
54 typedef uint16_t Subtype
;
55 // Subtypes for type |kTypeMessagePipeEndpoint|:
56 static const Subtype kSubtypeMessagePipeEndpointData
= 0;
57 // Subtypes for type |kTypeMessagePipe|:
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;
66 typedef uint32_t EndpointId
;
67 // Never a valid endpoint ID.
68 static const EndpointId kInvalidEndpointId
= 0;
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;
74 // Forward-declare |Header| so that |View| can use it:
78 // This represents a view of serialized message data in a raw buffer.
79 class MOJO_SYSTEM_IMPL_EXPORT View
{
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
);
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()|).
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;
98 // API parallel to that for |MessageInTransit| itself (mostly getters for
100 const void* main_buffer() const { return buffer_
; }
101 size_t main_buffer_size() const {
102 return RoundUpMessageAlignment(sizeof(Header
) + header()->num_bytes
);
104 const void* transport_data_buffer() const {
105 return (total_size() > main_buffer_size()) ?
106 static_cast<const char*>(buffer_
) + main_buffer_size() : NULL
;
108 size_t transport_data_buffer_size() const {
109 return total_size() - main_buffer_size();
111 size_t total_size() const { return header()->total_size
; }
112 uint32_t num_bytes() const { return header()->num_bytes
; }
113 const void* bytes() const {
114 return static_cast<const char*>(buffer_
) + sizeof(Header
);
116 Type
type() const { return header()->type
; }
117 Subtype
subtype() const { return header()->subtype
; }
118 EndpointId
source_id() const { return header()->source_id
; }
119 EndpointId
destination_id() const { return header()->destination_id
; }
122 const Header
* header() const { return static_cast<const Header
*>(buffer_
); }
124 const void* const buffer_
;
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
129 DISALLOW_COPY_AND_ASSIGN(View
);
132 // |bytes| is optional; if null, the message data will be zero-initialized.
133 MessageInTransit(Type type
,
137 // Constructs a |MessageInTransit| from a |View|.
138 explicit MessageInTransit(const View
& message_view
);
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
,
151 size_t* next_message_size
);
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
);
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
);
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
);
169 // Gets the main buffer and its size (in number of bytes), respectively.
170 const void* main_buffer() const { return main_buffer_
.get(); }
171 size_t main_buffer_size() const { return main_buffer_size_
; }
173 // Gets the transport data buffer (if any).
174 const TransportData
* transport_data() const { return transport_data_
.get(); }
175 TransportData
* transport_data() { return transport_data_
.get(); }
177 // Gets the total size of the message (see comment in |Header|, below).
178 size_t total_size() const { return header()->total_size
; }
180 // Gets the size of the message data.
181 uint32_t num_bytes() const { return header()->num_bytes
; }
183 // Gets the message data (of size |num_bytes()| bytes).
184 const void* bytes() const { return main_buffer_
.get() + sizeof(Header
); }
185 void* bytes() { return main_buffer_
.get() + sizeof(Header
); }
187 Type
type() const { return header()->type
; }
188 Subtype
subtype() const { return header()->subtype
; }
189 EndpointId
source_id() const { return header()->source_id
; }
190 EndpointId
destination_id() const { return header()->destination_id
; }
192 void set_source_id(EndpointId source_id
) { header()->source_id
= source_id
; }
193 void set_destination_id(EndpointId destination_id
) {
194 header()->destination_id
= destination_id
;
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).
200 DispatcherVector
* dispatchers() { return dispatchers_
.get(); }
202 // Returns true if this message has dispatchers attached.
203 bool has_dispatchers() const {
204 return dispatchers_
&& !dispatchers_
->empty();
207 // Rounds |n| up to a multiple of |kMessageAlignment|.
208 static inline size_t RoundUpMessageAlignment(size_t n
) {
209 return (n
+ kMessageAlignment
- 1) & ~(kMessageAlignment
- 1);
213 // To allow us to make compile-assertions about |Header| in the .cc file.
214 struct PrivateStructForCompileAsserts
;
216 // Header for the data (main buffer). Must be a multiple of
217 // |kMessageAlignment| bytes in size. Must be POD.
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.
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.
234 const Header
* header() const {
235 return reinterpret_cast<const Header
*>(main_buffer_
.get());
237 Header
* header() { return reinterpret_cast<Header
*>(main_buffer_
.get()); }
239 void UpdateTotalSize();
241 const size_t main_buffer_size_
;
242 const scoped_ptr
<char, base::AlignedFreeDeleter
> main_buffer_
; // Never null.
244 scoped_ptr
<TransportData
> transport_data_
; // May be null.
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
250 scoped_ptr
<DispatcherVector
> dispatchers_
;
252 DISALLOW_COPY_AND_ASSIGN(MessageInTransit
);
255 } // namespace system
258 #endif // MOJO_SYSTEM_MESSAGE_IN_TRANSIT_H_