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