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

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

Powered by Google App Engine
This is Rietveld 408576698