Home | History | Annotate | Download | only in lib
      1 // Copyright 2014 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/public/cpp/bindings/lib/router.h"
      6 
      7 #include "mojo/public/cpp/environment/logging.h"
      8 
      9 namespace mojo {
     10 namespace internal {
     11 
     12 // ----------------------------------------------------------------------------
     13 
     14 class ResponderThunk : public MessageReceiver {
     15  public:
     16   explicit ResponderThunk(const SharedData<Router*>& router)
     17       : router_(router) {
     18   }
     19   virtual ~ResponderThunk() {
     20   }
     21 
     22   // MessageReceiver implementation:
     23   virtual bool Accept(Message* message) MOJO_OVERRIDE {
     24     MOJO_DCHECK(message->has_flag(kMessageIsResponse));
     25 
     26     bool result = false;
     27 
     28     Router* router = router_.value();
     29     if (router)
     30       result = router->Accept(message);
     31 
     32     return result;
     33   }
     34 
     35  private:
     36   SharedData<Router*> router_;
     37 };
     38 
     39 // ----------------------------------------------------------------------------
     40 
     41 Router::HandleIncomingMessageThunk::HandleIncomingMessageThunk(Router* router)
     42     : router_(router) {
     43 }
     44 
     45 Router::HandleIncomingMessageThunk::~HandleIncomingMessageThunk() {
     46 }
     47 
     48 bool Router::HandleIncomingMessageThunk::Accept(Message* message) {
     49   return router_->HandleIncomingMessage(message);
     50 }
     51 
     52 // ----------------------------------------------------------------------------
     53 
     54 Router::Router(ScopedMessagePipeHandle message_pipe,
     55                FilterChain filters,
     56                const MojoAsyncWaiter* waiter)
     57     : thunk_(this),
     58       filters_(filters.Pass()),
     59       connector_(message_pipe.Pass(), waiter),
     60       weak_self_(this),
     61       incoming_receiver_(NULL),
     62       next_request_id_(0),
     63       testing_mode_(false) {
     64   filters_.SetSink(&thunk_);
     65   connector_.set_incoming_receiver(filters_.GetHead());
     66 }
     67 
     68 Router::~Router() {
     69   weak_self_.set_value(NULL);
     70 
     71   for (ResponderMap::const_iterator i = responders_.begin();
     72        i != responders_.end(); ++i) {
     73     delete i->second;
     74   }
     75 }
     76 
     77 bool Router::Accept(Message* message) {
     78   MOJO_DCHECK(!message->has_flag(kMessageExpectsResponse));
     79   return connector_.Accept(message);
     80 }
     81 
     82 bool Router::AcceptWithResponder(Message* message,
     83                                  MessageReceiver* responder) {
     84   MOJO_DCHECK(message->has_flag(kMessageExpectsResponse));
     85 
     86   // Reserve 0 in case we want it to convey special meaning in the future.
     87   uint64_t request_id = next_request_id_++;
     88   if (request_id == 0)
     89     request_id = next_request_id_++;
     90 
     91   message->set_request_id(request_id);
     92   if (!connector_.Accept(message))
     93     return false;
     94 
     95   // We assume ownership of |responder|.
     96   responders_[request_id] = responder;
     97   return true;
     98 }
     99 
    100 void Router::EnableTestingMode() {
    101   testing_mode_ = true;
    102   connector_.set_enforce_errors_from_incoming_receiver(false);
    103 }
    104 
    105 bool Router::HandleIncomingMessage(Message* message) {
    106   if (message->has_flag(kMessageExpectsResponse)) {
    107     if (incoming_receiver_) {
    108       MessageReceiver* responder = new ResponderThunk(weak_self_);
    109       bool ok = incoming_receiver_->AcceptWithResponder(message, responder);
    110       if (!ok)
    111         delete responder;
    112       return ok;
    113     }
    114 
    115     // If we receive a request expecting a response when the client is not
    116     // listening, then we have no choice but to tear down the pipe.
    117     connector_.CloseMessagePipe();
    118   } else if (message->has_flag(kMessageIsResponse)) {
    119     uint64_t request_id = message->request_id();
    120     ResponderMap::iterator it = responders_.find(request_id);
    121     if (it == responders_.end()) {
    122       MOJO_DCHECK(testing_mode_);
    123       return false;
    124     }
    125     MessageReceiver* responder = it->second;
    126     responders_.erase(it);
    127     bool ok = responder->Accept(message);
    128     delete responder;
    129     return ok;
    130   } else {
    131     if (incoming_receiver_)
    132       return incoming_receiver_->Accept(message);
    133     // OK to drop message on the floor.
    134   }
    135 
    136   return false;
    137 }
    138 
    139 // ----------------------------------------------------------------------------
    140 
    141 }  // namespace internal
    142 }  // namespace mojo
    143