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