OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "mojo/edk/system/shared_buffer_dispatcher.h" | 5 #include "mojo/edk/system/shared_buffer_dispatcher.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <algorithm> | |
11 #include <limits> | 10 #include <limits> |
12 #include <utility> | 11 #include <utility> |
13 | 12 |
14 #include "base/logging.h" | 13 #include "base/logging.h" |
15 #include "base/memory/scoped_ptr.h" | 14 #include "base/memory/scoped_ptr.h" |
16 #include "mojo/edk/embedder/embedder_internal.h" | 15 #include "mojo/edk/embedder/embedder_internal.h" |
17 #include "mojo/edk/embedder/platform_support.h" | 16 #include "mojo/edk/embedder/platform_support.h" |
18 #include "mojo/edk/system/configuration.h" | 17 #include "mojo/edk/system/configuration.h" |
19 #include "mojo/edk/system/options_validation.h" | 18 #include "mojo/edk/system/options_validation.h" |
20 #include "mojo/public/c/system/macros.h" | 19 #include "mojo/public/c/system/macros.h" |
21 | 20 |
22 namespace mojo { | 21 namespace mojo { |
23 namespace edk { | 22 namespace edk { |
24 | 23 |
25 namespace { | 24 namespace { |
26 | 25 |
27 struct MOJO_ALIGNAS(8) SerializedSharedBufferDispatcher { | 26 struct MOJO_ALIGNAS(8) SerializedSharedBufferDispatcher { |
28 MOJO_ALIGNAS(4) uint32_t num_bytes; | 27 size_t num_bytes; |
Anand Mistry (off Chromium)
2016/01/28 02:26:24
Please don't use size_t in serialised messages.
| |
29 MOJO_ALIGNAS(4) uint32_t platform_handle_index; | |
30 }; | 28 }; |
31 | 29 |
32 } // namespace | 30 } // namespace |
33 | 31 |
34 // static | 32 // static |
35 const MojoCreateSharedBufferOptions | 33 const MojoCreateSharedBufferOptions |
36 SharedBufferDispatcher::kDefaultCreateOptions = { | 34 SharedBufferDispatcher::kDefaultCreateOptions = { |
37 static_cast<uint32_t>(sizeof(MojoCreateSharedBufferOptions)), | 35 static_cast<uint32_t>(sizeof(MojoCreateSharedBufferOptions)), |
38 MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE}; | 36 MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE}; |
39 | 37 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
78 | 76 |
79 scoped_refptr<PlatformSharedBuffer> shared_buffer( | 77 scoped_refptr<PlatformSharedBuffer> shared_buffer( |
80 platform_support->CreateSharedBuffer(static_cast<size_t>(num_bytes))); | 78 platform_support->CreateSharedBuffer(static_cast<size_t>(num_bytes))); |
81 if (!shared_buffer) | 79 if (!shared_buffer) |
82 return MOJO_RESULT_RESOURCE_EXHAUSTED; | 80 return MOJO_RESULT_RESOURCE_EXHAUSTED; |
83 | 81 |
84 *result = CreateInternal(std::move(shared_buffer)); | 82 *result = CreateInternal(std::move(shared_buffer)); |
85 return MOJO_RESULT_OK; | 83 return MOJO_RESULT_OK; |
86 } | 84 } |
87 | 85 |
88 Dispatcher::Type SharedBufferDispatcher::GetType() const { | |
89 return Type::SHARED_BUFFER; | |
90 } | |
91 | |
92 // static | 86 // static |
93 scoped_refptr<SharedBufferDispatcher> SharedBufferDispatcher::Deserialize( | 87 scoped_refptr<SharedBufferDispatcher> SharedBufferDispatcher::Deserialize( |
94 const void* source, | 88 const void* bytes, |
95 size_t size, | 89 size_t num_bytes, |
96 PlatformHandleVector* platform_handles) { | 90 const ports::PortName* ports, |
97 | 91 size_t num_ports, |
98 if (size != sizeof(SerializedSharedBufferDispatcher)) { | 92 PlatformHandle* platform_handles, |
93 size_t num_platform_handles) { | |
94 if (num_bytes != sizeof(SerializedSharedBufferDispatcher)) { | |
99 LOG(ERROR) << "Invalid serialized shared buffer dispatcher (bad size)"; | 95 LOG(ERROR) << "Invalid serialized shared buffer dispatcher (bad size)"; |
100 return nullptr; | 96 return nullptr; |
101 } | 97 } |
102 | 98 |
103 const SerializedSharedBufferDispatcher* serialization = | 99 const SerializedSharedBufferDispatcher* serialization = |
104 static_cast<const SerializedSharedBufferDispatcher*>(source); | 100 static_cast<const SerializedSharedBufferDispatcher*>(bytes); |
105 size_t num_bytes = serialization->num_bytes; | 101 if (!serialization->num_bytes) { |
106 size_t platform_handle_index = serialization->platform_handle_index; | |
107 | |
108 if (!num_bytes) { | |
109 LOG(ERROR) | 102 LOG(ERROR) |
110 << "Invalid serialized shared buffer dispatcher (invalid num_bytes)"; | 103 << "Invalid serialized shared buffer dispatcher (invalid num_bytes)"; |
111 return nullptr; | 104 return nullptr; |
112 } | 105 } |
113 | 106 |
114 if (!platform_handles || platform_handle_index >= platform_handles->size()) { | 107 if (!platform_handles || num_platform_handles != 1 || num_ports) { |
115 LOG(ERROR) | 108 LOG(ERROR) |
116 << "Invalid serialized shared buffer dispatcher (missing handles)"; | 109 << "Invalid serialized shared buffer dispatcher (missing handles)"; |
117 return nullptr; | 110 return nullptr; |
118 } | 111 } |
119 | 112 |
120 // Starts off invalid, which is what we want. | 113 // Starts off invalid, which is what we want. |
121 PlatformHandle platform_handle; | 114 PlatformHandle platform_handle; |
122 // We take ownership of the handle, so we have to invalidate the one in | 115 // We take ownership of the handle, so we have to invalidate the one in |
123 // |platform_handles|. | 116 // |platform_handles|. |
124 std::swap(platform_handle, (*platform_handles)[platform_handle_index]); | 117 std::swap(platform_handle, *platform_handles); |
125 | 118 |
126 // Wrapping |platform_handle| in a |ScopedPlatformHandle| means that it'll be | 119 // Wrapping |platform_handle| in a |ScopedPlatformHandle| means that it'll be |
127 // closed even if creation fails. | 120 // closed even if creation fails. |
128 scoped_refptr<PlatformSharedBuffer> shared_buffer( | 121 scoped_refptr<PlatformSharedBuffer> shared_buffer( |
129 internal::g_platform_support->CreateSharedBufferFromHandle( | 122 internal::g_platform_support->CreateSharedBufferFromHandle( |
130 num_bytes, ScopedPlatformHandle(platform_handle))); | 123 serialization->num_bytes, ScopedPlatformHandle(platform_handle))); |
131 if (!shared_buffer) { | 124 if (!shared_buffer) { |
132 LOG(ERROR) | 125 LOG(ERROR) |
133 << "Invalid serialized shared buffer dispatcher (invalid num_bytes?)"; | 126 << "Invalid serialized shared buffer dispatcher (invalid num_bytes?)"; |
134 return nullptr; | 127 return nullptr; |
135 } | 128 } |
136 | 129 |
137 return CreateInternal(std::move(shared_buffer)); | 130 return CreateInternal(std::move(shared_buffer)); |
138 } | 131 } |
139 | 132 |
140 SharedBufferDispatcher::SharedBufferDispatcher( | 133 Dispatcher::Type SharedBufferDispatcher::GetType() const { |
141 scoped_refptr<PlatformSharedBuffer> shared_buffer) | 134 return Type::SHARED_BUFFER; |
142 : shared_buffer_(shared_buffer) { | |
143 DCHECK(shared_buffer_); | |
144 } | 135 } |
145 | 136 |
146 SharedBufferDispatcher::~SharedBufferDispatcher() { | 137 MojoResult SharedBufferDispatcher::Close() { |
147 } | 138 base::AutoLock lock(lock_); |
148 | 139 if (!shared_buffer_ || in_transit_) |
149 // static | |
150 MojoResult SharedBufferDispatcher::ValidateDuplicateOptions( | |
151 const MojoDuplicateBufferHandleOptions* in_options, | |
152 MojoDuplicateBufferHandleOptions* out_options) { | |
153 const MojoDuplicateBufferHandleOptionsFlags kKnownFlags = | |
154 MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE; | |
155 static const MojoDuplicateBufferHandleOptions kDefaultOptions = { | |
156 static_cast<uint32_t>(sizeof(MojoDuplicateBufferHandleOptions)), | |
157 MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE}; | |
158 | |
159 *out_options = kDefaultOptions; | |
160 if (!in_options) | |
161 return MOJO_RESULT_OK; | |
162 | |
163 UserOptionsReader<MojoDuplicateBufferHandleOptions> reader(in_options); | |
164 if (!reader.is_valid()) | |
165 return MOJO_RESULT_INVALID_ARGUMENT; | 140 return MOJO_RESULT_INVALID_ARGUMENT; |
166 | 141 |
167 if (!OPTIONS_STRUCT_HAS_MEMBER(MojoDuplicateBufferHandleOptions, flags, | 142 shared_buffer_ = nullptr; |
168 reader)) | |
169 return MOJO_RESULT_OK; | |
170 if ((reader.options().flags & ~kKnownFlags)) | |
171 return MOJO_RESULT_UNIMPLEMENTED; | |
172 out_options->flags = reader.options().flags; | |
173 | |
174 // Checks for fields beyond |flags|: | |
175 | |
176 // (Nothing here yet.) | |
177 | |
178 return MOJO_RESULT_OK; | 143 return MOJO_RESULT_OK; |
179 } | 144 } |
180 | 145 |
181 void SharedBufferDispatcher::CloseImplNoLock() { | 146 MojoResult SharedBufferDispatcher::DuplicateBufferHandle( |
182 lock().AssertAcquired(); | |
183 DCHECK(shared_buffer_); | |
184 shared_buffer_ = nullptr; | |
185 } | |
186 | |
187 scoped_refptr<Dispatcher> | |
188 SharedBufferDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock() { | |
189 lock().AssertAcquired(); | |
190 DCHECK(shared_buffer_); | |
191 return CreateInternal(std::move(shared_buffer_)); | |
192 } | |
193 | |
194 MojoResult SharedBufferDispatcher::DuplicateBufferHandleImplNoLock( | |
195 const MojoDuplicateBufferHandleOptions* options, | 147 const MojoDuplicateBufferHandleOptions* options, |
196 scoped_refptr<Dispatcher>* new_dispatcher) { | 148 scoped_refptr<Dispatcher>* new_dispatcher) { |
197 lock().AssertAcquired(); | |
198 | |
199 MojoDuplicateBufferHandleOptions validated_options; | 149 MojoDuplicateBufferHandleOptions validated_options; |
200 MojoResult result = ValidateDuplicateOptions(options, &validated_options); | 150 MojoResult result = ValidateDuplicateOptions(options, &validated_options); |
201 if (result != MOJO_RESULT_OK) | 151 if (result != MOJO_RESULT_OK) |
202 return result; | 152 return result; |
203 | 153 |
204 // Note: Since this is "duplicate", we keep our ref to |shared_buffer_|. | 154 // Note: Since this is "duplicate", we keep our ref to |shared_buffer_|. |
155 base::AutoLock lock(lock_); | |
156 if (in_transit_) | |
157 return MOJO_RESULT_INVALID_ARGUMENT; | |
205 *new_dispatcher = CreateInternal(shared_buffer_); | 158 *new_dispatcher = CreateInternal(shared_buffer_); |
206 return MOJO_RESULT_OK; | 159 return MOJO_RESULT_OK; |
207 } | 160 } |
208 | 161 |
209 MojoResult SharedBufferDispatcher::MapBufferImplNoLock( | 162 MojoResult SharedBufferDispatcher::MapBuffer( |
210 uint64_t offset, | 163 uint64_t offset, |
211 uint64_t num_bytes, | 164 uint64_t num_bytes, |
212 MojoMapBufferFlags flags, | 165 MojoMapBufferFlags flags, |
213 scoped_ptr<PlatformSharedBufferMapping>* mapping) { | 166 scoped_ptr<PlatformSharedBufferMapping>* mapping) { |
214 lock().AssertAcquired(); | |
215 DCHECK(shared_buffer_); | |
216 | |
217 if (offset > static_cast<uint64_t>(std::numeric_limits<size_t>::max())) | 167 if (offset > static_cast<uint64_t>(std::numeric_limits<size_t>::max())) |
218 return MOJO_RESULT_INVALID_ARGUMENT; | 168 return MOJO_RESULT_INVALID_ARGUMENT; |
219 if (num_bytes > static_cast<uint64_t>(std::numeric_limits<size_t>::max())) | 169 if (num_bytes > static_cast<uint64_t>(std::numeric_limits<size_t>::max())) |
220 return MOJO_RESULT_INVALID_ARGUMENT; | 170 return MOJO_RESULT_INVALID_ARGUMENT; |
221 | 171 |
222 if (!shared_buffer_->IsValidMap(static_cast<size_t>(offset), | 172 base::AutoLock lock(lock_); |
223 static_cast<size_t>(num_bytes))) | 173 DCHECK(shared_buffer_); |
174 if (in_transit_ || | |
175 !shared_buffer_->IsValidMap(static_cast<size_t>(offset), | |
176 static_cast<size_t>(num_bytes))) { | |
224 return MOJO_RESULT_INVALID_ARGUMENT; | 177 return MOJO_RESULT_INVALID_ARGUMENT; |
178 } | |
225 | 179 |
226 DCHECK(mapping); | 180 DCHECK(mapping); |
227 *mapping = shared_buffer_->MapNoCheck(static_cast<size_t>(offset), | 181 *mapping = shared_buffer_->MapNoCheck(static_cast<size_t>(offset), |
228 static_cast<size_t>(num_bytes)); | 182 static_cast<size_t>(num_bytes)); |
229 if (!*mapping) | 183 if (!*mapping) |
230 return MOJO_RESULT_RESOURCE_EXHAUSTED; | 184 return MOJO_RESULT_RESOURCE_EXHAUSTED; |
231 | 185 |
232 return MOJO_RESULT_OK; | 186 return MOJO_RESULT_OK; |
233 } | 187 } |
234 | 188 |
235 void SharedBufferDispatcher::StartSerializeImplNoLock( | 189 void SharedBufferDispatcher::StartSerialize(uint32_t* num_bytes, |
236 size_t* max_size, | 190 uint32_t* num_ports, |
237 size_t* max_platform_handles) { | 191 uint32_t* num_platform_handles) { |
238 *max_size = sizeof(SerializedSharedBufferDispatcher); | 192 *num_bytes = sizeof(SerializedSharedBufferDispatcher); |
239 *max_platform_handles = 1; | 193 *num_ports = 0; |
194 *num_platform_handles = 1; | |
240 } | 195 } |
241 | 196 |
242 bool SharedBufferDispatcher::EndSerializeAndCloseImplNoLock( | 197 bool SharedBufferDispatcher::EndSerialize(void* destination, |
243 void* destination, | 198 ports::PortName* ports, |
244 size_t* actual_size, | 199 PlatformHandle* handles) { |
245 PlatformHandleVector* platform_handles) { | |
246 DCHECK(shared_buffer_); | |
247 | |
248 SerializedSharedBufferDispatcher* serialization = | 200 SerializedSharedBufferDispatcher* serialization = |
249 static_cast<SerializedSharedBufferDispatcher*>(destination); | 201 static_cast<SerializedSharedBufferDispatcher*>(destination); |
250 // If there's only one reference to |shared_buffer_|, then it's ours (and no | 202 base::AutoLock lock(lock_); |
251 // one else can make any more references to it), so we can just take its | 203 serialization->num_bytes = shared_buffer_->GetNumBytes(); |
252 // handle. | 204 |
253 ScopedPlatformHandle platform_handle( | 205 handle_for_transit_ = shared_buffer_->DuplicatePlatformHandle(); |
254 shared_buffer_->HasOneRef() ? shared_buffer_->PassPlatformHandle() | 206 if (!handle_for_transit_.is_valid()) { |
255 : shared_buffer_->DuplicatePlatformHandle()); | |
256 if (!platform_handle.is_valid()) { | |
257 shared_buffer_ = nullptr; | 207 shared_buffer_ = nullptr; |
258 return false; | 208 return false; |
259 } | 209 } |
260 | 210 handles[0] = handle_for_transit_.get(); |
261 DCHECK(shared_buffer_->GetNumBytes() < std::numeric_limits<uint32_t>::max()); | |
262 serialization->num_bytes = | |
263 static_cast<uint32_t>(shared_buffer_->GetNumBytes()); | |
264 DCHECK(platform_handles->size() < std::numeric_limits<uint32_t>::max()); | |
265 serialization->platform_handle_index = | |
266 static_cast<uint32_t>(platform_handles->size()); | |
267 platform_handles->push_back(platform_handle.release()); | |
268 *actual_size = sizeof(SerializedSharedBufferDispatcher); | |
269 | |
270 shared_buffer_ = nullptr; | |
271 | |
272 return true; | 211 return true; |
273 } | 212 } |
274 | 213 |
214 bool SharedBufferDispatcher::BeginTransit() { | |
215 base::AutoLock lock(lock_); | |
216 if (in_transit_) | |
217 return false; | |
218 in_transit_ = shared_buffer_ != nullptr; | |
219 return in_transit_; | |
220 } | |
221 | |
222 void SharedBufferDispatcher::CompleteTransitAndClose() { | |
223 base::AutoLock lock(lock_); | |
224 in_transit_ = false; | |
225 shared_buffer_ = nullptr; | |
226 ignore_result(handle_for_transit_.release()); | |
227 } | |
228 | |
229 void SharedBufferDispatcher::CancelTransit() { | |
230 base::AutoLock lock(lock_); | |
231 in_transit_ = false; | |
232 handle_for_transit_.reset(); | |
233 } | |
234 | |
235 SharedBufferDispatcher::SharedBufferDispatcher( | |
236 scoped_refptr<PlatformSharedBuffer> shared_buffer) | |
237 : shared_buffer_(shared_buffer) { | |
238 DCHECK(shared_buffer_); | |
239 } | |
240 | |
241 SharedBufferDispatcher::~SharedBufferDispatcher() { | |
242 DCHECK(!shared_buffer_ && !in_transit_); | |
243 } | |
244 | |
245 // static | |
246 MojoResult SharedBufferDispatcher::ValidateDuplicateOptions( | |
247 const MojoDuplicateBufferHandleOptions* in_options, | |
248 MojoDuplicateBufferHandleOptions* out_options) { | |
249 const MojoDuplicateBufferHandleOptionsFlags kKnownFlags = | |
250 MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE; | |
251 static const MojoDuplicateBufferHandleOptions kDefaultOptions = { | |
252 static_cast<uint32_t>(sizeof(MojoDuplicateBufferHandleOptions)), | |
253 MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE}; | |
254 | |
255 *out_options = kDefaultOptions; | |
256 if (!in_options) | |
257 return MOJO_RESULT_OK; | |
258 | |
259 UserOptionsReader<MojoDuplicateBufferHandleOptions> reader(in_options); | |
260 if (!reader.is_valid()) | |
261 return MOJO_RESULT_INVALID_ARGUMENT; | |
262 | |
263 if (!OPTIONS_STRUCT_HAS_MEMBER(MojoDuplicateBufferHandleOptions, flags, | |
264 reader)) | |
265 return MOJO_RESULT_OK; | |
266 if ((reader.options().flags & ~kKnownFlags)) | |
267 return MOJO_RESULT_UNIMPLEMENTED; | |
268 out_options->flags = reader.options().flags; | |
269 | |
270 // Checks for fields beyond |flags|: | |
271 | |
272 // (Nothing here yet.) | |
273 | |
274 return MOJO_RESULT_OK; | |
275 } | |
275 | 276 |
276 } // namespace edk | 277 } // namespace edk |
277 } // namespace mojo | 278 } // namespace mojo |
OLD | NEW |