OLD | NEW |
| (Empty) |
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 | |
20 namespace mojo { | |
21 namespace system { | |
22 | |
23 class Channel; | |
24 class 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. | |
43 class 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_ | |
OLD | NEW |