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/system_impl_export.h" 18 19 namespace mojo { 20 namespace system { 21 22 class Channel; 23 class TransportData; 24 25 // This class is used to represent data in transit. It is thread-unsafe. 26 // 27 // |MessageInTransit| buffers: 28 // 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 32 // in size. 33 // 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. 39 // 40 // See |TransportData| for a description of the (serialized) transport data 41 // buffer. 42 class MOJO_SYSTEM_IMPL_EXPORT MessageInTransit { 43 public: 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; 53 54 typedef uint16_t Subtype; 55 // Subtypes for type |kTypeMessagePipeEndpoint|: 56 static const Subtype kSubtypeMessagePipeEndpointData = 0; 57 // Subtypes for type |kTypeMessagePipe|: 58 // Nothing currently. 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; 65 66 typedef uint32_t EndpointId; 67 // Never a valid endpoint ID. 68 static const EndpointId kInvalidEndpointId = 0; 69 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; 73 74 // Forward-declare |Header| so that |View| can use it: 75 private: 76 struct Header; 77 public: 78 // This represents a view of serialized message data in a raw buffer. 79 class MOJO_SYSTEM_IMPL_EXPORT View { 80 public: 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); 86 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()|). 91 // 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; 97 98 // API parallel to that for |MessageInTransit| itself (mostly getters for 99 // header data). 100 const void* main_buffer() const { return buffer_; } 101 size_t main_buffer_size() const { 102 return RoundUpMessageAlignment(sizeof(Header) + header()->num_bytes); 103 } 104 const void* transport_data_buffer() const { 105 return (total_size() > main_buffer_size()) ? 106 static_cast<const char*>(buffer_) + main_buffer_size() : NULL; 107 } 108 size_t transport_data_buffer_size() const { 109 return total_size() - main_buffer_size(); 110 } 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); 115 } 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; } 120 121 private: 122 const Header* header() const { return static_cast<const Header*>(buffer_); } 123 124 const void* const buffer_; 125 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 128 // something wrong.) 129 DISALLOW_COPY_AND_ASSIGN(View); 130 }; 131 132 // |bytes| is optional; if null, the message data will be zero-initialized. 133 MessageInTransit(Type type, 134 Subtype subtype, 135 uint32_t num_bytes, 136 const void* bytes); 137 // Constructs a |MessageInTransit| from a |View|. 138 explicit MessageInTransit(const View& message_view); 139 140 ~MessageInTransit(); 141 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, 150 size_t buffer_size, 151 size_t* next_message_size); 152 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); 158 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); 162 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); 168 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_; } 172 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(); } 176 177 // Gets the total size of the message (see comment in |Header|, below). 178 size_t total_size() const { return header()->total_size; } 179 180 // Gets the size of the message data. 181 uint32_t num_bytes() const { return header()->num_bytes; } 182 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); } 186 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; } 191 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; 195 } 196 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(); } 201 202 // Returns true if this message has dispatchers attached. 203 bool has_dispatchers() const { 204 return dispatchers_ && !dispatchers_->empty(); 205 } 206 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); 210 } 211 212 private: 213 // To allow us to make compile-assertions about |Header| in the .cc file. 214 struct PrivateStructForCompileAsserts; 215 216 // Header for the data (main buffer). Must be a multiple of 217 // |kMessageAlignment| bytes in size. Must be POD. 218 struct Header { 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. 224 uint32_t total_size; 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. 230 uint32_t num_bytes; 231 uint32_t unused; 232 }; 233 234 const Header* header() const { 235 return reinterpret_cast<const Header*>(main_buffer_.get()); 236 } 237 Header* header() { return reinterpret_cast<Header*>(main_buffer_.get()); } 238 239 void UpdateTotalSize(); 240 241 const size_t main_buffer_size_; 242 const scoped_ptr<char, base::AlignedFreeDeleter> main_buffer_; // Never null. 243 244 scoped_ptr<TransportData> transport_data_; // May be null. 245 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 249 // some reason.) 250 scoped_ptr<DispatcherVector> dispatchers_; 251 252 DISALLOW_COPY_AND_ASSIGN(MessageInTransit); 253 }; 254 255 } // namespace system 256 } // namespace mojo 257 258 #endif // MOJO_SYSTEM_MESSAGE_IN_TRANSIT_H_ 259