• 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/system/dispatcher.h"
6 
7 #include "base/logging.h"
8 #include "mojo/system/constants.h"
9 #include "mojo/system/message_pipe_dispatcher.h"
10 #include "mojo/system/platform_handle_dispatcher.h"
11 #include "mojo/system/shared_buffer_dispatcher.h"
12 
13 namespace mojo {
14 namespace system {
15 
16 namespace test {
17 
18 // TODO(vtl): Maybe this should be defined in a test-only file instead.
DispatcherTryStartTransport(Dispatcher * dispatcher)19 DispatcherTransport DispatcherTryStartTransport(Dispatcher* dispatcher) {
20   return Dispatcher::HandleTableAccess::TryStartTransport(dispatcher);
21 }
22 
23 }  // namespace test
24 
25 // Dispatcher ------------------------------------------------------------------
26 
27 // static
TryStartTransport(Dispatcher * dispatcher)28 DispatcherTransport Dispatcher::HandleTableAccess::TryStartTransport(
29     Dispatcher* dispatcher) {
30   DCHECK(dispatcher);
31 
32   if (!dispatcher->lock_.Try())
33     return DispatcherTransport();
34 
35   // We shouldn't race with things that close dispatchers, since closing can
36   // only take place either under |handle_table_lock_| or when the handle is
37   // marked as busy.
38   DCHECK(!dispatcher->is_closed_);
39 
40   return DispatcherTransport(dispatcher);
41 }
42 
43 // static
StartSerialize(Dispatcher * dispatcher,Channel * channel,size_t * max_size,size_t * max_platform_handles)44 void Dispatcher::TransportDataAccess::StartSerialize(
45     Dispatcher* dispatcher,
46     Channel* channel,
47     size_t* max_size,
48     size_t* max_platform_handles) {
49   DCHECK(dispatcher);
50   dispatcher->StartSerialize(channel, max_size, max_platform_handles);
51 }
52 
53 // static
EndSerializeAndClose(Dispatcher * dispatcher,Channel * channel,void * destination,size_t * actual_size,embedder::PlatformHandleVector * platform_handles)54 bool Dispatcher::TransportDataAccess::EndSerializeAndClose(
55     Dispatcher* dispatcher,
56     Channel* channel,
57     void* destination,
58     size_t* actual_size,
59     embedder::PlatformHandleVector* platform_handles) {
60   DCHECK(dispatcher);
61   return dispatcher->EndSerializeAndClose(
62       channel, destination, actual_size, platform_handles);
63 }
64 
65 // static
Deserialize(Channel * channel,int32_t type,const void * source,size_t size,embedder::PlatformHandleVector * platform_handles)66 scoped_refptr<Dispatcher> Dispatcher::TransportDataAccess::Deserialize(
67     Channel* channel,
68     int32_t type,
69     const void* source,
70     size_t size,
71     embedder::PlatformHandleVector* platform_handles) {
72   switch (static_cast<int32_t>(type)) {
73     case kTypeUnknown:
74       DVLOG(2) << "Deserializing invalid handle";
75       return scoped_refptr<Dispatcher>();
76     case kTypeMessagePipe:
77       return scoped_refptr<Dispatcher>(
78           MessagePipeDispatcher::Deserialize(channel, source, size));
79     case kTypeDataPipeProducer:
80     case kTypeDataPipeConsumer:
81       // TODO(vtl): Implement.
82       LOG(WARNING) << "Deserialization of dispatcher type " << type
83                    << " not supported";
84       return scoped_refptr<Dispatcher>();
85     case kTypeSharedBuffer:
86       return scoped_refptr<Dispatcher>(SharedBufferDispatcher::Deserialize(
87           channel, source, size, platform_handles));
88     case kTypePlatformHandle:
89       return scoped_refptr<Dispatcher>(PlatformHandleDispatcher::Deserialize(
90           channel, source, size, platform_handles));
91   }
92   LOG(WARNING) << "Unknown dispatcher type " << type;
93   return scoped_refptr<Dispatcher>();
94 }
95 
Close()96 MojoResult Dispatcher::Close() {
97   base::AutoLock locker(lock_);
98   if (is_closed_)
99     return MOJO_RESULT_INVALID_ARGUMENT;
100 
101   CloseNoLock();
102   return MOJO_RESULT_OK;
103 }
104 
WriteMessage(UserPointer<const void> bytes,uint32_t num_bytes,std::vector<DispatcherTransport> * transports,MojoWriteMessageFlags flags)105 MojoResult Dispatcher::WriteMessage(
106     UserPointer<const void> bytes,
107     uint32_t num_bytes,
108     std::vector<DispatcherTransport>* transports,
109     MojoWriteMessageFlags flags) {
110   DCHECK(!transports || (transports->size() > 0 &&
111                          transports->size() < kMaxMessageNumHandles));
112 
113   base::AutoLock locker(lock_);
114   if (is_closed_)
115     return MOJO_RESULT_INVALID_ARGUMENT;
116 
117   return WriteMessageImplNoLock(bytes, num_bytes, transports, flags);
118 }
119 
ReadMessage(UserPointer<void> bytes,UserPointer<uint32_t> num_bytes,DispatcherVector * dispatchers,uint32_t * num_dispatchers,MojoReadMessageFlags flags)120 MojoResult Dispatcher::ReadMessage(UserPointer<void> bytes,
121                                    UserPointer<uint32_t> num_bytes,
122                                    DispatcherVector* dispatchers,
123                                    uint32_t* num_dispatchers,
124                                    MojoReadMessageFlags flags) {
125   DCHECK(!num_dispatchers || *num_dispatchers == 0 ||
126          (dispatchers && dispatchers->empty()));
127 
128   base::AutoLock locker(lock_);
129   if (is_closed_)
130     return MOJO_RESULT_INVALID_ARGUMENT;
131 
132   return ReadMessageImplNoLock(
133       bytes, num_bytes, dispatchers, num_dispatchers, flags);
134 }
135 
WriteData(UserPointer<const void> elements,UserPointer<uint32_t> num_bytes,MojoWriteDataFlags flags)136 MojoResult Dispatcher::WriteData(UserPointer<const void> elements,
137                                  UserPointer<uint32_t> num_bytes,
138                                  MojoWriteDataFlags flags) {
139   base::AutoLock locker(lock_);
140   if (is_closed_)
141     return MOJO_RESULT_INVALID_ARGUMENT;
142 
143   return WriteDataImplNoLock(elements, num_bytes, flags);
144 }
145 
BeginWriteData(UserPointer<void * > buffer,UserPointer<uint32_t> buffer_num_bytes,MojoWriteDataFlags flags)146 MojoResult Dispatcher::BeginWriteData(UserPointer<void*> buffer,
147                                       UserPointer<uint32_t> buffer_num_bytes,
148                                       MojoWriteDataFlags flags) {
149   base::AutoLock locker(lock_);
150   if (is_closed_)
151     return MOJO_RESULT_INVALID_ARGUMENT;
152 
153   return BeginWriteDataImplNoLock(buffer, buffer_num_bytes, flags);
154 }
155 
EndWriteData(uint32_t num_bytes_written)156 MojoResult Dispatcher::EndWriteData(uint32_t num_bytes_written) {
157   base::AutoLock locker(lock_);
158   if (is_closed_)
159     return MOJO_RESULT_INVALID_ARGUMENT;
160 
161   return EndWriteDataImplNoLock(num_bytes_written);
162 }
163 
ReadData(UserPointer<void> elements,UserPointer<uint32_t> num_bytes,MojoReadDataFlags flags)164 MojoResult Dispatcher::ReadData(UserPointer<void> elements,
165                                 UserPointer<uint32_t> num_bytes,
166                                 MojoReadDataFlags flags) {
167   base::AutoLock locker(lock_);
168   if (is_closed_)
169     return MOJO_RESULT_INVALID_ARGUMENT;
170 
171   return ReadDataImplNoLock(elements, num_bytes, flags);
172 }
173 
BeginReadData(UserPointer<const void * > buffer,UserPointer<uint32_t> buffer_num_bytes,MojoReadDataFlags flags)174 MojoResult Dispatcher::BeginReadData(UserPointer<const void*> buffer,
175                                      UserPointer<uint32_t> buffer_num_bytes,
176                                      MojoReadDataFlags flags) {
177   base::AutoLock locker(lock_);
178   if (is_closed_)
179     return MOJO_RESULT_INVALID_ARGUMENT;
180 
181   return BeginReadDataImplNoLock(buffer, buffer_num_bytes, flags);
182 }
183 
EndReadData(uint32_t num_bytes_read)184 MojoResult Dispatcher::EndReadData(uint32_t num_bytes_read) {
185   base::AutoLock locker(lock_);
186   if (is_closed_)
187     return MOJO_RESULT_INVALID_ARGUMENT;
188 
189   return EndReadDataImplNoLock(num_bytes_read);
190 }
191 
DuplicateBufferHandle(UserPointer<const MojoDuplicateBufferHandleOptions> options,scoped_refptr<Dispatcher> * new_dispatcher)192 MojoResult Dispatcher::DuplicateBufferHandle(
193     UserPointer<const MojoDuplicateBufferHandleOptions> options,
194     scoped_refptr<Dispatcher>* new_dispatcher) {
195   base::AutoLock locker(lock_);
196   if (is_closed_)
197     return MOJO_RESULT_INVALID_ARGUMENT;
198 
199   return DuplicateBufferHandleImplNoLock(options, new_dispatcher);
200 }
201 
MapBuffer(uint64_t offset,uint64_t num_bytes,MojoMapBufferFlags flags,scoped_ptr<embedder::PlatformSharedBufferMapping> * mapping)202 MojoResult Dispatcher::MapBuffer(
203     uint64_t offset,
204     uint64_t num_bytes,
205     MojoMapBufferFlags flags,
206     scoped_ptr<embedder::PlatformSharedBufferMapping>* mapping) {
207   base::AutoLock locker(lock_);
208   if (is_closed_)
209     return MOJO_RESULT_INVALID_ARGUMENT;
210 
211   return MapBufferImplNoLock(offset, num_bytes, flags, mapping);
212 }
213 
GetHandleSignalsState() const214 HandleSignalsState Dispatcher::GetHandleSignalsState() const {
215   base::AutoLock locker(lock_);
216   if (is_closed_)
217     return HandleSignalsState();
218 
219   return GetHandleSignalsStateImplNoLock();
220 }
221 
AddWaiter(Waiter * waiter,MojoHandleSignals signals,uint32_t context,HandleSignalsState * signals_state)222 MojoResult Dispatcher::AddWaiter(Waiter* waiter,
223                                  MojoHandleSignals signals,
224                                  uint32_t context,
225                                  HandleSignalsState* signals_state) {
226   base::AutoLock locker(lock_);
227   if (is_closed_) {
228     if (signals_state)
229       *signals_state = HandleSignalsState();
230     return MOJO_RESULT_INVALID_ARGUMENT;
231   }
232 
233   return AddWaiterImplNoLock(waiter, signals, context, signals_state);
234 }
235 
RemoveWaiter(Waiter * waiter,HandleSignalsState * handle_signals_state)236 void Dispatcher::RemoveWaiter(Waiter* waiter,
237                               HandleSignalsState* handle_signals_state) {
238   base::AutoLock locker(lock_);
239   if (is_closed_) {
240     if (handle_signals_state)
241       *handle_signals_state = HandleSignalsState();
242     return;
243   }
244   RemoveWaiterImplNoLock(waiter, handle_signals_state);
245 }
246 
Dispatcher()247 Dispatcher::Dispatcher() : is_closed_(false) {
248 }
249 
~Dispatcher()250 Dispatcher::~Dispatcher() {
251   // Make sure that |Close()| was called.
252   DCHECK(is_closed_);
253 }
254 
CancelAllWaitersNoLock()255 void Dispatcher::CancelAllWaitersNoLock() {
256   lock_.AssertAcquired();
257   DCHECK(is_closed_);
258   // By default, waiting isn't supported. Only dispatchers that can be waited on
259   // will do something nontrivial.
260 }
261 
CloseImplNoLock()262 void Dispatcher::CloseImplNoLock() {
263   lock_.AssertAcquired();
264   DCHECK(is_closed_);
265   // This may not need to do anything. Dispatchers should override this to do
266   // any actual close-time cleanup necessary.
267 }
268 
WriteMessageImplNoLock(UserPointer<const void>,uint32_t,std::vector<DispatcherTransport> *,MojoWriteMessageFlags)269 MojoResult Dispatcher::WriteMessageImplNoLock(
270     UserPointer<const void> /*bytes*/,
271     uint32_t /*num_bytes*/,
272     std::vector<DispatcherTransport>* /*transports*/,
273     MojoWriteMessageFlags /*flags*/) {
274   lock_.AssertAcquired();
275   DCHECK(!is_closed_);
276   // By default, not supported. Only needed for message pipe dispatchers.
277   return MOJO_RESULT_INVALID_ARGUMENT;
278 }
279 
ReadMessageImplNoLock(UserPointer<void>,UserPointer<uint32_t>,DispatcherVector *,uint32_t *,MojoReadMessageFlags)280 MojoResult Dispatcher::ReadMessageImplNoLock(
281     UserPointer<void> /*bytes*/,
282     UserPointer<uint32_t> /*num_bytes*/,
283     DispatcherVector* /*dispatchers*/,
284     uint32_t* /*num_dispatchers*/,
285     MojoReadMessageFlags /*flags*/) {
286   lock_.AssertAcquired();
287   DCHECK(!is_closed_);
288   // By default, not supported. Only needed for message pipe dispatchers.
289   return MOJO_RESULT_INVALID_ARGUMENT;
290 }
291 
WriteDataImplNoLock(UserPointer<const void>,UserPointer<uint32_t>,MojoWriteDataFlags)292 MojoResult Dispatcher::WriteDataImplNoLock(UserPointer<const void> /*elements*/,
293                                            UserPointer<uint32_t> /*num_bytes*/,
294                                            MojoWriteDataFlags /*flags*/) {
295   lock_.AssertAcquired();
296   DCHECK(!is_closed_);
297   // By default, not supported. Only needed for data pipe dispatchers.
298   return MOJO_RESULT_INVALID_ARGUMENT;
299 }
300 
BeginWriteDataImplNoLock(UserPointer<void * >,UserPointer<uint32_t>,MojoWriteDataFlags)301 MojoResult Dispatcher::BeginWriteDataImplNoLock(
302     UserPointer<void*> /*buffer*/,
303     UserPointer<uint32_t> /*buffer_num_bytes*/,
304     MojoWriteDataFlags /*flags*/) {
305   lock_.AssertAcquired();
306   DCHECK(!is_closed_);
307   // By default, not supported. Only needed for data pipe dispatchers.
308   return MOJO_RESULT_INVALID_ARGUMENT;
309 }
310 
EndWriteDataImplNoLock(uint32_t)311 MojoResult Dispatcher::EndWriteDataImplNoLock(uint32_t /*num_bytes_written*/) {
312   lock_.AssertAcquired();
313   DCHECK(!is_closed_);
314   // By default, not supported. Only needed for data pipe dispatchers.
315   return MOJO_RESULT_INVALID_ARGUMENT;
316 }
317 
ReadDataImplNoLock(UserPointer<void>,UserPointer<uint32_t>,MojoReadDataFlags)318 MojoResult Dispatcher::ReadDataImplNoLock(UserPointer<void> /*elements*/,
319                                           UserPointer<uint32_t> /*num_bytes*/,
320                                           MojoReadDataFlags /*flags*/) {
321   lock_.AssertAcquired();
322   DCHECK(!is_closed_);
323   // By default, not supported. Only needed for data pipe dispatchers.
324   return MOJO_RESULT_INVALID_ARGUMENT;
325 }
326 
BeginReadDataImplNoLock(UserPointer<const void * >,UserPointer<uint32_t>,MojoReadDataFlags)327 MojoResult Dispatcher::BeginReadDataImplNoLock(
328     UserPointer<const void*> /*buffer*/,
329     UserPointer<uint32_t> /*buffer_num_bytes*/,
330     MojoReadDataFlags /*flags*/) {
331   lock_.AssertAcquired();
332   DCHECK(!is_closed_);
333   // By default, not supported. Only needed for data pipe dispatchers.
334   return MOJO_RESULT_INVALID_ARGUMENT;
335 }
336 
EndReadDataImplNoLock(uint32_t)337 MojoResult Dispatcher::EndReadDataImplNoLock(uint32_t /*num_bytes_read*/) {
338   lock_.AssertAcquired();
339   DCHECK(!is_closed_);
340   // By default, not supported. Only needed for data pipe dispatchers.
341   return MOJO_RESULT_INVALID_ARGUMENT;
342 }
343 
DuplicateBufferHandleImplNoLock(UserPointer<const MojoDuplicateBufferHandleOptions>,scoped_refptr<Dispatcher> *)344 MojoResult Dispatcher::DuplicateBufferHandleImplNoLock(
345     UserPointer<const MojoDuplicateBufferHandleOptions> /*options*/,
346     scoped_refptr<Dispatcher>* /*new_dispatcher*/) {
347   lock_.AssertAcquired();
348   DCHECK(!is_closed_);
349   // By default, not supported. Only needed for buffer dispatchers.
350   return MOJO_RESULT_INVALID_ARGUMENT;
351 }
352 
MapBufferImplNoLock(uint64_t,uint64_t,MojoMapBufferFlags,scoped_ptr<embedder::PlatformSharedBufferMapping> *)353 MojoResult Dispatcher::MapBufferImplNoLock(
354     uint64_t /*offset*/,
355     uint64_t /*num_bytes*/,
356     MojoMapBufferFlags /*flags*/,
357     scoped_ptr<embedder::PlatformSharedBufferMapping>* /*mapping*/) {
358   lock_.AssertAcquired();
359   DCHECK(!is_closed_);
360   // By default, not supported. Only needed for buffer dispatchers.
361   return MOJO_RESULT_INVALID_ARGUMENT;
362 }
363 
GetHandleSignalsStateImplNoLock() const364 HandleSignalsState Dispatcher::GetHandleSignalsStateImplNoLock() const {
365   lock_.AssertAcquired();
366   DCHECK(!is_closed_);
367   // By default, waiting isn't supported. Only dispatchers that can be waited on
368   // will do something nontrivial.
369   return HandleSignalsState();
370 }
371 
AddWaiterImplNoLock(Waiter *,MojoHandleSignals,uint32_t,HandleSignalsState * signals_state)372 MojoResult Dispatcher::AddWaiterImplNoLock(Waiter* /*waiter*/,
373                                            MojoHandleSignals /*signals*/,
374                                            uint32_t /*context*/,
375                                            HandleSignalsState* signals_state) {
376   lock_.AssertAcquired();
377   DCHECK(!is_closed_);
378   // By default, waiting isn't supported. Only dispatchers that can be waited on
379   // will do something nontrivial.
380   if (signals_state)
381     *signals_state = HandleSignalsState();
382   return MOJO_RESULT_FAILED_PRECONDITION;
383 }
384 
RemoveWaiterImplNoLock(Waiter *,HandleSignalsState * signals_state)385 void Dispatcher::RemoveWaiterImplNoLock(Waiter* /*waiter*/,
386                                         HandleSignalsState* signals_state) {
387   lock_.AssertAcquired();
388   DCHECK(!is_closed_);
389   // By default, waiting isn't supported. Only dispatchers that can be waited on
390   // will do something nontrivial.
391   if (signals_state)
392     *signals_state = HandleSignalsState();
393 }
394 
StartSerializeImplNoLock(Channel *,size_t * max_size,size_t * max_platform_handles)395 void Dispatcher::StartSerializeImplNoLock(Channel* /*channel*/,
396                                           size_t* max_size,
397                                           size_t* max_platform_handles) {
398   DCHECK(HasOneRef());  // Only one ref => no need to take the lock.
399   DCHECK(!is_closed_);
400   *max_size = 0;
401   *max_platform_handles = 0;
402 }
403 
EndSerializeAndCloseImplNoLock(Channel *,void *,size_t *,embedder::PlatformHandleVector *)404 bool Dispatcher::EndSerializeAndCloseImplNoLock(
405     Channel* /*channel*/,
406     void* /*destination*/,
407     size_t* /*actual_size*/,
408     embedder::PlatformHandleVector* /*platform_handles*/) {
409   DCHECK(HasOneRef());  // Only one ref => no need to take the lock.
410   DCHECK(is_closed_);
411   // By default, serializing isn't supported, so just close.
412   CloseImplNoLock();
413   return false;
414 }
415 
IsBusyNoLock() const416 bool Dispatcher::IsBusyNoLock() const {
417   lock_.AssertAcquired();
418   DCHECK(!is_closed_);
419   // Most dispatchers support only "atomic" operations, so they are never busy
420   // (in this sense).
421   return false;
422 }
423 
CloseNoLock()424 void Dispatcher::CloseNoLock() {
425   lock_.AssertAcquired();
426   DCHECK(!is_closed_);
427 
428   is_closed_ = true;
429   CancelAllWaitersNoLock();
430   CloseImplNoLock();
431 }
432 
433 scoped_refptr<Dispatcher>
CreateEquivalentDispatcherAndCloseNoLock()434 Dispatcher::CreateEquivalentDispatcherAndCloseNoLock() {
435   lock_.AssertAcquired();
436   DCHECK(!is_closed_);
437 
438   is_closed_ = true;
439   CancelAllWaitersNoLock();
440   return CreateEquivalentDispatcherAndCloseImplNoLock();
441 }
442 
StartSerialize(Channel * channel,size_t * max_size,size_t * max_platform_handles)443 void Dispatcher::StartSerialize(Channel* channel,
444                                 size_t* max_size,
445                                 size_t* max_platform_handles) {
446   DCHECK(channel);
447   DCHECK(max_size);
448   DCHECK(max_platform_handles);
449   DCHECK(HasOneRef());  // Only one ref => no need to take the lock.
450   DCHECK(!is_closed_);
451   StartSerializeImplNoLock(channel, max_size, max_platform_handles);
452 }
453 
EndSerializeAndClose(Channel * channel,void * destination,size_t * actual_size,embedder::PlatformHandleVector * platform_handles)454 bool Dispatcher::EndSerializeAndClose(
455     Channel* channel,
456     void* destination,
457     size_t* actual_size,
458     embedder::PlatformHandleVector* platform_handles) {
459   DCHECK(channel);
460   DCHECK(actual_size);
461   DCHECK(HasOneRef());  // Only one ref => no need to take the lock.
462   DCHECK(!is_closed_);
463 
464   // Like other |...Close()| methods, we mark ourselves as closed before calling
465   // the impl. But there's no need to cancel waiters: we shouldn't have any (and
466   // shouldn't be in |Core|'s handle table.
467   is_closed_ = true;
468 
469 #if !defined(NDEBUG)
470   // See the comment above |EndSerializeAndCloseImplNoLock()|. In brief: Locking
471   // isn't actually needed, but we need to satisfy assertions (which we don't
472   // want to remove or weaken).
473   base::AutoLock locker(lock_);
474 #endif
475 
476   return EndSerializeAndCloseImplNoLock(
477       channel, destination, actual_size, platform_handles);
478 }
479 
480 // DispatcherTransport ---------------------------------------------------------
481 
End()482 void DispatcherTransport::End() {
483   DCHECK(dispatcher_);
484   dispatcher_->lock_.Release();
485   dispatcher_ = nullptr;
486 }
487 
488 }  // namespace system
489 }  // namespace mojo
490