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