summaryrefslogtreecommitdiffstats
path: root/mojo/system/message_in_transit.cc
diff options
context:
space:
mode:
Diffstat (limited to 'mojo/system/message_in_transit.cc')
-rw-r--r--mojo/system/message_in_transit.cc51
1 files changed, 47 insertions, 4 deletions
diff --git a/mojo/system/message_in_transit.cc b/mojo/system/message_in_transit.cc
index a444a8e..9ac129e 100644
--- a/mojo/system/message_in_transit.cc
+++ b/mojo/system/message_in_transit.cc
@@ -89,6 +89,8 @@ 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)),
@@ -200,16 +202,19 @@ void MessageInTransit::SerializeAndCloseDispatchers(Channel* channel) {
continue;
}
+ void* destination = static_cast<char*>(secondary_buffer_) + current_offset;
size_t actual_size = 0;
if (Dispatcher::MessageInTransitAccess::SerializeAndClose(
- dispatcher, static_cast<char*>(secondary_buffer_) + current_offset,
- channel, &actual_size)) {
+ 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";
}
- // (Nothing to do on failure, since |secondary_buffer_| was cleared, and
- // |kTypeUnknown| is zero.)
current_offset += RoundUpMessageAlignment(actual_size);
DCHECK_LE(current_offset, size);
@@ -218,6 +223,44 @@ void MessageInTransit::SerializeAndCloseDispatchers(Channel* channel) {
UpdateTotalSize();
}
+void MessageInTransit::DeserializeDispatchers(Channel* channel) {
+ DCHECK(!dispatchers_.get());
+
+ if (!num_handles())
+ return;
+
+ // TODO(vtl): Restrict |num_handles()| to a sane range. (Maybe this should be
+ // done earlier?)
+
+ 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);
+ }
+}
+
void MessageInTransit::UpdateTotalSize() {
DCHECK_EQ(main_buffer_size_ % kMessageAlignment, 0u);
DCHECK_EQ(secondary_buffer_size_ % kMessageAlignment, 0u);