Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / mojo / system / message_in_transit.cc
index c56f4f3..3235a75 100644 (file)
@@ -6,24 +6,34 @@
 
 #include <string.h>
 
-#include <new>
-
 #include "base/compiler_specific.h"
 #include "base/logging.h"
-#include "base/memory/aligned_memory.h"
 #include "mojo/system/constants.h"
+#include "mojo/system/transport_data.h"
 
 namespace mojo {
 namespace system {
 
-namespace {
-
-
-}  // namespace
+STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type
+    MessageInTransit::kTypeMessagePipeEndpoint;
+STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type
+    MessageInTransit::kTypeMessagePipe;
+STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type
+    MessageInTransit::kTypeChannel;
+STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype
+    MessageInTransit::kSubtypeMessagePipeEndpointData;
+STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype
+    MessageInTransit::kSubtypeChannelRunMessagePipeEndpoint;
+STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype
+    MessageInTransit::kSubtypeChannelRemoveMessagePipeEndpoint;
+STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype
+    MessageInTransit::kSubtypeChannelRemoveMessagePipeEndpointAck;
+STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::EndpointId
+    MessageInTransit::kInvalidEndpointId;
+STATIC_CONST_MEMBER_DEFINITION const size_t MessageInTransit::kMessageAlignment;
 
 struct MessageInTransit::PrivateStructForCompileAsserts {
-  // The size of |Header| must be appropriate to maintain alignment of the
-  // following data.
+  // The size of |Header| must be a multiple of the alignment.
   COMPILE_ASSERT(sizeof(Header) % kMessageAlignment == 0,
                  sizeof_MessageInTransit_Header_invalid);
   // Avoid dangerous situations, but making sure that the size of the "header" +
@@ -36,35 +46,8 @@ struct MessageInTransit::PrivateStructForCompileAsserts {
   // size is a multiple of the alignment.
   COMPILE_ASSERT(kMaxMessageNumBytes % kMessageAlignment == 0,
                  kMessageAlignment_not_a_multiple_of_alignment);
-
-  COMPILE_ASSERT(kMaxSerializedDispatcherSize % kMessageAlignment == 0,
-                 kMaxSerializedDispatcherSize_not_a_multiple_of_alignment);
-
-  // The size of |HandleTableEntry| must be appropriate to maintain alignment.
-  COMPILE_ASSERT(sizeof(HandleTableEntry) % kMessageAlignment == 0,
-                 sizeof_MessageInTransit_HandleTableEntry_invalid);
 };
 
-STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type
-    MessageInTransit::kTypeMessagePipeEndpoint;
-STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type
-    MessageInTransit::kTypeMessagePipe;
-STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type
-    MessageInTransit::kTypeChannel;
-STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype
-    MessageInTransit::kSubtypeMessagePipeEndpointData;
-STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype
-    MessageInTransit::kSubtypeMessagePipePeerClosed;
-STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::EndpointId
-    MessageInTransit::kInvalidEndpointId;
-STATIC_CONST_MEMBER_DEFINITION const size_t MessageInTransit::kMessageAlignment;
-STATIC_CONST_MEMBER_DEFINITION const size_t
-    MessageInTransit::kMaxSerializedDispatcherSize;
-
-// static
-const size_t MessageInTransit::kMaxSecondaryBufferSize = kMaxMessageNumHandles *
-    (sizeof(HandleTableEntry) + kMaxSerializedDispatcherSize);
-
 MessageInTransit::View::View(size_t message_size, const void* buffer)
     : buffer_(buffer) {
   size_t next_message_size = 0;
@@ -83,11 +66,13 @@ bool MessageInTransit::View::IsValid(const char** error_message) const {
     return false;
   }
 
-  if (const char* secondary_buffer_error_message =
-          ValidateSecondaryBuffer(num_handles(), secondary_buffer(),
-                                  secondary_buffer_size())) {
-    *error_message = secondary_buffer_error_message;
-    return false;
+  if (transport_data_buffer_size() > 0) {
+    const char* e = TransportData::ValidateBuffer(transport_data_buffer(),
+                                                  transport_data_buffer_size());
+    if (e) {
+      *error_message = e;
+      return false;
+    }
   }
 
   return true;
@@ -96,14 +81,11 @@ bool MessageInTransit::View::IsValid(const char** error_message) const {
 MessageInTransit::MessageInTransit(Type type,
                                    Subtype subtype,
                                    uint32_t num_bytes,
-                                   uint32_t num_handles,
                                    const void* bytes)
     : main_buffer_size_(RoundUpMessageAlignment(sizeof(Header) + num_bytes)),
-      main_buffer_(base::AlignedAlloc(main_buffer_size_, kMessageAlignment)),
-      secondary_buffer_size_(0),
-      secondary_buffer_(NULL) {
+      main_buffer_(static_cast<char*>(base::AlignedAlloc(main_buffer_size_,
+                                                         kMessageAlignment))) {
   DCHECK_LE(num_bytes, kMaxMessageNumBytes);
-  DCHECK_LE(num_handles, kMaxMessageNumHandles);
 
   // |total_size| is updated below, from the other values.
   header()->type = type;
@@ -111,9 +93,9 @@ MessageInTransit::MessageInTransit(Type type,
   header()->source_id = kInvalidEndpointId;
   header()->destination_id = kInvalidEndpointId;
   header()->num_bytes = num_bytes;
-  header()->num_handles = num_handles;
-  // Note: If dispatchers are subsequently attached (in particular, if
-  // |num_handles| is nonzero), then |total_size| will have to be adjusted.
+  header()->unused = 0;
+  // Note: If dispatchers are subsequently attached, then |total_size| will have
+  // to be adjusted.
   UpdateTotalSize();
 
   if (bytes) {
@@ -125,37 +107,20 @@ MessageInTransit::MessageInTransit(Type type,
   }
 }
 
-// TODO(vtl): Do I really want/need to copy the secondary buffer here, or should
-// I just create (deserialize) the dispatchers right away?
 MessageInTransit::MessageInTransit(const View& message_view)
     : main_buffer_size_(message_view.main_buffer_size()),
-      main_buffer_(base::AlignedAlloc(main_buffer_size_, kMessageAlignment)),
-      secondary_buffer_size_(message_view.secondary_buffer_size()),
-      secondary_buffer_(secondary_buffer_size_ ?
-                            base::AlignedAlloc(secondary_buffer_size_,
-                                               kMessageAlignment) : NULL) {
+      main_buffer_(static_cast<char*>(base::AlignedAlloc(main_buffer_size_,
+                                                         kMessageAlignment))) {
   DCHECK_GE(main_buffer_size_, sizeof(Header));
   DCHECK_EQ(main_buffer_size_ % kMessageAlignment, 0u);
 
-  memcpy(main_buffer_, message_view.main_buffer(), main_buffer_size_);
-  memcpy(secondary_buffer_, message_view.secondary_buffer(),
-         secondary_buffer_size_);
-
+  memcpy(main_buffer_.get(), message_view.main_buffer(), main_buffer_size_);
   DCHECK_EQ(main_buffer_size_,
             RoundUpMessageAlignment(sizeof(Header) + num_bytes()));
 }
 
 MessageInTransit::~MessageInTransit() {
-  base::AlignedFree(main_buffer_);
-  base::AlignedFree(secondary_buffer_);  // Okay if null.
-#ifndef NDEBUG
-  main_buffer_size_ = 0;
-  main_buffer_ = NULL;
-  secondary_buffer_size_ = 0;
-  secondary_buffer_ = NULL;
-#endif
-
-  if (dispatchers_.get()) {
+  if (dispatchers_) {
     for (size_t i = 0; i < dispatchers_->size(); i++) {
       if (!(*dispatchers_)[i])
         continue;
@@ -163,7 +128,6 @@ MessageInTransit::~MessageInTransit() {
       DCHECK((*dispatchers_)[i]->HasOneRef());
       (*dispatchers_)[i]->Close();
     }
-    dispatchers_.reset();
   }
 }
 
@@ -188,9 +152,9 @@ bool MessageInTransit::GetNextMessageSize(const void* buffer,
 }
 
 void MessageInTransit::SetDispatchers(
-    scoped_ptr<std::vector<scoped_refptr<Dispatcher> > > dispatchers) {
-  DCHECK(dispatchers.get());
-  DCHECK(!dispatchers_.get());
+    scoped_ptr<DispatcherVector> dispatchers) {
+  DCHECK(dispatchers);
+  DCHECK(!dispatchers_);
 
   dispatchers_ = dispatchers.Pass();
 #ifndef NDEBUG
@@ -201,154 +165,24 @@ void MessageInTransit::SetDispatchers(
 
 void MessageInTransit::SerializeAndCloseDispatchers(Channel* channel) {
   DCHECK(channel);
-  DCHECK(!secondary_buffer_);
-  CHECK_EQ(num_handles(),
-           dispatchers_.get() ? dispatchers_->size() : static_cast<size_t>(0));
+  DCHECK(!transport_data_);
 
-  if (!num_handles())
+  if (!dispatchers_ || !dispatchers_->size())
     return;
 
-  size_t handle_table_size = num_handles() * sizeof(HandleTableEntry);
-  // The size of the secondary buffer. We'll start with the size of the handle
-  // table, and add to it as we go along.
-  size_t size = handle_table_size;
-  for (size_t i = 0; i < dispatchers_->size(); i++) {
-    if (Dispatcher* dispatcher = (*dispatchers_)[i].get()) {
-      size_t max_serialized_size =
-          Dispatcher::MessageInTransitAccess::GetMaximumSerializedSize(
-              dispatcher, channel);
-      DCHECK_LE(max_serialized_size, kMaxSerializedDispatcherSize);
-      size += RoundUpMessageAlignment(max_serialized_size);
-      DCHECK_LE(size, kMaxSecondaryBufferSize);
-    }
-  }
-
-  secondary_buffer_ = base::AlignedAlloc(size, kMessageAlignment);
-  secondary_buffer_size_ = static_cast<uint32_t>(size);
-  // Entirely clear out the secondary buffer, since then we won't have to worry
-  // about clearing padding or unused space (e.g., if a dispatcher fails to
-  // serialize).
-  memset(secondary_buffer_, 0, size);
-
-  HandleTableEntry* handle_table =
-      static_cast<HandleTableEntry*>(secondary_buffer_);
-  size_t current_offset = handle_table_size;
-  for (size_t i = 0; i < dispatchers_->size(); i++) {
-    Dispatcher* dispatcher = (*dispatchers_)[i].get();
-    if (!dispatcher) {
-      COMPILE_ASSERT(Dispatcher::kTypeUnknown == 0,
-                     value_of_Dispatcher_kTypeUnknown_must_be_zero);
-      continue;
-    }
-
-    void* destination = static_cast<char*>(secondary_buffer_) + current_offset;
-    size_t actual_size = 0;
-    if (Dispatcher::MessageInTransitAccess::SerializeAndClose(
-            dispatcher, channel, destination, &actual_size)) {
-      handle_table[i].type = static_cast<int32_t>(dispatcher->GetType());
-      handle_table[i].offset = static_cast<uint32_t>(current_offset);
-      handle_table[i].size = static_cast<uint32_t>(actual_size);
-    } else {
-      // (Nothing to do on failure, since |secondary_buffer_| was cleared, and
-      // |kTypeUnknown| is zero.)
-      // The handle will simply be closed.
-      LOG(ERROR) << "Failed to serialize handle to remote message pipe";
-    }
-
-    current_offset += RoundUpMessageAlignment(actual_size);
-    DCHECK_LE(current_offset, size);
-  }
+  transport_data_.reset(new TransportData(dispatchers_.Pass(), channel));
 
+  // Update the sizes in the message header.
   UpdateTotalSize();
 }
 
-void MessageInTransit::DeserializeDispatchers(Channel* channel) {
-  DCHECK(!dispatchers_.get());
-
-  // This should have been checked by calling |IsValid()| on the |View| first.
-  DCHECK_LE(num_handles(), kMaxMessageNumHandles);
-
-  if (!num_handles())
-    return;
-
-  dispatchers_.reset(
-      new std::vector<scoped_refptr<Dispatcher> >(num_handles()));
-
-  size_t handle_table_size = num_handles() * sizeof(HandleTableEntry);
-  if (secondary_buffer_size_ < handle_table_size) {
-    LOG(ERROR) << "Serialized handle table too small";
-    return;
-  }
-
-  const HandleTableEntry* handle_table =
-      static_cast<const HandleTableEntry*>(secondary_buffer_);
-  for (size_t i = 0; i < num_handles(); i++) {
-    size_t offset = handle_table[i].offset;
-    size_t size = handle_table[i].size;
-    // TODO(vtl): Sanity-check the size.
-    if (offset % kMessageAlignment != 0 || offset > secondary_buffer_size_ ||
-        offset + size > secondary_buffer_size_) {
-      // TODO(vtl): Maybe should report error (and make it possible to kill the
-      // connection with extreme prejudice).
-      LOG(ERROR) << "Invalid serialized handle table entry";
-      continue;
-    }
-
-    const void* source = static_cast<const char*>(secondary_buffer_) + offset;
-    (*dispatchers_)[i] = Dispatcher::MessageInTransitAccess::Deserialize(
-        channel, handle_table[i].type, source, size);
-  }
-}
-
-// Validates the secondary buffer. Returns null on success, or a human-readable
-// error message on error.
-// static
-const char* MessageInTransit::ValidateSecondaryBuffer(
-    size_t num_handles,
-    const void* secondary_buffer,
-    size_t secondary_buffer_size) {
-  if (!num_handles)
-    return NULL;
-
-  if (num_handles > kMaxMessageNumHandles)
-    return "Message handle payload too large";
-
-  if (secondary_buffer_size > kMaxSecondaryBufferSize)
-    return "Message secondary buffer too large";
-
-  if (secondary_buffer_size < num_handles * sizeof(HandleTableEntry))
-    return "Message secondary buffer too small";
-
-  DCHECK(secondary_buffer);
-  const HandleTableEntry* handle_table =
-      static_cast<const HandleTableEntry*>(secondary_buffer);
-
-  static const char kInvalidSerializedDispatcher[] =
-      "Message contains invalid serialized dispatcher";
-  for (size_t i = 0; i < num_handles; i++) {
-    size_t offset = handle_table[i].offset;
-    if (offset % kMessageAlignment != 0)
-      return kInvalidSerializedDispatcher;
-
-    size_t size = handle_table[i].size;
-    if (size > kMaxSerializedDispatcherSize || size > secondary_buffer_size)
-      return kInvalidSerializedDispatcher;
-
-    // Note: This is an overflow-safe check for |offset + size >
-    // secondary_buffer_size()| (we know that |size <= secondary_buffer_size()|
-    // from the previous check).
-    if (offset > secondary_buffer_size - size)
-      return kInvalidSerializedDispatcher;
-  }
-
-  return NULL;
-}
-
 void MessageInTransit::UpdateTotalSize() {
   DCHECK_EQ(main_buffer_size_ % kMessageAlignment, 0u);
-  DCHECK_EQ(secondary_buffer_size_ % kMessageAlignment, 0u);
-  header()->total_size =
-      static_cast<uint32_t>(main_buffer_size_ + secondary_buffer_size_);
+  header()->total_size = static_cast<uint32_t>(main_buffer_size_);
+  if (transport_data_) {
+    header()->total_size +=
+        static_cast<uint32_t>(transport_data_->buffer_size());
+  }
 }
 
 }  // namespace system