Upstream version 11.39.266.0
[platform/framework/web/crosswalk.git] / src / mojo / system / message_in_transit.h
index 6dfc434..9101f36 100644 (file)
@@ -5,17 +5,41 @@
 #ifndef MOJO_SYSTEM_MESSAGE_IN_TRANSIT_H_
 #define MOJO_SYSTEM_MESSAGE_IN_TRANSIT_H_
 
+#include <stddef.h>
 #include <stdint.h>
-#include <stdlib.h>  // For |free()|.
 
-#include "base/basictypes.h"
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/aligned_memory.h"
+#include "base/memory/scoped_ptr.h"
+#include "mojo/system/dispatcher.h"
+#include "mojo/system/memory.h"
 #include "mojo/system/system_impl_export.h"
 
 namespace mojo {
 namespace system {
 
+class Channel;
+class TransportData;
+
 // This class is used to represent data in transit. It is thread-unsafe.
-// Note: This class is POD.
+//
+// |MessageInTransit| buffers:
+//
+// A |MessageInTransit| can be serialized by writing the main buffer and then,
+// if it has one, the transport data buffer. Both buffers are
+// |kMessageAlignment|-byte aligned and a multiple of |kMessageAlignment| bytes
+// in size.
+//
+// The main buffer consists of the header (of type |Header|, which is an
+// internal detail of this class) followed immediately by the message data
+// (accessed by |bytes()| and of size |num_bytes()|, and also
+// |kMessageAlignment|-byte aligned), and then any padding needed to make the
+// main buffer a multiple of |kMessageAlignment| bytes in size.
+//
+// See |TransportData| for a description of the (serialized) transport data
+// buffer.
 class MOJO_SYSTEM_IMPL_EXPORT MessageInTransit {
  public:
   typedef uint16_t Type;
@@ -23,14 +47,22 @@ class MOJO_SYSTEM_IMPL_EXPORT MessageInTransit {
   static const Type kTypeMessagePipeEndpoint = 0;
   // Messages that are forwarded to |MessagePipe|s.
   static const Type kTypeMessagePipe = 1;
-  // Messages that are consumed by the channel.
-  static const Type TYPE_CHANNEL = 2;
+  // Messages that are consumed by the |Channel|.
+  static const Type kTypeChannel = 2;
+  // Messages that are consumed by the |RawChannel| (implementation).
+  static const Type kTypeRawChannel = 3;
 
   typedef uint16_t Subtype;
   // Subtypes for type |kTypeMessagePipeEndpoint|:
   static const Subtype kSubtypeMessagePipeEndpointData = 0;
   // Subtypes for type |kTypeMessagePipe|:
-  static const Subtype kSubtypeMessagePipePeerClosed = 0;
+  // Nothing currently.
+  // Subtypes for type |kTypeChannel|:
+  static const Subtype kSubtypeChannelRunMessagePipeEndpoint = 0;
+  static const Subtype kSubtypeChannelRemoveMessagePipeEndpoint = 1;
+  static const Subtype kSubtypeChannelRemoveMessagePipeEndpointAck = 2;
+  // Subtypes for type |kTypeRawChannel|:
+  static const Subtype kSubtypeRawChannelPosixExtraPlatformHandles = 0;
 
   typedef uint32_t EndpointId;
   // Never a valid endpoint ID.
@@ -40,42 +72,145 @@ class MOJO_SYSTEM_IMPL_EXPORT MessageInTransit {
   // quantity (which must be a power of 2).
   static const size_t kMessageAlignment = 8;
 
-  // Creates a |MessageInTransit| of the given |type| and |subtype|, with the
-  // data given by |bytes|/|num_bytes|.
-  static MessageInTransit* Create(Type type, Subtype subtype,
-                                  const void* bytes, uint32_t num_bytes);
+  // Forward-declare |Header| so that |View| can use it:
+ private:
+  struct Header;
 
-  // Destroys a |MessageInTransit| created using |Create()|.
-  inline void Destroy() {
-    // No need to call the destructor, since we're POD.
-    free(this);
-  }
+ public:
+  // This represents a view of serialized message data in a raw buffer.
+  class MOJO_SYSTEM_IMPL_EXPORT View {
+   public:
+    // Constructs a view from the given buffer of the given size. (The size must
+    // be as provided by |MessageInTransit::GetNextMessageSize()|.) The buffer
+    // must remain alive/unmodified through the lifetime of this object.
+    // |buffer| should be |kMessageAlignment|-byte aligned.
+    View(size_t message_size, const void* buffer);
 
-  // Gets the size of the data (in number of bytes).
-  uint32_t data_size() const {
-    return size_;
-  }
+    // Checks that the given |View| appears to be for a valid message, within
+    // predetermined limits (e.g., |num_bytes()| and |main_buffer_size()|, that
+    // |transport_data_buffer()|/|transport_data_buffer_size()| is for valid
+    // transport data -- see |TransportData::ValidateBuffer()|).
+    //
+    // It returns true (and leaves |error_message| alone) if this object appears
+    // to be a valid message (according to the above) and false, pointing
+    // |*error_message| to a suitable error message, if not.
+    bool IsValid(size_t serialized_platform_handle_size,
+                 const char** error_message) const;
 
-  // Gets the data (of size |size()| bytes).
-  const void* data() const {
-    return reinterpret_cast<const char*>(this) + sizeof(*this);
-  }
+    // API parallel to that for |MessageInTransit| itself (mostly getters for
+    // header data).
+    const void* main_buffer() const { return buffer_; }
+    size_t main_buffer_size() const {
+      return RoundUpMessageAlignment(sizeof(Header) + header()->num_bytes);
+    }
+    const void* transport_data_buffer() const {
+      return (total_size() > main_buffer_size())
+                 ? static_cast<const char*>(buffer_) + main_buffer_size()
+                 : nullptr;
+    }
+    size_t transport_data_buffer_size() const {
+      return total_size() - main_buffer_size();
+    }
+    size_t total_size() const { return header()->total_size; }
+    uint32_t num_bytes() const { return header()->num_bytes; }
+    const void* bytes() const {
+      return static_cast<const char*>(buffer_) + sizeof(Header);
+    }
+    Type type() const { return header()->type; }
+    Subtype subtype() const { return header()->subtype; }
+    EndpointId source_id() const { return header()->source_id; }
+    EndpointId destination_id() const { return header()->destination_id; }
 
-  size_t size_with_header_and_padding() const {
-    return RoundUpMessageAlignment(sizeof(*this) + size_);
-  }
+   private:
+    const Header* header() const { return static_cast<const Header*>(buffer_); }
+
+    const void* const buffer_;
+
+    // Though this struct is trivial, disallow copy and assign, since it doesn't
+    // own its data. (If you're copying/assigning this, you're probably doing
+    // something wrong.)
+    DISALLOW_COPY_AND_ASSIGN(View);
+  };
+
+  // |bytes| is optional; if null, the message data will be zero-initialized.
+  MessageInTransit(Type type,
+                   Subtype subtype,
+                   uint32_t num_bytes,
+                   const void* bytes);
+  // |bytes| should be valid (and non-null), unless |num_bytes| is zero.
+  MessageInTransit(Type type,
+                   Subtype subtype,
+                   uint32_t num_bytes,
+                   UserPointer<const void> bytes);
+  // Constructs a |MessageInTransit| from a |View|.
+  explicit MessageInTransit(const View& message_view);
+
+  ~MessageInTransit();
+
+  // Gets the size of the next message from |buffer|, which has |buffer_size|
+  // bytes currently available, returning true and setting |*next_message_size|
+  // on success. |buffer| should be aligned on a |kMessageAlignment| boundary
+  // (and on success, |*next_message_size| will be a multiple of
+  // |kMessageAlignment|).
+  // TODO(vtl): In |RawChannelPosix|, the alignment requirements are currently
+  // satisified on a faith-based basis.
+  static bool GetNextMessageSize(const void* buffer,
+                                 size_t buffer_size,
+                                 size_t* next_message_size);
+
+  // Makes this message "own" the given set of dispatchers. The dispatchers must
+  // not be referenced from anywhere else (in particular, not from the handle
+  // table), i.e., each dispatcher must have a reference count of 1. This
+  // message must not already have dispatchers.
+  void SetDispatchers(scoped_ptr<DispatcherVector> dispatchers);
+
+  // Sets the |TransportData| for this message. This should only be done when
+  // there are no dispatchers and no existing |TransportData|.
+  void SetTransportData(scoped_ptr<TransportData> transport_data);
+
+  // Serializes any dispatchers to the secondary buffer. This message must not
+  // already have a secondary buffer (so this must only be called once). The
+  // caller must ensure (e.g., by holding on to a reference) that |channel|
+  // stays alive through the call.
+  void SerializeAndCloseDispatchers(Channel* channel);
 
-  Type type() const { return type_; }
-  Subtype subtype() const { return subtype_; }
-  EndpointId source_id() const { return source_id_; }
-  EndpointId destination_id() const { return destination_id_; }
+  // Gets the main buffer and its size (in number of bytes), respectively.
+  const void* main_buffer() const { return main_buffer_.get(); }
+  size_t main_buffer_size() const { return main_buffer_size_; }
 
-  void set_source_id(EndpointId source_id) { source_id_ = source_id; }
+  // Gets the transport data buffer (if any).
+  const TransportData* transport_data() const { return transport_data_.get(); }
+  TransportData* transport_data() { return transport_data_.get(); }
+
+  // Gets the total size of the message (see comment in |Header|, below).
+  size_t total_size() const { return header()->total_size; }
+
+  // Gets the size of the message data.
+  uint32_t num_bytes() const { return header()->num_bytes; }
+
+  // Gets the message data (of size |num_bytes()| bytes).
+  const void* bytes() const { return main_buffer_.get() + sizeof(Header); }
+  void* bytes() { return main_buffer_.get() + sizeof(Header); }
+
+  Type type() const { return header()->type; }
+  Subtype subtype() const { return header()->subtype; }
+  EndpointId source_id() const { return header()->source_id; }
+  EndpointId destination_id() const { return header()->destination_id; }
+
+  void set_source_id(EndpointId source_id) { header()->source_id = source_id; }
   void set_destination_id(EndpointId destination_id) {
-    destination_id_ = destination_id;
+    header()->destination_id = destination_id;
   }
 
-  // TODO(vtl): Add whatever's necessary to transport handles.
+  // Gets the dispatchers attached to this message; this may return null if
+  // there are none. Note that the caller may mutate the set of dispatchers
+  // (e.g., take ownership of all the dispatchers, leaving the vector empty).
+  DispatcherVector* dispatchers() { return dispatchers_.get(); }
+
+  // Returns true if this message has dispatchers attached.
+  bool has_dispatchers() const {
+    return dispatchers_ && !dispatchers_->empty();
+  }
 
   // Rounds |n| up to a multiple of |kMessageAlignment|.
   static inline size_t RoundUpMessageAlignment(size_t n) {
@@ -83,31 +218,49 @@ class MOJO_SYSTEM_IMPL_EXPORT MessageInTransit {
   }
 
  private:
-  explicit MessageInTransit(uint32_t size, Type type, Subtype subtype)
-      : size_(size),
-        type_(type),
-        subtype_(subtype),
-        source_id_(kInvalidEndpointId),
-        destination_id_(kInvalidEndpointId) {}
-
-  // "Header" for the data.
-  uint32_t size_;
-  Type type_;
-  Subtype subtype_;
-  EndpointId source_id_;
-  EndpointId destination_id_;
-
-  // Intentionally unimplemented (and private): Use |Destroy()| instead (which
-  // simply frees the memory).
-  ~MessageInTransit();
+  // To allow us to make compile-assertions about |Header| in the .cc file.
+  struct PrivateStructForCompileAsserts;
+
+  // Header for the data (main buffer). Must be a multiple of
+  // |kMessageAlignment| bytes in size. Must be POD.
+  struct Header {
+    // Total size of the message, including the header, the message data
+    // ("bytes") including padding (to make it a multiple of |kMessageAlignment|
+    // bytes), and serialized handle information. Note that this may not be the
+    // correct value if dispatchers are attached but
+    // |SerializeAndCloseDispatchers()| has not been called.
+    uint32_t total_size;
+    Type type;                  // 2 bytes.
+    Subtype subtype;            // 2 bytes.
+    EndpointId source_id;       // 4 bytes.
+    EndpointId destination_id;  // 4 bytes.
+    // Size of actual message data.
+    uint32_t num_bytes;
+    uint32_t unused;
+  };
+
+  const Header* header() const {
+    return reinterpret_cast<const Header*>(main_buffer_.get());
+  }
+  Header* header() { return reinterpret_cast<Header*>(main_buffer_.get()); }
+
+  void ConstructorHelper(Type type, Subtype subtype, uint32_t num_bytes);
+  void UpdateTotalSize();
+
+  const size_t main_buffer_size_;
+  const scoped_ptr<char, base::AlignedFreeDeleter> main_buffer_;  // Never null.
+
+  scoped_ptr<TransportData> transport_data_;  // May be null.
+
+  // Any dispatchers that may be attached to this message. These dispatchers
+  // should be "owned" by this message, i.e., have a ref count of exactly 1. (We
+  // allow a dispatcher entry to be null, in case it couldn't be duplicated for
+  // some reason.)
+  scoped_ptr<DispatcherVector> dispatchers_;
 
   DISALLOW_COPY_AND_ASSIGN(MessageInTransit);
 };
 
-// The size of |MessageInTransit| must be appropriate to maintain alignment of
-// the following data.
-COMPILE_ASSERT(sizeof(MessageInTransit) == 16, MessageInTransit_has_wrong_size);
-
 }  // namespace system
 }  // namespace mojo