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

Side by Side 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, 7 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 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 #include "mojo/edk/system/message_for_transit.h"
6
7 #include <vector>
8
9 #include "base/memory/ptr_util.h"
10 #include "mojo/edk/embedder/platform_handle_vector.h"
11
12 namespace mojo {
13 namespace edk {
14
15 namespace {
16
17 static_assert(sizeof(MessageForTransit::MessageHeader) % 8 == 0,
18 "Invalid MessageHeader size.");
19 static_assert(sizeof(MessageForTransit::DispatcherHeader) % 8 == 0,
20 "Invalid DispatcherHeader size.");
21
22 const MessageForTransit::MessageHeader* GetHeader(const PortsMessage& message) {
23 return static_cast<const MessageForTransit::MessageHeader*>(
24 message.payload_bytes());
25 }
26
27 } // namespace
28
29 MessageForTransit::~MessageForTransit() {}
30
31 // static
32 MojoResult MessageForTransit::Create(
33 std::unique_ptr<MessageForTransit>* message,
34 uint32_t num_bytes,
35 const Dispatcher::DispatcherInTransit* dispatchers,
36 uint32_t num_dispatchers) {
37 // A structure for retaining information about every Dispatcher that will be
38 // sent with this message.
39 struct DispatcherInfo {
40 uint32_t num_bytes;
41 uint32_t num_ports;
42 uint32_t num_handles;
43 };
44
45 // This is only the base header size. It will grow as we accumulate the
46 // size of serialized state for each dispatcher.
47 size_t header_size = sizeof(MessageHeader) +
48 num_dispatchers * sizeof(DispatcherHeader);
49 size_t num_ports = 0;
50 size_t num_handles = 0;
51
52 std::vector<DispatcherInfo> dispatcher_info(num_dispatchers);
53 for (size_t i = 0; i < num_dispatchers; ++i) {
54 Dispatcher* d = dispatchers[i].dispatcher.get();
55 d->StartSerialize(&dispatcher_info[i].num_bytes,
56 &dispatcher_info[i].num_ports,
57 &dispatcher_info[i].num_handles);
58 header_size += dispatcher_info[i].num_bytes;
59 num_ports += dispatcher_info[i].num_ports;
60 num_handles += dispatcher_info[i].num_handles;
61 }
62
63 // We now have enough information to fully allocate the message storage.
64 std::unique_ptr<PortsMessage> msg = PortsMessage::NewUserMessage(
65 header_size + num_bytes, num_ports, num_handles);
66 if (!msg)
67 return MOJO_RESULT_RESOURCE_EXHAUSTED;
68
69 // Populate the message header with information about serialized dispatchers.
70 //
71 // The front of the message is always a MessageHeader followed by a
72 // DispatcherHeader for each dispatcher to be sent.
73 MessageHeader* header =
74 static_cast<MessageHeader*>(msg->mutable_payload_bytes());
75 DispatcherHeader* dispatcher_headers =
76 reinterpret_cast<DispatcherHeader*>(header + 1);
77
78 // Serialized dispatcher state immediately follows the series of
79 // DispatcherHeaders.
80 char* dispatcher_data =
81 reinterpret_cast<char*>(dispatcher_headers + num_dispatchers);
82
83 header->num_dispatchers = num_dispatchers;
84
85 // |header_size| is the total number of bytes preceding the message payload,
86 // including all dispatcher headers and serialized dispatcher state.
87 DCHECK_LE(header_size, std::numeric_limits<uint32_t>::max());
88 header->header_size = static_cast<uint32_t>(header_size);
89
90 if (num_dispatchers > 0) {
91 ScopedPlatformHandleVectorPtr handles(
92 new PlatformHandleVector(num_handles));
93 size_t port_index = 0;
94 size_t handle_index = 0;
95 bool fail = false;
96 for (size_t i = 0; i < num_dispatchers; ++i) {
97 Dispatcher* d = dispatchers[i].dispatcher.get();
98 DispatcherHeader* dh = &dispatcher_headers[i];
99 const DispatcherInfo& info = dispatcher_info[i];
100
101 // Fill in the header for this dispatcher.
102 dh->type = static_cast<int32_t>(d->GetType());
103 dh->num_bytes = info.num_bytes;
104 dh->num_ports = info.num_ports;
105 dh->num_platform_handles = info.num_handles;
106
107 // Fill in serialized state, ports, and platform handles. We'll cancel
108 // the send if the dispatcher implementation rejects for some reason.
109 if (!d->EndSerialize(static_cast<void*>(dispatcher_data),
110 msg->mutable_ports() + port_index,
111 handles->data() + handle_index)) {
112 fail = true;
113 break;
114 }
115
116 dispatcher_data += info.num_bytes;
117 port_index += info.num_ports;
118 handle_index += info.num_handles;
119 }
120
121 if (fail) {
122 // Release any platform handles we've accumulated. Their dispatchers
123 // retain ownership when message creation fails, so these are not actually
124 // leaking.
125 handles->clear();
126 return MOJO_RESULT_INVALID_ARGUMENT;
127 }
128
129 // Take ownership of all the handles and move them into message storage.
130 msg->SetHandles(std::move(handles));
131 }
132
133 message->reset(new MessageForTransit(std::move(msg)));
134 return MOJO_RESULT_OK;
135 }
136
137 // static
138 std::unique_ptr<MessageForTransit> MessageForTransit::WrapPortsMessage(
139 std::unique_ptr<PortsMessage> message) {
140 return base::WrapUnique(new MessageForTransit(std::move(message)));
141 }
142
143 const void* MessageForTransit::bytes() const {
144 DCHECK(message_);
145 return static_cast<const void*>(
146 static_cast<const char*>(message_->payload_bytes()) +
147 GetHeader(*message_)->header_size);
148 }
149
150 void* MessageForTransit::mutable_bytes() {
151 DCHECK(message_);
152 return static_cast<void*>(
153 static_cast<char*>(message_->mutable_payload_bytes()) +
154 GetHeader(*message_)->header_size);
155 }
156
157 size_t MessageForTransit::num_bytes() const {
158 DCHECK(message_);
159 size_t header_size = GetHeader(*message_)->header_size;
160 DCHECK_GE(message_->num_payload_bytes(), header_size);
161 return message_->num_payload_bytes() - header_size;
162 }
163
164 size_t MessageForTransit::num_handles() const {
165 DCHECK(message_);
166 return GetHeader(*message_)->num_dispatchers;
167 }
168
169 std::unique_ptr<PortsMessage> MessageForTransit::TakePortsMessage() {
170 return std::move(message_);
171 }
172
173 MessageForTransit::MessageForTransit(std::unique_ptr<PortsMessage> message)
174 : message_(std::move(message)) {
175 }
176
177 } // namespace edk
178 } // namespace mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698