1 // Copyright 2013 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/core.h"
6
7 #include <string.h>
8
9 #include <utility>
10
11 #include "base/bind.h"
12 #include "base/containers/stack_container.h"
13 #include "base/location.h"
14 #include "base/logging.h"
15 #include "base/macros.h"
16 #include "base/memory/ptr_util.h"
17 #include "base/message_loop/message_loop.h"
18 #include "base/rand_util.h"
19 #include "base/threading/thread_task_runner_handle.h"
20 #include "base/time/time.h"
21 #include "mojo/edk/embedder/embedder.h"
22 #include "mojo/edk/embedder/embedder_internal.h"
23 #include "mojo/edk/embedder/platform_shared_buffer.h"
24 #include "mojo/edk/system/channel.h"
25 #include "mojo/edk/system/configuration.h"
26 #include "mojo/edk/system/data_pipe_consumer_dispatcher.h"
27 #include "mojo/edk/system/data_pipe_producer_dispatcher.h"
28 #include "mojo/edk/system/handle_signals_state.h"
29 #include "mojo/edk/system/message_for_transit.h"
30 #include "mojo/edk/system/message_pipe_dispatcher.h"
31 #include "mojo/edk/system/platform_handle_dispatcher.h"
32 #include "mojo/edk/system/ports/name.h"
33 #include "mojo/edk/system/ports/node.h"
34 #include "mojo/edk/system/request_context.h"
35 #include "mojo/edk/system/shared_buffer_dispatcher.h"
36 #include "mojo/edk/system/wait_set_dispatcher.h"
37 #include "mojo/edk/system/waiter.h"
38
39 namespace mojo {
40 namespace edk {
41
42 namespace {
43
44 // This is an unnecessarily large limit that is relatively easy to enforce.
45 const uint32_t kMaxHandlesPerMessage = 1024 * 1024;
46
47 // TODO(rockot): Maybe we could negotiate a debugging pipe ID for cross-process
48 // pipes too; for now we just use a constant. This only affects bootstrap pipes.
49 const uint64_t kUnknownPipeIdForDebug = 0x7f7f7f7f7f7f7f7fUL;
50
CallWatchCallback(MojoWatchCallback callback,uintptr_t context,MojoResult result,const HandleSignalsState & signals_state,MojoWatchNotificationFlags flags)51 void CallWatchCallback(MojoWatchCallback callback,
52 uintptr_t context,
53 MojoResult result,
54 const HandleSignalsState& signals_state,
55 MojoWatchNotificationFlags flags) {
56 callback(context, result, static_cast<MojoHandleSignalsState>(signals_state),
57 flags);
58 }
59
MojoPlatformHandleToScopedPlatformHandle(const MojoPlatformHandle * platform_handle,ScopedPlatformHandle * out_handle)60 MojoResult MojoPlatformHandleToScopedPlatformHandle(
61 const MojoPlatformHandle* platform_handle,
62 ScopedPlatformHandle* out_handle) {
63 if (platform_handle->struct_size != sizeof(MojoPlatformHandle))
64 return MOJO_RESULT_INVALID_ARGUMENT;
65
66 if (platform_handle->type == MOJO_PLATFORM_HANDLE_TYPE_INVALID) {
67 out_handle->reset();
68 return MOJO_RESULT_OK;
69 }
70
71 PlatformHandle handle;
72 switch (platform_handle->type) {
73 #if defined(OS_POSIX)
74 case MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR:
75 handle.handle = static_cast<int>(platform_handle->value);
76 break;
77 #endif
78
79 #if defined(OS_MACOSX) && !defined(OS_IOS)
80 case MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT:
81 handle.type = PlatformHandle::Type::MACH;
82 handle.port = static_cast<mach_port_t>(platform_handle->value);
83 break;
84 #endif
85
86 #if defined(OS_WIN)
87 case MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE:
88 handle.handle = reinterpret_cast<HANDLE>(platform_handle->value);
89 break;
90 #endif
91
92 default:
93 return MOJO_RESULT_INVALID_ARGUMENT;
94 }
95
96 out_handle->reset(handle);
97 return MOJO_RESULT_OK;
98 }
99
ScopedPlatformHandleToMojoPlatformHandle(ScopedPlatformHandle handle,MojoPlatformHandle * platform_handle)100 MojoResult ScopedPlatformHandleToMojoPlatformHandle(
101 ScopedPlatformHandle handle,
102 MojoPlatformHandle* platform_handle) {
103 if (platform_handle->struct_size != sizeof(MojoPlatformHandle))
104 return MOJO_RESULT_INVALID_ARGUMENT;
105
106 if (!handle.is_valid()) {
107 platform_handle->type = MOJO_PLATFORM_HANDLE_TYPE_INVALID;
108 return MOJO_RESULT_OK;
109 }
110
111 #if defined(OS_POSIX)
112 switch (handle.get().type) {
113 case PlatformHandle::Type::POSIX:
114 platform_handle->type = MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR;
115 platform_handle->value = static_cast<uint64_t>(handle.release().handle);
116 break;
117
118 #if defined(OS_MACOSX) && !defined(OS_IOS)
119 case PlatformHandle::Type::MACH:
120 platform_handle->type = MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT;
121 platform_handle->value = static_cast<uint64_t>(handle.release().port);
122 break;
123 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
124
125 default:
126 return MOJO_RESULT_INVALID_ARGUMENT;
127 }
128 #elif defined(OS_WIN)
129 platform_handle->type = MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE;
130 platform_handle->value = reinterpret_cast<uint64_t>(handle.release().handle);
131 #endif // defined(OS_WIN)
132
133 return MOJO_RESULT_OK;
134 }
135
136 } // namespace
137
Core()138 Core::Core() {}
139
~Core()140 Core::~Core() {
141 if (node_controller_ && node_controller_->io_task_runner()) {
142 // If this races with IO thread shutdown the callback will be dropped and
143 // the NodeController will be shutdown on this thread anyway, which is also
144 // just fine.
145 scoped_refptr<base::TaskRunner> io_task_runner =
146 node_controller_->io_task_runner();
147 io_task_runner->PostTask(FROM_HERE,
148 base::Bind(&Core::PassNodeControllerToIOThread,
149 base::Passed(&node_controller_)));
150 }
151 }
152
SetIOTaskRunner(scoped_refptr<base::TaskRunner> io_task_runner)153 void Core::SetIOTaskRunner(scoped_refptr<base::TaskRunner> io_task_runner) {
154 GetNodeController()->SetIOTaskRunner(io_task_runner);
155 }
156
GetNodeController()157 NodeController* Core::GetNodeController() {
158 base::AutoLock lock(node_controller_lock_);
159 if (!node_controller_)
160 node_controller_.reset(new NodeController(this));
161 return node_controller_.get();
162 }
163
GetDispatcher(MojoHandle handle)164 scoped_refptr<Dispatcher> Core::GetDispatcher(MojoHandle handle) {
165 base::AutoLock lock(handles_lock_);
166 return handles_.GetDispatcher(handle);
167 }
168
SetDefaultProcessErrorCallback(const ProcessErrorCallback & callback)169 void Core::SetDefaultProcessErrorCallback(
170 const ProcessErrorCallback& callback) {
171 default_process_error_callback_ = callback;
172 }
173
AddChild(base::ProcessHandle process_handle,ConnectionParams connection_params,const std::string & child_token,const ProcessErrorCallback & process_error_callback)174 void Core::AddChild(base::ProcessHandle process_handle,
175 ConnectionParams connection_params,
176 const std::string& child_token,
177 const ProcessErrorCallback& process_error_callback) {
178 GetNodeController()->ConnectToChild(process_handle,
179 std::move(connection_params), child_token,
180 process_error_callback);
181 }
182
ChildLaunchFailed(const std::string & child_token)183 void Core::ChildLaunchFailed(const std::string& child_token) {
184 RequestContext request_context;
185 GetNodeController()->CloseChildPorts(child_token);
186 }
187
ConnectToPeerProcess(ScopedPlatformHandle pipe_handle,const std::string & peer_token)188 ScopedMessagePipeHandle Core::ConnectToPeerProcess(
189 ScopedPlatformHandle pipe_handle,
190 const std::string& peer_token) {
191 RequestContext request_context;
192 ports::PortRef port0, port1;
193 GetNodeController()->node()->CreatePortPair(&port0, &port1);
194 MojoHandle handle = AddDispatcher(new MessagePipeDispatcher(
195 GetNodeController(), port0, kUnknownPipeIdForDebug, 0));
196 ConnectionParams connection_params(std::move(pipe_handle));
197 GetNodeController()->ConnectToPeer(std::move(connection_params), port1,
198 peer_token);
199 return ScopedMessagePipeHandle(MessagePipeHandle(handle));
200 }
201
ClosePeerConnection(const std::string & peer_token)202 void Core::ClosePeerConnection(const std::string& peer_token) {
203 GetNodeController()->ClosePeerConnection(peer_token);
204 }
205
InitChild(ConnectionParams connection_params)206 void Core::InitChild(ConnectionParams connection_params) {
207 GetNodeController()->ConnectToParent(std::move(connection_params));
208 }
209
SetMachPortProvider(base::PortProvider * port_provider)210 void Core::SetMachPortProvider(base::PortProvider* port_provider) {
211 #if defined(OS_MACOSX) && !defined(OS_IOS)
212 GetNodeController()->CreateMachPortRelay(port_provider);
213 #endif
214 }
215
AddDispatcher(scoped_refptr<Dispatcher> dispatcher)216 MojoHandle Core::AddDispatcher(scoped_refptr<Dispatcher> dispatcher) {
217 base::AutoLock lock(handles_lock_);
218 return handles_.AddDispatcher(dispatcher);
219 }
220
AddDispatchersFromTransit(const std::vector<Dispatcher::DispatcherInTransit> & dispatchers,MojoHandle * handles)221 bool Core::AddDispatchersFromTransit(
222 const std::vector<Dispatcher::DispatcherInTransit>& dispatchers,
223 MojoHandle* handles) {
224 bool failed = false;
225 {
226 base::AutoLock lock(handles_lock_);
227 if (!handles_.AddDispatchersFromTransit(dispatchers, handles))
228 failed = true;
229 }
230 if (failed) {
231 for (auto d : dispatchers)
232 d.dispatcher->Close();
233 return false;
234 }
235 return true;
236 }
237
CreatePlatformHandleWrapper(ScopedPlatformHandle platform_handle,MojoHandle * wrapper_handle)238 MojoResult Core::CreatePlatformHandleWrapper(
239 ScopedPlatformHandle platform_handle,
240 MojoHandle* wrapper_handle) {
241 MojoHandle h = AddDispatcher(
242 PlatformHandleDispatcher::Create(std::move(platform_handle)));
243 if (h == MOJO_HANDLE_INVALID)
244 return MOJO_RESULT_RESOURCE_EXHAUSTED;
245 *wrapper_handle = h;
246 return MOJO_RESULT_OK;
247 }
248
PassWrappedPlatformHandle(MojoHandle wrapper_handle,ScopedPlatformHandle * platform_handle)249 MojoResult Core::PassWrappedPlatformHandle(
250 MojoHandle wrapper_handle,
251 ScopedPlatformHandle* platform_handle) {
252 base::AutoLock lock(handles_lock_);
253 scoped_refptr<Dispatcher> d;
254 MojoResult result = handles_.GetAndRemoveDispatcher(wrapper_handle, &d);
255 if (result != MOJO_RESULT_OK)
256 return result;
257 if (d->GetType() == Dispatcher::Type::PLATFORM_HANDLE) {
258 PlatformHandleDispatcher* phd =
259 static_cast<PlatformHandleDispatcher*>(d.get());
260 *platform_handle = phd->PassPlatformHandle();
261 } else {
262 result = MOJO_RESULT_INVALID_ARGUMENT;
263 }
264 d->Close();
265 return result;
266 }
267
CreateSharedBufferWrapper(base::SharedMemoryHandle shared_memory_handle,size_t num_bytes,bool read_only,MojoHandle * mojo_wrapper_handle)268 MojoResult Core::CreateSharedBufferWrapper(
269 base::SharedMemoryHandle shared_memory_handle,
270 size_t num_bytes,
271 bool read_only,
272 MojoHandle* mojo_wrapper_handle) {
273 DCHECK(num_bytes);
274 scoped_refptr<PlatformSharedBuffer> platform_buffer =
275 PlatformSharedBuffer::CreateFromSharedMemoryHandle(num_bytes, read_only,
276 shared_memory_handle);
277 if (!platform_buffer)
278 return MOJO_RESULT_UNKNOWN;
279
280 scoped_refptr<SharedBufferDispatcher> dispatcher;
281 MojoResult result = SharedBufferDispatcher::CreateFromPlatformSharedBuffer(
282 platform_buffer, &dispatcher);
283 if (result != MOJO_RESULT_OK)
284 return result;
285 MojoHandle h = AddDispatcher(dispatcher);
286 if (h == MOJO_HANDLE_INVALID)
287 return MOJO_RESULT_RESOURCE_EXHAUSTED;
288 *mojo_wrapper_handle = h;
289 return MOJO_RESULT_OK;
290 }
291
PassSharedMemoryHandle(MojoHandle mojo_handle,base::SharedMemoryHandle * shared_memory_handle,size_t * num_bytes,bool * read_only)292 MojoResult Core::PassSharedMemoryHandle(
293 MojoHandle mojo_handle,
294 base::SharedMemoryHandle* shared_memory_handle,
295 size_t* num_bytes,
296 bool* read_only) {
297 if (!shared_memory_handle)
298 return MOJO_RESULT_INVALID_ARGUMENT;
299
300 scoped_refptr<Dispatcher> dispatcher;
301 MojoResult result = MOJO_RESULT_OK;
302 {
303 base::AutoLock lock(handles_lock_);
304 // Get the dispatcher and check it before removing it from the handle table
305 // to ensure that the dispatcher is of the correct type. This ensures we
306 // don't close and remove the wrong type of dispatcher.
307 dispatcher = handles_.GetDispatcher(mojo_handle);
308 if (!dispatcher || dispatcher->GetType() != Dispatcher::Type::SHARED_BUFFER)
309 return MOJO_RESULT_INVALID_ARGUMENT;
310
311 result = handles_.GetAndRemoveDispatcher(mojo_handle, &dispatcher);
312 if (result != MOJO_RESULT_OK)
313 return result;
314 }
315
316 SharedBufferDispatcher* shm_dispatcher =
317 static_cast<SharedBufferDispatcher*>(dispatcher.get());
318 scoped_refptr<PlatformSharedBuffer> platform_shared_buffer =
319 shm_dispatcher->PassPlatformSharedBuffer();
320
321 if (!platform_shared_buffer)
322 return MOJO_RESULT_INVALID_ARGUMENT;
323
324 if (num_bytes)
325 *num_bytes = platform_shared_buffer->GetNumBytes();
326 if (read_only)
327 *read_only = platform_shared_buffer->IsReadOnly();
328 *shared_memory_handle = platform_shared_buffer->DuplicateSharedMemoryHandle();
329
330 shm_dispatcher->Close();
331 return result;
332 }
333
RequestShutdown(const base::Closure & callback)334 void Core::RequestShutdown(const base::Closure& callback) {
335 GetNodeController()->RequestShutdown(callback);
336 }
337
CreateParentMessagePipe(const std::string & token,const std::string & child_token)338 ScopedMessagePipeHandle Core::CreateParentMessagePipe(
339 const std::string& token, const std::string& child_token) {
340 RequestContext request_context;
341 ports::PortRef port0, port1;
342 GetNodeController()->node()->CreatePortPair(&port0, &port1);
343 MojoHandle handle = AddDispatcher(
344 new MessagePipeDispatcher(GetNodeController(), port0,
345 kUnknownPipeIdForDebug, 0));
346 GetNodeController()->ReservePort(token, port1, child_token);
347 return ScopedMessagePipeHandle(MessagePipeHandle(handle));
348 }
349
CreateChildMessagePipe(const std::string & token)350 ScopedMessagePipeHandle Core::CreateChildMessagePipe(const std::string& token) {
351 RequestContext request_context;
352 ports::PortRef port0, port1;
353 GetNodeController()->node()->CreatePortPair(&port0, &port1);
354 MojoHandle handle = AddDispatcher(
355 new MessagePipeDispatcher(GetNodeController(), port0,
356 kUnknownPipeIdForDebug, 1));
357 GetNodeController()->MergePortIntoParent(token, port1);
358 return ScopedMessagePipeHandle(MessagePipeHandle(handle));
359 }
360
SetProperty(MojoPropertyType type,const void * value)361 MojoResult Core::SetProperty(MojoPropertyType type, const void* value) {
362 base::AutoLock locker(property_lock_);
363 switch (type) {
364 case MOJO_PROPERTY_TYPE_SYNC_CALL_ALLOWED:
365 property_sync_call_allowed_ = *static_cast<const bool*>(value);
366 return MOJO_RESULT_OK;
367 default:
368 return MOJO_RESULT_INVALID_ARGUMENT;
369 }
370 }
371
GetTimeTicksNow()372 MojoTimeTicks Core::GetTimeTicksNow() {
373 return base::TimeTicks::Now().ToInternalValue();
374 }
375
Close(MojoHandle handle)376 MojoResult Core::Close(MojoHandle handle) {
377 RequestContext request_context;
378 scoped_refptr<Dispatcher> dispatcher;
379 {
380 base::AutoLock lock(handles_lock_);
381 MojoResult rv = handles_.GetAndRemoveDispatcher(handle, &dispatcher);
382 if (rv != MOJO_RESULT_OK)
383 return rv;
384 }
385 dispatcher->Close();
386 return MOJO_RESULT_OK;
387 }
388
Wait(MojoHandle handle,MojoHandleSignals signals,MojoDeadline deadline,MojoHandleSignalsState * signals_state)389 MojoResult Core::Wait(MojoHandle handle,
390 MojoHandleSignals signals,
391 MojoDeadline deadline,
392 MojoHandleSignalsState* signals_state) {
393 RequestContext request_context;
394 uint32_t unused = static_cast<uint32_t>(-1);
395 HandleSignalsState hss;
396 MojoResult rv = WaitManyInternal(&handle, &signals, 1, deadline, &unused,
397 signals_state ? &hss : nullptr);
398 if (rv != MOJO_RESULT_INVALID_ARGUMENT && signals_state)
399 *signals_state = hss;
400 return rv;
401 }
402
WaitMany(const MojoHandle * handles,const MojoHandleSignals * signals,uint32_t num_handles,MojoDeadline deadline,uint32_t * result_index,MojoHandleSignalsState * signals_state)403 MojoResult Core::WaitMany(const MojoHandle* handles,
404 const MojoHandleSignals* signals,
405 uint32_t num_handles,
406 MojoDeadline deadline,
407 uint32_t* result_index,
408 MojoHandleSignalsState* signals_state) {
409 RequestContext request_context;
410 if (num_handles < 1)
411 return MOJO_RESULT_INVALID_ARGUMENT;
412 if (num_handles > GetConfiguration().max_wait_many_num_handles)
413 return MOJO_RESULT_RESOURCE_EXHAUSTED;
414
415 uint32_t index = static_cast<uint32_t>(-1);
416 MojoResult rv;
417 if (!signals_state) {
418 rv = WaitManyInternal(handles, signals, num_handles, deadline, &index,
419 nullptr);
420 } else {
421 // Note: The |reinterpret_cast| is safe, since |HandleSignalsState| is a
422 // subclass of |MojoHandleSignalsState| that doesn't add any data members.
423 rv = WaitManyInternal(handles, signals, num_handles, deadline, &index,
424 reinterpret_cast<HandleSignalsState*>(signals_state));
425 }
426 if (index != static_cast<uint32_t>(-1) && result_index)
427 *result_index = index;
428 return rv;
429 }
430
Watch(MojoHandle handle,MojoHandleSignals signals,MojoWatchCallback callback,uintptr_t context)431 MojoResult Core::Watch(MojoHandle handle,
432 MojoHandleSignals signals,
433 MojoWatchCallback callback,
434 uintptr_t context) {
435 RequestContext request_context;
436 scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handle);
437 if (!dispatcher)
438 return MOJO_RESULT_INVALID_ARGUMENT;
439 return dispatcher->Watch(
440 signals, base::Bind(&CallWatchCallback, callback, context), context);
441 }
442
CancelWatch(MojoHandle handle,uintptr_t context)443 MojoResult Core::CancelWatch(MojoHandle handle, uintptr_t context) {
444 RequestContext request_context;
445 scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handle);
446 if (!dispatcher)
447 return MOJO_RESULT_INVALID_ARGUMENT;
448 return dispatcher->CancelWatch(context);
449 }
450
AllocMessage(uint32_t num_bytes,const MojoHandle * handles,uint32_t num_handles,MojoAllocMessageFlags flags,MojoMessageHandle * message)451 MojoResult Core::AllocMessage(uint32_t num_bytes,
452 const MojoHandle* handles,
453 uint32_t num_handles,
454 MojoAllocMessageFlags flags,
455 MojoMessageHandle* message) {
456 if (!message)
457 return MOJO_RESULT_INVALID_ARGUMENT;
458
459 if (num_handles == 0) { // Fast path: no handles.
460 std::unique_ptr<MessageForTransit> msg;
461 MojoResult rv = MessageForTransit::Create(&msg, num_bytes, nullptr, 0);
462 if (rv != MOJO_RESULT_OK)
463 return rv;
464
465 *message = reinterpret_cast<MojoMessageHandle>(msg.release());
466 return MOJO_RESULT_OK;
467 }
468
469 if (!handles)
470 return MOJO_RESULT_INVALID_ARGUMENT;
471
472 if (num_handles > kMaxHandlesPerMessage)
473 return MOJO_RESULT_RESOURCE_EXHAUSTED;
474
475 std::vector<Dispatcher::DispatcherInTransit> dispatchers;
476 {
477 base::AutoLock lock(handles_lock_);
478 MojoResult rv = handles_.BeginTransit(handles, num_handles, &dispatchers);
479 if (rv != MOJO_RESULT_OK) {
480 handles_.CancelTransit(dispatchers);
481 return rv;
482 }
483 }
484 DCHECK_EQ(num_handles, dispatchers.size());
485
486 std::unique_ptr<MessageForTransit> msg;
487 MojoResult rv = MessageForTransit::Create(
488 &msg, num_bytes, dispatchers.data(), num_handles);
489
490 {
491 base::AutoLock lock(handles_lock_);
492 if (rv == MOJO_RESULT_OK) {
493 handles_.CompleteTransitAndClose(dispatchers);
494 *message = reinterpret_cast<MojoMessageHandle>(msg.release());
495 } else {
496 handles_.CancelTransit(dispatchers);
497 }
498 }
499
500 return rv;
501 }
502
FreeMessage(MojoMessageHandle message)503 MojoResult Core::FreeMessage(MojoMessageHandle message) {
504 if (!message)
505 return MOJO_RESULT_INVALID_ARGUMENT;
506
507 delete reinterpret_cast<MessageForTransit*>(message);
508
509 return MOJO_RESULT_OK;
510 }
511
GetMessageBuffer(MojoMessageHandle message,void ** buffer)512 MojoResult Core::GetMessageBuffer(MojoMessageHandle message, void** buffer) {
513 if (!message)
514 return MOJO_RESULT_INVALID_ARGUMENT;
515
516 *buffer = reinterpret_cast<MessageForTransit*>(message)->mutable_bytes();
517
518 return MOJO_RESULT_OK;
519 }
520
GetProperty(MojoPropertyType type,void * value)521 MojoResult Core::GetProperty(MojoPropertyType type, void* value) {
522 base::AutoLock locker(property_lock_);
523 switch (type) {
524 case MOJO_PROPERTY_TYPE_SYNC_CALL_ALLOWED:
525 *static_cast<bool*>(value) = property_sync_call_allowed_;
526 return MOJO_RESULT_OK;
527 default:
528 return MOJO_RESULT_INVALID_ARGUMENT;
529 }
530 }
531
CreateWaitSet(MojoHandle * wait_set_handle)532 MojoResult Core::CreateWaitSet(MojoHandle* wait_set_handle) {
533 RequestContext request_context;
534 if (!wait_set_handle)
535 return MOJO_RESULT_INVALID_ARGUMENT;
536
537 scoped_refptr<WaitSetDispatcher> dispatcher = new WaitSetDispatcher();
538 MojoHandle h = AddDispatcher(dispatcher);
539 if (h == MOJO_HANDLE_INVALID) {
540 LOG(ERROR) << "Handle table full";
541 dispatcher->Close();
542 return MOJO_RESULT_RESOURCE_EXHAUSTED;
543 }
544
545 *wait_set_handle = h;
546 return MOJO_RESULT_OK;
547 }
548
AddHandle(MojoHandle wait_set_handle,MojoHandle handle,MojoHandleSignals signals)549 MojoResult Core::AddHandle(MojoHandle wait_set_handle,
550 MojoHandle handle,
551 MojoHandleSignals signals) {
552 RequestContext request_context;
553 scoped_refptr<Dispatcher> wait_set_dispatcher(GetDispatcher(wait_set_handle));
554 if (!wait_set_dispatcher)
555 return MOJO_RESULT_INVALID_ARGUMENT;
556
557 scoped_refptr<Dispatcher> dispatcher(GetDispatcher(handle));
558 if (!dispatcher)
559 return MOJO_RESULT_INVALID_ARGUMENT;
560
561 return wait_set_dispatcher->AddWaitingDispatcher(dispatcher, signals, handle);
562 }
563
RemoveHandle(MojoHandle wait_set_handle,MojoHandle handle)564 MojoResult Core::RemoveHandle(MojoHandle wait_set_handle,
565 MojoHandle handle) {
566 RequestContext request_context;
567 scoped_refptr<Dispatcher> wait_set_dispatcher(GetDispatcher(wait_set_handle));
568 if (!wait_set_dispatcher)
569 return MOJO_RESULT_INVALID_ARGUMENT;
570
571 scoped_refptr<Dispatcher> dispatcher(GetDispatcher(handle));
572 if (!dispatcher)
573 return MOJO_RESULT_INVALID_ARGUMENT;
574
575 return wait_set_dispatcher->RemoveWaitingDispatcher(dispatcher);
576 }
577
GetReadyHandles(MojoHandle wait_set_handle,uint32_t * count,MojoHandle * handles,MojoResult * results,MojoHandleSignalsState * signals_states)578 MojoResult Core::GetReadyHandles(MojoHandle wait_set_handle,
579 uint32_t* count,
580 MojoHandle* handles,
581 MojoResult* results,
582 MojoHandleSignalsState* signals_states) {
583 RequestContext request_context;
584 if (!handles || !count || !(*count) || !results)
585 return MOJO_RESULT_INVALID_ARGUMENT;
586
587 scoped_refptr<Dispatcher> wait_set_dispatcher(GetDispatcher(wait_set_handle));
588 if (!wait_set_dispatcher)
589 return MOJO_RESULT_INVALID_ARGUMENT;
590
591 DispatcherVector awoken_dispatchers;
592 base::StackVector<uintptr_t, 16> contexts;
593 contexts->assign(*count, MOJO_HANDLE_INVALID);
594
595 MojoResult result = wait_set_dispatcher->GetReadyDispatchers(
596 count, &awoken_dispatchers, results, contexts->data());
597
598 if (result == MOJO_RESULT_OK) {
599 for (size_t i = 0; i < *count; i++) {
600 handles[i] = static_cast<MojoHandle>(contexts[i]);
601 if (signals_states)
602 signals_states[i] = awoken_dispatchers[i]->GetHandleSignalsState();
603 }
604 }
605
606 return result;
607 }
608
CreateMessagePipe(const MojoCreateMessagePipeOptions * options,MojoHandle * message_pipe_handle0,MojoHandle * message_pipe_handle1)609 MojoResult Core::CreateMessagePipe(
610 const MojoCreateMessagePipeOptions* options,
611 MojoHandle* message_pipe_handle0,
612 MojoHandle* message_pipe_handle1) {
613 RequestContext request_context;
614 ports::PortRef port0, port1;
615 GetNodeController()->node()->CreatePortPair(&port0, &port1);
616
617 CHECK(message_pipe_handle0);
618 CHECK(message_pipe_handle1);
619
620 uint64_t pipe_id = base::RandUint64();
621
622 *message_pipe_handle0 = AddDispatcher(
623 new MessagePipeDispatcher(GetNodeController(), port0, pipe_id, 0));
624 if (*message_pipe_handle0 == MOJO_HANDLE_INVALID)
625 return MOJO_RESULT_RESOURCE_EXHAUSTED;
626
627 *message_pipe_handle1 = AddDispatcher(
628 new MessagePipeDispatcher(GetNodeController(), port1, pipe_id, 1));
629 if (*message_pipe_handle1 == MOJO_HANDLE_INVALID) {
630 scoped_refptr<Dispatcher> unused;
631 unused->Close();
632
633 base::AutoLock lock(handles_lock_);
634 handles_.GetAndRemoveDispatcher(*message_pipe_handle0, &unused);
635 return MOJO_RESULT_RESOURCE_EXHAUSTED;
636 }
637
638 return MOJO_RESULT_OK;
639 }
640
WriteMessage(MojoHandle message_pipe_handle,const void * bytes,uint32_t num_bytes,const MojoHandle * handles,uint32_t num_handles,MojoWriteMessageFlags flags)641 MojoResult Core::WriteMessage(MojoHandle message_pipe_handle,
642 const void* bytes,
643 uint32_t num_bytes,
644 const MojoHandle* handles,
645 uint32_t num_handles,
646 MojoWriteMessageFlags flags) {
647 if (num_bytes && !bytes)
648 return MOJO_RESULT_INVALID_ARGUMENT;
649
650 MojoMessageHandle message;
651 MojoResult rv = AllocMessage(num_bytes, handles, num_handles,
652 MOJO_ALLOC_MESSAGE_FLAG_NONE, &message);
653 if (rv != MOJO_RESULT_OK)
654 return rv;
655
656 if (num_bytes) {
657 void* buffer = nullptr;
658 rv = GetMessageBuffer(message, &buffer);
659 DCHECK_EQ(rv, MOJO_RESULT_OK);
660 memcpy(buffer, bytes, num_bytes);
661 }
662
663 return WriteMessageNew(message_pipe_handle, message, flags);
664 }
665
WriteMessageNew(MojoHandle message_pipe_handle,MojoMessageHandle message,MojoWriteMessageFlags flags)666 MojoResult Core::WriteMessageNew(MojoHandle message_pipe_handle,
667 MojoMessageHandle message,
668 MojoWriteMessageFlags flags) {
669 RequestContext request_context;
670 std::unique_ptr<MessageForTransit> message_for_transit(
671 reinterpret_cast<MessageForTransit*>(message));
672 auto dispatcher = GetDispatcher(message_pipe_handle);
673 if (!dispatcher)
674 return MOJO_RESULT_INVALID_ARGUMENT;
675
676 return dispatcher->WriteMessage(std::move(message_for_transit), flags);
677 }
678
ReadMessage(MojoHandle message_pipe_handle,void * bytes,uint32_t * num_bytes,MojoHandle * handles,uint32_t * num_handles,MojoReadMessageFlags flags)679 MojoResult Core::ReadMessage(MojoHandle message_pipe_handle,
680 void* bytes,
681 uint32_t* num_bytes,
682 MojoHandle* handles,
683 uint32_t* num_handles,
684 MojoReadMessageFlags flags) {
685 CHECK((!num_handles || !*num_handles || handles) &&
686 (!num_bytes || !*num_bytes || bytes));
687 RequestContext request_context;
688 auto dispatcher = GetDispatcher(message_pipe_handle);
689 if (!dispatcher)
690 return MOJO_RESULT_INVALID_ARGUMENT;
691 std::unique_ptr<MessageForTransit> message;
692 MojoResult rv =
693 dispatcher->ReadMessage(&message, num_bytes, handles, num_handles, flags,
694 false /* ignore_num_bytes */);
695 if (rv != MOJO_RESULT_OK)
696 return rv;
697
698 if (message && message->num_bytes())
699 memcpy(bytes, message->bytes(), message->num_bytes());
700
701 return MOJO_RESULT_OK;
702 }
703
ReadMessageNew(MojoHandle message_pipe_handle,MojoMessageHandle * message,uint32_t * num_bytes,MojoHandle * handles,uint32_t * num_handles,MojoReadMessageFlags flags)704 MojoResult Core::ReadMessageNew(MojoHandle message_pipe_handle,
705 MojoMessageHandle* message,
706 uint32_t* num_bytes,
707 MojoHandle* handles,
708 uint32_t* num_handles,
709 MojoReadMessageFlags flags) {
710 CHECK(message);
711 CHECK(!num_handles || !*num_handles || handles);
712 RequestContext request_context;
713 auto dispatcher = GetDispatcher(message_pipe_handle);
714 if (!dispatcher)
715 return MOJO_RESULT_INVALID_ARGUMENT;
716 std::unique_ptr<MessageForTransit> msg;
717 MojoResult rv =
718 dispatcher->ReadMessage(&msg, num_bytes, handles, num_handles, flags,
719 true /* ignore_num_bytes */);
720 if (rv != MOJO_RESULT_OK)
721 return rv;
722 *message = reinterpret_cast<MojoMessageHandle>(msg.release());
723 return MOJO_RESULT_OK;
724 }
725
FuseMessagePipes(MojoHandle handle0,MojoHandle handle1)726 MojoResult Core::FuseMessagePipes(MojoHandle handle0, MojoHandle handle1) {
727 RequestContext request_context;
728 scoped_refptr<Dispatcher> dispatcher0;
729 scoped_refptr<Dispatcher> dispatcher1;
730
731 bool valid_handles = true;
732 {
733 base::AutoLock lock(handles_lock_);
734 MojoResult result0 = handles_.GetAndRemoveDispatcher(handle0, &dispatcher0);
735 MojoResult result1 = handles_.GetAndRemoveDispatcher(handle1, &dispatcher1);
736 if (result0 != MOJO_RESULT_OK || result1 != MOJO_RESULT_OK ||
737 dispatcher0->GetType() != Dispatcher::Type::MESSAGE_PIPE ||
738 dispatcher1->GetType() != Dispatcher::Type::MESSAGE_PIPE)
739 valid_handles = false;
740 }
741
742 if (!valid_handles) {
743 if (dispatcher0)
744 dispatcher0->Close();
745 if (dispatcher1)
746 dispatcher1->Close();
747 return MOJO_RESULT_INVALID_ARGUMENT;
748 }
749
750 MessagePipeDispatcher* mpd0 =
751 static_cast<MessagePipeDispatcher*>(dispatcher0.get());
752 MessagePipeDispatcher* mpd1 =
753 static_cast<MessagePipeDispatcher*>(dispatcher1.get());
754
755 if (!mpd0->Fuse(mpd1))
756 return MOJO_RESULT_FAILED_PRECONDITION;
757
758 return MOJO_RESULT_OK;
759 }
760
NotifyBadMessage(MojoMessageHandle message,const char * error,size_t error_num_bytes)761 MojoResult Core::NotifyBadMessage(MojoMessageHandle message,
762 const char* error,
763 size_t error_num_bytes) {
764 if (!message)
765 return MOJO_RESULT_INVALID_ARGUMENT;
766
767 const PortsMessage& ports_message =
768 reinterpret_cast<MessageForTransit*>(message)->ports_message();
769 if (ports_message.source_node() == ports::kInvalidNodeName) {
770 DVLOG(1) << "Received invalid message from unknown node.";
771 if (!default_process_error_callback_.is_null())
772 default_process_error_callback_.Run(std::string(error, error_num_bytes));
773 return MOJO_RESULT_OK;
774 }
775
776 GetNodeController()->NotifyBadMessageFrom(
777 ports_message.source_node(), std::string(error, error_num_bytes));
778 return MOJO_RESULT_OK;
779 }
780
CreateDataPipe(const MojoCreateDataPipeOptions * options,MojoHandle * data_pipe_producer_handle,MojoHandle * data_pipe_consumer_handle)781 MojoResult Core::CreateDataPipe(
782 const MojoCreateDataPipeOptions* options,
783 MojoHandle* data_pipe_producer_handle,
784 MojoHandle* data_pipe_consumer_handle) {
785 RequestContext request_context;
786 if (options && options->struct_size != sizeof(MojoCreateDataPipeOptions))
787 return MOJO_RESULT_INVALID_ARGUMENT;
788
789 MojoCreateDataPipeOptions create_options;
790 create_options.struct_size = sizeof(MojoCreateDataPipeOptions);
791 create_options.flags = options ? options->flags : 0;
792 create_options.element_num_bytes = options ? options->element_num_bytes : 1;
793 // TODO(rockot): Use Configuration to get default data pipe capacity.
794 create_options.capacity_num_bytes =
795 options && options->capacity_num_bytes ? options->capacity_num_bytes
796 : 64 * 1024;
797
798 // TODO(rockot): Broker through the parent when necessary.
799 scoped_refptr<PlatformSharedBuffer> ring_buffer =
800 GetNodeController()->CreateSharedBuffer(
801 create_options.capacity_num_bytes);
802 if (!ring_buffer)
803 return MOJO_RESULT_RESOURCE_EXHAUSTED;
804
805 ports::PortRef port0, port1;
806 GetNodeController()->node()->CreatePortPair(&port0, &port1);
807
808 CHECK(data_pipe_producer_handle);
809 CHECK(data_pipe_consumer_handle);
810
811 uint64_t pipe_id = base::RandUint64();
812
813 scoped_refptr<Dispatcher> producer = new DataPipeProducerDispatcher(
814 GetNodeController(), port0, ring_buffer, create_options,
815 true /* initialized */, pipe_id);
816 scoped_refptr<Dispatcher> consumer = new DataPipeConsumerDispatcher(
817 GetNodeController(), port1, ring_buffer, create_options,
818 true /* initialized */, pipe_id);
819
820 *data_pipe_producer_handle = AddDispatcher(producer);
821 *data_pipe_consumer_handle = AddDispatcher(consumer);
822 if (*data_pipe_producer_handle == MOJO_HANDLE_INVALID ||
823 *data_pipe_consumer_handle == MOJO_HANDLE_INVALID) {
824 if (*data_pipe_producer_handle != MOJO_HANDLE_INVALID) {
825 scoped_refptr<Dispatcher> unused;
826 base::AutoLock lock(handles_lock_);
827 handles_.GetAndRemoveDispatcher(*data_pipe_producer_handle, &unused);
828 }
829 producer->Close();
830 consumer->Close();
831 return MOJO_RESULT_RESOURCE_EXHAUSTED;
832 }
833
834 return MOJO_RESULT_OK;
835 }
836
WriteData(MojoHandle data_pipe_producer_handle,const void * elements,uint32_t * num_bytes,MojoWriteDataFlags flags)837 MojoResult Core::WriteData(MojoHandle data_pipe_producer_handle,
838 const void* elements,
839 uint32_t* num_bytes,
840 MojoWriteDataFlags flags) {
841 RequestContext request_context;
842 scoped_refptr<Dispatcher> dispatcher(
843 GetDispatcher(data_pipe_producer_handle));
844 if (!dispatcher)
845 return MOJO_RESULT_INVALID_ARGUMENT;
846
847 return dispatcher->WriteData(elements, num_bytes, flags);
848 }
849
BeginWriteData(MojoHandle data_pipe_producer_handle,void ** buffer,uint32_t * buffer_num_bytes,MojoWriteDataFlags flags)850 MojoResult Core::BeginWriteData(MojoHandle data_pipe_producer_handle,
851 void** buffer,
852 uint32_t* buffer_num_bytes,
853 MojoWriteDataFlags flags) {
854 RequestContext request_context;
855 scoped_refptr<Dispatcher> dispatcher(
856 GetDispatcher(data_pipe_producer_handle));
857 if (!dispatcher)
858 return MOJO_RESULT_INVALID_ARGUMENT;
859
860 return dispatcher->BeginWriteData(buffer, buffer_num_bytes, flags);
861 }
862
EndWriteData(MojoHandle data_pipe_producer_handle,uint32_t num_bytes_written)863 MojoResult Core::EndWriteData(MojoHandle data_pipe_producer_handle,
864 uint32_t num_bytes_written) {
865 RequestContext request_context;
866 scoped_refptr<Dispatcher> dispatcher(
867 GetDispatcher(data_pipe_producer_handle));
868 if (!dispatcher)
869 return MOJO_RESULT_INVALID_ARGUMENT;
870
871 return dispatcher->EndWriteData(num_bytes_written);
872 }
873
ReadData(MojoHandle data_pipe_consumer_handle,void * elements,uint32_t * num_bytes,MojoReadDataFlags flags)874 MojoResult Core::ReadData(MojoHandle data_pipe_consumer_handle,
875 void* elements,
876 uint32_t* num_bytes,
877 MojoReadDataFlags flags) {
878 RequestContext request_context;
879 scoped_refptr<Dispatcher> dispatcher(
880 GetDispatcher(data_pipe_consumer_handle));
881 if (!dispatcher)
882 return MOJO_RESULT_INVALID_ARGUMENT;
883
884 return dispatcher->ReadData(elements, num_bytes, flags);
885 }
886
BeginReadData(MojoHandle data_pipe_consumer_handle,const void ** buffer,uint32_t * buffer_num_bytes,MojoReadDataFlags flags)887 MojoResult Core::BeginReadData(MojoHandle data_pipe_consumer_handle,
888 const void** buffer,
889 uint32_t* buffer_num_bytes,
890 MojoReadDataFlags flags) {
891 RequestContext request_context;
892 scoped_refptr<Dispatcher> dispatcher(
893 GetDispatcher(data_pipe_consumer_handle));
894 if (!dispatcher)
895 return MOJO_RESULT_INVALID_ARGUMENT;
896
897 return dispatcher->BeginReadData(buffer, buffer_num_bytes, flags);
898 }
899
EndReadData(MojoHandle data_pipe_consumer_handle,uint32_t num_bytes_read)900 MojoResult Core::EndReadData(MojoHandle data_pipe_consumer_handle,
901 uint32_t num_bytes_read) {
902 RequestContext request_context;
903 scoped_refptr<Dispatcher> dispatcher(
904 GetDispatcher(data_pipe_consumer_handle));
905 if (!dispatcher)
906 return MOJO_RESULT_INVALID_ARGUMENT;
907
908 return dispatcher->EndReadData(num_bytes_read);
909 }
910
CreateSharedBuffer(const MojoCreateSharedBufferOptions * options,uint64_t num_bytes,MojoHandle * shared_buffer_handle)911 MojoResult Core::CreateSharedBuffer(
912 const MojoCreateSharedBufferOptions* options,
913 uint64_t num_bytes,
914 MojoHandle* shared_buffer_handle) {
915 RequestContext request_context;
916 MojoCreateSharedBufferOptions validated_options = {};
917 MojoResult result = SharedBufferDispatcher::ValidateCreateOptions(
918 options, &validated_options);
919 if (result != MOJO_RESULT_OK)
920 return result;
921
922 scoped_refptr<SharedBufferDispatcher> dispatcher;
923 result = SharedBufferDispatcher::Create(
924 validated_options, GetNodeController(), num_bytes, &dispatcher);
925 if (result != MOJO_RESULT_OK) {
926 DCHECK(!dispatcher);
927 return result;
928 }
929
930 *shared_buffer_handle = AddDispatcher(dispatcher);
931 if (*shared_buffer_handle == MOJO_HANDLE_INVALID) {
932 LOG(ERROR) << "Handle table full";
933 dispatcher->Close();
934 return MOJO_RESULT_RESOURCE_EXHAUSTED;
935 }
936
937 return MOJO_RESULT_OK;
938 }
939
DuplicateBufferHandle(MojoHandle buffer_handle,const MojoDuplicateBufferHandleOptions * options,MojoHandle * new_buffer_handle)940 MojoResult Core::DuplicateBufferHandle(
941 MojoHandle buffer_handle,
942 const MojoDuplicateBufferHandleOptions* options,
943 MojoHandle* new_buffer_handle) {
944 RequestContext request_context;
945 scoped_refptr<Dispatcher> dispatcher(GetDispatcher(buffer_handle));
946 if (!dispatcher)
947 return MOJO_RESULT_INVALID_ARGUMENT;
948
949 // Don't verify |options| here; that's the dispatcher's job.
950 scoped_refptr<Dispatcher> new_dispatcher;
951 MojoResult result =
952 dispatcher->DuplicateBufferHandle(options, &new_dispatcher);
953 if (result != MOJO_RESULT_OK)
954 return result;
955
956 *new_buffer_handle = AddDispatcher(new_dispatcher);
957 if (*new_buffer_handle == MOJO_HANDLE_INVALID) {
958 LOG(ERROR) << "Handle table full";
959 dispatcher->Close();
960 return MOJO_RESULT_RESOURCE_EXHAUSTED;
961 }
962
963 return MOJO_RESULT_OK;
964 }
965
MapBuffer(MojoHandle buffer_handle,uint64_t offset,uint64_t num_bytes,void ** buffer,MojoMapBufferFlags flags)966 MojoResult Core::MapBuffer(MojoHandle buffer_handle,
967 uint64_t offset,
968 uint64_t num_bytes,
969 void** buffer,
970 MojoMapBufferFlags flags) {
971 RequestContext request_context;
972 scoped_refptr<Dispatcher> dispatcher(GetDispatcher(buffer_handle));
973 if (!dispatcher)
974 return MOJO_RESULT_INVALID_ARGUMENT;
975
976 std::unique_ptr<PlatformSharedBufferMapping> mapping;
977 MojoResult result = dispatcher->MapBuffer(offset, num_bytes, flags, &mapping);
978 if (result != MOJO_RESULT_OK)
979 return result;
980
981 DCHECK(mapping);
982 void* address = mapping->GetBase();
983 {
984 base::AutoLock locker(mapping_table_lock_);
985 result = mapping_table_.AddMapping(std::move(mapping));
986 }
987 if (result != MOJO_RESULT_OK)
988 return result;
989
990 *buffer = address;
991 return MOJO_RESULT_OK;
992 }
993
UnmapBuffer(void * buffer)994 MojoResult Core::UnmapBuffer(void* buffer) {
995 RequestContext request_context;
996 base::AutoLock lock(mapping_table_lock_);
997 return mapping_table_.RemoveMapping(buffer);
998 }
999
WrapPlatformHandle(const MojoPlatformHandle * platform_handle,MojoHandle * mojo_handle)1000 MojoResult Core::WrapPlatformHandle(const MojoPlatformHandle* platform_handle,
1001 MojoHandle* mojo_handle) {
1002 ScopedPlatformHandle handle;
1003 MojoResult result = MojoPlatformHandleToScopedPlatformHandle(platform_handle,
1004 &handle);
1005 if (result != MOJO_RESULT_OK)
1006 return result;
1007
1008 return CreatePlatformHandleWrapper(std::move(handle), mojo_handle);
1009 }
1010
UnwrapPlatformHandle(MojoHandle mojo_handle,MojoPlatformHandle * platform_handle)1011 MojoResult Core::UnwrapPlatformHandle(MojoHandle mojo_handle,
1012 MojoPlatformHandle* platform_handle) {
1013 ScopedPlatformHandle handle;
1014 MojoResult result = PassWrappedPlatformHandle(mojo_handle, &handle);
1015 if (result != MOJO_RESULT_OK)
1016 return result;
1017
1018 return ScopedPlatformHandleToMojoPlatformHandle(std::move(handle),
1019 platform_handle);
1020 }
1021
WrapPlatformSharedBufferHandle(const MojoPlatformHandle * platform_handle,size_t size,MojoPlatformSharedBufferHandleFlags flags,MojoHandle * mojo_handle)1022 MojoResult Core::WrapPlatformSharedBufferHandle(
1023 const MojoPlatformHandle* platform_handle,
1024 size_t size,
1025 MojoPlatformSharedBufferHandleFlags flags,
1026 MojoHandle* mojo_handle) {
1027 DCHECK(size);
1028 ScopedPlatformHandle handle;
1029 MojoResult result = MojoPlatformHandleToScopedPlatformHandle(platform_handle,
1030 &handle);
1031 if (result != MOJO_RESULT_OK)
1032 return result;
1033
1034 bool read_only = flags & MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_READ_ONLY;
1035 scoped_refptr<PlatformSharedBuffer> platform_buffer =
1036 PlatformSharedBuffer::CreateFromPlatformHandle(size, read_only,
1037 std::move(handle));
1038 if (!platform_buffer)
1039 return MOJO_RESULT_UNKNOWN;
1040
1041 scoped_refptr<SharedBufferDispatcher> dispatcher;
1042 result = SharedBufferDispatcher::CreateFromPlatformSharedBuffer(
1043 platform_buffer, &dispatcher);
1044 if (result != MOJO_RESULT_OK)
1045 return result;
1046
1047 MojoHandle h = AddDispatcher(dispatcher);
1048 if (h == MOJO_HANDLE_INVALID) {
1049 dispatcher->Close();
1050 return MOJO_RESULT_RESOURCE_EXHAUSTED;
1051 }
1052
1053 *mojo_handle = h;
1054 return MOJO_RESULT_OK;
1055 }
1056
UnwrapPlatformSharedBufferHandle(MojoHandle mojo_handle,MojoPlatformHandle * platform_handle,size_t * size,MojoPlatformSharedBufferHandleFlags * flags)1057 MojoResult Core::UnwrapPlatformSharedBufferHandle(
1058 MojoHandle mojo_handle,
1059 MojoPlatformHandle* platform_handle,
1060 size_t* size,
1061 MojoPlatformSharedBufferHandleFlags* flags) {
1062 scoped_refptr<Dispatcher> dispatcher;
1063 MojoResult result = MOJO_RESULT_OK;
1064 {
1065 base::AutoLock lock(handles_lock_);
1066 result = handles_.GetAndRemoveDispatcher(mojo_handle, &dispatcher);
1067 if (result != MOJO_RESULT_OK)
1068 return result;
1069 }
1070
1071 if (dispatcher->GetType() != Dispatcher::Type::SHARED_BUFFER) {
1072 dispatcher->Close();
1073 return MOJO_RESULT_INVALID_ARGUMENT;
1074 }
1075
1076 SharedBufferDispatcher* shm_dispatcher =
1077 static_cast<SharedBufferDispatcher*>(dispatcher.get());
1078 scoped_refptr<PlatformSharedBuffer> platform_shared_buffer =
1079 shm_dispatcher->PassPlatformSharedBuffer();
1080 CHECK(platform_shared_buffer);
1081
1082 CHECK(size);
1083 *size = platform_shared_buffer->GetNumBytes();
1084
1085 CHECK(flags);
1086 *flags = MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_NONE;
1087 if (platform_shared_buffer->IsReadOnly())
1088 *flags |= MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_READ_ONLY;
1089
1090 ScopedPlatformHandle handle = platform_shared_buffer->PassPlatformHandle();
1091 return ScopedPlatformHandleToMojoPlatformHandle(std::move(handle),
1092 platform_handle);
1093 }
1094
GetActiveHandlesForTest(std::vector<MojoHandle> * handles)1095 void Core::GetActiveHandlesForTest(std::vector<MojoHandle>* handles) {
1096 base::AutoLock lock(handles_lock_);
1097 handles_.GetActiveHandlesForTest(handles);
1098 }
1099
WaitManyInternal(const MojoHandle * handles,const MojoHandleSignals * signals,uint32_t num_handles,MojoDeadline deadline,uint32_t * result_index,HandleSignalsState * signals_states)1100 MojoResult Core::WaitManyInternal(const MojoHandle* handles,
1101 const MojoHandleSignals* signals,
1102 uint32_t num_handles,
1103 MojoDeadline deadline,
1104 uint32_t* result_index,
1105 HandleSignalsState* signals_states) {
1106 CHECK(handles);
1107 CHECK(signals);
1108 DCHECK_GT(num_handles, 0u);
1109 if (result_index) {
1110 DCHECK_EQ(*result_index, static_cast<uint32_t>(-1));
1111 }
1112
1113 // The primary caller of |WaitManyInternal()| is |Wait()|, which only waits on
1114 // a single handle. In the common case of a single handle, this avoid a heap
1115 // allocation.
1116 base::StackVector<scoped_refptr<Dispatcher>, 1> dispatchers;
1117 dispatchers->reserve(num_handles);
1118 for (uint32_t i = 0; i < num_handles; i++) {
1119 scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handles[i]);
1120 if (!dispatcher) {
1121 if (result_index)
1122 *result_index = i;
1123 return MOJO_RESULT_INVALID_ARGUMENT;
1124 }
1125 dispatchers->push_back(dispatcher);
1126 }
1127
1128 // TODO(vtl): Should make the waiter live (permanently) in TLS.
1129 Waiter waiter;
1130 waiter.Init();
1131
1132 uint32_t i;
1133 MojoResult rv = MOJO_RESULT_OK;
1134 for (i = 0; i < num_handles; i++) {
1135 rv = dispatchers[i]->AddAwakable(
1136 &waiter, signals[i], i, signals_states ? &signals_states[i] : nullptr);
1137 if (rv != MOJO_RESULT_OK) {
1138 if (result_index)
1139 *result_index = i;
1140 break;
1141 }
1142 }
1143 uint32_t num_added = i;
1144
1145 if (rv == MOJO_RESULT_ALREADY_EXISTS) {
1146 rv = MOJO_RESULT_OK; // The i-th one is already "triggered".
1147 } else if (rv == MOJO_RESULT_OK) {
1148 uintptr_t uintptr_result = *result_index;
1149 rv = waiter.Wait(deadline, &uintptr_result);
1150 *result_index = static_cast<uint32_t>(uintptr_result);
1151 }
1152
1153 // Make sure no other dispatchers try to wake |waiter| for the current
1154 // |Wait()|/|WaitMany()| call. (Only after doing this can |waiter| be
1155 // destroyed, but this would still be required if the waiter were in TLS.)
1156 for (i = 0; i < num_added; i++) {
1157 dispatchers[i]->RemoveAwakable(
1158 &waiter, signals_states ? &signals_states[i] : nullptr);
1159 }
1160 if (signals_states) {
1161 for (; i < num_handles; i++)
1162 signals_states[i] = dispatchers[i]->GetHandleSignalsState();
1163 }
1164
1165 return rv;
1166 }
1167
1168 // static
PassNodeControllerToIOThread(std::unique_ptr<NodeController> node_controller)1169 void Core::PassNodeControllerToIOThread(
1170 std::unique_ptr<NodeController> node_controller) {
1171 // It's OK to leak this reference. At this point we know the IO loop is still
1172 // running, and we know the NodeController will observe its eventual
1173 // destruction. This tells the NodeController to delete itself when that
1174 // happens.
1175 node_controller.release()->DestroyOnIOThreadShutdown();
1176 }
1177
1178 } // namespace edk
1179 } // namespace mojo
1180