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