Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(16)

Side by Side Diff: mojo/system/message_in_transit.h

Issue 265753006: Mojo: Factor MessageInTransit secondary buffer stuff out into a separate class. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: oops Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « mojo/system/dispatcher.cc ('k') | mojo/system/message_in_transit.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef MOJO_SYSTEM_MESSAGE_IN_TRANSIT_H_ 5 #ifndef MOJO_SYSTEM_MESSAGE_IN_TRANSIT_H_
6 #define MOJO_SYSTEM_MESSAGE_IN_TRANSIT_H_ 6 #define MOJO_SYSTEM_MESSAGE_IN_TRANSIT_H_
7 7
8 #include <stddef.h>
8 #include <stdint.h> 9 #include <stdint.h>
9 10
10 #include <vector> 11 #include <vector>
11 12
12 #include "base/macros.h" 13 #include "base/macros.h"
13 #include "base/memory/aligned_memory.h" 14 #include "base/memory/aligned_memory.h"
14 #include "base/memory/scoped_ptr.h" 15 #include "base/memory/scoped_ptr.h"
15 #include "mojo/embedder/platform_handle.h"
16 #include "mojo/system/dispatcher.h" 16 #include "mojo/system/dispatcher.h"
17 #include "mojo/system/system_impl_export.h" 17 #include "mojo/system/system_impl_export.h"
18 18
19 namespace mojo { 19 namespace mojo {
20 namespace system { 20 namespace system {
21 21
22 class Channel; 22 class Channel;
23 class TransportData;
23 24
24 // This class is used to represent data in transit. It is thread-unsafe. 25 // This class is used to represent data in transit. It is thread-unsafe.
25 // 26 //
26 // |MessageInTransit| buffers: 27 // |MessageInTransit| buffers:
27 // 28 //
28 // A |MessageInTransit| can be serialized by writing the main buffer and then, 29 // A |MessageInTransit| can be serialized by writing the main buffer and then,
29 // if it has one, the secondary buffer. Both buffers are 30 // if it has one, the transport data buffer. Both buffers are
30 // |kMessageAlignment|-byte aligned and a multiple of |kMessageAlignment| bytes 31 // |kMessageAlignment|-byte aligned and a multiple of |kMessageAlignment| bytes
31 // in size. 32 // in size.
32 // 33 //
33 // The main buffer consists of the header (of type |Header|, which is an 34 // The main buffer consists of the header (of type |Header|, which is an
34 // internal detail of this class) followed immediately by the message data 35 // internal detail of this class) followed immediately by the message data
35 // (accessed by |bytes()| and of size |num_bytes()|, and also 36 // (accessed by |bytes()| and of size |num_bytes()|, and also
36 // |kMessageAlignment|-byte aligned), and then any padding needed to make the 37 // |kMessageAlignment|-byte aligned), and then any padding needed to make the
37 // main buffer a multiple of |kMessageAlignment| bytes in size. 38 // main buffer a multiple of |kMessageAlignment| bytes in size.
38 // 39 //
39 // The secondary buffer consists first of a table of |HandleTableEntry|s (each 40 // See |TransportData| for a description of the (serialized) transport data
40 // of which is already a multiple of |kMessageAlignment| in size), followed by 41 // buffer.
41 // data needed for the |HandleTableEntry|s: A |HandleTableEntry| consists of an
42 // offset (in bytes, relative to the start of the secondary buffer; we guarantee
43 // that it's a multiple of |kMessageAlignment|), and a size (in bytes).
44 class MOJO_SYSTEM_IMPL_EXPORT MessageInTransit { 42 class MOJO_SYSTEM_IMPL_EXPORT MessageInTransit {
45 public: 43 public:
46 typedef uint16_t Type; 44 typedef uint16_t Type;
47 // Messages that are forwarded to |MessagePipeEndpoint|s. 45 // Messages that are forwarded to |MessagePipeEndpoint|s.
48 static const Type kTypeMessagePipeEndpoint = 0; 46 static const Type kTypeMessagePipeEndpoint = 0;
49 // Messages that are forwarded to |MessagePipe|s. 47 // Messages that are forwarded to |MessagePipe|s.
50 static const Type kTypeMessagePipe = 1; 48 static const Type kTypeMessagePipe = 1;
51 // Messages that are consumed by the channel. 49 // Messages that are consumed by the channel.
52 static const Type kTypeChannel = 2; 50 static const Type kTypeChannel = 2;
53 51
54 typedef uint16_t Subtype; 52 typedef uint16_t Subtype;
55 // Subtypes for type |kTypeMessagePipeEndpoint|: 53 // Subtypes for type |kTypeMessagePipeEndpoint|:
56 static const Subtype kSubtypeMessagePipeEndpointData = 0; 54 static const Subtype kSubtypeMessagePipeEndpointData = 0;
57 // Subtypes for type |kTypeMessagePipe|: 55 // Subtypes for type |kTypeMessagePipe|:
58 // Nothing currently. 56 // Nothing currently.
59 // Subtypes for type |kTypeChannel|: 57 // Subtypes for type |kTypeChannel|:
60 static const Subtype kSubtypeChannelRunMessagePipeEndpoint = 0; 58 static const Subtype kSubtypeChannelRunMessagePipeEndpoint = 0;
61 static const Subtype kSubtypeChannelRemoveMessagePipeEndpoint = 1; 59 static const Subtype kSubtypeChannelRemoveMessagePipeEndpoint = 1;
62 static const Subtype kSubtypeChannelRemoveMessagePipeEndpointAck = 2; 60 static const Subtype kSubtypeChannelRemoveMessagePipeEndpointAck = 2;
63 61
64 typedef uint32_t EndpointId; 62 typedef uint32_t EndpointId;
65 // Never a valid endpoint ID. 63 // Never a valid endpoint ID.
66 static const EndpointId kInvalidEndpointId = 0; 64 static const EndpointId kInvalidEndpointId = 0;
67 65
68 // Messages (the header and data) must always be aligned to a multiple of this 66 // Messages (the header and data) must always be aligned to a multiple of this
69 // quantity (which must be a power of 2). 67 // quantity (which must be a power of 2).
70 static const size_t kMessageAlignment = 8; 68 static const size_t kMessageAlignment = 8;
71 69
72 // The maximum size of a single serialized dispatcher. This must be a multiple
73 // of |kMessageAlignment|.
74 static const size_t kMaxSerializedDispatcherSize = 10000;
75
76 // The maximum number of platform handles to attach for a single serialized
77 // dispatcher.
78 static const size_t kMaxSerializedDispatcherPlatformHandles = 2;
79
80 // Forward-declare |Header| so that |View| can use it: 70 // Forward-declare |Header| so that |View| can use it:
81 private: 71 private:
82 struct Header; 72 struct Header;
83 public: 73 public:
84 // This represents a view of serialized message data in a raw buffer. 74 // This represents a view of serialized message data in a raw buffer.
85 class MOJO_SYSTEM_IMPL_EXPORT View { 75 class MOJO_SYSTEM_IMPL_EXPORT View {
86 public: 76 public:
87 // Constructs a view from the given buffer of the given size. (The size must 77 // Constructs a view from the given buffer of the given size. (The size must
88 // be as provided by |MessageInTransit::GetNextMessageSize()|.) The buffer 78 // be as provided by |MessageInTransit::GetNextMessageSize()|.) The buffer
89 // must remain alive/unmodified through the lifetime of this object. 79 // must remain alive/unmodified through the lifetime of this object.
90 // |buffer| should be |kMessageAlignment|-byte aligned. 80 // |buffer| should be |kMessageAlignment|-byte aligned.
91 View(size_t message_size, const void* buffer); 81 View(size_t message_size, const void* buffer);
92 82
93 // Checks the following things versus pre-determined limits: 83 // Checks that the given |View| appears to be for a valid message, within
94 // - |num_bytes()| and |main_buffer_size()|, 84 // predetermined limits (e.g., |num_bytes()| and |main_buffer_size()|, that
95 // - |num_handles()| and |secondary_buffer_size()|, 85 // |transport_data_buffer()|/|transport_data_buffer_size()| is for valid
96 // - the entries in the handle entry table (that the sizes and offsets are 86 // transport data -- see |TransportData::ValidateBuffer()|).
97 // valid).
98 // Note: It does not check the serialized dispatcher data itself.
99 // 87 //
100 // It returns true (and leaves |error_message| alone) if this object appears 88 // It returns true (and leaves |error_message| alone) if this object appears
101 // to be a valid message (according to the above) and false, pointing 89 // to be a valid message (according to the above) and false, pointing
102 // |*error_message| to a suitable error message, if not. 90 // |*error_message| to a suitable error message, if not.
103 bool IsValid(const char** error_message) const; 91 bool IsValid(const char** error_message) const;
104 92
105 // API parallel to that for |MessageInTransit| itself (mostly getters for 93 // API parallel to that for |MessageInTransit| itself (mostly getters for
106 // header data). 94 // header data).
107 const void* main_buffer() const { return buffer_; } 95 const void* main_buffer() const { return buffer_; }
108 size_t main_buffer_size() const { 96 size_t main_buffer_size() const {
109 return RoundUpMessageAlignment(sizeof(Header) + header()->num_bytes); 97 return RoundUpMessageAlignment(sizeof(Header) + header()->num_bytes);
110 } 98 }
111 const void* secondary_buffer() const { 99 const void* transport_data_buffer() const {
112 return (total_size() > main_buffer_size()) ? 100 return (total_size() > main_buffer_size()) ?
113 static_cast<const char*>(buffer_) + main_buffer_size() : NULL; 101 static_cast<const char*>(buffer_) + main_buffer_size() : NULL;
114 } 102 }
115 size_t secondary_buffer_size() const { 103 size_t transport_data_buffer_size() const {
116 return total_size() - main_buffer_size(); 104 return total_size() - main_buffer_size();
117 } 105 }
118 size_t total_size() const { return header()->total_size; } 106 size_t total_size() const { return header()->total_size; }
119 uint32_t num_bytes() const { return header()->num_bytes; } 107 uint32_t num_bytes() const { return header()->num_bytes; }
120 const void* bytes() const { 108 const void* bytes() const {
121 return static_cast<const char*>(buffer_) + sizeof(Header); 109 return static_cast<const char*>(buffer_) + sizeof(Header);
122 } 110 }
123 uint32_t num_handles() const { return header()->num_handles; }
124 Type type() const { return header()->type; } 111 Type type() const { return header()->type; }
125 Subtype subtype() const { return header()->subtype; } 112 Subtype subtype() const { return header()->subtype; }
126 EndpointId source_id() const { return header()->source_id; } 113 EndpointId source_id() const { return header()->source_id; }
127 EndpointId destination_id() const { return header()->destination_id; } 114 EndpointId destination_id() const { return header()->destination_id; }
128 115
129 private: 116 private:
130 const Header* header() const { return static_cast<const Header*>(buffer_); } 117 const Header* header() const { return static_cast<const Header*>(buffer_); }
131 118
132 const void* const buffer_; 119 const void* const buffer_;
133 120
134 // Though this struct is trivial, disallow copy and assign, since it doesn't 121 // Though this struct is trivial, disallow copy and assign, since it doesn't
135 // own its data. (If you're copying/assigning this, you're probably doing 122 // own its data. (If you're copying/assigning this, you're probably doing
136 // something wrong.) 123 // something wrong.)
137 DISALLOW_COPY_AND_ASSIGN(View); 124 DISALLOW_COPY_AND_ASSIGN(View);
138 }; 125 };
139 126
140 // |bytes| is optional; if null, the message data will be zero-initialized. 127 // |bytes| is optional; if null, the message data will be zero-initialized.
141 MessageInTransit(Type type, 128 MessageInTransit(Type type,
142 Subtype subtype, 129 Subtype subtype,
143 uint32_t num_bytes, 130 uint32_t num_bytes,
144 uint32_t num_handles,
145 const void* bytes); 131 const void* bytes);
146 // Constructs a |MessageInTransit| from a |View|. 132 // Constructs a |MessageInTransit| from a |View|.
147 explicit MessageInTransit(const View& message_view); 133 explicit MessageInTransit(const View& message_view);
148 134
149 ~MessageInTransit(); 135 ~MessageInTransit();
150 136
151 // Gets the size of the next message from |buffer|, which has |buffer_size| 137 // Gets the size of the next message from |buffer|, which has |buffer_size|
152 // bytes currently available, returning true and setting |*next_message_size| 138 // bytes currently available, returning true and setting |*next_message_size|
153 // on success. |buffer| should be aligned on a |kMessageAlignment| boundary 139 // on success. |buffer| should be aligned on a |kMessageAlignment| boundary
154 // (and on success, |*next_message_size| will be a multiple of 140 // (and on success, |*next_message_size| will be a multiple of
(...skipping 10 matching lines...) Expand all
165 // message must not already have dispatchers. 151 // message must not already have dispatchers.
166 void SetDispatchers( 152 void SetDispatchers(
167 scoped_ptr<std::vector<scoped_refptr<Dispatcher> > > dispatchers); 153 scoped_ptr<std::vector<scoped_refptr<Dispatcher> > > dispatchers);
168 154
169 // Serializes any dispatchers to the secondary buffer. This message must not 155 // Serializes any dispatchers to the secondary buffer. This message must not
170 // already have a secondary buffer (so this must only be called once). The 156 // already have a secondary buffer (so this must only be called once). The
171 // caller must ensure (e.g., by holding on to a reference) that |channel| 157 // caller must ensure (e.g., by holding on to a reference) that |channel|
172 // stays alive through the call. 158 // stays alive through the call.
173 void SerializeAndCloseDispatchers(Channel* channel); 159 void SerializeAndCloseDispatchers(Channel* channel);
174 160
175 // Deserializes any dispatchers from the secondary buffer. This message must
176 // not have any dispatchers attached.
177 // TODO(vtl): Having to copy the secondary buffer (in the constructor from a
178 // |View|) is suboptimal. Maybe this should just be done in the constructor?
179 void DeserializeDispatchers(Channel* channel);
180
181 // Gets the main buffer and its size (in number of bytes), respectively. 161 // Gets the main buffer and its size (in number of bytes), respectively.
182 const void* main_buffer() const { return main_buffer_.get(); } 162 const void* main_buffer() const { return main_buffer_.get(); }
183 size_t main_buffer_size() const { return main_buffer_size_; } 163 size_t main_buffer_size() const { return main_buffer_size_; }
184 164
185 // Gets the secondary buffer and its size (in number of bytes), respectively. 165 // Gets the transport data buffer (if any).
186 const void* secondary_buffer() const { return secondary_buffer_.get(); } 166 const TransportData* transport_data() const { return transport_data_.get(); }
187 size_t secondary_buffer_size() const { return secondary_buffer_size_; }
188 167
189 // Gets the total size of the message (see comment in |Header|, below). 168 // Gets the total size of the message (see comment in |Header|, below).
190 size_t total_size() const { return header()->total_size; } 169 size_t total_size() const { return header()->total_size; }
191 170
192 // Gets the size of the message data. 171 // Gets the size of the message data.
193 uint32_t num_bytes() const { return header()->num_bytes; } 172 uint32_t num_bytes() const { return header()->num_bytes; }
194 173
195 // Gets the message data (of size |num_bytes()| bytes). 174 // Gets the message data (of size |num_bytes()| bytes).
196 const void* bytes() const { return main_buffer_.get() + sizeof(Header); } 175 const void* bytes() const { return main_buffer_.get() + sizeof(Header); }
197 void* bytes() { return main_buffer_.get() + sizeof(Header); } 176 void* bytes() { return main_buffer_.get() + sizeof(Header); }
198 177
199 uint32_t num_handles() const { return header()->num_handles; }
200
201 Type type() const { return header()->type; } 178 Type type() const { return header()->type; }
202 Subtype subtype() const { return header()->subtype; } 179 Subtype subtype() const { return header()->subtype; }
203 EndpointId source_id() const { return header()->source_id; } 180 EndpointId source_id() const { return header()->source_id; }
204 EndpointId destination_id() const { return header()->destination_id; } 181 EndpointId destination_id() const { return header()->destination_id; }
205 182
206 void set_source_id(EndpointId source_id) { header()->source_id = source_id; } 183 void set_source_id(EndpointId source_id) { header()->source_id = source_id; }
207 void set_destination_id(EndpointId destination_id) { 184 void set_destination_id(EndpointId destination_id) {
208 header()->destination_id = destination_id; 185 header()->destination_id = destination_id;
209 } 186 }
210 187
211 // Gets the dispatchers attached to this message; this may return null if 188 // Gets the dispatchers attached to this message; this may return null if
212 // there are none. Note that the caller may mutate the set of dispatchers 189 // there are none. Note that the caller may mutate the set of dispatchers
213 // (e.g., take ownership of all the dispatchers, leaving the vector empty). 190 // (e.g., take ownership of all the dispatchers, leaving the vector empty).
214 std::vector<scoped_refptr<Dispatcher> >* dispatchers() { 191 std::vector<scoped_refptr<Dispatcher> >* dispatchers() {
215 return dispatchers_.get(); 192 return dispatchers_.get();
216 } 193 }
217 194
218 // Returns true if this message has dispatchers attached. 195 // Returns true if this message has dispatchers attached.
219 bool has_dispatchers() const { 196 bool has_dispatchers() const {
220 return dispatchers_ && !dispatchers_->empty(); 197 return dispatchers_ && !dispatchers_->empty();
221 } 198 }
222 199
223 // Gets the platform-specific handles attached to this message; this may
224 // return null if there are none. Note that the caller may mutate the set of
225 // platform-specific handles.
226 std::vector<embedder::PlatformHandle>* platform_handles() {
227 return platform_handles_.get();
228 }
229
230 // Returns true if this message has platform-specific handles attached.
231 bool has_platform_handles() const {
232 return platform_handles_ && !platform_handles_->empty();
233 }
234
235 // Rounds |n| up to a multiple of |kMessageAlignment|. 200 // Rounds |n| up to a multiple of |kMessageAlignment|.
236 static inline size_t RoundUpMessageAlignment(size_t n) { 201 static inline size_t RoundUpMessageAlignment(size_t n) {
237 return (n + kMessageAlignment - 1) & ~(kMessageAlignment - 1); 202 return (n + kMessageAlignment - 1) & ~(kMessageAlignment - 1);
238 } 203 }
239 204
240 private: 205 private:
241 // To allow us to make assertions about |Header| in the .cc file. 206 // To allow us to make compile-assertions about |Header| in the .cc file.
242 struct PrivateStructForCompileAsserts; 207 struct PrivateStructForCompileAsserts;
243 208
244 // Header for the data (main buffer). Must be a multiple of 209 // Header for the data (main buffer). Must be a multiple of
245 // |kMessageAlignment| bytes in size. Must be POD. 210 // |kMessageAlignment| bytes in size. Must be POD.
246 struct Header { 211 struct Header {
247 // Total size of the message, including the header, the message data 212 // Total size of the message, including the header, the message data
248 // ("bytes") including padding (to make it a multiple of |kMessageAlignment| 213 // ("bytes") including padding (to make it a multiple of |kMessageAlignment|
249 // bytes), and serialized handle information. Note that this may not be the 214 // bytes), and serialized handle information. Note that this may not be the
250 // correct value if dispatchers are attached but 215 // correct value if dispatchers are attached but
251 // |SerializeAndCloseDispatchers()| has not been called. 216 // |SerializeAndCloseDispatchers()| has not been called.
252 uint32_t total_size; 217 uint32_t total_size;
253 Type type; // 2 bytes. 218 Type type; // 2 bytes.
254 Subtype subtype; // 2 bytes. 219 Subtype subtype; // 2 bytes.
255 EndpointId source_id; // 4 bytes. 220 EndpointId source_id; // 4 bytes.
256 EndpointId destination_id; // 4 bytes. 221 EndpointId destination_id; // 4 bytes.
257 // Size of actual message data. 222 // Size of actual message data.
258 uint32_t num_bytes; 223 uint32_t num_bytes;
259 // Number of handles "attached".
260 uint32_t num_handles;
261 };
262
263 struct HandleTableEntry {
264 int32_t type; // From |Dispatcher::Type| (|kTypeUnknown| for "invalid").
265 uint32_t offset; // Relative to the start of the secondary buffer.
266 uint32_t size; // (Not including any padding.)
267 uint32_t unused; 224 uint32_t unused;
268 }; 225 };
269 226
270 // The maximum possible size of a valid secondary buffer.
271 static const size_t kMaxSecondaryBufferSize;
272
273 // The maximum total number of platform handles that may be attached.
274 static const size_t kMaxPlatformHandles;
275
276 // Validates the secondary buffer. Returns null on success, or a
277 // human-readable error message (meant for logging/debugging) on error.
278 static const char* ValidateSecondaryBuffer(size_t num_handles,
279 const void* secondary_buffer,
280 size_t secondary_buffer_size);
281
282 const Header* header() const { 227 const Header* header() const {
283 return reinterpret_cast<const Header*>(main_buffer_.get()); 228 return reinterpret_cast<const Header*>(main_buffer_.get());
284 } 229 }
285 Header* header() { return reinterpret_cast<Header*>(main_buffer_.get()); } 230 Header* header() { return reinterpret_cast<Header*>(main_buffer_.get()); }
286 231
287 void UpdateTotalSize(); 232 void UpdateTotalSize();
288 233
289 const size_t main_buffer_size_; 234 const size_t main_buffer_size_;
290 const scoped_ptr<char, base::AlignedFreeDeleter> main_buffer_; // Never null. 235 const scoped_ptr<char, base::AlignedFreeDeleter> main_buffer_; // Never null.
291 236
292 size_t secondary_buffer_size_; 237 scoped_ptr<TransportData> transport_data_; // May be null.
293 scoped_ptr<char, base::AlignedFreeDeleter> secondary_buffer_; // May be null.
294 238
295 // Any dispatchers that may be attached to this message. These dispatchers 239 // Any dispatchers that may be attached to this message. These dispatchers
296 // should be "owned" by this message, i.e., have a ref count of exactly 1. (We 240 // should be "owned" by this message, i.e., have a ref count of exactly 1. (We
297 // allow a dispatcher entry to be null, in case it couldn't be duplicated for 241 // allow a dispatcher entry to be null, in case it couldn't be duplicated for
298 // some reason.) 242 // some reason.)
299 scoped_ptr<std::vector<scoped_refptr<Dispatcher> > > dispatchers_; 243 scoped_ptr<std::vector<scoped_refptr<Dispatcher> > > dispatchers_;
300 244
301 // Any platform-specific handles attached to this message (for inter-process
302 // transport). The vector (if any) owns the handles that it contains (and is
303 // responsible for closing them).
304 // TODO(vtl): With C++11, change it to a vector of |ScopedPlatformHandles|.
305 scoped_ptr<std::vector<embedder::PlatformHandle> > platform_handles_;
306
307 DISALLOW_COPY_AND_ASSIGN(MessageInTransit); 245 DISALLOW_COPY_AND_ASSIGN(MessageInTransit);
308 }; 246 };
309 247
310 } // namespace system 248 } // namespace system
311 } // namespace mojo 249 } // namespace mojo
312 250
313 #endif // MOJO_SYSTEM_MESSAGE_IN_TRANSIT_H_ 251 #endif // MOJO_SYSTEM_MESSAGE_IN_TRANSIT_H_
OLDNEW
« no previous file with comments | « mojo/system/dispatcher.cc ('k') | mojo/system/message_in_transit.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698