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). main_buffer()102 const void* main_buffer() const { return buffer_; } main_buffer_size()103 size_t main_buffer_size() const { 104 return RoundUpMessageAlignment(sizeof(Header) + header()->num_bytes); 105 } transport_data_buffer()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 } transport_data_buffer_size()111 size_t transport_data_buffer_size() const { 112 return total_size() - main_buffer_size(); 113 } total_size()114 size_t total_size() const { return header()->total_size; } num_bytes()115 uint32_t num_bytes() const { return header()->num_bytes; } bytes()116 const void* bytes() const { 117 return static_cast<const char*>(buffer_) + sizeof(Header); 118 } type()119 Type type() const { return header()->type; } subtype()120 Subtype subtype() const { return header()->subtype; } source_id()121 EndpointId source_id() const { return header()->source_id; } destination_id()122 EndpointId destination_id() const { return header()->destination_id; } 123 124 private: header()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. main_buffer()178 const void* main_buffer() const { return main_buffer_.get(); } main_buffer_size()179 size_t main_buffer_size() const { return main_buffer_size_; } 180 181 // Gets the transport data buffer (if any). transport_data()182 const TransportData* transport_data() const { return transport_data_.get(); } transport_data()183 TransportData* transport_data() { return transport_data_.get(); } 184 185 // Gets the total size of the message (see comment in |Header|, below). total_size()186 size_t total_size() const { return header()->total_size; } 187 188 // Gets the size of the message data. num_bytes()189 uint32_t num_bytes() const { return header()->num_bytes; } 190 191 // Gets the message data (of size |num_bytes()| bytes). bytes()192 const void* bytes() const { return main_buffer_.get() + sizeof(Header); } bytes()193 void* bytes() { return main_buffer_.get() + sizeof(Header); } 194 type()195 Type type() const { return header()->type; } subtype()196 Subtype subtype() const { return header()->subtype; } source_id()197 EndpointId source_id() const { return header()->source_id; } destination_id()198 EndpointId destination_id() const { return header()->destination_id; } 199 set_source_id(EndpointId source_id)200 void set_source_id(EndpointId source_id) { header()->source_id = source_id; } set_destination_id(EndpointId destination_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). dispatchers()208 DispatcherVector* dispatchers() { return dispatchers_.get(); } 209 210 // Returns true if this message has dispatchers attached. has_dispatchers()211 bool has_dispatchers() const { 212 return dispatchers_ && !dispatchers_->empty(); 213 } 214 215 // Rounds |n| up to a multiple of |kMessageAlignment|. RoundUpMessageAlignment(size_t n)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 header()242 const Header* header() const { 243 return reinterpret_cast<const Header*>(main_buffer_.get()); 244 } header()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_ 268