Home | History | Annotate | Download | only in system
      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.
     19 DispatcherTransport DispatcherTryStartTransport(Dispatcher* dispatcher) {
     20   return Dispatcher::HandleTableAccess::TryStartTransport(dispatcher);
     21 }
     22 
     23 }  // namespace test
     24 
     25 // Dispatcher ------------------------------------------------------------------
     26 
     27 // static
     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
     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
     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
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    214 HandleSignalsState Dispatcher::GetHandleSignalsState() const {
    215   base::AutoLock locker(lock_);
    216   if (is_closed_)
    217     return HandleSignalsState();
    218 
    219   return GetHandleSignalsStateImplNoLock();
    220 }
    221 
    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 
    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 
    247 Dispatcher::Dispatcher() : is_closed_(false) {
    248 }
    249 
    250 Dispatcher::~Dispatcher() {
    251   // Make sure that |Close()| was called.
    252   DCHECK(is_closed_);
    253 }
    254 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    364 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 
    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 
    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 
    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 
    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 
    416 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 
    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>
    434 Dispatcher::CreateEquivalentDispatcherAndCloseNoLock() {
    435   lock_.AssertAcquired();
    436   DCHECK(!is_closed_);
    437 
    438   is_closed_ = true;
    439   CancelAllWaitersNoLock();
    440   return CreateEquivalentDispatcherAndCloseImplNoLock();
    441 }
    442 
    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 
    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 
    482 void DispatcherTransport::End() {
    483   DCHECK(dispatcher_);
    484   dispatcher_->lock_.Release();
    485   dispatcher_ = nullptr;
    486 }
    487 
    488 }  // namespace system
    489 }  // namespace mojo
    490