Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(473)

Unified Diff: mojo/edk/system/message_for_transit.cc

Issue 1880823005: [mojo-edk] Add explicit message object APIs (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « mojo/edk/system/message_for_transit.h ('k') | mojo/edk/system/message_pipe_dispatcher.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: mojo/edk/system/message_for_transit.cc
diff --git a/mojo/edk/system/message_for_transit.cc b/mojo/edk/system/message_for_transit.cc
new file mode 100644
index 0000000000000000000000000000000000000000..26658e161c630b0386fe98afe62abedd067e68c6
--- /dev/null
+++ b/mojo/edk/system/message_for_transit.cc
@@ -0,0 +1,136 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/edk/system/message_for_transit.h"
+
+#include <vector>
+
+#include "mojo/edk/embedder/platform_handle_vector.h"
+
+namespace mojo {
+namespace edk {
+
+namespace {
+
+static_assert(sizeof(MessageForTransit::MessageHeader) % 8 == 0,
+ "Invalid MessageHeader size.");
+static_assert(sizeof(MessageForTransit::DispatcherHeader) % 8 == 0,
+ "Invalid DispatcherHeader size.");
+
+} // namespace
+
+MessageForTransit::~MessageForTransit() {}
+
+// static
+MojoResult MessageForTransit::Create(
+ std::unique_ptr<MessageForTransit>* message,
+ uint32_t num_bytes,
+ const Dispatcher::DispatcherInTransit* dispatchers,
+ uint32_t num_dispatchers) {
+ // A structure for retaining information about every Dispatcher that will be
+ // sent with this message.
+ struct DispatcherInfo {
+ uint32_t num_bytes;
+ uint32_t num_ports;
+ uint32_t num_handles;
+ };
+
+ // This is only the base header size. It will grow as we accumulate the
+ // size of serialized state for each dispatcher.
+ size_t header_size = sizeof(MessageHeader) +
+ num_dispatchers * sizeof(DispatcherHeader);
+ size_t num_ports = 0;
+ size_t num_handles = 0;
+
+ std::vector<DispatcherInfo> dispatcher_info(num_dispatchers);
+ for (size_t i = 0; i < num_dispatchers; ++i) {
+ Dispatcher* d = dispatchers[i].dispatcher.get();
+ d->StartSerialize(&dispatcher_info[i].num_bytes,
+ &dispatcher_info[i].num_ports,
+ &dispatcher_info[i].num_handles);
+ header_size += dispatcher_info[i].num_bytes;
+ num_ports += dispatcher_info[i].num_ports;
+ num_handles += dispatcher_info[i].num_handles;
+ }
+
+ // We now have enough information to fully allocate the message storage.
+ std::unique_ptr<PortsMessage> msg = PortsMessage::NewUserMessage(
+ header_size + num_bytes, num_ports, num_handles);
+ if (!msg)
+ return MOJO_RESULT_RESOURCE_EXHAUSTED;
+
+ // Populate the message header with information about serialized dispatchers.
+ //
+ // The front of the message is always a MessageHeader followed by a
+ // DispatcherHeader for each dispatcher to be sent.
+ MessageHeader* header =
+ static_cast<MessageHeader*>(msg->mutable_payload_bytes());
+ DispatcherHeader* dispatcher_headers =
+ reinterpret_cast<DispatcherHeader*>(header + 1);
+
+ // Serialized dispatcher state immediately follows the series of
+ // DispatcherHeaders.
+ char* dispatcher_data =
+ reinterpret_cast<char*>(dispatcher_headers + num_dispatchers);
+
+ header->num_dispatchers = num_dispatchers;
+
+ // |header_size| is the total number of bytes preceding the message payload,
+ // including all dispatcher headers and serialized dispatcher state.
+ DCHECK_LE(header_size, std::numeric_limits<uint32_t>::max());
+ header->header_size = static_cast<uint32_t>(header_size);
+
+ if (num_dispatchers > 0) {
+ ScopedPlatformHandleVectorPtr handles(
+ new PlatformHandleVector(num_handles));
+ size_t port_index = 0;
+ size_t handle_index = 0;
+ bool fail = false;
+ for (size_t i = 0; i < num_dispatchers; ++i) {
+ Dispatcher* d = dispatchers[i].dispatcher.get();
+ DispatcherHeader* dh = &dispatcher_headers[i];
+ const DispatcherInfo& info = dispatcher_info[i];
+
+ // Fill in the header for this dispatcher.
+ dh->type = static_cast<int32_t>(d->GetType());
+ dh->num_bytes = info.num_bytes;
+ dh->num_ports = info.num_ports;
+ dh->num_platform_handles = info.num_handles;
+
+ // Fill in serialized state, ports, and platform handles. We'll cancel
+ // the send if the dispatcher implementation rejects for some reason.
+ if (!d->EndSerialize(static_cast<void*>(dispatcher_data),
+ msg->mutable_ports() + port_index,
+ handles->data() + handle_index)) {
+ fail = true;
+ break;
+ }
+
+ dispatcher_data += info.num_bytes;
+ port_index += info.num_ports;
+ handle_index += info.num_handles;
+ }
+
+ if (fail) {
+ // Release any platform handles we've accumulated. Their dispatchers
+ // retain ownership when message creation fails, so these are not actually
+ // leaking.
+ handles->clear();
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ }
+
+ // Take ownership of all the handles and move them into message storage.
+ msg->SetHandles(std::move(handles));
+ }
+
+ message->reset(new MessageForTransit(std::move(msg)));
+ return MOJO_RESULT_OK;
+}
+
+MessageForTransit::MessageForTransit(std::unique_ptr<PortsMessage> message)
+ : message_(std::move(message)) {
+}
+
+} // namespace edk
+} // namespace mojo
« no previous file with comments | « mojo/edk/system/message_for_transit.h ('k') | mojo/edk/system/message_pipe_dispatcher.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698